Twig i18n Extension =================== The ``i18n`` extension adds `gettext`_ support to Twig. It defines one tag, ``trans``. Installation ------------ This library can be installed via Composer running the following from the command line: .. code-block:: bash composer require phpmyadmin/twig-i18n-extension Configuration ------------- You need to register this extension before using the ``trans`` block .. code-block:: php use PhpMyAdmin\Twig\Extensions\I18nExtension; $twig->addExtension(new I18nExtension()); Note that you must configure the ``gettext`` extension before rendering any internationalized template. Here is a simple configuration example from the PHP `documentation`_ .. code-block:: php // Set language to French putenv('LC_ALL=fr_FR'); setlocale(LC_ALL, 'fr_FR'); // Specify the location of the translation tables bindtextdomain('myAppPhp', 'includes/locale'); bind_textdomain_codeset('myAppPhp', 'UTF-8'); // Choose domain textdomain('myAppPhp'); .. caution:: The ``i18n`` extension only works if the PHP `gettext`_ extension is enabled. Usage ----- Use the ``trans`` block to mark parts in the template as translatable: .. code-block:: twig {% trans "Hello World!" %} {% trans string_var %} {% trans %} Hello World! {% endtrans %} In a translatable string, you can embed variables: .. code-block:: twig {% trans %} Hello {{ name }}! {% endtrans %} During the gettext lookup these placeholders are converted. ``{{ name }}`` becomes ``%name%`` so the gettext ``msgid`` for this string would be ``Hello %name%!``. .. note:: ``{% trans "Hello {{ name }}!" %}`` is not a valid statement. If you need to apply filters to the variables, you first need to assign the result to a variable: .. code-block:: twig {% set name = name|capitalize %} {% trans %} Hello {{ name }}! {% endtrans %} To pluralize a translatable string, use the ``plural`` block: .. code-block:: twig {% trans %} Hey {{ name }}, I have one apple. {% plural apple_count %} Hey {{ name }}, I have {{ count }} apples. {% endtrans %} The ``plural`` tag should provide the ``count`` used to select the right string. Within the translatable string, the special ``count`` variable always contain the count value (here the value of ``apple_count``). To add notes for translators, use the ``notes`` block: .. code-block:: twig {% trans %} Hey {{ name }}, I have one apple. {% plural apple_count %} Hey {{ name }}, I have {{ count }} apples. {% notes %} This is shown in the user menu. This string should be shorter than 30 chars {% endtrans %} You can use ``notes`` with or without ``plural``. Once you get your templates compiled you should configure the ``gettext`` parser to get something like this: ``xgettext --add-comments=notes`` Within an expression or in a tag, you can use the ``trans`` filter to translate simple strings or variables: .. code-block:: twig {{ var|default(default_value|trans) }} Complex Translations within an Expression or Tag ------------------------------------------------ Translations can be done with both the ``trans`` tag and the ``trans`` filter. The filter is less powerful as it only works for simple variables or strings. For more complex scenario, like pluralization, you can use a two-step strategy: .. code-block:: twig {# assign the translation to a temporary variable #} {% set default_value %} {% trans %} Hey {{ name }}, I have one apple. {% plural apple_count %} Hey {{ name }}, I have {{ count }} apples. {% endtrans %} {% endset %} {# use the temporary variable within an expression #} {{ var|default(default_value|trans) }} Extracting Template Strings --------------------------- If you use the Twig I18n extension, you will probably need to extract the template strings at some point. Using Poedit 2 ~~~~~~~~~~~~~~ Poedit 2 has native support for extracting from Twig files and no extra setup is necessary (Pro version). Using ``xgettext`` or Poedit 1 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Unfortunately, the ``xgettext`` utility does not understand Twig templates natively and neither do tools based on it such as free versions of Poedit. But there is a simple workaround: as Twig converts templates to PHP files, you can use ``xgettext`` on the template cache instead. Create a script that forces the generation of the cache for all your templates. Here is a simple example to get you started .. code-block:: php use Twig\Environment; use Twig\Loader\FilesystemLoader; use PhpMyAdmin\Twig\Extensions\I18nExtension; $tplDir = __DIR__ . '/templates'; $tmpDir = '/tmp/cache/'; $loader = new FilesystemLoader($tplDir); // force auto-reload to always have the latest version of the template $twig = new Environment($loader, [ 'auto_reload' => true, 'cache' => $tmpDir, ]); $twig->addExtension(new I18nExtension()); // configure Twig the way you want // iterate over all your templates foreach (new RecursiveIteratorIterator(new RecursiveDirectoryIterator($tplDir), RecursiveIteratorIterator::LEAVES_ONLY) as $file) { // force compilation if ($file->isFile()) { $twig->loadTemplate(str_replace($tplDir . '/', '', $file)); } } Use the standard ``xgettext`` utility as you would have done with plain PHP code: .. code-block:: text xgettext --default-domain=messages -p ./locale --from-code=UTF-8 -n --omit-header -L PHP /tmp/cache/*.php Another workaround is to use `Twig Gettext Extractor`_ and extract the template strings right from `Poedit`_. .. _`gettext`: https://www.php.net/gettext .. _`documentation`: https://www.php.net/manual/en/function.gettext.php .. _`Twig Gettext Extractor`: https://github.com/umpirsky/Twig-Gettext-Extractor#readme .. _`Poedit`: https://poedit.net/ History ------- This project was forked in 2019 by the phpMyAdmin team, since it was abandoned by the `Twig project`_ but was still in use for phpMyAdmin. .. _`Twig project`: https://github.com/twigphp/Twig-extensions If you find this work useful, or have a pull request to contribute, please find us on `Github`_. .. _`Github`: https://github.com/phpmyadmin/twig-i18n-extension/