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 15:42:24 CST 2006


On Dec 11, 2006, at 1:46 PM, Pierre d'Herbemont wrote:

> This patch allows Mac OS X Users that set in System Preferences.app  
> a language (say English) and that don't use the default number and  
> text formatting currently associated with this language (for  
> instance if they use French number and text formatting), to have  
> Wine displaying text in their choosen language. And thus it allows  
> Wine to behave like 'regular' Mac OS X Applications.
>
> The only problem is that we have to translate the language id to a  
> locale id.
>
> Pierre.
> ---
>  dlls/kernel32/locale.c |   54 +++++++++++++++++++++++++++++++++++++ 
> ++++++++++-
>  1 files changed, 53 insertions(+), 1 deletions(-)
> diff --git a/dlls/kernel32/locale.c b/dlls/kernel32/locale.c
> index 8792623..345780f 100644
> --- a/dlls/kernel32/locale.c
> +++ b/dlls/kernel32/locale.c
> @@ -2832,7 +2841,50 @@ void LOCALE_Init(void)
>      unix_cp = CP_UTF8;  /* default to utf-8 even if we don't get a  
> valid locale */
>      setenv( "LANG", user_locale, 0 );
>      TRACE( "setting locale to '%s'\n", user_locale );
> -#endif
> +
> +    /* We still want to set the LC_MESSAGES env to what is the  
> prefered language in
> +       System Preferences.app, because it can differ from  
> CFLocaleCopyCurrent().
> +
> +       However this prefered language is stored using the general  
> language denotation
> +       that may not include the country code (en,fr,en-GB,...)  
> which is not accepted
> +       by setlocale (setlocale would expect en_US,fr_FR,en_GB,...).
> +
> +       So we retrieve possible locales from /usr/share/locale and  
> intersect them
> +       with the prefered languages using  
> CFBundleCopyLocalizationsForPreferences. */
> +    dir = opendir("/usr/share/locale");
> +    available_locales = CFArrayCreateMutable(kCFAllocatorDefault,  
> 0, NULL);
> +    while ((file = readdir(dir)))
> +    {
> +        /* This filters the 'right' locales (xx_xx.UTF-8) */
> +        if (strstr(file->d_name, ".UTF-8"))
> +            CFArrayAppendValue(available_locales, (void*) 
> CFStringCreateWithCString(kCFAllocatorDefault,
> +                                                            file- 
> >d_name, kCFStringEncodingUTF8));

The above should use CFStringCreateWithFileSystemRepresentation  
instead of CFStringCreateWithCString.  Also, you need to CFRelease  
the created string after adding it to the array.  (The array manages  
its references, but that doesn't relieve you of the responsibility to  
manage your own.)

> +    }
> +    closedir(dir);

I think the above code to scan /usr/share/locale is unnecessary.   
Doesn't CFLocaleCopyAvailableLocaleIdentifiers provide the equivalent?

> +
> +    CFPreferencesAppSynchronize(kCFPreferencesAnyApplication);
> +    prefered_languages = CFPreferencesCopyValue( CFSTR 
> ("AppleLanguages"), kCFPreferencesAnyApplication,
> +                                                  
> kCFPreferencesCurrentUser, kCFPreferencesAnyHost);
> +    if(prefered_languages)
> +    {
> +        CFArrayRef intersected_locales =  
> CFBundleCopyLocalizationsForPreferences(available_locales,  
> prefered_languages);

Do you need prefered_languages?  The docs say that if you pass NULL  
for the second parameter of CFBundleCopyLocalizationsForPreferences,  
it uses the user's preferences.  That would avoid you having to look  
them up, above.

Also, "preferred" is spelled with three R's.

> +        CFStringRef user_language = NULL;
> +
> +        if(CFArrayGetCount(intersected_locales))
> +            user_language = CFArrayGetValueAtIndex 
> (intersected_locales, 0);
> +        if(user_language)
> +        {
> +            CFStringGetCString( user_language, user_locale, sizeof 
> (user_locale), kCFStringEncodingUTF8 );
> +            CFRelease( user_language );
> +            TRACE( "setting LC_MESSAGES to '%s'\n", user_locale );
> +            setenv( "LC_MESSAGES", user_locale, 0 );
> +        }
> +        CFRelease(prefered_languages);
> +        CFRelease(intersected_locales);
> +    }
> +    CFRelease(available_locales);
> +#endif /* __APPLE__ */
> +
>      setlocale( LC_ALL, "" );
>
>      unix_cp = setup_unix_locales();
>
>




More information about the wine-devel mailing list