Skip to content

Commit

Permalink
Added Locale::Maketext
Browse files Browse the repository at this point in the history
  • Loading branch information
vti committed Apr 2, 2011
1 parent 92d7c48 commit 1dd3135
Show file tree
Hide file tree
Showing 7 changed files with 180 additions and 90 deletions.
27 changes: 15 additions & 12 deletions Makefile.PL
Original file line number Diff line number Diff line change
Expand Up @@ -35,18 +35,21 @@ WriteMakefile(
),

PREREQ_PM => {
'Carp' => '0',
'Class::Load' => '0',
'Config::Tiny' => '0',
'Cwd' => '0',
'File::Basename' => '0',
'File::Spec' => '0',
'Plack' => '0',
'Routes::Tiny' => '0',
'Scalar::Util' => '0',
'String::CamelCase' => '0',
'Text::Caml' => '0',
'Try::Tiny' => '0',
'Carp' => '0',
'Class::Load' => '0',
'Config::Tiny' => '0',
'Cwd' => '0',
'Encode' => '0',
'File::Basename' => '0',
'File::Spec' => '0',
'I18N::LangTags' => '0',
'I18N::LangTags::Detect' => '0',
'Plack' => '0',
'Routes::Tiny' => '0',
'Scalar::Util' => '0',
'String::CamelCase' => '0',
'Text::Caml' => '0',
'Try::Tiny' => '0',
},
test => {TESTS => 't/*.t t/*/*.t t/*/*/*.t t/*/*/*/*.t'}
);
85 changes: 67 additions & 18 deletions lib/Lamework/Middleware/I18N.pm
Original file line number Diff line number Diff line change
Expand Up @@ -5,56 +5,105 @@ use warnings;

use base 'Lamework::Middleware';

use I18N::AcceptLanguage;
use Encode ();
use I18N::LangTags ();
use I18N::LangTags::Detect ();

sub new {
my $self = shift->SUPER::new(@_);

$self->{default_language} ||= 'en';
die 'Namespace is required' unless $self->{namespace};

$self->{languages} = [$self->{languages}]
unless ref $self->{languages} eq 'ARRAY';
$self->{default_language} ||= 'en';

my $re = join '|' => @{$self->{languages}};
my $re = join '|' => $self->available_languages;
$self->{language_re} = qr{^/($re)(?=/|$)};

my $namespace = $self->{namespace};

eval <<"";
package $namespace\::I18N;
use base 'Locale::Maketext';
1;
my $default_language = $self->{default_language};
eval <<"";
package $namespace\::I18N::$default_language;
use base '$namespace\::I18N';
our %Lexicon = (_AUTO => 1);
1;
die $@ if $@;

return $self;
}

sub call {
my $self = shift;
my ($env) = @_;

my $languages = $self->{languages};

my $language;
my @languages;

my $re = $self->{language_re};
if ($env->{PATH_INFO} =~ s{$re}{}) {
$env->{PATH_INFO} = '/' if $env->{PATH_INFO} eq '';
$language = $1;
@languages = ($1);
}
else {
$language =
$self->acceptor->accepts($env->{HTTP_ACCEPT_LANGUAGE}, $languages);

$language ||= $self->{default_language};
@languages = I18N::LangTags::implicate_supers(
I18N::LangTags::Detect->http_accept_langs(
$env->{HTTP_ACCEPT_LANGUAGE}
)
);
}

$env->{SCRIPT_NAME} = $env->{SCRIPT_NAME} . '/' . $language;
push @languages, $self->{default_language};

my $namespace = $self->{namespace};
my $class = "$namespace\::I18N";
my $handle = $class->get_handle(@languages);
$handle->fail_with(sub { $_[1] });

$env->{'lamework.i18n.language'} = $handle->language_tag;
$env->{'lamework.i18n.maketext'} = sub {
return Encode::decode_utf8($handle->maketext(@_));
};

$env->{'lamework.i18n.language'} = $language;
$env->{SCRIPT_NAME} =
($env->{SCRIPT_NAME} || '') . '/' . $handle->language_tag;

return $self->app->($env);
}

