1

We have a site with multiple languages and have been using the Language Switch Dropdown menu to allow users to change languages on the site. But when we add "Browser | Language from the browser's language settings." as an additional detection option along with "Selected Language" then the selected language no longer works as it is always overridden by the browser's language, even if "Selected Language" is placed before it.

The ideal workflow would be:

  1. Language is detected from the browser and translated
  2. The Language Dropdown shows the current language (currently it always displays the default language, even if the browser detects and switches to a different language)
  3. The user can then override the browser language by selecting a different language from the drop-down switcher. (Currently the dropdown has no effect if a language is detected via the browser)

SOLUTION EDIT:

The proposed solution did not work for us so we ended up writing a custom form alter function and using a one-time cookie to achieve the functionality we were looking for.

In the language detection, we have "selected language" enable as the first item then "URL" and the second item and no other detections are used.

Then we used the below hook to the detect and set the language from the browser one-time using a cookie. The hook also sets the default value of the language dropdown so it shows what the language is, even if set from the browser.

<?php

function MY_MODULE_form_lang_dropdown_form_alter(&$form, \Drupal\Core\Form\FormStateInterface $form_state, $form_id){

    // Only run if our custom language cookie is not set yet
    if (!isset($_COOKIE['Drupal_visitor_user_lang'])){

      // Get language set in browser
      $language = substr($_SERVER['HTTP_ACCEPT_LANGUAGE'], 0, 2);
      user_cookie_save(['user_lang' => $language]);

      // Set the language dropdown's default value
      $form['lang_dropdown_select']['#default_value'] = $language;

      $current_path = \Drupal::service('path.current')->getPath();
      $path = \Drupal::service('path.alias_manager')->getAliasByPath($current_path);
      $config = \Drupal::config('system.site');
      $front_uri = $config->get('page.front');
      $front_alias = \Drupal::service('path.alias_manager')->getAliasByPath($front_uri);

      if ($path == $front_alias){
        $path = '';
      }
      $default_language = \Drupal::languageManager()->getDefaultLanguage()->getId();
      if ($language == $default_language){
        $language = '';
      }
      $response = new RedirectResponse('/' . $language . $path);
      $response->send();

    }
    $language = \Drupal::languageManager()->getCurrentLanguage()->getId();
    $form['lang_dropdown_select']['#default_value'] = $language;
}

enter image description here

1 Answer 1

3

The Selected language option comes with this description:

Changing the selected language here (and leaving this option as the last among the detection and selection options) is the easiest way to change the fallback language for the website, if you need to change how your site works by default (e.g., when using an empty path prefix or using the default domain). Changing the site's default language itself might have other undesired side effects.

This option is meant to be the last on the list and used only as a fallback.

If you give Browser option advantage on the list by placing it above the URL option the language will always be chosen by the browser criteria.

I'm guessing that there are cases where browser language might be not available in which case the URL option will kick in, but in most cases the URL option will not be used because Browser option will set the language and no options that come after it will even be evaluated.

It seems you need the Session option before the Browser option. This option should work with the Language switcher to add the parameter in the URL that will set the chosen language, but before the user selects something from the dropdown the Browser option will set the language.

Turn the URL option off completely if you don't need the language prefix to avoid confusion when the parameter is present. Having too many options turned on complicates the system unnecessarily and makes it more difficult to figure out what the causes are if there are bugs present.

I haven't tested this configuration. Language configuration can be tricky and you may need to do more adjustments and testing to get to where you want to be.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.