File Coverage

blib/lib/Locale/CLDR.pm
Criterion Covered Total %
statement 986 1405 70.1
branch 242 466 51.9
condition 78 217 35.9
subroutine 143 183 78.1
pod 53 53 100.0
total 1502 2324 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.2
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   567209 use v5.10.1;
  20         86  
41 20     20   13827 use version;
  20         42327  
  20         112  
42             our $VERSION = version->declare('v0.28.2');
43              
44 20     20   16709 use open ':encoding(utf8)';
  20         37280  
  20         123  
45 20     20   287866 use utf8;
  20         64  
  20         117  
46 20     20   1778 use if $^V ge v5.12.0, feature => 'unicode_strings';
  20         66  
  20         922  
47              
48 20     20   19139 use Moose;
  20         9805177  
  20         133  
49 20     20   162922 use MooseX::ClassAttribute;
  20         1936193  
  20         100  
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   6111302 use Class::Load;
  20         48  
  20         926  
56 20     20   119 use namespace::autoclean;
  20         39  
  20         220  
57 20     20   1923 use List::Util qw(first);
  20         41  
  20         1258  
58 20     20   105 use Class::MOP;
  20         34  
  20         421  
59 20     20   18700 use DateTime::Locale;
  20         1101770  
  20         684  
60 20     20   44219 use Unicode::Normalize();
  20         5527758  
  20         1420  
61 20     20   16793 use Locale::CLDR::Collator();
  20         83  
  20         722  
62 20     20   174 use File::Spec();
  20         35  
  20         2844  
