Related products


Polylang > Support > Guides > How to translate your WordPress theme and plugins: localization and internationalization

How to translate your WordPress theme and plugins: localization and internationalization

🎯 Objective: Learn how WordPress translation works and how to translate both static and dynamic strings in your themes and plugins using localization tools and Polylang Pro.

Understanding localization and internationalization in WordPress

WordPress uses translation files (POT, PO, and MO) to display content in different languages. These files are generated from the theme or plugin source code and loaded based on the site’s language settings.

POT vs PO vs MO translation files

1. POT File (Portable Object Template)

  • A model file containing all translatable strings from a theme or plugin
  • It’s used as the base for creating translations
  • It does not contain translations itself — only original strings

2. PO File (Portable Object)

  • A human-readable translation file
  • It contains the original strings and their corresponding translations
  • It can be edited with tools like Poedit or other translation editors

3. MO File (Machine Object)

  • A compiled, machine-readable version of the PO file
  • It is automatically generated from the PO file
  • It is used by WordPress to display translations on the front end

What Changed in WordPress 6.5?

With WordPress 6.5, performance improvements were introduced in the internationalization (i18n) system. It adds optimized internal PHP translation files for better performance.

  • WordPress now generates optimized internal PHP translation files (part of the l10n system).
  • These files allow translations to load faster, improving overall performance.
  • They are automatically generated by WordPress.
  • They do not replace existing POT, PO, or MO files.

👉 The original announcement explaining these improvements was published here.

Checking if your WordPress theme or plugin is translation-ready

If a theme or plugin is not translation-ready, its content will not be translated correctly when pages are displayed in languages other than the WordPress default language.

A WordPress theme or a plugin is considered translation-ready if all of the following conditions are met:

  • All static strings are wrapped in WordPress translation functions (such as __() or _e())
  • A text domain is properly defined and loaded
  • A POT file is provided by the theme author or can be generated 

⚠️ Warning: For themes hosted on WordPress.org, a POT file is not strictly required. If the developer follows WordPress internationalization guidelines correctly, all strings can be translated directly via translate.wordpress.org without a POT file.
However, for themes not on WordPress.org, providing a POT file is the standard way to enable localization (.po/.mo files) or to allow external translation tools like Poedit or Loco Translate to work.

