Skip Menu |

This queue is for tickets about the libintl-perl CPAN distribution.

Report information
The Basics
Id: 81315
Status: resolved
Priority: 0/
Queue: libintl-perl

People
Owner: Nobody in particular
Requestors: GUIDO [...] cpan.org
Cc:
AdminCc:

Bug Information
Severity: Normal
Broken in: 1.20
Fixed in: (no value)



Subject: Wrong usage of $ENV{LANGUAGE}
By Patrice Dumas: Hello Guido, We have released a pretest version of texinfo. And there is a report relevant for you. A user is setting LC_ALL=C while having LANGUAGE set, and he expects the locale to switch to C. This is indeed what GNU gettext does: http://www.gnu.org/software/gettext/manual/html_node/The-LANGUAGE-variable.html#The-LANGUAGE-variable Last paragraph: Note: The variable LANGUAGE is ignored if the locale is set to ‘C’. In other words, you have to first enable localization, by setting LANG (or LC_ALL) to a value other than ‘C’, before you can use a language priority list through the LANGUAGE variable. I think that libintl-perl should follow this too. (In general, I think that libintl-perl should try to be compatible with GNU gettext as it is more or less the defacto standard). Do you agree?
On Wed Nov 21 03:26:14 2012, GUIDO wrote: Show quoted text
> http://www.gnu.org/software/gettext/manual/html_node/The-LANGUAGE- > variable.html#The-LANGUAGE-variable > > Last paragraph: > > Note: The variable LANGUAGE is ignored if the locale is set to ‘C’. > In > other words, you have to first enable localization, by setting LANG > (or > LC_ALL) to a value other than ‘C’, before you can use a language > priority list through the LANGUAGE variable.
That note is actually not completely correct. The setting of LANG is irrelevant in that case. You _must_ set LC_ALL or LC_MESSAGES to a valid locale other than the POSIX locale. Internally, the condition in the GNU libc implementation of gettext seems to be that setlocale (LC_MESSAGES, NULL) returns a value other than "C" or "POSIX". That is not the case if just "LANG" is set. I have fixed the pure Perl version in git (branch "v1"!) so that it shows exactly the same behavior as the XS version on my (glibc/linux!) system. On systems that do not support LC_MESSAGES, the old behavior is preserved. It would be possible to check that at least for LC_ALL something other than "C" or "POSIX" is returned but that doesn't make much sense imho. I have attached a file "testenv.c". If you have the locales de_DE.utf-8 and fr_FR.utf-8, you can compile and run it, and pump the results for different combinations for LANGUAGE, LANG, LC_ALL, and LC_MESSAGES into an SQLite database. I have used a similar file for generating the test cases in tests/03environment_{pp,xs}.t. Guido
Subject: testenv.c
#include <stdio.h> #include <libintl.h> #include <locale.h> #include <stdlib.h> #include <string.h> static const char *values[] = { NULL, "C", "de_DE.utf-8", "fr_FR.utf-8" }; static void mysetenv (const char *key, const char *value); static char *quote (const char *arg); main (int argc, char *argv[]) { int i, j, k, l; const char *translation; const char *locale; printf ("DROP TABLE IF EXISTS t;\n"); printf ("CREATE TABLE t (LANGUAGE text, LANG text,\n" " LC_MESSAGES text, LC_ALL text,\n" " trans text, locale text);\n"); unsetenv ("LANGUAGE"); unsetenv ("LANG"); unsetenv ("LC_ALL"); unsetenv ("LC_MESSAGES"); unsetenv ("LC_TIME"); unsetenv ("LC_MONETARY"); unsetenv ("LC_CTYPE"); unsetenv ("LC_NUMERIC"); for (i = 0; i < 4; ++i) { mysetenv ("LANGUAGE", values[i]); for (j = 0; j < 4; ++j) { mysetenv ("LANG", values[j]); for (k = 0; k < 4; ++k) { mysetenv ("LC_MESSAGES", values[k]); for (l = 0; l < 4; ++l) { mysetenv ("LC_ALL", values[l]); locale = setlocale (LC_MESSAGES, NULL); translation = dcgettext ("libc", "No such file or directory", LC_MESSAGES); printf ("INSERT INTO t (LANGUAGE, LANG,\n" " LC_MESSAGES, LC_ALL,\n" " trans, locale)\n" " VALUES (%s, %s, %s, %s, %s, %s);\n", quote (values[i]), quote (values[j]), quote (values[k]), quote (values[l]), quote (translation), quote (locale)); } } } } return 0; } static void mysetenv (const char *key, const char *value) { if (value) setenv (key, value, 1); else unsetenv (key); } static char * quote (const char *arg) { char *retval; if (!arg) return "NULL"; retval = malloc (strlen (arg) + 3); if (!retval) exit (255); sprintf (retval, "'%s'", arg); return retval; }
Fixed in git.