locale

From the msgcat TclHelp:

LOCALE AND SUBLOCALE SPECIFICATION

The locale is specified by a locale string. The locale string consists of a language code, an optional country code, and an optional system-specific code, each separated by "_". The country and language codes are specified in standards ISO-639 and ISO-3166. For example, the locale "en" specifies English and "en_US" specifies U.S. English.

The locale defaults to the value in env(LANG) at the time the msgcat package is loaded. If env(LANG) is not defined, then the locale defaults to "C".

When a locale is specified by the user, a "best match" search is performed during string translation. For example, if a user specifies en_UK_Funky, the locales "en_UK_Funky", "en_UK", and "en" are searched in order until a matching translation string is found. If no translation string is available, then ::msgcat::unknown is called.


bll 2018-8-5: See also: locale package


RS offers an example of locale-use in Tcl programming:

 proc monthname {date} {
     if ![info exists ::env(LANG)] {set ::env(LANG) "C"}
     set index $::env(LANG)
     if ![info exists ::monthnames($index)] {set index "C"}
     lindex $::monthnames($index) [clock format $date -format %m]
 }
 # These lists indexed by locale must have a dummy first argument
 #
 set monthnames(C) {- January February March April...}
 set monthnames(de_AT) {- Jänner Feber März April ...}
 ...

Victor Wagner has a locale patch [L1 ]. Ralf Fassel: Victors home page has moved, it is currently (2004/12) at http://www.45.free.net/~vitus/ice/tcl/ .


A special kind of locale setting, the rendering of the decimal point, is expressed by the environment variable LC_NUMERIC (where set). But if it set to a value incompatible with the default "C", it may cause parsing problems for expr, witness this exchange on comp.lang.tcl:

Stefan Bruder: I have extended my TCL with SWIG to connect to a ORACLE database. Now I have a problem with expr command. The command expr 1000.0 + 1.0 works fine before calling the connect function to the database. After connecting the same command gives an error:

 syntax error in expression 1000.0

Debugging the code gives me the problem in the function "strtod", the function return the double 1000.0 and the rest ".0" the locale var's LC_NUMERIC is always "." after calling the database function, but later on in the TCL code it must be changed to ",".

Jeffrey Hobbs: Somehow the LC_NUMERIC locale has changed from C (or other compatible locale) to a European one which switches the meaning of , and . in numbers. Tcl requires operation in the LC_NUMERIC C locale.

schlenk IIRC this should be no longer the case after TIP 249 [L2 ], which moves the number parser to the Tcl core instead of using the strtod() function of the OS.

bll 2018-8-5: Tcl 8.6.8 still requires that the LC_NUMERIC locale be C (or something with a . decimal radix). The quoted TIP certainly did not fix that.


Ralf Fassel: We found on NT that, for some users, calling the native NT functions "printDlg()" and "CreateDC()" changes the LC_ALL setting from C to some localized Version (German_something in our case). After that "expr 1.0" does not work any more (for the same reason as Stefan notes above, "strtod()" returns early in the string). The solution was to restore the LC_ALL setting after the call to the printer dialog. It seemed that only the very first call to any of these functions had such an effect. Subsequent calls did not change the value of LC_ALL. Possibly an artefact of loading some printer driver dll's.


EKB On Windows 2000, XP (others??) you can use the registry key "\HKCU\Control Panel\International\sLanguage" [L3 ] this way:

 set locale [string tolower \
    [string range \
        [registry get {HKEY_CURRENT_USER\Control Panel\International} sLanguage] \
    0 1] \
 ]

This gives the 2-letter code for the language.

Here's the full code snippet that I use when I'm using msgcat and want to auto-detect the locale:

 ## Uncomment the first option when using a standalone executable
 ##     (e.g., using [tclkit] or [FreeWrap])
 #set appdir [file dirname [info nameofexecutable]]
 set appdir [file dirname $argv0]

 set locale "en"  ;# Use whatever is right for your app
 if {[catch {package require registry}]} {
    tk_messageBox -icon error -message "Could not get locale from registry"
 } else {
    set locale [string tolower \
        [string range \
            [registry get {HKEY_CURRENT_USER\Control Panel\International} sLanguage] \
        0 1] \
    ]
 }

 if {[catch {package require msgcat}]} {
    tk_messageBox -icon error -message "Could not load language catalog"
    proc mc {m} {set m}
 } else {
    namespace import msgcat::mc
    msgcat::mclocale $locale
    msgcat::mcload [file join $appdir msgs]
 }