lib/MGH_Biostat/Locale/POCatalog.pm
package MGH_Biostat::Locale::POCatalog;
use Modern::Perl '2012';
use experimental 'switch';
use Carp;
use Path::Tiny;
use Set::Tiny 'set';
use MGH_Biostat::Locale::PO;
use constant CTXSEP => chr(4);
our $DEFAULTS = { 'dir' => 'po', 'default_lang' => 'en-US' };
sub new {
my $class = shift;
my $self = { %$DEFAULTS, @_ };
if ( $self->{'dir'} !~ m[/$] ) { $self->{'dir'} .= '/'; }
my $langs = [];
for ( path( $self->{'dir'} )->children(qr/\.po$/) ) {
push @$langs, $_->basename('.po');
}
$self->{'langs'} = set($langs);
my $order = [
$self->{'default_lang'},
sort grep { $_ ne $self->{'default_lang'}; } $self->{'langs'}->members(),
];
$self->{'langs_order'} = $order;
my $data = {};
foreach my $lang ( $self->{'langs'}->members() ) {
my $pos = MGH_Biostat::Locale::PO->load_file_asarray( $self->{'dir'} . $lang . '.po', 'utf8' );
foreach my $po (@$pos) {
my $key = $po->hashkey;
if ( !defined( $po->msgid_plural ) and ( !defined( $po->msgstr ) or ( $po->msgstr eq '' ) ) ) {
no warnings 'uninitialized';
warn 'Missing translation for [' . $lang . '|' . $po->msgctxt . '|' . $po->msgid . ']; setting to msgid.' . "\n";
$po->msgstr( $po->msgid );
}
$data->{$lang}{$key} = $po;
}
}
$self->{'data'} = $data;
return bless $self, $class;
}
sub langs {
my $self = shift;
return $self->{'langs'};
}
sub default_lang {
my $self = shift;
return $self->{'default_lang'};
}
sub langs_order {
my $self = shift;
return $self->{'langs_order'};
}
sub is_valid_lang {
my $self = shift;
my ($lang) = @_;
return $self->{'langs'}->member($lang);
}
# look up a translation
# returns a MGH_Biostat::Locale::PO object
# the first parameter *must* be the language
# the second parameter is the lookup string
# if there is a context to be provided, you can either pass a third parameter,
# or use the CTXSEP constant to create a context lookup string
# if there is any kind of error, a warning will be fired,
# and a Locale::PO object with the same string as request will be returned
sub lookup {
my $self = shift;
my ( $lang, $msgid, $context ) = @_;
if ( $self->is_valid_lang($lang) ) {
my $key = ( defined($context) ? $context . CTXSEP : '' ) . $msgid;
my $data = $self->{'data'};
if ( defined( $data->{$lang}{$key} ) ) {
return $data->{$lang}{$key};
}
elsif ( defined( $data->{ $self->{'default_lang'} }{$key} ) ) {
no warnings 'uninitialized'; # $context may not be defined
carp "Key [$context|$msgid] not defined for $lang.";
return $data->{ $self->{'default_lang'} }{$key};
}
else {
no warnings 'uninitialized'; # $context may not be defined
carp "Key [$context|$msgid] not defined for any lang.";
return MGH_Biostat::Locale::PO->new( -msgid => $msgid, -msgstr => $msgid, -msgctxt => $context );
}
}
else {
carp "Language $lang not supported.";
return MGH_Biostat::Locale::PO->new( -msgid => $msgid, -msgstr => $msgid, -msgctxt => $context );
}
}
1;