summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBruno Haible <bruno@clisp.org>2018-09-16 19:12:44 +0200
committerBruno Haible <bruno@clisp.org>2018-09-16 19:12:44 +0200
commit6642aeb47aee3d82978a27497dc9ca57058c66b4 (patch)
treef714557b6b07f2948bae114b40d8b2b7c7d95805
parentb0af89dcdde2f4e966efd9d2c9c820557d57e381 (diff)
downloadgnulib-6642aeb47aee3d82978a27497dc9ca57058c66b4.tar.gz
setlocale: Improve locale handling on macOS 10.12 or newer.
* lib/setlocale.c: Include header files for CoreFoundation. Declare gl_locale_name_canonicalize. (libintl_setlocale): Try harder to set a locale for categories LC_CTYPE and LC_MESSAGES. * m4/setlocale.m4 (gl_PREREQ_SETLOCALE): Add comment.
-rw-r--r--ChangeLog9
-rw-r--r--lib/setlocale.c95
-rw-r--r--m4/setlocale.m45
3 files changed, 100 insertions, 9 deletions
diff --git a/ChangeLog b/ChangeLog
index 5fb9682595..51608264a5 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,14 @@
2018-09-16 Bruno Haible <bruno@clisp.org>
+ setlocale: Improve locale handling on macOS 10.12 or newer.
+ * lib/setlocale.c: Include header files for CoreFoundation. Declare
+ gl_locale_name_canonicalize.
+ (libintl_setlocale): Try harder to set a locale for categories LC_CTYPE
+ and LC_MESSAGES.
+ * m4/setlocale.m4 (gl_PREREQ_SETLOCALE): Add comment.
+
+2018-09-16 Bruno Haible <bruno@clisp.org>
+
Update list of locale names with scripts on macOS.
* lib/localename.c (gl_locale_name_canonicalize): Update tables to
match Mac OS X 10.13 and recent glibc.
diff --git a/lib/setlocale.c b/lib/setlocale.c
index 77bdabab46..63f870f1df 100644
--- a/lib/setlocale.c
+++ b/lib/setlocale.c
@@ -35,6 +35,18 @@
#include "localename.h"
+#if HAVE_CFLOCALECOPYPREFERREDLANGUAGES || HAVE_CFPREFERENCESCOPYAPPVALUE
+# if HAVE_CFLOCALECOPYPREFERREDLANGUAGES
+# include <CoreFoundation/CFLocale.h>
+# elif HAVE_CFPREFERENCESCOPYAPPVALUE
+# include <CoreFoundation/CFPreferences.h>
+# endif
+# include <CoreFoundation/CFPropertyList.h>
+# include <CoreFoundation/CFArray.h>
+# include <CoreFoundation/CFString.h>
+extern void gl_locale_name_canonicalize (char *name);
+#endif
+
#if 1
# undef setlocale
@@ -892,14 +904,81 @@ rpl_setlocale (int category, const char *locale)
)
if (setlocale_single (cat, name) == NULL)
# if defined __APPLE__ && defined __MACH__
- /* On Mac OS X 10.13, some locales can be set through
- System Preferences > Language & Region, that are not
- supported by libc. The system's setlocale() falls
- back to "C" for these locale categories. Let's do the
- same, but print a warning, to limit user expectations. */
- fprintf (stderr,
- "Warning: Failed to set locale category %s to %s.\n",
- category_to_name (cat), name);
+ {
+ /* On Mac OS X 10.13, some locales can be set through
+ System Preferences > Language & Region, that are not
+ supported by libc. The system's setlocale() falls
+ back to "C" for these locale categories. We can possibly
+ do better. If we can't, print a warning, to limit user
+ expectations. */
+ int warn = 1;
+
+ if (cat == LC_CTYPE)
+ warn = (setlocale_single (cat, "UTF-8") == NULL);
+# if HAVE_CFLOCALECOPYPREFERREDLANGUAGES || HAVE_CFPREFERENCESCOPYAPPVALUE /* MacOS X 10.4 or newer */
+ else if (cat == LC_MESSAGES)
+ {
+ /* Take the primary language preference. */
+# if HAVE_CFLOCALECOPYPREFERREDLANGUAGES /* MacOS X 10.5 or newer */
+ CFArrayRef prefArray = CFLocaleCopyPreferredLanguages ();
+# elif HAVE_CFPREFERENCESCOPYAPPVALUE /* MacOS X 10.4 or newer */
+ CFTypeRef preferences =
+ CFPreferencesCopyAppValue (CFSTR ("AppleLanguages"),
+ kCFPreferencesCurrentApplication);
+ if (preferences != NULL
+ && CFGetTypeID (preferences) == CFArrayGetTypeID ())
+ {
+ CFArrayRef prefArray = (CFArrayRef)preferences;
+# endif
+ int n = CFArrayGetCount (prefArray);
+ if (n > 0)
+ {
+ char buf[256];
+ CFTypeRef element = CFArrayGetValueAtIndex (prefArray, 0);
+ if (element != NULL
+ && CFGetTypeID (element) == CFStringGetTypeID ()
+ && CFStringGetCString ((CFStringRef)element,
+ buf, sizeof (buf),
+ kCFStringEncodingASCII))
+ {
+ /* Remove the country.
+ E.g. "zh-Hans-DE" -> "zh-Hans". */
+ char *last_minus = strrchr (buf, '-');
+ if (last_minus != NULL)
+ *last_minus = '\0';
+
+ /* Convert to Unix locale name.
+ E.g. "zh-Hans" -> "zh_CN". */
+ gl_locale_name_canonicalize (buf);
+
+ /* Try setlocale with this value. */
+ warn = (setlocale_single (cat, buf) == NULL);
+ }
+ }
+# if HAVE_CFLOCALECOPYPREFERREDLANGUAGES /* MacOS X 10.5 or newer */
+ CFRelease (prefArray);
+# elif HAVE_CFPREFERENCESCOPYAPPVALUE /* MacOS X 10.4 or newer */
+ }
+# endif
+ }
+# endif
+ /* No fallback possible for LC_NUMERIC. The application
+ should use the locale properties
+ kCFLocaleDecimalSeparator, kCFLocaleGroupingSeparator.
+ No fallback possible for LC_TIME. The application should
+ use the locale property kCFLocaleCalendarIdentifier.
+ No fallback possible for LC_COLLATE. The application
+ should use the locale properties
+ kCFLocaleCollationIdentifier, kCFLocaleCollatorIdentifier.
+ No fallback possible for LC_MONETARY. The application
+ should use the locale properties
+ kCFLocaleCurrencySymbol, kCFLocaleCurrencyCode. */
+
+ if (warn)
+ fprintf (stderr,
+ "Warning: Failed to set locale category %s to %s.\n",
+ category_to_name (cat), name);
+ }
# else
goto fail;
# endif
diff --git a/m4/setlocale.m4 b/m4/setlocale.m4
index 802ee01fa9..e0fb74a92d 100644
--- a/m4/setlocale.m4
+++ b/m4/setlocale.m4
@@ -1,4 +1,4 @@
-# setlocale.m4 serial 4
+# setlocale.m4 serial 5
dnl Copyright (C) 2011-2018 Free Software Foundation, Inc.
dnl This file is free software; the Free Software Foundation
dnl gives unlimited permission to copy and/or distribute it,
@@ -25,5 +25,8 @@ AC_DEFUN([gl_FUNC_SETLOCALE],
# Prerequisites of lib/setlocale.c.
AC_DEFUN([gl_PREREQ_SETLOCALE],
[
+ dnl No need to check for CFLocaleCopyPreferredLanguages and
+ dnl CFPreferencesCopyAppValue because lib/setlocale.c is not used on Mac OS X.
+ dnl (The Mac OS X specific code is only used in libintl.)
:
])