gnucash maint: Multiple changes pushed

John Ralls jralls at code.gnucash.org
Sat Mar 26 17:59:14 EDT 2016


Updated	 via  https://github.com/Gnucash/gnucash/commit/df8fa038 (commit)
	 via  https://github.com/Gnucash/gnucash/commit/a41a7e2b (commit)
	from  https://github.com/Gnucash/gnucash/commit/ed11f6d1 (commit)



commit df8fa038872e11e965f4a56586ad4e22accb7fb2
Author: John Ralls <jralls at ceridwen.us>
Date:   Thu Mar 24 09:12:33 2016 -0700

    Mac Localization: Prefer the country to the language for fall-back locales.
    
    On the theory that in countries where multiple languages are in use similar
    date and number formats will apply regardless of language, and especially
    that the default currency will be the same regardless of language.
    
    Also ensure that the specified language is in the list passed to gettext;
    the net effect of which is that the user will effectively get the requested
    localization behavior.

diff --git a/src/bin/gnucash-bin.c b/src/bin/gnucash-bin.c
index e122ec2..4cd4af3 100644
--- a/src/bin/gnucash-bin.c
+++ b/src/bin/gnucash-bin.c
@@ -189,9 +189,13 @@ mac_set_currency_locale(NSLocale *locale, NSString *locale_str)
 	    setlocale(LC_MONETARY, [money_locale UTF8String]);
     }
 }
-
+/* The locale that we got from AppKit isn't a supported POSIX one, so we need to
+ * find something close. First see if we can find another locale for the
+ * country; failing that, try the language. Ultimately fall back on en_US.
+ */
 static NSString*
-mac_find_close_country(NSString *locale_str, NSString *lang_str)
+mac_find_close_country(NSString *locale_str, NSString *country_str,
+                       NSString *lang_str)
 {
     NSArray *all_locales = [NSLocale availableLocaleIdentifiers];
     NSEnumerator *locale_iter = [all_locales objectEnumerator];
@@ -200,8 +204,8 @@ mac_find_close_country(NSString *locale_str, NSString *lang_str)
           " by the C runtime", [locale_str UTF8String]);
     while ((this_locale = (NSString*)[locale_iter nextObject]))
         if ([[[NSLocale componentsFromLocaleIdentifier: this_locale]
-              objectForKey: NSLocaleLanguageCode]
-             isEqualToString: lang_str] &&
+              objectForKey: NSLocaleCountryCode]
+             isEqualToString: country_str] &&
             setlocale (LC_ALL, [this_locale UTF8String]))
         {
             new_locale = this_locale;
@@ -210,6 +214,18 @@ mac_find_close_country(NSString *locale_str, NSString *lang_str)
     if (new_locale)
         locale_str = new_locale;
     else
+        while ((this_locale = (NSString*)[locale_iter nextObject]))
+            if ([[[NSLocale componentsFromLocaleIdentifier: this_locale]
+                  objectForKey: NSLocaleLanguageCode]
+                 isEqualToString: lang_str] &&
+                setlocale (LC_ALL, [this_locale UTF8String]))
+            {
+                new_locale = this_locale;
+                break;
+            }
+    if (new_locale)
+        locale_str = new_locale;
+    else
     {
         locale_str = @"en_US";
         setlocale(LC_ALL, [locale_str UTF8String]);
@@ -243,7 +259,7 @@ mac_convert_complex_language(NSString* this_lang)
 }
 
 static void
-mac_set_languages(NSArray* languages)
+mac_set_languages(NSArray* languages, NSString *lang_str)
 {
     /* Process the language list. */
 
@@ -260,10 +276,17 @@ mac_set_languages(NSArray* languages)
  * any messages can default to it */
         if ( [this_lang containsString: @"en"])
             new_languages = [new_languages arrayByAddingObject: @"C"];
+        if (![new_languages containsObject: lang_str]) {
+            NSArray *temp_array = [NSArray arrayWithObject: lang_str];
+            new_languages = [temp_array arrayByAddingObjectsFromArray: new_languages];
+        }
         langs = [[new_languages componentsJoinedByString:@":"] UTF8String];
     }
     if (langs && strlen(langs) > 0)
+    {
+        PWARN("Language list: %s", langs);
         g_setenv("LANGUAGE", langs, TRUE);
+    }
 }
 
 static void
