Skip to content

Instantly share code, notes, and snippets.

@gardejo
Created August 25, 2011 17:56
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save gardejo/1171301 to your computer and use it in GitHub Desktop.
Save gardejo/1171301 to your computer and use it in GitHub Desktop.
Reorganization of MooseX::Types::Locale::Language

NAME

MooseX::Types::Locale::Codes - Locale::Codes related type constraints and coercions for Moose

VERSION

This document describes MooseX::Types::Locale::Codes version 0.00.

SYNOPSIS

{
    package MyApp::Locale;

    use Moose;
    use MooseX::Types::Locale::Codes::Country  qw(CountryCode);
    use MooseX::Types::Locale::Codes::Currency qw(CurrencyCode);
    use MooseX::Types::Locale::Codes::Language qw(LanguageCode);
    use MooseX::Types::Locale::Codes::Script   qw(ScriptCode);

    has 'country'  => (isa => CountryCode[],  coerce => 1, is => 'ro');
    has 'currency' => (isa => CurrencyCode[], coerce => 1  is => 'ro');
    has 'language' => (isa => LanguageCode[], coerce => 1, is => 'ro');
    has 'script'   => (isa => ScriptCode[],   coerce => 1, is => 'ro');
    # See each modules for further type constraints and coercions.

    __PACKAGE__->meta->make_immutable;
}

my $locale = MyApp::Locale->new(
    country  => 'us',
    currency => 'usd',
    language => 'EN',
    script   => 'latn',
);
print $locale->country;  # 'US'   (letter case was canonized)
print $locale->currency; # 'USD'  (letter case was canonized)
print $locale->language; # 'en'   (letter case was canonized)
print $locale->script;   # 'Latn' (letter case was canonized)

DESCRIPTION

This distribution contains several Moose::Util::TypeConstraints with coercions, designed to work with the codes and names which were contained by Locale::Codes.

Currently, the following modules are included.

This module designed to work with the codes and names of Locale::Codes::Country by following parameterized types:

Country{Code or Name}

An alias of Country{Code or Name}['alpha-2'] .

Country{Code or Name}[]

An alias of Country{Code or Name}['alpha-2'] .

Country{Code or Name}['alpha-2']

It corresponds to alpha-2 country code set identified with the symbol LOCALE_CODE_ALPHA_2.

Country{Code or Name}['alpha2']

An alias of Country{Code or Name}['alpha-2'] .

Country{Code or Name}['alpha-3']

It corresponds to alpha-3 country code set identified with the symbol LOCALE_CODE_ALPHA_3.

Country{Code or Name}['alpha3']

An alias of Country{Code or Name}['alpha-3'] .

Country{Code or Name}['numeric']

It corresponds to numeric country code set identified with the symbol LOCALE_CODE_NUMERIC.

Country{Code or Name}['fips-10']

It corresponds to fips-10 country code set identified with the symbol LOCALE_CODE_FIPS.

Country{Code or Name}['fips']

An alias of Country{Code or Name}['fips-10'] .

Country{Code or Name}['dom']

It corresponds to dom country code set identified with the symbol LOCALE_CODE_DOM.

Country{Code or Name}['domain']

An alias of Country{Code or Name}['domain'] .

This module designed to work with the codes and names of Locale::Codes::Currency by following parameterized types:

Currency{Code or Name}

An alias of Currency{Code or Name}['alpha'] .

Currency{Code or Name}[]

An alias of Currency{Code or Name}['alpha'] .

Currency{Code or Name}['alpha']

It corresponds to alpha currency code set identified with the symbol LOCALE_CURR_ALPHA.

Currency{Code or Name}['numeric']

It corresponds to alpha currency code set identified with the symbol LOCALE_CURR_NUMERIC.

This module designed to work with the codes and names of Locale::Codes::Language by following parameterized types:

Language{Code or Name}

An alias of Language{Code or Name}['alpha-2'] .

Language{Code or Name}[]

An alias of Language{Code or Name}['alpha-2'] .

Language{Code or Name}['alpha-2']

It corresponds to alpha-2 language code set identified with the symbol LOCALE_LANG_ALPHA_2.

