Kompletní lokalizace Nette aplikací – GettextExtractor v2

Upozornění: Tohle vlákno je hodně staré a informace nemusí být platné pro současné Nette.
Karel Klíma
Člen | 31
+
+1
-

Pár slov úvodem: Na tomto fóru se objevují desítky dotazů, jak přeložit celou aplikaci napsanou v Nette do jiného jazyka, a to i včetně formulářů apod. Řešení, která se doteď dala používat, byla všechna dost polovičatá. Ukázalo se, že Konečné řešení lokalizace nebylo zas tak úplně konečné… Připoutejte se prosím, na scénu přichází nové eso – GettextExtractor v2

Co to je?

GettextExtractor je nástroj, který prochází soubory a hledá v nich gettextové řetězce k přeložení. Z vyhledaných frází pak vytvoří jeden human-readable balík v podobě *.po nebo *.pot souboru a drasticky tak usnadní překladateli práci.

Stažení:

Killer features

  • Parsery pro PHP syntax i LatteFilter syntax (dříve CurlyBrackets)
  • Podpora překladu formulářů
  • Podpora překladu DataGridu
  • Možnost nastavení stávajících parserů i vytvoření vlastních
  • Funguje skvěle s GettextTranslatorem

Jak to použít

<?php
define('BASE_DIR', dirname(__FILE__));
define('APP_DIR', BASE_DIR . '/application');

require BASE_DIR . '/library/GettextExtractor/NetteGettextExtractor.php';

$ge = new NetteGettextExtractor(); // provede základní nastavení pro šablony apod.
$ge->setupForms()->setupDataGrid(); // provede nastavení pro formuláře a DataGrid
$ge->scan(APP_DIR); // prohledá všechny aplikační soubory
$ge->save(APP_DIR . '/locale/myapp.en.po'); // vytvoří Gettextový soubor editovatelný např v Poeditu
?>

Definice vlastních pravidel

<?php
require dirname(__FILE__) . '/GettextExtractor/GettextExtractor.php';
$ge = new GettextExtractor('extractor.log') // průběh bude logován do souboru
$ge->removeAllFilters(); // zruší základní nastavení
$ge->setFilter('php', 'PHP'); // přiřadí PHPFilter příponě php
$ge->getFilter('PHP')->addFunction('translate')->addFunction('_'); // nastaví filtr PHP
?>

Více příkladů najdete přímo v distribuci.

Mám extrahováno, co dál?

Jakmile GettextExtractor vytvoří gettextový zdrojový soubor, mám vyhráno pouze z poloviny. Dále se nabízejí celkem tři možnosti:

  1. Jsme-li již v této fázi unavený a unuděný a znechucený, můžu se na lokalizaci vykašlat
  2. Můžu zkopírovat vytvořený soubour a ručně do něj dopsat překlady v nějakém textovém editoru.
  3. Můžu využít Poedit a pracovat s gettextem efektivně. Lze vytvořit nový katalog z POT souboru (což je šablona pro PO soubory), ten pohodlně upravit a následně uložit. Poedit již sám přeloží gettext do binárního MO souboru, což je cíl, kam se potřebujeme dostat. Tento MO soubor už může být zpracován například GettextTranslatorem

Související vlákna

https://forum.nette.org/…i-lokalizace

https://forum.nette.org/…tte-aplikaci

https://forum.nette.org/…-i18n-a-l10n

Co zbývá doladit

Především je potřeba vše otestovat a dále potom zjistit, jestli nechybí handlery pro některé formulářové nebo datagridové funkce. Kdo odhalí nějaký nedostatek, tomu budiž odměnou dobrý pocit v srdci :-) Budu rád za jakékoliv připomínky nebo nápady, jak by se tahle užitečná věcička dala ještě více zdokonalit.

Ondřej Mirtes
Člen | 1536
+
0
-

Ještě než to s chutí vyzkouším, zeptám se: vyžaduje to stále escapování řetězců v šablonác {!_'string'} nebo už mu stačí {_'string'}? Podporuje oboje?

Až se pustím do testování, určitě přijde více otázek :)

hurvajs
Člen | 86
+
0
-

Možná docela hloupá otázka, ale proč se všichni snažíte předělávat již dokonalý gettext v PHP? Osobně nechápu proč bych měl dělat lokalizace podle následujících kroků:

  1. napsat kód,
  2. vytvořit si PO soubory,
  3. následně přeložit např. EN → CZ,
  4. vygenerovat MO soubory,
  5. vytvořit objekt translate a zpětně rozparsovat binární MO soubory na text a jednotlivé klíče a překlady.

To je na mě nezlobte, ale je to nošení dříví do lesa. Bez problémů mohu skončit na bodu 4) protože PHP si vše zařídí samo a nemusím se o nic starat. Nehledě na to, že silně pochybuji, že by se objekt translate nemusel kešovat.

hurvajs
Člen | 86
+
0
-

A propo, vsechny uváděné Killer features umí sám o sobě xgettext ;-) Takze se v podstatě nejedná o žádné killer…

