多言語対応の問題点
UnityではTextMeshProなどを用いて文字を表示できます。
しかし多言語に対応する場合、例えば↓のようなスクリプトを書かなくてはいけません。
var lang = Application.systemLanguage;
if (lang == SystemLanguage.Japanese)
{
text.text = "ヘンゼルのパンくず";
}
else if (lang == SystemLanguage.English)
{
text.text = "English";
}
でもこれは大変面倒ですし、今後言語追加された場合など変更に弱いです。
さらに、文字列を企画担当の人が変更できないというのも問題になります。
対応方針
そこで今回は↓のように言語別の文字を表にして管理し、
ラベル |
日本語 |
英語 |
Title |
ヘンゼルのパンくず |
breadcrumbs |
Menu |
メニュー |
Menu |
Start |
ゲームスタート |
Start Game |
スクリプトからは↓のように言語に寄って書き換えが必要ないシステムを作成します。
text.text = LanguageUtil.GetText(LangTextLabel.Title, Application.systemLanguage);
3分クッキング
ご自身で使う際は、コードをコピペしてご利用ください。
まずは、対応する言語リストを定義します。
using UnityEngine;
public static class AvailableLanguageList
{
public static SystemLanguage[] AvailableLanguages = new SystemLanguage[]
{
SystemLanguage.Japanese,
SystemLanguage.English,
};
}
続いて、スプレッドシートに入力された言語ラベルをEnumに変換するスクリプトを作成します。
このファイルはEditor
という名前のフォルダに入れると良いです。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
using System.IO;
using System;
public class LangTextEditorExtention : MonoBehaviour
{
[MenuItem("多言語対応/言語シート変換")]
public static void CreateLangEnumFile()
{
var resultStr = "";
resultStr += "public enum LangTextLabel\n{\n";
float progress = 0;
EditorUtility.DisplayProgressBar("変換中...", "チョットマッテネ", progress);
var langTextAsset = Resources.Load<TextAsset>("LanguageText");
var reader = new StringReader(langTextAsset.text);
var lineCount = 0;
while (reader.Peek() != -1)
{
var line = reader.ReadLine().Split(',');
if (lineCount == 0)
{
lineCount++;
continue;
}
var label = line[0];
var labelSp = label.Split('.');
for (int i = 0; i < labelSp.Length; i++)
{
var chars = labelSp[i].ToCharArray();
var initial = char.ToUpper(chars[0]);
chars[0] = initial;
labelSp[i] = new string(chars);
}
var enumKey = string.Join("", labelSp);
resultStr += $" {enumKey},\n";
lineCount++;
}
resultStr += "}";
progress = 0.5f;
EditorUtility.DisplayProgressBar("変換中...", "チョットマッテネ", progress);
var stream = new StreamWriter($"{Application.dataPath}/Script/AutoGenerate/LangTextLabel.cs");
stream.WriteLine(resultStr);
stream.Flush();
stream.Close();
AssetDatabase.Refresh();
LanguageUtil.Init();
progress = 0.8f;
EditorUtility.DisplayProgressBar("変換中...", "チョットマッテネ", progress);
foreach (SystemLanguage lang in AvailableLanguageList.AvailableLanguages)
{
foreach (LangTextLabel label in Enum.GetValues(typeof(LangTextLabel)))
{
Debug.Log($"{lang} {label} : {LanguageUtil.GetText(label, lang)}");
}
}
progress = 1f;
EditorUtility.DisplayProgressBar("変換中...", "チョットマッテネ", progress);
EditorUtility.ClearProgressBar();
}
}
最後に、変換したEnumをもとに文字列を取得するためのユーティリティを作成します。
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using UnityEngine;
public static class LanguageUtil
{
private static bool hasInit = false;
private static Dictionary<SystemLanguage, Dictionary<string, string>> langDict = null;
private static SystemLanguage[] availableLanguages = new SystemLanguage[]
{
SystemLanguage.Japanese,
SystemLanguage.English,
};
public static void Init()
{
langDict = new Dictionary<SystemLanguage, Dictionary<string, string>>();
foreach (SystemLanguage lang in availableLanguages)
{
langDict.Add(lang, new Dictionary<string, string>());
}
var langTextAsset = Resources.Load<TextAsset>("LanguageText");
var reader = new StringReader(langTextAsset.text);
var lineCount = 0;
while (reader.Peek() != -1)
{
var line = reader.ReadLine().Split(',');
if (lineCount == 0)
{
lineCount++;
continue;
}
var label = line[0];
var labelSp = label.Split('.');
for (int i = 0; i < labelSp.Length; i++)
{
var chars = labelSp[i].ToCharArray();
var initial = char.ToUpper(chars[0]);
chars[0] = initial;
labelSp[i] = new string(chars);
}
var langTextEnumKey = string.Join("", labelSp);
for (int i = 0; i < availableLanguages.Length; i++)
{
var text = line[i + 1];
langDict[availableLanguages[i]].Add(langTextEnumKey, text);
}
lineCount++;
}
hasInit = true;
}
public static string GetText(LangTextLabel label, SystemLanguage language)
{
if (!hasInit)
Init();
return langDict[language][label.ToString()];
}
}
以上で準備完了です。
使い方
こんな感じのスプレッドシートもしくはエクセルファイルを作成します。
1列目(ラベル):Enumに変換される言語ラベルです。.
を使って文字を区切ることもできます。
2列目以降:各言語に対応する文字列です。言語の順番は`AvalableLanguageListで定義した順にしてください。
備考:対応言語以降の行は自由に使ってください。
ステップ2 スプレッドシートをUnityにインポート
- スプレッドシート左上から、
ファイル > ダウンロード > カンマ区切り形式(.csv)
を選択してください。
- ダウンロードされたファイルを
Assets/Resources
フォルダに入れてください。
- ファイル名を
LanguageText
に変更して下さい。
ステップ3 言語シート変換
Unityの上部のバーから、多言語対応 > 言語シート変換
を選択してください。
ステップ4
スクリプトから下記の要領で言語別のテキストを取得できます。
EnumキーLangTextLabel
はステップ3で自動生成されたものです。
var text = LanguageUtil.GetText(LangTextLabel.MenuStageTitle, Application.systemLanguage);
最後に
なにかあればコメントでお知らせください。