1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373
|
=for Pod::Coverage ngettextp new
=head1 NAME
Template::Plugin::Gettext - Gettext Support For the Template Toolkit Version 2
=head1 SYNOPSIS
Load the plug-in in templates:
[% USE Gettext('com.textdomain.my', 'fr', 'utf-8', 'DIRECTORIES'...) %]
[% Gettext.gettext('Hello, world!') %]
[% 'Hello, world!' | gettext %]
Or alias "Gettext":
[% USE gtx = Gettext('com.textdomain.my', 'fr', 'utf-8', 'DIRECTORIES'...) %]
[% gtx.gettext('Hello, world!') %]
Use method invocations:
[% Gettext.gettext("Hello, world!") %]
[% Gettext.xgettext("Hello, {name}!", name => 'John Doe') %]
Or filters (without the prefix):
[% FILTER gettext %]
Hello, world!
[% END %]
[% 'Hello, world!' | gettext %]
[% FILTER xgettext(name => 'John Doe') %]
Hello, {name}!
[% END %]
You have a multitude of methods available:
[% gtx.gettext("Hello, user!") %]
[% gtx.xgettext("Hello, {user}!", user => 'John Doe') %]
[% gtx.ngettext("One document deleted.",
"Multiple documents deleted."),
42) %]
[% gtx.nxgettext("One document deleted.",
"{num} documents deleted."),
42,
num => 42) %]
[% gtx.npgettext("context..."
"One document deleted.",
"Multiple documents deleted."),
42) %]
[% gtx.npxgettext("context...",
"One document deleted.",
"{num} documents deleted."),
42,
num => 42) %]
=head1 DESCRIPTION
The B<Template::Plugin::Gettext> plug-in makes the
L<GNU gettext API|https://www.gnu.org/software/gettext/> available for
documents using the
L<Template Toolkit version 2|http://template-toolkit.org/>. See
L<https://github.com/gflohr/Template-Plugin-Gettext> for an overall
picture and the recommended tool-chain.
=head1 FUNCTIONS
The following methods produce translatable content:
=over 4
=item B<[% gtx.gettext(STRING) %]>
Retrieves the translation for B<STRING>.
=item B<[% gtx.xgettext(STRING, PLACEHOLDER1 =E<gt> VALUE1, PLACEHOLDER2 =E<gt> VALUE2, ...) %]>
Gets the translation for a string with placeholders and interpolates values
into it. Placeholders have the format <{PLACEHOLDER}>. For a literal
left curly brace you can use this hack:
[% gtx.xgettext("String with {LBRACE}PLACEHOLDERS{RBRACE}",
LBRACE => "{", RBRACE => "}") %]
=item B<[% gtx.pgettext(CONTEXT, STRING) %]>
Retrieves the translation for B<STRING> in context B<CONTEXT>. You
should use message context to disambiguate identical strings that
require different translations depending on the context. See this
example for an explanation:
[% gtx.gettext("State: ") %]
[% gtx.gettext("Open")] | [% gtx.gettext("Close") %]
[% gtx.gettext("Menu:") %]
[% gtx.pgettext("menu", "Open")]
[% gtx.gettext("Save")]
[% gtx.gettext("Save As")]
[% gtx.pgettext("menu", "Close")]
The strings "Open" and "Close" in line 2 are adjectives. As
menu entries they are verb forms and will have a different
translation in many languages.
In doubt: Only use contexts if one of your translators complains
about a message having multiple meanings.
=item B<[% gtx.pxgettext(CONTEXT, STRING,
PLACEHOLDER1 =E<gt> VALUE1,
PLACEHOLDER2 =E<gt> VALUE2) %]>
Get the translation for B<STRING> with placeholders in context
B<CONTEXT>. This is a mixture of C<xgettext()> and C<pgettext()>
above.
=item B<[% gtx.nxgettext(SINGULAR, PLURAL, COUNT,
PLACEHOLDER1 =E<gt> VALUE1,
PLACEHOLDER2 =E<gt> VALUE2) %]>
Retrieves the translation for the string with the singular form
B<SINGULAR> and the plural from B<PLURAL>, both possibly
containing placeholders. The correct form is picked based
upon the third argument B<COUNT>.
Example:
[% gtx.nxgettext("One document deleted",
"{num} documents deleted"),
count,
num => count) %]
In English this will produce "42 documents deleted" if the variable
count has the value 42. It will produce "One document deleted" if
the variable count has the value 1.
In other languages, the rules for plural forms may be a lot
simpler (for example Chinese, which has no plural) or a lot more
complicated (for example Russian with two or Slovenian with even
3 plural forms). Using ngettext() gives your translators the
chance to provide syntactically correct translations for these
cases.
=item B<[% gtx.npxgettext(CONTEXT, SINGULAR, PLURAL, COUNT,
PLACEHOLDER1 =E<gt> VALUE1,
PLACEHOLDER2 =E<gt> VALUE2) %]>
Putting it all together: For message context B<CONTEXT>
the translation for a message in B<SINGULAR> and B<PLURAL>
is retrieved based on the argument B<COUNT>. Possible placeholders
are expanded.
The function is a mixture of xgettext(), ngettext(), and
pgettext(), see above!
=item B<[% gtx.ngettext(SINGULAR, PLURAL, COUNT) %]>
Useless function, provided for completeness. Use nxgettext()
instead, so that you can interpolate the value of B<COUNT>!
=item B<[% gtx.npgettext(CONTEXT, SINGULAR, PLURAL, COUNT) %]>
Useless function, provided for completeness. Use npxgettext()
instead, so that you can interpolate the value of B<COUNT>!
=back
In fact, you have also all the keywords used for L</FILTERS>
available but those not listed here have such an odd ordering
of arguments that they are not listed here.
=head2 FILTERS
The entire gettext API is also exposed as a filter. There are
two things to note here:
=over 4
=item *
When used as filters, you don't prefix the method names. It'
s "gettext" not "Gettext.gettext" or "gtx.gettext()".
=item *
The filters with message contexts have rather strange names, for example:
[% FILTER gettextp("greeting") %]
Hello, world!
[% END %]
or 100 % equivalent:
[% 'Hello, world!' | gettextp("greeting") %]
Why? The text between B<FILTER> and B<END> resp. the text
in front of the pipe symbol B<|> is always the first argument.
This plug-in therefore tries to make the first argument the
most significant one. Nobody stops you from writing the
following:
[% FILTER pgettext("Hello, world!") %]
greeting
[% END %]
or again 100 % equivalent:
[% 'greeting' | pgettext("Hello, world!") %]
It produces exactly the same results as above but it looks
a little bit odd, doesn't it?
It would have been arguably better understandable to silently
reorder the arguments, when using the plug-in as a filter.
But it would break extraction of your strings with
L<xgettext-tt2> (L<Locale::XGettext::TT2>) because the string
extractor would then confuse the arguments.
But stay relaxed! Message contexts are rarely needed, and when
you need them, you have to live with this little weirdness.
In order to avoid confusion, those filters that would not have
the translatable string (in the singular form) where one would
expect it, are not documented here.
=back
You can use the following filters:
=over 4
=item B<[% STRING | gettext %]>
=item B<[% FILTER gettext %]STRING[% FILTER %]>
Retrieves the translation for B<STRING>.
=item B<[% STRING | xgettext(PLACEHOLDER1 =E<gt> VALUE1, PLACEHOLDER2 =E<gt> VALUE2, ...) %]>
=item B<[% FILTER xgettext(PLACEHOLDER1 =E<gt> VALUE1, PLACEHOLDER2 =E<gt> VALUE2, ...) %]STRING[% END %]>
Gets the translation for a string with placeholders and interpolates values
into it. Placeholders have the format <{PLACEHOLDER}>. For a literal
left curly brace you can use this hack:
[% "String with {LBRACE}PLACEHOLDERS{RBRACE}" | xgettext(LBRACE => "{", RBRACE => "}") %]
=item B<[% STRING | gettextp(CONTEXT) %]>
=item B<[% FILTER gettextp(CONTEXT) %]STRING[% END %]>
Retrieves the translation for B<STRING> in context B<CONTEXT>. You
should use message context to disambiguate identical strings that
require different translations depending on the context. See the
docuemntation for pgettext() in L</FUNCTIONS> above for more details!
=item B<[% STRING | xgettextp(CONTEXT, STRING, PLACEHOLDER1 =E<gt> VALUE1, PLACEHOLDER2 =E<gt> VALUE2) %]>
=item B<[% FILTER xgettextp(CONTEXT, STRING, PLACEHOLDER1 =E<gt> VALUE1, PLACEHOLDER2 =E<gt> VALUE2) %]STRING[% END %]>
Get the translation for B<STRING> with placeholders in context
B<CONTEXT>. This is a mixture of C<xgettext()> and C<pgettext()>
above.
=item B<[% SINGULAR | nxgettext(PLURAL, COUNT, PLACEHOLDER1 =E<gt> VALUE1, PLACEHOLDER2 =E<gt> VALUE2) %]>
=item B<[% FILTER nxgettext(PLURAL, COUNT, PLACEHOLDER1 =E<gt> VALUE1, PLACEHOLDER2 =E<gt> VALUE2) %]SINGULAR[% END %]>
Retrieves the translation for the string with the singular form
B<SINGULAR> and the plural from B<PLURAL>, both possibly
containing placeholders. The correct form is picked based
upon the third argument B<COUNT>.
Example:
[% "One document deleted" | nxgettext("{num} documents deleted"),
count,
num => count) %]
In English this will produce "42 documents deleted" if the variable
count has the value 42. It will produce "One document deleted" if
the variable count has the value 1.
In other languages, the rules for plural forms may be a lot
simpler (for example Chinese, which has no plural) or a lot more
complicated (for example Russian with two or Slovenian with even
3 plural forms). Using ngettext() gives your translators the
chance to provide syntactically correct translations for these
cases.
=item B<[% SINGULAR | nxgettextp(PLURAL, COUNT, CONTEXT,
PLACEHOLDER1 =E<gt> VALUE1,
PLACEHOLDER2 =E<gt> VALUE2) %]>
=item B<[% FILTER nxgettextp(PLURAL, COUNT, CONTEXT,
PLACEHOLDER1 =E<gt> VALUE1,
PLACEHOLDER2 =E<gt> VALUE2) %]SINGULAR[% END %]>
Putting it all together: For message context B<CONTEXT>
the translation for a message in B<SINGULAR> and B<PLURAL>
is retrieved based on the argument B<COUNT>. Possible placeholders
are expanded.
The filter is a mixture of xgettext(), ngettext(), and
pgettext(), see above!
=item B<[% SINGULAR | ngettext(PLURAL, COUNT) %]>
=item B<[% FILTER ngettext(PLURAL, COUNT) %]SINGULAR[% END %]>
Useless filter, provided for completeness. Use nxgettext()
instead, so that you can interpolate the value of B<COUNT>!
=item B<[% SINGULAR | ngettextp[(PLURAL, COUNT, CONTEXT) %]>
=item B<[% FILTER | ngettextp[(PLURAL, COUNT, CONTEXT) %]SINGULAR[% END %]>
Useless filter, provided for completeness. Use nxgettextp()
instead, so that you can interpolate the value of B<COUNT>!
=item B<[% debug_locale %]>
The plug-in implicitly calls B<web_set_locale()> (see
L<Locale::Util>) if a language was specified in the B<USE>
statement. The function B<debug_locale()> gives you the return
value of the call for debugging purposes. Example:
[% USE gtx = Gettext('com.mydomain.www', de') %]
Using locale [% debug_locale() %].
This way, you can determine whether setting the specified locale
actually worked.
=back
=head1 CLASS METHODS
=over 4
=item B<textdomains>
Returns a hash where the keys are the textdomains found in templates that
invoked the plug-in, and the values are the corresponding template file names.
The purpose of this method is to allow harvesting files that should be
processed by L<xgettext-tt2>.
If the template is either "input text" or "input file handle", the template
variable C<gettext_filename> - if existing - is assumed as the template
name. Rationale: "input text" and "input file handle" are used by the
Template Toolkit as aliases, when reading from a scalar or a file handle.
=item B<resetTextdomains>
Resets the hash described above for B<textdomain()> to its initial, empty
state.
=back
=head1 COPYRIGHT
Copyright (C) 2016-2018 Guido Flohr (http://www.guido-flohr.net/).
License LGPLv3+: L<GNU General Public License version 3 or later|http://gnu.org/licenses/lgpl.html>.
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
Copyright (C) 2016-2018 Guido Flohr <guido.flohr@cantanea.com>,
all rights reserved.
=head1 SEE ALSO
L<Template>, L<Template::Manual::Filters>, L<xgettext-tt2>, L<perl>
|