File Coverage

blib/lib/Locale/CLDR.pm
Criterion Covered Total %
statement 985 1402 70.2
branch 240 464 51.7
condition 78 217 35.9
subroutine 143 183 78.1
pod 53 53 100.0
total 1499 2319 64.6


line stmt bran cond sub pod time code
1             package Locale::CLDR;
2              
3             =encoding utf8
4              
5             =head1 NAME
6              
7             Locale::CLDR - A Module to create locale objects with localisation data from the CLDR
8              
9             =head1 VERSION
10              
11             Version 0.28.1
12              
13             =head1 SYNOPSIS
14              
15             This module provides a locale object you can use to localise your output.
16             The localisation data comes from the Unicode Common Locale Data Repository.
17             Most of this code can be used with Perl version 5.10.1 or above. There are a
18             few parts of the code that require version 5.18 or above.
19              
20             =head1 USAGE
21              
22             my $locale = Locale::CLDR->new('en_US');
23              
24             or
25              
26             my $locale = Locale::CLDR->new(language_id => 'en', region_id => 'us');
27            
28             A full locale identifier is
29            
30             C<language>_C<script>_C<region>_C<variant>_u_C<extension name>_C<extension value>
31            
32             my $locale = Locale::CLDR->new('en_latn_US_SCOUSE_u_nu_traditional');
33            
34             or
35            
36             my $locale = Locale::CLDR->new(language_id => 'en', script_id => 'latn', region_id => 'US', variant => 'SCOUSE', extensions => { nu => 'traditional' } );
37            
38             =cut
39              
40 20     20   585595 use v5.10.1;
  20         77  
41 20     20   15220 use version;
  20         42024  
  20         194  
42             our $VERSION = version->declare('v0.28.1');
43              
44 20     20   33986 use open ':encoding(utf8)';
  20         37885  
  20         1302  
45 20     20   297142 use utf8;
  20         55  
  20         126  
46 20     20   1603 use if $^V ge v5.12.0, feature => 'unicode_strings';
  20         43  
  20         984  
47              
48 20     20   20190 use Moose;
  20         10106834  
  20         138  
49 20     20   167993 use MooseX::ClassAttribute;
  20         1998265  
  20         108  
50             with 'Locale::CLDR::ValidCodes', 'Locale::CLDR::EraBoundries', 'Locale::CLDR::WeekData',
51             'Locale::CLDR::MeasurementSystem', 'Locale::CLDR::LikelySubtags', 'Locale::CLDR::NumberingSystems',
52             'Locale::CLDR::NumberFormatter', 'Locale::CLDR::RegionContainment', 'Locale::CLDR::CalendarPreferences',
53             'Locale::CLDR::Currencies', 'Locale::CLDR::Plurals';
54            
55 20     20   6340030 use Class::Load;
  20         52  
  20         979  
56 20     20   157 use namespace::autoclean;
  20         42  
  20         224  
57 20     20   1982 use List::Util qw(first);
  20         40  
  20         1301  
58 20     20   103 use Class::MOP;
  20         38  
  20         432  
59 20     20   20586 use DateTime::Locale;
  20         1462053  
  20         726  
60 20     20   46886 use Unicode::Normalize();
  20         5526829  
  20         6911  
61 20     20   20669 use Locale::CLDR::Collator();
  20         82  
  20         753  
62 20     20   181 use File::Spec();
  20         44  
  20         2924  
