bug-gnulib
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

localename: fix default on macOS


From: Bruno Haible
Subject: localename: fix default on macOS
Date: Mon, 20 May 2019 02:59:03 +0200
User-agent: KMail/5.1.3 (Linux/4.4.0-145-generic; KDE/5.18.0; x86_64; ; )

On macOS 10.13.4, the locale name returned by gl_locale_name_default()
is wrong when two or more preferred languages are specified in the
system preferences. Namely, it returns, e.g. for me in Germany, "en_DE"
instead of the expected "de_DE" (where the language is the first
preferred language).

This is caused by an unexpected behaviour of CFLocaleCopyCurrent().
It may be the same bug as the one mentioned here:
- for macOS:
  
<https://stackoverflow.com/questions/45189185/regarding-cflocalecopycurrent-api-incorrect-return-value>
- for iOS:
  <https://openradar.appspot.com/34581827>
  <https://bugzilla.xamarin.com/show_bug.cgi?id=59596#c3>
  <https://bugreports.qt.io/browse/QTBUG-63324>

The fix is to use the older API instead, which still returns the
expected locale name.


2019-05-19  Bruno Haible  <address@hidden>

        localename: Fix default on macOS.
        * m4/intlmacosx.m4 (gt_INTL_MACOSX): Don't test for CFLocaleCopyCurrent.
        * lib/localename.c: Remove includes for HAVE_CFLOCALECOPYCURRENT.
        (gl_locale_name_environ, gl_locale_name_default): Remove code for
        HAVE_CFLOCALECOPYCURRENT.
        * lib/localename.h (gl_locale_name_default): Update.

diff --git a/m4/intlmacosx.m4 b/m4/intlmacosx.m4
index 30e6f50..3495174 100644
--- a/m4/intlmacosx.m4
+++ b/m4/intlmacosx.m4
@@ -1,4 +1,4 @@
-# intlmacosx.m4 serial 6 (gettext-0.20)
+# intlmacosx.m4 serial 7 (gettext-0.20.2)
 dnl Copyright (C) 2004-2014, 2016, 2019 Free Software Foundation, Inc.
 dnl This file is free software; the Free Software Foundation
 dnl gives unlimited permission to copy and/or distribute it,
