2026年11月12日

2026年11月12日

WordPress Multilingual Site with Polylang: Setup Steps and WPML Comparison

This article is a localized edition of the Japanese original. Read the Japanese original

WordPress core has no feature for managing posts in several languages on one site. To run Japanese and English pages side by side, you use a multilingual plugin. The best-known options are the free Polylang and the paid WPML.

This article walks through setting up Polylang with Japanese as the default language and English as the second language. The steps and code were tested in November 2026 with Polylang 3.9.2 (WordPress 7.1, PHP 8.3). The comparison with WPML is based on WPML's official website and documentation.

Polylang vs. WPML

Item Polylang (free) WPML
Where to get it The wordpress.org plugin directory Bought and downloaded from the official site (wpml.org)
Price Free (a paid Polylang Pro also exists) Paid (see below)
Entering translations You create a post per language and write it yourself Write them yourself, or use automatic translation and translator assignment features
WooCommerce Needs the separately sold add-on Polylang for WooCommerce Included in the higher plans
URL slugs A different slug per language (shared slugs are a Pro feature) The same slug can be used in each language

As shown on the official site in November 2026, WPML costs 39 euros for Multilingual Blog (1 production site), 99 euros for Multilingual CMS (3 production sites) and 199 euros for Multilingual Agency (unlimited sites), each with one year of support and updates. Multilingual Blog does not include WooCommerce support or string translation.

For a personal blog or a company site with a modest number of pages whose translations you write yourself, Polylang is enough. For a WooCommerce store with many products, or when you share a large translation workload with translators, WPML is a better fit.

Install Polylang and add languages

Installation

In the admin, go to "Plugins" → "Add Plugin", search for "Polylang", install it and activate it. If you have WP-CLI, this command does the same.

wp plugin install polylang --activate

Activation starts a setup wizard. If you close the wizard, you can make the same settings from the "Languages" menu in the admin.

Add languages

  1. Open "Languages" → "Languages".
  2. Pick "日本語" (Japanese) in "Choose a language" and click "Add new language".
  3. Add "English (United States)" or another language the same way.

The first language you add becomes the default language. You can change the default with the star icon in the language list.

After you add languages, a notice says that existing posts and pages have no language. Use the action in the notice to assign all existing content to the default language (Japanese).

Choose the URL format

Under "Languages" → "Settings", "URL modifications" decides where the language appears in the URL.

Setting Example URL
The language is set from the directory name in pretty permalinks (default) example.com/en/about/
Set from the subdomain name en.example.com/about/
Set from different domains example.com and example.jp, for example

By default, "Hide URL language information for default language" is also enabled, so Japanese posts keep their current URLs such as example.com/about/ and English posts get example.com/en/.... Existing Japanese URLs don't change, which makes this combination the safe choice when you add English to a site that is already running.

Changing this setting after launch changes URLs across the site and affects search rankings and inbound links. Decide on it before you publish English pages.

After changing the setting, open "Settings" → "Permalinks" and click "Save Changes" to refresh the permalinks.

Translate posts and pages

Polylang does not translate automatically. You create a separate post for each language and link them as translations of each other.

  1. Open "Posts" → "All Posts"; a column has been added for each language.
  2. On the row of the post you want in English, click the "+" in the English column.
  3. A new post editor opens with the language set to English. Write the title and content in English.
  4. Give it a slug different from the Japanese version (for example about-en if the Japanese version is about). In the free version, the same slug can't be used even across languages.
  5. Publish it.

Categories and tags are also created per language and linked. The "Posts" → "Categories" list has the same language columns as posts.

Add a language switcher

Polylang's "Language switcher" gives visitors links to change the language. How you place it depends on the theme type.

  • Block themes (such as Twenty Twenty-Five): Open the header navigation in the Site Editor and add Polylang's language switcher block.
  • Classic themes: In "Appearance" → "Menus", a "Language switcher" item appears on the left; add it to the menu. If you don't see it, tick "Language switcher" under "Screen Options" at the top right.
  • Themes that use widgets: Add the language switcher to a sidebar or other area in "Appearance" → "Widgets".

Flags, language names, dropdown display and similar options are chosen in each switcher's settings.

Output switcher links with code

To print links directly from a theme template, pass 'raw' => 1 to pll_the_languages() and get the URL and name of each language as an array. The code below appends links to the other languages at the end of the content, only when the current page has a translation.

Save it as wp-content/mu-plugins/my-lang-switcher.php and it is loaded automatically. It checks with function_exists() before calling Polylang, so the site doesn't break if Polylang is deactivated.

