ZF-8816: Plural translation returns only one letter
Description
It returns only the letter at position {$rule} in the $plural[0] string. We want it to return the string at index {$rule} in the $plural array.
We have to change [$plural[0]][$rule] to [$plural[$rule]] on line 566,567,580 and 581
$locale = (string) $locale;
if (isset($this->_translate[$locale][$messageId])) {
// return original translation
if ($plural === null) {
return $this->_translate[$locale][$messageId];
}
$rule = Zend_Translate_Plural::getPlural($number, $locale);
if (isset($this->_translate[$locale][$plural[$rule]])) { // was [$plural[0]][$rule]
return $this->_translate[$locale][$plural[$rule]]; // was [$plural[0]][$rule]
}
} else if (strlen($locale) != 2) {
// faster than creating a new locale and separate the leading part
$locale = substr($locale, 0, -strlen(strrchr($locale, '_')));
if (isset($this->_translate[$locale][$messageId])) {
// return regionless translation (en_US -> en)
if ($plural === null) {
return $this->_translate[$locale][$messageId];
}
$rule = Zend_Translate_Plural::getPlural($number, $locale);
if (isset($this->_translate[$locale][$plural[$rule]])) { // was [$plural[0]][$rule]
return $this->_translate[$locale][$plural[$rule]]; // was [$plural[0]][$rule]
}
}
}
<?php
$no = new Zend_Translate(
'gettext',
APPLICATION_PATH.'/configs/no.mo',
'no'
);
$en = new Zend_Translate(
'gettext',
APPLICATION_PATH.'/configs/en.mo',
'en'
);
for ( $number=0; $number<=2; $number++ ){
echo 'no: ' . $number . ' ' . $no->translate(array(_('car'),_('cars'),$number)) .'
';
echo 'en: ' . $number . ' ' . $en->translate(array(_('car'),_('cars'),$number)) .'
';
}
?>
no: 0 i
en: 0 a
no: 1 b
en: 1 c
no: 2 i
en: 2 a
The gettext mo/po files were generated with Poedit:
the "no" gettext file contains: car => bil cars => biler
the "en" gettext file contains: car => car cars => cars
Comments
Posted by Thomas Weidner (thomas) on 2010-01-14T07:44:01.000+0000
Please give a reproducable example. We will not change the core without knowing why.
Posted by Jone Hop (joho) on 2010-01-14T09:06:13.000+0000
Example appended to the description.
Posted by Thomas Weidner (thomas) on 2010-01-14T11:07:58.000+0000
I can not verify this behaviour Seems like your mo file is broken.
Your change eliminates plural notation for gettext and makes singular working like plurals. But plurals are noted differently within the gettext standard than plurals. So your change breaks this feature for others.
Maybe the po file you compiled the mo from is broken. See the file "/Translate/Adapter/_files/translation_en.mo" which adds plurals for the message5.
Posted by Thomas Weidner (thomas) on 2010-01-14T11:14:22.000+0000
I just verified that you get this issue when the po/mo file does not use plurals, but when you make multiple singulars and what them to be used as plural.
This does not work and there is no way to make it work. Plurals have to be defined within poEdit (or whatever program you use) explicitely. Otherwise the translations are simply added as singular.
Posted by Thomas Weidner (thomas) on 2010-01-14T12:21:56.000+0000
Closing as non-issue False mo files can not be corrected. See description above.
Posted by Menno Dekker (menno.dekker@erasmusmc.nl) on 2011-08-22T08:44:44.000+0000
I encountered this issue. I will explain what happens: I have used regular translate on 'week' and 'weeks' so both are in my po/mo file. Now I switched to plural, but poedit didn't pickup the plural (others that were not translated before are picked up!!). I know my PO file is missing the correct plural, but Zend doesn't see this and falsely returns just one letter (index) from the word it finds. The problem is in the isset check on line 764. When used on an array, it checks if the key exists, when used on a string (in my case) it will return the n'th char from the string. When my patch is applied, it will correctly be reported as missing.
I don't know how to attach a diff here so I will just paste it for Zend/Translate/Adapter.php :
Posted by Thomas Weidner (thomas) on 2011-09-03T07:46:49.000+0000
Fixed in ZF2 with GH-368