PHPackages                             phpmyadmin/twig-i18n-extension - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Localization &amp; i18n](/categories/localization)
4. /
5. phpmyadmin/twig-i18n-extension

ActiveLibrary[Localization &amp; i18n](/categories/localization)

phpmyadmin/twig-i18n-extension
==============================

Internationalization support for Twig via the gettext library

5.0.1(7mo ago)20949.1k↓30.6%4[1 issues](https://github.com/phpmyadmin/twig-i18n-extension/issues)[1 PRs](https://github.com/phpmyadmin/twig-i18n-extension/pulls)3MITPHPPHP ^8.2CI passing

Since Dec 19Pushed 7mo ago6 watchersCompare

[ Source](https://github.com/phpmyadmin/twig-i18n-extension)[ Packagist](https://packagist.org/packages/phpmyadmin/twig-i18n-extension)[ RSS](/packages/phpmyadmin-twig-i18n-extension/feed)WikiDiscussions master Synced 1mo ago

READMEChangelog (10)Dependencies (8)Versions (15)Used By (3)

Twig i18n Extension
===================

[](#twig-i18n-extension)

The `i18n` extension adds [gettext](https://www.php.net/gettext) support to Twig. It defines one tag, `trans`.

Code status
-----------

[](#code-status)

[![Tests](https://github.com/phpmyadmin/twig-i18n-extension/actions/workflows/tests.yml/badge.svg?branch=master)](https://github.com/phpmyadmin/twig-i18n-extension/actions/workflows/tests.yml?query=branch%3Amaster)[![Code coverage](https://camo.githubusercontent.com/c0f5e3277845c33f904fff1030e9bee9b44762985e33c371e12fa0f87a1a0c82/68747470733a2f2f636f6465636f762e696f2f67682f7068706d7961646d696e2f747769672d6931386e2d657874656e73696f6e2f6272616e63682f6d61737465722f67726170682f62616467652e737667)](https://codecov.io/gh/phpmyadmin/twig-i18n-extension)Installation
------------

[](#installation)

This library can be installed via Composer running the following from the command line:

```
composer require phpmyadmin/twig-i18n-extension
```

Configuration
-------------

[](#configuration)

You need to register this extension before using the `trans` block

```
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](https://www.php.net/manual/en/function.gettext.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](https://www.php.net/gettext) extension is enabled.

Usage
-----

[](#usage)

Use the `trans` block to mark parts in the template as translatable:

```
{% trans "Hello World!" %}

{% trans string_var %}

{% trans %}
    Hello World!
{% endtrans %}
```

In a translatable string, you can embed variables:

```
{% 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:

```
{% set name = name|capitalize %}

{% trans %}
    Hello {{ name }}!
{% endtrans %}
```

To pluralize a translatable string, use the `plural` block:

```
{% 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:

```
{% 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:

```
{{ var|default(default_value|trans) }}
```

Complex Translations within an Expression or Tag
------------------------------------------------

[](#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:

```
{# 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
---------------------------

[](#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

[](#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

[](#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

```
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->load(str_replace($tplDir . '/', '', $file->getRealPath()));
    }
}
```

Use the standard `xgettext` utility as you would have done with plain PHP code:

```
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](https://github.com/umpirsky/Twig-Gettext-Extractor#readme) and extract the template strings right from [Poedit](https://poedit.net/).

History
-------

[](#history)

This project was forked in 2019 by the phpMyAdmin team, since it was abandoned by the [Twig project](https://github.com/twigphp/Twig-extensions) but was still in use for phpMyAdmin.

If you find this work useful, or have a pull request to contribute, please find us on [Github](https://github.com/phpmyadmin/twig-i18n-extension/).

###  Health Score

58

—

FairBetter than 98% of packages

Maintenance61

Regular maintenance activity

Popularity48

Moderate usage in the ecosystem

Community32

Small or concentrated contributor base

Maturity77

Established project with proven stability

 Bus Factor2

2 contributors hold 50%+ of commits

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~175 days

Recently: every ~65 days

Total

13

Last Release

233d ago

Major Versions

v2.0.0 → v3.0.02020-06-14

v3.0.0 → v4.0.02021-02-25

4.1.3 → 5.0.02025-01-08

4.1.4 → 5.0.12025-09-26

PHP version history (5 changes)v2.0.0PHP &gt;=5.5.0

v3.0.0PHP &gt;=7.1

v4.0.0PHP ^7.1 || ^8.0

4.1.0PHP ^7.2 || ^8.0

5.0.0PHP ^8.2

### Community

Maintainers

![](https://www.gravatar.com/avatar/2b390aa578181e22baeeb561a42eba29a6fdbbd360d3d967afc59cdb8ff98ef7?d=identicon)[phpmyadmin](/maintainers/phpmyadmin)

![](https://www.gravatar.com/avatar/d9db27d970c150e94a773e41524ef8a343d307a7298eb475f494ea63c06cce07?d=identicon)[mauriciofauth](/maintainers/mauriciofauth)

![](https://www.gravatar.com/avatar/4bedd1de90555921e52b5384ca245494b0f787f79b751d24a128c8c2754895d8?d=identicon)[ibennetch](/maintainers/ibennetch)

---

Top Contributors

[![fabpot](https://avatars.githubusercontent.com/u/47313?v=4)](https://github.com/fabpot "fabpot (131 commits)")[![williamdes](https://avatars.githubusercontent.com/u/7784660?v=4)](https://github.com/williamdes "williamdes (91 commits)")[![MauricioFauth](https://avatars.githubusercontent.com/u/120970?v=4)](https://github.com/MauricioFauth "MauricioFauth (57 commits)")[![liviuconcioiu](https://avatars.githubusercontent.com/u/25424343?v=4)](https://github.com/liviuconcioiu "liviuconcioiu (4 commits)")[![umpirsky](https://avatars.githubusercontent.com/u/208957?v=4)](https://github.com/umpirsky "umpirsky (3 commits)")[![Trainmaster](https://avatars.githubusercontent.com/u/2514421?v=4)](https://github.com/Trainmaster "Trainmaster (2 commits)")[![joserobleda](https://avatars.githubusercontent.com/u/1263865?v=4)](https://github.com/joserobleda "joserobleda (2 commits)")[![stof](https://avatars.githubusercontent.com/u/439401?v=4)](https://github.com/stof "stof (2 commits)")[![Garfield-fr](https://avatars.githubusercontent.com/u/48578?v=4)](https://github.com/Garfield-fr "Garfield-fr (2 commits)")[![nicolas-grekas](https://avatars.githubusercontent.com/u/243674?v=4)](https://github.com/nicolas-grekas "nicolas-grekas (2 commits)")[![pyguerder](https://avatars.githubusercontent.com/u/6534215?v=4)](https://github.com/pyguerder "pyguerder (1 commits)")[![qpleple](https://avatars.githubusercontent.com/u/774546?v=4)](https://github.com/qpleple "qpleple (1 commits)")[![rgazelot](https://avatars.githubusercontent.com/u/1488251?v=4)](https://github.com/rgazelot "rgazelot (1 commits)")[![ricardclau](https://avatars.githubusercontent.com/u/613725?v=4)](https://github.com/ricardclau "ricardclau (1 commits)")[![romainneutron](https://avatars.githubusercontent.com/u/137574?v=4)](https://github.com/romainneutron "romainneutron (1 commits)")[![soullivaneuh](https://avatars.githubusercontent.com/u/1698357?v=4)](https://github.com/soullivaneuh "soullivaneuh (1 commits)")[![sroze](https://avatars.githubusercontent.com/u/804625?v=4)](https://github.com/sroze "sroze (1 commits)")[![Szymciosek](https://avatars.githubusercontent.com/u/3597951?v=4)](https://github.com/Szymciosek "Szymciosek (1 commits)")[![vslavik](https://avatars.githubusercontent.com/u/145881?v=4)](https://github.com/vslavik "vslavik (1 commits)")[![weaverryan](https://avatars.githubusercontent.com/u/121003?v=4)](https://github.com/weaverryan "weaverryan (1 commits)")

---

Tags

i18ngettext

###  Code Quality

TestsPHPUnit

Static AnalysisPHPStan

Type Coverage Yes

### Embed Badge

![Health badge](/badges/phpmyadmin-twig-i18n-extension/health.svg)

```
[![Health](https://phpackages.com/badges/phpmyadmin-twig-i18n-extension/health.svg)](https://phpackages.com/packages/phpmyadmin-twig-i18n-extension)
```

###  Alternatives

[gettext/gettext

PHP gettext manager

70130.2M102](/packages/gettext-gettext)[sepia/po-parser

Gettext \*.PO file parser for PHP.

1271.5M19](/packages/sepia-po-parser)[phpmyadmin/motranslator

Translation API for PHP using Gettext MO files

591.8M8](/packages/phpmyadmin-motranslator)[gettext/translator

Gettext translator functions

114.6M10](/packages/gettext-translator)[leaseweb/gettext-translation-bundle

Easy to use and native (faster) gettext translation support

2460.6k](/packages/leaseweb-gettext-translation-bundle)[om/potrans

Command line tool for translate Gettext with Google Translator API or DeepL API

10515.0k4](/packages/om-potrans)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
