Home » Documentation » Getting Started Guide » Language Setup » Custom Language Switcher

Custom Language Switcher

WPML comes with its own language switcher, implemented as a drop down list of languages. It’s pretty flexible, but not always enough.

You can build your own custom language switchers and insert them in the theme. I’ll show how to add a list of available languages to posts and a list of languages for the footer.

Getting the list of (other) languages

Use icl_get_languages() to get a list of translations for any page. Usage:

icl_get_languages('skip_missing=N&orderby=KEY&order=DIR&link_empty_to=str')

* N=0/1
* KEY=id/code/name (name -> translated_name), (defaut: id)
* DIR=asc/desc (defaut: asc)
* link_empty_to = str (default: empty, works in conjunction with skip_missing=0 and allows using custom links for the languages that do not have translations for the current element. {$lang} can be used as placeholder for the language code)

Notes:

  • The skip_missing parameter tells the function how to treat languages with no translations.
  • The combination of orderby and order allows creating the drop-down language switcher or language switchers where languages always display in the same position.

The function returns an array with entries per language. For example, for a WordPress site running English, French and Italian, it will return this:

Array
(
 [0] => Array
  (
   [id] => 1
   [active] => 1
   [native_name] => English
   [missing] => 0
   [translated_name] => English
   [language_code] => en
   [country_flag_url] => http://yourdomain/wpmlpath/res/flags/en.png
   [url] => http://yourdomain/about
  )

 [1] => Array
  (
   [id] => 4
   [active] => 0
   [native_name] => Français
   [missing] => 0
   [translated_name] => French
   [language_code] => fr
   [country_flag_url] => http://yourdomain/wpmlpath/res/flags/fr.png
   [url] => http://yourdomain/fr/a-propos
  )

 [2] => Array
  (
   [id] => 27
   [active] => 0
   [native_name] => Italiano
   [missing] => 0
   [translated_name] => Italian
   [language_code] => it
   [country_flag_url] => http://yourdomain/wpmlpath/res/flags/it.png
   [url] => http://yourdomain/it/circa
  )
)

Each language has its own array of parameters, which your theme function can use to build any language selector.

  • id: Internal reference id
  • active: This is the currently active language (exactly one language is active)
  • native_name: The native name of the language (never translated)
  • translated_name: The name of the language translated to the currently active language
  • country_flag_url: The URL to a PNG image with the country flag
  • url: The link to the translation in that language
  • missing: 1 if the translation for that element is missing, 0 if it it exists.

Handling missing translations

Some pages may not be translated to all languages. You can tell icl_get_languages what to return for languages with no translations.

If ‘skip_missing=1′, these languages will not appear in the output. If ‘skip_missing=0′, all the languages will appear and languages with missing translations will link back to the home page in that language.

How to use in your theme functions

You can build your own language switchers in whatever way you choose. Here, we’ll show two popular uses.

The example PHP functions we’re showing here should go in to your functions.php file (in the theme folder) – not added to the plugin.

This post is also available in…

Supposing you want to add a line, at the bottom (or top) of each post, saying in which other languages it’s available. This function should only return existing translated posts and if no translation is available, it shouldn’t output anything.

function icl_post_languages(){
  $languages = icl_get_languages('skip_missing=1');
  if(1 < count($languages)){
    echo __('This post is also available in: ');
    foreach($languages as $l){
      if(!$l['active']) $langs[] = '<a href="'.$l['url'].'">'.$l['translated_name'].'</a>';
    }
    echo join(', ', $langs);
  }
}

What this function does is:

  1. Get the list of languages from WPML – $languages = icl_get_languages(‘skip_missing=1′);
  2. Check that there’s more than one language for this post – if(1 < count($languages))
  3. Create the output, skipping the currently displayed language – if(!$l['active'])

