Apache mod_rewrite accept language subdomain redirection - apache

i have a multilingual site with 3 languages and i'm using the following rules to redirect requests to the right version of the website based in browser accept language.
#swedish
RewriteCond %{HTTP:Accept-Language} ^sv.*$ [NC]
RewriteCond %{REQUEST_URI} ^/$ [NC]
RewriteCond %{QUERY_STRING} !(^q\=) [NC]
RewriteRule ^(.*)$ /sv [L,R=301]
#norwegian bokmal
RewriteCond %{HTTP:Accept-Language} ^nb.*$ [NC]
RewriteCond %{REQUEST_URI} ^/$ [NC]
RewriteCond %{QUERY_STRING} !(^q\=) [NC]
RewriteRule ^(.*)$ /nb [L,R=301]
#norwegian
RewriteCond %{HTTP:Accept-Language} ^no.*$ [NC]
RewriteCond %{REQUEST_URI} ^/$ [NC]
RewriteCond %{QUERY_STRING} !(^q\=) [NC]
RewriteRule ^(.*)$ /nb [L,R=301]
#all others go to english
RewriteCond %{REQUEST_URI} ^/$ [NC]
RewriteCond %{QUERY_STRING} !(^q\=) [NC]
RewriteRule ^(.*)$ /en [L,R=301]
I need to upgrade this rules to do the same redirections keeping subdomains too
Example for a norwegian request:
www.domain.com/subdomain -> www.domain.com/nb/subdomain
How can i achieve this?
I have thank #faa for helping me out with the current rules.

UPDATE
Question Description
Regarding the pages vs subdomains issue in your comments, in this specific case is irrelevant. The fact is the incoming URL in your question is: www.domain.com/subdomain and, except for the name, /subdomain is clearly a page.
A real subdomain is indeed a domain that is part of another domain and the URL format that holds it, is something like subdomain.domain.com, so there was no confusion on my part.
What it is not clear enough, is how the redirection will be handled. According to your question, but replacing "subdomain" with the whole path, here are some examples:
www.domain.com/ should go to www.domain.com/LangCode/, (previous working redirection)
www.domain.com/page should go to www.domain.com/LangCode/page
www.domain.com/page1/page2/page3/etc/ should go to www.domain.com/LangCode/page1/page2/page3/etc. This possibility is not in the question, but eventually could be neded.
In those cases, the pages in the incoming and redirected URLs should have the same name, but, although in the incoming URL do not have to exist, in the redirected URL the pages MUST exist and so a loading default script (index.php or index.html, for example) to handle the request.
Which means, there has to be a script in each page subject to redirection. I would say at least 2 for each language.
As far a I understand, that's what the question and complementary comments indicate, but it seems it is not a practical approach.
Suggested Solution
A better approach could be a single script at the root folder that handles all requests. This is an idea that can be better described with examples:
www.domain.com/ always showing in the browser's address bar but going internally to
www.domain.com/lang_handler.php?lang=sv or
www.domain.com/page1/ always showing in the browser's address bar but going internally to www.domain.com/lang_handler.php?lang=sv&target_page1=page1
This can be achieved in .htaccess with mod_rewrite directives. Here is an example:
RewriteEngine On
RewriteBase /
# Set managed languages here, except default (en)
RewriteCond %{HTTP:Accept-Language} ^(sv|ne|no).*$ [NC]
# Replace the names of the script and the parameters in the next 2 lines
RewriteCond %{REQUEST_URI} !lang_handler\.php [NC]
RewriteRule ^([^/]+)?/?$ lang_handler.php?lang=%1&target_page1=$1 [L,QSA]
# If no match, set English
# Replace the names of the script and the parameters in the next 2 lines
RewriteCond %{REQUEST_URI} !lang_handler\.php [NC]
RewriteRule ^([^/]+)?/?$ lang_handler.php?lang=en&target_page1=$1 [L,QSA]
The above rule set maps silently
http://www.domain.com/ or http://www.domain.com/page1
To
http://www.domain.com/lang_handler.php?lang=LangCode&target_page1=page1
Where LangCode is sv ne no or en by default.
This example only works for 1 page or no page. Any number of pages can be handled though, but the rules have to be modified accordingly. More parameters and regex groups have to be added to the RewriteRules.