Language{Code or Name}['alpha2']

An alias of Language{Code or Name}['alpha-2'] .

Language{Code or Name}['alpha-3']

It corresponds to alpha-3 language code set identified with the symbol LOCALE_LANG_ALPHA_3.

Language{Code or Name}['alpha3']

An alias of Language{Code or Name}['alpha-3'] .

Language{Code or Name}['bibliographic']

An alias of Language{Code or Name}['alpha-3'] .

Language{Code or Name}['term']

It corresponds to term language code set identified with the symbol LOCALE_LANG_TERM.

Language{Code or Name}['terminologic']

An alias of Language{Code or Name}['term'] .

This module designed to work with the codes and names of Locale::Codes::LangExt by following parameterized types:

LanguageExtension{Code or Name}

An alias of LanguageExtension{Code or Name}['alpha'] .

LanguageExtension{Code or Name}[]

An alias of LanguageExtension{Code or Name}['alpha'] .

LanguageExtension{Code or Name}['alpha']

It corresponds to alpha language extension code set identified with the symbol LOCALE_LANGEXT_ALPHA.

This module designed to work with the codes and names of Locale::Codes::LangVar by following parameterized types:

LanguageVariation{Code or Name}

An alias of LanguageVariation{Code or Name}['alpha'] .

LanguageVariation{Code or Name}[]

An alias of LanguageVariation{Code or Name}['alpha'] .

LanguageVariation{Code or Name}['alpha']

It corresponds to alpha language variation code set identified with the symbol LOCALE_LANGVAR_ALPHA.

This module designed to work with the codes and names of Locale::Codes::Script by following parameterized types:

Script{Code or Name}

An alias of Script{Code or Name}['alpha'] .

Script{Code or Name}[]

An alias of Script{Code or Name}['alpha'] .

Script{Code or Name}['alpha']

It corresponds to alpha script code set identified with the symbol LOCALE_SCRIPT_ALPHA.

Script{Code or Name}['numeric']

It corresponds to numeric script code set identified with the symbol LOCALE_SCRIPT_NUMERIC.

Option Types for MooseX::Getopt

These modules provide you the optional type mappings for MooseX::Getopt when it was installed. Then you can use the option types for Getopt::Long with hand-maid type mappings.

See each modules for further information.

NOTE

Behaviors of Coercions are Only Canonization

These type coercions are intended solely for canonization of letter case. In other words, they do not convert codes and names by XXX2code(), code2XXX() and XXX_code2code() on Locale::Codes::API.

For example:

{
    package MyApp::Locale::Language;

    use Moose;
    use MooseX::Types::Locale::Codes::Language qw(
        LanguageCode
        LanguageName
    );

    has 'code' => (isa => LanguageCode[], coerce => 1, is => 'rw');
    has 'name' => (isa => LanguageName[], coerce => 1, is => 'rw');

    __PACKAGE__->meta->make_immutable;
}

my $language = MyApp::Locale::Language;
print $language->name('EN');      # It is not 'English' but 'en'.
print $language->code('english'); # It is not 'en' but 'English'.

If you want conversion, could you implement an individual locale class with several attributes?

{
    package MyApp::Locale::Language::Complex;

    use 5.010_001;
    use Moose;
    extends qw(MyApp::Locale::Language);
    use Data::Validator;
    use Locale::Language;

    has '+name' => (lazy_build => 1, trigger => sub { $_[0]->clear_code });
    has '+code' => (lazy_build => 1, trigger => sub { $_[0]->clear_name });

    around BUILDARGS => sub {
        state $rule = Data::Validator->new(
            code => { xor => [qw(name)] },
            name => { xor => [qw(code)] },
        )->with('Method');
        my ($next, $class, $init_args) = (shift, $rule->validate(@_));
        return $class->$next($init_args);
    };

    sub _build_code {
        confess 'Language name was not specified'
            unless $_[0]->has_name;
        return language2code($_[0]->name);
    }

    sub _build_name {
        confess 'Language code was not specified'
            unless $_[0]->has_code;
        return code2language($_[0]->code);
    }

    __PACKAGE__->meta->make_immutable;
}

