Blog Archive

Saturday 20 July 2013

Symfony 2 pluralization russian twig extension

I has the problem with symfony2, that I couldn't translate plural forms in a proper way inside the twig templates.
There are only two options with the standard symfony2  trans tag and transchoice tag. They are described here.

trans tag allows to translate a simple string
transchoice is something more complex. It allows to translate string based on number you provide. Simple logic looks like this.

1 - I have just one apple
2 - I have couple
3 - There is enough for three of us
4 - I have many apples
5
6
..
100 - I have many apples

So basically when you use transchoice you have to provide explicit translation and explicit range.
With russian language it is different

the formula for suffixes in russian looks like this:
<?php
(($number % 10 == 1) && ($number % 100 != 11))
    ? 0
    : ((($number % 10 >= 2)
        && ($number % 10 <= 4)
        && (($number % 100 < 10)
        || ($number % 100 >= 20)))
            ? 1
            : 2
);
?>

The problem with symfony2 is that it does not provide any mechanism to use it. If you use plain twig, it will have the translplural tag. but it is not included in symfony2, so I had to write my own.

<?php 
namespace YourBundleName\TwigExtensions; 
use Symfony\Bundle\FrameworkBundle\Translation\Translator; 
use Twig_Extension; 
 
class TransPlural extends Twig_Extension 
{ 
    protected $translator; 
    public function __construct(Translator $translator) 
    { 
        $this->translator = $translator; 
    } 
 
    public function getFilters() 
    { 
        return array( 
            new \Twig_SimpleFilter('transplural', array($this, 'transplural')), 
        ); 
    } 
 
    public function transplural($string, $number) 
    { 
        $translated = $this->translator->trans( 
            '%d '.$string, 
            array('%d' => $number) 
        ); 
        $type = (($number % 10 == 1) && ($number % 100 != 11)) 
        ? 0 
        : ((($number % 10 >= 2) 
            && ($number % 10 <= 4) 
            && (($number % 100 < 10) 
                || ($number % 100 >= 20))) 
            ? 1 
            : 2 
        ); 
        //this if condition here because on some servers $this->translator->tran
        //was returning wrong strings
        if (strpos($translated,"{")===false) 
        { 
            $translated_array = explode("|", $translated); 
            return $translated_array[$type]; 
        } 
        else 
        { 
            return $this->translator->transChoice($translated,  $type, array("%count%"=>$type)); 
 
        } 
 
    } 
 
    /** 
     * Returns the name of the extension. 
     * 
     * @return string The extension name 
     */ 
    public function getName() 
    { 
        return "translate_plural_russian"; 
    } 
}


And additionally you need to add following lines to the services.xml

<service id="twig.plural_extension" class="YourBundleName\TwigExtensions\TransPlural">
    <tag name="twig.extension" />
    <argument type="service" id="translator"></argument>
</service>

And then you will be able to use transplural tag inside your twig templates like this:

{{ "string to be pluralized"|transplural(number) }} 

No comments:

Post a Comment