norbe
Backer | 405
+
+1
-

hurvajs napsal(a): …

Přijde mi, že jsi moc nepochopil, k čemu tenhle script vlastně slouží. GettextExtractor neslouží k samotnému překladu. Jedná se o script, který ve spojení s Poeditem automaticky vytáhne texty, které je potřeba přeložit. To si myslím, že je velmi užitečný.

To jestli pak budeš používat pro překlad gettext, nebo jiný řešení je už na Tobě.

hurvajs
Člen | 86
+
0
-

Ano, to vim, k cemu slouzi. Ale na to je hotovy uz hoooodne davno xgettext, ktery ti prijde co chces a vygeneruje PO soubory. Takze je to k nicemu – myslim GettextExtractor.

Nehlede na to, ze POEdit je dost spatny. 100% lepsi je proste upravit soubor rucne. PO je v podstate textovy soubor a staci jen znat jeho format.

Karel Klíma
Člen | 31
+
+1
-

LastHunter napsal(a):

Ještě než to s chutí vyzkouším, zeptám se: vyžaduje to stále escapování řetězců v šablonác {!_'string'} nebo už mu stačí {_'string'}? Podporuje oboje?

Podporuje oboje. Dokonce podporuje libovolný prefix (i více prefixů), který se nadefinuje.

hurvajs napsal(a):

Možná docela hloupá otázka, ale proč se všichni snažíte předělávat již dokonalý gettext v PHP? Osobně nechápu proč bych měl dělat lokalizace podle následujících kroků:

  1. napsat kód,
  2. vytvořit si PO soubory,
  3. následně přeložit např. EN → CZ,
  4. vygenerovat MO soubory,
  5. vytvořit objekt translate a zpětně rozparsovat binární MO soubory na text a jednotlivé klíče a překlady.

S GettextExtractorem body 1) a 2) odpadají, bod 5) záleží už čistě na implementaci překladového adaptéru.

To je na mě nezlobte, ale je to nošení dříví do lesa. Bez problémů mohu skončit na bodu 4) protože PHP si vše zařídí samo a nemusím se o nic starat. Nehledě na to, že silně pochybuji, že by se objekt translate nemusel kešovat.

To je pravda. Někomu ale nativní podpora gettextu v PHP nemusí nutně vyhovovat, zvlášť nakládání s plurály je docela podivné. Implementace vlastního adaptéru pro překlad pak vývojáři umožní aplikace/stránky dělat přesně tak, jak potřebuje.

A propo, vsechny uváděné Killer features umí sám o sobě xgettext ;-) Takze se v podstatě nejedná o žádné killer…

A zvládne obyčejný smrtelník nakonfigurovat xgettext, aby dělal přesně tohle, za dvacet vteřin? Půvab tohoto řešení spočívá v tom, že je již přesně připravené na práci s Nette a šablonami, resp. LatteFilterem. V tomhle to xgettext trumfne na celé čáře, protože upřímně, komu by se chtělo psát vlastní parser pro xgettext?

hurvajs napsal(a):

Ano, to vim, k cemu slouzi. Ale na to je hotovy uz hoooodne davno xgettext, ktery ti prijde co chces a vygeneruje PO soubory. Takze je to k nicemu – myslim GettextExtractor.

Nehlede na to, ze POEdit je dost spatny. 100% lepsi je proste upravit soubor rucne. PO je v podstate textovy soubor a staci jen znat jeho format.

S některými tvrzeními bych byl opatrný. Přece jenom může existovat někdo, kdo nesdílí stejné názory.

Editoval Karel Klíma (22. 10. 2009 15:25)

jasir
Člen | 746
+
0
-

Pěkná práce, určitě vyzkouším.

hurvajs napsal(a):

A propo, vsechny uváděné Killer features umí sám o sobě xgettext ;-) Takze se v podstatě nejedná o žádné killer…

Mohu poprosit o další poučení? Jak na to tedy s xgettextem? Děkuji.

Editoval jasir (22. 10. 2009 15:48)

kravčo
Člen | 721
+
0
-

Karel Klíma napsal(a):

S některými tvrzeními bych byl opatrný. Přece jenom může existovat někdo, kdo nesdílí stejné názory.

Povedal by som, že v 100% prípadov sa nájde niekto, kto môj názor zdieľať nebude… To, že niečo tvrdím neznamená, že je to názor všetkých…

hurvajs
Člen | 86
+
0
-

Karel Klíma napsal(a):
S GettextExtractorem body 1) a 2) odpadají, bod 5) záleží už čistě na implementaci překladového adaptéru.

Odpadaji? Tomu moc nerozumim. Myslel jsem napsat samotnou aplikaci v Nette. Body 1), 2) a 4) jsou proste nutne. Pro POEdit jsou nutne PO soubory, takze se musi bud pouzit xgettext nebo Gettextextractor. Ale vysledek jsou nutne PO soubory. A jak jsem uvedl, mam radeji cista reseni, na gettext existuje velice dobry programek xgettext a umi vse co umi GettextExtractor.

