Set global language value in Yii2 application

35,748

Solution 1

You should use

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

inside the controller that is parent to all your controllers. The parent class should be inside the components folder, and if it is not available than create the component with something like

use yii\web\Controller;
class MyController extends Controller
{
    public function init()
    {
        parent::init();
        #add your logic: read the cookie and then set the language
    }
}

After that, you have to be sure that all your controllers extends your newly created MyController instead of the original one.

I hope it helps.

Solution 2

You can set your base language in the configuration file. In the basic application it's default location is: /config/web.php, in advanced: application-name/config/main.php and application-name/config/main-local.php.

$config = [
    'id' => 'basic',
    'language' => 'nl', // Set the language here
    'basePath' => dirname( __DIR__ ),
    'bootstrap' => ['log'],
    ...
];

Solution 3

The accepted answer is a very good one, but just in case you want something "even more global" you can use the bootstrap functionality, or the "on beforeAction" to trigger a function (both via the configuration):

Bootstrap:

$config = [
  ...
  'bootstrap' => ['your\own\component'],
  ...
];

You can then use the init()-function of that component for example.

"on beforeaction":

$config = [
   'on beforeAction' => function($event) {
      // set language
   } 
];

Solution 4

I know this is old but, I found this question while I was searching an answer. I also find a nice guide, link below.

One of the ways to do it to create a component and bootstrap it, like so:

Create a file in, say, common/components/LanguageSelector.php

<?php

namespace common\components;

use yii\base\BootstrapInterface;

class LanguageSelector implements \yii\base\BootstrapInterface
{
    public $supportedLanguages = [];

    public function bootstrap($app)
    {
        $preferredLanguage = $app->request->getPreferredLanguage($this->supportedLanguages);
        $app->language = $preferredLanguage;
    }
}

I'm using advanced app template, you can adjust the file location and namespace as needed.

Then, in your config file, you need to add this component, just like you are adding another component like debug, or log components, like so:

'components' => [
    'languageSelector' => [
        'class' => 'common\components\LanguageSelector',
        'supportedLanguages' => ['en-US', 'tr-TR'],
    ],
],

Also, you need to add this component to bootstrapped components in your config file:

'bootstrap' => ['languageSelector', ...]

This approach does not rely on cookies however, it relies on the language of the client browser. You also can find an example on below page in how to achieve preference based language selection. But basically what you need to do is, in your languageSelector component, getting the value from the cookie and change the language accordingly. If there is not a cookie present in the user browser, you can fallback to the browser language.

https://github.com/samdark/yii2-cookbook/blob/master/book/i18n-selecting-application-language.md

Solution 5

There are many answer to your question, depending on your logic. If you have a static rule:

return [
    ...
    'language' => 'it',
    ...
];

See http://www.yiiframework.com/doc-2.0/guide-tutorial-i18n.html#configuration

If you want implement the ordinary HTTP content negotiation, you have a dedicated component:

return [
    ...
    'components' => [
        ...
        'contentNegotiator' => [
            'class' => 'yii\filters\ContentNegotiator',
            'languages' => ['en', 'it'],
        ],
        ...
    ],
];

See http://www.yiiframework.com/doc-2.0/guide-structure-filters.html#content-negotiator

If you need a more complex negotiation, you can create a bootstrap component. Here is an example where the language is taken from user preferences for a logged in user or negotiated for guests. Note that you can overload your application with complex operations, like taking the supported languages from a database.

/**
 * Select a language from user preferences or content negotiation
 */
class LanguageSelector implements BootstrapInterface
{
    public function bootstrap($app)
    {
        if (\Yii::$app->user->isGuest) {
            $supportedLanguages = (new \yii\db\Query())
                ->select('iso639_1')
                ->from('language')
                ->orderBy(['priority' => SORT_ASC])
                ->column();

            $app->language = $app->request->getPreferredLanguage($supportedLanguages);

        } else {
            $app->language = Language::findOne(\Yii::$app->user->identity->language_id)->iso639_1;
        }
    }
}

There's a good reading here about this topic: https://yii2-cookbook.readthedocs.io/i18n-selecting-application-language/

Share:
35,748
bxN5
Author by

bxN5

Updated on April 21, 2020

Comments

  • bxN5
    bxN5 about 4 years

    Where can I set language (based on user's cookie) globally? How to make it work in the whole application (controllers,views, etc.) ?

    In documentation I found \Yii::$app->language = ''; but, where I can write my logic to change the language in right way?

  • Valery Bulash
    Valery Bulash over 7 years
    That's not working for YII2 basic template - site visible language remains 'en'
  • sankar muniyappa
    sankar muniyappa over 7 years
    Can please you provide full example of code for setting language as global. It will be helpful for all members.
  • NaturalBornCamper
    NaturalBornCamper about 6 years
    Remains "en-US" for me