bug-gettext
[Top][All Lists]
Advanced

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

Re: macOS 12 - cannot override LC_ALL=C setting from environment


From: Gavin Smith
Subject: Re: macOS 12 - cannot override LC_ALL=C setting from environment
Date: Sun, 1 Dec 2024 12:07:14 +0000

On Sun, Dec 01, 2024 at 02:41:43AM +0100, Bruno Haible wrote:
> > So even though we try to override LC_ALL by calling setlocale in the
> > program, nothing happens.
> 
> The reason why it does not work is that this program is not following
> the documented requirement from
> https://www.gnu.org/software/gettext/manual/html_node/C.html :
>   "Programmer must call setlocale (LC_ALL, "")"
> 
> In other words, instead of doing
>   setlocale (LC_ALL, "en_US.UTF-8");
> you need to do
>   setenv ("LC_ALL", "en_US.UTF-8", 1);
>   setlocale (LC_ALL, "");

Thanks, this appears to do the job.  (In the test program I sent, I
also needed to set LANGUAGE.)

We had "adapted" the requirement from the gettext manual, as we don't
want to use the user's locale settings for translated strings.

> It's unfortunate that your code is working as expected on GNU, FreeBSD, 
> NetBSD,
> Solaris systems but not on macOS, Windows, AIX, and OpenBSD. But there are
> (complicated) reasons for it, see
> https://git.savannah.gnu.org/gitweb/?p=gnulib.git;a=blob;f=lib/localename-unsafe.c;h=0a2654d8a3fcd025c80d4ad6eb34ce02c13879e5;hb=HEAD#l3202

I don't understand from this why using the locale name as the second
argument to setlocale doesn't work, but providing exactly the same string
as the argument to setenv does.  I couldn't see anywhere in the "gettext"
or "libc" manuals to say that the second argument to setlocale should
only be "" and not the locale name.  Could the gettext manual have a
note of the possibility of calling setenv before calling setlocale?

In texi2any, we use LC_MESSAGES instead of LC_ALL to try to avoid
disturbing other parts of the program.  However, the gettext manual also
says that LC_CTYPE should be set.

"Remember that gettext will act as a no-op if the LC_MESSAGES and LC_CTYPE 
locale categories are not both set."
https://www.gnu.org/software/gettext/manual/html_node/Language-Implementors.html

The gettext manual also has an example of setting both LC_MESSAGES and
LC_CTYPE, instead of LC_ALL.

       So it is sometimes necessary to replace the ‘LC_ALL’ line in the code
    above by a sequence of ‘setlocale’ lines
    
         {
           ...
           setlocale (LC_CTYPE, "");
           setlocale (LC_MESSAGES, "");
           ...
         }

https://www.gnu.org/software/gettext/manual/html_node/Triggering.html

We have a comment in the program:

  /*
  We need to set LC_MESSAGES to a valid locale other than "C" or "POSIX"
  for translation via LANGUAGE to work.  (The locale is "C" if the
  tests are being run.)
    LC_MESSAGES was reported not to exist for Perl on MS-Windows.  We
  could use LC_ALL instead, but (a) it's not clear if this would help,
  and (b) this could interfere with the LC_CTYPE setting in XSParagraph.
   */ 

So I expect we need to change LC_CTYPE as well.  Patrice reported that
just setting LC_MESSAGES wasn't enough in his testing.

We avoid calling this locale-switching code on MS-Windows, where LC_MESSAGES
does not exist.

Here's the change I applied for texi2any:

diff --git a/tp/Texinfo/XS/main/translations.c 
b/tp/Texinfo/XS/main/translations.c
index 6748cdb612..19020bda23 100644
--- a/tp/Texinfo/XS/main/translations.c
+++ b/tp/Texinfo/XS/main/translations.c
@@ -104,18 +104,24 @@ switch_messages_locale (void)
 
   if (working_locale)
     {
-      setenv_status = setenv ("LANG", working_locale, 1);
-      locale = setlocale (LC_MESSAGES, working_locale);
+      setenv_status = setenv ("LC_MESSAGES", working_locale, 1);
+                      || setenv ("LANG", working_locale, 1);
+      locale = setlocale (LC_MESSAGES, "");
+
+      /* Note that running "setlocale (LC_MESSAGES, working_locale)" directly
+         may not work depending on platform and/or gettext version. */
     }
   if (!locale || setenv_status)
     {
-      setenv_status = setenv ("LANG", "en_US.UTF-8", 1);
-      locale = setlocale (LC_MESSAGES, "en_US.UTF-8");
+      setenv_status = setenv ("LC_MESSAGES", "en_US.UTF-8", 1);
+                      || setenv ("LANG", "en_US.UTF-8", 1);
+      locale = setlocale (LC_MESSAGES, "");
     }
   if (!locale || setenv_status)
     {
-      setenv_status = setenv ("LANG", "en_US", 1);
-      locale = setlocale (LC_MESSAGES, "en_US");
+      setenv_status = setenv ("LC_MESSAGES", "en_US", 1);
+                      || setenv ("LANG", "en_US", 1);
+      locale = setlocale (LC_MESSAGES, "");
     }
   if ((!locale || setenv_status) && !locale_command)
     {
@@ -143,8 +149,9 @@ switch_messages_locale (void)
                   free (line);
                   continue;
                 }
-              setenv_status = setenv ("LANG", line, 1);
-              locale = setlocale (LC_MESSAGES, line);
+              setenv_status = setenv ("LC_MESSAGES", line, 1);
+                              || setenv ("LANG", line, 1);
+              locale = setlocale (LC_MESSAGES, "");
               if (locale && !setenv_status)
                 {
                   free (line);




reply via email to

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