Enabling Plugin Internationalization

Exclusive offer: get 50% off this eBook here
WordPress Plugin Development Cookbook

WordPress Plugin Development Cookbook — Save 50%

Over 80 step-by-step recipes to extend the most popular CMS and share your creations with its community with this book and ebook.

$26.99    $13.50
by Yannick Lefebvre | August 2012 | WordPress

Enabling Plugin Internationalization, prepares your plugin to be translated to any language to make it easier to be used by non-English speakers.

WordPress is a worldwide phenomenon, with users embracing the platform all around the globe. To create a more specific experience for users in different locales, WordPress offers the ability to translate all of its user and visitor-facing content, resulting in numerous localizations becoming available for download online.

In this article by Yannick Lefebvre, the author of WordPress Plugin Development Cookbook, we will learn about plugin localization through the following topics:

  • Changing the WordPress language configuration
  • Adapting default user settings for translation
  • Making admin page code ready for translation
  • Modifying shortcode output for translation
  • Translating text strings using Poedit
  • Loading a language file in the plugin initialization

 

Introduction

WordPress is a worldwide phenomenon, with users embracing the platform all around the globe. To create a more specific experience for users in different locales, WordPress offers the ability to translate all of its user and visitor-facing content, resulting in numerous localizations becoming available for download online. Like most other functionalities in the platform, internationalization is also available to plugin developers through a set of easy-to-use functions. The main difference being that plugin translations are typically included with the extension, instead of being downloaded separately as is the case with WordPress.

To prepare their plugin to be localized, developers must use special internationalization functions when dealing with text elements. Once this structure is in place, any user can create localizations by themselves for languages that they know and submit them back to the plugin author for inclusion in a future update to the extension.

This article explains how to prepare a plugin to be translated and shows how to use the Poedit tool to create a new language file for a simple plugin.

Changing the WordPress language configuration

The first step to translating a plugin is to configure WordPress to a different language setting other than English. This will automatically trigger mechanisms in the platform to look for alternate language content for any internationalized string.

In this recipe we will set the site to French.

Getting ready

You should have access to a WordPress development environment.

How to do it...

  1. Navigate to the root of your WordPress installation.
  2. Open the file called wp-config.php in a code editor.
  3. Change the line that declares the site language from define('WPLANG', ''); to define('WPLANG', 'fr_FR');.
  4. Save and close the configuration file.

How it works...

Whenever WordPress renders a page for visitors or site administrators, it executes the contents of the wp-config.php file, which declares a number of site-wide constants. One of these constants is the site language. By default, this constant has no value, indicating that WordPress should display all content in U.S. English. If defined, the system tries to find a translation file under the wp-content/languages or wp-includes/languages directories of the site to locate translation strings for the target language. In this case, it will try to find a file called fr_FR.mo. While it will not actually find this file in a default installation, setting this configuration option will facilitate the creation and testing of a plugin translation file in later recipes.

To learn more about translation files and find out where to download them from, visit the WordPress Codex available at http://codex.wordpress.org/WordPress_in_ Your_Language.

Adapting default user settings for translation

As mentioned in the introduction, plugin code needs to be specifically written to allow text items to be translated. This work starts in the plugin's activation routine, where default plugin option values are set, to find alternate values when a language other than English is specified in the site's configuration file.

This recipe shows how to assign a translated string to a plugin's default options array on initialization.

Getting ready

You should have already followed the Changing the WordPress language configuration recipe to have a specified translation language for the site.

How to do it...

  1. Navigate to the WordPress plugin directory of your development installation.
  2. Create a new directory called hello-world.
  3. Navigate to the directory and create a text file called hello-world.php.
  4. Open the new file in a code editor and add an appropriate header at the top of the plugin file, naming the plugin Hello World.
  5. Add the following line of code before the plugin's closing ?> PHP command to register a function to be called when the plugin is activated:
  6. register_activation_hook( __FILE__,
    'hw_set_default_options_array' );

  7. Insert the following block of code to provide an implementation for the hw_set_default_options_array function:
  8. function hw_set_default_options_array() {
        if ( false === get_option( 'hw_options' ) ) {
            $new_options = array();
            $new_options['default_text'] =
                __( 'Hello World', 'hw_hello_world' );

            add_option( 'hw_options', $new_options );
        }
    }

  9. Save and close the plugin file.
  10. Navigate to the Plugins management page and activate the Hello World plugin.
  11. Using phpMyAdmin or the NetBeans IDE, find the options table entry where the option_name field has a value of hw_options to see the newly-created option.

