practice
Internationalisation
also called i18n
Designing so that language, region and culture are parameters rather than assumptions — cheap upfront and very expensive to retrofit.
Definition
Internationalisation is structuring a system so it can be adapted to different languages and regions. Localisation is the adaptation itself.
What it affects beyond translated strings
- Formatting. Dates, numbers, currencies, addresses, names and phone numbers all vary. Formatting must use locale-aware libraries, never string concatenation.
- Time zones. Store instants in UTC; render in the user's zone; and store the zone identifier rather than an offset for future events, because offsets change with daylight saving and political decisions.
- Text direction. Right-to-left languages require layout that mirrors, which is a design and CSS concern rather than a translation one.
- Text expansion. Translated text is frequently 30–50% longer. Fixed-width layouts break.
- Sorting and searching. Collation is locale-specific; the same list sorts differently in different languages.
- Name and address models. Assuming first and last name, or a postcode format, excludes large parts of the world. This is a data model decision, and it is the most expensive one to retrofit.
- Content, not just labels. Emails, notifications, error messages, PDFs and support content.
The architectural decisions
- Locale as a request parameter, propagated through every layer including asynchronous work — an email sent by a background job needs the user's locale, which must have travelled with the job.
- No user-visible strings in code. Externalised from the start; retrofitting means finding every one.
- Pluralisation handled by a library. Languages have different plural rules, and no amount of string interpolation covers them.
- Locale-aware data storage for anything that will be sorted or searched.
- Content stored per locale, with a defined fallback chain.
Why retrofitting is so expensive
The cost is not translation. It is that assumptions are embedded everywhere: in the data model, in formatting code, in layout, in test fixtures, in URLs, and in business logic that assumed one currency or one address format.
Doing the structural work upfront costs little; discovering it later means touching every layer.
Failure scenarios
- String concatenation for messages, which cannot be translated correctly.
- Offsets stored instead of zone identifiers, so future events shift when rules change.
- Fixed-width layouts breaking on longer translations.
- Name and address assumptions in the data model.
- Locale not propagated to asynchronous work.
Interview question
"What must be designed for internationalisation on day one, and what can genuinely wait?"