テキストのローカライズ

ほとんどのゲームはキーベースのローカライズを使用します。つまり、特定のテキストを説明するためにキーが必要です。しかし、私はより良いオプションを提供します。



キーとは何か、なぜ必要なのか



キー、またはキーワードは、必要なテキストを決定するための単語であり、選択した言語の検索はすでに進行中です。 キーワードの例: scene_Escape_from_jail_Ethan_dialog_with_Mary_3 、はい、ゲームに多くのシーン、大きなプロットがある場合、キーは次のようになります。 言語の1つ、ほとんどの場合英語、またはプログラマーが流oneな言語ですぐにフレーズを直接書くことをお勧めします。 ちなみに、現在の言語とメイン言語のすべてのフレーズはRAMにあるため、ファイルから毎回取得するよりも生産性が高くなります。大規模なゲームでは、シーンごとにファイルをわずかに変更できます。



すべての配置方法



以下で説明するアクションでは、静的なLangクラスが使用されます。このクラスでは、すべての単語/フレーズの検索が行われます。 必要なライブラリを接続してクラスを宣言しましょう:



using UnityEngine; using System.Collections.Generic; // list and dictionary #if UNITY_EDITOR using UnityEditor; using System.IO; // created file in editor #endif public class Lang { private const string Path = "/Resources/"; // path to resources folder private const string FileName = "Language"; // file name with phrases }
      
      





したがって、リソースからファイルを取得するため、標準ライブラリなしでは実行できません。任意の便利な方法でダウンロードできますが、より便利で実用的です。 リスト、辞書を接続し、エディターからファイルを操作するには、システムライブラリが必要です。 UnityEditorライブラリは、フレーズの最初の記録中にファイルを更新するためにのみ必要です。 クイックリスタート後、すべてのフレーズが常に読み込まれるとは限りませんが、このライブラリを使用してこの問題を解決できます。 クラスには2つの静的フィールドが格納されます。ファイルの名前を使用します。この場合、パスはリソースのあるフォルダーであり、ファイルの名前は任意です。



次に、リストを追加して、言語と辞書で使用されるすべてを保存する必要があります。



 private static int LangIndex; // variable to store the index of the current language private static List<SystemLanguage> languages = new List<SystemLanguage>(); // having languages in game private static Dictionary<string, string> Phrases = new Dictionary<string, string>(); // keys and values
      
      





LangIndexフィールドは、ファイル内のレコードに関連する現在の言語のインデックスを保持します。 言語リスト-ファイルで使用されるすべての言語が記録されます。 辞書には、すべてのフレーズがメイン言語と現在の言語で保存されます。



上記のクラスのフィールドの初期化を追加する必要があります。



コード
 public static bool isStarting // bool for check starting { get; private set; } public static SystemLanguage language // return current language { get; private set; } #if UNITY_EDITOR public static void Starting(SystemLanguage _language, SystemLanguage default_language = SystemLanguage.English, params SystemLanguage[] _languages) // write languages without main language, it self added #else public static void Starting(SystemLanguage _language = SystemLanguage.English) // main language - only for compilation #endif { #if UNITY_EDITOR if (!File.Exists(Application.dataPath + Path + FileName + ".csv")) // if file wasn't created { File.Create(Application.dataPath + "/Resources/" + FileName + ".csv").Dispose(); // create and lose link File.WriteAllText(Application.dataPath + "/Resources/" + FileName + ".csv", SetLanguage(default_language, _languages)); // write default text with index } #endif string[] PhrasesArr = Resources.Load<TextAsset>(FileName).text.Split('\n'); // temp var for write in dicrionary string[] string_languages = PhrasesArr[0].Split(';'); // string with using languages int _length = string_languages.Length - 1; for (int i = 0; i < _length; i++) { languages.Add(SystemLanguageParse(string_languages[i])); // string language to SystemLanguage } LangIndex = FindIndexLanguage(_language); // index with current language for (int i = 0; i < PhrasesArr.Length; i++) // add keys and value { string[] temp_string = PhrasesArr[i].Split(';'); if (temp_string.Length > LangIndex) Phrases.Add(temp_string[0], temp_string[LangIndex]); else Phrases.Add(temp_string[0], temp_string[0]); } isStarting = true; }
      
      





