ZF-12547: Gettext adapter cannot translate plurals when the target language has only one plural form
Description
When a target language only has one plural form, calls to {{Zend_Translate::plural()}} just return the first character of the string.
Consider these two translation files (French - 2 plural forms, Turkish - 1 plural form). Compile them with the command "msgfmt XX.po -o XX.mo"
msgid ""
msgstr ""
"Content-Type: text/plain; charset=UTF-8\n"
"Plural-Forms: nplurals=2; plural=n > 1;\n"
msgid "There is %d fish"
msgid_plural "There are %d fishes"
msgstr[0] "Il ya %d poisson"
msgstr[1] "Il ya %d poissons"
msgid ""
msgstr ""
"Content-Type: text/plain; charset=UTF-8\n"
"Plural-Forms: nplurals=1; plural=0;\n"
msgid "There is %d fish"
msgid_plural "There are %d fishes"
msgstr[0] "%d balıklar var"
Here is a test script
require 'Zend/Translate.php';
// A language with more than one plural form - works OK
$translate = new Zend_Translate('gettext', 'fr.mo', 'fr');
for ($i=0; $i<5; ++$i) {
echo $translate->plural('There is %d fish', 'There are %d fishes', $i), PHP_EOL;
}
// A language with only one plural form - does not work
$translate = new Zend_Translate('gettext', 'tr.mo', 'tr');
for ($i=0; $i<5; ++$i) {
echo $translate->plural('There is %d fish', 'There are %d fishes', $i), PHP_EOL;
}
The actual output is
Il ya %d poisson
Il ya %d poisson
Il ya %d poissons
Il ya %d poissons
Il ya %d poissons
%
%
%
%
%
Note that the turkish translations contain just the first character of the sring.
This comes from code in {{Zend_Translate_Adapter::plural()}} which assumes that plural translations are always arrays. The [0] operator is finding the first character of a string, not the first element of an array.
$rule = Zend_Translate_Plural::getPlural($number, $locale);
if (isset($this->_translate[$locale][$plural[0]][$rule])) {
$this->_routed = array();
return $this->_translate[$locale][$plural[0]][$rule];
}
As far as I can tell, the bug comes from Zend_Translate_Adapter_Gettext, and can be fixed by the following patch
Index: Gettext.php
===================================================================
--- Gettext.php (revision 25275)
+++ Gettext.php (working copy)
@@ -122,7 +122,7 @@
fseek($this->_file, $transtemp[$count * 2 + 2]);
$translate = fread($this->_file, $transtemp[$count * 2 + 1]);
$translate = explode("\0", $translate);
- if ((count($original) > 1) && (count($translate) > 1)) {
+ if (count($original) > 1) {
$this->_data[$locale][$original[0]] = $translate;
array_shift($original);
foreach ($original as $orig) {
An explanation for the patch is that a translation is defined as a plural if there are more than one ENGLISH forms. It does not matter whether there is only one TRANSLATED form.
With the patch, the test script outputs the expected values:
Il ya %d poisson
Il ya %d poisson
Il ya %d poissons
Il ya %d poissons
Il ya %d poissons
%d balıklar var
%d balıklar var
%d balıklar var
%d balıklar var
%d balıklar var
Comments
Posted by Ralph Schindler (ralph) on 2013-04-05T16:06:55.000+0000
This issue has been closed on Jira and moved to GitHub for issue tracking. To continue following the resolution of this issues, please visit: https://github.com/zendframework/zf1/issues/66