09 maja 2008

Umiędzynarodowienie w Apache Wicket

Tempo rozwoju Apache Wicket może zdumiewać, gdyż jeszcze nie tak dawno podnosiłem wersję Wicket mojej testowej aplikacji do 1.3.3, a już mamy 1.4-m1. Z pomocą Apache Maven 2 temat sprowadził się do uaktualnienia pom.xml, w którym podniosłem wersję Wicketa oraz Spring Framework (do wersji 2.5.4). Jedną z głównych zmian w Wicketa 1.4 jest skorzystanie z mechanizmu wzorców w Javie (Java Generics), tak że musiałem zmienić sygnaturę metody WicketDemoApplication.getHomePage(), która zawęziła typ zwracanych obiektów do Class<? extends org.apache.wicket.Page>.
 c:\projs\sandbox\wicket-demo\src\main\java\pl\jaceklaskowski\wicket\WicketDemoApplication.java:[66,20] getHomePage() 
in pl.jaceklaskowski.wicket.WicketDemoApplication cannot override getHomePage() in org.apache.wicket.Application;
attempting to use incompatible return type
found : java.lang.Class<?>
required: java.lang.Class<? extends org.apache.wicket.Page>
Do mojej prezentacji Wicketa na kolejnym,wtorkowym spotkaniu Warszawa JUG pozostało już niewiele dni, więc kończąc lekturę książki Pro Wicket (Apress) trafiłem na rozdział przedstawiający mechanizm i18n - umiędzynarodowienia, który polega na przeniesieniu napisów do plików properties z przypisaniem im identyfikatorów wraz z ich wykorzystaniem w dedykowanych znacznikach <wicket:message>. Identyfikatory są niezmienne i zapisane są w ciele stron aplikacji, podczas gdy ich wartości zależne od języka są zapisane w plikach properties. Wskazanie miejsca umiędzynarodowienia polega na skorzystaniu ze znacznika <wicket:message key="..." />, który odszuka właściwego napisu dla podanego klucza (identyfikatora) wskazanego przez atrybut key. Pozostaje przedstawić, gdzie pliki properties powinny się znajdować. Jest kilka wariantów umieszczenia pliku properties, co daje nam różne poziomy granulacji komunikatów dla pojedyńczego formularza, pojedyńczej strony, dla całej grupy stron czy dla całej aplikacji. Nie wnikając w niepotrzebne szczegóły, umieszczę napisy w pliku odpowiadającym nazwie strony. Cała radość w "czystość" plików HTML została nieznacznie zaburzona wprowadzeniem specyficznych dla Wicketa znaczników <wicket:message>.

Oto strona DaneOsobowe.html ze znacznikami <wicket:message/>:
 <?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html xmlns:wicket="http://wicket.apache.org">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Wicket Demo App</title>
</head>
<body>
<strong>Wicket Demo App</strong>
<span wicket:id="komunikaty"></span>
<form wicket:id="daneOsobowe" action="">
<table>
<tr>
<td><wicket:message key="imie" />:</td>
<td colspan="2"><input type="text" wicket:id="imie" /></td>
</tr>
<tr>
<td><wicket:message key="nazwisko" />:</td>
<td colspan="2"><input type="text" wicket:id="nazwisko" /></td>
</tr>
<tr>
<td><wicket:message key="login" />:</td>
<td colspan="2"><input type="text" wicket:id="login" /></td>
</tr>
<tr>
<td><wicket:message key="miejscowosc" />:</td>
<td><select wicket:id="miejscowosc">
<option>Cokolwiek</option>
</select></td>
<td><input type="submit" value="Zatwierdź" /></td>
</tr>
</table>
</form>
</body>
</html>
i odpowiadający jej plik DaneOsobowe.properties z wartościami kluczy:
 imie=Imi\u0119
nazwisko=Nazwisko
login=Login
miejscowosc=Miejscowo\u015b\u0107
W zasadzie to plik DaneOsobowe.properties powinienem był nazwać DaneOsobowe_pl.properties, aby wskazać jaki język plik zawiera, ale dla prostoty przykłady postanowiłem zaniechać tego.

I to tyle. Teraz wystarczy przenieść wszystkie napisy do odpowiednich plików properties i stworzyć wiele ich wersji językowych dla każdego wspieranego przez aplikację języka. I to bez modyfikacji kodu źródłowego! Wprowadzenie obsługi wersji językowej dla kolejnego języka sprowadza się teraz do dodania kolejnego pliku properties.

Pytanie konkursowe: Jaka jest geneza akronimu i18n, który tłumaczy się jako umiędzynarodowienie? Nagród nie przewiduje się.