アプリケーションのコンパイル後に不要なアクションを実行しないように、組み込みのディレクティブをすぐに使用します。 Lang.Startingの呼び出し(...)は次のようになります。



 #if !UNITY_EDITOR Lang.Starting(LANGUAGE); #else Lang.Starting(LANGUAGE, SystemLanguage.English, SystemLanguage.Russian, SystemLanguage.Ukrainian); #endif private static int FindIndexLanguage(SystemLanguage _language) // finding index or current language { int _index = languages.IndexOf(_language); if (_index == -1) // if language not found return 0; // return main language return _index; } #if UNITY_EDITOR private static void Add(string AddString) // add phrases only form editor { File.AppendAllText(Application.dataPath + "/Resources/" + FileName +".csv", AddString + "\n"); // rewrite text to file Phrases.Add(AddString, AddString); // add phrase to dicrionary AssetDatabase.Refresh(); // refresh file } #endif #if UNITY_EDITOR private static string SetLanguage(SystemLanguage default_language, params SystemLanguage[] _languages) // set first string to file { string ret_string = ""; ret_string += default_language + ";"; foreach (SystemLanguage _language in _languages) { ret_string += _language + ";"; } return ret_string + "!@#$%\n"; // for last index } #endif
      
      







エディターで再生するときの呼び出しには2つの主要なパラメーターが含まれている必要があります。これは、現在どの言語フレーズを翻訳し、どの言語を主要言語として使用するか、他のすべてのパラメーターはファイルに含める必要がある言語パラメーターです。これらのパラメーターは最初の起動時にのみ必要です。ファイルがまだ作成されていない場合(および後で削除する必要はありません)、そうでない場合は、言語を追加する必要がある場合は、ファイルからすべてをコピーし、ファイルを削除し、エディターでコードを再起動するか、自分でファイルに追加する必要があります



上記のコードはSystemLanguageParse(...)メソッドを使用します。このメソッドは、言語名を文字列型からSystemLanguageに単純に変換します(このメソッドの方が低くなります)。



addメソッドについて詳しく見てみましょう。



 #if UNITY_EDITOR private static void Add(string AddString) // add phrases only form editor { File.AppendAllText(Application.dataPath + "/Resources/" + FileName +".csv", AddString + "\n"); // rewrite text to file Phrases.Add(AddString, AddString); // add phrase to dicrionary AssetDatabase.Refresh(); // refresh file } #endif
      
      





このメソッドはエディターから起動するときにのみ使用されるため、システムユーティリティを安全に使用してファイルを上書きし、Refresh()メソッドを使用して変更されたファイルをエディターに更新できます。 これらのアクションの間に、同じセッションでの再記録から身を守るために、フレーズを辞書に追加するだけです。



ちなみに、フレーズは.csvファイルに保存されることを忘れていました。これにより、フレーズを快適にExceleに変換できます。 ここで、言語を変更できる適切なメソッドを追加する必要があります。



  public static void ChangeLanguage(SystemLanguage _language) // change language { string[] PhrasesArr = Resources.Load<TextAsset>(FileName).text.Split('\n'); // load all text from file LangIndex = FindIndexLanguage(_language); Phrases.Clear(); // clear dictionary with phrases for (int i = 1; i < PhrasesArr.Length; i++) { string[] temp_string = PhrasesArr[i].Split(';'); if (temp_string.Length > LangIndex) Phrases.Add(temp_string[0], temp_string[LangIndex]); else Phrases.Add(temp_string[0], temp_string[0]); } }
      
      





そこで、最も重要な方法に到達しました。この方法では、メイン言語でフレーズを取得し、適切なユーザーに発行します。



  public static string Phrase(string DefaultPhrase) // translate phrase, args use to formating string { #if UNITY_EDITOR if (!isStarting) // if not starting { throw new System.Exception("Forgot initialization.Use Lang.Starting(...)"); // throw exception } #endif string temp_EnglishPhrase = DefaultPhrase; // temp variable for try get value if (Phrases.TryGetValue(DefaultPhrase, out DefaultPhrase)) // if value has been found { return temp_EnglishPhrase; } #if UNITY_EDITOR Add(temp_EnglishPhrase); // add phrase if value hasn't been found #endif return temp_EnglishPhrase; }
      
      





このメソッドは、単にメイン言語のフレーズを取得し、辞書にあるすべてのものを反復処理し、キーでそのようなフレーズを見つけ、必要な言語のフレーズであるこのキーの値を提供します。 このメソッドは、簡単なコード行で使用できます。



 string str = Lang.Phrase("Hello world");
      
      





これで、必要な言語のフレーズが文字列strに入れられますが、突然欠落している場合は、パラメーターで指定されたフレーズ、つまりHello worldが該当します。



