Lepší podpora vícejazyčnosti
- knyttl
- Člen | 196
Ahoj,
jelikož mám databázi pro překládání normálně v MySQL, tak abych ji mohl snadno měnit přes datagrid, překládání samozřejmě není nijak extra rychlé. Normální makra {_"…"} jsou překládány až při zobrazení stránky a tudíž neustále dokola při každém zobrazení.
Vyřešil jsem to tak, že jsem podědil funkci createPresenter a v ní šablonám změnil adresář podle vybraného jazyka a stejně tak i změnil adresář cachovací service; potom jsem si napsal filtry, které překládají makra {_"…"} již při kompilaci šablon. Mám tedy teď zvlášť cache pro každý jazyk. Mám tedy adresáře:
temp/cache
temp/cache/_
temp/cache/_Nette.RobotLoader
temp/cs/_NetteFileTemplate
temp/cs/_NetteTemplate.Cache
temp/en/_NetteFileTemplate
temp/en/_NetteTemplate.Cache
Přijde mi to ale dost „zprasené“ a myslím, že by něco takového mohlo umět samotné Nette.
Př.: Kdyby šlo v configu povolit jazykové verze [cs, en], zaregistrovat překládací službu a definovat jak se má daný jazyk rozpoznat. Nette pak automaticky by cachovalo do adresářů podle jazyka.
Přijde mi prostě nesmyslné překládat šablony neustále dokola, když to může proběhnout jen jednou.
Editoval knyttr (2. 5. 2011 8:43)
- Jur4
- Člen | 51
Myslím, že jsi nepochopil jak přesně to funguje (nebo jsem já nepochopil o co se snažíš).
Jde o to, že šablony se v jakémkoliv jazyce nakešujou úplně stejně,
protože makro {_'message'}
se nahradí voláním funkce
$template->translate('message')
a ne výsledným přeloženym
řetezcem. O překlad se stará až translátor při každém načtení
stránky. Kešování překladů je pak spíš jeho záležitost.
Sám to tak mám v projektech. V translátoru si sestavím slovník pro aktuální jazyk a uložím do keše. Dokud se v překladech něco nezmění tak se slovník bere z keše, jinak se znovu sestaví a zase uloží do keše.
Editoval Jur4 (2. 5. 2011 0:45)
- Patrik Votoček
- Člen | 2221
jsem na tom stejně jako Jur4… moc nerozumím proč se snažíš o to o co se snažíš…
- knyttl
- Člen | 196
Prostě mi jde o to, aby se šablona překládala při kompilaci a ne při běhu.
Pokud mám šablonu, ve které mám 100 překladů, tak se šablona přeloží jen jednou a pak při každém zobrazení stránek, kde je šablona použita, tak už překlad nemusí probíhat a generování stránky proběhne významně rychleji.
Ještě jinak: chtěl bych přesunout překládání z úrovně helperů na úroveň filtrů.
- Filip Procházka
- Moderator | 4668
To přece můžeš udělat, úpravou storage a napsáním vlastního filtru :) Popř. rozšířením Latte
- Patrik Votoček
- Člen | 2221
knyttr napsal(a):
Ještě jinak: chtěl bych přesunout překládání z úrovně helperů na úroveň filtrů.
To je nemožné. Protože pak by nefungovali pluráry!
- Ondřej Mirtes
- Člen | 1536
Řešíš to na nesprávné úrovni. Proč zařizovat kešování překladů jen pro šablony? Tenhle mechanismus patří do samotného překládání – tedy kešovat si na úrovni ITranslator výstup pro dané kombinace parametrů.
- Patrik Votoček
- Člen | 2221
Jak by jsi to řešil:
<table>
<tr>
<th>{_"Name"}</th>
<th>{_"Participation"}</th>
</tr>
{foreach $actions as $action}
<tr>
<td>{$action->name}</td>
<td>{_['%d participant', '%d participants'], $action->participants}</td>
</tr>
{/foreach}
</table>
- knyttl
- Člen | 196
Třeba takhle:
CS:
<?php
<table>
<tr>
<th>Jméno</th>
<th>Účast</th>
</tr>
{foreach $actions as $action}
<tr>
<td>{$action->name}</td>
<td>{__['%d účastník', '%d účastníků'], $action->participants}</td>
</tr>
{/foreach}
</table>
?>
S tím, že {__[…], $value} makro by jen rozhodlo, který překlad použít.
Editoval knyttr (2. 5. 2011 11:58)
- David Grudl
- Nette Core | 8218
Teoreticky by to udělat šlo, úprava by šla nad rámec vlastního makra, protože je třeba ještě zajistit, aby se pro každý jazyk vytvářela samostatná cache šablony.
- knyttl
- Člen | 196
David Grudl napsal(a):
Teoreticky by to udělat šlo, úprava by šla nad rámec vlastního makra, protože je třeba ještě zajistit, aby se pro každý jazyk vytvářela samostatná cache šablony.
Právě proto jsem myslel, že by to mohlo být součástí Nette – v tuhle chvíli tu cache doslova znásilňuju a rozhodně to pěkné není.
- Ondřej Brejla
- Člen | 746
To si se asi s moc lidmi nesetkal ;-) Tím samozřejmě neříkám, že to není overkill ;-)
- knyttl
- Člen | 196
No, tak můžeš díky tomu mít všechna data na jednom místě a nemusíš používat žádné nástroje navíc.
Btw, to makro {__['', ''], $var} by vlastně mohlo být prospěšné i pro jednojazyčné verze – dalo by se uplatnit kdekoliv je potřeba vypisovat plurály.
Ještě v těch filtrech takhle používám např. bloky {cs}…{/cs} a {en}…{/en}, přičemž {cs} bloky jsou z anglické verze odstraněny a vice versa.
Editoval knyttr (3. 5. 2011 18:53)
- knyttl
- Člen | 196
A ještě mě napadá – i kdybych byl jediný člověk, který ukládá překlady do databáze a i kdyby to byl „overkill“, tak proč by to mělo být špatně? Trochu mi tohle vlákno přijde, jakože se mi od počátku snažíte naznačit, že jsem úplnej debil :-)
Už tak jsem očividně jediný člověk, kdo si překládá šablony v compile-time. Potrestejte mě :-)
Editoval knyttr (3. 5. 2011 18:58)
- Ondřej Mirtes
- Člen | 1536
Viz můj
příspěvek. Řešíš daný problém na úplně špatném místě a
z toho vyplývají všechny ty problémy. Přesuň kešování do tvé
implementace ITranslator
, zrychlení pocítíš stejné a budeš
mít kešované překlady v celé aplikaci, nejen v šablonách. A bez
problémů.
- Jur4
- Člen | 51
Já taky ukládám překlady v databázi. Jak už jsem ale psal, kešuju je na úrovni Translatoru (pokud je možnost tak do MemcachedStorage, ale to není všude). Mám tak překlady pro celou aplikaci na jednom místě a jednoduše je můžu invalidovat.
S tvým přístupem stejně budu muset mít Translator, který bude překládat všechny ostatní věci a při změně překladů budu muset řešit nejen invalidaci keše Translatoru ale i invalidaci šablon. A to pro pár milisekund.
- Filip Procházka
- Moderator | 4668
Ondřeji, tvůj přístup je pravděpodobně správný, ale když budeš mít šablonu ukládanou jako navrhuje knyttr, tak bude zrychlení ještě drastičtější. Nemám v plánu se to snažit implementovat, ale nápad na zrychlení je to opravdu dobrý a nezavrhoval bych ho.
Nebyla by paráda, mít dvou-stupňové cachování? Jednou by se přeložily „statické“ texty do šablony a podruhé by se cachovaly výsledky pro ostatní dynamické překlady?
- redhead
- Člen | 1313
Taky si myslím, že to není úplně špatný nápad. Proč by se měli pořád vyhledávat texty v nějaké kolekci, která ve velkých aplikací nebude malá, když by mohly být statické texty rovnou v šabloně a není tak nutná naprosto žádná režie.
Jediné, co se musí řešit je invalidace šablon, pokud se změní překlad.
A to pro pár milisekund.
Jistě.. Tak, prosím, smaž veškeré cache z velkých aplikací a pak si řeknem něco o pár milisekundách.
Edit: dodatek – jsem ale pro obě cache současné jak translatoru, tak přeložených šablon.
Editoval redhead (3. 5. 2011 21:18)
- Tharos
- Člen | 1030
IMHO to není chyba návrhu. Mně to připomíná klasickou výstupní cache (uchovávající kompletní vygenerované HTML či generující patřičné hlavičky) a ta se přece běžně používá. Každý přístup má své výhody i nevýhody a určitě bych něco neprezentoval jako „jediné správné řešení“. Zrovna tak je to IMHO s ukládáním překladů do databáze, to má přece taky svá pro i proti a určitě to není „zhmotnělé zlo“. :)
Editoval Tharos (3. 5. 2011 21:49)
- knyttl
- Člen | 196
Tharos napsal(a):
IMHO to není chyba návrhu. Mně to připomíná klasickou výstupní cache (uchovávající kompletní vygenerované HTML či generuje patřičné hlavičky) a ta se přece běžně používá. Každý přístup má své výhody i nevýhody a určitě bych něco neprezentoval jako „jediné správné řešení“. Zrovna tak je to IMHO s ukládáním překladů do databáze, to má přece taky svá pro i proti a určitě to není „zhmotnělé zlo“. :)
Ono jde o to, když z jedné šablony generuješ stovky stránek, tak u stránek, které se otevírají hodně a jsou už nakešované, není problém. Potom ale ty stránky, které se otevírají zřídka a nakešované nejsou, tak se pak poprvé generují zbytečně dlouho.
- Jur4
- Člen | 51
redhead napsal(a):
Jistě.. Tak, prosím, smaž veškeré cache z velkých aplikací a pak si řeknem něco o pár milisekundách.
Ja jsem myslel rozdíl mezi keší v Translatoru (ten se ve většině případů bude muset stejně načíst) a keší v šablonách, ne smazanou keš. Tam ten rozdíl nebude nijak velký.
Editoval Jur4 (3. 5. 2011 22:11)
- Filip Procházka
- Moderator | 4668
knyttr napsal(a):
Ono jde o to, když z jedné šablony generuješ stovky stránek, tak u stránek, které se otevírají hodně a jsou už nakešované, není problém. Potom ale ty stránky, které se otevírají zřídka a nakešované nejsou, tak se pak poprvé generují zbytečně dlouho.
To je ale normální princip invalidace, to přece jinak udělat nejde. Jeden z těch uživatelů prostě odnese generování stránky a o nepatrné cuknutí se mu zpomalí vykreslování.
- trubi
- Člen | 25
Mě přijde naprosto přirozené mít překlady v databázi. Zákazník (příp. někdo od SEO) si může v klidu kdykoliv změnit jakýkoliv text přímo v administraci aplikace. A jakmile už je to jednou přeložené, ty změny se zas tak často nedělají, takže vygenerovat znovu šablony přece není problém a návštěvník to téměř nepozná.
Překlad při kompilaci mám implementovaný už chvíli, rozšířil jsem si
TemplateCacheStorage
, jehož instanci vkládám do šablony v
BasePresenteru
. Je to hodně ohackované, ale funguje to
docela dobře.
Problém je v tom, že to není univerzální řešení. Plno věcí při kompilaci překládat nejde, rozhodně se tím ale nějaký čas ušetří a toho textu, který se překládá až při běhu zas tak moc většinou není.
- David Grudl
- Nette Core | 8218
Už bych nerozpitvával, jestli požadavek je oprávněný nebo ne, protože oprávněný je, howgh :-)
Na straně přidání Latte makra by žádný zádrhel být neměl, prostě
bude to obdoba implementace makra {_}
, které se předá
translator. Aby k tomu bylo možné použít FileTemplate, je třeba změnit
klíč ze současného $this->file
na vlastní zahrnující
jazyk. Taktéž by se asi hodila možnost specifikovat vlastní podmínky při
ukládání cache.
Ale – totéž platí i pro třídu Template, byť tady by se změna
klíče dala simulovat přidáním nějakého {* lang:cs *}
na
konec řetězce. Napadá někoho šikovný refaktoring, jak kešování upravit
v Template i FileTemplate?
- knyttl
- Člen | 196
Já se obávám, že ten refactoring nenavrhnu.
Každopádně s tím, jak to mám ohnuté docela válčím – jedna z nevýhod je třeba ta, že laděnka mi nevypisuje trace z šablon ale jen například z „../libs/Nette.php:5225 eval(…“ což moc k ničemu není.
Co jsem si ale teď díky tomu zvykl dělat je používat makra {cs}, {en}:
{cs}Tohle se vygeneruje v české šabloně{/cs} {en}This will appear in english template{/en}
Výhodou je, že člověk ty překlady nemá nikde zašité mimo a snadno se mění.
- mancze
- Člen | 58
knyttl napsal(a):
Co jsem si ale teď díky tomu zvykl dělat je používat makra {cs}, {en}:
{cs}Tohle se vygeneruje v české šabloně{/cs} {en}This will appear in english template{/en}
Výhodou je, že člověk ty překlady nemá nikde zašité mimo a snadno se mění.
Nevýhodou je, že překladateli nestačí poslat jeden soubor s klíči, ale musí se vrtat v šablonách. A zvyšuje se tím riziko, že něco rozvrtá.
Nicméně ale souhlasím s tím, že překlad při compile-time je dobrý nápad. Co se tím ušetří?
- Soubor s překlady se nemusí vůbec ani parsovat, případně stahovat z databáze
- Neprobíhá X vyhledávání v kolekci (kde X je počet překladů na stránce)
- Neparametrické překlady ani nemusí vést k zavolání nějaké funkce, jsou do šablony prostě vepsané
- Parametrické mají za následek pouze vložení parametrů, v nejhorším rozhodnutí formy plurálu
- knyttl
- Člen | 196
mancze napsal(a):
knyttl napsal(a):
Co jsem si ale teď díky tomu zvykl dělat je používat makra {cs}, {en}:
{cs}Tohle se vygeneruje v české šabloně{/cs} {en}This will appear in english template{/en}
Výhodou je, že člověk ty překlady nemá nikde zašité mimo a snadno se mění.
Nevýhodou je, že překladateli nestačí poslat jeden soubor s klíči, ale musí se vrtat v šablonách. A zvyšuje se tím riziko, že něco rozvrtá.
V našem případě si šablony překládáme sami, to znamená máme snadno pod kontrolou jejich veškerý obsah. Obrovskou výhodou je to, že člověk nemusí řešit, jestli daný klíč ještě je, nebo není používaný a může se z databáze překladů odstranit.