Internationalizing a ClassicPress plugin: Localizing a string including notes for the translator

ClassicPress PluginsThis post is part of the sub-series on Internationalizing a ClassicPress plugin which is part of the Internationalizing a ClassicPress plugin series.

The esc_html_x function is very similar to the esc_html__ one, but has the addition of a comment section where context for the translator can be supplied. This is sometimes beneficial to use as the English language has words and phrases which can have different meanings dependent on context.

For example, the word minute:

$str = esc_html_x('Minute', 'measure of time', 'plugin-text-domain');
$str = esc_html_x('Minute', 'extremely small', 'plugin-text-domain');

Translating a ClassicPress plugin

Internationalizing a ClassicPress plugin
How does internationalization work?
What is a Text Domain and how is it specified?
Localization functions
Which localization functions to use?
Localizing a string
Don't paramaterize your text domain
Localizing a string containing a parameter
Localizing a string including plurals
Localizing a string including notes for the translator

Internationalizing a ClassicPress plugin: Localizing a string including plurals

ClassicPress PluginsThis post is part of the sub-series on Internationalizing a ClassicPress plugin which is part of the Internationalizing a ClassicPress plugin series.

As well as translating strings, and strings with parameters, you can also translate strings which include plurals. For example, you might have a counts of comments which would vary between 1 comment and 2 comments. This can be handled using the _n function.

There is no equivalent of esc_html__ for the plurals function, so you will need to wrap the _n function call with esc_html__ or esc_html_e:

esc_html_e(sprintf(
    _n(
        '%s comment',
        '%s comments',
        get_comments_number(),
        'plugin-text-domain'
    ),
    number_format_i18n(get_comments_number())
)
);

The _n() function accepts four arguments:

  1. single – the text to be used if the number is singular..
  2. plural – the text to be used if the number is plural.
  3. count – number to compare against to use either the singular or plural form.
  4. text domain – the plugin text domain.

The function returns the correct translated string for the supplied count.

Translating a ClassicPress plugin

Internationalizing a ClassicPress plugin
How does internationalization work?
What is a Text Domain and how is it specified?
Localization functions
Which localization functions to use?
Localizing a string
Don't paramaterize your text domain
Localizing a string containing a parameter
Localizing a string including plurals
Localizing a string including notes for the translator

Internationalizing a ClassicPress plugin: Localizing a string containing a parameter

ClassicPress PluginsThis post is part of the sub-series on Internationalizing a ClassicPress plugin which is part of the Internationalizing a ClassicPress plugin series.

If you have a string containing a parameter, say for example someone making a statement about the number of lights, you can combine your esc_html__ function with sprintf to switch out a placeholder with the number in a variable:

$str = sprintf(esc_html__('There are %d lights.', 'plugin-text-domain'), $number);

The %d will be contained in the string which can be translated; this is necessary as some languages may place the number in a different place of the sentence if it has a different sentence structure.

Translating a ClassicPress plugin

Internationalizing a ClassicPress plugin
How does internationalization work?
What is a Text Domain and how is it specified?
Localization functions
Which localization functions to use?
Localizing a string
Don't paramaterize your text domain
Localizing a string containing a parameter
Localizing a string including plurals
Localizing a string including notes for the translator

Internationalizing a ClassicPress plugin: Don’t paramaterize your text domain

ClassicPress PluginsThis post is part of the sub-series on Internationalizing a ClassicPress plugin which is part of the Internationalizing a ClassicPress plugin series.

A plugin can have a lot of strings to translate; the larger the plugin the more translations there are likely to be. It is quite common for developers to look for ways to reduce typing the same parameter every time through the use of variables or constants, but this must be resisted when it comes to setting the text domain parameter of the localization functions.

The reason for this is that it is not just the PHP of the plugin which needs to parse the translatable strings, but also the gettext libraries which are used to produce the POT templates, used by translators.

gettext is not a PHP parser, so it is unable to read variables or constants; it can only read the strings.

Translating a ClassicPress plugin

Internationalizing a ClassicPress plugin
How does internationalization work?
What is a Text Domain and how is it specified?
Localization functions
Which localization functions to use?
Localizing a string
Don't paramaterize your text domain
Localizing a string containing a parameter
Localizing a string including plurals
Localizing a string including notes for the translator

Internationalizing a ClassicPress plugin: Localizing a string

ClassicPress PluginsThis post is part of the sub-series on Internationalizing a ClassicPress plugin which is part of the Internationalizing a ClassicPress plugin series.

Over the previous posts I’ve discussed adding text domains and which functions are available to use, it’s time to look at a practical application.

To return a translated string we’d use the esc_html__ function with the string which can be localized as the first parameter and the text domain as the second:

$str = esc_html__('This is the string to translate', 'plugin-text-domain');

If we wanted to echo the translated string rather than return it, we’d use the esc_html_e function:

esc_html_e('This is the string to translate', 'plugin-text-domain');

Translating a ClassicPress plugin

Internationalizing a ClassicPress plugin
How does internationalization work?
What is a Text Domain and how is it specified?
Localization functions
Which localization functions to use?
Localizing a string
Don't paramaterize your text domain
Localizing a string containing a parameter
Localizing a string including plurals
Localizing a string including notes for the translator

Internationalizing a ClassicPress plugin: Which localization functions to use?