このメソッドは少し改善できるため、引数を受け入れて入力できます。



  public static string Phrase(string DefaultPhrase, params string[] args) // translate phrase, args use to formating string { #if UNITY_EDITOR if (!isStarting) // if not starting { throw new System.Exception("Forgot initialization.Use Lang.Starting(...)"); // throw exception } #endif string temp_EnglishPhrase = DefaultPhrase; // temp variable for try get value if (Phrases.TryGetValue(DefaultPhrase, out DefaultPhrase)) // if value has been found { if (args.Length == 0) return DefaultPhrase; return string.Format(DefaultPhrase, args); } #if UNITY_EDITOR Add(temp_EnglishPhrase); // add phrase if value hasn't been found #endif if (args.Length == 0) return temp_EnglishPhrase; return string.Format(temp_EnglishPhrase, args); }
      
      





これで、このメソッドを以前のように呼び出すことができます。



 string str = Lang.Phrase("Hello world");
      
      





しかし、今では、メソッドにはフォーマットされた出力があり、コンマで区切られたパラメーターを示しています。



 string str = Lang.Phrase("Hello {0} from {1}", "world", "habr");
      
      





フレーズ翻訳



上記で書いたように、ファイルは.csv拡張子を使用してExcelですべてを実行できますが、それほど単純ではありません。C字型とExcelの問題は、異なるエンコーディングでキリル文字を理解することです。ExcelはUTF-8-BOMエンコーディングのみを理解しますまたはYaPが理解できないものは、UTF-8のみを使用する必要がありますが、ユニタリエディタはUTF-8-BOMを理解しますが、コードには異なるエンコーディング(UTF-8とUTF-8- BOM)は等しくないため、ファイルに同じ単語が絶えず追加されます。



無料のNotePad ++を使用してファイルをエンコードするには、offからダウンロードします。 サイト。 ファイルを編集しても問題はありません。1つの単語を追加するには、テキストエディタ、同じメモ帳、またはプログラミング環境を使用することもできます。