To je pravda. Někomu ale nativní podpora gettextu v PHP nemusí nutně vyhovovat, zvlášť nakládání s plurály je docela podivné. Implementace vlastního adaptéru pro překlad pak vývojáři umožní aplikace/stránky dělat přesně tak, jak potřebuje.

Podotykam, ze u sebe samotneho nevidim duvod, proc bych mel pouzivat nejakou nahradu za gettext. Stejne v kodu pisi _('gettext is perfect'), tak mohu nechat preklad primo na gettextu. Reseni bude na 100% rychlejsi, nemusi se kesovat (uz si to kesuje Apache). Drtiva vetsina hostingu ma gettext zapnuty, takze opravdu nevidim duvod pouzivat neco jineho. Dalsi nespornou vyhodou, je treba v Linuxu se gettext pouziva na lokalizace aplikaci.

Plural ze je spatne? He, to je docela zajima informace. Pouzivam gettext asi tak 6 let a jeste jsem nemel problem, ze bych mel spatne sklonovanou cestinu napriklad.

A zvládne obyčejný smrtelník nakonfigurovat xgettext, aby dělal přesně tohle, za dvacet vteřin? Půvab tohoto řešení spočívá v tom, že je již přesně připravené na práci s Nette a šablonami, resp. LatteFilterem. V tomhle to xgettext trumfne na celé čáře, protože upřímně, komu by se chtělo psát vlastní parser pro xgettext?

Nemusi se nic psat. Implementovano jiz v OS. Takze pokud clovek spusti xgettext s prislusnymi parametry (treba jake typy souboru ma prohledat), tak mu to vyplivne PO. Cele kouzlo. Zalezitost na 1 sek. Pak upravim v text. editoru PO a preklady klicu, pregeneruji do binarnich MO a mam hotovo.

S některými tvrzeními bych byl opatrný. Přece jenom může existovat někdo, kdo nesdílí stejné názory.

S jakymi tvrzenimi? To ze je POEdit na dve veci? Na nic a na smazani. Za tim si stojim… :-D

Samozrejme, chapu ze neco nemusi vyhovovat vsem, kazdy ma jine naroky. Nikomu nic neberu. Jen jsem se ptal, proc se „v uvozovkach“ delaji nektere veci znova, kdyz na to jiz existuji silne nastroje.

redhead
Člen | 1313
+
0
-

Taky zajímavá myšlenka, proč se věci dělají znova?

To je jakoby proč by měli být všechny distribuce linuxu, když už je windows, nebo naopak. Nebo proč vlastně David dělá Nette, když je už celá řada jinejch frameworků, který dělají to samé a ještě víc (btw. na nette nedám dopustit)?? Proč je Photoshop, když už je Gimp?

Nemám linux, čili říkám hned, že to (nejspíš, nevím zdali je nějaká windows verze) například já nerozjedu. Navíc mám averzi k těmhle konzolovým přepínačovým programům.

Nevím zdali je rychlejší napsat tenhle command, než jenom dát v prohlížeči F5! Pro mě určitě ne!

Nechci žádný flamewar, jen jsem chtěl trochu vyjádřit i svůj názor na to co jsi tu řekl. Nemám nic proti xgettext, jen chci říct, že každý může používat to co má radši. Není to o tom, že je tu jeden nástroj, že ho hned musí používat všichni a nemůže být jiný.

Já osobně jsem za tohle rád.

S pozdravem
redhead

hurvajs
Člen | 86
+
0
-

Vsak ja to nikomu neberu. Ja pouzivam xgettext, jsem s nim spokojen. Puvodne jsem se ptal, proc p. Klima se psal GettextExtractor kdyz na to uz jsou hotove veci a dobre. Ze v podstate se tim nahrazuje funkcionalita gettextu. Ale to je jedno. nicmene, klobouk dolu, protoze na tom musel nechat nejakou tu hodinu a udelat to.

GettextExtractor a gettext neni preci o F5 v browseru, ale o tom jak vytahnout klice, ktere se pak prekladaji. Alespon tak chapu ja fci GettextExtractoru.

Verim, ze nekomu to opravdu pomuze. Me asi ne. Samozrejme nechavam kazdemu pravo volby, at pouziva co chce.

Ja bych byl treba rad za mnohem obsirnejsi dokumentaci a priklady – neco jako ZF. Taky kazdy z Vas/nas musi uznat, ze Nette dost pokulhava, ikdyz se na tom podle p. Grudla urputne pracuje. Jen to prosim, nikdo neberte spatne nebo navazeni se do Nette ;-)

hurvajs
Člen | 86
+
0
-

jasir napsal(a):

Mohu poprosit o další poučení? Jak na to tedy s xgettextem? Děkuji.

Třeba takto:

find ./ -name \*.php | xargs xgettext --no-wrap --from-code=utf-8 --language=PHP

Čímž vytáhneš gettext ze všech PHP souborů. Lze to jednoduše rozšířit i na šablony či cokoliv jiného. Samozřejmě xgettext má mnohem více možností.

