2

I am trying to achieve more things:

  1. HTTP:// should redirect to HTTPS://
  2. www.example.com should redirect to www.example.com/en/ or /it/ depending on client language
  3. links should resolve to www.example.com?lang=en
  4. All urls different from index.php? (e.g. www.example.com/abcd) should all be redirected to index.php

I got working the 1.3.4 by using:

RewriteEngine On

RewriteCond %{SERVER_PORT} !^443$ 
RewriteCond %{HTTPS} off 
RewriteRule ^(.*)$ https://www.example.com/$1 [R=301,L]

# RewriteCond %{HTTP:Accept-Language} ^en [NC]
# RewriteRule ^$ https://www.example.com/en/ [L,R=301]
# RewriteCond %{HTTP:Accept-Language} ^it [NC]
# RewriteRule ^$ https://www.example.com/it/ [L,R=301]

RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-l
RewriteRule ^(en|it)/(.*) $2?lang=$1 [QSA]
RewriteRule ^([^/]+)$ index.php?op=$1 [L,NS,QSA] index.php

Trying now to achieve point 2. If I remove the comments it ends up in a redirect loop + error

Is there any way?

2 Answers 2

1

This answer comes from memory. If I'm 100% correct with the syntax, you'll want to replaced your 4 commented out lines of code with:

RewriteCond %{REQUEST_URI} !^/en(.*)$
RewriteCond %{HTTP:Accept-Language} ^en [NC]
RewriteRule ^$ https://www.example.com/en/ [L,R=301]
RewriteCond %{REQUEST_URI} !^/it(.*)$
RewriteCond %{HTTP:Accept-Language} ^it [NC]
RewriteRule ^$ https://www.example.com/it/ [L,R=301]

The intent here is to check the request URI (the part that comes after https://www.example.com) and see that it is anything but the URI you want to redirect to (thereby avoiding a redirect loop). If the request URI matches, then the rule doesn't get processed.

For example:

RewriteCond %{REQUEST_URI} !^/en(.*)$

..checks to see someone didn't type a url that begins with https://www.example.com/en and if that's the case, then this is checked:

RewriteCond %{HTTP:Accept-Language} ^en [NC]

..which checks that "en" is in the accept-language header. If the header has "en" and the url does NOT begin with https://www.example.com/en then the user who attempts to go to https://www.example.com/ will be redirected to https://www.example.com/en/ via this rule:

RewriteRule ^$ https://www.example.com/en/ [L,R=301]
1
  • Thanx Mike, but is not working, it redirects incorrectly. But I'll work on your idea. Jan 28, 2016 at 8:23
1

The rewrite loop is actually caused by rules later in your script:

RewriteRule ^(en|it)/(.*) $2?lang=$1 [QSA]
RewriteRule ^([^/]+)$ index.php?op=$1 [L,NS,QSA] index.php

Having redirected the user to /en/ (with the Accept-Language rules), the first directive here rewrites the request back to ?lang=en (no URL-path) but the second directive then fails to match (since there is no URL-path), so it's not rewritten to index.php (a URL-path). The URL-rewriting process then starts over and the user gets redirected to /en/ again (since there is no URL-path), etc.

Providing your script can handle an empty op parameter (it should) then you could probably resolve this by simply changing the last RewriteRule pattern from ^([^/]+)$ to ^([^/]*)$ to catch the empty string.

OR, make sure your penultimate RewriteRule always includes a URL-path. For example, change:

RewriteRule ^(en|it)/(.*) $2?lang=$1 [QSA]

to

RewriteRule ^(en|it)/(.*) index.php?op=$2&lang=$1 [QSA,L]

Although that really duplicates what the last directive is doing (hence the addition of the L flag).

OR, include a condition in your language redirect and only redirect when the lang URL parameter is not present. For example:

RewriteCond %{QUERY_STRING} !lang=[a-z]{2}
RewriteCond %{HTTP:Accept-Language} ^(en|it) [NC]
RewriteRule ^$ https://www.example.com/%1/ [L,R=301]

This also combines the two rules (en and it) into one.

Just to add... whilst this type of language detection is common, it is possibly over simplified and could potentially result in incorrect language detection. It assumes that the languages are specified in order to preference (which they might not be) and ignores the "quality" (q) parameter. (There have been other questions on this very subject, but I can't just find them at the moment.)


Aside, do you need to check both...?

RewriteCond %{SERVER_PORT} !^443$ 
RewriteCond %{HTTPS} off

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.