The app and the site in English, Ukrainian and Russian

Until today the app’s interface was in Russian only, while the site already spoke three languages. Someone who came from the Ukrainian page, downloaded the app and opened it saw Russian. Now the app and the site both work in English, Ukrainian and Russian.

In the app

The app takes the first of these three languages from your macOS language list. If none of them is there, it uses English. In Settings you can choose a language yourself, and it applies at once, without a restart.

Where we store the choice matters. It goes to the same place that the system’s own per-app language setting (System Settings, General, Language and Region, Applications) writes to. So the two switches cannot disagree, and the choice survives a restart with no extra code. “Follow the system” is simply the absence of a saved choice.

Switching at once turned out to be the harder half. The usual way to load strings in a Mac app reads the language at launch and never changes it. We load the strings through our own object that can swap the language while the app runs. A missing string falls back to English, and then to the key itself, so a gap shows up as a visible oddity instead of blank space.

The menu was the first trap. Windows redraw themselves, but a menu holds finished text. The app lives in the menu bar, so forgetting this would mean the language changed everywhere except the place you use most. The second trap came after: several places had stored a finished sentence, not the thing to translate. A permission test result, the status message on the dictation panel, the loading label of the pinned translation window. Each had to remember the reason for the message, so a language switch could reach it. Old history entries had the Russian words for “dictation” and “secretary” written inside them, so they stayed Russian after a switch. They are now mapped to language-neutral labels.

Two things we left alone on purpose. The words you can say aloud for punctuation are recognition data, not interface, so they were not translated with the interface. And the interface language and the speech language are different things: you can dictate in Ukrainian on an English Mac. One does not change the other.

The texts of the system’s permission requests have their own files, because macOS draws those windows itself. After a manual language change, the new language appears there from the next launch.

On the site

Each language now has its own address: the root for English, /ru/ for Russian, /uk/ for Ukrainian. The text is in the page itself, not swapped by a script after loading, so search engines can read each language separately.

At first the root address picked the language from the browser. But a visitor in Ukraine with a Russian or English browser would have stayed on the English page, and we wanted the Ukrainian version to open first for visitors in Ukraine. So the site now looks at the visitor’s country as well. Once you click the language switcher, your choice wins on every later visit.

More from the blog