「Unity/多言語化」の版間の差分
提供: 初心者エンジニアの簡易メモ
(内容を「==翻訳ファイルサンプル== AndroidでStreamingAssetsが取得できなかったので、Resourcesに入れた。 Assets/Resources/Localization/localizedText_ja.js...」で置換) |
|||
行1: | 行1: | ||
+ | ==ダウンロード== | ||
+ | https://learn.unity.com/tutorial/recorded-video-session-localization-tools/?tab=detail#5c7f8528edbc2a002053b671 | ||
+ | <pre> | ||
+ | LocalizationData.cs | ||
+ | LocalizationManager.cs | ||
+ | StartupManager.cs | ||
+ | LocalizedText.cs | ||
+ | LocalizedTextEditor.cs | ||
+ | </pre> | ||
+ | |||
==翻訳ファイルサンプル== | ==翻訳ファイルサンプル== | ||
AndroidでStreamingAssetsが取得できなかったので、Resourcesに入れた。 | AndroidでStreamingAssetsが取得できなかったので、Resourcesに入れた。 | ||
行20: | 行30: | ||
} | } | ||
</pre> | </pre> | ||
+ | |||
+ | ==上記DLしたファイル設定とカスタマイズ== | ||
+ | LocalizationData.cs | ||
+ | <pre> | ||
+ | [System.Serializable] | ||
+ | public class LocalizationData | ||
+ | { | ||
+ | public LocalizationItem[] items; | ||
+ | } | ||
+ | |||
+ | [System.Serializable] | ||
+ | public class LocalizationItem | ||
+ | { | ||
+ | public string key; | ||
+ | public string value; | ||
+ | } | ||
+ | </pre> | ||
+ | LocalizationManager.cs | ||
+ | <pre> | ||
+ | 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"; | ||
+ | |||
+ | // Use this for initialization | ||
+ | void Awake () | ||
+ | { | ||
+ | if (instance == null) { | ||
+ | instance = this; | ||
+ | } else if (instance != this) | ||
+ | { | ||
+ | Destroy (gameObject); | ||
+ | } | ||
+ | DontDestroyOnLoad (gameObject); | ||
+ | } | ||
+ | public void LoadLocalizedText(string fileName)//, Font font) | ||
+ | { | ||
+ | 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; | ||
+ | } | ||
+ | } | ||
+ | </pre> | ||
+ | StartupManager.cs | ||
+ | <pre> | ||
+ | using System.Collections; | ||
+ | using System.Collections.Generic; | ||
+ | using UnityEngine; | ||
+ | using UnityEngine.SceneManagement; | ||
+ | |||
+ | public class StartupManager : MonoBehaviour { | ||
+ | |||
+ | // Use this for initialization | ||
+ | private IEnumerator Start () | ||
+ | { | ||
+ | while (!LocalizationManager.instance.GetIsReady ()) | ||
+ | { | ||
+ | yield return null; | ||
+ | } | ||
+ | |||
+ | SceneManager.LoadScene ("MenuScreen"); | ||
+ | } | ||
+ | |||
+ | } | ||
+ | </pre> | ||
+ | LocalizedText.cs | ||
+ | <pre> | ||
+ | using System.Collections.Generic; | ||
+ | using UnityEngine; | ||
+ | using UnityEngine.UI; | ||
+ | |||
+ | public class LocalizedText : MonoBehaviour { | ||
+ | |||
+ | public string key; | ||
+ | |||
+ | void Start () | ||
+ | { | ||
+ | Text text = GetComponent<Text> (); | ||
+ | LocalizationManager manager = LocalizationManager.instance; | ||
+ | if (manager == null) | ||
+ | { | ||
+ | return; | ||
+ | } | ||
+ | string str = manager.GetLocalizedValue(key); | ||
+ | if (str == null) | ||
+ | { | ||
+ | return; | ||
+ | } | ||
+ | Debug.Log("LocalizedText key=" + key); | ||
+ | text.text = str; | ||
+ | } | ||
+ | |||
+ | } | ||
+ | </pre> | ||
+ | LocalizedTextEditor.cs | ||
+ | <pre> | ||
+ | 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 (); | ||
+ | } | ||
+ | } | ||
+ | </pre> | ||
+ | LocalizationManagerStarter.cs | ||
+ | <pre> | ||
+ | using System.Collections; | ||
+ | using UnityEngine; | ||
+ | |||
+ | [DefaultExecutionOrder(-1)] | ||
+ | public class LocalizationManagerStarter : MonoBehaviour | ||
+ | { | ||
+ | IEnumerator Start() | ||
+ | { | ||
+ | var lang = Application.systemLanguage; | ||
+ | string setlang = ""; | ||
+ | if (lang == SystemLanguage.Japanese) | ||
+ | { | ||
+ | setlang = "localizedText_ja.json"; | ||
+ | } | ||
+ | else if (lang == SystemLanguage.ChineseSimplified) | ||
+ | { | ||
+ | setlang = "localizedText_zh-Hans.json"; | ||
+ | } | ||
+ | else if (lang == SystemLanguage.ChineseTraditional) | ||
+ | { | ||
+ | setlang = "localizedText_zh-Hant.json"; | ||
+ | } | ||
+ | else | ||
+ | { | ||
+ | setlang = "localizedText_en.json"; | ||
+ | } | ||
+ | LocalizationManager manager = LocalizationManager.instance; | ||
+ | manager.LoadLocalizedText(setlang); | ||
+ | while (!LocalizationManager.instance.GetIsReady()) yield return null; | ||
+ | } | ||
+ | } | ||
+ | </pre> | ||
+ | ==設置方法== | ||
+ | #起動sceneに適当に空のGameObjectを作る | ||
+ | #そこにLocalizationManagerとLocalizationManagerStarterを貼り付ける | ||
+ | #翻訳したいTextオブジェクトにAddComponentsでLocalizedTextを選択しKeyにjsonのkeyに指定したtitle1などと入れる。 | ||
+ | |||
+ | 無事翻訳できた。 | ||
+ | |||
+ | ==アプリタイトル多言語== | ||
+ | Assets/Plugins/Android/res/values-ja/strings.xml | ||
+ | <pre> | ||
+ | <?xml version="1.0" encoding="utf-8"?> | ||
+ | <resources> | ||
+ | <string name="app_name">タイトル1</string> | ||
+ | </resources> | ||
+ | </pre> | ||
+ | |||
+ | ==Androidの場合は読み込めない== | ||
+ | StreamingAssetsではAndroidの場合は読み込めないのでResourcesに移動する必要がある。 | ||
+ | |||
+ | 参考:https://teratail.com/questions/169361 | ||
+ | |||
+ | ==参考== | ||
+ | https://www.growthsoftware.jp/unity-multilang/ | ||
+ | |||
+ | https://qiita.com/chocho/items/c32e75bf498d8beec08f |
2020年5月19日 (火) 13:57時点における版
ダウンロード
LocalizationData.cs LocalizationManager.cs StartupManager.cs LocalizedText.cs LocalizedTextEditor.cs
翻訳ファイルサンプル
AndroidでStreamingAssetsが取得できなかったので、Resourcesに入れた。
Assets/Resources/Localization/localizedText_ja.json
{ "items":[ {"key":"title","value":"タイトル1"}, {"key":"edit","value":"編集1"} ] }
Assets/Resources/Localization//localizedText_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"; // Use this for initialization void Awake () { if (instance == null) { instance = this; } else if (instance != this) { Destroy (gameObject); } DontDestroyOnLoad (gameObject); } public void LoadLocalizedText(string fileName)//, Font font) { 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; } }
StartupManager.cs
using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.SceneManagement; public class StartupManager : MonoBehaviour { // Use this for initialization private IEnumerator Start () { while (!LocalizationManager.instance.GetIsReady ()) { yield return null; } SceneManager.LoadScene ("MenuScreen"); } }
LocalizedText.cs
using System.Collections.Generic; using UnityEngine; using UnityEngine.UI; public class LocalizedText : MonoBehaviour { public string key; void Start () { Text text = GetComponent<Text> (); LocalizationManager manager = LocalizationManager.instance; if (manager == null) { return; } string str = manager.GetLocalizedValue(key); if (str == null) { return; } Debug.Log("LocalizedText key=" + key); text.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 (); } }
LocalizationManagerStarter.cs
using System.Collections; using UnityEngine; [DefaultExecutionOrder(-1)] public class LocalizationManagerStarter : MonoBehaviour { IEnumerator Start() { var lang = Application.systemLanguage; string setlang = ""; if (lang == SystemLanguage.Japanese) { setlang = "localizedText_ja.json"; } else if (lang == SystemLanguage.ChineseSimplified) { setlang = "localizedText_zh-Hans.json"; } else if (lang == SystemLanguage.ChineseTraditional) { setlang = "localizedText_zh-Hant.json"; } else { setlang = "localizedText_en.json"; } LocalizationManager manager = LocalizationManager.instance; manager.LoadLocalizedText(setlang); while (!LocalizationManager.instance.GetIsReady()) yield return null; } }
設置方法
- 起動sceneに適当に空のGameObjectを作る
- そこにLocalizationManagerとLocalizationManagerStarterを貼り付ける
- 翻訳したいTextオブジェクトにAddComponentsでLocalizedTextを選択しKeyにjsonのkeyに指定したtitle1などと入れる。
無事翻訳できた。
アプリタイトル多言語
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