Changeset 2594

Show
Ignore:
Timestamp:
06/18/08 02:03:47 (6 months ago)
Author:
fumiakiy
Message:

Updating I18N::LangTags to version 0.35 and Locale::MakeText to version 1.13 for better support of Perl 5.10. BugId:80126

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • branches/release-40/extlib/I18N/LangTags.pm

    r1098 r2594  
    11 
    2 # Time-stamp: "2002-02-02 20:43:03 MST" 
     2# Time-stamp: "2004-10-06 23:26:33 ADT" 
    33# Sean M. Burke <sburke@cpan.org> 
    44 
     
    1515                locale2language_tag alternate_language_tags 
    1616                encode_language_tag panic_languages 
     17                implicate_supers 
     18                implicate_supers_strictly 
    1719               ); 
    1820%EXPORT_TAGS = ('ALL' => \@EXPORT_OK); 
    1921 
    20 $VERSION = "0.27"; 
     22$VERSION = "0.35"; 
     23 
     24sub uniq { my %seen; return grep(!($seen{$_}++), @_); } # a util function 
     25 
    2126 
    2227=head1 NAME 
     
    2631=head1 SYNOPSIS 
    2732 
    28     use I18N::LangTags qw(is_language_tag same_language_tag 
    29                           extract_language_tags super_languages 
    30                           similarity_language_tag is_dialect_of 
    31                           locale2language_tag alternate_language_tags 
    32                           encode_language_tag panic_languages 
    33                          ); 
    34  
    35 ...or whatever of those functions you want to import.  Those are 
    36 all the exportable functions -- you're free to import only some, 
    37 or none at all.  By default, none are imported.  If you say: 
     33  use I18N::LangTags(); 
     34 
     35...or specify whichever of those functions you want to import, like so: 
     36 
     37  use I18N::LangTags qw(implicate_supers similarity_language_tag); 
     38 
     39All the exportable functions are listed below -- you're free to import 
     40only some, or none at all.  By default, none are imported.  If you 
     41say: 
    3842 
    3943    use I18N::LangTags qw(:ALL) 
     
    400404 
    401405  $lang =~ tr<_><->;  # "en_US" -> en-US 
    402   $lang =~ s<\.[-_a-zA-Z0-9\.]*><>s;  # "en_US.ISO8859-1" -> en-US 
     406  $lang =~ s<(?:[\.\@][-_a-zA-Z0-9]+)+$><>s;  # "en_US.ISO8859-1" -> en-US 
     407   # it_IT.utf8@euro => it-IT 
    403408 
    404409  return $lang if &is_language_tag($lang); 
     
    530535  $tag =~ s/^iw\b/he/i; # Hebrew 
    531536  $tag =~ s/^in\b/id/i; # Indonesian 
     537  $tag =~ s/^cre\b/cr/i; # Cree 
     538  $tag =~ s/^jw\b/jv/i; # Javanese 
    532539  $tag =~ s/^[ix]-lux\b/lb/i;  # Luxemburger 
    533540  $tag =~ s/^[ix]-navajo\b/nv/i;  # Navajo 
    534541  $tag =~ s/^ji\b/yi/i;  # Yiddish 
     542  # SMB 2003 -- Hm.  There's a bunch of new XXX->YY variances now, 
     543  #  but maybe they're all so obscure I can ignore them.   "Obscure" 
     544  #  meaning either that the language is obscure, and/or that the 
     545  #  XXX form was extant so briefly that it's unlikely it was ever 
     546  #  used.  I hope. 
    535547  # 
    536548  # These go FROM the simplex to complex form, to get 
     
    731743} 
    732744 
     745#--------------------------------------------------------------------------- 
     746#--------------------------------------------------------------------------- 
     747 
     748=item * the function implicate_supers( ...languages... ) 
     749 
     750This takes a list of strings (which are presumed to be language-tags; 
     751strings that aren't, are ignored); and after each one, this function 
     752inserts super-ordinate forms that don't already appear in the list. 
     753The original list, plus these insertions, is returned. 
     754 
     755In other words, it takes this: 
     756 
     757  pt-br de-DE en-US fr pt-br-janeiro 
     758 
     759and returns this: 
     760 
     761  pt-br pt de-DE de en-US en fr pt-br-janeiro 
     762 
     763This function is most useful in the idiom 
     764 
     765  implicate_supers( I18N::LangTags::Detect::detect() ); 
     766 
     767(See L<I18N::LangTags::Detect>.) 
     768 
     769 
     770=item * the function implicate_supers_strictly( ...languages... ) 
     771 
     772This works like C<implicate_supers> except that the implicated 
     773forms are added to the end of the return list. 
     774 
     775In other words, implicate_supers_strictly takes a list of strings 
     776(which are presumed to be language-tags; strings that aren't, are 
     777ignored) and after the whole given list, it inserts the super-ordinate forms  
     778of all given tags, minus any tags that already appear in the input list. 
     779 
     780In other words, it takes this: 
     781 
     782  pt-br de-DE en-US fr pt-br-janeiro 
     783 
     784and returns this: 
     785 
     786  pt-br de-DE en-US fr pt-br-janeiro pt de en 
     787 
     788The reason this function has "_strictly" in its name is that when 
     789you're processing an Accept-Language list according to the RFCs, if 
     790you interpret the RFCs quite strictly, then you would use 
     791implicate_supers_strictly, but for normal use (i.e., common-sense use, 
     792as far as I'm concerned) you'd use implicate_supers. 
     793 
     794=cut 
     795 
     796sub implicate_supers { 
     797  my @languages = grep is_language_tag($_), @_; 
     798  my %seen_encoded; 
     799  foreach my $lang (@languages) { 
     800    $seen_encoded{ I18N::LangTags::encode_language_tag($lang) } = 1 
     801  } 
     802 
     803  my(@output_languages); 
     804  foreach my $lang (@languages) { 
     805    push @output_languages, $lang; 
     806    foreach my $s ( I18N::LangTags::super_languages($lang) ) { 
     807      # Note that super_languages returns the longest first. 
     808      last if $seen_encoded{ I18N::LangTags::encode_language_tag($s) }; 
     809      push @output_languages, $s; 
     810    } 
     811  } 
     812  return uniq( @output_languages ); 
     813 
     814} 
     815 
     816sub implicate_supers_strictly { 
     817  my @tags = grep is_language_tag($_), @_; 
     818  return uniq( @_,   map super_languages($_), @_ ); 
     819} 
     820 
     821 
     822 
    733823########################################################################### 
    7348241; 
     
    771861C<http://www.perl.com/CPAN/modules/by-module/Locale/> 
    772862 
    773 * ISO 639, "Code for the representation of names of languages", 
    774 C<http://www.indigo.ie/egt/standards/iso639/iso639-1-en.html> 
    775  
    776863* ISO 639-2, "Codes for the representation of names of languages", 
    777 including three-letter codes, 
    778 C<http://lcweb.loc.gov/standards/iso639-2/bibcodes.html> 
     864including two-letter and three-letter codes, 
     865C<http://www.loc.gov/standards/iso639-2/langcodes.html> 
    779866 
    780867* The IANA list of registered languages (hopefully up-to-date), 
    781 C<ftp://ftp.isi.edu/in-notes/iana/assignments/languages/
     868C<http://www.iana.org/assignments/language-tags
    782869 
    783870=head1 COPYRIGHT 
    784871 
    785 Copyright (c) 1998-2001 Sean M. Burke. All rights reserved. 
     872Copyright (c) 1998+ Sean M. Burke. All rights reserved. 
    786873 
    787874This library is free software; you can redistribute it and/or 
  • branches/release-40/extlib/I18N/LangTags/List.pm

    r1098 r2594  
    22require 5; 
    33package I18N::LangTags::List; 
    4 #  Time-stamp: "2002-02-02 20:13:58 MST" 
     4#  Time-stamp: "2004-10-06 23:26:21 ADT" 
    55use strict; 
    6 use vars qw(%Name $Debug $VERSION); 
    7 $VERSION = '0.25'; 
     6use vars qw(%Name %Is_Disrec $Debug $VERSION); 
     7$VERSION = '0.35'; 
    88# POD at the end. 
    99 
     
    1313  my $seeking = 1; 
    1414  my $count = 0; 
    15   my($tag,$name); 
     15  my($disrec,$tag,$name); 
     16  my $last_name = ''; 
    1617  while(<I18N::LangTags::List::DATA>) { 
    1718    if($seeking) { 
    1819      $seeking = 0 if m/=for woohah/; 
    19     } else { 
    20       next unless ($tag, $name) = 
    21        m/\{([-0-9a-zA-Z]+)\}(?:\s*:)?\s*([^\[\]]+)/; 
     20    } elsif( ($disrec, $tag, $name) = 
     21          m/(\[?)\{([-0-9a-zA-Z]+)\}(?:\s*:)?\s*([^\[\]]+)/ 
     22    ) { 
    2223      $name =~ s/\s*[;\.]*\s*$//g; 
    2324      next unless $name; 
    2425      ++$count; 
    2526      print "<$tag> <$name>\n" if $Debug; 
    26       $Name{$tag} = $name; 
     27      $last_name = $Name{$tag} = $name; 
     28      $Is_Disrec{$tag} = 1 if $disrec; 
     29    } elsif (m/[Ff]ormerly \"([-a-z0-9]+)\"/) { 
     30      $Name{$1} = "$last_name (old tag)" if $last_name; 
     31      $Is_Disrec{$1} = 1; 
    2732    } 
    2833  } 
     
    7277} 
    7378 
     79#-------------------------------------------------------------------------- 
     80 
     81sub is_decent { 
     82  my $tag = lc($_[0] || return 0); 
     83  #require I18N::LangTags; 
     84 
     85  return 0 unless 
     86    $tag =~  
     87    /^(?:  # First subtag 
     88         [xi] | [a-z]{2,3} 
     89      ) 
     90      (?:  # Subtags thereafter 
     91         -           # separator 
     92         [a-z0-9]{1,8}  # subtag   
     93      )* 
     94    $/xs; 
     95 
     96  my @supers = (); 
     97  foreach my $bit (split('-', $tag)) { 
     98    push @supers,  
     99      scalar(@supers) ? ($supers[-1] . '-' . $bit) : $bit; 
     100  } 
     101  return 0 unless @supers; 
     102  shift @supers if $supers[0] =~ m<^(i|x|sgn)$>s; 
     103  return 0 unless @supers; 
     104 
     105  foreach my $f ($tag, @supers) { 
     106    return 0 if $Is_Disrec{$f}; 
     107    return 2 if $Name{$f}; 
     108     # so that decent subforms of indecent tags are decent 
     109  } 
     110  return 2 if $Name{$tag}; # not only is it decent, it's known! 
     111  return 1; 
     112} 
     113 
     114#-------------------------------------------------------------------------- 
    741151; 
    75116 
     
    103144 
    104145The function I18N::LangTags::List::name(...) is not exported. 
     146 
     147This module also provides a function 
     148C<I18N::LangTags::List::is_decent( I<langtag> )> that returns true iff 
     149the language tag is syntactically valid and is for general use (like 
     150"fr" or "fr-ca", below).  That is, it returns false for tags that are 
     151syntactically invalid and for tags, like "aus", that are listed in 
     152brackets below.  This function is not exported. 
    105153 
    106154The map of tags-to-names that it uses is accessable as 
     
    196244=item {ada} : Adangme 
    197245 
     246=item {ady} : Adyghe 
     247 
     248eq Adygei 
     249 
    198250=item {aa} : Afar 
    199251 
     
    206258=item [{afa} : Afro-Asiatic (Other)] 
    207259 
    208 =item {aka} : Akan 
     260=item {ak} : Akan 
     261 
     262(Formerly "aka".) 
    209263 
    210264=item {akk} : Akkadian 
     
    265319=item {hy} : Armenian 
    266320 
     321=item {an} : Aragonese 
     322 
    267323=item [{art} : Artificial (Other)] 
    268324 
     325=item {ast} : Asturian 
     326 
     327eq Bable. 
     328 
    269329=item {as} : Assamese 
    270330 
     
    277337=item [{map} : Austronesian (Other)] 
    278338 
    279 =item {ava} : Avaric 
     339=item {av} : Avaric 
     340 
     341(Formerly "ava".) 
    280342 
    281343=item {ae} : Avestan 
     
    291353eq Azeri 
    292354 
     355Notable forms: 
     356{az-Arab} Azerbaijani in Arabic script; 
     357{az-Cyrl} Azerbaijani in Cyrillic script; 
     358{az-Latn} Azerbaijani in Latin script. 
     359 
    293360=item {ban} : Balinese 
    294361 
     
    297364=item {bal} : Baluchi 
    298365 
    299 =item {bam} : Bambara 
     366=item {bm} : Bambara 
     367 
     368(Formerly "bam".) 
    300369 
    301370=item [{bai} : Bamileke languages] 
     
    404473 
    405474Many forms are mutually un-intelligible in spoken media. 
    406 Notable subforms: 
     475Notable forms: 
     476{zh-Hans} Chinese, in simplified script; 
     477{zh-Hant} Chinese, in traditional script; 
     478{zh-tw} Taiwan Chinese; 
    407479{zh-cn} PRC Chinese; 
     480{zh-sg} Singapore Chinese; 
     481{zh-mo} Macau Chinese; 
    408482{zh-hk} Hong Kong Chinese; 
    409 {zh-mo} Macau Chinese; 
    410 {zh-sg} Singapore Chinese; 
    411 {zh-tw} Taiwan Chinese; 
    412483{zh-guoyu} Mandarin [Putonghua/Guoyu]; 
    413 {zh-hakka} Hakka [formerly i-hakka]; 
     484{zh-hakka} Hakka [formerly "i-hakka"]; 
    414485{zh-min} Hokkien; 
    415486{zh-min-nan} Southern Hokkien; 
     
    448519eq Corse. 
    449520 
    450 =item {cre} : Cree 
    451  
    452 NOT Creek! 
     521=item {cr} : Cree 
     522 
     523NOT Creek!  (Formerly "cre".) 
    453524 
    454525=item {mus} : Creek 
     
    477548 
    478549=item {da} : Danish 
     550 
     551=item {dar} : Dargwa 
    479552 
    480553=item {day} : Dayak 
     
    492565=item {din} : Dinka 
    493566 
    494 =item {div} : Divehi 
     567=item {dv} : Divehi 
     568 
     569eq Maldivian.  (Formerly "div".) 
    495570 
    496571=item {doi} : Dogri 
     
    556631eq Anglo-Saxon.  (Historical) 
    557632 
     633=item {i-enochian} : Enochian (Artificial) 
     634 
     635=item {myv} : Erzya 
     636 
    558637=item {eo} : Esperanto 
    559638 
     
    562641=item {et} : Estonian 
    563642 
    564 =item {ewe} : Ewe 
     643=item {ee} : Ewe 
     644 
     645(Formerly "ewe".) 
    565646 
    566647=item {ewo} : Ewondo 
     
    604685=item {fur} : Friulian 
    605686 
    606 =item {ful} : Fulah 
     687=item {ff} : Fulah 
     688 
     689(Formerly "ful".) 
    607690 
    608691=item {gaa} : Ga 
     
    616699eq Galician 
    617700 
    618 =item {lug} : Ganda 
     701=item {lg} : Ganda 
     702 
     703(Formerly "lug".) 
    619704 
    620705=item {gay} : Gayo 
     
    680765=item {hai} : Haida 
    681766 
     767=item {ht} : Haitian 
     768 
     769eq Haitian Creole 
     770 
    682771=item {ha} : Hausa 
    683772 
     
    717806=item {is} : Icelandic 
    718807 
    719 =item {ibo} : Igbo 
     808=item {io} : Ido 
     809 
     810(Artificial) 
     811 
     812=item {ig} : Igbo 
     813 
     814(Formerly "ibo".) 
    720815 
    721816=item {ijo} : Ijo 
     
    733828=for etc 
    734829{in} Indonesian (old tag) 
     830 
     831=item {inh} : Ingush 
    735832 
    736833=item {ia} : Interlingua (International Auxiliary Language Association) 
     
    774871(NOT "jp"!) 
    775872 
    776 =item {jw} : Javanese 
     873=item {jv} : Javanese 
     874 
     875(Formerly "jw" because of a typo.) 
    777876 
    778877=item {jrb} : Judeo-Arabic 
     
    780879=item {jpr} : Judeo-Persian 
    781880 
     881=item {kbd} : Kabardian 
     882 
    782883=item {kab} : Kabyle 
    783884 
     
    788889eq Greenlandic "Eskimo" 
    789890 
     891=item {xal} : Kalmyk 
     892 
    790893=item {kam} : Kamba 
    791894 
     
    794897eq Kanarese.  NOT Canadian! 
    795898 
    796 =item {kau} : Kanuri 
     899=item {kr} : Kanuri 
     900 
     901(Formerly "kau".) 
     902 
     903=item {krc} : Karachay-Balkar 
    797904 
    798905=item {kaa} : Kara-Kalpak 
     
    802909=item {ks} : Kashmiri 
    803910 
     911=item {csb} : Kashubian 
     912 
     913eq Kashub 
     914 
    804915=item {kaw} : Kawi 
    805916 
     
    830941=item {kv} : Komi 
    831942 
    832 =item {kon} : Kongo 
     943=item {kg} : Kongo 
     944 
     945(Formerly "kon".) 
    833946 
    834947=item {kok} : Konkani 
     
    878991=item {lb} : Letzeburgesch 
    879992 
    880 eq Luxemburgian, eq Luxemburger.  (Formerly i-lux.) 
     993eq Luxemburgian, eq Luxemburger.  (Formerly "i-lux".) 
    881994 
    882995=for etc 
     
    885998=item {lez} : Lezghian 
    886999 
     1000=item {li} : Limburgish 
     1001 
     1002eq Limburger, eq Limburgan.  NOT Letzeburgesch! 
     1003 
    8871004=item {ln} : Lingala 
    8881005 
     
    8931010eq Low Saxon.  eq Low German.  eq Low Saxon. 
    8941011 
     1012=item {art-lojban} : Lojban (Artificial) 
     1013 
    8951014=item {loz} : Lozi 
    8961015 
    897 =item {lub} : Luba-Katanga 
     1016=item {lu} : Luba-Katanga 
     1017 
     1018(Formerly "lub".) 
    8981019 
    8991020=item {lua} : Luba-Lulua 
     
    9861107=item {moh} : Mohawk 
    9871108 
     1109=item {mdf} : Moksha 
     1110 
    9881111=item {mo} : Moldavian 
    9891112 
     
    10081131=item {nah} : Nahuatl 
    10091132 
     1133=item {nap} : Neapolitan 
     1134 
    10101135=item {na} : Nauru 
    10111136 
    10121137=item {nv} : Navajo 
    10131138 
    1014 eq Navaho.  (Formerly i-navajo.) 
     1139eq Navaho.  (Formerly "i-navajo".) 
    10151140 
    10161141=for etc 
     
    10391164=item {niu} : Niuean 
    10401165 
     1166=item {nog} : Nogai 
     1167 
    10411168=item {non} : Old Norse 
    10421169 
     
    10471174Do not use this. 
    10481175 
    1049 =item {se} : Northern Sami 
    1050  
    1051 eq Lappish.  eq Lapp.  eq (Northern) Saami. 
    1052  
    10531176=item {no} : Norwegian 
    10541177 
     
    10571180=item {nb} : Norwegian Bokmal 
    10581181 
    1059 eq BokmE<aring>l, (A form of Norwegian.)  (Formerly no-bok.) 
     1182eq BokmE<aring>l, (A form of Norwegian.)  (Formerly "no-bok".) 
    10601183 
    10611184=for etc 
     
    10641187=item {nn} : Norwegian Nynorsk 
    10651188 
    1066 (A form of Norwegian.)  (Formerly no-nyn.) 
     1189(A form of Norwegian.)  (Formerly "no-nyn".) 
    10671190 
    10681191=for etc 
     
    10831206eq ProvenE<ccedil>al, eq Provencal 
    10841207 
    1085 =item {oji} : Ojibwa 
    1086  
    1087 eq Ojibwe. 
     1208=item {oj} : Ojibwa 
     1209 
     1210eq Ojibwe.  (Formerly "oji".) 
    10881211 
    10891212=item {or} : Oriya 
     
    12031326NOT Aramaic! 
    12041327 
     1328=item {se} : Northern Sami 
     1329 
     1330eq Lappish.  eq Lapp.  eq (Northern) Saami. 
     1331 
     1332=item {sma} : Southern Sami 
     1333 
     1334=item {smn} : Inari Sami 
     1335 
     1336=item {smj} : Lule Sami 
     1337 
     1338=item {sms} : Skolt Sami 
     1339 
    12051340=item [{smi} : Sami languages (Other)] 
    12061341 
     
    12341369 
    12351370eq Serb.  NOT Sorbian. 
     1371 
     1372Notable forms: 
     1373{sr-Cyrl} : Serbian in Cyrillic script; 
     1374{sr-Latn} : Serbian in Latin script. 
    12361375 
    12371376=item {srr} : Serer 
     
    12501389{sgn-ni} Nicaraguan Sign Language (ISN); 
    12511390{sgn-us} American Sign Language (ASL). 
     1391 
     1392(And so on with other country codes as the subtag.) 
    12521393 
    12531394=item {bla} : Siksika 
     
    14231564=item {tum} : Tumbuka 
    14241565 
     1566=item [{tup} : Tupi languages] 
     1567 
    14251568=item {tr} : Turkish 
    14261569 
     
    14311574(Typically in Arabic script)  (Historical) 
    14321575 
     1576=item {crh} : Crimean Turkish 
     1577 
     1578eq Crimean Tatar 
     1579 
    14331580=item {tk} : Turkmen 
    14341581 
     
    14431590=item {tw} : Twi 
    14441591 
     1592=item {udm} : Udmurt 
     1593 
    14451594=item {uga} : Ugaritic 
    14461595 
     
    14631612eq E<Ouml>zbek 
    14641613 
     1614Notable forms: 
     1615{uz-Cyrl} Uzbek in Cyrillic script; 
     1616{uz-Latn} Uzbek in Latin script. 
     1617 
    14651618=item {vai} : Vai 
    14661619 
    1467 =item {ven} : Venda 
    1468  
    1469 NOT Wendish!  NOT Wend!  NOT Avestan! 
     1620=item {ve} : Venda 
     1621 
     1622NOT Wendish!  NOT Wend!  NOT Avestan!  (Formerly "ven".) 
    14701623 
    14711624=item {vi} : Vietnamese 
     
    14821635 
    14831636=item [{wak} : Wakashan languages] 
     1637 
     1638=item {wa} : Walloon 
    14841639 
    14851640=item {wal} : Walamo 
     
    15181673eq Yap 
    15191674 
     1675=item {ii} : Sichuan Yi 
     1676 
    15201677=item {yi} : Yiddish 
    15211678 
    1522 Formerly "ji".  Sometimes in Roman script, sometimes in Hebrew script. 
    1523  
    1524 =for etc 
    1525 {ji} Yiddish (old tag) 
     1679Formerly "ji".  Usually in Hebrew script. 
     1680 
     1681Notable forms: 
     1682{yi-latn} Yiddish in Latin script 
    15261683 
    15271684=item {yo} : Yoruba 
     
    15591716=head1 COPYRIGHT AND DISCLAIMER 
    15601717 
    1561 Copyright (c) 2001,2002 Sean M. Burke. All rights reserved. 
     1718Copyright (c) 2001+ Sean M. Burke. All rights reserved. 
    15621719 
    15631720You can redistribute and/or 
  • branches/release-40/extlib/Locale/Maketext.pm

    r1098 r2594  
    1  
    2 # Time-stamp: "2001-06-21 23:09:33 MDT" 
    3  
    4 require 5; 
    51package Locale::Maketext; 
    62use strict; 
    73use vars qw( @ISA $VERSION $MATCH_SUPERS $USING_LANGUAGE_TAGS 
    8              $USE_LITERALS); 
     4$USE_LITERALS $MATCH_SUPERS_TIGHTLY); 
    95use Carp (); 
    10 use I18N::LangTags 0.21 (); 
     6use I18N::LangTags 0.30 (); 
    117 
    128#-------------------------------------------------------------------------- 
    139 
    1410BEGIN { unless(defined &DEBUG) { *DEBUG = sub () {0} } } 
    15  # define the constant 'DEBUG' at compile-time 
    16  
    17 $VERSION = "1.03"
     11# define the constant 'DEBUG' at compile-time 
     12 
     13$VERSION = '1.13'
    1814@ISA = (); 
    1915 
    2016$MATCH_SUPERS = 1; 
    21 $USING_LANGUAGE_TAGS = 1; 
    22  # Turning this off is somewhat of a security risk in that little or no 
    23  # checking will be done on the legality of tokens passed to the 
    24  # eval("use $module_name") in _try_use.  If you turn this off, you have 
    25  # to do your own taint checking. 
     17$MATCH_SUPERS_TIGHTLY = 1; 
     18$USING_LANGUAGE_TAGS  = 1; 
     19# Turning this off is somewhat of a security risk in that little or no 
     20# checking will be done on the legality of tokens passed to the 
     21# eval("use $module_name") in _try_use.  If you turn this off, you have 
     22# to do your own taint checking. 
    2623 
    2724$USE_LITERALS = 1 unless defined $USE_LITERALS; 
    28  # a hint for compiling bracket-notation things. 
     25# a hint for compiling bracket-notation things. 
    2926 
    3027my %isa_scan = (); 
     
    3330 
    3431sub quant { 
    35   my($handle, $num, @forms) = @_; 
    36  
    37   return $num if @forms == 0; # what should this mean? 
    38   return $forms[2] if @forms > 2 and $num == 0; # special zeroth case 
    39  
    40   # Normal case: 
    41   # Note that the formatting of $num is preserved. 
    42   return( $handle->numf($num) . ' ' . $handle->numerate($num, @forms) ); 
    43    # Most human languages put the number phrase before the qualified phrase. 
     32    my($handle, $num, @forms) = @_; 
     33 
     34    return $num if @forms == 0; # what should this mean? 
     35    return $forms[2] if @forms > 2 and $num == 0; # special zeroth case 
     36 
     37    # Normal case: 
     38    # Note that the formatting of $num is preserved. 
     39    return( $handle->numf($num) . ' ' . $handle->numerate($num, @forms) ); 
     40    # Most human languages put the number phrase before the qualified phrase. 
    4441} 
    4542 
    4643 
    4744sub numerate { 
    48  # return this lexical item in a form appropriate to this number 
    49   my($handle, $num, @forms) = @_; 
    50   my $s = ($num == 1); 
    51  
    52   return '' unless @forms; 
    53   if(@forms == 1) { # only the headword form specified 
    54     return $s ? $forms[0] : ($forms[0] . 's'); # very cheap hack. 
    55   } else { # sing and plural were specified 
    56     return $s ? $forms[0] : $forms[1]; 
    57   } 
     45    # return this lexical item in a form appropriate to this number 
     46    my($handle, $num, @forms) = @_; 
     47    my $s = ($num == 1); 
     48 
     49    return '' unless @forms; 
     50    if(@forms == 1) { # only the headword form specified 
     51        return $s ? $forms[0] : ($forms[0] . 's'); # very cheap hack. 
     52    } 
     53    else { # sing and plural were specified 
     54        return $s ? $forms[0] : $forms[1]; 
     55    } 
    5856} 
    5957 
     
    6159 
    6260sub numf { 
    63   my($handle, $num) = @_[0,1]; 
    64   if($num < 10_000_000_000 and $num > -10_000_000_000 and $num == int($num)) { 
    65     $num += 0;  # Just use normal integer stringification. 
    66          # Specifically, don't let %G turn ten million into 1E+007 
    67   } else { 
    68     $num = CORE::sprintf("%G", $num); 
    69      # "CORE::" is there to avoid confusion with the above sub sprintf. 
    70   } 
    71   while( $num =~ s/^([-+]?\d+)(\d{3})/$1,$2/s ) {1}  # right from perlfaq5 
    72    # The initial \d+ gobbles as many digits as it can, and then we 
    73    #  backtrack so it un-eats the rightmost three, and then we 
    74    #  insert the comma there. 
    75  
    76   $num =~ tr<.,><,.> if ref($handle) and $handle->{'numf_comma'}; 
    77    # This is just a lame hack instead of using Number::Format 
    78   return $num; 
     61    my($handle, $num) = @_[0,1]; 
     62    if($num < 10_000_000_000 and $num > -10_000_000_000 and $num == int($num)) { 
     63        $num += 0;  # Just use normal integer stringification. 
     64        # Specifically, don't let %G turn ten million into 1E+007 
     65    } 
     66    else { 
     67        $num = CORE::sprintf('%G', $num); 
     68        # "CORE::" is there to avoid confusion with the above sub sprintf. 
     69    } 
     70    while( $num =~ s/^([-+]?\d+)(\d{3})/$1,$2/s ) {1}  # right from perlfaq5 
     71    # The initial \d+ gobbles as many digits as it can, and then we 
     72    #  backtrack so it un-eats the rightmost three, and then we 
     73    #  insert the comma there. 
     74 
     75    $num =~ tr<.,><,.> if ref($handle) and $handle->{'numf_comma'}; 
     76    # This is just a lame hack instead of using Number::Format 
     77    return $num; 
    7978} 
    8079 
    8180sub sprintf { 
    82   no integer; 
    83   my($handle, $format, @params) = @_; 
    84   return CORE::sprintf($format, @params); 
     81    no integer; 
     82    my($handle, $format, @params) = @_; 
     83    return CORE::sprintf($format, @params); 
    8584    # "CORE::" is there to avoid confusion with myself! 
    8685} 
     
    9190 
    9291sub language_tag { 
    93   my $it = ref($_[0]) || $_[0]; 
    94   return undef unless $it =~ m/([^':]+)(?:::)?$/s; 
    95   $it = lc($1); 
    96   $it =~ tr<_><->; 
    97   return $it; 
     92    my $it = ref($_[0]) || $_[0]; 
     93    return undef unless $it =~ m/([^':]+)(?:::)?$/s; 
     94    $it = lc($1); 
     95    $it =~ tr<_><->; 
     96    return $it; 
    9897} 
    9998 
    10099sub encoding { 
    101   my $it = $_[0]; 
    102   return( 
    103    (ref($it) && $it->{'encoding'}) 
    104    || "iso-8859-1"   # Latin-1 
    105   ); 
    106 }  
     100    my $it = $_[0]; 
     101    return( 
     102        (ref($it) && $it->{'encoding'}) 
     103        || 'iso-8859-1'   # Latin-1 
     104    ); 
     105} 
    107106 
    108107#-------------------------------------------------------------------------- 
     
    115114 
    116115sub fail_with { # an actual attribute method! 
    117   my($handle, @params) = @_; 
    118   return unless ref($handle); 
    119   $handle->{'fail'} = $params[0] if @params; 
    120   return $handle->{'fail'}; 
     116    my($handle, @params) = @_; 
     117    return unless ref($handle); 
     118    $handle->{'fail'} = $params[0] if @params; 
     119    return $handle->{'fail'}; 
    121120} 
    122121 
     
    124123 
    125124sub failure_handler_auto { 
    126   # Meant to be used like: 
    127   #  $handle->fail_with('failure_handler_auto') 
    128  
    129   my($handle, $phrase, @params) = @_; 
    130   $handle->{'failure_lex'} ||= {}; 
    131   my $lex = $handle->{'failure_lex'}; 
    132  
    133   my $value; 
    134   $lex->{$phrase} ||= ($value = $handle->_compile($phrase)); 
    135  
    136   # Dumbly copied from sub maketext: 
    137   { 
    138     local $SIG{'__DIE__'}; 
    139     eval { $value = &$value($handle, @_) }; 
    140   } 
    141   # If we make it here, there was an exception thrown in the 
    142   #  call to $value, and so scream: 
    143   if($@) { 
    144     my $err = $@; 
    145     # pretty up the error message 
    146     $err =~ s<\s+at\s+\(eval\s+\d+\)\s+line\s+(\d+)\.?\n?> 
    147              <\n in bracket code [compiled line $1],>s; 
    148     #$err =~ s/\n?$/\n/s; 
    149     Carp::croak "Error in maketexting \"$phrase\":\n$err as used"; 
    150     # Rather unexpected, but suppose that the sub tried calling 
    151     # a method that didn't exist. 
    152   } else { 
    153     return $value; 
    154   } 
     125    # Meant to be used like: 
     126    #  $handle->fail_with('failure_handler_auto') 
     127 
     128    my $handle = shift; 
     129    my $phrase = shift; 
     130 
     131    $handle->{'failure_lex'} ||= {}; 
     132    my $lex = $handle->{'failure_lex'}; 
     133 
     134    my $value; 
     135    $lex->{$phrase} ||= ($value = $handle->_compile($phrase)); 
     136 
     137    # Dumbly copied from sub maketext: 
     138    return ${$value} if ref($value) eq 'SCALAR'; 
     139    return $value    if ref($value) ne 'CODE'; 
     140    { 
     141        local $SIG{'__DIE__'}; 
     142        eval { $value = &$value($handle, @_) }; 
     143    } 
     144    # If we make it here, there was an exception thrown in the 
     145    #  call to $value, and so scream: 
     146    if($@) { 
     147        my $err = $@; 
     148        # pretty up the error message 
     149        $err =~ s{\s+at\s+\(eval\s+\d+\)\s+line\s+(\d+)\.?\n?} 
     150                 {\n in bracket code [compiled line $1],}s; 
     151        #$err =~ s/\n?$/\n/s; 
     152        Carp::croak "Error in maketexting \"$phrase\":\n$err as used"; 
     153        # Rather unexpected, but suppose that the sub tried calling 
     154        # a method that didn't exist. 
     155    } 
     156    else { 
     157        return $value; 
     158    } 
    155159} 
    156160 
     
    158162 
    159163sub new { 
    160   # Nothing fancy! 
    161   my $class = ref($_[0]) || $_[0]; 
    162   my $handle = bless {}, $class; 
    163   $handle->init; 
    164   return $handle; 
     164    # Nothing fancy! 
     165    my $class = ref($_[0]) || $_[0]; 
     166    my $handle = bless {}, $class; 
     167    $handle->init; 
     168    return $handle; 
    165169} 
    166170 
     
    170174 
    171175sub maketext { 
    172   # Remember, this can fail.  Failure is controllable many ways. 
    173   Carp::croak "maketext requires at least one parameter" unless @_ > 1; 
    174  
    175   my($handle, $phrase) = splice(@_,0,2); 
    176  
    177   # Look up the value: 
    178  
    179   my $value; 
    180   foreach my $h_r ( 
    181     @{  $isa_scan{ref($handle) || $handle} || $handle->_lex_refs  } 
    182   ) { 
    183     print "* Looking up \"$phrase\" in $h_r\n" if DEBUG; 
    184     if(exists $h_r->{$phrase}) { 
    185       print "  Found \"$phrase\" in $h_r\n" if DEBUG; 
    186       unless(ref($value = $h_r->{$phrase})) { 
    187         # Nonref means it's not yet compiled.  Compile and replace. 
    188         $value = $h_r->{$phrase} = $handle->_compile($value); 
    189       } 
    190       last; 
    191     } elsif($phrase !~ m/^_/s and $h_r->{'_AUTO'}) { 
    192       # it's an auto lex, and this is an autoable key! 
    193       print "  Automaking \"$phrase\" into $h_r\n" if DEBUG; 
    194        
    195       $value = $h_r->{$phrase} = $handle->_compile($phrase); 
    196       last; 
    197     } 
    198     print "  Not found in $h_r, nor automakable\n" if DEBUG > 1; 
    199     # else keep looking 
    200   } 
    201  
    202   unless(defined($value)) { 
    203     print "! Lookup of \"$phrase\" in/under ", ref($handle) || $handle, 
    204       " fails.\n" if DEBUG; 
    205     if(ref($handle) and $handle->{'fail'}) { 
    206       print "WARNING0: maketext fails looking for <$phrase>\n" if DEBUG; 
    207       my $fail; 
    208       if(ref($fail = $handle->{'fail'}) eq 'CODE') { # it's a sub reference 
    209         return &{$fail}($handle, $phrase, @_); 
    210          # If it ever returns, it should return a good value. 
    211       } else { # It's a method name 
    212         return $handle->$fail($phrase, @_); 
    213          # If it ever returns, it should return a good value. 
    214       } 
    215     } else { 
    216       # All we know how to do is this; 
    217       Carp::croak("maketext doesn't know how to say:\n$phrase\nas needed"); 
    218     } 
    219   } 
    220  
    221   return $$value if ref($value) eq 'SCALAR'; 
    222   return $value unless ref($value) eq 'CODE'; 
    223    
    224   { 
    225     local $SIG{'__DIE__'}; 
    226     eval { $value = &$value($handle, @_) }; 
    227   } 
    228   # If we make it here, there was an exception thrown in the 
    229   #  call to $value, and so scream: 
    230   if($@) { 
    231     my $err = $@; 
    232     # pretty up the error message 
    233     $err =~ s<\s+at\s+\(eval\s+\d+\)\s+line\s+(\d+)\.?\n?> 
    234              <\n in bracket code [compiled line $1],>s; 
    235     #$err =~ s/\n?$/\n/s; 
    236     Carp::croak "Error in maketexting \"$phrase\":\n$err as used"; 
    237     # Rather unexpected, but suppose that the sub tried calling 
    238     # a method that didn't exist. 
    239   } else { 
    240     return $value; 
    241   } 
     176    # Remember, this can fail.  Failure is controllable many ways. 
     177    Carp::croak 'maketext requires at least one parameter' unless @_ > 1; 
     178 
     179    my($handle, $phrase) = splice(@_,0,2); 
     180    Carp::confess('No handle/phrase') unless (defined($handle) && defined($phrase)); 
     181 
     182 
     183    # Don't interefere with $@ in case that's being interpolated into the msg. 
     184    local $@; 
     185 
     186    # Look up the value: 
     187 
     188    my $value; 
     189    foreach my $h_r ( 
     190        @{  $isa_scan{ref($handle) || $handle} || $handle->_lex_refs  } 
     191    ) { 
     192        DEBUG and warn "* Looking up \"$phrase\" in $h_r\n"; 
     193        if(exists $h_r->{$phrase}) { 
     194            DEBUG and warn "  Found \"$phrase\" in $h_r\n"; 
     195            unless(ref($value = $h_r->{$phrase})) { 
     196                # Nonref means it's not yet compiled.  Compile and replace. 
     197                $value = $h_r->{$phrase} = $handle->_compile($value); 
     198            } 
     199            last; 
     200        } 
     201        elsif($phrase !~ m/^_/s and $h_r->{'_AUTO'}) { 
     202            # it's an auto lex, and this is an autoable key! 
     203            DEBUG and warn "  Automaking \"$phrase\" into $h_r\n"; 
     204 
     205            $value = $h_r->{$phrase} = $handle->_compile($phrase); 
     206            last; 
     207        } 
     208        DEBUG>1 and print "  Not found in $h_r, nor automakable\n"; 
     209        # else keep looking 
     210    } 
     211 
     212    unless(defined($value)) { 
     213        DEBUG and warn "! Lookup of \"$phrase\" in/under ", ref($handle) || $handle, " fails.\n"; 
     214        if(ref($handle) and $handle->{'fail'}) { 
     215            DEBUG and warn "WARNING0: maketext fails looking for <$phrase>\n"; 
     216            my $fail; 
     217            if(ref($fail = $handle->{'fail'}) eq 'CODE') { # it's a sub reference 
     218                return &{$fail}($handle, $phrase, @_); 
     219                # If it ever returns, it should return a good value. 
     220            } 
     221            else { # It's a method name 
     222                return $handle->$fail($phrase, @_); 
     223                # If it ever returns, it should return a good value. 
     224            } 
     225        } 
     226        else { 
     227            # All we know how to do is this; 
     228            Carp::croak("maketext doesn't know how to say:\n$phrase\nas needed"); 
     229        } 
     230    } 
     231 
     232    return $$value if ref($value) eq 'SCALAR'; 
     233    return $value unless ref($value) eq 'CODE'; 
     234 
     235    { 
     236        local $SIG{'__DIE__'}; 
     237        eval { $value = &$value($handle, @_) }; 
     238    } 
     239    # If we make it here, there was an exception thrown in the 
     240    #  call to $value, and so scream: 
     241    if ($@) { 
     242        my $err = $@; 
     243        # pretty up the error message 
     244        $err =~ s{\s+at\s+\(eval\s+\d+\)\s+line\s+(\d+)\.?\n?} 
     245                 {\n in bracket code [compiled line $1],}s; 
     246        #$err =~ s/\n?$/\n/s; 
     247        Carp::croak "Error in maketexting \"$phrase\":\n$err as used"; 
     248        # Rather unexpected, but suppose that the sub tried calling 
     249        # a method that didn't exist. 
     250    } 
     251    else { 
     252        return $value; 
     253    } 
    242254} 
    243255 
     
    245257 
    246258sub get_handle {  # This is a constructor and, yes, it CAN FAIL. 
    247   # Its class argument has to be the base class for the current 
    248   # application's l10n files. 
    249   my($base_class, @languages) = @_; 
    250   $base_class = ref($base_class) || $base_class; 
    251    # Complain if they use __PACKAGE__ as a project base class? 
    252  
    253   unless(@languages) {  # Calling with no args is magical!  wooo, magic! 
    254     if(length( $ENV{'REQUEST_METHOD'} || '' )) { # I'm a CGI 
    255       my $in = $ENV{'HTTP_ACCEPT_LANGUAGE'} || ''; 
    256         # supposedly that works under mod_perl, too. 
    257       $in =~ s<\([\)]*\)><>g; # Kill parens'd things -- just a hack. 
    258       @languages = &I18N::LangTags::extract_language_tags($in) if length $in; 
    259         # ...which untaints, incidentally. 
    260        
    261     } else { # Not running as a CGI: try to puzzle out from the environment 
    262       if(length( $ENV{'LANG'} || '' )) { 
    263         push @languages, split m/[,:]/, $ENV{'LANG'}; 
    264          # LANG can be only /one/ locale as far as I know, but what the hey. 
    265       } 
    266       if(length( $ENV{'LANGUAGE'} || '' )) { 
    267         push @languages, split m/[,:]/, $ENV{'LANGUAGE'}; 
    268       } 
    269       print "Noting ENV LANG ", join(',', @languages),"\n" if DEBUG; 
    270       # Those are really locale IDs, but they get xlated a few lines down. 
    271        
    272       if(&_try_use('Win32::Locale')) { 
    273         # If we have that module installed... 
    274         push @languages, Win32::Locale::get_language() 
    275          if defined &Win32::Locale::get_language; 
    276       } 
    277     } 
    278   } 
    279  
    280   #------------------------------------------------------------------------ 
    281   print "Lgs1: ", map("<$_>", @languages), "\n" if DEBUG; 
    282  
    283   if($USING_LANGUAGE_TAGS) { 
    284     @languages = map &I18N::LangTags::locale2language_tag($_), @languages; 
    285      # if it's a lg tag, fine, pass thru (untainted) 
    286      # if it's a locale ID, try converting to a lg tag (untainted), 
    287      # oth