最終コード
 using UnityEngine; using System.Collections.Generic; // list and dictionary #if UNITY_EDITOR using UnityEditor; using System.IO; // created file in editor #endif public class Lang { private const string Path = "/Resources/"; // path to resources folder private const string FileName = "Language"; // file name with phrases private static int NumberOfLanguage; // variable to store the index of the current language private static List<SystemLanguage> languages = new List<SystemLanguage>(); // having languages in game private static Dictionary<string, string> Phrases = new Dictionary<string, string>(); // keys and values private static SystemLanguage language; // current language #if UNITY_EDITOR public static void Starting(SystemLanguage _language, SystemLanguage default_language, params SystemLanguage[] _languages) // write languages without main language, it self added #else public static void Starting(SystemLanguage _language = SystemLanguage.English) // main language - only for compilation #endif { #if UNITY_EDITOR if (!File.Exists(Application.dataPath + Path + FileName + ".csv")) // if file wasn't created { File.Create(Application.dataPath + "/Resources/" + FileName + ".csv").Dispose(); // create and lose link File.WriteAllText(Application.dataPath + "/Resources/" + FileName + ".csv", SetLanguage(default_language, _languages)); // write default text with index } #endif string[] PhrasesArr = Resources.Load<TextAsset>(FileName).text.Split('\n'); // temp var for write in dicrionary string[] string_languages = PhrasesArr[0].Split(';'); // string with using languages int _length = string_languages.Length - 1; for (int i = 0; i < _length; i++) { languages.Add(SystemLanguageParse(string_languages[i])); // string language to SystemLanguage } NumberOfLanguage = FindIndexLanguage(_language); // index with current language for (int i = 0; i < PhrasesArr.Length; i++) // add keys and value { string[] temp_string = PhrasesArr[i].Split(';'); if (temp_string.Length > NumberOfLanguage) Phrases.Add(temp_string[0], temp_string[NumberOfLanguage]); else Phrases.Add(temp_string[0], temp_string[0]); } isStarting = true; } public static bool isStarting // bool for check starting { get; private set; } public static SystemLanguage Language // return current language { get { return language; } } public static string Phrase(string DefaultPhrase, params string[] args) // translate phrase, args use to formating string { #if UNITY_EDITOR if (!isStarting) // if not starting { throw new System.Exception("Forgot initialization.Use Lang.Starting(...)"); // throw exception } #endif string temp_EnglishPhrase = DefaultPhrase; // temp variable for try get value if (Phrases.TryGetValue(DefaultPhrase, out DefaultPhrase)) // if value has been found { if (args.Length == 0) return DefaultPhrase; return string.Format(DefaultPhrase, args); } #if UNITY_EDITOR Add(temp_EnglishPhrase); // add phrase if value hasn't been found #endif if (args.Length == 0) return temp_EnglishPhrase; return string.Format(temp_EnglishPhrase, args); } public static void ChangeLanguage(SystemLanguage _language) // change language { string[] PhrasesArr = Resources.Load<TextAsset>(FileName).text.Split('\n'); // load all text from file NumberOfLanguage = FindIndexLanguage(_language); Phrases.Clear(); // clear dictionary with phrases for (int i = 1; i < PhrasesArr.Length; i++) { string[] temp_string = PhrasesArr[i].Split(';'); if (temp_string.Length > NumberOfLanguage) Phrases.Add(temp_string[0], temp_string[NumberOfLanguage]); else Phrases.Add(temp_string[0], temp_string[0]); } } private static int FindIndexLanguage(SystemLanguage _language) // finding index or current language { int _index = languages.IndexOf(_language); if (_index == -1) // if language not found return 0; // return main language return _index; } #if UNITY_EDITOR private static void Add(string AddString) // add phrases only form editor { File.AppendAllText(Application.dataPath + "/Resources/" + FileName + ".csv", AddString + "\n"); // rewrite text to file Phrases.Add(AddString, AddString); // add phrase to dicrionary AssetDatabase.Refresh(); // refresh file } #endif #if UNITY_EDITOR private static string SetLanguage(SystemLanguage default_language, params SystemLanguage[] _languages) // set first string to file { string ret_string = ""; ret_string += default_language + ";"; foreach (SystemLanguage _language in _languages) { ret_string += _language + ";"; } return ret_string + "!@#$%\n"; // for last index } #endif private static SystemLanguage SystemLanguageParse(string _language) // just parse from string to SystemLanguage { switch (_language) { case "English": return SystemLanguage.English; case "Russian": return SystemLanguage.Russian; case "Ukrainian": return SystemLanguage.Ukrainian; case "Polish": return SystemLanguage.Polish; case "French": return SystemLanguage.French; case "Japanese": return SystemLanguage.Japanese; case "Chinese": return SystemLanguage.Chinese; case "Afrikaans": return SystemLanguage.Afrikaans; case "Arabic": return SystemLanguage.Arabic; case "Basque": return SystemLanguage.Basque; case "Belarusian": return SystemLanguage.Belarusian; case "Bulgarian": return SystemLanguage.Bulgarian; case "ChineseSimplified": return SystemLanguage.ChineseSimplified; case "ChineseTraditional": return SystemLanguage.ChineseTraditional; case "Czech": return SystemLanguage.Czech; case "Danish": return SystemLanguage.Danish; case "Dutch": return SystemLanguage.Dutch; case "Estonian": return SystemLanguage.Estonian; case "Faroese": return SystemLanguage.Faroese; case "Finnish": return SystemLanguage.Finnish; case "German": return SystemLanguage.German; case "Greek": return SystemLanguage.Greek; case "Hebrew": return SystemLanguage.Hebrew; case "Hungarian": return SystemLanguage.Hungarian; case "Icelandic": return SystemLanguage.Icelandic; case "Indonesian": return SystemLanguage.Indonesian; case "Italian": return SystemLanguage.Italian; case "Korean": return SystemLanguage.Korean; case "Latvian": return SystemLanguage.Latvian; case "Lithuanian": return SystemLanguage.Lithuanian; case "Norwegian": return SystemLanguage.Norwegian; case "Portuguese": return SystemLanguage.Portuguese; case "Romanian": return SystemLanguage.Romanian; case "SerboCroatian": return SystemLanguage.SerboCroatian; case "Slovak": return SystemLanguage.Slovak; case "Slovenian": return SystemLanguage.Slovenian; case "Spanish": return SystemLanguage.Spanish; case "Swedish": return SystemLanguage.Swedish; case "Thai": return SystemLanguage.Thai; case "Turkish": return SystemLanguage.Turkish; case "Vietnamese": return SystemLanguage.Vietnamese; } return SystemLanguage.Unknown; } }
      
      





主なものを覚えておいてください:UTF-8-BOM-Excelで作業する場合、コードで作業する場合はUTF-8を忘れないでください。



All Articles