package lang; # $Id: lang.pm,v 1.3 2003/10/31 14:13:23 rider Exp $ use common; use log; # # NOTE: we cheat for UTF-8 locales, in DrakX they are the 8bit ones; # it's easier like that now. Of course, on the installed system a real # UTF-8 locale will be used # my %languages = ( 'en_US' => [ 'English|United States', 'iso-8859-1', 'en', 'en_US:en' ], 'en_GB' => [ 'English|United Kingdom', 'iso-8859-1', 'en', 'en_GB:en' ], 'en_IE' => [ 'English|Ireland','iso-8859-15', 'en', 'en_IE:en_GB:en' ], 'be_BY.CP1251' => [ 'Belarussian', 'cp1251', 'be', 'be_BY.CP1251:ru_RU.CP1251:be' ], 'de_AT' => [ 'German|Austria','iso-8859-15','de', 'de_AT:de' ], 'de_BE' => [ 'German|Belgium', 'iso-8859-15', 'de', 'de_BE:de' ], 'de_CH' => [ 'German|Switzerland', 'iso-8859-1', 'de', 'de_CH:de' ], 'de_DE' => [ 'German|Germany', 'iso-8859-15', 'de', 'de_DE:de' ], 'es_AR' => [ 'Spanish|Argentina', 'iso-8859-1', 'es', 'es_AR:es_UY:es:es_ES' ], 'es_ES' => [ 'Spanish|Spain', 'iso-8859-15', 'es', 'es_ES:es' ], 'es_MX' => [ 'Spanish|Mexico', 'iso-8859-1', 'es', 'es_MX:es:es_ES' ], 'fr_BE'=> [ 'French|Belgium', 'iso-8859-15','fr', 'fr_BE:fr' ], 'fr_CA' => [ 'French|Canada', 'iso-8859-15','fr', 'fr_CA:fr' ], 'fr_CH' => [ 'French|Switzerland', 'iso-8859-1', 'fr', 'fr_CH:fr' ], 'fr_FR'=> [ 'French|France', 'iso-8859-15','fr', 'fr_FR:fr' ], 'kk_KZ' => [ 'Kazakh', 'pt154', 'kk', 'kk_KZ:ru_RU.CP1251' ], 'pt_BR' => [ 'Portuguese|Brazil', 'iso-8859-1', 'pt_BR', 'pt_BR:pt_PT:pt' ], 'pt_PT'=> [ 'Portuguese|Portugal','iso-8859-15','pt', 'pt_PT:pt:pt_BR' ], 'ru_RU.KOI8-R' => [ 'Russian|KOI8-R', 'koi8-r', 'ru', 'ru_RU.KOI8-R' ], 'ru_RU.CP1251' => [ 'Russian|CP1251', 'cp1251', 'ru', 'ru_RU.CP1251' ,'koi8-r'], 'uk_UA.KOI8-U' => [ 'Ukrainian|KOI8-U', 'koi8-u', 'uk', 'uk_UA.KOI8-U' ], 'uk_UA.CP1251' => [ 'Ukrainian|CP1251', 'cp1251', 'uk', 'uk_UA.CP1251','koi8-r' ], ); sub std2 { "-*-*-medium-r-normal-*-$_[1]-*-*-*-*-*-$_[0]" } sub std_ { std2($_[0], 10), std2($_[0], 10) } sub std { std2($_[0], $_[1] || 10), std2($_[0], 8) } my %charsets = ( "armscii-8" => [ "arm8", "armscii8.uni", "trivial.trans", undef, undef, std_("armscii-8") ], "iso-8859-1" => [ "lat0-sun16", undef, "iso15", "iso8859-1", "850", sub { std("iso8859-1", @_) } ], "iso-8859-2" => [ "lat2-sun16", undef, "iso02", "iso8859-2", "852", sub { std("iso8859-2", @_) } ], "iso-8859-3" => [ "iso03.f16", undef, "iso03", "iso8859-3", undef, std_("iso8859-3") ], "iso-8859-4" => [ "lat4u-16", undef, "iso04", "iso8859-4", "775", std_("iso8859-4") ], "iso-8859-5" => [ "iso05.f16", "iso05", "trivial.trans", "iso8859-5", "855", sub { std("microsoft-cp1251", @_) } ], "iso-8859-6" => [ "iso06.f16", "iso06", "trivial.trans", "iso8859-6", "864", std_("iso8859-6") ], "iso-8859-7" => [ "iso07.f16", "iso07", "trivial.trans", "iso8859-7", "869", std_("iso8859-7") ], "iso-8859-8" => [ "iso08.f16", "iso08", "trivial.trans", # std_("iso8859-8") ], "iso8859-8", "862", std_("microsoft-cp1255") ], "iso-8859-9" => [ "iso09.f16", "iso09", "trivial.trans", "iso8859-9", "857", sub { std("iso8859-9", @_) } ], # "iso-8859-13" => [ "tlat7", "iso13", "trivial.trans", # "iso8859-13", "775", std_("iso8859-13") ], "iso-8859-14" => [ "tlat8", "iso14", "trivial.trans", "iso8859-14", "850", std_("iso8859-14") ], "iso-8859-15" => [ "lat0-sun16", undef, "iso15", "iso8859-15", "850", sub { std("iso8859-15", @_) } ], "iso-8859-9e" => [ "tiso09e", "iso09", "trivial.trans", "iso8859-9", "857", std2("iso8859-9e",10) ], "jisx0208" => [ undef, undef, "trivial.trans", "euc-jp", "932", "-*-*-*-*-*-*-*-*-*-*-*-*-jisx*.*-0" ], "koi8-r" => [ "UniCyr_8x16", undef, "koi8-r", "koi8-r", "866", sub { std("koi8-r", @_) } ], "koi8-u" => [ "UniCyr_8x16", undef, "koi8-u", "koi8-u", "866", sub { std("koi8-u", @_) } ], "cp1251" => [ "UniCyr_8x16", undef, "cp1251", "cp1251", "866", sub { std("microsoft-cp1251", @_) } ], "cp1255" => [ "iso08.f16", "iso08", "trivial.trans", "cp1255", "862", std_("microsoft-cp1255") ], "cp1256" => [ undef, undef, "trivial.trans", undef, "864", std_("microsoft-cp1255") ], "ksc5601" => [ undef, undef, undef, "euc-kr", "949", "-*-*-*-*-*-*-*-*-*-*-*-*-ksc5601.1987-*" ], "viscii" => [ "viscii10-8x16", "viscii.uni", "viscii1.0_to_viscii1.1.trans", undef, undef, std2("tcvn-5712", 13), std2("tcvn-5712", 10) ], "unicode" => [ undef, undef, "trivial.trans", "utf8", undef, "-*-*-*-*-*-*-*-*-*-*-*-*-iso10646-1" ], ); my %bigfonts = ( ksc5601 => 'baekmuk_gulim_h_14.pcf.gz', unicode => 'cu12.pcf.gz', ); sub list { keys %languages } sub lang2text { exists $languages{$_[0]} && $languages{$_[0]}[0] } sub lang2charset { exists $languages{$_[0]} && $languages{$_[0]}[1] } sub lang2installer{ exists $languages{$_[0]} && ($languages{$_[0]}[4] || $languages{$_[0]}[1]) } sub lang2LANG { exists $languages{$_[0]} && $languages{$_[0]}[2] } sub lang2LANGUAGE { exists $languages{$_[0]} && $languages{$_[0]}[3] } sub set { my ($lang) = @_; if ($lang && !exists $languages{$lang}) { my ($lang2) = grep { /^\Q$lang/ } list(); my ($lang3) = grep { $lang =~ /^\Q$_/ } list(); log::l("lang::set: fixing $lang with ", $lang2 || $lang3); $lang = $lang2 || $lang3; } if ($lang && exists $languages{$lang}) { # if (!-e "$ENV{SHARE_PATH}/locale/$lang" && common::usingRamdisk()) { # @ENV{qw(LANG LC_ALL LANGUAGE LINGUAS)} = (); # # eval { rm_rf("$ENV{SHARE_PATH}/locale") }; # eval { # require packdrake; # my $packer = new packdrake("$ENV{SHARE_PATH}/locale.cz2", quiet => 1); # my $tmplang = lang2LANG($lang); # print "tmplang: $tmplang, lang: $lang\n"; # foreach(list()){ # print "dir: $_\n"; # $packer->extract_archive("$ENV{SHARE_PATH}/locale", $_) if $_ =~ /^$tmplang/; # } # $packer->extract_archive("$ENV{SHARE_PATH}/locale", $tmplang); # }; # } $ENV{LC_NUMERIC} = "C"; $ENV{LC_TIME} = "C"; $ENV{LC_COLLATE} = "C"; $ENV{LC_MONETARY} = "C"; $ENV{LC_PAPER} = "C"; $ENV{LC_NAME} = "C"; $ENV{LC_ADDRESS} = "C"; $ENV{LC_TELEPHONE} = "C"; $ENV{LC_MEASUREMENT} = "C"; $ENV{LC_IDENTIFICATION} = "C"; ( my $current_l = lang2LANGUAGE($lang) ) =~ s/:.*//; $ENV{LC_CTYPE} = $current_l; # 1 $ENV{LC_MESSAGES} = $current_l; #2 $ENV{LANG} = $current_l; #3 $ENV{LANGUAGE} = lang2LANGUAGE($lang); load_mo(); } else { # stick with the default (English) */ delete $ENV{LANG}; delete $ENV{LC_ALL}; delete $ENV{LANGUAGE}; delete $ENV{LINGUAS}; } $lang; } sub langs { my ($l) = @_; grep { $l->{$_} } keys %$l; } sub all_langs { my ($l) = @_; join ":", grep { $l->{$_} } keys %$l ; } sub install_langs { my ($l) = @_; my %hh; foreach (grep { $l->{$_} } keys %$l){ s/^([^.]*)\..*/$1/; $hh{$_}=1; $hh{"ru_RU"}=1 if /be|uk/; } return keys %hh; } sub langsLANGUAGE { my ($l) = @_; my @l = $l->{all} ? list() : langs($l); uniq(map { split ':', lang2LANGUAGE($_) } @l); } sub pack_langs { my ($l) = @_; my $s = $l->{all} ? 'all' : join ':',install_langs($l); $ENV{RPM_INSTALL_LANG} = $s; $s; } sub unpack_langs { my ($s) = @_; my @l = uniq(map { split ':', lang2LANGUAGE($_) } split(':', $s)); my @l2 = intersection(\@l, [ keys %languages ]); +{ map { $_ => 1 } @l2 }; } sub read { my ($prefix) = @_; my %h = getVarsFromSh("$prefix/etc/sysconfig/i18n"); my $lang = $h{LC_MESSAGES} || 'en_US'; my $langs = cat_("$prefix/etc/rpm/macros") =~ /%_install_langs (.*)/ ? unpack_langs($1) : { $lang => 1 }; $lang, $langs; } sub write_langs { my ($prefix, $langs) = @_; my $s = pack_langs($langs); symlink "$prefix/etc/rpm", "/etc/rpm" if $prefix; # substInFile { s/%_install_langs.*//; $_ .= "%_install_langs $s\n" if eof && $s } "$prefix/etc/rpm/macros"; } sub write { my ($prefix, $lang,$langs) = @_; $lang or return; my $h = {}; #$h->{$_} = $lang foreach qw(LC_COLLATE LC_CTYPE LC_MESSAGES LC_NUMERIC LC_MONETARY LC_TIME); if ($lang && exists $languages{$lang}) { # add2hash $h, { LANG => $lang, LANGUAGE => lang2LANGUAGE($lang) }; add2hash $h, { LANG => $lang, LANGUAGE => all_langs($langs) }; my $c = $charsets{lang2charset($lang) || ''}; if ($c) { my $p = "$prefix/usr/lib/kbd"; if ($c->[0]) { add2hash $h, { SYSFONT => $c->[0] }; eval { cp_af("$p/consolefonts/$c->[0].psf.gz", "$prefix/etc/sysconfig/console/consolefonts"); }; $@ and log::l("missing console font $c->[0]"); } if ($c->[1]) { add2hash $h, { UNIMAP => $c->[1] }; eval { cp_af(glob_("$p/consoletrans/$c->[1]*"), "$prefix/etc/sysconfig/console/consoletrans"); }; $@ and log::l("missing console unimap file $c->[1]"); } if ($c->[2]) { add2hash $h, { SYSFONTACM => $c->[2] }; eval { cp_af(glob_("$p/consoletrans/$c->[2]*"), "$prefix/etc/sysconfig/console/consoletrans"); }; $@ and log::l("missing console acm file $c->[2]"); } } } setVarsInSh("$prefix/etc/sysconfig/i18n", $h); } sub load_mo { my ($lang) = @_; my ($localedir, $suffix) = ("$ENV{SHARE_PATH}/locale", 'LC_MESSAGES/libDrakX.mo'); $localedir .= "_special" if $::isInstall; $lang ||= $ENV{LANGUAGE} || $ENV{LC_ALL} || $ENV{LC_MESSAGES} || $ENV{LANG}; c::setlocale(); c::bindtextdomain('libDrakX', $localedir); foreach (split '_', $lang) { my $f = "$localedir/$_/$suffix"; -s $f and return $_; if ($::isInstall && common::usingRamdisk()) { # cleanup eval { rm_rf($localedir) }; eval { mkdir_p(dirname("$localedir/$_/$suffix")) }; install_any::getAndSaveFile ("$localedir/$_/$suffix"); -s $f and return $_; } } ''; } sub console_font_files { map { -e $_ ? $_ : "$_.gz" } (map { "/usr/lib/kbd/consolefonts/$_.psf" } uniq grep {$_} map { $_->[0] } values %charsets), (map { -e $_ ? $_ : "$_.sfm" } map { "/usr/lib/kbd/consoletrans/$_" } uniq grep {$_} map { $_->[1] } values %charsets), (map { -e $_ ? $_ : "$_.acm" } map { "/usr/lib/kbd/consoletrans/$_" } uniq grep {$_} map { $_->[2] } values %charsets), } sub load_console_font { my ($lang) = @_; my ($f, $u, $m) = @{$charsets{lang2installer($lang)} || []}; require run_program; run_program::run(if_($ENV{LD_LOADER}, $ENV{LD_LOADER}), 'consolechars', '-v', '-f', $f || 'lat0-sun16', if_($u, '-u', $u), if_($m, '-m', $m)); } sub get_x_fontset { my ($lang, $size) = @_; my $charset = lang2charset($lang) or return; my $c = $charsets{$charset} or return; if (my $f = $bigfonts{$charset}) { my $dir = "/usr/X11R6/lib/X11/fonts"; if (! -e "$dir/$f" && $::isInstall && common::usingRamdisk()) { unlink "$dir/$_" foreach values %bigfonts; install_any::remove_bigseldom_used (); install_any::getAndSaveFile ("$dir/$f"); } } my ($big, $small) = @$c[5..6]; ($big, $small) = $big->($size) if ref $big; ($big, $small); } sub fs_options { my ($lang) = @_; my $charset = lang2charset($lang) or return; my $c = $charsets{$charset} or return; my ($iocharset, $codepage) = @$c[3..4]; $iocharset, $codepage; } sub charset { my ($lang, $prefix) = @_; my $l = lang2LANG($lang); foreach (cat_("$prefix/usr/X11R6/lib/X11/locale/locale.alias")) { /$l:\s+.*\.(\S+)/ and return $1; } $l =~ /.*\.(\S+)/ and return $1; } 1;