NAME
Locale::VersionedMessages - handle all aspects of the localization
process
SYNOPSIS
use Locale::VersionedMessages
$obj = new Locale::VersionedMessages;
$vers = $obj->version();
$obj->search(LOCALE_LIST);
DESCRIPTION
Although several modules exist for handling internationalization and
localization of a program, they are missing functionality for dealing
with all of the functions to perform the task fully. Existing modules
work fine with respect to a programmer who wants to access localized
messages, but the modules do not contain the necessary functions to
maintain those messages.
This module (and the programs that are distributed with it) form a
complete package for handling the localization problem.
At the heart of the localization problem, you have a set of messages.
These messages may be translated into any number of locales, and a
programmer can then look up the appropriate message, as it would appear
in the desired locale.
Any number of sets of messages may be used by a program. A set of
messages is best thought of as a set of related messages which might be
used by any number of programs. For example, one set of messages might
be I/O error messages encountered when working with files. Another set
might be the messages specific to one particular program.
Each set of messages can be translated into the language for any number
of locales. Ideally, all messages would be translated into all locales,
but that is often not the case. However, every set of messages has a
default locale (which may not be the same across all sets of messages)
which MUST have all of the messages in it.
This allows you to look up a message in either the locale you are
working with, or the default locale if it is not available there.
Unlike most existing localization modules, this module keeps track of
the version of every message in every locale. Although this information
is not typically useful to those programmers who are simply looking up
messages in the table, it is extremely useful to those who are
responsible for translating and maintaining the messages.
METHODS
The following methods are available:
new
$obj = new Locale::VersionedMessages;
This creates a new Locale::VersionedMessages object.
version
use Locale::VersionedMessages;
$obj = new Locale::VersionedMessages;
$vers = $obj->version();
Check the module version.
err
$err = $obj->err();
This returns any error message set during the previous operation.
set
$obj->set(SET0 [,SET1,SET2,...]);
This loads any number of message sets into the object. You can only
look up messages from sets that have been loaded.
@set = $obj->set();
This returns the names of the message sets that have been loaded.
SETi is a string containing alphanumeric and underscore characters.
query_set_default
query_set_locales
query_set_msgid
These return information about a message set.
$locale = $obj->query_set_default();
returns the default locale.
@locale = $obj->query_set_locales();
returns the list of all locales for which this message set is
defined.
@msgid = $obj->query_set_msgid();
returns a list of all message IDs in this set of messages. The
message ID is the label used in the program to access a message.
search
This method is used to specify the search order of the locales.
By default, all messages are returned in the default locale of the
message set (which may not be the same across message sets), but you
can change this using these methods.
$obj->search(LOCALE0 [,LOCALE1,LOCALE2,...]);
This specifies the global search order. This is the default search
order of locales used for all message sets. This specifies that, in
all message sets, the default is to use LOCALE0, followed by
LOCALE1, LOCALE2, etc.
If the message is not found in any of the locales, the default
locale for the set will be used.
The global search order can be overridden on a per-set basis.
$obj->search();
This erases the global default search order.
$obj->search(SET, LOCALE0 [,LOCALE1,LOCALE2,...]);
This specifies the search order for the given set, overriding the
global default search order. It is not necessary that all of the
locales actually have translations. Any that don't will be silently
ignored.
If a message is not found in any of these locales, the default
locale for the message set will be used.
$obj->search(SET);
This erases the search order for the given set, so the global search
order will be used.
For example:
$obj->search('BUTTONS','en','en_US','en_GB');
would look for a messages in the 'BUTTONS' set in the locales: 'en',
'en_US', and 'en_GB' in that order. If a message were not found in
any of those three, the default locale would be used.
query_search
@locale = $obj->query_search();
@locale = $obj->query_search(SET);
This returns the global search order or the search order for the
set.
In the second call, the global search order is NOT returned if the
set-specific search order is not set.
message
$text = $obj(SET, MSGID [,LOCALE] [,VALUES]);
($text,$locale) = $obj(SET, MSGID [,LOCALE] [,VALUES]);
This method is used to look up a message in the given set and
substitutes in VALUES (described below in MESSAGE SUBSTITUTIONS). If
LOCALE is present, it only looks up the message in that locale. By
default, it will look in the search order for that set.
If the message is not found, $text will be the empty string.
In list context, the text will be returned along with the name of
the locale in which the message was found.
If any error occurs, an empty string will be returned for $text.
query_msg_locales
query_msg_vers
These return information about a specific message.
@locale = $obj->query_msg_locales(SET, MSGID);
returns a list of all locales for which this message is defined. The
first one will be the default locale.
$vers = $obj->query_msg_vers(SET, MSGID [,LOCALE]);
returns the version of the message in the given locale. If LOCALE is
not given, it defaults to the default locale. If the message is not
defined in the locale, a version of 0 is returned.
MESSAGE SUBSTITUTIONS
When a message is defined, it can have values that will be passed in
which can be inserted into the message.
Unlike most localization tool kits, the values are passed in by name,
rather than position in a list, so the substitution looks a bit
different than other tool kits.
When a message is initially defined, two pieces of information are
required: the message ID and a list of substitution variables. Other
information (such as a description of the message) may also be provided,
but is not relevant to message substitution.
If one of the substitution variables is named 'foo', then anywhere in
the message, I can include '[foo...]' and that portion of the message
will be replaced based on the value of foo that is passed in.
The syntax of the substitution string can be any of the following:
[foo]
In it's simplest form, the value is simply inserted into the string.
For example, if the text is defined (in the default lexicon) as:
Set: Set1
Message ID: Foo value [foo]
Text: The value of foo is [foo].
Then:
$obj->message('Set1','Foo value [foo]',
'foo' => 'bar');
=> 'The value of foo is bar.
[foo:FORMAT]
The value can be formatted using standard sprintf formats. Only
simple formats are allowed, so FORMAT can be something like '%.3f'
but not 'the number %3d'. To be exact, FORMAT must be any valid
format that can be handled by sprintf that takes exactly one
argument, so something like %% is not allowed, but any %d format is.
Set: Set1
Message ID: Foo value [foo]
Text: The value of foo is >[foo:%5s]<.
$obj->message('Set1','Foo value [foo]',
'foo' => 'bar');
=> 'The value of foo is > bar<.
[foo:quant ...] or [foo:quant:FORMAT ...]
This is for handling plural elements. These two forms are identical
except that the number will be formatted using a sprintf format in
the second case.
The general form of this is:
[VAL:quant COND1 STRING1 COND2 STRING2 ... DEFAULT_STRING]
Each of the tokens in this form (CONDi, STRINGi, and DEFAULT_STRING)
can be a string that is wrapped in square brackets, single, or
double quotes. So, the string foobar can appear as foobar, [foobar],
'foobar', or "foobar". If a token starts with a square bracket, or a
single or double quote, it must be wrapped in one of the others.
Each CONDi is a string involving a correctly specified numerical
test. It should be noted that the tests are NOT passed to the perl
interpreter, so the full perl syntax is not supported. Since tests
are specified in user (i.e. translator) defined files, passing
portions of these files to eval would represent a security risk, so
instead, the condition strings are manually parsed, and only a
limited syntax is supported. However, the syntax should be flexible
enough to handle all real-life cases.
A condition can be a simple test. Simple tests are all of one of the
forms:
NUM < NUM
NUM <= NUM
NUM == NUM
NUM >= NUM
NUM > NUM
NUM != NUM
and each NUM can be:
_VAL
_VAL % DIGITS
DIGITS
Note that there are no signs allowed... only positive integers are
allowed. Also, parentheses are not allowed inside a simple test
(though the simple test can be enclosed in parentheses).
Simple tests can also be combined using parentheses and the two
operators '&&' and '||'.
If COND1 is met, then STRING1 is used. If COND2 is met, then STRING2
is used. If none of the conditions are met, then the DEFAULT_STRING
is met.
The DEFAULT_STRING is required, and at least one COND and STRING
should be included (though they are not strictly required... if they
are not present,t hen the DEFAULT_STRING will always be used.
An actual example might be:
Set: Set1
Message ID: Number of oranges [n]
Text: I have [n:quant [_n>1] '_n oranges' _n==1 "1 orange" [no oranges]].
and:
$obj->message('Set1','Number of oranges [n]',1);
=> 'I have 1 orange.'
$obj->message('Set1','Number of oranges [n]',3);
=> 'I have 3 oranges.'
$obj->message('Set1','Number of oranges [n]',0);
=> 'I have no oranges.'
Note that it is not required that '_VAL' be included in every one of
the strings. It can be included zero, one, or even multiple times if
desired.
Most whitespace is ignored, so the following are equivalent:
[foo]
[ foo ]
as are:
[foo:FORMAT]
[ foo : FORMAT ]
KNOWN PROBLEMS
None at this point.
SEE ALSO
Locale::VersionedMessages::Overview An overview of the
internationalization problem with a comparison to other Locale::*
modules
lm_gui A GUI tool for creating and maintaining sets of messages and
their translation tables.
LICENSE
This script is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.
AUTHOR
Sullivan Beck (sbeck@cpan.org)