views:

713

answers:

2

I'm trying to implement language switching in .htaccess, and the only thing left now is to handle clients which don't support cookies. To do that, I must set prefer-language when the user clicks a link with a language parameter.

RewriteEngine On
RewriteBase /
RewriteCond %{QUERY_STRING} (?:^|&)language=(en|fr|no)
RewriteRule ^(.*)$ $1? [cookie=language:%1:.example.com,env=language:%1,R]

SetEnv prefer-language $language

The problem is with the last line - The value is always set to empty. It works if I hardcode it, but not if I try to refer to a variable. Is there some special syntax to refer to environment variables in this context, or is there some other way to set prefer-language?

Edit: Cross-posted to Apache users list.

+1  A: 

You can set environment variables with mod_rewrite as well. Actually, you already did that (see env/E flag).


I can’t test it with mod_negotiation myself, but the following should work and set the prefer-language:

RewriteCond %{QUERY_STRING} ^((?:[^&]&)*)language=(en|fr|no)&?([^&].*)?$
RewriteRule ^ %{REQUEST_URI}?%1%3 [L,CO=language:%2,R]
RewriteCond %{HTTP_COOKIE} (^|[,\s])language=([^\s,;]+)
RewriteRule ^ - [L,E=prefer-language:%2]
SetEnvIf REDIRECT_prefer-language (.+) prefer-language=$1

But it would be far easier if you put the language identifier into the URL path like /en/…:

SetEnvIf Request_URI ^/(en|fr|no)/ prefer-language=$1
SetEnvIf REDIRECT_prefer-language (.+) prefer-language=$1

I don’t know if you need the additional/second SetEnvIf variable.

Gumbo
I've tried it, and it doesn't work (at least with this): RewriteRule ^(.*)$ $1? [cookie=language:%1:.example.com:7200:/,env=prefer-language:%1,redirect=permanent] Am I misunderstanding something?
l0b0
You can’t set an environment variable and do a redirect at the same time. So you rather need to test the cookie: `RewriteCond %{HTTP_COOKIE} (?:^|[,\ ])language=(en|fr|no) RewriteRule ^ - [E=prefer-language:%1]`
Gumbo
l0b0
Turns out the problem was that the rule was applied once, but because of "redirect=permanent" it would do another request, and that one would no longer match the RewriteCond.
l0b0
A: 

Looks like there's no support for variables in SetEnv, but here's a working configuration if someone else is trying to do the same. It's a simpler kind of language selection, since it just copies the language parameter from the referer to the current URL if it's not changed:

RewriteEngine On
RewriteBase /

# Keep the language parameter if specified in the last URL
RewriteCond %{HTTP_REFERER} ^(?:.*[&?])?language=(en|fr|no).*$
RewriteCond %{QUERY_STRING} !^(?:.*&)?language=(en|fr|no).*$
RewriteRule ^(.*)$ $1?language=%1 [redirect=permanent]

# Set the language from the URL parameter
RewriteCond %{QUERY_STRING} ^(?:.*&)?language=(en|fr|no).*$
RewriteRule ^ - [env=prefer-language:%1]

# Cache only when the language parameter is set
<IfDefine !prefer-language>
    Header set Vary *
</IfDefine>
l0b0