はじめに
Unity でモバイルアプリを作成するときのローカライズについてです。
共通の string ファイル用意してとか簡単にできるのかと思ったのですがすこしめんどくさそうです。。。
下記を参考にアプリ内文言とアプリ名を日本語と英語表示できるようにしてみました。
アプリ内文言のローカライズ
Application.systemLanguage
で現在の言語設定を取得できるようなのでこれを使用して文言を出し分けます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
public class TextLocalizer : MonoBehaviour { [SerializeField] private string _text_jp; [SerializeField] private string _text_en; void Start() { SetLanguageUI(); } private void SetLanguageUI() { Text text = GetComponent<Text>(); // SerializeFieldでもいいかも? SystemLanguage sl = Application.systemLanguage; switch (sl) { case SystemLanguage.Japanese: if (text) { text.text = _text_jp; } break; default: if (text) { text.text = _text_en; } break; } } } |
上記スクリプトを指定の Text に設定すれば完了です。
コードで文言を設定する場合は _text_jp
とかを public
にして下記のようにするといけるかも?
1 2 3 |
TextLocalizer localizer = GetComponent<TextLocalizer>(); localizer.text_ja = "日本語"; localizer.text_en = "英語"; |
アプリ名のローカライズ
アプリ名のローカライズは Android と iOS で別々に設定しなければいけないようです。
Android
- Assets/Plugins/Android/res フォルダを作成する
- 言語ごとに「values-言語コード」でフォルダを作成する
- string.xml を作成する
string.xml の中身はこんな感じです。
1 2 3 4 |
<?xml version="1.0" encoding="utf-8"?> <resources> <string name="app_name">お天気</string> </resources> |
これで Android のアプリ名のローカライズは完成です。
下記のように aar を作成してアプリ名のローカライズをするのが推奨のようです?
【Unity】Andoridでアプリ名をローカライズするならaarライブラリを作ろう
res フォルダ直下に string.xml を作成すればデフォルトの文言リソースになるのかと思いましたがそういうわけではないようでした。。。
デフォルトのアプリ名は Product Name になるようです(設定によって Product Name 変更で Bundle Identifier と Package Name が変更されてしまうのでそれぞれ Override Default のチェックを ON にしておきましょう)。
iOS
iOS の場合はビルド後に Xcode で InfoPlist を作成しなければいけないようです。
InfoPlist の作成はこちらをどうぞ。
iOSアプリのローカライズ
わりとめんどくさいので下記参考に半自動化しました。
【Unity】[iOS]Xcode projectの Localization 自動化
Assets/Editor 配下に下記スクリプトを置きます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 |
using System.IO; using UnityEditor; using UnityEditor.Callbacks; using System.Collections; using System.Collections.Generic; #if UNITY_IOS using UnityEditor.iOS.Xcode; #endif public class PostXcodeBuild { #if UNITY_IOS private struct InfoPlistInfo { public string key; public string value; public InfoPlistInfo(string key, string value) { this.key = key; this.value = value; } }; private struct LocalizationInfo { public string lang; public InfoPlistInfo[] infoPlist; public LocalizationInfo(string lang, InfoPlistInfo[] infoPlist) { this.lang = lang; this.infoPlist = infoPlist; } }; private static LocalizationInfo[] localizationInfo = { new LocalizationInfo("en", new InfoPlistInfo[] { new InfoPlistInfo("CFBundleDisplayName", "Weather") }), new LocalizationInfo("ja", new InfoPlistInfo[] { new InfoPlistInfo("CFBundleDisplayName", "お天気") }) }; private static void createInfoPlistString(string pjDirPath, LocalizationInfo localizationInfo) { string dirPath = Path.Combine(pjDirPath, "Unity-iPhone Tests"); if (!Directory.Exists(Path.Combine(dirPath, string.Format("{0}.lproj", localizationInfo.lang)))) { Directory.CreateDirectory(Path.Combine(dirPath, string.Format("{0}.lproj", localizationInfo.lang))); } string plistPath = Path.Combine(dirPath, string.Format("{0}.lproj/InfoPlist.strings", localizationInfo.lang)); StreamWriter writer = new StreamWriter(plistPath, false); foreach (InfoPlistInfo info in localizationInfo.infoPlist) { string convertedValue = System.Text.Encoding.UTF8.GetString( System.Text.Encoding.Convert( System.Text.Encoding.Unicode, System.Text.Encoding.UTF8, System.Text.Encoding.Unicode.GetBytes(info.value) ) ); writer.WriteLine(string.Format(info.key + " = \"{0}\";", convertedValue)); } writer.Close(); } private static void addKnownRegions(string pjDirPath, LocalizationInfo[] infoList) { string tmpString = ""; string pjPath = PBXProject.GetPBXProjectPath(pjDirPath); foreach (LocalizationInfo info in infoList) { tmpString += "\t\t" + info.lang + ",\n"; } tmpString += "\t\t);\n"; StreamReader reader = new StreamReader(pjPath); string text = ""; string tmpLine = ""; while (reader.Peek() >= 0) { tmpLine = reader.ReadLine(); if (tmpLine.IndexOf("knownRegions") != -1) { text += tmpLine + "\n"; text += tmpString; while (true) { tmpLine = reader.ReadLine(); if (tmpLine.IndexOf(");") != -1) { break; } } } else { text += tmpLine + "\n"; } } reader.Close(); StreamWriter writer = new StreamWriter(pjPath, false); writer.Write(text); writer.Close(); } [PostProcessBuild] public static void SetXcodePlist(BuildTarget buildTarget, string pathToBuiltProject) { if (buildTarget != BuildTarget.iOS) { return; } foreach (LocalizationInfo info in localizationInfo) { createInfoPlistString(pathToBuiltProject, info); } addKnownRegions(pathToBuiltProject, localizationInfo); } #endif } |
これでビルドすると Unity-iPhone Tests の InfoPlist にアプリ名が設定されます。これだけだと不十分で設定を反映するには下記の操作が必要になります。
- Localization の Japanese にチェック
- ダイアログの Use file 選択
- Target Membership の Unity-iPhone にチェック
完全自動ではないですがこれだけでも十分楽になりました。
おわりに
無事 iOS, Android のローカライズ対応ができました。ダークモード対応もしたかったのですがどちらもネイティブプラグインが必要そうなのでいったんあきらめます。。。
まだまだ Unity さわり始めたばかりなので下記の本で勉強中。
ステップアップUnity──プロが教える現場の教科書 WEB DB PRESS plus 新品価格 |
コメント