.NET - Globalizace a lokalizace aplikací (2.)
Toto je druhá část tutoriálu, ve kteý se zabývá globalizovatelnými a lokalizovatelnými aplikacemi. V prvním díle jsem psal o globalizaci aplikací, což znamená že aplikace funguje korektně v libovolném prostředí a také se podle tohoto nastavení chová.
V tomto druhém díle se dočtete o tom jak vytvářet lokalizovatelné aplikace, které lze snadno překládat do různých jazyků (tedy lokalizovat), protože takovéto aplikace mají oddělené zdroje, které jsou závislé na jazyce od samotného kódu.
Více o probíraných tématech naleznete například v MSDN v sekci Planning World-Ready Applications [1].
Co se dočtete v této části tutoriálu
- Možné postupy při lokalizování webových aplikací
- Práce s resources pomocí třidy
ResourceManager
- Lokalizace WinForms aplikací
Lokalizace webových aplikací
Při lokalizaci webových aplikací lze zvolit několik možných přístupů podle typu aplikace.
Pokud se jedná o aplikaci s větším množstvím statických textů, je nejjednodušší možností
zkopírovat aspx
a ascx
soubory s textovým obsahem do adresářů
podle jazyka a přeložit jejich obsah. Pokud je kód aplikace psán v codebehind souborech
a nejsou v nich žádné texty, není ani potřeba aby pro každý jazyk existovala webová
aplikace, protože stačí nechat zkompilovanou dll
knihovnu v adresáři bin
a jednotlivé lokalizované stránky uložit například do adresářů en
a cs
.
Pokud se jedná o aplikaci kde nejsou příliš rozsáhlé texty, ale může být i velmi rozsáhlá
a komplikovaná je nejlepší možností uložení jazykově specifických zdrojů do takzvaných satellite
assemblies. Jedná se o dll
soubory, které jsou uloženy v adresářové struktuře
určené jazyky v adresáři bin
. K textům uloženým v těchto satellite assemblies
lze poté přistupovat pomocí objektu ResourceManager.
Detekce jazyka
Ať již ve vaší aplikaci zvolíte kterýkoliv z možných přístupů, budete potřebovat
detekovat jaký jazyk má uživatel nastaven jako výchozí. K tomu lze požít HTTP hlavičku
Accept-Languages
(která by měla obsahovat uživatelem preferované jazyky).
V ASP.NET je možné tyto jazyky zjišťovat pomocí pole Request.UserLanguages
,
které obsahuje kódy jednotlivých jazyků. Pokud chcete tedy ve vaší aplikaci rozlišit
české a ostatní uživatele, můžete toho dosáhnout následujícím kódem:
// Pokud ma uzivatel nastavenou cestinu.. foreach(string lang in Request.UserLanguages) { if (lang=="cs") { // .. provede se redirect na ceskou verzi Response.Redirect("cs/default.aspx"); return; } } // .. ostatnim uzivatelum se zobrazi anglicka Response.Redirect("en/default.aspx");
Pokud chcete tento příklad otestovat, tak ve všech prohlížečích naleznete někde v nastavení volbu jazyka. Internet Explorer přebírá toto nastavení z Windows, Firefox má po nainstalování nastavený jazyk na angličtinu (alespoň anglická verze).
Lokalizace pomocí resources
V následující části vytvoříme jednoduchý projekt na kterém se pokusím demonstrovat základní
postupy při tvorbě lokalizovatelných webových aplikací, které mají texty uložené v
resources. Visual studio umí vygenerovat satellite assemblies automaticky, pokud do projektu
přidáte soubor *.resx
s textovými zdroji a jak jsem již zmiňoval lze k nim
přistupovat pomocí třidy ResourceManager
. Vytváření resx
souborů
není ve VS.Net 2003 příliš pohodlné a proto doporučuji například plugin Resource Editor (viz [2] ).
Nejprve do projektu přidáme soubory Texts.resx
(výchozí jazyk) a Texts.cs.resx
(texty v českém jazyce). V následující ukázce se podíváme jak lze z těchto resource souborů
získat texty:
public string GetText(string key) { // 'LocalizationWeb' je vychozi namespace projektu ResourceManager rm=new ResourceManager("LocalizationWeb.Texts", System.Reflection.Assembly.GetExecutingAssembly()); // Pokud neni zadano jinak tak ResourceManager // pouziva jazyk urceny v CurrentUICulture // Zde se nastavi CurrentUICulture podle nastaveni uzivatele Thread.CurrentThread.CurrentUICulture= new CultureInfo(Request.UserLanguages[0]); // .. zjistuje text se zadanym klicem return rm.GetString(key); }
Metoda GetString
umožňuje jako druhý parametr předat objekt typu
CultureInfo
kterým se bude řídit při hledání textu. Pokud zadáte například
en-US
, tak se nejprve pokousí nalézt text, který byl zadán v souboru
Texts.en-US.resx
, pokud neexistuje tak Texts.en.resx
a naposledy Texts.resx
.
Protože toto načítání textů vyžaduje vytváření objektů a nějaké další
operace s nimi nebylo by příliš pohodlné opisovat tento kód pokaždé když potřebujete
načítat text z resources. Proto je dobré vytvořit si pomocnou třídu, která přístup
k resources zjednoduší. V ukázkové aplikaci (kterou naleznete ke stažení na
konci článku) jednu takovou naleznete. Navíc je v ní ještě implementována
možnost změnit jazyk (toto nastavení se ukládá do cookie a je testováno
dříve než se jazyk načte z Request.UserLanguages
).
Další velké usnadnění, které umožní snadno vkládat texty z resources do
aspx
stránek je vytvořit si následující bázovou stránku a od ní
podědit všechny stránky v projektu:
// Bazova stranka umoznujici pristup k resources public class ResPage : System.Web.UI.Page { // Metoda pro nacitani resources - viz predchozi priklad protected string GetText(string key) { // ... } }
Tato bázová třída vám totiž umožní vkládat texty z resources do stránky takto:
<%@@ Page language="c#" Inherits="LocalizationWeb.ResPage" %> <html> <body> <h1><%=GetText("pageHeader") %></h1> </body> </html>
V přiložené ukázce jsou všechny soubory s přeloženými texty (resx
) součástí
projektu a to není nejlepší řešení pokud potřebujete podporu pro další jayzky přidávat
bez překompilování projektu. Lokalizované texty lze ukládat i mimo projekt, ale není to
úplně snadné. Pro více informací se můžete podívat na článek, který k tomuto tématu vyšel
na serveru Interval.cz (viz [3] ).
Lokalizace WinForms aplikací
Lokalizace WinForms aplikací je jednodušší díky zabudované podpoře ve VisualStudiu.Net.
Designer ve kterém se tvoří návrh formulářů totiž umožňuje ukládat automaticky hodnoty
vlastností, které se v něm nastavují do resources (resx
souborů), které
se dále zkompilují do satellite assemblies obdobně jako tomu bylo v předcházejícím
příkladu u webových aplikací. Pokud tedy vytvoříte WinForms aplikaci a chcete přeložit
formulář do jiného jazyka stačí ve vlastnostech formuláře nastavit Localizable
na hodnotu true
. Poté můžete zvolit jazyk (Language
)
a pokud poté provedete nějaké změny (například změnu textu), tak se změny uloží
pouze pro právě vybraný jazyk.
Na obrázku vlevo je naznačeno jak umožnit formuláři aby byl lokalizovatelný. Na obrázku
v pravo je poté vidět jakou strukturu resource soubourů Visual Studio vytváří. V souboru
MainForm.resx
je výchozí nastavení (které se použije pro všechny jazyky pro
které neexistuje specifický resx
soubor). V MainForm.cs.resx
a
MainForm.en.resx
jsou uloženy změny, které byly provedeny v době, kdy byla
vybrána jako jazyk čeština (respektive angličtina).
Pokud se podíváte do vygenerovaného zdrojového kódu, naleznete přibližně toto (bez připsaných komentářů):
private void InitializeComponent() { // Zde se vytvori resource manager pro formular MainForm System.Resources.ResourceManager resources= new System.Resources.ResourceManager(typeof(MainForm)); // ... vytvareni ovladacich prvku ...// Lokalizovane vlastnosti se nacitaji z resources this.label1.Enabled = ((bool)(resources.GetObject("label1.Enabled"))); this.label1.Font = ((System.Drawing.Font)(resources.GetObject("label1.Font"))); this.label1.Text = resources.GetString("label1.Text"); // ... }
Lokalizace tedy používá již známý objekt ResourceManager
.
Nejedná se tedy o nic tajemného, ale je to velmi přijemné zjdednodušení práce.
Pokud ve vaší aplikaci potřebujete načítat nějaké další texty (například
chybová hlášení), můžete postupovat stejně jako u webových aplikací tak, že
přidáte další resx
soubor (a jeho jazykové mutace) ve kterém budete
ukládat vaše texty.
Na obrázku v pravo vidíte, jak se ukázková aplikace zobrazí ve dvou různých jazycích.
Abych mohl takvýto screenshot pořídit přidal jsem do aplikace ještě možnost změnit
před spuštěním jazyk. Stejně jako u webových aplikací i zde načítá objekt
ResourceManager
data z resources podle nastavení CurrentUICulture
.
Můžete tedy ve vaší aplikaci měnit CurrentUICulture
a tak změnit jazyk
ve kterém se aplikace spustí. Tuto změnu je ale potřeba provést před tím, než se
spustí metoda InitializeComponent
, tj. v metodě Main
před voláním Application.Run
:
static void Main() { // Umozni uzivateli zmenit jazyk.. DialogResult ret=MessageBox.Show( "Click 'Yes' if you want to run english version of application.\n"+ "Kliknete na 'Ne' pokud chcete spustit ceskou verzi aplikace.\n"+ "Pokud kliknete na 'Cancel' pouzije se aktualni nastaveni", "Localization",MessageBoxButtons.YesNoCancel); if (ret==DialogResult.Yes) { // zmenime CurrentUICulture na anglictinu Thread.CurrentThread.CurrentUICulture= CultureInfo.CreateSpecificCulture("en"); } else if (ret==DialogResult.No) { // zmenime CurrentUICulture na cestinu Thread.CurrentThread.CurrentUICulture= CultureInfo.CreateSpecificCulture("cs"); } // a spustit aplikaci v danem jazyce.. Application.Run(new MainForm()); }
Soubory na stažení a odkazy
- [1] Overview of Globalization and Localization [^] - MSDN
- [2] Resource Editor for VS.NET 2003 [^] - CodeProject.com a novější verze [^] - Weblog autora
- [3] Vícejazyčné aplikace a autodetekce preferovaného jazyka v ASP.NET [^] - Interval.cz