Perl Fails to Set Locale Even Though It Is Installed

Perl fails to set locale even though it is installed

Found the answer while writing the question:

The culprit is LC_CTYPE=UTF-8, which is apparently perfectly valid in macOS (and Perl will accept it there), but not on Linux. To avoid it, one can override LC_CTYPE as follows:

root@Box:~# update-locale LC_CTYPE=en_US.UTF-8

After logging out and back in again, Perl will no longer complain.

user@Box:~# perl -e 'print "Hack the Planet!\n"'
Hack the Planet!

How to fix a locale setting warning from Perl

Your OS doesn't know about en_US.UTF-8.

You didn't mention a specific platform, but I can reproduce your problem:

% uname -a
OSF1 hunter2 V5.1 2650 alpha
% perl -e exit
perl: warning: Setting locale failed.
perl: warning: Please check that your locale settings:
LC_ALL = (unset),
LANG = "en_US.UTF-8"
are supported and installed on your system.
perl: warning: Falling back to the standard locale ("C").

My guess is you used ssh to connect to this older host from a newer desktop machine. It's common for /etc/ssh/sshd_config to contain

AcceptEnv LANG LC_*

which allows clients to propagate the values of those environment variables into new sessions.

The warning gives you a hint about how to squelch it if you don't require the full-up locale:

% env LANG=C perl -e exit
%

or with Bash:

$ LANG=C perl -e exit
$

For a permanent fix, choose one of

  1. On the older host, set the LANG environment variable in your shell's initialization file.
  2. Modify your environment on the client side, e.g., rather than ssh hunter2, use the command LANG=C ssh hunter2.
  3. If you have administrator rights, stop ssh from sending the environment variables by commenting out the SendEnv LANG LC_* line in the local /etc/ssh/ssh_config file. (Thanks to this answer. See Bug 1285 for OpenSSH for more.)

Unable to fetch system locale in perl on Windows

To get the Windows locale (as opposed to a non-existent POSIX locale) in a POSIX-style format, you can Win32::Locale's get_locale.

>perl -e"use Win32::Locale qw( ); CORE::say Win32::Locale::get_locale()"
en_ca

That's mostly a guess. Windows locales are really numbers.

>perl -e"use Win32::Locale qw( ); CORE::say sprintf '0x%X', Win32::Locale::get_ms_locale()"
0x1009

Locale::TextDomain fails when $LANG is not initially set

The locale "" (the empty string) denotes the system locale. All known Un*x implementations of setlocale() use then environment variables to set the locale. You are setting the environment variable after the call to setlocale(), and it is therefore ignored.

Locale::TextDomain does not fail here. It is a configuration error.

There are several approaches for fixing such problems. If you know the language that you want to use you can let libintl-perl do the heavy liftings:

use Locale::Util qw(set_locale);

set_locale(LC_MESSAGES, 'pt', 'BR', 'utf-8');

The call to set_locale() will try all known conventions for locale identifiers for setting the language to Portuguese 'pt' for Brazil ('BR'). It will also try to select a UTF-8 locale. See http://search.cpan.org/dist/libintl-perl/lib/Locale/Util.pm#FUNCTIONS for more information! The name set_locale() was intentionally chosen to avoid a name clash with setlocale() from POSIX.pm.

Beginning with libintl-perl 1.22, you can also switch to the "dumb" gettext backend:

use Locale::Messages qw(select_package);

BEGIN { Locale::Messages->select_package('gettext_dumb') }

The "dumb" backend never bothers to call setlocale() to find the current locale settings but only inspects environment variables. Please see http://search.cpan.org/dist/libintl-perl/lib/Locale/gettext_dumb.pm for the pros and cons of this approach. The biggest disadvantage is that C code does not honor this, so that $! for example will not use the configured language.

Alternatively you can switch to the 'gettext_pp' backend just as described for 'gettext_dumb' above. This will force using the pure Perl implementation of the gettext runtime. The main advantage of this is actually that it is easier to debug. But there are also subtle differences to the C implementation.

Just a side note: You should keep in mind that the environment variable LANGUAGE is a GNU extension and may not work in a non-GNU environment.

How to set locale settings while upgrading PostgreSQL from 9.3 to 9.4

You need to run this:

aptitude install language-pack-es-base
locale-gen

export LANGUAGE=en_US.UTF-8
export LANG=en_US.UTF-8
export LC_ALL=en_US.UTF-8
locale-gen en_US.UTF-8
dpkg-reconfigure locales

echo LANGUAGE=en_US.UTF-8 > /etc/default/locale
echo LANG=en_US.UTF-8 >> /etc/default/locale
echo export LC_ALL=en_US.UTF-8 >> /etc/default/locale

This will solve your issue.

How to fix a locale setting warning from Perl

Your OS doesn't know about en_US.UTF-8.

You didn't mention a specific platform, but I can reproduce your problem:

% uname -a
OSF1 hunter2 V5.1 2650 alpha
% perl -e exit
perl: warning: Setting locale failed.
perl: warning: Please check that your locale settings:
LC_ALL = (unset),
LANG = "en_US.UTF-8"
are supported and installed on your system.
perl: warning: Falling back to the standard locale ("C").

My guess is you used ssh to connect to this older host from a newer desktop machine. It's common for /etc/ssh/sshd_config to contain

AcceptEnv LANG LC_*

which allows clients to propagate the values of those environment variables into new sessions.

The warning gives you a hint about how to squelch it if you don't require the full-up locale:

% env LANG=C perl -e exit
%

or with Bash:

$ LANG=C perl -e exit
$

For a permanent fix, choose one of

  1. On the older host, set the LANG environment variable in your shell's initialization file.
  2. Modify your environment on the client side, e.g., rather than ssh hunter2, use the command LANG=C ssh hunter2.
  3. If you have administrator rights, stop ssh from sending the environment variables by commenting out the SendEnv LANG LC_* line in the local /etc/ssh/ssh_config file. (Thanks to this answer. See Bug 1285 for OpenSSH for more.)


Related Topics



Leave a reply



Submit