Lekce 13 - Multilingual (vícejazyková) aplikace
Vyzkoušel jsem několik způsobů na překlad aplikace. Každý z nich má
nějaké výhody a nevýhody. Zkoušel jsem překlad načítaný ze
souboru. Lze lehko modifikovat a uživatel si tak může nadefinovat
lehce i vlastní jazyk. Ovšem překlad v aplikaci se pak řeší strašně.
Poté jsem zkoušel pomocí ***.resx** metodou projetí všech komponent a
najítí k jejich vlastnostem (tooltip, text) odpovídající překlad. Nejvíce
se mi však osvědčila metoda, kterou si nyní ukážeme a to vytvoření si
onech *.resx souborů pro jednotlivé jazyky. A data z nich budeme získávat
pomocí metoda Translate
, která vyhledá zadaný výraz v souboru
a vrátí jeho překlad. Lze takto skládat jednoduše věty a na použití je
to velmi jednoduché. V *.resx souboru je vlastně XML, kde jsou uložený
jednotlivé hodnoty.
Do Properties jsem si přidal složku
Strings v níž jsem si vytvořil soubor s resources
_default.resx
(default se jmenovat nemůže, bže je to klíčové
slovo). Teď přichází ta nejhnusnější část. A to přepsat sem všechny
stringy. Ovšem lze si to zjednodušit. Projet všechny komponenty
foreach (Control c in Controls)
a pokud je to třeba
Label
c is Label
(některé komponenty nemají
vlastnost text) a jeho Text
má nějakou hodnotu
!String.IsNullOrEmpty(c.Text)
tak si ji uložím do souboru. Když
si otevřete onen soubor _default.resx
a sjedete dolů uvidíte jak
se to tam generuje:
<data name="hello" xml:space="preserve"> <value>Ahoj</value> </data>
Takže můžete udělat toto:
foreach (Control c in Controls) { if ((c is Label) && (!String.IsNullOrEmpty(c.text))) { sw.WriteLine("<data name=\"" + c.Name + "\" xml:space=\"preserve\">\r\n" + "<value>" + c.Text + "</value>\r\n" + "</data>" ); } }
Pak to jen přidáte do souboru uložíte a VS si to načte => pohodička.
Pak už soubor jen zduplikujete pojmenujete například cs-CZ.resx
a změníte hodnoty na jejich český ekvivalent.
V aplikaci si vytvoříte nějaký ComboBox a do něj si přidáte třeba:
English Česky
Takto by mohla vypadat třída LangManager
:
public static class LangManager {
Do listu Languages si dáme podporované jazyky, ve stejném pořadí jako jsou v ComboBoxu
public static List<string> Languages = new List<string>() { "en-GB", "cs-CZ" }; public static string currentCulture; public static System.Resources.ResourceManager strings; public static void SetLangFromFile() { string culture = null; if (File.Exists(Global.appDataFolder + "lang.ini")) { using (StreamReader sr = new StreamReader(Global.appDataFolder + "lang.ini", Encoding.UTF8)) { culture = sr.ReadLine(); } } SetLanguage(culture); } public static void SaveLangToFile(string culture) { using (StreamWriter sw = new StreamWriter(Global.appDataFolder + "lang.ini", false, Encoding.UTF8)) { sw.WriteLine(culture); } } public static void SetLanguage(string culture) { if (culture == "cs-CZ") { Thread.CurrentThread.CurrentCulture = new CultureInfo("cs-CZ"); strings = Properties.Strings.cs_CZ.ResourceManager; currentCulture = "cs-CZ"; } else { Thread.CurrentThread.CurrentCulture = new CultureInfo("en-GB"); strings = Properties.Strings._default.ResourceManager; currentCulture = "en-GB"; } } public static string Translate(string name) { if (strings == null) SetLanguage(null); return strings.GetString(name); } }
Při nastavování vybraného jazyka:
languageSelector.SelectedIndex = Global.LangManager.Languages.IndexOf(Global.LangManager.currentCulture);
Ukládání vybraného jazyka:
string culture = "en-GB"; if (languageSelector.SelectedIndex != -1) culture = Global.LangManager.Languages[languageSelector.SelectedIndex]; if (Global.LangManager.currentCulture != culture) { Global.LangManager.SaveLangToFile(culture); Global.LangManager.SetLanguage(culture); Global.OpenForms.mainForm.TranslateForm(); }
Zde je vidět, jak pošéfit překlad za běhu aplikace. Prostě si uděláte nějakou metodu, která přeloží formulář a zavoláte ji.
No a pak už jen voláte
nameTB.Text = LangManager.Translate("name");
