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:
Po rozbalení:
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í…
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):
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, či die()?
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.
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().
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ě…
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.
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).
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?
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.
ajax ale tady zrovna nepotřebujeme, že? A i kdyby není to pravidlem, že
musíme požít zrovna jQuery. Podle mě pro jednoduchý show/hide není
potřeba tahat celý jQuery..
Byl bych pro panel, který bude postaven na čistém js. Jednotlivé
nástroje ať potom využívají co uznají jejich autoři za vhodné. Každý
si pak může rozmyslet, jestli si kvůli danému nástroji požadované
knihovny naincluduje nebo ne.
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)
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)
ahoj, dostal jsem se k tomu testu až nyní a bouhžel nechápu co myslíš
tím: … a zajistit, že předávaný $translator bude implementovat
následující rozhraní…
můžeš to prosím nějak upřesnit? Díky moc.