NAME

Locale::TextDomain::OO - Perl OO Interface to Uniforum Message Translation

$Id: OO.pm 150 2009-12-05 21:02:30Z steffenw $

$HeadURL: https://perl-gettext-oo.svn.sourceforge.net/svnroot/perl-gettext-oo/trunk/lib/Locale/TextDomain/OO.pm $

VERSION

0.02

DESCRIPTION

This module provides a high-level interface to Perl message translation.

Why a new module?

This module is very similar to Locale::TextDomain.

The most important problem of Locale::TextDomain is the functional interface and consequently the use of the caller to figure out the text domain. That is why is not possible to wrap Locale::TextDomain functions into a new package.

Locale::TextDomain::OO has a flexible object oriented interface.

Why to write a wrapper?

Locale::TextDomain depends on Locale::Messages and Locale::Messages depends on gettext mo-files. This is a very good idea to do this. It is a standard.

But if the data are not saved in mo-files and the project is not a new project, how to bind a database or anything else to the Locale::TextDomain API?

Now it is possible to change the source of data.

Why to inherit?

In case of change a project from Locale::Maketext or Locale::Maketext::Simple use an extended API Locale::TextDomain::OO::Maketext.

Why bind late to a more simple functional interface?

Locale::TextDomain::OO::FunctionalInterface is a wrapper to have functions like Locale::TextDomain for the application interface and all the benefit from the binded object too.

Do not follow the dead end of Locale::Maketext!

What is the problem of?

  • Locale::Maketext allows 2 plural forms (and zero) only. This is changable, but the developer has to control the plural forms. He is not an omniscient translator.

  • 'quant' inside a phrase is the end of the automatic translation because quant is an 'or'-construct.

    begin of phrase [quant,_1,singular,plural,zero] end of phrase
  • The plural form is allowed after a number, followed by a whitespace, not a non-breaking whitespace.

    1 book
    2 books

    A plural form can not be before a number.

    It is 1 book.
    These are 2 books.
  • There is no plural form without a nummber in the phrase.

    I like this book.
    I like these books.
  • Placeholders are numbered serially. It is difficult to translate this, because the sense of the phrase could be lost.

    [_1] is a [_2] in [_3].
    
    Erlangen is a town in Bavaria.
  • But there are a lot of modules around Locale::Maketext.

This is the reason for another module to have:

What is the difference?

As default this module calls the subroutines like module Locale::Messages.

This behaviour is changeable. Choose a functional or object oriented module. Locale::Messages is an functional module. Locale::TextDomain::OO::MessagesStruct is an object oriented module.

Locale::TextDomain::OO::MessagesStruct implements the idea to read the full data into a data structure for fast access.

More informations

Read the documentation of Locale::TextDoamin to learn more about the translation subroutines.

Run the examples of this distribution (folder example).

Overview

     Application calls           Application calls         Application calls
      TextDomain subs     .------ TextDomain subs           method maketext
         (the goal)       |     and Maketext methods -.     (the beginning)
             |            |       (the changeover)    |                |
             |            |                           |                |
             |            |                           '------------.   |
             |            v                                        |   |
             |   .---------------------------------------------.   |   |
             |   |             functional interface            |   |   |
             |   |---------------------------------------------|   |   |
             |   | Locale::TextDomain::OO::FunctionalInterface |   |   |
             |   |---------------------------------------------|   |   |
             |   |                 calls methods               |   |   |
             |   `---------------------------------------------'   |   |
             |                          |                          |   |
             |                          v                          v   v
             |            .------------------------------------------------.
             |            |               OO interface like                |
             |            |            Locale::Maketext::Simple            |
             |            |                      and (!)                   |
             |            |             Locale::TextDomain::OO             |
             |            |------------------------------------------------|
             |            |        Locale::TextDomain::OO::Maketext        |
             |            `------------------------------------------------'
             |                    |
             v                    v
         .----------------------------.
         |       interface like       |
         |     Locale::TextDomain     |
         |----------------------------|
         |   Locale::TextDomain::OO   |
         `----------------------------'
             |                    |
             v                    v
.-------------------------.   .----------------------------------------.
| Locale::gettext_(xs|pp) |   | Locale::TextDomain::OO::MessagesStruct |
|      (the default)      |   |            (a possibility)             |
`-------------------------'   `----------------------------------------'
          |                                  |
          |                                  v
          |                        .-------------------.
          |                        |    data struct    |
          |                        |-------------------|
          |                        |  |                |
          |                        |  +--[text domain] |
          |                        |     |             |
          |                        |     `--[...]      |
          |                        `-------------------'
          |                          ^               ^
          |                          |               |
          |      .------------------------.          |
          |      |       build using      |   .-------------.
          |      |   po extrction tools   |   | build using |
          |      |      like DBD::PO      |   |     DBI     |
          |      | or DBD::PO::Locale::PO |   `-------------'
          |      `------------------------'          ^
          |                   ^                      |
          v                   |                 _____|_____
   .----------.         .----------.           /_ _ _ _ _ _\
   | mo-files |-.       | po-files |-.         |           |
   `----------' |       `----------' |         | Database  |
     `----------'         `----------'         `-----------'
          ^                   ^                      ^
          |                   |                      |
     build using         build using            existing data
    gettext tools       gettext tools

