How the setlocale() works in OpenSolaris
By Jan Lana on Feb 18, 2009
Programs should respect locale specific way how to format date, time, numbers, how to sort strings, etc. People in different regions use different ways how to write such things and it is very confusing for them if you for example want write a date and write day, month and year in wrong order.
Near all programs use for this functions from libc like strftime(3C), strcoll(3C), ... Not all - Java for example does not use the libc functions and does it by itself - it is the reason why java programs do the things equally on all platforms but sometimes differently that non-java programs on the same platform.
All programs which want to use the libc locale data must call setlocale(3C):
char \*setlocale(int category, const char \*locale);
First parameter is locale category - LC_MONETARY, LC_TIME, ... The second is name of locale you want to use - "en_US.UTF-8", "cs_CZ.ISO8859-2", ...
The setlocale() initializes internal date structures for the locale. If you forget to call the setlocale(), your program will use the POSIX locale, also known as the C locale. 'C' locale is special - it is available everytime, the others locales are optional and you need to install them.
Most common way how to call the setlocale() function is
it sets all locale categories to locale defined by env. variables LANG, LC_ALL, LC_CTYPE, ... Interesting is to call the function with NULL as the second parameter - it returns name of current locale.
How does the setlocale() works? It expand the second argument, try locale cache and if not found the locale there, try to load it. Locale data are in locale objects. Locale objects are shared libraries in the path
on 64bit platforms
/usr/lib/locale/<locale>/amd64/<locale>.so.3 resp. /usr/lib/locale/<locale>/sparcv9/<locale>.so.3
If the file exists, setlocale() dlopen the shared objects and initialize the locale structures in memory by calling instantiate() function. The new locale object is ready to use. The structures contains information about locale and the rest of libc functions will use them. But program can use different locales for different locale categories. Then more locale objects are loaded and a composite locale is created from them.
If something fails, setlocale() return NULL and the program's locale is not changed.
You can check some data in the locale objects by command locale(1):
$ LC_ALL=cs_CZ.UTF-8 locale -ck LC_TIME LC_TIME d_t_fmt="%e. %B %Y %k:%M:%S %Z" d_fmt="%e.%m.%y" t_fmt="%k:%M:%S" t_fmt_ampm="" am_pm="dop.";"odp." day="neděle";"pondělí";"úterý";"středa";"čtvrtek";"pátek";"sobota" abday="ne";"po";"út";"st";"čt";"pá";"so" mon="ledna";"února";"března";"dubna";"května";"června";"července";"srpna";"září";"října";"listopadu";"prosince" abmon="led";"úno";"bře";"dub";"kvě";"črn";"črc";"srp";"zář";"říj";"lis";"pro" era="" era_d_fmt="" era_d_t_fmt="" era_t_fmt="" alt_digits=""
In OpenSolaris the locales objects are in SUNWlang-\* pkgs.
You can create your own locales by command localedef(1). If you put result of the localedef cmd to the /usr/lib/locale/<your locale>/[amd64|sparc|]/<your locale>.so.3, the next call of setlocale() will find and use it.