WPML Coding API and Custom Language Switcher

老是打不开这些页面,干脆复制到自己的地盘来了。方便自己也方便大家。

神马?WPML 是啥,自己百度吧!

WPML offers functions that can be used in your WordPress theme to provide correct support for multilingual themes.

Function Purpose Notes
do_action(‘icl_language_selector’) Insert the drop down language selector. Described in the language setup section of the getting started guide.
do_action(‘icl_navigation_menu’) Insert the top navigation menu. Described in the navitaionsection of the getting started guide.
do_action(‘icl_navigation_breadcrumb’) Insert the breadcrumbs trail.
do_action(‘icl_navigation_sidebar’) Insert the sidebar navigation.
icl_get_home_url() Link to the home page in the active language. Described in the home page link section of the getting started guide.
icl_get_languages(‘skip_missing=N’) Used for building custom language selectors. Described in the custom language switcher section of the getting started guide.
icl_link_to_element(ID, type, text, arguments, anchor) Used for creating language dependent links in themes. Described in the hard coded links section of the getting started guide.
icl_object_id(ID, type, return_original_if_missing, language_code) Used for calculating the IDs of objects (usually categories) in the current language. Described in the language dependent IDs section of the getting started guide.
icl_register_string(context, name, value) Registers a string for translation Described in the guide fortranslating texts in other plugins and themes.
icl_unregister_string(context, name) Removes a string from the translation table
icl_t(context, name, value) Gets the translated value of a string.

Language constants

WPML defines the following constants which can be used in the theme:

Constant Description Example
ICL_LANGUAGE_CODE Code for the current language fr
ICL_LANGUAGE_NAME Name of current language, in the current language Français
ICL_LANGUAGE_NAME_EN Name of the current language name in English French

Disabling WPML’s CSS and JS files

WPML comes with its own CSS and JS files that style its navigation and drop-down language switcher.

If you don’t need them in your theme, you can tell WPML not to load these files. Do to that, define the following constants in your theme:

Constant The file it disables
ICL_DONT_LOAD_NAVIGATION_CSS Navigation stylesheets – cms-navigation-base.css and cms-navigation.css
ICL_DONT_LOAD_LANGUAGE_SELECTOR_CSS Drop-down language selector stylesheet – language-selector.css
ICL_DONT_LOAD_LANGUAGES_JS Drop-down language selector Javascript – sitepress.js

To set these constants, define them in the theme’s functions.php file. For example:

define('ICL_DONT_LOAD_NAVIGATION_CSS', true);

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_nametranslated_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.