Notes:

  1. The message goes through gettext. This is very important, so that this message, which you’ll append to posts in different languages will appear in the correct language:  __(‘This post is also available in: ‘);
  2. The language names used are the translated language names. This would guarantee that the entire sentence is written in the correct language: $l['translated_name']

The result is this:

Message about post available in other languages

Message about post available in other languages

To include this message in posts, add a call to icl_post_languages() from single.php.

List of language names and flags for the footer

Even if you have a language selector at the top of the page, it’s a good idea to add a list of language names and flags to the footer. Many people immediately scroll down the the bottom of the page, to get a better idea of what’s ahead, so placing a prominent language switcher there is likely to help your foreign visitors.

function languages_list_footer(){
    $languages = icl_get_languages('skip_missing=0&orderby=code');
    if(!empty($languages)){
        echo '<div id="footer_language_list"><ul>';
        foreach($languages as $l){
            echo '<li>';
            if($l['country_flag_url']){
                if(!$l['active']) echo '<a href="'.$l['url'].'">';
                echo '<img src="'.$l['country_flag_url'].'" height="12" alt="'.$l['language_code'].'" width="18" />';
                if(!$l['active']) echo '</a>';
            }
            if(!$l['active']) echo '<a href="'.$l['url'].'">';
            echo icl_disp_language($l['native_name'], $l['translated_name']);
            if(!$l['active']) echo '</a>';
            echo '</li>';
        }
        echo '</ul></div>';
    }
}

This function does the following:

  1. If there’s any translation language, creates a DIV and starts an unordered list: if(!empty($languages)){ echo ‘<div id=”footer_language_list”><ul>’;
  2. Goes through each of the languages and adds it as a list item.
  3. If it’s not the active language, also link to that page in that language: if(!$l['active']) echo ‘<a href=”‘.$l['url'].’”>’;
  4. Adds the language flag: <img src=”‘.$l['country_flag_url'].’” alt=”‘.$l['language_code'].’” width=”18″ height=”12″ />
  5. Add both native and translated language names, if they’re different: echo icl_disp_language($l['native_name'], $l['translated_name']);

The icl_disp_language() function is created by WPML. What it does is check if the two arguments (native_language_name, translated_language_name) are different. If so, it returns them both, otherwise, it returns them just once.

We should also add some CSS to style this languages list. This CSS will center the languages list in your footer and format it a bit:

#footer_language_list{
  margin-bottom: 25px;
  text-align: center;
}

#footer_language_list ul{
  list-style: none;
  margin:0;
  padding:0;
}

#footer_language_list ul li img{
  margin-right:5px;
}

#footer_language_list ul li{
  display:inline;
  margin:0 5px 0 5px;
  padding:0;
}

#footer_language_list ul li a, #footer_language_list ul li a:visited{
  color: #fff;
  text-decoration:underline;
}

#footer_language_list ul li a:hover, #footer_language_list ul li a:active{
  color: #fff;
}

Here is the language switcher:

Language footer

Language footer

To add it to your theme, add the call to languages_list_footer to the footer.php file.

* Note: you can easily change turn this horizontal language switcher into a vertical language switcher. Just remove the display: inline statement from the CSS.

Language selector with flags only

Simple function for displaying flags linked to the translations of the current page.

function language_selector_flags(){
    $languages = icl_get_languages('skip_missing=0&orderby=code');
    if(!empty($languages)){
        foreach($languages as $l){
            if(!$l['active']) echo '<a href="'.$l['url'].'">';
            echo '<img src="'.$l['country_flag_url'].'" height="12" alt="'.$l['language_code'].'" width="18" />';
            if(!$l['active']) echo '</a>';
        }
    }
}

The output of this function needs to be styled separately. For instance placing the function into a div block and defining custom styles for the img tags.

<div id="flags_language_selector"><?php language_selector_flags(); ?></div >

The CSS:

#flags_language_selector img{
      margin:1px;
      border:1px solid #333;
}

Flags language selector

Replacing the country flags and changing language names

