Hreflang tells Google which language or regional version of a page to show to whom: a user with a Ukrainian interface gets /ua/, a user with an English one gets /en/. Without this markup a multilingual website often ranks with the "wrong" version: the Ukrainian page shows up in Polish search results while the English one is never treated as a separate page at all. Below we break down what the hreflang attribute actually does, the three ways to declare it, which language and region codes are valid, and where multilingual sites usually break the markup.

The hreflang attribute links together pages with the same content in different languages or for different countries. Google reads that link and, for each country or interface language, serves the most appropriate version in search results. The key word here is "serves": all versions must already be indexed, hreflang only helps pick one of them for a specific user.
What hreflang does not do, and this is where most of the confusion lives:
/en/ page still has Ukrainian text on it, Google will notice, and hreflang will not help.The practical takeaway is simple. If you have one language and one market, you do not need hreflang at all. You need it when there are at least two language versions, or one language for several countries with different prices or shipping (en-US and en-GB, for instance).
Google accepts the markup from three sources, and all three are equal. Pick one method for the whole site, because mixing them produces conflicts that are hard to track down later.
The most common option for CMS-based sites. On every version of the page, the <head> lists all versions, including the page itself:
<link rel="alternate" hreflang="uk" href="https://site.ua/ua/dostavka/" />
<link rel="alternate" hreflang="ru" href="https://site.ua/dostavka/" />
<link rel="alternate" hreflang="en" href="https://site.ua/en/delivery/" />
<link rel="alternate" hreflang="x-default" href="https://site.ua/ua/dostavka/" />
Upside: visible in the source, easy to eyeball. Downside: on a site with 20,000 pages and five languages every page gets five or six extra lines, so the CMS has to generate this, not a person.
For non-HTML files such as PDF catalogues, the server response carries a header:
Link: <https://site.ua/ua/catalog.pdf>; rel="alternate"; hreflang="uk", <https://site.ua/en/catalog.pdf>; rel="alternate"; hreflang="en"
A rare method, configured at the server level. Nobody uses it for regular pages.
Every <url> in the sitemap is extended with <xhtml:link> elements listing all versions. An example for one page:
<url><loc>https://site.ua/ua/dostavka/</loc><xhtml:link rel="alternate" hreflang="uk" href="https://site.ua/ua/dostavka/"/><xhtml:link rel="alternate" hreflang="en" href="https://site.ua/en/delivery/"/></url>
Upside: page HTML stays lean, everything sits in one file that is easy to generate and validate with a script. Downside: the sitemap grows, and on large catalogues you end up splitting it into several files. At Query we tend to choose the sitemap for stores with tens of thousands of pages, while for small service sites the link tag in the head is more convenient.
Reciprocity means this: if page A points to page B as its English version, page B must point back to A as the Ukrainian version. Google ignores a one-way link completely, and this is the single most common reason behind "we added hreflang and nothing changed". You have to check pairs, not individual pages.
x-default says which version to show to people whose language and country match none of the listed ones. For a Ukrainian site with uk/ru/en, it makes sense to point x-default either to the English version (for foreign visitors) or to a language selector page if one exists. Pointing x-default to the Ukrainian version is also acceptable: then undetermined users see the primary version. What matters is that there is exactly one x-default and it leads to a real page returning a 200 code.
The language is written in ISO 639-1 (two letters), the region in ISO 3166-1 Alpha-2 after a hyphen. A region without a language is not allowed: hreflang="UA" is invalid, you need uk-UA. The most frequent mistake involves Ukrainian: its code is uk, not ua. The value ua is a domain, not a language, and Google does not recognise it.
| Code | Meaning | When to use |
|---|---|---|
| uk | Ukrainian, any country | Standard for the Ukrainian version |
| uk-UA | Ukrainian for Ukraine | Only with another Ukrainian version |
| ru | Russian, any country | Version not tied to a country |
| en | English, any country | One English version for all |
| en-GB, en-US | English for the UK / US | Different prices, currency, delivery |
| x-default | Version "for everyone else" | Once per set |
If you have a single English version, write plain en. Adding a region "just in case" is a bad idea: en-US narrows the audience, and a British user formally falls outside it, even though Google does try to pick the closest language.
In our experience, on most sites that come to us for technical SEO, the markup is either broken or missing entirely. The mistakes repeat from site to site.
| Mistake | Consequence | Fix |
|---|---|---|
| No return link | Google ignores the pair | One list of versions on every page |
| Points to a non-canonical page | Conflicting signals | Canonical URLs only |
| Relative URLs | Invalid markup | Absolute URLs with the domain |
| Conflict with canonical | A version drops out | Each version canonical to itself |
| Several languages on one URL | Versions are not linked | One language = one URL |
| Code ua instead of uk | Version without markup | Replace the code in the template |
| Points to noindex, 404, redirect | The pair breaks | Check versions before output |
| No translation, but hreflang | Link to a missing page | Only really translated pages |

&gl=gb&hl=en and see which version appears. This is the most honest test.The official requirements and examples for all three methods are collected in Google's documentation on localized versions. Where a validator and the documentation disagree, Google is right.
The typical setup for a Ukrainian business: Ukrainian as the primary language, Russian for part of the audience, English for export or foreign clients. A few practical recommendations we give in such projects.
/ua/, but consistently across the whole site. A mixed structure where some pages have the prefix and others do not destroys the markup.ru with no region. ru-UA is justified only when there is another ru version for a different country.uk, not ua.Hreflang does not add rankings, it removes losses. When the right version is shown to the right user, CTR grows and the "wrong language" bounces disappear. For a site with two or three languages this is one or two days of developer work plus half a day of checks, and that investment pays back reliably.