Yii 2 Internationalization (i18n)
Configuration for Translated Views

Configure sourceLanguage and language (target language) in the application configuration file, such as @app/config/web.php or @common/config/main.php:

<?php
return [
    //...
    'components' => [
        //...
    ],
    // set source language to be English
    'sourceLanguage' => 'en-US',
    // set target language to be Spanish (US)
    //'language' => 'es-US',
    // set target language to be Russian
    'language' => 'ru-RU',
    //...
];

Then translate the view and place it under its own locale folder. For example, when translating view @app/views/payment/view.php, place it in @app/views/payment/ru-RU/view.php.

Configuration for Translated Messages

Edit configuration file to include i18n translations.

<?php
return [
    // ...
    'components' => [
        // ...
        // set translations
        'i18n' => [
            'translations' => [
                // Default Message Source
                '*' => [
                    'class' => 'yii\i18n\PhpMessageSource'
                ],
                // Yii Framework Message Source
                // Place your adjusted translations to @app/messages/<language>/yii.php
                'yii' => [
                    'class'          => 'yii\i18n\PhpMessageSource',
                    'sourceLanguage' => 'en-US',
                    'basePath'       => '@app/messages'
                ],
                // App Message Source
                //'app*' => [
                //    'class' => 'yii\i18n\PhpMessageSource',
                //    'fileMap' => [
                //        'app' => 'app.php',
                //        'app/error' => 'error.php',
                //    ],
                //    'on missingTranslation' => [
                //        'app\components\TranslationEventHandler', 'handleMissingTranslation'
                //    ]
                //],
            ],
        ],
    ],
    // set source language to be English
    'sourceLanguage' => 'en-US',
    // set target language to be Spanish (US)
    //'language' => 'es-US',
    // ...
];

Generate i18n Config File

Generate the config file i18n.php in the config folder:

$ ./yii message/config @app/config/i18n.php

Customize the config file:

<?php
 
return [
    // string, required, root directory of all source files
    'sourcePath' => __DIR__ . DIRECTORY_SEPARATOR . '..',
 
    // Root directory containing message translations.
    'messagePath' => __DIR__ . DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR . 'messages',
 
    // array, required, list of language codes that the extracted messages
    // should be translated to. For example, ['zh-CN', 'de'].
    'languages' => ['de','es','fr','pt'],
 
    // string, the name of the function for translating messages.
    // Defaults to 'Yii::t'. This is used as a mark to find the messages to be
    // translated. You may use a string for single function name or an array for
    // multiple function names.
    'translator' => 'Yii::t',
 
    // boolean, whether to sort messages by keys when merging new messages
    // with the existing ones. Defaults to false, which means the new (untranslated)
    // messages will be separated from the old (translated) ones.
    'sort' => false,
 
    // boolean, whether to remove messages that no longer appear in the source code.
    // Defaults to false, which means each of these messages will be enclosed with a pair of '@@' marks.
    'removeUnused' => false,
 
    // array, list of patterns that specify which files (not directories) should be processed.
    // If empty or not set, all files/directories will be processed.
    // A path matches a pattern if it contains the pattern string at its end. For example,
    // '/a/b' will match all files and directories ending with '/a/b';
    // the '*.svn' will match all files and directories whose name ends with '.svn'.
    // and the '.svn' will match all files and directories named exactly '.svn'.
    // Note, the '/' characters in a pattern matches both '/' and '\'.
    // See helpers/FileHelper::findFiles() description for more details on pattern matching rules.
    'only' => ['*.php'],
 
    // array, list of patterns that specify which files/directories should NOT be processed.
    // If empty or not set, all files will be processed.
    // Please refer to "except" for details about the patterns.
    // If a file/directory matches both a pattern in "only" and "except", it will NOT be processed.
    'except' => [
        '.svn',
        '.git',
        '.gitignore',
        '.gitkeep',
        '.hgignore',
        '.hgkeep',
        '/messages',
        '/vendor/kartik-v/yii2-detail-view/DetailView.php',
        '/vendor/kartik-v',
    ],
 
    // 'php' output format is for saving messages to php files.
    'format' => 'php',
 
    // boolean, whether the message file should be overwritten with the merged messages
    'overwrite' => true,
 
 
    /*
    // 'db' output format is for saving messages to database.
    'format' => 'db',
    // Connection component to use. Optional.
    'db' => 'db',
    // Custom source message table. Optional.
    // 'sourceMessageTable' => '{{%source_message}}',
    // Custom name for translation message table. Optional.
    // 'messageTable' => '{{%message}}',
    */
 
    /*
    // 'po' output format is for saving messages to gettext po files.
    'format' => 'po',
    // Root directory containing message translations.
    'messagePath' => __DIR__ . DIRECTORY_SEPARATOR . 'messages',
    // Name of the file that will be used for translations.
    'catalog' => 'messages',
    // boolean, whether the message file should be overwritten with the merged messages
    'overwrite' => true,
    */
];    