How it works...

The __ function (that's two underscores) is a WordPress utility function that tries to find a translation for the text that it receives in its first argument, within the text domain specified in the second argument. A text domain is essentially a subsection of the global translation table that is managed by WordPress. In this example, the text to be translated is the string Hello World, for which the system tries to find a translation in the hw_hello_world domain. Since this domain is not available at this time, the function returns the original string that it received as its first parameter. The plugin code assigns the value it receives to the default configuration array.

It should be noted that the __ function is actually an alias for the translate function. While both functions have the same functionality, using __ makes the code shorter when it contains a lot of text elements to be translated.

While it may be tempting for developers to use a variable or constant in the first parameter of the __ function if they need to display the same text multiple times, this should not be done as it will cause problems with the translation lookup mechanism.

See also

  • Changing the WordPress language configuration recipe
WordPress Plugin Development Cookbook Over 80 step-by-step recipes to extend the most popular CMS and share your creations with its community with this book and ebook.
Published: July 2012
eBook Price: $26.99
Book Price: $44.99
See more
Select your format and quantity:

(For more resources on Wordpress, see here.)

Making admin page code ready for translation

While the previous recipe showed how to look up the translation of a text item and return its value for further processing in the plugin code, there are many instances where it is more practical to display the translated content immediately.

This recipe shows how to translate the contents of a simple administration page for immediate display.

Getting ready

You should have already followed the Adapting default user settings for translation recipe to have a starting point for this recipe. Before starting, check that the name of the file is hello-world.php.

How to do it...

  1. Navigate to the hello-world folder of the WordPress plugin directory of your development installation.
  2. Open the hello-world.php file in a text editor.
  3. Add the following line of code at the end of the file to register a function to be called when WordPress is building the administration pages menu:
  4. add_action( 'admin_menu', 'ch10hw_settings_menu' );

  5. Add the following code section to provide an implementation for the hw_settings_menu function:
  6. function ch10hw_settings_menu() {
        add_options_page(
            __( 'Hello World Configuration', 'ch10hw_hello_world' ),
            __( 'Hello World', 'ch10hw_hello_world' ),
           'manage_options',
           'ch10hw-hello-world', 'ch10hw_config_page' );
    }

  7. Insert the following block of code to create the hw_config_page function, declared in the call to add_options_page:
  8. function hw_config_page() {
        $options = get_option( 'hw_options' );
        ?>

        <div id="hw-general" class="wrap">
        <!-- Echo translation for "Hello World" to the browser -->
        <h2><?php _e( 'Hello World', 'hw_hello_world' ); ?></h2>

        <form method="post" action="admin-post.php">
     
        <input type="hidden" name="action"
               value="save_hw_options" />

        <?php wp_nonce_field( 'hw' ); ?>
        <!-- Echo translation for "Hello World" to the browser -->
        <?php _e( 'Default Text', 'hw_hello_world' ); ?>:
        <input type="text" name="default_text"
               value="<?php echo esc_html( $options['default_text']
        ); ?>"/>
        <br />

        <input type="submit" value="<?php _e( 'Submit',
            'hw_hello_world' ); ?>" class="button-primary"/>
        </form>
        </div>
    <?php }

  9. Add the following line of code to register a function to be executed when the administration panel is being prepared to be displayed:
  10. add_action( 'admin_init', 'hw_admin_init' );

  11. Append the following code segment to provide an implementation for the hw_admin_init function:
  12. function hw_admin_init() {
         add_action( 'admin_post_save_hw_options',
                     'process_hw_options' );
    }

  13. Provide code for the process_hw_options function, declared in the previous step, by inserting the following code:
  14. function process_ch10hw_options() {
        if ( !current_user_can( 'manage_options' ) )
             wp_die( 'Not allowed' );

        check_admin_referer( 'ch10hw' );

        $options = get_option( 'ch10hw_options' );

        $options['default_text'] = $_POST['default_text'];

        update_option( 'ch10hw_options', $options );
        wp_redirect( add_query_arg( 'page', 'ch10hw-hello-world',
                               admin_url( 'options-general.php' ) ) );
        exit;
    }

  15. Save and close the plugin file.
  16. Navigate to the administration page of your development WordPress installation.
  17. Click on the Settings section in the left-hand navigation menu to expand it. You will see a new menu item called Hello World in the tree. Selecting the new entry displays the plugin's simple configuration form, as shown in the following screenshot:

