Drupal - Switch a language programatically

In a custom module, you should use a custom LanguageNegotiator and assign it to your LanguageManager, using LanguageManager->setNegotiator();

1) First, you must define a CustomLanguageNegotiator, which overwrites initializeType() method. That method should return a Language object, which you can externally define using a custom setLanguageCode() method:

<?php

namespace Drupal\custom_module\Language;


/**
 * Class responsible for performing language negotiation.
 */
class CustomLanguageNegotiator extends \Drupal\language\LanguageNegotiator {

    var $languageCode = NULL;

    /**
     * {@inheritdoc}
     */
    public function initializeType($type) {
        $language = NULL;
        $method_id = static::METHOD_ID;
        $availableLanguages = $this->languageManager->getLanguages();

        if ($this->languageCode && isset($availableLanguages[$this->languageCode])) {
            $language = $availableLanguages[$this->languageCode];
        }
        else {
            // If no other language was found use the default one.
            $language = $this->languageManager->getDefaultLanguage();
        }

        return array($method_id => $language);
    }

    /**
     * @param string $languageCode
     */
    public function setLanguageCode($languageCode)
    {
        $this->languageCode = $languageCode;
    }


}

2) Define your CustomLanguageNegotiator as a service, in your custom module service file, "custom_module.services.yml":

custom_module.language_negotiator:
  class: Drupal\custom_module\Language\CustomLanguageNegotiator
  arguments: ['@language_manager', '@plugin.manager.language_negotiation_method', '@config.factory', '@settings', '@request_stack']
  calls:
    - [initLanguageManager]

3) Rebuild your cache and use your CustomLanguageNegotiator like this:

$languageManager = \Drupal::languageManager();
$customLanguageNegotiator = \Drupal::service('custom.language_negotiator');
$languageManager->setNegotiator($customLanguageNegotiator);


// Set new language by its langcode
$languageManager->reset(); // Needed to re-run language negotiation
$languageManager->getNegotiator()->setLanguageCode('fr'); // 'en', 'es', 'fr', etc

// Run any code, and its output will be displayed in french
// ...

$languageManager->reset(); 
$languageManager->getNegotiator()->setLanguageCode('en');

// Run any code, and its output will be displayed in english
// ...

// Do not forget to set language to its initial value
$languageManager->reset(); 
$languageManager->getNegotiator()->setLanguageCode('XX');

You can change the current language to $lang_code with the following code.

$lang_code = 'fr';     
\Drupal::configFactory()->getEditable('system.site')->set('default_langcode', $lang_code)->save();

Best way is to create a new Language Negotiation plugin, create a new file in a custom module in the folder src/Plugin/LanguageNegotiation, to keep with naming convention I called my class LanguageNegotiationXXX, the contents of this file should be:

<?php

namespace Drupal\my_module\Plugin\LanguageNegotiation;

use Drupal\language\LanguageNegotiationMethodBase;
use Symfony\Component\HttpFoundation\Request;

/**
 * Custom class for identifying language.
 *
 * @LanguageNegotiation(
 *   id = Drupal\my_module\Plugin\LanguageNegotiation\LanguageNegotiationXXX::METHOD_ID,
 *   weight = -99,
 *   name = @Translation("XXX Language Switching"),
 *   description = @Translation("Language based on XXX."),
 * )
 */
class LanguageNegotiationXXX extends LanguageNegotiationMethodBase {

  /**
   * The language negotiation method id.
   */
  const METHOD_ID = 'language-XXX';

  /**
   * {@inheritdoc}
   */
  public function getLangcode(Request $request = NULL) {
    $langcode = NULL;

    // Custom logic goes here, but should set a langcode such as fr

    return $langcode;
  }

}

Enable module or clear caches for this to take effect, go to admin/config/regional/language/detection and enable your new detection method.

This worked perfectly for me with all users, all the other methods I tried didn't work with anonymous users.

Tags:

8