Getting a user's location and language

This is an off-shoot of the previous thread, asking the community for some knowledge!

Juce has no way to get the user’s location and language preferences as set on their machine - but this can be done on each platform. Why don’t we try to figure this out, and get it put into Juce? It’d be a feature of great value, when glued in with the existing localization framework.

Now, it’s not even 100% clear what a correct answer would be to that - localization and internationalization is a huge subject!

So why don’t we simply try to get a list of language codes for our platforms (PC, Mac, Linux, even iOS perhaps?), and simply not define what a language code is other than “a string”.

I don’t actually know how to do this on any system but :smiley: I know an awful lot about language codes and that sort of thing - if I don’t get any response I’ll figure out eventually how this is done and report back to the group…

in linux, you can make a “wild guess” by doing String(getenv(“LANG”)).upToFirstOccurrenceOf(".", false, false). Usually people have “en.UTF-8” or “en_US.UTF-8” or “fr.UTF-8” as their LANG environment variable.
Under windows, you can query the system information, using GetUILanguageInfo (vista and later), or you need to apply a very tricking code like this one:

function dptGetLang
    -- Returns the language of the session of the user.
    -- This function will read the operation system configuration and will
  ##  return the current language used by the user.
    local theItemNo,theLangCode,theLangStrings
    local theVersion,theWinLangCodes
    local theUserLang = "en"
   
    if the platform is "MacOS" then
        put replacetext(shell("defaults read NSGlobalDomain AppleLanguages"),"(\s|\(|\)|" & quote & ")","") into theLangStrings
        put char 1 to 2 of theLangStrings into theUserLang
    else if the platform is "Win32" then
        -- http://windowssdk.msdn.microsoft.com/en-us/library/aa365069.aspx
        -- http://windowssdk.msdn.microsoft.com/en-us/library/ms776286.aspx
        --http://msdn.microsoft.com/library/default.asp?url=/library/en-us/intl/mui_GetUILanguageInfo.asp
        -- http://support.microsoft.com/kb/181604
       
        ## FIRST CHECK FOR MUI INSTALLS
        if queryregistry("HKEY_LOCAL_MACHINE\MUI\Enable") is 1 then
            put queryregistry("HKEY_CURRENT_USER\MUI\CurLang") into theLangCode
        end if
       
        if theLangCode is empty then
            put word 2 of the systemversion into theVersion
           
            if word 1 of the systemversion is "Windows" then    # 95/98/ME
                put queryregistry("HKEY_CURRENT_USER\Control Panel\desktop\ResourceLocale") into theLangCode
            else if theVersion >= 4 and theVersion < 5 then    # NT
                put queryregistry("HKEY_USERS\.DEFAULT\Control Panel\International\Locale") into theLangCode
                ## THIS COULD FAIL IN WHICH CASE YOU HAVE TO CHECK THE RESOURCES OF SOME INSTALLED DLL.
                ## VERY SILLY.edit script the
            else    # XP/Vista
                put queryregistry("HKEY_CURRENT_USER\Control Panel\International\Locale") into theLangCode
            end if
        end if
       
        put word 1 to -1 of theLangCode into theLangCode
    ## Vista bug in version up to 2.9 rc-2: trailing white space
       
        put baseconvert(theLangCode,16,10) into theLangCode
       
        ## THE ORDER OF THIS LIST MATCHES THE ORDER OF theLangCodes
        put "za,al,fr,et,dz,bh,eg,iq,jo,kw,lb,ly,ma,om,qa,sa,sy,tn,ae,ye,am,in,az,az,ru,es,by,ba,ba,fr,bg,es,hk,mo,sg,fr,ba,hr,cz,dk,af,mv,be,nl,au,be,ca,in,ie,ie,jm,my,nz,ph,sg,za,tt,gb,us,zw,ee,fo,ph,fi,be,ca,fr,lu,mc,ch,nl,es,ge,at,de,li,lu,ch,gr,gl,in,ng,il,in,hu,is,ng,id,ca,ca,ie,it,ch,jp,in,kz,kh,gt,rw,in,kr,kg,la,lv,lt,de,lu,mk,bn,my,in,mt,nz,cl,in,ca,mn,cn,np,no,no,fr,in,af,ir,pl,br,pt,pt,in,bo,ec,pe,ro,ch,ru,fi,no,se,fi,no,se,fi,no,se,in,ba,ba,cs,cs,za,za,lk,sk,si,ar,bo,cl,co,cr,do,ec,sv,gt,hn,mx,ni,pa,py,pe,pr,es,uy,ve,ke,fi,se,se,sy,tj,dz,in,ru,in,th,cn,tr,tm,cn,ua,de,pk,uz,uz,vn,gb,sn,za,ru,cn,ng,za" into theLangStrings
        put "1078,1052,1156,1118,5121,15361,3073,2049,11265,13313,12289,4097,6145,8193,16385,1025,10241,7169,14337,9217,1067,1101,2092,1068,1133,1069,1059,8218,5146,1150,1026,1027,3076,5124,4100,1155,4122,1050,1029,1030,1164,1125,2067,1043,3081,10249,4105,16393,6153,6153,8201,17417,5129,13321,18441,7177,11273,2057,1033,12297,1061,1080,1124,1035,2060,3084,1036,5132,6156,4108,1122,1110,1079,3079,1031,5127,4103,2055,1032,1135,1095,1128,1037,1081,1038,1039,1136,1057,2141,1117,2108,1040,2064,1041,1099,1087,1107,1158,1159,1111,1042,1088,1108,1062,1063,2094,1134,1071,2110,1086,1100,1082,1153,1146,1102,1148,1104,2128,1121,1044,2068,1154,1096,1123,1065,1045,1046,2070,2070,1094,1131,2155,3179,1048,1047,1049,9275,4155,5179,3131,1083,2107,8251,6203,7227,1103,26,6170,3098,2074,1132,1074,1115,1051,1060,11274,16394,13322,9226,5130,7178,12298,17418,4106,18442,2058,19466,6154,15370,10250,20490,3082,14346,8202,1089,2077,1053,1053,1114,1064,2143,1097,1092,1098,1054,1105,1055,1090,1152,1058,1070,1056,2115,1091,1066,1106,1160,1076,1157,1144,1130,1077" into theWinLangCodes
       
        set wholematches to true
        put itemoffset(theLangCode, theWinLangCodes) into theItemNo
        if theItemNo > 0 then
            put item theItemNo of theLangStrings into theUserLang
        end if
    else
        ## LINUX
        return char 1 to 2 of $LANG -- Easy Unix.
    end if
   
    return theUserLang
