V předcházejícím tutoriálu jsem psal o tom jak vytvářet globalizovatelné aplikace. V tomto druhém díle se podíváme ještě dále a to na tvorbu a lokalizaci vícejazyčných aplikací. Nejprve si ukážeme jak detekovat jazyk uživatele ve webových aplikacích a jak používat třídu ResourceManager k načítání textových zdrojů z resources a na konec se ještě podíváme i na lokalizaci WinForms aplikací.
reklama
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