🌐 Localization

Updated at 2013-04-28 00:58

This note is about localization. Localization (l10n) is making an application work for a particular market, such as French-speaking Canadians.

Internationalization (i18n) is structuring applications in a way that makes it possible for them to be localized.

You should allow users to specify: location, language and currency:

  • Location and country are important when you are working with times.
  • Language is important if your content should be reachable to general public of a specific foreign country and when showing times.
  • Currency is important if you do e-commerce.

Use these standards (as of 2013):

  • ISO 639: Language codes
  • ISO 3166-1 alpha-2: Country codes
  • ISO 8601: Date and time backend format
  • ISO 4217: Currency codes

You can get starting localization parameters from HTTP header. But you should allow user to change the settings in the user interface e.g. save selection to a cookie.

// Language, use  ISO 639
Accept-Language: en,en-US,fr;q=0.6
Content-Language: en

// Currency, use ISO 4217 code
X-Currency: USD

Localizing Language

You should move all user-visible strings from your code into resource files. Titles, product names, error messages, strings in images etc.

Prefer using UTF-8. You can consider using UTF-16 if you are working primarily with Asian languages and absolutely need the efficiency.

<meta http-equiv="Content-Type" content="text/html; charset=utf-8">

// HTTP Header
Content-Type: text/html; charset=utf-8

Never concatenate multiple localization strings.

show_name = prdct.color +
// red pencil -> crayon rouge
// Adjective changes place in French.

Put all of your punctuation in the resourced string.

"Username:" in English.
"Nom d'utilisateur :" in French, with extra a space.

Give strings room to grow and shrink e.g. by placing labels over inputs. Repeat password is over 50% wider in German than in English.

Plan for languages that read right to left.

input { direction: rtl; }

Never sort alphabetically in pure JavaScript. JavaScript sucks at it.

Localizing Time

On servers, set hardware, operating system and database clocks to UTC.

Always store date and time using server time, not client time, so everything should be UTC if it not being shown to the user.

Use date library like Date.js, Moment.js, Carbon (PHP) to convert them to local time zone at the last possible moment.

When user inputs a date or time, convert it to UTC as soon as possible.

Store and transfer all dates in ISO 8601.


Store and transfer all times in ISO 8601.


Store and transfer all date times in ISO 8601.


Learn to use your databases time functions.

    date_trunc('year', '2013-04-05'::date) AS year,
    date_trunc('month', '2013-04-05'::date) AS month,
    date_trunc('day', '2013-04-05'::date) AS day;

--          year          |         month          |          day
-- 2013-01-01 00:00:00-05 | 2013-04-01 00:00:00-04 | 2013-04-05 00:00:00-04

    to_char('2013-04-05'::date, 'YYYY') AS year,
    to_char('2013-04-05'::date, 'MM-YYYY') AS month,
    to_char('2013-04-05'::date, 'YYYYMMDD') AS day;

-- year |  month  |   day
-- 2013 | 04-2013 | 20130405

SELECT to_timestamp(1365560673);

--      to_timestamp
-- 2013-04-09 22:24:33-04

A week has a different meaning in different places of the world.

In Estonia, week starts on Saturday.
In US, week starts on Sunday.
In UK/Finland, week starts on Monday.
In Maldives, week starts on Friday.

Localizing Currency

Note that some currencies use same symbol.

English, USA, US Dollars
Price: $99.00, Delivery: 8/1/2013 8:15:00 PM

Spanish, Mexico, Mexican Pesos
Precio: $1216.28, Entrega: 1/8/2013 20:15:00

Some people want to work with seemingly foreign currency for them.

English, Canada, Canadian Dollars
Price: CA$1.00, Delivery: 2013-08-01 8:15:00 PM

English, Canada, Peruvian Pesos
Price: 464.34 CLP, Delivery: 2013-08-01 8:15:00 PM