Community Documentation

Compact language switcher

Last updated September 26, 2008. Created by Jose Reyero on September 26, 2008.
Log in to edit this page.

There is a snippet that can be used for language switching instead of the standard language switching block (see an example of page template code appended) - the point is (1) being more compact (e.g. you can insert the switcher into the page header next to the site name, slogan, or search box), and (2) hiding the current language. See #242646: Do not show a link to the current language D6

<?php
 
// this is copy&paste from locale_block in locale.module
 
$languages = language_list('enabled');
 
$links = array();
  foreach (
$languages[1] as $language) {
    if (
$language->language != $current) {
     
$links[$language->language] = array(
       
'href'       => $_GET['q'],
       
'title'      => $language->native,
       
'language'   => $language,
       
'attributes' => array('class' => 'language-link'),
      );
    }
  }

 
// this adds the real paths, i.e. if we are on a german page,
  // the british flag will point to en/english_alias instead of
  // en/node_with_german_content
 
translation_translation_link_alter($links, $_GET['q']);

 
// This one adds extended languages, i.e. those that are not enabled.
  // Disable if you want only flags for enabled languages.
 
i18n_translation_link_alter($links, $_GET['q']);

 
// now add or replace text links by flags, according to your i18n settings.
 
if (function_exists('languageicons_translation_link_alter'))
   
languageicons_translation_link_alter($links, $_GET['q']);

 
// Or do your own stuff, e.g. set the flags and no lang names,
  // no matter what the i18n icon settings say.
  //if ($icon = theme('languageicons_icon', $language, NULL)) {
  //   $links[$language->language]['title'] = theme('languageicons_place', $link['title'], $icon);
  //   $links[$language->language]['html'] = TRUE;         
  //}

  // remove the current language again. We cannot do that
  // earlier because i18n_translation_link_alter would add it
  // again, thinking it was an extendeg language because it
  // was not yet contained in $links. If you don't use
  // i18n_translation_link_alter, you can also make a case distinction
  // in the foreach loop
 
$current = i18n_get_lang();
  unset(
$links[$current]);

 
// format as you like, e.g.
 
echo theme('links', $links, array());
?>

Comments

Hello,

I am not really good with defining classes and or elements on the page templates. I was wondering how should the code be modified so that I can have a class I can use to format the way the languages appear?. I am particularly interested to get the languages to appear inline one to the next instead of getting them to appear as a unordered list.

Any help would be great.

"// format as you like"

As seen at the bottom of the snippet's code:

  // format as you like, e.g.
  echo theme('links', $links, array('INSERT ONE OR MORE CLASSES HERE'));
?>

This will only let you "inject" class names into the unordered list generated by the links function. I am fairly new to customizing Drupal's output using functions, but I hope this helps!

