Přejít k navigační liště

Zdroják » JavaScript » Lokalizujeme web pomocí L20n.js

Lokalizujeme web pomocí L20n.js

Nedávno se rozšířila informace o lokalizačním frameworku L20n.js od Mozilly. Vyplatí se ho znát? Pojďme si ukázat, jak s ním lokalizovat naší webovou aplikaci do více jazyků, tak aby nás to co nejméně bolelo.

Stručný úvod

Podle Mozilly je L20n.js developer-friendly lokalizační framework, který dovolí vývojáři úplně se odprostit od jazykových specialit a lokalizérovi zase umožní vytvářet mnohem lepší překlady. Co to je a jak se to projevuje?

Jakou úlohu v tom hraje kodér, je asi snadné uhodnout. Ten jen k jednotlivým HTML tagům přidá určitý data-* atribut s jasným identifikátorem. A lokalizér? Ten k těmto identifikátorům přiřadí odpovídající texty pomocí tzv. entit s možností využití pokročilejších funkcí frameworku. Ale dost mluvení, ukažme si alespoň krátký úryvek ze syntaxe L20n.js:

<hello "Ahoj světe">

<skill "Už umím napsat {{hello}}">

<website {
    *nominative : "Zdroják",
    locative : "Zdrojáku"
}>

<description """
    Právě jste na webu {{website}}.
    Přečtěte si něco o {{website.locative}}:
""">

Nasazení

Na webu projektu je odkaz na soubor na Githubu. Ten si stačí uložit a přidat ho do stránky. Podle Mozilly má být script tag s l20n.js jako poslední v head:

<head>
    ...
    <script type="text/javascript" src="cesta/k/l20n.js"></script>
</head>

Následně je potřeba vložit manifest JSON soubor, který L20n.js řekne, jaké jazyky máme k dispozici, který z nich je výchozí, a kde je má hledat. Pokud neuvedete výchozí jazyk, použije se i-default. Pokud máte k dispozici zatím jen jeden jazyk (ten výchozí), není třeba uvádět dostupné jazyky. Manifest soubor může vypadat například takto:

{
  "locales": [
    "en-US",
    "cs"
  ],
  "default_language": "cs",
  "resources": [
    "../locales/{{locale}}.l20n"
  ]
}

Pravděpodobně jste se dovtípili, že ve vlastnosti resources vám za {{locale}} framework dosadí požadovaný jazyk. Dokonce můžete definovat více cest, takže nemáte svázané ruce, co se týče struktury složek a dělení do souborů. Je samozřejmě na vás, jaké názvy pro jazyky použijete, nicméně se doporujučuje řídit se podle BCP 47. To v důsledku znamená použít ISO 639-1 kódy a pokud se daný jazyk liší v různých regionech, tak k nim ještě za pomlčku přidat ISO 3166-1 kód.

Vraťme se k našemu manifest souboru. Ten už jen stačí vložit do našeho webu nějak takhle:

<link rel="localization" href="cesta/k/manifest.json">

Pro vývoj aplikace s L20n.js je také vhodné zmínit to, že prohlížeče mohou *.l20n soubory cachovat a při reloadu brát uloženou verzi. Může být pak velmi frustrující, když přidáte nebo smažete novou entitu, ale ve vaší aplikaci se to neprojeví. Proto doporučuji dočasně si vypnout cache, což lze v Chrome udělat velmi snadno v nastavení dev tools.

Jdeme lokalizovat

Role „vývojář“

Můžeme si vybrat, zda budeme používat „HTML“ způsob nebo „JavaScript“ způsob. Ač jsem se prozatím nezmínil, doteď jsme jeli přes „HTML“ variantu. Jazyky, cestu k nim a dokonce i jednotlivé entity totiž můžeme definovat také pomocí JavaScriptového API. Avšak způsob, jaký jsme využili my, mi příjde pohodlnější. Přestože můžou existovat use cases, kdy je potřeba použít JavaScript přímo. Pokud jste v takové situaci, L20n.js nabízí slušně zdokumentované API.

Jak tedy vypadá náš lokalizovatelný HTML kód? Například takto:

<h1 data-l10n-id="heading"></h1>
<section data-l10n-id="description"></section>
<section data-l10n-id="signin">
    <input type="text" /><br>
    <input type="text" /><br>
    <input type="submit" />
</section>

Je vhodné se zmínit o tom, že můžeme dovnitř tagů napsat výchozí text tak, jak bychom to udělali normálně, když bychom nechtěli lokalizovat. Proč to dělat nebo proč to nedělat? Než se L20n.js načte a inicializuje, může to chvilku trvat a tu chvilku je schopen uživatel zaregistrovat. Pak záleží na vás, zda mu nabídnout nějaký text, než se vše správně přeloží, anebo nechat stránku do té doby bez textu. Domnívám se, že neexistuje správná cesta, je to jen a jen na vás.

