odan / twig-translation
A Twig Translation Extension
Installs: 12 523
Dependents: 2
Suggesters: 0
Security: 0
Stars: 14
Watchers: 3
Forks: 3
Open Issues: 0
Requires
- php: ^7.3 || ^8.0
- symfony/translation-contracts: ^2
- twig/twig: ^3.1
Requires (Dev)
- friendsofphp/php-cs-fixer: ^2
- mikey179/vfsstream: ^1
- overtrue/phplint: ^2
- phpstan/phpstan: 0.*
- phpunit/phpunit: ^9
- squizlabs/php_codesniffer: ^3
- symfony/config: ^4 || ^5
- symfony/translation: ^4 || ^5
README
A Twig Translation Extension.
Please read this first!
The symfony/twig-bridge also provides a
Twig 3 TranslationExtension
to translate messages with the trans filter.
For this reason the odan/twig-translation
component is just redundant and will be deprecated in the near future.
I strongly recommend you to use the symfony/twig-bridge
TranslationExtension instead.
Here you can find an installation guide:
Requirements
- PHP 7.3+ or 8.0+
Installation
composer require odan/twig-translation
Registering the extension
This example uses the symfony/translation component:
composer require symfony/translation
Register the Twig Extension:
$loader = new \Twig\Loader\FilesystemLoader('/path/to/templates'); $twig = new \Twig\Environment($loader, array( 'cache' => '/path/to/twig-cache', )); $translator = new \Symfony\Component\Translation\Translator( 'en_US', new MessageFormatter(new IdentityTranslator()), null ); $translator->addLoader('mo', new MoFileLoader()); $twig->addExtension(new \Odan\Twig\TwigTranslationExtension($translator));
Slim 4 integration
To install the symfony/translation component, run:
composer require symfony/translation
Add settings:
// Locale settings $settings['locale'] = [ 'path' => '/path/to/resources/locale', 'cache' => '/path/to/locale-cache', 'locale' => 'en_US', 'domain' => 'messages', // Should be set to false in production 'debug' => false, ];
Add a new container definition:
<?php use Odan\Twig\TwigTranslationExtension; use Psr\Container\ContainerInterface; use Symfony\Component\Translation\Formatter\MessageFormatter; use Symfony\Component\Translation\IdentityTranslator; use Symfony\Component\Translation\Loader\MoFileLoader; use Symfony\Component\Translation\Translator; // ... return [ // ... Translator::class => function (ContainerInterface $container) { $settings = $container->get('settings')['locale']; $translator = new Translator( $settings['locale'], new MessageFormatter(new IdentityTranslator()), $settings['cache'], $settings['debug'] ); $translator->addLoader('mo', new MoFileLoader()); // Optional: Inject the translator instance into the __() function // __($translator); return $translator; }, Twig::class => function (ContainerInterface $container) { $twig = Twig::create('/path/to/templates', []); // Add extension $translator = $container->get(Translator::class); $twig->addExtension(new TwigTranslationExtension($translator)); // Add more extension ... return $twig; }, ];
Create a global translation function
This step is optional, but recommend if you want to translate messages directly in PHP.
Create the file src/Utility/translate.php
and copy / paste this content:
<?php use Symfony\Contracts\Translation\TranslatorInterface; /** * Translate text. * * @param string|TranslatorInterface $message The message being translated or the translator * @param string|int|float|bool ...$context The context arguments * * @return string The translated message */ function __($message, ...$context): string { /** @var TranslatorInterface $translator */ static $translator = null; if ($message instanceof TranslatorInterface) { $translator = $message; return ''; } $translated = $translator->trans($message); if (!empty($context)) { $translated = vsprintf($translated, $context); } return $translated; }
Register the composer autoloader in composer.json:
"autoload": { "files": [ "src/Utility/translate.php" ] },
Run: composer update
Usage
Translate a text:
{{ __('Yes') }}
Translate a text with a placeholder:
{{ __('Hello: %s', username) }}
Output (depends on the language):
Hello admin
Translate a text with multiple placeholders:
{{ __('First name: %s, Last name: %s', firstName, lastName) }}
Output (depends on the language):
First name: John, Last name: Doe
Create a plural translation:
Example 1:
{% if count > 1 %} {{ count }} {{ __('Users') }} {% else %} {{ count }} {{ __('User') }} {% endif %}
Example 2:
{% if users|length > 1 %} {{ users|length }} {{ __('Users') }} {% else %} {{ users|length }} {{ __('User') }} {% endif %}
Create a complex plural translation:
{% if not count %} {{ __('No users') }} {% elseif count = 1 %} {{ count }} {{ __('User') }} {% else %} {{ count }} {{ __('Users') }} {% endif %}
Parsing with Poedit
The workflow
- Parse all twig files (
php bin/parse-twig.php
) - Start Poedit and open the .po file
- Click the
Update
button to parse all PHP and Twig cache files - Translate the text and save the file.
Poedit Setup
- Start Poedit and open the .po file
- Open the menu:
Catalogue
>Properties...
- Open the tab:
Source paths
- Add a new path and point it to the twig cache
- The path must be relative to the base path e.g.
..\temp\twig-cache
- Open the tab:
Source keyword
- Add a new keyword with the name
__
(2 underscores)
- Add a new keyword with the name
- Click the
OK
button andUpdate
the calalogue.
Parsing Twig files
You need to iterate and compile all your Twig templates. The compilation step generates the PHP cache files that can be parsed from Poedit. This script is only an example and must be adapted to your individual environment.
Twig settings:
// Twig settings $settings['twig'] = [ 'path' => '/path/to/twig/templates', // Should be set to true in production 'cache_enabled' => true, 'cache_path' => '/path/to/twig-cache', // <--- ];
File: bin/parse-twig.php
use Odan\Twig\TwigCompiler; use Slim\App; use Slim\Views\Twig; // Bootstrap Slim application /** @var ContainerInterface $container */ $container = (require __DIR__ . '/../config/bootstrap.php')->getContainer(); /** @var App $app */ $app = $container->get(App::class); // Read twig settings $settings = $container->get('settings')['twig']; $cachePath = (string)$settings['cache_path']; $twig = $container->get(Twig::class)->getEnvironment(); // Compile twig templates (*.twig) to PHP code $compiler = new TwigCompiler($twig, $cachePath, true); $compiler->compile(); echo "Done\n"; return 0;
To run this script just enter: php bin/parse-twig.php
Similar libraries
The symfony/twig-bridge provides TranslationExtension
for Twig 3+.
Read more
License
- MIT