kernel32: Allow the prefered language to be different from the prefered locale on Mac OS X by correctly setting LC_MESSAGES.

Ken Thomases ken at codeweavers.com
Mon Dec 11 19:43:31 CST 2006


On Dec 11, 2006, at 5:49 PM, Pierre d'Herbemont wrote:

>
> On 12 déc. 06, at 00:20, Pierre d'Herbemont wrote:
>
>>
>>>> +    }
>>>> +    closedir(dir);
>>>
>>> I think the above code to scan /usr/share/locale is unnecessary.   
>>> Doesn't CFLocaleCopyAvailableLocaleIdentifiers provide the  
>>> equivalent?
>>
>> You're quite right. I though setlocale didn't handle 'en' properly  
>> expecting full 'en_US' or 'en_GB', I can't understand why now.  
>> Probably didn't have enough sleep last night.
>
> I do remember now :) setlocale don't handle properly two letters  
> language code like 'es' it expect a full locale name like 'es_ES' .  
> And using the CFLocale API to obtain the full local from 'es' does  
> not seem possible.
>
> And even with CFLocaleCopyAvailableLocaleIdentifiers() the returned  
> array will contain 'es' among 'es_ES' and 'en_GB' so, when  
> intersecting with the preferred languages [1] threw  
> CFBundleCopyLocalizationsForPreferences() 'es' will be returned.  
> setlocale(LC_MESSAGES, NULL) will return "C", and thus fallback the  
> standard english language (LC_CTYPE is not set on Mac OS X),  
> whereas setlocale should have returned es.
>
> The fix for this is to provide to setlocale a full locale name like  
> 'es_ES', that's why I did it that way.
>
> Do you see any better way to do this rather than probably filling a  
> bug report to Apple?
>
> [1] #defaults read -g AppleLanguages
> 	( es, fr, en, de, ja, it, nl, sv, nb, da, fi, pt, "zh-Hans", "zh- 
> Hant", ko)

Hmm.  Well, it probably results in more cumbersome code, but you  
could filter the array returned by  
CFLocaleCopyAvailableLocaleIdentifiers by testing which elements have  
a country code.  For each, call  
CFLocaleCreateComponentsFromLocaleIdentifier and check if the  
resulting dictionary has an object for the kCFLocaleCountryCode key.   
You'd accumulate the locale IDs which pass the test in the mutable  
array.

However, this whole strategy (however it's implemented, by scanning / 
usr/share/locale or the above method) seems to produce bad results.   
When I test here, CFBundleCopyLocalizationsForPreferences() spits out  
"en_ZW" (English, Zimbabwe).  Some testing reveals that it is *not*  
just picking the last entry in the locale array whose language  
matches.  It's not entirely predictable.  I suspect it's doing a  
binary search.

In System Preferences, I have my language preference set to English.   
If I edit the list and add U.S. English and put it at the top, then  
the above method does produce U.S. English.  However, that's not how  
most people have things set up.


I suppose we could use a multi-step approach.  If the first element  
of the AppleLanguages array has a country code, use it directly.   
Otherwise, combine the language code from that element with the  
country code from the current locale.  If that combination is present  
in the array of available locales, use that.  Otherwise, fall back to  
CFBundleCopyLocalizationsForPreferences.


-Ken


More information about the wine-devel mailing list