1The i18n Extension 2================== 3 4Configuration 5------------- 6 7The ``i18n`` extension adds `gettext`_ support to Twig. It defines one tag, 8``trans``. 9 10To use it, first, :ref:`install the Extensions library<extensions-install>`. 11 12You need to register this extension before using the ``trans`` block:: 13 14 $twig->addExtension(new Twig_Extensions_Extension_I18n()); 15 16Note that you must configure the ``gettext`` extension before rendering any 17internationalized template. Here is a simple configuration example from the 18PHP `documentation`_:: 19 20 // Set language to French 21 putenv('LC_ALL=fr_FR'); 22 setlocale(LC_ALL, 'fr_FR'); 23 24 // Specify the location of the translation tables 25 bindtextdomain('myAppPhp', 'includes/locale'); 26 bind_textdomain_codeset('myAppPhp', 'UTF-8'); 27 28 // Choose domain 29 textdomain('myAppPhp'); 30 31.. caution:: 32 33 The ``i18n`` extension only works if the PHP `gettext`_ extension is 34 enabled. 35 36Usage 37----- 38 39Use the ``trans`` block to mark parts in the template as translatable: 40 41.. code-block:: jinja 42 43 {% trans "Hello World!" %} 44 45 {% trans string_var %} 46 47 {% trans %} 48 Hello World! 49 {% endtrans %} 50 51In a translatable string, you can embed variables: 52 53.. code-block:: jinja 54 55 {% trans %} 56 Hello {{ name }}! 57 {% endtrans %} 58 59During the gettext lookup these placeholders are converted. ``{{ name }}`` becomes ``%name%`` so the gettext ``msgid`` for this string would be ``Hello %name%!``. 60 61.. note:: 62 63 ``{% trans "Hello {{ name }}!" %}`` is not a valid statement. 64 65If you need to apply filters to the variables, you first need to assign the 66result to a variable: 67 68.. code-block:: jinja 69 70 {% set name = name|capitalize %} 71 72 {% trans %} 73 Hello {{ name }}! 74 {% endtrans %} 75 76To pluralize a translatable string, use the ``plural`` block: 77 78.. code-block:: jinja 79 80 {% trans %} 81 Hey {{ name }}, I have one apple. 82 {% plural apple_count %} 83 Hey {{ name }}, I have {{ count }} apples. 84 {% endtrans %} 85 86The ``plural`` tag should provide the ``count`` used to select the right 87string. Within the translatable string, the special ``count`` variable always 88contain the count value (here the value of ``apple_count``). 89 90To add notes for translators, use the ``notes`` block: 91 92.. code-block:: jinja 93 94 {% trans %} 95 Hey {{ name }}, I have one apple. 96 {% plural apple_count %} 97 Hey {{ name }}, I have {{ count }} apples. 98 {% notes %} 99 This is shown in the user menu. This string should be shorter than 30 chars 100 {% endtrans %} 101 102You can use ``notes`` with or without ``plural``. Once you get your templates compiled you should 103configure the ``gettext`` parser to get something like this: ``xgettext --add-comments=notes`` 104 105Within an expression or in a tag, you can use the ``trans`` filter to translate 106simple strings or variables: 107 108.. code-block:: jinja 109 110 {{ var|default(default_value|trans) }} 111 112Complex Translations within an Expression or Tag 113------------------------------------------------ 114 115Translations can be done with both the ``trans`` tag and the ``trans`` filter. 116The filter is less powerful as it only works for simple variables or strings. 117For more complex scenario, like pluralization, you can use a two-step 118strategy: 119 120.. code-block:: jinja 121 122 {# assign the translation to a temporary variable #} 123 {% set default_value %} 124 {% trans %} 125 Hey {{ name }}, I have one apple. 126 {% plural apple_count %} 127 Hey {{ name }}, I have {{ count }} apples. 128 {% endtrans %} 129 {% endset %} 130 131 {# use the temporary variable within an expression #} 132 {{ var|default(default_value|trans) }} 133 134Extracting Template Strings 135--------------------------- 136 137If you use the Twig I18n extension, you will probably need to extract the 138template strings at some point. 139 140Using Poedit 2 141~~~~~~~~~~~~~~ 142 143Poedit 2 has native support for extracting from Twig files and no extra 144setup is necessary (Pro version). 145 146Using ``xgettext`` or Poedit 1 147~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 148 149Unfortunately, the ``xgettext`` utility does not understand Twig templates 150natively and neither do tools based on it such as free versions of Poedit. 151But there is a simple workaround: as Twig converts templates to 152PHP files, you can use ``xgettext`` on the template cache instead. 153 154Create a script that forces the generation of the cache for all your 155templates. Here is a simple example to get you started:: 156 157 $tplDir = dirname(__FILE__).'/templates'; 158 $tmpDir = '/tmp/cache/'; 159 $loader = new Twig_Loader_Filesystem($tplDir); 160 161 // force auto-reload to always have the latest version of the template 162 $twig = new Twig_Environment($loader, array( 163 'cache' => $tmpDir, 164 'auto_reload' => true 165 )); 166 $twig->addExtension(new Twig_Extensions_Extension_I18n()); 167 // configure Twig the way you want 168 169 // iterate over all your templates 170 foreach (new RecursiveIteratorIterator(new RecursiveDirectoryIterator($tplDir), RecursiveIteratorIterator::LEAVES_ONLY) as $file) 171 { 172 // force compilation 173 if ($file->isFile()) { 174 $twig->loadTemplate(str_replace($tplDir.'/', '', $file)); 175 } 176 } 177 178Use the standard ``xgettext`` utility as you would have done with plain PHP 179code: 180 181.. code-block:: text 182 183 xgettext --default-domain=messages -p ./locale --from-code=UTF-8 -n --omit-header -L PHP /tmp/cache/*.php 184 185Another workaround is to use `Twig Gettext Extractor`_ and extract the template 186strings right from `Poedit`_. 187 188.. _`gettext`: http://www.php.net/gettext 189.. _`documentation`: http://fr.php.net/manual/en/function.gettext.php 190.. _`Twig Gettext Extractor`: https://github.com/umpirsky/Twig-Gettext-Extractor 191.. _`Poedit`: http://www.poedit.net/ 192