Revision: Thu, 22 Feb 2024 17:59:01 GMT

Component — Internationalization

The Spiral i18n component is based on the symfony/translator package and provides compatible interfaces. The web bundle includes this extension by default.

Installation

To enable the extension in alternative builds:

composer require spiral/translator

Register the bootloader I18nBootloader in your application.

php
app/src/Application/Kernel.php
public function defineBootloaders(): array
{
    return [
        // ...
        \Spiral\Bootloader\I18nBootloader::class,
        // ...
    ];
}

Read more about bootloaders in the Framework — Bootloaders section.

Usage

By default, the translator component will automatically load all locale files located in app/locale/{lang} directories.

To get a list of available locales:

php
namespace App\Endpoint\Web;

use Spiral\Translator\TranslatorInterface;

class HomeController
{
    public function index(TranslatorInterface $translator): void
    {
        dump($translator->getCatalogueManager()->getLocales());
    }
}

To change the locale, use the setLocale method.

Note
It's recommended to use the setLocale method inside middleware or domain core and then properly reset the original locate.

Configuration

The framework supplies a default configuration automatically, inside Spiral\Bootloader\I18nBootloader. If you need custom settings, you can define them in app/config/translator.php:

Configuration File

Here's what a typical configuration might look like:

php
app/config/translator.php
use Symfony\Component\Translation\Dumper;
use Symfony\Component\Translation\Loader;

return [
    'locale' => env('LOCALE', 'en'),
    'fallbackLocale' => env('LOCALE', 'en'),
    'directory' => directory('locale'),
    'autoRegister' => env('DEBUG', true),
    // available locale loaders (the key is extension)
    'loaders' => [
        'php'  => Loader\PhpFileLoader::class,
        'po'   => Loader\PoFileLoader::class,
        'csv'  => Loader\CsvFileLoader::class,
        'json' => Loader\JsonFileLoader::class
    ],
    // export methods
    'dumpers'  => [
        'php'  => Dumper\PhpFileDumper::class,
        'po'   => Dumper\PoFileDumper::class,
        'csv'  => Dumper\CsvFileDumper::class,
        'json' => Dumper\JsonFileDumper::class,
    ],
    'domains' => [
        // by default we can store all messages in one domain
        'messages' => ['*']
    ]
];

Key Points:

  1. Locale Settings: The locale is your primary language, while fallbackLocale is the default language the app will use if the specified one isn't available.
  2. Directory Setting: This is where the language files reside. By default, it's set to the app/locale directory.
  3. Loaders and Dumpers: These are classes that handle reading from and writing to translation files.

Changing the Directory for Locale Files

If you want to use a different directory for your language files, modify the directory option:

php
app/config/translator.php
return [
    'directory' => directory('locale'),
];

Sometimes, you might need translations from more than one location. For example, when you're using external packages that bring their own translations.

To specify multiple directories use directories:

php
app/config/translator.php
return [
    'directory' => directory('locale'),
    // ...
    'directories' => [
        directory('vendor/package/name/locale'),
        ...
    ],
    // ...
];

You can also add new directories using the Spiral\Bootloader\I18nBootloader bootloader:

php
use Spiral\Boot\Bootloader\Bootloader;
use Spiral\Bootloader\I18nBootloader;

final class AppBootloader extends Bootloader
{
    public function init(I18nBootloader $i18n): void
    {
        $i18n->addDirectory('some/directory');
    }
}

Note
If there's a conflict between translation files, the ones in the main application will take priority over additional directories.

Import and Export

It is possible to export application locale bundles into the following formats:

  • PHP
  • GetText PO
  • CSV
  • JSON

Export Locale

To export application locate bundles run:

php app.php i18n:export en ./

Note
Export the locale en into the current directory.

You should see the file messages.en.php created in this directory. To export in alternative formats:

php app.php i18n:export en ./ -d po

This command will export the locale into the GetText format.

Generate Locale

The framework is able to automatically generate locale files using static code indexation. Run the command i18n:index to find all the declared stings.

php app.php i18n:index -vv

Import Locale

Import the locale into the project by placing the files app/locale/{lang} directory. Use the GetText, PHP, or JSON formats.

View Localization

Spiral includes a view process available for Twig and Stempler engines to translate view source code. The translated view will be stored in a separate view cache and it provides the ability to translate views without any performance penalty.

View Translation

To activate view translation, enable the bootloader Spiral\Bootloader\Views\TranslatedCacheBootloader. Make sure to add this bootloader before viewing engine bootloaders:

php
app/src/Application/Kernel.php
public function defineBootloaders(): array
{
    return [
         // ...
         \Spiral\Views\Bootloader\ViewsBootloader::class,
         \Spiral\Bootloader\Views\TranslatedCacheBootloader::class,
         // ...
    ];
}

Read more about bootloaders in the Framework — Bootloaders section.

Embrace the string to be translated with [[ string ]] in your template:

html
[[hello world]]

Note
Change the locale in your application to switch translation in the view.

Say Trait

It is possible to add translation abilities to any application object using the specialized trait Spiral\Translator\Traits\TranslatorTrait.

Usage

We can add the translator trait to the controller:

php
namespace App\Endpoint\Web;

use Spiral\Translator\Traits\TranslatorTrait;

class HomeController
{
    use TranslatorTrait;

    public function index(): string
    {
        return $this->say('hello world!');
    }
}

Note
Run 'i18n:index' to index the string invocation.

Class messages

In cases where a message is defined by logic and can not be indexed, use constants or properties to declare class messages, every string wrapped with [[]] will be automatically indexed.

php
class HomeController 
{
    use TranslatorTrait;

    protected const MESSAGES = [
        'error'   => '[[An error]]',
        'success' => '[[Success]]'
    ];

    public function index(): string
    {
        echo $this->say(self::MESSAGES['error']);
    }
}

Events

Event Description
Spiral\Translator\Event\LocaleUpdated The Event will be fired after changing the locale.

Note
To learn more about dispatching events, see the Events section in our documentation.