63              
64             # Backwards compatibility
65             BEGIN {
66 20 50   20   101 if (defined &CORE::fc) { #v5.16
67 20         28665 *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 106     106   253 my $self = shift;
613            
614 318         946 my @path = map { ucfirst lc }
615 106 100       671 map { $_ ? $_ : 'Any' } (
  318         1078  
616             $self->language_id,
617             $self->script_id,
618             $self->region_id,
619             );
620              
621             my @likely_path =
622 106 100       4970 map { ucfirst lc } (
  318 100       928  
    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 106         624 for (my $i = 0; $i < @path; $i++) {
629 318 100 66     2450 $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 106         535 @path = join '::', @likely_path;
634 106         374 push @path, join '::', $likely_path[0], 'Any', $likely_path[2];
635 106         427 push @path, join '::', @likely_path[0 .. 1];
636 106         263 push @path, join '::', $likely_path[0];
637            
638             # Now we go through the path loading each module
639             # And calling new on it.
640 106         206 my $module;
641 106         293 foreach my $module_name (@path) {
642 273         1141 $module_name = "Locale::CLDR::Locales::$module_name";
643 273 100       2433 if (Class::Load::try_load_class($module_name, { -version => $VERSION})) {
644 86         11915 Class::Load::load_class($module_name, { -version => $VERSION});
645             }
646             else {
647 186         105817 next;
648             }
649 86         12861 $module = $module_name->new;
650 86         337 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 105 50       502 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 105         3898 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   130 no strict 'refs';
  20         39  
  20         17084  
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   11 my ($self, $what) = @_;
1078              
1079 4         23 my $vars = $self->_build_break_vars($what);
1080 4         21 my $rules = $self->_build_break_rules($vars, $what);
1081 4         205 return $rules;
1082             }
1083              
1084             sub _build_break_vars {
1085 4     4   9 my ($self, $what) = @_;
1086              
1087 4         12 my $name = "${what}_variables";
1088 4         27 my @bundles = $self->_find_bundle($name);
1089 4         9 my @vars;
1090 4         12 foreach my $bundle (reverse @bundles) {
1091 4         7 push @vars, @{$bundle->$name};
  4         205  
1092             }
1093              
1094 4         12 my %vars = ();
1095 4         21 while (my ($name, $value) = (shift @vars, shift @vars)) {
1096 146 100       279 last unless defined $name;
1097 142 50       232 if (! defined $value) {
1098 0         0 delete $vars{$name};
1099 0         0 next;
1100             }
1101              
1102 142         288 $value =~ s{ ( \$ \p{ID_START} \p{ID_CONTINUE}* ) }{$vars{$1}}msxeg;
  148         473  
1103 142         568 $vars{$name} = $value;
1104             }
1105              
1106 4         15 return \%vars;
1107             }
1108              
1109             sub _build_break_rules {
1110 4     4   9 my ($self, $vars, $what) = @_;
1111              
1112 4         19 my $name = "${what}_rules";
1113 4         18 my @bundles = $self->_find_bundle($name);
1114              
1115 4         10 my %rules;
1116 4         13 foreach my $bundle (reverse @bundles) {
1117 4         14 %rules = (%rules, %{$bundle->$name});
  4         174  
1118             }
1119              
1120 4         10 my @rules;
1121 4         43 foreach my $rule_number ( sort { $a <=> $b } keys %rules ) {
  378         513  
1122             # Test for deleted rules
1123 98 50       348 next unless defined $rules{$rule_number};
1124              
1125 98         757 $rules{$rule_number} =~ s{ ( \$ \p{ID_START} \p{ID_CONTINUE}* ) }{$vars->{$1}}msxeg;
  293         1605  
1126 98         1005 my ($first, $opp, $second) = split /(×|÷)/, $rules{$rule_number};
1127              
1128 98         230 foreach my $operand ($first, $second) {
1129 196 100       102350 if ($operand =~ m{ \S }msx) {
1130 163         5222 $operand = _unicode_to_perl($operand);
1131             }
1132             else {
1133 33         77 $operand = '.';
1134             }
1135             }
1136            
1137 20     20   63616 no warnings 'deprecated';
  20         46  
  20         49693  
1138 98 100       100401 push @rules, [qr{$first}msx, qr{$second}msx, ($opp eq '×' ? 1 : 0)];
1139             }
1140              
1141 4         30 push @rules, [ '.', '.', 0 ];
1142              
1143 4         75 return \@rules;
1144             }
1145              
1146             sub BUILDARGS {
1147 98     98 1 1866 my $self = shift;
1148 98         269 my %args;
1149              
1150             # Used for arguments when we call new from our own code
1151 98         340 my %internal_args = ();
1152 98 50 66     751 if (@_ > 1 && ref $_[-1] eq 'HASH') {
1153 0         0 %internal_args = %{pop @_};
  0         0  
1154             }
1155              
1156 98 100 66     742 if (1 == @_ && ! ref $_[0]) {
1157 77         832 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 77         257 foreach ($language, $script, $region, $variant) {
1167 308 100       857 $_ = '' unless defined $_;
1168             }
1169              
1170             %args = (
1171 77         620 language_id => $language,
1172             script_id => $script,
1173             region_id => $region,
1174             variant_id => $variant,
1175             extensions => $extensions,
1176             );
1177             }
1178              
1179 98 100       415 if (! keys %args ) {
1180             %args = ref $_[0]
1181 21 50       124 ? %{$_[0]}
  0         0  
1182             : @_
1183             }
1184              
1185             # Split up the extensions
1186 98 100 66     565 if ( defined $args{extensions} && ! ref $args{extensions} ) {
1187             $args{extensions} = {
1188 14         52 map {lc}
1189             split /[_-]/, $args{extensions}
1190 5         31 };
1191             }
1192              
1193             # Fix casing of args
1194 98 100       646 $args{language_id} = lc $args{language_id} if defined $args{language_id};
1195 98 100       598 $args{script_id} = ucfirst lc $args{script_id} if defined $args{script_id};
1196 98 100       512 $args{region_id} = uc $args{region_id} if defined $args{region_id};
1197 98 100       443 $args{variant_id} = uc $args{variant_id} if defined $args{variant_id};
1198            
1199             # Set up undefined language
1200 98   100     365 $args{language_id} //= 'und';
1201              
1202 98         783 $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 = exists $key_aliases{$key} ? $key_aliases{$key} : undef;
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              
1247             $self->_set_extensions($args->{extensions});
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             if (exists $extensions->{cu}) {
1317             $self->_set_default_cu($extensions->{cu});
1318             }
1319             };
1320              
1321             # Defaults
1322             # Calendar, currency format
1323             foreach my $default (qw( ca cf cu)) {
1324             has "default_$default" => (
1325             is => 'ro',
1326             isa => 'Str',
1327             init_arg => undef,
1328             default => '',
1329             traits => ['String'],
1330             handles => {
1331             "_set_default_$default" => 'append',
1332             "_test_default_$default" => 'length',
1333             },
1334             );
1335             }
1336              
1337             sub default_calendar {
1338 68     68 1 141 my ($self, $region) = @_;
1339              
1340 68         129 my $default = '';
1341 68 100       3298 if ($self->_test_default_ca) {
1342 66         2372 $default = $self->default_ca();
1343             }
1344             else {
1345 2         88 my $calendar_preferences = $self->calendar_preferences();
1346 2   33     22 $region //= ( $self->region_id() || $self->likely_subtag->region_id );
      33        
1347 2         6 my $current_region = $region;
1348              
1349 2         12 while (! $default) {
1350 10         23 $default = $calendar_preferences->{$current_region};
1351 10 100       23 if ($default) {
1352 2         9 $default = $default->[0];
1353             }
1354             else {
1355 8         342 $current_region = $self->region_contained_by()->{$current_region}
1356             }
1357             }
1358 2         94 $self->_set_default_ca($default);
1359             }
1360 68         236 return $default;
1361             }
1362              
1363             sub default_currency_format {
1364 20     20 1 41 my $self = shift;
1365            
1366 20         34 my $default = 'standard';
1367 20 50       1096 if ($self->_test_default_cf) {
1368 20         685 $default = $self->default_cf();
1369             }
1370             else {
1371 0         0 $self->_set_default_cf($default);
1372             }
1373            
1374 20         80 return $default;
1375             }
1376              
1377             use overload
1378 40     40   154 'bool' => sub { 1 },
1379 20     20   137 '""' => sub {shift->id};
  20     0   41  
  20         267  
  0         0  
1380              
1381             sub _build_id {
1382 32     32   72 my $self = shift;
1383 32         197 my $string = lc $self->language_id;
1384              
1385 32 100       1128 if ($self->script_id) {
1386 25         860 $string.= '_' . ucfirst lc $self->script_id;
1387             }
1388              
1389 32 100       175 if ($self->region_id) {
1390 25         112 $string.= '_' . uc $self->region_id;
1391             }
1392              
1393 32 100       1162 if ($self->variant_id) {
1394 3         108 $string.= '_' . uc $self->variant_id;
1395             }
1396              
1397 32 50       1077 if (defined $self->extensions) {
1398 0         0 $string.= '_u';
1399 0         0 foreach my $key (sort keys %{$self->extensions}) {
  0         0  
1400 0         0 my $value = $self->extensions->{$key};
1401 0         0 $string .= "_${key}_$value";
1402             }
1403 0         0 $string =~ s/_u$//;
1404             }
1405              
1406 32         1003 return $string;
1407             }
1408              
1409             sub _get_english {
1410 0     0   0 my $self = shift;
1411 0         0 my $english;
1412 0 0       0 if ($self->language_id eq 'en') {
1413 0         0 $english = $self;
1414             }
1415             else {
1416 0         0 $english = Locale::CLDR->new('en_Latn_US');
1417             }
1418              
1419 0         0 return $english;
1420             }
1421              
1422             sub _build_name {
1423 0     0   0 my $self = shift;
1424              
1425 0         0 return $self->_get_english->native_name($self);
1426             }
1427              
1428             sub _build_native_name {
1429 0     0   0 my ($self, $for) = @_;
1430              
1431 0         0 return $self->locale_name($for);
1432             }
1433              
1434             sub _build_language {
1435 0     0   0 my $self = shift;
1436              
1437 0         0 return $self->_get_english->native_language($self);
1438             }
1439              
1440             sub _build_native_language {
1441 0     0   0 my ($self, $for) = @_;
1442              
1443 0   0     0 return $self->language_name($for) // '';
1444             }
1445              
1446             sub _build_script {
1447 0     0   0 my $self = shift;
1448              
1449 0         0 return $self->_get_english->native_script($self);
1450             }
1451              
1452             sub _build_native_script {
1453 0     0   0 my ($self, $for) = @_;
1454              
1455 0         0 return $self->script_name($for);
1456             }
1457              
1458             sub _build_region {
1459 0     0   0 my $self = shift;
1460              
1461 0         0 return $self->_get_english->native_region($self);
1462             }
1463              
1464             sub _build_native_region {
1465 0     0   0 my ($self, $for) = @_;
1466              
1467 0         0 return $self->region_name($for);
1468             }
1469              
1470             sub _build_variant {
1471 0     0   0 my $self = shift;
1472              
1473 0         0 return $self->_get_english->native_variant($self);
1474             }
1475              
1476             sub _build_native_variant {
1477 0     0   0 my ($self, $for) = @_;
1478              
1479 0         0 return $self->variant_name($for);
1480             }
1481              
1482             # Method to locate the resource bundle with the required data
1483             sub _find_bundle {
1484 3292     3292   5286 my ($self, $method_name) = @_;
1485 3292 50       134001 my $id = $self->has_likely_subtag()
1486             ? $self->likely_subtag()->id()
1487             : $self->id();
1488            
1489            
1490 3292 100       109939 if ($self->method_cache->{$id}{$method_name}) {
1491             return wantarray
1492 2440         79597 ? @{$self->method_cache->{$id}{$method_name}}
1493 3214 100       31007 : $self->method_cache->{$id}{$method_name}[0];
1494             }
1495              
1496 78         2784 foreach my $module ($self->module->meta->linearized_isa) {
1497 390 100       19875 last if $module eq 'Moose::Object';
1498 312 100       1946 if ($module->meta->has_method($method_name)) {
1499 118         9705 push @{$self->method_cache->{$id}{$method_name}}, $module->new;
  118         4658  
1500             }
1501             }
1502              
1503 78 50       3193 return unless $self->method_cache->{$id}{$method_name};
1504             return wantarray
1505 65         2215 ? @{$self->method_cache->{$id}{$method_name}}
1506 78 100       714 : $self->method_cache->{$id}{$method_name}[0];
1507             }
1508              
1509             =back
1510              
1511             =head2 Names
1512              
1513             These methods allow you to pass in a locale, either by C<id> or as a
1514             Locale::CLDR object and return an name formatted in the locale of $self.
1515             If you don't pass in a locale then it will use $self.
1516              
1517             =over 4
1518              
1519             =item locale_name($name)
1520              
1521             Returns the given locale name in the current locale's format. The name can be
1522             a locale id or a locale object or non existent. If a name is not passed in
1523             then the name of the current locale is returned.
1524              
1525             =cut
1526              
1527             sub locale_name {
1528 6     6 1 5230 my ($self, $name) = @_;
1529 6   66     32 $name //= $self;
1530              
1531 6 50       28 my $code = ref $name
    100          
1532             ? join ( '_', $name->language_id, $name->region_id ? $name->region_id : () )
1533             : $name;
1534            
1535 6         29 my @bundles = $self->_find_bundle('display_name_language');
1536              
1537 6         19 foreach my $bundle (@bundles) {
1538 6         256 my $display_name = $bundle->display_name_language->($code);
1539 6 100       45 return $display_name if defined $display_name;
1540             }
1541              
1542             # $name can be a string or a Locale::CLDR::Locales::*
1543 2 50       8 if (! ref $name) {
1544 2         20 $name = Locale::CLDR->new($name);
1545             }
1546              
1547             # Now we have to process each individual element
1548             # to pass to the display name pattern
1549 2         49 my $language = $self->language_name($name);
1550 2         15 my $script = $self->script_name($name);
1551 2         13 my $region = $self->region_name($name);
1552 2         12 my $variant = $self->variant_name($name);
1553              
1554 2         11 my $bundle = $self->_find_bundle('display_name_pattern');
1555 2         17 return $bundle
1556             ->display_name_pattern($language, $region, $script, $variant);
1557             }
1558              
1559             =item language_name($language)
1560              
1561             Returns the language name in the current locale's format. The name can be
1562             a locale language id or a locale object or non existent. If a name is not
1563             passed in then the language name of the current locale is returned.
1564              
1565             =cut
1566              
1567             sub language_name {
1568 8     8 1 8616 my ($self, $name) = @_;
1569              
1570 8   66     47 $name //= $self;
1571              
1572 8 100       49 my $code = ref $name ? $name->language_id : eval { Locale::CLDR->new(language_id => $name)->language_id };
  3         30  
1573              
1574 8         2731 my $language = undef;
1575 8         6356 my @bundles = $self->_find_bundle('display_name_language');
1576 8 100       36 if ($code) {
1577 7         23 foreach my $bundle (@bundles) {
1578 7         349 my $display_name = $bundle->display_name_language->($code);
1579 7 50       36 if (defined $display_name) {
1580 7         16 $language = $display_name;
1581 7         22 last;
1582             }
1583             }
1584             }
1585             # If we don't have a display name for the language we try again
1586             # with the und tag
1587 8 100       33 if (! defined $language ) {
1588 1         5 foreach my $bundle (@bundles) {
1589 1         45 my $display_name = $bundle->display_name_language->('und');
1590 1 50       6 if (defined $display_name) {
1591 1         3 $language = $display_name;
1592 1         3 last;
1593             }
1594             }
1595             }
1596              
1597 8         52 return $language;
1598             }
1599              
1600             =item all_languages()
1601              
1602             Returns a hash ref keyed on language id of all the languages the system
1603             knows about. The values are the language names for the corresponding id's
1604              
1605             =cut
1606              
1607             sub all_languages {
1608 1     1 1 4 my $self = shift;
1609              
1610 1         5 my @bundles = $self->_find_bundle('display_name_language');
1611 1         3 my %languages;
1612 1         3 foreach my $bundle (@bundles) {
1613 1         42 my $languages = $bundle->display_name_language->();
1614              
1615             # Remove existing languages
1616 1         3 delete @{$languages}{keys %languages};
  1         4  
1617              
1618             # Assign new ones to the hash
1619 1         410 @languages{keys %$languages} = values %$languages;
1620             }
1621              
1622 1         7 return \%languages;
1623             }
1624              
1625             =item script_name($script)
1626              
1627             Returns the script name in the current locale's format. The script can be
1628             a locale script id or a locale object or non existent. If a script is not
1629             passed in then the script name of the current locale is returned.
1630              
1631             =cut
1632              
1633             sub script_name {
1634 7     7 1 5826 my ($self, $name) = @_;
1635 7   66     38 $name //= $self;
1636              
1637 7 100       33 if (! ref $name ) {
1638 3         8 $name = eval {__PACKAGE__->new(script_id => $name)};
  3         26  
1639             }
1640              
1641 7 100 100     2695 if ( ref $name && ! $name->script_id ) {
1642 3         14 return '';
1643             }
1644              
1645 4         12 my $script = undef;
1646 4         27 my @bundles = $self->_find_bundle('display_name_script');
1647 4 100       26 if ($name) {
1648 3         47 foreach my $bundle (@bundles) {
1649 3         130 $script = $bundle->display_name_script->($name->script_id);
1650 3 50       14 if (defined $script) {
1651 3         7 last;
1652             }
1653             }
1654             }
1655              
1656 4 100       20 if (! $script) {
1657 1         4 foreach my $bundle (@bundles) {
1658 1         46 $script = $bundle->display_name_script->('Zzzz');
1659 1 50       6 if (defined $script) {
1660 1         3 last;
1661             }
1662             }
1663             }
1664              
1665 4         32 return $script;
1666             }
1667              
1668             =item all_scripts()
1669              
1670             Returns a hash ref keyed on script id of all the scripts the system
1671             knows about. The values are the script names for the corresponding id's
1672              
1673             =cut
1674              
1675             sub all_scripts {
1676 1     1 1 5511 my $self = shift;
1677              
1678 1         7 my @bundles = $self->_find_bundle('display_name_script');
1679 1         3 my %scripts;
1680 1         4 foreach my $bundle (@bundles) {
1681 1         43 my $scripts = $bundle->display_name_script->();
1682              
1683             # Remove existing scripts
1684 1         4 delete @{$scripts}{keys %scripts};
  1         4  
1685              
1686             # Assign new ones to the hash
1687 1         116 @scripts{keys %$scripts} = values %$scripts;
1688             }
1689              
1690 1         8 return \%scripts;
1691             }
1692              
1693             =item region_name($region)
1694              
1695             Returns the region name in the current locale's format. The region can be
1696             a locale region id or a locale object or non existent. If a region is not
1697             passed in then the region name of the current locale is returned.
1698              
1699             =cut
1700              
1701             sub region_name {
1702 9     9 1 12265 my ($self, $name) = @_;
1703 9   66     43 $name //= $self;
1704              
1705 9 100       43 if (! ref $name ) {
1706 5         14 $name = eval { __PACKAGE__->new(language_id => 'und', region_id => $name); };
  5         44  
1707             }
1708              
1709 9 50 66     4942 if ( ref $name && ! $name->region_id) {
1710 0         0 return '';
1711             }
1712              
1713 9         26 my $region = undef;
1714 9         56 my @bundles = $self->_find_bundle('display_name_region');
1715 9 100       53 if ($name) {
1716 7         26 foreach my $bundle (@bundles) {
1717 7         304 $region = $bundle->display_name_region->{$name->region_id};
1718 7 50       35 if (defined $region) {
1719 7         20 last;
1720             }
1721             }
1722             }
1723              
1724 9 100       37 if (! defined $region) {
1725 2         9 foreach my $bundle (@bundles) {
1726 2         94 $region = $bundle->display_name_region->{'ZZ'};
1727 2 50       10 if (defined $region) {
1728 2         7 last;
1729             }
1730             }
1731             }
1732              
1733 9         60 return $region;
1734             }
1735              
1736             =item all_regions
1737              
1738             Returns a hash ref keyed on region id of all the region the system
1739             knows about. The values are the region names for the corresponding ids
1740              
1741             =cut
1742              
1743             sub all_regions {
1744 1     1 1 4889 my $self = shift;
1745              
1746 1         36 my @bundles = $self->_find_bundle('display_name_region');
1747 1         3 my %regions;
1748 1         3 foreach my $bundle (@bundles) {
1749 1         42 my $regions = $bundle->display_name_region;
1750              
1751             # Remove existing regions
1752 1         3 delete @{$regions}{keys %regions};
  1         3  
1753              
1754             # Assign new ones to the hash
1755 1         239 @regions{keys %$regions} = values %$regions;
1756             }
1757              
1758 1         8 return \%regions;
1759             }
1760              
1761             =item variant_name($variant)
1762              
1763             Returns the variant name in the current locale's format. The variant can be
1764             a locale variant id or a locale object or non existent. If a variant is not
1765             passed in then the variant name of the current locale is returned.
1766              
1767             =cut
1768              
1769             sub variant_name {
1770 7     7 1 6828 my ($self, $name) = @_;
1771 7   66     27 $name //= $self;
1772              
1773 7 100       26 if (! ref $name ) {
1774 4         35 $name = __PACKAGE__->new(language_id=> 'und', variant_id => $name);
1775             }
1776              
1777 6 100       283 return '' unless $name->variant_id;
1778 3         9 my $variant = undef;
1779 3 50       124 if ($name->has_variant) {
1780 3         24 my @bundles = $self->_find_bundle('display_name_variant');
1781 3         14 foreach my $bundle (@bundles) {
1782 3         144 $variant= $bundle->display_name_variant->{$name->variant_id};
1783 3 100       18 if (defined $variant) {
1784 2         6 last;
1785             }
1786             }
1787             }
1788              
1789 3   100     36 return $variant // '';
1790             }
1791              
1792             =item key_name($key)
1793              
1794             Returns the key name in the current locale's format. The key must be
1795             a locale key id as a string
1796              
1797             =cut
1798              
1799             sub key_name {
1800 3     3 1 13075 my ($self, $key) = @_;
1801              
1802 3         18 $key = lc $key;
1803            
1804 3         157 my %key_aliases = $self->key_aliases;
1805 3         153 my %key_names = $self->key_names;
1806 3         135 my %valid_keys = $self->valid_keys;
1807              
1808 3   100     35 my $alias = $key_aliases{$key} // '';
1809 3   100     18 my $name = $key_names{$key} // '';
1810              
1811 3 50 66     43 return '' unless exists $valid_keys{$key} || exists $valid_keys{$alias} || exists $valid_keys{$name};
      33        
1812 3         18 my @bundles = $self->_find_bundle('display_name_key');
1813 3         13 foreach my $bundle (@bundles) {
1814 3         138 my $return = $bundle->display_name_key->{$key};
1815 3   66     56 $return //= $bundle->display_name_key->{$alias};
1816 3   33     11 $return //= $bundle->display_name_key->{$name};
1817              
1818 3 50 33     94 return $return if defined $return && length $return;
1819             }
1820              
1821 0   0     0 return ucfirst ($key_names{$name} || $key_names{$alias} || $key_names{$key} || $key);
1822             }
1823              
1824             =item type_name($key, $type)
1825              
1826             Returns the type name in the current locale's format. The key and type must be
1827             a locale key id and type id as a string
1828              
1829             =cut
1830              
1831             sub type_name {
1832 3     3 1 11 my ($self, $key, $type) = @_;
1833              
1834 3         12 $key = lc $key;
1835 3         9 $type = lc $type;
1836              
1837 3         150 my %key_aliases = $self->key_aliases;
1838 3         128 my %valid_keys = $self->valid_keys;
1839 3         120 my %key_names = $self->key_names;
1840              
1841 3   100     32 my $alias = $key_aliases{$key} // '';
1842 3   100     17 my $name = $key_names{$key} // '';
1843              
1844 3 50 66     30 return '' unless exists $valid_keys{$key} || $valid_keys{$alias} || $valid_keys{$name};
      33        
1845 3 100   20   17 return '' unless first { $_ eq $type } @{$valid_keys{$key} || []}, @{$valid_keys{$alias} || []}, @{$valid_keys{$name} || []};
  20 50       35  
  3 100       21  
  3 50       19  
  3         29  
1846              
1847 3         21 my @bundles = $self->_find_bundle('display_name_type');
1848 3         13 foreach my $bundle (@bundles) {
1849 3   66     134 my $types = $bundle->display_name_type->{$key} // $bundle->display_name_type->{$alias} // $bundle->display_name_type->{$name};
      33        
1850 3         9 my $type = $types->{$type};
1851 3 50       86 return $type if defined $type;
1852             }
1853              
1854 0         0 return '';
1855             }
1856            
1857             =item measurement_system_name($measurement_system)
1858              
1859             Returns the measurement system name in the current locale's format. The measurement system must be
1860             a measurement system id as a string
1861              
1862             =cut
1863            
1864             sub measurement_system_name {
1865 6     6 1 40 my ($self, $name) = @_;
1866              
1867             # Fix case of code
1868 6         19 $name = uc $name;
1869 6 100       26 $name = 'metric' if $name eq 'METRIC';
1870              
1871 6         24 my @bundles = $self->_find_bundle('display_name_measurement_system');
1872 6         17 foreach my $bundle (@bundles) {
1873 6         257 my $system = $bundle->display_name_measurement_system->{$name};
1874 6 50       49 return $system if defined $system;
1875             }
1876              
1877 0         0 return '';
1878             }
1879              
1880             =item transform_name($name)
1881              
1882             Returns the transform (transliteration) name in the current locale's format. The transform must be
1883             a transform id as a string
1884              
1885             =cut
1886              
1887             sub transform_name {
1888 1     1 1 2 my ($self, $name) = @_;
1889              
1890 1         4 $name = lc $name;
1891              
1892 1         4 my @bundles = $self->_find_bundle('display_name_transform_name');
1893 1         4 foreach my $bundle (@bundles) {
1894 1         45 my $key = $bundle->display_name_transform_name->{$name};
1895 1 50       11 return $key if length $key;
1896             }
1897              
1898 0         0 return '';
1899             }
1900              
1901             =item code_pattern($type, $locale)
1902              
1903             This method formats a language, script or region name, given as C<$type>
1904             from C<$locale> in a way expected by the current locale. If $locale is
1905             not passed in or is undef() the method uses the current locale.
1906              
1907             =cut
1908              
1909             sub code_pattern {
1910 3     3 1 41 my ($self, $type, $locale) = @_;
1911 3         10 $type = lc $type;
1912              
1913             # If locale is not passed in then we are using ourself
1914 3   33     19 $locale //= $self;
1915              
1916             # If locale is not an object then inflate it
1917 3 50       22 $locale = __PACKAGE__->new($locale) unless blessed $locale;
1918              
1919 3 50       21 return '' unless $type =~ m{ \A (?: language | script | region ) \z }xms;
1920              
1921 3         8 my $method = $type . '_name';
1922 3         23 my $substitute = $self->$method($locale);
1923              
1924 3         17 my @bundles = $self->_find_bundle('display_name_code_patterns');
1925 3         9 foreach my $bundle (@bundles) {
1926 3         131 my $text = $bundle->display_name_code_patterns->{$type};
1927 3 50       9 next unless defined $text;
1928 3         12 my $match = qr{ \{ 0 \} }xms;
1929 3         64 $text=~ s{ $match }{$substitute}gxms;
1930 3         35 return $text;
1931             }
1932              
1933 0         0 return '';
1934             }
1935              
1936             =item text_orientation($type)
1937              
1938             Gets the text orientation for the locale. Type must be one of
1939             C<lines> or C<characters>
1940              
1941             =cut
1942              
1943             sub text_orientation {
1944 2     2 1 30 my $self = shift;
1945 2         6 my $type = shift;
1946              
1947 2         11 my @bundles = $self->_find_bundle('text_orientation');
1948 2         7 foreach my $bundle (@bundles) {
1949 2         119 my $orientation = $bundle->text_orientation;
1950 2 50       7 next unless defined $orientation;
1951 2         16 return $orientation->{$type};
1952             }
1953              
1954 0         0 return;
1955             }
1956              
1957             sub _set_casing {
1958 0     0   0 my ($self, $casing, $string) = @_;
1959              
1960 0         0 my @words = $self->split_words($string);
1961              
1962 0 0       0 if ($casing eq 'titlecase-firstword') {
    0          
    0          
1963             # Check to see whether $words[0] is white space or not
1964 0         0 my $firstword_location = 0;
1965 0 0       0 if ($words[0] =~ m{ \A \s }msx) {
1966 0         0 $firstword_location = 1;
1967             }
1968              
1969 0         0 $words[$firstword_location] = ucfirst $words[$firstword_location];
1970             }
1971             elsif ($casing eq 'titlecase-words') {
1972 0         0 @words = map{ ucfirst } @words;
  0         0  
1973             }
1974             elsif ($casing eq 'lowercase-words') {
1975 0         0 @words = map{ lc } @words;
  0         0  
1976             }
1977              
1978 0         0 return join '', @words;
1979             }
1980              
1981             =back
1982              
1983             =head2 Segmentation
1984              
1985             This group of methods allow you to split a string in various ways
1986             Note you need Perl 5.18 or above for this
1987              
1988             =over 4
1989              
1990             =item split_grapheme_clusters($string)
1991              
1992             Splits a string on grapheme clusters using the locale's segmentation rules.
1993             Returns a list of grapheme clusters.
1994              
1995             =cut
1996             # Need 5.18 and above
1997             sub _new_perl {
1998 10 50   10   138 die "You need Perl 5.18 or later for this functionality\n"
1999             if $^V lt v5.18.0;
2000             }
2001              
2002             sub split_grapheme_clusters {
2003 1     1 1 50 _new_perl();
2004            
2005 1         4 my ($self, $string) = @_;
2006              
2007 1         42 my $rules = $self->break_grapheme_cluster;
2008 1         6 my @clusters = $self->_split($rules, $string, 1);
2009              
2010 1         18 return @clusters;
2011             }
2012              
2013             =item split_words($string)
2014              
2015             Splits a string on word boundaries using the locale's segmentation rules.
2016             Returns a list of words.
2017              
2018             =cut
2019              
2020             sub split_words {
2021 1     1 1 1060 _new_perl();
2022            
2023 1         4 my ($self, $string) = @_;
2024              
2025 1         50 my $rules = $self->break_word;
2026 1         6 my @words = $self->_split($rules, $string);
2027              
2028 1         12 return @words;
2029             }
2030              
2031             =item split_sentences($string)
2032              
2033             Splits a string on on all points where a sentence could
2034             end using the locale's segmentation rules. Returns a list
2035             the end of each list element is the point where a sentence
2036             could end.
2037              
2038             =cut
2039              
2040             sub split_sentences {
2041 1     1 1 871 _new_perl();
2042            
2043 1         4 my ($self, $string) = @_;
2044              
2045 1         60 my $rules = $self->break_sentence;
2046 1         12 my @sentences = $self->_split($rules, $string);
2047              
2048 1         8 return @sentences;
2049             }
2050              
2051             =item split_lines($string)
2052              
2053             Splits a string on on all points where a line could
2054             end using the locale's segmentation rules. Returns a list
2055             the end of each list element is the point where a line
2056             could end.
2057              
2058             =cut
2059              
2060             sub split_lines {
2061 1     1 1 782 _new_perl();
2062            
2063 1         4 my ($self, $string) = @_;
2064              
2065 1         54 my $rules = $self->break_line;
2066 1         7 my @lines = $self->_split($rules, $string);
2067              
2068 1         8 return @lines;
2069             }
2070              
2071             sub _split {
2072 4     4   12 my ($self, $rules, $string, $grapheme_split) = @_;
2073              
2074 4         36 my @split = (scalar @$rules) x (length($string) - 1);
2075              
2076 4         15 pos($string)=0;
2077             # The Unicode Consortium has deprecated LB=Surrogate but the CLDR still
2078             # uses it, at last in this version.
2079 20     20   100404 no warnings 'deprecated';
  20         48  
  20         88220  
2080 4         22 while (length($string) -1 != pos $string) {
2081 160         219 my $rule_number = 0;
2082 160         174 my $first;
2083 160         320 foreach my $rule (@$rules) {
2084 2666 100       53995 unless( ($first) = $string =~ m{
2085             \G
2086             ($rule->[0])
2087             $rule->[1]
2088             }msx) {
2089 2506         2084148 $rule_number++;
2090 2506         40033 next;
2091             }
2092 160         169033 my $location = pos($string) + length($first) -1;
2093 160         368 $split[$location] = $rule_number;
2094            
2095             # If the left hand side was part of a grapheme cluster
2096             # we have to jump past the entire cluster
2097 160         272 my $length = length $first;
2098 160         1349 my ($gc) = $string =~ /\G(\X)/;
2099 160 100 66     912 $length = (! $grapheme_split && length($gc)) > $length ? length($gc) : $length;
2100 160         424 pos($string)+= $length;
2101 160         767 last;
2102             }
2103             }
2104              
2105 4         16 push @$rules,[undef,undef,1];
2106 4 100       14 @split = map {$rules->[$_][2] ? 1 : 0} @split;
  164         380  
2107 4         16 my $count = 0;
2108 4         12 my @sections = ('.');
2109 4         14 foreach my $split (@split) {
2110 164 100       295 $count++ unless $split;
2111 164         238 $sections[$count] .= '.';
2112             }
2113            
2114 4         23 my $regex = '(' . join(')(', @sections) . ')';
2115 4         117 $regex = qr{ \A $regex \z}msx;
2116 4         56 @split = $string =~ $regex;
2117              
2118 4         47 return @split;
2119             }
2120              
2121             =back
2122              
2123             =head2 Characters
2124              
2125             =over 4
2126              
2127             =item is_exemplar_character( $type, $character)
2128              
2129             =item is_exemplar_character($character)
2130              
2131             Tests if the given character is used in the locale. There are
2132             three possible types; C<main>, C<auxiliary> and C<punctuation>.
2133             If no type is given C<main> is assumed. Unless the C<index> type
2134             is given you will have to have a Perl version of 5.18 or above
2135             to use this method
2136              
2137             =cut
2138              
2139             sub is_exemplar_character {
2140 6     6 1 55 my ($self, @parameters) = @_;
2141 6 100       22 unshift @parameters, 'main' if @parameters == 1;
2142              
2143 6 50       30 _new_perl() unless $parameters[0] eq 'index';
2144            
2145 6         32 my @bundles = $self->_find_bundle('characters');
2146 6         14 foreach my $bundle (@bundles) {
2147 9         330 my $characters = $bundle->characters->{lc $parameters[0]};
2148 9 100       22 next unless defined $characters;
2149 7 100       59 return 1 if fc($parameters[1])=~$characters;
2150             }
2151              
2152 3         16 return;
2153             }
2154              
2155             =item index_characters()
2156              
2157             Returns an array ref of characters normally used when creating
2158             an index and ordered appropriately.
2159              
2160             =cut
2161              
2162             sub index_characters {
2163 1     1 1 298 my $self = shift;
2164              
2165 1         4 my @bundles = $self->_find_bundle('characters');
2166 1         4 foreach my $bundle (@bundles) {
2167 1         38 my $characters = $bundle->characters->{index};
2168 1 50       5 next unless defined $characters;
2169 1         11 return $characters;
2170             }
2171 0         0 return [];
2172             }
2173              
2174             sub _truncated {
2175 6     6   20 my ($self, $type, @params) = @_;
2176              
2177 6         21 my @bundles = $self->_find_bundle('ellipsis');
2178 6         17 foreach my $bundle (@bundles) {
2179 6         222 my $ellipsis = $bundle->ellipsis->{$type};
2180 6 50       14 next unless defined $ellipsis;
2181 6         35 $ellipsis=~s{ \{ 0 \} }{$params[0]}msx;
2182 6         25 $ellipsis=~s{ \{ 1 \} }{$params[1]}msx;
2183 6         41 return $ellipsis;
2184             }
2185             }
2186              
2187             =back
2188              
2189             =head2 Truncation
2190              
2191             These methods format a string to show where part of the string has been removed
2192              
2193             =over 4
2194              
2195             =item truncated_beginning($string)
2196              
2197             Adds the locale specific marking to show that the
2198             string has been truncated at the beginning.
2199              
2200             =cut
2201              
2202             sub truncated_beginning {
2203 1     1 1 29 shift->_truncated(initial => @_);
2204             }
2205              
2206             =item truncated_between($string, $string)
2207              
2208             Adds the locale specific marking to show that something
2209             has been truncated between the two strings. Returns a
2210             string comprising of the concatenation of the first string,
2211             the mark and the second string
2212              
2213             =cut
2214              
2215             sub truncated_between {
2216 1     1 1 5 shift->_truncated(medial => @_);
2217             }
2218              
2219             =item truncated_end($string)
2220              
2221             Adds the locale specific marking to show that the
2222             string has been truncated at the end.
2223              
2224             =cut
2225              
2226             sub truncated_end {
2227 1     1 1 7 shift->_truncated(final => @_);
2228             }
2229              
2230             =item truncated_word_beginning($string)
2231              
2232             Adds the locale specific marking to show that the
2233             string has been truncated at the beginning. This
2234             should be used in preference to C<truncated_beginning>
2235             when the truncation occurs on a word boundary.
2236              
2237             =cut
2238              
2239             sub truncated_word_beginning {
2240 1     1 1 4 shift->_truncated('word-initial' => @_);
2241             }
2242              
2243             =item truncated_word_between($string, $string)
2244              
2245             Adds the locale specific marking to show that something
2246             has been truncated between the two strings. Returns a
2247             string comprising of the concatenation of the first string,
2248             the mark and the second string. This should be used in
2249             preference to C<truncated_between> when the truncation
2250             occurs on a word boundary.
2251              
2252             =cut
2253              
2254             sub truncated_word_between {
2255 1     1 1 6 shift->_truncated('word-medial' => @_);
2256             }
2257              
2258             =item truncated_word_end($string)
2259              
2260             Adds the locale specific marking to show that the
2261             string has been truncated at the end. This should be
2262             used in preference to C<truncated_end> when the
2263             truncation occurs on a word boundary.
2264              
2265             =cut
2266              
2267             sub truncated_word_end {
2268 1     1 1 3913 shift->_truncated('word-final' => @_);
2269             }
2270              
2271             =back
2272              
2273             =head2 Quoting
2274              
2275             =over 4
2276              
2277             =item quote($string)
2278              
2279             Adds the locale's primary quotation marks to the ends of the string.
2280             Also scans the string for paired primary and auxiliary quotation
2281             marks and flips them.
2282              
2283             eg passing C<z “abc” z> to this method for the C<en_GB> locale
2284             gives C<“z ‘abc’ z”>
2285              
2286             =cut
2287              
2288             sub quote {
2289 3     3 1 1415 my ($self, $text) = @_;
2290              
2291 3         6 my %quote;
2292 3         14 my @bundles = $self->_find_bundle('quote_start');
2293 3         11 foreach my $bundle (@bundles) {
2294 3         115 my $quote = $bundle->quote_start;
2295 3 50       9 next unless defined $quote;
2296 3         9 $quote{start} = $quote;
2297 3         5 last;
2298             }
2299              
2300 3         12 @bundles = $self->_find_bundle('quote_end');
2301 3         10 foreach my $bundle (@bundles) {
2302 3         118 my $quote = $bundle->quote_end;
2303 3 50       10 next unless defined $quote;
2304 3         8 $quote{end} = $quote;
2305 3         6 last;
2306             }
2307              
2308 3         9 @bundles = $self->_find_bundle('alternate_quote_start');
2309 3         9 foreach my $bundle (@bundles) {
2310 3         124 my $quote = $bundle->alternate_quote_start;
2311 3 50       11 next unless defined $quote;
2312 3         8 $quote{alternate_start} = $quote;
2313 3         7 last;
2314             }
2315              
2316 3         20 @bundles = $self->_find_bundle('alternate_quote_end');
2317 3         3290 foreach my $bundle (@bundles) {
2318 3         143 my $quote = $bundle->alternate_quote_end;
2319 3 50       11 next unless defined $quote;
2320 3         8 $quote{alternate_end} = $quote;
2321 3         8 last;
2322             }
2323              
2324             # Check to see if we need to switch quotes
2325 3         7 foreach (qw( start end alternate_start alternate_end)) {
2326 12   50     38 $quote{$_} //= '';
2327             }
2328              
2329 3         11 my $from = join ' | ', map {quotemeta} @quote{qw( start end alternate_start alternate_end)};
  12         36  
2330 3         6 my %to;
2331             @to{@quote{qw( start end alternate_start alternate_end)}}
2332 3         18 = @quote{qw( alternate_start alternate_end start end)};
2333              
2334 3         12 my $outer = index($text, $quote{start});
2335 3         8 my $inner = index($text, $quote{alternate_start});
2336              
2337 3 50 33     26 if ($inner == -1 || ($outer > -1 && $inner > -1 && $outer < $inner)) {
      33        
      66        
2338 3         109 $text =~ s{ ( $from ) }{ $to{$1} }msxeg;
  6         37  
2339             }
2340              
2341 3         27 return "$quote{start}$text$quote{end}";
2342             }
2343              
2344             =back
2345              
2346             =head2 Miscellaneous
2347              
2348             =over 4
2349              
2350             =item more_information()
2351              
2352             The more information string is one that can be displayed
2353             in an interface to indicate that more information is
2354             available.
2355              
2356             =cut
2357              
2358             sub more_information {
2359 1     1 1 3 my $self = shift;
2360              
2361 1         3 my @bundles = $self->_find_bundle('more_information');
2362 1         4 foreach my $bundle (@bundles) {
2363 1         44 my $info = $bundle->more_information;
2364 1 50       4 next unless defined $info;
2365 1         8 return $info;
2366             }
2367 0         0 return '';
2368             }
2369              
2370              
2371             =item measurement()
2372              
2373             Returns the measurement type for the locale
2374              
2375             =cut
2376              
2377             sub measurement {
2378 1     1 1 23 my $self = shift;
2379            
2380 1         43 my $measurement_data = $self->measurement_system;
2381 1   50     6 my $region = $self->region_id || '001';
2382            
2383 1         5 my $data = $measurement_data->{$region};
2384            
2385 1         6 until (defined $data) {
2386 0         0 $region = $self->region_contained_by->{$region};
2387 0         0 $data = $measurement_data->{$region};
2388             }
2389            
2390 1         10 return $data;
2391             }
2392              
2393             =item paper()
2394              
2395             Returns the paper type for the locale
2396              
2397             =cut
2398              
2399             sub paper {
2400 1     1 1 3 my $self = shift;
2401            
2402 1         46 my $paper_size = $self->paper_size;
2403 1   50     6 my $region = $self->region_id || '001';
2404            
2405 1         5 my $data = $paper_size->{$region};
2406            
2407 1         5 until (defined $data) {
2408 0         0 $region = $self->region_contained_by->{$region};
2409 0         0 $data = $paper_size->{$region};
2410             }
2411            
2412 1         5 return $data;
2413             }
2414              
2415             =back
2416              
2417             =head2 Units
2418              
2419             =over 4
2420              
2421             =item all_units()
2422              
2423             Returns a list of all the unit identifiers for the locale
2424              
2425             =cut
2426              
2427             sub all_units {
2428 0     0 1 0 my $self = shift;
2429 0         0 my @bundles = $self->_find_bundle('units');
2430            
2431 0         0 my %units;
2432 0         0 foreach my $bundle (reverse @bundles) {
2433 0         0 %units = %units, $bundle->units;
2434             }
2435            
2436 0         0 return keys %units;
2437             }
2438              
2439             =item unit($number, $unit, $width)
2440              
2441             Returns the localised string for the given number and unit formatted for the
2442             required width. The number must not be the localized version of the number.
2443             The returned string will be in the locale's format, including the number.
2444              
2445             =cut
2446              
2447             sub unit {
2448 738     738 1 1945 my ($self, $number, $what, $type) = @_;
2449 738   100     2696 $type //= 'long';
2450            
2451 738         3174 my $plural = $self->plural($number);
2452            
2453 738         2149 my @bundles = $self->_find_bundle('units');
2454 738         1146 my $format;
2455 738         4892 foreach my $bundle (@bundles) {
2456 748 100       27651 if (exists $bundle->units()->{$type}{$what}{$plural}) {
2457 728         25944 $format = $bundle->units()->{$type}{$what}{$plural};
2458 728         1261 last;
2459             }
2460            
2461 20 50       710 if (exists $bundle->units()->{$type}{$what}{other}) {
2462 0         0 $format = $bundle->units()->{$type}{$what}{other};
2463 0         0 last;
2464             }
2465             }
2466            
2467             # Check for aliases
2468 738 100       1969 unless ($format) {
2469 10         22 my $original_type = $type;
2470 10         28 my @aliases = $self->_find_bundle('unit_alias');
2471 10         26 foreach my $alias (@aliases) {
2472 10         374 $type = $alias->unit_alias()->{$original_type};
2473 10 50       27 next unless $type;
2474 10         22 foreach my $bundle (@bundles) {
2475 16 100       581 if (exists $bundle->units()->{$type}{$what}{$plural}) {
2476 4         139 $format = $bundle->units()->{$type}{$what}{$plural};
2477 4         10 last;
2478             }
2479            
2480 12 50       417 if (exists $bundle->units()->{$type}{$what}{other}) {
2481 0         0 $format = $bundle->units()->{$type}{$what}{other};
2482 0         0 last;
2483             }
2484             }
2485             }
2486 10         23 $type = $original_type;
2487             }
2488            
2489             # Check for a compound unit that we don't specifically have
2490 738 100 66     2176 if (! $format && (my ($dividend, $divisor) = $what =~ /^(.+)-per-(.+)$/)) {
2491 6         19 return $self->_unit_compound($number, $dividend, $divisor, $type);
2492             }
2493            
2494 732         2457 $number = $self->format_number($number);
2495 732 50       1801 return $number unless $format;
2496            
2497 732         2543 $format =~ s/\{0\}/$number/g;
2498            
2499 732         4771 return $format;
2500             }
2501              
2502             sub _unit_compound {
2503 6     6   13 my ($self, $number, $dividend_what, $divisor_what, $type) = @_;
2504            
2505 6   50     15 $type //= 'long';
2506            
2507 6         25 my $dividend = $self->unit($number, $dividend_what, $type);
2508 6         21 my $divisor = $self->_unit_per($divisor_what, $type);
2509 6 50       17 if ($divisor) {
2510 6         12 my $format = $divisor;
2511 6         17 $format =~ s/\{0\}/$dividend/;
2512 6         41 return $format;
2513             }
2514            
2515 0         0 $divisor = $self->unit(1, $divisor_what, $type);
2516            
2517 0         0 my $one = $self->format_number(1);
2518 0         0 $divisor =~ s/\s*$one\s*//;
2519            
2520 0         0 my @bundles = $self->_find_bundle('units');
2521 0         0 my $format;
2522 0         0 foreach my $bundle (@bundles) {
2523 0 0       0 if (exists $bundle->units()->{$type}{per}{''}) {
2524 0         0 $format = $bundle->units()->{$type}{per}{''};
2525 0         0 last;
2526             }
2527             }
2528              
2529             # Check for aliases
2530 0 0       0 unless ($format) {
2531 0         0 my $original_type = $type;
2532 0         0 my @aliases = $self->_find_bundle('unit_alias');
2533 0         0 foreach my $alias (@aliases) {
2534 0         0 $type = $alias->unit_alias()->{$original_type};
2535 0         0 foreach my $bundle (@bundles) {
2536 0 0       0 if (exists $bundle->units()->{$type}{per}{1}) {
2537 0         0 $format = $bundle->units()->{$type}{per}{1};
2538 0         0 last;
2539             }
2540             }
2541             }
2542             }
2543            
2544 0         0 $format =~ s/\{0\}/$dividend/g;
2545 0         0 $format =~ s/\{1\}/$divisor/g;
2546            
2547 0         0 return $format;
2548             }
2549              
2550             =item unit_name($unit_identifier)
2551              
2552             This method returns the localised name of the unit
2553              
2554             =cut
2555              
2556             sub unit_name {
2557 0     0 1 0 my ($self, $what) = @_;
2558            
2559 0         0 my @bundles = $self->_find_bundle('units');
2560 0         0 my $name;
2561 0         0 foreach my $bundle (@bundles) {
2562 0 0       0 if (exists $bundle->units()->{long}{$what}{name}) {
2563 0         0 return $bundle->units()->{long}{$what}{name};
2564             }
2565             }
2566            
2567             # Check for aliases
2568 0         0 my $type = 'long';
2569 0         0 my @aliases = $self->_find_bundle('unit_alias');
2570 0         0 foreach my $alias (@aliases) {
2571 0         0 $type = $alias->unit_alias()->{$type};
2572 0 0       0 next unless $type;
2573 0         0 foreach my $bundle (@bundles) {
2574 0 0       0 if (exists $bundle->units()->{$type}{$what}{name}) {
2575 0         0 return $bundle->units()->{$type}{$what}{name};
2576             }
2577             }
2578             }
2579            
2580 0         0 return '';
2581             }
2582              
2583             sub _unit_per {
2584 6     6   12 my ($self, $what, $type) = @_;
2585            
2586 6         15 my @bundles = $self->_find_bundle('units');
2587 6         9 my $name;
2588 6         14 foreach my $bundle (@bundles) {
2589 8 100       284 if (exists $bundle->units()->{$type}{$what}{per}) {
2590 4         139 return $bundle->units()->{$type}{$what}{per};
2591             }
2592             }
2593            
2594             # Check for aliases
2595 2         8 my @aliases = $self->_find_bundle('unit_alias');
2596 2         5 foreach my $alias (@aliases) {
2597 2         77 $type = $alias->unit_alias()->{$type};
2598 2 50       7 next unless $type;
2599 2         4 foreach my $bundle (@bundles) {
2600 2 50       75 if (exists $bundle->units()->{$type}{$what}{per}) {
2601 2         71 return $bundle->units()->{$type}{$what}{per};
2602             }
2603             }
2604             }
2605            
2606 0         0 return '';
2607             }
2608              
2609             sub _get_time_separator {
2610 12     12   23 my $self = shift;
2611              
2612 12         36 my @number_symbols_bundles = $self->_find_bundle('number_symbols');
2613 12         65 my $symbols_type = $self->default_numbering_system;
2614            
2615 12         32 foreach my $bundle (@number_symbols_bundles) {
2616 24 50       926 if (exists $bundle->number_symbols()->{$symbols_type}{alias}) {
2617 0         0 $symbols_type = $bundle->number_symbols()->{$symbols_type}{alias};
2618 0         0 redo;
2619             }
2620            
2621             return $bundle->number_symbols()->{$symbols_type}{timeSeparator}
2622 24 100       929 if exists $bundle->number_symbols()->{$symbols_type}{timeSeparator};
2623             }
2624 0         0 return ':';
2625             }
2626              
2627             =item duration_unit($format, @data)
2628              
2629             This method formats a duration. The format must be one of
2630             C<hm>, C<hms> or C<ms> corresponding to C<hour minute>,
2631             C<hour minute second> and C<minute second> respectively.
2632             The data must correspond to the given format.
2633              
2634             =cut
2635              
2636             sub duration_unit {
2637             # data in hh,mm; hh,mm,ss or mm,ss
2638 3     3 1 10 my ($self, $format, @data) = @_;
2639            
2640 3         10 my $bundle = $self->_find_bundle('duration_units');
2641 3         143 my $parsed = $bundle->duration_units()->{$format};
2642            
2643 3         6 my $num_format = '#';
2644 3         21 foreach my $entry ( qr/(hh?)/, qr/(mm?)/, qr/(ss?)/) {
2645 9 100       56 $num_format = '00' if $parsed =~ s/$entry/$self->format_number(shift(@data), $num_format)/e;
  7         32  
2646             }
2647            
2648 3         17 my $time_separator = $self->_get_time_separator;
2649            
2650 3         19 $parsed =~ s/:/$time_separator/g;
2651            
2652 3         19 return $parsed;
2653             }
2654              
2655             =back
2656              
2657             =head2 Yes or No?
2658              
2659             =over 4
2660              
2661             =item is_yes($string)
2662              
2663             Returns true if the passed in string matches the locale's
2664             idea of a string designating yes. Note that under POSIX
2665             rules unless the locale's word for yes starts with C<Y>
2666             (U+0079) then a single 'y' will also be accepted as yes.
2667             The string will be matched case insensitive.
2668              
2669             =cut
2670              
2671             sub is_yes {
2672 2     2 1 8 my ($self, $test_str) = @_;
2673            
2674 2         9 my $bundle = $self->_find_bundle('yesstr');
2675 2 100       80 return $test_str =~ $bundle->yesstr ? 1 : 0;
2676             }
2677              
2678             =item is_no($string)
2679              
2680             Returns true if the passed in string matches the locale's
2681             idea of a string designating no. Note that under POSIX
2682             rules unless the locale's word for no starts with C<n>
2683             (U+006E) then a single 'n' will also be accepted as no
2684             The string will be matched case insensitive.
2685              
2686             =cut
2687              
2688             sub is_no {
2689 2     2 1 6 my ($self, $test_str) = @_;
2690            
2691 2         10 my $bundle = $self->_find_bundle('nostr');
2692 2 100       77 return $test_str =~ $bundle->nostr ? 1 : 0;
2693             }
2694              
2695             =back
2696              
2697             =head2 Transliteration
2698              
2699             This method requires Perl version 5.18 or above to use and for you to have
2700             installed the optional C<Bundle::CLDR::Transformations>
2701              
2702             =over 4
2703              
2704             =item transform(from => $from, to => $to, variant => $variant, text => $text)
2705              
2706             This method returns the transliterated string of C<text> from script C<from>
2707             to script C<to> using variant C<variant>. If C<from> is not given then the
2708             current locale's script is used. If C<text> is not given then it defaults to an
2709             empty string. The C<variant> is optional.
2710              
2711             =cut
2712              
2713             sub transform {
2714 0     0 1 0 _new_perl();
2715            
2716 0         0 my ($self, %params) = @_;
2717            
2718 0   0     0 my $from = $params{from} // $self;
2719 0         0 my $to = $params{to};
2720 0   0     0 my $variant = $params{variant} // 'Any';
2721 0   0     0 my $text = $params{text} // '';
2722            
2723 0 0       0 ($from, $to) = map {ref $_ ? $_->likely_script() : $_} ($from, $to);
  0         0  
2724 0         0 $_ = ucfirst(lc $_) foreach ($from, $to, $variant);
2725            
2726 0         0 my $package = __PACKAGE__ . "::Transformations::${variant}::${from}::${to}";
2727 0         0 eval { Class::Load::load_class($package); };
  0         0  
2728 0 0       0 warn $@ if $@;
2729 0 0       0 return $text if $@; # Can't load transform module so return original text
2730 20     20   145 use feature 'state';
  20         40  
  20         228398  
2731 0         0 state $transforms;
2732 0   0     0 $transforms->{$variant}{$from}{$to} //= $package->new();
2733 0         0 my $rules = $transforms->{$variant}{$from}{$to}->transforms();
2734            
2735             # First get the filter rule
2736 0         0 my $filter = $rules->[0];
2737            
2738             # Break up the input on the filter
2739 0         0 my @text;
2740 0         0 pos($text) = 0;
2741 0         0 while (pos($text) < length($text)) {
2742 0         0 my $characters = '';
2743 0         0 while (my ($char) = $text =~ /($filter)/) {
2744 0         0 $characters .= $char;
2745 0         0 pos($text) = pos($text) + length $char;
2746             }
2747 0         0 push @text, $characters;
2748 0 0       0 last unless pos($text) < length $text;
2749            
2750 0         0 $characters = '';
2751 0         0 while ($text !~ /$filter/) {
2752 0         0 my ($char) = $text =~ /\G(\X)/;
2753 0         0 $characters .= $char;
2754 0         0 pos($text) = pos($text) + length $char;
2755             }
2756 0         0 push @text, $characters;
2757             }
2758            
2759 0         0 my $to_transform = 1;
2760            
2761 0         0 foreach my $characters (@text) {
2762 0 0       0 if ($to_transform) {
2763 0         0 foreach my $rule (@$rules[1 .. @$rules -1 ]) {
2764 0 0       0 if ($rule->{type} eq 'transform') {
2765 0         0 $characters = $self->_transformation_transform($characters, $rule->{data}, $variant);
2766             }
2767             else {
2768 0         0 $characters = $self->_transform_convert($characters, $rule->{data});
2769             }
2770             }
2771             }
2772 0         0 $to_transform = ! $to_transform;
2773             }
2774            
2775 0         0 return join '', @text;
2776             }
2777              
2778             sub _transformation_transform {
2779 0     0   0 my ($self, $text, $rules, $variant) = @_;
2780            
2781 0         0 foreach my $rule (@$rules) {
2782 0         0 for (lc $rule->{to}) {
2783 0 0       0 if ($_ eq 'nfc') {
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
2784 0         0 $text = Unicode::Normalize::NFC($text);
2785             }
2786             elsif($_ eq 'nfd') {
2787 0         0 $text = Unicode::Normalize::NFD($text);
2788             }
2789             elsif($_ eq 'nfkd') {
2790 0         0 $text = Unicode::Normalize::NFKD($text);
2791             }
2792             elsif($_ eq 'nfkc') {
2793 0         0 $text = Unicode::Normalize::NFKC($text);
2794             }
2795             elsif($_ eq 'lower') {
2796 0         0 $text = lc($text);
2797             }
2798             elsif($_ eq 'upper') {
2799 0         0 $text = uc($text);
2800             }
2801             elsif($_ eq 'title') {
2802 0         0 $text =~ s/(\X)/\u$1/g;
2803             }
2804             elsif($_ eq 'null') {
2805             }
2806             elsif($_ eq 'remove') {
2807 0         0 $text = '';
2808             }
2809             else {
2810 0         0 $text = $self->transform($text, $variant, $rule->{from}, $rule->to);
2811             }
2812             }
2813             }
2814 0         0 return $text;
2815             }
2816              
2817             sub _transform_convert {
2818 0     0   0 my ($self, $text, $rules) = @_;
2819            
2820 0         0 pos($text) = 0; # Make sure we start scanning at the beginning of the text
2821            
2822 0         0 CHARACTER: while (pos($text) < length($text)) {
2823 0         0 foreach my $rule (@$rules) {
2824 0 0 0     0 next if length $rule->{before} && $text !~ /$rule->{before}\G/;
2825 0         0 my $regex = $rule->{replace};
2826 0 0       0 $regex .= '(' . $rule->{after} . ')' if length $rule->{after};
2827 0         0 my $result = 'q(' . $rule->{result} . ')';
2828 0 0       0 $result .= '. $1' if length $rule->{after};
2829 0 0       0 if ($text =~ s/\G$regex/eval $result/e) {
  0         0  
2830 0         0 pos($text) += length($rule->{result}) - $rule->{revisit};
2831 0         0 next CHARACTER;
2832             }
2833             }
2834            
2835 0         0 pos($text)++;
2836             }
2837            
2838 0         0 return $text;
2839             }
2840              
2841             =back
2842              
2843             =head2 Lists
2844              
2845             =over 4
2846              
2847             =item list(@data)
2848              
2849             Returns C<data> as a string formatted by the locales idea of producing a list
2850             of elements. What is returned can be effected by the locale and the number
2851             of items in C<data>. Note that C<data> can contain 0 or more items.
2852              
2853             =cut
2854              
2855             sub list {
2856 5     5 1 43 my ($self, @data) = @_;
2857            
2858             # Short circuit on 0 or 1 entries
2859 5 100       28 return '' unless @data;
2860 4 100       21 return $data[0] if 1 == @data;
2861            
2862 3         14 my @bundles = $self->_find_bundle('listPatterns');
2863            
2864 3         7 my %list_data;
2865 3         8 foreach my $bundle (reverse @bundles) {
2866 6         14 my %listPatterns = %{$bundle->listPatterns};
  6         232  
2867 6         33 @list_data{keys %listPatterns} = values %listPatterns;
2868             }
2869            
2870 3 100       14 if (my $pattern = $list_data{scalar @data}) {
2871 1         8 $pattern=~s/\{([0-9]+)\}/$data[$1]/eg;
  2         13  
2872 1         12 return $pattern;
2873             }
2874            
2875 2         7 my ($start, $middle, $end) = @list_data{qw( start middle end )};
2876            
2877             # First do the end
2878 2         4 my $pattern = $end;
2879 2         8 $pattern=~s/\{1\}/pop @data/e;
  2         6  
2880 2         8 $pattern=~s/\{0\}/pop @data/e;
  2         6  
2881            
2882             # If there is any data left do the middle
2883 2         8 while (@data > 1) {
2884 1         3 my $current = $pattern;
2885 1         3 $pattern = $middle;
2886 1         4 $pattern=~s/\{1\}/$current/;
2887 1         4 $pattern=~s/\{0\}/pop @data/e;
  1         4  
2888             }
2889            
2890             # Now do the start
2891 2         4 my $current = $pattern;
2892 2         4 $pattern = $start;
2893 2         7 $pattern=~s/\{1\}/$current/;
2894 2         6 $pattern=~s/\{0\}/pop @data/e;
  2         5  
2895            
2896 2         16 return $pattern;
2897             }
2898              
2899             =back
2900              
2901             =head2 Pluralisation
2902              
2903             =over 4
2904              
2905             =item plural($number)
2906              
2907             This method takes a number and uses the locale's pluralisation
2908             rules to calculate the type of pluralisation required for
2909             units, currencies and other data that changes depending on
2910             the plural state of the number
2911              
2912             =item plural_range($start, $end)
2913              
2914             This method returns the plural type for the range $start to $end
2915             $start and $end can either be numbers or one of the plural types
2916             C<zero one two few many other>
2917              
2918             =cut
2919              
2920             sub _clear_calendar_data {
2921 0     0   0 my $self = shift;
2922              
2923 0         0 foreach my $property (qw(
2924             month_format_wide month_format_abbreviated month_format_narrow
2925             month_stand_alone_wide month_stand_alone_abbreviated
2926             month_stand_alone_narrow day_format_wide day_format_abbreviated
2927             day_format_narrow day_stand_alone_wide day_stand_alone_abreviated
2928             day_stand_alone_narrow quater_format_wide quater_format_abbreviated
2929             quater_format_narrow quater_stand_alone_wide
2930             quater_stand_alone_abreviated quater_stand_alone_narrow
2931             am_pm_wide am_pm_abbreviated am_pm_narrow am_pm_format_wide
2932             am_pm_format_abbreviated am_pm_format_narrow am_pm_stand_alone_wide
2933             am_pm_stand_alone_abbreviated am_pm_stand_alone_narrow era_wide
2934             era_abbreviated era_narrow date_format_full date_format_long date_format_medium
2935             date_format_short time_format_full
2936             time_format_long time_format_medium time_format_short
2937             datetime_format_full datetime_format_long
2938             datetime_format_medium datetime_format_short
2939             available_formats format_data
2940             )) {
2941 0         0 my $method = "_clear_$property";
2942 0         0 $self->$method;
2943             }
2944             }
2945              
2946             sub _build_any_month {
2947 8     8   20 my ($self, $type, $width) = @_;
2948 8         36 my $default_calendar = $self->default_calendar();
2949 8         39 my @bundles = $self->_find_bundle('calendar_months');
2950             BUNDLES: {
2951 8         15 foreach my $bundle (@bundles) {
  12         29  
2952 16         619 my $months = $bundle->calendar_months;
2953 16 50       54 if (exists $months->{$default_calendar}{alias}) {
2954 0         0 $default_calendar = $months->{$default_calendar}{alias};
2955 0         0 redo BUNDLES;
2956             }
2957              
2958 16 100       68 if (exists $months->{$default_calendar}{$type}{$width}{alias}) {
2959 4         6 ($type, $width) = @{$months->{$default_calendar}{$type}{$width}{alias}}{qw(context type)};
  4         20  
2960 4         14 redo BUNDLES;
2961             }
2962            
2963 12         26 my $result = $months->{$default_calendar}{$type}{$width}{nonleap};
2964 12 100       320 return $result if defined $result;
2965             }
2966 0 0       0 if ($default_calendar ne 'gregorian') {
2967 0         0 $default_calendar = 'gregorian';
2968 0         0 redo BUNDLES;
2969             }
2970             }
2971 0         0 return [];
2972             }
2973              
2974             sub _build_month_format_wide {
2975 2     2   4 my $self = shift;
2976 2         9 my ($type, $width) = (qw(format wide));
2977            
2978 2         12 return $self->_build_any_month($type, $width);
2979             }
2980              
2981             sub _build_month_format_abbreviated {
2982 1     1   2 my $self = shift;
2983 1         4 my ($type, $width) = (qw(format abbreviated));
2984            
2985 1         6 return $self->_build_any_month($type, $width);
2986             }
2987              
2988             sub _build_month_format_narrow {
2989 1     1   3 my $self = shift;
2990 1         3 my ($type, $width) = (qw(format narrow));
2991            
2992 1         5 return $self->_build_any_month($type, $width);
2993             }
2994              
2995             sub _build_month_stand_alone_wide {
2996 1     1   2 my $self = shift;
2997 1         3 my ($type, $width) = ('stand-alone', 'wide');
2998            
2999 1         5 return $self->_build_any_month($type, $width);
3000             }
3001              
3002             sub _build_month_stand_alone_abbreviated {
3003 2     2   5 my $self = shift;
3004 2         6 my ($type, $width) = ('stand-alone', 'abbreviated');
3005            
3006 2         9 return $self->_build_any_month($type, $width);
3007             }
3008              
3009             sub _build_month_stand_alone_narrow {
3010 1     1   2 my $self = shift;
3011 1         3 my ($type, $width) = ('stand-alone', 'narrow');
3012            
3013 1         5 return $self->_build_any_month($type, $width);
3014             }
3015              
3016             sub _build_any_day {
3017 7     7   23 my ($self, $type, $width) = @_;
3018            
3019 7         26 my $default_calendar = $self->default_calendar();
3020              
3021 7         23 my @bundles = $self->_find_bundle('calendar_days');
3022             BUNDLES: {
3023 7         15 foreach my $bundle (@bundles) {
  10         22  
3024 13         498 my $days= $bundle->calendar_days;
3025            
3026 13 50       47 if (exists $days->{$default_calendar}{alias}) {
3027 0         0 $default_calendar = $days->{$default_calendar}{alias};
3028 0         0 redo BUNDLES;
3029             }
3030              
3031 13 100       50 if (exists $days->{$default_calendar}{$type}{$width}{alias}) {
3032 3         5 ($type, $width) = @{$days->{$default_calendar}{$type}{$width}{alias}}{qw(context type)};
  3         16  
3033 3         9 redo BUNDLES;
3034             }
3035 10         21 my $result = $days->{$default_calendar}{$type}{$width};
3036 10 100       36 return [ @{$result}{qw( mon tue wed thu fri sat sun )} ] if keys %$result;
  7         280  
3037             }
3038 0 0       0 if ($default_calendar ne 'gregorian') {
3039 0         0 $default_calendar = 'gregorian';
3040 0         0 redo BUNDLES;
3041             }
3042             }
3043              
3044 0         0 return [];
3045             }
3046              
3047             sub _build_day_format_wide {
3048 2     2   6 my $self = shift;
3049 2         7 my ($type, $width) = (qw(format wide));
3050            
3051 2         16 return $self->_build_any_day($type, $width);
3052             }
3053              
3054             sub _build_day_format_abbreviated {
3055 1     1   3 my $self = shift;
3056 1         3 my ($type, $width) = (qw(format abbreviated));
3057            
3058 1         6 return $self->_build_any_day($type, $width);
3059             }
3060              
3061             sub _build_day_format_narrow {
3062 1     1   2 my $self = shift;
3063 1         3 my ($type, $width) = (qw(format narrow));
3064            
3065 1         4 return $self->_build_any_day($type, $width);
3066             }
3067              
3068             sub _build_day_stand_alone_wide {
3069 1     1   8 my $self = shift;
3070 1         2 my ($type, $width) = ('stand-alone', 'wide');
3071            
3072 1         5 return $self->_build_any_day($type, $width);
3073             }
3074              
3075             sub _build_day_stand_alone_abbreviated {
3076 1     1   3 my $self = shift;
3077 1         3 my ($type, $width) = ('stand-alone', 'abbreviated');
3078              
3079 1         4 return $self->_build_any_day($type, $width);
3080             }
3081              
3082             sub _build_day_stand_alone_narrow {
3083 1     1   3 my $self = shift;
3084 1         3 my ($type, $width) = ('stand-alone', 'narrow');
3085            
3086 1         4 return $self->_build_any_day($type, $width);
3087             }
3088              
3089             sub _build_any_quarter {
3090 6     6   12 my ($self, $type, $width) = @_;
3091            
3092 6         20 my $default_calendar = $self->default_calendar();
3093              
3094 6         49 my @bundles = $self->_find_bundle('calendar_quarters');
3095             BUNDLES: {
3096 6         12 foreach my $bundle (@bundles) {
  9         21  
3097 12         458 my $quarters= $bundle->calendar_quarters;
3098            
3099 12 50       39 if (exists $quarters->{$default_calendar}{alias}) {
3100 0         0 $default_calendar = $quarters->{$default_calendar}{alias};
3101 0         0 redo BUNDLES;
3102             }
3103              
3104 12 100       45 if (exists $quarters->{$default_calendar}{$type}{$width}{alias}) {
3105 3         4 ($type, $width) = @{$quarters->{$default_calendar}{$type}{$width}{alias}}{qw(context type)};
  3         14  
3106 3         10 redo BUNDLES;
3107             }
3108            
3109 9         18 my $result = $quarters->{$default_calendar}{$type}{$width};
3110 9 100       31 return [ @{$result}{qw( 0 1 2 3 )} ] if keys %$result;
  6         232  
3111             }
3112 0 0       0 if ($default_calendar ne 'gregorian') {
3113 0         0 $default_calendar = 'gregorian';
3114 0         0 redo BUNDLES;
3115             }
3116             }
3117              
3118 0         0 return [];
3119             }
3120              
3121             sub _build_quarter_format_wide {
3122 1     1   4 my $self = shift;
3123 1         3 my ($type, $width) = (qw( format wide ));
3124            
3125 1         6 return $self->_build_any_quarter($type, $width);
3126             }
3127              
3128             sub _build_quarter_format_abbreviated {
3129 1     1   2 my $self = shift;
3130 1         4 my ($type, $width) = (qw(format abbreviated));
3131              
3132 1         4 return $self->_build_any_quarter($type, $width);
3133             }
3134              
3135             sub _build_quarter_format_narrow {
3136 1     1   3 my $self = shift;
3137 1         2 my ($type, $width) = (qw(format narrow));
3138              
3139 1         12 return $self->_build_any_quarter($type, $width);
3140             }
3141              
3142             sub _build_quarter_stand_alone_wide {
3143 1     1   2 my $self = shift;
3144 1         3 my ($type, $width) = ('stand-alone', 'wide');
3145              
3146 1         4 return $self->_build_any_quarter($type, $width);
3147             }
3148              
3149             sub _build_quarter_stand_alone_abbreviated {
3150 1     1   2 my $self = shift;
3151 1         3 my ($type, $width) = ('stand-alone', 'abbreviated');
3152            
3153 1         3 return $self->_build_any_quarter($type, $width);
3154             }
3155              
3156             sub _build_quarter_stand_alone_narrow {
3157 1     1   2 my $self = shift;
3158 1         4 my ($type, $width) = ('stand-alone', 'narrow');
3159              
3160 1         4 return $self->_build_any_quarter($type, $width);
3161             }
3162              
3163             sub get_day_period {
3164             # Time in hhmm
3165 3     3 1 1886 my ($self, $time, $type) = @_;
3166 3   50     43 $type //= 'default';
3167            
3168 3         24 my $default_calendar = $self->default_calendar();
3169            
3170 3         20 my $bundle = $self->_find_bundle('day_period_data');
3171            
3172 3         145 my $day_period = $bundle->day_period_data;
3173 3         18 $day_period = $self->$day_period($default_calendar, $time, $type);
3174            
3175             # The day period for root is commented out but I need that data so will
3176             # fix up here as a default
3177 3 0 33     12 $day_period ||= $time < 1200 ? 'am' : 'pm';
3178            
3179 3         131 my $am_pm = $self->am_pm_format_abbreviated;
3180            
3181 3         17 return $am_pm->{$day_period};
3182             }
3183              
3184             sub _build_any_am_pm {
3185 10     10   22 my ($self, $type, $width) = @_;
3186              
3187 10         35 my $default_calendar = $self->default_calendar();
3188 10         28 my @result;
3189 10         34 my @bundles = $self->_find_bundle('day_periods');
3190 10         21 my %return;
3191              
3192             BUNDLES: {
3193 10         15 foreach my $bundle (@bundles) {
  19         41  
3194 38         1456 my $am_pm = $bundle->day_periods;
3195            
3196 38 50       112 if (exists $am_pm->{$default_calendar}{alias}) {
3197 0         0 $default_calendar = $am_pm->{$default_calendar}{alias};
3198 0         0 redo BUNDLES;
3199             }
3200              
3201 38 50       113 if (exists $am_pm->{$default_calendar}{$type}{alias}) {
3202 0         0 $type = $am_pm->{$default_calendar}{$type}{alias};
3203 0         0 redo BUNDLES;
3204             }
3205            
3206 38 100       113 if (exists $am_pm->{$default_calendar}{$type}{$width}{alias}) {
3207 9         14 my $original_width = $width;
3208 9         21 $width = $am_pm->{$default_calendar}{$type}{$width}{alias}{width};
3209 9         21 $type = $am_pm->{$default_calendar}{$type}{$original_width}{alias}{context};
3210 9         22 redo BUNDLES;
3211             }
3212            
3213 29         87 my $result = $am_pm->{$default_calendar}{$type}{$width};
3214            
3215 29         93 foreach (keys %$result) {
3216 140 100       417 $return{$_} = $result->{$_} unless exists $return{$_};
3217             }
3218             }
3219             }
3220              
3221 10         227 return \%return;
3222             }
3223              
3224             # The first 3 are to link in with Date::Time::Locale
3225             sub _build_am_pm_wide {
3226 1     1   2 my $self = shift;
3227 1         4 my ($type, $width) = (qw( format wide ));
3228            
3229 1         6 my $result = $self->_build_any_am_pm($type, $width);
3230            
3231 1         43 return [ @$result{qw( am pm )} ];
3232             }
3233              
3234             sub _build_am_pm_abbreviated {
3235 2     2   11 my $self = shift;
3236 2         8 my ($type, $width) = (qw( format abbreviated ));
3237              
3238 2         13 my $result = $self->_build_any_am_pm($type, $width);
3239            
3240 2         78 return [ @$result{qw( am pm )} ];
3241             }
3242              
3243             sub _build_am_pm_narrow {
3244 1     1   2 my $self = shift;
3245 1         3 my ($type, $width) = (qw( format narrow ));
3246            
3247 1         17 my $result = $self->_build_any_am_pm($type, $width);
3248            
3249 1         37 return [ @$result{qw( am pm )} ];
3250             }
3251              
3252             # Now we do the full set of data
3253             sub _build_am_pm_format_wide {
3254 1     1   2 my $self = shift;
3255 1         4 my ($type, $width) = (qw( format wide ));
3256            
3257 1         4 return $self->_build_any_am_pm($type, $width);
3258             }
3259              
3260             sub _build_am_pm_format_abbreviated {
3261 1     1   4 my $self = shift;
3262 1         8 my ($type, $width) = (qw( format abbreviated ));
3263              
3264 1         3 return $self->_build_any_am_pm($type, $width);
3265             }
3266              
3267             sub _build_am_pm_format_narrow {
3268 1     1   4 my $self = shift;
3269 1         3 my ($type, $width) = (qw( format narrow ));
3270            
3271 1         4 return $self->_build_any_am_pm($type, $width);
3272             }
3273              
3274             sub _build_am_pm_stand_alone_wide {
3275 1     1   3 my $self = shift;
3276 1         2 my ($type, $width) = ('stand-alone', 'wide');
3277            
3278 1         5 return $self->_build_any_am_pm($type, $width);
3279             }
3280              
3281             sub _build_am_pm_stand_alone_abbreviated {
3282 1     1   3 my $self = shift;
3283 1         3 my ($type, $width) = ('stand-alone', 'abbreviated');
3284              
3285 1         5 return $self->_build_any_am_pm($type, $width);
3286             }
3287              
3288             sub _build_am_pm_stand_alone_narrow {
3289 1     1   3 my $self = shift;
3290 1         9 my ($type, $width) = ('stand-alone', 'narrow');
3291            
3292 1         4 return $self->_build_any_am_pm($type, $width);
3293             }
3294              
3295             sub _build_any_era {
3296 9     9   19 my ($self, $width) = @_;
3297              
3298 9         26 my $default_calendar = $self->default_calendar();
3299 9         32 my @bundles = $self->_find_bundle('eras');
3300             BUNDLES: {
3301 9         18 foreach my $bundle (@bundles) {
  9         20  
3302 9         329 my $eras = $bundle->eras;
3303            
3304 9 50       32 if (exists $eras->{$default_calendar}{alias}) {
3305 0         0 $default_calendar = $eras->{$default_calendar}{alias};
3306 0         0 redo BUNDLES;
3307             }
3308              
3309 9 50       28 if (exists $eras->{$default_calendar}{$width}{alias}) {
3310 0         0 $width = $eras->{$default_calendar}{$width}{alias};
3311 0         0 redo BUNDLES;
3312             }
3313            
3314 9         26 my $result = $eras->{$default_calendar}{$width};
3315            
3316 9         13 my @result;
3317 9         47 @result[keys %$result] = values %$result;
3318            
3319 9 50       246 return \@result if keys %$result;
3320             }
3321 0 0       0 if ($default_calendar ne 'gregorian') {
3322 0         0 $default_calendar = 'gregorian';
3323 0         0 redo BUNDLES;
3324             }
3325             }
3326              
3327 0         0 return [];
3328             }
3329            
3330             # The next three are for DateDime::Locale
3331             sub _build_era_wide {
3332 1     1   2 my $self = shift;
3333 1         2 my ($width) = (qw( wide ));
3334              
3335 1         6 my $result = $self->_build_any_era($width);
3336            
3337 1         40 return [@$result[0, 1]];
3338             }
3339              
3340             sub _build_era_abbreviated {
3341 1     1   3 my $self = shift;
3342 1         2 my ($width) = (qw( abbreviated ));
3343              
3344 1         5 my $result = $self->_build_any_era($width);
3345            
3346 1         36 return [@$result[0, 1]];
3347             }
3348              
3349             sub _build_era_narrow {
3350 1     1   2 my $self = shift;
3351 1         3 my ($width) = (qw( narrow ));
3352              
3353 1         4 my $result = $self->_build_any_era($width);
3354            
3355 1         34 return [@$result[0, 1]];
3356             }
3357              
3358             # Now get all the era data
3359             sub _build_era_format_wide {
3360 2     2   5 my $self = shift;
3361 2         4 my ($width) = (qw( wide ));
3362              
3363 2         6 return $self->_build_any_era($width);
3364             }
3365              
3366             sub _build_era_format_abbreviated {
3367 2     2   5 my $self = shift;
3368 2         5 my ($width) = (qw( abbreviated ));
3369              
3370 2         7 return $self->_build_any_era($width);
3371             }
3372              
3373             sub _build_era_format_narrow {
3374 2     2   3 my $self = shift;
3375 2         5 my ($type, $width) = (qw( narrow ));
3376              
3377 2         14 return $self->_build_any_era($type, $width);
3378             }
3379              
3380             *_build_era_stand_alone_wide = \&_build_era_format_wide;
3381             *_build_era_stand_alone_abbreviated = \&_build_era_format_abbreviated;
3382             *_build_era_stand_alone_narrow = \&_build_era_format_narrow;
3383              
3384             sub _build_any_date_format {
3385 9     9   24 my ($self, $width) = @_;
3386 9         38 my $default_calendar = $self->default_calendar();
3387            
3388 9         38 my @bundles = $self->_find_bundle('date_formats');
3389              
3390             BUNDLES: {
3391 9         18 foreach my $bundle (@bundles) {
  9         25  
3392 9         352 my $date_formats = $bundle->date_formats;
3393 9 50       34 if (exists $date_formats->{alias}) {
3394 0         0 $default_calendar = $date_formats->{alias};
3395 0         0 redo BUNDLES;
3396             }
3397            
3398 9         31 my $result = $date_formats->{$default_calendar}{$width};
3399 9 50       178 return $result if $result;
3400             }
3401 0 0       0 if ($default_calendar ne 'gregorian') {
3402 0         0 $default_calendar = 'gregorian';
3403 0         0 redo BUNDLES;
3404             }
3405             }
3406            
3407 0         0 return '';
3408             }
3409              
3410             sub _build_date_format_full {
3411 1     1   5 my $self = shift;
3412            
3413 1         4 my ($width) = ('full');
3414 1         9 return $self->_build_any_date_format($width);
3415             }
3416              
3417             sub _build_date_format_long {
3418 1     1   3 my $self = shift;
3419            
3420 1         3 my ($width) = ('long');
3421 1         4 return $self->_build_any_date_format($width);
3422             }
3423              
3424             sub _build_date_format_medium {
3425 1     1   2 my $self = shift;
3426            
3427 1         3 my ($width) = ('medium');
3428 1         3 return $self->_build_any_date_format($width);
3429             }
3430              
3431             sub _build_date_format_short {
3432 1     1   4 my $self = shift;
3433            
3434 1         2 my ($width) = ('short');
3435 1         5 return $self->_build_any_date_format($width);
3436             }
3437              
3438             sub _build_any_time_format {
3439 9     9   20 my ($self, $width) = @_;
3440 9         37 my $default_calendar = $self->default_calendar();
3441            
3442 9         35 my @bundles = $self->_find_bundle('time_formats');
3443              
3444             BUNDLES: {
3445 9         16 foreach my $bundle (@bundles) {
  9         26  
3446 9         349 my $time_formats = $bundle->time_formats;
3447 9 50       38 if (exists $time_formats->{$default_calendar}{alias}) {
3448 0         0 $default_calendar = $time_formats->{$default_calendar}{alias};
3449 0         0 redo BUNDLES;
3450             }
3451            
3452 9         25 my $result = $time_formats->{$default_calendar}{$width};
3453 9 50       31 if ($result) {
3454 9         37 my $time_separator = $self->_get_time_separator;
3455 9         43 $result =~ s/:/$time_separator/g;
3456 9         164 return $result;
3457             }
3458             }
3459 0 0       0 if ($default_calendar ne 'gregorian') {
3460 0         0 $default_calendar = 'gregorian';
3461 0         0 redo BUNDLES;
3462             }
3463             }
3464 0         0 return '';
3465             }
3466              
3467             sub _build_time_format_full {
3468 1     1   3 my $self = shift;
3469 1         3 my $width = 'full';
3470            
3471 1         5 return $self->_build_any_time_format($width);
3472             }
3473              
3474             sub _build_time_format_long {
3475 1     1   3 my $self = shift;
3476            
3477 1         3 my $width = 'long';
3478 1         5 return $self->_build_any_time_format($width);
3479             }
3480              
3481             sub _build_time_format_medium {
3482 1     1   3 my $self = shift;
3483            
3484 1         3 my $width = 'medium';
3485 1         6 return $self->_build_any_time_format($width);
3486             }
3487              
3488             sub _build_time_format_short {
3489 1     1   3 my $self = shift;
3490            
3491 1         2 my $width = 'short';
3492 1         4 return $self->_build_any_time_format($width);
3493             }
3494              
3495             sub _build_any_datetime_format {
3496 5     5   13 my ($self, $width) = @_;
3497 5         20 my $default_calendar = $self->default_calendar();
3498            
3499 5         21 my @bundles = $self->_find_bundle('datetime_formats');
3500              
3501             BUNDLES: {
3502 5         13 foreach my $bundle (@bundles) {
  5         15  
3503 5         213 my $datetime_formats = $bundle->datetime_formats;
3504 5 50       21 if (exists $datetime_formats->{$default_calendar}{alias}) {
3505 0         0 $default_calendar = $datetime_formats->{$default_calendar}{alias};
3506 0         0 redo BUNDLES;
3507             }
3508            
3509 5         16 my $result = $datetime_formats->{$default_calendar}{$width};
3510 5 50       25 return $result if $result;
3511             }
3512 0 0       0 if ($default_calendar ne 'gregorian') {
3513 0         0 $default_calendar = 'gregorian';
3514 0         0 redo BUNDLES;
3515             }
3516             }
3517            
3518 0         0 return '';
3519             }
3520              
3521             sub _build_datetime_format_full {
3522 2     2   7 my $self = shift;
3523            
3524 2         5 my $width = 'full';
3525 2         11 my $format = $self->_build_any_datetime_format($width);
3526            
3527 2         12 my $date = $self->_build_any_date_format($width);
3528 2         14 my $time = $self->_build_any_time_format($width);
3529            
3530 2         10 $format =~ s/\{0\}/$time/;
3531 2         11 $format =~ s/\{1\}/$date/;
3532            
3533 2         74 return $format;
3534             }
3535              
3536             sub _build_datetime_format_long {
3537 1     1   3 my $self = shift;
3538            
3539 1         2 my $width = 'long';
3540 1         4 my $format = $self->_build_any_datetime_format($width);
3541            
3542 1         6 my $date = $self->_build_any_date_format($width);
3543 1         5 my $time = $self->_build_any_time_format($width);
3544            
3545 1         5 $format =~ s/\{0\}/$time/;
3546 1         4 $format =~ s/\{1\}/$date/;
3547            
3548 1         36 return $format;
3549             }
3550              
3551             sub _build_datetime_format_medium {
3552 1     1   3 my $self = shift;
3553            
3554 1         3 my $width = 'medium';
3555 1         4 my $format = $self->_build_any_datetime_format($width);
3556            
3557 1         6 my $date = $self->_build_any_date_format($width);
3558 1         5 my $time = $self->_build_any_time_format($width);
3559            
3560 1         6 $format =~ s/\{0\}/$time/;
3561 1         4 $format =~ s/\{1\}/$date/;
3562            
3563 1         35 return $format;
3564             }
3565              
3566             sub _build_datetime_format_short {
3567 1     1   2 my $self = shift;
3568            
3569 1         2 my $width = 'short';
3570 1         5 my $format = $self->_build_any_datetime_format($width);
3571            
3572 1         6 my $date = $self->_build_any_date_format($width);
3573 1         4 my $time = $self->_build_any_time_format($width);
3574            
3575 1         5 $format =~ s/\{0\}/$time/;
3576 1         5 $format =~ s/\{1\}/$date/;
3577            
3578 1         36 return $format;
3579             }
3580              
3581             sub _build_format_data {
3582 0     0   0 my $self = shift;
3583 0         0 my $default_calendar = $self->default_calendar();
3584              
3585 0         0 my @bundles = $self->_find_bundle('datetime_formats_available_formats');
3586 0         0 foreach my $calendar ($default_calendar, 'gregorian') {
3587 0         0 foreach my $bundle (@bundles) {
3588 0         0 my $datetime_formats_available_formats = $bundle->datetime_formats_available_formats;
3589 0         0 my $result = $datetime_formats_available_formats->{$calendar};
3590 0 0       0 return $result if $result;
3591             }
3592             }
3593              
3594 0         0 return {};
3595             }
3596              
3597             sub format_for {
3598 0     0 1 0 my ($self, $format) = @_;
3599              
3600 0         0 my $format_data = $self->format_data;
3601              
3602 0   0     0 return $format_data->{$format} // '';
3603             }
3604              
3605             sub _build_available_formats {
3606 0     0   0 my $self = shift;
3607              
3608 0         0 my $format_data = $self->format_data;
3609              
3610 0         0 return [keys %$format_data];
3611             }
3612              
3613             sub _build_default_date_format_length {
3614 0     0   0 my $self = shift;
3615            
3616 0         0 my $default_calendar = $self->default_calendar();
3617              
3618 0         0 my @bundles = $self->_find_bundle('date_formats');
3619 0         0 foreach my $calendar ($default_calendar, 'gregorian') {
3620 0         0 foreach my $bundle (@bundles) {
3621 0         0 my $date_formats = $bundle->date_formats;
3622 0         0 my $result = $date_formats->{$calendar}{default};
3623 0 0       0 return $result if $result;
3624             }
3625             }
3626             }
3627              
3628             sub _build_default_time_format_length {
3629 0     0   0 my $self = shift;
3630            
3631 0         0 my $default_calendar = $self->default_calendar();
3632              
3633 0         0 my @bundles = $self->_find_bundle('time_formats');
3634 0         0 foreach my $calendar ($default_calendar, 'gregorian') {
3635 0         0 foreach my $bundle (@bundles) {
3636 0         0 my $time_formats = $bundle->time_formats;
3637 0         0 my $result = $time_formats->{$calendar}{default};
3638 0 0       0 return $result if $result;
3639             }
3640             }
3641             }
3642              
3643             sub _build_prefers_24_hour_time {
3644 1     1   2 my $self = shift;
3645              
3646 1 50       41 return $self->time_format_short() =~ /h|K/ ? 0 : 1;
3647             }
3648              
3649             {
3650             my %days_2_number = (
3651             mon => 1,
3652             tue => 2,
3653             wen => 3,
3654             thu => 4,
3655             fri => 5,
3656             sat => 6,
3657             sun => 7,
3658             );
3659              
3660             sub _build_first_day_of_week {
3661              
3662 1     1   3 my $self = shift;
3663              
3664 1         6 my $first_day = $self->week_data_first_day;
3665            
3666 1         37 return $days_2_number{$first_day};
3667             }
3668             }
3669              
3670             # Sub to mangle Unicode regex to Perl regex
3671             # Backwards compatibility hack
3672 20 50   20   178 *_unicode_to_perl = eval <<'EOT' || \&_new_perl;
  20     20   44  
  20     163   1024  
  20         107  
  20         56  
  20         1106  
  163         300  
  163         626  
  163         913  
  99         2795  
  163         2551  
3673             sub {
3674             my $regex = shift;
3675              
3676             return '' unless length $regex;
3677             $regex =~ s/
3678             (?:\\\\)*+ # Pairs of \
3679             (?!\\) # Not followed by \
3680             \K # But we don't want to keep that
3681             (?<set> # Capture this
3682             \[ # Start a set
3683             (?:
3684             [^\[\]\\]+ # One or more of not []\
3685             | # or
3686             (?:
3687             (?:\\\\)*+ # One or more pairs of \ without back tracking
3688             \\. # Followed by an escaped character
3689             )
3690             | # or
3691             (?&set) # An inner set
3692             )++ # Do the inside set stuff one or more times without backtracking
3693             \] # End the set
3694             )
3695             / _convert($1) /xeg;
3696             no warnings "experimental::regex_sets";
3697             no warnings "deprecated"; # Because CLDR uses surrogates
3698             return qr/$regex/x;
3699             };
3700              
3701             EOT
3702              
3703             # Backwards compatibility hack
3704 99 50   99   227 *_convert = eval <<'EOT' || \&_new_perl;
  99 50       307  
  99         238  
  0         0  
  99         125  
  99         1090  
  99         198  
  99         218  
  99         3367  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
3705             sub {
3706             my $set = shift;
3707            
3708             # Some definitions
3709             my $posix = qr/(?(DEFINE)
3710             (?<posix> (?> \[: .+? :\] ) )
3711             )/x;
3712            
3713             # Convert Unicode escapes \u1234 to characters
3714             $set =~ s/\\u(\p{Ahex}+)/chr(hex($1))/egx;
3715            
3716             # Check to see if this is a normal character set
3717             my $normal = 0;
3718            
3719             $normal = 1 if $set =~ /^
3720             \s* # Possible white space
3721             \[ # Opening set
3722             ^? # Possible negation
3723             (?: # One of
3724             [^\[\]]++ # Not an open or close set
3725             | # Or
3726             (?<=\\)[\[\]] # An open or close set preceded by \
3727             | # Or
3728             (?:
3729             \s* # Possible white space
3730             (?&posix) # A posix class
3731             (?! # Not followed by
3732             \s* # Possible white space
3733             [&-] # A Unicode regex op
3734             \s* # Possible white space
3735             \[ # A set opener
3736             )
3737             )
3738             )+
3739             \] # Close the set
3740             \s* # Possible white space
3741             $
3742             $posix
3743             /x;
3744            
3745             # Convert posix to perl
3746             $set =~ s/\[:(.*?):\]/\\p{$1}/g;
3747            
3748             if ($normal) {
3749             return "$set";
3750             }
3751            
3752             # Fix up [abc[de]] to [[abc][de]]
3753             $set =~ s/\[ ( (?>\^? \s*) [^\]]+? ) \s* \[/[[$1][/gx;
3754            
3755             # Fix up [[ab]cde] to [[ab][cde]]
3756             $set =~ s/\[ \^?+ \s* \[ [^\]]+? \] \K \s* ( [^\[]+ ) \]/[$1]]/gx;
3757            
3758             # Unicode uses ^ to compliment the set where as Perl uses !
3759             $set =~ s/\[ \^ \s*/[!/gx;
3760            
3761             # The above can leave us with empty sets. Strip them out
3762             $set =~ s/\[\]//g;
3763            
3764             # Fixup inner sets with no operator
3765             1 while $set =~ s/ \] \s* \[ /] + [/gx;
3766             1 while $set =~ s/ \] \s * (\\p\{.*?\}) /] + $1/xg;
3767             1 while $set =~ s/ \\p\{.*?\} \s* \K \[ / + [/xg;
3768             1 while $set =~ s/ \\p\{.*?\} \s* \K (\\p\{.*?\}) / + $1/xg;
3769            
3770             # Unicode uses [] for grouping as well as starting an inner set
3771             # Perl uses ( ) So fix that up now
3772            
3773             $set =~ s/. \K \[ (?> (!?) \s*) \[ /($1\[/gx;
3774             $set =~ s/ \] \s* \] (.) /])$1/gx;
3775            
3776             return "(?$set)";
3777             }
3778              
3779             EOT
3780              
3781             # The following pod is for methods defined in the Moose Role
3782             # files that are automatically generated from the data
3783             =back
3784              
3785             =head2 Valid codes
3786              
3787             =over 4
3788              
3789             =item valid_languages()
3790              
3791             This method returns a list containing all the valid language codes
3792              
3793             =item valid_scripts()
3794              
3795             This method returns a list containing all the valid script codes
3796              
3797             =item valid_regions()
3798              
3799             This method returns a list containing all the valid region codes
3800              
3801             =item valid_variants()
3802              
3803             This method returns a list containing all the valid variant codes
3804              
3805             =item key_aliases()
3806              
3807             This method returns a hash that maps valid keys to their valid aliases
3808              
3809             =item key_names()
3810              
3811             This method returns a hash that maps valid key aliases to their valid keys
3812              
3813             =item valid_keys()
3814              
3815             This method returns a hash of valid keys and the valid type codes you
3816             can have with each key
3817              
3818             =item language_aliases()
3819              
3820             This method returns a hash that maps valid language codes to their valid aliases
3821              
3822             =item region_aliases()
3823              
3824             This method returns a hash that maps valid region codes to their valid aliases
3825              
3826             =item variant_aliases()
3827              
3828             This method returns a hash that maps valid variant codes to their valid aliases
3829              
3830             =back
3831              
3832             =head2 Information about weeks
3833              
3834             There are no standard codes for the days of the weeks so CLDR uses the following
3835             three letter codes to represent unlocalised days
3836              
3837             =over 4
3838              
3839             =item sun
3840              
3841             Sunday
3842              
3843             =item mon
3844              
3845             Monday
3846              
3847             =item tue
3848              
3849             Tuesday
3850              
3851             =item wed
3852              
3853             Wednesday
3854              
3855             =item thu
3856              
3857             Thursday
3858              
3859             =item fri
3860              
3861             Friday
3862              
3863             =item sat
3864              
3865             Saturday
3866              
3867             =back
3868              
3869             =cut
3870              
3871             sub _week_data {
3872 5     5   12 my ($self, $region_id, $week_data_hash) = @_;
3873            
3874 5   33     34 $region_id //= ( $self->region_id || $self->likely_subtag->region_id );
      33        
3875            
3876 5 100       26 return $week_data_hash->{$region_id} if exists $week_data_hash->{$region_id};
3877            
3878 2         4 while (1) {
3879 8         325 $region_id = $self->region_contained_by()->{$region_id};
3880 8 50       19 return unless defined $region_id;
3881 8 100       30 return $week_data_hash->{$region_id} if exists $week_data_hash->{$region_id};
3882             }
3883             }
3884              
3885             =over 4
3886              
3887             =item week_data_min_days($region_id)
3888              
3889             This method takes an optional region id and returns a the minimum number of days
3890             a week must have to count as the starting week of the new year. It uses the current
3891             locale's region if no region id is passed in.
3892              
3893             =cut
3894              
3895             sub week_data_min_days {
3896 1     1 1 3 my ($self, $region_id) = @_;
3897            
3898 1         45 my $week_data_hash = $self->_week_data_min_days();
3899 1         4 return _week_data($self, $region_id, $week_data_hash);
3900             }
3901              
3902             =item week_data_first_day($region_id)
3903              
3904             This method takes an optional region id and returns the three letter code of the
3905             first day of the week for that region. If no region id is passed in then it
3906             uses the current locale's region.
3907              
3908             =cut
3909              
3910             sub week_data_first_day {
3911 2     2 1 5 my ($self, $region_id) = @_;
3912            
3913 2         85 my $week_data_hash = $self->_week_data_first_day();
3914 2         14 return _week_data($self, $region_id, $week_data_hash);
3915             }
3916              
3917             =item week_data_weekend_start()
3918              
3919             This method takes an optional region id and returns the three letter code of the
3920             first day of the week end for that region. If no region id is passed in then it
3921             uses the current locale's region.
3922              
3923             =cut
3924              
3925             sub week_data_weekend_start {
3926 1     1 1 3 my ($self, $region_id) = @_;
3927 1         45 my $week_data_hash = $self->_week_data_weekend_start();
3928            
3929 1         5 return _week_data($self, $region_id, $week_data_hash);
3930             }
3931              
3932             =item week_data_weekend_end()
3933              
3934             This method takes an optional region id and returns the three letter code of the
3935             first day of the week end for that region. If no region id is passed in then it
3936             uses the current locale's region.
3937              
3938             =cut
3939              
3940             sub week_data_weekend_end {
3941 1     1 1 4 my ($self, $region_id) = @_;
3942 1         45 my $week_data_hash = $self->_week_data_weekend_end();
3943            
3944 1         5 return _week_data($self, $region_id, $week_data_hash);
3945             }
3946              
3947             =item month_patterns($context, $width, $type)
3948              
3949             The Chinese lunar calendar can insert a leap month after nearly any month of its year;
3950             when this happens, the month takes the name of the preceding month plus a special marker.
3951             The Hindu lunar calendars can insert a leap month before any one or two months of the year;
3952             when this happens, not only does the leap month take the name of the following month plus a
3953             special marker, the following month also takes a special marker. Moreover, in the Hindu
3954             calendar sometimes a month is skipped, in which case the preceding month takes a special marker
3955             plus the names of both months. The monthPatterns() method returns an array ref of month names
3956             with the marker added.
3957              
3958             =cut
3959              
3960             my %month_functions = (
3961             format => {
3962             wide => 'month_format_wide',
3963             abbreviated => 'month_format_abbreviated',
3964             narrow => 'month_format_narrow',
3965             },
3966             'stand-alone' => {
3967             wide => 'month_stand_alone_wide',
3968             abbreviated => 'month_stand_alone_abbreviated',
3969             narrow => 'month_stand_alone_narrow',
3970             }
3971             );
3972              
3973             sub month_patterns {
3974 1     1 1 3389 my ($self, $context, $width, $type) = @_;
3975            
3976 1         4 my @months;
3977 1 50       8 if ($context eq 'numeric') {
3978 0         0 @months = ( 1 .. 14 );
3979             }
3980             else {
3981 1         8 my $months_method = $month_functions{$context}{$width};
3982 1         140 my $months = $self->$months_method;
3983 1         8 @months = @$months;
3984             }
3985            
3986 1         5 my $default_calendar = $self->default_calendar();
3987            
3988 1         6 my @bundles = $self->_find_bundle('month_patterns');
3989              
3990 1         3 my $result;
3991             BUNDLES: {
3992 1         2 foreach my $bundle (@bundles) {
  2         6  
3993 2         79 my $month_patterns = $bundle->month_patterns;
3994 2 50       7 if (exists $month_patterns->{$default_calendar}{alias}) {
3995 0         0 $default_calendar = $month_patterns->{$default_calendar}{alias};
3996 0         0 redo BUNDLES;
3997             }
3998            
3999             # Check for width alias
4000 2 100       10 if (exists $month_patterns->{$default_calendar}{$context}{$width}{alias}) {
4001 1         4 $context = $month_patterns->{$default_calendar}{$context}{$width}{alias}{context};
4002 1         4 $width = $month_patterns->{$default_calendar}{$context}{$width}{alias}{width};
4003 1         4 redo BUNDLES;
4004             }
4005            
4006 1         5 $result = $month_patterns->{$default_calendar}{$context}{$width}{$type};
4007 1 50       5 last BUNDLES if $result;
4008             }
4009 0 0       0 if ($default_calendar ne 'gregorian') {
4010 0         0 $default_calendar = 'gregorian';
4011 0         0 redo BUNDLES;
4012             }
4013             }
4014            
4015 1 50       4 if ($result) {
4016 1         3 foreach my $month (@months) {
4017 12         29 (my $fixed_month = $result) =~ s/\{0\}/$month/g;
4018 12         21 $month = $fixed_month;
4019             }
4020             }
4021            
4022 1         14 return \@months;
4023             }
4024              
4025             =item cyclic_name_sets($context, $width, $type)
4026              
4027             This method returns an arrayref containing the cyclic names for the locale's
4028             default calendar using the given context, width and type.
4029              
4030             Context can can currently only be c<format>
4031              
4032             Width is one of C<abbreviated>, C<narrow> or C<wide>
4033              
4034             Type is one of C<dayParts>, C<days>, C<months>, C<solarTerms>, C<years> or C<zodiacs>
4035              
4036             =cut
4037              
4038             sub cyclic_name_sets {
4039 1     1 1 5 my ($self, $context, $width, $type) = @_;
4040            
4041 1         6 my @bundles = $self->_find_bundle('cyclic_name_sets');
4042 1         8 my $default_calendar = $self->default_calendar();
4043 1         5 foreach my $bundle (@bundles) {
4044 2         84 my $cyclic_name_set = $bundle->cyclic_name_sets();
4045             NAME_SET: {
4046 2 50       3 if (my $alias_calendar = $cyclic_name_set->{$default_calendar}{alias}) {
  3         11  
4047 0         0 $default_calendar = $alias_calendar;
4048 0         0 redo NAME_SET;
4049             }
4050            
4051 3 50       12 if (my $type_alias = $cyclic_name_set->{$default_calendar}{$type}{alias}) {
4052 0         0 $type = $type_alias;
4053 0         0 redo NAME_SET;
4054             }
4055            
4056 3 100       16 if (my $width_alias = $cyclic_name_set->{$default_calendar}{$type}{$context}{$width}{alias}) {
4057 1         3 $context = $width_alias->{context};
4058 1         3 $type = $width_alias->{name_set};
4059 1         2 $width = $width_alias->{type};
4060 1         5 redo NAME_SET;
4061             }
4062            
4063             my $return = [
4064 2         10 @{ $cyclic_name_set->{$default_calendar}{$type}{$context}{$width} }
4065 2         3 {sort { $a <=> $b } keys %{ $cyclic_name_set->{$default_calendar}{$type}{$context}{$width} }}
  30         52  
  2         18  
4066             ];
4067            
4068 2 100       22 return $return if @$return;
4069             }
4070             }
4071 0         0 return [];
4072             }
4073              
4074             =back
4075              
4076             =head2 region Containment
4077              
4078             =over 4
4079              
4080             =item region_contains()
4081              
4082             This method returns a hash ref keyed on region id. The value is an array ref.
4083             Each element of the array ref is a region id of a region immediately
4084             contained in the region used as the key
4085              
4086             =item region_contained_by()
4087              
4088             This method returns a hash ref keyed on region id. The value of the hash
4089             is the region id of the immediately containing region.
4090              
4091             =back
4092              
4093             =head2 Numbering Systems
4094              
4095             =over 4
4096              
4097             =item numbering_system()
4098              
4099             This method returns a hash ref keyed on numbering system id which, for a given
4100             locale, can be got by calling the default_numbering_system() method. The values
4101             of the hash are a two element hash ref the keys being C<type> and C<data>. If the
4102             type is C<numeric> then the data is an array ref of characters. The position in the
4103             array matches the numeric value of the character. If the type is C<algorithmic>
4104             then data is the name of the algorithm used to display numbers in that format.
4105              
4106             =back
4107              
4108             =head2 Number Formatting
4109              
4110             =over 4
4111              
4112             =item format_number($number, $format, $currency, $for_cash)
4113              
4114             This method formats the number $number using the format $format. If the format contains
4115             the currency symbol C<¤> then the currency symbol for the currency code in $currency
4116             will be used. If $currency is undef() then the default currency code for the locale
4117             will be used.
4118              
4119             Note that currency codes are based on region so if you do not pass in a currency
4120             and your locale did not get passed a region in the constructor you are going
4121             to end up with the L<likely sub tag's|/likely_subtags> idea of the currency. This
4122             functionality may be removed or at least changed to emit a warning in future
4123             releases.
4124              
4125             $for_cash is only used during currency formatting. If true then cash rounding
4126             will be used otherwise financial rounding will be used.
4127              
4128             This function also handles rule based number formatting. If $format is string equivalent
4129             to one of the current locale's public rule based number formats then $number will be
4130             formatted according to that rule.
4131              
4132             =item format_currency($number, $for_cash)
4133              
4134             This method formats the number $number using the default currency and currency format for the locale.
4135             If $for_cash is a true value then cash rounding will be used otherwise financial rounding will be used.
4136              
4137             =item default_currency_formt
4138              
4139             This method returns the currency format for the current locale
4140              
4141             It takes no paramaters
4142              
4143             =item add_currency_symbol($format, $symbol)
4144              
4145             This method returns the format with the currency symbol $symbol correctly inserted
4146             into the format
4147              
4148             =item parse_number_format($format, $currency, $currency_data, $for_cash)
4149              
4150             This method parses a CLDR numeric format string into a hash ref containing data used to
4151             format a number. If a currency is being formatted then $currency contains the
4152             currency code, $currency_data is a hashref containing the currency rounding
4153             information and $for_cash is a flag to signal cash or financial rounding.
4154              
4155             This should probably be a private function.
4156              
4157             =item round($number, $increment, $decimal_digits)
4158              
4159             This method returns $number rounded to the nearest $increment with $decimal_digits
4160             digits after the decimal point
4161              
4162             =item get_formatted_number($number, $format, $currency_data, $for_cash)
4163              
4164             This method takes the $format produced by parse_number_format() and uses it to
4165             parse $number. It returns a string containing the parsed number. If a currency
4166             is being formatted then $currency_data is a hashref containing the currency
4167             rounding information and $for_cash is a flag to signal cash or financial rounding.
4168              
4169             =item get_digits()
4170              
4171             This method returns an array containing the digits used by the locale, The order of the
4172             array is the order of the digits. It the locale's numbering system is C<algorithmic> it
4173             will return C<[0,1,2,3,4,5,6,7,8,9]>
4174              
4175             =item default_numbering_system()
4176              
4177             This method returns the numbering system id for the locale.
4178              
4179             =item default_currency_format()
4180              
4181             This method returns the locale's currenc format. This can be used by the number formatting code to
4182             correctly format the locale's currency
4183              
4184             =item currency_format($format_type)
4185              
4186             This method returns the format string for the currencies for the locale
4187              
4188             There are two types of formatting I<standard> and I<accounting> you can
4189             pass C<standard> or C<account> as the paramater to the method to pick one of
4190             these ot it will use the locales default
4191              
4192             =cut
4193              
4194             sub currency_format {
4195 22     22 1 14662 my ($self, $default_currency_format) = @_;
4196            
4197 22 50 100     113 die "Invalid Currency format: must be one of 'standard' or 'account'"
      66        
4198             if defined $default_currency_format
4199             && $default_currency_format ne 'standard'
4200             && $default_currency_format ne 'account';
4201            
4202 22   66     116 $default_currency_format //= $self->default_currency_format;
4203 22         75 my @bundles = $self->_find_bundle('number_currency_formats');
4204            
4205 22         55 my $format = {};
4206 22         96 my $default_numbering_system = $self->default_numbering_system();
4207 22         55 foreach my $bundle (@bundles) {
4208             NUMBER_SYSTEM: {
4209 22         28 $format = $bundle->number_currency_formats();
  22         885  
4210 22 50       78 if (exists $format->{$default_numbering_system}{alias}) {
4211 0         0 $default_numbering_system = $format->{$default_numbering_system}{alias};
4212 0         0 redo NUMBER_SYSTEM;
4213             }
4214            
4215 22 50       93 if (exists $format->{$default_numbering_system}{pattern}{default}{$default_currency_format}{alias}) {
4216 0         0 $default_currency_format = $format->{$default_numbering_system}{pattern}{default}{$default_currency_format}{alias};
4217 0         0 redo NUMBER_SYSTEM;
4218             }
4219             }
4220            
4221 22 50       78 last if exists $format->{$default_numbering_system}{pattern}{default}{$default_currency_format}
4222             }
4223            
4224 22 100       57 $default_currency_format = 'accounting' if $default_currency_format eq 'account';
4225            
4226             return join ';',
4227             $format->{$default_numbering_system}{pattern}{default}{$default_currency_format}{positive},
4228             defined $format->{$default_numbering_system}{pattern}{default}{$default_currency_format}{negative}
4229             ? $format->{$default_numbering_system}{pattern}{default}{$default_currency_format}{negative}
4230 22 100       217 : ();
4231             }
4232              
4233             =back
4234              
4235             =head2 Measurement Information
4236              
4237             =over 4
4238              
4239             =item measurement_system()
4240              
4241             This method returns a hash ref keyed on region, the value being the measurement system
4242             id for the region. If the region you are interested in is not listed use the
4243             region_contained_by() method until you find an entry.
4244              
4245             =item paper_size()
4246              
4247             This method returns a hash ref keyed on region, the value being the paper size used
4248             in that region. If the region you are interested in is not listed use the
4249             region_contained_by() method until you find an entry.
4250              
4251             =back
4252              
4253             =head2 Likely Tags
4254              
4255             =over 4
4256              
4257             =item likely_subtags()
4258              
4259             A full locale tag requires, as a minimum, a language, script and region code. However for
4260             some locales it is possible to infer the missing element if the other two are given, e.g.
4261             given C<en_GB> you can infer the script will be latn. It is also possible to fill in the
4262             missing elements of a locale with sensible defaults given sufficient knowledge of the layout
4263             of the CLDR data and usage patterns of locales around the world.
4264              
4265             This function returns a hash ref keyed on partial locale id's with the value being the locale
4266             id for the most likely language, script and region code for the key.
4267              
4268             =back
4269              
4270             =head2 Currency Information
4271              
4272             =over 4
4273              
4274             =item currency_fractions()
4275              
4276             This method returns a hash ref keyed on currency id. The value is a hash ref containing four keys.
4277             The keys are
4278              
4279             =over 8
4280              
4281             =item digits
4282              
4283             The number of decimal digits normally formatted.
4284              
4285             =item rounding
4286              
4287             The rounding increment, in units of 10^-digits.
4288              
4289             =item cashdigits
4290              
4291             The number of decimal digits to be used when formatting quantities used in cash transactions (as opposed
4292             to a quantity that would appear in a more formal setting, such as on a bank statement).
4293              
4294             =item cashrounding
4295              
4296             The cash rounding increment, in units of 10^-cashdigits.
4297              
4298             =back
4299              
4300             =item default_currency($region_id)
4301              
4302             This method returns the default currency id for the region id.
4303             If no region id is given then the current locale's is used
4304              
4305             =cut
4306              
4307             sub default_currency {
4308 17     17 1 31 my ($self, $region_id) = @_;
4309            
4310 17 100       850 return $self->default_cu if $self->_test_default_cu();
4311            
4312 9   33     51 $region_id //= $self->region_id;
4313            
4314 9 50       26 if (! $region_id) {
4315 0         0 $region_id = $self->likely_subtag->region_id;
4316 0         0 warn "Locale::CLDR::default_currency:- No region given using $region_id at ";
4317             }
4318            
4319 9         337 my $default_currencies = $self->_default_currency;
4320            
4321 9 50       52 return $default_currencies->{$region_id} if exists $default_currencies->{$region_id};
4322            
4323 0         0 while (1) {
4324 0         0 $region_id = $self->region_contained_by($region_id);
4325 0 0       0 last unless $region_id;
4326 0 0       0 if (exists $default_currencies->{$region_id}) {
4327 0         0 $self->_set_default_cu($default_currencies->{$region_id});
4328 0         0 return $default_currencies->{$region_id};
4329             }
4330             }
4331             }
4332              
4333             =item currency_symbol($currency_id)
4334              
4335             This method returns the currency symbol for the given currency id in the current locale.
4336             If no currency id is given it uses the locale's default currency
4337              
4338             =cut
4339              
4340             sub currency_symbol {
4341 17     17 1 32 my ($self, $currency_id) = @_;
4342            
4343 17   33     39 $currency_id //= $self->default_currency;
4344            
4345 17         44 my @bundles = reverse $self->_find_bundle('currencies');
4346 17         44 foreach my $bundle (@bundles) {
4347 17         657 my $symbol = $bundle->currencies()->{uc $currency_id}{symbol};
4348 17 50       92 return $symbol if $symbol;
4349             }
4350            
4351 0           return '';
4352             }
4353              
4354             =back
4355              
4356             =head2 Calendar Information
4357              
4358             =over 4
4359              
4360             =item calendar_preferences()
4361              
4362             This method returns a hash ref keyed on region id. The values are array refs containing the preferred
4363             calendar id's in order of preference.
4364              
4365             =item default_calendar($region)
4366              
4367             This method returns the default calendar id for the given region. If no region id given it
4368             used the region of the current locale.
4369              
4370             =back
4371              
4372             =head2 Collation
4373              
4374             =over 4
4375              
4376             =item collation()
4377              
4378             This method returns a Locale::CLDR::Collator object. This is still in development. Future releases will
4379             try and match the API from L<Unicode::Collate> as much as possible and add tailoring for locales.
4380              
4381             =back
4382              
4383             =cut
4384              
4385             sub collation {
4386 0     0 1   my ($self) = @_;
4387            
4388 0           my %params;
4389 0           $params{type} = $self->_collation_type;
4390 0           $params{alternate} = $self->_collation_alternate;
4391 0           $params{backwards} = $self->_collation_backwards;
4392 0           $params{case_level} = $self->_collation_case_level;
4393 0           $params{case_ordering} = $self->_collation_case_ordering;
4394 0           $params{normalization} = $self->_collation_normalization;
4395 0           $params{numeric} = $self->_collation_numeric;
4396 0           $params{reorder} = $self->_collation_reorder;
4397 0           $params{strength} = $self->_collation_strength;
4398 0           $params{max_variable} = $self->_collation_max_variable;
4399            
4400 0           return Locale::CLDR::Collator->new(locale => $self, %params);
4401             }
4402              
4403             sub _collation_overrides {
4404 0     0     my ($self, $type) = @_;
4405            
4406 0           my @bundles = reverse $self->_find_bundle('collation');
4407            
4408 0           my $override = '';
4409 0           foreach my $bundle (@bundles) {
4410 0 0         last if $override = $bundle->collation()->{$type};
4411             }
4412            
4413 0 0 0       if ($type ne 'standard' && ! $override) {
4414 0           foreach my $bundle (@bundles) {
4415 0 0         last if $override = $bundle->collation()->{standard};
4416             }
4417             }
4418            
4419 0   0       return $override || [];
4420             }
4421            
4422             sub _collation_type {
4423 0     0     my $self = shift;
4424            
4425 0 0 0       return $self->extensions()->{co} if ref $self->extensions() && $self->extensions()->{co};
4426 0           my @bundles = reverse $self->_find_bundle('collation_type');
4427 0           my $collation_type = '';
4428            
4429 0           foreach my $bundle (@bundles) {
4430 0 0         last if $collation_type = $bundle->collation_type();
4431             }
4432            
4433 0   0       return $collation_type || 'standard';
4434             }
4435              
4436             sub _collation_alternate {
4437 0     0     my $self = shift;
4438            
4439 0 0 0       return $self->extensions()->{ka} if ref $self->extensions() && $self->extensions()->{ka};
4440 0           my @bundles = reverse $self->_find_bundle('collation_alternate');
4441 0           my $collation_alternate = '';
4442            
4443 0           foreach my $bundle (@bundles) {
4444 0 0         last if $collation_alternate = $bundle->collation_alternate();
4445             }
4446            
4447 0   0       return $collation_alternate || 'noignore';
4448             }
4449              
4450             sub _collation_backwards {
4451 0     0     my $self = shift;
4452            
4453 0 0 0       return $self->extensions()->{kb} if ref $self->extensions() && $self->extensions()->{kb};
4454 0           my @bundles = reverse $self->_find_bundle('collation_backwards');
4455 0           my $collation_backwards = '';
4456            
4457 0           foreach my $bundle (@bundles) {
4458 0 0         last if $collation_backwards = $bundle->collation_backwards();
4459             }
4460            
4461 0   0       return $collation_backwards || 'noignore';
4462             }
4463              
4464             sub _collation_case_level {
4465 0     0     my $self = shift;
4466            
4467 0 0 0       return $self->extensions()->{kc} if ref $self->extensions() && $self->extensions()->{kc};
4468 0           my @bundles = reverse $self->_find_bundle('collation_case_level');
4469 0           my $collation_case_level = '';
4470            
4471 0           foreach my $bundle (@bundles) {
4472 0 0         last if $collation_case_level = $bundle->collation_case_level();
4473             }
4474            
4475 0   0       return $collation_case_level || 'false';
4476             }
4477              
4478             sub _collation_case_ordering {
4479 0     0     my $self = shift;
4480            
4481 0 0 0       return $self->extensions()->{kf} if ref $self->extensions() && $self->extensions()->{kf};
4482 0           my @bundles = reverse $self->_find_bundle('collation_case_ordering');
4483 0           my $collation_case_ordering = '';
4484            
4485 0           foreach my $bundle (@bundles) {
4486 0 0         last if $collation_case_ordering = $bundle->collation_case_ordering();
4487             }
4488            
4489 0   0       return $collation_case_ordering || 'false';
4490             }
4491              
4492             sub _collation_normalization {
4493 0     0     my $self = shift;
4494            
4495 0 0 0       return $self->extensions()->{kk} if ref $self->extensions() && $self->extensions()->{kk};
4496 0           my @bundles = reverse $self->_find_bundle('collation_normalization');
4497 0           my $collation_normalization = '';
4498            
4499 0           foreach my $bundle (@bundles) {
4500 0 0         last if $collation_normalization = $bundle->collation_normalization();
4501             }
4502            
4503 0   0       return $collation_normalization || 'true';
4504             }
4505              
4506             sub _collation_numeric {
4507 0     0     my $self = shift;
4508            
4509 0 0 0       return $self->extensions()->{kn} if ref $self->extensions() && $self->extensions()->{kn};
4510 0           my @bundles = reverse $self->_find_bundle('collation_numeric');
4511 0           my $collation_numeric = '';
4512            
4513 0           foreach my $bundle (@bundles) {
4514 0 0         last if $collation_numeric = $bundle->collation_numeric();
4515             }
4516            
4517 0   0       return $collation_numeric || 'false';
4518             }
4519              
4520             sub _collation_reorder {
4521 0     0     my $self = shift;
4522            
4523 0 0 0       return $self->extensions()->{kr} if ref $self->extensions() && $self->extensions()->{kr};
4524 0           my @bundles = reverse $self->_find_bundle('collation_reorder');
4525 0           my $collation_reorder = [];
4526            
4527 0           foreach my $bundle (@bundles) {
4528 0 0 0       last if ref( $collation_reorder = $bundle->collation_reorder()) && @$collation_reorder;
4529             }
4530            
4531 0   0       return $collation_reorder || [];
4532             }
4533              
4534             sub _collation_strength {
4535 0     0     my $self = shift;
4536            
4537 0   0       my $collation_strength = ref $self->extensions() && $self->extensions()->{ks};
4538 0 0         if ($collation_strength) {
4539 0           $collation_strength =~ s/^level//;
4540 0 0         $collation_strength = 5 unless ($collation_strength + 0);
4541 0           return $collation_strength;
4542             }
4543            
4544 0           my @bundles = reverse $self->_find_bundle('collation_strength');
4545 0           $collation_strength = 0;
4546            
4547 0           foreach my $bundle (@bundles) {
4548 0 0         last if $collation_strength = $bundle->collation_strength();
4549             }
4550            
4551 0   0       return $collation_strength || 3;
4552             }
4553              
4554             sub _collation_max_variable {
4555 0     0     my $self = shift;
4556            
4557 0 0 0       return $self->extensions()->{kv} if ref $self->extensions() && $self->extensions()->{kv};
4558 0           my @bundles = reverse $self->_find_bundle('collation_max_variable');
4559 0           my $collation_max_variable = '';
4560            
4561 0           foreach my $bundle (@bundles) {
4562 0 0         last if $collation_max_variable = $bundle->collation_max_variable();
4563             }
4564            
4565 0   0       return $collation_max_variable || 3;
4566             }
4567              
4568             =head1 Locales
4569              
4570             Other locales can be found on CPAN. You can install Language packs from the
4571             Locale::CLDR::Locales::* packages. You will in future be able to install language
4572             packs for a given region by looking for a Bundle::Locale::CLDR::* package.
4573              
4574             If you are looking for a language pack that is not yet published then get hold of
4575             the version 0.25.4 from http://search.cpan.org/CPAN/authors/id/J/JG/JGNI/Locale-CLDR-v0.25.4.tar.gz
4576             which has data for all locals alternatively you can get hold of the latest version of the
4577             code from git hub at https://github.com/ThePilgrim/perlcldr
4578              
4579             =head1 AUTHOR
4580              
4581             John Imrie, C<< <JGNI at cpan dot org> >>
4582              
4583             =head1 BUGS
4584              
4585             Please report any bugs or feature requests to C<bug-locale-cldr at rt.cpan.org>, or through
4586             the web interface at L<http://rt.cpan.org/NoAuth/ReportBug.html?Queue=Locale-CLDR>. I will be notified, and then you'll
4587             automatically be notified of progress on your bug as I make changes.
4588              
4589             =head1 SUPPORT
4590              
4591             You can find documentation for this module with the perldoc command.
4592              
4593             perldoc Locale::CLDR
4594              
4595             You can also look for information at:
4596              
4597             =over 4
4598              
4599             =item * RT: CPAN's request tracker
4600              
4601             L<http://rt.cpan.org/NoAuth/Bugs.html?Dist=Locale-CLDR>
4602              
4603             =item * AnnoCPAN: Annotated CPAN documentation
4604              
4605             L<http://annocpan.org/dist/Locale-CLDR>
4606              
4607             =item * CPAN Ratings
4608              
4609             L<http://cpanratings.perl.org/d/Locale-CLDR>
4610              
4611             =item * Search CPAN
4612              
4613             L<http://search.cpan.org/dist/Locale-CLDR/>
4614              
4615             =back
4616              
4617              
4618             =head1 ACKNOWLEDGEMENTS
4619              
4620             Everyone at the Unicode Consortium for providing the data.
4621              
4622             Karl Williams for his tireless work on Unicode in the Perl
4623             regex engine.
4624              
4625             =head1 COPYRIGHT & LICENSE
4626              
4627             Copyright 2009-2015 John Imrie.
4628              
4629             This program is free software; you can redistribute it and/or modify it
4630             under the terms of either: the GNU General Public License as published
4631             by the Free Software Foundation; or the Artistic License.
4632              
4633             See http://dev.perl.org/licenses/ for more information.
4634              
4635             =cut
4636              
4637             1; # End of Locale::CLDR