Key point: POT files are optional for WP.org themes but still required for other themes/plugins to be translatable outside of WordPress.org. The theme outputs correct language attributes in its HTML markup.
Example commonly found in header.php:

    <html <?php language_attributes(); ?>>

    Theme or plugin internationalization vs theme or plugin localization

    Internationalization (i18n) prepares the theme’s or plugin’s PHP files for translation. It requires wrapping text strings in WordPress translation functions
    → You need basic programming knowledge
    → It’s usually handled by the theme or plugin author
    Localization (l10n) provides translations for a specific language. It involves creating .po and .mo files
    → It requires linguistic skills, not coding
    → Content translation can be done using tools like Poedit or Loco Translate, or translate.wordpress.org (for themes and plugins hosted on WordPress.org.)
    A theme or a plugin must be internationalized before it can be localized.

      Translating your theme or plugin’s static strings in WordPress

      Static strings are written directly in a theme’s or plugin’s PHP files (for example: labels, buttons, or headings).

      • These strings are translated using PO/MO files.
      • When the theme or plugin author provides translations, Polylang automatically loads them on the front end. No manual action is required inside Polylang for the static strings with existing translations. 

      For example: the “read more” button for a blog post will be loaded by Polylang in French, “En lire plus”. 

      Good to know

      For all themes and plugins available on WordPress.org, you can also provide or contribute translations online via translate.wordpress.org.

      Here’s how it works:

      • Translations are submitted directly on the platform.
      • Once approved, they are automatically included in theme and plugin updates.
      • When the update is installed on your site, the translations are downloaded automatically
      • Polylang loads these translations normally on your website; no additional manual action is required.

      In short: you can contribute online → translations are integrated into updates → Polylang loads them automatically.

      What to do if a translation is missing

      If the required language translation does not exist:

      • You must create it manually using a translation tool
      • Once the PO/MO files are available, Polylang will load them automatically based on the current language

      Common tools used for this purpose:

      • Loco Translate
      • Poedit

      How to translate static strings with Loco Translate

      Static strings (titles, buttons, labels written directly in theme or plugin PHP files) must be translated using standard WordPress localization files (POT / PO / MO), not the Polylang Translations table.

      Important: Make sure the language is added and active in Polylang.

      1. Install and activate Loco Translate from Plugins > Add New in your WordPress dashboard.

      2. Go to Loco Translate > Themes or Plugins in the admin menu, then click the theme you want to translate.

      Choosing the theme to translate
      Choosing the theme to translate

      3. Translations are available for three languages on our site, but not in Japanese. Click on Edit under the Japanese language to add the translation. 

      Add the Japanese translation by clicking on the Edit button
      Add the Japanese translation by clicking on the Edit button

      4. Add the translation: 

      Translate your content
      Translate your content

      5. Click Save. Loco Translate automatically generates the .po and .mo files. 

      6. Polylang will then load this translation on the front end as needed, based on the page’s current language.

      đź’ˇ Hint: For a complete step-by-step guide on translating themes and plugins with Loco Translate, see our dedicated article Loco Translate: the right complement to Polylang.

      How to translate static strings with Poedit

      Good to know:

      • Poedit works offline, unlike Loco Translate.
      • Make sure you have access to your WordPress theme files locally.
      • You must manually upload translation files when using Poedit.
      • Loco Translate works directly in the WordPress admin and does not require FTP.
      • Polylang does not create theme translations; it ensures the correct language is displayed and handles translations of dynamic options.

      1. Install Poedit on your computer (available for macOS, Windows, and Linux).

      2. Open Poedit and click Create New.

      Create a new translation
      Create a new translation

      3. Open your theme’s or plugin’s .pot file (usually located in the languages file of your theme or plugin).

      Open the .pot file
      Open the .pot file

      4. Specify the language of the translation (e.g, Japanese) and translate each source string in the Translation field. (You can use Poedit’s pre-translations suggestions if needed.)

      Translating using Poedit
      Translating using Poedit

      5. Click Save. Poedit generates both:

      • A .po file (editable)
      • A .mo file (compiled)

      6. Upload the generated files to your server via FTP or cPanel, inside:
      wp-content/themes/your-theme/languages/ (for a plugin: wp-content/plugins/your-plugin/languages/) and make sure the file name follows WordPress conventions.

      For example: ja_JP.po and ja_JP.mo

      Once uploaded, WordPress will automatically load the translation, and Polylang will display the correct language based on the page’s language. 

      Translating your theme’s or plugin’s dynamic strings using Polylang

      Dynamic strings are generated from theme or plugin options, custom fields, or database settings. To appear in this table, dynamic strings must be registered, and they are not stored in PO/MO files. As a result, they must be translated through Polylang.

      1. Go to Languages >Translations and filter the strings by the theme or plugin group. In our example, it’s “themes/astra” and hit the filter button.

      Filtering the content to display only the dynamic strings from the theme
      Filtering the content to display only the dynamic strings from the theme

      2. Add the translations in the right language fields.

      Translation of theme strings
      Translation of theme strings

      Registering dynamic strings for translation

      Theme and plugin authors have two main ways to register dynamic strings:

      • A wpml-config.xml file tells Polylang which strings should be translatable
      • Registered strings automatically appear in the Translations table
      • This is the recommended method for theme and plugin authors. 

      Why?

      This method is safer because it does not rely on PHP code. From our experience, developers often forget to declare the Polylang functions they use. If Polylang is temporarily deactivated (e.g., during a Polylang update, which is how WordPress handles updates) this can cause fatal errors. Using a wpml-config.xml file avoids this problem.

      Good to know: If you are a Polylang Pro user, the Polylang team can create it for you. 

      Using Polylang functions for translating dynamic strings

      To avoid confusion, it is important to distinguish between:

      • Static strings (hardcoded in PHP files)
      • Dynamic option strings (entered in the WordPress admin via your theme or plugin options)

      The Polylang Translations table is dedicated exclusively to dynamic strings stored in the database, not to strings directly written in theme or plugin PHP files. Many users mistakenly use the Translations table to translate hardcoded PHP strings. This is not the correct approach since WordPress already provides a native system for translating code strings (__(), _e(), _n(), etc.), which is fast, efficient, making it much better than using the Translations table for hardcoded PHP strings In other words, the Translations table should not be used to translate hardcoded PHP strings.

      Static strings (PHP Files)

      For strings directly present in theme or plugin PHP files (titles, buttons, labels, static text), developers must use native WordPress internationalization functions, such as:

      • __()
      • _e()
      • _n()
      • etc.

      These strings are:

      • Extracted into POT files
      • Translated via PO files
      • Compiled into MO files
      • Automatically loaded by Polylang on the site.

      Summary:
      Theme or plugin PHP files→ WordPress native functions → PO/MO files → Automatically loaded by Polylang

      Dynamic option strings (admin input)

      The Polylang Translations table is intended for:

      • Theme or plugin options entered in the WordPress admin
      • Strings stored in the database
      • Custom or conditional content defined by users

      Developers must:

      1. Register the string:
        pll_register_string()
      2. Display the translated string (if needed):
        pll_e()

      Summary:
      Dynamic options → Translations table → pll_register_string() / pll_e()

      Key rules

      • Static strings (those in theme or plugin PHP files) → You can use WordPress native i18n functions
      • Dynamic options → You can use the Polylang Translations table and Polylang functions.Â