File Coverage

blib/lib/Locale/TextDomain.pm
Criterion Covered Total %
statement 72 138 52.1
branch 14 48 29.1
condition 5 36 13.8
subroutine 18 34 52.9
pod 7 7 100.0
total 116 263 44.1


line stmt bran cond sub pod time code
1             #! /bin/false
2              
3             # vim: set autoindent shiftwidth=4 tabstop=4:
4              
5             # High-level interface to Perl i18n.
6             # Copyright (C) 2002-2026 Guido Flohr <guido.flohr@cantanea.com>,
7             # all rights reserved.
8              
9             # This program is free software: you can redistribute it and/or modify
10             # it under the terms of the GNU General Public License as published by
11             # the Free Software Foundation; either version 3 of the License, or
12             # (at your option) any later version.
13              
14             # This program is distributed in the hope that it will be useful,
15             # but WITHOUT ANY WARRANTY; without even the implied warranty of
16             # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17             # GNU General Public License for more details.
18              
19             # You should have received a copy of the GNU General Public License
20             # along with this program. If not, see <http://www.gnu.org/licenses/>.
21              
22             package __TiedTextDomain;
23              
24 3     3   200718 use strict;
  3         7  
  3         832  
25              
26             sub TIEHASH
27             {
28 3     3   37 my ($class, $function) = @_;
29 3         19 bless {
30             __function => $function,
31             }, $class;
32             }
33              
34             sub FETCH
35             {
36 0     0   0 my ($self, $msg) = @_;
37            
38 0         0 &{$self->{__function}} ($msg);
  0         0  
39             }
40              
41             sub FIRSTKEY
42             {
43 0     0   0 my $self = shift;
44 0         0 my $reset_iterator = keys %$self;
45 0         0 return scalar each %$self;
46             }
47              
48             sub NEXTKEY
49             {
50 0     0   0 my $self = shift;
51 0         0 return scalar each %$self;
52             }
53              
54       0     sub CLEAR {}
55       0     sub STORE {}
56       0     sub DELETE {}
57              
58             1;
59              
60             package Locale::TextDomain;
61              
62 3     3   24 use strict;
  3         6  
  3         159  
63              
64 3     3   1497 use Locale::Messages qw (textdomain bindtextdomain dgettext dngettext dpgettext dnpgettext);
  3         10  
  3         484  
65 3     3   23 use Cwd qw (abs_path);
  3         7  
  3         210  
66              
67 3     3   22 use vars qw ($VERSION);
  3         6  
  3         211  
68              
69             $VERSION = '1.37';
70              
71             require Exporter;
72              
73 3     3   24 use vars qw (@ISA @EXPORT %__ $__);
  3         7  
  3         830  
