On 12 September Lonevi, a longevity product in the group's catalogue, changed the language it speaks by default. Until that day an unprefixed address such as lonevi.com/articles answered in Russian, and English lived under /en. A product meant for readers worldwide introduced itself in Russian to anyone who had not chosen a language, and its sitemap listed only Russian addresses. Now English holds the unprefixed addresses and Russian moved to /ru.

It sounds like a setting. It is not one, and this note is about why.

A default language is an address layout

The product follows one rule for public pages: the default language lives at the bare address, every other language carries a prefix. So flipping the default does not change which words are shown. It changes which page every existing address points at.

Before the change, production was measured rather than assumed. The sitemap listed 45 addresses, all of them unprefixed. 34 of those were articles, and their slugs were transliterated from Russian. The English version of the same article lives under a different slug. A naive flip would therefore have handed every indexed article address to a language that has no article there, and every one of them would have answered 404 — erasing exactly the search presence the change was made to grow.

The rules that replaced the naive flip:

  • /en/<anything> answers a permanent 308 redirect to the same path without the prefix, so old English links keep working.

  • An article address whose slug belongs to another language answers 308 to that language's prefix — but only on an explicit yes from the backend. If the backend is silent, the reader is not sent to a foreign address on a guess.

  • A slug that exists in no language stays a 404 rather than becoming a redirect to somewhere.

Defaults nobody had named

The server rendered a visitor's language from the address, then a cookie. The browser's Accept-Language preference reached it only on the next request, through a cookie set on the way out. While the default was Russian, a Russian browser's first page came out right by coincidence. The coincidence would have ended on the day of the flip. The order is now explicit: the language named by the address, then the cookie, then the browser's preference, then the default.

Separately, the change found four places where "the default is Russian" had been written without being named, and made each of them derive from a single declared default instead of retyping it: the prefix logic in the sign-in callback, the language declared in structured data, the anchor language of the sitemap's translation clusters, and a scattering of literal "ru" values in the backend beside a competing constant of its own.

The sitemap would have lost the whole Russian corpus

Review found the most expensive defect before release, and it was not a line of wrong code. The sitemap emitted one row per cluster of translations, anchored on the default language; the other languages appeared only as annotations inside that row. With Russian as the default, Russian addresses stood in the rows. With English as the default, the anchor becomes English — and the Russian corpus would have left the sitemap's address list at the very moment its addresses changed.

The sitemap now carries a row for every language variant. On production today it lists 101 addresses, 34 of them Russian articles under /ru/, 34 English articles beside them, and 21 in Kazakh under /kk/.

One more default, found after release

The flip shipped. The same day, production showed our own two signals about the same article disagreeing. The article's page declared the Russian version as the default for its translation cluster; the sitemap declared the English one. The page assembled its language set on its own and pinned the default to a literal 'ru', beside a comment saying Russian was the site's unprefixed canonical — a comment that became untrue on the day of the flip.

Nothing failed. Every page answered 200 and the sitemap looked healthy. But Google documents that it may ignore contradictory language annotations altogether, and every translated article carried the same contradiction. The discoverability the change was made for would simply not have arrived, and nothing would have said so.

The fix gave both consumers one source for the set, with the language order derived from the default rather than typed by hand. The release went out the same day, and since then the default is declared once on each side of the product.

Checked on production, 12–13 SeptemberAnswer
lonevi.com/200, page declared in English
lonevi.com/en308 to the root
Old unprefixed address of a Russian article308 to the same article under /ru/
A slug that exists nowhere404
Default of a translation cluster, in the page head and in the sitemapThe same English address in both

What the tests now ask

The check written for that last defect compares the two sources with each other, not each with its own expectation. A test that asks whether the page is right and a separate test that asks whether the sitemap is right will both pass in the world where they disagree — which is how the disagreement reached production. The check also asks the real page for its metadata instead of searching the page's source code for a function call: an earlier draft did the latter, and a mutant that removed the annotations from what the page returns left it green.

The flip also exposed tests that had been passing for the wrong reason. Several checks that a draft article is invisible to readers created the draft in the editorial default language and read it back without naming a language, that is, in the product's default. Both were Russian, so the draft was invisible — not because of the visibility filter, but because the reader was looking in the same place by coincidence. With the filter removed outright, 8 of 62 tests failed when reads named no language, and 14 failed once every read named its language. Six tests had been guarding nothing, and they now guard the filter.

What this is evidence of

A language switch is a routine request. The part worth describing is the discipline around it: measure the production state before touching it, count the places where an assumption is written without being named, make every fallback choose a side on purpose, and check two signals against each other rather than trusting each one alone. That is how we treat the products we build and ship.

The group