ClassicPress PluginsThis post is part of the sub-series on Internationalizing a ClassicPress plugin which is part of the Internationalizing a ClassicPress plugin series.

In the previous post, of this series, I explained what functions were available for use in internationalizing a plugin, but there is something you need to consider when deciding which one to use.

With security at the forefront, it is important to remember that you cannot trust translators as you do not know who the translator will be. As you don’t know them, you can’t be sure that they won’t add something malicious to the translated string. To protect against this, you need to treat the localized strings as you would any other untrusted input: by escaping them.

So instead of using the plugins at the top of the previous post, you should be using the ones at the bottom which escape the returned or echoed strings.

Translating a ClassicPress plugin

Internationalizing a ClassicPress plugin
How does internationalization work?
What is a Text Domain and how is it specified?
Localization functions
Which localization functions to use?
Localizing a string
Don't paramaterize your text domain
Localizing a string containing a parameter
Localizing a string including plurals
Localizing a string including notes for the translator

Internationalizing a ClassicPress plugin: Localization functions

ClassicPress PluginsThis post is part of the sub-series on Internationalizing a ClassicPress plugin which is part of the Internationalizing a ClassicPress plugin series.

There is a number of functions available in ClassicPress which can be used in localising code:

  • __() – this function takes a string and returns the translation if it exists.
  • _e() – this function takes a string and echos the translation if it exists.
  • _n() – this function allows plurals to be handled. It takes 4 parameters: the single form, the plural form, the number based on which one or the other will be displayed and the text domain.
  • _x() – this function is to prevent collisions of similar words. If you plugin uses pair in the sense of a couple of people and pair in the sense of pairing a device via bluetooth as well, collisions could arise. A foreign language might well use very different words for the two.
  • _ex() – this function is the same as the above, but echos the result rather than returning it.
  • _nx() – this function is a combination of pairs and plurals.

There are also six functions which allow us to escape the value for safe usage in attributes and HTML. Considering the above functions, the names are very descriptive:

  • esc_attr__()
  • esc_attr_e()
  • esc_attr_x()
  • esc_html__()
  • esc_html_e()
  • esc_html_x()

Translating a ClassicPress plugin

Internationalizing a ClassicPress plugin
How does internationalization work?
What is a Text Domain and how is it specified?
Localization functions
Which localization functions to use?
Localizing a string
Don't paramaterize your text domain
Localizing a string containing a parameter
Localizing a string including plurals
Localizing a string including notes for the translator

Internationalizing a ClassicPress plugin: What is a Text Domain and how is it specified?

ClassicPress PluginsThis post is part of the sub-series on Internationalizing a ClassicPress plugin which is part of the Internationalizing a ClassicPress plugin series.

A text domain is a unique identifier which makes sure ClassicPress can distinguish between all loaded translations and apply the correct one.

The text domain should be a unique string, not used by any other translation (which would include plugins and themes) and so is recommended to match the plugin slug. So if you have a plugin with the slug of my-classicpress-plugin the text domain should be the same.

If the text domain matches the plugin slug, ClassicPress does not require the text domain to be defined in th plugin header (although it is very much recommended that it does i order to avoid collisions with other plugins or themes), but if the text domain is different to the plugin slug, then you need to include the following highlighted line in the header:

/*
 * Plugin Name: My ClassicPress Plugin
 * Author: Ian Grieve
 * Text Domain: my-classicpress-plugin
 */

One important point to remember, is that a text domain cannot include underscores.

Translating a ClassicPress plugin

Internationalizing a ClassicPress plugin
How does internationalization work?
What is a Text Domain and how is it specified?
Localization functions
Which localization functions to use?
Localizing a string
Don't paramaterize your text domain
Localizing a string containing a parameter
Localizing a string including plurals
Localizing a string including notes for the translator

Internationalizing a ClassicPress plugin: How does internationalization work?

ClassicPress PluginsThis post is part of the sub-series on Translating a ClassicPress plugin which is part of the Translating a ClassicPress plugin series.

ClassicPress uses the gettext libraries and tools for internationalization; gettext is an old and respectable piece of software which is widely used in the world of open-source.

The basics of how it works are:

  • Developers wrap translatable strings in special gettext functions.
  • Special tools parse the source code files and extract the translatable strings into POT (Portable Objects Template) files.
  • Translators translate the strings in the POT file and save the translations into a PO file.
  • PO files are compiled to binary MO files, which give faster access to the strings at run-time.

Over the next few posts, I’ll be stepping through what you have to do while developing an internationalized plugin to allow a POT file to be created.

Translating a ClassicPress plugin

Internationalizing a ClassicPress plugin
How does internationalization work?
What is a Text Domain and how is it specified?
Localization functions
Which localization functions to use?
Localizing a string
Don't paramaterize your text domain
Localizing a string containing a parameter
Localizing a string including plurals
Localizing a string including notes for the translator

Internationalizing a ClassicPress plugin: Series Index

ClassicPress PluginsThis series is part of a wider series on Internationalizing a ClassicPress plugin.

In the first posts on the parent series, I explained what internationalization and localization are and, in this sub-series, I am going to explain the process of internationalizing a plugin developed for ClassicPress.

Continue reading “Internationalizing a ClassicPress plugin: Series Index”