redhead
Člen | 1313
+
0
-

No právě že F5 v prohlížeči stačí pro vytáhnutí těch klíčů. O to jde.

Píšu si do aplikace texty, skočím do browseru, F5, skočím do PoEditu a překládám, CTRL+S, skočím do browseru F5 a všechno krásně přeloženo.

Myslím, že je to prostě komfort, který se mě osobně líbí! Jen tak dál..

hurvajs
Člen | 86
+
0
-

Hmm, tak to v podstate stejny postup jako mam ja, jen s tim rozdilem, ze ja misto F5 pouziji bash, misto POedit VIM. Jinak je to uplne stejne a stejny komfort ;-). A pokud se nejedna o prvotni parsovani gettextu, tak vlezu do administrace a menim preklady tam.

Editoval hurvajs (22. 10. 2009 18:11)

redhead
Člen | 1313
+
0
-

Aha, tak to ok. Ovšem linux nemám :)

jasir
Člen | 746
+
0
-

hurvajs napsal(a):

jasir napsal(a):

Mohu poprosit o další poučení? Jak na to tedy s xgettextem? Děkuji.

Třeba takto:

find ./ -name \*.php | xargs xgettext --no-wrap --from-code=utf-8 --language=PHP

Čímž vytáhneš gettext ze všech PHP souborů. Lze to jednoduše rozšířit i na šablony či cokoliv jiného. Samozřejmě xgettext má mnohem více možností.

Díky. Ale vytáhne to i ze šablon konstrukce {_ a {_! a volání translate() metod? Volání php funkce to jistě zvládá, jde mi o tyto konkrétní věci. Používám tedy také windows a pod ním cygwin.

romansklenar
Člen | 655
+
0
-

hurvajs napsal(a):

Reseni bude na 100% rychlejsi, nemusi se kesovat (uz si to kesuje Apache).

Nevíš jestli se nějak nedá vynutit, aby si Apache .mo soubor nakešoval znovu?

wdolek
Člen | 331
+
+1
-

vzhledem k tomu, ze jsem s GetTextem nikdy nepracoval, mam trosku problémy pochopit, jak to cele funguje. z prikladu z archivu jsem se toho moc nedozvedel – respektive sem si mohl zacit myslet neco o zahadne magii, kdy tento program nejak precte vsechny skripty, a nejak nahradi (?) / prelozi texty treba v popisku formularovych prvku.

nanestesti to je v ostrem kontrastu s tim malem, co o gettextu vim – tedy ze se pouziva funkce gettext( ) nebo jeji alias _( ). tuto funkci musim uvest vsude, kde chci, aby se texty prekladaly + vyrobit .po soubor, prelozit, umistit na web .mo soubor, a pridat nekam na zacatek inicializaci gettextu…

takze :) odpustte mi muj skromny duvtip (respektive velkolepy neduvtip), ale poradi mi nekdo, co vse musim udelat, kdyz mam nyni web kompletne v cestine (nikde zadne volani _( ) nebo jakesi translate funkce (co je to zac?)) a chci vyrobit anglickou mutaci? (predpokladam, ze musim zeditovat vsechny texty a nacpat je do _( ) – ale jak rikam, z ukazek jsem moc nepobral, jestli to je automatizovane, nebo ne… pak nejakou editaci pomoci Poeditu jeste chapu… a pak zase zpetne namontovani do Nette – to uz mi take neni jasne)

predem diky :)

Karel Klíma
Člen | 31
+
0
-

wdolek napsal(a):

vzhledem k tomu, ze jsem s GetTextem nikdy nepracoval, mam trosku problémy pochopit, jak to cele funguje. z prikladu z archivu jsem se toho moc nedozvedel – respektive sem si mohl zacit myslet neco o zahadne magii, kdy tento program nejak precte vsechny skripty, a nejak nahradi (?) / prelozi texty treba v popisku formularovych prvku.

nanestesti to je v ostrem kontrastu s tim malem, co o gettextu vim – tedy ze se pouziva funkce gettext( ) nebo jeji alias _( ). tuto funkci musim uvest vsude, kde chci, aby se texty prekladaly + vyrobit .po soubor, prelozit, umistit na web .mo soubor, a pridat nekam na zacatek inicializaci gettextu…

takze :) odpustte mi muj skromny duvtip (respektive velkolepy neduvtip), ale poradi mi nekdo, co vse musim udelat, kdyz mam nyni web kompletne v cestine (nikde zadne volani _( ) nebo jakesi translate funkce (co je to zac?)) a chci vyrobit anglickou mutaci? (predpokladam, ze musim zeditovat vsechny texty a nacpat je do _( ) – ale jak rikam, z ukazek jsem moc nepobral, jestli to je automatizovane, nebo ne… pak nejakou editaci pomoci Poeditu jeste chapu… a pak zase zpetne namontovani do Nette – to uz mi take neni jasne)

predem diky :)

