commit:     ecfd3d86eec3e87037cd54c64b2cfc2c991742f5
Author:     Kerin Millar <kfm <AT> plushkava <DOT> net>
AuthorDate: Tue Oct 28 00:13:58 2025 +0000
Commit:     Kerin Millar <kfm <AT> plushkava <DOT> net>
CommitDate: Tue Oct 28 00:49:13 2025 +0000
URL:        https://gitweb.gentoo.org/proj/locale-gen.git/commit/?id=ecfd3d86

Warn if a locale not incorporating a codeset is in effect

The localedef(1) utility can be made to generate locales bearing
ambiguously named aliases, such as "en_US".

# locale -a
en_US
en_US.iso85591

These short-form aliases are bad for interoperability. Nevertheless,
locale-gen(8) now explicitly supports their generation, for reasons of
backward-compatibility. It stands to reason that some Gentoo users will
have chosen to globally effect a locale by such an alias, though there
is no way of knowing how many. At any rate, the sooner this practice can
be eradicated, the better.

To that end, this commit introduces the check_effective_locale()
subroutine, which is called just before locale-gen(8) successfully
exits. If the effective locale is found to be supported, but does not
incorporate a codeset, a warning shall be issued. This warning can also
be propagated by the sys-libs/glibc ebuild.

# export LANG=en_US
# locale-gen 2>&1 | tail -n2
WARNING! An ambiguous locale is currently in effect: en_US
It is strongly recommended to choose another with eselect(1) or localectl(1).

Note that eselect-1.4.31, which is currently in testing, no longer
presents locales whose names do not incorporate the UTF-8 codeset,
except for C and POSIX.

See-also: d1d1854a402b02b23b08725dac069984506f1f96
Bug: https://bugs.gentoo.org/963974
Bug: https://bugs.gentoo.org/964713
Signed-off-by: Kerin Millar <kfm <AT> plushkava.net>

 locale-gen | 25 ++++++++++++++++++++-----
 1 file changed, 20 insertions(+), 5 deletions(-)

diff --git a/locale-gen b/locale-gen
index 3265b0d..3253d02 100644
--- a/locale-gen
+++ b/locale-gen
@@ -11,7 +11,7 @@ use Errno qw(ENOENT);
 use File::Spec::Functions qw(canonpath catfile catdir path splitpath);
 use File::Temp qw(tempdir);
 use Getopt::Long ();
-use List::Util qw(any);
+use List::Util qw(any first);
 use Term::ANSIColor qw(colored);
 
 # Formally stable as of v5.40; sufficiently functional in both v5.36 and v5.38.
@@ -69,8 +69,11 @@ umask 0022;
        # Compose a list of up to two configuration files to be read.
        my @config_files = select_config_files($prefix, %opt);
 
+       # Compose a dictionary of supported locale/charmap combinations.
+       my $supported_by = map_supported_combinations($prefix);
+
        # Collect the locales that are being requested for installation.
-       push @locales, read_config($prefix, @config_files);
+       push @locales, read_config($prefix, $supported_by, @config_files);
 
        # Compose a dictionary of installed locales for the --update option.
        my %installed_by;
@@ -129,6 +132,9 @@ umask 0022;
        my $total = scalar @locales + scalar %installed_by;
        printf "Successfully installed an archive containing %d locale%s, of %s 
MiB in size.\n",
                $total, plural($total), round($size / 2 ** 20);
+
+       # Issue a warning if the effective locale does not specify a charmap.
+       check_effective_locale($supported_by);
 }
 
 sub get_locale_dir () {
@@ -274,9 +280,7 @@ sub normalize ($canonical) {
        }
 }
 
-sub read_config ($prefix, @paths) {
-       my $supported_by = map_supported_combinations($prefix);
-
+sub read_config ($prefix, $supported_by, @paths) {
        # Iterate over the given paths and return the first non-empty list of
        # valid locale declarations that can be found among them, if any.
        for my $i (keys @paths) {
@@ -586,6 +590,17 @@ sub install_archive ($src_path, $dst_path, 
$may_reset_labels) {
        }
 }
 
+sub check_effective_locale ($supported_by) {
+       my $locale = first(sub { length $_ }, @ENV{'LC_ALL', 'LANG'});
+       if (! defined $locale || $locale =~ m/\./) {
+               # No locale is effective, or that which is specifies a codeset.
+               return;
+       } elsif (exists $supported_by->{$locale}) {
+               print_warning("WARNING! An ambiguous locale is currently in 
effect: $locale\n");
+               print_warning("It is strongly recommended to choose another 
with eselect(1) or localectl(1).\n");
+       }
+}
+
 sub copy_security_context ($src_path, $dst_path) {
        local @ENV{'SRC_PATH', 'DST_PATH'} = ($src_path, $dst_path);
        my $stderr = qx{ LC_ALL=C chcon --reference="\$SRC_PATH" -- 
"\$DST_PATH" 2>&1 >/dev/null };

Reply via email to