WordPress & multilingual sites
Multilingual WordPress Without a Plugin: Multisite, Hreflang and Trade-offs
Yes, WordPress can serve several languages without a translation plugin. Here is how Multisite works for it, a tested hreflang snippet, and an honest look at what you give up.
By AYM FlowPublished: 8 min read
Building a multilingual WordPress site without a plugin is possible, and for some projects it is the cleaner choice. WordPress core has no built-in translation management, but it does have Multisite, which lets you run one site per language on a single installation. Add a small piece of code to connect the translations and print hreflang tags, and you have a multilingual setup with no third-party translation layer. This guide explains how that works, shows a tested snippet, compares the alternatives and is honest about the cases where a translation plugin saves you more time than it costs.
Multilingual WordPress without a plugin: what you need to cover
Before choosing an approach, list what a multilingual site actually needs. Translation plugins bundle these features, so going without one means solving each of them yourself:
- Separate URLs per language, such as /de/ and /tr/, so each version can be indexed and shared.
- A link between translations, so the system knows which German page belongs to which English page.
- A language switcher that leads to the translated page, not to the other language's home page.
- Hreflang annotations that tell search engines which version to show to whom.
- Translated menus, widgets, theme strings and slugs, not only post content.
- An editorial workflow for who translates what, and how missing translations are spotted.
Any approach that covers these six points works. The question is how much effort each one costs to build and to maintain.
Option 1: WordPress Multisite with one site per language
Multisite turns one WordPress installation into a network of sites that share the same code, themes and plugins but have their own content, settings and media. Giving each language its own site is the most robust way to go multilingual without a translation plugin, because every language has its own menus, widgets, slugs and site language setting by design.
Setting up the network
- Back up the site and its database before changing anything.
- Add the line define( 'WP_ALLOW_MULTISITE', true ); to wp-config.php, as described in the official Create A Network guide.
- Open Tools, Network Setup, and choose sub-directories (example.com/de/) or sub-domains (de.example.com).
- Copy the configuration lines WordPress shows into wp-config.php and the rewrite rules into .htaccess, then log in again.
- Create one site per language and set its Site Language under Settings, General.
- Network-activate the theme and the plugins every language needs.
Sub-directories keep everything on one domain, which is usually simpler for SSL and for search engines to understand as one brand. Converting a site that already has content and traffic deserves the same care as any migration; our website migration SEO checklist covers redirects and monitoring.
What you gain and what you give up
You gain clean separation: each language can have different menus, legal pages or even products, and an editor can work on one language without touching another. You give up convenience: there is no side-by-side translation screen, media is uploaded per site, and plugins must be compatible with Multisite. Some hosting plans also restrict Multisite, so check before you start.
Linking translations and printing hreflang without a plugin
Multisite does not know that a German post is the translation of an English one. The simplest reliable link is a shared value in a custom field: give all translations of one article the same group key, for example in a field called _acme_group. The network plugin below reads that key, finds the matching post on every language site and prints hreflang links, including an x-default that points to the main site. Google's documentation on localized versions of your pages describes the rules these tags follow.
<?php
/**
* Plugin Name: Acme Network Hreflang
* Description: Prints hreflang links between translated posts on a Multisite network with one site per language.
* Network: true
* License: GPL-2.0-or-later
*/
defined( 'ABSPATH' ) || exit;
// Translations of one article share the same value in the "_acme_group" post meta.
add_action( 'wp_head', function () {
if ( ! is_singular() ) {
return;
}
$group = get_post_meta( get_queried_object_id(), '_acme_group', true );
if ( '' === $group ) {
return;
}
$links = array();
$default = '';
foreach ( get_sites( array( 'public' => 1, 'number' => 20 ) ) as $site ) {
switch_to_blog( (int) $site->blog_id );
$ids = get_posts( array(
'post_type' => 'any',
'post_status' => 'publish',
'meta_key' => '_acme_group',
'meta_value' => $group,
'fields' => 'ids',
'posts_per_page' => 1,
'no_found_rows' => true,
) );
if ( $ids ) {
$locale = get_option( 'WPLANG' ) ?: 'en_US'; // empty WPLANG means English
$lang = strtolower( strtok( $locale, '_' ) );
$url = get_permalink( $ids[0] );
$links[ $lang ] = $url;
if ( is_main_site() ) {
$default = $url;
}
}
restore_current_blog();
}
if ( count( $links ) < 2 ) {
return; // one language needs no hreflang
}
foreach ( $links as $lang => $url ) {
printf( '<link rel="alternate" hreflang="%s" href="%s" />' . "\n", esc_attr( $lang ), esc_url( $url ) );
}
if ( $default ) {
printf( '<link rel="alternate" hreflang="x-default" href="%s" />' . "\n", esc_url( $default ) );
}
} );We ran this exact file through php -l and through a test harness that simulates a three-language network: it prints every language plus x-default, skips languages without a translation, prints nothing for single-language posts or archives, and always restores the original site context. Save it in wp-content/mu-plugins or network-activate it as a plugin.
Three practical notes. First, the language code is taken from each site's language setting, so en_US becomes en; if you serve two variants of one language, such as en-GB and en-US, extend the code to keep the region. Second, the loop switches between sites on every request, which is fine for a handful of languages but should be cached on large networks. Third, a language switcher can reuse the same lookup to link directly to the translated page.
Option 2 and 3: separate installations or custom code in one site
Separate WordPress installations
Each language can also be a completely independent WordPress site, on a sub-directory or its own domain. This gives the strongest separation and works on any hosting, but it multiplies updates, backups and user accounts, and linking translations means maintaining a mapping by hand or through an API. It suits organisations where each country team runs its own site.
One site with custom fields per language
In theory you can store every language in one site, for example with extra fields per language and a URL prefix handled by rewrite rules. In practice this grows quickly: menus, widgets, search, slugs, sitemaps, theme strings and shop data all need language awareness. By the time it works properly you have written a translation plugin yourself, without the years of testing an established one has.
Menus, theme strings and the language switcher
Post content is only part of a translated site. On a Multisite network the rest falls into place more easily than in a single site, but it still needs a plan:
- Menus and widgets are stored per site, so each language simply gets its own menu with translated labels and links.
- Theme and plugin strings such as buttons, form labels and dates are translated through language files (.po and .mo). WordPress loads the right file automatically based on each site's language setting, provided the theme ships or receives a translation.
- Slugs are set per post, so translated URLs like /de/leistungen/ are natural and should be used rather than copying the original slug.
- The language switcher belongs in the header template. It can reuse the same group-key lookup as the hreflang code and fall back to the other language's home page only when no translation exists.
Decide early how the switcher behaves for missing translations. Hiding a language that has no matching page is usually clearer for visitors than sending them to a home page they did not ask for.
Editorial workflow: keeping translations in sync
Without a plugin there is no dashboard that flags outdated translations, so agree on a lightweight routine instead:
- Assign the group key when the original article is published, even before the translation exists.
- Keep a simple overview, such as a spreadsheet or a small admin report, of group keys and the languages that have them.
- When the original changes, note the date in the overview so translators know which versions need a review.
- Let a native speaker review titles, descriptions and slugs, because these are what searchers see first.
- Check the hreflang output of a few pages after each release, especially after theme or plugin updates.
This routine takes minutes per article and prevents the most common multilingual problem: one language quietly falling behind while the others are updated.
When a translation plugin is the better choice
Going without a plugin is a good fit when languages differ in content, when separate teams manage them, or when you need full control over every URL. A plugin is usually the better choice when the same content is translated one to one, when editors want to translate side by side, or when a WooCommerce shop needs translated products, prices and checkout. Our own AYM Multilingual plugin exists for exactly that second group, and we build and maintain both kinds of setup in our multilingual WordPress service.
Whichever route you take, the search side works the same way: separate URLs, reciprocal hreflang and fully translated metadata. Our hreflang tags guide covers those rules and the mistakes that most often break them.
Frequently asked questions
Can WordPress be multilingual without any plugin?
Yes. WordPress Multisite with one site per language provides separate URLs, menus and settings per language. You only need a small piece of code, or a mu-plugin like the one above, to link translations and print hreflang.
Is Multisite good for SEO?
It can be. Search engines care about clear URLs per language, correct reciprocal hreflang and translated content. Multisite gives you the URLs; hreflang and content quality are up to your implementation.
Can I convert an existing site to Multisite?
Yes, but treat it like a migration: back up first, test on a staging copy, keep existing URLs or redirect them with 301s, and check that every plugin you rely on supports Multisite.
Does this approach work with WooCommerce?
Each language site can run its own WooCommerce store, but products, stock and orders are then separate per site. If you need one shared catalogue in several languages, a translation plugin is usually simpler.
Related articles
WordPress & multilingual sites
Localization vs Translation: The Difference and How to Apply It to Your Website
Translation moves text into another language; localization rebuilds the site for someone living in that market. We explain the difference with examples from our own keyword research.
WordPress & multilingual sites
Add a Language to a WordPress Site: A Step-by-Step Guide
You want to add English or another language to your existing WordPress site. The “Site Language” setting is not enough; here is how to do it with the right structure, priorities and SEO steps.
WordPress & multilingual sites
Language Switcher Design: User-Friendly, Accessible and SEO-Safe
Flags or language names? Top-right corner or footer? The principles of a language switcher that visitors can find, use with a keyboard and that search engines understand.
