I modified the handler a little bit, and the output looks like this here:
Did setlocale succeed?
LC_MESSAGES: de_DE.UTF-8
LC_TIME: de_DE.UTF-8
LC_ALL: de_DE.UTF-8
Today: Montag
Perl gettext from Messages:
I18N_OPENXPKI_CLIENT_HTML_MASON_API_CERT_INFO_TITLE
Pure Perl gettext: I18N_OPENXPKI_CLIENT_HTML_MASON_API_CERT_INFO_TITLE
Command_line: I18N_OPENXPKI_CLIENT_HTML_MASON_API_CERT_INFO_TITLE
XS gettext: I18N_OPENXPKI_CLIENT_HTML_MASON_API_CERT_INFO_TITLE
Command_line: I18N_OPENXPKI_CLIENT_HTML_MASON_API_CERT_INFO_TITLE
The important part is that the calls to setlocale() all succeed. You
can also see that changing LC_TIME also worked, because the day of the
week is output in German. It is no wonder that nothing else gets
translated, because I don't have your mo files, but that isn't important.
I think I have to clarify the meaning of the environment for the GNU
implementation of gettext (and libintl-perl, which is mostly compatible
to GNU gettext).
The file ABOUT-NLS (see for example
http://cvs.savannah.gnu.org/viewvc/gettext/gettext-tools/ABOUT-NLS?revision=1.12&root=gettext&view=markup,
please read part 1.3 "Using this package") recommends to users (users!
not programs!) to set the LC_* variables to valid locale identifiers on
their system. The only reason for that is that an internationalized
program should begin like this:
setlocale (LC_ALL, "");
But this is pure convention, and especially server applications like
yours will usually violate that convention on purpose. The reason for
that convention is that a POSIX compliant setlocale implementation in
the libc will interpret the empty (empty! not undefined!) second
argument so, that it will inspect the various LC_* environment variables
for setting the locale.
There are two more environment variables, LANG and LANGUAGE which have a
special meaning. LANG defines the user's preferred language (language
is a LL_CC combination with LL being the 2-letter language code and CC
the optional two-letter country-code). LANG is however ignored, if the
locale is set to anything else but "C" or "POSIX". The environment
variable LANGUAGE should contain a colon separated list of languages,
for example "de:bg_BG". A trailing charset declaration for a language,
for example "de.utf-8" is gracefully stripped off and ignored. You can
force a certain charset by setting the environment variable
"OUTPUT_CHARSET" to a valid charset definition. BTW, if you set
LANGUAGE you should still set LANG, not for gettext but for other system
components, see ABOUT-NLS.
So, how does gettext_pp decide on how to search for a messages catalog,
say $locale_prefix/de_DE/LC_MESSAGES? If the environment variable
LANGUAGE is set, then it is split at colons (:) into a list of language
identifiers to try, otherwise it calls setlocale() with an undefined
second argument. The return value is the current locale setting (for
the first argument category). If the return value matches the expected
format (LL_CC@region.charset, with everything but LL being optional),
this value is taken.
What happens on the BSD systems, where things don't work as expected? I
can only guess, but my guess is that your calls to setlocale() fail (see
my modified handler for a check for that). If you use gettext_pp, these
failures are healed, because you override everything with the
environment variable LANGUAGE. The behavior of GNU gettext is the same
(I hope so at least), but your system's gettext may of course be
implemented slightly different. So, if you want to rely on the
behavior, that LANGUAGE overrides everything else, you should force the
usage of gettext_pp.
Is the day of the week output in German on your test system? If not,
then it is also no wonder that gettext fails to translate the strings,
becauses it uses more or less the same mechanism.
Remember that you actually do a (legitimate) abuse of gettext, by
hardcoding locale identifiers into your code. The idea of gettext is
that the identifiers are set in the user's environment, because their
format is completely system-dependent. On Windows a German locale may
look like "German_Germany.cp1252" instead of "de_DE.utf-8". On some
systems case matters, on others it doesn't. The exact spelling of
charset identifiers is also system-dependent ("utf8", "utf-8", "UTF-8",
...). So, even if you know the language, the country and the charset,
you still have to take wild guesses at a recognized format, and in the
end you can still have a failure, if the desired locale is not installed
at all on the system. See the file Locale/Util.pm that I mentioned in
my posting on your sourceforge bugtracking system.
The environment variables LANGUAGE and OUTPUT_CHARSET (if honored by
your gettext) are a way out of that dilemma, because they interface
directly with gettext, so that setlocale() is bypassed when determining
the desired locale.
Final advice, please s/Locale::gettext_pp::(.*)/Locale::gettext::$1/ for
a test. You have to install Locale::gettext from CPAN for that. If
Locale::gettext::gettext() shows the same behavior as gettext_xs from
libintl-perl you can clearly see that it is not a problem of
libintl-perl, but that your system's gettext simply does not work as you
expect.