end dptGetLang

Wow, thanks, an excellent start.

A simple getenv(“LANG”) seems like a perfectly good first cut for Linux.

It’s a shame that $LANG isn’t defined on OS/X, but defaults read NSGlobalDomain AppleLanguages does work perfectly well from the shell - we either have to figure out how to make an equivalent call from Objective C, or how to spawn off a shell and read from it.

The Windows version seems painful only because of all those special cases to deal with old OSes. I at least am willing to fail to deliver on such old machines - because they are a fairly small portion of our customers, and because the user only has to be able to read enough English in that case to pull down a menu and select their language.

After doing a bit of “Googling”, here are the C++ locale functions for Windows (as far as I have time to search). (Compatibility: Vista and above, accept where noted.)

[list]
[]GetUserDefaultLocaleName()[/]
[]GetUserDefaultLCID() [Minimum supported client: Windows 2000 Professional][/]
[]GetLocaleInfo()[/]
[]GetLocaleInfoEx()[/]
[]GetSystemDefaultLCID() [Minimum supported client: Windows 2000 Professional][/]
[]GetSystemDefaultLocaleName()[/][/list]

Here’s the list of locale IDs for Windows XP and Windows Server 2003: http://msdn.microsoft.com/en-us/goglobal/bb895996
Here’s another list of locale IDs: http://msdn.microsoft.com/en-us/goglobal/bb964664

Additional information: http://msdn.microsoft.com/en-us/library/dd318716