$1 should do the trick.
RewriteCond %{HTTP:Accept-Language} ^no.*$ [NC]
RewriteCond %{REQUEST_URI} ^/$ [NC]
RewriteCond %{QUERY_STRING} !(^q\=) [NC]
RewriteRule ^(.*)$ /nb/$1 [L,R=301]

Related

Redirect url with ids range to another url using htaccess

I try to redirect user from Joomla plugins links that have specific IDs to the default admin page as following:
When user login in Joomla backend, he can reach this page of plugins:
https://www.example.com/administrator/index.php?option=com_plugins
Then if he wants to open a plugin with the id like 422 to edit it, he's to click on this link:
https://www.example.com/administrator/index.php?option=com_plugins&task=plugin.edit&extension_id=422
But instead of opening the plugin, I want the user to get redirected to this page:
https://www.example.com/administrator/index.php
To achieve this, I created a .htaccess in the folder administrator and placed the code at the end. So, I set a range of IDs of plugins that user cannot edit, but gets redirected.
Please find the all content of .htaccess file as following:
# Canonical https/www
<IfModule mod_rewrite.c>
RewriteCond %{HTTPS} off
RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
RewriteCond %{HTTP_HOST} !^www\. [NC]
RewriteRule (.*) https://www.%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
</IfModule>
# Redirect plug id from 350 to 423:
RewriteCond %{HTTP_HOST} ^www\.example\.com$
RewriteCond %{QUERY_STRING} (^|&)option\=com_plugins($|&)
RewriteCond %{QUERY_STRING} (^|&)extension_id=\b(3[5-8][0-9]|39[0-9]|4[01][0-9]|42[0-3])\b($|&)
RewriteRule ^administrator/index\.php$ https://www.example.com/administrator/index.php? [L,R=302]
# Redirect plug id from 425 to 10864:
RewriteCond %{HTTP_HOST} ^www\.example\.com$
RewriteCond %{QUERY_STRING} (^|&)option\=com_plugins($|&)
RewriteCond %{QUERY_STRING} (^|&)extension_id=\b(42[5-9]|4[3-9][0-9]|[5-9][0-9]{2}|[1-8][0-9]{3}|9[0-8][0-9]{2}|99[0-8][0-9]|999[0-9]|10[0-7][0-9]{2}|108[0-5][0-9]|1086[0-4])\b($|&)
RewriteRule ^administrator/index\.php$ https://www.example.com/administrator/index.php? [L,R=302]
But does not work.
I create a .htaccess in the folder administrator and placed the code at the end.
# Redirect plug id from 350 to 423:
RewriteCond %{HTTP_HOST} ^www\.example\.com$
RewriteCond %{QUERY_STRING} (^|&)option\=com_plugins($|&)
RewriteCond %{QUERY_STRING} (^|&)extension_id=\b(3[5-8][0-9]|39[0-9]|4[01][0-9]|42[0-3])\b($|&)
RewriteRule ^administrator/index\.php$ https://www.example.com/administrator/index.php? [L,R=302]
If the .htaccess file is inside the /administrator subdirectory then you need to remove administrator/ from the start of the RewriteRule pattern (1st argument), otherwise the rule will never match.
In .htaccess, the RewriteRule pattern matches against a relative URL-path to the directory that contains the .htaccess file.
In other words, it should look like this:
:
RewriteRule ^index\.php$ https://www.example.com/administrator/index.php [QSD,R=302,L]
Also, on Apache 2.4 you can use the QSD (Query String Discard) flag instead of appending an empty query string to remove the original query string.
The preceding conditions that match the query string and plugin id are OK and should match the requested URL. (Although the word boundary \b elements are unnecessary.)
Depending on what other directives you have, this rule should be near the top of the .htaccess file, not "at the end". Since you have used an absolute substitution string it would be more optimal to include these rules before your general canonical redirects (although this does assume you are not implementing HSTS).
You are also missing the RewriteEngine On directive from the rules in question.
So, it should look like this instead:
RewriteEngine On
# Redirect plug id from 350 to 423:
RewriteCond %{HTTP_HOST} ^www\.example\.com$
RewriteCond %{QUERY_STRING} (^|&)option\=com_plugins($|&)
RewriteCond %{QUERY_STRING} (^|&)extension_id=(3[5-8][0-9]|39[0-9]|4[01][0-9]|42[0-3])($|&)
RewriteRule ^index\.php$ https://www.example.com/administrator/index.php? [QSD,R=302,L]
# Redirect plug id from 425 to 10864:
RewriteCond %{HTTP_HOST} ^www\.example\.com$
RewriteCond %{QUERY_STRING} (^|&)option\=com_plugins($|&)
RewriteCond %{QUERY_STRING} (^|&)extension_id=(42[5-9]|4[3-9][0-9]|[5-9][0-9]{2}|[1-8][0-9]{3}|9[0-8][0-9]{2}|99[0-8][0-9]|999[0-9]|10[0-7][0-9]{2}|108[0-5][0-9]|1086[0-4])($|&)
RewriteRule ^index\.php$ https://www.example.com/administrator/index.php [QSD,R=302,L]
# Canonical https/www
RewriteCond %{HTTP_HOST} !^www\. [NC]
RewriteRule ^ https://www.%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
RewriteCond %{HTTPS} off
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
Additional notes:
I assume you have not implemented HSTS.
I reversed the order of your two canonical redirects to reduce the number of redirects when requesting http://example.com/ (HTTP + non-www). But this does assume #1 above.
Optimised the regex on the canonical redirects... no need to traverse and capture the entire URL-path when using the REQUEST_URI server variable.
Removed the word boundary \b from the regex as this would seem unnecessary here.

