📄 locale::maketext::tpj13.3
字号:
.\" Automatically generated by Pod::Man 2.16 (Pod::Simple 3.05).\".\" Standard preamble:.\" ========================================================================.de Sh \" Subsection heading.br.if t .Sp.ne 5.PP\fB\\$1\fR.PP...de Sp \" Vertical space (when we can't use .PP).if t .sp .5v.if n .sp...de Vb \" Begin verbatim text.ft CW.nf.ne \\$1...de Ve \" End verbatim text.ft R.fi...\" Set up some character translations and predefined strings. \*(-- will.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left.\" double quote, and \*(R" will give a right double quote. \*(C+ will.\" give a nicer C++. Capital omega is used to do unbreakable dashes and.\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff,.\" nothing in troff, for use with C<>..tr \(*W-.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p'.ie n \{\. ds -- \(*W-. ds PI pi. if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch. if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch. ds L" "". ds R" "". ds C` "". ds C' ""'br\}.el\{\. ds -- \|\(em\|. ds PI \(*p. ds L" ``. ds R" '''br\}.\".\" Escape single quotes in literal strings from groff's Unicode transform..ie \n(.g .ds Aq \(aq.el .ds Aq '.\".\" If the F register is turned on, we'll generate index entries on stderr for.\" titles (.TH), headers (.SH), subsections (.Sh), items (.Ip), and index.\" entries marked with X<> in POD. Of course, you'll have to process the.\" output yourself in some meaningful fashion..ie \nF \{\. de IX. tm Index:\\$1\t\\n%\t"\\$2"... nr % 0. rr F.\}.el \{\. de IX...\}.\".\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2)..\" Fear. Run. Save yourself. No user-serviceable parts.. \" fudge factors for nroff and troff.if n \{\. ds #H 0. ds #V .8m. ds #F .3m. ds #[ \f1. ds #] \fP.\}.if t \{\. ds #H ((1u-(\\\\n(.fu%2u))*.13m). ds #V .6m. ds #F 0. ds #[ \&. ds #] \&.\}. \" simple accents for nroff and troff.if n \{\. ds ' \&. ds ` \&. ds ^ \&. ds , \&. ds ~ ~. ds /.\}.if t \{\. ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u". ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u'. ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u'. ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u'. ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u'. ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u'.\}. \" troff and (daisy-wheel) nroff accents.ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V'.ds 8 \h'\*(#H'\(*b\h'-\*(#H'.ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#].ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H'.ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u'.ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#].ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#].ds ae a\h'-(\w'a'u*4/10)'e.ds Ae A\h'-(\w'A'u*4/10)'E. \" corrections for vroff.if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u'.if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u'. \" for low resolution devices (crt and lpr).if \n(.H>23 .if \n(.V>19 \\{\. ds : e. ds 8 ss. ds o a. ds d- d\h'-1'\(ga. ds D- D\h'-1'\(hy. ds th \o'bp'. ds Th \o'LP'. ds ae ae. ds Ae AE.\}.rm #[ #] #H #V #F C.\" ========================================================================.\".IX Title "Locale::Maketext::TPJ13 3".TH Locale::Maketext::TPJ13 3 "2007-12-18" "perl v5.10.0" "Perl Programmers Reference Guide".\" For nroff, turn off justification. Always turn off hyphenation; it makes.\" way too many mistakes in technical documents..if n .ad l.nh.SH "NAME"Locale::Maketext::TPJ13 \-\- article about software localization.SH "SYNOPSIS".IX Header "SYNOPSIS".Vb 1\& # This an article, not a module..Ve.SH "DESCRIPTION".IX Header "DESCRIPTION"The following article by Sean M. Burke and Jordan Lachlerfirst appeared in \fIThe Perl Journal\fR #13and is copyright 1999 The Perl Journal. It appearscourtesy of Jon Orwant and The Perl Journal. This document may bedistributed under the same terms as Perl itself..SH "Localization and Perl: gettext breaks, Maketext fixes".IX Header "Localization and Perl: gettext breaks, Maketext fixes"by Sean M. Burke and Jordan Lachler.PPThis article points out cases where gettext (a common system forlocalizing software interfaces \*(-- i.e., making them work in the user'slanguage of choice) fails because of basic differences between humanlanguages. This article then describes Maketext, a new system capableof correctly treating these differences..Sh "A Localization Horror Story: It Could Happen To You".IX Subsection "A Localization Horror Story: It Could Happen To You".RS 4\&\*(L"There are a number of languages spoken by human beings in thisworld.\*(R".Sp\&\-\- Harald Tveit Alvestrand, in \s-1RFC\s0 1766, \*(L"Tags for theIdentification of Languages\*(R".RE.PPImagine that your task for the day is to localize a piece of software\&\*(-- and luckily for you, the only output the program emits is twomessages, like this:.PP.Vb 1\& I scanned 12 directories.\&\& Your query matched 10 files in 4 directories..Ve.PPSo how hard could that be? You look at the code thatproduces the first item, and it reads:.PP.Vb 2\& printf("I scanned %g directories.",\& $directory_count);.Ve.PPYou think about that, and realize that it doesn't even work right forEnglish, as it can produce this output:.PP.Vb 1\& I scanned 1 directories..Ve.PPSo you rewrite it to read:.PP.Vb 5\& printf("I scanned %g %s.",\& $directory_count,\& $directory_count == 1 ?\& "directory" : "directories",\& );.Ve.PP\&...which does the Right Thing. (In case you don't recall, \*(L"%g\*(R" is forlocale-specific number interpolation, and \*(L"%s\*(R" is for stringinterpolation.).PPBut you still have to localize it for all the languages you'reproducing this software for, so you pull Locale::gettext off of \s-1CPAN\s0so you can access the \f(CW\*(C`gettext\*(C'\fR C functions you've heard are standardfor localization tasks..PPAnd you write:.PP.Vb 5\& printf(gettext("I scanned %g %s."),\& $dir_scan_count,\& $dir_scan_count == 1 ?\& gettext("directory") : gettext("directories"),\& );.Ve.PPBut you then read in the gettext manual (Drepper, Miller, and Pinard 1995)that this is not a good idea, since how a single word like \*(L"directory\*(R"or \*(L"directories\*(R" is translated may depend on context \*(-- and this istrue, since in a case language like German or Russian, you'd may needthese words with a different case ending in the first instance (where theword is the object of a verb) than in the second instance, which you haven't evengotten to yet (where the word is the object of a preposition, \*(L"in \f(CW%g\fRdirectories\*(R") \*(-- assuming these keep the same syntax when translatedinto those languages..PPSo, on the advice of the gettext manual, you rewrite:.PP.Vb 4\& printf( $dir_scan_count == 1 ?\& gettext("I scanned %g directory.") :\& gettext("I scanned %g directories."),\& $dir_scan_count );.Ve.PPSo, you email your various translators (the boss decides that thelanguages du jour are Chinese, Arabic, Russian, and Italian, so youhave one translator for each), asking for translations for \*(L"I scanned\&\f(CW%g\fR directory.\*(R" and \*(L"I scanned \f(CW%g\fR directories.\*(R". When they reply,you'll put that in the lexicons for gettext to use when it localizesyour software, so that when the user is running under the \*(L"zh\*(R"(Chinese) locale, gettext(\*(L"I scanned \f(CW%g\fR directory.\*(R") will return theappropriate Chinese text, with a \*(L"%g\*(R" in there where printf can theninterpolate \f(CW$dir_scan\fR..PPYour Chinese translator emails right back \*(-- he says both of thesephrases translate to the same thing in Chinese, because, in linguisticjargon, Chinese \*(L"doesn't have number as a grammatical category\*(R" \*(--whereas English does. That is, English has grammatical rules thatrefer to \*(L"number\*(R", i.e., whether something is grammatically singularor plural; and one of these rules is the one that forces nouns to takea plural suffix (generally \*(L"s\*(R") when in a plural context, as they are whenthey follow a number other than \*(L"one\*(R" (including, oddly enough, \*(L"zero\*(R").Chinese has no such rules, and so has just the one phrase where Englishhas two. But, no problem, you can have this one Chinese phrase appearas the translation for the two English phrases in the \*(L"zh\*(R" gettextlexicon for your program..PPEmboldened by this, you dive into the second phrase that your softwareneeds to output: \*(L"Your query matched 10 files in 4 directories.\*(R". You noticethat if you want to treat phrases as indivisible, as the gettextmanual wisely advises, you need four cases now, instead of two, tocover the permutations of singular and plural on the two items,\&\f(CW$dir_count\fR and \f(CW$file_count\fR. So you try this:.PP.Vb 9\& printf( $file_count == 1 ?\& ( $directory_count == 1 ?\& gettext("Your query matched %g file in %g directory.") :\& gettext("Your query matched %g file in %g directories.") ) :\& ( $directory_count == 1 ?\& gettext("Your query matched %g files in %g directory.") :\& gettext("Your query matched %g files in %g directories.") ),\& $file_count, $directory_count,\& );.Ve.PP(The case of \*(L"1 file in 2 [or more] directories\*(R" could, I suppose,occur in the case of symlinking or something of the sort.).PPIt occurs to you that this is not the prettiest code you've everwritten, but this seems the way to go. You mail off to thetranslators asking for translations for these four cases. TheChinese guy replies with the one phrase that these all translate to inChinese, and that phrase has two \*(L"%g\*(R"s in it, as it should \*(-- butthere's a problem. He translates it word-for-word back: \*(L"In \f(CW%g\fRdirectories contains \f(CW%g\fR files match your query.\*(R" The \f(CW%g\fRslots are in an order reverse to what they are in English. You wonderhow you'll get gettext to handle that..PPBut you put it aside for the moment, and optimistically hope that theother translators won't have this problem, and that their languageswill be better behaved \*(-- i.e., that they will be just like English..PPBut the Arabic translator is the next to write back. First off, yourcode for \*(L"I scanned \f(CW%g\fR directory.\*(R" or \*(L"I scanned \f(CW%g\fR directories.\*(R"assumes there's only singular or plural. But, to use linguisticjargon again, Arabic has grammatical number, like English (but unlikeChinese), but it's a three-term category: singular, dual, and plural.In other words, the way you say \*(L"directory\*(R" depends on whether there'sone directory, or \fItwo\fR of them, or \fImore than two\fR of them. Your
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -