SHORT ANSWER
A multilingual migration is several migrations at once: each language gets its own redirect map, and every old url lands on the same language on the new site — never on another language, never on a language picker. The rules have to run on every host the old languages lived on, which matters most when language subdomains or country domains become folders. After the move, hreflang is rebuilt on the new urls: every version lists itself and all the others, reciprocally, with full urls that answer 200.
Where languages live, and what that means for redirects
Google’s page on managing multi-regional and multilingual sites names four ways to put languages or countries into urls. It calls country domains expensive but clear, subdomains and subfolders easy to set up, and url parameters not recommended. For a migration the question is a different one: where do the redirect rules have to run?
| structure | example | what it means for the redirects |
|---|---|---|
| country domains | example.de, example.fr | each domain needs its own redirect rules and its own host |
| subdomains | de.example.com | rules on each subdomain; each is a separate site to a crawler |
| subfolders | example.com/de/ | one host, one rule set; wildcards per folder |
| url parameter | example.com/?lang=de | rules on the query string; most redirect importers cannot |
The moves that come up most: language subdomains or country domains consolidated into folders on one domain; a WordPress site that used the WPML option of a ?lang= parameter (WPML offers folders, domains and a parameter) moving to folders; and a relaunch onto a platform with built-in localisation, such as Webflow’s locale subfolders.
Collecting the old urls per language
A complete list per language is the part most often skipped, because the default language gets all the attention. Sources worth going through for each one:
- the old sitemaps. Multilingual sites often publish one per language, or one with hreflang alternates for every url — which is a ready-made list of each page in every language.
- the old hreflang tags. Crawled from the html, they tell you which pages were translations of each other, and therefore which new pages should be translations of each other.
- Search Console, per property. A language subdomain or country domain verified as its own property has its own performance report; export each one, not just the main domain.
- the backlink report, filtered by host or folder. Smaller languages often have few internal links and a handful of strong external ones.
Count the pages per language before matching. If the German site had 180 pages and the German half of the map has 120 rows, the gap is a list of urls nobody decided about yet (finding the urls nothing links to).
Map each language on its own
The rule that keeps a multilingual map correct is simple: the language of the target is the language of the source. A German page whose closest match by slug happens to be an English page is still a German page; if the new site has no German equivalent, the answer is the nearest German page or the German section’s start page, not the English one.
slugs unchanged — the cheap case. If /de/produkte/zange keeps its slug and only the language prefix or the host changes, one wildcard rule per language covers every page of it, including the ones the crawl never found.
slugs translated or restructured — the usual case in a relaunch. Translators renamed pages, sections were merged, the English site gained pages the others never had. These need one row per page, matched within the language.
the default language moves — a site that had English at the root and adds /en/, or the other way round, moves its whole default language. One wildcard does it — but write it so it cannot match its own target. /(.*) to /en/%1 also matches /en/… and loops; list the other languages’ folders above it, or redirect the root-level pages one by one.
In Silentfrog, a site with language folders is one crawl: old and new site in full, every language at once. The matching does not know about languages, so check that no row crosses one — type /de/ into the search box and every target in the filtered table should start with /de/ as well. Where a language folder simply moved, a directory rule per language with keep sub-paths writes one wildcard row for it. Language subdomains are separate sites to the crawler, because only www. is treated as the same host, so each subdomain is a run of its own against the new site.
redirect a whole directory
map every crawled page below a directory at once — optionally as a single webflow wildcard rule that also covers urls the crawl missed.
3 pages · 3 targets exist on the new site · + wildcard /blog/(.*) → /magazin/%1
- /blog/relaunch-checkliste → /magazin/relaunch-checkliste
- /blog/301-vs-302 → /magazin/301-vs-302
- /blog/ladezeit → /magazin/ladezeit
the directory rule form mapping /blog to /magazin with sub-paths kept, exported as a wildcard, and a live preview of how many pages it affects.
Subdomains, country domains and parameters
A redirect can only answer where the request arrives. When de.example.com becomes example.com/de/, the 301s for every German url have to be served by whatever answers for de.example.com after the switch. Before you retire the old host, decide what that will be: the new platform, if it can carry the subdomain as an additional domain with redirects; a small server or cdn rule; or the old host itself, left running with nothing but redirects on it.
# nginx on the old German subdomain: renamed pages first, then the folder
server {
server_name de.example.com;
location = /ueber-uns { return 301 https://example.com/de/unternehmen; }
location = /kontakt { return 301 https://example.com/de/kontakt; }
location / { return 301 https://example.com/de$request_uri; }
}The last line is the wildcard: everything not renamed keeps its path under the new folder. Exact location = blocks win over the prefix block in nginx regardless of their order, which is what keeps the renamed pages from falling through.
Parameter-based languages are the awkward case. /kontakt?lang=de and /kontakt?lang=fr share a path, and most redirect importers — Webflow, Shopify, Squarespace — match on the path alone, so they cannot tell the two apart. Those rules belong on a server that can read the query:
# Apache, in .htaccess: ?lang=de urls to the German folder, keeping the path
RewriteEngine On
RewriteCond %{QUERY_STRING} (^|&)lang=de(&|$)
RewriteRule ^(.*)$ /de/$1 [R=301,L,QSD]Silentfrog ignores query strings, so a parameter-based site crawls as one language: it is useful for matching the default language, and the other languages are better listed per language from Search Console or the old sitemap and turned into rules like the one above; a url list does not help here, because Silentfrog drops its query strings too.
Languages that are added, dropped or merged
- a dropped language — its pages redirect to the closest version that still exists, usually English or the language most of its visitors also read, page by page where an equivalent exists. Where none does, a 404 or 410 is more honest than sending everything to one homepage, which Google may treat as a soft 404.
- a regional variant merged into one language —
/de-at/and/de-ch/folded into/de/is a folder wildcard each, as long as the slugs match. - a new language needs no redirects at all, only hreflang. Do not point existing urls at it.
EXAMPLE
a company runs example.com in English, de.example.com and fr.example.com, and relaunches on one domain with /de/ and /fr/. Three runs: the English site against the new root, each subdomain against its new folder. German slugs were kept, so the German map is one wildcard plus eleven renamed pages; the French site was retranslated and is 140 rows matched one by one.
Hreflang after the move
Redirects tell search engines where each old url went; hreflang tells them which new urls are the same page in different languages. Google’s site-move guidance says to update hreflang annotations to the new urls when a multilingual site moves. The rules for them, from Google’s page on localized versions:
- every language version lists itself and every other version;
- the annotations are reciprocal — if two pages do not point at each other, Google ignores them;
- the urls are fully qualified, with https:// and the host, not /de/kontakt;
- language codes are ISO 639-1, optionally with an ISO 3166-1 alpha-2 region: de, de-AT, en-GB;
- x-default names the page for every language not listed;
- they go in the html head, in http headers or in the sitemap — one method is enough.
<!-- on https://example.com/de/unternehmen, and the same set on each of the others --> <link rel="alternate" hreflang="en" href="https://example.com/company" /> <link rel="alternate" hreflang="de" href="https://example.com/de/unternehmen" /> <link rel="alternate" hreflang="fr" href="https://example.com/fr/entreprise" /> <link rel="alternate" hreflang="x-default" href="https://example.com/company" />
Two migration-specific checks. Hreflang should point at the final urls that answer 200 — an annotation left on an old url that now redirects sends search engines through a hop for every pair, and leftovers like that are typical of a template that hardcoded the old structure. And the set has to be complete on the new site from the first day: one language published a week later leaves the others pointing at pages that do not exist yet.
Platforms with built-in localisation generate the tags. Webflow’s localized seo settings add hreflang to the page head and the generated sitemap automatically, with a toggle to switch it off; a custom sitemap then needs the tags added by hand. On WordPress the translation plugin writes them. Either way, check the rendered html of a few pages per language rather than trusting the setting.
Do not redirect by browser language
A relaunch is often when someone asks for the homepage to send visitors to their language automatically. Google advises against redirecting based on what you think the user’s language may be, because it can stop users and search engines from reaching all versions — and it notes that most of its crawls originate from the US without varying location. A 301 from / to /de/ for every German browser makes the root url mean different things to different visitors.
Keep the permanent redirects for urls that moved, the same for every visitor; offer language with a banner or a picker. The redirect map should contain no rule whose target depends on who is asking.
Testing a multilingual migration
- Request a sample of old urls per language and per host, with the old host name, before dns changes: one 301 to the same language, then 200.
- Filter the redirect file by each language prefix and look for targets in another language.
- Crawl the new site and compare each page's hreflang set with its partners: same set everywhere, every url 200, every page listing itself.
- Keep old subdomains and country domains registered and answering with redirects for at least a year; Google recommends keeping redirects at least that long.
For the matching itself, Silentfrog crawls both sites and builds the per-language rows and the folder wildcards; the first 50 pages of the old site are free, enough to see whether one language matches cleanly.
In short
- One redirect map per language; the target is always in the language of the source.
- Unchanged slugs: one wildcard per language folder. Translated slugs: one row per page.
- Subdomains and country domains need their redirects served on those hosts after the switch.
- ?lang= parameters need server rules on the query string; path-only importers cannot express them.
- Rebuild hreflang on the new urls: self-referencing, reciprocal, fully qualified, pointing at 200 pages.
- No automatic redirects by browser language or location.