How it works...

This recipe makes use of the __ function, covered in the previous recipe, along with the _e function. This second function's purpose is similar to __, except that it immediately echoes the outcome of the translation lookup to the browser. It should be used for all text elements that would previously have just been simple text in HTML code. Of course, making a call to this function requires the presence of standard opening and closing PHP tags (<? and ?>) to be executed amongst the surrounding HTML.

The rest of this plugin's code takes care of storing user updates to the site database.

See also

  • Adapting default user settings for translation recipe

Modifying shortcode output for translation

Shortcodes are powerful tools that provide an easy way for users to add content to their site posts and pages. Since this content is presented to users, it can benefit from a translation just as much as the site's administration pages.

This recipe shows how to translate shortcode output before it is displayed. It also explains how to deal with variable data elements that can be positioned differently between languages.

Getting ready

You should have already followed the Making admin page code ready for translation recipe entitled to have a starting point for this recipe. Before starting, check that the name of the file is hello-world.php.

How to do it...

  1. Navigate to the hello-world folder of the WordPress plugin directory of your development installation.
  2. Open the hello-world.php file in a text editor.
  3. Add the following line of code at the end of the file to declare a new shortcode that will be available to content authors:
  4. add_shortcode( 'hello-world', 'hw_hello_world_shortcode' );

  5. Add the following code section to provide an implementation for the hw_hello_world_shortcode function:
  6. function ch10hw_hello_world_shortcode() {
        $options = get_option( 'ch10hw_options' );
        $output = sprintf( __( 'The current text string is: %s.',
                               'ch10hw_hello_world' ),
                               $options['default_text'] );
    return $output;
    }

  7. Save and close the plugin file.
  8. Create a new page and insert the new shortcode [hello-world] in the content.
  9. View the page to see the output of the shortcode.

How it works...

This recipe shows something that's a bit more complex than the previous two, as we want the shortcode output to be a combination of static text with a dynamic element, and we want that element to appear in different places based on the grammatical structure of the target language. The way to achieve this functionality is to combine the __ internationalization function with the sprintf standard PHP function.

The purpose of the sprintf function is to insert a variable in a string. It performs this task by looking for a placeholder in the target string sent in the first argument, and replaces it with the variable that it receives as its second argument. Some examples of placeholders are %s for a string and %d for an integer. With this functionality in mind, we use a placeholder as part of the string to be translated so that users who create localization files can choose where the value will be placed as part of the sentence structure. Once the translation has been obtained by the __ function, we can immediately send the alternate language string to sprintf to create the final text.

See also

  • Adapting default user settings for translation recipe
WordPress Plugin Development Cookbook Over 80 step-by-step recipes to extend the most popular CMS and share your creations with its community with this book and ebook.
Published: July 2012
eBook Price: $26.99
Book Price: $44.99
See more
Select your format and quantity:

(For more resources on Wordpress, see here.)

Translating text strings using Poedit

After inserting all the necessary code to look up translations for text elements, we need to create the actual translation files. While there are multiple tools available to perform this task, we will focus our efforts around the most popular one, the free multi-platform Poedit.

This recipe shows how to extract all strings to be translated from the plugin's code using Poedit, translate them, and save the resulting language file under the plugin directory.

Getting ready

You should have already followed the Modifying shortcode output for translation recipe to have a starting point for this recipe.Once again, check that the name of your file is hello-world.php.

