Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Kdyby/Translation

 Kdyby/Translation

Talk about my solution for translations and Nette Framework.
The Kdyby/Translation is an integration of Symfony/Translation into Nette Framework.

Filip Procházka

November 30, 2014
Tweet

More Decks by Filip Procházka

Other Decks in Technology

Transcript

  1. Co si povíme? - Co to je - Něco si

    přeložíme - Typické úlohy s Nette - Co to neumí
  2. Co je Kdyby/Translation? - Localization\ITranslator - Symfony/Translation Kdyby/Translation je implementací

    Nette\Localization\ITranslator pro Nette, využívající Symfony/Translator, díky kterému má podporu pro spoustu super featur.
  3. Instalace $ composer install kdyby/translation A do configu s tím!

    extensions: translation: Kdyby\Translation\DI\TranslationExtension Instalace je jako vždy primitívní, stačí použít composer a vložit extension do configu.
  4. Základní nastavení translation: default: cs fallback: [cs_CZ, cs] $translator->getDefaultLocale() Základní

    nastavení jsou také jednoduchá. Je nutné nastavit pouze výchozí jazyk, který pak jde získat metodou getDefaultLocale(). Fallback umožňuje načíst překlady z “náhradního” slovníku - tedy například když není překlady dostupný v němčině a máte nastavený fallback na angličtinu, načte se z anglického slovníku.
  5. Odkud se berou překlady - slovníky v aplikaci - neon

    - po / mo - xlf - csv - ts - ... Rozšíření umožňuje díky Symfony načítat slovníky v hromadě formátů, z nichž nejzajímavější jsou asi po/mo, díky kterým můžete translator použít jako drop-in replacement vašeho současného gettext translatoru. Kdyby pak přidává ještě navíc podporu pro neon slovníky.
  6. Slovník v neonu app/locale/messages.cs_CZ.neon "Hello World": Ahoj světe! Vytvoříme si

    slovník ve formátu neon pro češtinu a do něj vložíme nějaký překlad.
  7. “Lepší” slovník v neonu app/locale/front.cs_CZ.neon hello: world: Ahoj světe! A

    nebo si vytvoříme lepší slovník, kde nebudeme mít jako klíče stringy, ale identifikátory, které pak máme unikátní napříč aplikací. Je možné pak mít více slovníků, kde název souboru se bere vždy jako první část identifikátoru, což je v tomto případě slovo front.
  8. Použití s identifikátory $translator->translate( 'front.hello.world' ); // Ahoj světe! Translatoru

    řekneme že chceme překládat nějaký identifikátor a on nám ho přeloží.
  9. Plurály orderForm: useCredits: Použít %count% kredit|Použít %count% kredity|Použít %count% kreditů

    Díky Symfony má translator podporu pluralizačních pravidel pro 95 různých jazyku a sám ví, který z výrazů v překladu použít, pokud se mění počet v předmětu daného překladu.
  10. Použití plurálů $translator->translate( 'front.orderForm.useCredits', 3 ); Tady translator sám pozná,

    že má vybrat druhý výraz a správně vrátí “Použít 3 kredity”.
  11. Použití v šablonách {_front.orderForm.useCredits} {_front.orderForm.useCredits, 3} {_}front.hello.world{/_} {!_front.hello.world} Kdyby řeší

    i překlady v šablonách a přidává vlastní makra. Samozřejmostí je opět podpora plurálů a parametrů. Druhý argument s počtem je opět volitelný.
  12. Jak nastavím jazyk? Kdyby obsahuje plně automatickou detekci jazyka, už

    žádné Environment::getService(translator) a setLocale() podle parametru v každém BasePresenteru. Při každém requestu se volají resolvery, které samy rozhodnou jaký jazyk použít.
  13. Routování abstract class BasePresenter { /** @persistent */ public $locale;

    První z resolverů vybírá jazyk podle parametrů App\Request, který vytváří router. Pokud jej chcete využívat, je potřeba definovat persistentní parametr locale.
  14. Routování new Route( '[<locale=cs cs|en>/]<presenter>/<action>', "Homepage:default" ); Parametr je potřeba

    taky definovat v routeru na vhodném místě, aby se předával do requestu a translator si ho mohl načíst.
  15. Accept-Language hlavička Accept-Language: cs,en;q=0.8,en-US;q=0.6 Pokud translator není schopný si přečíst

    locale z App\Request, tak zkouší zpracovat hlavičku s požadovaným jazykem, kterou posílá prohlížeč. Jazyk vybírá na základě dostupných slovníků s překlady.
  16. Jazyk v session translation: resolvers: session: on Protože ukládat jazyk

    stránky do session není zrovna best practise, je potřeba toto chování explicitně zapnout.
  17. Jazyk v session abstract class BasePresenter { /** * @var

    SessionResolver * @inject */ public $localeSession; Je potom možné si do presenteru injectnout třídu SessionResolver, kterou budeme potřebovat abychom do ní mohli nastavit jazyk, když si ho uživatel změní. Třída si ho pamatuje díky uložení do session.
  18. Jazyk v session abstract class BasePresenter { public function handleLanguage($locale)

    { $this->localeSession ->setLocale($locale); $this->redirect('this'); Jazyk je pak možné měnit například vlastním signálem.
  19. Jazyk v session {link language!, cs} {link language!, en} Vygenerovat

    odkaz na signál s jazykem, který se má nastavit, je velice snadné.
  20. Flash messages <div n:foreach='$flashes as $flash' n:class='flash, $flash->type'> {_$flash->message} </div>

    Nejsnadnější způsob jak překládat flash zprávy je použít makro na překlad v šabloně.
  21. Formuláře $form->setTranslator( $translator ); Překládat formuláře je také snadné, stačí

    jim předat translator. Nejlépe nějak globálně, pomocí DI Containeru.
  22. Formuláře $form->addText( 'name', 'front.registrationForm.name' ); Formulář pak své texty pro

    label nejprve předá translatoru, než je vykresluje. Samozřejmě je ale lepší vůbec titulek nenastavovat, vykreslovat formulář ručně a tedy mu i předat tento text k překladu až v šabloně.
  23. Formuláře $form->setTranslator( $translator->domain( 'front.registrationForm' ) ); Do formuláře si pomocí

    metody domain() můžu předat “prefixovaný translator”, což je šikovná zkratka, která vám umožní zbavit se opakování společné části identifikátoru v daném formuláři (nebo komponentě či konkrétní šabloně) a psát jen to co je v něm skutečně unikátní.
  24. Formuláře $control->setTranslator(NULL); Občas se hodí vypnutí překladů pro jeden konkrétní

    prvek, to jde udělat snadno jedním voláním. Je pak ale potřeba ručně přeložit například titulek prvku. Hodí se to když máme například dynamické hodnoty v selectu.
  25. Parametry ve formulářích $form->addText( 'name', new Phrase( 'front.registrationForm.name', ['name' =>

    $name] Ve formulářích není prostor pro nějaké parametrizované překlady nebo plurály, zajímá ho prostě titulek pro label a jak mu ho předáte je mu jedno. Jenže tento titulek vždy předává translatoru. Je tedy možné využít objekt Phrase, který dokáže propašovat parametry i počet až do translatoru, kde se správně očasuje a přeloží.
  26. Whitelisting translation: whitelist: [cs, en, de] $translator->getAvailableLocales() Pokud máte univerzální

    komponenty typu Symfony/Validator, které přidávají překlady pro 25 různých jazyků, tak nechcete, aby translator procházel a zpracovával slovníky pro jazyky které nepoužíváte. Od toho je whitelist, který odfiltruje nepotřebné jazyky. Dostupné jazyky je pak možné získat metodou getAvailableLocales()
  27. Extrakci umí, ale.. - latte je implementováno - PHP extraktor

    stále není - _() & __() jsou prasárny - Kdyby/Console command Kdyby/Translation obsahuje extractor ve formě Kdyby/Console commandu, který umí extrahovat Latte soubory. Neumí ovšem extrahovat přehlady z presenterů, komponent a dalších php souborů. Komunito, zapoj se prosím!