Pokud aplikace pro překlad není připravená, bude se muset upravit. (Nette)GettextExtractor umí automaticky vytáhnout řetězce pro překlad třeba z formulářů, ale z šablon už ne – tam je třeba každou frázi hodit do makra {_"Něco na překlad"}, respektive {!_"Něco na překlad s escapováním"} (pokud je použit LatteFilter). Z tohoto zápisu si to už umí GettextExtractor vytáhnout. Naproti tomu pokud je v šabloně třeba něco jako <p>Věta v odstavci</p>, pak to ignoruje.

Pro lokalizaci celé aplikace je třeba učinit tyto kroky:

  1. Upravit šablony podle vzoru výše, viz filtr Latte
  2. Vytvořit soubor podobný souboru Examples/NetteGettextExtractor.php v distribuci. Zde je potřeba akorát správně nastavit, kde všude se má hledat (metoda GettextExtractor::scan()) a kam se to pak má uložit (metoda GettextExtractor::save()). Obě dvě jsou v tomto příkladu k nalezení.
  3. Spustit soubor z předchozího bodu (například skrz prohlížeč)
  4. Zkopírovat vygenerovaný *.po(t) soubor a přeložit v Poeditu. Kopírování silně doporučuji, protože při každém spuštění GettextExtractoru se vygenerovaný soubor přepíše a zmizí tak veškerá manuálně vytvořená data (překlady).
  5. Použít GettextTranslator, který nevyžaduje přímou podporu gettextu, nebo si napsat vlastní Translator, který bude využívat nativní gettextové funkce gettext a ngettext.
vladik
Člen | 3
+
0
-

Ahoj Karle myslíš, že by jsi mohl udělat konkrétní příklad buď video nebo podrobný popis? Já s Nette teprve začínám, ale nevím kde uvedenou část kódu vložit …do index.php nebo do šablony @layout.phtml ?

Adresář GettextExtractor jsem nakopíroval do adresáře libs a v adresáři app mám adresář locale. Knihovnu GettextTranslator.php mám v libs/Nette.

Jak dál pokračovat?

děkuji ua info

Karel Klíma
Člen | 31
+
0
-

vladik napsal(a):

Ahoj Karle myslíš, že by jsi mohl udělat konkrétní příklad buď video nebo podrobný popis? Já s Nette teprve začínám, ale nevím kde uvedenou část kódu vložit …do index.php nebo do šablony @layout.phtml ?

Adresář GettextExtractor jsem nakopíroval do adresáře libs a v adresáři app mám adresář locale. Knihovnu GettextTranslator.php mám v libs/Nette.

Jak dál pokračovat?

Vezmi soubor Examples/NetteGettextExtractor.php a zkopíruj ho do stejný složky jako je index.php (složka public například podle suggested directory structure). Pak soubor uprav a nastav mu správně cesty, tzn. změň ho nějak takhle:

<?php

echo '<pre>';
echo 'NetteGettextExtractor';

require_once dirname(__FILE__) . '/../libs/GettextExtractor/NetteGettextExtractor.php';

$ge = new NetteGettextExtractor();

$ge->setupForms();
$ge->setupDataGrid();

$ge->scan(dirname(__FILE__) . '/../app');

$ge->save(dirname(__FILE__) . '/../app/locale/translation.po');

echo '</pre>';
?>

Snad jsem tam někde neudělal chybu… Dále už stačí jenom zobrazit soubor NetteGettextExtractor.php v prohlížečí a spuštěný skript pak vytvoří soubor translation.po v adrešáři app/locale.

Pro použití GettextTranslator viz jeho dokumentaci.

Patrik Votoček
Člen | 2221
+
0
-

Karel Klíma napsal(a):

  1. Zkopírovat vygenerovaný *.po(t) soubor a přeložit v Poeditu. Kopírování silně doporučuji, protože při každém spuštění GettextExtractoru se vygenerovaný soubor přepíše a zmizí tak veškerá manuálně vytvořená data (překlady).

A nešlo by udělat něco jako metodu saveMerge() aneb že by to spojilo prave vygenerovany *.po(t) soubor se souborem ktery už obsahuje nějáké překlady?

Karel Klíma
Člen | 31
+
0
-

vrtak-cz napsal(a):

Karel Klíma napsal(a):

  1. Zkopírovat vygenerovaný *.po(t) soubor a přeložit v Poeditu. Kopírování silně doporučuji, protože při každém spuštění GettextExtractoru se vygenerovaný soubor přepíše a zmizí tak veškerá manuálně vytvořená data (překlady).

A nešlo by udělat něco jako metodu saveMerge() aneb že by to spojilo prave vygenerovany *.po(t) soubor se souborem ktery už obsahuje nějáké překlady?

Bylo by to proti logice věci. Tohle jsou argumenty, proč to neimplementovat:

  1. Podporuje to přímo Poedit. POT soubory jsou jakési šablony, které mají obsahovat pouze nepřeložené fráze, složí jako vzor. Poedit pak umí z těchto souborů udělat update PO souboru, a to tak, že se zachovají pouze fráze, které jsou v POT souboru. Jinými slovy – fráze, které v aplikaci nejsou, se vymažou.
  2. Lokalizace většinou počítá s větším množstvím jazyků. Měly by se pak mergovat všechny soubory? Jednoduše řečeno, zdroj a výsledek by měly zůstat odděleny.