(I *believe* this is the function being implemented, if you're curious. I don't know that for a fact, but hopefully someone will correct me if I'm wrong!)

note: If you're trying to get your language switcher to appear inline with other blocks (i.e. to the right or left of a horizontal navbar), you will have to override the "block" class using CSS.

"Nothing will work unless you do." - Maya Angelou

Just alter the output completely

Here an example of how I do it. Please note that I'm using "Language by domain name only" and that I use a special text for the title element. Additionally my flags aren't added by the module, I add them via CSS according to the HTML-ID.

<?php
 
// This is copy&paste from locale_block in locale.module.
 
$languages = language_list('enabled');
 
$path = drupal_is_front_page() ? '' : $_GET['q'];
 
$links = array();
  foreach (
$languages[1] as $language) {
    if (
$language->language != $current) {
     
$links[$language->language] = array(
       
'href'       => $language->domain .'/'. $path,
       
'title'      => t('Watch this page in @language.', array('@language' => $language->native)),
       
'text'       => $language->native,
       
'language'   => $language->language,
      );
    }
  }

 
// This adds the real paths, i. e. if we are on a german page,
  // the british flag will point to "en/english_alias" instead of
  // "en/node_with_german_content".
 
translation_translation_link_alter($links, $path);

 
// This one adds extended languages, i.e. those that are not enabled.
  // Disable if you want only flags for enabled languages.
 
i18n_translation_link_alter($links, $path);

 
// Remove the current language again. We cannot do that
  // earlier because i18n_translation_link_alter would add it
  // again, thinking it was an extendeg language because it
  // was not yet contained in $links. If you don't use
  // i18n_translation_link_alter, you can also make a case distinction
  // in the foreach loop.
 
unset($links[i18n_get_lang()]);

 
// Go through all language links and print 'em out.
 
foreach ($links as $link) {
    echo
' <a id="'. $link['language'] .'" lang="'. $link['language'] .'" href="'. $link['href'] .'" title="'. $link['title'] .'">';
      echo
$link['text'];
    echo
'</a>';
  }
?>

show all the enable language

How about to show all the enable language ...

I can't find the snippet that compatible in version 6.x.

Your help is really appreciated..

Thanks...

Tryig to do the same thing in a menu item

This code has proven very useful to me when implemented as a block. But my life as a programmer would be much simpler if I could implement this as a menu item instead of a block because that's how all the designers I work with tend to think about the language switcher. I've had some success when working this code into a hook_menu() implementation that uses a wildcard for the path. Any help to bring this to completion would be very welcome. I've posted this at the internationalization group here : http://groups.drupal.org/node/25253

drupal_alter()

I found it helpful to replace

<?php
translation_translation_link_alter
($links, $_GET['q']);
?>

with

<?php
drupal_alter
('translation_link', $links, $_GET['q']);
?>

I noticed that my language switching link was not working on taxonomy paths, but locale's language switching block does. After using drupal_alter() on the links, taxonomy gets to do it's part too.

I have a bilingual site that is configured to detect language via path-prefix w/browser fall-back. The default site language is English.

I've noticed that this switcher code works great if I connect to the site with an English browser. I can click the link and switch back and forth from English to French without difficulty.

However, using a French-enabled browser, I get locked into the French side of the site. It seems like the browser setting is taking precedence over the user's choice - but only when dealing with the non-default site language.

Go to

Go to admin/settings/language/configure/language (Language negotiation:)

Select "Path prefix only."

i8n cookie redirection?

Is there any way to Drupal remember chosen language for anonymous users? I mean, user picks language and next time he get redirected to previously chosen language?

should this snippet of code

should this snippet of code put in the page.tpl.php template file directly ? or

paste in a new block and put the block in whatever region I like.

path prefix output

Hi there!

My troubles are wth the path prefix output on my cutom theme (http://drupal.org/node/739384) ! Same problem for the standard language switcher, as well as with this code. Any idea where Im going wrong with my theme? On the standard drupal themes it workes just as anticipated... Hmmmm ... :-(

Duplicated Content (SEO)

Use the following code snippet if you want to reduce problems with duplicated content (frontpage). Additionally I added the HTML attribute "lang", browsers and robots know then that this particular anchor is in a different language.

<?php
/**
* Custom language selection block.
*
* @return string
*   All language links as string.
*/
function draw_language_selection() {
 
// This is more or less a copy&paste from locale_block in locale.module
 
$path = drupal_is_front_page() ? '<front>' : $_GET['q'];
 
$languages = language_list('enabled');
 
$links = array();
  foreach (
$languages[1] as $language) {
   
$links[$language->language] = array(
     
'href'       => $path,
     
'title'      => $language->native,
     
'language'   => $language,
     
'attributes' => array(
       
'id'    => $language->language,
       
'lang'  => $language->language,
       
'title' => t('Watch this page in @language.', array('@language' => $language->native), $language->language),
      ),
    );
  }

 
// This adds the real paths, i.e. if we are on a german page, the british flag
  // will point to "en/english_alias" instead of "en/node_with_german_content".
 
drupal_alter('translation_link', $links, $path);

 
// Remove the current language again. We cannot do that earlier because
  // i18n_translation_link_alter would add it again, thinking it was an extendeg
  // language because it was not yet contained in $links. If you don't use
  // i18n_translation_link_alter, you can also make a case distinction in the
  // foreach loop.
 
unset($links[i18n_get_lang()]);

 
// Draw the language selection links.
 
return theme('links', $links, array());
}
?>

You can put this directly into you page.tpl.php file, but I would not recommend that. Create an extra module or put it into your template.php file.

<?php
// template.php
function draw_language_selection() {
 
// Place code snippet here.
}
?>

You can now draw the language selection within your page.tpl.php by just calling the function draw_language_selection().

alter link to view

I have created link in page.tpl.php, pointing to /viewname. If I change language to english with language switcher link is not changed to /viewname/en. I know I can achieve this with Drupal menu but I don't want to create a menu for just one link. How to alter href in plain html link?

Hi, i'd like to use your

Hi,

i'd like to use your code, but i have 3 languages enabled (french, ducth and english) and i only want to display the languages for witch a translation really exists (french and dutch).
How can i do it ?

Thanks

Language switch block with images in a list

I was looking into creating a language selector as a list of images (flags of course).

Below is the code for Drupal 6. Just add a block (with PHP input) and use this in whatever place or change it accordingly.
Hope it helps!

<?php
// Code modified from modules/locale/locale.module

$path = drupal_is_front_page() ? '<front>' : $_GET['q'];
$languages = language_list('enabled');

print
'<ul id="language">';

foreach (
$languages[1] as $lang) {
 
 
$label = '<img src="' . base_path() . path_to_theme() .'/images/flags/'.$lang->language.'.gif" />';

  print
 
'<li>'.
 
l($label, $path, array('language'=>$lang, 'html'=>'true')).
 
'</li>';
}

print
'</ul>';
?>

language dropdown-switcher

<?php
           
// this is copy&paste from locale_block in locale.module
           
$languages = language_list('enabled');
           
$links = array();
            foreach (
$languages[1] as $language) {
                   
$links[$language->language] = array(
                   
'href' => $_GET['q'],
                   
'title' => $language->native,
                   
'language' => $language->language,
                   
'attributes' => array('class' => 'language-link'),
                    );
                }
            
           
// this adds the real paths, i.e. if we are on a german page,
            // the british flag will point to en/english_alias instead of
            // en/node_with_german_content
           
translation_translation_link_alter($links, $_GET['q']);
            
           
// This one adds extended languages, i.e. those that are not enabled.
            // Disable if you want only flags for enabled languages.
           
i18n_translation_link_alter($links, $_GET['q']);

          print
'<select name="select1" onChange="surfto(this.form)">' . "\n";
          foreach (
$links as $lang){
            print
'<option value="/' . $lang["language"] . "/" . $lang["href"] . '"';
            print
$lang["language"] == i18n_get_lang() ? ' selected="selected"' : '';
            print
'>' . $lang["title"];
            print
'</option>' . "\n";
          }
          print
'</select>' . "\n";
       
?>

'language' => $language

In the original code in line 10 should read: "'language' => $language->language,"

You need the whole $language object

No, this is correct as it is, you need to provide the whole $language object there.

This snippet has been super

This snippet has been super useful, but definitely contains a few holes.

Here is a complete module that provides a language drop down switcher block http://drupal.org/project/lang_dropdown

Any idea on how to create

Any idea on how to create this compact language switcher for Drupal 7?

Status

I'm looking forward to that too.

Did you find an answer yet?

nobody click here