📄 maketext.pod
字号:
# Time-stamp: "2001-06-21 23:12:39 MDT"=head1 NAMELocale::Maketext -- framework for localization=head1 SYNOPSIS package MyProgram; use strict; use MyProgram::L10N; # ...which inherits from Locale::Maketext my $lh = MyProgram::L10N->get_handle() || die "What language?"; ... # And then any messages your program emits, like: warn $lh->maketext( "Can't open file [_1]: [_2]\n", $f, $! ); ...=head1 DESCRIPTIONIt is a common feature of applications (whether run directly,or via the Web) for them to be "localized" -- i.e., for themto a present an English interface to an English-speaker, a Germaninterface to a German-speaker, and so on for all languages it'sprogrammed with. Locale::Maketextis a framework for software localization; it provides you with thetools for organizing and accessing the bits of text and text-processingcode that you need for producing localized applications.In order to make sense of Maketext and how all itscomponents fit together, you should probablygo read L<Locale::Maketext::TPJ13|Locale::Maketext::TPJ13>, andI<then> read the following documentation.You may also want to read over the source for C<File::Findgrep>and its constituent modules -- they are a complete (if small)example application that uses Maketext.=head1 QUICK OVERVIEWThe basic design of Locale::Maketext is object-oriented, andLocale::Maketext is an abstract base class, from which youderive a "project class".The project class (with a name like "TkBocciBall::Localize",which you then use in your module) is in turn the base classfor all the "language classes" for your project(with names "TkBocciBall::Localize::it", "TkBocciBall::Localize::en","TkBocciBall::Localize::fr", etc.).A language class isa class containing a lexicon of phrases as class data,and possibly also some methods that are of use in interpretingphrases in the lexicon, or otherwise dealing with text in thatlanguage.An object belonging to a language class is called a "languagehandle"; it's typically a flyweight object.The normal course of action is to call: use TkBocciBall::Localize; # the localization project class $lh = TkBocciBall::Localize->get_handle(); # Depending on the user's locale, etc., this will # make a language handle from among the classes available, # and any defaults that you declare. die "Couldn't make a language handle??" unless $lh;From then on, you use the C<maketext> function to accessentries in whatever lexicon(s) belong to the language handleyou got. So, this: print $lh->maketext("You won!"), "\n";...emits the right text for this language. If the objectin C<$lh> belongs to class "TkBocciBall::Localize::fr" and%TkBocciBall::Localize::fr::Lexicon contains C<("You won!"=E<gt> "Tu as gagnE<eacute>!")>, then the abovecode happily tells the user "Tu as gagnE<eacute>!".=head1 METHODSLocale::Maketext offers a variety of methods, which fallinto three categories:=over=item *Methods to do with constructing language handles.=item *C<maketext> and other methods to do with accessing %Lexicon datafor a given language handle.=item *Methods that you may find it handy to use, from routines ofyours that you put in %Lexicon entries.=backThese are covered in the following section.=head2 Construction MethodsThese are to do with constructing a language handle:=over=item *$lh = YourProjClass->get_handle( ...langtags... ) || die "lg-handle?";This tries loading classes based on the language-tags you give (likeC<("en-US", "sk", "kon", "es-MX", "ja", "i-klingon")>, and for the first classthat succeeds, returns YourProjClass::I<language>->new().It runs thru the entire given list of language-tags, and finds no classesfor those exact terms, it then tries "superordinate" language classes.So if no "en-US" class (i.e., YourProjClass::en_us)was found, nor classes for anything else in that list, we then tryits superordinate, "en" (i.e., YourProjClass::en), and so on thru the other language-tags in the given list: "es".(The other language-tags in our example list: happen to have no superordinates.)If none of those language-tags leads to loadable classes, we thentry classes derived from YourProjClass->fallback_languages() andthen if nothing comes of that, we use classes named byYourProjClass->fallback_language_classes(). Then in the (probablyquite unlikely) event that that fails, we just return undef.=item *$lh = YourProjClass->get_handleB<()> || die "lg-handle?";When C<get_handle> is called with an empty parameter list, magic happens:If C<get_handle> senses that it's running in program that wasinvoked as a CGI, then it tries to get language-tags out of theenvironment variable "HTTP_ACCEPT_LANGUAGE", and it pretends thatthose were the languages passed as parameters to C<get_handle>.Otherwise (i.e., if not a CGI), this tries various OS-specific waysto get the language-tags for the current locale/language, and thenpretends that those were the value(s) passed to C<cet_handle>.Currently this OS-specific stuff consists of looking in the environmentvariables "LANG" and "LANGUAGE"; and on MSWin machines (where thosevariables are typically unused), this also tries usingthe module Win32::Locale to get a language-tag for whatever language/localeis currently selected in the "Regional Settings" (or "International"?)Control Panel. I welcome furthersuggestions for making this do the Right Thing under other operatingsystems that support localization.If you're using localization in an application that keeps a configurationfile, you might consider something like this in your project class: sub get_handle_via_config { my $class = $_[0]; my $preferred_language = $Config_settings{'language'}; my $lh; if($preferred_language) { $lh = $class->get_handle($chosen_language) || die "No language handle for \"$chosen_language\" or the like"; } else { # Config file missing, maybe? $lh = $class->get_handle() || die "Can't get a language handle"; } return $lh; }=item *$lh = YourProjClass::langname->new();This constructs a language handle. You usually B<don't> call thisdirectly, but instead let C<get_handle> find a language class to C<use>and to then call ->new on.=item *$lh->init();This is called by ->new to initialize newly-constructed language handles.If you define an init method in your class, remember that it's usuallyconsidered a good idea to call $lh->SUPER::init in it (presumably at thebeginning), so that all classes get a chance to initialize a new objecthowever they see fit.=item *YourProjClass->fallback_languages()C<get_handle> appends the return value of this to the end ofwhatever list of languages you pass C<get_handle>. Unlessyou override this method, your project classwill inherit Locale::Maketext's C<fallback_languages>, whichcurrently returns C<('i-default', 'en', 'en-US')>.("i-default" is defined in RFC 2277).This method (by having it return the nameof a language-tag that has an existing language class)can be used for making sure thatC<get_handle> will always manage to construct a languagehandle (assuming your language classes are in an appropriate@INC directory). Or you can use the next method:=item *YourProjClass->fallback_language_classes()C<get_handle> appends the return value of this to the endof the list of classes it will try using. Unlessyou override this method, your project classwill inherit Locale::Maketext's C<fallback_language_classes>,which currently returns an empty list, C<()>.By setting this to some value (namely, the name of a loadablelanguage class), you can be sure thatC<get_handle> will always manage to construct a languagehandle.=back=head2 The "maketext" MethodThis is the most important method in Locale::Maketext:$text = $lh->maketext(I<key>, ...parameters for this phrase...);This looks in the %Lexicon of the language handle$lh and all its superclasses, lookingfor an entry whose key is the string I<key>. Assuming suchan entry is found, various things then happen, depending on thevalue found:If the value is a scalarref, the scalar is dereferenced and returned(and any parameters are ignored).If the value is a coderef, we return &$value($lh, ...parameters...).If the value is a string that I<doesn't> look like it's in Bracket Notation,we return it (after replacing it with a scalarref, in its %Lexicon).If the value I<does> look like it's in Bracket Notation, then we compileit into a sub, replace the string in the %Lexicon with the new coderef,and then we return &$new_sub($lh, ...parameters...).Bracket Notation is discussed in a later section. Notethat trying to compile a string into Bracket Notation can throwan exception if the string is not syntactically valid (say, by notbalancing brackets right.)Also, calling &$coderef($lh, ...parameters...) can throw any sort ofexception (if, say, code in that sub tries to divide by zero). Buta very common exception occurs when you have BracketNotation text that says to call a method "foo", but there is no suchmethod. (E.g., "You have [quaB<tn>,_1,ball]." will throw an exceptionon trying to call $lh->quaB<tn>($_[1],'ball') -- you presumably meant"quant".) C<maketext> catches these exceptions, but only to make theerror message more readable, at which point it rethrows the exception.An exception I<may> be thrown if I<key> is not found in anyof $lh's %Lexicon hashes. What happens if a key is not found,is discussed in a later section, "Controlling Lookup Failure".Note that you might find it useful in some cases to overridethe C<maketext> method with an "after method", if you want totranslate encodings, or even scripts: package YrProj::zh_cn; # Chinese with PRC-style glyphs use base ('YrProj::zh_tw'); # Taiwan-style sub maketext { my $self = shift(@_); my $value = $self->maketext(@_); return Chineeze::taiwan2mainland($value); }Or you may want to override it with something that trapsany exceptions, if that's critical to your program: sub maketext { my($lh, @stuff) = @_; my $out; eval { $out = $lh->SUPER::maketext(@stuff) }; return $out unless $@; ...otherwise deal with the exception... }Other than those two situations, I don't imagine thatit's useful to override the C<maketext> method. (Ifyou run into a situation where it is useful, I'd beinterested in hearing about it.)=over=item $lh->fail_with I<or> $lh->fail_with(I<PARAM>)=item $lh->failure_handler_autoThese two methods are discussed in the section "ControllingLookup Failure".=back=head2 Utility MethodsThese are methods that you may find it handy to use, generallyfrom %Lexicon routines of yours (whether expressed asBracket Notation or not).=over=item $language->quant($number, $singular)=item $language->quant($number, $singular, $plural)=item $language->quant($number, $singular, $plural, $negative)This is generally meant to be called from inside Bracket Notation(which is discussed later), as in "Your search matched [quant,_1,document]!"It's for I<quantifying> a noun (i.e., saying how much of it there is,while giving the currect form of it). The behavior of this method ishandy for English and a few other Western European languages, and youshould override it for languages where it's not suitable. You can feelfree to read the source, but the current implementation is basically
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -