Figma Pluginの開発でi18n(国際化)する方法

先日、また新しく[Figmaプラグイン](https://www.figma.com/community/plugin/1080046874598231357/Status-Changer)をリリースしたんですが、これを開発した際に各エリア別の情報を出さなければならないことがあり、少しだけトンチを使ったので備忘録として残しておきます。  
（尚、メニューからの呼び出しとかは多言語化できませんでの悪しからず、また記事中にJSと出てるのはTSに置き換えても問題ないのですが便宜上JSと記述しています。）


## どうしてプラグインごとき？でも多言語化しなければならないか？

今回どうして多言語化しなければならないか？と言ったら**時刻**を扱うからです。  
そうじゃなくても通貨とかインチ、cm、フィート、kg、ポンド、華氏、摂氏とか結構面倒です。  

日本人でも多いと思いますが、もし**私がアメリカ人だった時に表記が**「**2022/01/02 23:00**」**とかだったら**「**読みづらいなぁ**」**と感じる**と思います。
UI/UXを作る？ツールなのにそのプラグインのUI/UXがイケてないのって本末転倒な気がします。

```~JavaScript
sample = {
"en-CA":"DD/MM/YY H:m a",
"it":"DD/MM/YY H:m a",
"en-GB":"DD/MM/YY H.m a",
"ja":"YYYY/MM/DD HH:mm",
"no":"DD-MM-YY H:m a",
"es":"DD-MM-YY H:m a",
"fr":"DD/MM/YYYY H:m a",
"th":"DD/MM/YYYY HH:mm",
"en-US":"MM-DD-YY H:m a",
"SV":"YYYY-MM-DD H:m a",
"da":"YYYY-MM-DD H:m a",
"fi":"DD.MM.YYYY H:m a",
"de-de":"YYYY-MM-DD H:m a"
}
```


## Figma plugin APIで言語設定取得ができない

[公式](https://www.figma.com/plugin-docs/api/api-reference/) をサラっと眺めたところ、どうもユーザーの言語（もしくは地域）を取得する方法がなさそうでした。  
もちろん、通常のJavascriptであれば「window.navigator.language」を使えばいいのですが、メインロジック側？のjsでは「window.navigator.language」が使えないのです。

そう、メインロジック側ではね。

## UI側からhideモードを使って無理やり実装する

もう、結論から書いてますが

```~JavaScript
figma.showUI(__html__,{width:0,height:0, title:""})
figma.ui.hide()
```

これを使うことでフロント側？のHTMLから「window.navigator.language」を取得することができます。  
なので、UIがないプラグインでもui.htmlを使うことになります。(直接コードを書けますがコードを分離できた方が管理が楽だと思うので…)

### アラートを出す場合(不完全版)

基本的に、ユーザーへのアラート？的なものであれば**「Figma.notify」を使え！**ってのが多いと思いますがこれってUI側からだとコールできないので使い勝手が微妙なんですよね。
なので、下記のようにやります。

1. manifest.jsonに「"ui":"ui.html"」を追記します。

```json:manifest.json
{
  "name": "AlertSample",
  "id": "XXXXXXXXXXXXXXXX",
  "api": "1.0.0",
  "main": "code.js",
  "ui":"ui.html",
  "editorType": [
    "figma"
  ]
}
```

2. background側のjsからUI側へpostMessageします。

```JavaScript:code.js

function showAlert(message) {
    figma.showUI(__html__,{width:0,height:0, title:""})
    figma.ui.hide()
    figma.ui.postMessage({type:"alert", message:message})
}

main(){
    //Figma.notify("Hi!")
    showAlert({en:"Hi!",ja:"こんにちわ"})
}

main()

```

3. ui.htmlでalertします。

```HTML:ui.html
<script>
onmessage = (event) => {
  if (event.data.pluginMessage.type === "alert"){
    let massage = event.data.pluginMessage.message.en
    if (window.navigator.language == "ja"){
      massage = event.data.pluginMessage.message.ja
    }
    alert(massage)
  }
}
</script>
```

これで、なんとなくできるんですが、ちょっと**罠**があります。
alertを閉じたあと、プラグインのプロセスが残っているので使い勝手が悪いですね。  
その場合「figma.closePlugin()」を記載するんですが**ui.html側では「figma.closePlugin()」が使えない**ですし、**showAlertメソッドに追加するとalertが出ずにプラグインが終了します**。


## アラートを出す場合(完全版)

前段が長くなりましたが、alertをクリックしてpluginのプロセスを消す場合はui側からcode.js側にparent.postMessageでcallします。


```JavaScript:code.js

function showAlert(message) {
    figma.showUI(__html__,{width:0,height:0, title:""})
    figma.ui.hide()
    figma.ui.postMessage({type:"alert", message:message})
}

main(){
    //Figma.notify("Hi!")
    showAlert({en:"Hi!",ja:"こんにちは"})
}

main()

figma.ui.onmessage = (msg) => {
    if (msg.kind === "exit"){
        figma.closePlugin()
        return
    }
}

```


```HTML:ui.html
<script>
onmessage = (event) => {
  if (event.data.pluginMessage.type === "alert"){
    let massage = event.data.pluginMessage.message.en
    if (window.navigator.language == "ja"){
      massage = event.data.pluginMessage.message.ja
    }
    alert(massage)
    parent.postMessage({ pluginMessage: { kind: 'exit', type:""} }, '*')
    return
  }
}
</script>
```

## まとめ
google chrome extensionのようにjson自体で多言語化できない(?)のでmenu側の文字列を多言語化はできませんが、実際に使った場合

figma.ui.hide()はhtmlを記載していても表示されないので、本来backgroud側からwindow.confirmなどYes/NoによってUIを出すか？などを使いたい場合などすごく便利に使えると思います。

あ、サンプル中には日本語と英語だけのものになってますが値が取得できれば通常のi18n系のライブラリが使えるはずなので通常のようにjsonを用意して使うのが可能になります。