⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 langtags.pm

📁 1. 记录每个帖子的访问人情况
💻 PM
📖 第 1 页 / 共 2 页
字号:
  $lang =~ s<\.[-_a-zA-Z0-9\.]*><>s;  # "en_US.ISO8859-1" -> en-US  return $lang if &is_language_tag($lang);  return;}###########################################################################=item * the function encode_language_tag($lang1)This function, if given a language tag, returns an encoding of it suchthat:* tags representing different languages never get the same encoding.* tags representing the same language always get the same encoding.* an encoding of a formally valid language tag always is a stringvalue that is defined, has length, and is true if considered as aboolean.Note that the encoding itself is B<not> a formally valid language tag.Note also that you cannot, currently, go from an encoding back to alanguage tag that it's an encoding of.Note also that you B<must> consider the encoded value as atomic; i.e.,you should not consider it as anything but an opaque, unanalysablestring value.  (The internals of the encoding method may change infuture versions, as the language tagging standard changes over time.)C<encode_language_tag> returns undef if given anything other than aformally valid language tag.The reason C<encode_language_tag> exists is because different languagetags may represent the same language; this is normally treatable withC<same_language_tag>, but consider this situation:You have a data file that expresses greetings in different languages.Its format is "[language tag]=[how to say 'Hello']", like:          en-US=Hiho          fr=Bonjour          i-mingo=Hau'And suppose you write a program that reads that file and then runs asa daemon, answering client requests that specify a language tag andthen expect the string that says how to greet in that language.  So aninteraction looks like:          greeting-client asks:    fr          greeting-server answers: BonjourSo far so good.  But suppose the way you're implementing this is:          my %greetings;          die unless open(IN, "<in.dat");          while(<IN>) {            chomp;            next unless /^([^=]+)=(.+)/s;            my($lang, $expr) = ($1, $2);            $greetings{$lang} = $expr;          }          close(IN);at which point %greetings has the contents:          "en-US"   => "Hiho"          "fr"      => "Bonjour"          "i-mingo" => "Hau'"And suppose then that you answer client requests for language $wantedby just looking up $greetings{$wanted}.If the client asks for "fr", that will look up successfully in%greetings, to the value "Bonjour".  And if the client asks for"i-mingo", that will look up successfully in %greetings, to the value"Hau'".But if the client asks for "i-Mingo" or "x-mingo", or "Fr", then thelookup in %greetings fails.  That's the Wrong Thing.You could instead do lookups on $wanted with:          use I18N::LangTags qw(same_language_tag);          my $repsonse = '';          foreach my $l2 (keys %greetings) {            if(same_language_tag($wanted, $l2)) {              $response = $greetings{$l2};              last;            }          }But that's rather inefficient.  A better way to do it is to start yourprogram with:          use I18N::LangTags qw(encode_language_tag);          my %greetings;          die unless open(IN, "<in.dat");          while(<IN>) {            chomp;            next unless /^([^=]+)=(.+)/s;            my($lang, $expr) = ($1, $2);            $greetings{                        encode_language_tag($lang)                      } = $expr;          }          close(IN);and then just answer client requests for language $wanted by justlooking up          $greetings{encode_language_tag($wanted)}And that does the Right Thing.=cutsub encode_language_tag {  # Only similarity_language_tag() is allowed to analyse encodings!  ## Changes in the language tagging standards may have to be reflected here.  my($tag) = $_[0] || return undef;  return undef unless &is_language_tag($tag);  # For the moment, these legacy variances are few enough that  #  we can just handle them here with regexps.  $tag =~ s/^iw\b/he/i; # Hebrew  $tag =~ s/^in\b/id/i; # Indonesian  $tag =~ s/^[ix]-lux\b/lb/i;  # Luxemburger  $tag =~ s/^[ix]-navajo\b/nv/i;  # Navajo  $tag =~ s/^ji\b/yi/i;  # Yiddish  #  # These go FROM the simplex to complex form, to get  #  similarity-comparison right.  And that's okay, since  #  similarity_language_tag is the only thing that  #  analyzes our output.  $tag =~ s/^[ix]-hakka\b/zh-hakka/i;  # Hakka  $tag =~ s/^nb\b/no-bok/i;  # BACKWARDS for Bokmal  $tag =~ s/^nn\b/no-nyn/i;  # BACKWARDS for Nynorsk  $tag =~ s/^[xiXI]-//s;   # Just lop off any leading "x/i-"  return "~" . uc($tag);}#--------------------------------------------------------------------------=item * the function alternate_language_tags($lang1)This function, if given a language tag, returns all language tags thatare alternate forms of this language tag.  (I.e., tags which refer tothe same language.)  This is meant to handle legacy tags caused bythe minor changes in language tag standards over the years; andthe x-/i- alternation is also dealt with.Note that this function does I<not> try to equate new (and never-used,and unusable)ISO639-2 three-letter tags to old (and still in use) ISO639-1two-letter equivalents -- like "ara" -> "ar" -- because"ara" has I<never> been in use as an Internet language tag,and RFC 3066 stipulates that it never should be, since a shortertag ("ar") exists.Examples:          alternate_language_tags('no-bok')       is ('nb')          alternate_language_tags('nb')           is ('no-bok')          alternate_language_tags('he')           is ('iw')          alternate_language_tags('iw')           is ('he')          alternate_language_tags('i-hakka')      is ('zh-hakka', 'x-hakka')          alternate_language_tags('zh-hakka')     is ('i-hakka', 'x-hakka')          alternate_language_tags('en')           is ()          alternate_language_tags('x-mingo-tom')  is ('i-mingo-tom')          alternate_language_tags('x-klikitat')   is ('i-klikitat')          alternate_language_tags('i-klikitat')   is ('x-klikitat')This function returns empty-list if given anything other than a formallyvalid language tag.=cutmy %alt = qw( i x   x i   I X   X I );sub alternate_language_tags {  my $tag = $_[0];  return() unless &is_language_tag($tag);  my @em; # push 'em real goood!  # For the moment, these legacy variances are few enough that  #  we can just handle them here with regexps.    if(     $tag =~ m/^[ix]-hakka\b(.*)/i) {push @em, "zh-hakka$1";  } elsif($tag =~ m/^zh-hakka\b(.*)/i) {  push @em, "x-hakka$1", "i-hakka$1";  } elsif($tag =~ m/^he\b(.*)/i) { push @em, "iw$1";  } elsif($tag =~ m/^iw\b(.*)/i) { push @em, "he$1";  } elsif($tag =~ m/^in\b(.*)/i) { push @em, "id$1";  } elsif($tag =~ m/^id\b(.*)/i) { push @em, "in$1";  } elsif($tag =~ m/^[ix]-lux\b(.*)/i) { push @em, "lb$1";  } elsif($tag =~ m/^lb\b(.*)/i) {       push @em, "i-lux$1", "x-lux$1";  } elsif($tag =~ m/^[ix]-navajo\b(.*)/i) { push @em, "nv$1";  } elsif($tag =~ m/^nv\b(.*)/i) {          push @em, "i-navajo$1", "x-navajo$1";  } elsif($tag =~ m/^yi\b(.*)/i) { push @em, "ji$1";  } elsif($tag =~ m/^ji\b(.*)/i) { push @em, "yi$1";  } elsif($tag =~ m/^nb\b(.*)/i) {     push @em, "no-bok$1";  } elsif($tag =~ m/^no-bok\b(.*)/i) { push @em, "nb$1";    } elsif($tag =~ m/^nn\b(.*)/i) {     push @em, "no-nyn$1";  } elsif($tag =~ m/^no-nyn\b(.*)/i) { push @em, "nn$1";  }  push @em, $alt{$1} . $2 if $tag =~ /^([XIxi])(-.+)/;  return @em;}###########################################################################{  # Init %Panic...    my @panic = (  # MUST all be lowercase!   # Only large ("national") languages make it in this list.   #  If you, as a user, are so bizarre that the /only/ language   #  you claim to accept is Galician, then no, we won't do you   #  the favor of providing Catalan as a panic-fallback for   #  you.  Because if I start trying to add "little languages" in   #  here, I'll just go crazy.   # Scandinavian lgs.  All based on opinion and hearsay.   'sv' => [qw(nb no da nn)],   'da' => [qw(nb no sv nn)], # I guess   [qw(no nn nb)], [qw(no nn nb sv da)],   'is' => [qw(da sv no nb nn)],   'fo' => [qw(da is no nb nn sv)], # I guess      # I think this is about the extent of tolerable intelligibility   #  among large modern Romance languages.   'pt' => [qw(es ca it fr)], # Portuguese, Spanish, Catalan, Italian, French   'ca' => [qw(es pt it fr)],   'es' => [qw(ca it fr pt)],   'it' => [qw(es fr ca pt)],   'fr' => [qw(es it ca pt)],      # Also assume that speakers of the main Indian languages prefer   #  to read/hear Hindi over English   [qw(     as bn gu kn ks kok ml mni mr ne or pa sa sd te ta ur   )] => 'hi',    # Assamese, Bengali, Gujarati, [Hindi,] Kannada (Kanarese), Kashmiri,    # Konkani, Malayalam, Meithei (Manipuri), Marathi, Nepali, Oriya,    # Punjabi, Sanskrit, Sindhi, Telugu, Tamil, and Urdu.   'hi' => [qw(bn pa as or)],   # I welcome finer data for the other Indian languages.   #  E.g., what should Oriya's list be, besides just Hindi?      # And the panic languages for English is, of course, nil!   # My guesses at Slavic intelligibility:   ([qw(ru be uk)]) x 2,  # Russian, Belarusian, Ukranian   'sr' => 'hr', 'hr' => 'sr', # Serb + Croat   'cs' => 'sk', 'sk' => 'cs', # Czech + Slovak   'ms' => 'id', 'id' => 'ms', # Malay + Indonesian   'et' => 'fi', 'fi' => 'et', # Estonian + Finnish   #?? 'lo' => 'th', 'th' => 'lo', # Lao + Thai  );  my($k,$v);  while(@panic) {    ($k,$v) = splice(@panic,0,2);    foreach my $k (ref($k) ? @$k : $k) {      foreach my $v (ref($v) ? @$v : $v) {        push @{$Panic{$k} ||= []}, $v unless $k eq $v;      }    }  }}=item * the function @langs = panic_languages(@accept_languages)This function takes a list of 0 or more languagetags that constitute a given user's Accept-Language list, andreturns a list of tags for I<other> (non-super)languages that are probably acceptable to the user, to beused I<if all else fails>.For example, if a user accepts only 'ca' (Catalan) and'es' (Spanish), and the documents/interfaces you haveavailable are just in German, Italian, and Chinese, thenthe user will most likely want the Italian one (and notthe Chinese or German one!), instead of gettingnothing.  So C<panic_languages('ca', 'es')> returnsa list containing 'it' (Italian).English ('en') is I<always> in the return list, butwhether it's at the very end or not dependson the input languages.  This function works by consultingan internal table that stipulates what commonlanguages are "close" to each other.A useful construct you might consider using is:  @fallbacks = super_languages(@accept_languages);  push @fallbacks, panic_languages(    @accept_languages, @fallbacks,  );=cutsub panic_languages {  # When in panic or in doubt, run in circles, scream, and shout!  my(@out, %seen);  foreach my $t (@_) {    next unless $t;    next if $seen{$t}++; # so we don't return it or hit it again    # push @out, super_languages($t); # nah, keep that separate    push @out, @{ $Panic{lc $t} || next };  }  return grep !$seen{$_}++,  @out, 'en';}###########################################################################1;__END__=back=head1 ABOUT LOWERCASINGI've considered making all the above functions that output languagetags return all those tags strictly in lowercase.  Having all yourlanguage tags in lowercase does make some things easier.  But youmight as well just lowercase as you like, or callC<encode_language_tag($lang1)> where appropriate.=head1 ABOUT UNICODE PLAINTEXT LANGUAGE TAGSIn some future version of I18N::LangTags, I plan to include supportfor RFC2482-style language tags -- which are basically just normallanguage tags with their ASCII characters shifted into Plane 14.=head1 SEE ALSO* L<I18N::LangTags::List|I18N::LangTags::List>* RFC 3066, C<ftp://ftp.isi.edu/in-notes/rfc3066.txt>, "Tags for theIdentification of Languages".  (Obsoletes RFC 1766)* RFC 2277, C<ftp://ftp.isi.edu/in-notes/rfc2277.txt>, "IETF Policy onCharacter Sets and Languages".* RFC 2231, C<ftp://ftp.isi.edu/in-notes/rfc2231.txt>, "MIME ParameterValue and Encoded Word Extensions: Character Sets, Languages, andContinuations".* RFC 2482, C<ftp://ftp.isi.edu/in-notes/rfc2482.txt>, "Language Tagging in Unicode Plain Text".* Locale::Codes, inC<http://www.perl.com/CPAN/modules/by-module/Locale/>* ISO 639, "Code for the representation of names of languages",C<http://www.indigo.ie/egt/standards/iso639/iso639-1-en.html>* ISO 639-2, "Codes for the representation of names of languages",including three-letter codes,C<http://lcweb.loc.gov/standards/iso639-2/bibcodes.html>* The IANA list of registered languages (hopefully up-to-date),C<ftp://ftp.isi.edu/in-notes/iana/assignments/languages/>=head1 COPYRIGHTCopyright (c) 1998-2001 Sean M. Burke. All rights reserved.This library is free software; you can redistribute it and/ormodify it under the same terms as Perl itself.The programs and documentation in this dist are distributed inthe hope that they will be useful, but without any warranty; withouteven the implied warranty of merchantability or fitness for aparticular purpose.=head1 AUTHORSean M. Burke C<sburke@cpan.org>=cut

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -