Localizing the marketing site into 38 languages — and what we deliberately didn't translate

Publikované autor The Language Level Check team

The marketing site shipped initially in English. Deliberate “do the minimum, watch the data” choice. We wanted to know whether non-English traffic was finding us at all before committing to the work of localizing.

The data was clear enough. A significant majority of our web traffic came from non-English-speaking countries, primarily landing on language-specific pages via search for queries in their native language. Search engines were doing a great job of finding us. The site was then making those visitors read English. That’s a translation gap, not a traffic gap.

So this week we shipped a redesign that includes:

  • Full localization of the UI chrome into 38 locales, including the few regional variants (es-MX, pt-PT, en-GB, en-AU) that didn’t end up in the final language picker but exist in the i18n tables for completeness.
  • Locale-prefixed URLs for every page (/ja/languages/japanese, /de/faq, etc.), with proper hreflang metadata so search engines understand the relationship.
  • Localized app screenshots. We generated screenshots in every locale, so the Japanese version of the site shows the Japanese version of the app. The automated capture run across all 38 locales took most of a day.
  • Localized language-name search. When a German user types “Japanisch” into the language picker, they should find Japanese. We built a search index keyed by the localized language name in every supported locale.
  • A small but cute touch: when a Japanese user lands on the homepage, the hero image shows a French test question (because Japanese users testing themselves on a foreign language are probably not testing themselves on Japanese). The mapping is deliberate per locale.

What we deliberately did not translate

Two things stayed in English:

  • The test content itself. Test prompts, options, and reading passages stay in the target language. That’s the entire point of the test. A Spanish A2 question doesn’t become more accessible in Japanese. It stops being a Spanish A2 question.
  • This blog. Posts here are written by our team in English. Translating every post into 33 languages would either slow our release cadence to a crawl or produce machine-translated content we couldn’t quality-check. We added a small banner on non-English versions of the blog explaining this.

The general principle: localize anything that helps a user decide whether to use the product. Don’t localize things where the translation would degrade quality faster than the English original.

What we learned doing i18n on a static site

We built the localization as a thin layer over our existing static-site setup rather than pulling in a third-party i18n framework. A few things that worked well, a few that didn’t.

Worked well:

  • A single TypeScript module with one translation record per locale, accessed through a small useTranslations(locale) helper. We considered per-locale JSON files but the single module gives us autocomplete and type-checking for free.
  • Locale routing driven off a supported-locales list, with each page generating its variants at build time. Adding a locale is roughly one line.
  • Trailing-slash off across the board. Search engines do not need both /languages/japanese and /languages/japanese/ indexed.

Didn’t work well:

  • We let regional variant locales (es-MX, fr-CA) live in the i18n tables for a while before realizing nothing in the UI surfaced them. They’re still there for the future, but we removed them from the language picker because they were confusing users who couldn’t find their language.
  • We had a brief period where the Japanese version of the hero image was the Japanese question screenshot. Which makes no sense. Japanese users would want to see a non-Japanese test screen, because they’re testing themselves on a language other than their own. We fixed this with a per-locale screenshot mapping.

What the data showed afterwards

A few weeks after the localized site shipped, our top entry pages started including locale-prefixed paths (/ru/languages/russian, for example) for the first time. Search engines are now ranking the localized versions for native-language queries. The canonical English versions still rank higher overall in many cases, but the localized share is climbing.

The biggest remaining gap is China, which sends us a surprising volume of traffic but where our App Store routing was, until recently, sending desktop visitors to the US store. That’s a separate post.