From 2f688aa96807681657ba73fc6869e2b013121a45 Mon Sep 17 00:00:00 2001
From: Mika Tammi <mikatammi@gmail.com>
Date: Tue, 3 Nov 2026 20:09:13 +0100
Subject: [PATCH] lib/intl: cache the primary language preference in setlocale

Assisted-by: Claude Code (Claude Opus 5.5)
---
 lib/intl/setlocale.c | 117 ++++++++++++++++++++++++++-----------------
 1 file changed, 70 insertions(+), 47 deletions(-)

diff --git a/lib/intl/setlocale.c b/lib/intl/setlocale.c
index 04236e18..36ee27ed 100644
--- a/lib/intl/setlocale.c
+++ b/lib/intl/setlocale.c
@@ -1439,6 +1439,67 @@ get_main_locale_with_same_territory (const char *locale)
   return NULL;
 }
 
+#  if HAVE_CFLOCALECOPYPREFERREDLANGUAGES || HAVE_CFPREFERENCESCOPYAPPVALUE /* MacOS X 10.4 or newer */
+/* Returns the primary language preference as a Unix locale name, e.g. "de"
+   or "zh_CN", or NULL if there is none.
+   The result is cached: programs that fork() without exec(), such as shells,
+   call setlocale (LC_ALL, "") again in the child process, and CoreFoundation
+   must not be used in a child process before exec().  */
+static const char *
+get_primary_language_preference (void)
+{
+  static char cached_language[256];
+  static int cache_initialized;
+
+  if (!cache_initialized)
+    {
+#   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);
+
+                  strcpy (cached_language, buf);
+                }
+            }
+#   if HAVE_CFLOCALECOPYPREFERREDLANGUAGES /* MacOS X 10.5 or newer */
+      CFRelease (prefArray);
+#   elif HAVE_CFPREFERENCESCOPYAPPVALUE /* MacOS X 10.4 or newer */
+        }
+#   endif
+      cache_initialized = 1;
+    }
+
+  return cached_language[0] != '\0' ? cached_language : NULL;
+}
+#  endif
+
 # endif
 
 SHLIB_EXPORTED
@@ -1539,55 +1600,17 @@ libintl_setlocale (int category, const char *locale)
                       {
 #  if HAVE_CFLOCALECOPYPREFERREDLANGUAGES || HAVE_CFPREFERENCESCOPYAPPVALUE /* MacOS X 10.4 or newer */
                         /* 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 ())
+                        const char *pref = get_primary_language_preference ();
+                        if (pref != NULL
+                            && setlocale_single (cat, pref) == NULL)
                           {
-                            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.  */
-                                    if (setlocale_single (cat, buf) == NULL)
-                                      {
-                                        const char *last_try =
-                                          get_main_locale_with_same_language (buf);
-
-                                        if (last_try == NULL
-                                            || setlocale_single (cat, last_try) == NULL)
-                                          warn = 1;
-                                      }
-                                  }
-                              }
-#   if HAVE_CFLOCALECOPYPREFERREDLANGUAGES /* MacOS X 10.5 or newer */
-                        CFRelease (prefArray);
-#   elif HAVE_CFPREFERENCESCOPYAPPVALUE /* MacOS X 10.4 or newer */
+                            const char *last_try =
+                              get_main_locale_with_same_language (pref);
+
+                            if (last_try == NULL
+                                || setlocale_single (cat, last_try) == NULL)
+                              warn = 1;
                           }
-#   endif
 #  else
                         const char *last_try =
                           get_main_locale_with_same_language (name);
-- 
2.54.0 (Apple Git-157)

