Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Localization in Perl using gettext and Locale::TextDomain, with fallback if Locale::TextDomain is not available

The "On the state of i18n in Perl" blog post from 26 April 2009 recommends using Locale::TextDomain module from libintl-perl distribution for l10n / i18n in Perl. Besides I have to use gettext anyway, and gettext support in Locale::Messages / Locale::TextDomain is more natural than in gettext emulation in Locale::Maketext.

The subsection "15.5.18 Perl" in chapter "15 Other Programming Languages" in GNU gettext manual says:

Portability

The libintl-perl package is platform independent but is not part of the Perl core. The programmer is responsible for providing a dummy implementation of the required functions if the package is not installed on the target system.

However neither of two examples in examples/hello-perl in gettext sources (one using lower level Locale::Messages, one using higher level Locale::TextDomain) includes detecting if the package is installed on the target system, and providing dummy implementation if it is not.

What is complicating matter (with respect to detecting if package is installed or not) is the following fragment of Locale::TextDomain manpage:

SYNOPSIS

use Locale::TextDomain ('my-package', @locale_dirs);

use Locale::TextDomain qw (my-package);

USAGE

It is crucial to remember that you use Locale::TextDomain(3) as specified in the section "SYNOPSIS", that means you have to use it, not require it. The module behaves quite differently compared to other modules.

Could you please tell me how one should detect if libintl-perl is present on target system, and how to provide dummy fallthrough implementation if it is not installed? Or give examples of programs / modules which do this?

like image 963
Jakub Narębski Avatar asked Jun 03 '10 11:06

Jakub Narębski


1 Answers

The gettext manual is wrong to suggest that it is not okay for you to demand a CPAN prerequisite. Everyone does this in the Perl world, and thanks to the CPAN infrastructure and toolchain, it works just fine. In the worst case you can bundle the dependencies you need.

The straight answer to your question is:

use Try::Tiny;
try {
    require Locale::TextDomain;
    Locale::TextDomain->import('my-package', @locale_dirs);
} catch {
    warn 'Soft dependency could not be loaded, using fallback.';
    require inc::Local::Dummy::Locale::TextDomain;
}

Explanation: use is just require at compile time followed by import, and it is acceptable to split it in order to force this to execute at run time.

like image 83
daxim Avatar answered Sep 28 '22 18:09

daxim