mod_perl 设置中的多个语言环境之间存在冲突吗?

发布于 2024-12-20 05:15:41 字数 859 浏览 2 评论 0 原文

我目前正在致力于大型 Perl/Mason Web 应用程序的国际化(Perl 5.8.0、Mason 1.48、mod_perl 和 Apache)。在选择本地化模块时,我决定使用 Locale::TextDomain 优于 Locale::Maketext,主要是因为后者的复数形式支持不如我想要的那么好。

我在 Locale::TextDomain 中遇到的问题是它根据进程的区域设置来解析用于翻译的目录。当我意识到这一点时,我担心如果我希望用户能够使用不同的区域设置,这将如何影响我的应用程序 - 为适应一个用户的设置而更改区域设置是否可能会影响另一个用户的会话?例如,是否会出现这样的情况:由于德语用户的会话更改了进程的区域设置,英语用户收到了德语页面?我不太了解 Apache 的线程/进程模型是如何工作的,尽管似乎如果多个用户可以由同一个线程提供服务,这种情况就可能发生。

此电子邮件线程将表明这是可能的; 这里OP描述了我正在考虑的情况。

如果这是真的,有没有办法可以在仍然使用 Locale::TextDomain 的同时防止这种情况发生?我想我总是可以破解模块以独立于语言环境加载目录(可能使用 DBD::PO),但希望我只是缺少一些可以解决我的问题的东西......

I'm currently working on internationalizing a large Perl/Mason web application (Perl 5.8.0, Mason 1.48, mod_perl & Apache). In choosing a localization module, I decided to go with Locale::TextDomain over Locale::Maketext, mostly because the latter's plural form support isn't as nice as I'd like.

The hang-up I'm having with Locale::TextDomain is that it resolves which catalog to use for translations based on the process' locale. When I realized this, I got worried about how this would affect my application if I wanted users to be able to use different locales -- would it be possible that a change in locale to suit one user's settings would affect another user's session? For example, could there be a situation in which an English user received a page in German because a German user's session changed the process' locale? I'm not very knowledgeable about how Apache's thread/process model works, though it seems that if multiple users can be served by the same thread, this could happen.

This email thread would indicate that this is possible; here the OP describes the situation I'm thinking about.

If this is true, is there a way I can prevent this scenario while still using Locale::TextDomain? I suppose I could always hack at the module to load the catalogs in a locale-independent (probably using DBD::PO), but hopefully I'm just missing something that will solve my problem...

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

落花浅忆 2024-12-27 05:15:41

通过使用 setlocale 问题改为“nofollow">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 的位置,添加代码或 web_set_locale($DEFAULT_LANGUAGE),这样尽管使用了全局设置,该行为也无法持续存在,因为我们保证每个请求都会设置/更改一次。


编辑2:进一步测试表明它不是线程安全的,抱歉。仅使用将请求隔离为进程的 prefork MPM;但是,workerevent 会受到影响,因为它们是基于线程的。

You entirely avoid the setlocale problems by using web_set_locale instead.

(That message on the mailing list predates the addition of that function by about 4 years.)


Edit: You are correct that global behaviour persists in Apache children, leading to buggy behaviour.

I wrote up a test case:

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;
}

The app runs as a PerlResponseHandler. When the user request a language that cannot be set, the call fails silently and the language that was used last successfully is still enabled.

The trick to fix this is to always set to a language that exists with a fallback mechanism. At the spot marked XXX, add the code or web_set_locale($DEFAULT_LANGUAGE), so that despite using a global setting, the behaviour cannot persist because we guarantee that it is set/changed once per request.


Edit 2: Further testing reveals that it's not thread-safe, sorry. Use the prefork MPM only which isolates requests as processes; however worker and event are affected because they are thread-based.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文