@@ -273,7 +296,7 @@ set_mac_locale()
     NSUserDefaults *defs = [NSUserDefaults standardUserDefaults];
     NSLocale *locale = [NSLocale currentLocale];
     NSString *lang_str, *country_str, *locale_str;
-    NSArray *languages = [defs objectForKey: @"AppleLanguages"];
+    NSArray *languages = [[defs arrayForKey: @"AppleLanguages"] retain];
     @try
     {
         lang_str = [locale objectForKey: NSLocaleLanguageCode];
@@ -293,8 +316,9 @@ set_mac_locale()
     if ([locale_str isEqualToString: @"_"])
 	locale_str = @"en_US";
 
+    lang_str = mac_convert_complex_language(lang_str);
     if (!setlocale(LC_ALL, [locale_str UTF8String]))
-        locale_str =  mac_find_close_country(locale_str, lang_str);
+        locale_str =  mac_find_close_country(locale_str, country_str, lang_str);
     if (g_getenv("LANG") == NULL)
 	g_setenv("LANG", [locale_str UTF8String], TRUE);
     mac_set_currency_locale(locale, locale_str);
@@ -303,8 +327,10 @@ set_mac_locale()
     gnc_localeconv ();
     /* Process the languages, including the one from the Apple locale. */
     if ([languages count] > 0)
-        mac_set_languages(languages);
-
+        mac_set_languages(languages, lang_str);
+    else
+        g_setenv("LANGUAGE", [lang_str UTF8String], TRUE);
+    [languages release];
     [pool drain];
 }
 #endif /* MAC_INTEGRATION */

commit a41a7e2b50aea5ea9932de9d3376fefcc279b2c5
Author: John Ralls <jralls at ceridwen.us>
Date:   Tue Mar 22 17:46:49 2016 -0700

    Extract some functions to make the Mac locale setup a bit more maintainable.

diff --git a/src/bin/gnucash-bin.c b/src/bin/gnucash-bin.c
index c1c74d5..e122ec2 100644
--- a/src/bin/gnucash-bin.c
+++ b/src/bin/gnucash-bin.c
@@ -162,62 +162,9 @@ gnc_print_unstable_message(void)
 
 #ifdef MAC_INTEGRATION
 static void
