LoginSignup
0
0

Unity Localizationで動的にエントリを取得する

Last updated at Posted at 2024-05-18

コード

using UnityEngine.Localization.Settings;
using UnityEngine.Localization.Tables;

public static class LocalizedStringHandler
{
    private static StringTable _table;

    private static StringTable Table
    {
        get
        {
            if (_table != null)
            {
                return _table;
            }

            Debug.LogError($"[{nameof(LocalizedStringHandler)}] Tableがロードされていません");
            return null;
        }
    }

    public static string GetEntry(long id)
    {
        return Table.GetEntry(id).Value;
    }

    /// <summary>
    /// アプリ立ち上げ時にTableをキャッシュする
    /// </summary>
    internal static void CacheTable()
    {
        LocalizationSettings.Instance.OnSelectedLocaleChanged += _ => CacheTable();

        _table = LocalizationSettings.StringDatabase.GetTable(LocalizationConst.StringTableReference);
    }
}

使い方

string entry = LocalizedStringHandler.GetEntry({取得したいエントリのID});

エントリのIDはlongなのですが(stringもある)ハードコーディングするのはイケてないと思います。
そこでエントリIDの定数クラスを自動生成すると良いでしょう。

自動生成されたクラス
namespace Project.Runtime.Constant
{
    /// <summary>
    /// LocalizationのStringTableのKeyの定数クラス
    /// 自動生成されたクラスです
    /// </summary>
    public static class LocalizationStringKeys
    {
    		public static long Hoge => 101385924099694606;
      		public static long Fuga => 101385924099694607;
    }

}

下記の記事のコードを自分なりにカスタマイズしてます。

自動生成を行うクラス
public static class ConstantClassCreator
{
    //拡張子
    private const string ScriptExtension = ".cs";

    //定数の区切り文字
    private const char Delimiter = '_';

    //無効な文字を管理する配列
    private static readonly string[] InvalidChars =
    {
        " ", "!", "\"", "#", "$",
        "%", "&", "\'", "(", ")",
        "-", "=", "^", "~", "\\",
        "|", "[", "{", "@", "`",
        "]", "}", ":", "*", ";",
        "+", "/", "?", ".", ">",
        ",", "<"
    };

    /// <summary>
    /// 定数を管理するクラスを自動生成する
    /// </summary>
    /// <param name="className">クラス名</param>
    /// <param name="summary">記載したいサマリ</param>
    /// <param name="variableDict">記載したい変数 Key:変数名 Value:値</param>
    /// <param name="exportDirectoryPath">Assets/ から始まるパス</param>
    /// <param name="nameSpace">名前空間</param>
    /// <param name="isVariableTypeElias">記載したい変数の型をエイリアスで記載するか</param>
    /// <typeparam name="T">記載したい変数の型</typeparam>
    public static void Create<T>(string className, string summary, Dictionary<string, T> variableDict,
        string exportDirectoryPath, string nameSpace, bool isVariableTypeElias = true)
    {
        //ディクショナリーをソートしたものに
        var sortDict = new SortedDictionary<string, T>(variableDict);

        //入力された辞書のkeyから無効な文字列を削除して、大文字に_を設定した定数名と同じものに変更し新たな辞書に登録
        //次の定数の最大長求めるところで、_を含めたものを取得したいので、先に実行
        var newValueDict = new Dictionary<string, T>();

        foreach (var valuePair in sortDict)
        {
            var newKey = RemoveInvalidChars(valuePair.Key);
            newValueDict[newKey] = valuePair.Value;
        }

        //コード全文
        var builder = new StringBuilder();

        //ネームスペースがあれば設定
        if (!string.IsNullOrEmpty(nameSpace))
        {
            builder.AppendLine("namespace " + nameSpace);
            builder.AppendLine("{");
        }

        //コメント文とクラス名を入力
        builder.AppendLine("\t/// <summary>");
        builder.AppendLine($"\t/// {summary}");
        builder.AppendLine("\t/// </summary>");
        builder.AppendLine($"\tpublic static class {className}");
        builder.AppendLine("\t{");

        //入力された定数とその値のペアを書き出していく
        var keyArray = newValueDict.Keys.ToArray();
        foreach (var key in keyArray)
        {
            if (string.IsNullOrEmpty(key))
            {
                continue;
            }

            //数字だけのkeyだったらスルー
            if (Regex.IsMatch(key, @"^[0-9]+$"))
            {
                continue;
            }

            var variableName = typeof(T).Name;
            variableName = isVariableTypeElias ? variableName.ToLower() : variableName;
            variableName = typeof(T) == typeof(float) ? "float" : variableName;
            variableName = typeof(T) == typeof(long) ? "long" : variableName;
            //型と定数名を入力
            builder.Append($"\t\tpublic static {variableName} {key} => ");

            //Tがstringの場合は値の前後に"を付ける
            if (typeof(T) == typeof(string))
            {
                builder.Append($@"""{newValueDict[key]}"";").AppendLine();
            }
            //Tがfloatの場合は値の後にfを付ける
            else if (typeof(T) == typeof(float))
            {
                builder.Append($"{newValueDict[key]}f;").AppendLine();
            }
            else
            {
                builder.Append($"{newValueDict[key]};").AppendLine();
            }
        }

        builder.AppendLine("\t}");

        //ネームスペースがあれば最後にカッコ追加
        if (!string.IsNullOrEmpty(nameSpace))
        {
            builder.AppendLine("}");
        }

        //書き出し、ファイル名はクラス名.cs
        var exportPath = Path.Combine(exportDirectoryPath, className + ScriptExtension);
        var exportText = builder.ToString();

        //書き出し先のディレクトリが無ければ作成
        var directoryName = Path.GetDirectoryName(exportPath);
        if (!Directory.Exists(directoryName) && !string.IsNullOrEmpty(directoryName))
        {
            Directory.CreateDirectory(directoryName);
        }

        //書き出し先のファイルがあるかチェック
        if (File.Exists(exportPath))
        {
            //同名ファイルの中身をチェック、全く同じだったら書き出さない
            var sr = new StreamReader(exportPath, Encoding.UTF8);
            var isSame = sr.ReadToEnd() == exportText;
            sr.Close();

            if (isSame)
            {
                return;
            }
        }

        //書き出し
        File.WriteAllText(exportPath, exportText, Encoding.UTF8);
        AssetDatabase.Refresh(ImportAssetOptions.ImportRecursive);

        CustomDebug.Log(className + ScriptExtension + "の作成が完了しました");
    }

    /// <summary>
    /// 無効な文字を削除します
    /// </summary>
    private static string RemoveInvalidChars(string str)
    {
        InvalidChars.ForEach(c => str = str.Replace(c, string.Empty));
        return str;
    }
}

MenuItem等を使用して、こちらの関数を呼び出すと良いでしょう。

使用例
ConstantClassCreator.Create(className: "LocalizationStringKeys",
                 summary: $"LocalizationのStringTableのKeyの定数クラス" + 
                          $"{Environment.NewLine}\t/// 自動生成されたクラスです",
                 variableDict: variableDict,
                 exportDirectoryPath: FilePath,
                 nameSpace: "Project.Runtime.Constant");
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0