27 marca 2009

Rozdział 7. o umiędzynarodowianiu i lokalizacji w Grails z DGG2

Powrót do relacji z lektury książki "The Definitive Guide to Grails, Second Edition". Dzisiaj o umiędzynarodowianiu i lokalizacji aplikacji w Grails.

Grails udostępnia różne mechanizmy umiędzynarodowienia i lokalizacji aplikacji. Zakłada się, że wszystkie komunikaty aplikacji w Grails umieszczone są w dedykowanych plikach komunikatów w katalogu grails-app/i18n. Domyślne komunikaty w języku angielskim są w grails-app/i18n/messages.properties, a pozostałe tłumaczenia w innych. Zasada rządząca, który plik jest przypisany danemu językowi, odpowiada zasadom w Javie (patrz dokumentacja klasy java.util.Locale). Komunikaty są wykorzystywane m.in. do informowania użytkownika o błędach walidacji danych w klasach domenowych czy poleceń (np. przy wywołaniu validate() lub save()).

Grails udostępnia znacznik GSP g:message, który korzysta z plików komunikatów w grails-app/i18n. Obowiązkowy atrybut code wskazuje na dany identyfikator komunikatu, np. (Listing 7-3):
 <g:message code="gtunes.welcome" />
Jak to bywa w innych szkieletach webowych, tak i w Grails, domyślnym językiem jest język domyślny w przeglądarce. Wystarczy jednak wywołać URL z parametrem lang, aby go zmienić, np. http://serwer/aplikacja/?lang=pl. Możemy również zdefiniować własne mapowanie, w którym explicite wskażemy miejsce w adresie URL, z którego aplikacja (a właściwie sam Grails) będzie pobierała wskazanie na język, np. (Listing 7-7):
 class UrlMappings {
static mappings = {
"/store/$lang"(controller:'store')
}
}
W ten sposób wywołanie http://serwer/aplikacja/store/pl będzie wskazaniem na polską wersję językową aplikacji.

Istnieje możliwość parametryzowania komunikatów konstrukcją {#}, gdzie # oznacza numer parametru, np.
 komunikat.powitalny = Witaj {0}!
Znacznik GSP - g:message - ma opcjonalny atrybut args, który jest listą parametrów wejściowych dla komunikatu (kolejność ma znaczenie), np.
 <g:message code="komunikat.powitalny" args="[Jacek]" />
Oczywiście (jak to w wielu innych miejscach w Grails) przekazane parametry mogą być wyliczane dynamicznie, np.
 <g:message code="komunikat.powitalny" args="[session.user?.firstName ?: 'Nieznajomy']" />
Pamiętamy znaczenie operatora ?: (operator Elvis)? Jest on skrótem dla javowego operatora "warunek? wartość-dla-true : wartość-dla-false". W przypadku braku wartości zwracana jest ta po ?:.

W Grails mamy do dyspozycji ziarno springowe messageSource (typu org.springframework.context.MessageSource), które może być przekazane (wstrzyknięte) do dowolnego artefaktu grailsowego - kontrolera, znacznika GSP czy innych ziaren springowych. Za jego pomocą możemy pobrać komunikaty z poziomu kodu w Javie. Wystarczy zadeklarować referencję (atrybut) w naszej klasie, aby Grails (właściwie Spring) ją poprawnie zainicjował, np. (Listing 7-18):
 class StoreController {

def messageSource

def index = {
def msg = messageSource.getMessage('komunikat.powitalny', ['Jacek'], new Locale('pl'))
}

}
Już w nadchodzącą sobotę - 4.04.2009 - java4people w Szczecinie będę miał okazję przedstawić Grails praktycznie. Zapraszam! Zachęcam również do zadawania pytań/składania propozycji tematów do omówienia podczas mojego wystąpienia. Szkoda, abyście poświęcili swój czas na nic. Graeme zbudował kompletną aplikację ala twitter w 40 minut (Webinar: Twitter with Grails in 40 Minutes). Może i mi uda się coś fajnego skonstruować w tym czasie?! Pomoc wskazana.

3 komentarze:

  1. Hej,
    "W przypadku braku wartości zwracana jest ta po ?:"

    to jak to jest? Ta po '?', czy ta po ':' ?

    OdpowiedzUsuń
  2. Jedna fajna rzecz, której nie napisałeś (albo nie widzę :)) to możliwość wykorzystania tagu g:message bezpośrednio w kontrolerze, i wtedy nie trzeba includować mesageSource (co więcej api jest prostsze). Robi się to po prostu (w kontrolerze) tak:
    g.message(code:'komunikat.powitalny', args:['Jacek'])

    Jest to o tyle lepsze, że nie trzeba znać ani uzyskiwać locale (tak jak tu u Ciebie statycznie ustawione na polskie)

    pzdr

    OdpowiedzUsuń
  3. @MZ: Elvis Operator (?: ). I wszystko jasne :P

    @Paweł - dzięki. Nie miałem świadomości istnienia tego cuda. Wiedziałem, że znaczniki można wykorzystać jako metody, ale przykłady były z GSP i ${}. W końcu biblioteki znaczników to klasy Groovy, a same znaczniki to metody, więc niby nic odkrywczego, ale nie wpadłem na to wcześniej. Rządzisz! Jak kiedyś zagramy w bilarda, to dam Ci wygrać :P

    OdpowiedzUsuń