63              
64             # Backwards compatibility
65             BEGIN {
66 20 50   20   97 if (defined &CORE::fc) { #v5.16
67 20         29106 *fc = \&CORE::fc;
68             }
69             else {
70             # We only use fc() with code that expects Perl v5.18 or above
71 0         0 *fc = sub {};
72             }
73             }
74              
75             =head1 ATTRIBUTES
76              
77             These can be passed into the constructor and all are optional.
78              
79             =over 4
80              
81             =item language_id
82              
83             A valid language or language alias id, such as C<en>
84              
85             =cut
86              
87             has 'language_id' => (
88             is => 'ro',
89             isa => 'Str',
90             required => 1,
91             );
92              
93             # language aliases
94             around 'language_id' => sub {
95             my ($orig, $self) = @_;
96             my $value = $self->$orig;
97             return $self->language_aliases->{$value} // $value;
98             };
99              
100             =item script_id
101              
102             A valid script id, such as C<latn> or C<Ctcl>. The code will pick a likely script
103             depending on the given language if non is provided.
104              
105             =cut
106              
107             has 'script_id' => (
108             is => 'ro',
109             isa => 'Str',
110             default => '',
111             predicate => 'has_script',
112             );
113              
114             =item region_id
115              
116             A valid region id or region alias such as C<GB>
117              
118             =cut
119              
120             has 'region_id' => (
121             is => 'ro',
122             isa => 'Str',
123             default => '',
124             predicate => 'has_region',
125             );
126              
127             # region aliases
128             around 'region_id' => sub {
129             my ($orig, $self) = @_;
130             my $value = $self->$orig;
131             my $alias = $self->region_aliases->{$value};
132             return $value if ! defined $alias;
133             return (split /\s+/, $alias)[0];
134             };
135              
136             =item variant_id
137              
138             A valid variant id. The code currently ignores this
139              
140             =cut
141              
142             has 'variant_id' => (
143             is => 'ro',
144             isa => 'Str',
145             default => '',
146             predicate => 'has_variant',
147             );
148              
149             =item extensions
150              
151             A Hashref of extension names and values. You can use this to override
152             the locales number formatting and calendar by passing in the Unicode
153             extension names or aliases as keys and the extension value as the hash
154             value.
155              
156             Currently supported extensions are
157              
158             =over 8
159              
160             =item nu
161              
162             =item numbers
163              
164             The number type can be one of
165              
166             =over 12
167              
168             =item arab
169              
170             Arabic-Indic Digits
171              
172             =item arabext
173              
174             Extended Arabic-Indic Digits
175              
176             =item armn
177              
178             Armenian Numerals
179              
180             =item armnlow
181              
182             Armenian Lowercase Numerals
183              
184             =item bali
185              
186             Balinese Digits
187              
188             =item beng
189              
190             Bengali Digits
191              
192             =item brah
193              
194             Brahmi Digits
195              
196             =item cakm
197              
198             Chakma Digits
199              
200             =item cham
201              
202             Cham Digits
203              
204             =item deva
205              
206             Devanagari Digits
207              
208             =item ethi
209              
210             Ethiopic Numerals
211              
212             =item finance
213              
214             Financial Numerals
215              
216             =item fullwide
217              
218             Full Width Digits
219              
220             =item geor
221              
222             Georgian Numerals
223              
224             =item grek
225              
226             Greek Numerals
227              
228             =item greklow
229              
230             Greek Lowercase Numerals
231              
232             =item gujr
233              
234             Gujarati Digits
235              
236             =item guru
237              
238             Gurmukhi Digits
239              
240             =item hanidays
241              
242             Chinese Calendar Day-of-Month Numerals
243              
244             =item hanidec
245              
246             Chinese Decimal Numerals
247              
248             =item hans
249              
250             Simplified Chinese Numerals
251              
252             =item hansfin
253              
254             Simplified Chinese Financial Numerals
255              
256             =item hant
257              
258             Traditional Chinese Numerals
259              
260             =item hantfin
261              
262             Traditional Chinese Financial Numerals
263              
264             =item hebr
265              
266             Hebrew Numerals
267              
268             =item java
269              
270             Javanese Digits
271              
272             =item jpan
273              
274             Japanese Numerals
275              
276             =item jpanfin
277              
278             Japanese Financial Numerals
279              
280             =item kali
281              
282             Kayah Li Digits
283              
284             =item khmr
285              
286             Khmer Digits
287              
288             =item knda
289              
290             Kannada Digits
291              
292             =item lana
293              
294             Tai Tham Hora Digits
295              
296             =item lanatham
297              
298             Tai Tham Tham Digits
299              
300             =item laoo
301              
302             Lao Digits
303              
304             =item latn
305              
306             Western Digits
307              
308             =item lepc
309              
310             Lepcha Digits
311              
312             =item limb
313              
314             Limbu Digits
315              
316             =item mlym
317              
318             Malayalam Digits
319              
320             =item mong
321              
322             Mongolian Digits
323              
324             =item mtei
325              
326             Meetei Mayek Digits
327              
328             =item mymr
329              
330             Myanmar Digits
331              
332             =item mymrshan
333              
334             Myanmar Shan Digits
335              
336             =item native
337              
338             Native Digits
339              
340             =item nkoo
341              
342             N'Ko Digits
343              
344             =item olck
345              
346             Ol Chiki Digits
347              
348             =item orya
349              
350             Oriya Digits
351              
352             =item osma
353              
354             Osmanya Digits
355              
356             =item roman
357              
358             Roman Numerals
359              
360             =item romanlow
361              
362             Roman Lowercase Numerals
363              
364             =item saur
365              
366             Saurashtra Digits
367              
368             =item shrd
369              
370             Sharada Digits
371              
372             =item sora
373              
374             Sora Sompeng Digits
375              
376             =item sund
377              
378             Sundanese Digits
379              
380             =item takr
381              
382             Takri Digits
383              
384             =item talu
385              
386             New Tai Lue Digits
387              
388             =item taml
389              
390             Traditional Tamil Numerals
391              
392             =item tamldec
393              
394             Tamil Digits
395              
396             =item telu
397              
398             Telugu Digits
399              
400             =item thai
401              
402             Thai Digits
403              
404             =item tibt
405              
406             Tibetan Digits
407              
408             =item traditional
409              
410             Traditional Numerals
411              
412             =item vaii
413              
414             Vai Digits
415              
416             =back
417              
418             =item ca
419              
420             =item calendar
421              
422             You can use this to override a locales default calendar. Valid values are
423              
424             =over 12
425              
426             =item buddhist
427              
428             Buddhist Calendar
429              
430             =item chinese
431              
432             Chinese Calendar
433              
434             =item coptic
435              
436             Coptic Calendar
437              
438             =item dangi
439              
440             Dangi Calendar
441              
442             =item ethiopic
443              
444             Ethiopic Calendar
445              
446             =item ethiopic-amete-alem
447              
448             Ethiopic Amete Alem Calendar
449              
450             =item gregorian
451              
452             Gregorian Calendar
453              
454             =item hebrew
455              
456             Hebrew Calendar
457              
458             =item indian
459              
460             Indian National Calendar
461              
462             =item islamic
463              
464             Islamic Calendar
465              
466             =item islamic-civil
467              
468             Islamic Calendar (tabular, civil epoch)
469              
470             =item islamic-rgsa
471              
472             Islamic Calendar (Saudi Arabia, sighting)
473              
474             =item islamic-tbla
475              
476             Islamic Calendar (tabular, astronomical epoch)
477              
478             =item islamic-umalqura
479              
480             Islamic Calendar (Umm al-Qura)
481              
482             =item iso8601
483              
484             ISO-8601 Calendar
485              
486             =item japanese
487              
488             Japanese Calendar
489              
490             =item persian
491              
492             Persian Calendar
493              
494             =item roc
495              
496             Minguo Calendar
497              
498             =back
499              
500             =back
501              
502             =cut
503              
504             has 'extensions' => (
505             is => 'ro',
506             isa => 'Undef|HashRef',
507             default => undef,
508             writer => '_set_extensions',
509             );
510              
511             =back
512              
513             =head1 Methods
514              
515             The following methods can be called on the locale object
516              
517             =over 4
518              
519             =item id()
520              
521             The local identifier. This is what you get if you attempt to
522             stringify a locale object.
523              
524             =item likely_language()
525              
526             Given a locale with no language passed in or with the explicit language
527             code of C<und>, this method attempts to use the script and region
528             data to guess the locale's language.
529              
530             =cut
531              
532             has 'likely_language' => (
533             is => 'ro',
534             isa => 'Str',
535             init_arg => undef,
536             lazy => 1,
537             builder => '_build_likely_language',
538             );
539              
540             sub _build_likely_language {
541 0     0   0 my $self = shift;
542            
543 0         0 my $language = $self->language();
544            
545 0 0       0 return $language unless $language eq 'und';
546            
547 0         0 return $self->likely_subtag->language;
548             }
549              
550             =item likely_script()
551              
552             Given a locale with no script passed in this method attempts to use the
553             language and region data to guess the locale's script.
554              
555             =cut
556              
557             has 'likely_script' => (
558             is => 'ro',
559             isa => 'Str',
560             init_arg => undef,
561             lazy => 1,
562             builder => '_build_likely_script',
563             );
564              
565             sub _build_likely_script {
566 0     0   0 my $self = shift;
567            
568 0         0 my $script = $self->script();
569            
570 0 0       0 return $script if $script;
571            
572 0   0     0 return $self->likely_subtag->script || '';
573             }
574              
575             =item likely_region()
576              
577             Given a locale with no region passed in this method attempts to use the
578             language and script data to guess the locale's region.
579              
580             =back
581              
582             =cut
583              
584             has 'likely_region' => (
585             is => 'ro',
586             isa => 'Str',
587             init_arg => undef,
588             lazy => 1,
589             builder => '_build_likely_region',
590             );
591              
592             sub _build_likely_region {
593 0     0   0 my $self = shift;
594            
595 0         0 my $region = $self->region();
596            
597 0 0       0 return $region if $region;
598            
599 0   0     0 return $self->likely_subtag->region || '';
600             }
601              
602             has 'module' => (
603             is => 'ro',
604             isa => 'Object',
605             init_arg => undef,
606             lazy => 1,
607             builder => '_build_module',
608             );
609              
610             sub _build_module {
611             # Create the new path
612 102     102   256 my $self = shift;
613            
614 306         932 my @path = map { ucfirst lc }
615 102 100       708 map { $_ ? $_ : 'Any' } (
  306         1016  
616             $self->language_id,
617             $self->script_id,
618             $self->region_id,
619             );
620              
621             my @likely_path =
622 102 100       4531 map { ucfirst lc } (
  306 100       865  
    100          
623             $self->has_likely_subtag ? $self->likely_subtag->language_id : 'Any',
624             $self->has_likely_subtag ? $self->likely_subtag->script_id : 'Any',
625             $self->has_likely_subtag ? $self->likely_subtag->region_id : 'Any',
626             );
627            
628 102         539 for (my $i = 0; $i < @path; $i++) {
629 306 100 66     2359 $likely_path[$i] = $path[$i] unless $path[$i] eq 'und' or $path[$i] eq 'Any';
630             }
631            
632             # Note the order we push these onto the stack is important
633 102         521 @path = join '::', @likely_path;
634 102         419 push @path, join '::', $likely_path[0], 'Any', $likely_path[2];
635 102         413 push @path, join '::', @likely_path[0 .. 1];
636 102         249 push @path, join '::', $likely_path[0];
637            
638             # Now we go through the path loading each module
639             # And calling new on it.
640 102         182 my $module;
641 102         297 foreach my $module_name (@path) {
642 267         707 $module_name = "Locale::CLDR::Locales::$module_name";
643 267 100       1855 if (Class::Load::try_load_class($module_name, { -version => $VERSION})) {
644 82         11432 Class::Load::load_class($module_name, { -version => $VERSION});
645             }
646             else {
647 184         104489 next;
648             }
649 82         12345 $module = $module_name->new;
650 82         303 last;
651             }
652              
653             # If we only have the root module then we have a problem as
654             # none of the language specific data is in the root. So we
655             # fall back to the en module
656              
657 101 50       516 if ( ref $module eq 'Locale::CLDR::Locales::Root') {
658 0         0 Class::Load::load_class('Locale::CLDR::Locales::En');
659 0         0 $module = Locale::CLDR::Locales::En->new
660             }
661              
662 101         3698 return $module;
663             }
664              
665             class_has 'method_cache' => (
666             is => 'rw',
667             isa => 'HashRef[HashRef[ArrayRef[Object]]]',
668             init_arg => undef,
669             default => sub { return {}},
670             );
671              
672             has 'break_grapheme_cluster' => (
673             is => 'ro',
674             isa => 'ArrayRef',
675             init_arg => undef(),
676             lazy => 1,
677             default => sub {shift->_build_break('GraphemeClusterBreak')},
678             );
679              
680             has 'break_word' => (
681             is => 'ro',
682             isa => 'ArrayRef',
683             init_arg => undef(),
684             lazy => 1,
685             default => sub {shift->_build_break('WordBreak')},
686             );
687              
688             has 'break_line' => (
689             is => 'ro',
690             isa => 'ArrayRef',
691             init_arg => undef(),
692             lazy => 1,
693             default => sub {shift->_build_break('LineBreak')},
694             );
695              
696             has 'break_sentence' => (
697             is => 'ro',
698             isa => 'ArrayRef',
699             init_arg => undef(),
700             lazy => 1,
701             default => sub {shift->_build_break('SentenceBreak')},
702             );
703              
704             =head2 Meta Data
705              
706             The following methods return, in English, the names if the various
707             id's passed into the locales constructor. I.e. if you passed
708             C<language =E<gt> 'fr'> to the constructor you would get back C<French>
709             for the language.
710              
711             =over 4
712              
713             =item name
714              
715             The locale's name. This is usually built up out of the language,
716             script, region and variant of the locale
717              
718             =item language
719              
720             The name of the locale's language
721              
722             =item script
723              
724             The name of the locale's script
725              
726             =item region
727              
728             The name of the locale's region
729              
730             =item variant
731              
732             The name of the locale's variant
733              
734             =back
735              
736             =head2 Native Meta Data
737              
738             Like Meta Data above this provides the names of the various id's
739             passed into the locale's constructor. However in this case the
740             names are formatted to match the locale. I.e. if you passed
741             C<language =E<gt> 'fr'> to the constructor you would get back
742             C<français> for the language.
743              
744             =over 4
745              
746             =item native_name
747              
748             The locale's name. This is usually built up out of the language,
749             script, region and variant of the locale. Returned in the locale's
750             language and script
751              
752             =item native_language
753              
754             The name of the locale's language in the locale's language and script.
755              
756             =item native_script
757              
758             The name of the locale's script in the locale's language and script.
759              
760             =item native_region
761              
762             The name of the locale's region in the locale's language and script.
763              
764             =item native_variant
765              
766             The name of the locale's variant in the locale's language and script.
767              
768             =back
769              
770             =cut
771              
772             foreach my $property (qw( name language script region variant)) {
773             has $property => (
774             is => 'ro',
775             isa => 'Str',
776             init_arg => undef,
777             lazy => 1,
778             builder => "_build_$property",
779             );
780              
781 20     20   134 no strict 'refs';
  20         37  
  20         17436  
782             *{"native_$property"} = sub {
783 0     0   0 my ($self, $for) = @_;
784            
785 0   0     0 $for //= $self;
786 0         0 my $build = "_build_native_$property";
787 0         0 return $self->$build($for);
788             };
789             }
790              
791             =head2 Calenders
792              
793             The Calendar data is built to hook into L<DateTime::Locale> so that
794             all Locale::CLDR objects can be used as replacements for DateTime::Locale's
795             locale data. To use, say, the French data do
796              
797             my $french_locale = Locale::CLDR->new('fr_FR');
798             my $french_dt = DateTime->now(locale => $french_locale);
799             say "French month : ", $french_dt->month_name; # prints out the current month in French
800              
801             =over 4
802              
803             =item month_format_wide
804              
805             =item month_format_abbreviated
806              
807             =item month_format_narrow
808              
809             =item month_stand_alone_wide
810              
811             =item month_stand_alone_abbreviated
812              
813             =item month_stand_alone_narrow
814              
815             All the above return an arrayref of month names in the requested style.
816              
817             =item day_format_wide
818              
819             =item day_format_abbreviated
820              
821             =item day_format_narrow
822              
823             =item day_stand_alone_wide
824              
825             =item day_stand_alone_abbreviated
826              
827             =item day_stand_alone_narrow
828              
829             All the above return an array ref of day names in the requested style.
830              
831             =item quarter_format_wide
832              
833             =item quarter_format_abbreviated
834              
835             =item quarter_format_narrow
836              
837             =item quarter_stand_alone_wide
838              
839             =item quarter_stand_alone_abbreviated
840              
841             =item quarter_stand_alone_narrow
842              
843             All the above return an arrayref of quarter names in the requested style.
844              
845             =item am_pm_wide
846              
847             =item am_pm_abbreviated
848              
849             =item am_pm_narrow
850              
851             All the above return the date period name for AM and PM
852             in the requested style
853              
854             =item era_wide
855              
856             =item era_abbreviated
857              
858             =item era_narrow
859              
860             All the above return an array ref of era names. Note that these
861             return the first two eras which is what you normally want for
862             BC and AD etc. but won't work correctly for Japanese calendars.
863              
864             =back
865              
866             =cut
867              
868             foreach my $property (qw(
869             month_format_wide month_format_abbreviated month_format_narrow
870             month_stand_alone_wide month_stand_alone_abbreviated month_stand_alone_narrow
871             day_format_wide day_format_abbreviated day_format_narrow
872             day_stand_alone_wide day_stand_alone_abbreviated day_stand_alone_narrow
873             quarter_format_wide quarter_format_abbreviated quarter_format_narrow
874             quarter_stand_alone_wide quarter_stand_alone_abbreviated quarter_stand_alone_narrow
875             am_pm_wide am_pm_abbreviated am_pm_narrow
876             era_wide era_abbreviated era_narrow
877             era_format_wide era_format_abbreviated era_format_narrow
878             era_stand_alone_wide era_stand_alone_abbreviated era_stand_alone_narrow
879             )) {
880             has $property => (
881             is => 'ro',
882             isa => 'ArrayRef',
883             init_arg => undef,
884             lazy => 1,
885             builder => "_build_$property",
886             clearer => "_clear_$property",
887             );
888             }
889              
890             =pod
891              
892             The next set of methods are not used by DateTime::Locale but CLDR provide
893             the data and you might want it
894              
895             =over 4
896              
897             =item am_pm_format_wide
898              
899             =item am_pm_format_abbreviated
900              
901             =item am_pm_format_narrow
902              
903             =item am_pm_stand_alone_wide
904              
905             =item am_pm_stand_alone_abbreviated
906              
907             =item am_pm_stand_alone_narrow
908              
909             All the above return a hashref keyed on date period
910             with the value being the value for that date period
911              
912             =item era_format_wide
913              
914             =item era_format_abbreviated
915              
916             =item era_format_narrow
917            
918             =item era_stand_alone_wide
919              
920             =item era_stand_alone_abbreviated
921              
922             =item era_stand_alone_narrow
923              
924             All the above return an array ref with I<all> the era data for the
925             locale formatted to the requested width
926              
927             =cut
928              
929             foreach my $property (qw(
930             am_pm_format_wide am_pm_format_abbreviated am_pm_format_narrow
931             am_pm_stand_alone_wide am_pm_stand_alone_abbreviated am_pm_stand_alone_narrow
932             )) {
933             has $property => (
934             is => 'ro',
935             isa => 'HashRef',
936             init_arg => undef,
937             lazy => 1,
938             builder => "_build_$property",
939             clearer => "_clear_$property",
940             );
941             }
942              
943             =item date_format_full
944              
945             =item date_format_long
946              
947             =item date_format_medium
948              
949             =item date_format_short
950              
951             =item time_format_full
952              
953             =item time_format_long
954              
955             =item time_format_medium
956              
957             =item time_format_short
958              
959             =item datetime_format_full
960              
961             =item datetime_format_long
962              
963             =item datetime_format_medium
964              
965             =item datetime_format_short
966              
967             All the above return the CLDR I<date format pattern> for the given
968             element and width
969              
970             =cut
971              
972             foreach my $property (qw(
973             id
974             date_format_full date_format_long
975             date_format_medium date_format_short
976             time_format_full time_format_long
977             time_format_medium time_format_short
978             datetime_format_full datetime_format_long
979             datetime_format_medium datetime_format_short
980             )) {
981             has $property => (
982             is => 'ro',
983             isa => 'Str',
984             init_arg => undef,
985             lazy => 1,
986             builder => "_build_$property",
987             clearer => "_clear_$property",
988             );
989             }
990              
991             has '_available_formats' => (
992             traits => ['Array'],
993             is => 'ro',
994             isa => 'ArrayRef',
995             init_arg => undef,
996             lazy => 1,
997             builder => "_build_available_formats",
998             clearer => "_clear_available_formats",
999             handles => {
1000             available_formats => 'elements',
1001             },
1002             );
1003              
1004             has 'format_data' => (
1005             is => 'ro',
1006             isa => 'HashRef',
1007             init_arg => undef,
1008             lazy => 1,
1009             builder => "_build_format_data",
1010             clearer => "_clear_format_data",
1011             );
1012              
1013             # default_calendar
1014             foreach my $property (qw(
1015             default_date_format_length default_time_format_length
1016             )) {
1017             has $property => (
1018             is => 'ro',
1019             isa => 'Str',
1020             init_arg => undef,
1021             lazy => 1,
1022             builder => "_build_$property",
1023             writer => "set_$property"
1024             );
1025             }
1026              
1027             =item prefers_24_hour_time()
1028              
1029             Returns a boolean value, true if the locale has a preference
1030             for 24 hour time over 12 hour
1031              
1032             =cut
1033              
1034             has 'prefers_24_hour_time' => (
1035             is => 'ro',
1036             isa => 'Bool',
1037             init_arg => undef,
1038             lazy => 1,
1039             builder => "_build_prefers_24_hour_time",
1040             );
1041              
1042             =item first_day_of_week()
1043              
1044             Returns the numeric representation of the first day of the week
1045             With 0 = Saturday
1046              
1047             =item get_day_period($time, $type = 'default')
1048              
1049             This method will calculate the correct
1050             period for a given time and return the period name in
1051             the locale's language and script
1052              
1053             =item format_for($date_time_format)
1054              
1055             This method takes a CLDR date time format and returns
1056             the localised version of the format.
1057              
1058             =cut
1059              
1060             has 'first_day_of_week' => (
1061             is => 'ro',
1062             isa => 'Int',
1063             init_arg => undef,
1064             lazy => 1,
1065             builder => "_build_first_day_of_week",
1066             );
1067              
1068             has 'likely_subtag' => (
1069             is => 'ro',
1070             isa => __PACKAGE__,
1071             init_arg => undef,
1072             writer => '_set_likely_subtag',
1073             predicate => 'has_likely_subtag',
1074             );
1075              
1076             sub _build_break {
1077 4     4   12 my ($self, $what) = @_;
1078              
1079 4         21 my $vars = $self->_build_break_vars($what);
1080 4         19 my $rules = $self->_build_break_rules($vars, $what);
1081 4         264 return $rules;
1082             }
1083              
1084             sub _build_break_vars {
1085 4     4   11 my ($self, $what) = @_;
1086              
1087 4         16 my $name = "${what}_variables";
1088 4         22 my @bundles = $self->_find_bundle($name);
1089 4         7 my @vars;
1090 4         15 foreach my $bundle (reverse @bundles) {
1091 4         6 push @vars, @{$bundle->$name};
  4         176  
1092             }
1093              
1094 4         14 my %vars = ();
1095 4         22 while (my ($name, $value) = (shift @vars, shift @vars)) {
1096 146 100       259 last unless defined $name;
1097 142 50       240 if (! defined $value) {
1098 0         0 delete $vars{$name};
1099 0         0 next;
1100             }
1101              
1102 142         310 $value =~ s{ ( \$ \p{ID_START} \p{ID_CONTINUE}* ) }{$vars{$1}}msxeg;
  148         462  
1103 142         553 $vars{$name} = $value;
1104             }
1105              
1106 4         15 return \%vars;
1107             }
1108              
1109             sub _build_break_rules {
1110 4     4   12 my ($self, $vars, $what) = @_;
1111              
1112 4         14 my $name = "${what}_rules";
1113 4         18 my @bundles = $self->_find_bundle($name);
1114              
1115 4         11 my %rules;
1116 4         17 foreach my $bundle (reverse @bundles) {
1117 4         12 %rules = (%rules, %{$bundle->$name});
  4         195  
1118             }
1119              
1120 4         15 my @rules;
1121 4         41 foreach my $rule_number ( sort { $a <=> $b } keys %rules ) {
  390         492  
1122             # Test for deleted rules
1123 98 50       362 next unless defined $rules{$rule_number};
1124              
1125 98         826 $rules{$rule_number} =~ s{ ( \$ \p{ID_START} \p{ID_CONTINUE}* ) }{$vars->{$1}}msxeg;
  293         1571  
1126 98         1051 my ($first, $opp, $second) = split /(×|÷)/, $rules{$rule_number};
1127              
1128 98         248 foreach my $operand ($first, $second) {
1129 196 100       142816 if ($operand =~ m{ \S }msx) {
1130 163         5192 $operand = _unicode_to_perl($operand);
1131             }
1132             else {
1133 33         88 $operand = '.';
1134             }
1135             }
1136            
1137 20     20   1256333 no warnings 'deprecated';
  20         46  
  20         50457  
1138 98 100       111954 push @rules, [qr{$first}msx, qr{$second}msx, ($opp eq '×' ? 1 : 0)];
1139             }
1140              
1141 4         38 push @rules, [ '.', '.', 0 ];
1142              
1143 4         85 return \@rules;
1144             }
1145              
1146             sub BUILDARGS {
1147 94     94 1 1640 my $self = shift;
1148 94         232 my %args;
1149              
1150             # Used for arguments when we call new from our own code
1151 94         357 my %internal_args = ();
1152 94 50 66     697 if (@_ > 1 && ref $_[-1] eq 'HASH') {
1153 0         0 %internal_args = %{pop @_};
  0         0  
1154             }
1155              
1156 94 100 66     791 if (1 == @_ && ! ref $_[0]) {
1157 73         788 my ($language, $script, $region, $variant, $extensions)
1158             = $_[0]=~/^
1159             ([a-zA-Z]+)
1160             (?:[-_]([a-zA-Z]{4}))?
1161             (?:[-_]([a-zA-Z]{2,3}))?
1162             (?:[-_]([a-zA-Z0-9]+))?
1163             (?:[-_]u[_-](.+))?
1164             $/x;
1165              
1166 73         252 foreach ($language, $script, $region, $variant) {
1167 292 100       878 $_ = '' unless defined $_;
1168             }
1169              
1170             %args = (
1171 73         602 language_id => $language,
1172             script_id => $script,
1173             region_id => $region,
1174             variant_id => $variant,
1175             extensions => $extensions,
1176             );
1177             }
1178              
1179 94 100       404 if (! keys %args ) {
1180             %args = ref $_[0]
1181 21 50       160 ? %{$_[0]}
  0         0  
1182             : @_
1183             }
1184              
1185             # Split up the extensions
1186 94 100 66     568 if ( defined $args{extensions} && ! ref $args{extensions} ) {
1187             $args{extensions} = {
1188 6         29 map {lc}
1189             split /[_-]/, $args{extensions}
1190 3         20 };
1191             }
1192              
1193             # Fix casing of args
1194 94 100       621 $args{language_id} = lc $args{language_id} if defined $args{language_id};
1195 94 100       576 $args{script_id} = ucfirst lc $args{script_id} if defined $args{script_id};
1196 94 100       536 $args{region_id} = uc $args{region_id} if defined $args{region_id};
1197 94 100       430 $args{variant_id} = uc $args{variant_id} if defined $args{variant_id};
1198            
1199             # Set up undefined language
1200 94   100     353 $args{language_id} //= 'und';
1201              
1202 94         760 $self->SUPER::BUILDARGS(%args, %internal_args);
1203             }
1204              
1205             sub BUILD {
1206             my ($self, $args) = @_;
1207              
1208             # Check that the args are valid
1209             # also check for aliases
1210             $args->{language_id} = $self->language_aliases->{$args->{language_id}}
1211             // $args->{language_id};
1212            
1213             die "Invalid language" if $args->{language_id}
1214             && ! first { $args->{language_id} eq $_ } $self->valid_languages;
1215              
1216             die "Invalid script" if $args->{script_id}
1217             && ! first { ucfirst lc $args->{script_id} eq ucfirst lc $_ } $self->valid_scripts;
1218              
1219             die "Invalid region" if $args->{region_id}
1220             && ( ! ( first { uc $args->{region_id} eq uc $_ } $self->valid_regions )
1221             && ( ! $self->region_aliases->{$self->{region_id}} )
1222             );
1223            
1224             die "Invalid variant" if $args->{variant_id}
1225             && ( ! ( first { uc $args->{variant_id} eq uc $_ } $self->valid_variants )
1226             && ( ! $self->variant_aliases->{lc $self->{variant_id}} )
1227             );
1228            
1229             if ($args->{extensions}) {
1230             my %valid_keys = $self->valid_keys;
1231             my %key_aliases = $self->key_names;
1232             my @keys = keys %{$args->{extensions}};
1233              
1234             foreach my $key ( @keys ) {
1235             my $canonical_key = $key_aliases{$key} if exists $key_aliases{$key};
1236             $canonical_key //= $key;
1237             if ($canonical_key ne $key) {
1238             $args->{extensions}{$canonical_key} = delete $args->{extensions}{$key};
1239             }
1240              
1241             $key = $canonical_key;
1242             die "Invalid extension name" unless exists $valid_keys{$key};
1243             die "Invalid extension value" unless
1244             first { $_ eq $args->{extensions}{$key} } @{$valid_keys{$key}};
1245              
1246             $self->_set_extensions($args->{extensions})
1247             }
1248             }
1249              
1250             # Check for variant aliases
1251             if ($args->{variant_id} && (my $variant_alias = $self->variant_aliases->{lc $self->variant_id})) {
1252             delete $args->{variant_id};
1253             my ($what) = keys %{$variant_alias};
1254             my ($value) = values %{$variant_alias};
1255             $args->{$what} = $value;
1256             }
1257            
1258             # Now set up the module
1259             $self->_build_module;
1260             }
1261              
1262             after 'BUILD' => sub {
1263              
1264             my $self = shift;
1265            
1266             # Fix up likely sub tags
1267            
1268             my $likely_subtags = $self->likely_subtags;
1269             my $likely_subtag;
1270             my ($language_id, $script_id, $region_id) = ($self->language_id, $self->script_id, $self->region_id);
1271            
1272             unless ($language_id ne 'und' && $script_id && $region_id ) {
1273             $likely_subtag = $likely_subtags->{join '_', grep { length() } ($language_id, $script_id, $region_id)};
1274            
1275             if (! $likely_subtag ) {
1276             $likely_subtag = $likely_subtags->{join '_', $language_id, $region_id};
1277             }
1278            
1279             if (! $likely_subtag ) {
1280             $likely_subtag = $likely_subtags->{join '_', $language_id, $script_id};
1281             }
1282            
1283             if (! $likely_subtag ) {
1284             $likely_subtag = $likely_subtags->{$language_id};
1285             }
1286            
1287             if (! $likely_subtag ) {
1288             $likely_subtag = $likely_subtags->{join '_', 'und', $script_id};
1289             }
1290             }
1291            
1292             my ($likely_language_id, $likely_script_id, $likely_region_id);
1293             if ($likely_subtag) {
1294             ($likely_language_id, $likely_script_id, $likely_region_id) = split /_/, $likely_subtag;
1295             $likely_language_id = $language_id unless $language_id eq 'und';
1296             $likely_script_id = $script_id if length $script_id;
1297             $likely_region_id = $region_id if length $region_id;
1298             $self->_set_likely_subtag(__PACKAGE__->new(join '_',$likely_language_id, $likely_script_id, $likely_region_id));
1299             }
1300            
1301             # Fix up extension overrides
1302             my $extensions = $self->extensions;
1303             if (exists $extensions->{ca}) {
1304             $self->_set_default_ca($extensions->{ca});
1305             }
1306              
1307             if (exists $extensions->{cf}) {
1308             $self->_set_default_cf($extensions->{cf});
1309             }
1310            
1311             if (exists $extensions->{nu}) {
1312             $self->_clear_default_nu;
1313             $self->_set_default_nu($extensions->{nu});
1314             }
1315             };
1316              
1317             # Defaults
1318             # Calendar, currency format
1319             foreach my $default (qw( ca cf )) {
1320             has "default_$default" => (
1321             is => 'ro',
1322             isa => 'Str',
1323             init_arg => undef,
1324             default => '',
1325             traits => ['String'],
1326             handles => {
1327             "_set_default_$default" => 'append',
1328             "_test_default_$default" => 'length',
1329             },
1330             );
1331             }
1332              
1333             sub default_calendar {
1334 68     68 1 131 my ($self, $region) = @_;
1335              
1336 68         112 my $default = '';
1337 68 100       3314 if ($self->_test_default_ca) {
1338 66         2300 $default = $self->default_ca();
1339             }
1340             else {
1341 2         89 my $calendar_preferences = $self->calendar_preferences();
1342 2   33     21 $region //= ( $self->region_id() || $self->likely_subtag->region_id );
      33        
1343 2         5 my $current_region = $region;
1344              
1345 2         9 while (! $default) {
1346 10         22 $default = $calendar_preferences->{$current_region};
1347 10 100       24 if ($default) {
1348 2         10 $default = $default->[0];
1349             }
1350             else {
1351 8         310 $current_region = $self->region_contained_by()->{$current_region}
1352             }
1353             }
1354 2         95 $self->_set_default_ca($default);
1355             }
1356 68         172 return $default;
1357             }
1358              
1359             sub default_currency_format {
1360 10     10 1 22 my $self = shift;
1361            
1362 10         20 my $default = 'standard';
1363 10 50       650 if ($self->_test_default_cf) {
1364 10         349 $default = $self->default_cf();
1365             }
1366             else {
1367 0         0 $self->_set_default_cf($default);
1368             }
1369            
1370 10         42 return $default;
1371             }
1372              
1373             use overload
1374 40     40   155 'bool' => sub { 1 },
1375 20     20   148 '""' => sub {shift->id};
  20     0   43  
  20         386  
  0         0  