vladik
Člen | 3
+
0
-

Ahoj Karle,

tak jak jsi mi poradil, tak to opravdu zafungovalo. Nicméně byl vytvořen jen jeden soubor translation.po
Proto abych měl více překladů jsem si vytvořil strukturu locale/cs/LC_MESSAGES/messages.po pak locale/en/LC_MESSAGES/mesages.po locale/sk/LC_MESSAGES/messages.po atd.

otázka

1. Když mám vygenerovaný soubor .po z řetězců, které jsou v šabloně česky {!_"Něco na překlad s escapováním"}
tak, v souboru locale/cs/LC_MESSAGES/messages.po bude jak originál tak i překlad česky?

2. Když jsem použil {!_"Něco na překlad s escapováním"} tak mi to vyhodilo chybovou hlášku

MemberAccessException
Call to undefined method Template::translate().

3. Jakou definici mám použít pro přepínání jazykových verzí?
a tuto definici mám uložit do index.php v adresáři www nebo do šablony @layout.phtml v adresáři Template?

děkuji za radu

Vladik

Karel Klíma
Člen | 31
+
0
-

vladik napsal(a):

tak jak jsi mi poradil, tak to opravdu zafungovalo. Nicméně byl vytvořen jen jeden soubor translation.po
Proto abych měl více překladů jsem si vytvořil strukturu locale/cs/LC_MESSAGES/messages.po pak locale/en/LC_MESSAGES/mesages.po locale/sk/LC_MESSAGES/messages.po atd.

To jsi udělal správně. Přesně tak to má fungovat.

otázka

1. Když mám vygenerovaný soubor .po z řetězců, které jsou v šabloně česky {!_"Něco na překlad s escapováním"}
tak, v souboru locale/cs/LC_MESSAGES/messages.po bude jak originál tak i překlad česky?

Ano. Nebo to můžeš úplně vynechat. Sice bych osobně doporučil do šablon nepsat diakritiku (i když všechno běží v unicode), ale i takhle se to dá řešit.

2. Když jsem použil {!_"Něco na překlad s escapováním"} tak mi to vyhodilo chybovou hlášku

MemberAccessException
Call to undefined method Template::translate().

Hm… Není nějaký problém s definicí helperu ‚translate‘? Jakým způsobem inicializuješ Translator? Pokud můžeš, používej radši verzi bez vykřičníku, tj. {_"Něco"}.

3. Jakou definici mám použít pro přepínání jazykových verzí?
a tuto definici mám uložit do index.php v adresáři www nebo do šablony @layout.phtml v adresáři Template?

To závisí čistě na tobě. Implementace by měla být každopádně v buď v indexu (respektive bootstrapu) nebo v presenteru. Překladovou logiku bych v šabloně určitě neřešil.

wdolek
Člen | 331
+
0
-
Notice: Undefined index:  extension in /.../www/.../document_root/GettextExtractor.php on line 153

:) ja vim, je to „jen“ Notice, ale kdyz ja jsem takovy puntickar

wdolek
Člen | 331
+
0
-

inu, tak jsem si s tim chvilku hral, postupoval podle navodu, ale bez vysledku

  1. prepsal sem sablony na volani {_" "}
  2. projel sem GettextExtractorem projekt
  3. pomoci POEditu prelozil (cs → en)
  4. soubor .mo jsem nahral do app/locale/en/LC_MESSAGES/messages.mo
  5. pridal do DefaultPresenter do metody beforeRender prirazeni prekladace sablony (ne vsechny presentery potrebuju prekladat – administracni presenter je pouze v cestine, default je v cestine i anglictine)
  6. smazal app/temp … ale nic :(

sablona:

<a href="#">{_"Kniha návštěv"}</a>

DefaultPresenter:

protected function beforeRender() {
	// translator
	$translator = new Translator($this->lang, (APP_DIR . '/locale'));
	$this->template->setTranslator($translator);

	...
}

… skutecne $this->lang obsahuje en pro anglictinu, cs pro cestinu

jako transrator jsem si vzal ten co je na http://charlie.cz/…t-extractor/


mimochodem, takto vypada muj translatoidni skript

<?php
echo '<pre>';

require_once dirname(__FILE__) . '/NetteGettextExtractor.php';

$ge = new NetteGettextExtractor();
$ge->setupForms();
$ge->scan(array('../app/models/', '../app/templates/Default/', '../app/templates/@layout.phtml'));
$ge->save('nette.po');

echo '</pre>';

prekvapilo me ale, ze v prekladech sem mel pouze veci ze sablon, nic z formularu (cesty sedi). .po soubor obsahoval pouze veci z @layout.phtmldefault.phtml

wdolek
Člen | 331
+
0
-

4. soubor .mo jsem nahral do app/locale/en/LC_MESSAGES/messages.mo

:) tak jsem na to „vyzral“ a prejmenoval slozku „en“ na „en_US“ a voala, vse slo… tedy temer – GettextExtractor stale nevyzoba vsechny texty :(

vladik
Člen | 3
+
0
-

Ahoj,

rád bych ještě požádal o radu…já když použiji {_"Kniha návštěv"} v šabloně v adresáři template

tak mi to vyhodí chybu

MemberAccessException

Call to undefined method Template::translate().

Line 223:                foreach ($this->helperLoaders as $loader) {
Line 224:                    $helper = call_user_func($loader, $lname);
Line 225:                    if ($helper) {
Line 226:                        $this->registerHelper($lname, $helper);
Line 227:                        return call_user_func_array($helper, $args);
Line 228:                    }
Line 229:                }
Line 230:                return parent::__call($name, $args);
Line 231:            }
Line 232:
Line 233:            return call_user_func_array($this->helpers[$lname], $args);
Line 234:        }
Line 235:
Line 236:
Line 237:

