The thoughts of G. Allen Morris III

Creating a new locale and using it on Debian

August 25th 2018

I am now living in Amsterdam and as such wanted to set my local to reflect my new location.

One simple way to achive this is to set each of the different Locale Information Categories.

LANG=en_US
LC_CTYPE=en_US
LC_NUMERIC=nl_NL
LC_TIME=en_GB
LC_COLLATE=en_US
LC_MONETARY=nl_NL
LC_MESSAGES=en_US
LC_PAPER=nl_NL
LC_NAME=nl_NL
LC_ADDRESS=nl_NL
LC_TELEPHONE=nl_NL
LC_MEASUREMENT=nl_NL
LC_IDENTIFICATION=en_DK

And for the most part this would work, but I am not sure I like the date format.

The 'nl_NL' locale displays the date as 'za 25 aug 2018 12:58:42 CEST'. Where 'enGB' displays it as 'Sat 25 Aug 13:00:16 CEST 2018'. Which is better than the 'enUS' locale which uses 'Sat Aug 25 12:59:54 CEST 2018'.

Hovever, I would really like it to be 'sa 25 aug 2018 12:58:42 CEST', as I just want it in English. I had some hope the 'enDK' would give me a nice date format, but it seems to just use a format very similar to 'enUS'.

The only solution, that I know of, if you want you own LC_TIME format is to write your own local file. This is not very difficult. As you'll see below the integration was a much larger problem.

Basically by using the copy command you can do almost the same thing as was done above using the Locale Information Categories.

LC_CTYPE
copy "en_US"
END LC_CTYPE

LC_NUMERIC
copy "nl_NL"
END LC_NUMERIC

LC_COLLATE
copy "en_GB"
END LC_COLLATE

LC_MONETARY
copy "nl_NL"
END LC_MONETARY

LC_MESSAGES
copy "en_US"
END LC_MESSAGES

LC_PAPER
copy "nl_NL"
END LC_PAPER

LC_NAME
copy "nl_NL"
END LC_NAME

LC_ADDRESS
copy "nl_NL"
END LC_ADDRESS

LC_TELEPHONE
copy "nl_NL"
END LC_TELEPHONE

_MEASUREMENT
copy "nl_NL"
END LC_MEASUREMENT

The LC_IDENTIFICATION section just describes the locale.

LC_IDENTIFICATION
title      "English locale for The Netherlands"
source     "None"
address    "Hekelvel 1, Amsterdam, Netherlands 1012SN"
contact    ""
email      "gam3@gam3.org"
tel        ""
fax        ""
language   "English"
territory  "Netherlands"
revision   "1.0"
date       "2018-08-21"

Then we come to the LC_TIME section. All we have to do here is change the name of the days of the week from Dutch to English and we will be done.

LC_TIME
abday   "<U007A><U006F>";"<U006D><U0061>";"<U0064><U0069>";/
        "<U0077><U006F>";"<U0064><U006F>";"<U0076><U0072>";/
        "<U007A><U0061>"
day     "<U007A><U006F><U006E><U0064><U0061><U0067>";/
        "<U006D><U0061><U0061><U006E><U0064><U0061><U0067>";/
        "<U0064><U0069><U006E><U0073><U0064><U0061><U0067>";/
        "<U0077><U006F><U0065><U006E><U0073><U0064><U0061><U0067>";/
        "<U0064><U006F><U006E><U0064><U0065><U0072><U0064><U0061><U0067>";/
        "<U0076><U0072><U0069><U006A><U0064><U0061><U0067>";/
        "<U007A><U0061><U0074><U0065><U0072><U0064><U0061><U0067>"
abmon   "<U006A><U0061><U006E>";"<U0066><U0065><U0062>";/
        "<U006D><U0072><U0074>";"<U0061><U0070><U0072>";/
        "<U006D><U0065><U0069>";"<U006A><U0075><U006E>";/
        "<U006A><U0075><U006C>";"<U0061><U0075><U0067>";/
        "<U0073><U0065><U0070>";"<U006F><U006B><U0074>";/
        "<U006E><U006F><U0076>";"<U0064><U0065><U0063>"
mon     "<U006A><U0061><U006E><U0075><U0061><U0072><U0069>";/
        "<U0066><U0065><U0062><U0072><U0075><U0061><U0072><U0069>";/
        "<U006D><U0061><U0061><U0072><U0074>";/
        "<U0061><U0070><U0072><U0069><U006C>";/
        "<U006D><U0065><U0069>";/
        "<U006A><U0075><U006E><U0069>";/
        "<U006A><U0075><U006C><U0069>";/
        "<U0061><U0075><U0067><U0075><U0073><U0074><U0075><U0073>";/
        "<U0073><U0065><U0070><U0074><U0065><U006D><U0062><U0065><U0072>";/
        "<U006F><U006B><U0074><U006F><U0062><U0065><U0072>";/
        "<U006E><U006F><U0076><U0065><U006D><U0062><U0065><U0072>";/
        "<U0064><U0065><U0063><U0065><U006D><U0062><U0065><U0072>"
d_t_fmt "<U0025><U0061><U0020><U0025><U0064><U0020><U0025><U0062><U0020><U0025><U0059><U0020><U0025><U0054><U0020><U0025><U005A>"
d_fmt   "<U0025><U0064><U002D><U0025><U006D><U002D><U0025><U0079>"
t_fmt   "<U0025><U0054>"
am_pm   "";""
t_fmt_ampm ""
date_fmt       "<U0025><U0061><U0020><U0025><U0065><U0020><U0025><U0062>/
<U0020><U0025><U0059><U0020><U0025><U006B><U003A><U0025><U004D><U003A>/
<U0025><U0053><U0020><U0025><U005A>"