Extract i18n Strings from App

To get all the translatable strings into our @app/messages folder, run:

$ mkdir messages
$./yii message/extract @app/config/i18n.php

Now translate the strings in @app/messages/es/app.php, @app/messages/es/frontend.php, etc.:

/*
 * NOTE: this file must be saved in UTF-8 encoding.
 *
 * Each array element represents the translation (value) of a message (key).
 * If the value is empty, the message is considered as not translated.
 *
 * Messages that no longer need translation will have their translations
 * enclosed between a pair of '@@' marks.
 */
return [
    'About'      => '',
    'Contact'    => '',
    'Home'       => '',
    'Logout'     => '',
    'My Company' => '',
    'Sign In'    => '',
    'Sign Up'    => '',
    'Status'     => '',
    //...
];    

Models

In the models, all strings to be displayed need to include the Yii::t(…) notation. Eg:

class PaymentController extends Controller
{
  // ...
  public function attributeLabels()
  {
    return [
      'id'          => Yii::t('app', 'ID'),
      'message'     => Yii::t('app', 'Message'),
      'permissions' => Yii::t('app', 'Permissions'),
      // ...
      'created_at'  => Yii::t('app', 'Created At'),
      'updated_at'  => Yii::t('app', 'Updated At'),        
    ];
  }
}

Controllers

In the controller, all string to be displayed need to include the Yii::t(…) notation. eg:

// Basic Messages
echo Yii::t('app', 'User List');
 
// Messages can contain parameter placeholders which will be replaced 
// with the actual parameter values when calling Yii::t(). For example, 
// the following message translation request would replace 
// the {alias} placeholder in the original message with the actual alias value.
echo Yii::t('app', "Unable to view user ID {id}'s profile.", ['id' => $id]);
 
// Positional placeholders
$price = 100;
$count = 2;
$subtotal = 200;
echo \Yii::t('app', 'Price: {0}, Count: {1}, Subtotal: {2}', [$price, $count, $subtotal]);
echo \Yii::t('app', 'Price: {0}', $price);

See more formatting and placeholders: Tutorial i18n

Detecting Language Automatically

Create bootstrap code. For example, create file app\components\LanguageSelector:

<?php
/* Detecting language automatically
 * Source: https://github.com/samdark/yii2-cookbook/blob/master/book/i18n-selecting-application-language.md
 * 
 * Requires configuration entry in 'bootstrap':
 * // return [
 * //     'bootstrap' => [
 * //         [
 * //             'class' => 'app\components\LanguageSelector',
 * //             'supportedLanguages' => ['en_US', 'ru_RU'],
 * //         ],
 * //     ],
 * //     // ...
 * // ];
*/
namespace app\components;
use yii\base\BootstrapInterface;
 
class LanguageSelector implements BootstrapInterface
{
    public $supportedLanguages = [];
 
    public function bootstrap($app)
    {
        $preferredLanguage = $app->request->getPreferredLanguage($this->supportedLanguages);
        $app->language = $preferredLanguage;
    }
}
 
?>

Add bootstrap code in config file, such as @app/config/web.php or @common/config/main.php:

$config = [
    //...
];
$config['bootstrap'][] = [
    'class' => 'app\components\LanguageSelector',
    'supportedLanguages' => ['es_US', 'en_US'],
];
References