Text::PO::Gettext - A GNU Gettext implementation
use Text::PO::Gettext; my $po = Text::PO::Gettext->new || die( Text::PO::Gettext->error, "\n" ); my $po = Text::PO::Gettext->new({ category => 'LC_MESSAGES', debug => 3, domain => "com.example.api", locale => 'ja-JP', path => "/home/joe/locale", use_json => 1, }) || die( Text::PO::Gettext->error, "\n" );
v0.3.1
This module is used to access the data in either po, mo or json file and provides various methods to access those data.
po
mo
json
The conventional way to use GNU gettext is to set the global environment variable LANGUAGE (not LANG by the way. GNU gettext only uses LANGUAGE), then set the "setlocale" in POSIX to the language such as:
LANGUAGE
LANG
use Locale::gettext; use POSIX (); POSIX::setlocale( &POSIX::LC_ALL, 'ja_JP' ); my $d = Locale::gettext->domain( 'com.example.api' );
And then in your application, you would write a statement like:
print $d->get( 'Hello!' );
Or possibly using direct access to the C function:
use Locale::gettext; use POSIX (); POSIX::setlocale( &POSIX::LC_ALL, 'ja_JP' ); textdomain( 'com.example.api' );
And then:
print gettext( 'Hello!' );
See Locale::gettext for more on this.
This works fine, but has the inconvenience that it uses the global LANGUAGE environment variable and makes it less than subpar as to the necessary flexibility when using multiple domains and flipping back and forth among locales.
Thus comes a more straightforward object-oriented interface offered by this module.
You instantiate an object, passing the domain, the locale and the filesystem path where the locale data resides.
my $po = Text::PO::Gettext->new( domain => 'com.example.api', locale => 'ja_JP', path => '/some/where/locale' ); print $po->gettext( 'Hello!' );
This will load into memory the locale data whether they are stored as .po, .mo or even .json file, thus making calls to "gettext" super fast since they are in memory.
.po
.mo
.json
More than one locale can be loaded, each with its own Text::PO::Gettext object
This distribution comes with its Javascript library equivalent. See the share folder alone with its own test units.
share
Also, there is a script in scripts that can be used to transcode .po or .mo files into json format and vice versa.
scripts
Still, it is better to convert the original .po files to json using the po.pl utility that comes in this Text::PO distribution since it would allow the standalone JavaScript library to read json-based po files. For example:
po.pl
./po.pl --as-json --output /home/joe/www/locale/ja_JP/LC_MESSAGES/com.example.api.json ./ja_JP.po
This api supports locale that use hyphens or underscore in them such as en-GB or en_GB. You can use either, it will be converted internally.
en-GB
en_GB
Takes the following options and returns a Gettext object.
category
If category is defined, such as LC_MESSAGES (by default), it will be used when building the path.
LC_MESSAGES
Other possible category values are: LC_CTYPE, LC_NUMERIC, LC_TIME, LC_COLLATE, LC_MONETARY
LC_CTYPE
LC_NUMERIC
LC_TIME
LC_COLLATE
LC_MONETARY
See GNU documentation for more information and "LOCALE CATEGORIES" in perllocale
On the web, using the path is questionable.
See the GNU documentation for more information on this.
domain
The portable object domain, such as com.example.api
com.example.api
locale
The locale, such as ja_JP, or en, or it could even contain a dash instead of an underscore, such as en-GB. Internally, though, this will be converted to underscore.
ja_JP
en
path
The uri path where the gettext localised data are.
This is used to form a path along with the locale string. For example, with a locale of ja_JP and a domain of com/example.api, if the path were /locale, the data po json data would be fetched from /locale/ ja_JP/LC_MESSAGES/com.example.api.json
com/example.api
/locale
/locale/ ja_JP/LC_MESSAGES/com.example.api.json
This takes a locale, a message id and its localised version and it will add this to the current dictionary for the current domain.
$po->addItem( 'ja_JP', 'Hello!' => "今日は!" );
The category to use. This defaults to LC_MESSAGES, but if you prefer you can nix its use by making it undefined, or empty:
my $po = Text::PO::Gettext->new( category => '', domain => 'com.example.api', locale => 'ja_JP', path => '/some/where/locale' ); # Setting category to empty string will have the module get the po data # under C</some/where/locale/ja_JP/com.example.api.json> for example. print $po->gettext( 'Hello!' );
Returns a string containing the value of the charset encoding as defined in the Content-Type header.
Content-Type
$po->charset()
Returns a string containing the value of the header Content-Encoding.
Content-Encoding
$po->contentEncoding();
Returns a string containing the value of the header Content-Type.
$po->contentType(); # text/plain; charset=utf-8
Return the current globally used locale. This is the value found in environment variables LANGUAGE or LANG. Note that GNU gettext only recognises LANGUAGE
and thus, this is different from the locale set in the Gettext class object using </setLocale> or upon class object instantiation.
Takes a domain and a message id and returns the equivalent localised string if any, otherwise the original message id.
$po->dgettext( 'com.example.auth', 'Please enter your e-mail address' ); # Assuming the locale currently set is ja_JP, this would return: # 電子メールアドレスをご入力下さい。
Same as "ngettext", but takes also a domain as first argument. For example:
$po->ngettext( 'com.example.auth', '%d comment awaiting moderation', '%d comments awaiting moderation', 12 ); # Assuming the locale is ru_RU, this would return: # %d комментариев ожидают проверки
Note that as of version v0.5.0, this returns a Text::PO::String, which is lightweight and stringifies automatically. It provides the benefit of tagging the string with the locale attached to it.
v0.5.0
Text::PO::String
Thus, in the example above, the resulting Text::PO::String would have its method locale value set to ru_RU, and you could do:
ru_RU
my $localised = $po->ngettext( 'com.example.auth', '%d comment awaiting moderation', '%d comments awaiting moderation', 12 ); say "Locale for this string is: ", $localised->locale;
If no locale string was found, locale would be undefined.
Sets or gets the domain.
$po->domain( 'com.example.api' );
By doing so, this will call "textdomain" and load the associated data from file, if any are found.
Provided with a locale, and this returns true if the locale exists in the current domain, or false otherwise.
Given an original string (msgid), this returns an array of <span> html element each for one language and its related localised content. For example:
my $array = $po->fetchLocale( "Hello!" ); # Returns: <span lang="de-DE">Grüß Gott!</span> <span lang="fr-FR">Salut !</span> <span lang="ja-JP">今日は!</span> <span lang="ko-KR">안녕하세요!</span>
This is designed to be added to the html, and based on lang attribute of the html tag, and using the following css trick, this will automatically display the right localised data:
lang
html
[lang=de-DE] [lang=en-GB], [lang=de-DE] [lang=fr-FR], [lang=de-DE] [lang=ja-JP], [lang=de-DE] [lang=ko-KR], [lang=en-GB] [lang=de-DE], [lang=en-GB] [lang=fr-FR], [lang=en-GB] [lang=ja-JP], [lang=en-GB] [lang=ko-KR], [lang=fr-FR] [lang=de-DE], [lang=fr-FR] [lang=en-GB], [lang=fr-FR] [lang=ja-JP], [lang=fr-FR] [lang=ko-KR], [lang=ja-JP] [lang=de-DE], [lang=ja-JP] [lang=en-GB] [lang=ja-JP] [lang=fr-FR], [lang=ja-JP] [lang=ko-KR] { display: none !important; visibility: hidden !important; }
This takes no argument and will check for the environment variables TEXTDOMAINDIR. If found, it will use this in lieu of the path option used during object instantiation.
TEXTDOMAINDIR
It returns the value found. This is just a helper method and does not affect the value of the path property set during object instantiation.
Returns an array reference containing the 7 days of the week in their long representation.
my $ref = $po->getDaysLong(); # Assuming the locale is fr_FR, this would yield print $ref->[0], "\n"; # dim.
Returns an array reference containing the 7 days of the week in their short representation.
my $ref = $po->getDaysShort(); # Assuming the locale is fr_FR, this would yield print $ref->[0], "\n"; # dimanche
This takes an optional hash of parameters and return the global hash dictionary used by this class to store the localised data.
# Will use the default domain as set in po.domain my $data = $po->getDomainHash(); # Explicitly specify another domain my $data = $po->getDomainHash( domain => "net.example.api" ); # Specify a domain and a locale my $l10n = $po->getDomainHash( domain => "com.example.api", locale => "ja_JP" );
Possible options are:
domain The domain for the data, such as com.example.api
locale The locale to return the associated dictionary.
Contrary to its JavaScript equivalent, this takes no parameter. It returns the value of the environment variable TEXTLOCALEDIR if found.
TEXTLOCALEDIR
This is used internally during object instantiation when the path parameter is not provided.
Provided with a locale, such as ja_JP and this will return the dictionary for the current domain and the given locale.
Returns the locale set for the current object, such as fr_FR or ja_JP
fr_FR
Locale returned are always formatted for the server-side, which means having an underscore rather than an hyphen like in the web environment.
Provided with a msgid (i.e. an original text) and this will call "fetchLocale" and return those span tags as a string containing their respective localised content, joined by a new line
msgid
span
This is similar to "getLocale", except that it does a sprintf internally before returning the resulting value.
Returns an array of the meta field names used.
Provided with a meta field name and this returns its corresponding value.
Returns an array reference containing the 12 months in their long representation.
my $ref = $po->getMonthsLong(); # Assuming the locale is fr_FR, this would yield print $ref->[0], "\n"; # janvier
Returns an array reference containing the 12 months in their short representation.
my $ref = $po->getMonthsShort(); # Assuming the locale is fr_FR, this would yield print $ref->[0], "\n"; # janv.
Returns an hash reference containing the following properties:
my $ref = $po->getNumericDict();
currency string
currency
Contains the usual currency symbol, such as €, or $, or ¥
€
$
¥
decimal string
decimal
Contains the character used to separate decimal. In English speaking countries, this would typically be a dot.
int_currency string
int_currency
Contains the 3-letters international currency symbol, such as USD, or EUR or JPY
USD
EUR
JPY
negative_sign string
negative_sign
Contains the negative sign used for negative number
precision integer
precision
An integer whose value represents the fractional precision allowed for monetary context.
For example, in Japanese, this value would be 0 while in many other countries, it would be 2.
thousand string
thousand
Contains the character used to group and separate thousands.
For example, in France, it would be a space, such as :
1 000 000,00
While in English countries, including Japan, it would be a comma :
1,000,000.00
Returns the full hash reference returned by "lconv" in POSIX. It contains the following properties:
Here the values shown as example are for the locale en_US
en_US
currency_symbol string
currency_symbol
The local currency symbol: $
decimal_point string
decimal_point
The decimal point character, except for currency values, cannot be an empty string: .
.
frac_digits integer
frac_digits
The number of digits after the decimal point in the local style for currency value: 2
grouping
The sizes of the groups of digits, except for currency values. unpack( "C*", $grouping ) will give the number
int_curr_symbol string
int_curr_symbol
The standardized international currency symbol: USD
int_frac_digits integer
int_frac_digits
The number of digits after the decimal point in an international-style currency value: 2
int_n_cs_precedes integer
int_n_cs_precedes
Same as n_cs_precedes, but for internationally formatted monetary quantities: 1
int_n_sep_by_space integer
int_n_sep_by_space
Same as n_sep_by_space, but for internationally formatted monetary quantities: 1
int_n_sign_posn integer
int_n_sign_posn
Same as n_sign_posn, but for internationally formatted monetary quantities: 1
int_p_cs_precedes integer
int_p_cs_precedes
Same as p_cs_precedes, but for internationally formatted monetary quantities: 1
int_p_sep_by_space integer
int_p_sep_by_space
Same as p_sep_by_space, but for internationally formatted monetary quantities: 1
int_p_sign_posn integer
int_p_sign_posn
Same as p_sign_posn, but for internationally formatted monetary quantities: 1
mon_decimal_point string
mon_decimal_point
The decimal point character for currency values: .
mon_grouping
Like grouping but for currency values.
mon_thousands_sep string
mon_thousands_sep
The separator for digit groups in currency values: ,
,
n_cs_precedes integer
n_cs_precedes
Like p_cs_precedes but for negative values: 1
n_sep_by_space integer
n_sep_by_space
Like p_sep_by_space but for negative values: 0
n_sign_posn integer
n_sign_posn
Like p_sign_posn but for negative currency values: 1
The character used to denote negative currency values, usually a minus sign: -
-
p_cs_precedes integer
p_cs_precedes
1 if the currency symbol precedes the currency value for nonnegative values, 0 if it follows: 1
p_sep_by_space integer
p_sep_by_space
1 if a space is inserted between the currency symbol and the currency value for nonnegative values, 0 otherwise: 0
p_sign_posn integer
p_sign_posn
The location of the positive_sign with respect to a nonnegative quantity and the currency_symbol, coded as follows:
0 Parentheses around the entire string. 1 Before the string. 2 After the string. 3 Just before currency_symbol. 4 Just after currency_symbol.
positive_sign string
positive_sign
The character used to denote nonnegative currency values, usually the empty string
thousands_sep string
thousands_sep
The separator between groups of digits before the decimal point, except for currency values: ,
Calls "plural" in Text::PO and returns an array object (Module::Generic::Array) with 2 elements.
See "plural" in Text::PO for more details.
Provided with an original string, and this will return its localised equivalent if it exists, or by default, it will return the original string.
Provided with an original string, and this will get its localised equivalent that wil be used as a template for the sprintf function. The resulting formatted localised content will be returned.
Provided with a msgid represented by a string, and this return a localised version of the string, if any is found and is translated, otherwise returns the msgid that was provided.
$po->gettext( "Hello" ); # With locale of fr_FR, this would return "Bonjour"
See the global function "_" for more information.
Thus, in the example above, the resulting Text::PO::String would have its method locale value set to fr_FR, and you could do:
my $localised = $po->gettext( "Hello" ); say "Locale for this string is: ", $localised->locale;
This is an alias to "getTextf"
Provided with a locale such as fr-FR or ja_JP no matter whether an underscore or a dash is used, and this will return true if the locale has already been loaded and thus is supported. False otherwise.
fr-FR
Returns a string containing the value of the header Language.
Language
$po->language();
Returns a string containing the value of the header Language-Team.
Language-Team
$po->languageTeam();
Returns a string containing the value of the header Last-Translator.
Last-Translator
$po->lastTranslator();
Returns the locale set in the object. if sets, this will trigger the (re)load of po data by calling "textdomain"
Provided with a locale, such as en-GB and this will return its equivalent formatted for server-side such as en_GB
Provided with a locale, such as en_GB and this will return its equivalent formatted for the web such as en-GB
Returns a string containing the value of the header MIME-Version.
MIME-Version
$po->mimeVersion();
Takes an original string (a.k.a message id), the plural version of that string, and an integer representing the applicable count. For example:
$po->ngettext( '%d comment awaiting moderation', '%d comments awaiting moderation', 12 ); # Assuming the locale is ru_RU, this would return: # %d комментариев ожидают проверки
Sets or gets the filesystem path to the base directory containing the locale data:
$po->path( '/locale' ); # /locale contains en_GB/LC_MESSAGES/com.example.api.mo for example
Sets or gets the definition for plural for the current domain and locale.
It takes and returns an array reference of 2 elements:
n>1
or more complex for Russian:
(n==1) ? 0 : (n%10==1 && n%100!=11) ? 3 : ((n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20)) ? 1 : 2)
Returns a string containing the value of the header Plural-Forms.
Plural-Forms
$po->pluralForms();
Returns the Text::PO object used.
Returns a string containing the value of the header PO-Revision-Date.
PO-Revision-Date
$po->poRevisionDate();
Returns a string containing the value of the header POT-Creation-Date.
POT-Creation-Date
$po->potCreationDate();
Returns a string containing the value of the header Project-Id-Version.
Project-Id-Version
$po->projectIdVersion();
Returns a string containing the value of the header Report-Msgid-Bugs-To.
Report-Msgid-Bugs-To
$po->reportBugsTo();
Given a string representing a domain, such as com.example.api and this will load the .json (if the "use_json" option is enabled), .po or .mo file found in that order.
Takes a boolean and if set, Text::PO::Gettext will use a json po data if it exists, otherwise it will use a .po file or a .mo file in that order of preference.
Jacques Deguest <jack@deguest.jp>
perl
Copyright(c) 2021 DEGUEST Pte. Ltd. DEGUEST Pte. Ltd.
To install Text::PO, copy and paste the appropriate command in to your terminal.
cpanm
cpanm Text::PO
CPAN shell
perl -MCPAN -e shell install Text::PO
For more information on module installation, please visit the detailed CPAN module installation guide.