Вы полностью избегаете проблем setlocale
, используя вместо этого web_set_locale
.
(Это сообщение в списке рассылки предшествует добавлению этой функции примерно на 4 года.)
Редактировать: Вы правы, что глобальное поведение сохраняется у детей Apache, что приводит к ошибочному поведению .
Я написалконтрольный пример:
app.psgi
use 5.010;
use strictures;
use Foo::Bar qw(run);
my $app = sub {
my ($env) = @_;
run($env);
};
Foo / Bar.pm
package Foo::Bar;
use 5.010;
use strictures;
use Encode qw(encode);
use File::Basename qw(basename);
use Locale::TextDomain __PACKAGE__, '/tmp/Foo-Bar/share/locale';
use Locale::Util qw(web_set_locale);
use Plack::Request qw();
use Sub::Exporter -setup => { exports => [ 'run' ] };
our $DEFAULT_LANGUAGE = 'en'; # untranslated source strings
sub run {
my ($env) = @_;
my $req = Plack::Request->new($env);
web_set_locale($env->{HTTP_ACCEPT_LANGUAGE}, undef, undef, [
map { basename $_ } grep { -d } glob '/tmp/Foo-Bar/share/locale/*'
]); # XXX here
return $req
->new_response(
200,
['Content-Type' => 'text/plain; charset=UTF-8'],
[encode('UTF-8', __ 'Hello, world!')],
)->finalize;
}
Приложениеработает как PerlResponseHandler.Когда пользователь запрашивает язык, который не может быть установлен, вызов завершается неудачно, и язык, который использовался в последний раз успешно, все еще включен.
Хитрость для исправления этого состоит в том, чтобы всегда устанавливать язык, который существует с резервныммеханизм.В месте, помеченном XXX, добавьте код or web_set_locale($DEFAULT_LANGUAGE)
, чтобы, несмотря на использование глобального параметра, поведение не могло сохраняться, поскольку мы гарантируем, что оно устанавливается / изменяется один раз за запрос.
Изменить 2: Дальнейшее тестирование показывает, что это не потокобезопасно, извините.Используйте только prefork
MPM, который изолирует запросы как процессы;однако worker
и event
затронуты, потому что они основаны на потоке.