Drupal developer

How to create Bootstrap 3 language dropdown switcher in Drupal 7?

Posted on 3. September 2015 - 10:00 in category Drupal 7, Bootstrap

It could be quite challenging to theme Drupal output, especially if you want to use the Bootstrap framework. It's crucial to be able to modify the markup as you want. One of the typical elements of a multilanguage site is language switcher. Today I will show you how to create Bootstrap 3 language dropdown switcher by theme function.

Drupal 7 locale module has a block called "Language switcher (User interface text)", which could be used to switch languages on your website. It looks like this:

How could we improve user experience?

As you can see, it has very basic functionality, but we can make it better. It will be great to show a flag instead of just language name. In the same way, if you have lot of languages or not enough space, it could be better to use dropdown menu instead. Many developers use Language Switcher Dropdown and Language Icons module for that. But what if you want total control of the markup?

Let's find a theme function

Every good developer should start with looking for appropriate theme function before programming a custom module. There are two candidates for markup overwriting in locale_block_view(). One of them is hook_block_view_alter() which I don't want to use because it's too generic and I would have to deal with rendered markup. Better choice will be the theme_links__locale_block() function which provides an array of language links. I think the provided code is self explanatory. Just put this code to your theme directory into template.php file.

<?php
function THEME_links__locale_block($vars) {

 
$content = '';

  global
$language_url;
 
$languages = $vars['links'];
 
$items = array();
 
$language_selected = '';

  foreach (
$languages as $lang_code => $lang_options) {
    if (isset(
$lang_options['href']) &&
         (
$lang_options['href'] == $_GET['q'] ||
           (
$lang_options['href'] == '<front>' &&
          
drupal_is_front_page())) &&
         (empty(
$lang_options['language']) ||
        
$lang_options['language']->language == $language_url->language)
       ) {
     
$language_selected  = '<ul><li class="' . $lang_code . '">';
     
$language_selected .= '<span class="flag-icon flag-icon-' . $lang_code . '"></span>';
     
$language_selected .= '<span class="flag-title">' . $lang_options['title'] . '</span></li></ul>';
    }else{
      if(isset(
$lang_options['href'])) {
       
$li  = '<li class="' . $lang_code . '">';
       
$li .= '<span class="flag-icon flag-icon-' . $lang_code . '"></span><span class="flag-title">';
       
$li .= l($lang_options['title'], $lang_options['href'], array('language' => $lang_options['language']));
       
$li .= '</span></li>';
       
$items[] = $li;
      }else{
       
$li  = '<li class="' . $lang_code . ' language-nexist">';
       
$li .= '<span class="flag-icon flag-icon-' . $lang_code . '"></span>';
       
$li .= '<span class="flag-title">' . $lang_options['title'] . '</span>';
       
$li .= '</li>';
       
$items[] = $li;
      }
    }

  }

 
$content .= '<div class="dropdown">';
 
$content .= '<button class="btn btn-default dropdown-toggle" type="button" id="dropdown-language" data-toggle="dropdown" aria-haspopup="true" aria-expanded="true">';
 
$content .= $language_selected;
 
$content .= '<span class="caret"></span></button>';
 
$content .= '<ul class="dropdown-menu" aria-labelledby="dropdown-language">';
 
$content .= implode($items);
 
$content .= '</ul>';
 
$content .= '</div>';

  return
$content;
}
?>

I am using vector flags in my example and the final solution with some CSS polishing could look like this:

Comments