SYNOPSIS

require Locale::TextDomain::OO;

SUBROUTINES/METHODS

method new

optional parameter text_domain

Set the default text domian __PACKAGE__.

my $loc = Locale::TextDoamin::OO->new(
    ...
);

Set the text domain.

my $loc = Locale::TextDoamin::OO->new(
    ...
    text_domain => 'exapmle',
    ...
);

optional parameter search_dirs

Set the search dirs.

my $loc = Locale::TextDoamin::OO->new(
    ...
    search_dirs => \@local_dirs,
    ...
);

The default for search_dirs is:

my @locale_dirs = map {
    -d "$_/LocaleData"
    ? "$_/LocaleData"
    : ();
} (
    @INC,
    qw(/usr/share/locale /usr/local/share/locale),
);

optional parameter gettext_package or alternative gettext_object

Note, that the default of gettest_package is Locale::gettext_xs or Locale::gettext_pp. This package has to implement the subroutines 'dgettext', 'dngettext', 'dpgettext', 'dnpgettext' and can implement the subroutine 'bindtextdomain'.

my $loc = Locale::TextDoamin::OO->new(
    gettext_package => 'Package::With::Subroutines',
    ...
);

Or alternative the package which has to implement the methods 'dgettext', 'dngettext', 'dpgettext', 'dnpgettext'.

my $loc = Locale::TextDoamin::OO->new(
    gettext_object => Locale::TextDomain::OO::MessagesStruct->new(\my %struct),
    ...
);

optional parameter language_detect

Describe as code, how to detect the language. This example code describes the default in list context.

my $loc = Locale::TextDoamin::OO->new(
    ...
    language_detect => sub {
       my @languages_want = I18N::LangTags::Detect::detect();
       my @languages_all  = implicate_supers(@languages_want);
       return @languages_all, panic_languages(@languages_all);
    },
    ...
);

Read I18N::LangTags, panic_languages for more informations.

method get_default_language_detect

This method returns a code reference. Run this code reference to find the needed language from the environment and all the fallbacks.

get the code reference

my $code_ref = Locale::TextDomain::OO->get_default_language_detect();

or

my $code_ref = $loc->get_default_language_detect();

run the code in list context

@langauges = $code_ref->();

or in scalar context typical for

local $ENV{LANGUAGE} = $code_ref->(); # result joined by :

method get_file_path

my $file_suffix = '.mo';
my $file_path   = $loc->get_file_path($text_domain, $file_suffix);

If a file based database system not exists, create an extra file system. Write down for which language and which text domain a database exists. Instead of an "$text_domain$suffix" database file create some empty dummy files.

If possible, extract this informations automaticly from the database.

Than the method get_file_path checks the wanted languages and matches the existing langauges.

my ($dir, $language) = $loc->get_file_path($text_domain, $file_suffix);

Another way to use this module with a none file based database system is to implement the language selection self.

object or class method get_nplurals

How many plurals has the translation? This is one-time interesting to read the translation data.

$nplurals = $self->get_nplurals(
    'nplurals=2; plural=n != 1;' # look at po-/mo-file header
);

or

