view release on metacpan or search on metacpan
Moo::Role method modifiers but not a requirement of Moo::Role itself
0.18 2016-03-17
[ New CLDR version ]
- Upgrade CLDR data from v28 (2015-09-17) to v29 (2016-03-16)
- Release notes: http://cldr.unicode.org/index/downloads/cldr-29
[ New languages ]
- yue (Cantonese)
[ New locales for existing languages ]
- es-BR (Spanish in Brazil)
- pt-CH (Portuguese in Switzerland)
- pt-GQ (Portuguese in Equatorial Guinea)
- pt-LU (Portuguese in Luxembourg)
[ Updated locales ]
- da (Danish): at_least pattern
- gl (Galician): currency pattern
- ka (Georgian): GEL (Georgian Lari) currency symbol
- os (Ossetic): GEL (Georgian Lari) currency symbol
0.17 2016-03-10
- Bugfix: prohibit Moo v2.001000 because it introduced a bug that breaks this
module, which was fixed in v2.001001, as tested and reported by Slaven ReziÄ
@eserte++ and fixed by Graham Knop @haarg++ in
https://rt.cpan.org/Public/Bug/Display.html?id=112677 [#48]
- Docs: new FAQ entry on fallback for non-existant locales by Michael LaGrasta
@mnlagrasta++ [#41]
- Docs: update example output for CLDR v28
0.16 2015-09-23
[ Minimum grouping digits ]
- Add support for minimum grouping digits, introduced in the CLDR v26 spec and
data [#36]
- Add minimum_grouping_digits attribute with default value `1` (which has no
effect on formatting) to all classes
- Locales with value `1`: root (Root), es-419 (Latin American Spanish)
- Bugfix: fix formatting negative numbers along with a custom
rounding_increment value, which had caused double negative signs
- Bugfix: fix formatting of string values `inf` and `nan` which werenât treated
as numeric on combinations of some operating systems with some older versions
of Perl [#44, #45]
- Docs: typo fix by Fred Moyer @redhotpenguin++ [#43]
0.13 2015-09-20
[ New CLDR version ]
- Upgrade CLDR data from v27.0.1 (2015-03-30) to v28 (2015-09-17)
- âAdded several English locales for Europe and W Asiaâ
- âMajor review of and improvement to Spanish locales for Latin Americaâ
- See also: http://cldr.unicode.org/index/downloads/cldr-28
[ New languages ]
- ce (Chechen)
- ckb (Central Kurdish)
- cu (Church Slavic)
- lrc (Northern Luri)
- mzn (Mazanderani)
- tk (Turkmen)
[ New locales for existing languages ]
- en-AT (English in Austria)
- en-BI (English in Burundi)
- en-CH (English in Switzerland)
- en-DE (English in Germany)
- en-DK (English in Denmark)
- en-FI (English in Finland)
- en-NL (English in Netherlands)
- en-SE (English in Sweden)
- es-DO (Spanish in Dominican Republic)
- es-GT (Spanish in Guatemala)
formatting methods (format, at_least, range) on all formatting classes
(decimal, percent, currency), because those are valid numeric values in Perl,
which are now all localized even though it doesnât always make
sense [issue #26]
- Add `infinity` and `nan` attributes to all classes in addition to the decimal
formatter
0.11 2015-08-25
- Upgrade CLDR data from v24 (2013-09-18) to v27.0.1 (2015-03-30) [issue #33]
- Add bin/generate-cldr-data.pl script to update Perl data from CLDR JSON
- Add new locales including dsb (Lower Sorbian), fy (West Frisian),
hsb (Upper Sorbian), lb (Luxembourgish), qu (Quechua), smn (Inari Sami),
and ug (Uyghur)
- Remove CLDR data with draft status of 'provisional' or 'unconfirmed', only
including 'contributed' or 'approved', which is the same threshold as the
ICU Project as well as the CLDR JSON data as of v27.0.1
- Remove 'provisional' draft numbering systems until they become at least
'contributed': brah (Brahmi), cakm (Chakma), osma (Osmanya), shrd (Sharada),
sora (Sora Sompeng), takr (Takri)
- Change various symbols for several locales, including grouping symbol in
es (Spanish, not including Latin American Spanish locales) from
'Â ' (no-break space) to '.' (full stop) and fr-SH (Swiss French) from
"'" (apostrophe) to 'Â ' (no-break space)
- Change negative number format for any locales using formats with parentheses
like '(N)', including ko (Korean), to using the minus sign like '-N', except
for accounting format which is not yet supported
- Change currency decimal symbol for sv (Swedish) from ':' to ',' now matching
the regular (non-currency) decimal symbol and common usage, resulting in no
locale having a different decimal symbol for currencies
- Change THB (Thai Baht) symbol from '฿' to 'THB' for most locales including
root and th (Thai), due to its general obscurity
- Change many other currency symbols for many locales, but generally minor
changes, for example DKK (Danish Krone) in da (Danish) from 'kr' to 'kr.' and
USD (US Dollar) in fr-CA (Canadian French) from '$US' to '$Â US'
- Change CLF (Chilean Unit of Account (UF)) currency fraction digits
from 0 to 4
- Change CZK (Czech Republic Koruna) currency cash fraction digits from 2 to 0
with default fraction digits remaining 2
- Change HUF (Hungarian Forint) currency fraction digits from 0 to 2 with
cash fraction digits remaining 0
- Change UYI (Uruguayan Peso (Indexed Units)) currency fraction digits
from 2 to 0
0.10 2015-03-26
- Improve documentation and unit tests (no functional changes)
- Docs: Fix attribute name in CLDR::Number::Format::Currency
synopsis [issue #40] (by Olaf Alders @oalders++)
0.09 2014-11-12
- Deprecate use of the the `locale` method as a setter. In the future the
formatter objectsâ locale will become immutable. Please see [issue #38] for
details and to submit comments or concerns:
https://github.com/patch/cldr-number-pm5/issues/38
- Add items to the FAQ and TODO docs
0.08 2014-03-28
- Improve locale inheritance to use parent overrides from CLDR data [issue #34]
0.07 2014-03-25
- Add numbering_system attribute and support non-Latin decimal numbering
systems [issue #8]
- Use default numbering system for locale [issue #9]
- Use numbering system from Unicode extension of locale when provided
- Integrate Travis CI, Devel::Cover, and Coveralls with GitHub repo
0.06 2014-02-28
- Improve documentation
- Add FAQ
0.05 2014-01-26
- Validate numeric arguments to methods in the same way as core Perl functions:
warn on non-numeric values and use the leading numeric portion when
available, otherwise 0 [issue #23]
README
t/00-load.t
t/currency.t
t/format.t
t/from-icu4c.t
t/from-shutterstock.t
t/from-twittercldr.t
t/from-uts35.t
t/inf-nan.t
t/inheritance.t
t/locales.t
t/minmax-digits.t
t/numbering-system.t
t/objects.t
t/pattern-coerce.t
t/pattern-trigger.t
t/quoting.t
t/range.t
t/rounding.t
NAME
CLDR::Number - Localized number formatters using the Unicode CLDR
VERSION
This document describes CLDR::Number v0.19, built with Unicode CLDR v29.
SYNOPSIS
use CLDR::Number;
# new object with 'es' (Spanish) locale
$cldr = CLDR::Number->new(locale => 'es');
# decimals
$decf = $cldr->decimal_formatter;
# when locale is 'es' (Spanish)
say $decf->format(1234.5); # '1234,5'
# when locale is 'es-MX' (Mexican Spanish)
say $decf->format(1234.5); # '1,234.5'
# when locale is 'ar' (Arabic)
say $decf->format(1234.5); # '١٬٢٣٤٫٥'
# percents
$perf = $cldr->percent_formatter;
# when locale is 'tr' (Turkish)
say $perf->format(0.05); # '%5'
# currencies
$curf = $cldr->currency_formatter(currency_code => 'USD');
# when locale is 'en' (English) and currency is USD (US dollars)
say $curf->format(9.99); # '$9.99'
# when locale is 'en-CA' (Canadian English) and currency is USD
say $curf->format(9.99); # 'US$9.99'
# when locale is 'fr-CA' (Canadian French) and currency is USD
say $curf->format(9.99); # '9,99 $ US'
DEPRECATION
Using the "locale" method as a setter is deprecated. In the future the
objectâs locale will become immutable. Please see issue #38
<https://github.com/patch/cldr-number-pm5/issues/38> for details and to
submit comments or concerns.
DESCRIPTION
Software localization includes much more than just translations.
Numbers, prices, and even percents should all be localized based on the
userâs language, script, and region. Fortunately, the Unicode Common
Locale Data Repository (CLDR) provides locale data and specifications
for formatting numeric data to use with many of the worldâs locales.
This class provides common attributes shared among the supported
formatter classes as well as methods to instantiate decimal, percent,
and currency formatter objects. The value for any attribute (such as
locale or decimal_sign) will be passed to the formatter objects on
instantiation but can be overwritten by manually passing another value
for the attribute or calling a setter method on the formatter object.
Methods
decimal_formatter
Returns a decimal formatter, which is a
CLDR::Number::Format::Decimal object instantiated with all of the
attributes from your CLDR::Number object as well as any attributes
passed to this method.
passed to this method.
currency_formatter
Returns a currency formatter, which is a
CLDR::Number::Format::Currency object instantiated with all of the
attributes from your CLDR::Number object as well as any attributes
passed to this method.
Common Attributes
These are common attributes among this class and all formatter classes.
All attributes other than locale, default_locale, and cldr_version have
defaults that change depending on the current locale. All string
attributes are expected to be character strings, not byte strings.
locale
Default: value of default_locale attribute if it exists, otherwise
"root"
Valid: Unicode locale identifiers
Examples: "es" (Spanish), "es-ES" (European Spanish), "es-419"
(Latin American Spanish), "zh-Hant" (Traditional Chinese), "zh-Hans"
(Simplified Chinese), "chr" (Cherokee)
The locale is case-insensitive and can use either "-" (hyphen-minus)
or "_" (low line) as a separator.
default_locale
Default: none
Valid: Unicode locale identifiers
Use this if you want a locale other than the generic "root" if the
locale attribute is not set or not valid.
numbering_system
Valid: currently only decimal numbering systems are supported
Examples: "latn" (Western Digits), "arab" (Arabic-Indic Digits),
"hanidec" (Chinese Decimal Numerals), "fullwide" (Full Width Digits)
In the future, algorithmic numbering systems like "hant"
(Traditional Chinese Numerals), "hebr" (Hebrew Numerals), and
"roman" (Roman Numerals) will be supported.
The numbering system may alternately be provided as a Unicode locale
extension subtag. For example, locale "ja-u-nu-fullwide" for the
Japanese language ("ja") with the numbering system ("nu") set to
Full Width Digits ("fullwide").
decimal_sign
Examples: "." (full stop) for root, en; "," (comma) for de, fr
group_sign
Examples: "," (comma) for root, en; "." (full stop) for de; " "
(no-break space) for fr
plus_sign
Examples: "+" (plus sign) for root, en, and most locales
minus_sign
Examples: "-" (hyphen-minus) for root, en, and most locales
infinity
Examples: "â" (infinity) for root, en, and almost all locales
nan Examples: "NaN" for root, en, and most locales; many other
variations for individual locales like "не ÑиÑло" for ru and "鿏å¼"
for zh-Hant
cldr_version
Value: 29
This is a read-only attribute that will always reflect the currently
supported Unicode CLDR version.
NOTES
The Unicode private-use characters U+F8F0 through U+F8F4 are used
lib/CLDR/Number.pm view on Meta::CPAN
sub currency_formatter {
my ($self, %args) = @_;
require CLDR::Number::Format::Currency;
CLDR::Number::Format::Currency->new($self->_make_args(%args));
}
sub _make_args {
my ($self, %new_args) = @_;
my %args = (locale => $self->locale, %new_args);
return %args;
}
1;
__END__
=encoding UTF-8
lib/CLDR/Number.pm view on Meta::CPAN
CLDR::Number - Localized number formatters using the Unicode CLDR
=head1 VERSION
This document describes CLDR::Number v0.19, built with Unicode CLDR v29.
=head1 SYNOPSIS
use CLDR::Number;
# new object with 'es' (Spanish) locale
$cldr = CLDR::Number->new(locale => 'es');
# decimals
$decf = $cldr->decimal_formatter;
# when locale is 'es' (Spanish)
say $decf->format(1234.5); # '1234,5'
# when locale is 'es-MX' (Mexican Spanish)
say $decf->format(1234.5); # '1,234.5'
# when locale is 'ar' (Arabic)
say $decf->format(1234.5); # '١٬٢٣٤٫٥'
# percents
$perf = $cldr->percent_formatter;
# when locale is 'tr' (Turkish)
say $perf->format(0.05); # '%5'
# currencies
$curf = $cldr->currency_formatter(currency_code => 'USD');
# when locale is 'en' (English) and currency is USD (US dollars)
say $curf->format(9.99); # '$9.99'
# when locale is 'en-CA' (Canadian English) and currency is USD
say $curf->format(9.99); # 'US$9.99'
# when locale is 'fr-CA' (Canadian French) and currency is USD
say $curf->format(9.99); # '9,99Â $Â US'
=head1 DEPRECATION
Using the C<locale> method as a setter is deprecated. In the future the objectâs
locale will become immutable. Please see
L<issue #38|https://github.com/patch/cldr-number-pm5/issues/38> for details and
to submit comments or concerns.
=head1 DESCRIPTION
Software localization includes much more than just translations. Numbers,
prices, and even percents should all be localized based on the userâs language,
script, and region. Fortunately, the Unicode Common Locale Data Repository
(CLDR) provides locale data and specifications for formatting numeric data to
use with many of the worldâs locales.
This class provides common attributes shared among the supported formatter
classes as well as methods to instantiate decimal, percent, and currency
formatter objects. The value for any attribute (such as B<locale> or
B<decimal_sign>) will be passed to the formatter objects on instantiation but
can be overwritten by manually passing another value for the attribute or
calling a setter method on the formatter object.
=head2 Methods
=over
=item decimal_formatter
lib/CLDR/Number.pm view on Meta::CPAN
Returns a currency formatter, which is a L<CLDR::Number::Format::Currency>
object instantiated with all of the attributes from your CLDR::Number object as
well as any attributes passed to this method.
=back
=head2 Common Attributes
These are common attributes among this class and all formatter classes. All
attributes other than B<locale>, B<default_locale>, and B<cldr_version> have
defaults that change depending on the current B<locale>. All string attributes
are expected to be character strings, not byte strings.
=over
=item locale
Default: value of B<default_locale> attribute if it exists, otherwise C<root>
Valid: Unicode locale identifiers
Examples: C<es> (Spanish), C<es-ES> (European Spanish), C<es-419> (Latin
American Spanish), C<zh-Hant> (Traditional Chinese), C<zh-Hans> (Simplified
Chinese), C<chr> (Cherokee)
The locale is case-insensitive and can use either C<-> (hyphen-minus) or C<_>
(low line) as a separator.
=item default_locale
Default: none
Valid: Unicode locale identifiers
Use this if you want a locale other than the generic C<root> if the B<locale>
attribute is not set or not valid.
=item numbering_system
Valid: currently only decimal numbering systems are supported
Examples: C<latn> (Western Digits), C<arab> (Arabic-Indic Digits), C<hanidec>
(Chinese Decimal Numerals), C<fullwide> (Full Width Digits)
In the future, algorithmic numbering systems like C<hant> (Traditional Chinese
Numerals), C<hebr> (Hebrew Numerals), and C<roman> (Roman Numerals) will be
supported.
The numbering system may alternately be provided as a Unicode locale extension
subtag. For example, locale C<ja-u-nu-fullwide> for the Japanese language
(C<ja>) with the numbering system (C<nu>) set to Full Width Digits
(C<fullwide>).
=item decimal_sign
Examples: C<.> (full stop) for B<root>, B<en>; C<,> (comma) for B<de>, B<fr>
=item group_sign
Examples: C<,> (comma) for B<root>, B<en>; C<.> (full stop) for B<de>; C<Â >
(no-break space) for B<fr>
=item plus_sign
Examples: C<+> (plus sign) for B<root>, B<en>, and most locales
=item minus_sign
Examples: C<-> (hyphen-minus) for B<root>, B<en>, and most locales
=item infinity
Examples: C<â> (infinity) for B<root>, B<en>, and almost all locales
=item nan
Examples: C<NaN> for B<root>, B<en>, and most locales; many other variations for
individual locales like C<не ÑиÑло> for B<ru> and C<鿏å¼> for B<zh-Hant>
=item cldr_version
Value: C<29>
This is a read-only attribute that will always reflect the currently supported
Unicode CLDR version.
=back
lib/CLDR/Number/FAQ.pod view on Meta::CPAN
When displaying whole monetary numbers, it is sometimes desired to leave off the
fraction digits (e.g. cents) for marketing purposes. To do this, set the
C<maximum_fraction_digits> attribute to C<0>. Beware though that some currencies
have a number of fraction digits other than two, so it is not safe to set
C<minimum_fraction_digits> and C<maximum_fraction_digits> to C<2> for arbitrary
currencies.
=item How do I set a default currency?
L<CLDR::Number::Format::Currency> does not provide a default currency for the
C<currency_code> attribute like we have for the C<locale> attribute nor does it
provide a I<default_currency_code> attribute like the C<default_locale>
attribute. This is because a price without a known currency has no known value.
Setting a default currency is just as inaccurate as setting a default number. If
your application depends on a default currency, the C<currency_code> attribute
can be explicitly set.
âB<Note:> I<Currency values should B<never> be interchanged without a known
currency code. You never want the number 3.5 interpreted as $3.50 by one user
and â¬3.50 by another.> Locale data contains localization information for
currencies, not a currency value for a country. A currency amount logically
consists of a numeric value, plus an accompanying currency code (or
lib/CLDR/Number/FAQ.pod view on Meta::CPAN
=item How do I format years?
Years are a type of date, and dates have very different formatting rules than
regular numbers. Resources for localized date/time formatting include
L<DateTime>, L<DateTime::Locale>, and L<UTS #35: Unicode LDML, Part 4:
Dates|http://unicode.org/reports/tr35/tr35-dates.html>.
=item Why is the format different than expected?
Users occasionally report incorrect formatting for several non-existent locales.
This is most often the result of specifying a locale composed of an unrecognized
combination of language and country, which will cause the formatting to default
to the base language. Two common examples of this are C<en-MX> (Mexican English)
and C<es-BR> (Brazilian Spanish), which would default to C<en> (English) and
C<es> (Spanish), respectively. However, if demand is shown for them, they may be
added to the CLDR, such as C<es-BR>, which was added to CLDR v29.
=back
=head1 SEE ALSO
lib/CLDR/Number/Format/Currency.pm view on Meta::CPAN
coerce => sub { $_[0] ? 1 : 0 },
trigger => 1,
default => 0,
);
has _pattern_type => (
is => 'ro',
default => 'currency',
);
after _trigger_locale => sub {
my ($self) = @_;
if ($self->currency_code) {
$self->_build_currency_sign;
}
if (my $decimal = $self->_get_data(symbol => 'currency_decimal')) {
$self->decimal_sign($decimal);
}
};
lib/CLDR/Number/Format/Currency.pm view on Meta::CPAN
$self->_trigger_cash;
}
sub _build_currency_sign {
my ($self) = @_;
my $data = $CLDR::Number::Data::Currency::LOCALES;
my $currency_sign;
return if $self->_has_init_arg('currency_sign');
for my $locale (@{$self->_locale_inheritance}) {
next if !exists $data->{$locale} || !exists $data->{$locale}{$self->currency_code};
$currency_sign = $data->{$locale}{$self->currency_code};
last;
}
$self->currency_sign($currency_sign || $self->currency_code);
}
sub _trigger_cash {
my ($self) = @_;
my $currencies = $CLDR::Number::Data::Currency::CURRENCIES;
my $currency_data
lib/CLDR/Number/Format/Currency.pm view on Meta::CPAN
=head1 VERSION
This document describes CLDR::Number::Format::Currency v0.19, built with Unicode
CLDR v29.
=head1 SYNOPSIS
# either
use CLDR::Number::Format::Currency;
$curf = CLDR::Number::Format::Currency->new(
locale => 'en',
currency_code => 'USD',
);
# or
use CLDR::Number;
$cldr = CLDR::Number->new(locale => 'en');
$curf = $cldr->currency_formatter(currency_code => 'USD');
# when locale is 'en' (English) and currency is USD (US dollars)
say $curf->format(9.99); # '$9.99'
# when locale is 'en-CA' (Canadian English) and currency is USD
say $curf->format(9.99); # 'US$9.99'
# when locale is 'fr-CA' (Canadian French) and currency is USD
say $curf->format(9.99); # '9,99Â $Â US'
# when locale is 'bn' (Bengali) and currency is INR (Indian rupees)
say $curf->format(123456); # 'à§§,২৩,৪৫৬.০০â¹'
=head1 DEPRECATION
Using the C<locale> method as a setter is deprecated. In the future the objectâs
locale will become immutable. Please see
L<issue #38|https://github.com/patch/cldr-number-pm5/issues/38> for details and
to submit comments or concerns.
=head1 DESCRIPTION
Localized currency formatter using the Unicode Common Locale Data Repository
(CLDR).
=head2 Methods
=over
=item format
Accepts a number and returns a formatted currency value as a character string,
using the currency from the B<currency_code> attribute and localized for the
current locale.
=back
=head2 Attributes
The common attributes B<locale>, B<default_locale>, B<numbering_system>,
B<decimal_sign>, B<group_sign>, B<plus_sign>, B<minus_sign>, and B<cldr_version>
are described under L<common attributes in
CLDR::Number|CLDR::Number/"Common Attributes">. All attributes described here
other than B<currency_code> and B<cash> have defaults that change depending on
the current B<locale>. The attributes B<currency_sign>,
B<minimum_fraction_digits>, B<maximum_fraction_digits>, and
B<rounding_increment> also change depending on the B<currency_code> and B<cash>
values. All string attributes are expected to be character strings, not byte
strings.
=over
=item currency_code
Default: none
Valid: ISO 4217 3-letter alphabetic currency codes
Examples: C<EUR> (Euro), C<USD> (US Dollar), C<JPY> (Japanese Yen)
The currency code is case-insensitive and is required in order to call the
B<format> method, but not required to instantiate this formatter object.
=item currency_sign
Default: based on both B<locale> and B<currency_code>
Examples: C<US$> for B<root>, B<en-CA> with B<USD>; C<$> for B<en>, B<de> with
B<USD>; C<$US> for B<fr> with B<USD>; C<USD> for B<es-MX> with B<USD>
=item cash
Default: false (C<0>)
Formatting for cash can be different for some currencies. Setting B<cash> to
true (C<1>) enables cash formatting when different from standard formatting.
=item pattern
Examples: C<¤ #,##0.00> for B<root>; C<¤#,##0.00> for B<en>; C<#,##0.00 ¤> for
B<de>, B<fr>; C<¤ #,##0.00;¤ -#,##0.00> for B<nl>; and many other variations for
different locales
=item minimum_integer_digits
Examples: C<1> for all locales
=item minimum_fraction_digits
Examples: C<2> for most currencies; C<3> for B<BHD>; C<0> for B<JPY> or for
B<TWD> when B<cash> is true
=item maximum_fraction_digits
Examples: C<2> for most currencies; C<3> for B<BHD>; C<0> for B<JPY> or for
B<TWD> when B<cash> is true
=item primary_grouping_size
Examples: C<3> for B<root> and almost all locales
Not used when value is C<0>.
=item secondary_grouping_size
Examples: C<0> for B<root>, B<en>, and most locales; C<2> for B<hi>, B<bn>,
B<en-IN>, and other locales of the Indian subcontinent
Not used when value is C<0>.
=item minimum_grouping_digits
Examples: C<1> for B<root>, B<en>, and most locales; C<2> for C<es> (excluding
C<es-419>), C<pt-PT>, C<pl>, and several others; C<3> for C<lv> and C<my>
=item rounding_increment
Examples: C<0> for all currencies; C<5> for B<CAD>, B<CHF> when B<cash> is true
C<0> and C<1> are treated the same.
=back
lib/CLDR/Number/Format/Decimal.pm view on Meta::CPAN
=head1 VERSION
This document describes CLDR::Number::Format::Decimal v0.19, built with Unicode
CLDR v29.
=head1 SYNOPSIS
# either
use CLDR::Number::Format::Decimal;
$decf = CLDR::Number::Format::Decimal->new(locale => 'es');
# or
use CLDR::Number;
$cldr = CLDR::Number->new(locale => 'es');
$decf = $cldr->decimal_formatter;
# when locale is 'es' (Spanish)
say $decf->format(1234.5); # '1234,5'
# when locale is 'es-MX' (Mexican Spanish)
say $decf->format(1234.5); # '1,234.5'
# when locale is 'ar' (Arabic)
say $decf->format(1234.5); # '١٬٢٣٤٫٥'
# when locale is 'bn' (Bengali)
say $curf->format(123456); # '১,২৩,৪৫৬'
=head1 DEPRECATION
Using the C<locale> method as a setter is deprecated. In the future the objectâs
locale will become immutable. Please see
L<issue #38|https://github.com/patch/cldr-number-pm5/issues/38> for details and
to submit comments or concerns.
=head1 DESCRIPTION
Localized decimal formatter using the Unicode Common Locale Data Repository
(CLDR).
=head2 Methods
Any argument that Perl can treat as a number is supported, including infinity,
negative infinity, and NaN, which are all localized appropriately. All methods
return character strings, not encoded byte strings.
=over
=item format
Accepts a number and returns a formatted decimal, localized for the current
locale.
=item at_least
Accepts a number and returns a formatted decimal for at least the supplied
number.
say $decf->at_least(100); # '100+'
=item range
Accepts two numbers and returns a formatted range of decimals.
say $decf->range(1, 10); # '1â10'
=back
=head2 Attributes
The common attributes B<locale>, B<default_locale>, B<numbering_system>,
B<decimal_sign>, B<group_sign>, B<plus_sign>, B<minus_sign>, and B<cldr_version>
are described under L<common attributes in
CLDR::Number|CLDR::Number/"Common Attributes">. All attributes described here
have defaults that change depending on the current B<locale>. All string
attributes are expected to be character strings, not byte strings.
=over
=item pattern
Examples: C<#,##0.###> for B<root>, B<en>, and most locales; C<#,##,##0.###> for
B<hi>, B<bn>, B<en-IN>, and other locales of the Indian subcontinent
=item minimum_integer_digits
Examples: C<1> for all locales
=item minimum_fraction_digits
Examples: C<0> for all locales
=item maximum_fraction_digits
Examples: C<3> for B<root> and almost all locales
=item primary_grouping_size
Examples: C<3> for B<root> and almost all locales
Not used when value is C<0>.
=item secondary_grouping_size
Examples: C<0> for B<root>, B<en>, and most locales; C<2> for B<hi>, B<bn>,
B<en-IN>, and other locales of the Indian subcontinent
Not used when value is C<0>.
=item minimum_grouping_digits
Examples: C<1> for B<root>, B<en>, and most locales; C<2> for C<es> (excluding
C<es-419>), C<pt-PT>, C<pl>, and several others; C<3> for C<lv> and C<my>
=item rounding_increment
Examples: C<0> for all locales
C<0> and C<1> are treated the same.
=back
=head1 SEE ALSO
L<CLDR::Number>
=head1 AUTHOR
lib/CLDR/Number/Format/Percent.pm view on Meta::CPAN
has permil_sign => (
is => 'rw',
);
has _pattern_type => (
is => 'ro',
default => 'percent',
);
after _trigger_locale => sub {
my ($self) = @_;
$self->_build_signs(qw{ percent_sign permil_sign });
};
sub BUILD {}
sub format {
my ($self, $num) = @_;
my ($factor, $sign);
lib/CLDR/Number/Format/Percent.pm view on Meta::CPAN
=head1 VERSION
This document describes CLDR::Number::Format::Percent v0.19, built with Unicode
CLDR v29.
=head1 SYNOPSIS
# either
use CLDR::Number::Format::Percent;
$perf = CLDR::Number::Format::Percent->new(locale => 'tr');
# or
use CLDR::Number;
$cldr = CLDR::Number->new(locale => 'tr');
$perf = $cldr->percent_formatter;
# when locale is 'tr' (Turkish)
say $perf->format(0.05); # '%5'
# when locale is 'ar' (Arabic)
say $perf->format(0.05); # '٥٪'
# when locale is 'fr' (French)
say $perf->format(0.05); # '5Â %'
$perf->permil(1); # per mil
say $perf->format(0.05); # '50Â â°'
=head1 DEPRECATION
Using the C<locale> method as a setter is deprecated. In the future the objectâs
locale will become immutable. Please see
L<issue #38|https://github.com/patch/cldr-number-pm5/issues/38> for details and
to submit comments or concerns.
=head1 DESCRIPTION
Localized percent formatter using the Unicode Common Locale Data Repository
(CLDR).
=head2 Methods
=over
=item format
Accepts a number and returns a formatted percent as a character string,
localized for the current locale. If the B<permil> attribute is true, formats as
I<per mil> instead of I<percent>.
=back
=head2 Attributes
The common attributes B<locale>, B<default_locale>, B<numbering_system>,
B<decimal_sign>, B<group_sign>, B<plus_sign>, B<minus_sign>, and B<cldr_version>
are described under L<common attributes in
CLDR::Number|CLDR::Number/"Common Attributes">. All attributes described here
other than B<permil> have defaults that change depending on the current
B<locale>. All string attributes are expected to be character strings, not byte
strings.
=over
=item permil
Default: false (C<0>)
=item percent_sign
Examples: C<%> (percent sign) for all locales
=item permil_sign
Examples: C<â°> (per mille sign) for B<root> and almost all locales
=item pattern
Examples: C<#,##0%> for B<root>, B<en>; C<#,##0Â %> for B<de>, B<fr>;
C<#,##,##0%> for B<hi>, B<bn>, B<en-IN>, and other locales of the Indian
subcontinent
=item minimum_integer_digits
Examples: C<1> for all locales
=item minimum_fraction_digits
Examples: C<0> for all locales
=item maximum_fraction_digits
Examples: C<0> for all locales
=item primary_grouping_size
Examples: C<3> for B<root> and almost all locales
Not used when value is C<0>.
=item secondary_grouping_size
Examples: C<0> for B<root>, B<en>, and most locales; C<2> for B<hi>, B<bn>,
B<en-IN>, and other locales of the Indian subcontinent
Not used when value is C<0>.
=item minimum_grouping_digits
Examples: C<1> for B<root>, B<en>, and most locales; C<2> for C<es> (excluding
C<es-419>), C<pt-PT>, C<pl>, and several others; C<3> for C<lv> and C<my>
=item rounding_increment
Examples: C<0> for all locales
C<0> and C<1> are treated the same.
=back
=head1 SEE ALSO
L<CLDR::Number>
=head1 AUTHOR
lib/CLDR/Number/Role/Base.pm view on Meta::CPAN
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'
lib/CLDR/Number/Role/Base.pm view on Meta::CPAN
);
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) = @_;
lib/CLDR/Number/Role/Base.pm view on Meta::CPAN
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;
lib/CLDR/Number/Role/Base.pm view on Meta::CPAN
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;
lib/CLDR/Number/Role/Format.pm view on Meta::CPAN
is => 'rw',
);
has _negative_pattern => (
is => 'rw',
);
before BUILD => sub {
my ($self) = @_;
return if $self->_has_init_arg('locale');
$self->_build_pattern;
};
after _trigger_locale => sub {
my ($self) = @_;
$self->_build_pattern;
};
sub _build_pattern {
my ($self) = @_;
$self->_set_unless_init_arg(
pattern => $self->_get_data(pattern => $self->_pattern_type)
lib/CLDR/Number/TODO.pod view on Meta::CPAN
=item * number parsers
I<L<#19|https://github.com/patch/cldr-number-pm5/issues/19>>
=back
=head2 Optimization
=over
=item * deprecate mutable locales (in progress)
I<L<#38|https://github.com/patch/cldr-number-pm5/issues/38>>
=item * locale subtag attributes for use without locale attribute parsing
I<L<#4|https://github.com/patch/cldr-number-pm5/issues/4>>
=item * passing prebuilt locales to formatters from CLDR::Number
I<L<#5|https://github.com/patch/cldr-number-pm5/issues/5>>
=item * parsed pattern caching
I<L<#6|https://github.com/patch/cldr-number-pm5/issues/6>>
=back
=head1 SEE ALSO
=over
t/currency.t view on Meta::CPAN
use Test::Exception;
use CLDR::Number;
my ($cldr, $curf, $decf);
$cldr = CLDR::Number->new;
$curf = $cldr->currency_formatter;
throws_ok { $curf->format(1.99) } qr{Missing required attribute: currency_code};
{
# currency decimal is no longer used by any locale, so we manually add it here
# to test the feature in case itâs reintroduced in the future
local $CLDR::Number::Data::Base::DATA->{sv}{symbol}{currency_decimal} = ':';
$cldr = CLDR::Number->new(locale => 'sv');
is $cldr->decimal_sign, ',', 'Swedish decimal from format generator';
$decf = $cldr->decimal_formatter;
is $decf->decimal_sign, ',', 'Swedish decimal from decimal formatter';
is $decf->format(1.99), '1,99', 'formatted Swedish decimal';
$curf = $cldr->currency_formatter(currency_code => 'SEK');
is $curf->decimal_sign, ':', 'Swedish currency decimal from currency formatter';
is $curf->format(1.99), '1:99Â kr', 'formatted Swedish currency';
}
$curf = $cldr->currency_formatter(
locale => 'en-AU',
currency_code => 'AUD',
);
is $curf->format(10), '$10.00', 'en-AU with AUD uses currency sign $ instead of A$';
$curf = $cldr->currency_formatter(
locale => 'en',
currency_code => 'USD',
maximum_fraction_digits => 0,
);
is $curf->maximum_fraction_digits, 0, 'max frac digits spared by currency code';
is $curf->format(10), '$10', 'max frac digits spared by currency code';
$curf = $cldr->currency_formatter(
locale => 'en',
currency_code => 'USD',
pattern => '¤00',
);
is $curf->pattern, '¤00', 'pattern spared by locale on create';
is $curf->format(5), '$05', 'pattern spared by locale on create';
$curf = $cldr->currency_formatter(
currency_code => 'USD',
currency_sign => '!!!',
pattern => '¤ 0',
);
is $curf->currency_sign, '!!!', 'sign spared by currency code on create';
is $curf->format(1), '!!! 1', 'sign spared by currency code on create';
use open qw( :encoding(UTF-8) :std );
use Test::More tests => 60;
use Test::Warn;
use CLDR::Number;
my $cldr = CLDR::Number->new;
my $decf = $cldr->decimal_formatter;
my $perf = $cldr->percent_formatter;
my $curf = $cldr->currency_formatter(currency_code => 'EUR');
$decf->locale('en');
is $decf->format(5.0), '5';
is $decf->format(0), '0';
is $decf->format(.5), '0.5';
is $decf->format(.05), '0.05';
is $decf->format(.005), '0.005';
is $decf->format(50_000.05), '50,000.05';
is $decf->format(5_000_000.05), '5,000,000.05';
is $decf->format(5_000_000_000.05), '5,000,000,000.05';
is $decf->format(-50_000.05), '-50,000.05';
$decf->locale('fr');
is $decf->format(5.0), '5';
is $decf->format(0), '0';
is $decf->format(.5), '0,5';
is $decf->format(.05), '0,05';
is $decf->format(.005), '0,005';
is $decf->format(50_000.05), '50Â 000,05';
is $decf->format(5_000_000.05), '5Â 000Â 000,05';
is $decf->format(5_000_000_000.05), '5Â 000Â 000Â 000,05';
is $decf->format(-50_000.05), '-50Â 000,05';
$decf->locale('ar');
is $decf->format(-50.0), "\N{RIGHT-TO-LEFT MARK}-Ù¥Ù ";
is $decf->format(-50_000), "\N{RIGHT-TO-LEFT MARK}-Ù¥Ù Ù¬Ù Ù Ù ";
is $decf->format(-50.05), "\N{RIGHT-TO-LEFT MARK}-Ù¥Ù Ù«Ù Ù¥";
is $decf->format(-.05), "\N{RIGHT-TO-LEFT MARK}-Ù Ù«Ù Ù¥";
$decf->locale('en-IN');
is $decf->format(1_23_456), '1,23,456';
is $decf->format(1_23_45_678), '1,23,45,678';
warning_is {
is $decf->format(undef), undef, 'decimal format when undef';
} 'Use of uninitialized value in CLDR::Number::Format::Decimal::format';
warning_is {
is $decf->at_least(undef), undef, 'decimal at_least when undef';
} 'Use of uninitialized value in CLDR::Number::Format::Decimal::at_least';
warning_is {
my $perf = $cldr->percent_formatter;
is $perf->format(undef), undef, 'percent format when undef';
} 'Use of uninitialized value in CLDR::Number::Format::Percent::format';
warning_is {
my $curf = $cldr->currency_formatter(currency_code => 'EUR');
is $curf->format(undef), undef, 'currency format when undef';
} 'Use of uninitialized value in CLDR::Number::Format::Currency::format';
$decf->locale('it');
$perf->locale('it');
$curf->locale('it');
warning_is {
is $decf->format('X'), '0', 'decimal format when not num';
} q{Argument "X" isn't numeric in CLDR::Number::Format::Decimal::format};
warning_is {
is $decf->format('1.5X'), '1,5', 'decimal format when not all num';
} q{Argument "1.5X" isn't numeric in CLDR::Number::Format::Decimal::format};
warning_is {
t/from-shutterstock.t view on Meta::CPAN
use utf8;
use strict;
use warnings;
use open qw( :encoding(UTF-8) :std );
use Test::More tests => 59;
use CLDR::Number::Format::Currency;
# Tests using locales and currencies supported by Shutterstock
while (my $line = <DATA>) {
chomp $line;
my ($currency, $locale, $expected) = split /\t/, $line;
my $curf = CLDR::Number::Format::Currency->new(
locale => $locale,
currency_code => $currency,
);
is $curf->format(1000), $expected, "1000 $currency in $locale";
}
__DATA__
AUD en-AU $1,000.00
BRL en-BR R$1,000.00
BRL pt-BR R$1.000,00
CAD en-CA $1,000.00
CAD fr-CA 1Â 000,00Â $
CHF de-CH CHFÂ 1'000.00
CHF en-CH CHFÂ 1.000,00
t/from-twittercldr.t view on Meta::CPAN
use Test::More tests => 22;
use CLDR::Number;
my $cldr = CLDR::Number->new;
# Tests adapted from:
# TwitterCldr (twitter-cldr-rb)
# https://github.com/twitter/twitter-cldr-rb/tree/master/spec/formatters/numbers
# number_formatter_spec.rb
my $decf = $cldr->decimal_formatter(locale => 'sv');
is $decf->format(12), '12', 'format a basic integer';
is $decf->format(12.0), '12', 'format a basic decimal';
is $decf->format(1337), '1Â 337', 'formats an integer larger than 999';
is $decf->format(1337.37), '1Â 337,37', 'formats a decimal larger than 999.9';
$decf->maximum_fraction_digits(0); is $decf->format(12.1), '12', 'formats with precision of 0';
$decf->maximum_fraction_digits(1); is $decf->format(12.25), '12,2', 'half-even rounding and formats with precision of 1';
# decimal_formatter_spec.rb
$decf->locale('sv');
is $decf->format(12.0), '12', 'format positive decimals correctly';
is $decf->format(-12.0), 'â12', 'format negative decimals correctly';
$decf->minimum_fraction_digits(3);
is $decf->format(-12), 'â12,000', 'respect the minimum_fraction_digits attribute';
# percent_formatter_spec.rb
my $perf = $cldr->percent_formatter(locale => 'da');
is $perf->format(0.12), '12Â %', 'format the number correctly';
is $perf->format(-0.12), '-12Â %', 'format negative numbers correctly';
$perf->minimum_fraction_digits(3);
is $perf->format(-0.12), '-12,000Â %', 'respect the minimum_fraction_digits attribute';
# currency_formatter_spec.rb
my $curf = $cldr->currency_formatter(locale => 'ko', currency_code => 'USD');
is $curf->format(12), 'US$12.00', 'handles positive numbers';
is $curf->format(-12), '-US$12.00', 'handles negative numbers';
$curf->locale('ms');
$curf->currency_sign('S/.'); is $curf->format(12), 'S/. 12.00', 'use the specified currency symbol when specified';
$curf->currency_code('XYZ'); is $curf->format(12), 'XYZÂ 12.00', 'use the currency code as the symbol if the currency code cannot be identified';
$curf->currency_code('THB'); is $curf->format(12), 'THBÂ 12.00', 'use the currency symbol for the corresponding currency code';
$curf->currency_code('TND'); is $curf->format(12), 'TNDÂ 12.000', 'use the currency-specific default minimum fraction digits';
$curf->currency_code('CAD'); is $curf->format(12), 'CADÂ 12.00', 'use the currency-specific default minimum fraction digits';
$curf->minimum_fraction_digits(3); is $curf->format(12), 'CADÂ 12.000', 'overrides the default minimum fraction digits';
$curf->currency_code('CHF');
$curf->rounding_increment(0.05); # TODO: should this be 5?
is $curf->format(12.03), 'CHFÂ 12.05', 'use the currency rounding for the currency code';
t/from-uts35.t view on Meta::CPAN
use CLDR::Number;
my $cldr = CLDR::Number->new;
my ($decf, $perf, $scif, $curf);
# Tests adapted from examples in:
# UTS #35: Unicode LDML, Part 1: Core
# http://www.unicode.org/reports/tr35/tr35.html
TODO: {
local $TODO = 'Unicode locale extensions not currently retained';
# 3.7 Unicode BCP 47 Extension Data
$cldr->locale('th-u-foo-bar-nu-thai-ca-buddhist');
is $cldr->locale, 'th-u-bar-foo-ca-buddhist-nu-thai', 'sort attributes & keywords';
};
# Tests adapted from examples in:
# UTS #35: Unicode LDML, Part 3: Numbers
# http://www.unicode.org/reports/tr35/tr35-numbers.html
# 2.3 Number Symbols
$decf = $cldr->decimal_formatter(locale => 'en');
$decf->pattern('#,###'); is $decf->format(100_000_000), '100,000,000', 'group by 3';
$decf->pattern('#,####'); is $decf->format(1_0000_0000), '1,0000,0000', 'group by 4';
$decf->pattern('#,##,###'); is $decf->format(12_34_56_789), '12,34,56,789', 'primary group by 3, secondary group by 2';
$decf->pattern('###,###,####'); is $decf->format(100_000_0000), '100,000,0000', 'primary group by 4, secondary group by 3';
$decf->pattern('#,##,###,####'); is $decf->format(100_000_0000), '100,000,0000', 'ignore tertiary group';
$decf->pattern('##,#,###,####'); is $decf->format(100_000_0000), '100,000,0000', 'ignore tertiary group';
$perf = $cldr->percent_formatter(locale => 'en', permil => 1);
is $perf->format(1.23), '1,230â°', 'per mille multiplied by 1,000 before formatting';
SKIP: {
skip 'format_short NYI', 1;
# 2.4.1 Compact Number Formats
$decf = $cldr->decimal_formatter(locale => 'fr');
is $decf->format_short(12_345), '12Â K', 'short decimal format';
};
# 2.4.2 Currency Formats
$curf = $cldr->currency_formatter(locale => 'en', currency_code => 'USD');
$curf->pattern('¤#,##0.00'); is $curf->format(-3.27), '-$3.27', 'default negative currency';
$curf->pattern('¤#,##0.00;(¤#,##0.00)'); is $curf->format(-3.27), '($3.27)', 'custom negative currency';
# 2.5 Miscellaneous Patterns
$decf = $cldr->decimal_formatter(locale => 'en');
is $decf->at_least(99), '99+', 'at least 99';
is $decf->range(99, 103), '99â103', 'range from 99 to 103';
# 3.1 Number Patterns
$decf = $cldr->decimal_formatter(locale => 'fr');
$decf->pattern('#,##0.##'); is $decf->format(1_234.567), '1Â 234,57';
$decf->pattern('#,##0.###'); is $decf->format(1_234.567), '1Â 234,567';
$decf->pattern('###0.#####'); is $decf->format(1_234.567), '1234,567';
$decf->pattern('###0.0000#'); is $decf->format(1_234.567), '1234,5670';
$decf->pattern('00000.0000'); is $decf->format(1_234.567), '01234,5670';
$curf = $cldr->currency_formatter(locale => 'fr', pattern => '#,##0.00 ¤');
$curf->currency_code('EUR'); is $curf->format(1_234.567), '1 234,57 â¬';
$curf->currency_code('JPY'); is $curf->format(1_234.567), '1Â 235Â JPY';
# 3.2 Special Pattern Characters
$decf = $cldr->decimal_formatter(locale => 'en');
$decf->pattern("'#'#"); is $decf->format(123), '#123', 'quote special characters';
$decf->pattern("# o''clock"); is $decf->format(1), "1 o'clock", 'single quote itself';
# minimumGroupingDigits
$decf = $cldr->decimal_formatter(locale => 'pl');
is $decf->minimum_grouping_digits, 2, 'pl: default min group';
is $decf->primary_grouping_size, 3, 'pl: default primary_grouping_size';
is $decf->format(9_999), '9999', 'pl: under min group';
is $decf->format(10_000), '10Â 000', 'pl: at min group';
$decf = $cldr->decimal_formatter(locale => 'en');
is $decf->minimum_grouping_digits, 1, 'en: default min group';
is $decf->primary_grouping_size, 3, 'en: default primary_grouping_size';
is $decf->format(1_000), '1,000', 'en: at min group';
is $decf->format(10_000), '10,000', 'en: over min group';
$decf->minimum_grouping_digits(2);
is $decf->format(1_000), '1000', 'under custom min group';
is $decf->format(10_000), '10,000', 'at custom min group';
$decf->minimum_grouping_digits(1);
$decf->primary_grouping_size(4);
is $decf->format(10_000), '1,0000', 'at min group w/ custom grouping size';
$decf->minimum_grouping_digits(2);
is $decf->format(10_000), '10000', 'under min group w/ custom grouping size';
# 3.3 Formatting
$decf = $cldr->decimal_formatter(locale => 'en');
# TODO: maximum integer digits
$decf->pattern('00000'); is $decf->format(1997), '01997', 'minimum integer digits';
$decf->pattern('0.##'); is $decf->format(0.125), '0.12', 'maximum fraction digits';
$decf->pattern('0.0000'); is $decf->format(0.125), '0.1250', 'minimum fraction digits';
$decf->pattern('0.####'); is $decf->format(0.10004), '0.1', 'trailing fractional zeros are not displayed';
# 3.4 Scientific Notation
SKIP: {
skip 'scientific_formatter NYI', 7;
$scif = $cldr->scientific_formatter(locale => 'en');
$scif->pattern('0.###E0');
is $scif->format(1234), '1.234E3', 'scientific notation';
$scif->pattern('0.###E+0');
is $scif->format(10), '1E+1', 'scientific with explicit positive exponent';
is $scif->format(1), '1E+0', 'scientific with explicit positive exponent';
is $scif->format(0.1), '1E-1', 'scientific with explicit positive exponent when negative';
$scif->pattern('00.###E0'); is $scif->format(0.00123), '12.3E-4', 'scientific with minimum integer digits';
$scif->pattern('##0.####E0'); is $scif->format(12345), '12.345E3', 'scientific with maximum integer digits';
$scif->pattern('##0.##E0'); is $scif->format(12345), '12.3E3', 'scientific with significant digits logic';
};
# 3.5 Significant Digits
SKIP: {
skip 'significant digits NYI', 5;
$decf = $cldr->decimal_formatter(locale => 'en');
$decf->pattern('@@@'); is $decf->format(12345), '12300', 'significant digits; min/max: 3';
$decf->pattern('@@@'); is $decf->format(0.12345), '0.123', 'significant digits; min/max: 3';
$decf->pattern('@@##'); is $decf->format(3.14159), '3.142', 'significant digits; min: 2, max: 4';
$decf->pattern('@@##'); is $decf->format(1.23004), '1.23', 'significant digits; min: 2, max: 4';
$decf->pattern('@##'); is $decf->format(0.1203), '0.12', 'significant digits; min: 1, max: 3';
}
# 3.6 Padding
TODO: {
local $TODO = 'padding NYI';
$curf = $cldr->currency_formatter(locale => 'en', currency_code => 'USD');
$curf->pattern('¤*x#,##0.00');
is $curf->format(123), '$xx123.00', 'padding (applied)';
}
is $curf->format(1234), '$1,234.00', 'padding (not applied)';
# Rounding
$decf = $cldr->decimal_formatter(locale => 'en');
$decf->pattern('0.65');
is $decf->format(1.234), '1.30', 'rounding to 0.65';
# 3.7 Quoting Rules
$decf = $cldr->decimal_formatter(locale => 'en');
$decf->pattern("'X '#' Q '");
is $decf->format(1939), 'X 1939 Q ', 'pattern quoting';
# 4 Currencies
$curf = $cldr->currency_formatter(currency_code => 'USD');
$curf->locale('lg');
is $curf->currency_sign, 'US$', 'expected currency sign';
is $curf->pattern, '#,##0.00¤', 'expected pattern';
is $curf->format(1), '1.00Â US$', 'currency spacing inserted';
$curf->locale('ak');
is $curf->currency_sign, 'US$', 'expected currency sign';
is $curf->pattern, '¤#,##0.00', 'expected pattern';
is $curf->format(1), 'US$1.00', 'no currency spacing inserted';
$curf->currency_code('RUR');
$curf->locale('ru'); is $curf->format(1234.57), '1Â 234,57Â Ñ.', 'RUR in ru';
$curf->locale('en'); is $curf->format(1234.57), 'RURÂ 1,234.57', 'RUR in en';
t/inf-nan.t view on Meta::CPAN
use strict;
use warnings;
use open qw( :encoding(UTF-8) :std );
use Test::More tests => 28;
use CLDR::Number;
my $inf = 9**9**9;
my $neg = -$inf;
my $nan = -sin($inf);
my $cldr = CLDR::Number->new(locale => 'en');
my $decf = $cldr->decimal_formatter;
my $perf = $cldr->percent_formatter;
my $curf = $cldr->currency_formatter(currency_code => 'EUR');
is $cldr->infinity, 'â', 'infinity attribute';
is $cldr->nan, 'NaN', 'nan attribute';
is $decf->format($inf), 'â', 'format infinity';
is $decf->format($neg), '-â', 'format negative infinity';
is $decf->format($nan), 'NaN', 'format NaN';
t/inf-nan.t view on Meta::CPAN
is $curf->format($inf), 'â¬â', 'format infinity euros';
is $curf->format($neg), '-â¬â', 'format negative infinity euros';
is $curf->format($nan), 'â¬NaN', 'format NaN euros';
is $decf->at_least($inf), 'â+', 'format at least infinity';
is $decf->at_least($nan), 'NaN+', 'format at least NaN';
is $decf->range($neg, $inf), '-âââ', 'format range of infinity';
is $decf->range($nan, $nan), 'NaNâNaN', 'format range of NaN';
$cldr = CLDR::Number->new(locale => 'dz');
$decf = $cldr->decimal_formatter;
$perf = $cldr->percent_formatter;
$curf = $cldr->currency_formatter(currency_code => 'BTN');
is $cldr->infinity, 'à½à¾²à½à½¦à¼à½à½ºà½', 'infinity attribute (dz)';
is $cldr->nan, 'ཨà½à¼à½à½', 'nan attribute (dz)';
is $decf->format($inf), 'à½à¾²à½à½¦à¼à½à½ºà½', 'format infinity (dz)';
is $decf->format($neg), '-à½à¾²à½à½¦à¼à½à½ºà½', 'format negative infinity (dz)';
is $decf->format($nan), 'ཨà½à¼à½à½', 'format NaN (dz)';
t/inheritance.t view on Meta::CPAN
use utf8;
use strict;
use warnings;
use open qw( :encoding(UTF-8) :std );
use Test::More tests => 15;
use Test::Differences;
use CLDR::Number;
my $cldr = CLDR::Number->new;
$cldr->locale('ar-DZ');
is $cldr->decimal_sign, ',', 'decimal directly from ar-DZ';
$cldr->locale('ar-EG');
is $cldr->decimal_sign, 'Ù«', 'decimal inherited from ar';
$cldr->locale('lu');
is $cldr->decimal_sign, ',', 'decimal directly from lu';
is $cldr->minus_sign, '-', 'minus inherited from root';
$cldr->locale('es-US');
is $cldr->decimal_sign, '.', 'decimal inherited from es-419, not es';
is $cldr->group_sign, ',', 'group inherited from es-419, not es';
{
# currency decimal is no longer used by any locale, so we manually add it here
# to test the feature in case itâs reintroduced in the future
local $CLDR::Number::Data::Base::DATA->{sv}{symbol}{currency_decimal} = ':';
my $curf = $cldr->currency_formatter(locale => 'sv-FI');
is $curf->decimal_sign, ':', 'currency decimal inherited from sv';
}
my $curf = $cldr->currency_formatter(locale => 'en-NZ');
$curf->currency_code('NZD');
is $curf->currency_sign, '$', 'currency sign directly from en-NZ';
$curf->currency_code('JPY');
is $curf->currency_sign, 'JPÂ¥', 'currency sign inherited from en-001';
$cldr->locale('sr-Cyrl-XK');
eq_or_diff(
$cldr->_locale_inheritance,
[qw( sr-Cyrl-XK sr-Cyrl sr root )],
'locale inheritance'
);
$cldr->locale('root');
eq_or_diff(
$cldr->_locale_inheritance,
[qw( root )],
'root has a single level of inheritance'
);
$cldr->locale('es-MX');
eq_or_diff(
$cldr->_locale_inheritance,
[qw( es-MX es-419 es root )],
'locale inheritance with added step'
);
$cldr->locale('az-Cyrl');
eq_or_diff(
$cldr->_locale_inheritance,
[qw( az-Cyrl root )],
'locale inheritance with removed step'
);
$cldr->locale('zh-Hant-MO');
eq_or_diff(
$cldr->_locale_inheritance,
[qw( zh-Hant-MO zh-Hant-HK zh-Hant root )],
'locale inheritance with added and removed steps'
);
$cldr->locale('en-US-u-va-posix');
eq_or_diff(
$cldr->_locale_inheritance,
[qw( en-US-u-va-posix en root )],
'locale inheritance with Unicode extension'
);
t/locales.t view on Meta::CPAN
use strict;
use warnings;
use open qw( :encoding(UTF-8) :std );
use Test::More tests => 24;
use Test::Warn;
use CLDR::Number;
my $cldr = CLDR::Number->new;
# conversion
$cldr->locale('zh_Hant_HK');
is $cldr->locale, 'zh-Hant-HK', 'convert undercore to dash';
$cldr->locale('ZH-Hant-HK');
is $cldr->locale, 'zh-Hant-HK', 'convert language to lowercase';
$cldr->locale('zh-hANT-hk');
is $cldr->locale, 'zh-Hant-HK', 'convert script to titlecase';
$cldr->locale('zh-Hant-hk');
is $cldr->locale, 'zh-Hant-HK', 'convert region to uppercase';
$cldr->locale('AST');
is $cldr->locale, 'ast', 'convert 3-letter language to lowercase';
$cldr->locale('en-');
is $cldr->locale, 'en', 'allow trailing dash and remove';
$cldr->locale('fr_');
is $cldr->locale, 'fr', 'allow trailing underscore and remove';
# BCP 47 conversion
$cldr->locale('und');
is $cldr->locale, 'root', 'und â root';
# Unicode locale extensions
TODO: {
local $TODO = 'Unicode locale extensions not currently retained';
$cldr->locale('ja-u-nu-fullwide-cu-jpy');
is $cldr->locale, 'ja-u-cu-jpy-nu-fullwide', 'sort keywords';
};
# defaults
$cldr = CLDR::Number->new;
is $cldr->locale, 'root', 'locale is root when undefined with no default';
ok !$cldr->default_locale, 'no default for the default locale';
$cldr->locale('xx');
is $cldr->locale, 'root', 'locale is root when invalid with no default';
warning_is {
$cldr = CLDR::Number->new(default_locale => 'xx');
ok !$cldr->default_locale, 'default locale does not fallback like locale';
} q{default_locale 'xx' is unknown};
$cldr = CLDR::Number->new(default_locale => 'en-GB');
is $cldr->default_locale, 'en-GB', 'default locale is set';
is $cldr->locale, 'en-GB', 'locale is default when undefined with default';
$cldr->locale('xx');
is $cldr->locale, 'en-GB', 'locale is default when invalid with default';
# fallbacks
$cldr = CLDR::Number->new;
$cldr->locale('en-XX');
is $cldr->locale, 'en', 'locale is language when invalid country';
$cldr->locale('eo-IR');
is $cldr->locale, 'eo', 'locale is language when unavailable country';
$cldr->locale('en-Xxxx');
is $cldr->locale, 'en', 'locale is language when invalid script';
$cldr->locale('zh-Latn');
is $cldr->locale, 'zh', 'locale is language when unavailable script';
$cldr->locale('zh-Hant-GB');
is $cldr->locale, 'zh-Hant', 'locale is language-script when unavailable country';
$cldr->locale('en-Hant-GB');
is $cldr->locale, 'en-GB', 'locale is language-country when unavailable script';
$cldr->locale('es-419');
is $cldr->locale, 'es-419', 'numeric regions are supported';
t/minmax-digits.t view on Meta::CPAN
minimum_fraction_digits => 1,
maximum_fraction_digits => 2,
);
is $decf->minimum_integer_digits, 2, 'set min integer digits on create';
is $decf->minimum_fraction_digits, 1, 'set min fraction digits on create';
is $decf->maximum_fraction_digits, 2, 'set max fraction digits on create';
is $decf->format(5), '05.0', 'integer less than min';
my $curf = $cldr->currency_formatter(locale => 'en', currency_code => 'USD');
is $curf->minimum_fraction_digits, 2, 'default currency min fraction digits';
is $curf->maximum_fraction_digits, 2, 'default currency max fraction digits';
is $curf->format(5), '$5.00', 'fraction less than min';
is $curf->format(7.777), '$7.78', 'fraction greater than max';
t/numbering-system.t view on Meta::CPAN
use utf8;
use strict;
use warnings;
use open qw( :encoding(UTF-8) :std );
use Test::More tests => 29;
use Test::Warn;
use CLDR::Number;
my $cldr = CLDR::Number->new(locale => 'en');
my $decf = $cldr->decimal_formatter;
my $perf = $cldr->percent_formatter;
my $curf = $cldr->currency_formatter(currency_code => 'USD');
can_ok $cldr, 'numbering_system';
can_ok $decf, 'numbering_system';
can_ok $perf, 'numbering_system';
can_ok $curf, 'numbering_system';
is $cldr->numbering_system, 'latn', 'default numbering system (base)';
t/numbering-system.t view on Meta::CPAN
is $cldr->numbering_system, 'thai', 'set numbering system to thai (base)';
is $decf->numbering_system, 'thai', 'set numbering system to thai (decimal)';
is $perf->numbering_system, 'thai', 'set numbering system to thai (percent)';
is $curf->numbering_system, 'thai', 'set numbering system to thai (currency)';
is $decf->format(1234.09), 'à¹,à¹à¹à¹.à¹à¹', 'format in thai (decimal)';
is $perf->format(1234.09), 'à¹à¹à¹,à¹à¹à¹%', 'format in thai (percent)';
is $curf->format(1234.09), '$à¹,à¹à¹à¹.à¹à¹', 'format in thai (currency)';
$cldr->locale('en-u-nu-latn');
is $cldr->numbering_system, 'latn', 'set numbering system to latn via locale';
$cldr->locale('en-u-nu-thai');
is $cldr->numbering_system, 'thai', 'set numbering system to thai via locale';
$decf->locale('ar');
is $decf->numbering_system, 'arab', 'default numbering system (ar)';
is $decf->format(1234.09), '١٬٢٣٤٫٠٩', 'format in arab (ar)';
$decf->locale('ar-DZ');
is $decf->numbering_system, 'latn', 'default numbering system (ar-DZ)';
is $decf->format(1234.09), '1.234,09', 'format in latn (ar-DZ)';
$decf->locale('uz');
is $decf->numbering_system, 'latn', 'default numbering system (uz)';
is $decf->format(1234.09), '1Â 234,09', 'format in latn (uz)';
$decf->locale('uz-Arab');
is $decf->numbering_system, 'arabext', 'default numbering system (uz-Arab)';
is $decf->format(1234.09), 'Û±Ù¬Û²Û³Û´Ù«Û°Û¹', 'format in arabext (uz-Arab)';
$cldr = CLDR::Number->new(locale => 'bn');
is $cldr->numbering_system, 'beng', 'num sytem on generator instantiation';
$decf = $cldr->decimal_formatter(locale => 'ar');
is $decf->numbering_system, 'arab', 'num system on formatter instantiation';
warning_is {
$cldr = CLDR::Number->new(locale => 'ar', numbering_system => 'xxxx');
is $cldr->numbering_system, 'arab', 'never set unknown numbering system';
} q{numbering_system 'xxxx' is unknown};
t/objects.t view on Meta::CPAN
use utf8;
use strict;
use warnings;
use open qw( :encoding(UTF-8) :std );
use Test::More tests => 31;
use CLDR::Number;
use CLDR::Number::Data::Base;
my $cldr = new_ok 'CLDR::Number' => [locale => 'zh'], 'CLDR::Number';
is $cldr->locale, 'zh', 'generator locale set on instantiation';
$cldr->locale('ja');
is $cldr->locale, 'ja', 'generator locale updated';
is $cldr->version, $CLDR::Number::VERSION,
'version attribute matches $VERSION';
is $cldr->version, $CLDR::Number::Data::Base::VERSION,
'version attribute matches data $VERSION';
is $cldr->cldr_version, $CLDR::Number::Data::Base::CLDR_VERSION,
'cldr_version attribute matches data $CLDR_VERSION';
my $decf = $cldr->decimal_formatter;
isa_ok $decf, 'CLDR::Number::Format::Decimal';
is $decf->locale, 'ja', 'generator locale passed to formatter';
$decf->locale('ko');
is $decf->locale, 'ko', 'formatter locale updated';
is $cldr->locale, 'ja', 'generator locale remains the same';
$cldr->locale('vi');
is $cldr->locale, 'vi', 'generator locale updated';
is $decf->locale, 'ko', 'formatter locale remains the same';
$decf = $cldr->decimal_formatter(
locale => 'en',
minimum_integer_digits => 2,
maximum_integer_digits => 3,
minimum_fraction_digits => 1,
maximum_fraction_digits => 2,
primary_grouping_size => 2,
secondary_grouping_size => 1,
minimum_grouping_digits => 2,
rounding_increment => 2,
);
is $decf->minimum_integer_digits, 2, 'min int spared by locale on create';
is $decf->maximum_integer_digits, 3, 'max int spared by locale on create';
is $decf->minimum_fraction_digits, 1, 'min frac spared by locale on create';
is $decf->maximum_fraction_digits, 2, 'max frac spared by locale on create';
is $decf->primary_grouping_size, 2, '1st group spared by locale on create';
is $decf->secondary_grouping_size, 1, '2nd group spared by locale on create';
is $decf->minimum_grouping_digits, 2, 'min group spared by locale on create';
is $decf->rounding_increment, 2, 'rounding spared by locale on create';
$decf = $cldr->decimal_formatter(
locale => 'en',
pattern => '00.0#',
);
is $decf->pattern, '00.0#', 'pattern spared by locale on create';
is $decf->format(5), '05.0', 'pattern spared by locale on create';
my $perf = $cldr->percent_formatter;
my $curf = $cldr->currency_formatter;
ok !$cldr->can('has'), 'generator: has should not be inherited';
ok !$decf->can('has'), 'decimal: has should not be inherited';
ok !$perf->can('has'), 'percent: has should not be inherited';
ok !$curf->can('has'), 'currency: has should not be inherited';
ok !$cldr->can('croak'), 'generator: croak should not be inherited';
ok !$decf->can('croak'), 'decimal: croak should not be inherited';
t/quoting.t view on Meta::CPAN
use utf8;
use strict;
use warnings;
use open qw( :encoding(UTF-8) :std );
use Test::More tests => 7;
use CLDR::Number;
my $cldr = CLDR::Number->new;
my $decf = $cldr->decimal_formatter(locale => 'en');
$decf->pattern("'foo'"); is $decf->format(123), 'foo';
$decf->pattern("'#'"); is $decf->format(123), '#';
$decf->pattern("'#"); is $decf->format(123), '#';
$decf->pattern("#'#'"); is $decf->format(123), '123#';
$decf->pattern("#'#"); is $decf->format(123), '123#';
$decf->pattern("''#''"); is $decf->format(123), "'123'";
$decf->pattern("'#''#'"); is $decf->format(123), "#'#";
use utf8;
use strict;
use warnings;
use open qw( :encoding(UTF-8) :std );
use Test::More tests => 6;
use CLDR::Number;
my ($cldr, $decf, $perf, $curf);
$cldr = CLDR::Number->new(locale => 'en');
$decf = $cldr->decimal_formatter;
$perf = $cldr->percent_formatter;
$curf = $cldr->currency_formatter(currency_code => 'EUR');
is $decf->range(1, 5), '1â5', 'range of numbers (en)';
is $perf->range(0.01, 0.05), '1%â5%', 'range of percents (en)';
is $curf->range(1, 5), 'â¬1.00ââ¬5.00', 'range of prices (en)';
$cldr = CLDR::Number->new(locale => 'es-CO');
$decf = $cldr->decimal_formatter;
$perf = $cldr->percent_formatter;
$curf = $cldr->currency_formatter(currency_code => 'COP');
is $decf->range(1, 5), 'de 1 a 5', 'range of numbers (es-CO)';
is $perf->range(0.01, 0.05), 'de 1% a 5%', 'range of percents (es-CO)';
is $curf->range(1, 5), 'de $Â 1,00 a $Â 5,00', 'range of prices (es-CO)';
t/rounding.t view on Meta::CPAN
use utf8;
use strict;
use warnings;
use open qw( :encoding(UTF-8) :std );
use Test::More tests => 37;
use CLDR::Number;
my $cldr = CLDR::Number->new;
my $decf = $cldr->decimal_formatter(locale => 'fr');
$decf->maximum_fraction_digits(1);
is $decf->format(0.05), '0';
is $decf->format(0.051), '0,1';
is $decf->format(0.149), '0,1';
is $decf->format(0.15), '0,2';
is $decf->format(0.25), '0,2';
is $decf->format(0.251), '0,3';
is $decf->format(0.349), '0,3';
is $decf->format(0.35), '0,4';