TranslationClient – překlad řetězců přímo na stráce
- Panda
- Člen | 569
Zdravím všechny,
zhruba po dni kódování a psaní úděsného JavaScriptu se mi povedlo
zrealizovat dle mého názoru docela zajímavou myšlenku – nástroj pro
překládání přímo na stránce. Abyste si udělali představu, jak to
vypadá, tak 2 ukázky:
Před rozbalením:
Hezké, co?
Asi vás napadne, co bude použití takové srandy v projektu obnášet –
moc toho není. Stačí přidat zhruba jeden řádek do
bootstrap.php
…
TranslationClient::enable($translator);
… a zajistit, že předávaný $translator
bude implementovat
následující rozhraní…
interface IEditableTranslator extends ITranslator
{
public function getVariantsCount();
public function getStrings();
public function setTranslation($message, $string);
public function save();
}
… a to by mělo být vše. Může se překládat.
Nyní se ještě trošku vrátím k tomu rozhraní.
Metoda getVariantsCount()
by měla vracet
počet tvarů slov podle kvantity v daném jazyce. Pro angličtinu se tedy
vrací 2 (singulár, plurál), čeština 3 (singulár, plurál pro 2 – 4,
plurál pro 5+).
Metoda getStrings()
by měla vracet
asociativní pole řetězců, které se zobrazí v klientovi. Pokud řetězec
není závislý na počtu, měl by se vrátit jako řetězec. Pokud závislý
je, tak by se mělo vrátit pole s tolika prvky, kolik je variant.
Názornější asi bude příklad (psáno v JSONu):
{
"news": "Novinky",
"categories": [
"%n kategorie",
"%n kategorie",
"%n kategorií"
]
}
Tento seznam řetězců samozřejmě nemusí být jen nějaký nadefinovaný
seznam, IEditableTranslator
si klidně může ukládat bokem
„neuspokojené“ překlady a do klienta je naservírovat k překladu –
klient totiž tuto metodu volá až při ukončování scriptu (ve stejnou dobu,
kdy se renderuje např. profiler), takže se tam může promítnout opravdu
vše, co bylo voláno.
Metoda setTranslation($message, $string)
nastaví překlad nějakého řetězce. Pro řetězec bez plurálů se opět
použije jen string, pro řetězec s plurály pole všech variant.
Mno a metoda save()
všechny provedené
překlady uloží.
Nastavování jednotlivých překladů probíhá AJAXem. Uživatel v klientovi přeloží jeden či více řetězců a klepne na uložit. Klient provede AJAXový požadavek (identifikovaný speciální hlavičkou, takže se nebude míchat s ostatními požadavky) na URL se současnou stránkou (bez signálů atp.) a během požadavku se jeho data uloží.
Ukládání momentálně probíhá na konci volání
TranslationClient::enable(...)
a po uložení dat vykonávání
scriptu zemře (die()
), aby se předešlo případným vedlejším
efektům. Toto chování mi nepřipadá úplně ideální a určitě by sneslo
nějakou změnu. Také z toho vyplývá jeden možná trochu nepříjemný
požadavek – IEditableTranslator
už v době volání musí
být schopen data bez problémů ukládat.
Na závěr bych chtěl říct, že to celé je zatím spíš ve stádiu experimentu, takže 100% funkčnost a stabilita není garantována. Dokonce to jde tak daleko, že mohu garantovat jedině nefunkčnost snad v jakékoliv verzi IE. Fungovat by to mělo ve FF, Chrome a Opeře + možná v dalších prohlížečích, pro které „moderní standarty“ nejsou jen sprosté slovo.
Na závěr bych chtěl vznést několik námětů na diskuzi, budu rád za jakýkoliv komentář:
- Chybí vám tam něco? Mělo by to ještě něco zohledňovat?
- Kam by jste dali zpracování ukládaných dat? A po něm být, či nebýt?
continue
, čidie()
? - Má smysl podporovat IE6? Je to převážně nástroj pro vývojáře a žádného masochistu, co vyvíjí primárně na IE6, neznám…
- Má to vůbec smysl?
A teď už samotné zdrojáky, byl bych rád, kdyby si někdo našel chvilku
času na prozkoumání a otestování: TranslationClient.zip. Nějakou ukázkovou miniaplikaci
včetně translatoru, který bude implementovat
IEditableTranslator
, dodám snad v průběhu víkendu. Nějakou
ukázku toho translatoru vážným zájemcům dodám na požádání.
A ještě si neodpustím malé varování: kód není komentovaný, neobsahuje phpdoc, míst k refaktorování by se tam našlo mnoho… To bude až časem.
- norbe
- Backer | 405
No musím říct, že to vypadá fakt dobře a rozhodně si dokážu představit, že by to mohlo nahradit nástroje jako poedit, u kterých je problém se získáváním všech řetězců.
- IE6 podporovat je podle mýho naprosto zbytečný.
die()
bych asi nepoužíval, to si může nastavit každý podle svého přímo v metoděsave()
, ne? A když už tak bych volal spíš$presenter->terminate()
.
- Panda
- Člen | 569
Presenter v bootstrap.php
ještě není k dispozici, čím se
dostáváme otázce: kde nejlépe provést zpracování požadavku tak, aby
dopad na zbytek aplikace byl co nejmenší? Teď mě napadl event
Application::onRequest
, ale ten se taky volá těsně před
vytvořením presenteru…
die()
bych do save()
rozhodně netahal, nemusí se
volat jen v tomto konkrétním případě…
- Honza Kuchař
- Člen | 1662
Vypadá to suprově!
P.S.: Ad. die() a kód ještě před spuštění Presenteru. MultipleFileUpload funguje se zpracováváním svých požadavků dost podobně. V Application::onStartup si zaregistruje co se má dělat a pak volá exit.
Editoval honzakuchar (19. 2. 2010 19:12)
- Honza Marek
- Člen | 1664
Dostal jsem teď takový nápad. Možná by bylo pěkné, kdyby existovalo nějaké oficiální API pro tvoření takových šikovných nástrojů a jejich integrace do nějakého jednotného panelu. Více napoví obrázek.
Jistě by vznikla celá řada zajímavých vývojářských nástrojů. Jen teď mě napadá tlačítko na smazání cache či tlačítko na jednoduché vytvoření presenteru a souvisejících souborů (šablon).
- Panda
- Člen | 569
Honza Marek napsal(a):
Dostal jsem teď takový nápad. Možná by bylo pěkné, kdyby existovalo nějaké oficiální API pro tvoření takových šikovných nástrojů a jejich integrace do nějakého jednotného panelu. Více napoví obrázek.
Jistě by vznikla celá řada zajímavých vývojářských nástrojů. Jen teď mě napadá tlačítko na smazání cache či tlačítko na jednoduché vytvoření presenteru a souvisejících souborů (šablon).
Přesně tento nápad jsem taky v posledních dnech měl, dokonce jsem měl už 2× nutkání to začít realizovat. Váhal jsem převážně nad tím, jestli to postavit na jQuery (snadná varianta), nebo to podobně jako TranslationClient napsat v čistém JS (pomalá a bolestná varianta). Co myslíte?
- Honza Marek
- Člen | 1664
Já bych byl proti pomalým a bolestným variantám. Zkusil bych to pod jQuery. Jedině pokud by se zjistilo, že z celého frameworku je potřeba jen show a hide, tak bych to přepsal.
Jaké jsou vlastně výhody čistého JS? Natáhnutí frameworku bych jako velký problém neviděl (při nepřítomnosti se stáhne od googlu), s konkurencí se taky jQuery pomocí jQuery.noConflict() umí dohodnout.
- Ondřej Mirtes
- Člen | 1536
Pokud by se to mělo pak implementovat do Nette, tak bych to od jQuery osvobodil. Formuláře ani Laděnka to taky nevyužívá.
- Honza Kuchař
- Člen | 1662
Upřimě řečeno. Ať si to klidně tahá třeba celý ExtJS. Jen ať to autorovi panelu zabere co nejmíň času. (řači o nějakou tu hodinku déle spát) Stejně je to pro ladění na localhostu. Takže i pokud ten JS bude mít třeba 1MB, tak mě to nijak neohrozí. Takže klidně jQuery + ExtJS + co bude potřeba + klidně ještě něco dalšího. ;) (pokud to ušetří autorovi čas; resp. ušetří určitě, protože jQuery je více méně cross-browser)
- jasir
- Člen | 746
honzakuchar napsal(a):
Upřimě řečeno. Ať si to klidně tahá třeba celý ExtJS. Jen ať to autorovi panelu zabere co nejmíň času. (řači o nějakou tu hodinku déle spát) Stejně je to pro ladění na localhostu. Takže i pokud ten JS bude mít třeba 1MB, tak mě to nijak neohrozí. Takže klidně jQuery + ExtJS + co bude potřeba + klidně ještě něco dalšího. ;) (pokud to ušetří autorovi čas; resp. ušetří určitě, protože jQuery je více méně cross-browser)
Jasný souhlas :-)