Decide once per product from your audience and brand voice, write it down where translators and AI can see it, apply it to every string, and know which languages make the choice visible.
Put a BCP 47 tag in the `lang` attribute of the root element, for example `<html lang="de">`. The `<meta http-equiv="content-language">` pragma is non-conforming in the HTML standard, and the `Content-Language` HTTP header describes the intended audience, not the language the page is written in.
Read `navigator.languages`, the user's ordered list of BCP 47 tags (`navigator.language` is its first entry), or the `Accept-Language` header on the server. Match that list against your supported locales with a language-only fallback, and let the user override the result.
Check what you can verify mechanically, placeholders, length, plurals and terminology, use a back-translation to check the meaning, and leave judgment of style to a native speaker.
Set a maximum length on the string key so every language is checked against it, then shorten the long translations by cutting filler, using the target language's natural short forms, or asking the AI Assistant to rewrite them within the limit.
Keep UI strings in resource files, not in tables. For user or editorial content, use a translation table per entity, such as `product_translations(product_id, locale, name, description)` with a unique key on `(product_id, locale)`, BCP 47 locale tags and a fallback locale in the query layer.
Use `en-US`. The hyphen is the BCP 47 form used by HTML `lang`, hreflang, `Accept-Language`, JavaScript `Intl` and Apple language IDs. The underscore `en_US` is the POSIX locale form that Java `Locale.toString()`, gettext and Android `values-en-rUS` use, so convert at those boundaries.
Simplified Chinese is `zh-Hans` and Traditional Chinese is `zh-Hant`, BCP 47 tags with an ISO 15924 script subtag. Add a region only when the market matters (`zh-Hans-CN`, `zh-Hant-TW`, `zh-Hant-HK`). The older `zh-CN` and `zh-TW` tags still work but only imply the script.
Pseudo-localization runs your app with source strings transformed to look translated (accented letters, 30 to 50 percent longer, bracketed, optionally right-to-left) while placeholders stay intact. It exposes hard-coded strings, concatenation and truncation before any real translation exists.