Need a htaccess redirect rule to ignore a certain folder

I'm redirecting my .com website to .net using this
RewriteCond %{HTTP_HOST} ^cartoonizemypet\.com$ [OR]
RewriteCond %{HTTP_HOST} ^www\.cartoonizemypet\.com$
RewriteRule ^(.*)$ "http\:\/\/www\.cartoonizemypet\.net\/$1" [R=302,L]
Which works (huzzah!) The problem is I need to also exclude a single folder and all of it's contents: http://www.cartoonizemypet.com/catoonizer
I've been messing around with it all day, trying to adapt other peoples from here, but I just keep breaking the site. I'm afraid I just don't know that much about rewrite rules.
Does anyone know how I can make it work?
Try:
RewriteCond %{REQUEST_URI} !^/catoonizer
RewriteCond %{HTTP_HOST} ^cartoonizemypet\.com$ [OR]
RewriteCond %{HTTP_HOST} ^www\.cartoonizemypet\.com$
RewriteRule ^(.*)$ "http\:\/\/www\.cartoonizemypet\.net\/$1" [R=302,L]
Another way of doing it:
# Turn the engine on if it's not already
RewriteEngine On
# Check to make sure we're on the right host (www is optional)
RewriteCond %{HTTP_HOST} ^(www\.)?cartoonizemypet\.com$ [NC]
# Check to make sure we're not at the catoonizer URI (I assume that's a misspelling
# but it's what was in the example).
RewriteCond %{REQUEST_URI} !^(/catoonizer) [NC]
# If all conditions are met, redirect as 302.
RewriteRule ^(.*)$ http://www.cartoonizemypet.net/$1 [R=302,L]

How can I allow specific URL in htaccess?

My root .htaccess in a Magento store ensures that any visits not written as (www.)domain.com/correct will go to our 404 (where "correct" is an existing sub-directory). (www.)domain.com/admin is also allowed through.
I now need to also allow some other URLs that do not follow the (www.)domain.com/correct form.
Presently the code in the .htaccess is:
RewriteCond %{HTTP_HOST} ^domain.com$ [NC]
RewriteRule ^(.*)$ http://www.domain.com/$1 [R=301,L]
RewriteCond %{HTTP_HOST} ^www.domain.com$ [NC]
RewriteRule ^$ go404 [R=301,L]
How can I make the following go through as well (ie NOT go404 on me)?
www.domain.com/correct/index.php/folder1/folder2/folder3/

Redirect subdomain to main domain