1376              
1377             sub _build_id {
1378 30     30   69 my $self = shift;
1379 30         184 my $string = lc $self->language_id;
1380              
1381 30 100       1070 if ($self->script_id) {
1382 23         767 $string.= '_' . ucfirst lc $self->script_id;
1383             }
1384              
1385 30 100       149 if ($self->region_id) {
1386 23         109 $string.= '_' . uc $self->region_id;
1387             }
1388              
1389 30 100       1144 if ($self->variant_id) {
1390 3         98 $string.= '_' . uc $self->variant_id;
1391             }
1392              
1393 30 50       1020 if (defined $self->extensions) {
1394 0         0 $string.= '_u';
1395 0         0 foreach my $key (sort keys %{$self->extensions}) {
  0         0  
1396 0         0 my $value = $self->extensions->{$key};
1397 0         0 $string .= "_${key}_$value";
1398             }
1399 0         0 $string =~ s/_u$//;
1400             }
1401              
1402 30         930 return $string;
1403             }
1404              
1405             sub _get_english {
1406 0     0   0 my $self = shift;
1407 0         0 my $english;
1408 0 0       0 if ($self->language_id eq 'en') {
1409 0         0 $english = $self;
1410             }
1411             else {
1412 0         0 $english = Locale::CLDR->new('en_Latn_US');
1413             }
1414              
1415 0         0 return $english;
1416             }
1417              
1418             sub _build_name {
1419 0     0   0 my $self = shift;
1420              
1421 0         0 return $self->_get_english->native_name($self);
1422             }
1423              
1424             sub _build_native_name {
1425 0     0   0 my ($self, $for) = @_;
1426              
1427 0         0 return $self->locale_name($for);
1428             }
1429              
1430             sub _build_language {
1431 0     0   0 my $self = shift;
1432              
1433 0         0 return $self->_get_english->native_language($self);
1434             }
1435              
1436             sub _build_native_language {
1437 0     0   0 my ($self, $for) = @_;
1438              
1439 0   0     0 return $self->language_name($for) // '';
1440             }
1441              
1442             sub _build_script {
1443 0     0   0 my $self = shift;
1444              
1445 0         0 return $self->_get_english->native_script($self);
1446             }
1447              
1448             sub _build_native_script {
1449 0     0   0 my ($self, $for) = @_;
1450              
1451 0         0 return $self->script_name($for);
1452             }
1453              
1454             sub _build_region {
1455 0     0   0 my $self = shift;
1456              
1457 0         0 return $self->_get_english->native_region($self);
1458             }
1459              
1460             sub _build_native_region {
1461 0     0   0 my ($self, $for) = @_;
1462              
1463 0         0 return $self->region_name($for);
1464             }
1465              
1466             sub _build_variant {
1467 0     0   0 my $self = shift;
1468              
1469 0         0 return $self->_get_english->native_variant($self);
1470             }
1471              
1472             sub _build_native_variant {
1473 0     0   0 my ($self, $for) = @_;
1474              
1475 0         0 return $self->variant_name($for);
1476             }
1477              
1478             # Method to locate the resource bundle with the required data
1479             sub _find_bundle {
1480 3248     3248   5933 my ($self, $method_name) = @_;
1481 3248 50       133803 my $id = $self->has_likely_subtag()
1482             ? $self->likely_subtag()->id()
1483             : $self->id();
1484            
1485            
1486 3248 100       110217 if ($self->method_cache->{$id}{$method_name}) {
1487             return wantarray
1488 2406         79418 ? @{$self->method_cache->{$id}{$method_name}}
1489 3170 100       30726 : $self->method_cache->{$id}{$method_name}[0];
1490             }
1491              
1492 78         2794 foreach my $module ($self->module->meta->linearized_isa) {
1493 390 100       20834 last if $module eq 'Moose::Object';
1494 312 100       1997 if ($module->meta->has_method($method_name)) {
1495 118         10216 push @{$self->method_cache->{$id}{$method_name}}, $module->new;
  118         4782  
1496             }
1497             }
1498              
1499 78 50       3271 return unless $self->method_cache->{$id}{$method_name};
1500             return wantarray
1501 65         2228 ? @{$self->method_cache->{$id}{$method_name}}
1502 78 100       758 : $self->method_cache->{$id}{$method_name}[0];
1503             }
1504              
1505             =back
1506              
1507             =head2 Names
1508              
1509             These methods allow you to pass in a locale, either by C<id> or as a
1510             Locale::CLDR object and return an name formatted in the locale of $self.
1511             If you don't pass in a locale then it will use $self.
1512              
1513             =over 4
1514              
1515             =item locale_name($name)
1516              
1517             Returns the given locale name in the current locale's format. The name can be
1518             a locale id or a locale object or non existent. If a name is not passed in
1519             then the name of the current locale is returned.
1520              
1521             =cut
1522              
1523             sub locale_name {
1524 6     6 1 5058 my ($self, $name) = @_;
1525 6   66     33 $name //= $self;
1526              
1527 6 50       30 my $code = ref $name
    100          
1528             ? join ( '_', $name->language_id, $name->region_id ? $name->region_id : () )
1529             : $name;
1530            
1531 6         31 my @bundles = $self->_find_bundle('display_name_language');
1532              
1533 6         19 foreach my $bundle (@bundles) {
1534 6         246 my $display_name = $bundle->display_name_language->($code);
1535 6 100       48 return $display_name if defined $display_name;
1536             }
1537              
1538             # $name can be a string or a Locale::CLDR::Locales::*
1539 2 50       8 if (! ref $name) {
1540 2         20 $name = Locale::CLDR->new($name);
1541             }
1542              
1543             # Now we have to process each individual element
1544             # to pass to the display name pattern
1545 2         52 my $language = $self->language_name($name);
1546 2         11 my $script = $self->script_name($name);
1547 2         13 my $region = $self->region_name($name);
1548 2         12 my $variant = $self->variant_name($name);
1549              
1550 2         10 my $bundle = $self->_find_bundle('display_name_pattern');
1551 2         16 return $bundle
1552             ->display_name_pattern($language, $region, $script, $variant);
1553             }
1554              
1555             =item language_name($language)
1556              
1557             Returns the language name in the current locale's format. The name can be
1558             a locale language id or a locale object or non existent. If a name is not
1559             passed in then the language name of the current locale is returned.
1560              
1561             =cut
1562              
1563             sub language_name {
1564 8     8 1 7736 my ($self, $name) = @_;
1565              
1566 8   66     41 $name //= $self;
1567              
1568 8 100       49 my $code = ref $name ? $name->language_id : eval { Locale::CLDR->new(language_id => $name)->language_id };
  3         24  
1569              
1570 8         2697 my $language = undef;
1571 8         6532 my @bundles = $self->_find_bundle('display_name_language');
1572 8 100       39 if ($code) {
1573 7         20 foreach my $bundle (@bundles) {
1574 7         303 my $display_name = $bundle->display_name_language->($code);
1575 7 50       39 if (defined $display_name) {
1576 7         18 $language = $display_name;
1577 7         22 last;
1578             }
1579             }
1580             }
1581             # If we don't have a display name for the language we try again
1582             # with the und tag
1583 8 100       31 if (! defined $language ) {
1584 1         4 foreach my $bundle (@bundles) {
1585 1         46 my $display_name = $bundle->display_name_language->('und');
1586 1 50       5 if (defined $display_name) {
1587 1         4 $language = $display_name;
1588 1         4 last;
1589             }
1590             }
1591             }
1592              
1593 8         52 return $language;
1594             }
1595              
1596             =item all_languages()
1597              
1598             Returns a hash ref keyed on language id of all the languages the system
1599             knows about. The values are the language names for the corresponding id's
1600              
1601             =cut
1602              
1603             sub all_languages {
1604 1     1 1 2 my $self = shift;
1605              
1606 1         6 my @bundles = $self->_find_bundle('display_name_language');
1607 1         3 my %languages;
1608 1         4 foreach my $bundle (@bundles) {
1609 1         43 my $languages = $bundle->display_name_language->();
1610              
1611             # Remove existing languages
1612 1         3 delete @{$languages}{keys %languages};
  1         3  
1613              
1614             # Assign new ones to the hash
1615 1         473 @languages{keys %$languages} = values %$languages;
1616             }
1617              
1618 1         9 return \%languages;
1619             }
1620              
1621             =item script_name($script)
1622              
1623             Returns the script name in the current locale's format. The script can be
1624             a locale script id or a locale object or non existent. If a script is not
1625             passed in then the script name of the current locale is returned.
1626              
1627             =cut
1628              
1629             sub script_name {
1630 7     7 1 5525 my ($self, $name) = @_;
1631 7   66     33 $name //= $self;
1632              
1633 7 100       31 if (! ref $name ) {
1634 3         10 $name = eval {__PACKAGE__->new(script_id => $name)};
  3         27  
1635             }
1636              
1637 7 100 100     2588 if ( ref $name && ! $name->script_id ) {
1638 3         13 return '';
1639             }
1640              
1641 4         15 my $script = undef;
1642 4         29 my @bundles = $self->_find_bundle('display_name_script');
1643 4 100       26 if ($name) {
1644 3         14 foreach my $bundle (@bundles) {
1645 3         109 $script = $bundle->display_name_script->($name->script_id);
1646 3 50       15 if (defined $script) {
1647 3         9 last;
1648             }
1649             }
1650             }
1651              
1652 4 100       19 if (! $script) {
1653 1         6 foreach my $bundle (@bundles) {
1654 1         45 $script = $bundle->display_name_script->('Zzzz');
1655 1 50       4 if (defined $script) {
1656 1         3 last;
1657             }
1658             }
1659             }
1660              
1661 4         56 return $script;
1662             }
1663              
1664             =item all_scripts()
1665              
1666             Returns a hash ref keyed on script id of all the scripts the system
1667             knows about. The values are the script names for the corresponding id's
1668              
1669             =cut
1670              
1671             sub all_scripts {
1672 1     1 1 5448 my $self = shift;
1673              
1674 1         6 my @bundles = $self->_find_bundle('display_name_script');
1675 1         3 my %scripts;
1676 1         4 foreach my $bundle (@bundles) {
1677 1         47 my $scripts = $bundle->display_name_script->();
1678              
1679             # Remove existing scripts
1680 1         4 delete @{$scripts}{keys %scripts};
  1         4  
1681              
1682             # Assign new ones to the hash
1683 1         112 @scripts{keys %$scripts} = values %$scripts;
1684             }
1685              
1686 1         8 return \%scripts;
1687             }
1688              
1689             =item region_name($region)
1690              
1691             Returns the region name in the current locale's format. The region can be
1692             a locale region id or a locale object or non existent. If a region is not
1693             passed in then the region name of the current locale is returned.
1694              
1695             =cut
1696              
1697             sub region_name {
1698 9     9 1 12624 my ($self, $name) = @_;
1699 9   66     65 $name //= $self;
1700              
1701 9 100       44 if (! ref $name ) {
1702 5         12 $name = eval { __PACKAGE__->new(language_id => 'und', region_id => $name); };
  5         41  
1703             }
1704              
1705 9 50 66     5527 if ( ref $name && ! $name->region_id) {
1706 0         0 return '';
1707             }
1708              
1709 9         27 my $region = undef;
1710 9         50 my @bundles = $self->_find_bundle('display_name_region');
1711 9 100       53 if ($name) {
1712 7         22 foreach my $bundle (@bundles) {
1713 7         299 $region = $bundle->display_name_region->{$name->region_id};
1714 7 50       33 if (defined $region) {
1715 7         16 last;
1716             }
1717             }
1718             }
1719              
1720 9 100       36 if (! defined $region) {
1721 2         7 foreach my $bundle (@bundles) {
1722 2         88 $region = $bundle->display_name_region->{'ZZ'};
1723 2 50       10 if (defined $region) {
1724 2         7 last;
1725             }
1726             }
1727             }
1728              
1729 9         59 return $region;
1730             }
1731              
1732             =item all_regions
1733              
1734             Returns a hash ref keyed on region id of all the region the system
1735             knows about. The values are the region names for the corresponding ids
1736              
1737             =cut
1738              
1739             sub all_regions {
1740 1     1 1 5081 my $self = shift;
1741              
1742 1         7 my @bundles = $self->_find_bundle('display_name_region');
1743 1         3 my %regions;
1744 1         3 foreach my $bundle (@bundles) {
1745 1         45 my $regions = $bundle->display_name_region;
1746              
1747             # Remove existing regions
1748 1         4 delete @{$regions}{keys %regions};
  1         3  
1749              
1750             # Assign new ones to the hash
1751 1         290 @regions{keys %$regions} = values %$regions;
1752             }
1753              
1754 1         7 return \%regions;
1755             }
1756              
1757             =item variant_name($variant)
1758              
1759             Returns the variant name in the current locale's format. The variant can be
1760             a locale variant id or a locale object or non existent. If a variant is not
1761             passed in then the variant name of the current locale is returned.
1762              
1763             =cut
1764              
1765             sub variant_name {
1766 7     7 1 6571 my ($self, $name) = @_;
1767 7   66     33 $name //= $self;
1768              
1769 7 100       27 if (! ref $name ) {
1770 4         36 $name = __PACKAGE__->new(language_id=> 'und', variant_id => $name);
1771             }
1772              
1773 6 100       286 return '' unless $name->variant_id;
1774 3         10 my $variant = undef;
1775 3 50       127 if ($name->has_variant) {
1776 3         20 my @bundles = $self->_find_bundle('display_name_variant');
1777 3         12 foreach my $bundle (@bundles) {
1778 3         134 $variant= $bundle->display_name_variant->{$name->variant_id};
1779 3 100       15 if (defined $variant) {
1780 2         7 last;
1781             }
1782             }
1783             }
1784              
1785 3   100     35 return $variant // '';
1786             }
1787              
1788             =item key_name($key)
1789              
1790             Returns the key name in the current locale's format. The key must be
1791             a locale key id as a string
1792              
1793             =cut
1794              
1795             sub key_name {
1796 3     3 1 12687 my ($self, $key) = @_;
1797              
1798 3         11 $key = lc $key;
1799            
1800 3         148 my %key_aliases = $self->key_aliases;
1801 3         136 my %key_names = $self->key_names;
1802 3         125 my %valid_keys = $self->valid_keys;
1803              
1804 3   100     35 my $alias = $key_aliases{$key} // '';
1805 3   100     17 my $name = $key_names{$key} // '';
1806              
1807 3 50 66     46 return '' unless exists $valid_keys{$key} || exists $valid_keys{$alias} || exists $valid_keys{$name};
      33        
1808 3         18 my @bundles = $self->_find_bundle('display_name_key');
1809 3         13 foreach my $bundle (@bundles) {
1810 3         123 my $return = $bundle->display_name_key->{$key};
1811 3   66     52 $return //= $bundle->display_name_key->{$alias};
1812 3   33     9 $return //= $bundle->display_name_key->{$name};
1813              
1814 3 50 33     139 return $return if defined $return && length $return;
1815             }
1816              
1817 0   0     0 return ucfirst ($key_names{$name} || $key_names{$alias} || $key_names{$key} || $key);
1818             }
1819              
1820             =item type_name($key, $type)
1821              
1822             Returns the type name in the current locale's format. The key and type must be
1823             a locale key id and type id as a string
1824              
1825             =cut
1826              
1827             sub type_name {
1828 3     3 1 12 my ($self, $key, $type) = @_;
1829              
1830 3         11 $key = lc $key;
1831 3         7 $type = lc $type;
1832              
1833 3         130 my %key_aliases = $self->key_aliases;
1834 3         125 my %valid_keys = $self->valid_keys;
1835 3         124 my %key_names = $self->key_names;
1836              
1837 3   100     30 my $alias = $key_aliases{$key} // '';
1838 3   100     16 my $name = $key_names{$key} // '';
1839              
1840 3 50 66     29 return '' unless exists $valid_keys{$key} || $valid_keys{$alias} || $valid_keys{$name};
      33        
1841 3 100   20   17 return '' unless first { $_ eq $type } @{$valid_keys{$key} || []}, @{$valid_keys{$alias} || []}, @{$valid_keys{$name} || []};
  20 50       40  
  3 100       21  
  3 50       22  
  3         29  
1842              
1843 3         20 my @bundles = $self->_find_bundle('display_name_type');
1844 3         12 foreach my $bundle (@bundles) {
1845 3   66     128 my $types = $bundle->display_name_type->{$key} // $bundle->display_name_type->{$alias} // $bundle->display_name_type->{$name};
      33        
1846 3         11 my $type = $types->{$type};
1847 3 50       88 return $type if defined $type;
1848             }
1849              
1850 0         0 return '';
1851             }
1852            
1853             =item measurement_system_name($measurement_system)
1854              
1855             Returns the measurement system name in the current locale's format. The measurement system must be
1856             a measurement system id as a string
1857              
1858             =cut
1859            
1860             sub measurement_system_name {
1861 6     6 1 45 my ($self, $name) = @_;
1862              
1863             # Fix case of code
1864 6         18 $name = uc $name;
1865 6 100       23 $name = 'metric' if $name eq 'METRIC';
1866              
1867 6         26 my @bundles = $self->_find_bundle('display_name_measurement_system');
1868 6         25 foreach my $bundle (@bundles) {
1869 6         254 my $system = $bundle->display_name_measurement_system->{$name};
1870 6 50       52 return $system if defined $system;
1871             }
1872              
1873 0         0 return '';
1874             }
1875              
1876             =item transform_name($name)
1877              
1878             Returns the transform (transliteration) name in the current locale's format. The transform must be
1879             a transform id as a string
1880              
1881             =cut
1882              
1883             sub transform_name {
1884 1     1 1 3 my ($self, $name) = @_;
1885              
1886 1         4 $name = lc $name;
1887              
1888 1         3 my @bundles = $self->_find_bundle('display_name_transform_name');
1889 1         5 foreach my $bundle (@bundles) {
1890 1         45 my $key = $bundle->display_name_transform_name->{$name};
1891 1 50       14 return $key if length $key;
1892             }
1893              
1894 0         0 return '';
1895             }
1896              
1897             =item code_pattern($type, $locale)
1898              
1899             This method formats a language, script or region name, given as C<$type>
1900             from C<$locale> in a way expected by the current locale. If $locale is
1901             not passed in or is undef() the method uses the current locale.
1902              
1903             =cut
1904              
1905             sub code_pattern {
1906 3     3 1 39 my ($self, $type, $locale) = @_;
1907 3         10 $type = lc $type;
1908              
1909             # If locale is not passed in then we are using ourself
1910 3   33     14 $locale //= $self;
1911              
1912             # If locale is not an object then inflate it
1913 3 50       20 $locale = __PACKAGE__->new($locale) unless blessed $locale;
1914              
1915 3 50       21 return '' unless $type =~ m{ \A (?: language | script | region ) \z }xms;
1916              
1917 3         10 my $method = $type . '_name';
1918 3         23 my $substitute = $self->$method($locale);
1919              
1920 3         17 my @bundles = $self->_find_bundle('display_name_code_patterns');
1921 3         12 foreach my $bundle (@bundles) {
1922 3         140 my $text = $bundle->display_name_code_patterns->{$type};
1923 3 50       10 next unless defined $text;
1924 3         11 my $match = qr{ \{ 0 \} }xms;
1925 3         59 $text=~ s{ $match }{$substitute}gxms;
1926 3         34 return $text;
1927             }
1928              
1929 0         0 return '';
1930             }
1931              
1932             =item text_orientation($type)
1933              
1934             Gets the text orientation for the locale. Type must be one of
1935             C<lines> or C<characters>
1936              
1937             =cut
1938              
1939             sub text_orientation {
1940 2     2 1 27 my $self = shift;
1941 2         7 my $type = shift;
1942              
1943 2         11 my @bundles = $self->_find_bundle('text_orientation');
1944 2         7 foreach my $bundle (@bundles) {
1945 2         104 my $orientation = $bundle->text_orientation;
1946 2 50       9 next unless defined $orientation;
1947 2         18 return $orientation->{$type};
1948             }
1949              
1950 0         0 return;
1951             }
1952              
1953             sub _set_casing {
1954 0     0   0 my ($self, $casing, $string) = @_;
1955              
1956 0         0 my @words = $self->split_words($string);
1957              
1958 0 0       0 if ($casing eq 'titlecase-firstword') {
    0          
    0          
1959             # Check to see whether $words[0] is white space or not
1960 0         0 my $firstword_location = 0;
1961 0 0       0 if ($words[0] =~ m{ \A \s }msx) {
1962 0         0 $firstword_location = 1;
1963             }
1964              
1965 0         0 $words[$firstword_location] = ucfirst $words[$firstword_location];
1966             }
1967             elsif ($casing eq 'titlecase-words') {
1968 0         0 @words = map{ ucfirst } @words;
  0         0  
1969             }
1970             elsif ($casing eq 'lowercase-words') {
1971 0         0 @words = map{ lc } @words;
  0         0  
1972             }
1973              
1974 0         0 return join '', @words;
1975             }
1976              
1977             =back
1978              
1979             =head2 Segmentation
1980              
1981             This group of methods allow you to split a string in various ways
1982             Note you need Perl 5.18 or above for this
1983              
1984             =over 4
1985              
1986             =item split_grapheme_clusters($string)
1987              
1988             Splits a string on grapheme clusters using the locale's segmentation rules.
1989             Returns a list of grapheme clusters.
1990              
1991             =cut
1992             # Need 5.18 and above
1993             sub _new_perl {
1994 10 50   10   155 die "You need Perl 5.18 or later for this functionality\n"
1995             if $^V lt v5.18.0;
1996             }
1997              
1998             sub split_grapheme_clusters {
1999 1     1 1 48 _new_perl();
2000            
2001 1         4 my ($self, $string) = @_;
2002              
2003 1         39 my $rules = $self->break_grapheme_cluster;
2004 1         7 my @clusters = $self->_split($rules, $string, 1);
2005              
2006 1         22 return @clusters;
2007             }
2008              
2009             =item split_words($string)
2010              
2011             Splits a string on word boundaries using the locale's segmentation rules.
2012             Returns a list of words.
2013              
2014             =cut
2015              
2016             sub split_words {
2017 1     1 1 1415 _new_perl();
2018            
2019 1         6 my ($self, $string) = @_;
2020              
2021 1         52 my $rules = $self->break_word;
2022 1         11 my @words = $self->_split($rules, $string);
2023              
2024 1         12 return @words;
2025             }
2026              
2027             =item split_sentences($string)
2028              
2029             Splits a string on on all points where a sentence could
2030             end using the locale's segmentation rules. Returns a list
2031             the end of each list element is the point where a sentence
2032             could end.
2033              
2034             =cut
2035              
2036             sub split_sentences {
2037 1     1 1 1134 _new_perl();
2038            
2039 1         4 my ($self, $string) = @_;
2040              
2041 1         57 my $rules = $self->break_sentence;
2042 1         8 my @sentences = $self->_split($rules, $string);
2043              
2044 1         11 return @sentences;
2045             }
2046              
2047             =item split_lines($string)
2048              
2049             Splits a string on on all points where a line could
2050             end using the locale's segmentation rules. Returns a list
2051             the end of each list element is the point where a line
2052             could end.
2053              
2054             =cut
2055              
2056             sub split_lines {
2057 1     1 1 1107 _new_perl();
2058            
2059 1         4 my ($self, $string) = @_;
2060              
2061 1         55 my $rules = $self->break_line;
2062 1         10 my @lines = $self->_split($rules, $string);
2063              
2064 1         10 return @lines;
2065             }
2066              
2067             sub _split {
2068 4     4   13 my ($self, $rules, $string, $grapheme_split) = @_;
2069              
2070 4         41 my @split = (scalar @$rules) x (length($string) - 1);
2071              
2072 4         16 pos($string)=0;
2073             # The Unicode Consortium has deprecated LB=Surrogate but the CLDR still
2074             # uses it, at last in this version.
2075 20     20   99644 no warnings 'deprecated';
  20         47  
  20         90055  
2076 4         22 while (length($string) -1 != pos $string) {
2077 160         208 my $rule_number = 0;
2078 160         174 my $first;
2079 160         349 foreach my $rule (@$rules) {
2080 2666 100       54613 unless( ($first) = $string =~ m{
2081             \G
2082             ($rule->[0])
2083             $rule->[1]
2084             }msx) {
2085 2506         2067597 $rule_number++;
2086 2506         39169 next;
2087             }
2088 160         171175 my $location = pos($string) + length($first) -1;
2089 160         374 $split[$location] = $rule_number;
2090            
2091             # If the left hand side was part of a grapheme cluster
2092             # we have to jump past the entire cluster
2093 160         265 my $length = length $first;
2094 160         11326 my ($gc) = $string =~ /\G(\X)/;
2095 160 100 66     1110 $length = (! $grapheme_split && length($gc)) > $length ? length($gc) : $length;
2096 160         448 pos($string)+= $length;
2097 160         797 last;
2098             }
2099             }
2100              
2101 4         17 push @$rules,[undef,undef,1];
2102 4 100       15 @split = map {$rules->[$_][2] ? 1 : 0} @split;
  164         338  
2103 4         17 my $count = 0;
2104 4         12 my @sections = ('.');
2105 4         17 foreach my $split (@split) {
2106 164 100       296 $count++ unless $split;
2107 164         245 $sections[$count] .= '.';
2108             }
2109            
2110 4         22 my $regex = '(' . join(')(', @sections) . ')';
2111 4         117 $regex = qr{ \A $regex \z}msx;
2112 4         57 @split = $string =~ $regex;
2113              
2114 4         55 return @split;
2115             }
2116              
2117             =back
2118              
2119             =head2 Characters
2120              
2121             =over 4
2122              
2123             =item is_exemplar_character( $type, $character)
2124              
2125             =item is_exemplar_character($character)
2126              
2127             Tests if the given character is used in the locale. There are
2128             three possible types; C<main>, C<auxiliary> and C<punctuation>.
2129             If no type is given C<main> is assumed. Unless the C<index> type
2130             is given you will have to have a Perl version of 5.18 or above
2131             to use this method
2132              
2133             =cut
2134              
2135             sub is_exemplar_character {
2136 6     6 1 57 my ($self, @parameters) = @_;
2137 6 100       26 unshift @parameters, 'main' if @parameters == 1;
2138              
2139 6 50       29 _new_perl() unless $parameters[0] eq 'index';
2140            
2141 6         28 my @bundles = $self->_find_bundle('characters');
2142 6         18 foreach my $bundle (@bundles) {
2143 9         345 my $characters = $bundle->characters->{lc $parameters[0]};
2144 9 100       21 next unless defined $characters;
2145 7 100       61 return 1 if fc($parameters[1])=~$characters;
2146             }
2147              
2148 3         16 return;
2149             }
2150              
2151             =item index_characters()
2152              
2153             Returns an array ref of characters normally used when creating
2154             an index and ordered appropriately.
2155              
2156             =cut
2157              
2158             sub index_characters {
2159 1     1 1 412 my $self = shift;
2160              
2161 1         5 my @bundles = $self->_find_bundle('characters');
2162 1         3 foreach my $bundle (@bundles) {
2163 1         40 my $characters = $bundle->characters->{index};
2164 1 50       4 next unless defined $characters;
2165 1         14 return $characters;
2166             }
2167 0         0 return [];
2168             }
2169              
2170             sub _truncated {
2171 6     6   20 my ($self, $type, @params) = @_;
2172              
2173 6         24 my @bundles = $self->_find_bundle('ellipsis');
2174 6         14 foreach my $bundle (@bundles) {
2175 6         225 my $ellipsis = $bundle->ellipsis->{$type};
2176 6 50       15 next unless defined $ellipsis;
2177 6         37 $ellipsis=~s{ \{ 0 \} }{$params[0]}msx;
2178 6         17 $ellipsis=~s{ \{ 1 \} }{$params[1]}msx;
2179 6         43 return $ellipsis;
2180             }
2181             }
2182              
2183             =back
2184              
2185             =head2 Truncation
2186              
2187             These methods format a string to show where part of the string has been removed
2188              
2189             =over 4
2190              
2191             =item truncated_beginning($string)
2192              
2193             Adds the locale specific marking to show that the
2194             string has been truncated at the beginning.
2195              
2196             =cut
2197              
2198             sub truncated_beginning {
2199 1     1 1 30 shift->_truncated(initial => @_);
2200             }
2201              
2202             =item truncated_between($string, $string)
2203              
2204             Adds the locale specific marking to show that something
2205             has been truncated between the two strings. Returns a
2206             string comprising of the concatenation of the first string,
2207             the mark and the second string
2208              
2209             =cut
2210              
2211             sub truncated_between {
2212 1     1 1 7 shift->_truncated(medial => @_);
2213             }
2214              
2215             =item truncated_end($string)
2216              
2217             Adds the locale specific marking to show that the
2218             string has been truncated at the end.
2219              
2220             =cut
2221              
2222             sub truncated_end {
2223 1     1 1 5 shift->_truncated(final => @_);
2224             }
2225              
2226             =item truncated_word_beginning($string)
2227              
2228             Adds the locale specific marking to show that the
2229             string has been truncated at the beginning. This
2230             should be used in preference to C<truncated_beginning>
2231             when the truncation occurs on a word boundary.
2232              
2233             =cut
2234              
2235             sub truncated_word_beginning {
2236 1     1 1 5 shift->_truncated('word-initial' => @_);
2237             }
2238              
2239             =item truncated_word_between($string, $string)
2240              
2241             Adds the locale specific marking to show that something
2242             has been truncated between the two strings. Returns a
2243             string comprising of the concatenation of the first string,
2244             the mark and the second string. This should be used in
2245             preference to C<truncated_between> when the truncation
2246             occurs on a word boundary.
2247              
2248             =cut
2249              
2250             sub truncated_word_between {
2251 1     1 1 5 shift->_truncated('word-medial' => @_);
2252             }
2253              
2254             =item truncated_word_end($string)
2255              
2256             Adds the locale specific marking to show that the
2257             string has been truncated at the end. This should be
2258             used in preference to C<truncated_end> when the
2259             truncation occurs on a word boundary.
2260              
2261             =cut
2262              
2263             sub truncated_word_end {
2264 1     1 1 6 shift->_truncated('word-final' => @_);
2265             }
2266              
2267             =back
2268              
2269             =head2 Quoting
2270              
2271             =over 4
2272              
2273             =item quote($string)
2274              
2275             Adds the locale's primary quotation marks to the ends of the string.
2276             Also scans the string for paired primary and auxiliary quotation
2277             marks and flips them.
2278              
2279             eg passing C<z “abc” z> to this method for the C<en_GB> locale
2280             gives C<“z ‘abc’ z”>
2281              
2282             =cut
2283              
2284             sub quote {
2285 3     3 1 1536 my ($self, $text) = @_;
2286              
2287 3         5 my %quote;
2288 3         17 my @bundles = $self->_find_bundle('quote_start');
2289 3         10 foreach my $bundle (@bundles) {
2290 3         117 my $quote = $bundle->quote_start;
2291 3 50       10 next unless defined $quote;
2292 3         9 $quote{start} = $quote;
2293 3         4 last;
2294             }
2295              
2296 3         11 @bundles = $self->_find_bundle('quote_end');
2297 3         12 foreach my $bundle (@bundles) {
2298 3         114 my $quote = $bundle->quote_end;
2299 3 50       9 next unless defined $quote;
2300 3         8 $quote{end} = $quote;
2301 3         6 last;
2302             }
2303              
2304 3         12 @bundles = $self->_find_bundle('alternate_quote_start');
2305 3         10 foreach my $bundle (@bundles) {
2306 3         119 my $quote = $bundle->alternate_quote_start;
2307 3 50       11 next unless defined $quote;
2308 3         7 $quote{alternate_start} = $quote;
2309 3         6 last;
2310             }
2311              
2312 3         11 @bundles = $self->_find_bundle('alternate_quote_end');
2313 3         7 foreach my $bundle (@bundles) {
2314 3         117 my $quote = $bundle->alternate_quote_end;
2315 3 50       9 next unless defined $quote;
2316 3         7 $quote{alternate_end} = $quote;
2317 3         5 last;
2318             }
2319              
2320             # Check to see if we need to switch quotes
2321 3         11 foreach (qw( start end alternate_start alternate_end)) {
2322 12   50     38 $quote{$_} //= '';
2323             }
2324              
2325 3         9 my $from = join ' | ', map {quotemeta} @quote{qw( start end alternate_start alternate_end)};
  12         34  
2326 3         7 my %to;
2327             @to{@quote{qw( start end alternate_start alternate_end)}}
2328 3         18 = @quote{qw( alternate_start alternate_end start end)};
2329              
2330 3         13 my $outer = index($text, $quote{start});
2331 3         6 my $inner = index($text, $quote{alternate_start});
2332              
2333 3 50 33     25 if ($inner == -1 || ($outer > -1 && $inner > -1 && $outer < $inner)) {
      33        
      66        
2334 3         86 $text =~ s{ ( $from ) }{ $to{$1} }msxeg;
  6         28  
2335             }
2336              
2337 3         26 return "$quote{start}$text$quote{end}";
2338             }
2339              
2340             =back
2341              
2342             =head2 Miscellaneous
2343              
2344             =over 4
2345              
2346             =item more_information()
2347              
2348             The more information string is one that can be displayed
2349             in an interface to indicate that more information is
2350             available.
2351              
2352             =cut
2353              
2354             sub more_information {
2355 1     1 1 3 my $self = shift;
2356              
2357 1         5 my @bundles = $self->_find_bundle('more_information');
2358 1         4 foreach my $bundle (@bundles) {
2359 1         44 my $info = $bundle->more_information;
2360 1 50       4 next unless defined $info;
2361 1         8 return $info;
2362             }
2363 0         0 return '';
2364             }
2365              
2366              
2367             =item measurement()
2368              
2369             Returns the measurement type for the locale
2370              
2371             =cut
2372              
2373             sub measurement {
2374 1     1 1 25 my $self = shift;
2375            
2376 1         43 my $measurement_data = $self->measurement_system;
2377 1   50     6 my $region = $self->region_id || '001';
2378            
2379 1         4 my $data = $measurement_data->{$region};
2380            
2381 1         5 until (defined $data) {
2382 0         0 $region = $self->region_contained_by->{$region};
2383 0         0 $data = $measurement_data->{$region};
2384             }
2385            
2386 1         10 return $data;
2387             }
2388              
2389             =item paper()
2390              
2391             Returns the paper type for the locale
2392              
2393             =cut
2394              
2395             sub paper {
2396 1     1 1 4 my $self = shift;
2397            
2398 1         45 my $paper_size = $self->paper_size;
2399 1   50     5 my $region = $self->region_id || '001';
2400            
2401 1         5 my $data = $paper_size->{$region};
2402            
2403 1         4 until (defined $data) {
2404 0         0 $region = $self->region_contained_by->{$region};
2405 0         0 $data = $paper_size->{$region};
2406             }
2407            
2408 1         6 return $data;
2409             }
2410              
2411             =back
2412              
2413             =head2 Units
2414              
2415             =over 4
2416              
2417             =item all_units()
2418              
2419             Returns a list of all the unit identifiers for the locale
2420              
2421             =cut
2422              
2423             sub all_units {
2424 0     0 1 0 my $self = shift;
2425 0         0 my @bundles = $self->_find_bundle('units');
2426            
2427 0         0 my %units;
2428 0         0 foreach my $bundle (reverse @bundles) {
2429 0         0 %units = %units, $bundle->units;
2430             }
2431            
2432 0         0 return keys %units;
2433             }
2434              
2435             =item unit($number, $unit, $width)
2436              
2437             Returns the localised string for the given number and unit formatted for the
2438             required width. The number must not be the localized version of the number.
2439             The returned string will be in the locale's format, including the number.
2440              
2441             =cut
2442              
2443             sub unit {
2444 738     738 1 2126 my ($self, $number, $what, $type) = @_;
2445 738   100     2717 $type //= 'long';
2446            
2447 738         3060 my $plural = $self->plural($number);
2448            
2449 738         2371 my @bundles = $self->_find_bundle('units');
2450 738         1241 my $format;
2451 738         1349 foreach my $bundle (@bundles) {
2452 748 100       28543 if (exists $bundle->units()->{$type}{$what}{$plural}) {
2453 728         26457 $format = $bundle->units()->{$type}{$what}{$plural};
2454 728         1380 last;
2455             }
2456            
2457 20 50       752 if (exists $bundle->units()->{$type}{$what}{other}) {
2458 0         0 $format = $bundle->units()->{$type}{$what}{other};
2459 0         0 last;
2460             }
2461             }
2462            
2463             # Check for aliases
2464 738 100       1876 unless ($format) {
2465 10         18 my $original_type = $type;
2466 10         28 my @aliases = $self->_find_bundle('unit_alias');
2467 10         22 foreach my $alias (@aliases) {
2468 10         393 $type = $alias->unit_alias()->{$original_type};
2469 10 50       29 next unless $type;
2470 10         18 foreach my $bundle (@bundles) {
2471 16 100       590 if (exists $bundle->units()->{$type}{$what}{$plural}) {
2472 4         144 $format = $bundle->units()->{$type}{$what}{$plural};
2473 4         9 last;
2474             }
2475            
2476 12 50       438 if (exists $bundle->units()->{$type}{$what}{other}) {
2477 0         0 $format = $bundle->units()->{$type}{$what}{other};
2478 0         0 last;
2479             }
2480             }
2481             }
2482 10         24 $type = $original_type;
2483             }
2484            
2485             # Check for a compound unit that we don't specifically have
2486 738 100 66     2144 if (! $format && (my ($dividend, $divisor) = $what =~ /^(.+)-per-(.+)$/)) {
2487 6         20 return $self->_unit_compound($number, $dividend, $divisor, $type);
2488             }
2489            
2490 732         3306 $number = $self->format_number($number);
2491 732 50       1770 return $number unless $format;
2492            
2493 732         2703 $format =~ s/\{0\}/$number/g;
2494            
2495 732         8873 return $format;
2496             }
2497              
2498             sub _unit_compound {
2499 6     6   13 my ($self, $number, $dividend_what, $divisor_what, $type) = @_;
2500            
2501 6   50     16 $type //= 'long';
2502            
2503 6         20 my $dividend = $self->unit($number, $dividend_what, $type);
2504 6         24 my $divisor = $self->_unit_per($divisor_what, $type);
2505 6 50       17 if ($divisor) {
2506 6         9 my $format = $divisor;
2507 6         17 $format =~ s/\{0\}/$dividend/;
2508 6         47 return $format;
2509             }
2510            
2511 0         0 $divisor = $self->unit(1, $divisor_what, $type);
2512            
2513 0         0 my $one = $self->format_number(1);
2514 0         0 $divisor =~ s/\s*$one\s*//;
2515            
2516 0         0 my @bundles = $self->_find_bundle('units');
2517 0         0 my $format;
2518 0         0 foreach my $bundle (@bundles) {
2519 0 0       0 if (exists $bundle->units()->{$type}{per}{''}) {
2520 0         0 $format = $bundle->units()->{$type}{per}{''};
2521 0         0 last;
2522             }
2523             }
2524              
2525             # Check for aliases
2526 0 0       0 unless ($format) {
2527 0         0 my $original_type = $type;
2528 0         0 my @aliases = $self->_find_bundle('unit_alias');
2529 0         0 foreach my $alias (@aliases) {
2530 0         0 $type = $alias->unit_alias()->{$original_type};
2531 0         0 foreach my $bundle (@bundles) {
2532 0 0       0 if (exists $bundle->units()->{$type}{per}{1}) {
2533 0         0 $format = $bundle->units()->{$type}{per}{1};
2534 0         0 last;
2535             }
2536             }
2537             }
2538             }
2539            
2540 0         0 $format =~ s/\{0\}/$dividend/g;
2541 0         0 $format =~ s/\{1\}/$divisor/g;
2542            
2543 0         0 return $format;
2544             }
2545              
2546             =item unit_name($unit_identifier)
2547              
2548             This method returns the localised name of the unit
2549              
2550             =cut
2551              
2552             sub unit_name {
2553 0     0 1 0 my ($self, $what) = @_;
2554            
2555 0         0 my @bundles = $self->_find_bundle('units');
2556 0         0 my $name;
2557 0         0 foreach my $bundle (@bundles) {
2558 0 0       0 if (exists $bundle->units()->{long}{$what}{name}) {
2559 0         0 return $bundle->units()->{long}{$what}{name};
2560             }
2561             }
2562            
2563             # Check for aliases
2564 0         0 my $type = 'long';
2565 0         0 my @aliases = $self->_find_bundle('unit_alias');
2566 0         0 foreach my $alias (@aliases) {
2567 0         0 $type = $alias->unit_alias()->{$type};
2568 0 0       0 next unless $type;
2569 0         0 foreach my $bundle (@bundles) {
2570 0 0       0 if (exists $bundle->units()->{$type}{$what}{name}) {
2571 0         0 return $bundle->units()->{$type}{$what}{name};
2572             }
2573             }
2574             }
2575            
2576 0         0 return '';
2577             }
2578              
2579             sub _unit_per {
2580 6     6   12 my ($self, $what, $type) = @_;
2581            
2582 6         15 my @bundles = $self->_find_bundle('units');
2583 6         11 my $name;
2584 6         13 foreach my $bundle (@bundles) {
2585 8 100       305 if (exists $bundle->units()->{$type}{$what}{per}) {
2586 4         142 return $bundle->units()->{$type}{$what}{per};
2587             }
2588             }
2589            
2590             # Check for aliases
2591 2         8 my @aliases = $self->_find_bundle('unit_alias');
2592 2         5 foreach my $alias (@aliases) {
2593 2         76 $type = $alias->unit_alias()->{$type};
2594 2 50       8 next unless $type;
2595 2         5 foreach my $bundle (@bundles) {
2596 2 50       99 if (exists $bundle->units()->{$type}{$what}{per}) {
2597 2         75 return $bundle->units()->{$type}{$what}{per};
2598             }
2599             }
2600             }
2601            
2602 0         0 return '';
2603             }
2604              
2605             sub _get_time_separator {
2606 12     12   22 my $self = shift;
2607              
2608 12         34 my @number_symbols_bundles = $self->_find_bundle('number_symbols');
2609 12         70 my $symbols_type = $self->default_numbering_system;
2610            
2611 12         31 foreach my $bundle (@number_symbols_bundles) {
2612 24 50       934 if (exists $bundle->number_symbols()->{$symbols_type}{alias}) {
2613 0         0 $symbols_type = $bundle->number_symbols()->{$symbols_type}{alias};
2614 0         0 redo;
2615             }
2616            
2617             return $bundle->number_symbols()->{$symbols_type}{timeSeparator}
2618 24 100       910 if exists $bundle->number_symbols()->{$symbols_type}{timeSeparator};
2619             }
2620 0         0 return ':';
2621             }
2622              
2623             =item duration_unit($format, @data)
2624              
2625             This method formats a duration. The format must be one of
2626             C<hm>, C<hms> or C<ms> corresponding to C<hour minute>,
2627             C<hour minute second> and C<minute second> respectively.
2628             The data must correspond to the given format.
2629              
2630             =cut
2631              
2632             sub duration_unit {
2633             # data in hh,mm; hh,mm,ss or mm,ss
2634 3     3 1 11 my ($self, $format, @data) = @_;
2635            
2636 3         10 my $bundle = $self->_find_bundle('duration_units');
2637 3         124 my $parsed = $bundle->duration_units()->{$format};
2638            
2639 3         5 my $num_format = '#';
2640 3         19 foreach my $entry ( qr/(hh?)/, qr/(mm?)/, qr/(ss?)/) {
2641 9 100       51 $num_format = '00' if $parsed =~ s/$entry/$self->format_number(shift(@data), $num_format)/e;
  7         31  
2642             }
2643            
2644 3         18 my $time_separator = $self->_get_time_separator;
2645            
2646 3         14 $parsed =~ s/:/$time_separator/g;
2647            
2648 3         20 return $parsed;
2649             }
2650              
2651             =back
2652              
2653             =head2 Yes or No?
2654              
2655             =over 4
2656              
2657             =item is_yes($string)
2658              
2659             Returns true if the passed in string matches the locale's
2660             idea of a string designating yes. Note that under POSIX
2661             rules unless the locale's word for yes starts with C<Y>
2662             (U+0079) then a single 'y' will also be accepted as yes.
2663             The string will be matched case insensitive.
2664              
2665             =cut
2666              
2667             sub is_yes {
2668 2     2 1 5 my ($self, $test_str) = @_;
2669            
2670 2         11 my $bundle = $self->_find_bundle('yesstr');
2671 2 100       81 return $test_str =~ $bundle->yesstr ? 1 : 0;
2672             }
2673              
2674             =item is_no($string)
2675              
2676             Returns true if the passed in string matches the locale's
2677             idea of a string designating no. Note that under POSIX
2678             rules unless the locale's word for no starts with C<n>
2679             (U+006E) then a single 'n' will also be accepted as no
2680             The string will be matched case insensitive.
2681              
2682             =cut
2683              
2684             sub is_no {
2685 2     2 1 6 my ($self, $test_str) = @_;
2686            
2687 2         9 my $bundle = $self->_find_bundle('nostr');
2688 2 100       86 return $test_str =~ $bundle->nostr ? 1 : 0;
2689             }
2690              
2691             =back
2692              
2693             =head2 Transliteration
2694              
2695             This method requires Perl version 5.18 or above to use and for you to have
2696             installed the optional C<Bundle::CLDR::Transformations>
2697              
2698             =over 4
2699              
2700             =item transform(from => $from, to => $to, variant => $variant, text => $text)
2701              
2702             This method returns the transliterated string of C<text> from script C<from>
2703             to script C<to> using variant C<variant>. If C<from> is not given then the
2704             current locale's script is used. If C<text> is not given then it defaults to an
2705             empty string. The C<variant> is optional.
2706              
2707             =cut
2708              
2709             sub transform {
2710 0     0 1 0 _new_perl();
2711            
2712 0         0 my ($self, %params) = @_;
2713            
2714 0   0     0 my $from = $params{from} // $self;
2715 0         0 my $to = $params{to};
2716 0   0     0 my $variant = $params{variant} // 'Any';
2717 0   0     0 my $text = $params{text} // '';
2718            
2719 0 0       0 ($from, $to) = map {ref $_ ? $_->likely_script() : $_} ($from, $to);
  0         0  
2720 0         0 $_ = ucfirst(lc $_) foreach ($from, $to, $variant);
2721            
2722 0         0 my $package = __PACKAGE__ . "::Transformations::${variant}::${from}::${to}";
2723 0         0 eval { Class::Load::load_class($package); };
  0         0  
2724 0 0       0 warn $@ if $@;
2725 0 0       0 return $text if $@; # Can't load transform module so return original text
2726 20     20   160 use feature 'state';
  20         46  
  20         231725  
2727 0         0 state $transforms;
2728 0   0     0 $transforms->{$variant}{$from}{$to} //= $package->new();
2729 0         0 my $rules = $transforms->{$variant}{$from}{$to}->transforms();
2730            
2731             # First get the filter rule
2732 0         0 my $filter = $rules->[0];
2733            
2734             # Break up the input on the filter
2735 0         0 my @text;
2736 0         0 pos($text) = 0;
2737 0         0 while (pos($text) < length($text)) {
2738 0         0 my $characters = '';
2739 0         0 while (my ($char) = $text =~ /($filter)/) {
2740 0         0 $characters .= $char;
2741 0         0 pos($text) = pos($text) + length $char;
2742             }
2743 0         0 push @text, $characters;
2744 0 0       0 last unless pos($text) < length $text;
2745            
2746 0         0 $characters = '';
2747 0         0 while ($text !~ /$filter/) {
2748 0         0 my ($char) = $text =~ /\G(\X)/;
2749 0         0 $characters .= $char;
2750 0         0 pos($text) = pos($text) + length $char;
2751             }
2752 0         0 push @text, $characters;
2753             }
2754            
2755 0         0 my $to_transform = 1;
2756            
2757 0         0 foreach my $characters (@text) {
2758 0 0       0 if ($to_transform) {
2759 0         0 foreach my $rule (@$rules[1 .. @$rules -1 ]) {
2760 0 0       0 if ($rule->{type} eq 'transform') {
2761 0         0 $characters = $self->_transformation_transform($characters, $rule->{data}, $variant);
2762             }
2763             else {
2764 0         0 $characters = $self->_transform_convert($characters, $rule->{data});
2765             }
2766             }
2767             }
2768 0         0 $to_transform = ! $to_transform;
2769             }
2770            
2771 0         0 return join '', @text;
2772             }
2773              
2774             sub _transformation_transform {
2775 0     0   0 my ($self, $text, $rules, $variant) = @_;
2776            
2777 0         0 foreach my $rule (@$rules) {
2778 0         0 for (lc $rule->{to}) {
2779 0 0       0 if ($_ eq 'nfc') {
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
2780 0         0 $text = Unicode::Normalize::NFC($text);
2781             }
2782             elsif($_ eq 'nfd') {
2783 0         0 $text = Unicode::Normalize::NFD($text);
2784             }
2785             elsif($_ eq 'nfkd') {
2786 0         0 $text = Unicode::Normalize::NFKD($text);
2787             }
2788             elsif($_ eq 'nfkc') {
2789 0         0 $text = Unicode::Normalize::NFKC($text);
2790             }
2791             elsif($_ eq 'lower') {
2792 0         0 $text = lc($text);
2793             }
2794             elsif($_ eq 'upper') {
2795 0         0 $text = uc($text);
2796             }
2797             elsif($_ eq 'title') {
2798 0         0 $text =~ s/(\X)/\u$1/g;
2799             }
2800             elsif($_ eq 'null') {
2801             }
2802             elsif($_ eq 'remove') {
2803 0         0 $text = '';
2804             }
2805             else {
2806 0         0 $text = $self->transform($text, $variant, $rule->{from}, $rule->to);
2807             }
2808             }
2809             }
2810 0         0 return $text;
2811             }
2812              
2813             sub _transform_convert {
2814 0     0   0 my ($self, $text, $rules) = @_;
2815            
2816 0         0 pos($text) = 0; # Make sure we start scanning at the beginning of the text
2817            
2818 0         0 CHARACTER: while (pos($text) < length($text)) {
2819 0         0 foreach my $rule (@$rules) {
2820 0 0 0     0 next if length $rule->{before} && $text !~ /$rule->{before}\G/;
2821 0         0 my $regex = $rule->{replace};
2822 0 0       0 $regex .= '(' . $rule->{after} . ')' if length $rule->{after};
2823 0         0 my $result = 'q(' . $rule->{result} . ')';
2824 0 0       0 $result .= '. $1' if length $rule->{after};
2825 0 0       0 if ($text =~ s/\G$regex/eval $result/e) {
  0         0  
2826 0         0 pos($text) += length($rule->{result}) - $rule->{revisit};
2827 0         0 next CHARACTER;
2828             }
2829             }
2830            
2831 0         0 pos($text)++;
2832             }
2833            
2834 0         0 return $text;
2835             }
2836              
2837             =back
2838              
2839             =head2 Lists
2840              
2841             =over 4
2842              
2843             =item list(@data)
2844              
2845             Returns C<data> as a string formatted by the locales idea of producing a list
2846             of elements. What is returned can be effected by the locale and the number
2847             of items in C<data>. Note that C<data> can contain 0 or more items.
2848              
2849             =cut
2850              
2851             sub list {
2852 5     5 1 43 my ($self, @data) = @_;
2853            
2854             # Short circuit on 0 or 1 entries
2855 5 100       28 return '' unless @data;
2856 4 100       20 return $data[0] if 1 == @data;
2857            
2858 3         15 my @bundles = $self->_find_bundle('listPatterns');
2859            
2860 3         7 my %list_data;
2861 3         8 foreach my $bundle (reverse @bundles) {
2862 6         8 my %listPatterns = %{$bundle->listPatterns};
  6         240  
2863 6         37 @list_data{keys %listPatterns} = values %listPatterns;
2864             }
2865            
2866 3 100       12 if (my $pattern = $list_data{scalar @data}) {
2867 1         9 $pattern=~s/\{([0-9]+)\}/$data[$1]/eg;
  2         14  
2868 1         14 return $pattern;
2869             }
2870            
2871 2         8 my ($start, $middle, $end) = @list_data{qw( start middle end )};
2872            
2873             # First do the end
2874 2         4 my $pattern = $end;
2875 2         9 $pattern=~s/\{1\}/pop @data/e;
  2         8  
2876 2         8 $pattern=~s/\{0\}/pop @data/e;
  2         4  
2877            
2878             # If there is any data left do the middle
2879 2         8 while (@data > 1) {
2880 1         3 my $current = $pattern;
2881 1         2 $pattern = $middle;
2882 1         4 $pattern=~s/\{1\}/$current/;
2883 1         5 $pattern=~s/\{0\}/pop @data/e;
  1         5  
2884             }
2885            
2886             # Now do the start
2887 2         4 my $current = $pattern;
2888 2         6 $pattern = $start;
2889 2         6 $pattern=~s/\{1\}/$current/;
2890 2         7 $pattern=~s/\{0\}/pop @data/e;
  2         5  
2891            
2892 2         14 return $pattern;
2893             }
2894              
2895             =back
2896              
2897             =head2 Pluralisation
2898              
2899             =over 4
2900              
2901             =item plural($number)
2902              
2903             This method takes a number and uses the locale's pluralisation
2904             rules to calculate the type of pluralisation required for
2905             units, currencies and other data that changes depending on
2906             the plural state of the number
2907              
2908             =item plural_range($start, $end)
2909              
2910             This method returns the plural type for the range $start to $end
2911             $start and $end can either be numbers or one of the plural types
2912             C<zero one two few many other>
2913              
2914             =cut
2915              
2916             sub _clear_calendar_data {
2917 0     0   0 my $self = shift;
2918              
2919 0         0 foreach my $property (qw(
2920             month_format_wide month_format_abbreviated month_format_narrow
2921             month_stand_alone_wide month_stand_alone_abbreviated
2922             month_stand_alone_narrow day_format_wide day_format_abbreviated
2923             day_format_narrow day_stand_alone_wide day_stand_alone_abreviated
2924             day_stand_alone_narrow quater_format_wide quater_format_abbreviated
2925             quater_format_narrow quater_stand_alone_wide
2926             quater_stand_alone_abreviated quater_stand_alone_narrow
2927             am_pm_wide am_pm_abbreviated am_pm_narrow am_pm_format_wide
2928             am_pm_format_abbreviated am_pm_format_narrow am_pm_stand_alone_wide
2929             am_pm_stand_alone_abbreviated am_pm_stand_alone_narrow era_wide
2930             era_abbreviated era_narrow date_format_full date_format_long date_format_medium
2931             date_format_short time_format_full
2932             time_format_long time_format_medium time_format_short
2933             datetime_format_full datetime_format_long
2934             datetime_format_medium datetime_format_short
2935             available_formats format_data
2936             )) {
2937 0         0 my $method = "_clear_$property";
2938 0         0 $self->$method;
2939             }
2940             }
2941              
2942             sub _build_any_month {
2943 8     8   18 my ($self, $type, $width) = @_;
2944 8         36 my $default_calendar = $self->default_calendar();
2945 8         37 my @bundles = $self->_find_bundle('calendar_months');
2946             BUNDLES: {
2947 8         15 foreach my $bundle (@bundles) {
  12         27  
2948 16         657 my $months = $bundle->calendar_months;
2949 16 50       54 if (exists $months->{$default_calendar}{alias}) {
2950 0         0 $default_calendar = $months->{$default_calendar}{alias};
2951 0         0 redo BUNDLES;
2952             }
2953              
2954 16 100       60 if (exists $months->{$default_calendar}{$type}{$width}{alias}) {
2955 4         9 ($type, $width) = @{$months->{$default_calendar}{$type}{$width}{alias}}{qw(context type)};
  4         21  
2956 4         15 redo BUNDLES;
2957             }
2958            
2959 12         28 my $result = $months->{$default_calendar}{$type}{$width}{nonleap};
2960 12 100       313 return $result if defined $result;
2961             }
2962 0 0       0 if ($default_calendar ne 'gregorian') {
2963 0         0 $default_calendar = 'gregorian';
2964 0         0 redo BUNDLES;
2965             }
2966             }
2967 0         0 return [];
2968             }
2969              
2970             sub _build_month_format_wide {
2971 2     2   4 my $self = shift;
2972 2         9 my ($type, $width) = (qw(format wide));
2973            
2974 2         12 return $self->_build_any_month($type, $width);
2975             }
2976              
2977             sub _build_month_format_abbreviated {
2978 1     1   2 my $self = shift;
2979 1         4 my ($type, $width) = (qw(format abbreviated));
2980            
2981 1         5 return $self->_build_any_month($type, $width);
2982             }
2983              
2984             sub _build_month_format_narrow {
2985 1     1   3 my $self = shift;
2986 1         4 my ($type, $width) = (qw(format narrow));
2987            
2988 1         13 return $self->_build_any_month($type, $width);
2989             }
2990              
2991             sub _build_month_stand_alone_wide {
2992 1     1   2 my $self = shift;
2993 1         4 my ($type, $width) = ('stand-alone', 'wide');
2994            
2995 1         4 return $self->_build_any_month($type, $width);
2996             }
2997              
2998             sub _build_month_stand_alone_abbreviated {
2999 2     2   5 my $self = shift;
3000 2         5 my ($type, $width) = ('stand-alone', 'abbreviated');
3001            
3002 2         11 return $self->_build_any_month($type, $width);
3003             }
3004              
3005             sub _build_month_stand_alone_narrow {
3006 1     1   3 my $self = shift;
3007 1         4 my ($type, $width) = ('stand-alone', 'narrow');
3008            
3009 1         4 return $self->_build_any_month($type, $width);
3010             }
3011              
3012             sub _build_any_day {
3013 7     7   16 my ($self, $type, $width) = @_;
3014            
3015 7         28 my $default_calendar = $self->default_calendar();
3016              
3017 7         35 my @bundles = $self->_find_bundle('calendar_days');
3018             BUNDLES: {
3019 7         15 foreach my $bundle (@bundles) {
  10         24  
3020 13         502 my $days= $bundle->calendar_days;
3021            
3022 13 50       41 if (exists $days->{$default_calendar}{alias}) {
3023 0         0 $default_calendar = $days->{$default_calendar}{alias};
3024 0         0 redo BUNDLES;
3025             }
3026              
3027 13 100       79 if (exists $days->{$default_calendar}{$type}{$width}{alias}) {
3028 3         4 ($type, $width) = @{$days->{$default_calendar}{$type}{$width}{alias}}{qw(context type)};
  3         15  
3029 3         10 redo BUNDLES;
3030             }
3031 10         18 my $result = $days->{$default_calendar}{$type}{$width};
3032 10 100       37 return [ @{$result}{qw( mon tue wed thu fri sat sun )} ] if keys %$result;
  7         287  
3033             }
3034 0 0       0 if ($default_calendar ne 'gregorian') {
3035 0         0 $default_calendar = 'gregorian';
3036 0         0 redo BUNDLES;
3037             }
3038             }
3039              
3040 0         0 return [];
3041             }
3042              
3043             sub _build_day_format_wide {
3044 2     2   12 my $self = shift;
3045 2         6 my ($type, $width) = (qw(format wide));
3046            
3047 2         17 return $self->_build_any_day($type, $width);
3048             }
3049              
3050             sub _build_day_format_abbreviated {
3051 1     1   2 my $self = shift;
3052 1         4 my ($type, $width) = (qw(format abbreviated));
3053            
3054 1         6 return $self->_build_any_day($type, $width);
3055             }
3056              
3057             sub _build_day_format_narrow {
3058 1     1   3 my $self = shift;
3059 1         3 my ($type, $width) = (qw(format narrow));
3060            
3061 1         4 return $self->_build_any_day($type, $width);
3062             }
3063              
3064             sub _build_day_stand_alone_wide {
3065 1     1   2 my $self = shift;
3066 1         4 my ($type, $width) = ('stand-alone', 'wide');
3067            
3068 1         4 return $self->_build_any_day($type, $width);
3069             }
3070              
3071             sub _build_day_stand_alone_abbreviated {
3072 1     1   2 my $self = shift;
3073 1         4 my ($type, $width) = ('stand-alone', 'abbreviated');
3074              
3075 1         3 return $self->_build_any_day($type, $width);
3076             }
3077              
3078             sub _build_day_stand_alone_narrow {
3079 1     1   8 my $self = shift;
3080 1         3 my ($type, $width) = ('stand-alone', 'narrow');
3081            
3082 1         3 return $self->_build_any_day($type, $width);
3083             }
3084              
3085             sub _build_any_quarter {
3086 6     6   13 my ($self, $type, $width) = @_;
3087            
3088 6         17 my $default_calendar = $self->default_calendar();
3089              
3090 6         20 my @bundles = $self->_find_bundle('calendar_quarters');
3091             BUNDLES: {
3092 6         12 foreach my $bundle (@bundles) {
  9         17  
3093 12         499 my $quarters= $bundle->calendar_quarters;
3094            
3095 12 50       36 if (exists $quarters->{$default_calendar}{alias}) {
3096 0         0 $default_calendar = $quarters->{$default_calendar}{alias};
3097 0         0 redo BUNDLES;
3098             }
3099              
3100 12 100       42 if (exists $quarters->{$default_calendar}{$type}{$width}{alias}) {
3101 3         6 ($type, $width) = @{$quarters->{$default_calendar}{$type}{$width}{alias}}{qw(context type)};
  3         14  
3102 3         9 redo BUNDLES;
3103             }
3104            
3105 9         17 my $result = $quarters->{$default_calendar}{$type}{$width};
3106 9 100       28 return [ @{$result}{qw( 0 1 2 3 )} ] if keys %$result;
  6         240  
3107             }
3108 0 0       0 if ($default_calendar ne 'gregorian') {
3109 0         0 $default_calendar = 'gregorian';
3110 0         0 redo BUNDLES;
3111             }
3112             }
3113              
3114 0         0 return [];
3115             }
3116              
3117             sub _build_quarter_format_wide {
3118 1     1   3 my $self = shift;
3119 1         3 my ($type, $width) = (qw( format wide ));
3120            
3121 1         5 return $self->_build_any_quarter($type, $width);
3122             }
3123              
3124             sub _build_quarter_format_abbreviated {
3125 1     1   3 my $self = shift;
3126 1         3 my ($type, $width) = (qw(format abbreviated));
3127              
3128 1         10 return $self->_build_any_quarter($type, $width);
3129             }
3130              
3131             sub _build_quarter_format_narrow {
3132 1     1   3 my $self = shift;
3133 1         3 my ($type, $width) = (qw(format narrow));
3134              
3135 1         3 return $self->_build_any_quarter($type, $width);
3136             }
3137              
3138             sub _build_quarter_stand_alone_wide {
3139 1     1   3 my $self = shift;
3140 1         4 my ($type, $width) = ('stand-alone', 'wide');
3141              
3142 1         9 return $self->_build_any_quarter($type, $width);
3143             }
3144              
3145             sub _build_quarter_stand_alone_abbreviated {
3146 1     1   2 my $self = shift;
3147 1         3 my ($type, $width) = ('stand-alone', 'abbreviated');
3148            
3149 1         4 return $self->_build_any_quarter($type, $width);
3150             }
3151              
3152             sub _build_quarter_stand_alone_narrow {
3153 1     1   2 my $self = shift;
3154 1         2 my ($type, $width) = ('stand-alone', 'narrow');
3155              
3156 1         4 return $self->_build_any_quarter($type, $width);
3157             }
3158              
3159             sub get_day_period {
3160             # Time in hhmm
3161 3     3 1 1701 my ($self, $time, $type) = @_;
3162 3   50     17 $type //= 'default';
3163            
3164 3         12 my $default_calendar = $self->default_calendar();
3165            
3166 3         11 my $bundle = $self->_find_bundle('day_period_data');
3167            
3168 3         122 my $day_period = $bundle->day_period_data;
3169 3         15 $day_period = $self->$day_period($default_calendar, $time, $type);
3170            
3171             # The day period for root is commented out but I need that data so will
3172             # fix up here as a default
3173 3 0 33     10 $day_period ||= $time < 1200 ? 'am' : 'pm';
3174            
3175 3         113 my $am_pm = $self->am_pm_format_abbreviated;
3176            
3177 3         17 return $am_pm->{$day_period};
3178             }
3179              
3180             sub _build_any_am_pm {
3181 10     10   21 my ($self, $type, $width) = @_;
3182              
3183 10         37 my $default_calendar = $self->default_calendar();
3184 10         28 my @result;
3185 10         31 my @bundles = $self->_find_bundle('day_periods');
3186 10         18 my %return;
3187              
3188             BUNDLES: {
3189 10         15 foreach my $bundle (@bundles) {
  19         38  
3190 38         1471 my $am_pm = $bundle->day_periods;
3191            
3192 38 50       108 if (exists $am_pm->{$default_calendar}{alias}) {
3193 0         0 $default_calendar = $am_pm->{$default_calendar}{alias};
3194 0         0 redo BUNDLES;
3195             }
3196              
3197 38 50       112 if (exists $am_pm->{$default_calendar}{$type}{alias}) {
3198 0         0 $type = $am_pm->{$default_calendar}{$type}{alias};
3199 0         0 redo BUNDLES;
3200             }
3201            
3202 38 100       114 if (exists $am_pm->{$default_calendar}{$type}{$width}{alias}) {
3203 9         11 my $original_width = $width;
3204 9         26 $width = $am_pm->{$default_calendar}{$type}{$width}{alias}{width};
3205 9         19 $type = $am_pm->{$default_calendar}{$type}{$original_width}{alias}{context};
3206 9         24 redo BUNDLES;
3207             }
3208            
3209 29         52 my $result = $am_pm->{$default_calendar}{$type}{$width};
3210            
3211 29         89 foreach (keys %$result) {
3212 140 100       419 $return{$_} = $result->{$_} unless exists $return{$_};
3213             }
3214             }
3215             }
3216              
3217 10         230 return \%return;
3218             }
3219              
3220             # The first 3 are to link in with Date::Time::Locale
3221             sub _build_am_pm_wide {
3222 1     1   2 my $self = shift;
3223 1         3 my ($type, $width) = (qw( format wide ));
3224            
3225 1         6 my $result = $self->_build_any_am_pm($type, $width);
3226            
3227 1         41 return [ @$result{qw( am pm )} ];
3228             }
3229              
3230             sub _build_am_pm_abbreviated {
3231 2     2   7 my $self = shift;
3232 2         7 my ($type, $width) = (qw( format abbreviated ));
3233              
3234 2         12 my $result = $self->_build_any_am_pm($type, $width);
3235            
3236 2         81 return [ @$result{qw( am pm )} ];
3237             }
3238              
3239             sub _build_am_pm_narrow {
3240 1     1   2 my $self = shift;
3241 1         9 my ($type, $width) = (qw( format narrow ));
3242            
3243 1         5 my $result = $self->_build_any_am_pm($type, $width);
3244            
3245 1         38 return [ @$result{qw( am pm )} ];
3246             }
3247              
3248             # Now we do the full set of data
3249             sub _build_am_pm_format_wide {
3250 1     1   3 my $self = shift;
3251 1         3 my ($type, $width) = (qw( format wide ));
3252            
3253 1         4 return $self->_build_any_am_pm($type, $width);
3254             }
3255              
3256             sub _build_am_pm_format_abbreviated {
3257 1     1   3 my $self = shift;
3258 1         3 my ($type, $width) = (qw( format abbreviated ));
3259              
3260 1         4 return $self->_build_any_am_pm($type, $width);
3261             }
3262              
3263             sub _build_am_pm_format_narrow {
3264 1     1   2 my $self = shift;
3265 1         3 my ($type, $width) = (qw( format narrow ));
3266            
3267 1         4 return $self->_build_any_am_pm($type, $width);
3268             }
3269              
3270             sub _build_am_pm_stand_alone_wide {
3271 1     1   3 my $self = shift;
3272 1         9 my ($type, $width) = ('stand-alone', 'wide');
3273            
3274 1         3 return $self->_build_any_am_pm($type, $width);
3275             }
3276              
3277             sub _build_am_pm_stand_alone_abbreviated {
3278 1     1   2 my $self = shift;
3279 1         3 my ($type, $width) = ('stand-alone', 'abbreviated');
3280              
3281 1         5 return $self->_build_any_am_pm($type, $width);
3282             }
3283              
3284             sub _build_am_pm_stand_alone_narrow {
3285 1     1   3 my $self = shift;
3286 1         3 my ($type, $width) = ('stand-alone', 'narrow');
3287            
3288 1         4 return $self->_build_any_am_pm($type, $width);
3289             }
3290              
3291             sub _build_any_era {
3292 9     9   15 my ($self, $width) = @_;
3293              
3294 9         28 my $default_calendar = $self->default_calendar();
3295 9         27 my @bundles = $self->_find_bundle('eras');
3296             BUNDLES: {
3297 9         15 foreach my $bundle (@bundles) {
  9         19  
3298 9         339 my $eras = $bundle->eras;
3299            
3300 9 50       30 if (exists $eras->{$default_calendar}{alias}) {
3301 0         0 $default_calendar = $eras->{$default_calendar}{alias};
3302 0         0 redo BUNDLES;
3303             }
3304              
3305 9 50       28 if (exists $eras->{$default_calendar}{$width}{alias}) {
3306 0         0 $width = $eras->{$default_calendar}{$width}{alias};
3307 0         0 redo BUNDLES;
3308             }
3309            
3310 9         15 my $result = $eras->{$default_calendar}{$width};
3311            
3312 9         10 my @result;
3313 9         47 @result[keys %$result] = values %$result;
3314            
3315 9 50       236 return \@result if keys %$result;
3316             }
3317 0 0       0 if ($default_calendar ne 'gregorian') {
3318 0         0 $default_calendar = 'gregorian';
3319 0         0 redo BUNDLES;
3320             }
3321             }
3322              
3323 0         0 return [];
3324             }
3325            
3326             # The next three are for DateDime::Locale
3327             sub _build_era_wide {
3328 1     1   2 my $self = shift;
3329 1         4 my ($width) = (qw( wide ));
3330              
3331 1         5 my $result = $self->_build_any_era($width);
3332            
3333 1         36 return [@$result[0, 1]];
3334             }
3335              
3336             sub _build_era_abbreviated {
3337 1     1   4 my $self = shift;
3338 1         3 my ($width) = (qw( abbreviated ));
3339              
3340 1         5 my $result = $self->_build_any_era($width);
3341            
3342 1         38 return [@$result[0, 1]];
3343             }
3344              
3345             sub _build_era_narrow {
3346 1     1   3 my $self = shift;
3347 1         3 my ($width) = (qw( narrow ));
3348              
3349 1         3 my $result = $self->_build_any_era($width);
3350            
3351 1         37 return [@$result[0, 1]];
3352             }
3353              
3354             # Now get all the era data
3355             sub _build_era_format_wide {
3356 2     2   9 my $self = shift;
3357 2         4 my ($width) = (qw( wide ));
3358              
3359 2         7 return $self->_build_any_era($width);
3360             }
3361              
3362             sub _build_era_format_abbreviated {
3363 2     2   9 my $self = shift;
3364 2         5 my ($width) = (qw( abbreviated ));
3365              
3366 2         6 return $self->_build_any_era($width);
3367             }
3368              
3369             sub _build_era_format_narrow {
3370 2     2   5 my $self = shift;
3371 2         3 my ($type, $width) = (qw( narrow ));
3372              
3373 2         12 return $self->_build_any_era($type, $width);
3374             }
3375              
3376             *_build_era_stand_alone_wide = \&_build_era_format_wide;
3377             *_build_era_stand_alone_abbreviated = \&_build_era_format_abbreviated;
3378             *_build_era_stand_alone_narrow = \&_build_era_format_narrow;
3379              
3380             sub _build_any_date_format {
3381 9     9   21 my ($self, $width) = @_;
3382 9         32 my $default_calendar = $self->default_calendar();
3383            
3384 9         37 my @bundles = $self->_find_bundle('date_formats');
3385              
3386             BUNDLES: {
3387 9         22 foreach my $bundle (@bundles) {
  9         21  
3388 9         350 my $date_formats = $bundle->date_formats;
3389 9 50       35 if (exists $date_formats->{alias}) {
3390 0         0 $default_calendar = $date_formats->{alias};
3391 0         0 redo BUNDLES;
3392             }
3393            
3394 9         28 my $result = $date_formats->{$default_calendar}{$width};
3395 9 50       173 return $result if $result;
3396             }
3397 0 0       0 if ($default_calendar ne 'gregorian') {
3398 0         0 $default_calendar = 'gregorian';
3399 0         0 redo BUNDLES;
3400             }
3401             }
3402            
3403 0         0 return '';
3404             }
3405              
3406             sub _build_date_format_full {
3407 1     1   3 my $self = shift;
3408            
3409 1         3 my ($width) = ('full');
3410 1         7 return $self->_build_any_date_format($width);
3411             }
3412              
3413             sub _build_date_format_long {
3414 1     1   3 my $self = shift;
3415            
3416 1         4 my ($width) = ('long');
3417 1         5 return $self->_build_any_date_format($width);
3418             }
3419              
3420             sub _build_date_format_medium {
3421 1     1   3 my $self = shift;
3422            
3423 1         3 my ($width) = ('medium');
3424 1         4 return $self->_build_any_date_format($width);
3425             }
3426              
3427             sub _build_date_format_short {
3428 1     1   3 my $self = shift;
3429            
3430 1         2 my ($width) = ('short');
3431 1         4 return $self->_build_any_date_format($width);
3432             }
3433              
3434             sub _build_any_time_format {
3435 9     9   18 my ($self, $width) = @_;
3436 9         33 my $default_calendar = $self->default_calendar();
3437            
3438 9         34 my @bundles = $self->_find_bundle('time_formats');
3439              
3440             BUNDLES: {
3441 9         20 foreach my $bundle (@bundles) {
  9         23  
3442 9         351 my $time_formats = $bundle->time_formats;
3443 9 50       42 if (exists $time_formats->{$default_calendar}{alias}) {
3444 0         0 $default_calendar = $time_formats->{$default_calendar}{alias};
3445 0         0 redo BUNDLES;
3446             }
3447            
3448 9         25 my $result = $time_formats->{$default_calendar}{$width};
3449 9 50       28 if ($result) {
3450 9         41 my $time_separator = $self->_get_time_separator;
3451 9         42 $result =~ s/:/$time_separator/g;
3452 9         163 return $result;
3453             }
3454             }
3455 0 0       0 if ($default_calendar ne 'gregorian') {
3456 0         0 $default_calendar = 'gregorian';
3457 0         0 redo BUNDLES;
3458             }
3459             }
3460 0         0 return '';
3461             }
3462              
3463             sub _build_time_format_full {
3464 1     1   3 my $self = shift;
3465 1         3 my $width = 'full';
3466            
3467 1         5 return $self->_build_any_time_format($width);
3468             }
3469              
3470             sub _build_time_format_long {
3471 1     1   2 my $self = shift;
3472            
3473 1         4 my $width = 'long';
3474 1         5 return $self->_build_any_time_format($width);
3475             }
3476              
3477             sub _build_time_format_medium {
3478 1     1   3 my $self = shift;
3479            
3480 1         3 my $width = 'medium';
3481 1         4 return $self->_build_any_time_format($width);
3482             }
3483              
3484             sub _build_time_format_short {
3485 1     1   2 my $self = shift;
3486            
3487 1         3 my $width = 'short';
3488 1         4 return $self->_build_any_time_format($width);
3489             }
3490              
3491             sub _build_any_datetime_format {
3492 5     5   14 my ($self, $width) = @_;
3493 5         25 my $default_calendar = $self->default_calendar();
3494            
3495 5         27 my @bundles = $self->_find_bundle('datetime_formats');
3496              
3497             BUNDLES: {
3498 5         11 foreach my $bundle (@bundles) {
  5         16  
3499 5         245 my $datetime_formats = $bundle->datetime_formats;
3500 5 50       23 if (exists $datetime_formats->{$default_calendar}{alias}) {
3501 0         0 $default_calendar = $datetime_formats->{$default_calendar}{alias};
3502 0         0 redo BUNDLES;
3503             }
3504            
3505 5         15 my $result = $datetime_formats->{$default_calendar}{$width};
3506 5 50       27 return $result if $result;
3507             }
3508 0 0       0 if ($default_calendar ne 'gregorian') {
3509 0         0 $default_calendar = 'gregorian';
3510 0         0 redo BUNDLES;
3511             }
3512             }
3513            
3514 0         0 return '';
3515             }
3516              
3517             sub _build_datetime_format_full {
3518 2     2   7 my $self = shift;
3519            
3520 2         9 my $width = 'full';
3521 2         17 my $format = $self->_build_any_datetime_format($width);
3522            
3523 2         17 my $date = $self->_build_any_date_format($width);
3524 2         14 my $time = $self->_build_any_time_format($width);
3525            
3526 2         12 $format =~ s/\{0\}/$time/;
3527 2         11 $format =~ s/\{1\}/$date/;
3528            
3529 2         72 return $format;
3530             }
3531              
3532             sub _build_datetime_format_long {
3533 1     1   2 my $self = shift;
3534            
3535 1         3 my $width = 'long';
3536 1         5 my $format = $self->_build_any_datetime_format($width);
3537            
3538 1         5 my $date = $self->_build_any_date_format($width);
3539 1         6 my $time = $self->_build_any_time_format($width);
3540            
3541 1         5 $format =~ s/\{0\}/$time/;
3542 1         5 $format =~ s/\{1\}/$date/;
3543            
3544 1         36 return $format;
3545             }
3546              
3547             sub _build_datetime_format_medium {
3548 1     1   2 my $self = shift;
3549            
3550 1         2 my $width = 'medium';
3551 1         7 my $format = $self->_build_any_datetime_format($width);
3552            
3553 1         5 my $date = $self->_build_any_date_format($width);
3554 1         5 my $time = $self->_build_any_time_format($width);
3555            
3556 1         4 $format =~ s/\{0\}/$time/;
3557 1         6 $format =~ s/\{1\}/$date/;
3558            
3559 1         36 return $format;
3560             }
3561              
3562             sub _build_datetime_format_short {
3563 1     1   3 my $self = shift;
3564            
3565 1         3 my $width = 'short';
3566 1         4 my $format = $self->_build_any_datetime_format($width);
3567            
3568 1         5 my $date = $self->_build_any_date_format($width);
3569 1         4 my $time = $self->_build_any_time_format($width);
3570            
3571 1         5 $format =~ s/\{0\}/$time/;
3572 1         3 $format =~ s/\{1\}/$date/;
3573            
3574 1         35 return $format;
3575             }
3576              
3577             sub _build_format_data {
3578 0     0   0 my $self = shift;
3579 0         0 my $default_calendar = $self->default_calendar();
3580              
3581 0         0 my @bundles = $self->_find_bundle('datetime_formats_available_formats');
3582 0         0 foreach my $calendar ($default_calendar, 'gregorian') {
3583 0         0 foreach my $bundle (@bundles) {
3584 0         0 my $datetime_formats_available_formats = $bundle->datetime_formats_available_formats;
3585 0         0 my $result = $datetime_formats_available_formats->{$calendar};
3586 0 0       0 return $result if $result;
3587             }
3588             }
3589              
3590 0         0 return {};
3591             }
3592              
3593             sub format_for {
3594 0     0 1 0 my ($self, $format) = @_;
3595              
3596 0         0 my $format_data = $self->format_data;
3597              
3598 0   0     0 return $format_data->{$format} // '';
3599             }
3600              
3601             sub _build_available_formats {
3602 0     0   0 my $self = shift;
3603              
3604 0         0 my $format_data = $self->format_data;
3605              
3606 0         0 return [keys %$format_data];
3607             }
3608              
3609             sub _build_default_date_format_length {
3610 0     0   0 my $self = shift;
3611            
3612 0         0 my $default_calendar = $self->default_calendar();
3613              
3614 0         0 my @bundles = $self->_find_bundle('date_formats');
3615 0         0 foreach my $calendar ($default_calendar, 'gregorian') {
3616 0         0 foreach my $bundle (@bundles) {
3617 0         0 my $date_formats = $bundle->date_formats;
3618 0         0 my $result = $date_formats->{$calendar}{default};
3619 0 0       0 return $result if $result;
3620             }
3621             }
3622             }
3623              
3624             sub _build_default_time_format_length {
3625 0     0   0 my $self = shift;
3626            
3627 0         0 my $default_calendar = $self->default_calendar();
3628              
3629 0         0 my @bundles = $self->_find_bundle('time_formats');
3630 0         0 foreach my $calendar ($default_calendar, 'gregorian') {
3631 0         0 foreach my $bundle (@bundles) {
3632 0         0 my $time_formats = $bundle->time_formats;
3633 0         0 my $result = $time_formats->{$calendar}{default};
3634 0 0       0 return $result if $result;
3635             }
3636             }
3637             }
3638              
3639             sub _build_prefers_24_hour_time {
3640 1     1   2 my $self = shift;
3641              
3642 1 50       40 return $self->time_format_short() =~ /h|K/ ? 0 : 1;
3643             }
3644              
3645             {
3646             my %days_2_number = (
3647             mon => 1,
3648             tue => 2,
3649             wen => 3,
3650             thu => 4,
3651             fri => 5,
3652             sat => 6,
3653             sun => 7,
3654             );
3655              
3656             sub _build_first_day_of_week {
3657              
3658 1     1   3 my $self = shift;
3659              
3660 1         6 my $first_day = $self->week_data_first_day;
3661            
3662 1         36 return $days_2_number{$first_day};
3663             }
3664             }
3665              
3666             # Sub to mangle Unicode regex to Perl regex
3667             # Backwards compatibility hack
3668 20 50   20   183 *_unicode_to_perl = eval <<'EOT' || \&_new_perl;
  20     20   45  
  20     163   1160  
  20         108  
  20         45  
  20         1119  
  163         338  
  163         661  
  163         992  
  99         2995  
  163         2747  
