DRAFT: This page is still a draft and being actively written. If you find an error, please comment below.

WordPress developers chose to use the GNU gettext localization framework to provide localization infrastructure to WordPress. gettext is a mature, widely-used framework for modular translation of software, and is the de facto standard for localization in the open source/free software realm.

gettext uses message-level translation – that is, every “message” displayed to users is translated individually, whether it be a paragraph or a single word. In WordPress, such “messages” are generated, translated, and used by the WordPress PHP files via two PHP functions. __() is used when the message is passed as an argument to another function; _e() is used to write the message directly to the page. More detail on these two functions:

__(‘message’)

Searches the localization module for the translation of ‘message’, and passes the translation to the PHP return statement. If no translation is found for ‘message’, it just returns ‘message’.

_e(‘message’)

Searches the localization module for the translation of ‘message’, and passes the translation to the PHP echo statement. If no translation is found for ‘message’, it just echoes ‘message’.

<?php $translated_text = __( $text, $domain ); ?>

The gettext framework takes care of most of WordPress. However, there are a few places in the WordPress distribution where gettext cannot be used – see Files For Direct Translation for more information on how to translate these spots.

Getting Started #

[needs a write up here; something about how you don't *need* to use gettext, and can use Rosetta]

  1. Download the official WordPress POT file
  2. Open the file in your favorite text editor
  3. Update the header information
  4. Translate the messages
  5. Save the file with a .po file extension
  6. Issue msgfmt -o filename.mo filename.po

Top ↑

The PO File Header #

At the beginning of the PO file is something called the header. This gives information about what package and version the translation is for, who the translator was, and when it was created. Certain portions of this header should be universal for all WordPress translations:

# LANGUAGE (LOCALE) translation for WordPress.
# Copyright (C) YEAR WordPress contributors.
# This file is distributed under the same license as the WordPress package.
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
#
#, fuzzy
msgid ""
msgstr ""
"Project-Id-Version: WordPress VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2005-02-27 17:11-0600\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=CHARSET\n"
"Content-Transfer-Encoding: 8bit\n"

Fill in the rest of the capitalized text with the appropriate values.

Top ↑

Message Format #

The remainder of the file will be in a format as follows:

#: wp-comments-post.php:13
msgid "Sorry, comments are closed for this item."
msgstr ""

#: wp-comments-post.php:29
msgid "Sorry, you must be logged in to post a comment."
msgstr ""

#: wp-comments-post.php:35
msgid "Error: please fill the required fields (name, email)."
msgstr ""

The first line of each message contains the location of the message in the WordPress code. In the case of these messages, they’re all located in wp-comments-post.php, on lines 13, 29, and 35, respectively. Occasionally you will come across a message for which you will need to check its context; look at the appropriate line or lines in the WordPress core, and you should be able to figure out when and where the message is displayed, and even reproduce it yourself using your web browser. Some messages will also appear with the same text in multiple locations; in that case, there may be more than one line giving a file and line location.

The next line, msgid, is the source message. This is the string that WordPress passes to its __() or _e() functions, and the message you will need to translate.

The final line, msgstr, is a blank string where you will fill in your translation.

Here’s how the same few lines would look after being translated, using the French (France) locale as an example:

#: wp-comments-post.php:13
msgid "Sorry, comments are closed for this item."
msgstr "L'ajout de commentaire n'est pas ou plus possible pour cet article."

#: wp-comments-post.php:29
msgid "Sorry, you must be logged in to post a comment."
msgstr "Vous devez être connecté pour rédiger un commentaire."

#: wp-comments-post.php:35
msgid "Error: please fill the required fields (name, email)."
msgstr "Erreur : veuillez remplir les champs obligatoires vides (nom, e-mail)."