Unityの多言語対応（UnityEditor.L10n＆UnityEditor.Localization）

個人的には `#if UNITY_EDITOR_LOCALE_JA` みたいなプリプロセッサで対応できると良いなーと思っていたんですが…。


<!--
https://qiita.com/sator_imaging/items/81c9066caa9e21feda8c
-->


### もくじ


- [はじめに](#はじめに)
- [多言語対応の方法](#多言語対応の方法)
   - [メニューが多言語化できない問題](#メニューが多言語化できない問題)
- [プリプロセッサーでの対応（が理想）](#プリプロセッサーでの対応が理想)
- [おわりに](#おわりに)





## はじめに


パッケージの多言語化に向けて下準備をしている中、`UnityChanSpringBone` が多言語化しましたってメールが来てたので調べてみました。

- [Add localization and make default language to English · unity3d-jp/UnityChanSpringBone@7cc16f3](https://github.com/unity3d-jp/UnityChanSpringBone/commit/7cc16f3ae1a2372d8258442fa1cafe9ebaad4b3f)
   <iframe
      class="embed-card embed-webcard"
      scrolling="no"  frameborder="0"
      style="
         display: block;  border: none;
         margin: 10px 0px;
         width: 100%; height: 155px;
         max-width: 500px;
      "
      src="https://hatenablog-parts.com/embed?url=https://github.com/unity3d-jp/UnityChanSpringBone/commit/7cc16f3ae1a2372d8258442fa1cafe9ebaad4b3f">
   </iframe>





## 多言語対応の方法


多言語化の方法ですが、`UnityEditor.Localization` で検索すると、既に纏めてくださってる方がいます。

- [Unityエディタ拡張で多言語対応する方法](https://caitsithware.com/wordpress/archives/2227)
   - コチラでこれまでの経緯含めて全部わかります。

UTJ の `UnityChanSpringBone` の更新も ↑ 記載の方法なので、公式の推奨するやり方だと思って問題なさそうです。


--


`UnityEditor.Localization.Editor.Localization.Tr()`、頭痛が痛い状態のクラスですが、案の定 Unity 2020 では `UnityEditor.L10n.Tr()` に変更されています。

[Unity - Scripting API: Localization](https://docs.unity3d.com/ScriptReference/Localization.Editor.Localization.html)

<img src="https://dl.dropbox.com/s/1rbp02sabs52agy/L10n_ClassHierarchy.png" />


↓ ↓ ↓


[Unity - Scripting API: L10n](https://docs.unity3d.com/2020.2/Documentation/ScriptReference/L10n.html)



`UnityEditor.Localization` がサポートされているのは Unity 2019 だけなので要注意ですね。





### メニューが多言語化できない問題


[VRM Tool Kit](https://sator-imaging.booth.pm/items/2254383) というパッケージでも多言語化の準備を進めているのですが、`UnityEditor.L10n` / `UnityEditor.Localization` ではメニュー項目の多言語化が出来ない、という問題があります。

Unity エディターへのメニュー項目の追加はアトリビュートを通して行うので、文字列は `const` である必要があります。

が、`public static readonly string foo = L10n.Tr("bar")` だとここで躓いてしまいます。


※ なにか凡ミス or 勘違いしてる？？
<img src="https://dl.dropbox.com/s/aqc4vi90srtb7rh/L10n_ErrorOnMenuItemAttribute.png" />






## プリプロセッサーでの対応（が理想）


`L10n` は `UnityEngine` 以下ではないことからエディターしか念頭に置いていないと思われ、その割には Assembly Definition が必須で手間がかかる、という代物。


大規模なパッケージなら Poedit のようなエディターで編集できるのは良いことですが、小規模なプロジェクトのエディター関連だけを多言語化、という需要の為にはオーバーキル。

もっと簡単に対応できるように、プリプロセッサーのシンボルも追加して欲しいところです。


- 日本語 → `#if UNITY_EDITOR_LOCALE_JA`
- 英語 → `#if !UNITY_EDITOR_LOCALIZED`（下位互換性が確保できるハズ）


[VRM Tool Kit](https://sator-imaging.booth.pm/items/2254383) では `UIResource.en-US.cs` というファイルに英語のインターフェイス関連の文字列をまとめているんですが、シンボルがあれば `UIResource.[language-country].cs` の中身をプリプロセッサーで包んでやるだけで対応できるし、メニューの多言語化も可能。Assembly Definition も要らないのでお手軽です。


※ あとは全体を `#if` ～ `#endif` で包むだけ

```csharp
public static class UIResource
{

#if UNITY_EDITOR_WIN
   const string MenuIndent = "&   ";
   const string MenuAmpersand = "&&";
#else
   const string MenuIndent = "   ";
   const string MenuAmpersand = "&";
#endif

   public static class CharacterMenu
   {
      public const string Label = "Character";
      public const string MenuPath = VRMToolKitRootMenu + "/" + Label + "/";

      public const string CharacterToTPose = MenuPath +
         "Character to T-Pose";

      public const string RevertToDefaultPose = MenuPath +
         "Revert to Default Pose";
      public const string CharacterToTPoseExceptForArm = MenuPath +
         MenuIndent + "Except for Arm " + MenuAmpersand + " Finger Root";

      public const string RevertAllTransformsToDefault = MenuPath +
         "Revert All Transforms to Default";
   }
}
```



特定の機能のためにプロジェクト全体に及ぶ設定にシンボルを追加して対応、はイヤなので、是非公式に対応して欲しいですね。



## おわりに


プリプロセッサーを使って多言語対応する方法、実は知られてないだけであるんじゃないかと思ってますが、どうなんでしょう。一番簡単だしそうなるだろうと思って UIResource に全部纏めたんですが。。。


L10n を使うと Unity 2020 以前と以後のパッケージを複数用意しなきゃいけないし、多言語化っていってもエディターだけだし、Poedit は Unity エディターの多言語化みたいな大規模な作業には向いてるだろうけども、そこまでの規模じゃない場合はちょっと大変ですよね。


--


以上です。お疲れ様でした。