3669             sub {
3670             my $regex = shift;
3671              
3672             return '' unless length $regex;
3673             $regex =~ s/
3674             (?:\\\\)*+ # Pairs of \
3675             (?!\\) # Not followed by \
3676             \K # But we don't want to keep that
3677             (?<set> # Capture this
3678             \[ # Start a set
3679             (?:
3680             [^\[\]\\]+ # One or more of not []\
3681             | # or
3682             (?:
3683             (?:\\\\)*+ # One or more pairs of \ without back tracking
3684             \\. # Followed by an escaped character
3685             )
3686             | # or
3687             (?&set) # An inner set
3688             )++ # Do the inside set stuff one or more times without backtracking
3689             \] # End the set
3690             )
3691             / _convert($1) /xeg;
3692             no warnings "experimental::regex_sets";
3693             no warnings "deprecated"; # Because CLDR uses surrogates
3694             return qr/$regex/x;
3695             };
3696              
3697             EOT
3698              
3699             # Backwards compatibility hack
3700 99 50   99   253 *_convert = eval <<'EOT' || \&_new_perl;
  99 50       355  
  99         267  
  0         0  
  99         148  
  99         1212  
  99         291  
  99         256  
  99         3754  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
3701             sub {
3702             my $set = shift;
3703            
3704             # Some definitions
3705             my $posix = qr/(?(DEFINE)
3706             (?<posix> (?> \[: .+? :\] ) )
3707             )/x;
3708            
3709             # Convert Unicode escapes \u1234 to characters
3710             $set =~ s/\\u(\p{Ahex}+)/chr(hex($1))/egx;
3711            
3712             # Check to see if this is a normal character set
3713             my $normal = 0;
3714            
3715             $normal = 1 if $set =~ /^
3716             \s* # Possible white space
3717             \[ # Opening set
3718             ^? # Possible negation
3719             (?: # One of
3720             [^\[\]]++ # Not an open or close set
3721             | # Or
3722             (?<=\\)[\[\]] # An open or close set preceded by \
3723             | # Or
3724             (?:
3725             \s* # Possible white space
3726             (?&posix) # A posix class
3727             (?! # Not followed by
3728             \s* # Possible white space
3729             [&-] # A Unicode regex op
3730             \s* # Possible white space
3731             \[ # A set opener
3732             )
3733             )
3734             )+
3735             \] # Close the set
3736             \s* # Possible white space
3737             $
3738             $posix
3739             /x;
3740            
3741             # Convert posix to perl
3742             $set =~ s/\[:(.*?):\]/\\p{$1}/g;
3743            
3744             if ($normal) {
3745             return "$set";
3746             }
3747            
3748             # Fix up [abc[de]] to [[abc][de]]
3749             $set =~ s/\[ ( (?>\^? \s*) [^\]]+? ) \s* \[/[[$1][/gx;
3750            
3751             # Fix up [[ab]cde] to [[ab][cde]]
3752             $set =~ s/\[ \^?+ \s* \[ [^\]]+? \] \K \s* ( [^\[]+ ) \]/[$1]]/gx;
3753            
3754             # Unicode uses ^ to compliment the set where as Perl uses !
3755             $set =~ s/\[ \^ \s*/[!/gx;
3756            
3757             # The above can leave us with empty sets. Strip them out
3758             $set =~ s/\[\]//g;
3759            
3760             # Fixup inner sets with no operator
3761             1 while $set =~ s/ \] \s* \[ /] + [/gx;
3762             1 while $set =~ s/ \] \s * (\\p\{.*?\}) /] + $1/xg;
3763             1 while $set =~ s/ \\p\{.*?\} \s* \K \[ / + [/xg;
3764             1 while $set =~ s/ \\p\{.*?\} \s* \K (\\p\{.*?\}) / + $1/xg;
3765            
3766             # Unicode uses [] for grouping as well as starting an inner set
3767             # Perl uses ( ) So fix that up now
3768            
3769             $set =~ s/. \K \[ (?> (!?) \s*) \[ /($1\[/gx;
3770             $set =~ s/ \] \s* \] (.) /])$1/gx;
3771            
3772             return "(?$set)";
3773             }
3774              
3775             EOT
3776              
3777             # The following pod is for methods defined in the Moose Role
3778             # files that are automatically generated from the data
3779             =back
3780              
3781             =head2 Valid codes
3782              
3783             =over 4
3784              
3785             =item valid_languages()
3786              
3787             This method returns a list containing all the valid language codes
3788              
3789             =item valid_scripts()
3790              
3791             This method returns a list containing all the valid script codes
3792              
3793             =item valid_regions()
3794              
3795             This method returns a list containing all the valid region codes
3796              
3797             =item valid_variants()
3798              
3799             This method returns a list containing all the valid variant codes
3800              
3801             =item key_aliases()
3802              
3803             This method returns a hash that maps valid keys to their valid aliases
3804              
3805             =item key_names()
3806              
3807             This method returns a hash that maps valid key aliases to their valid keys
3808              
3809             =item valid_keys()
3810              
3811             This method returns a hash of valid keys and the valid type codes you
3812             can have with each key
3813              
3814             =item language_aliases()
3815              
3816             This method returns a hash that maps valid language codes to their valid aliases
3817              
3818             =item region_aliases()
3819              
3820             This method returns a hash that maps valid region codes to their valid aliases
3821              
3822             =item variant_aliases()
3823              
3824             This method returns a hash that maps valid variant codes to their valid aliases
3825              
3826             =back
3827              
3828             =head2 Information about weeks
3829              
3830             There are no standard codes for the days of the weeks so CLDR uses the following
3831             three letter codes to represent unlocalised days
3832              
3833             =over 4
3834              
3835             =item sun
3836              
3837             Sunday
3838              
3839             =item mon
3840              
3841             Monday
3842              
3843             =item tue
3844              
3845             Tuesday
3846              
3847             =item wed
3848              
3849             Wednesday
3850              
3851             =item thu
3852              
3853             Thursday
3854              
3855             =item fri
3856              
3857             Friday
3858              
3859             =item sat
3860              
3861             Saturday
3862              
3863             =back
3864              
3865             =cut
3866              
3867             sub _week_data {
3868 5     5   11 my ($self, $region_id, $week_data_hash) = @_;
3869            
3870 5   33     33 $region_id //= ( $self->region_id || $self->likely_subtag->region_id );
      33        
3871            
3872 5 100       31 return $week_data_hash->{$region_id} if exists $week_data_hash->{$region_id};
3873            
3874 2         5 while (1) {
3875 8         300 $region_id = $self->region_contained_by()->{$region_id};
3876 8 50       19 return unless defined $region_id;
3877 8 100       30 return $week_data_hash->{$region_id} if exists $week_data_hash->{$region_id};
3878             }
3879             }
3880              
3881             =over 4
3882              
3883             =item week_data_min_days($region_id)
3884              
3885             This method takes an optional region id and returns a the minimum number of days
3886             a week must have to count as the starting week of the new year. It uses the current
3887             locale's region if no region id is passed in.
3888              
3889             =cut
3890              
3891             sub week_data_min_days {
3892 1     1 1 3 my ($self, $region_id) = @_;
3893            
3894 1         47 my $week_data_hash = $self->_week_data_min_days();
3895 1         4 return _week_data($self, $region_id, $week_data_hash);
3896             }
3897              
3898             =item week_data_first_day($region_id)
3899              
3900             This method takes an optional region id and returns the three letter code of the
3901             first day of the week for that region. If no region id is passed in then it
3902             uses the current locale's region.
3903              
3904             =cut
3905              
3906             sub week_data_first_day {
3907 2     2 1 4 my ($self, $region_id) = @_;
3908            
3909 2         90 my $week_data_hash = $self->_week_data_first_day();
3910 2         7 return _week_data($self, $region_id, $week_data_hash);
3911             }
3912              
3913             =item week_data_weekend_start()
3914              
3915             This method takes an optional region id and returns the three letter code of the
3916             first day of the week end for that region. If no region id is passed in then it
3917             uses the current locale's region.
3918              
3919             =cut
3920              
3921             sub week_data_weekend_start {
3922 1     1 1 2 my ($self, $region_id) = @_;
3923 1         45 my $week_data_hash = $self->_week_data_weekend_start();
3924            
3925 1         6 return _week_data($self, $region_id, $week_data_hash);
3926             }
3927              
3928             =item week_data_weekend_end()
3929              
3930             This method takes an optional region id and returns the three letter code of the
3931             first day of the week end for that region. If no region id is passed in then it
3932             uses the current locale's region.
3933              
3934             =cut
3935              
3936             sub week_data_weekend_end {
3937 1     1 1 3 my ($self, $region_id) = @_;
3938 1         47 my $week_data_hash = $self->_week_data_weekend_end();
3939            
3940 1         5 return _week_data($self, $region_id, $week_data_hash);
3941             }
3942              
3943             =item month_patterns($context, $width, $type)
3944              
3945             The Chinese lunar calendar can insert a leap month after nearly any month of its year;
3946             when this happens, the month takes the name of the preceding month plus a special marker.
3947             The Hindu lunar calendars can insert a leap month before any one or two months of the year;
3948             when this happens, not only does the leap month take the name of the following month plus a
3949             special marker, the following month also takes a special marker. Moreover, in the Hindu
3950             calendar sometimes a month is skipped, in which case the preceding month takes a special marker
3951             plus the names of both months. The monthPatterns() method returns an array ref of month names
3952             with the marker added.
3953              
3954             =cut
3955              
3956             my %month_functions = (
3957             format => {
3958             wide => 'month_format_wide',
3959             abbreviated => 'month_format_abbreviated',
3960             narrow => 'month_format_narrow',
3961             },
3962             'stand-alone' => {
3963             wide => 'month_stand_alone_wide',
3964             abbreviated => 'month_stand_alone_abbreviated',
3965             narrow => 'month_stand_alone_narrow',
3966             }
3967             );
3968              
3969             sub month_patterns {
3970 1     1 1 3801 my ($self, $context, $width, $type) = @_;
3971            
3972 1         4 my @months;
3973 1 50       25 if ($context eq 'numeric') {
3974 0         0 @months = ( 1 .. 14 );
3975             }
3976             else {
3977 1         8 my $months_method = $month_functions{$context}{$width};
3978 1         70 my $months = $self->$months_method;
3979 1         7 @months = @$months;
3980             }
3981            
3982 1         8 my $default_calendar = $self->default_calendar();
3983            
3984 1         6 my @bundles = $self->_find_bundle('month_patterns');
3985              
3986 1         3 my $result;
3987             BUNDLES: {
3988 1         2 foreach my $bundle (@bundles) {
  2         7  
3989 2         80 my $month_patterns = $bundle->month_patterns;
3990 2 50       9 if (exists $month_patterns->{$default_calendar}{alias}) {
3991 0         0 $default_calendar = $month_patterns->{$default_calendar}{alias};
3992 0         0 redo BUNDLES;
3993             }
3994            
3995             # Check for width alias
3996 2 100       9 if (exists $month_patterns->{$default_calendar}{$context}{$width}{alias}) {
3997 1         4 $context = $month_patterns->{$default_calendar}{$context}{$width}{alias}{context};
3998 1         3 $width = $month_patterns->{$default_calendar}{$context}{$width}{alias}{width};
3999 1         5 redo BUNDLES;
4000             }
4001            
4002 1         5 $result = $month_patterns->{$default_calendar}{$context}{$width}{$type};
4003 1 50       6 last BUNDLES if $result;
4004             }
4005 0 0       0 if ($default_calendar ne 'gregorian') {
4006 0         0 $default_calendar = 'gregorian';
4007 0         0 redo BUNDLES;
4008             }
4009             }
4010            
4011 1 50       6 if ($result) {
4012 1         3 foreach my $month (@months) {
4013 12         26 (my $fixed_month = $result) =~ s/\{0\}/$month/g;
4014 12         21 $month = $fixed_month;
4015             }
4016             }
4017            
4018 1         15 return \@months;
4019             }
4020              
4021             =item cyclic_name_sets($context, $width, $type)
4022              
4023             This method returns an arrayref containing the cyclic names for the locale's
4024             default calendar using the given context, width and type.
4025              
4026             Context can can currently only be c<format>
4027              
4028             Width is one of C<abbreviated>, C<narrow> or C<wide>
4029              
4030             Type is one of C<dayParts>, C<days>, C<months>, C<solarTerms>, C<years> or C<zodiacs>
4031              
4032             =cut
4033              
4034             sub cyclic_name_sets {
4035 1     1 1 10 my ($self, $context, $width, $type) = @_;
4036            
4037 1         12 my @bundles = $self->_find_bundle('cyclic_name_sets');
4038 1         13 my $default_calendar = $self->default_calendar();
4039 1         4 foreach my $bundle (@bundles) {
4040 2         100 my $cyclic_name_set = $bundle->cyclic_name_sets();
4041             NAME_SET: {
4042 2 50       5 if (my $alias_calendar = $cyclic_name_set->{$default_calendar}{alias}) {
  3         14  
4043 0         0 $default_calendar = $alias_calendar;
4044 0         0 redo NAME_SET;
4045             }
4046            
4047 3 50       14 if (my $type_alias = $cyclic_name_set->{$default_calendar}{$type}{alias}) {
4048 0         0 $type = $type_alias;
4049 0         0 redo NAME_SET;
4050             }
4051            
4052 3 100       15 if (my $width_alias = $cyclic_name_set->{$default_calendar}{$type}{$context}{$width}{alias}) {
4053 1         4 $context = $width_alias->{context};
4054 1         3 $type = $width_alias->{name_set};
4055 1         3 $width = $width_alias->{type};
4056 1         4 redo NAME_SET;
4057             }
4058            
4059             my $return = [
4060 2         11 @{ $cyclic_name_set->{$default_calendar}{$type}{$context}{$width} }
4061 2         5 {sort { $a <=> $b } keys %{ $cyclic_name_set->{$default_calendar}{$type}{$context}{$width} }}
  31         42  
  2         18  
4062             ];
4063            
4064 2 100       24 return $return if @$return;
4065             }
4066             }
4067 0         0 return [];
4068             }
4069              
4070             =back
4071              
4072             =head2 region Containment
4073              
4074             =over 4
4075              
4076             =item region_contains()
4077              
4078             This method returns a hash ref keyed on region id. The value is an array ref.
4079             Each element of the array ref is a region id of a region immediately
4080             contained in the region used as the key
4081              
4082             =item region_contained_by()
4083              
4084             This method returns a hash ref keyed on region id. The value of the hash
4085             is the region id of the immediately containing region.
4086              
4087             =back
4088              
4089             =head2 Numbering Systems
4090              
4091             =over 4
4092              
4093             =item numbering_system()
4094              
4095             This method returns a hash ref keyed on numbering system id which, for a given
4096             locale, can be got by calling the default_numbering_system() method. The values
4097             of the hash are a two element hash ref the keys being C<type> and C<data>. If the
4098             type is C<numeric> then the data is an array ref of characters. The position in the
4099             array matches the numeric value of the character. If the type is C<algorithmic>
4100             then data is the name of the algorithm used to display numbers in that format.
4101              
4102             =back
4103              
4104             =head2 Number Formatting
4105              
4106             =over 4
4107              
4108             =item format_number($number, $format, $currency, $for_cash)
4109              
4110             This method formats the number $number using the format $format. If the format contains
4111             the currency symbol C<¤> then the currency symbol for the currency code in $currency
4112             will be used. If $currency is undef() then the default currency code for the locale
4113             will be used.
4114              
4115             Note that currency codes are based on region so if you do not pass in a currency
4116             and your locale did not get passed a region in the constructor you are going
4117             to end up with the L<likely sub tag's|/likely_subtags> idea of the currency. This
4118             functionality may be removed or at least changed to emit a warning in future
4119             releases.
4120              
4121             $for_cash is only used during currency formatting. If true then cash rounding
4122             will be used otherwise financial rounding will be used.
4123              
4124             This function also handles rule based number formatting. If $format is string equivalent
4125             to one of the current locale's public rule based number formats then $number will be
4126             formatted according to that rule.
4127              
4128             =item format_currency($number, $for_cash)
4129              
4130             This method formats the number $number using the default currency and currency format for the locale.
4131             If $for_cash is a true value then cash rounding will be used otherwise financial rounding will be used.
4132              
4133             =item default_currency_formt
4134              
4135             This method returns the currency format for the current locale
4136              
4137             It takes no paramaters
4138              
4139             =item add_currency_symbol($format, $symbol)
4140              
4141             This method returns the format with the currency symbol $symbol correctly inserted
4142             into the format
4143              
4144             =item parse_number_format($format, $currency, $currency_data, $for_cash)
4145              
4146             This method parses a CLDR numeric format string into a hash ref containing data used to
4147             format a number. If a currency is being formatted then $currency contains the
4148             currency code, $currency_data is a hashref containing the currency rounding
4149             information and $for_cash is a flag to signal cash or financial rounding.
4150              
4151             This should probably be a private function.
4152              
4153             =item round($number, $increment, $decimal_digits)
4154              
4155             This method returns $number rounded to the nearest $increment with $decimal_digits
4156             digits after the decimal point
4157              
4158             =item get_formatted_number($number, $format, $currency_data, $for_cash)
4159              
4160             This method takes the $format produced by parse_number_format() and uses it to
4161             parse $number. It returns a string containing the parsed number. If a currency
4162             is being formatted then $currency_data is a hashref containing the currency
4163             rounding information and $for_cash is a flag to signal cash or financial rounding.
4164              
4165             =item get_digits()
4166              
4167             This method returns an array containing the digits used by the locale, The order of the
4168             array is the order of the digits. It the locale's numbering system is C<algorithmic> it
4169             will return C<[0,1,2,3,4,5,6,7,8,9]>
4170              
4171             =item default_numbering_system()
4172              
4173             This method returns the numbering system id for the locale.
4174              
4175             =item default_currency_format()
4176              
4177             This method returns the locale's currenc format. This can be used by the number formatting code to
4178             correctly format the locale's currency
4179              
4180             =item currency_format($format_type)
4181              
4182             This method returns the format string for the currencies for the locale
4183              
4184             There are two types of formatting I<standard> and I<accounting> you can
4185             pass C<standard> or C<account> as the paramater to the method to pick one of
4186             these ot it will use the locales default
4187              
4188             =cut
4189              
4190             sub currency_format {
4191 12     12 1 7046 my ($self, $default_currency_format) = @_;
4192            
4193 12 50 100     63 die "Invalid Currency format: must be one of 'standard' or 'account'"
      66        
4194             if defined $default_currency_format
4195             && $default_currency_format ne 'standard'
4196             && $default_currency_format ne 'account';
4197            
4198 12   66     67 $default_currency_format //= $self->default_currency_format;
4199 12         49 my @bundles = $self->_find_bundle('number_currency_formats');
4200            
4201 12         32 my $format = {};
4202 12         56 my $default_numbering_system = $self->default_numbering_system();
4203 12         38 foreach my $bundle (@bundles) {
4204             NUMBER_SYSTEM: {
4205 12         20 $format = $bundle->number_currency_formats();
  12         514  
4206 12 50       50 if (exists $format->{$default_numbering_system}{alias}) {
4207 0         0 $default_numbering_system = $format->{$default_numbering_system}{alias};
4208 0         0 redo NUMBER_SYSTEM;
4209             }
4210            
4211 12 50       49 if (exists $format->{$default_numbering_system}{pattern}{default}{$default_currency_format}{alias}) {
4212 0         0 $default_currency_format = $format->{$default_numbering_system}{pattern}{default}{$default_currency_format}{alias};
4213 0         0 redo NUMBER_SYSTEM;
4214             }
4215             }
4216            
4217 12 50       45 last if exists $format->{$default_numbering_system}{pattern}{default}{$default_currency_format}
4218             }
4219            
4220 12 100       38 $default_currency_format = 'accounting' if $default_currency_format eq 'account';
4221            
4222             return join ';',
4223             $format->{$default_numbering_system}{pattern}{default}{$default_currency_format}{positive},
4224             defined $format->{$default_numbering_system}{pattern}{default}{$default_currency_format}{negative}
4225             ? $format->{$default_numbering_system}{pattern}{default}{$default_currency_format}{negative}
4226 12 100       115 : ();
4227             }
4228              
4229             =back
4230              
4231             =head2 Measurement Information
4232              
4233             =over 4
4234              
4235             =item measurement_system()
4236              
4237             This method returns a hash ref keyed on region, the value being the measurement system
4238             id for the region. If the region you are interested in is not listed use the
4239             region_contained_by() method until you find an entry.
4240              
4241             =item paper_size()
4242              
4243             This method returns a hash ref keyed on region, the value being the paper size used
4244             in that region. If the region you are interested in is not listed use the
4245             region_contained_by() method until you find an entry.
4246              
4247             =back
4248              
4249             =head2 Likely Tags
4250              
4251             =over 4
4252              
4253             =item likely_subtags()
4254              
4255             A full locale tag requires, as a minimum, a language, script and region code. However for
4256             some locales it is possible to infer the missing element if the other two are given, e.g.
4257             given C<en_GB> you can infer the script will be latn. It is also possible to fill in the
4258             missing elements of a locale with sensible defaults given sufficient knowledge of the layout
4259             of the CLDR data and usage patterns of locales around the world.
4260              
4261             This function returns a hash ref keyed on partial locale id's with the value being the locale
4262             id for the most likely language, script and region code for the key.
4263              
4264             =back
4265              
4266             =head2 Currency Information
4267              
4268             =over 4
4269              
4270             =item currency_fractions()
4271              
4272             This method returns a hash ref keyed on currency id. The value is a hash ref containing four keys.
4273             The keys are
4274              
4275             =over 8
4276              
4277             =item digits
4278              
4279             The number of decimal digits normally formatted.
4280              
4281             =item rounding
4282              
4283             The rounding increment, in units of 10^-digits.
4284              
4285             =item cashdigits
4286              
4287             The number of decimal digits to be used when formatting quantities used in cash transactions (as opposed
4288             to a quantity that would appear in a more formal setting, such as on a bank statement).
4289              
4290             =item cashrounding
4291              
4292             The cash rounding increment, in units of 10^-cashdigits.
4293              
4294             =back
4295              
4296             =item default_currency($region_id)
4297              
4298             This method returns the default currency id for the region id.
4299             If no region id is given then the current locale's is used
4300              
4301             =cut
4302              
4303             sub default_currency {
4304 9     9 1 18 my ($self, $region_id) = @_;
4305            
4306 9   33     53 $region_id //= $self->region_id;
4307            
4308 9 50       25 if (! $region_id) {
4309 0         0 $region_id = $self->likely_subtag->region_id;
4310 0         0 warn "Locale::CLDR::default_currency:- No region given using $region_id at ";
4311             }
4312            
4313 9         339 my $default_currencies = $self->_default_currency;
4314            
4315 9 50       63 return $default_currencies->{$region_id} if exists $default_currencies->{$region_id};
4316            
4317 0         0 while (1) {
4318 0         0 $region_id = $self->region_contained_by($region_id);
4319 0 0       0 last unless $region_id;
4320 0 0       0 return $default_currencies->{$region_id} if exists $default_currencies->{$region_id};
4321             }
4322             }
4323              
4324             =item currency_symbol($currency_id)
4325              
4326             This method returns the currency symbol for the given currency id in the current locale.
4327             If no currency id is given it uses the locale's default currency
4328              
4329             =cut
4330              
4331             sub currency_symbol {
4332 9     9 1 19 my ($self, $currency_id) = @_;
4333            
4334 9   33     20 $currency_id //= $self->default_currency;
4335            
4336 9         35 my @bundles = reverse $self->_find_bundle('curriencies');
4337 9         27 foreach my $bundle (@bundles) {
4338 9         350 my $symbol = $bundle->curriencies()->{$currency_id}{symbol};
4339 9 50       50 return $symbol if $symbol;
4340             }
4341            
4342 0           return '';
4343             }
4344              
4345             =back
4346              
4347             =head2 Calendar Information
4348              
4349             =over 4
4350              
4351             =item calendar_preferences()
4352              
4353             This method returns a hash ref keyed on region id. The values are array refs containing the preferred
4354             calendar id's in order of preference.
4355              
4356             =item default_calendar($region)
4357              
4358             This method returns the default calendar id for the given region. If no region id given it
4359             used the region of the current locale.
4360              
4361             =back
4362              
4363             =head2 Collation
4364              
4365             =over 4
4366              
4367             =item collation()
4368              
4369             This method returns a Locale::CLDR::Collator object. This is still in development. Future releases will
4370             try and match the API from L<Unicode::Collate> as much as possible and add tailoring for locales.
4371              
4372             =back
4373              
4374             =cut
4375              
4376             sub collation {
4377 0     0 1   my ($self) = @_;
4378            
4379 0           my %params;
4380 0           $params{type} = $self->_collation_type;
4381 0           $params{alternate} = $self->_collation_alternate;
4382 0           $params{backwards} = $self->_collation_backwards;
4383 0           $params{case_level} = $self->_collation_case_level;
4384 0           $params{case_ordering} = $self->_collation_case_ordering;
4385 0           $params{normalization} = $self->_collation_normalization;
4386 0           $params{numeric} = $self->_collation_numeric;
4387 0           $params{reorder} = $self->_collation_reorder;
4388 0           $params{strength} = $self->_collation_strength;
4389 0           $params{max_variable} = $self->_collation_max_variable;
4390            
4391 0           return Locale::CLDR::Collator->new(locale => $self, %params);
4392             }
4393              
4394             sub _collation_overrides {
4395 0     0     my ($self, $type) = @_;
4396            
4397 0           my @bundles = reverse $self->_find_bundle('collation');
4398            
4399 0           my $override = '';
4400 0           foreach my $bundle (@bundles) {
4401 0 0         last if $override = $bundle->collation()->{$type};
4402             }
4403            
4404 0 0 0       if ($type ne 'standard' && ! $override) {
4405 0           foreach my $bundle (@bundles) {
4406 0 0         last if $override = $bundle->collation()->{standard};
4407             }
4408             }
4409            
4410 0   0       return $override || [];
4411             }
4412            
4413             sub _collation_type {
4414 0     0     my $self = shift;
4415            
4416 0 0 0       return $self->extensions()->{co} if ref $self->extensions() && $self->extensions()->{co};
4417 0           my @bundles = reverse $self->_find_bundle('collation_type');
4418 0           my $collation_type = '';
4419            
4420 0           foreach my $bundle (@bundles) {
4421 0 0         last if $collation_type = $bundle->collation_type();
4422             }
4423            
4424 0   0       return $collation_type || 'standard';
4425             }
4426              
4427             sub _collation_alternate {
4428 0     0     my $self = shift;
4429            
4430 0 0 0       return $self->extentions()->{ka} if ref $self->extensions() && $self->extentions()->{ka};
4431 0           my @bundles = reverse $self->_find_bundle('collation_alternate');
4432 0           my $collation_alternate = '';
4433            
4434 0           foreach my $bundle (@bundles) {
4435 0 0         last if $collation_alternate = $bundle->collation_alternate();
4436             }
4437            
4438 0   0       return $collation_alternate || 'noignore';
4439             }
4440              
4441             sub _collation_backwards {
4442 0     0     my $self = shift;
4443            
4444 0 0 0       return $self->extensions()->{kb} if ref $self->extensions() && $self->extensions()->{kb};
4445 0           my @bundles = reverse $self->_find_bundle('collation_backwards');
4446 0           my $collation_backwards = '';
4447            
4448 0           foreach my $bundle (@bundles) {
4449 0 0         last if $collation_backwards = $bundle->collation_backwards();
4450             }
4451            
4452 0   0       return $collation_backwards || 'noignore';
4453             }
4454              
4455             sub _collation_case_level {
4456 0     0     my $self = shift;
4457            
4458 0 0 0       return $self->extensions()->{kc} if ref $self->extensions() && $self->extensions()->{kc};
4459 0           my @bundles = reverse $self->_find_bundle('collation_case_level');
4460 0           my $collation_case_level = '';
4461            
4462 0           foreach my $bundle (@bundles) {
4463 0 0         last if $collation_case_level = $bundle->collation_case_level();
4464             }
4465            
4466 0   0       return $collation_case_level || 'false';
4467             }
4468              
4469             sub _collation_case_ordering {
4470 0     0     my $self = shift;
4471            
4472 0 0 0       return $self->extensions()->{kf} if ref $self->extensions() && $self->extensions()->{kf};
4473 0           my @bundles = reverse $self->_find_bundle('collation_case_ordering');
4474 0           my $collation_case_ordering = '';
4475            
4476 0           foreach my $bundle (@bundles) {
4477 0 0         last if $collation_case_ordering = $bundle->collation_case_ordering();
4478             }
4479            
4480 0   0       return $collation_case_ordering || 'false';
4481             }
4482              
4483             sub _collation_normalization {
4484 0     0     my $self = shift;
4485            
4486 0 0 0       return $self->extensions()->{kk} if ref $self->extensions() && $self->extensions()->{kk};
4487 0           my @bundles = reverse $self->_find_bundle('collation_normalization');
4488 0           my $collation_normalization = '';
4489            
4490 0           foreach my $bundle (@bundles) {
4491 0 0         last if $collation_normalization = $bundle->collation_normalization();
4492             }
4493            
4494 0   0       return $collation_normalization || 'true';
4495             }
4496              
4497             sub _collation_numeric {
4498 0     0     my $self = shift;
4499            
4500 0 0 0       return $self->extensions()->{kn} if ref $self->extensions() && $self->extensions()->{kn};
4501 0           my @bundles = reverse $self->_find_bundle('collation_numeric');
4502 0           my $collation_numeric = '';
4503            
4504 0           foreach my $bundle (@bundles) {
4505 0 0         last if $collation_numeric = $bundle->collation_numeric();
4506             }
4507            
4508 0   0       return $collation_numeric || 'false';
4509             }
4510              
4511             sub _collation_reorder {
4512 0     0     my $self = shift;
4513            
4514 0 0 0       return $self->extensions()->{kr} if ref $self->extensions() && $self->extensions()->{kr};
4515 0           my @bundles = reverse $self->_find_bundle('collation_reorder');
4516 0           my $collation_reorder = [];
4517            
4518 0           foreach my $bundle (@bundles) {
4519 0 0 0       last if ref( $collation_reorder = $bundle->collation_reorder()) && @$collation_reorder;
4520             }
4521            
4522 0   0       return $collation_reorder || [];
4523             }
4524              
4525             sub _collation_strength {
4526 0     0     my $self = shift;
4527            
4528 0   0       my $collation_strength = ref $self->extensions() && $self->extensions()->{ks};
4529 0 0         if ($collation_strength) {
4530 0           $collation_strength =~ s/^level//;
4531 0 0         $collation_strength = 5 unless ($collation_strength + 0);
4532 0           return $collation_strength;
4533             }
4534            
4535 0           my @bundles = reverse $self->_find_bundle('collation_strength');
4536 0           $collation_strength = 0;
4537            
4538 0           foreach my $bundle (@bundles) {
4539 0 0         last if $collation_strength = $bundle->collation_strength();
4540             }
4541            
4542 0   0       return $collation_strength || 3;
4543             }
4544              
4545             sub _collation_max_variable {
4546 0     0     my $self = shift;
4547            
4548 0 0 0       return $self->extensions()->{kv} if ref $self->extensions() && $self->extensions()->{kv};
4549 0           my @bundles = reverse $self->_find_bundle('collation_max_variable');
4550 0           my $collation_max_variable = '';
4551            
4552 0           foreach my $bundle (@bundles) {
4553 0 0         last if $collation_max_variable = $bundle->collation_max_variable();
4554             }
4555            
4556 0   0       return $collation_max_variable || 3;
4557             }
4558              
4559             =head1 Locales
4560              
4561             Other locales can be found on CPAN. You can install Language packs from the
4562             Locale::CLDR::Locales::* packages. You will in future be able to install language
4563             packs for a given region by looking for a Bundle::Locale::CLDR::* package.
4564              
4565             If you are looking for a language pack that is not yet published then get hold of
4566             the version 0.25.4 from http://search.cpan.org/CPAN/authors/id/J/JG/JGNI/Locale-CLDR-v0.25.4.tar.gz
4567             which has data for all locals alternatively you can get hold of the latest version of the
4568             code from git hub at https://github.com/ThePilgrim/perlcldr
4569              
4570             =head1 AUTHOR
4571              
4572             John Imrie, C<< <JGNI at cpan dot org> >>
4573              
4574             =head1 BUGS
4575              
4576             Please report any bugs or feature requests to C<bug-locale-cldr at rt.cpan.org>, or through
4577             the web interface at L<http://rt.cpan.org/NoAuth/ReportBug.html?Queue=Locale-CLDR>. I will be notified, and then you'll
4578             automatically be notified of progress on your bug as I make changes.
4579              
4580             =head1 SUPPORT
4581              
4582             You can find documentation for this module with the perldoc command.
4583              
4584             perldoc Locale::CLDR
4585              
4586             You can also look for information at:
4587              
4588             =over 4
4589              
4590             =item * RT: CPAN's request tracker
4591              
4592             L<http://rt.cpan.org/NoAuth/Bugs.html?Dist=Locale-CLDR>
4593              
4594             =item * AnnoCPAN: Annotated CPAN documentation
4595              
4596             L<http://annocpan.org/dist/Locale-CLDR>
4597              
4598             =item * CPAN Ratings
4599              
4600             L<http://cpanratings.perl.org/d/Locale-CLDR>
4601              
4602             =item * Search CPAN
4603              
4604             L<http://search.cpan.org/dist/Locale-CLDR/>
4605              
4606             =back
4607              
4608              
4609             =head1 ACKNOWLEDGEMENTS
4610              
4611             Everyone at the Unicode Consortium for providing the data.
4612              
4613             Karl Williams for his tireless work on Unicode in the Perl
4614             regex engine.
4615              
4616             =head1 COPYRIGHT & LICENSE
4617              
4618             Copyright 2009-2015 John Imrie.
4619              
4620             This program is free software; you can redistribute it and/or modify it
4621             under the terms of either: the GNU General Public License as published
4622             by the Free Software Foundation; or the Artistic License.
4623              
4624             See http://dev.perl.org/licenses/ for more information.
4625              
4626             =cut
4627              
4628             1; # End of Locale::CLDR