Internationalisation
This page explains how to make your code ready for translators to create translation files in their language. If you need to learn the basics on translating, also check languages guide.
i18n?
i18n
is a abbreviation for internationalization, or the process of making code ready for translation. It is called "i18n" because there are 18 letters between the i and the n. In our YOURLS case, it means marking strings which should be translated in a special way.
Hardcoded vs Translatable
The regular way of echoing or returning strings, in PHP, would be for instance:
echo "This is a message.";
return "another string";
In this example, the strings are hardcoded so you can't change them unless you edit the PHP file. Not very practical.
YOURLS uses a set of functions to indicate that strings should be translated if a translation file is available.
Marking strings for translation
The principle is the following:
yourls_i18n_function( $string, $textdomain )
where
yourls_i18n_function
will be one i18n functions, see below$string
is the string to translate$textdomain
is a unique identifier, the "text domain", you'll use across your project. Make sure it is a unique name, based on your plugin name for instance.
The above example would become:
// echo a string
yourls_e( 'This is a message', 'john-plugin' );
// return a string
$message = yourls__( 'another string', 'john-plugin' );
This will make 2 things happen:
- i18n functions return translated string if a translation file is found, or the original string otherwise.
- these functions also mark the strings as translatable: a utility like Poedit (see below) can generate a PO or POT file with these strings, so that translators can make their translation file.
Loading your text domain
Pick a unique name, preferably related to the project name. For instance if you're coding a plugin named Funny Redirection
, the domain could be funny-redirection
.
Your code must have the following function call:
yourls_load_custom_textdomain( $domain, $path_to_translation_files );
For instance in your plugin that would be:
// Trigger when all plugins are loaded
yourls_add_action( 'plugins_loaded', 'funny_redirection_load_textdomain' );
// load custom text domain
function funny_redirection_load_textdomain() {
yourls_load_custom_textdomain( 'funny-redirection', dirname( __FILE__ ) . '/translations' );
}
This would tell YOURLS to look for translation files inside the translations
directory of your plugin folder.
The translation filenames must follow the following format: domain dash locale
, eg funny_redirection-pt_BR.mo
i18n functions
YOURLS i18n functions are located in includes/functions-i18n.php
. The main functions are:
-
yourls__( $string, $domain )
Return a translated string -
yourls_e( $string, $domain )
Echo a translated string -
yourls_n( $single, $plural, $number, $domain )
Return the plural or single form based on the amount. Example:$msg = yourls_n( '1 tooth', '%s teeth', $number, 'funny-redirection' );
Escaping functions:
-
yourls_esc_html__( $string, $domain )
Retrieves the translation of $string and escapes it for safe use in HTML output -
yourls_esc_attr__( $string, $domain )
Return a translated string, escaped for a use in an attribute (liketitle=""
)
There are also the corresponding xxxx_e()
function to echo instead of return.
There are more complex functions you probably won't need for basic stuff, but reading the source of includes/functions-i18n.php
will make your day a whole lot brighter anyway 😊
Placeholders
Translatable strings cannot contain dynamic content. For instance,
- while this will work:
echo "We have $count short URL";
- this won't:
yourls_e( "We have $count short URL", "myplugin" );
During the parsing of your code to generate PO files, the PO generator will mark "We have $count short URL"
as translatable. However in the application yourls_e()
will be called with an argument like "We have 1337 short URL"
: YOURLS won't find a suitable translation of this string and will return it untranslated.
The solution is to use functions printf()
(to echo) and sprintf()
(to return).
Here is what the right solution of the short URL count problem will look like:
printf( yourls__( "We have %s short URL", "myplugin" ), $count );
Generate a POT file
Once all your code is ready for translation, generate a POT file. You'll need to configure your software (eg PoEdit) with these strings, which are the i18n functions used in YOURLS:
yourls__
yourls_e
yourls_s
yourls_se
yourls_esc_attr__
yourls_esc_html__
yourls_x
yourls_ex
yourls_esc_attr_x
yourls_esc_html_x
yourls_n:1,2
yourls_nx:1,2
yourls_n_noop:1,2
yourls_nx_noop:1,2
Configure also the parser to include comments for translators. In PoEdit: File, Preferences, Parsers, PHP: edit and in the Parser command
add parameter --add-comments=/
You'll find plenty of guides on the net to show you how to use PoEdit. Also check the official YOURLS.pot
Get a few translators to work
Your work is now ready to be translated. Ask a few Japanese / Brazilian / Czech friends to create translation files, and ship your code with all these translation files 😊