use Try::Tiny;

my $language = MyApp::Locale::Language::Comprex->new(code => 'EN');
print $language->code;       # 'en'        (was canonized by coercion)
print $language->name;       # 'English'   (was converted by builder)
print $language->code('EO'); # 'eo'        (was canonized by coercion)
print $language->name;       # 'Esperanto' (was canonized by builder)

try {
    MyApp::Locale::Language::Complex->new(code => 'en', name => 'English');
}
catch {
    print $_; # Exclusive parameters passed togther: 'code' v.s. 'name'...
};

SEE ALSO

INCOMPATIBILITIES

None reported.

Note that MooseX::Types::Locale::Language and MooseX::Types::Locale::Country which become the predecessors of MooseX::Types::Locale::Codes::Language and MooseX::Types::Locale::Codes::Country are deprecated. The original two modules will continue to work, but all new type constraints and coercions will be added in the MooseX::Types::Locale::Codes namespace.

Also MooseX::Types::Locale::Language::Fast and MooseX::Types::Locale::Country::Fast which do not provide coercions to save memory footprint and to quicken initialization will continue to work too, but the original two modules now provide coercions. Because these variations can easily be ignored.

TO DO

  • More tests.

BUGS AND LIMITATIONS

No bugs have been reported.

Making Suggestions and Reporting Bugs

Please report any found bugs, feature requests, and ideas for improvements to bug-moosex-types-locale-codes at rt.cpan.org, or through the web interface at http://rt.cpan.org/Public/Bug/Report.html?Queue=MooseX-Types-Locale-Codes. I will be notified, and then you'll automatically be notified of progress on your bugs/requests as I make changes.

When reporting bugs, if possible, please add as small a sample as you can make of the code that produces the bug. And of course, suggestions and patches are welcome.

SUPPORT

You can find documentation for this module with the perldoc command.

perldoc MooseX::Types::Locale::Codes

You can also look for information at:

RT: CPAN's request tracker

http://rt.cpan.org/Public/Dist/Display.html?Name=MooseX-Types-Locale-Codes

AnnoCPAN: Annotated CPAN documentation

http://annocpan.org/dist/MooseX-Types-Locale-Codes

Search CPAN

http://search.cpan.org/dist/MooseX-Types-Locale-Codes

CPAN Ratings

http://cpanratings.perl.org/dist/MooseX-Types-Locale-Codes

VERSION CONTROL

This module is maintained using Git. You can get the latest version from git://github.com/gardejo/p5-moosex-types-locale-codes.git.

AUTHOR

MORIYA Masaki, alias Gardejo

<moriya at cpan dot org>, http://gardejo.org/

COPYRIGHT AND LICENSE

Copyright (c) 2009-2011 MORIYA Masaki, alias Gardejo

This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself. See perlgpl and perlartistic.

The full text of the license can be found in the LICENSE file included with this distribution.