@@ -33,21 +33,15 @@ AC_DEFUN([gt_INTL_MACOSX],
     AC_DEFINE([HAVE_CFPREFERENCESCOPYAPPVALUE], [1],
       [Define to 1 if you have the Mac OS X function CFPreferencesCopyAppValue 
in the CoreFoundation framework.])
   fi
-  dnl Check for API introduced in Mac OS X 10.5.
-  AC_CACHE_CHECK([for CFLocaleCopyCurrent], [gt_cv_func_CFLocaleCopyCurrent],
-    [gt_save_LIBS="$LIBS"
-     LIBS="$LIBS -Wl,-framework -Wl,CoreFoundation"
-     AC_LINK_IFELSE(
-       [AC_LANG_PROGRAM(
-          [[#include <CoreFoundation/CFLocale.h>]],
-          [[CFLocaleCopyCurrent();]])],
-       [gt_cv_func_CFLocaleCopyCurrent=yes],
-       [gt_cv_func_CFLocaleCopyCurrent=no])
-     LIBS="$gt_save_LIBS"])
-  if test $gt_cv_func_CFLocaleCopyCurrent = yes; then
-    AC_DEFINE([HAVE_CFLOCALECOPYCURRENT], [1],
-      [Define to 1 if you have the Mac OS X function CFLocaleCopyCurrent in 
the CoreFoundation framework.])
-  fi
+  dnl Don't check for the API introduced in Mac OS X 10.5, CFLocaleCopyCurrent,
+  dnl because in macOS 10.13.4 it has the following behaviour:
+  dnl When two or more languages are specified in the
+  dnl "System Preferences > Language & Region > Preferred Languages" panel,
+  dnl it returns en_CC where CC is the territory (even when English is not 
among
+  dnl the preferred languages!).  What we want instead is what
+  dnl CFLocaleCopyCurrent returned in earlier macOS releases and what
+  dnl CFPreferencesCopyAppValue still returns, namely ll_CC where ll is the
+  dnl first among the preferred languages and CC is the territory.
   AC_CACHE_CHECK([for CFLocaleCopyPreferredLanguages], 
[gt_cv_func_CFLocaleCopyPreferredLanguages],
     [gt_save_LIBS="$LIBS"
      LIBS="$LIBS -Wl,-framework -Wl,CoreFoundation"
@@ -64,7 +58,6 @@ AC_DEFUN([gt_INTL_MACOSX],
   fi
   INTL_MACOSX_LIBS=
   if test $gt_cv_func_CFPreferencesCopyAppValue = yes \
-     || test $gt_cv_func_CFLocaleCopyCurrent = yes \
      || test $gt_cv_func_CFLocaleCopyPreferredLanguages = yes; then
     INTL_MACOSX_LIBS="-Wl,-framework -Wl,CoreFoundation"
   fi
diff --git a/lib/localename.c b/lib/localename.c
index 1b1bb19..b6b94c2 100644
--- a/lib/localename.c
+++ b/lib/localename.c
@@ -66,13 +66,9 @@ extern char * getlocalename_l(int, locale_t);
 # endif
 #endif
 
-#if HAVE_CFLOCALECOPYCURRENT || HAVE_CFPREFERENCESCOPYAPPVALUE
+#if HAVE_CFPREFERENCESCOPYAPPVALUE
 # include <CoreFoundation/CFString.h>
-# if HAVE_CFLOCALECOPYCURRENT
-#  include <CoreFoundation/CFLocale.h>
-# elif HAVE_CFPREFERENCESCOPYAPPVALUE
-#  include <CoreFoundation/CFPreferences.h>
-# endif
+# include <CoreFoundation/CFPreferences.h>
 #endif
 
 #if defined _WIN32 && !defined __CYGWIN__
@@ -1156,7 +1152,7 @@ extern char * getlocalename_l(int, locale_t);
 #endif
 
 
-#if HAVE_CFLOCALECOPYCURRENT || HAVE_CFPREFERENCESCOPYAPPVALUE
+#if HAVE_CFPREFERENCESCOPYAPPVALUE
 /* Mac OS X 10.4 or newer */
 
 /* Canonicalize a Mac OS X locale name to a Unix locale name.
@@ -3326,7 +3322,7 @@ gl_locale_name_environ (int category, const char 
*categoryname)
   retval = getenv ("LANG");
   if (retval != NULL && retval[0] != '\0')
     {
-#if HAVE_CFLOCALECOPYCURRENT || HAVE_CFPREFERENCESCOPYAPPVALUE
+#if HAVE_CFPREFERENCESCOPYAPPVALUE
       /* Mac OS X 10.2 or newer.
          Ignore invalid LANG value set by the Terminal application.  */
       if (strcmp (retval, "UTF-8") != 0)
@@ -3373,7 +3369,7 @@ gl_locale_name_default (void)
          "C.UTF-8" locale, which operates in the same way as the "C" locale.
   */
 
-#if !(HAVE_CFLOCALECOPYCURRENT || HAVE_CFPREFERENCESCOPYAPPVALUE || defined 
WINDOWS_NATIVE || defined __CYGWIN__)
+#if !(HAVE_CFPREFERENCESCOPYAPPVALUE || defined WINDOWS_NATIVE || defined 
__CYGWIN__)
 
   /* The system does not have a way of setting the locale, other than the
      POSIX specified environment variables.  We use C as default locale.  */
@@ -3386,8 +3382,17 @@ gl_locale_name_default (void)
      context, because message catalogs are not specific to a single
      codeset.  */
 
-# if HAVE_CFLOCALECOPYCURRENT || HAVE_CFPREFERENCESCOPYAPPVALUE
+# if HAVE_CFPREFERENCESCOPYAPPVALUE
   /* Mac OS X 10.4 or newer */
+  /* Don't use the API introduced in Mac OS X 10.5, CFLocaleCopyCurrent,
+     because in macOS 10.13.4 it has the following behaviour:
+     When two or more languages are specified in the
+     "System Preferences > Language & Region > Preferred Languages" panel,
+     it returns en_CC where CC is the territory (even when English is not among
+     the preferred languages!).  What we want instead is what
+     CFLocaleCopyCurrent returned in earlier macOS releases and what
+     CFPreferencesCopyAppValue still returns, namely ll_CC where ll is the
+     first among the preferred languages and CC is the territory.  */
   {
     /* Cache the locale name, since CoreFoundation calls are expensive.  */
     static const char *cached_localename;
@@ -3395,17 +3400,12 @@ gl_locale_name_default (void)
     if (cached_localename == NULL)
       {
         char namebuf[256];
-#  if HAVE_CFLOCALECOPYCURRENT /* Mac OS X 10.5 or newer */
-        CFLocaleRef locale = CFLocaleCopyCurrent ();
-        CFStringRef name = CFLocaleGetIdentifier (locale);
-#  elif HAVE_CFPREFERENCESCOPYAPPVALUE /* Mac OS X 10.4 or newer */
         CFTypeRef value =
           CFPreferencesCopyAppValue (CFSTR ("AppleLocale"),
                                      kCFPreferencesCurrentApplication);
         if (value != NULL && CFGetTypeID (value) == CFStringGetTypeID ())
           {
             CFStringRef name = (CFStringRef)value;
-#  endif
 
             if (CFStringGetCString (name, namebuf, sizeof (namebuf),
                                     kCFStringEncodingASCII))
@@ -3413,12 +3413,7 @@ gl_locale_name_default (void)
                 gl_locale_name_canonicalize (namebuf);
                 cached_localename = strdup (namebuf);
               }
-
-#  if HAVE_CFLOCALECOPYCURRENT /* Mac OS X 10.5 or newer */
-        CFRelease (locale);
-#  elif HAVE_CFPREFERENCESCOPYAPPVALUE /* Mac OS X 10.4 or newer */
           }
-#  endif
         if (cached_localename == NULL)
           cached_localename = "C";
       }
diff --git a/lib/localename.h b/lib/localename.h
index 071248a..c0839b8 100644
--- a/lib/localename.h
+++ b/lib/localename.h
@@ -86,8 +86,7 @@ extern const char * gl_locale_name_environ (int category, 
const char *categoryna
 
    The result must not be freed; it is statically allocated.  */
 extern const char * gl_locale_name_default (void)
-#if !(HAVE_CFLOCALECOPYCURRENT || HAVE_CFPREFERENCESCOPYAPPVALUE \
-      || defined _WIN32 || defined __CYGWIN__)
+#if !(HAVE_CFPREFERENCESCOPYAPPVALUE || defined _WIN32 || defined __CYGWIN__)
   _GL_ATTRIBUTE_CONST
 #endif
   ;




reply via email to

[Prev in Thread] Current Thread [Next in Thread]