2022-09-09

I check the weather in Celsius, weigh espresso beans in grams, measure water in milliliters, estimate distances in meters, use a 24-hour clock, and write dates in big-endian order. These habits clash with US conventions, but I formed them deliberately out of a desire to be more forward-looking and globally oriented.

It’s long been a nuisance that in computing my language has been tied to customs that I aspire to leave behind. A locale typically is a single preset covering spell check language, date and time formatting, units of measurement, currency, paper size, and more. There are workarounds to an unfit locale—you can hunt for another preset that does what you want and then, for example, mix US currency with Denmark time—but this approach is often inadequate.

Today I finally took the time to learn how locales work and created one that reflects my own practices. It’s derived from en_US with the following changes:

Absent an ergonomic inheritance mechanism, the definition is verbose:

LC_IDENTIFICATION
title "English locale for the USA with SI units, 24-hour time, IETF RFC 3339, ITU-T E.164, ten-digit dialing, and weekbeginnings"
language "American English"
territory "United States"

category "i18n:2012";LC_ADDRESS
category "i18n:2012";LC_COLLATE
category "i18n:2012";LC_CTYPE
category "i18n:2012";LC_IDENTIFICATION
category "i18n:2012";LC_MEASUREMENT
category "i18n:2012";LC_MESSAGES
category "i18n:2012";LC_MONETARY
category "i18n:2012";LC_NAME
category "i18n:2012";LC_NUMERIC
category "i18n:2012";LC_PAPER
category "i18n:2012";LC_TELEPHONE
category "i18n:2012";LC_TIME
END LC_IDENTIFICATION

LC_ADDRESS
copy "en_US"
END LC_ADDRESS

LC_COLLATE
copy "en_US"
END LC_COLLATE

LC_CTYPE
copy "en_US"
END LC_CTYPE

LC_MEASUREMENT
# SI units
copy "i18n"
END LC_MEASUREMENT

LC_MESSAGES
copy "en_US"
END LC_MESSAGES

LC_MONETARY
copy "en_US"
END LC_MONETARY

LC_NAME
copy "en_US"
END LC_NAME

LC_NUMERIC
copy "en_US"
END LC_NUMERIC

LC_PAPER
copy "en_US"
END LC_PAPER

LC_TELEPHONE
# Duplicated from en_US
int_prefix "1"
int_select "11"

# Ten-digit dialing
tel_dom_fmt "%a-%l"

# ITU-T E.164
tel_int_fmt "+%c%a%l"
END LC_TELEPHONE

LC_TIME
# Duplicated from en_US
week 7;19971130;1
day "Sunday";"Monday";"Tuesday";"Wednesday";"Thursday";"Friday";"Saturday"
abday "Sun" ;"Mon" ;"Tue" ;"Wed" ;"Thu" ;"Fri"; "Sat"
mon "January";"February";"March";"April";"May";"June";"July";"August";"September";"October";"November";"December"
abmon "Jan" ;"Feb" ;"Mar" ;"Apr" ;"May";"Jun" ;"Jul" ;"Aug" ;"Sep" ;"Oct" ;"Nov" ;"Dec"

# Weekbeginnings
first_weekday 7

# 24-hour time
t_fmt "%T"
t_fmt_ampm ""
am_pm "";""

# IETF RFC 3339
d_fmt "%F"
d_t_fmt "%FT%T%:z"
date_fmt "%FT%T%:z"
END LC_TIME

I’m happy to have this in place now, but stepping back, it was too much work for something that I’d hoped other people might emulate.