Learn to implement WordPress internationalization (i18n) to make your plugins translation-ready. Master text domains, translation functions, and POT file generation.
Previously in this course, we discussed handling plugin updates to keep your database schema in sync with your codebase. Now that our Knowledge Base plugin is stable and secure, it’s time to open it up to the world by implementing internationalization (i18n).
Internationalization—often abbreviated as "i18n" because there are 18 letters between the 'i' and the 'n'—is the process of developing your plugin so it can easily be adapted for different languages and regions. Without this, your plugin is locked into the language you wrote it in, severely limiting your user base.
To make your plugin "translation-ready," you must stop hardcoding display strings directly into your PHP files. Instead, you wrap every user-facing string in specific WordPress functions. These functions tell WordPress that the string should be passed through a translation engine before being sent to the browser.
When you do this, you define a text domain. A text domain is a unique string—usually the slug of your plugin—that acts as a namespace for your translations. This ensures that WordPress knows which language file belongs to your plugin and not another.
There are two primary functions you need to master for basic output:
__(): Retrieves the translated string. Use this when you need to store the string in a variable or pass it to another function._e(): Retrieves and echoes the translated string. Use this for direct output in your templates.Both functions accept two arguments: the string to translate and the text domain.
PHP#6A9955">// Storing for later use $label = __('Knowledge Base Article', 'knowledge-base-plugin'); #6A9955">// Echoing directly to the page _e('Click here to read more', 'knowledge-base-plugin');
Let's update our plugin's core initialization to load our text domain. In your main plugin file, you need to hook into the plugins_loaded action.
PHPclass KnowledgeBasePlugin { public function __construct() { add_action('plugins_loaded', [$this, 'load_textdomain']); } public function load_textdomain() { load_plugin_textdomain( 'knowledge-base-plugin', false, dirname(plugin_basename(__FILE__)) . '/languages' ); } }
Now, every time you output text in your views or admin controllers, use the translation functions. For example, in your AdminController, when you define your menu page:
PHPadd_menu_page( __('Knowledge Base Settings', 'knowledge-base-plugin'), __('Knowledge Base', 'knowledge-base-plugin'), 'manage_options', 'knowledge-base', [$this, 'render_admin_page'] );
A POT (Portable Object Template) file is a master template containing all the translatable strings in your plugin. Translators use this file to create language-specific .po files.
You don't need to write this file manually. You can use tools like the WP-CLI to generate it automatically:
wp i18n make-pot . languages/knowledge-base-plugin.potThis command scans your entire directory for __() and _e() functions, extracts the strings, and creates the .pot file in your /languages folder.
AdminController and your frontend shortcode views. Find every hardcoded string (like "Submit," "Settings," or "Article Title") and wrap it in the __() or _e() function.wp i18n make-pot command and verify that your languages/ folder now contains your .pot file.__('Hello ' . $user_name, 'domain'). The translation engine cannot parse concatenated strings. Instead, use printf() with placeholders: printf(__('Hello %s', 'domain'), $user_name);.By following these practices, you ensure that your plugin remains accessible to a global audience, allowing community contributors to localize your work effectively.
Up next: We'll dive into Debugging WordPress Plugins to learn how to identify and resolve issues when things don't go according to plan.
Master the WordPress event-driven architecture. Learn the difference between actions and filters and how to implement callbacks to build robust plugins.
Internationalization (i18n)
Plugin Security Best Practices
Composer for Dependencies
Theme Integration Hooks
Managing Assets with Gulp/Webpack
Documentation Standards
Plugin Deployment Strategy
Advanced MVC: Dependency Injection
Handling Large Datasets
Error Handling and Logging