A bilingual site is not two versions of the text but an agreement with the search engine: this page is in Ukrainian, here is its counterpart in another language, show each person the one that suits them. The agreement is formalized with the hreflang attribute.
The problem is that a broken hreflang looks exactly like a working one: the site opens, the switcher works, the markup is there in the code. The error only becomes visible when you look for it deliberately.
Below are five real configurations we have come across while measuring Ukrainian sites.
1. hreflang set up twice, with the two sets contradicting each other
The most complex case we have seen. On a lingerie store, language markup had been added by two different mechanisms at once — probably by the theme and a separate extension that did not know about each other.
The first set declared ru-ru, uk-ua and pl, pointing to root URLs. The second declared ru, x-default and uk, pointing to URLs with the /ua/ prefix. On top of that, the link declared as uk-ua served Russian content, and the same was true of the Polish one.
For a search engine this is not “two opinions” but a contradiction it resolves at its own discretion — which most often means ignoring both sets.
2. The language code is wrong
On a military gear store, the language versions really did exist — the root one and /ua/. In the markup they were declared as uk-UA and uk-RU.
The second code does not mean “Russian for Ukraine”: the first part is the language, the second is the region. uk-RU reads as “Ukrainian language, Russia region”. The correct code for a Russian-language version of a Ukrainian site is ru-UA.
An extra touch on the same site: <html lang="ru"> on the root version, meaning the page’s language attribute contradicted what hreflang declared.
A separate variant of this error turned up in a sample of construction companies: the same language code declared twice — one site out of eight checked on 8 August 2026.
3. The sitemap contains only one language version
The site is bilingual, hreflang is declared correctly — but the sitemap has URLs in only one language. The second version exists for a person using the switcher and does not exist for a crawler that starts from the sitemap.
From real measurements:
- a spice store: all 590 unique URLs in the sitemap point to the Russian version, even though the code has
<html lang="uk"> and hreflang for Ukrainian is declared;
- a tool store: 100% of the URLs in the sitemap are Russian-language, while the site serves Ukrainian by default;
- a garden equipment store: the sitemap has only the Ukrainian-language branch; the Russian version is declared in hreflang but did not make it into the sitemap;
- a wholesale cosmetics store: not a single Russian-language URL in the sitemap, despite full bilingual support with a switcher.
There is no pattern in which language “disappears” — and that is the best proof that the cause is technical, not content-related: that is simply how the sitemap generator ended up configured, and nobody checked the result.
A subtler case. The language version exists, the interface is translated, <html lang="uk"> is set correctly — but the <title> and meta description stayed in the original language.
We saw this on the lingerie store: the Ukrainian-language /ua version had a translated interface and the correct language attribute, but its meta tags remained Russian. To a search engine such a page looks like a duplicate — meta tags are the primary way it tells pages apart.
This is the classic partial localization mistake: what is visible in the layout gets translated, and what is visible only in search results does not.
5. hreflang is there, but the second version is not
The reverse case: the markup declares language versions that physically do not exist — a leftover from plans or from a template. The search engine follows the link, gets a 404 or a redirect to the same page, and stops trusting the entire group.
A separate variant is hreflang with only one entry pointing to the page itself, plus x-default. Formally not an error, in practice markup that does nothing: a group of one page does not connect it to anything.
How to check your site
- Open the Ukrainian homepage and view the source: find all lines containing
hreflang. There should be as many as you have language versions, plus x-default if needed.
- Check the language codes:
uk-UA for Ukrainian, ru-UA for the Russian-language version of a Ukrainian site. Each code should appear exactly once.
- Open each hreflang link and make sure it opens exactly the language that is declared, and that the page returns 200, not a redirect.
- Check reciprocity: the page that hreflang points to must link back to the first one. Search engines ignore one-sided declarations.
- Compare
<html lang> with what hreflang declares — they should match.
- Check the sitemap: does it contain URLs for both language versions?
- Check the
<title> and meta description on the second language version — they should be translated, not inherited.
How much work is involved
The markup itself takes hours: it is a block of links in <head> generated from the list of a page’s language versions. What can be harder is untangling a situation where the theme and an extension both add markup at the same time: first you need to find both sources and disable one.
The most expensive item is usually the fourth — translating meta tags on every page of the second language version. This is no longer technical work but content work, and on a catalog of thousands of items it requires either a translator or automation followed by spot checks.
The limits of this data
The figures are measurements taken on specific dates (August 2026); we deliberately do not name the sites. The market sample of construction companies that the duplicated language code example comes from consisted of eight sites — so the “1 of 8” share describes those particular sites, not the market.