Co jsme to vlastně vytvořili? Určitou šablonu pro kus naší stránky, kde si následně zobrazíme název, popisek a formulář k přihlášení. Někoho by mohlo mást, že framework se jmenuje L20n a v kódu používáme data-l10n-id. Pro ty, co nevědí, l10n je zkratka pro „localization“, a Mozilla představuje toto dílo jako „l10n 2.0“ => „L20n“. Je to však jen název frameworku. Pro všechno ostatní je použito standardní „l10n“.

Ještě nám zbývá vytvořit skriptovou část naší aplikace, kde budem odchytávat chyby, měnit jazyky apod. Potřebujeme nejdříve lokalizační kontext, který můžeme získat buď pomocí L20n.getContext(), anebo využijeme toho, že jsme již vše nadefinovali v manifestu a použijeme kontext, který nám framework poskytuje via document.l10n. Po kontextu můžeme vyžadovat změnu jazyka, můžeme díky němu sami překládat, nebo třeba odposlouchávat události. Ty jsou tři: „ready“, „error“ a „warning“. Máme taky k dispozici přímo metodu ready, která nám supluje danou událost. Další událost – „DocumentLocalized“ – odposloucháváme přímo na dokumentu a můžeme ji použít například k inicializaci naší aplikace. Povídání bylo dost, přejděme raději ke kódu:

document.addEventListener('DocumentLocalized', function () {
    //zavolá se pouze jednou
    console.log('dokument byl lokalizován');
});

var ctx = document.l10n;

ctx.ready(function () {
    //zavolá se vždy, když se změní kontext (přepne jazyk)
    console.log('lokalizační kontext je připraven');
    console.log(ctx.supportedLocales);
    //vrací pole tzv. fallback chainu, což je seznam jazyků použitých pro překlad
    //tzn. většinou aktuální jazyk (pokud je jiný než výchozí) a jazyk výchozí
    //fallback chain umožní to, že pokud se nenajde překlad pro nastavený jazyk,
    //použije se následující jazyk v pořadí
});

ctx.addEventListener('error', function (err) {
    console.log('nastala chyba', err);
});

ctx.addEventListener('warning', function (warn) {
    console.log('přišlo varování', warn);
});

function zmenJazyk(jazyk) {
    if (jazyk) {
        ctx.requestLocales(jazyk); //nastav jazyk na požadovaný
    }

    else {
        ctx.requestLocales(); //nastav jazyk na výchozí
    }
}

To by bylo vše podstatné k vývojáři. Samozřejmě se dá dělat mnohem víc věcí, prozatím však pozici vývojáře opusťme. Pokud byste byli zvědaví, můžete prolítnout již zmiňované API.

Role „lokalizér“

L20n.js je prý postaven tak, aby jednoduché věci zůstaly jednoduchými, a komplexní, aby se staly možné. V základu jde o to pouze definovat jednotlivé entity a k nim přiřadit odpovídající hodnoty. Syntaxe je, jak už jsme si ukázali, opravdu velmi jednoduchá. Pojďme si tedy lokalizovat nadpis a popisek:

<heading {
    *nominative : "Zdroják",
    locative : "Zdrojáku"
}>

<description """
    {{heading}} je portál o tvorbě webových stránek a aplikací.
    Na {{heading.locative}} najdete mnoho velmi užitečných článků a tutoriálů.
""">

Jak jste si jistě všimli, entita heading je rozdělena na dvě části. V tomhle případě jsme si tak označili pády, ale je samozřejmě na vás, co potřebujete o entitě všechno říct. Důležitá je hvězdička u jedné z vlastností. Tím totiž frameworku říkáme, co má použít jako výchozí. Přistupovat k jednotlivým vlastnostem můžeme buď pomocí single dot syntaxe (entita.vlastnost) nebo square bracket syntaxe (entita['vlastnost']). U entity description vidíme text v troj-uvozovkách. Takhle se zapisuje víceřádkový obsah. Jednořádkové entity se definují s klasickými závorkami. Jednotlivé entity jsou vlastně proměnné, a ty můžeme také interpolovat pomocí dvojitých složených závorek, tedy {{promenna}}. A pozor, názvy entit nesmí obsahovat pomlčku.

Tohle bylo jednoduché, přejděme proto k přihlašovacímu formuláři. Nejdříve kód:

<signin """
    <input placeholder="uživatelské jméno" /><br>
    <input placeholder="heslo" /><br>
    <input value="Přihlásit se" />
""">