sub acceptor {
sub available_languages {
my $self = shift;

$self->{acceptor} ||= I18N::AcceptLanguage->new;
my @languages = @{$self->{languages} || []};
return @languages if @languages;

return $self->detect_languages;
}

sub detect_languages {
my $self = shift;

my $namespace = $self->{namespace};

my $path = $INC{"$namespace\.pm"};
die "Can't detect available languages" unless $path && -f $path;
$path =~ s{\.pm$}{/I18N};

die "Can't detect available languages" unless $path && -d $path;

opendir(my $dh, $path) or die "Can't opendir $path: $!";
my @files = grep { /\.pm$/ && -f "$path/$_" } readdir($dh);
closedir $dh;

@files = map { s{\.pm$}{}; $_ } @files;

return $self->{acceptor};
push @files, $self->{default_language};

return @files;
}

1;
49 changes: 2 additions & 47 deletions t/app_i18n.t
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ use HTTP::Request::Common;

use lib 't/lib';

use MyAppI18N;

my $app = MyAppI18N->new->psgi_app;

test_psgi $app, sub {
Expand All @@ -19,50 +21,3 @@ test_psgi $app, sub {
$res = $cb->(GET '/ru');
is $res->content, 'http://localhost/ru';
};

package MyAppI18N;

use base 'Lamework';

use Plack::Builder;

sub startup {
my $self = shift;

$self->routes->add_route(
'/',
name => 'foo',
defaults => {action => 'foo'}
);
}

sub compile_psgi_app {
my $self = shift;

my $app = sub {
my $env = shift;

return [404, [], ['404 Not Found']];
};

builder {
enable '+Lamework::Middleware::I18N', languages => [qw/en ru/];

enable '+Lamework::Middleware::RoutesDispatcher';

enable '+Lamework::Middleware::ActionBuilder';

$app;
};
}

package MyAppI18N::Action::Foo;

use base 'Lamework::Action';

sub run {
my $self = shift;

$self->res->code(200);
$self->res->body($self->url_for('foo'));
}
37 changes: 37 additions & 0 deletions t/lib/MyAppI18N.pm
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package MyAppI18N;

use base 'Lamework';

use Plack::Builder;

sub startup {
my $self = shift;

$self->routes->add_route(
'/',
name => 'foo',
defaults => {action => 'foo'}
);
}

sub compile_psgi_app {
my $self = shift;

my $app = sub {
my $env = shift;

return [404, [], ['404 Not Found']];
};

builder {
enable '+Lamework::Middleware::I18N', namespace => 'MyAppI18N';

enable '+Lamework::Middleware::RoutesDispatcher';

enable '+Lamework::Middleware::ActionBuilder';

$app;
};
}

1;
12 changes: 12 additions & 0 deletions t/lib/MyAppI18N/Action/Foo.pm
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package MyAppI18N::Action::Foo;

use base 'Lamework::Action';

sub run {
my $self = shift;

$self->res->code(200);
$self->res->body($self->url_for('foo'));
}

1;
13 changes: 13 additions & 0 deletions t/lib/MyAppI18N/I18N/ru.pm
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package MyAppI18N::I18N::ru;

use strict;
use warnings;
use utf8;

use base 'MyAppI18N::I18N';

our %Lexicon = (
'Hello' => 'Привет'
);

1;
47 changes: 34 additions & 13 deletions t/middleware/i18n.t
Original file line number Diff line number Diff line change
@@ -1,57 +1,78 @@
package MyAppI18N::I18N::ru;

use strict;
use warnings;

use Test::More tests => 19;
use base 'MyAppI18N::I18N';

our %Lexicon = (
'Hello' => 'Привет'
);

package main;

use strict;
use warnings;

use utf8;

use Test::More tests => 22;
use Test::MockObject;

use_ok('Lamework::Middleware::I18N');

use Lamework::Registry;

my $middleware =
Lamework::Middleware::I18N->new(app => sub { }, languages => [qw/en ru/]);
my $middleware = Lamework::Middleware::I18N->new(
app => sub { },
namespace => 'MyAppI18N',
languages => [qw/en ru/]
);

my $env = {PATH_INFO => ''};
$middleware->call($env);
is $env->{'lamework.i18n.language'} => 'en';
is $env->{PATH_INFO} => '';
is $env->{'lamework.i18n.language'} => 'en';
is $env->{PATH_INFO} => '';
is $env->{'lamework.i18n.maketext'}->('Hello') => 'Hello';

$env = {PATH_INFO => '/'};
$middleware->call($env);
is $env->{'lamework.i18n.language'} => 'en';
is $env->{PATH_INFO} => '/';
is $env->{PATH_INFO} => '/';

$env = {PATH_INFO => '/hello'};
$middleware->call($env);
is $env->{'lamework.i18n.language'} => 'en';
is $env->{PATH_INFO} => '/hello';
is $env->{PATH_INFO} => '/hello';

$env = {PATH_INFO => '/enhello'};
$middleware->call($env);
is $env->{'lamework.i18n.language'} => 'en';
is $env->{PATH_INFO} => '/enhello';
is $env->{PATH_INFO} => '/enhello';

$env = {PATH_INFO => '/en'};
$middleware->call($env);
is $env->{'lamework.i18n.language'} => 'en';
is $env->{PATH_INFO} => '/';
is $env->{PATH_INFO} => '/';

$env = {PATH_INFO => '/ru/'};
$middleware->call($env);
is $env->{'lamework.i18n.language'} => 'ru';
is $env->{PATH_INFO} => '/';
is $env->{PATH_INFO} => '/';
is $env->{'lamework.i18n.maketext'}->('Hello') => 'Привет';
is $env->{'lamework.i18n.maketext'}->('Unknown') => 'Unknown';

$env = {PATH_INFO => '/ru/hello'};
$middleware->call($env);
is $env->{'lamework.i18n.language'} => 'ru';
is $env->{PATH_INFO} => '/hello';
is $env->{PATH_INFO} => '/hello';

$env = {PATH_INFO => '/', HTTP_ACCEPT_LANGUAGE => 'en-us,en; q=0.5'};
$middleware->call($env);
is $env->{'lamework.i18n.language'} => 'en';
is $env->{PATH_INFO} => '/';
is $env->{PATH_INFO} => '/';

$env = {PATH_INFO => '/', HTTP_ACCEPT_LANGUAGE => 'ru-ru,ru; q=0.5'};
$middleware->call($env);
is $env->{'lamework.i18n.language'} => 'ru';
is $env->{PATH_INFO} => '/';
is $env->{PATH_INFO} => '/';

0 comments on commit 1dd3135

Please sign in to comment.