通过 MultiViews 选择语言仅在请求其他资源时部分起作用
我有一个提供不同语言版本的小网站,这些语言是根据以下条件(优先顺序递增)进行选择的:
- 浏览器发送的
Accept-Language
- 指定首选语言的 cookie
- 包含最后的语言偏好
该网站本身仅由静态 HTML 页面组成,并且在可能的情况下我希望保持这种方式。我通过 mod_negotiation
、mod_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
:自八月左右开始工作正常,允许以下情况:
- 不存在 cookie,
Accept-Language
接管(感谢MultiViews
) - 存在 Cookie,cookie 的将使用的语言 (
prefer-language
) - 请求路径为
/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):
Accept-Language
sent by the browser- A cookie specifying the preferred language
- 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:
- No cookie present,
Accept-Language
takes over (thanks toMultiViews
) - Cookie present, the cookie's language will be used (
prefer-language
) - The request path is
/es
or similar and that will be used to (a) set a cookie and (b) setprefer-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 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
我现在通过混合
RewriteRule
和SetEnvIf
之间的语言选择解决了这个问题:规则现在仅设置 cookie 并指向正确的资源,而语言选择由匹配请求 URI。仍然感觉很奇怪,特别是当某些东西需要以 REDIRECT_ 为前缀时它不容易可见,但至少现在它可以工作了。
I solved the problem now by mixing the language selection between
RewriteRule
andSetEnvIf
: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.