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

📄 maketext.pod

📁 1. 记录每个帖子的访问人情况
💻 POD
📖 第 1 页 / 共 4 页
字号:
Bracket Notation is a like a miniature "template" system (in the senseof L<Text::Template|Text::Template>, not in the sense of C++ templates),where normal text is passed thru basically as is, but text is specialregions is specially interpreted.  In Bracket Notation, you use brackets("[...]" -- not "{...}"!) to note sections that are specially interpreted.For example, here all the areas that are taken literally are underlined witha "^", and all the in-bracket special regions are underlined with an X:  "Minimum ([_1]) is larger than maximum ([_2])!\n",   ^^^^^^^^^ XX ^^^^^^^^^^^^^^^^^^^^^^^^^^ XX ^^^^When that string is compiled from bracket notation into a real Perl sub,it's basically turned into:  sub {    my $lh = $_[0];    my @params = @_;    return join '',      "Minimum (",      ...some code here...      ") is larger than maximum (",      ...some code here...      ")!\n",  }  # to be called by $lh->maketext(KEY, params...)   In other words, text outside bracket groups is turned into stringliterals.  Text in brackets is rather more complex, and currently followsthese rules:=over=item *Bracket groups that are empty, or which consist only of whitespace,are ignored.  (Examples: "[]", "[    ]", or a [ and a ] with returnsand/or tabs and/or spaces between them.Otherwise, each group is taken to be a comma-separated group of items,and each item is interpreted as follows:=item *An item that is "_I<digits>" or "_-I<digits>" is interpreted as$_[I<value>].  I.e., "_1" is becomes with $_[1], and "_-3" is interpretedas $_[-3] (in which case @_ should have at least three elements in it).Note that $_[0] is the language handle, and is typically not nameddirectly.=item *An item "_*" is interpreted to mean "all of @_ except $_[0]".I.e., C<@_[1..$#_]>.  Note that this is an empty list in the caseof calls like $lh->maketext(I<key>) where there are noparameters (except $_[0], the language handle).=item *Otherwise, each item is interpreted as a string literal.=backThe group as a whole is interpreted as follows:=over=item *If the first item in a bracket group looks like a method name,then that group is interpreted like this:  $lh->that_method_name(    ...rest of items in this group...  ),=item *If the first item in a bracket group is "*", it's taken as shorthandfor the so commonly called "quant" method.  Similarly, if the firstitem in a bracket group is "#", it's taken to be shorthand for"numf".=item *If the first item in a bracket group is empty-string, or "_*"or "_I<digits>" or "_-I<digits>", then that group is interpretedas just the interpolation of all its items:  join('',    ...rest of items in this group...  ),Examples:  "[_1]" and "[,_1]", which are synonymous; and"[,ID-(,_4,-,_2,)]", which compiles asC<join "", "ID-(", $_[4], "-", $_[2], ")">.=item *Otherwise this bracket group is invalid.  For example, in the group"[!@#,whatever]", the first item C<"!@#"> is neither empty-string,"_I<number>", "_-I<number>", "_*", nor a valid method name; and soLocale::Maketext will throw an exception of you try compiling anexpression containing this bracket group.=backNote, incidentally, that items in each group are comma-separated,not C</\s*,\s*/>-separated.  That is, you might expect that thisbracket group:  "Hoohah [foo, _1 , bar ,baz]!"would compile to this:  sub {    my $lh = $_[0];    return join '',      "Hoohah ",      $lh->foo( $_[1], "bar", "baz"),      "!",  }But it actually compiles as this:  sub {    my $lh = $_[0];    return join '',      "Hoohah ",      $lh->foo(" _1 ", " bar ", "baz"),  #!!!      "!",  }In the notation discussed so far, the characters "[" and "]" are givenspecial meaning, for opening and closing bracket groups, and "," hasa special meaning inside bracket groups, where it separates items in thegroup.  This begs the question of how you'd express a literal "[" or"]" in a Bracket Notation string, and how you'd express a literalcomma inside a bracket group.  For this purpose I've adopted "~" (tilde)as an escape character:  "~[" means a literal '[' character anywherein Bracket Notation (i.e., regardless of whether you're in a bracketgroup or not), and ditto for "~]" meaning a literal ']', and "~," meaninga literal comma.  (Altho "," means a literal comma outside ofbracket groups -- it's only inside bracket groups that commas are special.)And on the off chance you need a literal tilde in a bracket expression,you get it with "~~".Currently, an unescaped "~" before a characterother than a bracket or a comma is taken to mean just a "~" and thatcharecter.  I.e., "~X" means the same as "~~X" -- i.e., one literal tilde,and then one literal "X".  However, by using "~X", you are assuming thatno future version of Maketext will use "~X" as a magic escape sequence.In practice this is not a great problem, since first off you can justwrite "~~X" and not worry about it; second off, I doubt I'll add lotsof new magic characters to bracket notation; and third off, youaren't likely to want literal "~" characters in your messages anyway,since it's not a character with wide use in natural language text.Brackets must be balanced -- every openbracket must haveone matching closebracket, and vice versa.  So these are all B<invalid>:  "I ate [quant,_1,rhubarb pie."  "I ate [quant,_1,rhubarb pie[."  "I ate quant,_1,rhubarb pie]."  "I ate quant,_1,rhubarb pie[."Currently, bracket groups do not nest.  That is, you B<cannot> say:  "Foo [bar,baz,[quux,quuux]]\n";If you need a notation that's that powerful, use normal Perl:  %Lexicon = (    ...    "some_key" => sub {      my $lh = $_[0];      join '',        "Foo ",        $lh->bar('baz', $lh->quux('quuux')),        "\n",    },    ...  );Or write the "bar" method so you don't need to pass it theoutput from calling quux.I do not anticipate that you will need (or particularly want)to nest bracket groups, but you are welcome to email me withconvincing (real-life) arguments to the contrary.=head1 AUTO LEXICONSIf maketext goes to look in an individual %Lexicon for an entryfor I<key> (where I<key> does not start with an underscore), andsees none, B<but does see> an entry of "_AUTO" => I<some_true_value>,then we actually define $Lexicon{I<key>} = I<key> right then and there,and then use that value as if it had been there allalong.  This happens before we even look in any superclass %Lexicons!(This is meant to be somewhat like the AUTOLOAD mechanism inPerl's function call system -- or, looked at another way,like the L<AutoLoader|AutoLoader> module.)I can picture all sorts of circumstances where you justdo not want lookup to be able to fail (since failingnormally means that maketext throws a C<die>, althosee the next section for greater control over that).  Buthere's one circumstance where _AUTO lexicons are meant tobe I<especially> useful:As you're writing an application, you decide as you go what messagesyou need to emit.  Normally you'd go to write this:  if(-e $filename) {    go_process_file($filename)  } else {    print "Couldn't find file \"$filename\"!\n";  }but since you anticipate localizing this, you write:  use ThisProject::I18N;  my $lh = ThisProject::I18N->get_handle();   # For the moment, assume that things are set up so   # that we load class ThisProject::I18N::en   # and that that's the class that $lh belongs to.  ...  if(-e $filename) {    go_process_file($filename)  } else {    print $lh->maketext(      "Couldn't find file \"[_1]\"!\n", $filename    );  }Now, right after you've just written the above lines, you'dnormally have to go open the file ThisProject/I18N/en.pm, and immediately add an entry:  "Couldn't find file \"[_1]\"!\n"  => "Couldn't find file \"[_1]\"!\n",But I consider that somewhat of a distraction from the workof getting the main code working -- to say nothing of the factthat I often have to play with the program a few times beforeI can decide exactly what wording I want in the messages (whichin this case would require me to go changing three lines of code:the call to maketext with that key, and then the two lines inThisProject/I18N/en.pm).However, if you set "_AUTO => 1" in the %Lexicon in,ThisProject/I18N/en.pm (assuming that English (en) isthe language that all your programmers will be using for thisproject's internal message keys), then you don't ever have togo adding lines like this  "Couldn't find file \"[_1]\"!\n"  => "Couldn't find file \"[_1]\"!\n",to ThisProject/I18N/en.pm, because if _AUTO is true there,then just looking for an entry with the key "Couldn't findfile \"[_1]\"!\n" in that lexicon will cause it to be added,with that value!Note that the reason that keys that start with "_"are immune to _AUTO isn't anything generally magical aboutthe underscore character -- I just wanted a way to have mostlexicon keys be autoable, except for possibly a few, and Iarbitrarily decided to use a leading underscore as a signalto distinguish those few.=head1 CONTROLLING LOOKUP FAILUREIf you call $lh->maketext(I<key>, ...parameters...),and there's no entry I<key> in $lh's class's %Lexicon, norin the superclass %Lexicon hash, I<and> if we can't auto-makeI<key> (because either it starts with a "_", or because noneof its lexicons have C<_AUTO =E<gt> 1,>), then we havefailed to find a normal way to maketext I<key>.  What thenhappens in these failure conditions, depends on the $lh object"fail" attribute.If the language handle has no "fail" attribute, maketextwill simply throw an exception (i.e., it calls C<die>, mentioningthe I<key> whose lookup failed, and naming the line number wherethe calling $lh->maketext(I<key>,...) was.If the language handle has a "fail" attribute whose value is acoderef, then $lh->maketext(I<key>,...params...) gives up and calls:  return &{$that_subref}($lh, $key, @params);Otherwise, the "fail" attribute's value should be a string denotinga method name, so that $lh->maketext(I<key>,...params...) cangive up with:  return $lh->$that_method_name($phrase, @params);The "fail" attribute can be accessed with the C<fail_with> method:  # Set to a coderef:  $lh->fail_with( \&failure_handler );  # Set to a method name:  $lh->fail_with( 'failure_method' );    # Set to nothing (i.e., so failure throws a plain exception)  $lh->fail_with( undef );    # Simply read:  $handler = $lh->fail_with();Now, as to what you may want to do with these handlers:  Maybe you'dwant to log what key failed for what class, and then die.  Maybeyou don't like C<die> and instead you want to send the error messageto STDOUT (or wherever) and then merely C<exit()>.Or maybe you don't want to C<die> at all!  Maybe you could use ahandler like this:  # Make all lookups fall back onto an English value,  #  but after we log it for later fingerpointing.  my $lh_backup = ThisProject->get_handle('en');  open(LEX_FAIL_LOG, ">>wherever/lex.log") || die "GNAARGH $!";  sub lex_fail {    my($failing_lh, $key, $params) = @_;    print LEX_FAIL_LOG scalar(localtime), "\t",       ref($failing_lh), "\t", $key, "\n";

⌨️ 快捷键说明

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