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 browserThe 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:
Accept-Language
takes over (thanks to MultiViews
)prefer-language
)/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?
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.