通过 MultiViews 选择语言仅在请求其他资源时部分起作用

发布于 2024-12-14 23:35:03 字数 1816 浏览 5 评论 0原文

我有一个提供不同语言版本的小网站,这些语言是根据以下条件(优先顺序递增)进行选择的:

  1. 浏览器发送的 Accept-Language
  2. 指定首选语言的 cookie
  3. 包含最后的语言偏好

该网站本身仅由静态 HTML 页面组成,并且在可能的情况下我希望保持这种方式。我通过 mod_negotiationmod_rewrite 和以下 .htaccess 文件(缩写为省略语言和字符集的声明)实现了语言选择

Options FollowSymLinks MultiViews
DirectoryIndex index

Header set Pragma no-cache

RewriteEngine on
RewriteRule ^([a-zA-Z-]{2,5})$ index [CO=language:$1:.example.com:525600,E=LANG:$1]

SetEnvIf Cookie "language=([a-zA-Z-]+)" COOKIE_LANG=$1

SetEnvIf COOKIE_LANG (.+) prefer-language=$1
SetEnvIf REDIRECT_LANG (.+) prefer-language=$1

# plenty of AddLanguage and AddCharset calls

LanguagePriority en-us
DefaultLanguage en-us
ForceLanguagePriority Prefer Fallback

:自八月左右开始工作正常,允许以下情况:

  1. 不存在 cookie,Accept-Language 接管(感谢 MultiViews
  2. 存在 Cookie,cookie 的将使用的语言 (prefer-language)
  3. 请求路径为 /es 或类似路径,将用于 (a) 设置 cookie 和 (b) 设置 prefer-language 到该值。

现在,我在网站上有了更多的资源,感谢 MultiViews,可以通过 /resource 而不是 /resource.html 选择这些资源内容协商和 cookie 选项仍然可以在此处选择适当的语言。

现在我想扩展 URI 处理,以便像 /resource/en 这样的东西可以直接选择特定语言的资源,这样这不仅仅适用于 / 。我尝试了以下 RewriteRule:

RewriteRule ^(([^/]+)/)?([a-zA-Z-]{2,5})$ /$2 [CO=language:$3:.example.com:525600,E=LANG:$3]

,它的工作原理是发送正确的资源并设置正确的 cookie,但首选语言显然不再从环境变量中获取。现在唯一强制选择语言的是 cookie,但这仍然与之前的请求相同,因此在刷新页面之前我不会看到新语言。到目前为止,我对规则所做的尝试都没有对这种行为产生影响。有趣的是,有了这条规则,上面记录的旧行为仍然可以正常工作。只有当我请求与 / 不同的东西时,它才会做奇怪的事情。

这是在共享主机上(在 FreeBSD 监狱内),所以我无法启用重写日志(因为我什至不知道文件所在的物理路径);此外,它显然似乎忽略了环境变量,并且出于某种原因仅使用 cookie 来设置首选语言。而且到目前为止我还没有弄清楚为什么。有什么帮助吗?

I have a little site that's available in different languages which are selected based on the following criteria (increasing order of preference):

  1. Accept-Language sent by the browser
  2. A cookie specifying the preferred language
  3. The request path containing a language preference at the end

The site itself consists of only static HTML pages and insofar possible I'd like to keep it that way. I implemented the language selection via mod_negotiation, mod_rewrite and the following .htaccess file (shortened to omit declaration of languages and charsets):

Options FollowSymLinks MultiViews
DirectoryIndex index

Header set Pragma no-cache

RewriteEngine on
RewriteRule ^([a-zA-Z-]{2,5})$ index [CO=language:$1:.example.com:525600,E=LANG:$1]

SetEnvIf Cookie "language=([a-zA-Z-]+)" COOKIE_LANG=$1

SetEnvIf COOKIE_LANG (.+) prefer-language=$1
SetEnvIf REDIRECT_LANG (.+) prefer-language=$1

# plenty of AddLanguage and AddCharset calls

LanguagePriority en-us
DefaultLanguage en-us
ForceLanguagePriority Prefer Fallback

which has been working fine since August or so to allow for the following:

  1. No cookie present, Accept-Language takes over (thanks to MultiViews)
  2. Cookie present, the cookie's language will be used (prefer-language)
  3. The request path is /es or similar and that will be used to (a) set a cookie and (b) set prefer-language to that value.

Now, I have a few more resources on the site which, thanks to MultiViews, can be selected via /resource instead of /resource.html and content negotiation and the cookie option still work fine for selecting the appropriate language here.

Now I wanted to expand URI processing so that things like /resource/en work in directly selecting the resource in a specific language, so that this doesn't only work for /. I tried the following RewriteRule:

RewriteRule ^(([^/]+)/)?([a-zA-Z-]{2,5})$ /$2 [CO=language:$3:.example.com:525600,E=LANG:$3]

and it works insofar that the correct resource is sent and the correct cookie is set, but the preferred language apparently isn't taken from the environment variable anymore. The only thing now forcing the language selection is the cookie, but that is still the same as before on that request, so I won't see the new language until I refreshed the page. Nothing I tried so far with the rules had an effect on that behaviour. Interestingly, with this rule the old behaviour documented above still works fine. It's only if I request something different from / that it does strange things.

This is on shared hosting (within a FreeBSD jail) so I can't enable the rewrite log (as I don't even know the physical path where the files are); besides, it quite clearly seems to ignore the environment variable and only using the cookie for setting the preferred language for some reason. And I haven't figured out why so far. Any help?

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

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

发布评论

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

评论(1

孤独患者 2024-12-21 23:35:03

我现在通过混合 RewriteRuleSetEnvIf 之间的语言选择解决了这个问题:

SetEnvIf Cookie "language=([a-zA-Z-]+)" prefer-language=$1
SetEnvIf REDIRECT_prefer-language "(.+)" prefer-language=$1
SetEnvIf Request_URI "/([a-zA-Z-]{2,5})$" prefer-language=$1

RewriteRule "^(([^/]+)/)?([a-zA-Z-]{2,5})$" /$2 [CO=language:$3:.example.com:525600]

规则现在仅设置 cookie 并指向正确的资源,而语言选择由匹配请求 URI。仍然感觉很奇怪,特别是当某些东西需要以 REDIRECT_ 为前缀时它不容易可见,但至少现在它可以工作了。

I solved the problem now by mixing the language selection between RewriteRule and SetEnvIf:

SetEnvIf Cookie "language=([a-zA-Z-]+)" prefer-language=$1
SetEnvIf REDIRECT_prefer-language "(.+)" prefer-language=$1
SetEnvIf Request_URI "/([a-zA-Z-]{2,5})$" prefer-language=$1

RewriteRule "^(([^/]+)/)?([a-zA-Z-]{2,5})$" /$2 [CO=language:$3:.example.com:525600]

The rule now only sets the cookie and points to the correct resource, while the language selection is handled by matching on the request URI. Still feels weird, especially since it's not easily visible when something needs to be prefixed with REDIRECT_, but at least it works now.

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