WordPress multilingual sites: what developers should know
When you're building a WordPress site that serves customers across borders, language barriers quickly become a technical problem. WordPress multilingual sites: what developers should know starts with a hard truth—you can't just drop translated strings into your database and call it done. We'll walk through the tools, strategies, and pitfalls that separate a functioning multilingual setup from one that actually ranks well, feels native to each market, and doesn't fall apart when content editors update a page.
Choosing between WPML and Polylang
The two dominant plugins for managing multilingual WordPress sites are WPML (WordPress Multilingual) and Polylang. Both solve the core problem of creating separate content versions per language, but they approach it differently, and choosing the wrong one early means painful migration later.
WPML uses a post duplication model: you create a post in English, and WPML creates linked copies in French, Spanish, and so on. Each language gets its own database records. This means your database grows proportionally with languages, but you get fine-grained control over each translation without shared term IDs causing confusion. WPML also includes automatic translation services (paid) and integrates deeply with WooCommerce for e-commerce sites. The trade-off is cost—premium licenses run $99–$299/year depending on the site plan and language count.
Polylang takes a term-based approach, storing language information as taxonomy terms. Posts aren't duplicated; instead, they're tagged with language metadata. This keeps your database leaner and feels more native to WordPress architecture. Polylang is free (with a paid Pro version at €179/year for advanced features), making it appealing for budget-conscious teams. However, the term-based model can complicate custom queries and taxonomy filtering if you're not careful.
For a real-world scenario: if you're running an e-commerce store in 8 languages with frequent inventory and pricing updates, WPML's post duplication model ensures each language gets independent control without risk of taxonomy conflicts. If you're building a content site in 3–4 languages where editors rarely touch taxonomy, Polylang's lean approach saves database overhead and licensing cost.
Both plugins handle the same core tasks—language switching, content duplication, admin language selection—but your language count, budget, and custom functionality should drive the choice. Test both in a staging environment if multilingual is a core requirement.
Setting up hreflang tags correctly
Once your multilingual content exists, search engines need to know which page is the canonical version and which are language variants. That's what hreflang tags do. Without them, Google may index duplicate content or show the wrong language to users in different regions—tanking your SEO across all markets.
Both WPML and Polylang generate hreflang tags automatically, but understanding what they're doing prevents subtle bugs. A basic hreflang setup looks like this:
<link rel="alternate" hreflang="en" href="https://example.com/about" />
<link rel="alternate" hreflang="fr" href="https://example.com/fr/about" />
<link rel="alternate" hreflang="es" href="https://example.com/es/about" />
<link rel="alternate" hreflang="x-default" href="https://example.com/about" />Each page must reference all its language variants, plus an x-default fallback for users in regions where none of your languages match. If your English page only references itself, Google may not recognize the French and Spanish versions as intentional translations.
Most WordPress multilingual plugins generate these automatically in the head tag. Verify they're present by viewing the page source and checking Search Console's International Targeting report. Watch for common mistakes: inconsistent URL structures (mixing subdirectories, subdomains, and URL parameters) confuse hreflang parsers, and forgetting the x-default tag means unmatched-language users see random versions.
If you're using a custom URL structure—say, /en/, /fr/, /es/—the hreflang tags must respect that. A mismatch between your actual URLs and the hreflang declarations breaks everything.
Translating menus and widgets
Users notice immediately when navigation menus appear in the wrong language. A French visitor landing on your site's French version shouldn't see English menu items—yet this happens constantly because developers forget that menus are stored as terms, and widgets contain hardcoded text.
WPML provides a menu translation interface in the admin. When you translate a page, you also translate the menu items that link to it. Polylang requires manual duplication of menus per language or using a filter to swap them. Here's a Polylang approach using the wp_nav_menu_args filter:
add_filter( 'wp_nav_menu_args', function( $args ) {
if ( function_exists( 'pll_current_language' ) ) {
$current_lang = pll_current_language();
$menu_mapping = array(
'en' => 'main-menu-en',
'fr' => 'main-menu-fr',
'es' => 'main-menu-es',
);
$args['menu'] = $menu_mapping[ $current_lang ] ?? $args['menu'];
}
return $args;
} );This approach avoids duplicating menu structure; instead, each language gets its own menu with translated labels and links. It's maintainable because adding a language just requires creating one new menu.
Widgets are trickier. Text widgets, image captions, and CTA buttons often contain hardcoded strings that plugins can't automatically translate. Use WPML's String Translation feature or Polylang's string translations to mark widget text for translation. Alternatively, move static text into custom fields attached to the widget, then query them by language in your widget template:
if ( function_exists( 'pll_current_language' ) ) {
$current_lang = pll_current_language();
$text = get_option( "widget_cta_text_{$current_lang}" );
echo wp_kses_post( $text );
}This pattern is more robust than relying on automatic detection of widget strings.
Planning your URL structure early
Your URL structure is a foundational decision that affects everything downstream: SEO, internal links, canonical tags, redirects, and caching strategy. Change it after launch, and you'll spend weeks fixing hreflang tags and 404 errors.
There are three common URL structures for multilingual sites:
- Subdirectories:
example.com/en/,example.com/fr/,example.com/es/. Easiest to implement in WordPress; all languages on one domain. - Subdomains:
en.example.com,fr.example.com,es.example.com. Treats each language like a separate site; can complicate cookie sharing and analytics. - Domain-based:
example.com,example.fr,example.es. Strongest SEO signal per region; requires multiple domain registrations and SSL certificates.
For most WordPress teams, subdirectories are the pragmatic choice. They're simple to configure, require no additional domain setup, and both WPML and Polylang handle them natively. Choose subdirectories in your plugin settings and let WordPress rewrite rules do the work.
Subdomains work but require careful cache configuration. If you're using Redis or Memcache, ensure language-specific cache keys don't collide. Domain-based structures are best for large organizations or regional SEO focus but come with operational overhead.
Whatever you choose, commit to it before launch. Test URL generation thoroughly: ensure post permalinks, term archives, and pagination all respect the language prefix. In WPML, verify the "Languages" settings match your chosen structure. In Polylang, check that the language is properly appended to every canonical tag and alternate link.
Common mistakes
Forgetting to translate custom post types and taxonomies. If your site has custom CPTs (e.g., "Services") or custom taxonomies (e.g., "Industry"), both WPML and Polylang need to know they're translatable. In WPML, register them with 'show_in_rest' => true and enable translation in WPML settings. In Polylang, use the register_taxonomy_for_translations API. Skip this, and taxonomy pages render with untranslated slugs and broken category filtering.
Mixing language detection with hardcoded redirects. Avoid logic like "if user is French, redirect to /fr/". Use WordPress's built-in language detection (via browser headers or domain), let the plugin handle the redirect, and only force redirects when necessary. Premature redirects confuse crawlers and break shared links.
Not testing translated content on mobile. Language switchers look clean on desktop but often break navigation menus on mobile. Test the language switcher and menu rendering on a real phone before calling it done.
Ignoring plugin compatibility. Not every WordPress plugin is multilingual-aware. Theme builders, SEO plugins, and custom form builders may override hreflang tags or ignore language settings. Always check plugin documentation for multilingual support before integrating a large ecosystem.
Key takeaways
- Choose WPML for complex, multi-language e-commerce sites; choose Polylang for simpler content sites or tight budgets.
- Always generate and verify hreflang tags across all language variants, including the x-default fallback.
- Translate menus and widgets explicitly—don't assume automatic detection will cover navigation and UI text.
- Commit to a URL structure (subdirectories recommended) before launch; changing it after means broken redirects and SEO damage.
- Test custom post types, taxonomies, and plugins for multilingual compatibility early in development.






Comments
Loading comments…