CLDR-Number
view release on metacpan or search on metacpan
lib/CLDR/Number/Role/Base.pm view on Meta::CPAN
package CLDR::Number::Role::Base;
use v5.8.1;
use utf8;
use Carp;
use Scalar::Util qw( looks_like_number );
use CLDR::Number::Data::Base;
use CLDR::Number::Data::System;
use Moo::Role;
# This role does not have a publicly supported interface and may change in
# backward incompatible ways in the future. Please use one of the documented
# classes instead.
our $VERSION = '0.19';
requires qw( BUILD );
has version => (
is => 'ro',
default => $VERSION,
);
has cldr_version => (
is => 'ro',
default => $CLDR::Number::Data::Base::CLDR_VERSION,
);
has locale => (
is => 'rw',
trigger => 1,
);
has default_locale => (
is => 'ro',
coerce => sub {
my ($locale) = @_;
if (!defined $locale) {
carp 'default_locale is not defined';
}
elsif (!exists $CLDR::Number::Data::Base::DATA->{$locale}) {
carp "default_locale '$locale' is unknown";
}
else {
return $locale;
}
return;
},
);
has numbering_system => (
is => 'rw',
isa => sub {
carp 'numbering_system is not defined'
unless defined $_[0];
carp "numbering_system '$_[0]' is unknown"
unless exists $CLDR::Number::Data::System::DATA->{$_[0]};
},
coerce => sub { defined $_[0] ? lc $_[0] : $_[0] },
trigger => 1,
);
has minimum_grouping_digits => (
is => 'rw',
isa => sub {
croak "minimum_grouping_digits '$_[0]' is invalid"
if defined $_[0] && !looks_like_number $_[0];
},
);
# TODO: length NYI
has length => (
is => 'rw',
);
has decimal_sign => (
is => 'rw',
);
has group_sign => (
is => 'rw',
);
has plus_sign => (
is => 'rw',
);
has minus_sign => (
is => 'rw',
);
has infinity => (
is => 'rw',
);
has nan => (
is => 'rw',
);
has _locale_inheritance => (
is => 'rw',
default => sub { [] },
);
has _init_args => (
is => 'rw',
);
around BUILDARGS => sub {
my ($orig, $class, @args) = @_;
return $class->$orig(@args) if @args % 2;
return $class->$orig(@args, _init_args => {@args});
};
before BUILD => sub {
my ($self) = @_;
return if $self->_has_init_arg('locale');
$self->_trigger_locale;
};
after BUILD => sub {
my ($self) = @_;
$self->_init_args({});
};
sub _has_init_arg {
my ($self, $arg) = @_;
return unless $self->_init_args;
return exists $self->_init_args->{$arg};
}
sub _set_unless_init_arg {
my ($self, $attribute, $value) = @_;
return if $self->_has_init_arg($attribute);
$self->$attribute($value);
}
sub _build_signs {
my ($self, @signs) = @_;
for my $sign (@signs) {
my $attribute = $sign;
next if $self->_has_init_arg($attribute);
$sign =~ s{ _sign $ }{}x;
$self->$attribute($self->_get_data(symbol => $sign));
}
}
sub _trigger_locale {
my ($self, $locale) = @_;
my ($lang, $script, $region, $ext) = _split_locale($locale);
if ($lang && exists $CLDR::Number::Data::Base::DATA->{$lang}) {
$self->_locale_inheritance(
_build_inheritance($lang, $script, $region, $ext)
);
$locale = $self->_locale_inheritance->[0];
}
elsif ($self->default_locale) {
$locale = $self->default_locale;
($lang, $script, $region, $ext) = _split_locale($locale);
$self->_locale_inheritance(
_build_inheritance($lang, $script, $region, $ext)
);
}
else {
$locale = 'root';
$self->_locale_inheritance( [$locale] );
}
if ($ext && $ext =~ m{ -nu- ( [^-]+ ) }x) {
$self->numbering_system($1);
}
else {
$self->_trigger_numbering_system;
}
$self->{locale} = $locale;
$self->_build_signs(qw{
decimal_sign group_sign plus_sign minus_sign infinity nan
});
$self->_set_unless_init_arg(
minimum_grouping_digits => $self->_get_data(attr => 'min_group')
);
}
sub _trigger_numbering_system {
my ($self, $system) = @_;
return if defined $system
&& exists $CLDR::Number::Data::System::DATA->{$system};
$self->{numbering_system} = $self->_get_data(attr => 'system');
}
sub _split_locale {
my ($locale) = @_;
return unless defined $locale;
$locale = lc $locale;
$locale =~ tr{_}{-};
my ($lang, $script, $region, $ext) = $locale =~ m{ ^
( [a-z]{2,3} ) # language
(?: - ( [a-z]{4} ) )? # script
(?: - ( [a-z]{2} | [0-9]{3} ) )? # country or region
(?: - ( u- .+ ) )? # extension
-? # trailing separator
$ }xi;
$script = ucfirst $script if $script;
$region = uc $region if $region;
return $lang, $script, $region, $ext;
}
sub _build_inheritance {
my ($lang, $script, $region, $ext) = @_;
my @tree;
for my $subtags (
[$lang, $region, $ext],
[$lang, $script, $region],
[$lang, $script],
[$lang, $region],
[$lang],
) {
next if grep { !$_ } @$subtags;
my $locale = join '-', @$subtags;
next if !exists $CLDR::Number::Data::Base::DATA->{$locale};
push @tree, $locale;
if (my $parent = $CLDR::Number::Data::Base::PARENT->{$locale}) {
push @tree, @{_build_inheritance(_split_locale($parent))};
last;
}
}
if (!@tree || $tree[-1] ne 'root') {
push @tree, 'root';
}
return \@tree;
}
sub _get_data {
my ($self, $type, $key) = @_;
my $data = $CLDR::Number::Data::Base::DATA;
for my $locale (@{$self->_locale_inheritance}) {
return $data->{$locale}{$type}{$key}
if exists $data->{$locale}
&& exists $data->{$locale}{$type}
&& exists $data->{$locale}{$type}{$key};
}
return undef;
}
1;
( run in 1.077 second using v1.01-cache-2.11-cpan-ceb78f64989 )