# HG changeset patch # User Bruno Haible # Date 1537117964 -7200 # Node ID dbb326309f2afa7e410061a0cf3ec4e4bb8d67ee # Parent 6b89ce1f6b378cb92c542cad0058fc50e4c8534c 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. diff -r 6b89ce1f6b37 -r dbb326309f2a ChangeLog --- a/ChangeLog Sun Sep 16 17:14:12 2018 +0200 +++ b/ChangeLog Sun Sep 16 19:12:44 2018 +0200 @@ -1,3 +1,12 @@ +2018-09-16 Bruno Haible + + 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 Update list of locale names with scripts on macOS. diff -r 6b89ce1f6b37 -r dbb326309f2a lib/setlocale.c --- a/lib/setlocale.c Sun Sep 16 17:14:12 2018 +0200 +++ b/lib/setlocale.c Sun Sep 16 19:12:44 2018 +0200 @@ -35,6 +35,18 @@ #include "localename.h" +#if HAVE_CFLOCALECOPYPREFERREDLANGUAGES || HAVE_CFPREFERENCESCOPYAPPVALUE +# if HAVE_CFLOCALECOPYPREFERREDLANGUAGES +# include +# elif HAVE_CFPREFERENCESCOPYAPPVALUE +# include +# endif +# include +# include +# include +extern void gl_locale_name_canonicalize (char *name); +#endif + #if 1 # undef setlocale @@ -892,14 +904,81 @@ ) 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 -r 6b89ce1f6b37 -r dbb326309f2a m4/setlocale.m4 --- a/m4/setlocale.m4 Sun Sep 16 17:14:12 2018 +0200 +++ b/m4/setlocale.m4 Sun Sep 16 19:12:44 2018 +0200 @@ -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 @@ # 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.) : ])