If you're developing a WordPress theme for ThemeForest, making it translation-ready isn't just a nice-to-have—it's a crucial selling point. With WordPress powering websites in dozens of languages worldwide, a properly internationalized theme opens your product to a global market. ThemeForest reviewers also look favorably on themes that follow WordPress best practices for translation.
This comprehensive checklist will walk you through every step of preparing your theme for translation, from setting up your text domain to generating the .pot file that translators need.
1. Understanding WordPress i18n Basics
Internationalization (i18n) is the process of developing your theme so it can be easily translated into other languages. Localization (l10n) is the subsequent process of translating an internationalized theme for a specific language and locale.
Key Translation Files
- .pot Portable Object Template – the master template containing all translatable strings. This is what you distribute with your theme.
- .po Portable Object – human-readable translation file. Created by translators from the .pot file.
- .mo Machine Object – compiled binary file that WordPress actually uses to display translations.
2. Theme Header Configuration
The first step is configuring your theme's style.css header with the proper text domain and domain path declarations.
/*
* Theme Name: Your Theme Name
* Theme URI: https://your-theme-url.com
* Author: Your Name
* Text Domain: your-theme-name
* Domain Path: /languages
*/
Important: The text domain should match your theme's slug (folder name). Use lowercase letters and hyphens, not underscores.
3. Loading the Text Domain
Add this code to your theme's functions.php to tell WordPress where to find translation files:
function yourtheme_load_textdomain() {
load_theme_textdomain(
'your-theme-name',
get_template_directory() . '/languages'
);
}
add_action( 'after_setup_theme', 'yourtheme_load_textdomain' );
💡 For child themes, use load_child_theme_textdomain() instead.
4. Wrapping Strings for Translation
Every user-facing string in your theme must be wrapped in a WordPress translation function. Here are the essential functions you'll use:
Essential Translation Functions
__() Returns translated string. Use when you need to store or manipulate the result.
_e() Echoes translated string directly. Use for simple output.
esc_html__() Returns escaped and translated string. Safe for HTML output.
esc_html_e() Echoes escaped and translated string. Recommended for HTML content.
esc_attr__() Returns escaped and translated string. Safe for HTML attributes.
_n() Handles singular/plural forms based on count.
_x() Translation with context. Helps translators understand usage.
Code Examples
Basic translation:
<?php _e( 'Read More', 'your-theme-name' ); ?>
With HTML escaping:
<?php echo esc_html__( 'Posted by', 'your-theme-name' ); ?>
For attributes:
<input placeholder="<?php echo esc_attr__( 'Search...', 'your-theme-name' ); ?>">
Pluralization:
printf(
_n( '%d comment', '%d comments', $count, 'your-theme-name' ),
$count
);
With variables (using printf):
printf(
esc_html__( 'Written by %s', 'your-theme-name' ),
get_the_author()
);
5. RTL (Right-to-Left) Language Support
Supporting RTL languages like Arabic, Hebrew, and Persian significantly expands your theme's market reach. WordPress will automatically load an rtl.css file when an RTL language is active.
Creating Your RTL Stylesheet
- Create an rtl.css file in your theme's root directory
- Mirror horizontal properties: Swap left/right values for text-align, float, clear, margins, padding, and positioning
- Flip directional images: Create mirrored versions of arrows, icons, and other directional graphics
- Use automated tools: RTLCSS or CSSJanus can generate RTL stylesheets automatically
RTL CSS Example
/* rtl.css */
body {
direction: rtl;
unicode-bidi: embed;
}
.sidebar {
float: left; /* was: float: right; */
}
.nav-arrow {
margin-right: 10px; /* was: margin-left: 10px; */
margin-left: 0; /* reset */
}
💡 Test your RTL stylesheet by switching WordPress to Hebrew or Arabic in Settings > General > Site Language.
6. Generating Your .pot File
The .pot file is the template that translators use to create translations. You have several options for generating it:
Method 1: WP-CLI (Recommended)
If you have WP-CLI installed, this is the fastest and most reliable method:
# Navigate to your theme directory
cd wp-content/themes/your-theme-name
# Generate the .pot file
wp i18n make-pot . languages/your-theme-name.pot
```
### Method 2: Loco Translate Plugin
1. Install and activate the Loco Translate plugin
2. Go to Loco Translate > Themes in WordPress admin
3. Select your theme and click "Create template"
4. The plugin will scan your files and generate a .pot file
### Method 3: Poedit
Use the desktop application Poedit to scan your theme files and extract translatable strings. Configure it to look for WordPress translation functions like `__`, `_e`, `_n`, etc.
### Method 4: PoGen.org
For a quick, hassle-free solution, use [PoGen.org](https://pogen.org) to generate .pot files directly in your browser. Simply upload your theme's PHP files and get a ready-to-use translation template.
---
## 7. Recommended File Structure
Your theme should have a `/languages` directory containing your translation files:
```
your-theme-name/
├── languages/
│ ├── your-theme-name.pot (Template)
│ ├── de_DE.po (German translation)
│ ├── de_DE.mo (German compiled)
│ ├── fr_FR.po (French translation)
│ └── fr_FR.mo (French compiled)
├── style.css
├── rtl.css
├── functions.php
└── ...
8. Common Mistakes to Avoid
1. Hardcoded strings
Never output text directly. Always wrap in translation functions.
2. Variables in translation functions
Don't pass variables—translators can't translate dynamic content.
// ❌ WRONG
__( $variable, 'your-theme-name' );
// ✅ CORRECT
sprintf( __( 'Hello, %s', 'your-theme-name' ), $name );
3. Concatenating translations
Translate complete sentences, not fragments.
// ❌ WRONG
__( 'Read', 'your-theme' ) . ' ' . __( 'More', 'your-theme' );
// ✅ CORRECT
__( 'Read More', 'your-theme-name' );
4. Missing text domain
Always include your text domain as the second parameter.
5. Wrong text domain format
Use hyphens (your-theme-name), not underscores (your_theme_name).
6. Forgetting to escape
Use esc_html__() or esc_attr__() for security.
9. Pre-Submission Checklist
Before submitting to ThemeForest, verify each item:
Theme Header
- Text Domain declared in style.css
- Domain Path specified (usually /languages)
- Text domain matches theme slug
Functions.php
load_theme_textdomain()properly hooked- Path to languages directory is correct
All Theme Files
- All user-facing strings wrapped in translation functions
- Text domain included in every translation call
- Proper escaping functions used (
esc_html__,esc_attr__) - Pluralization handled with
_n()where needed
Translation Files
- .pot file generated and placed in /languages
- .pot file includes all translatable strings
- .pot file includes theme description and template names
RTL Support
- rtl.css file created in theme root
- Layout properly mirrors for RTL languages
- Tested with RTL language active
Conclusion
Properly internationalizing your WordPress theme is an investment that pays dividends in customer satisfaction and global sales. ThemeForest reviewers appreciate themes that follow these best practices, and your international customers will thank you for the seamless translation experience.
Remember: internationalization isn't a feature—it's a fundamental aspect of professional WordPress development. Take the time to do it right from the start, and you'll save yourself (and your users) countless headaches down the road.
Need to translate a .po file quickly? Visit PoGen.org for instant .po file translation 50+ languages.