1#!/usr/bin/perl
2
3use strict;
4use warnings;
5
6use 5.006;
7
8use lib './lib', 'tools/lib';
9
10use Data::Dumper;
11use File::Copy qw( copy );
12use File::Find::Rule;
13use File::Slurp qw( read_file );
14use Getopt::Long;
15use LDML;
16use Lingua::EN::Inflect qw( PL_N );
17use List::AllUtils qw( first );
18use Locale::Country
19    qw( country_code2code LOCALE_CODE_ALPHA_2 LOCALE_CODE_ALPHA_3 );
20use Path::Class;
21
22my $VERSION = '0.05';
23
24my $ScriptName = file($0)->basename();
25
26{
27    no warnings 'once';
28    $DateTime::Locale::InGenerator = 1;
29}
30
31my %opts;
32my $glibc_dir;
33
34sub main {
35    GetOptions(
36        'dir:s'     => \$opts{dir},
37        'file:s'    => \$opts{file},
38        'version:s' => \$opts{version},
39        'clean'     => \$opts{clean},
40        'quiet'     => \$opts{quiet},
41        'verbose'   => \$opts{verbose},
42        'help'      => \$opts{help},
43    );
44
45    $opts{help} = 1
46        unless defined $opts{dir} && -d $opts{dir};
47
48    usage() if $opts{help};
49
50    require_version();
51
52    clean() if $opts{clean};
53
54    binmode STDOUT, ':utf8' if $opts{verbose};
55    $| = 1;
56
57    ( $glibc_dir = $opts{dir} ) =~ s{cldr/.+}{};
58    $glibc_dir .= 'glibc';
59
60    generate_from_cldr_xml();
61}
62
63sub usage {
64    print <<'EOF';
65
66This script parses the CLDR locale files and turns them into a set of
67Perl modules.  It also generates the MANIFEST file.
68
69It takes the following arguments:
70
71  --dir      A directory containing CLDR XML files.  Required.
72
73  --file     Parse just the file with the given name.  For debugging.
74
75  --version  The CLDR version. Required when not debugging a single file.
76
77  --clean    Remove old generated modules (which may not be valid with
78             the latest CLDR data).
79
80  --quiet    Don't display any output while processing files.
81
82  --verbose  Spew lots of output while processing.
83
84  --help     What you are reading
85
86If the --file or --name options are specified, the MANIFEST will not
87be generated.
88
89EOF
90
91    exit;
92}
93
94sub require_version {
95    return if $opts{version};
96
97    warn <<'EOF';
98
99You must supply a CLDR version.
100
101EOF
102
103    exit;
104}
105
106sub clean {
107    for my $f ( File::Find::Rule->file->name('*.pm')
108        ->grep('This file is auto-generated')->in('lib') ) {
109        unlink $f or die "Cannot unlink $f: $!";
110    }
111}
112
113sub generate_from_cldr_xml {
114    my @ldml = read_all_files();
115    generate_pm_files(@ldml);
116    generate_catalog(@ldml);
117    generate_pm_file_pod($_) for @ldml;
118
119    print "\nAll done\n" unless $opts{quiet};
120}
121
122sub read_all_files {
123    my $dir = dir( $opts{dir} );
124
125    my @ldml;
126    while ( my $file = $dir->next() ) {
127        next unless -f $file;
128        next unless $file->basename() =~ /\.xml$/;
129        next if $opts{file} && $opts{file} ne $file->basename();
130
131        print "Reading $file\n" if $opts{verbose};
132
133        my $ldml = LDML->new_from_file($file);
134
135        # Any locale without this cannot be registered by
136        # DateTime::Locale.
137        next unless defined $ldml->en_language();
138
139        push @ldml, $ldml;
140    }
141
142    return sort { $a->id() cmp $b->id() } @ldml;
143}
144
145sub generate_pm_files {
146    my @ldml = @_;
147
148    print "\nGenerating PM files\n" if $opts{verbose};
149
150    for my $ldml ( sort @ldml ) {
151        if ( $opts{verbose} ) {
152            print sprintf(
153                <<"EOF", $ldml->id(), $ldml->parent_id(), $ldml->version(), $ldml->generation_date() );
154  %s
155    parent_id:       %s
156    version:         %s
157    generation date: %s
158
159EOF
160        }
161
162        generate_pm_file($ldml);
163    }
164}
165
166sub generate_pm_file {
167    my $ldml = shift;
168
169    my $pm_file = file( qw( lib DateTime Locale ), $ldml->id() . q{.pm} );
170    write_to_manifest($pm_file);
171
172    open my $fh, '>:utf8', $pm_file
173        or die "Cannot write to $pm_file: $!";
174
175    write_pm_header( $fh, $ldml );
176    write_pm_inheritance( $fh, $ldml );
177    write_pm_cldr_version($fh);
178    write_pm_subs( $fh, $ldml );
179    write_pm_glibc_subs( $fh, $ldml );
180    write_pm_footer( $fh, $ldml );
181}
182
183sub write_pm_header {
184    my $fh   = shift;
185    my $ldml = shift;
186
187    my $source_file = $ldml->source_file()->basename();
188    my $version     = $ldml->version();
189    my $date        = $ldml->generation_date();
190    my $id          = $ldml->id();
191
192    print {$fh} <<"EOF" or die "print failed: $!";
193###########################################################################
194#
195# This file is auto-generated by the Perl DateTime Suite locale
196# generator ($VERSION).  This code generator comes with the
197# DateTime::Locale distribution in the tools/ directory, and is called
198# $ScriptName.
199#
200# This file as generated from the CLDR XML locale data.  See the
201# LICENSE.cldr file included in this distribution for license details.
202#
203# This file was generated from the source file $source_file
204# The source file version number was $version, generated on
205# $date.
206#
207# Do not edit this file directly.
208#
209###########################################################################
210
211package DateTime::Locale::$id;
212
213use strict;
214use warnings;
215use utf8;
216
217EOF
218}
219
220sub write_pm_inheritance {
221    my $fh   = shift;
222    my $ldml = shift;
223
224    my $parent = $ldml->parent_id();
225
226    print {$fh} "use base 'DateTime::Locale::$parent';\n\n";
227}
228
229sub write_pm_cldr_version {
230    my $fh = shift;
231
232    my $cldr_version = q{"} . quotemeta( $opts{version} ) . q{"};
233
234    print {$fh} "sub cldr_version { return $cldr_version }\n\n";
235}
236
237sub write_pm_subs {
238    my $fh   = shift;
239    my $ldml = shift;
240
241    foreach my $attr ( sort { $a->name() cmp $b->name() }
242        LDML->meta()->get_all_attributes() ) {
243        next
244            unless $attr->name()
245                =~ /^(?:day_|month_|quarter_|am_pm|era_|date_|time_|datetime_|first_day_)/;
246
247        next if make_alias( $fh, $ldml, $attr->name() );
248
249        my $type = $attr->type_constraint();
250
251        if ( $type->is_a_type_of('ArrayRef') ) {
252            write_arrayref_sub( $fh, $ldml, $attr->name() );
253        }
254        elsif ( $type->is_a_type_of('HashRef') ) {
255            write_hashref_sub( $fh, $ldml, $attr->name() );
256        }
257        elsif ( $type->is_a_type_of('Str') ) {
258            write_string_sub( $fh, $ldml, $attr->name() );
259        }
260        elsif ( $type->is_a_type_of('Int') ) {
261            write_int_sub( $fh, $ldml, $attr->name() );
262        }
263        else {
264            die "Cannot handle type: " . $type->name();
265        }
266    }
267
268    for my $attr (qw( default_date_format_length default_time_format_length ))
269    {
270        my $def = $ldml->$attr();
271        next unless defined $def;
272
273        print {$fh} string_sub( q{_} . $attr,, $def );
274    }
275
276    write_available_format_subs( $fh, $ldml );
277}
278
279sub write_pm_glibc_subs {
280    my $fh   = shift;
281    my $ldml = shift;
282
283    my $file = _glibc_file_for_ldml($ldml);
284    return unless -f $file;
285
286    my %formats = _read_glibc_data($file);
287
288    for my $key ( grep { defined $formats{$_} } sort keys %formats ) {
289        print {$fh} string_sub( 'glibc_' . $key . '_format', $formats{$key} );
290    }
291}
292
293sub _glibc_file_for_ldml
294{
295    my $ldml = shift;
296
297    my $glibc_id = join '_', grep { defined } $ldml->language(), $ldml->territory();
298    if ( my $script = $ldml->en_script() ) {
299        $glibc_id .= '@' . lc $script;
300    }
301
302    # This ensures some sort of sanish fallback
303    $glibc_id = 'POSIX' if $ldml->id() eq 'root';
304
305    return "$glibc_dir/$glibc_id";
306}
307
308sub _read_glibc_data {
309    my $file = shift;
310
311    my $glibc = read_file($file);
312
313    return (
314        datetime => _extract_glibc_value( 'd_t_fmt',    $glibc ),
315        date     => _extract_glibc_value( 'd_fmt',      $glibc ),
316        time     => _extract_glibc_value( 't_fmt',      $glibc ),
317        time_12  => _extract_glibc_value( 't_fmt_ampm', $glibc ),
318        date_1   => _extract_glibc_value( 'date_fmt',   $glibc ),
319    );
320}
321
322sub _extract_glibc_value {
323    my $key = shift;
324    my $data = shift;
325
326    my ($val) = $data =~ /^\Q$key\E\s+"([^"]+?)"/m
327        or return undef;
328
329    $val =~ s/[\\\/]\n//g;
330
331    $val =~ s/\<U([A-F\d]+)\>/chr(hex($1))/eg;
332
333    return $val;
334}
335
336sub make_alias {
337    my $fh   = shift;
338    my $ldml = shift;
339    my $name = shift;
340
341    if ( $name =~ /stand_alone/ ) {
342        return make_stand_alone_alias( $fh, $ldml, $name );
343    }
344    elsif ( $name =~ /(?:abbreviated|narrow)/ ) {
345        return make_length_alias( $fh, $ldml, $name );
346    }
347
348}
349
350sub make_stand_alone_alias {
351    my $fh   = shift;
352    my $ldml = shift;
353    my $name = shift;
354
355    ( my $format = $name ) =~ s/stand_alone/format/;
356
357    return maybe_make_alias( $fh, $ldml, $name, $format );
358}
359
360sub make_length_alias {
361    my $fh   = shift;
362    my $ldml = shift;
363    my $name = shift;
364
365    # This isn't well documented (or really documented at all) in the
366    # LDML spec, but the example seem to suggest that for the narrow
367    # form, the format type should "inherit" from the stand-alone
368    # type if possible, rather than the abbreviated type.
369    #
370    # See
371    # http://www.unicode.org/cldr/data/charts/by_type/calendar-gregorian.day.html
372    # for examples of the expected output. Note that the format narrow
373    # days for English are inherited from its stand-alone narrow form,
374    # not the root locale.
375    if ( $name =~ /format_narrow/ ) {
376        ( my $to_name = $name ) =~ s/format/stand_alone/;
377
378        return 1
379            if maybe_make_alias( $fh, $ldml, $name, $to_name );
380    }
381
382    # It seems like the quarters should just inherit up the (Perl)
383    # inheritance chain, rather than from the next biggest size. See
384    # http://www.unicode.org/cldr/data/charts/by_type/calendar-gregorian.quarter.html
385    # for an example. Note that the English format narrow quarter is
386    # "1", not "Q1".
387    if ( $name =~ /quarter_(\w+)_narrow/ ) {
388        return;
389    }
390
391    ( my $to_name = $name );
392    $to_name =~ s/abbreviated/wide/;
393    $to_name =~ s/narrow/abbreviated/;
394
395    return maybe_make_alias( $fh, $ldml, $name, $to_name );
396}
397
398sub maybe_make_alias {
399    my $fh   = shift;
400    my $ldml = shift;
401    my $from = shift;
402    my $to   = shift;
403
404    my $val = $ldml->$from();
405
406    return if @{$val};
407
408    return unless $ldml->can($to);
409
410    my $to_val = $ldml->$to();
411
412    return unless @{$to_val};
413
414    write_alias_sub( $fh, $from, $to );
415
416    return 1;
417}
418
419sub write_alias_sub {
420    my $fh   = shift;
421    my $from = shift;
422    my $to   = shift;
423
424    print {$fh} <<"EOF";
425
426sub $from { \$_[0]->$to() }
427
428EOF
429}
430
431sub write_arrayref_sub {
432    my $fh   = shift;
433    my $ldml = shift;
434    my $name = shift;
435
436    my $arr = $ldml->$name();
437
438    return unless @{$arr};
439
440    print {$fh} arrayref_sub( $name, $arr );
441}
442
443sub arrayref_sub {
444    my $name = shift;
445    my $arr  = shift;
446
447    my $val = join ', ', map { q{"} . quotemeta($_) . q{"} } @{$arr};
448
449    return <<"EOF";
450{
451    my \$$name = [ $val ];
452    sub $name { return \$$name }
453}
454EOF
455}
456
457sub write_hashref_sub {
458    my $fh   = shift;
459    my $ldml = shift;
460    my $name = shift;
461
462    my $hash = $ldml->$name();
463
464    return unless keys %{$hash};
465
466    print {$fh} hashref_sub( $name, $hash );
467}
468
469sub hashref_sub {
470    my $name = shift;
471    my $hash = shift;
472
473    my $val = (
474        join ",\n",
475        map {
476            q{          "}
477                . quotemeta($_)
478                . q{" => "}
479                . quotemeta( $hash->{$_} ) . q{"}
480            }
481            sort keys %{$hash}
482    );
483
484    return <<"EOF";
485{
486    my \$$name =
487        {
488$val
489        };
490    sub $name { return \$$name }
491}
492
493EOF
494}
495
496sub write_string_sub {
497    my $fh   = shift;
498    my $ldml = shift;
499    my $name = shift;
500
501    my $str = $ldml->$name();
502
503    return unless defined $str;
504
505    print {$fh} string_sub( $name, $str );
506}
507
508sub string_sub {
509    my $name = shift;
510    my $str  = shift;
511
512    my $val = quotemeta $str;
513
514    return <<"EOF";
515{
516    my \$$name = "$val";
517    sub $name { return \$$name }
518}
519
520EOF
521}
522
523sub write_int_sub {
524    my $fh   = shift;
525    my $ldml = shift;
526    my $name = shift;
527
528    my $int = $ldml->$name();
529
530    return unless defined $int;
531
532    print {$fh} int_sub( $name, $int );
533}
534
535sub int_sub {
536    my $name = shift;
537    my $int  = shift;
538
539    return <<"EOF";
540{
541    my \$$name = $int;
542    sub $name { return \$$name }
543}
544
545EOF
546}
547
548sub write_available_format_subs {
549    my $fh   = shift;
550    my $ldml = shift;
551
552    my $formats = $ldml->available_formats();
553
554    return unless keys %{$formats};
555
556    for my $format ( sort keys %{$formats} ) {
557        my $sub_name = '_format_for_' . $format;
558
559        print {$fh} string_sub( $sub_name, $formats->{$format} );
560    }
561
562    my $avail = join ', ',
563        map { q{"} . quotemeta($_) . q{"} } keys %{$formats};
564
565    print {$fh} hashref_sub( '_available_formats', $formats );
566}
567
568sub write_pm_footer {
569    my $fh   = shift;
570    my $ldml = shift;
571
572    print {$fh} <<'EOF';
5731;
574
575__END__
576
577EOF
578}
579
580sub generate_catalog {
581    my @ldml = @_;
582
583    my $file = file(qw( lib DateTime Locale Catalog.pm ));
584
585    open my $fh, '>:utf8', $file
586        or die "Cannot write to $file: $!";
587
588    generate_catalog_code( $fh, \@ldml );
589    generate_catalog_pod( $fh, \@ldml );
590}
591
592sub generate_catalog_code {
593    my $fh   = shift;
594    my $ldml = shift;
595
596    my $cldr_version = q{"} . quotemeta( $opts{version} ) . q{"};
597
598    print {$fh} <<"EOF";
599###########################################################################
600#
601# This file is auto-generated by the Perl DateTime Suite time locale
602# generator ($VERSION).  This code generator comes with the
603# DateTime::Locale distribution in the tools/ directory, and is called
604# $ScriptName.
605#
606# This file as generated from the CLDR XML locale data.  See the
607# LICENSE.cldr file included in this distribution for license details.
608#
609# Do not edit this file directly.
610#
611###########################################################################
612
613package DateTime::Locale::Catalog;
614
615use strict;
616use warnings;
617use utf8;
618
619sub CLDRVersion { return $cldr_version }
620
621my \@Locales;
622sub Locales { return \@Locales }
623
624my \%Aliases;
625sub Aliases { return \%Aliases }
626
627EOF
628
629    print {$fh} '@Locales = (', "\n";
630
631    for my $l ( @{$ldml} ) {
632        print {$fh} catalog_data_for_locale($l);
633    }
634
635    print {$fh} q{);};
636    print {$fh} "\n\n";
637
638    print {$fh} catalog_data_for_aliases($ldml);
639
640    print {$fh} <<'EOF';
641
6421;
643
644__END__
645
646EOF
647}
648
649sub catalog_data_for_locale {
650    my $ldml = shift;
651
652    my $data = qq[    {\n];
653
654    foreach my $k (
655        qw( id
656        en_language en_script en_territory en_variant
657        native_language native_script native_territory native_variant
658        )
659        ) {
660        my $val = $ldml->$k();
661        next unless defined $val;
662
663        $data .= sprintf( q{      %-16s => "}, $k );
664        $data .= quotemeta($val);
665        $data .= q{",} . "\n";
666    }
667
668    $data .= qq[    },\n];
669
670    return $data;
671}
672
673sub catalog_data_for_aliases {
674    my $ldml = shift;
675
676    my %aliases = valid_aliases($ldml);
677
678    my $code = '%Aliases = (' . "\n";
679
680    for my $id ( sort keys %aliases ) {
681        $code .= qq{    $id => "} . quotemeta( $aliases{$id} ) . qq{",\n};
682    }
683
684    $code .= ");\n";
685
686    return $code;
687}
688
689sub generate_catalog_pod {
690    my $fh   = shift;
691    my $ldml = shift;
692
693    my $locales_in_pod = '';
694
695    for my $ldml ( @{$ldml} ) {
696        my @pieces = join ' ',
697            grep {defined}
698            map  { $ldml->$_() } qw( en_language en_territory en_variant );
699
700        my $script = $ldml->en_script();
701        push @pieces, "($script)" if defined $script;
702
703        $locales_in_pod
704            .= sprintf( " %-18s  %s\n", $ldml->id(), join ' ', @pieces );
705    }
706
707    my %aliases = valid_aliases($ldml);
708
709    my $aliases_in_pod = '';
710    foreach my $id ( sort keys %aliases ) {
711        $aliases_in_pod .= sprintf( " %-18s  %s\n", $id, $aliases{$id} );
712    }
713
714    print {$fh} <<"EOF";
715=head1 NAME
716
717DateTime::Locale::Catalog - Provides a list of all valid locale names
718
719=head1 SYNOPSIS
720
721See DateTime::Locale for usage details.
722
723=head1 DESCRIPTION
724
725This module contains a list of all known locales.
726
727=head1 LOCALES
728
729Any method taking locale id or name arguments should use one of the
730values listed below. Ids and names are case sensitive. The id starts
731with the ISO639-1 language code, and may also include information
732identifying any or all of territory, script, or variant.
733
734Always select the closest matching locale - for example, French
735Canadians would choose fr_CA over fr - and B<always> use locale ids in
736preference to names; locale ids offer greater compatibility when using
737localized third party modules.
738
739The available locales are:
740
741 Locale id           Locale name
742 ==================================================
743$locales_in_pod
744
745There are also many aliases available, mostly for three-letter
746(ISO639-2) language codes, these are:
747
748 Locale id           Is an alias for
749 ==================================================
750$aliases_in_pod
751
752=head1 SUPPORT
753
754See L<DateTime::Locale>.
755
756=head1 AUTHOR
757
758Dave Rolsky <autarch\@urth.org>
759
760=head1 COPYRIGHT
761
762Copyright (c) 2008 David Rolsky. All rights reserved. This program is
763free software; you can redistribute it and/or modify it under the same
764terms as Perl itself.
765
766This module was generated from data provided by the CLDR project, see
767the LICENSE.cldr in this distribution for details on the CLDR data's
768license.
769
770=cut
771EOF
772}
773
774{
775    my %aliases;
776
777    sub valid_aliases {
778        return %aliases if keys %aliases;
779
780        my $ldml = shift;
781
782        my %ids = map { $_->id() => 1 } @{$ldml};
783
784        for my $ldml ( @{$ldml} ) {
785            my $three = iso639_2_to_3( $ldml->language() );
786
787            next unless defined $three;
788
789            my $three_id = (
790                join '_',
791                grep {defined}
792                    $three, $ldml->territory(), $ldml->script(),
793                $ldml->variant()
794            );
795
796            next if $ids{$three_id};
797
798            $aliases{$three_id} = $ldml->id();
799        }
800
801        %aliases = ( %aliases, %{ LDML->Aliases() } );
802
803        return %aliases;
804    }
805}
806
807{
808    my %iso639_map;
809
810    sub iso639_2_to_3 {
811        my $two = shift;
812
813        _build_iso639_map() unless keys %iso639_map;
814
815        return $iso639_map{$two};
816    }
817
818    sub _build_iso639_map {
819        while ( defined( my $line = <DATA> ) ) {
820            next unless $line =~ /\S/;
821            next if $line =~ /^\#/;
822
823            my ( $three, undef, $two, undef, undef ) = split /\|/, $line;
824
825            next unless defined $two;
826
827            $iso639_map{$two} = $three;
828        }
829    }
830}
831
832sub generate_pm_file_pod {
833    my $ldml = shift;
834
835    my $pm_file = file( qw( lib DateTime Locale ), $ldml->id() . q{.pm} );
836
837    require DateTime::Locale;
838
839    my $locale = DateTime::Locale->load( $ldml->id() );
840
841    open my $fh, '>>:utf8', $pm_file
842        or die "Cannot append to $pm_file: $!";
843
844    write_pm_file_pod_header( $fh, $locale, $ldml );
845
846    print {$fh} pod_for_days($locale);
847    print {$fh} pod_for_months($locale);
848    print {$fh} pod_for_quarters($locale);
849    print {$fh} pod_for_eras($locale);
850    print {$fh} pod_for_formats($locale);
851    print {$fh} pod_for_misc($locale);
852    print {$fh} pod_footer($locale);
853}
854
855sub write_pm_file_pod_header {
856    my $fh     = shift;
857    my $locale = shift;
858    my $ldml   = shift;
859
860    my $class = ref $locale;
861    my $id    = $locale->id();
862    my $name  = $locale->name();
863
864    print {$fh} <<"EOF";
865
866=pod
867
868=encoding utf8
869
870=head1 NAME
871
872$class
873
874=head1 SYNOPSIS
875
876  use DateTime;
877
878  my \$dt = DateTime->now( locale => '$id' );
879  print \$dt->month_name();
880
881=head1 DESCRIPTION
882
883This is the DateTime locale package for $name.
884
885=head1 DATA
886
887EOF
888
889    if ( $id ne 'root' ) {
890        print {$fh} 'This locale inherits from the L<DateTime::Locale::'
891            . $ldml->parent_id()
892            . "> locale.\n\n";
893    }
894
895    print {$fh} "It contains the following data.\n\n";
896}
897
898sub pod_for_days {
899    my $locale = shift;
900
901    return pod_for_variations( $locale, 'day' );
902}
903
904sub pod_for_months {
905    my $locale = shift;
906
907    return pod_for_variations( $locale, 'month' );
908}
909
910sub pod_for_quarters {
911    my $locale = shift;
912
913    return pod_for_variations( $locale, 'quarter' );
914}
915
916sub pod_for_eras {
917    my $locale = shift;
918
919    return pod_for_variations( $locale, 'era' );
920}
921
922sub pod_for_variations {
923    my $locale = shift;
924    my $thing  = shift;
925
926    my $pod = '';
927
928    my $pl = PL_N($thing);
929    $pod .= "=head2 \u$pl\n\n";
930
931    my @forms = $thing eq 'era' ? ('') : ( 'format', 'stand_alone' );
932
933    for my $form (@forms) {
934        for my $size (qw( wide abbreviated narrow )) {
935            my $meth
936                = $form
937                ? $thing . q{_} . $form . q{_} . $size
938                : $thing . q{_} . $size;
939
940            next unless $locale->can($meth);
941
942            my $head = ucfirst $size;
943
944            if ($form) {
945                ( my $f = $form ) =~ s/_/-/;
946                $head .= " ($f)";
947            }
948
949            $pod .= "=head3 $head\n\n";
950
951            for my $val ( @{ $locale->$meth() } ) {
952                $pod .= "  $val\n";
953            }
954
955            $pod .= "\n";
956        }
957    }
958
959    return $pod;
960}
961
962sub pod_for_formats {
963    my $locale = shift;
964
965    unless ( DateTime->can('new') ) {
966        eval "use DateTime 0.43";
967        die $@ if $@;
968    }
969
970    my @dts = (
971        DateTime->new(
972            year      => 2008,
973            month     => 2,
974            day       => 5,
975            hour      => 18,
976            minute    => 30,
977            second    => 30,
978            locale    => $locale,
979            time_zone => 'UTC',
980        ),
981        DateTime->new(
982            year       => 1995,
983            month      => 12,
984            day        => 22,
985            hour       => 9,
986            minute     => 5,
987            second     => 2,
988            nanosecond => 505_196,
989            locale     => $locale,
990            time_zone  => 'UTC',
991        ),
992        DateTime->new(
993            year      => -10,
994            month     => 9,
995            day       => 15,
996            hour      => 4,
997            minute    => 44,
998            second    => 23,
999            locale    => $locale,
1000            time_zone => 'UTC',
1001        ),
1002    );
1003
1004    return pod_for_standard_formats( $locale, \@dts )
1005        . pod_for_available_formats( $locale, \@dts );
1006}
1007
1008sub pod_for_standard_formats {
1009    my $locale = shift;
1010    my $dts    = shift;
1011
1012    my $pod = '';
1013
1014    for my $type (qw( date time datetime )) {
1015        $pod .= "=head2 \u$type Formats\n\n";
1016
1017        for my $length (qw( full long medium short default )) {
1018            $pod .= "=head3 \u$length\n\n";
1019
1020            my $meth = $type . q{_} . 'format' . q{_} . $length;
1021
1022            for my $dt ( @{$dts} ) {
1023                $pod .= sprintf(
1024                    '  %20s = %s',
1025                    $dt->iso8601(),
1026                    $dt->format_cldr( $locale->$meth() ),
1027                );
1028                $pod .= "\n";
1029            }
1030
1031            $pod .= "\n";
1032        }
1033    }
1034
1035    return $pod;
1036}
1037
1038sub pod_for_available_formats {
1039    my $locale = shift;
1040    my $dts    = shift;
1041
1042    my $pod = '';
1043
1044    $pod .= "=head2 Available Formats\n\n";
1045
1046    for my $format ( sort { lc $a cmp lc $b or $a cmp $b }
1047        $locale->available_formats() ) {
1048        my $cldr = $locale->format_for($format);
1049
1050        $pod .= "=head3 $format ($cldr)\n\n";
1051
1052        for my $dt ( @{$dts} ) {
1053            $pod .= sprintf(
1054                '  %20s = %s',
1055                $dt->iso8601(),
1056                $dt->format_cldr($cldr),
1057            );
1058
1059            $pod .= "\n";
1060        }
1061
1062        $pod .= "\n";
1063    }
1064
1065    return $pod;
1066}
1067
1068sub pod_for_misc {
1069    my $locale = shift;
1070
1071    my $pod = "=head2 Miscellaneous\n\n";
1072
1073    $pod .= "=head3 Prefers 24 hour time?\n\n";
1074
1075    $pod .= $locale->prefers_24_hour_time() ? 'Yes' : 'No';
1076    $pod .= "\n\n";
1077
1078    $pod .= "=head3 Local first day of the week\n\n";
1079
1080    $pod .= $locale->day_format_wide()->[ $locale->first_day_of_week() - 1 ];
1081    $pod .= "\n\n";
1082
1083    return $pod;
1084}
1085
1086sub pod_footer {
1087    return <<'EOF';
1088
1089=head1 SUPPORT
1090
1091See L<DateTime::Locale>.
1092
1093=head1 AUTHOR
1094
1095Dave Rolsky <autarch@urth.org>
1096
1097=head1 COPYRIGHT
1098
1099Copyright (c) 2008 David Rolsky. All rights reserved. This program is
1100free software; you can redistribute it and/or modify it under the same
1101terms as Perl itself.
1102
1103This module was generated from data provided by the CLDR project, see
1104the LICENSE.cldr in this distribution for details on the CLDR data's
1105license.
1106
1107=cut
1108EOF
1109}
1110
1111sub write_to_manifest {
1112    return if $opts{file};
1113
1114    my $fh = _manifest_handle();
1115
1116    print {$fh} $_, "\n" for @_;
1117}
1118
1119{
1120    my $fh;
1121
1122    sub _manifest_handle {
1123        return $fh if defined $fh;
1124
1125        copy( 'MANIFEST.base', 'MANIFEST' );
1126        open $fh, '>>', 'MANIFEST' or die "Cannot write to MANIFEST: $!";
1127
1128        return $fh;
1129    }
1130}
1131
1132main();
1133
1134__DATA__
1135# This is the ISO-639 data downloaded from http://www.loc.gov/standards/iso639-2/ISO-639-2_utf-8.txt
1136# The version in the Locale::Codes distro is way out of date.
1137aar||aa|Afar|afar
1138abk||ab|Abkhazian|abkhaze
1139ace|||Achinese|aceh
1140ach|||Acoli|acoli
1141ada|||Adangme|adangme
1142ady|||Adyghe; Adygei|adyghé
1143afa|||Afro-Asiatic languages|afro-asiatiques, langues
1144afh|||Afrihili|afrihili
1145afr||af|Afrikaans|afrikaans
1146ain|||Ainu|aïnou
1147aka||ak|Akan|akan
1148akk|||Akkadian|akkadien
1149alb|sqi|sq|Albanian|albanais
1150ale|||Aleut|aléoute
1151alg|||Algonquian languages|algonquines, langues
1152alt|||Southern Altai|altai du Sud
1153amh||am|Amharic|amharique
1154ang|||English, Old (ca.450-1100)|anglo-saxon (ca.450-1100)
1155anp|||Angika|angika
1156apa|||Apache languages|apaches, langues
1157ara||ar|Arabic|arabe
1158arc|||Official Aramaic (700-300 BCE); Imperial Aramaic (700-300 BCE)|araméen d'empire (700-300 BCE)
1159arg||an|Aragonese|aragonais
1160arm|hye|hy|Armenian|arménien
1161arn|||Mapudungun; Mapuche|mapudungun; mapuche; mapuce
1162arp|||Arapaho|arapaho
1163art|||Artificial languages|artificielles, langues
1164arw|||Arawak|arawak
1165asm||as|Assamese|assamais
1166ast|||Asturian; Bable; Leonese; Asturleonese|asturien; bable; léonais; asturoléonais
1167ath|||Athapascan languages|athapascanes, langues
1168aus|||Australian languages|australiennes, langues
1169ava||av|Avaric|avar
1170ave||ae|Avestan|avestique
1171awa|||Awadhi|awadhi
1172aym||ay|Aymara|aymara
1173aze||az|Azerbaijani|azéri
1174bad|||Banda languages|banda, langues
1175bai|||Bamileke languages|bamiléké, langues
1176bak||ba|Bashkir|bachkir
1177bal|||Baluchi|baloutchi
1178bam||bm|Bambara|bambara
1179ban|||Balinese|balinais
1180baq|eus|eu|Basque|basque
1181bas|||Basa|basa
1182bat|||Baltic languages|baltes, langues
1183bej|||Beja; Bedawiyet|bedja
1184bel||be|Belarusian|biélorusse
1185bem|||Bemba|bemba
1186ben||bn|Bengali|bengali
1187ber|||Berber languages|berbères, langues
1188bho|||Bhojpuri|bhojpuri
1189bih||bh|Bihari|bihari
1190bik|||Bikol|bikol
1191bin|||Bini; Edo|bini; edo
1192bis||bi|Bislama|bichlamar
1193bla|||Siksika|blackfoot
1194bnt|||Bantu (Other)|bantoues, autres langues
1195bos||bs|Bosnian|bosniaque
1196bra|||Braj|braj
1197bre||br|Breton|breton
1198btk|||Batak languages|batak, langues
1199bua|||Buriat|bouriate
1200bug|||Buginese|bugi
1201bul||bg|Bulgarian|bulgare
1202bur|mya|my|Burmese|birman
1203byn|||Blin; Bilin|blin; bilen
1204cad|||Caddo|caddo
1205cai|||Central American Indian languages|amérindiennes de L'Amérique centrale, langues
1206car|||Galibi Carib|karib; galibi; carib
1207cat||ca|Catalan; Valencian|catalan; valencien
1208cau|||Caucasian languages|caucasiennes, langues
1209ceb|||Cebuano|cebuano
1210cel|||Celtic languages|celtiques, langues; celtes, langues
1211cha||ch|Chamorro|chamorro
1212chb|||Chibcha|chibcha
1213che||ce|Chechen|tchétchène
1214chg|||Chagatai|djaghataï
1215chi|zho|zh|Chinese|chinois
1216chk|||Chuukese|chuuk
1217chm|||Mari|mari
1218chn|||Chinook jargon|chinook, jargon
1219cho|||Choctaw|choctaw
1220chp|||Chipewyan; Dene Suline|chipewyan
1221chr|||Cherokee|cherokee
1222chu||cu|Church Slavic; Old Slavonic; Church Slavonic; Old Bulgarian; Old Church Slavonic|slavon d'église; vieux slave; slavon liturgique; vieux bulgare
1223chv||cv|Chuvash|tchouvache
1224chy|||Cheyenne|cheyenne
1225cmc|||Chamic languages|chames, langues
1226cop|||Coptic|copte
1227cor||kw|Cornish|cornique
1228cos||co|Corsican|corse
1229cpe|||Creoles and pidgins, English based|créoles et pidgins basés sur l'anglais
1230cpf|||Creoles and pidgins, French-based |créoles et pidgins basés sur le français
1231cpp|||Creoles and pidgins, Portuguese-based |créoles et pidgins basés sur le portugais
1232cre||cr|Cree|cree
1233crh|||Crimean Tatar; Crimean Turkish|tatar de Crimé
1234crp|||Creoles and pidgins |créoles et pidgins
1235csb|||Kashubian|kachoube
1236cus|||Cushitic languages|couchitiques, langues
1237cze|ces|cs|Czech|tchèque
1238dak|||Dakota|dakota
1239dan||da|Danish|danois
1240dar|||Dargwa|dargwa
1241day|||Land Dayak languages|dayak, langues
1242del|||Delaware|delaware
1243den|||Slave (Athapascan)|esclave (athapascan)
1244dgr|||Dogrib|dogrib
1245din|||Dinka|dinka
1246div||dv|Divehi; Dhivehi; Maldivian|maldivien
1247doi|||Dogri|dogri
1248dra|||Dravidian languages|dravidiennes, langues
1249dsb|||Lower Sorbian|bas-sorabe
1250dua|||Duala|douala
1251dum|||Dutch, Middle (ca.1050-1350)|néerlandais moyen (ca. 1050-1350)
1252dut|nld|nl|Dutch; Flemish|néerlandais; flamand
1253dyu|||Dyula|dioula
1254dzo||dz|Dzongkha|dzongkha
1255efi|||Efik|efik
1256egy|||Egyptian (Ancient)gyptien
1257eka|||Ekajuk|ekajuk
1258elx|||Elamitelamite
1259eng||en|English|anglais
1260enm|||English, Middle (1100-1500)|anglais moyen (1100-1500)
1261epo||eo|Esperanto|espéranto
1262est||et|Estonian|estonien
1263ewe||ee|Ewe|éwé
1264ewo|||Ewondowondo
1265fan|||Fang|fang
1266fao||fo|Faroese|féroïen
1267fat|||Fanti|fanti
1268fij||fj|Fijian|fidjien
1269fil|||Filipino; Pilipino|filipino; pilipino
1270fin||fi|Finnish|finnois
1271fiu|||Finno-Ugrian languages|finno-ougriennes, langues
1272fon|||Fon|fon
1273fre|fra|fr|French|français
1274frm|||French, Middle (ca.1400-1600)|français moyen (1400-1600)
1275fro|||French, Old (842-ca.1400)|français ancien (842-ca.1400)
1276frr|||Northern Frisian|frison septentrional
1277frs|||Eastern Frisian|frison oriental
1278fry||fy|Western Frisian|frison occidental
1279ful||ff|Fulah|peul
1280fur|||Friulian|frioulan
1281gaa|||Ga|ga
1282gay|||Gayo|gayo
1283gba|||Gbaya|gbaya
1284gem|||Germanic languages|germaniques, langues
1285geo|kat|ka|Georgian|géorgien
1286ger|deu|de|German|allemand
1287gez|||Geez|guèze
1288gil|||Gilbertese|kiribati
1289gla||gd|Gaelic; Scottish Gaelic|gaélique; gaélique écossais
1290gle||ga|Irish|irlandais
1291glg||gl|Galician|galicien
1292glv||gv|Manx|manx; mannois
1293gmh|||German, Middle High (ca.1050-1500)|allemand, moyen haut (ca. 1050-1500)
1294goh|||German, Old High (ca.750-1050)|allemand, vieux haut (ca. 750-1050)
1295gon|||Gondi|gond
1296gor|||Gorontalo|gorontalo
1297got|||Gothic|gothique
1298grb|||Grebo|grebo
1299grc|||Greek, Ancient (to 1453)|grec ancien (jusqu'à 1453)
1300gre|ell|el|Greek, Modern (1453-)|grec moderne (après 1453)
1301grn||gn|Guarani|guarani
1302gsw|||Swiss German; Alemannic; Alsatian|suisse alémanique; alémanique; alsacien
1303guj||gu|Gujarati|goudjrati
1304gwi|||Gwich'in|gwich'in
1305hai|||Haida|haida
1306hat||ht|Haitian; Haitian Creole|haïtien; créole haïtien
1307hau||ha|Hausa|haoussa
1308haw|||Hawaiian|hawaïen
1309heb||he|Hebrew|hébreu
1310her||hz|Herero|herero
1311hil|||Hiligaynon|hiligaynon
1312him|||Himachali|himachali
1313hin||hi|Hindi|hindi
1314hit|||Hittite|hittite
1315hmn|||Hmong|hmong
1316hmo||ho|Hiri Motu|hiri motu
1317hrv||hr|Croatian|croate
1318hsb|||Upper Sorbian|haut-sorabe
1319hun||hu|Hungarian|hongrois
1320hup|||Hupa|hupa
1321iba|||Iban|iban
1322ibo||ig|Igbo|igbo
1323ice|isl|is|Icelandic|islandais
1324ido||io|Ido|ido
1325iii||ii|Sichuan Yi; Nuosu|yi de Sichuan
1326ijo|||Ijo languages|ijo, langues
1327iku||iu|Inuktitut|inuktitut
1328ile||ie|Interlingue; Occidental|interlingue
1329ilo|||Iloko|ilocano
1330ina||ia|Interlingua (International Auxiliary Language Association)|interlingua (langue auxiliaire internationale)
1331inc|||Indic languages|indo-aryennes, langues
1332ind||id|Indonesian|indonésien
1333ine|||Indo-European languages|indo-européennes, langues
1334inh|||Ingush|ingouche
1335ipk||ik|Inupiaq|inupiaq
1336ira|||Iranian languages|iraniennes, langues
1337iro|||Iroquoian languages|iroquoises, langues
1338ita||it|Italian|italien
1339jav||jv|Javanese|javanais
1340jbo|||Lojban|lojban
1341jpn||ja|Japanese|japonais
1342jpr|||Judeo-Persian|judéo-persan
1343jrb|||Judeo-Arabic|judéo-arabe
1344kaa|||Kara-Kalpak|karakalpak
1345kab|||Kabyle|kabyle
1346kac|||Kachin; Jingpho|kachin; jingpho
1347kal||kl|Kalaallisut; Greenlandic|groenlandais
1348kam|||Kamba|kamba
1349kan||kn|Kannada|kannada
1350kar|||Karen languages|karen, langues
1351kas||ks|Kashmiri|kashmiri
1352kau||kr|Kanuri|kanouri
1353kaw|||Kawi|kawi
1354kaz||kk|Kazakh|kazakh
1355kbd|||Kabardian|kabardien
1356kha|||Khasi|khasi
1357khi|||Khoisan languages|khoïsan, langues
1358khm||km|Central Khmer|khmer central
1359kho|||Khotanese; Sakan|khotanais; sakan
1360kik||ki|Kikuyu; Gikuyu|kikuyu
1361kin||rw|Kinyarwanda|rwanda
1362kir||ky|Kirghiz; Kyrgyz|kirghiz
1363kmb|||Kimbundu|kimbundu
1364kok|||Konkani|konkani
1365kom||kv|Komi|kom
1366kon||kg|Kongo|kongo
1367kor||ko|Korean|coréen
1368kos|||Kosraean|kosrae
1369kpe|||Kpelle|kpellé
1370krc|||Karachay-Balkar|karatchai balkar
1371krl|||Karelian|carélien
1372kro|||Kru languages|krou, langues
1373kru|||Kurukh|kurukh
1374kua||kj|Kuanyama; Kwanyama|kuanyama; kwanyama
1375kum|||Kumyk|koumyk
1376kur||ku|Kurdish|kurde
1377kut|||Kutenai|kutenai
1378lad|||Ladino|judéo-espagnol
1379lah|||Lahnda|lahnda
1380lam|||Lamba|lamba
1381lao||lo|Lao|lao
1382lat||la|Latin|latin
1383lav||lv|Latvian|letton
1384lez|||Lezghian|lezghien
1385lim||li|Limburgan; Limburger; Limburgish|limbourgeois
1386lin||ln|Lingala|lingala
1387lit||lt|Lithuanian|lituanien
1388lol|||Mongo|mongo
1389loz|||Lozi|lozi
1390ltz||lb|Luxembourgish; Letzeburgesch|luxembourgeois
1391lua|||Luba-Lulua|luba-lulua
1392lub||lu|Luba-Katanga|luba-katanga
1393lug||lg|Ganda|ganda
1394lui|||Luiseno|luiseno
1395lun|||Lunda|lunda
1396luo|||Luo (Kenya and Tanzania)|luo (Kenya et Tanzanie)
1397lus|||Lushai|lushai
1398mac|mkd|mk|Macedonian|macédonien
1399mad|||Madurese|madourais
1400mag|||Magahi|magahi
1401mah||mh|Marshallese|marshall
1402mai|||Maithili|maithili
1403mak|||Makasar|makassar
1404mal||ml|Malayalam|malayalam
1405man|||Mandingo|mandingue
1406mao|mri|mi|Maori|maori
1407map|||Austronesian languages|austronésiennes, langues
1408mar||mr|Marathi|marathe
1409mas|||Masai|massaï
1410may|msa|ms|Malay|malais
1411mdf|||Moksha|moksa
1412mdr|||Mandar|mandar
1413men|||Mende|mendé
1414mga|||Irish, Middle (900-1200)|irlandais moyen (900-1200)
1415mic|||Mi'kmaq; Micmac|mi'kmaq; micmac
1416min|||Minangkabau|minangkabau
1417mis|||Uncoded languages|langues non codées
1418mkh|||Mon-Khmer languages|môn-khmer, langues
1419mlg||mg|Malagasy|malgache
1420mlt||mt|Maltese|maltais
1421mnc|||Manchu|mandchou
1422mni|||Manipuri|manipuri
1423mno|||Manobo languages|manobo, langues
1424moh|||Mohawk|mohawk
1425mon||mn|Mongolian|mongol
1426mos|||Mossi|moré
1427mul|||Multiple languages|multilingue
1428mun|||Munda languages|mounda, langues
1429mus|||Creek|muskogee
1430mwl|||Mirandese|mirandais
1431mwr|||Marwari|marvari
1432myn|||Mayan languages|maya, langues
1433myv|||Erzya|erza
1434nah|||Nahuatl languages|nahuatl, langues
1435nai|||North American Indian languages|nord-amérindiennes, langues
1436nap|||Neapolitan|napolitain
1437nau||na|Nauru|nauruan
1438nav||nv|Navajo; Navaho|navaho
1439nbl||nr|Ndebele, South; South Ndebele|ndébélé du Sud
1440nde||nd|Ndebele, North; North Ndebele|ndébélé du Nord
1441ndo||ng|Ndonga|ndonga
1442nds|||Low German; Low Saxon; German, Low; Saxon, Low|bas allemand; bas saxon; allemand, bas; saxon, bas
1443nep||ne|Nepali|népalais
1444new|||Nepal Bhasa; Newari|nepal bhasa; newari
1445nia|||Nias|nias
1446nic|||Niger-Kordofanian languages|nigéro-kordofaniennes, langues
1447niu|||Niuean|niué
1448nno||nn|Norwegian Nynorsk; Nynorsk, Norwegian|norvégien nynorsk; nynorsk, norvégien
1449nob||nb|Bokmål, Norwegian; Norwegian Bokmål|norvégien bokmål
1450nog|||Nogai|nogaï; nogay
1451non|||Norse, Old|norrois, vieux
1452nor||no|Norwegian|norvégien
1453nqo|||N'Ko|n'ko
1454nso|||Pedi; Sepedi; Northern Sotho|pedi; sepedi; sotho du Nord
1455nub|||Nubian languages|nubiennes, langues
1456nwc|||Classical Newari; Old Newari; Classical Nepal Bhasa|newari classique
1457nya||ny|Chichewa; Chewa; Nyanja|chichewa; chewa; nyanja
1458nym|||Nyamwezi|nyamwezi
1459nyn|||Nyankole|nyankolé
1460nyo|||Nyoro|nyoro
1461nzi|||Nzima|nzema
1462oci||oc|Occitan (post 1500); Provençal|occitan (après 1500); provençal
1463oji||oj|Ojibwa|ojibwa
1464ori||or|Oriya|oriya
1465orm||om|Oromo|galla
1466osa|||Osage|osage
1467oss||os|Ossetian; Ossetic|ossète
1468ota|||Turkish, Ottoman (1500-1928)|turc ottoman (1500-1928)
1469oto|||Otomian languages|otomi, langues
1470paa|||Papuan languages|papoues, langues
1471pag|||Pangasinan|pangasinan
1472pal|||Pahlavi|pahlavi
1473pam|||Pampanga; Kapampangan|pampangan
1474pan||pa|Panjabi; Punjabi|pendjabi
1475pap|||Papiamento|papiamento
1476pau|||Palauan|palau
1477peo|||Persian, Old (ca.600-400 B.C.)|perse, vieux (ca. 600-400 av. J.-C.)
1478per|fas|fa|Persian|persan
1479phi|||Philippine languages|philippines, langues
1480phn|||Phoenician|phénicien
1481pli||pi|Pali|pali
1482pol||pl|Polish|polonais
1483pon|||Pohnpeian|pohnpei
1484por||pt|Portuguese|portugais
1485pra|||Prakrit languages|prâkrit, langues
1486pro|||Provençal, Old (to 1500)|provençal ancien (jusqu'à 1500)
1487pus||ps|Pushto; Pashto|pachto
1488qaa-qtz|||Reserved for local use|réservée à l'usage local
1489que||qu|Quechua|quechua
1490raj|||Rajasthani|rajasthani
1491rap|||Rapanui|rapanui
1492rar|||Rarotongan; Cook Islands Maori|rarotonga; maori des îles Cook
1493roa|||Romance languages|romanes, langues
1494roh||rm|Romansh|romanche
1495rom|||Romany|tsigane
1496rum|ron|ro|Romanian; Moldavian; Moldovan|roumain; moldave
1497run||rn|Rundi|rundi
1498rup|||Aromanian; Arumanian; Macedo-Romanian|aroumain; macédo-roumain
1499rus||ru|Russian|russe
1500sad|||Sandawe|sandawe
1501sag||sg|Sango|sango
1502sah|||Yakut|iakoute
1503sai|||South American Indian (Other)|indiennes d'Amérique du Sud, autres langues
1504sal|||Salishan languages|salishennes, langues
1505sam|||Samaritan Aramaic|samaritain
1506san||sa|Sanskrit|sanskrit
1507sas|||Sasak|sasak
1508sat|||Santali|santal
1509scn|||Sicilian|sicilien
1510sco|||Scotscossais
1511sel|||Selkup|selkoupe
1512sem|||Semitic languages|sémitiques, langues
1513sga|||Irish, Old (to 900)|irlandais ancien (jusqu'à 900)
1514sgn|||Sign Languages|langues des signes
1515shn|||Shan|chan
1516sid|||Sidamo|sidamo
1517sin||si|Sinhala; Sinhalese|singhalais
1518sio|||Siouan languages|sioux, langues
1519sit|||Sino-Tibetan languages|sino-tibétaines, langues
1520sla|||Slavic languages|slaves, langues
1521slo|slk|sk|Slovak|slovaque
1522slv||sl|Slovenian|slovène
1523sma|||Southern Sami|sami du Sud
1524sme||se|Northern Sami|sami du Nord
1525smi|||Sami languages|sames, langues
1526smj|||Lule Sami|sami de Lule
1527smn|||Inari Sami|sami d'Inari
1528smo||sm|Samoan|samoan
1529sms|||Skolt Sami|sami skolt
1530sna||sn|Shona|shona
1531snd||sd|Sindhi|sindhi
1532snk|||Soninke|soninké
1533sog|||Sogdian|sogdien
1534som||so|Somali|somali
1535son|||Songhai languages|songhai, langues
1536sot||st|Sotho, Southern|sotho du Sud
1537spa||es|Spanish; Castilian|espagnol; castillan
1538srd||sc|Sardinian|sarde
1539srn|||Sranan Tongo|sranan tongo
1540srp||sr|Serbian|serbe
1541srr|||Serer|sérère
1542ssa|||Nilo-Saharan languages|nilo-sahariennes, langues
1543ssw||ss|Swati|swati
1544suk|||Sukuma|sukuma
1545sun||su|Sundanese|soundanais
1546sus|||Susu|soussou
1547sux|||Sumerian|sumérien
1548swa||sw|Swahili|swahili
1549swe||sv|Swedish|suédois
1550syc|||Classical Syriac|syriaque classique
1551syr|||Syriac|syriaque
1552tah||ty|Tahitian|tahitien
1553tai|||Tai languages|tai, langues
1554tam||ta|Tamil|tamoul
1555tat||tt|Tatar|tatar
1556tel||te|Telugu|télougou
1557tem|||Timne|temne
1558ter|||Tereno|tereno
1559tet|||Tetum|tetum
1560tgk||tg|Tajik|tadjik
1561tgl||tl|Tagalog|tagalog
1562tha||th|Thai|thaï
1563tib|bod|bo|Tibetan|tibétain
1564tig|||Tigre|tigré
1565tir||ti|Tigrinya|tigrigna
1566tiv|||Tiv|tiv
1567tkl|||Tokelau|tokelau
1568tlh|||Klingon; tlhIngan-Hol|klingon
1569tli|||Tlingit|tlingit
1570tmh|||Tamashek|tamacheq
1571tog|||Tonga (Nyasa)|tonga (Nyasa)
1572ton||to|Tonga (Tonga Islands)|tongan les Tonga)
1573tpi|||Tok Pisin|tok pisin
1574tsi|||Tsimshian|tsimshian
1575tsn||tn|Tswana|tswana
1576tso||ts|Tsonga|tsonga
1577tuk||tk|Turkmen|turkmène
1578tum|||Tumbuka|tumbuka
1579tup|||Tupi languages|tupi, langues
1580tur||tr|Turkish|turc
1581tut|||Altaic languages|altaïques, langues
1582tvl|||Tuvalu|tuvalu
1583twi||tw|Twi|twi
1584tyv|||Tuvinian|touva
1585udm|||Udmurt|oudmourte
1586uga|||Ugaritic|ougaritique
1587uig||ug|Uighur; Uyghur|ouïgour
1588ukr||uk|Ukrainian|ukrainien
1589umb|||Umbundu|umbundu
1590und|||Undetermined|indéterminée
1591urd||ur|Urdu|ourdou
1592uzb||uz|Uzbek|ouszbek
1593vai|||Vai|vaï
1594ven||ve|Venda|venda
1595vie||vi|Vietnamese|vietnamien
1596vol||vo|Volapük|volapük
1597vot|||Votic|vote
1598wak|||Wakashan languages|wakashanes, langues
1599wal|||Walamo|walamo
1600war|||Waray|waray
1601was|||Washo|washo
1602wel|cym|cy|Welsh|gallois
1603wen|||Sorbian languages|sorabes, langues
1604wln||wa|Walloon|wallon
1605wol||wo|Wolof|wolof
1606xal|||Kalmyk; Oirat|kalmouk; oïrat
1607xho||xh|Xhosa|xhosa
1608yao|||Yao|yao
1609yap|||Yapese|yapois
1610yid||yi|Yiddish|yiddish
1611yor||yo|Yoruba|yoruba
1612ypk|||Yupik languages|yupik, langues
1613zap|||Zapotec|zapotèque
1614zbl|||Blissymbols; Blissymbolics; Bliss|symboles Bliss; Bliss
1615zen|||Zenaga|zenaga
1616zha||za|Zhuang; Chuang|zhuang; chuang
1617znd|||Zande languages|zandé, langues
1618zul||zu|Zulu|zoulou
1619zun|||Zuni|zuni
1620zxx|||No linguistic content; Not applicable|pas de contenu linguistique; non applicable
1621zza|||Zaza; Dimili; Dimli; Kirdki; Kirmanjki; Zazaki|zaza; dimili; dimli; kirdki; kirmanjki; zazaki
1622