1Locale::TextDomain::OO(U3s)er Contributed Perl DocumentatLioocnale::TextDomain::OO(3)
2
3
4

NAME

6       Locale::TextDomain::OO - Perl OO Interface to Uniforum Message
7       Translation
8
9       $Id: OO.pm 724 2018-12-24 11:50:32Z steffenw $
10
11       $HeadURL:
12       svn+ssh://steffenw@svn.code.sf.net/p/perl-gettext-oo/code/module/trunk/lib/Locale/TextDomain/OO.pm
13       $
14

VERSION

16       1.036
17
18       Starting with version 1.000 the interface has changed.
19

DESCRIPTION

21       This module provides a high-level interface to Perl message
22       translation.
23
24       It is based on Singleton objects for translator and lexicon.  So it is
25       easy to attach that without any Web or Cmd plugins.  There is no
26       conflict between singleton and more than 1 project at the same time.
27       The lexicon has a project key to split.
28
29       You are able to use the translator singleton earlier then language
30       initialization but do not call the translation methods before.  Create
31       the lexicon singleton during compilation time.
32
33       Maketext is implemented here for moving existing projects to Gettext.
34
35       BabelFish is implemented for multi-plural in one phrase.  But use
36       BabelFish in that case only.  BabelFish is much harder to translate
37       (similar to maketext) by translation office or automatic translation.
38
39       For combinded plurals watch the Gettext multiplural example.  In that
40       case you have to write that awful long formulas but it is possibel.
41
42       Never use keys instead of English language in code.  You can't read,
43       execute (with placeholders) or test your code without translation.
44
45   Why a new module?
46       This module is similar to Locale::TextDomain and Locale::Maketext.
47
48       This module is not using/changing any system locale like
49       Locale::TextDomain.
50
51       This module has no magic in how to get the language like
52       Locale::Maketext.  You decide what you need.
53
54       There are some plugins, so it is possible to use different the Gettext,
55       BabelFish and/or Maketext styles.
56
57       Locale::TextDomain::OO has a flexible object oriented interface based
58       on Moo.
59
60       Creating the Lexicon and translating are two split things.  So it is
61       possible to create the lexicon during the compilation phase.  The
62       connection between both is the singleton mechanism of the lexicon
63       module using MooX::Singleton.
64
65   Plugin for the web framework?
66       This module was first used in a Catalyst based web project.
67
68       It was great to call everything on the Catalyst context object.  It was
69       great until we used module in web and shell scripts together and called
70       the translation methods there.
71
72       What we have done was removing the Catalyst Maketext plugin.  We are
73       using a role in the Catalyst application and so we can call all the
74       translation methods on the Catalyst context object like before.
75
76       For the shell scripts we have a role for this Cmd's to call all the
77       methods on $self.
78
79       In that roles we delegate a bunch of methods to Locale::TextDomain::OO.
80       We also added our project specific methods there.
81
82       Write you own role. There is no need for a plugin for any framework.
83
84   Who is sets the languages?
85       Not this module.
86
87       In a web application are lots of ideas to do that.  But never we use
88       the server settings, never.
89
90       The HTTP request contains that information.  Extend this with super and
91       panic languages.  Normally you support only a bunch of world languages,
92       so reduce.  This module will find the first match.
93
94       Or you store and get the language in the session.
95
96       Or your application has a language selection menu.  (Never use flags
97       for that.  There are multilanguage countries and more countries have
98       the same language.)
99
100   How to extract the project files?
101       Use module Locale::TextDomain::OO::Extract.  This is a base class for
102       all source scanner to create po/pot files.  Use this base class and
103       give this module the rules or use one of the already extended classes.
104       Locale::TextDomain::OO::Extract::Perl is a extension for Perl code and
105       so on.
106
107   How to build the lexicon - without Gettext tools?
108       Use module Locale::TextDomain::OO::Extract::Process.  This is able to
109       read, strip, extract, merge, write and clean PO and MO files.
110
111       There is a module named
112       Locale::TextDomain::OO::Util::JoinSplitLexiconKeys.  That helps you to
113       build the lexicon keys.  Do not join the keys by yourself, it can break
114       in future versions.  Use the category, domain, language and project
115       part to describe your lexicon.  category, domain and language you can
116       use during translation.  The only reason for project is to separate
117       your different lexicons.
118
119   How to use the lexicon?
120       The lexicons or all lexicons are stored in memory.  The idea to build a
121       combined lexicon is overwriting hash values by same key.  So read and
122       overwrite common stuff with specials.  In an example case the region
123       file en-gb.mo contains only the differences.  The common file en.mo
124       contains all messages.  So it is possible to create full lexicons for
125       any language and region.  What you have to describe is: Where are the
126       files - directories.  Pick up the common file en.mo as en.  Pick up the
127       common file en.mo and the special en-gb.mo as en-gb.
128
129   Do not follow the dead end of Locale::Maketext!
130       But it is allowed to use that writing for backward compatiblity.
131
132       What is the problem of Maketext?
133
134       ·   Locale::Maketext allows 2 plural forms (and zero) only.  This is
135           changeable, but the developer has to control the plural forms.  He
136           is not an omniscient translator.
137
138           Gettext allows as much as needed plural forms at destination
139           language.
140
141       ·   Maketext has a plural formula as placeholder in strings to
142           translate.  Gettext has fully readable strings with simple
143           placeholders.  Then a very good automatic translation is possible
144           and this module helps you.
145
146           (Some projects have keywords instead of English language in code.
147           This module helps you to write readable, uncrypic code.
148           Programmers optimisation is a very bad idea for translations.
149           Never split a sentence.)
150
151       ·   'quant' inside a phrase is the end of the automatic translation
152           because quant is an 'or'-construct.
153
154               begin of phrase [quant,_1,singular,plural,zero] end of phrase
155
156           Gettext used full qualified sentences.
157
158       ·   The plural form is allowed after a number, followed by a
159           whitespace, not a non-breaking whitespace.
160
161               1 book
162               2 books
163
164           A plural form can not be before a number.
165
166               It is 1 book.
167               These are 2 books.
168
169           Gettext is using full qualified sentences.
170
171       ·   There is no plural form without a number in the phrase.
172
173               I like this book.
174               I like these books.
175
176           Gettext used an extra count to select the plural form.
177           Placeholders are placeholders not combined things.
178
179       ·   Placeholders are numbered serially.  It is difficult to translate
180           this because the sense of the phrase could be lost.
181
182               Still [_1] [_2] to [_3].
183
184               Still 5 hours to midnight.
185               Still 15 days to Olympics.
186
187           Locale::TextDomain::OO used named placeholders like
188
189               Still {count :num} {datetime unit} to {event}.
190
191       ·   But there are lots of modules around Locale::Maketext.
192
193       This is the reason for another module to have:
194
195       ·   Endless (real: up to 6) plural forms controlled by the translator
196           and not by the developer.
197
198       ·   Named placeholders.
199
200   More information
201       Run the examples of this distribution (folder example).
202
203   Overview
204        Application calls           Application calls         Application calls
205        Gettext methods             Gettext and               Maketext methods
206        (Hint: select this)         Maketext methods              |
207                |                   (Hint: Maketext already       |
208                |                   exists in your project)       |
209                |                               |                 |
210                v                               v                 v
211        .----------------------------------------------------------------------.
212        | Locale::TextDomain::OO                                               |
213        | with plugin LanguageOfLanguages                                      |
214        | with plugins Locale::TextDomain::OO::Plugin::Expand::...             |
215        |----------------------------------------------------------------------|
216        | Gettext                           |\       /| Maketext               |
217        | Gettext::DomainAndCategory        | |     | |                        |
218        | Gettext::Loc (Hint: select this)  | |     | | Maketext::Loc          |
219        | Gettext::Loc::DomainAndCategory   | > and < | (Hint: select this)    |
220        | Gettext::Named (experimental)     | |     | |                        |
221        | BabelFish::Loc                    | |     | | Maketext::Localise     |
222        | BabelFish::Loc::DomainAndCategory |/       \| Maketext::Localize     |
223        `----------------------------------------------------------------------'
224                                   ^
225                                   |
226        .--------------------------'-----------------.
227        | Locale::TextDomain::OO::Singleton::Lexicon |-------------------------.
228        `--------------------------------------------'                         |
229                                   ^                                           |
230                                   |                                           |
231        .--------------------------'-------------------------------.           |
232        | build lexicon using Locale::TextDomain::OO::Lexicon::... |           |
233        |----------------------------------------------------------|           |
234        |           Hash              |   File::PO     | File::MO  |           |
235        `----------------------------------------------------------'           |
236              ^               ^               ^                  ^             |
237              |               |               |                  |             |
238        .-----'-----.    _____|_____    .-----'----.       .-----'----.        |
239        | Perl      |   /_ _ _ _ _ _\   | po files |-.     | mo files |-.      |
240        | data      |   |           |   `----------' |-.   `----------' |-.    |
241        | structure |   | Database  |     `----------' |     `----------' |    |
242        `-----------'   `-----------'       `----------'       `----------'    |
243              ^                               ^   ^              ^             |
244              |                               |   |              |             |
245              |   .---------------------------'   |              |             |
246         _____|___|_____                          |              |             |
247        /_ _ _ _ _ _ _ _\   .----------------------------------------------.   |
248        | Autotranslate |   | build using PO/MO                            |   |
249        | Cache         |   | Locale::TextDomain::OO::Extract              |   |
250        | CacheDatabase |   | and Locale::TextDomain::OO::Extract::Process |   |
251        `---------------'   `----------------------------------------------'   |
252                                                                               |
253                                         .-------------------------------------'
254                                         v
255        .---------------------------------------------------------------------.
256        | build JSON lexicon using Locale::TextDomain::OO::Lexicon::StoreJSON |
257        |---------------------------------------------------------------------|
258        |       to_json      |       to_javascript       |      to_html       |
259        `---------------------------------------------------------------------'
260                                         |
261                                         v
262                     .---------------------------------------.
263                     | var localeTextDomainOOLexicon = json; |
264                     `---------------------------------------'
265                                         ^
266                                         |
267        .--------------------------------'-------------------------------------------------.
268        | requires:                                                                        |
269        | - http://jquery.com/                                                             |
270        | - javascript/Locale/TextDomain/OO/Util/Constants.js                              |
271        | - javascript/Locale/TextDomain/OO/Util/JoinSplitLexiconKeys.js                   |
272        | - javascript/Locale/Utils/PlaceholderNamed.js                                    |
273        |                                                                                  |
274        | implemented:                                                                     |
275        | javascript/Locale/TextDomain/OO.js                                               |
276        | javascript/Locale/TextDomain/OO/Plugin/Expand/BabelFish.js (under development)   |
277        | javascript/Locale/TextDomain/OO/Plugin/Expand/Gettext.js                         |
278        | javascript/Locale/TextDomain/OO/Plugin/Expand/Gettext/DomainAndCategory.js       |
279        | javascript/Locale/TextDomain/OO/Plugin/Expand/Gettext/Loc.js (Hint: select this) |
280        | javascript/Locale/TextDomain/OO/Plugin/Expand/Gettext/Loc/DomainAndCategory.js   |
281        |                                                                                  |
282        | not implemented:                                                                 |
283        | javascript/Locale/TextDomain/OO/Expand/Maketext.js                               |
284        | javascript/Locale/TextDomain/OO/Expand/Maketext/Loc.js                           |
285        | javascript/Locale/TextDomain/OO/Expand/Maketext/Localise.js                      |
286        | javascript/Locale/TextDomain/OO/Expand/Maketext/Localize.js                      |
287        |                                                                                  |
288        | Example:                                                                         |
289        | javascript/Example.html                                                          |
290        `----------------------------------------------------------------------------------'
291                ^                     ^                            ^
292                |                     |                            |
293        JavaScript calls      JavaScript calls             JavaScript calls
294        Gettext methods       Gettext and                  Maketext methods
295        (Hint: select this)   Maketext methods             (Maketext not implemented)
296                              (Maketext not implemented)
297

SYNOPSIS

299           require Locale::TextDomain::OO;
300           use Log::Any qw($log);
301           my $loc = Locale::TextDomain::OO->new(
302               # all parameters are optional
303               plugins  => [ qw(
304                   Expand::Gettext::Loc
305                   +My::Special::Plugin
306               ) ],
307               language => 'de',          # default is i-default
308               category => 'LC_MESSAGES', # default is q{}
309               domain   => 'MyDomain',    # default is q{}
310               project  => 'MyProject',   # default is undef
311               filter   => sub {
312                   my ($self, $translation_ref) = @_;
313                   # encode if needed
314                   # run a formatter if needed, e.g.
315                   ${$translation_ref} =~ s{__ ( .+? ) __}{<b>$1</b>}xmsg;
316                   return;
317               },
318               logger   => sub {
319                   my ($message, $arg_ref) = @_;
320                   my $type = $arg_ref->{type}; # debug or warn
321                   $log->$type($message);
322                   return;
323               },
324           );
325
326       This configuration would be use Lexicon
327       "de:LC_MESSAGES:MyDomain::MyProject".  That lexicon should be filled
328       with data.
329
330   as singleton
331       Instead of method new call method instance to get a singleton.
332
333           my $instance = Locale::TextDomain::OO->instance(
334               # Same parameters like new,
335               # Initialization on first call only.
336           );
337           $same_instance = Locale::TextDomain::OO->instance;
338
339   Attributes handled e.g. with plugin Expand::Gettext::Loc
340       This plugin can handle named placeholders like "{name}".  For numeric
341       placeholders add attribute ":num".  That allows easier automatic
342       translation and to localize numbers.  E.g. write "{books :numf}" to
343       msgid, msgid_plural.
344
345       Grammar rules for string placeholders are able to handle affixes.  The
346       translation office can add attributes, e.g. "{town :accusative}" to
347       msgstr, msgstr[n].
348
349       Add the modifier code like that to handle that attributes.
350
351           $loc->expand_gettext->modifier_code(
352               sub {
353                   my ( $value, $attribute ) = @_;
354                   if ( $loc->language eq 'ru' ) {
355                       if ( $attribute eq 'accusative' ) {
356                          ...
357                       }
358                   }
359                   elsif ( $loc->language eq 'de' }xms ) {
360                       if ( $attribute eq 'numf' ) {
361                           ...
362                           $value =~ tr{.,}{,.};
363                       }
364                   }
365                   return $value;
366               },
367           );
368
369   Attributes handled with plugin Expand::Gettext
370       Like before but a little difference. Instead of
371
372           $loc->expand_gettext_loc->modifier_code(...
373
374       write
375
376           $loc->expand_gettext->modifier_code(...
377
378   Localize numbers with plugin Expand::Maketext
379       Add the code to localize numbers.
380
381           $loc->expand_maketext->formatter_code(
382               sub {
383                   my $value = shift;
384                   if ( $loc->language eq 'de' ) {
385                       ...
386                       $value =~ tr{.,}{,.};
387                   }
388                   return $value;
389               },
390           );
391

JAVASCRIPT

393       How to use the JavaScript framework see
394       Locale::TextDomain::OO::JavaScript.
395

SUBROUTINES/METHODS

397   method new
398       see SYNOPSIS
399
400       It is not possible to call method new with different plugins parameter.
401       The first call will load the plugins.  Later call set parameter plugins
402       equal or do not set.
403
404   method instance
405       When using the singleton mechanism, the object need not be transported
406       through all the subroutines.
407
408       Instead of
409
410           my $loc = Locale::TextDomain::OO->new(...);
411           ...
412           $loc->any_method(...);
413
414       write
415
416           Locale::TextDomain::OO->instance(...);
417           ...
418           my $loc = Locale::TextDomain::OO->instance;
419           $loc->any_method(...);
420
421       In case of webserver child or similar, set the language for every
422       request not as parameter of the first instance call.
423
424   method language
425       Set the language an prepare the translation.  You know exactly how to
426       set.  This module is stupid.
427
428           $loc->language( $language );
429
430       Get back
431
432           $language = $loc->language;
433
434   method category
435       You are able to ignore or set the category.  That depends on your
436       project.
437
438           $loc->category($category || q{} );
439           $category = $loc->category;
440
441   method domain
442       You are able to ignore or set the domain.  That depends on your
443       project.
444
445           $loc->domain($domain || q{} );
446           $domain = $loc->domain;
447
448   method filter
449       You are allowed to run code after each translation.
450
451           $loc->filter( sub {
452               my ( $self, $translation_ref ) = @_;
453
454               # $self is $loc
455               # manipulate ${$translation_ref}
456               # do not undef ${$translation_ref}
457
458               return;
459           } );
460
461       Switch off the filter
462
463           $loc->filter(undef);
464
465   method logger
466       Set the logger
467
468           $loc->logger(
469               sub {
470                   my ($message, $arg_ref) = @_;
471                   my $type = $arg_ref->{type};
472                   $log->$type($message);
473                   return;
474               },
475           );
476
477       $arg_ref contains
478
479           object => $loc, # the object itself
480           type   => 'debug', # or 'warn'
481           event  => 'language,selection', # 'language,selection,fallback'
482                                           # or 'translation,fallback'
483
484   method translate
485       Do never call that method in your project.  This method was called from
486       expand plugins only.
487
488           $translation
489               = $self->translate($msgctxt, $msgid, $msgid_plural, $count, $is_n);
490
491   method run_filter
492       Do never call that method in your project.  This method was called from
493       expand plugins only.
494
495           $self->filter(\$translation);
496

EXAMPLE

498       Inside of this distribution is a directory named example.  Read the
499       file README there.  Then run the *.pl files.
500

DIAGNOSTICS

502       confess
503

CONFIGURATION AND ENVIRONMENT

505       none
506

DEPENDENCIES

508       Locale::TextDomain::OO::Translator
509

INCOMPATIBILITIES

511       not known
512

BUGS AND LIMITATIONS

514       In the Gettext manual you can read at "15.5.18.9 Bugs, Pitfalls, And
515       Things That Do Not Work" something that is not working with Perl.  The
516       examples there are rewritten and explained here.
517
518   string interpolation and joined strings
519           print <<"EOT";
520               $loc->loc_(
521                   'The dot operator'
522                   . ' does not work'
523                   . ' here!'
524               )
525               Likewise, you cannot @{[ $loc->loc_('interpolate function calls') ]}
526               inside quoted strings or quote-like expressions.
527           EOT
528
529       The fist call can not work.  Methods are not callable in interpolated
530       strings/"here documents".  The . operator is normally not implemented
531       at the extractor.  The first parameter of method loc_ must be a
532       constant.
533
534       There is no problem for the second call because the extractor extracts
535       the Perl file as text and did not parse the code.
536
537   Regex eval
538       This example is no problem here, because the file is extracted as text.
539
540           s/<!--START_OF_WEEK-->/$loc->loc_('Sunday')/e;
541
542   named placeholders
543       Method loc_ is an alias for method loc_x.  But {OPTIONS} is not a
544       placeholder because key "OPTIONS" is not in parameters.
545
546           die $loc->loc_("usage: $0 {OPTIONS} FILENAME...\n");
547
548           die $loc->loc_x("usage: {program} {OPTIONS} FILENAME...\n", program => $0);
549

SEE ALSO

551       Locale::TextDoamin
552
553       Locale::Maketext
554
555       <http://www.gnu.org/software/gettext/manual/gettext.html>
556
557       <http://en.wikipedia.org/wiki/Gettext>
558
559       <http://translate.sourceforge.net/wiki/l10n/pluralforms>
560
561       <http://rassie.org/archives/247> The choice of the right module for the
562       translation.
563

AUTHOR

565       Steffen Winkler
566
568       Copyright (c) 2009 - 2019, Steffen Winkler "<steffenw at cpan.org>".
569       All rights reserved.
570
571       This module is free software; you can redistribute it and/or modify it
572       under the same terms as Perl itself.
573
574
575
576perl v5.30.1                      2020-01-30         Locale::TextDomain::OO(3)
Impressum