Screencast, který jsem svého času vytvořil pro MSTV.cz
Slides a dema ke screencastu:
Viz též:
Screencast, který jsem svého času vytvořil pro MSTV.cz
Slides a dema ke screencastu:
Viz též:
Slides a dema z přednášky na konferenci TechEd Praha 2009:
Z přednášky nebyl pořizován záznam, část tématiky o web.config transformacích lze najít ve v podobě screencastu, který jsem svého času dělal pro MSTV.cz.
Slides a dema z přednášky na konferenci SQL DevCon 2008:
Z přednášky byl pořizován záznam, který najdete na našem YouTube Channelu:
Předesílám, že se v tomto článku budu zabývat výhradně explicitní lokalizací webových projektů, tedy přímým odkazováním na resources pomocí <%$ Resources: … %>, popř. metod GetLocalResourceObject() nebo GetGlobalResourceObject(). Osobně mám tuto metodu radši, protože mám přesně pod explicitní kontrolou každý bajt, který chci lokalizovat.
Co všechno je tedy pro úspěšnou implementaci lokalizace udělat?
Předpokládám běžnou práci ve Visual Studiu nebo Web Developer Express, nebudu se tedy zabývat takovými věcmi jako je resgen. VS/WDE přímo podporují přehledné vytváření a editaci .resx souborů.
Důležité je, že rozlišujeme dva typy resources:
Resource-file vytvoříme snadno, ve VS/WDE prostě vytvoříme příslušnou složku a do ní přes Add přidáme položku typu Resource. Resource soubor .resx je ve skutečnosti XML souborem, který je přibuildován do assembly, pozadí však nechme stranou.
Po otevření .resx souboru se nám standardně zobrazí grid pro editaci/přidávání objektů typu string. Resource nemusí být jen typu string, ale například i obrázky, ikony, zvuky, soubory nebo obecné objekty, nicméně pro běžnou lokalizaci si naprosto vystačíme s typem String, protože ve webových aplikací i u obrázků a ostatních objektů obvykle „lokalizujeme“ jen odkaz na příslušný soubor na disku (ImageUrl = „vlajka_cz.gif“) spíše než samotné soubory.
V praxi .resx záznamy v .resx souborech vznikají současně s prvním odkazem na ně, přistupme tedy k použití ve stránce/kódu.
Explicitní použití resource ve stránce je primitivní, v tagu controlu, všude, kde lze přiřadit string, stačí zapsat odkaz
<asp:Localize Text="<%$ Resources: UvodniText %>" ... runat="server" /> <asp:Label Text="<%$ Resources: Glossary, Telefon %>" ... runat="server" /> <asp:Image ImageUrl="<%$ Resources: Images, Vlajka %>" ... runat="server" />
Pozor, že nejde použít <%$ … %> mimo serverové tagy, pro takový účel slouží právě nový control Localize, který není ničím jiným než Literalem s lepší design-time podporou.
Pro použití resources v kódu je několik možností
public static object GetGlobalResourceObject(string classKey, string resourceKey);
public static object GetGlobalResourceObject(string classKey, string resourceKey, CultureInfo culture);
public static object GetLocalResourceObject(string virtualPath, string resourceKey);
public static object GetLocalResourceObject(string virtualPath, string resourceKey, CultureInfo culture);
// typicky třeba maily
mail.Subject = (string)HttpContext.GetGlobalResourceObject("MailTemplates", "MyMailSubject");
// nebo ve stránce
MessageLb.Text = (string)GetLocalResourceObject("Neuspech");
Metody jsou mimo třídy HttpContext přístupné i v třídě TemplateControl a jejích potomcích, tedy např. i Page.
Pro local resources bohužel ASP.NET žádný wrapper negeneruje a z kódu na ně přistupujeme rovnou přes GetLocalResourceObject().
Pro přístup k resources můžeme použít samozřejmě i standardní techniky přes ResourceManager atp., ale ve webových aplikacích to není běžné.
Co jsme dosud udělali nám samo o sobě už bude fungovat a zobrazovat, nicméně stále jsme jen u jednoho primárního jazyka. Pro přidání dalších jazyků a případně i možnost jejich přepínání musíme provést ještě dva kroky.
Vytvoření resources pro další jazyky je velmi primitivní záležitostí. Stačí vzít .resx soubor primárního jazyka a vytvořit jeho kopii se jménem Soubor.jazyk.resx, například tedy ze souboru ~/App_GlobalResources/Glossary.resx vytvoříme kopii ~/App_GlobalResources/Glossary.en.resx (pro angličtinu), nebo ze souboru ~/App_LocalResources/Login.aspx.resx vytvoříme kopii ~/App_LocalResources/Login.aspx.de.resx (pro němčinu).
…a nyní nezbývá než hodnoty v novém souboru přeložit. Pokud navíc nainstalujeme překladateli WDE a naučíme ho editovat přímo .resx soubory, krása. Existují dokonce mnohé šikovné utilitky pro práci s .resx soubory, aby nebylo nutné instalovat něco tak velkého jako WDE:
Jakou jazykovou verzi odešle ASP.NET na klienta se řídí hodnotou Thread.CurrentThread.CurrentUICulture, zároveň se doporučuje volit i Thread.CurrentThread.CurrentCulture, protože tím se řídí formát čísel, času, dat, měny, atp.
První, co můžeme chtít, je, aby ASP.NET použilo jazykový požadavek prohlížeče, který ho posílá v HTTP requestu. Česká prostředí tedy rovnou uvidí české stránky, anglická anglické, atp. a nic nemusíme ani přepínat. Prohlížeče mají jazyk přednastaven od instalace a například v Internet Exploreru je možné ho měnit přes Nástroje ~ Možnosti Internetu ~ Obecné ~ Jazyky.
Jediné, co pro implementaci tohoto postupu potřebujeme udělat, je ve web.config nastavit hodnoty elementu <globalization>, atributy uiCulture, popř. culture:
<globalization requestEncoding="utf-8" responseEncoding="utf-8" culture="auto:cs-CZ" uiCulture="auto:cs-CZ" />
Volba auto říká, že se má použít požadavek prohlížeče, za dvojtečku lze volitelně umístit primární nastavení, které se má použít, pokud není požadavek prohlížeče realizovatelný, resp. pokud prohlížeč požadavek neudal. Pro úplnost uvádím i volby encoding, ty však nejsou předmětem tohoto článku.
Dále můžeme chtít, aby si uživatel sám mohl přepnou jazyk, nezávisle na požadavku prohlížeče. Je jasné, že budeme muset přepnout Thread.CurrentThread.CurrentUICulture popř. i CurrentCulture. Zvolený jazyk si budeme ukládat třeba do cookie (použitelná je i session) a je potřeba ho přepnout pro každý request, a to co nejdříve. Buď můžeme udělat override prázdné virtuální metody Page.InitializeCulture(), pokud máme připravenou bázovou třídu pro všechny stránky, anebo změnu provádět rovnou v události Application_BeginRequest, v Global.asax.cs:
private void Application_BeginRequest()
{
HttpCookie cookie = Request.Cookies["Culture"];
if (cookie != null)
{
CultureInfo culture = new CultureInfo(cookie.Value);
Thread.CurrentThread.CurrentCulture = culture;
Thread.CurrentThread.CurrentUICulture = culture;
}
}
a pro vlastní přepínání si uděláme třeba stránku Language.aspx:
protected override void OnInit(EventArgs e)
{
string culture = Request.QueryString["culture"];
if ((culture != null) && (culture.Length > 0))
{
HttpCookie cookie = new HttpCookie("Culture");
cookie.Value = culture;
Response.Cookies.Add(cookie);
}
string returnUrl = Request.QueryString["returnUrl"];
if ((returnUrl != null) && (returnUrl.Length > 0))
{
Response.Redirect(returnUrl);
}
else
{
Response.Redirect("~/");
}
base.OnInit(e);
}
odkaz pro přepnutí stránky, pak může být třeba
<a href="language.aspx?culture=en-US">en</a>
nebo s ReturnUrl stejně jako login-page.
V příloze najdete PowerPoint slides: Lokalizace webových aplikací.ppt