Tady už to zavání kouzly, pojďme si to vysvětlit. Když se pozorně podíváte, text uvnitř trojitých uvozovek je velmi podobný tomu, co jsme napsali do HTML naší stránky. Alespoň se tedy shodují HTML tagy. A to je ono. L20n.js nám text entity spojí s kódem a vytvoří nám chtěný výsledek. Pozor však na některé atributy, které byste chtěli psát do lokalizačního souboru. Například href, type nebo onclick nebudou z l20n souboru do kódu přidány, protože nejsou „safe“ – bezpečné.

Výsledek

Co vlastně tedy z našeho krátkého příkladu vzejde? Takhle bude vypadat výsledné HTML:

<h1 data-l10n-id="heading">Zdroják</h1>
<section data-l10n-id="description">
    Zdroják je portál o tvorbě webových stránek a aplikací. Na Zdrojáku najdete mnoho velmi užitečných článků a tutoriálů.
</section>
<section data-l10n-id="signin">
    <input type="text" placeholder="uživatelské jméno"/><br>
    <input type="text" placeholder="heslo" /><br>
    <input type="submit" value="Přihlásit se" />
</section>

Mírně upravený zdrojový kód k tomuto článku jsem vložil do gistu. Stačí si ho stáhnout nebo naklonovat, kam potřebujete, a vyzkoušet si, že to opravdu funguje. Případně si můžete vyzkoušet pokročilejší funkcionalitu.

Porovnání s jinými

Zkusil jsem jenom tak prolétnout Githubem, zda jiný projekt nabízí to, co L20n.js. Resumé? Lokalizovat vám pomůže třeba l10n.js, webL10n nebo Angular localization service. První jmenovaný vám nabízí pouze JavaScriptové API, takže žádné HTML data-* atributy. Žádné varianty entit, žádná interpolace proměnných.

Druhý projekt už HTML variantu nabízí. Zajímavá je jeho syntaxe, která je, zdá se, ještě jednodušší než u frameworku od Mozilly. Nezkoumal jsem ho do hloubky, ale vypadá to, že všechny jazyky mohou být pouze v jednom inicializačním souboru, což může být neefektivní a náročné na bandwidth. Avšak stejně jako L20n.js nabízí například interpolaci proměnných, různé varianty entit, apod. Angular service používá tradiční JSON syntaxi, ale neumožňuje pokročilejší postupy.

Avšak hlavním předpokladem, který mluví stoprocentně pro L20n.js, je dokumentace a fakt, že to stvořila Mozilla. Protože máte jistotu, že vývoj bude ještě nějakou dobu pokračovat a komunita poroste, takže na problémy nezůstanete sami. A to se počítá, no ne?

Závěr

Ani zdaleka jsem neukázal vše, co L20n.js nabízí. Jsou tu další užitečné fíčury jako práce s proměnnými, makra, atd. Bohužel už však nezbylo místo. Pokud bude zájem, můžeme si to ukázat příště.

Komentáře

Subscribe
Upozornit na
guest
16 Komentářů
Nejstarší
Nejnovější Most Voted
Inline Feedbacks
View all comments
SebastianBusek

Hezký článek, díky za něj.
Mimochodem, máte někdo zkušenost s jQuery UI i18n?

Martin Pecka

Interpolace promennych asi neni uplne spravny preklad… Interpretace?

Stejne tak jako odposlouchavani udalosti :-D Hned jsem si vzpomnel na doby StB :)

Petr Sýkora

A co takové dosazování proměných?

Misaz

Nevím teda jak Vám, ale mě to developer friendly nepřijde, mnohem víc se mi líbí použití data-* attributů, jak to řešil MS v Modern UI aplikacích.

Smajl

K těm porovnáním: co třeba Jed?

Petr

může uživatel na frontendu vybrat jednoduše locale podle toho, který chce a ne podle jazyka prohlížeče?

Martin Hassman

Nevím přesně, zda to tak l20n.js dělá, ale obvykle se webové lokalizace řídí HTTP hlavičkou Accept-Language, ta sice obvykle odpovídá jazyku prohlížeče, ale uživatel si to může změnit.

Petr

PN: „Takže u L20n.js právě volíte vy sám, který jazyk se zobrazí jako první a můžete jej i libovolně měnit za chodu.“

Můžete prosím stručně ukázat jak za chodu změnit jazyk, díky.

Tohoto se snažím docílit, např. že uživatel tam bude mít dva radio buttony a může si přepínat jazyky.

Petr

suprovka, díky

Enum a statická analýza kódu

Mám jednu univerzální radu pro začínající programátorty. V učení sice neexistují rychlé zkratky, ovšem tuhle radu můžete snadno začít používat a zrychlit tak tempo učení. Tou tajemnou ingrediencí je statická analýza kódu. Ukážeme si to na příkladu enum.