1

I want to show a block to visitors based on their browser language. (I guess it should be based on the Accept-Language HTTP header).

The page should stay in English but there should be something like this site is available in your language, click here translated into the relevant language.

How can I achieve this?

3 Answers 3

1

I don't think this is possible without custom code if you want to do this differently from the current language.

However, you don't need to do all the heavy lifting yourself. See LanguageNegotiationBrowser and the code there, you should be able to more or less copy that 1:1.

Then it will only do it if the language actually exists, respects language mappings and so on. You just have to call that, check if it's different from the current language and if so, display something.

However, properly caching that is going to be fun:

You need a cache context for an arbitrary http header, similar to CookiesCacheContext. so something like http_header:HTTP_ACCEPT_LANGUAGE as a cache context.

That will however not work for anonymous page cache, since that doesn't check cache contexts at all. To work around that, you need your own page cache implementation, that caches by that header, which will obviously result in lots and lots of variations.

So.. maybe you should just do this completely in JS?

1

Because i needed the same i have created a solution based on Berdir's answer. I created a menu callback where i compare the active language against the browser language. This callback i access with ajax, and based on the json result i do something. In my case i rewrite the language string itself in the browser language and highlight it. You can see the result here https://www.masterhomes.net/.

/**
 * Implements hook_menu().
 *
 * Add a menu callback to compare the browser language with the active language.
 */
function custom_menu() {
  $items = array();
  $items['browser-lang'] = array(
    'title' => 'Check browser language',
    'page callback' => 'custom_browser_lang',
    'access arguments' => array('access content'),
    'type' => MENU_CALLBACK,
  );
  return $items;
}

/**
 * Page Callback to handle the browser language.
 */
function custom_browser_lang() {
  // Set default output.
  $output = FALSE;
  // Get active langcode.
  global $language;
  $active_lang = $language->language;
  // Get browser langcode.
  $browser_lang = locale_language_from_browser(language_list());
  // If we found the browser language and it's not the same like the current
  // language.
  if ($browser_lang && $active_lang != $browser_lang) {
    // Get "Language" string in browser language.
    $output = array(
      'langString' => t('Language', array(), array(
        'langcode' => $browser_lang,
      )),
      'langCode' => $browser_lang,
    );
  }
  // Output json data.
  drupal_json_output($output);
  // Prevent caching.
  exit;
}
0

Either use dependency injection for the block plugin or call \Drupal::request() directly and determine the language using code similar to the following one.

$languages = \Drupal::request()->server->get('HTTP_ACCEPT_LANGUAGE');
$languages = explode(';', $languages)[0];
$languages = explode(',', $languages);
$language = explode('-', $languages[0])[0];

print $language;

If you want to apply this to any block, not just your own block plugin block, you could create a route context provider. Take the classes that implement \Drupal\Core\Plugin\Context\ContextProviderInterface as example.

0

Your Answer

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