File Coverage

blib/lib/Doit/Locale.pm
Criterion Covered Total %
statement 18 80 22.5
branch 1 36 2.7
condition 3 28 10.7
subroutine 7 10 70.0
pod 0 4 0.0
total 29 158 18.3


line stmt bran cond sub pod time code
1             # -*- perl -*-
2              
3             #
4             # Author: Slaven Rezic
5             #
6             # Copyright (C) 2017,2018,2020,2024,2025 Slaven Rezic. All rights reserved.
7             # This package is free software; you can redistribute it and/or
8             # modify it under the same terms as Perl itself.
9             #
10             # Mail: slaven@rezic.de
11             # WWW: http://www.rezic.de/eserte/
12             #
13              
14             package Doit::Locale;
15              
16 1     1   5 use strict;
  1         2  
  1         27  
17 1     1   3 use warnings;
  1         1  
  1         41  
18             our $VERSION = '0.027';
19              
20 1     1   4 use Doit::Log;
  1         2  
  1         46  
21 1     1   3 use Doit::Util qw(get_os_release);
  1         1  
  1         778  
22              
23 1     1 0 9 sub new { bless {}, shift }
24 1     1 0 2 sub functions { qw(locale_enable_locale) }
25              
26             sub add_components {
27 1     1 0 1 my @components;
28 1         4 my $osr = get_os_release;
29 1 50 50     7 if (($osr->{ID}||'') eq 'fedora' || ($osr->{ID_LIKE}||'') =~ /\bfedora\b/) {
      50        
      33        
30 0         0 push @components, 'rpm';
31             }
32 1         10 @components;
33             }
34              
35             sub locale_enable_locale {
36 0     0 0   my($self, $locale) = @_;
37 0           my %locale;
38 0 0         if (ref $locale eq 'ARRAY') {
39 0           %locale = map{($_,1)} @$locale;
  0            
40             } else {
41 0           %locale = ($locale => 1);
42             }
43              
44             ######################################################################
45             # Is locale already present?
46             my $is_locale_present = sub {
47 0 0   0     open my $fh, '-|', 'locale', '-a'
48             or error "Error while running 'locale -a': $!";
49 0           while(<$fh>) {
50 0           chomp;
51 0 0         if ($locale{$_}) {
52 0           return 1;
53             }
54             }
55 0 0         close $fh
56             or error "Error while running 'locale -a': $!";
57 0           return 0;
58 0           };
59              
60 0 0         if ($is_locale_present->()) {
61 0           return 0; # no change
62             }
63              
64             ######################################################################
65             # locale-gen (e.g. Ubuntu 12.03)
66 0 0 0       if (-x "/usr/sbin/locale-gen" && !-e "/etc/locale.gen") {
67 0           $self->system('locale-gen', $locale->[0]);
68 0           return 1;
69             }
70              
71             ######################################################################
72             # localedef (e.g RedHat, CentOS)
73 0 0 0       if (-x "/usr/bin/localedef" && -e "/etc/redhat-release") {
74             # It also exists on Debian-based systems, but works differently there.
75 0           my $use_glibc_langpack;
76             {
77 0           my $osr = get_os_release;
  0            
78 0 0 0       if (
      0        
      0        
      0        
      0        
79             ($osr->{ID} eq 'fedora' && $osr->{VERSION_ID} >= 28) # XXX since when we should take this path?
80             || ($osr->{ID} eq 'centos' && $osr->{VERSION_ID} >= 8)
81             || ($osr->{ID} eq 'rocky' && $osr->{VERSION_ID} >= 8)
82             ) {
83 0           $use_glibc_langpack = 1;
84             }
85             }
86             TRY_LOCALE: {
87 0           my @errors;
  0            
88 0 0         if ($use_glibc_langpack) {
89 0 0         if ((keys(%locale))[0] =~ m{^([^_]+)}) {
90 0           my $lang = $1;
91 0           my $package = 'glibc-langpack-'.$lang;
92 0           eval { $self->rpm_install_packages($package) };
  0            
93 0 0         if (!$@) {
94 0           last TRY_LOCALE;
95             }
96 0           push @errors, "Installing $package failed: $@";
97             }
98             }
99 0           for my $try_locale (sort keys %locale) {
100 0 0         if (my($lang_country, $charset) = $try_locale =~ m{^(.*)\.(.*)$}) {
101 0           my $stderr;
102 0           eval { $self->open3({errref => \$stderr}, '/usr/bin/localedef', '-c', '-i', $lang_country, '-f', $charset, $try_locale) };
  0            
103 0 0         if (!$@) {
104 0           last TRY_LOCALE;
105             }
106             # an error, but maybe successful?
107 0 0         if ($is_locale_present->()) {
108 0           last TRY_LOCALE;
109             }
110 0           push @errors, "Can't add '$try_locale': $stderr";
111             } else {
112 0           push @errors, "Can't parse '$try_locale' as lang_COUNTRY.charset";
113             }
114             }
115 0           error "Can't install locale. Errors:\n" . join("\n", @errors);
116             }
117 0           return 1;
118             }
119              
120             ######################################################################
121             # /etc/locale.gen (e.g. Debian and Debian-like)
122             # This file may also exist on RedHat-like systems (seen on rocky 9),
123             # but does not contain a list of commented out locales there.
124 0 0         if (-e "/etc/locale.gen") {
125 0           my $all_locales = '(' . join('|', map { quotemeta $_ } keys %locale) . ')';
  0            
126             my $changes = $self->change_file("/etc/locale.gen",
127             {match => qr{^#\s+$all_locales(\s|$)},
128 0     0     action => sub { $_[0] =~ s{^#\s+}{}; },
129             },
130 0           );
131 0 0         if (!$changes) {
132 0           error "Cannot find prepared locale '$locale->[0]' in /etc/locale.gen";
133             }
134 0           $self->system('locale-gen');
135 0           return 1;
136             }
137              
138 0 0         if ($^O eq 'darwin') {
139 0           error "No support for adding new locale '$locale->[0]' on Mac OS X";
140             }
141              
142             ######################################################################
143             # not implemented elsewhere
144 0           error "Don't know how to enable locales on this system";
145             }
146              
147             1;
148              
149             __END__