nevím, kde mám co definovat

také nevím jak nadeginovat v hlavičce šablony aby se defaultně použila čeština

a jak volat v odkazu jiné překlady?

<a href="http://www.pokus.cz"><img src="{$baseUri}images/cs.gif" alt="Čeština (Česká republika)" title="Čeština (Česká republika)" /></a>

děkuji za info

Vladik

Editoval vladik (7. 11. 2009 21:36)

Kevas
Člen | 12
+
0
-

Ahoj,

je verze php 5.2.2 a vyšší důležitá pro funkčnost? Mám totiž na hostingu verzy 5.2.0–8+etch15.

Děkuji

Editoval Kevas (11. 11. 2009 22:19)

Karel Klíma
Člen | 31
+
0
-

Kevas napsal(a):

Ahoj,

je verze php 5.2.2 a vyšší důležitá pro funkčnost? Mám totiž na hostingu verzy 5.2.0–8+etch15.

Děkuji

Nejsem si jistý. Pravděpodobně tam to omezení je kvůli Tokenizeru, ale nedá se vyloučit, že knihovna bude správně pracovat i v nižších verzích PHP.

despiq
Člen | 320
+
0
-

ahoj, myslim ze gettextextractor neextrahuje z latte zapisu {!_'I see %d little indians', 100} nic

v examples by mel byt asi funkcni NetteGettextExtractor.php ale vlastne neni

Honza Kuchař
Člen | 1662
+
0
-

Nechcete to přidat do extras?

ji_ri_k
Člen | 44
+
0
-

Laboruji teď také s gettextem, ale nedaří se mi jak bych chtěl. Nikdy jsem s tímto nástrojem nepracoval, proto se na vás obracím. V šabloně mám:

<p>{_'You have %s new message.', 1}</p>

Při použití GettextExtractoru mi to tento text ze šablony do .po souboru nevytáhne. Najde to jen {_'You have %s new message.'}. Jakým jiným způsobem ve windows je možno tyto soubory vytáhnout?

Další problém mám s plurály. Jakým způsobem to mám do šablony zadat? Stačí to zanechat takto? {_'You have %s new message.', 1} a pak to v .po souboru doeditovat?

A jak v např. v Poeditu ty plurály doplním? Nikdy se mi tam možnost je zadat nezobrazila.

Lokalizaci webů jsem řešil vždy jinými způsoby a rád bych se seznámil s tímto řešením, budu rád, když mi někdo pomůžete. Teď v tom bohužel plavu jak kámen v rybníku…

dotTwelve
Člen | 167
+
0
-

Pouzivam aplikaci s moduly a tato vyjimka se mi vyhodi pri zavolani gettext.php

Cannot load presenter 'Gettext:Php', class 'Gettext_PhpPresenter' was not found in 'www/document_root/../app/GettextModule/presenters/PhpPresenter.php'.

Obsah gettext.php

<?php
define('BASE_DIR', dirname(__FILE__));
define('APP_DIR', BASE_DIR . '/app');

require BASE_DIR . '/libs/GettextExtractor/NetteGettextExtractor.php';

$ge = new NetteGettextExtractor(); // provede základní nastavení pro šablony apod.
$ge->setupForms()->setupDataGrid(); // provede nastavení pro formuláře a DataGrid
$ge->scan(APP_DIR); // prohledá všechny aplikační soubory
$ge->save(APP_DIR . '/locale/front/template.po'); // vytvoří Gettextový soubor editovatelný např v Poeditu
?>
sodae
Nette Evangelist | 250
+
0
-

dotTwelve: přidej do .htaccess do podmínky že i php se neodešlou do index.php ale spíše se myslim že to nemáš ve složce document_root (nebo kde je index.php)

dotTwelve
Člen | 167
+
0
-

Uz jsem si vytvoril routu a presenter Tools a v nem akci getText() a tedka si volam pouze /tools/gettext/modul a generuje se mi podle toho soubor .po pro admin modul, nebo front modul.

ji_ri_k
Člen | 44
+
0
-

