Český internet je oproti tomu mezinárodnímu pouhým rybníčkem. To (a nejen to) může být důvodem k internacionalizaci aplikací. V dnešním díle se budeme věnovat překladu a formátování, využívat k tomu budeme převážně knihovnu JSON Formatting.
3.9.2013 00:00 | Petr Horáček | czytane 9637×
RELATED ARTICLES
KOMENTARZE
V minulých dvou dílech jsme se věnovali nástrojům, které slouží především vývojářům, dnes se již ale vrátíme k tvorbě uživatelského prostředí. Povíme si něco o internacionalizace obecně, knihovně JSTL Formatting a nakonec si předvedeme praktickou ukázku na naší aplikaci.
Internacionalizace (i18n)
Pod pojmem internacionalizace (zmezinárodnění) se skrývá hned několik postupů. Především jde o překlad aplikace do více jazyků, mezi kterými lze libovolně přecházet (není tedy vytvořena pouze přeložená verze aplikace, ale je k dispozici více jazykových voleb). Jednou z vlastností internacionalizované aplikace by mělo být i přizpůsobení gramatiky a typografie (např.: úprava plurálů a zápis datových údajů).
Více si můžete o překladu softwaru přečíst zde: http://cs.wikipedia.org/wiki/Internacionalizace_a_lokalizace
Překlad webové aplikace
Začneme zmezinárodněním uživatelského prostředí čistě pomocí překladu. Pro tento úkon bude stačit vytvoření souborů s řetězci a přidání nekolika řádek kódu do viewů (připadně přidat novou adresu do controlleru).
Pro účely internacionalizace budeme využívat formátovací tagy z knihovny JSTL (více zde: http://www.tutorialspoint.com/jsp/jsp_standard_tag_library.htm).
Ukládání řetězců
Jako úložiště různých jazykových verzí budou sloužit soubory s příponou propreties obsahující jednotlivé řetězce i jejich klíče (ve kterých lze uplatňovat princip tečkové konvence). Pro tyto soubory je vhodné v aplikaci vyhradit samostatný balíček.
Základní jazyk (nejčastěji angličtina, je zvolen pokud není možno uplatnit uživatelův jazyk) je umístěn v jazykově neoznačeném souboru (např. text.propreties) a může vypadat třeba takto:
greeting.morning = Good morning
greeting.afternoon = Good afternoon
greeting.evening = Good evening
Další jazykové mutace jsou umístěny v souborech označených pomocí ISO jazykových kódů. Soubor s českými řetězci (např. text_cs.propreties) by mohl vypadat třeba takto:
greeting.morning = Dobré ráno
greeting.afternoon = Dobré odpoledne
greeting.evening = Dobrý večer
Poznámka: NetBeans obsahuje nástroje usnadňující překlad, hodí se ale pouze do klasických aplikací (s řetězci umístěnými v kódu Javy), pro překlad webové aplikace jsou nepoužitelné.
Import knihoven
V každém viewu bude potřeba získat proměnnou jazyka a nahrát řetězce z jejich úložiště. Pro tyto operace budeme potřebovat knihovny Formatting a Core, vložte tedy ne začátek všech viewů tento kód:
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
Zjištění jazyka
V dalším kroku bude nutné zjistit uživatelem požadovaný jazyk a uložit jej jako proměnnou do současné session. Pro nastavení jazyka budeme využívat formulář s metodou GET, všechen přiřazovací kód bude umístěn ve viewu. Pod importy na začátku viewu tedy vložte toto:
<c:set var="language"
value="${not empty param.language ? param.language
: not empty language ? language : pageContext.request.locale}"
scope="session" />
Do proměnné language (sdílené pro celou session) se pokusíme dosadit jazyk získaný z metody GET, pokud parametr nenalezneme, pokusíme se nahrát hodnotu již v session uloženou, pokud ani tu nenalezneme, zapíšeme jazyk získaný z HTTP hlavičky requestu.
Samotný formulář určený pro změnu jazyka by mohl vypadat třeba takto:
<form>
<select id="language" name="language" onchange="submit()">
<option value="en" ${language == 'en' ? 'selected' : ''}>
English
</option>
<option value="nl" ${language == 'cs' ? 'selected' : ''}>
Česky
</option>
</select>
</form>
Pokud si chcete v aplikaci udržet pěkné URL, můžete namísto metody GET využít POST v kombinaci se servletem, který zajistí úpravu session.
Nahrání řetězců
Po zjištění požadovaného jazyka stačí už jen určit jazyk a nahrát řetězce z určeného úložiště.
<fmt:setLocale value="${language}" />
<fmt:setBundle basename="cesta.k.i18n.retezcum" />
Vkládání řetězců
Nakonec nezbývá než uložené řetězce vložit do textu, to lze provést pomocí následujícího tagu:
<fmt:message key="klic.retezce" />
Formátování dat a čísel
Knihovna JSTL Formatting také nabízí několik nástrojů sloužících pro výpis čísel či dat v daném formátu:
<fmt:formatNumber>
<!-- Vypíše číselnou hodnotu ve specifikovaném formátu -->
<fmt:parseNumber>
<!-- Převede předaný řetězec na číslo -->
<fmt:formatDate>
<!-- Vypíše datum a/nebo čas ve specifikovaném formátu -->
<fmt:parseDate>
<!-- Převede řetězec na datový údaj -->
<fmt:timeZone>
<!-- Upraví výpis data a/nebo času v závislosti na časové zóně -->
<fmt:setTimeZone>
<!-- Nastaví požadovanou časovou zónu -->
Zápis českého data a času by mohl vypadat takto:
<fmt:formatDate pattern="h.mm d. M. yyyy" value="${now}" />
Doporučuji alespoň letmé prohlédnutí dokumentace knihovny, každý tag má celou řadu atributů a přednastavení.
Úprava aplikace
Nyní už k naší aplikaci.
Úložiště
Začněme s úložištěm řetězců. Vytvořte tedy v naší aplikaci balíček internacionalizace a přidejte do něj soubor text.propreties:
base.header = Notebook
base.title = Notebook
login.username = Username
login.password = Password
login.submit = Login
login.invalid = Username or password is incorrect.
notes.header = Header
notes.edit = Edit
notes.delete = Delete
notes.addnew = Add
notes.warning.fillboth = You must fill in both fields.
notes.warning.none = There are no notes yet.
a text_cs.propreties:
base.header = Zápisník
base.title = Zápisník
login.username = Přihlašovací jméno
login.password = Heslo
login.submit = Přihlásit
login.invalid = Zadané údaje nejsou platné.
notes.header = Nadpis
notes.edit = Upravit
notes.delete = Smazat
notes.addnew = Přidat
notes.warning.fillboth = Musíte vyplnit obě pole.
notes.warning.none = Dosud nebyl přidán žádný zápisek.
Zjištění jazyka, nahrání a vkládání řetězců
Přidejte do všech šablon včetně tagu Base tento kód (pod import knihovny core):
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
<c:set var="language"
value="${not empty param.language ? param.language : not empty language ?
language : pageContext.request.locale}" scope="session" />
<fmt:setLocale value="${language}" />
<fmt:setBundle basename="internacionalizace.text" />
Importujeme zde knihovnu formatting, nastavíme proměnnou language se zvoleným jazykem, ten následovně přiřadíme knihovně formatting a nakonec načteme úložiště řetězců.
Následovně nahraďte v těchto souborech všechny vypisované textové řetězce (i popisky tlačítek) kódem pro výpis uloženého řetězce, například nadpis v tagu Base se změní na:
<h1><fmt:message key="base.header" /></h1>
Problém nastane u předávání titulku v attributu titulek tagu Base, v tomto případě bude nutné předem si připravit proměnnou, kterou poté přiřadíme pomocí EL jako titulek. Upravte tedy ve všech viewech otevření tagu Base:
<fmt:message key="base.title" var="titulek" />
<m:Base titulek='${titulek}'>
Pro přecházení mezi jazyky využijeme formulář s prvkem select. Aby na stránkách využívajících metodu GET nedošlo k potížím (např.: Změna jazyka by přepsala attribut id v url a následovně by došlo k chybě.) přidáme do formuláře navíc cyklus předávající ve skrytých vstupech všechny již získané GET argumenty, krom nastavení jazyka. Vložte v tagu Base pod <h1>
nadpis toto:
<form action="" style="display: inline">
<c:forEach items="${param}" var="parameter">
<c:if test="${parameter.key != 'language'}">
<input type="hidden" name="${parameter.key}"
value="${parameter.value}" />
</c:if>
</c:forEach>
<select name="language" onchange="submit()">
<option value="en" ${language == 'en' ? 'selected' : ''}>
English
</option>
<option value="cs" ${language == 'cs' ? 'selected' : ''}>
Česky
</option>
</select>
</form>
Díky JavaScriptovému příkazu onchange="submit()"
se formulář po změně hodnoty automaticky odešle. Pomocí EL nastavíme v selectu aktuální jazyk jako vybraný.
Poznámka: Pokud chcete mít volbu jazyka a nadpis na jednom řádku, přidejte oběma prvkům attribut style="display: inline".
Závěr
A to je vše, nyní je naše aplikace kompletní a plně připravená na nasazení do provozu. V příštím díle si popíšeme umístění aplikace na server a možnosti hostingu.
Zdrojové kódy aplikace naleznete na GitHubu: https://github.com/PetrHoracek/JavaNaWeb