<?php
/**
 * Plugin Name: Language switch links
 */

// List links to languages that have a translation (outputs nothing if Polylang is inactive)
function my_language_links() {
	if ( ! function_exists( 'pll_the_languages' ) ) {
		return '';
	}
	$languages = pll_the_languages( array( 'raw' => 1 ) );
	$items     = array();
	foreach ( $languages as $lang ) {
		if ( $lang['current_lang'] || $lang['no_translation'] ) {
			continue; // Skip the current language and languages without a translation
		}
		$items[] = sprintf(
			'<a href="%s" hreflang="%s" lang="%s">%s</a>',
			esc_url( $lang['url'] ),
			esc_attr( $lang['slug'] ),
			esc_attr( $lang['slug'] ),
			esc_html( $lang['name'] )
		);
	}
	return $items ? '<p class="my-lang-links">' . implode( ' / ', $items ) . '</p>' : '';
}

// Append to the end of the content
add_filter( 'the_content', function ( $content ) {
	if ( is_singular() && in_the_loop() && is_main_query() ) {
		$content .= my_language_links();
	}
	return $content;
} );

Polylang 3.9 reorganized the arguments of pll_the_languages(), and older arguments such as dropdown, show_names and display_names_as are deprecated. If you use it to print HTML directly, check the argument documentation (the comments in the plugin's src/api.php). Getting an array with 'raw' => 1 is not affected by this change.

Other commonly used functions:

Function Returns
pll_current_language() The code of the current language (ja, en, etc.)
pll_default_language() The code of the default language
pll_get_post( $post_id, 'en' ) The ID of the English version of the given post (empty if none)
pll_home_url( 'en' ) The URL of the English home page

Translate fixed text in the theme

Text written directly in theme code, such as a "Contact us" line in the footer, can't be translated through post translations. Register it with pll_register_string() and you can enter a translation per language on the "Languages" → "Translations" (string translations) screen, then retrieve the current language's translation with pll__().

<?php
// Register the string (in functions.php or similar)
add_action( 'init', function () {
	if ( function_exists( 'pll_register_string' ) ) {
		pll_register_string( 'footer-contact', 'Contact us', 'my-theme' );
	}
} );

// Display it in a template
$label = function_exists( 'pll__' ) ? pll__( 'Contact us' ) : 'Contact us';
echo esc_html( $label );

The site title and tagline are listed on the "Translations" screen from the start, without registering them.

hreflang and search engine settings

Polylang automatically outputs hreflang links pointing to each language version in the <head> of posts and pages that have translations. <html lang="..."> also changes to the current language. Adding your own code that prints hreflang in wp_head duplicates them, so don't. To check the output, view the page source and search for hreflang.

If you use Yoast SEO, Polylang has a built-in integration with it: the XML sitemaps include posts in each language, and Yoast SEO title templates and similar strings can be translated per language on the "Languages" → "Translations" screen.

WPML also outputs hreflang automatically on pages that have translations.

Using WPML

WPML is not on wordpress.org, so a command like wp plugin install wpml won't install it. Buy it on wpml.org, download the installer from your account page, and install it with "Plugins" → "Add Plugin" → "Upload Plugin".

To use WPML data from a theme or plugin, call the filters WPML provides with apply_filters(). When WPML is inactive, the second argument is returned unchanged, so nothing breaks.

<?php
// Code of the current language
$current_lang = apply_filters( 'wpml_current_language', null );

// ID of the English version of post 123 (returns the original ID if there is no translation)
$en_id = apply_filters( 'wpml_object_id', 123, 'post', true, 'en' );

// Convert a URL to the English version's URL
$en_url = apply_filters( 'wpml_permalink', get_permalink( 123 ), 'en' );

Things to watch

  • Language switching and caching. With the directory format, each language has its own URL, so conflicts with page caching are unlikely. If "Detect browser language" is enabled, the home page redirects visitors based on their browser language, so if you use a caching plugin, check that the home page shows correctly in a browser set to another language.
  • Pages without a translation. A post with no English version is either left out of the English switcher or linked to the English home page (depending on settings). Translating the main pages first keeps English visitors from getting lost.
  • Switching plugins. Polylang and WPML store translation links differently, so switching later requires a migration. Decide your approach first, including whether you plan to use WooCommerce.

Related articles

Questions about WordPress? The publisher of this site is based in Japan and replies in Japanese. Contact (Japanese)

お気軽にご相談ください

お見積りへ お問い合わせへ
▲