ji_ri_k napsal(a):

Laboruji teď také s gettextem, ale nedaří se mi jak bych chtěl. Nikdy jsem s tímto nástrojem nepracoval, proto se na vás obracím. V šabloně mám:

<p>{_'You have %s new message.', 1}</p>

Při použití GettextExtractoru mi to tento text ze šablony do .po souboru nevytáhne. Najde to jen {_'You have %s new message.'}. Jakým jiným způsobem ve windows je možno tyto soubory vytáhnout?

Další problém mám s plurály. Jakým způsobem to mám do šablony zadat? Stačí to zanechat takto? {_'You have %s new message.', 1} a pak to v .po souboru doeditovat?

A jak v např. v Poeditu ty plurály doplním? Nikdy se mi tam možnost je zadat nezobrazila.

Lokalizaci webů jsem řešil vždy jinými způsoby a rád bych se seznámil s tímto řešením, budu rád, když mi někdo pomůžete. Teď v tom bohužel plavu jak kámen v rybníku…

Tak jsem se k tomu dnes opět dostal, ale koukám, že odpověď jsem nedostal. Možná jsem se špatně zeptal.

Některé části jsem dnes vyřešil, ale co se mi stále nedaří je vytažení všech textů do .po souboru.
Proto by mne zajímalo, jakým způsobem vytahujete z phtml šablon texty k překladu?
např.:

{_'You have %s new message.', 1}
iguana007
Člen | 970
+
0
-

Mám podobný problém a nedaří se mi jej vyřešit: https://forum.nette.org/…i-lokalizace?…

despiq
Člen | 320
+
0
-

musi se predelat ten pattern na latte sablony

ClaryAldringen
Člen | 5
+
0
-

Zdravím, mám takový problém s Translatorem. Všechny texty se v pořádku přeloží, akorát v polích, kde je prázdná EmptyValue se nachází tento text:

Project-Id-Version:
POT-Creation-Date:
PO-Revision-Date:
Last-Translator: Martin Zadražil <zadram1@gmail.com>
Language-Team:
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Nevíte někdo jak se tohoto zbavit? Díky

norbe
Backer | 405
+
0
-

Přidáš do translatoru podmínku, aby se prázdný řetězec nepřekládal :)

Jarda
Člen | 25
+
0
-

Ahoj, zkouším toto chytré řešení, ale zápasím s poEditem. Jak ho přinutím, aby mi nabídl zápis 3 plurálů pro řetězec: I see %d little indians!

katalog mám nastavený dle návodu na plurály:

nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4 ? 1 : 2);

přesto mi poedit nabízí ke klíči pouze jeden překlad a nikde se mi nepodařilo vygooglit jak na to.

Předem díky za pomoc

verze poeditu: 1.4.6 (win)

Lopo
Člen | 277
+
0
-

Jarda napsal(a):

Ahoj, zkouším toto chytré řešení, ale zápasím s poEditem. Jak ho přinutím, aby mi nabídl zápis 3 plurálů pro řetězec: I see %d little indians!

katalog mám nastavený dle návodu na plurály:

nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4 ? 1 : 2);

přesto mi poedit nabízí ke klíči pouze jeden překlad a nikde se mi nepodařilo vygooglit jak na to.

Předem díky za pomoc

verze poeditu: 1.4.6 (win)

skus

nplurals=3; plural=((n==1) ? 0 : (n>=2 && n<=4 ? 1 : 2));

mam totiz dojem ze najprv priradi do premennej vysledok (n==1) a to potom posuva do ternaru

Editoval Lopo (3. 6. 2010 7:27)

Jarda
Člen | 25
+
0
-

bohužel ani to nepomohlo…

despiq
Člen | 320
+
0
-

nplurals=3; plural=(n==1) ? 0 : ((n>=2 && n<=4) ? 1 : 2);

Jarda
Člen | 25
+
0
-

tak po dalším experimentování jsem zjistil, že nakonec byla chyba v .po souboru.

U plurálových forem musí být v .po souboru následující úprava

msgid "I see %d little indians!"
msgid_plural "I see %d little indians!"
msgstr[0] ""
msgstr[1] ""
msgstr[2] ""

to jsem nevěděl a GettextExtractor udělá pouze

msgid "I see %d little indians!"
msgstr "I see %d little indians!"

Domníval jsem se, že plurály poedit nabídne automaticky u řetězců s %d.

Dá se to řešit nějak automatizovaně v GettextExtractoru nebo v poeditu? nebo se musejí plurály ručně doupravit?

voda
Člen | 561
+
0
-

Jarda napsal(a):

Dá se to řešit nějak automatizovaně v GettextExtractoru nebo v poeditu? nebo se musejí plurály ručně doupravit?

Je to v zakomentováno metodě GettextExtractor::formatData. Mělo by stačit odkomentovat.

Jarda
Člen | 25
+
0
-

jj, už na to koukám, stačilo trochu poupravit a už jede jak po másle. GettextExtractor je vážně kůl tůl :) Díky za něj!