Pelokalan teks apa pun

Sebagian besar permainan menggunakan pelokalan berbasis kunci, yaitu, diperlukan kunci untuk menggambarkan teks tertentu, tetapi saya menawarkan opsi yang lebih baik, meskipun opsi ini tidak cocok untuk mereka yang memiliki akting suara dalam permainan, lebih mudah melalui kunci.

Apa itu kunci dan mengapa itu dibutuhkan


Kuncinya, atau lebih tepatnya kata kunci, adalah kata yang dengannya akan ditentukan teks mana yang dibutuhkan, dan kemudian pencarian untuk bahasa yang dipilih sudah berlangsung. Contoh kata kunci: scene_Escape_from_jail_Ethan_dialog_with_Mary_3 , ya, kuncinya akan terlihat seperti ini jika game Anda memiliki banyak adegan, plot besar. Saya sarankan segera segera menulis frasa dalam salah satu bahasa, paling sering bahasa Inggris atau yang programmer fasih. Ngomong-ngomong, karena semua frasa bahasa saat ini dan bahasa utama akan terletak pada RAM, itu akan lebih produktif daripada mendapatkannya dari file setiap kali, untuk gim besar, Anda dapat sedikit memodifikasi file untuk setiap adegan.

Bagaimana semuanya akan diatur


Dalam tindakan yang dijelaskan di bawah ini, kelas Lang statis akan digunakan, di mana semua pencarian kata / frasa akan dilakukan. Mari kita mendeklarasikan kelas dengan menghubungkan perpustakaan yang kita butuhkan:

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 } 

Jadi, kami tidak dapat melakukannya tanpa pustaka standar, karena kami akan mendapatkan file dari sumbernya, kami dapat mengunduhnya dengan cara yang nyaman, tetapi lebih mudah dan praktis. Pustaka sistem diperlukan untuk menghubungkan daftar, kamus, dan bekerja dengan file dari editor. Pustaka UnityEditor hanya diperlukan untuk memperbarui file selama catatan frase pertama, karena setelah restart cepat, semua frasa tidak akan selalu dimuat, tetapi dengan bantuan perpustakaan ini kita bisa menyelesaikan masalah ini. Kelas menyimpan dua bidang statis, biarlah itu nama-nama file, dalam kasus kami path adalah folder dengan sumber daya, dan mungkin ada nama file.

Sekarang Anda perlu menambahkan daftar untuk menyimpan semua yang digunakan oleh bahasa dan kamus.

 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 

Bidang LangIndex akan menyimpan indeks bahasa saat ini relatif terhadap catatan dalam file. Dalam daftar bahasa - semua bahasa yang digunakan dalam file akan direkam. Kamus akan menyimpan semua frasa dalam bahasa utama dan bahasa saat ini.

Penting untuk menambahkan inisialisasi bidang yang dijelaskan di atas dari kelas.

Kode
 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; } 

Ini akan segera menggunakan arahan built-in sehingga tidak akan melakukan tindakan yang tidak perlu setelah kompilasi aplikasi. Panggilan ke Lang.Starting (...) harus seperti ini:

 #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 


Panggilan saat bermain di editor harus berisi dua parameter utama, ini adalah frasa bahasa apa yang harus diterjemahkan sekarang, dan bahasa mana yang akan digunakan sebagai bahasa utama, semua parameter lain adalah parameter bahasa yang harus terkandung dalam file, parameter ini hanya diperlukan selama peluncuran pertama, ketika file belum dibuat (dan tidak perlu untuk menghapusnya nanti), jika tidak, jika Anda perlu menambahkan beberapa bahasa, Anda perlu menyalin semuanya dari file, menghapus file, dan menjalankan kembali kode dalam editor atau menambahkannya ke file sendiri.

Kode di atas menggunakan metode SystemLanguageParse (...) , yang hanya menerjemahkan nama bahasa dari tipe string ke SystemLanguage (metode ini akan lebih rendah).

Mari kita bahas metode 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 

Karena metode ini hanya akan digunakan ketika mulai dari editor, kita dapat menggunakan utilitas sistem dengan aman untuk menimpa file, serta memperbarui file yang diubah ke editor menggunakan metode Refresh (). Di antara tindakan-tindakan ini, frasa hanya ditambahkan ke kamus, untuk melindungi diri Anda dari perekaman ulang di sesi yang sama.

Ngomong-ngomong, saya lupa mengatakan bahwa frasa akan disimpan dalam file .csv, yang memungkinkan kita menerjemahkan frasa ke Excele dengan nyaman. Sekarang kita perlu menambahkan metode yang baik untuk kita, yang akan memungkinkan kita untuk mengubah bahasa:

  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]); } } 

Jadi, kami sampai pada metode yang paling penting, yang akan mengambil frasa dalam bahasa utama dan mengeluarkannya ke pengguna yang tepat:

  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; } 

Metode ini hanya mengambil frasa dalam bahasa utama, kemudian mengulangi semua yang ada di kamus, menemukan frasa tersebut dengan kunci, memberi kita nilai-nilai kunci ini, yang merupakan frasa dalam bahasa yang kita butuhkan. Anda dapat menggunakan metode ini dengan satu baris kode sederhana:

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

Sekarang frasa dalam bahasa yang kita butuhkan akan masuk ke string str, jika tiba-tiba hilang, maka frasa yang ditentukan dalam parameter, yaitu, Hello world, akan jatuh.

Metode ini dapat sedikit ditingkatkan, sehingga Anda dapat mengambil argumen untuk mengisi:

  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); } 

Sekarang metode ini dapat dipanggil seperti sebelumnya:

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

Tetapi sekarang metode kami telah memformat output, menunjukkan parameter yang dipisahkan oleh koma:

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

Terjemahan frasa


Seperti yang saya tulis di atas, file tersebut menggunakan ekstensi .csv yang akan memungkinkan Anda untuk melakukan segalanya di Excel, tetapi tidak begitu sederhana, masalah C-sharpe dan Excel adalah mereka memahami alfabet Cyrillic dalam pengkodean berbeda, Excel hanya memahami pengkodean UTF-8-BOM atau yang tidak dimengerti oleh YaP, kita harus menggunakan hanya UTF-8 di dalamnya, meskipun editor kesatuan akan mengerti UTF-8-BOM, dalam kode ada dua kata yang identik pada pengkodean yang berbeda (UTF-8 dan UTF-8- BOM) tidak akan sama, yang akan mengarah pada penambahan konstan kata-kata identik ke file kita.

Kita dapat menyandikan file menggunakan NotePad ++ gratis dengan mengunduhnya dari mati. situs Mengedit file tidak akan menimbulkan masalah bagi Anda, untuk menambahkan satu kata Anda bahkan dapat menggunakan editor teks, note pad yang sama atau bahkan lingkungan pemrograman kami.

Kode akhir
 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; } } 

Hal utama yang perlu diingat: UTF-8-BOM - untuk bekerja di Excel, UTF-8 untuk bekerja dengan kode, jangan lupa.

Source: https://habr.com/ru/post/id446844/


All Articles