Unity/多言語化/全体
ダウンロード
AssetStoreではなく以下からDLする。
LocalizationData.cs LocalizationManager.cs StartupManager.cs LocalizedText.cs LocalizedTextEditor.cs
翻訳ファイルサンプル
AndroidでStreamingAssetsが取得できなかったので、Resourcesに入れた。
Assets/Resources/Localization/ja.json
{
"items":[
{"key":"title","value":"タイトル1"},
{"key":"edit","value":"編集1"}
]
}
Assets/Resources/Localization/en.json
{
"items":[
{"key":"title","value":"title1"},
{"key":"edit","value":"edit1"}
]
}
上記DLしたファイル設定
端末言語を自動で判定し翻訳するようにカスタマイズしてあります。 指定することもできます。(下の項目でやり方記載)
LocalizationData.cs
[System.Serializable]
public class LocalizationData
{
public LocalizationItem[] items;
}
[System.Serializable]
public class LocalizationItem
{
public string key;
public string value;
}
LocalizationManager.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.IO;
public class LocalizationManager : MonoBehaviour {
public static LocalizationManager instance;
private Dictionary<string, string> localizedText;
private bool isReady = false;
private string missingTextString = "Localized text not found";
private string lang = "";
// Use this for initialization
void Awake ()
{
if (instance == null) {
instance = this;
} else if (instance != this)
{
Destroy (gameObject);
}
DontDestroyOnLoad (gameObject);
}
public void LoadLocalizedText(string fileName)
{
LoadAsset(fileName);
}
public void LoadAsset(string fileName)
{
string filePath = Path.Combine("Localization", fileName);
filePath = filePath.Replace(".json", "");
string dataAsJson = Resources.Load<TextAsset>(filePath).text;
LoadJson(dataAsJson);
}
private void LoadJson(string dataAsJson)
{
localizedText = new Dictionary<string, string>();
LocalizationData loadedData = JsonUtility.FromJson<LocalizationData>(dataAsJson);
for (int i = 0; i < loadedData.items.Length; i++)
{
localizedText.Add(loadedData.items[i].key, loadedData.items[i].value);
}
Debug.Log("Data loaded, dictionary contains: " + localizedText.Count + " entries");
isReady = true;
}
public string GetLocalizedValue(string key)
{
string result = missingTextString;
if (localizedText.ContainsKey (key))
{
result = localizedText [key];
}
return result;
}
public bool GetIsReady()
{
return isReady;
}
public void LoadLanguageTerminal()
{
var language = Application.systemLanguage;
if (language == SystemLanguage.Japanese)
{
lang = "ja";
}
else if (language == SystemLanguage.ChineseSimplified)
{
// 簡体字
lang = "zh-CN";
}
else if (language == SystemLanguage.ChineseTraditional)
{
// 繁体字
lang = "zh-TW";
}
else if (language == SystemLanguage.Vietnamese)
{
lang = "vi";
}
else if (language == SystemLanguage.Dutch)
{
lang = "de";
}
else if (language == SystemLanguage.Korean)
{
lang = "ko";
}
else if (language == SystemLanguage.Spanish)
{
lang = "es";
}
else
{
lang = "en";
}
LoadLocalizedText(lang + ".json");
}
public void LoadLanguage(string lang)
{
this.lang = lang;
if (!lang.Equals("terminal"))
{
LoadLocalizedText(lang + ".json");
}
}
public string GetLanguage()
{
return lang;
}
}
LocalizedText.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using TMPro;
public class LocalizedText : MonoBehaviour {
public string key;
void Start ()
{
if (gameObject.TryGetComponent<Text>(out var text))
{
LocalizationManager manager = LocalizationManager.instance;
if (manager == null)
{
return;
}
string str = manager.GetLocalizedValue(key);
if (str == null)
{
return;
}
text.text = str;
}
else if (gameObject.TryGetComponent<TextMeshProUGUI>(out var textPro))
{
LocalizationManager manager = LocalizationManager.instance;
if (manager == null)
{
return;
}
string str = manager.GetLocalizedValue(key);
if (str == null)
{
return;
}
textPro.text = str;
}
}
}
LocalizedTextEditor.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
using System.IO;
public class LocalizedTextEditor : EditorWindow
{
public LocalizationData localizationData;
[MenuItem ("Window/Localized Text Editor")]
static void Init()
{
EditorWindow.GetWindow (typeof(LocalizedTextEditor)).Show ();
}
private void OnGUI()
{
if (localizationData != null)
{
SerializedObject serializedObject = new SerializedObject (this);
SerializedProperty serializedProperty = serializedObject.FindProperty ("localizationData");
EditorGUILayout.PropertyField (serializedProperty, true);
serializedObject.ApplyModifiedProperties ();
if (GUILayout.Button ("Save data"))
{
SaveGameData ();
}
}
if (GUILayout.Button ("Load data"))
{
LoadGameData ();
}
if (GUILayout.Button ("Create new data"))
{
CreateNewData ();
}
}
private void LoadGameData()
{
string filePath = EditorUtility.OpenFilePanel ("Select localization data file", Application.streamingAssetsPath, "json");
if (!string.IsNullOrEmpty (filePath))
{
string dataAsJson = File.ReadAllText (filePath);
localizationData = JsonUtility.FromJson<LocalizationData> (dataAsJson);
}
}
private void SaveGameData()
{
string filePath = EditorUtility.SaveFilePanel ("Save localization data file", Application.streamingAssetsPath, "", "json");
if (!string.IsNullOrEmpty(filePath))
{
string dataAsJson = JsonUtility.ToJson(localizationData);
File.WriteAllText (filePath, dataAsJson);
}
}
private void CreateNewData()
{
localizationData = new LocalizationData ();
}
}
StartupManager.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
[DefaultExecutionOrder(-1)]
public class StartupManager : MonoBehaviour {
// Use this for initialization
private IEnumerator Start ()
{
LocalizationManager.instance.LoadLanguageTerminal();
while (!LocalizationManager.instance.GetIsReady ())
{
yield return null;
}
}
}
設置方法
- 起動sceneに適当に空のGameObjectを作る
- そこにLocalizationManagerとStartupManagerを貼り付ける
- 翻訳したいTextオブジェクトにAddComponentsでLocalizedTextを選択しKeyにjsonのkeyに指定したtitle1などと入れる。
無事翻訳できた。
初回sceneで翻訳されない場合
StartupManagerのクラスの上に[DefaultExecutionOrder(-1)]を記述して実行順をどのsceneよりも早くロードするように
[DefaultExecutionOrder(-1)]
public class StartupManager : MonoBehaviour {
手動で切り替え
手動でやりたい場合は以下のようにすると良い。
LocalizationManager.instance.LoadLanguage("ja");
Scriptで文言を出す
LocalizationManager.instance.GetLocalizedValue("welcome")
日本語以外のとき翻訳
LocalizationManager localizationManager = LocalizationManager.instance;
if (localizationManager != null)
{
if (!localizationManager.GetLanguage().Equals("ja"))
{
GameObject.Find("HelloButton/Text").GetComponent<Text>().text = localizationManager.GetLocalizedValue("hello");
}
}
翻訳キーを動的に変更する場合
Awakeに以下を入れると、keyがcompleteになり、文字がStart時に反映される。
GameObject.Find("EditButton/Text").GetComponent<LocalizedText>().key = "complete";
Androidのアプリタイトルの多言語化
Assets/Plugins/Android/res/values-ja/strings.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">タイトル1</string>
</resources>
Androidの場合は読み込めない
StreamingAssetsではAndroidの場合は読み込めないのでResourcesに移動してある
参考:https://teratail.com/questions/169361