Subject: bug#65908: 29.1.50; Emacs 29 regresses on macOS

From: Gerd Möllmann <[email-masked]>
Date: Thu, 05 Oct 2023 18:39:56 +0200

Eli Zaretskii <[email-masked]> writes:

>> From: Gerd Möllmann <[email-masked]>
>> Cc: Eli Zaretskii <[email-masked]>,  [email-masked],
>>   [email-masked],  [email-masked],  [email-masked]
>> Date: Thu, 05 Oct 2023 17:11:09 +0200
>> 
>> Remains the question if that should go into emacs-29?  I'm for not
>> rocking the boat too much.  Although...
>
> Let's see the final patch, and decide then.

Please find attached.  Not much gas changed, though.

>From f1ba5bbbd9526197052949525d2ac680337b6d6b Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Gerd=20M=C3=B6llmann?= <[email-masked]>
Date: Thu, 5 Oct 2023 17:29:17 +0200
Subject: [PATCH] Handle LANG on macOS differently (bug#65908)

* src/nsterm.m (ns_init_locale): If LANG is set, try to use that,
otherwise try to deduce what LANG should be.  Check is the result is
valid, and use LANG="en_US.UTF-8" if not.
---
 src/nsterm.m | 39 +++++++++++++++++++++------------------
 1 file changed, 21 insertions(+), 18 deletions(-)

diff --git a/src/nsterm.m b/src/nsterm.m
index 4e0dfa58c63..56865987b93 100644
--- a/src/nsterm.m
+++ b/src/nsterm.m
@@ -554,29 +554,32 @@ - (unsigned long)unsignedLong
 /* macOS doesn't set any environment variables for the locale when run
    from the GUI. Get the locale from the OS and set LANG.  */
 {
-  NSLocale *locale = [NSLocale currentLocale];
-
   NSTRACE ("ns_init_locale");
 
-  /* If we were run from a terminal then assume an unset LANG variable
-     is intentional and don't try to "fix" it.  */
-  if (!isatty (STDIN_FILENO))
+  /* Either use LANG, if set, or try to construct LANG from
+     NSLocale.  */
+  const char *lang = getenv ("LANG");
+  if (lang == NULL)
     {
-      char *oldLocale = setlocale (LC_ALL, NULL);
-      /* It seems macOS should probably use UTF-8 everywhere.
-         'localeIdentifier' does not specify the encoding, and I can't
-         find any way to get the OS to tell us which encoding to use,
-         so hard-code '.UTF-8'.  */
-      NSString *localeID = [NSString stringWithFormat:@"%@.UTF-8",
-                                     [locale localeIdentifier]];
-
-      /* Check the locale ID is valid and if so set LANG, but not if
-         it is already set.  */
-      if (setlocale (LC_ALL, [localeID UTF8String]))
-        setenv("LANG", [localeID UTF8String], 0);
+      const NSLocale *locale = [NSLocale currentLocale];
+      const NSString *localeID = [NSString stringWithFormat:@"%@.UTF-8",
+					   [locale localeIdentifier]];
+      lang = [localeID UTF8String];
+    }
 
-      setlocale (LC_ALL, oldLocale);
+  /* Check if LANG can be used for initializing the locale.  If not,
+     use a default setting.  Note that Emacs' main will undo the
+     setlocale below, initializing the locale from the
+     environment.  */
+  if (setlocale (LC_ALL, lang) == NULL)
+    {
+      const char *const default_lang = "en_US.UTF-8";
+      fprintf (stderr, "LANG=%s cannot be used, using %s instead.\n",
+	       lang, default_lang);
+      lang = default_lang;
     }
+
+  setenv ("LANG", lang, 1);
 }

-- 
2.39.3 (Apple Git-145)