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');
core/modules/language/src/Plugin/Block/LanguageBlock.php
this is responsible for the menu to change language.