74              
75             @ISA = ('Exporter');
76             @EXPORT = qw (__ __x __n __nx __xn __p __px __np __npx $__ %__
77             N__ N__n N__p N__np);
78              
79             my %textdomains = ();
80             my %bound_dirs = ();
81             my @default_dirs = ();
82              
83             sub __ ($);
84            
85             sub __find_domain ($);
86             sub __expand ($%);
87             sub __tied_gettext ($$);
88              
89             BEGIN {
90             # Tie the hash to gettext().
91 3     3   30 tie %__, '__TiedTextDomain', \&__tied_gettext;
92 3         7 $__ = \%__;
93              
94             # Add default search directories, but only if they exist.
95 3         8 for my $dir (qw (/usr/share/locale /usr/local/share/locale)) {
96 3 50       122 if (-d $dir) {
97 3         12 @default_dirs = ($dir);
98 3         7609 last;
99             }
100             }
101             }
102              
103             # Class methods.
104             sub keywords {
105 2     2 1 15 join ' ', (
106             '--keyword=__',
107             '--keyword=%__',
108             '--keyword=$__',
109             '--keyword=__x',
110             '--keyword=__n:1,2',
111             '--keyword=__nx:1,2',
112             '--keyword=__xn:1,2',
113             '--keyword=__p:1c,2',
114             '--keyword=__px:1c,2',
115             '--keyword=__np:1c,2,3',
116             '--keyword=__npx:1c,2,3',
117             '--keyword=N__',
118             '--keyword=N__n:1,2',
119             '--keyword=N__p:1c,2',
120             '--keyword=N__np:1c,2,3',
121             );
122             }
123              
124             sub flags {
125 2     2 1 106 join ' ', (
126             '--flag=__:1:pass-perl-format',
127             '--flag=%__:1:pass-perl-format',
128             '--flag=$__:1:pass-perl-format',
129             '--flag=__x:1:perl-brace-format',
130             '--flag=__x:1:pass-perl-format',
131             '--flag=__n:1:pass-perl-format',
132             '--flag=__n:2:pass-perl-format',
133             '--flag=__nx:1:perl-brace-format',
134             '--flag=__nx:1:pass-perl-format',
135             '--flag=__nx:2:perl-brace-format',
136             '--flag=__nx:2:pass-perl-format',
137             '--flag=__xn:1:perl-brace-format',
138             '--flag=__xn:1:pass-perl-format',
139             '--flag=__xn:2:perl-brace-format',
140             '--flag=__xn:2:pass-perl-format',
141             '--flag=__p:2:pass-perl-format',
142             '--flag=__px:2:perl-brace-format',
143             '--flag=__px:2:pass-perl-format',
144             '--flag=__np:2:pass-perl-format',
145             '--flag=__np:3:pass-perl-format',
146             '--flag=__npx:2:perl-brace-format',
147             '--flag=__npx:2:pass-perl-format',
148             '--flag=__npx:3:perl-brace-format',
149             '--flag=__npx:3:pass-perl-format',
150             '--flag=N__:1:pass-perl-format',
151             '--flag=N__n:1:pass-perl-format',
152             '--flag=N__n:2:pass-perl-format',
153             '--flag=N__p:2:pass-perl-format',
154             '--flag=N__np:2:pass-perl-format',
155             '--flag=N__np:3:pass-perl-format',
156             );
157             }
158              
159             sub options {
160 1     1 1 49 my ($class) = @_;
161              
162 1         4 join ' ', $class->keywords, $class->flags;
163             }
164              
165             # Normal gettext.
166             sub __ ($)
167             {
168 2     2   189687 my $msgid = shift;
169            
170 2         6 my $package = caller;
171            
172 2         5 my $textdomain = $textdomains{$package};
173            
174             __find_domain $textdomain if
175 2 100 66     18 defined $textdomain && defined $bound_dirs{$textdomain};
176            
177 2         6 return dgettext $textdomain => $msgid;
178             }
179              
180             # Called from tied hash.
181             sub __tied_gettext ($$)
182             {
183 0     0   0 my ($msgid) = @_;
184            
185 0         0 my ($package) = caller (1);
186            
187 0         0 my $textdomain = $textdomains{$package};
188 0 0       0 unless (defined $textdomain) {
189 0         0 my ($maybe_package, $filename, $line) = caller (2);
190 0 0       0 if (exists $textdomains{$maybe_package}) {
191 0         0 warn <<EOF;
192             Probable use of \$__ or \%__ where __() should be used at $filename:$line.
193             EOF
194             }
195             }
196             __find_domain $textdomain if
197 0 0 0     0 defined $textdomain && defined $bound_dirs{$textdomain};
198            
199 0         0 return dgettext $textdomain => $msgid;
200             }
201              
202             # With interpolation.
203             sub __x ($@)
204             {
205 0     0   0 my ($msgid, %vars) = @_;
206            
207 0         0 my $package = caller;
208            
209 0         0 my $textdomain = $textdomains{$package};
210            
211             __find_domain $textdomain if
212 0 0 0     0 defined $textdomain && defined $bound_dirs{$textdomain};
213            
214 0         0 return __expand ((dgettext $textdomain => $msgid), %vars);
215             }
216              
217             # Plural.
218             sub __n ($$$)
219             {
220 0     0   0 my ($msgid, $msgid_plural, $count) = @_;
221            
222 0         0 my $package = caller;
223            
224 0         0 my $textdomain = $textdomains{$package};
225            
226             __find_domain $textdomain if
227 0 0 0     0 defined $textdomain && defined $bound_dirs{$textdomain};
228            
229 0         0 return dngettext $textdomain, $msgid, $msgid_plural, $count;
230             }
231              
232             # Plural with interpolation.
233             sub __nx ($$$@)
234             {
235 0     0   0 my ($msgid, $msgid_plural, $count, %args) = @_;
236            
237 0         0 my $package = caller;
238            
239 0         0 my $textdomain = $textdomains{$package};
240            
241             __find_domain $textdomain if
242 0 0 0     0 defined $textdomain && defined $bound_dirs{$textdomain};
243            
244 0         0 return __expand ((dngettext $textdomain, $msgid, $msgid_plural, $count),
245             %args);
246             }
247              
248             # Plural with interpolation.
249             sub __xn ($$$@)
250             {
251 0     0   0 my ($msgid, $msgid_plural, $count, %args) = @_;
252            
253 0         0 my $package = caller;
254            
255 0         0 my $textdomain = $textdomains{$package};
256            
257             __find_domain $textdomain if
258 0 0 0     0 defined $textdomain && defined $bound_dirs{$textdomain};
259            
260 0         0 return __expand ((dngettext $textdomain, $msgid, $msgid_plural, $count),
261             %args);
262             }
263              
264             # Context. (p is for particular or special)
265             sub __p ($$)
266             {
267 0     0   0 my $msgctxt = shift;
268 0         0 my $msgid = shift;
269            
270 0         0 my $package = caller;
271            
272 0         0 my $textdomain = $textdomains{$package};
273            
274             __find_domain $textdomain if
275 0 0 0     0 defined $textdomain && defined $bound_dirs{$textdomain};
276            
277 0         0 return dpgettext $textdomain => $msgctxt, $msgid;
278             }
279              
280             # With interpolation.
281             sub __px ($$@)
282             {
283 0     0   0 my ($msgctxt, $msgid, %vars) = @_;
284            
285 0         0 my $package = caller;
286            
287 0         0 my $textdomain = $textdomains{$package};
288            
289             __find_domain $textdomain if
290 0 0 0     0 defined $textdomain && defined $bound_dirs{$textdomain};
291            
292 0         0 return __expand ((dpgettext $textdomain => $msgctxt, $msgid), %vars);
293             }
294              
295             # Context + Plural.
296             sub __np ($$$$)
297             {
298 0     0   0 my ($msgctxt, $msgid, $msgid_plural, $count) = @_;
299            
300 0         0 my $package = caller;
301            
302 0         0 my $textdomain = $textdomains{$package};
303            
304             __find_domain $textdomain if
305 0 0 0     0 defined $textdomain && defined $bound_dirs{$textdomain};
306            
307 0         0 return dnpgettext $textdomain, $msgctxt, $msgid, $msgid_plural, $count;
308             }
309              
310             # Plural with interpolation.
311             sub __npx ($$$$@)
312             {
313 0     0   0 my ($msgctxt, $msgid, $msgid_plural, $count, %args) = @_;
314            
315 0         0 my $package = caller;
316            
317 0         0 my $textdomain = $textdomains{$package};
318            
319             __find_domain $textdomain if
320 0 0 0     0 defined $textdomain && defined $bound_dirs{$textdomain};
321            
322 0         0 return __expand ((dnpgettext $textdomain, $msgctxt, $msgid, $msgid_plural, $count),
323             %args);
324             }
325              
326             # Dummy functions for string marking.
327             sub N__($)
328             {
329 2     2 1 214318 return shift;
330             }
331              
332             sub N__n($$$)
333             {
334 1     1 1 120 return @_;
335             }
336              
337             sub N__p($$) {
338 1     1 1 63 return @_;
339             }
340              
341             sub N__np($$$$) {
342 1     1 1 47 return @_;
343             }
344              
345             sub import
346             {
347 2     2   24 my ($self, $textdomain, @search_dirs) = @_;
348            
349             # Check our caller.
350 2         6 my $package = caller;
351 2 50       10 return if exists $textdomains{$package};
352            
353             # Was a textdomain specified?
354 2 100 66     14 $textdomain = textdomain unless defined $textdomain && length $textdomain;
355            
356             # Remember the textdomain of that package.
357 2         7 $textdomains{$package} = $textdomain;
358            
359             # Remember that we still have to bind that textdomain to
360             # a directory.
361 2 50       13 unless (exists $bound_dirs{$textdomain}) {
362 2 50       6 unless (@search_dirs) {
363 2 50       26 @search_dirs = ((map $_ . '/LocaleData', @INC), @default_dirs)
364             unless @search_dirs;
365 2 50       6 if (my $share = eval {
366 2         1445 require File::ShareDir;
367 2         85484 File::ShareDir::dist_dir ($textdomain);
368             }) {
369             unshift @search_dirs,
370 0         0 map { "$share/$_" }
  0         0  
371             qw (locale LocaleData);
372             }
373             }
374 2         2524 $bound_dirs{$textdomain} = [grep { -d $_ } @search_dirs];
  21         400  
375             }
376            
377 2         431 Locale::TextDomain->export_to_level (1, $package, @EXPORT);
378            
379 2         2563 return;
380             }
381              
382             # Private functions.
383             sub __find_domain ($)
384             {
385 1     1   4 my $domain = shift;
386            
387 1         3 my $try_dirs = $bound_dirs{$domain};
388            
389 1 50       21 if (defined $try_dirs) {
390 1         2 my $found_dir;
391            
392 1         2 TRYDIR: foreach my $dir (grep { -d $_ } @$try_dirs) {
  2         39  
393             # Is there a message catalog? We have to search recursively
394             # for it. Since globbing is reported to be buggy under
395             # MS-DOS, we roll our own version.
396 1         4 local *DIR;
397 1 50       63 if (opendir DIR, $dir) {
398 4         9 my @files = map { "$dir/$_/LC_MESSAGES/$domain.mo" }
399 1         31 grep { ! /^\.\.?$/ } readdir DIR;
  6         14  
400              
401 1         4 foreach my $file (@files) {
402 1 50 33     39 if (-f $file || -l $file) {
403             # If we find a non-readable file on our way,
404             # we access has been disabled on purpose.
405             # Therefore no -r check here.
406 1         4 $found_dir = $dir;
407 1         19 last TRYDIR;
408             }
409             }
410             }
411             }
412            
413             # If there was no success, this will fall back to the default search
414             # directories.
415 1 50       36 bindtextdomain $domain => abs_path $found_dir if defined $found_dir;
416             }
417            
418             # The search has completed.
419 1         2 undef $bound_dirs{$domain};
420            
421 1         3 return 1;
422             }
423              
424             sub __expand ($%)
425             {
426 0     0     my ($translation, %args) = @_;
427            
428 0           my $re = join '|', map { quotemeta $_ } keys %args;
  0            
429 0 0         $translation =~ s/\{($re)\}/defined $args{$1} ? $args{$1} : "{$1}"/ge;
  0            
430            
431 0           return $translation;
432             }
433              
434             1;
435              
436             __END__
437              
438             =head1 NAME
439              
440             Locale::TextDomain - Perl Interface to Uniforum Message Translation
441              
442             =head1 SYNOPSIS
443              
444             use Locale::TextDomain ('my-package', @locale_dirs);
445            
446             use Locale::TextDomain qw (my-package);
447            
448             my $translated = __"Hello World!\n";
449            
450             my $alt = $__{"Hello World!\n"};
451            
452             my $alt2 = $__->{"Hello World!\n"};
453              
454             my @list = (N__"Hello",
455             N__"World");
456            
457             printf (__n ("one file read",
458             "%d files read",
459             $num_files),
460             $num_files);
461              
462             print __nx ("one file read", "{num} files read", $num_files,
463             num => $num_files);
464              
465             my $translated_context = __p ("Verb, to view", "View");
466              
467             printf (__np ("Files read from filesystems",
468             "one file read",
469             "%d files read",
470             $num_files),
471             $num_files);
472              
473             print __npx ("Files read from filesystems",
474             "one file read",
475             "{num} files read",
476             $num_files,
477             num => $num_files);
478              
479              
480             =head1 DESCRIPTION
481              
482             The module Locale::TextDomain(3pm) provides a high-level interface
483             to Perl message translation.
484              
485             =head2 Textdomains
486              
487             When you request a translation for a given string, the system used
488             in libintl-perl follows a standard strategy to find a suitable message
489             catalog containing the translation: Unless you explicitely define
490             a name for the message catalog, libintl-perl will assume that your
491             catalog is called 'messages' (unless you have changed the default
492             value to something else via Locale::Messages(3pm), method textdomain()).
493              
494             You might think that his default strategy leaves room for optimization
495             and you are right. It would be a lot smarter if multiple software
496             packages, all with their individual message catalogs, could be installed
497             on one system, and it should also be possible that third-party
498             components of your software (like Perl modules) can load their
499             message catalogs, too, without interfering with yours.
500              
501             The solution is clear, you have to assign a unique name to your message
502             database, and you have to specify that name at run-time. That unique
503             name is the so-called I<textdomain> of your software package. The name is
504             actually arbitrary but you should follow these best-practice guidelines
505             to ensure maximum interoperability:
506              
507             =over 8
508              
509             =item File System Safety
510              
511             In practice, textdomains get mapped into file names, and you should
512             therefore make sure that the textdomain you choose is a valid filename
513             on every system that will run your software.
514              
515             =item Case-sensitivity
516              
517             Textdomains are always case-sensitive (i. e. 'Package' and 'PACKAGE'
518             are not the same). However, since the message catalogs will be stored
519             on file systems, that may or may not distinguish case when looking
520             up file names, you should avoid potential conflicts here.
521              
522             =item Textdomain Should Match CPAN Name
523              
524             If your software is listed as a module on CPAN, you should simply
525             choose the name on CPAN as your textdomain. The textdomain for
526             libintl-perl is hence 'libintl-perl'. But please replace all
527             periods ('.') in your package name with an underscore because ...
528              
529             =item Internet Domain Names as a Fallback
530              
531             ... if your software is I<not> a module listed on CPAN, as a last
532             resort you should use the Java(tm) package scheme, i. e. choose
533             an internet domain that you are owner of (or ask the owner of an
534             internet domain) and concatenate your preferred textdomain with the
535             reversed internet domain. Example: Your company runs the web-site
536             'www.foobar.org' and is the owner of the domain 'foobar.org'. The
537             textdomain for your company's software 'barfoos' should hence be
538             'org.foobar.barfoos'.
539              
540             =back
541              
542             If your software is likely to be installed in different versions on
543             the same system, it is probably a good idea to append some version
544             information to your textdomain.
545              
546             Other systems are less strict with the naming scheme for textdomains
547             but the phenomena known as Perl is actually a plethora of small,
548             specialized modules and it is probably wisest to postulate some
549             namespace model in order to avoid chaos.
550              
551             =head2 Binding textdomains to directories
552              
553             Once the system knows the I<textdomain> of the message that you
554             want to get translated into the user's language, it still has to
555             find the correct message catalog. By default, libintl-perl will
556             look up the string in the translation database found in the
557             directories F</usr/share/locale> and F</usr/local/share/locale>
558             (in that order).
559              
560             It is neither guaranteed that these directories exist on the target
561             machine, nor can you be sure that the installation routine has write
562             access to these locations. You can therefore instruct libintl-perl
563             to search other directories prior to the default directories. Specifying
564             a differnt search directory is called I<binding> a textdomain to a
565             directory.
566              
567             Beginning with version 1.20, B<Locale::TextDomain> extends the default
568             strategy by a Perl-specific approach. If L<File::ShareDir> is installed, it
569             will look in the subdirectories named F<locale> and F<LocaleData> (in that
570             order) in the directory returned by C<File::ShareDir::dist_dir ($textdomain)>
571             (if L<File::ShareDir> is installed),
572             and check for a database containing the message for your textdomain there.
573             This allows you to install your database in the Perl-specific shared directory
574             using L<Module::Install>'s C<install_share> directive or the Dist::Zilla
575             L<ShareDir plugin|Dist::Zilla::Plugin::ShareDir>.
576              
577             If L<File::ShareDir> is not availabe, or if Locale::TextDomain fails to find
578             the translation files in the L<File::ShareDir> directory, it will next look in
579             every directory found in the standard include path C<@INC>, and check for a
580             database containing the message for your textdomain there. Example: If the
581             path F</usr/lib/perl/5.8.0/site_perl> is in your C<@INC>, you can install your
582             translation files in F</usr/lib/perl/5.8.0/site_perl/LocaleData>, and they
583             will be found at run-time.
584              
585             =head1 USAGE
586              
587             It is crucial to remember that you use Locale::TextDomain(3) as
588             specified in the section L</SYNOPSIS>, that means you have to
589             B<use> it, not B<require> it. The module behaves quite differently
590             compared to other modules.
591              
592             The most significant difference is the meaning of the list passed
593             as an argument to the use() function. It actually works like this:
594              
595             use Locale::TextDomain (TEXTDOMAIN, DIRECTORY, ...)
596              
597             The first argument (the first string passed to use()) is the textdomain
598             of your package, optionally followed by a list of directories to search
599             I<instead> of the Perl-specific directories (see above: F</LocaleData>
600             appended to a F<File::ShareDir> directory and every path in C<@INC>).
601              
602             If you are the author of a package 'barfoos', you will probably put
603             the line
604              
605             use Locale::TextDomain 'barfoos';
606              
607             resp. for non-CPAN modules
608              
609             use Locale::TextDomain 'org.foobar.barfoos';
610              
611             in every module of your package that contains translatable strings. If
612             your module has been installed properly, including the message catalogs,
613             it will then be able to retrieve these translations at run-time.
614              
615             If you have not installed the translation database in a directory
616             F<LocaleData> in the L<File::ShareDir> directory or the standard include
617             path C<@INC> (or in the system directories F</usr/share/locale> resp.
618             F</usr/local/share/locale>), you have to explicitely specify a search
619             path by giving the names of directories (as strings!) as additional
620             arguments to use():
621              
622             use Locale::TextDomain qw (barfoos ./dir1 ./dir2);
623              
624             Alternatively you can call the function bindtextdomain() with suitable
625             arguments (see the entry for bindtextdomain() in
626             L<Locale::Messages/FUNCTIONS>). If you do so, you should pass
627             C<undef> as an additional argument in order to avoid unnecessary
628             lookups:
629              
630             use Locale::TextDomain ('barfoos', undef);
631              
632             You see that the arguments given to use() have nothing to do with
633             what is imported into your namespace, but they are rather arguments
634             to textdomain(), resp. bindtextdomain(). Does that mean that
635             B<Locale::TextDomain> exports nothing into your namespace? Umh, not
636             exactly ... in fact it imports I<all> functions listed below into
637             your namespace, and hence you should not define conflicting functions
638             (and variables) yourself.
639              
640             So, why has Locale::TextDomain to be different from other modules?
641             If you have ever written software in C and prepared it for
642             internationalization (i18n), you will probably have defined some
643             preprocessor macros like:
644              
645             #define _(String) dgettext ("my-textdomain", String)
646             #define N_(String) String
647              
648             You only have to define that once in C, and the textdomain for your
649             package is automatically inserted into all gettext functions. In
650             Perl there is no such mechanism (at least it is not portable,
651             option -P) and using the gettext functions could become quite
652             cumbersome without some extra fiddling:
653              
654             print dgettext ("my-textdomain", "Hello world!\n");
655              
656             This is no fun. In C it would merely be a
657              
658             printf (_("Hello world!\n"));
659              
660             Perl has to be more concise and shorter than C ... see the next
661             section for how you can use B<Locale::TextDomain> to end up in Perl
662             with a mere
663              
664             print __"Hello World!\n";
665              
666             =head1 EXPORTED FUNCTIONS
667              
668             All functions have quite funny names on purpose. In fact the
669             purpose for that is quite clear: They should be short, operator-like,
670             and they should not yell for conflicts with existing functions in
671             I<your> namespace. You will understand it, when you internationalize
672             your first Perl program or module. Preparing it is more like marking
673             strings as being translatable than inserting function calls. Here
674             we go:
675              
676             =over 4
677              
678             =item B<__ MSGID>
679              
680             B<NOTE:> This is a I<double> underscore!
681              
682             The basic and most-used function. It is a short-cut for a call
683             to gettext() resp. dgettext(), and simply returns the translation for
684             B<MSGID>. If your old code reads like this:
685              
686             print "permission denied";
687            
688             You will now write:
689              
690             print __"permission denied";
691              
692             That's all, the string will be output in the user's preferred language,
693             provided that you have installed a translation for it.
694              
695             Of course you can also use parentheses:
696              
697             print __("permission denied");
698              
699             Or even:
700              
701             print (__("permission denied"));
702              
703             In my eyes, the first version without parentheses looks best.
704              
705             =item B<__x MSGID, ID1 =E<gt> VAL1, ID2 =E<gt> VAL2, ...>
706              
707             One of the nicest features in Perl is its capability to interpolate
708             variables into strings:
709              
710             print "This is the $color $thing.\n";
711              
712             This nice feature might con you into thinking that you could now
713             write
714              
715             print __"This is the $color $thing.\n";
716              
717             Alas, that would be nice, but it is not possible. Remember that the
718             function __() serves both as an operator for translating strings
719             I<and> as a mark for translatable strings. If the above string would
720             get extracted from your Perl code, the un-interpolated form would
721             end up in the message catalog because when parsing your code it
722             is unpredictable what values the variables C<$thing> and C<$color>
723             will have at run-time (this fact is most probably one of the reasons
724             you have written your program for).
725              
726             However, at run-time, Perl will have interpolated the values already
727             I<before> __() (resp. the underlying gettext() function) has seen the
728             original string. Consequently something like "This is the red car.\n"
729             will be looked up in the message catalog, it will not be found (because
730             only "This is the $color $thing.\n" is included in the database),
731             and the original, untranslated string will be returned.
732             Honestly, because this is almost always an error, the xgettext(1)
733             program will bail out with a fatal error when it comes across that
734             string in your code.
735              
736             There are two workarounds for that:
737              
738             printf __"This is the %s %s.\n", $color, $thing;
739              
740             But that has several disadvantages: Your translator will only
741             see the isolated string, and without the surrounding code it
742             is almost impossible to interpret it correctly. Of course, GNU
743             emacs and other software capable of editing PO translation files
744             will allow you to examine the context in the source code, but it
745             is more likely that your translator will look for a less challenging
746             translation project when she frequently comes across such messages.
747              
748             And even if she does understand the underlying programming, what
749             if she has to reorder the color and the thing like in French:
750              
751             msgid "This is the red car.\n";
752             msgstr "Cela est la voiture rouge.\n"
753              
754             Zut alors! While it is possible to reorder the arguments to printf()
755             and friends, it requires a syntax that is is nothing that you want to
756             learn.
757              
758             So what? The Perl backend to GNU gettext has defined an alternative
759             format for interpolatable strings:
760              
761             "This is the {color} {thing}.\n";
762              
763             Instead of Perl variables you use place-holders (legal Perl variables
764             are also legal place-holders) in curly braces, and then you call
765              
766             print __x ("This is the {color} {thing}.\n",
767             thing => $thang,
768             color => $color);
769              
770             The function __x() will take the additional hash and replace all
771             occurencies of the hash keys in curly braces with the corresponding
772             values. Simple, readable, understandable to translators, what else
773             would you want? And if the translator forgets, misspells or otherwise
774             messes up some "variables", the msgfmt(1) program, that is used to
775             compile the textual translation file into its binary representation
776             will even choke on these errors and refuse to compile the translation.
777              
778             =item B<__n MSGID, MSGID_PLURAL, COUNT>
779              
780             Whew! That looks complicated ... It is best explained with an example.
781             We'll have another look at your vintage code:
782              
783             if ($files_deleted > 1) {
784             print "All files have been deleted.\n";
785             } else {
786             print "One file has been deleted.\n";
787             }
788              
789             Your intent is clear, you wanted to avoid the cumbersome
790             "1 files deleted". This is okay for English, but other languages
791             have more than one plural form. For example in Russian it makes
792             a difference whether you want to say 1 file, 3 files or 6 files.
793             You will use three different forms of the noun 'file' in each
794             case. [Note: Yep, very smart you are, the Russian word for 'file'
795             is in fact the English word, and it is an invariable noun, but if you
796             know that, you will also understand the rest despite this little
797             simplification ...].
798              
799             That is the reason for the existance of the function ngettext(),
800             that __n() is a short-cut for:
801              
802             print __n"One file has been deleted.\n",
803             "All files have been deleted.\n",
804             $files_deleted;
805              
806             Alternatively:
807              
808             print __n ("One file has been deleted.\n",
809             "All files have been deleted.\n",
810             $files_deleted);
811              
812             The effect is always the same: libintl-perl will find out which
813             plural form to pick for your user's language, and the output string
814             will always look okay.
815              
816             =item B<__nx MSGID, MSGID_PLURAL, COUNT, VAR1 =E<gt> VAL1, VAR2 =E<gt> VAL2, ...>
817              
818             Bringing it all together:
819              
820             print __nx ("One file has been deleted.\n",
821             "{count} files have been deleted.\n",
822             $num_files,
823             count => $num_files);
824              
825             The function __nx() picks the correct plural form (also for English!)
826             I<and> it is capable of interpolating variables into strings.
827              
828             Have a close look at the order of arguments: The first argument is the
829             string in the singular, the second one is the plural string. The third
830             one is an integer indicating the number of items. This third argument
831             is I<only> used to pick the correct translation. The optionally
832             following arguments make up the hash used for interpolation. In the
833             beginning it is often a little confusing that the variable holding the
834             number of items will usually be repeated somewhere in the interpolation
835             hash.
836              
837             =item B<__xn MSGID, MSGID_PLURAL, COUNT, VAR1 =E<gt> VAL1, VAR2 =E<gt> VAL2, ...>
838              
839             Does exactly the same thing as __nx(). In fact it is a common typo
840             promoted to a feature.
841              
842             =item B<__p MSGCTXT, MSGID>
843              
844             This is much like __. The "p" stands for "particular", and the MSGCTXT
845             is used to provide context to the translator. This may be neccessary
846             when your string is short, and could stand for multiple things. For example:
847              
848             print __p"Verb, to view", "View";
849             print __p"Noun, a view", "View";
850              
851             The above may be "View" entries in a menu, where View->Source and File->View
852             are different forms of "View", and likely need to be translated differently.
853              
854             A typical usage are GUI programs. Imagine a program with a main
855             menu and the notorious "Open" entry in the "File" menu. Now imagine,
856             there is another menu entry Preferences->Advanced->Policy where you have
857             a choice between the alternatives "Open" and "Closed". In English, "Open"
858             is the adequate text at both places. In other languages, it is very
859             likely that you need two different translations. Therefore, you would
860             now write:
861              
862             __p"File|", "Open";
863             __p"Preferences|Advanced|Policy", "Open";
864              
865             In English, or if no translation can be found, the second argument
866             (MSGID) is returned.
867              
868             This function was introduced in libintl-perl 1.17.
869              
870             =item B<__px MSGCTXT, MSGID, VAR1 =E<gt> VAL1, VAR2 =E<gt> VAL2, ...>
871              
872             Like __p(), but supports variable substitution in the string, like __x().
873              
874             print __px("Verb, to view", "View {file}", file => $filename);
875              
876             See __p() and __x() for more details.
877              
878             This function was introduced in libintl-perl 1.17.
879              
880             =item B<__np MSGCTXT, MSGID, MSGID_PLURAL, COUNT>
881              
882             This adds context to plural calls. It should not be needed very often,
883             if at all, due to the __nx() function. The type of variable substitution
884             used in other gettext libraries (using sprintf-like sybols, like %s or %1)
885             sometimes required context. For a (bad) example of this:
886              
887             printf (__np("[count] files have been deleted",
888             "One file has been deleted.\n",
889             "%s files have been deleted.\n",
890             $num_files),
891             $num_files);
892              
893             NOTE: The above usage is discouraged. Just use the __nx() call, which
894             provides inline context via the key names.
895              
896             This function was introduced in libintl-perl 1.17.
897              
898             =item B<__npx MSGCTXT, MSGID, MSGID_PLURAL, COUNT, VAR1 =E<gt> VAL1, VAR2 =E<gt> VAL2, ...>
899              
900             This is provided for comleteness. It adds the variable interpolation
901             into the string to the previous method, __np().
902              
903             It's usage would be like so:
904              
905             print __npx ("Files being permenantly removed",
906             "One file has been deleted.\n",
907             "{count} files have been deleted.\n",
908             $num_files,
909             count => $num_files);
910              
911             I cannot think of any situations requiring this, but we can easily
912             support it, so here it is.
913              
914             This function was introduced in libintl-perl 1.17.
915              
916             =item B<N__(ARG1)>
917              
918             A no-op function that simply echoes its arguments to the caller. Take
919             the following piece of Perl:
920              
921             my @options = (
922             "Open",
923             "Save",
924             "Save As",
925             );
926              
927             ...
928              
929             my $option = $options[1];
930              
931             Now say that you want to have this translatable. You could sometimes
932             simply do:
933              
934             my @options = (
935             __"Open",
936             __"Save",
937             __"Save As",
938             );
939              
940             ...
941              
942             my $option = $options[1];
943              
944             But often times this will not be what you want, for example when you
945             also need the unmodified original string. Sometimes it may not even
946             work, for example, when the preferred user language is not yet
947             determined at the time that the list is initialized.
948              
949             In these cases you would write:
950              
951             my @options = (
952             N__"Open",
953             N__"Save",
954             N__"Save As",
955             );
956              
957             ...
958              
959             my $option = __($options[1]);
960             # or: my $option = dgettext ('my-domain', $options[1]);
961              
962             Now all the strings in C<@options> will be left alone, since N__()
963             returns its arguments (one ore more) unmodified. Nevertheless, the
964             string extractor will be able to recognize the strings as being
965             translatable. And you can still get the translation later by passing
966             the variable instead of the string to one of the above translation
967             functions.
968              
969             =item B<N__n (MSGID, MSGID_PLURAL, COUNT)>
970              
971             Does exactly the same as N__(). You will use this form if you have
972             to mark the strings as having plural forms.
973              
974             =item B<N__p (MSGCTXT, MSGID)>
975              
976             Marks B<MSGID> as N__() does, but in the context B<MSGCTXT>.
977              
978             =item B<N__np (MSGCTXT, MSGID, MSGID_PLURAL, COUNT)>
979              
980             Marks B<MSGID> as N__n() does, but in the context B<MSGCTXT>.
981              
982             =back
983              
984             =head1 EXPORTED VARIABLES
985              
986             The module exports several variables into your namespace:
987              
988             =over 4
989              
990             =item B<%__>
991              
992             A tied hash. Its keys are your original messages, the values are
993             their translations:
994              
995             my $title = "<h1>$__{'My Homepage'}</h1>";
996              
997             This is much better for your translation team than
998              
999             my $title = __"<h1>My Homepage</h1>";
1000              
1001             In the second case the HTML code will make it into the translation
1002             database and your translators have to be aware of HTML syntax when
1003             translating strings.
1004              
1005             B<Warning:> Do I<not> use this hash outside of double-quoted strings!
1006             The code in the tied hash object relies on the correct working of
1007             the function caller() (see "perldoc -f caller"), and this function
1008             will report incorrect results if the tied hash value is the argument
1009             to a function from another package, for example:
1010              
1011             my $result = Other::Package::do_it ($__{'Some string'});
1012              
1013             The tied hash code will see "Other::Package" as the calling package,
1014             instead of your own package. Consequently it will look up the message
1015             in the wrong text domain. There is no workaround for this bug.
1016             Therefore:
1017              
1018             Never use the tied hash interpolated strings!
1019              
1020             =item B<$__>
1021              
1022             A reference to C<%__>, in case you prefer:
1023              
1024             my $title = "<h1>$__->{'My Homepage'}</h1>";
1025              
1026             =back
1027              
1028             =head1 CLASS METHODS
1029              
1030             The following class methods are defined:
1031              
1032             =over 4
1033              
1034             =item B<options>
1035              
1036             Returns a space-separated list of all '--keyword' and all '--flag' options
1037             for B<xgettext(1)>, when extracing strings from Perl source files localized
1038             with B<Locale::TextDomain>.
1039              
1040             The option should rather be called B<xgettextDefaultOptions>. With regard
1041             to the typical use-case, a shorter name has been picked:
1042              
1043             xgettext `perl -MLocale::TextDomain -e 'print Locale::TextDomain->options'`
1044              
1045             See L<https://www.gnu.org/software/gettext/manual/html_node/xgettext-Invocation.html>
1046             for more information about the xgettext options '--keyword' and '--flag'.
1047              
1048             If you want to disable the use of the xgettext default keywords, you
1049             should pass an option '--keyword=""' to xgettext before the options returned
1050             by this method.
1051              
1052             If you doubt the usefulness of this method, check the output on the
1053             command-line:
1054              
1055             perl -MLocale::TextDomain -e 'print Locale::TextDomain->options'
1056              
1057             Nothing that you want to type yourself.
1058              
1059             This method was added in libintl-perl 1.28.
1060              
1061             =item B<keywords>
1062              
1063             Returns a space-separated list of all '--keyword' options for B<xgettext(1)>
1064             so that all translatable strings are properly extracted.
1065              
1066             This method was added in libintl-perl 1.28.
1067              
1068             =item B<flags>
1069              
1070             Returns a space-separated list of all '--flag' options for B<xgettext(1)>
1071             so that extracted strings are properly flagged.
1072              
1073             This method was added in libintl-perl 1.28.
1074              
1075             =back
1076              
1077             =head1 PERFORMANCE
1078              
1079             Message translation can be a time-consuming task. Take this little
1080             example:
1081              
1082             1: use Locale::TextDomain ('my-domain');
1083             2: use POSIX (:locale_h);
1084             3:
1085             4: setlocale (LC_ALL, '');
1086             5: print __"Hello world!\n";
1087              
1088             This will usually be quite fast, but in pathological cases it may
1089             run for several seconds. A worst-case scenario would be a
1090             Chinese user at a terminal that understands the codeset Big5-HKSCS.
1091             Your translator for Chinese has however chosen to encode the translations
1092             in the codeset EUC-TW.
1093              
1094             What will happen at run-time? First, the library will search and load a
1095             (maybe large) message catalog for your textdomain 'my-domain'. Then
1096             it will look up the translation for "Hello world!\n", it will find that
1097             it is encoded in EUC-TW. Since that differs from the output codeset
1098             Big5-HKSCS, it will first load a conversion table containing several
1099             ten-thousands of codepoints for EUC-TW, then it does the same with
1100             the smaller, but still very large conversion table for Big5-HKSCS,
1101             it will convert the translation on the fly from EUC-TW into Big5-HKSCS,
1102             and finally it will return the converted translation.
1103              
1104             A worst-case scenario but realistic. And for these five lines of codes,
1105             there is not much you can do to make it any faster. You should understand,
1106             however, I<when> the different steps will take place, so that you can
1107             arrange your code for it.
1108              
1109             You have learned in the section L</DESCRIPTION> that line 1 is
1110             responsible for locating your message database. However, the
1111             use() will do nothing more than remembering your settings. It will
1112             not search any directories, it will not load any catalogs or
1113             conversion tables.
1114              
1115             Somewhere in your code you will always have a call to
1116             POSIX::setlocale(), and the performance of this call may be time-consuming,
1117             depending on the architecture of your system. On some systems, this
1118             will consume very little time, on others it will only consume a
1119             considerable amount of time for the first call, and on others it may
1120             always be time-consuming. Since you cannot know, how setlocale() is
1121             implemented on the target system, you should reduce the calls to
1122             setlocale() to a minimum.
1123              
1124             Line 5 requests the translation for your string. Only now, the library
1125             will actually load the message catalog, and only now will it load
1126             eventually needed conversion tables. And from now on, all this information
1127             will be cached in memory. This strategy is used throughout libintl-perl,
1128             and you may describe it as 'load-on-first-access'. Getting the next
1129             translation will consume very little resources.
1130              
1131             However, although the translation retrieval is somewhat obfuscated
1132             by an operator-like function call, it is still a function call, and in
1133             fact it even involves a chain of function calls. Consequently, the
1134             following example is probably bad practice:
1135              
1136             foreach (1 .. 100_000) {
1137             print __"Hello world!\n";
1138             }
1139              
1140             This example introduces a lot of overhead into your program. Better
1141             do this:
1142              
1143             my $string = __"Hello world!\n";
1144             foreach (1 .. 100_000) {
1145             print $string;
1146             }
1147              
1148             The translation will never change, there is no need to retrieve it
1149             over and over again. Although libintl-perl will of course cache
1150             the translation read from the file system, you can still avoid the
1151             overhead for the function calls.
1152              
1153             =head1 AUTHOR
1154              
1155             Copyright (C) 2002-2026 L<Guido Flohr|http://www.guido-flohr.net/>
1156             (L<mailto:guido.flohr@cantanea.com>), all rights reserved. See the source
1157             code for details!code for details!
1158              
1159             =head1 SEE ALSO
1160              
1161             Locale::Messages(3pm), Locale::gettext_pp(3pm), perl(1),
1162             gettext(1), gettext(3)
1163              
1164             =cut
1165             Local Variables:
1166             mode: perl
1167             perl-indent-level: 4
1168             perl-continued-statement-offset: 4
1169             perl-continued-brace-offset: 0
1170             perl-brace-offset: -4
1171             perl-brace-imaginary-offset: 0
1172             perl-label-offset: -4
1173             cperl-indent-level: 4
1174             cperl-continued-statement-offset: 2
1175             tab-width: 4
1176             End: