雨小屋-あまごや-

多言語対応

調べてみても、どうやって実装するのがいいのかいまいちわからなかった多言語対応。
それでも自分なりにどうにか実装したやり方を備忘録程度にまとめました。
改善案等ありましたら、教えていただけると幸いです。

ざっくりとした仕組みと実装の手順は以下の通り。

①ScriptableObjectの文字列データを作成する。
②キーを受け取って①のデータから文字列を返すメソッドを作る。
③各文字列の使用箇所で②を呼び出す。
 (動的に生成しない文字列はInspectorでキーを設定するだけで使えるように共通スクリプトも作っておく)

キーを受け取って各言語の文字列を返す、っていうのを、ScriptableObjectを使って実装している、という感じです。
以下もうちょっと詳細に。

①ScriptableObjectの文字列データを作成する。

Key(文字列キー)とValue(表示する文字列)を持つScriptableObjectを、各言語の各文字列単位で作成します。
ファイル名は「Lang_言語キー_文字列キー」で統一してます。

このScriptableObjectの作成は、CSVから一括で行いました。
参考:【Unity】CSVからScriptableObjectにデータを流し込むEditor拡張サンプル

やり方は上記の参考先のやり方をほぼそのまま使わせていただいたのですが、ファイル名に言語キーを入れるために、CsvImporterにlangKeyを追加して、ScriptableObjectの生成時に使用しています。
CSVファイルの一行目とかに言語キーを持たせた方が楽かなと思ったのですが、そちらは原因不明のエラーでうまくいかなかったので……

また、英文内で使用しているカンマのエスケープ処理も必要なため追加していますが、真面目に考えるのが面倒で、置き換え用の文字列を用意して生成時にそれを置き換えるぐらいの処理しかしていないので割愛で。
ともかくこれで、「Lang_言語キー_文字列キー」というファイル名で、valueに文字列データを保持したScriptableObjectができました。

②キーを受け取って①のデータから文字列を返すメソッドを作る。

言語キーと文字列キーを受け取って、それらを元にファイル名を指定して読み込むだけ。


using UnityEngine;

public static class LanguageDataManager {
    public static string GetLangString(string key, string lang) {
        LangData langData = Resources.Load("Scripts/lang_" + lang + "_" + key);
        return langData.value;
    }
}
				

③各文字列の使用箇所で②を呼び出す。

上記のGetLangString()に言語キーと文字列キーを渡して文字列を取得します。
ボタン上の文字列みたいな動的に生成しない部分は、以下のスクリプトを使ってInspector上でキーを設定するだけで表示される仕組み。


using UnityEngine;

using TMPro;

public class LoadText : MonoBehaviour
{
    public string key;
    public int fontSizeJa = 0;
    public int fontSizeEn = 0;

    // Start is called before the first frame update
    void Start()
    {
        string langKey = SaveManager.instance.GetSettingLanguage();
        string text = LanguageDataManager.GetLangString(key, langKey);
        GetComponent ().text = text;
        switch (langKey) {
            case "ja":
                if (fontSizeJa > 0) {
                    GetComponent ().fontSize = fontSizeJa;
                }
                break;
            case "en":
                if (fontSizeEn > 0) {
                    GetComponent ().fontSize = fontSizeEn;
                }
                break;
        }
    }
}
				

各fontSizeは、言語に応じてフォントサイズを変更したい場合用。
以下の画像のような、文字数が大きく違う箇所とかで使ってます。

Auto Sizeを使うやり方でもいいとは思うのですが(てるてるの画面左上の称号部分は使ってるし)、余白とかも含めて読みやすいように調整するならこちらの方がいいかなぁ、と。

また、配列形式で文字列が必要な場合は、文字列キーに数値を含める形で実装しています。(例:key0, key1, key2)
配列形式で文字列を保持するようなScriptableObjectを用意して、みたいなやり方の方がいろいろ便利かもしれないですが、今回はひとまず上記で事足りたのと、今後の更新予定も64ビット対応みたいなのがまたない限り特にないのでこれでいいかな、と。


▽参考

【Unity】CSVからScriptableObjectにデータを流し込むEditor拡張サンプル