Internationalization

If you are building a site for an international audience, you will likely want to provide localized versions of common strings on your website, including menu items, form labels, button labels, and more. Additionally, some websites require that route path segments be localized.

Zend Framework provides internationalization (i18n) tools via the zend-i18n component, and integration with zend-mvc via the zend-mvc-i18n component.

Installation

Install zend-mvc-i18n via Composer:

$ composer require zendframework/zend-mvc-i18n

Assuming you are using zend-component-installer (which is installed by default with the skeleton application), this will prompt you to install the component as a module in your application; make sure you select either application.config.php or modules.config.php for the location.

Once installed, this component exposes several services, including:

By default, until you configure translations, installation has no practical effect. So the next step is creating translations to use in your application.

Creating translations

The zend-i18n Translation chapter covers the details of adding translations to your application. You can use PHP arrays, INI files, or the popular gettext package (which allows you to use industry standard tools such as poedit to edit translations).

poedit

Once you have some translation sources, you will need to put them somewhere your application can access them. Options include:

Make sure you follow the guidelines from the zend-i18n documentation with regards to naming your files. Additionally, you may want to further segregate any such directory by text domain.

From here, you need to configure the translator to use your files. This requires adding configuration in either your module or application configuration files that provides:

As examples:

// in a module's module.config.php:
'translator' => [
    'locale' => 'en_US',
    'translation_file_patterns' => [
        [
            'type'     => 'gettext',
            'base_dir' => __DIR__ . '/../language',
            'pattern'  => '%s.mo',
        ],
    ],
],

// or in config/autoload/global.php:
'translator' => [
    'locale' => 'en_US',
    'translation_file_patterns' => [
        [
            'type'     => 'gettext',
            'base_dir' => getcwd() .  '/data/language',
            'pattern'  => '%s.mo',
        ],
    ],
],

Once the above configuration is in place, the translator will be active in your application, allowing you to use it.

Translating strings in templates

Once you have defined some strings to translate, and configured the application to use them, you can translate them in your application. The translate() and translatePlural() view helpers allow you to provide translations within your view scripts.

As an example, you might want to translate the string "All rights reserved" in your footer. You could do the following in your layout script:

<p>&copy; 2016 by Examples Ltd. <?= $this->translate('All rights reserved') ?></p>

Translating route segments

In order to enable route translation, you need to do two things:

To tell the application to use the translation-aware route class, we can update our routing configuration. Underneath the top-level router key, we'll add the router_class key:

// In a module.config.php file, or config/autoload/global.php:
'router' => [
    'router_class' => Zend\Mvc\I18n\Router\TranslatorAwareTreeRouteStack::class,
    'routes' => [
        /* ... */
    ],
],

If you want to use an alternate text domain, you can do so via the translator_text_domain key, also directly below the router key:

// In a module.config.php file, or config/autoload/global.php:
'router' => [
    'router_class' => Zend\Mvc\I18n\Router\TranslatorAwareTreeRouteStack::class,
    'translator_text_domain' => 'router',
    'routes' => [
        /* ... */
    ],
],

Now that the router is aware of translations, we can use translatable strings in our routes. To do so, surround the string capable of translation with braces ({}). As an example:

'route' => '/{login}',

specifies the word "login" as translatable.