WPML includes a GUI for editing language information. Go to WPML->Languages and click on Edit languages. You will be able to change the language names, edit their locale values and choose different flags.

'skip_missing=0&orderby=name'

144 Responses to “Custom Language Switcher”

  1. Marcio says:

    Hi,

    is possible to leave the flags appearing only and not the dropdown menu? how do I?

    tks
    M4RC10

  2. Maxoud says:

    @A: You have to set up language switcher in admin area.
    @Marcio: Read the article before you ask the question.

  3. javier says:

    Hi, great plugin! But i was wondering if its possible to center the language switcher on the sidebar instead of being aligned to the left, is there a way to do it?

    Any help would be highly apretiated!

    Thanks in advance

  4. Chiara says:

    Hi,
    I’m using Geoplaces by templatic,
    I’d like to add flags on the header and tried to use your explanation here above (Language selector with flags only), I added code in function php and in the header.php, nothing is shown ! what I’m doing wrong?
    is my theme not compatible with WPML?

  5. George says:

    I have the language selector in one sidebar and I want it in the others too, but there’s only “one” which is no longer available to the others. How can I fix this?
    Thanks

    One comment (I work in the language industry) – A lot of people object to being associated with a particular flag/country simply because they speak the same language. Generally not a good idea unless you can geo-automate flag display. Language & country are not the same thing.

  6. Oliver says:

    great plugin, does the above code work in the lastest version (2.0.4.1)?

  7. I was able to place language switcher in a header easily (thanks for idiot-proof instructions), but I have a challenge to remove text (language names) from it – need only flags. I`m reading instructions above 10 times, but can`t get it. I`m not a coder so need very simple and straight forward explanation what and where. Thank you in advance.

  8. Oh, no need to reply to my previous post. I figured out finally which code goes where. It is working now!!!

    Just one tiny detail. Could you please guide me how to adjust position of language switcher in a header? I know you can do it in your sleep :)

    Thank you in advance!

  9. Jarek says:

    I have the problem:

    Fatal error: Call to undefined function icl_get_languages() in /home/www/wp-content/themes/hik/header.php on line 59

    <li >

    <a title="” href=”"><img src="” height=”12″ alt=”" width=”18″ />

    Any body help me?

  10. Vedrana says:

    Hi,
    im having a small problem with my language switcher. Its working perfectly fine on all pages, but when you switch on blogs it says in the footer :
    Catchable fatal error: Object of class stdClass could not be converted to string in /homepages/14/d276549189/htdocs/wordpress/wp-content/plugins/sitepress-multilingual-cms/sitepress.class.php on line 3476

    i have no idea what it means…could you please help :)

    thanks !

  11. Ernesto says:

    I am using a dropdown language selector, but would like to have to this text as a default “Choose language” , and then list the languages beneath that text, is this possible to achieve? how?

  12. Billyben says:

    Hello, Your plugin works perfectly! Really Great Job!

    But now, I’m trying to have something like icl_get_languages for a specific post Id. Indeed, I’m trying to add flags for post in the index.php, but icl_get_languages returns an array corresponding to that page. Is there a way to get the same info for each post in the main loop?

    Thanks

    Billyben

    • Billyben says:

      Ok, sorry, I’ve found my solution quite as soon as I’ve posted….

      Combination of get_the_ID(), icl_get_languages, icl_object_id, and get_permalink…

  13. Radek says:

    Hi Amir,

    Is there any simple way how to create a custom lang switcher which would just display the country codes in upper case like this. CZ | EN | DE | PL ? This would be present on any site no matter whether there is a translation or not.

    Thanks a lot Radek

  14. leonor says:

    Please help me I have copy pasted but It dose nothing to my page! What am I doing wrong?

    This is my header.php:

  15. Nokao says:

    Hi.

    I need (like I was doing in the past with my edited version of language switcher) to switch the language flag images URL from the plugin directory to the theme directory.

    So I wonder if other than $l['country_flag_url'] is there something like $l['country_flag_code']
    So I can do a blog_info(‘template_url’).$l['country_flag_code']

    Why?
    This because I use various websites in only one installation of wordpress, thanks to a wp-config database hack.

    So I only change templates, and not plugins.
    And some of the websites needs to have customized flags.

    Can you help me to do so?

    • amir says:

      Why don’t you post about this in our technical forum?
      http://forum.wpml.org

      • Nokao says:

        Actually because it seems to be a post-sale service.

        I still did not buy the plugin,
        but honestly I don’t want to get polemic here,
        because I like this plugin so much,
        and i’ll buy it as soon as I can.

        I used language switcher for two years,
        now it seems the time for a change.

  16. bernhard says:

    where do i find the css for the language switcher style. i want the list of languages dispalyed next to each other, aligned on the right of the page without the border.

    many thanks. bernhard

  17. shamrai says:

    How can i decrease the width of list language swticher

  18. Rym says:

    How can I publish language switcher for category page?

  19. Edgars says:

    function icl_get_languages uses data from table ‘wp_icl_languages’, right?
    I changed ID’s of languages (and deleted unused) so I can get particular order of languages, but then by using icl_get_languages(‘orderby=id’) I get old order

    or is it a MySQl bug?

    • amir says:

      I’m not really sure that’s doing that. It would require debug on your DB.

      I suggest that you locate the code that does the SQL query and output it. Then, see if the query matches what gets back from the DB.

  20. Nik says:

    I’ve purchased the WPML plugin to make my site multilingual. But I have a small problem :

    The WPML plugin has the option to insert the language selector in the footer as well as in any sidebar or page template column. But it has also the following option :
    “The drop-down language switcher can be added to your theme by inserting this PHP code: or as a widget.”

    My question is : where must I insert this drop-down language switcher in the theme so it will be displayed next to search field ? As a widget or by hardcoding (which is not by strongest point). Any suggestions or a heads up ?
    Do I have to make additions in the header file (by coding) as well as in the css style sheet file or is there something that can be done from the plugin options panel ?
    By the way the project I’m working is based on the ThemeForest PureVision template, if that helps

    Please help out, I’m on a dead end.
    Thanks in advance,

    Nik

    • amir says:

      Can you repost this in our forum? It’s a much better place for technical discussion. Please explain about your theme. In order to tell you where to add code to your theme, we need to know it.

  21. Flavio says:

    Ref above. Language selector with flags only

    Would you be so kind to specify which is the file where I should copy and paste the function language_selector_flags() ?

    Thanks!

  22. Janek says:

    Well, I figured out, hout to put the language selector with flags only. I used the
    code to accomplish that.

    But now the languages are in the wrong order. Right now they are in English, Estonina, Finnish, but i woult like them to be Estonina, English, Finnish.

    Is there a way to chane it? I cruised around the forum, but did not find any reasonable solution? And also, it shpult be implemented in WPML dasbhoard as a default option.

    Thanks in advance

  23. neo says:

    Hi, I have two langs, english and french, I’m displaying them correctly with this switcher, but I’m not able to get just the available translation li and hide the currently shown language.
    For example, if my website is now is english, I want to show just “french”, when my page gets french I want it to show “english”.
    Any idea? Thanks!

    • amir says:

      This is exactly the kind of stuff that you can do with a custom language switcher. I suggest that you start a new thread in our forum, paste the code that you have now and we’ll help you get it right.

  24. mic says:

    How can I just show the available translations flags except the current translated language in the website?

    for example, my website is in english, and shows flags english, french, italian
    I just want to show french and italian flag

    which is the parameter for this exception? thanks.

  25. pablo says:

    is there any way to make that lenguage selector dont show the link of the current lenguage of the page im viewing?

Leave a Reply

Please leave here comments about this page only.
For technical support and feature suggestions, head to our forum. We are waiting there!

You can use these tags:
<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>