week    7;19971130;4
first_weekday 2
END LC_TIME

And the English version

LC_TIME
abday   "<U0073><U0075>";"<U006D><U006F>";"<U0074><U0075>";/
        "<U0077><U0065>";"<U0074><U0068>";"<U0066><U0072>";/
        "<U0073><U0061>"
day     "<U0073><U0075><U006E><U0064><U0061><U0079>";/
        "<U006D><U006F><U006E><U0064><U0061><U0079>";/
        "<U0074><U0075><U0065><U0073><U0064><U0061><U0079>";/
        "<U0077><U0065><U0064><U006E><U0065><U0073><U0064><U0061><U0079>";/
        "<U0074><U0068><U0075><U0072><U0073><U0064><U0061><U0079>";/
        "<U0066><U0072><U0069><U0064><U0061><U0079>";/
        "<U0073><U0061><U0074><U0065><U0072><U0064><U0061><U0079>"
abmon   "<U006A><U0061><U006E>";"<U0066><U0065><U0062>";/
        "<U006D><U0061><U0072>";"<U0061><U0070><U0072>";/
        "<U006D><U0061><U0079>";"<U006A><U0075><U006E>";/
        "<U006A><U0075><U006C>";"<U0061><U0075><U0067>";/
        "<U0073><U0065><U0070>";"<U006F><U0063><U0074>";/
        "<U006E><U006F><U0076>";"<U0064><U0065><U0063>"
mon     "<U006A><U0061><U006E><U0075><U0061><U0072><U0079>";/
        "<U0066><U0065><U0062><U0072><U0075><U0061><U0072><U0079>";/
        "<U006D><U0061><U0072><U0063><U0068>";/
        "<U0061><U0070><U0072><U0069><U006C>";/
        "<U006D><U0065><U0079>";/
        "<U006A><U0075><U006E><U0065>";/
        "<U006A><U0075><U006C><U0079>";/
        "<U0061><U0075><U0067><U0075><U0073><U0074>";/
        "<U0073><U0065><U0070><U0074><U0065><U006D><U0062><U0065><U0072>";/
        "<U006F><U0063><U0074><U006F><U0062><U0065><U0072>";/
        "<U006E><U006F><U0076><U0065><U006D><U0062><U0065><U0072>";/
        "<U0064><U0065><U0063><U0065><U006D><U0062><U0065><U0072>"
d_t_fmt "<U0025><U0061><U0020><U0025><U0064><U0020><U0025><U0062><U0020><U0025><U0059><U0020><U0025><U0054><U0020><U0025><U005A>"
d_fmt   "<U0025><U0064><U002D><U0025><U006D><U002D><U0025><U0079>"
t_fmt   "<U0025><U0054>"
am_pm   "";""
t_fmt_ampm ""
date_fmt       "<U0025><U0061><U0020><U0025><U0065><U0020><U0025><U0062>/
<U0020><U0025><U0059><U0020><U0025><U006B><U003A><U0025><U004D><U003A>/
<U0025><U0053><U0020><U0025><U005A>"

week    7;19971130;4
first_weekday 2
END LC_TIME

To make it easier to edit I converted the Unicode to ascii with a very simple ruby script

STDIN.each_line do |line|
  puts line.chomp.gsub!(/<U([^>]*)>/) {|match, b| "<" + $1.hex.chr.to_s + ">" }
end

and then restored it with

STDIN.each_line do |line|
  puts line.chomp.gsub!(/<(.)>/) {|match, b|
    "<" + ("U%04x" % $1.ord).upcase + ">"
  }
end

Configuration

To generate the locale files from the locale definision we need to run the localedef command.

localedef -i en_NL -f UTF-8 en_NL.UTF-8
localedef -i en_NL -f ISO-8859-1 en_NL.ISO8859-1
localedef -i en_NL -f ISO-8859-15 en_NL.ISO8859-15

We could also add the following to the /etc/locale.gen file and run the locale-gen command.

en_NL.en_NL.ISO8859-1
en_NL.en_NL.ISO8859-15
en_NL.UTF-8

X11

For X11 to work with our new locale we need to add text to 2 files: /usr/share/X11/locale/locale.dir, and /usr/share/X11/locale/locale.alias. As shown below.

UTF-8/XLC_LOCALE:                       en_NL.UTF-8
iso8859-1/XLC_LOCALE                    en_NL.ISO8859-1
iso8859-15/XLC_LOCALE                   en_NL.ISO8859-15

and

en_NL                                           en_NL.ISO8859-1
en_NL.iso88591                                  en_NL.ISO8859-1
en_NL.ISO-8859-1                                en_NL.ISO8859-1
en_NL.iso885915                                 en_NL.ISO8859-15
en_NL.ISO-8859-15                               en_NL.ISO8859-15
en_NL.utf8                                      en_NL.UTF-8
en_NL:                                          en_NL.ISO8859-1
en_NL.iso88591:                                 en_NL.ISO8859-1
en_NL.ISO-8859-1:                               en_NL.ISO8859-1
en_NL.iso885915:                                en_NL.ISO8859-15
en_NL.ISO-8859-15:                              en_NL.ISO8859-15
en_NL.utf8:                                     en_NL.UTF-8

gitlab

You can find all the code on gitlab.