i18n a l10n?
- brablc
- Člen | 6
David Grudl napsal(a):
Co bys konkrétně potřeboval udělat?
Tak třeba my jsme potřebovali vyřešit problém s parametrizovanými překlady:
{_'There are %2$d messages for user %1$s', 'test', 10}
Kolegové to vyřešili takto:
class NjoyTranslator implements /*Nette\*/ITranslator
{
...
public function translate($message, $plural = NULL)
{
if (isset($this->dictionary[$message]))
$message = $this->dictionary[$message];
$pars = func_get_args();
if (count($pars)>1) {
array_shift($pars);
return vsprintf($message, $pars);
}
return $message;
}
}
Parametr $plural je sám o sobě nedostatečný (viz http://www.gnu.org/…gettext.html#… ), proto jsme si dovolili ho ignorovat.
- brablc
- Člen | 6
Ještě bychom potřebovali něco jako neescapovany translate:
{!_'Please click here to view your <a href="/orderstatus.php">order status</a>.'}.
S naším rozšířením o parametry potom ještě přichází otázka, zda-li je lepší
{!_'Please click here to view your <a href="%s">order status</a>.', '/orderstatus.php'}.
nebo
{!_'Please click here to view your %sorder status%s.', '<a href="/orderstatus.php">', '</a>'}.
Samozřejmě, že tu je vždy alternativa rozsekat to na spoustu řetězců, ale to není ideální z pohledu překladatele.
- brablc
- Člen | 6
Jod napsal(a):
A skúšali ste tanslator od Zendu?
Teď nevím, jestli to je otázka na nás, pokud ano tak tohle není problém použitého adaptéru, ale problém rozhraní Nette\ITranslator a funkčnosti CurlyBracketsFilter. Naštěstí pro nás jsou všechny dodatečné parametry použity při volání translate metody, takže parametrizace dotazů nám funguje. Pokud se rozšíření CurlyBracketsFilter týká, tak tady navrhujeme patch:
Index: CurlyBracketsFilter.php
===================================================================
--- CurlyBracketsFilter.php (revision 181)
+++ CurlyBracketsFilter.php (working copy)
@@ -32,6 +32,7 @@
* - {!=expression} echo without escaping
* - {?expression} evaluate PHP statement
* - {_expression} echo with escaping and translation
+ * - {!_expression} echo with translation and without escaping
* - {link destination ...} control link
* - {plink destination ...} presenter link
* - {ajaxlink destination ...} ajax link
@@ -90,6 +91,7 @@
'!=' => '<?php echo # ?>',
'_' => '<?php echo $template->{$_cb->escape}($template->translate(#)) ?>',
+ '!_' => '<?php echo $template->translate(#) ?>',
'=' => '<?php echo $template->{$_cb->escape}(#) ?>',
'!$' => '<?php echo # ?>',
'!' => '<?php echo # ?>',
Mimochodem, translátor od Zendu s gettext adaptérem jsme zkoušeli, ale je to trošku řešení přes ruku, navíc gettext parsuje binárně .mo soubory a natahuje řetězce do paměti, takže efektivní to také moc není. Náš translátor tedy zatím řeší parametry překladu, zobrazení defaultní jazykové mutace, pokud překlad chybí a nabízí základní podporu kontextu:
<?php
class NjoyTranslator implements /*Nette\*/ITranslator
{
protected $dictPref;
protected $dictDef;
protected $filePref;
protected $fileDef;
/**
* @param string file with associative array called $dictionary]
*/
public function __construct($preferredDictionaryFile, $defaultDictionaryFile)
{
$this->filePref = $preferredDictionaryFile;
$this->fileDef = $defaultDictionaryFile;
}
/**
* Translates the given string.
* @param string message
* @param int plural
* @return string
*/
public function translate($message, $plural = NULL)
{
if (!$this->dictPref) {
require_once($this->filePref);
$this->dictPref = $dictionary;
if ($this->filePref == $this->fileDef) {
$this->dictDef = $this->dictPref;
}
}
if (isset($this->dictPref[$message])) {
$message = $this->dictPref[$message];
}
else {
if (!$this->dictDef) {
require_once($this->fileDef);
$this->dictDef = $dictionary;
}
if (isset($this->dictDef[$message]))
$message = $this->dictDef[$message];
else if ( ($pos = strpos($message,'\\')) > 0)
$message = substr($message, $pos+1);
}
$args = func_get_args();
if (count($args)>1) {
array_shift($args);
return vsprintf($message, $args);
}
return $message;
}
}
?>
Pokud překlad neexistuje, tak z defaultní mutace bude kontext (tedy vše před \\) odstraněn. Protože chceme psát delší odstavce pouze do překladových souborů a ve zdrojácích používat pouze identifikátory, tak plánujeme rozšíření kontexu například na:
'\\help\\how_to_change_password' => '...'
V takovém případě by se mohly překlady rozložit do více souborů, které by se jmenovaly podle svého kontextu a natahovaly by se do dictionary až v okamžiku potřeby. Ale těch možností, jak optimalizovat přebujelé překlady je spousta.
Takže když to shrnu, tak naše problémy s i18n jsou vyřešené (ale budeme rádi pokud dojde k přijetí našeho patche) a naše téměř minimalistické řešení uvedené výše by mělo být použitelné i pro ostatní, kteří neví, kde začít. Alespoň jako inspirace.
- David Grudl
- Nette Core | 8228
brablc napsal(a):
Tak třeba my jsme potřebovali vyřešit problém s parametrizovanými překlady:
{_'There are %2$d messages for user %1$s', 'test', 10}
Kolegové to vyřešili takto:
Hezké řešení.
Parametr $plural je sám o sobě nedostatečný (viz http://www.gnu.org/…gettext.html#… ), proto jsme si dovolili ho ignorovat.
$plural
je nevýstižný název, mělo by jít o počet prvků
($count
by asi bylo lepší). Pokud by se překládala zpráva
There are %d message
, došlo by ke chtěnému vedlejšímu
efektu – parametr počet by měl vlastně dvě funkce. Možná by
bylo vhodné zprávy o více parametrech jako
There are %2$d messages for user %1$s
koncipovat tak, aby počet
byl uveden jako druhý.
- David Grudl
- Nette Core | 8228
brablc napsal(a):
Takže když to shrnu, tak naše problémy s i18n jsou vyřešené (ale budeme rádi pokud dojde k přijetí našeho patche) a naše téměř minimalistické řešení uvedené výše by mělo být použitelné i pro ostatní, kteří neví, kde začít. Alespoň jako inspirace.
Už ho tam dávám. Vlastně jsem byl překvapen, že {!_
chybí ;)