package MooseX::Types::Locale::Codes::Language;
# ******************************************************************************
# Dependency(-ies)
# ******************************************************************************
# ==============================================================================
# Pragma(ta)
# ==============================================================================
use 5.008_001;
# MooseX::Types turns strict/warnings pragmas on,
# however, kwalitee scorer can not detect such mechanism.
# (Perl::Critic can it, with equivalent_modules parameter)
use strict;
use warnings;
# ==============================================================================
# Namespace Cleaner
# ==============================================================================
use namespace::autoclean;
# ==============================================================================
# MOP Module(s)
# ==============================================================================
use MooseX::Types -declare => [qw(LanguageCode LanguageName)];
use MooseX::Types::Moose qw(Maybe Str);
use MooseX::Types::Parameterizable qw(Parameterizable);
# ==============================================================================
# General Module(s)
# ==============================================================================
use Devel::PartialDump qw(dump);
use Locale::Codes::Language 3.17
qw(language2code code2language language_code2code);
use Try::Tiny;
# ******************************************************************************
# Class Variable(s) and Constant(s)
# ******************************************************************************
our $VERSION = "0.07";
use constant CANONICAL_CODE_SET_OF => {
# aliased code set => canonical code set
# perldoc Locale::Codes::Language = 'alpha-2' but impl = 'alpha2' ...
'alpha-2' => 'alpha2',
'alpha-3' => 'alpha3',
# sugers
'default' => 'alpha2',
'bibliographic' => 'alpha3',
'terminologic' => 'term',
};
# ******************************************************************************
# Type Constraint(s) and Coercion(s)
# ******************************************************************************
# ==============================================================================
# Language Code
# ==============================================================================
subtype LanguageCode,
as Parameterizable[Str, Maybe[Str]],
where {
my ($code, $code_set) = @_;
my $canonized_code_set = _canonize_code_set($code_set);
return defined language_code2code
($code, $canonized_code_set, $canonized_code_set);
},
message {
my ($code, $code_set) = @_;
return sprintf(
'Validation failed for %s failed with value (%s) '
. 'because specified case sensitive language code '
. 'does not exist in ("%s") code set',
__PACKAGE__ . '::LanguageCode',
dump($code),
_canonize_code_set($code_set),
);
};
coerce LanguageCode,
from Str,
via {
my ($code, $code_set) = @_;
my $canonized_code_set = _canonize_code_set($code_set);
return language_code2code
($code, $canonized_code_set, $canonized_code_set);
};
# ==============================================================================
# Language Name
# ==============================================================================
subtype LanguageName,
as Parameterizable[Str, Maybe[Str]],
where {
my ($name, $code_set) = @_;
my $canonized_code_set = _canonize_code_set($code_set);
my $code = language2code($name, $canonized_code_set);
return defined $code
&& $name eq code2language($code, $canonized_code_set);
},
message {
my ($name, $code_set) = @_;
return sprintf(
'Validation failed for "%s" failed with value (%s) '
. 'because specified case sensitive language name '
. 'does not exist in ("%s") code set',
__PACKAGE__ . '::LanguageName',
dump($name),
_canonize_code_set($code_set),
);
};
coerce LanguageName,
from Str,
via {
my ($name, $code_set) = @_;
my $canonized_code_set = _canonize_code_set($code_set);
return code2language(
language2code($name, $canonized_code_set),
$canonized_code_set
);
};
# ******************************************************************************
# Function(s)
# ******************************************************************************
# ==============================================================================
# Private Function(s)
# ==============================================================================
sub _canonize_code_set {
my $code_set = shift;
$code_set = 'default'
unless defined $code_set;
return exists CANONICAL_CODE_SET_OF->{$code_set}
? CANONICAL_CODE_SET_OF->{$code_set}
: $code_set;
}
# ******************************************************************************
# Optionally Add Getopt Option Type
# ******************************************************************************
if ( try { require MooseX::Getopt } ) {
MooseX::Getopt::OptionTypeMap->add_option_type_to_map( $_, '=s', )
for (LanguageCode, LanguageName);
}
# ******************************************************************************
# Return True
# ******************************************************************************
1;
__END__
# ******************************************************************************
# Documentation
# ******************************************************************************
=pod
=encoding utf-8
=head1 NAME
MooseX::Types::Locale::Codes::Language - Locale::Codes::Language related type constraints and coercions for Moose
=head1 VERSION
This document describes L<MooseX::Types::Locale::Codes::Language> version
C<0.00>.
=head1 SYNOPSIS
{
package MyApp::Locale::Language;
use Moose;
use MooseX::Types::Locale::Codes::Language qw(
LanguageCode
LanguageName
);
has 'code' => (isa => LanguageCode[], coerce => 1, is => 'rw');
has 'name' => (isa => LanguageName[], coerce => 1, is => 'rw');
__PACKAGE__->meta->make_immutable;
}
my $language = MyApp::Locale::Language->new(
code => 'EN',
name => 'ENGLISH',
);
print $language->code; # 'en' (letter case was canonized)
print $language->name; # 'English' (letter case was canonized)
=head1 DESCRIPTION
This module packages several L<Moose::Util::TypeConstraints> with coercions,
designed to work with the values of L<Locale::Codes::Language>.
=head2 Type Constraints and Coercions
=head3 LanguageCode[`a]
=head4 C<LanguageCode>
An alias of L<LanguageCode['alpha-2']|/LanguageCode['alpha-2']>.
=head4 C<LanguageCode[]>
An alias of L<LanguageCode['alpha-2']|/LanguageCode['alpha-2']>.
=head4 C<LanguageCode['alpha-2']>
A subtype of C<Str>, which should be defined in B<case sensitive> language code
of ISO 639-1 alpha-2.
For example, it allows not C<'JA'> but C<'ja'> as C<'Japanese'>.
If you turned C<coerce> option on, C<Str> will be lower-case.
For example, C<'JA'> will convert to C<'ja'>.
It corresponds to L<C<alpha-2> language code set
|Locale::Codes::Language/alpha-2> identified with the symbol
C<LOCALE_LANG_ALPHA_2>.
=head4 C<LanguageCode['alpha2']>
An alias of L<LanguageCode['alpha-2']|/LanguageCode['alpha-2']>.
=head4 C<LanguageCode['alpha-3']>
A subtype of C<Str>, which should be defined in B<case sensitive> language code
of ISO 639-2/B alpha-3.
For example, it allows not C<'GER'> but C<'ger'> as C<'German'>.
If you turned C<coerce> option on, C<Str> will be lower-case.
For example, C<'GER'> will convert to C<'ger'>.
It corresponds to L<C<alpha-3> language code set
|Locale::Codes::Language/alpha-3> identified with the symbol
C<LOCALE_LANG_ALPHA_3>.
=head4 C<LanguageCode['alpha3']>
An alias of L<LanguageCode['alpha-3']|/LanguageCode['alpha-3']>.
=head4 C<LanguageCode['bibliographic']>
An alias of L<LanguageCode['alpha-3']|/LanguageCode['alpha-3']>.
=head4 C<LanguageCode['term']>
A subtype of C<Str>, which should be defined in B<case sensitive> language code
of ISO 639-2/T alpha-3.
For example, it allows not C<'DEU'> but C<'deu'> as C<'German'>.
If you turned C<coerce> option on, C<Str> will be lower-case.
For example, C<'DEU'> will convert to C<'deu'>.
It corresponds to L<C<term> language code set
|Locale::Codes::Language/term> identified with the symbol
C<LOCALE_LANG_TERM>.
=head4 C<LanguageCode['terminologic']>
An alias of L<LanguageCode['term']|/LanguageCode['term']>.
=head3 LanguageName[`a]
=head4 C<LanguageName>
An alias of L<LanguageName['alpha-2']|/LanguageName['alpha-2']>.
=head4 C<LanguageName[]>
An alias of L<LanguageName['alpha-2']|/LanguageName['alpha-2']>.
=head4 C<LanguageName['alpha-2']>
A subtype of C<Str>, which should be defined in B<case sensitive> language name
of ISO 639-1.
For example, it allows not C<'ESPERANTO'> but C<'Esperanto'> as C<'eo'>.
If you turned C<coerce> option on, C<Str> will be same case as canonical name.
For example, C<'ESPERANTO'> will convert to C<'Esperanto'>.
It corresponds to L<C<alpha-2> language code set
|Locale::Codes::Language/term> identified with the symbol
C<LOCALE_LANG_ALPHA_2>.
=head4 C<LanguageName['alpha2']>
An alias of L<LanguageName['alpha-2']|/LanguageName['alpha-2']>.
=head4 C<LanguageName['alpha-3']>
A subtype of C<Str>, which should be defined in B<case sensitive> language name
of ISO 639-2/B alpha-3.
For example, it allows not C<'CHINESE'> but C<'Chinese'> as C<'chi'>.
If you turned C<coerce> option on, C<Str> will be same case as canonical name.
For example, C<'CHINESE'> will convert to C<'Chinese'>.
It corresponds to L<C<alpha-3> language code set
|Locale::Codes::Language/term> identified with the symbol
C<LOCALE_LANG_ALPHA_3>.
=head4 LanguageName['alpha3']
An alias of L<LanguageName['alpha-3']|/LanguageName['alpha-3']>.
=head4 C<LanguageName['bibliographic']>
An alias of L<LanguageName['alpha-3']|/LanguageName['alpha-3']>.
=head4 C<LanguageName['term']>
A subtype of C<Str>, which should be defined in B<case sensitive> language code
of ISO 639-2/T alpha-3.
For example, it allows not C<'CHINESE'> but C<'Chinese'> as C<'zho'>.
If you turned C<coerce> option on, C<Str> will be lower-case.
For example, C<'CHINESE'> will convert to C<'Chinese'>.
It corresponds to L<C<term> language code set
|Locale::Codes::Language/term> identified with the symbol
C<LOCALE_LANG_TERM>.
=head4 C<LanguageName['terminologic']>
An alias of L<LanguageName['term']|/LanguageName['term']>.
=head2 Option Types for L<MooseX::Getopt>
The module provides you the optional type mappings of L<MooseX::Getopt>
when it was installed.
Then you can use the option types for L<Getopt::Long> with hand-maid type
mappings.
=head3 C<String> (C<"=s">) types
=over 4
=item * C<LanguageCode>
=item * C<LanguageName>
=back
=head1 NOTE
=head2 Behaviors of Coercions are Only Canonization
These type coercions are intended solely for B<canonization> of letter case.
In other words, they B<do not convert> codes and names by C<XXX2code()>,
C<code2XXX()> and C<XXX_code2code> on L<Locale::Codes::API>.
See L<MooseX::Types::Locale::Codes
|MooseX::Types::Locale::Codes/Behaviors of Coercions are Only Canonization>
for further example.
=head2 Aliases of Language will be Canonized
Aliases of language name do not satisfy with type constraints.
my $alias = 'Old English (ca. 450-1100)';
my $is_valid = LanguageName['alpha-3']->check($alias);
# $is_valid is false,
# but Locale::Codes::Language::language2code($alias) returns 'ang'.
Therefore, type coercion provides the canonical name for you.
my $name = LanguageName['alpha-3']->coerce($alias);
# $name is 'English, Old (ca.450-1100)',
# that is to say, it is not equal to $alias.
=head1 SEE ALSO
=head2 Moose Related Modules
=over 4
=item *
L<Moose>
=item *
L<MooseX::Types>
=item *
L<MooseX::Types::Moose>
=item *
L<MooseX::Types::Parameterizable>
=item *
L<MooseX::Types::Getopt>
=back
=head2 Locale::Codes Related Modules
=over 4
=item *
L<Locale::Codes::Language>
=back
=head1 INCOMPATIBILITIES
See L<MooseX::Types::Locale::Codes
|MooseX::Types::Locale::Codes/INCOMPATIBILITIES>.
=head1 TO DO
See L<MooseX::Types::Locale::Codes
|MooseX::Types::Locale::Codes/TO DO>.
=head1 BUGS AND LIMITATIONS
See L<MooseX::Types::Locale::Codes
|MooseX::Types::Locale::Codes/BUGS AND LIMITATIONS>.
=head1 SUPPORT
See L<MooseX::Types::Locale::Codes
|MooseX::Types::Locale::Codes/SUPPORT>.
=head1 VERSION CONTROL
See L<MooseX::Types::Locale::Codes
|MooseX::Types::Locale::Codes/VERSION CONTROL>.
=head1 AUTHOR
=over 4
=item MORIYA Masaki, alias Gardejo
C<< <moriya at cpan dot org> >>,
L<http://gardejo.org/>
=back
=head1 COPYRIGHT AND LICENSE
Copyright (c) 2009-2011 MORIYA Masaki, alias Gardejo
This library is free software; you can redistribute it and/or modify it under
the same terms as Perl itself.
See L<perlgpl> and L<perlartistic>.
The full text of the license can be found in the F<LICENSE> file included with
this distribution.
=cut
@gardejo
Copy link
Author

gardejo commented Sep 9, 2011

It (MooseX::Types::Locale::Codes) gets ready for release as soon as MooseX::Types::Parameterizable is fixed.
https://github.com/gardejo/p5-moosex-types-locale-codes

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment