Creating a multilanguage application

Every day, we meet more and more international companies, software products, and information resources that publish content on multiple languages. Yii2 provides built-in i18n support for making multilanguage applications.

In this recipe, we are translating the application interface to different languages.

Getting ready

Create a new yii2-app-basic application using the composer, as described in the official guide at http://www.yiiframework.com/doc-2.0/guide-start-installation.html.

How to do it…

  1. Change the main menu labels in the views/layouts/main.php file to use the Yii::t('app/nav', '...') method:
    echo Nav::widget([
        'options' => ['class' => 'navbar-nav navbar-right'],
        'items' => [
            ['label' => Yii::t('app/nav', 'Home'), 'url' => ['/site/index']],
            ['label' => Yii::t('app/nav', 'About'), 'url' => ['/site/about']],
            ['label' => Yii::t('app/nav', 'Contact'), 'url' => ['/site/contact']],
            ...
        ],
    ]);
  2. Change all your titles and breadcrumbs to use the common Yii::t('app, '...') method:
    $this->title = Yii::t('app', 'Contact');
    $this->params['breadcrumbs'][] = $this->title;
  3. Also, change all the labels of your buttons:
    <div class="form-group">
        <?= Html::submitButton(Yii::t('app', 'Submit'), ['class' => 'btn btn-primary'']) ?>
    </div>

    Change other hard-coded messages as well:

    <p>
        <?= Yii::t('app', 'The above error occurred while the Web server was processing your request.') ?>
    </p>
  4. Change the attribute labels of your ContactForm model:
    class LoginForm extends Model
    {
        ...
    
        public function attributeLabels()
        {
            return [
                'username' => Yii::t('app/user', 'Username'),
                'password' => Yii::t('app/user', 'Password'),
                'rememberMe' => Yii::t('app/user', 'Remember Me'),
            ];
        }
    }

    Also, change the attribute labels of the LoginForm model:

    class ContactForm extends Model
    {
        ...
    
        public function attributeLabels()
        {
            return [
                'name' => Yii::t('app/contact', 'Name'),
                'email' => Yii::t('app/contact', 'Email'),
                'subject' => Yii::t('app/contact', 'Subject'),
                'body' => Yii::t('app/contact', 'Body'),
                'verifyCode' => Yii::t('app', 'Verification Code'),
            ];
        }
    }

    It will output translated labels for the current language instead of originals.

  5. To prepare translations, create the messages directory. Right now, we can create translation files for all needed languages. We can do it manually, but there is a helpful crawler that can scan all project files and extract all messages from Yii::t() constructions. Let's use it.
  6. Generate the configuration file for the message scanner:
    ./yii message/config-template config/messages.php
    
  7. Open the configuration file and set the following values:
    <?php
    
    return [
        'sourcePath' => '@app',
        'languages' => ['de', 'fr'],
        'translator' => 'Yii::t',
        'sort' => false,
        'removeUnused' => false,
        'markUnused' => true,
        'only' => ['*.php'],
        'except' => [
            '.svn',
            '.git',
            '.gitignore',
            '.gitkeep',
            '.hgignore',
            '.hgkeep',
            '/messages',
            '/vendor',
        ],
    
        'format' => 'php',
        'messagePath' => '@app/messages',
        'overwrite' => true,
    
        'ignoreCategories' => [
            'yii',
        ],
    ];
  8. Run crawler while passing this configuration file to it:
    ./yii message config/messages.php
    
  9. After the process, we must get the following directory structure:
    messages
    ├── de
    │   ├── app
    │   │   ├── contact.php
    │   │   ├── nav.php
    │   │   └── user.php
    │   └── app.php
    └── fr
        ├── app
        │   ├── contact.php
        │   ├── nav.php
        │   └── user.php
        └── app.php
  10. For example, the messages/de/app/contact file contains the following content:
    <?php
    ... 
    return [
        'Body' => '',
        'Email' => '',
        'Name' => '',
        'Subject' => '',
    ];
  11. It is a plain PHP array with original sentences in keys and translated messages in values.
  12. Just put in the values needed to translate messages from Deutsch:
    <?php
    ... 
    return [
        'Password' => 'Passwort',
        'Remember Me' => 'Erinnere dich an mich',
        'Username' => 'Benutzername',
    ];
  13. Attach these translations to the i18n component of application in the config/web.php file:
    $config = [
        'id' => 'basic',
        'basePath' => dirname(__DIR__),
        'bootstrap' => ['log'],
        'components' => [
            …
            'i18n' => [
                'translations' => [
                    'app*' => [
                        'class' => 'yiii18nPhpMessageSource',
                        'sourceLanguage' => 'en-US',
                    ],
                ],
            ],
            'db' => require(__DIR__ . '/db.php'),
        ],
        'params' => $params,
    ];
  14. Open the login page with the default language:
    How to do it…
  15. Switch the application language to de:
    $config = [
        'id' => 'basic',
        'language' => 'de',
        'basePath' => dirname(__DIR__),
        'bootstrap' => ['log'],
        ...
    ];

    Then refresh the login page:

    How to do it…
  16. The built-in frameworks messages and default validation errors will be translated automatically.

How it works…

Yii2 provides the Yii::t() method for translating interface messages via the i18n component, which supports different types of sources. In this recipe, we use yiii18nhpMessageSource, which stores translated messages in plain PHP files.

The framework does not have artificial intelligence and does not translate messages by itself. You must put prepared translations in files or in the database and framework to get the needed message from this message source.

You can set the current language manually:

$config = [
    'id' => 'basic',
    'language' => 'de',
    ...
];

Instead of setting the language in the configuration file, you can switch the application language in runtime:

Yii::$app->language = 'fr';

For example, if you store the user language in the lang field of the User model, you can create the language loader:

<?php
namespace appootstrap;

use yiiaseBootstrapInterface;

class LanguageBootstrap implements BootstrapInterface
{
    public function bootstrap($app)
    {
        if (!$app->user->isGuest) {
            $app->language = $app->user->identity->lang;
        }
    }
}

Register this class in the bootstrapping list:

$config = [
    'id' => 'basic',
    'basePath' => dirname(__DIR__),
    'bootstrap' => ['log', 'app'bootstrapLanguageBoostrap'],
    ...
];

Now, every authenticated user will see the interface in their own language.

Also, you can override the yiiwebUrlManager class for passing the current language as a GET parameter or as a prefix of a URL. Also, as an alternative you can store selected languages in browser cookies.

When you generate models and another code with Gii, you can check the following option:

How it works…

All labels in the generated code will be embraced into the Yii::t() calls.

Note

We did not cover the translating of model content in this recipe. However, for example, you can store translated texts in separate tables (such as the post_lang table for post model table) in a database and use the value of the Yii::$app->language property to get the current language and extract needed content for your models by the value.

See also

For more information about internationalization in Yii2, refer to http://www.yiiframework.com/doc-2.0/guide-tutorial-i18n.html.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.21.76.0