I'm dealing with a site that supports both English and Spanish, and I'd like to know how to redirect all the requests to the language-specific subdomains to the main domain (en.mysite.com and es.mysite.com to mysite.com).
The whole site is programmed in PHP and it has a main script index.php that processes the language and section GET parameters and displays stuff accordingly.
Now, I tried to do the following in the .htaccess file in the root of mysite.com. I think it clarifies what I'm trying to do:
RewriteEngine On
# English redirects
RewriteRule ^en.mysite.com$ index.php?language=English&section=Main
RewriteRule ^en.mysite.com/store$ index.php?language=English&section=Store
RewriteRule ^en.mysite.com/create_account$ index.php?language=English&section=CreateAcc
# Spanish redirects
RewriteRule ^es.mysite.com$ index.php?language=Spanish&section=Feed
RewriteRule ^es.mysite.com/comprar$ index.php?language=Spanish&section=Store
RewriteRule ^es.mysite.com/crear_cuenta$ index.php?language=Spanish&section=CreateAcc
But this doesn't work. Can anyone tell me what I'm doing wrong here?
You can't include the hostname as part of the match in a RewriteRule, as it only matches against the URI. You'll need to use a separate RewriteCond that matches against the hostname for each of your rules:
RewriteCond %{HTTP_HOST} ^en.mysite.com$ [NC]
RewriteRule ^$ /index.php?language=English&section=Main
RewriteCond %{HTTP_HOST} ^en.mysite.com$ [NC]
RewriteRule ^store$ /index.php?language=English&section=Store
RewriteCond %{HTTP_HOST} ^en.mysite.com$ [NC]
RewriteRule ^create_account$ /index.php?language=English&section=CreateAcc
Then the spanish rewrites:
RewriteCond %{HTTP_HOST} ^es.mysite.com$ [NC]
RewriteRule ^$ /index.php?language=English&section=Feed
RewriteCond %{HTTP_HOST} ^es.mysite.com$ [NC]
RewriteRule ^comprar$ /index.php?language=English&section=Store
RewriteCond %{HTTP_HOST} ^es.mysite.com$ [NC]
RewriteRule ^crear_cuenta$ /index.php?language=English&section=CreateAcc

Redirect www.domain.com/uk to www.domain.co.uk/uk

I'm no .htaccess expert, but I've tried a few different things to redirect a domain to no avail.
I've got a UK and US domain...some US pages have uk extension, and need to be pointed to the proper UK domain:
www.domain.com/uk needs to be rewritten to www.domain.co.uk/uk
Ex. If someone types in www.domain.com/uk/about it will be rewritten as www.domain.co.uk/uk/about
Edit: Paths with /uk should be rewritten
So www.domain.com/uk and www.domain.co.uk should be rewritten to www.domain.co.uk/uk/
You can try something like this:
RewriteEngine on
RewriteCond %{HTTP_HOST} ^(www\.)?domain\.com$ [NC]
RewriteRule (.*) http://www.domain.co.uk/$1 [L,R=301]
The important point is to use a RewriteCondition that works on the HTTP Host header. Simply speaking, if a RewriteCond is placed before a normal RewriteRule then the rule is only used if the the condition matches.
The code excerpt above redirects all requests from the .COM to the .CO.UK domain, so if you only need to redirect certain directory, then you need to adjust the rule accordingly, e.g.:
RewriteEngine on
RewriteCond %{HTTP_HOST} ^(www\.)?domain\.com$
RewriteRule uk(.*) http://www.domain.co.uk/uk$1 [L,R=301]
Edit: I hope that this will work for you according to your edit.
The first rule rewrites http://www.domain.com/uk and http://www.domain.com/uk/anything to http://www.domain.co.uk/uk/anything.
The second rule rewrites http://www.domain.co.uk to http://www.domain.co.uk/uk/.
Edit 2: I changed the rule (modified the last one and added another one) to reflect the demand for rewrites on .co.uk/something. If the path starts with uk/ then it just passes through, otherwise it gets rewritten to uk/something.
RewriteEngine On
RewriteCond %{HTTP_HOST} ^(www\.)?domain\.com$ [NC]
RewriteRule uk($|/.*) http://www.domain.co.uk/uk$1 [L,R=301]
RewriteCond %{HTTP_HOST} ^(www\.)?domain\.co\.uk$ [NC]
RewriteRule ^uk/(.*) - [PT,L]
RewriteCond %{HTTP_HOST} ^(www\.)?domain\.co\.uk$ [NC]
RewriteRule (.*) http://www.domain.co.uk/uk/$1 [L,R=301]