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

Pierre d'Herbemont pdherbemont at free.fr
Mon Dec 11 13:46:50 CST 2006


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(-)
-------------- next part --------------
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
@@ -31,9 +31,13 @@
 #include <stdio.h>
 #include <ctype.h>
 #include <stdlib.h>
+#include <sys/types.h>
+#include <sys/dir.h>
 
 #ifdef __APPLE__
+# include <CoreFoundation/CFBundle.h>
 # include <CoreFoundation/CFLocale.h>
+# include <CoreFoundation/CFPreferences.h>
 # include <CoreFoundation/CFString.h>
 #endif
 
@@ -2822,7 +2826,12 @@ void LOCALE_Init(void)
 
 #ifdef __APPLE__
     /* MacOS doesn't set the locale environment variables so we have to do it ourselves */
+    CFArrayRef prefered_languages;
+    CFMutableArrayRef available_locales;
     char user_locale[50];
+    struct direct *file;
+    DIR *dir;
+    
     CFLocaleRef user_locale_ref = CFLocaleCopyCurrent();
     CFStringRef user_locale_string_ref = CFLocaleGetIdentifier( user_locale_ref );
 
@@ -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));
+    }
+    closedir(dir);
+
+    CFPreferencesAppSynchronize(kCFPreferencesAnyApplication);
+    prefered_languages = CFPreferencesCopyValue( CFSTR("AppleLanguages"), kCFPreferencesAnyApplication,
+                                                 kCFPreferencesCurrentUser, kCFPreferencesAnyHost);
+    if(prefered_languages)
+    {
+        CFArrayRef intersected_locales = CFBundleCopyLocalizationsForPreferences(available_locales, prefered_languages);
+        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-patches mailing list