$nplurals = Locale::Text::Domain::OO->get_nplurals(
    'nplurals=2; plural=n != 1;' # look at po-/mo-file header
);

object or class method get_function_ref_plural

Which plural form sould be used? The code runs during every plural tranlation.

$code_ref = $self->get_function_ref_plural(
    'nplurals=2; plural=n != 1;' # look at po-/mo-file header
);

or

$code_ref = Locale::Text::Domain::OO->get_function_ref_plural(
    'nplurals=2; plural=n != 1;' # look at po-/mo-file header
);

Translating methods

How to build the method name?

Use __ and append this with 'n', 'p' and/or 'x' in alphabetic order.

.----------------------------------------------------------------.
| Snippet | Description                                          |
|---------+------------------------------------------------------|
| __      | Special marked for extraction.                       |
| x       | Last parameters are the hash for named placeholders. |
| n       | Using plural forms.                                  |
| p       | Context is the first parameter.                      |
'----------------------------------------------------------------'

__ Translate only

print $loc->__(
    'Hello World!',
);

__x Named placeholders

print $loc->__x(
    'Hello {name}!',
    name => 'Steffen',
);

__n Plural

print $loc->__n(
    'one file read',
    'a lot of files read',
    $num_files,
);

__nx Plural and named placeholders

print $loc->__nx(
    'one file read',
    '{num} files read',
    $num_files,
    num => $num_files,
);

The sub __xn is the same like sub __nx at Locale::TextDomain.

Method __xn is not implemented because it is the same like method __nx.

__p Context

print $loc->__p (
    'time',
    'to',
);

print $loc->__p (
    'destination',
    'to',
);

__px Context and named placeholders

print $loc->__px (
    'destination',
    'from {town_from} to {town_to}',
    town_from => 'Chemnitz',
    town_to   => 'Erlangen',
);

__np Context and plural

print $loc->__np (
    'maskulin',
    'Dear friend',
    'Dear friends',
    $friends,
);

__npx Context, plural and named placeholders

print $loc->__npx(
    'maskulin',
    'Mr. {name} has {num} book.',
    'Mr. {name} has {num} books.',
    $books,
    name => $name,
);

Methods to mark the translation for extraction only

How to bild the method name?

Use N__ and append this with 'n', 'p' and/or 'x' in alphabetic order.

.----------------------------------------------------------------.
| Snippet | Description                                          |
|---------+------------------------------------------------------|
| N__     | Special marked for extraction.                       |
| x       | Last parameters are the hash for named placeholders. |
| n       | Using plural forms.                                  |
| p       | Context is the first parameter.                      |
'----------------------------------------------------------------'

N__, N__x, N__n, N__nx, N__p, N__px, N__np, N__npx

The extractor looks for __('...' and has no problem with $loc-N__('...')>.

This is the idea of the N-Methods.

$loc->N__('...');

EXAMPLE

Inside of this Distribution is a directory named example. Read the file README there. Then run the *.pl files.

DIAGNOSTICS

Error message in case of unknown parameters.

Unknown parameter: ...

Error message during load of the implementation package.

Can't locate ...

Error message during load of the default implementation package.

gettext_xs_version ... is to old.

Error message at calculation plural forms.

Plural-Forms are not defined

Code of Plural-Forms ... is not safe, ...

Code ... is not safe, ...

CONFIGURATION AND ENVIRONMENT

none

DEPENDENCIES

Carp

Cwd

English

I18N::LangTags::Detect

I18N::LangTags

Safe

dynamic require

Locale::gettext_xs

Locale::gettext_pp

INCOMPATIBILITIES

not known

BUGS AND LIMITATIONS

none

SEE ALSO

Locale::TextDoamin

Locale::Messages

http://www.gnu.org/software/gettext/manual/gettext.html

http://en.wikipedia.org/wiki/Gettext

http://translate.sourceforge.net/wiki/l10n/pluralforms

http://rassie.org/archives/247 The choice of the right module for the translation.

AUTHOR

Steffen Winkler

LICENSE AND COPYRIGHT

Copyright (c) 2009, Steffen Winkler <steffenw at cpan.org>. All rights reserved.

This module is free software; you can redistribute it and/or modify it under the same terms as Perl itself.