[erlang-questions] Read out the operating system language

Richard A. O'Keefe <>
Tue Mar 22 00:37:49 CET 2016

On 22/03/16 2:23 am, Michael S wrote:

> Not the type ;)
> I mean the language english, german, spanish, french etc.

The operating system doesn't *have* a language.
In the C / UNIX world, "language" is broken up into facets:
     $LANG             - ultimate default
       $LC_ALL         - interim default
         $LC_COLLATE   - how to compare strings
         $LC_CTYPE     - how to classify characters
         $LC_MESSAGE   - how to display error/warning/info messages
         $LC_MONETARY  - how to display amounts of money
         $LC_NUMERIC   - how to display numbers
         $LC_TIME      - how to display dates and times

When you ask about a particular facet, if that facet is not set,
LC_ALL will be tried, and if that is not set, LANG will be tried.
Locales include
     C                 - the ASCII-ish default from the C standard
     POSIX             - the ASCII-ish default from the POSIX standard
The locale names are less standardised than one would like.
The format is *typically* as shown, where the <language> is a 2-letter
ISO language code if the language has one, a 3-letter ISO code if it
doesn't, and dear knows what if it hasn't even one of those.
That's usually in lower case.
The <territory> is a 2-letter ISO country code if it has one, a
3-letter ISO code if it doesn't, and whatever otherwise.
That's usually in upper case.
The <encoding> could be UTF-8, GBK, KOI8-U, ISO8859-n, &c.
You might think it's upper case, but you might get BIG5 or Big5,
EUC-JP or eucJP, and so on.
The <variant> is used for things like @euro, @bokmal, @nynorsk

As a rough suggestion, try
in that order until one of them starts with a bunch of letters
and is not C or POSIX.

language() ->
     case check_language("LC_MESSAGES")
       of {yes,Lang} -> Lang
        ; no ->
          case check_language("LC_ALL")
            of {yes,Lang} -> Lang
             ; no ->
               case check_language("LANG")
                 of {yes,Lang} -> Lang

check_language(Source) ->
     case os:getenv(Source)
       of false                     -> no
        ; Chars when is_list(Chars) -> check_language(Chars, [])

check_language([Char|Chars], Acc)
   when Char >= $a, Char =< $z ->
     check_language(Chars, [Char|Acc]);
check_language([Char|Chars], Acc)
   when Char >= $A, Char =< $Z ->
     check_language(Chars, [Char+32|Acc]);
check_language([], "c") ->
check_language([], "xisop") ->
check_language([_|_], []) ->
check_language(_, Acc) ->
     {yes, lists:reverse(Acc)}.

Much depends on what you want this for.  If you are going to
use it for reporting messages, you really want to pay attention
to the *whole* of $LC_MESSAGES, lest you display semi-
comprehensible text with risible spelling and grammar errors,
as will happen if you generate en_US text for an en_NZ user.

One reason for @ variants is that countries sometimes
go through spelling reforms, although from what a German
student a couple of years ago told me, not always successfully.
Point is, you might need a date or revision name as well as
language and territory.

More information about the erlang-questions mailing list