-set_mac_locale()
+mac_set_currency_locale(NSLocale *locale, NSString *locale_str)
 {
-    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
-    NSUserDefaults *defs = [NSUserDefaults standardUserDefaults];
-    NSArray *languages = [defs objectForKey: @"AppleLanguages"];
-    const gchar *langs = NULL;
-    NSLocale *locale = [NSLocale currentLocale];
-    NSString *locale_str;
-    @try
-    {
-	locale_str = [[[locale objectForKey: NSLocaleLanguageCode]
-		       stringByAppendingString: @"_"]
-		      stringByAppendingString:
-		      [locale objectForKey: NSLocaleCountryCode]];
-    }
-    @catch (NSException *err)
-    {
-	PWARN("Locale detection raised error %s: %s. "
-	      "Check that your locale settings in "
-	      "System Preferences>Languages & Text are set correctly.",
-	      [[err name] UTF8String], [[err reason] UTF8String]);
-	locale_str = @"_";
-    }
-/* If we didn't get a valid current locale, the string will be just "_" */
-    if ([locale_str isEqualToString: @"_"])
-	locale_str = @"en_US";
-
-    if (!setlocale(LC_ALL, [locale_str UTF8String]))
-    {
-	NSArray *all_locales = [NSLocale availableLocaleIdentifiers];
-	NSEnumerator *locale_iter = [all_locales objectEnumerator];
-	NSString *this_locale, *new_locale = nil;
-	NSString *lang = [locale objectForKey: NSLocaleLanguageCode];
-	PWARN("Apple Locale is set to a value %s not supported"
-	      " by the C runtime", [locale_str UTF8String]);
-	while ((this_locale = (NSString*)[locale_iter nextObject]))
-	    if ([[[NSLocale componentsFromLocaleIdentifier: this_locale]
-		  objectForKey: NSLocaleLanguageCode]
-		 isEqualToString: lang] &&
-		setlocale (LC_ALL, [this_locale UTF8String]))
-	    {
-		new_locale = this_locale;
-		break;
-	    }
-	if (new_locale)
-	    locale_str = new_locale;
-	else
-	{
-	    locale_str = @"en_US";
-	    setlocale(LC_ALL, [locale_str UTF8String]);
-	}
-	PWARN("Using %s instead.", [locale_str UTF8String]);
-    }
-    if (g_getenv("LANG") == NULL)
-	g_setenv("LANG", [locale_str UTF8String], TRUE);
-/* If the currency doesn't match the base locale, we need to find a locale that does match, because setlocale won't know what to do with just a currency identifier. */
+    /* If the currency doesn't match the base locale, we need to find a locale that does match, because setlocale won't know what to do with just a currency identifier. */
     if (![[locale objectForKey: NSLocaleCurrencyCode] isEqualToString:
 	  [[[NSLocale alloc] initWithLocaleIdentifier: locale_str] objectForKey: NSLocaleCurrencyCode]]) {
 	NSArray *all_locales = [NSLocale availableLocaleIdentifiers];
@@ -241,49 +188,123 @@ set_mac_locale()
 	if (money_locale)
 	    setlocale(LC_MONETARY, [money_locale UTF8String]);
     }
-/* Now call gnc_localeconv() to force creation of the app locale
- * before another call to setlocale messes it up. */
-    gnc_localeconv ();
-/* Process the language list.
- *
- * Language subgroups (e.g., US English) are reported in the form
- * "ll-SS" (e.g. again, "en-US"), not what gettext wants. We convert
- * those to old-style locales, which is easy for most cases. There are
- * two where it isn't, though: Simplified Chinese (zh-Hans) and
- * traditional Chinese (zh-Hant), which are normally assigned the
- * locales zh_CN and zh_TW, respectively. Those are handled
- * specially.*/
-    if ([languages count] > 0) {
-	NSEnumerator *lang_iter = [languages objectEnumerator];
-	NSString *this_lang;
-	NSArray *elements;
-	NSArray *new_languages = [NSArray array];
-	while ((this_lang = [lang_iter nextObject])) {
-	    this_lang = [this_lang stringByTrimmingCharactersInSet:
-			 [NSCharacterSet characterSetWithCharactersInString:
-			  @"\""]];
-	    elements = [this_lang componentsSeparatedByString: @"-"];
-	    if ([elements count] > 1) {
-		if ([[elements objectAtIndex: 0] isEqualToString: @"zh"]) {
-		    if ([[elements objectAtIndex: 1] isEqualToString: @"Hans"])
-			this_lang = @"zh_CN";
-		    else
-			this_lang = @"zh_TW";
-		}
-		else
-		  this_lang = [elements componentsJoinedByString: @"_"];
-	    }
-	    new_languages = [new_languages arrayByAddingObject: this_lang];
+}
+
+static NSString*
+mac_find_close_country(NSString *locale_str, NSString *lang_str)
+{
+    NSArray *all_locales = [NSLocale availableLocaleIdentifiers];
+    NSEnumerator *locale_iter = [all_locales objectEnumerator];
+    NSString *this_locale, *new_locale = nil;
+    PWARN("Apple Locale is set to a value %s not supported"
+          " by the C runtime", [locale_str UTF8String]);
+    while ((this_locale = (NSString*)[locale_iter nextObject]))
+        if ([[[NSLocale componentsFromLocaleIdentifier: this_locale]
+              objectForKey: NSLocaleLanguageCode]
+             isEqualToString: lang_str] &&
+            setlocale (LC_ALL, [this_locale UTF8String]))
+        {
+            new_locale = this_locale;
+            break;
+        }
+    if (new_locale)
+        locale_str = new_locale;
+    else
+    {
+        locale_str = @"en_US";
+        setlocale(LC_ALL, [locale_str UTF8String]);
+    }
+    PWARN("Using %s instead.", [locale_str UTF8String]);
+    return locale_str;
+}
+
+/* Language subgroups (e.g., US English) are reported in the form "ll-SS"
+ * (e.g. again, "en-US"), not what gettext wants. We convert those to
+ * old-style locales, which is easy for most cases. There are two where it
+ * isn't, though: Simplified Chinese (zh-Hans) and traditional Chinese
+ * (zh-Hant), which are normally assigned the locales zh_CN and zh_TW,
+ * respectively. Those are handled specially.
+ */
+static NSString*
+mac_convert_complex_language(NSString* this_lang)
+{
+    NSArray *elements = [this_lang componentsSeparatedByString: @"-"];
+    if ([elements count] == 1)
+        return this_lang;
+    if ([[elements objectAtIndex: 0] isEqualToString: @"zh"]) {
+        if ([[elements objectAtIndex: 1] isEqualToString: @"Hans"])
+            this_lang = @"zh_CN";
+        else
+            this_lang = @"zh_TW";
+    }
+    else
+        this_lang = [elements componentsJoinedByString: @"_"];
+    return this_lang;
+}
+
+static void
+mac_set_languages(NSArray* languages)
+{
+    /* Process the language list. */
+
+    const gchar *langs = NULL;
+    NSEnumerator *lang_iter = [languages objectEnumerator];
+    NSArray *new_languages = [NSArray array];
+    NSString *this_lang = NULL;
+    while ((this_lang = [lang_iter nextObject])) {
+        this_lang = [this_lang stringByTrimmingCharactersInSet:
+                     [NSCharacterSet characterSetWithCharactersInString: @"\""]];
+        this_lang = mac_convert_complex_language(this_lang);
+        new_languages = [new_languages arrayByAddingObject: this_lang];
 /* If it's an English language, add the "C" locale after it so that
  * any messages can default to it */
-	    if ( [[elements objectAtIndex: 0] isEqualToString: @"en"])
-		new_languages = [new_languages arrayByAddingObject: @"C"];
-
-	}
-	langs = [[new_languages componentsJoinedByString:@":"] UTF8String];
+        if ( [this_lang containsString: @"en"])
+            new_languages = [new_languages arrayByAddingObject: @"C"];
+        langs = [[new_languages componentsJoinedByString:@":"] UTF8String];
     }
     if (langs && strlen(langs) > 0)
-	g_setenv("LANGUAGE", langs, TRUE);
+        g_setenv("LANGUAGE", langs, TRUE);
+}
+
+static void
+set_mac_locale()
+{
+    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+    NSUserDefaults *defs = [NSUserDefaults standardUserDefaults];
+    NSLocale *locale = [NSLocale currentLocale];
+    NSString *lang_str, *country_str, *locale_str;
+    NSArray *languages = [defs objectForKey: @"AppleLanguages"];
+    @try
+    {
+        lang_str = [locale objectForKey: NSLocaleLanguageCode];
+        country_str = [locale objectForKey: NSLocaleCountryCode];
+	locale_str = [[lang_str stringByAppendingString: @"_"]
+		      stringByAppendingString: country_str];
+    }
+    @catch (NSException *err)
+    {
+	PWARN("Locale detection raised error %s: %s. "
+	      "Check that your locale settings in "
+	      "System Preferences>Languages & Text are set correctly.",
+	      [[err name] UTF8String], [[err reason] UTF8String]);
+	locale_str = @"_";
+    }
+/* If we didn't get a valid current locale, the string will be just "_" */
+    if ([locale_str isEqualToString: @"_"])
+	locale_str = @"en_US";
+
+    if (!setlocale(LC_ALL, [locale_str UTF8String]))
+        locale_str =  mac_find_close_country(locale_str, lang_str);
+    if (g_getenv("LANG") == NULL)
+	g_setenv("LANG", [locale_str UTF8String], TRUE);
+    mac_set_currency_locale(locale, locale_str);
+/* Now call gnc_localeconv() to force creation of the app locale
+ * before another call to setlocale messes it up. */
+    gnc_localeconv ();
+    /* Process the languages, including the one from the Apple locale. */
+    if ([languages count] > 0)
+        mac_set_languages(languages);
+
     [pool drain];
 }
 #endif /* MAC_INTEGRATION */



Summary of changes:
 src/bin/gnucash-bin.c | 235 ++++++++++++++++++++++++++++++--------------------
 1 file changed, 141 insertions(+), 94 deletions(-)



More information about the gnucash-changes mailing list