Issues

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

Please give a reproducable example. We will not change the core without knowing why.

Example appended to the description.

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.

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.

Closing as non-issue False mo files can not be corrected. See description above.

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 :


Index: Adapter.php
===================================================================
--- Adapter.php (revision 24397)
+++ Adapter.php (working copy)
@@ -758,8 +758,9 @@
             }
 
             $rule = Zend_Translate_Plural::getPlural($number, $locale);
-            if (isset($this->_translate[$locale][$plural[0]][$rule])) {
+            if (is_array($this->_translate[$locale][$plural[0]]) && isset($this->_translate[$locale][$plural[0]][$rule])) {
                 $this->_routed = array();
+
                 return $this->_translate[$locale][$plural[0]][$rule];
             }
         } else if (strlen($locale) != 2) {

Fixed in ZF2 with GH-368