How to do it...

  1. Navigate to the hello-world folder of the WordPress plugin directory of your development installation.
  2. Create a new subdirectory named languages.
  3. Navigate to the Poedit download page and download the appropriate version of the tool for your computer (http://www.poedit.net/download.php).
  4. Install and start the Poedit application.
  5. Select the New Catalog... item under the application's File menu.
  6. Set the Project name and version field to Hello World under the Project Info tab.
  7. Switch to the Paths tab.
  8. Create a new entry in the Paths list by pressing the New item button.
  9. Set the value of the new path entry to .. (two period characters).
  10. Switch to the Keywords tab.
  11. Select and delete the gettext and gettext_noop entries in the Keywords list.
  12. Select the remaining entry (_), click on the Edit item button, then change its value to __ (two underscores instead of a single one).
  13. Click on the Add Item button and create a second entry with a value of _e.
  14. Click on the OK button to close the Settings dialog.
  15. In the Save As... dialog that automatically comes up, navigate to the newly-created languages folder under the plugin's directory and set the target filename to hw_hello_world-fr_FR.po.
  16. Click on OK in the Update summary dialog to acknowledge that five new strings were found in the plugin's source code.
  17. Select the items one by one in order to display them in the lower section of the window.
  18. Enter a translation for each text element in the lower dialog box. The following screenshot shows the translations of each item to French:
  19. Save the translation file once completed.

How it works...

The Poedit tool searches through PHP files, looking for functions that have specific names, as specified in the Keywords configuration section. It looks through all files located in the same directory as the catalog itself and in any additional folders specified under the Paths section of the catalog settings. By specifying .. as an additional path, we tell Poedit to look one directory up from the languages folder, where the plugin files are located.

Based on the configuration that we specified, Poedit is able to find all instances of the __ and _e functions in the plugin code and retrieve the text strings that are set as the first argument to these functions. Once all strings have been found, Poedit provides a simple interface to provide translations for each string and save the resulting translation file. Upon saving, Poedit actually creates two files. The first, with a .po extension, is a simple text file that contains a flat textual version of the original strings and the localized versions of each item. The second, sporting a .mo extension, is a file that is optimized for quick access on the web server.

The name of the language files is made from two parts: the name of the text domain, hw_hello_world, which was used in all of our calls to the __ and _e functions in the previous recipes, and the target language code, fr_FR, to match the language configuration that we set earlier in this article.

There's more...

If you are only comfortable with English, create a template file that users will be able to import to start their translation.

Translation template file

When you are only familiar with English, you can create a translation template that only contains the text to be translated by saving the catalog as a .pot file, instead of a .po/.mo combination. In addition to the special extension, the filename should not contain a language tag (for example, hw_hello_world.pot).

See also

  • Adapting default user settings for translation recipe

Loading a language file in the plugin initialization

The final step to plugin translation is to put the code in place to load a translation file. This is done by registering an action hook callback and calling a single function when it gets executed.

This recipe shows how to load the translation file created in the previous recipe.

Getting ready

You should have already followed the Making admin page code ready for translation and Translating text strings using Poedit recipes to have the proper files required for this recipe. The file name should be hello-world.php and copy the languages folder to the right location before starting.

How to do it...

  1. Navigate to the hello-world folder of the WordPress plugin directory of your development installation.
  2. Open the hello-world.php file in a text editor.
  3. Add the following line of code at the end of the file to register a function to be called when the plugin is initialized:
  4. add_action( 'init', 'ch10hw_plugin_init' );

  5. Add the following code section to provide an implementation for the hw_plugin_init function:
  6. function ch10hw_plugin_init() {
        load_plugin_textdomain( 'ch10hw_hello_world',
                                false,
                                dirname( plugin_basename( __FILE__ ) )
                                .'/languages' );
    }

  7. Save and close the plugin file.
  8. Navigate to the Settings menu to see if the plugin's menu item has changed.
  9. Select the Bonjour Monde item to see the translated configuration page.

How it works...

The load_plugin_textdomain function has three arguments. When called, it looks in the folder specified in the last parameter for a .mo file with a name starting with the text domain specified in the first parameter, followed by the current language set in the WordPress configuration file. If found, the translation file is loaded in memory and is used to search for translations every time the __ or _e functions are encountered during execution. The middle argument, set to a false value, is obsolete but is still needed for backward compatibility.

Once all hooks are in place in the plugin code, and a first translation file (or template) is made available with the plugin, users can easily modify text elements to other languages, which they can use immediately. They can also provide these new translations back to the plugin author for inclusion in future updates.

There's more...

As a plugin evolves over time, new text items may need to be translated. There may also be a need to use more advanced translation functions and translate JavaScript code.

Updating a translation file

When new calls to the __ or _e functions are made in a plugin, the translation file needs to be updated to take new text elements into account. To do this, start the Poedit tool and open the existing catalog. Then, select the Update from sources item under the Catalog menu. This will extract all text items and identify new entries. Once this is done, new items can be translated and saved back to the catalog file.

Advanced translation functions

While we used the most common internationalization functions in this article, there are a few more advanced functions that may be useful in your efforts:

  • _n( $singular, $plural, $number, $domain ): This function will look up one of the first two strings received, depending on whether the number is one or more.
  • ff _x( $text, $context, $domain ): Adds a parameter to the localization lookup to add a context parameter. This is useful when dealing with words that have the same spelling but different meanings.
  • ff _ex( $text, $context, $domain ): Same as _x but echoes the result of the lookup.
  • ff _nx( $singular, $plural, $number, $context, $domain ): Same as _n with the additional context parameter from _x.

There are also a number of functions that will perform a localization lookup immediately followed by the escape of the resulting string. These functions include esc_attr__(), esc_attr_e(), esc_html__(), esc_html_x(), and many more. For a full list of internationalization functions, visit http://codex.wordpress.org/L10n.

Localizing JavaScript files

JavaScript files are a bit more tricky to translate as they are often read from an external file that cannot contain any PHP code. The solution to this is the wp_localize_script function. When called, this function declares new variables in scripts that have already been queued up to be loaded and populates these variables with localized strings. Upon execution, the code will be able to access and display the proper text on-screen. The following code snippet is an example showing how to use the function:

wp_enqueue_script( 'script_handle' );
$translation_vars = array( 'string_val' =>
                           __( 'Text to be translated' ) );
wp_localize_script( 'script_handle', 'javascript_object',
                    $translation_vars );

In the previous code example , a new object called javascript_object will be created inside the script_handle script, with a data member called string_val that contains a translation of the target text in the current WordPress language, if available.

See also

  • Translating text strings using Poedit recipe

Resources for Article :



Further resources on this subject:


Books From Packt


WordPress 3 Complete
WordPress 3 Complete

WordPress 2.9 E-Commerce
WordPress 2.9 E-Commerce

WordPress 3.0 jQuery
WordPress 3.0 jQuery

Social Media for Wordpress: Build Communities, Engage Members and Promote Your Site
Social Media for Wordpress: Build Communities, Engage Members and Promote Your Site

 Internet Marketing with WordPress
Internet Marketing with WordPress

WordPress Plugin Development: Beginner's Guide
WordPress Plugin Development: Beginner's Guide

WordPress for Education
WordPress for Education

WordPress Mobile Web Development: Beginner's Guide
WordPress Mobile Web Development: Beginner's Guide


No votes yet

Post new comment

CAPTCHA
This question is for testing whether you are a human visitor and to prevent automated spam submissions.
B
T
A
x
F
n
Enter the code without spaces and pay attention to upper/lower case.
Code Download and Errata
Packt Anytime, Anywhere
Register Books
Print Upgrades
eBook Downloads
Video Support
Contact Us
Awards Voting Nominations Previous Winners
Judges Open Source CMS Hall Of Fame CMS Most Promising Open Source Project Open Source E-Commerce Applications Open Source JavaScript Library Open Source Graphics Software
Resources
Open Source CMS Hall Of Fame CMS Most Promising Open Source Project Open Source E-Commerce Applications Open Source JavaScript Library Open Source Graphics Software