How to rewrite from /page to /xx/page, using htaccess & apache only?

7,891

Solution 1

This does work (tested):

RewriteCond %{REQUEST_URI} !^/../ [NC]
RewriteRule ^(.*)$ /en$1 [R=301,L]

Apache Mod_Rewrite documentation, Rewrite Guide, and Advanced Rewrite Guide.

Edit:
Tested the above (it's the same as it was before); works on my Apache 2.2 server.

Edit 2:
Should be no problem, just need something like this:

# If just the language is specified (ie example.com/en)
RewriteCond %{REQUEST_URI} ^/..$ [NC]
RewriteRule ^(.*)$ $1/

# If no language subfolder, default to 'en'
RewriteCond %{REQUEST_URI} !^/../ [NC]
RewriteRule ^(.*)$ /en$1 [R=301]

# If no page specified, default to home.
RewriteCond %{REQUEST_URI} !^/../.+ [NC]
RewriteRule ^/(..) /$1/home.html [R=301]

# If no ln query, tack it on
RewriteCond %{QUERY_STRING} !ln= [NC]
RewriteRule ^/(..)/(.*) /$1/$2?ln=$1 [R=301]

Note: Be careful your 404 page works correctly. If it doesn't invalid links will end up in an infinite loop (ie, the 404 page wont work).
Note 2: If the user types in example.com/en, they will be redirected to example.com/en/en?ln=en, so be sure the tailing slash is in the URL, or else.
Note 3: If you want, you can drop the [R=301] from the last rule, then users will see example.com/en/home.html the request to the page will actually be example.com/en/home.html?ln=en. This will not work if your site uses GET requests though.

Edit 3:
Added another cond/rule pair to catch if someone types in just the language, without a trailing slash.

Solution 2

Here is the code I use. It will accept any languages and country.

# Tout pays de 2 digits et langue de 2 ou 3 digits ou juste la langue pas de pays - fonctionne bien et passe language et country
#www.country.com/index.html  devient www.country.com/index.php
#www.country.com/fr/index.html  devient www.country.com/index.php?language=fr
#www.country.com/ca/fr/index.html  devient www.country.com/index.php?country=ca&language=fr
RewriteRule ^([a-zA-Z]{2})/([a-zA-Z]{2,3})/index\.html$ index.html?country=$1&language=$2
RewriteRule ^([a-zA-Z]{2,3})/index\.html$ index.html?language=$1
RewriteRule ^index\.html$ /index.php [L]
Share:
7,891

Related videos on Youtube

Såm
Author by

Såm

Updated on September 17, 2022

Comments

  • Såm
    Såm over 1 year

    Visualise a three step jump sporting event, with the first two steps perfect in place and the third step launching into air, never coming back and eventually a crash! That is what this question boils down to :)

    STEP 1:WORKS serve /somepage?ln=xx when user navigates to /xx/somepage.

    # if user inputs nice urls /xx/somepage  to serve page /someapge?ln=xx
    RewriteRule ^([a-z][a-z])/(.*) /$2?ln=$1 [L]
    

    STEP 2:WORKS go to the homepage when only language is given /xx/

    # if language xx given but no page given? then redirect to its home /xx/home
    RewriteRule ^([a-z][a-z])/?$ /$1/home [R=301,L]
    

    STEP 3:CRASH

    # if user inputs /somepage then redirect to default english: /en/somepage
    # if user inputs /somepage?ln=xx redirect to nice url /xx/somepage
    RewriteCond %{REQUEST_URI} !^/../ [NC]
    RewriteRule ^(.*)$ /en/$1 [R=301,L]
    

    The third rule is where we are stuck... PS: The redirection should work both for extensionless files somepage?ln=xx as well as files with extension somepage.abc?ln=xx where the extension can be any 2 or 3 char-word, or if easier, checked manually with the following extensions i use [.php .uu .u3c .vls]

    Thanks a Thousand!

  • Såm
    Såm over 13 years
    thanks Chris, but gives error: page isn't redirecting properly and nothing appears.
  • Philip
    Philip over 13 years
    @Sam, just checked it, it works as expected. What error? Sure you got the curly brackets, parenthesizes, and braces correct?
  • Såm
    Såm over 13 years
    Thanks Chris, gave you a great comment for your persintence/checking. 1) when /somepage is typed: goes into a loop /enenenenenenenenenenenenenenensomepage and gives error 2) when / is typed (just domain no page) it gives redirect error in firefox, nothing loads)
  • Såm
    Såm over 13 years
    Repacing !^/../ with ![^/.]+ gives no errors, but also doesnt redirect /somepage to /en/somepage ... i have the feeling its the condition that is causing the error... language folders are two lowercase chars. is !^([a-z][a-z]) a better condition? unfortunately loops also when /somepage is typet, giving a url like: /enenenenenenenenenenenenenenenenenenenenhome.php
  • Philip
    Philip over 13 years
    It's possible your Apache server is interpreting something slightly different; try replacing /en$1 in the rule with /en/$1. Are there any other rules in the .htaccess file?
  • Såm
    Såm over 13 years
    Already did that, same: nothing appears. Firefox says redirection error. [hands in my hair from this problem!]
  • Philip
    Philip over 13 years
    What version of Apache are you running? If you manually type in /en/somepage.php does it show up correctly?
  • Såm
    Såm over 13 years
    Gosh, i'm in all ways against any wars! so how should i make them sing peace? Perhaps the Conditional rules together with the [ ] endings can help to chain these three rules into one elegant rule. should i start a new question and mark yours as answered?
  • Philip
    Philip over 13 years
    @Sam, it's probably be easiest to just edit the other rules into this question and include exactly how you want requests to be handled.
  • Såm
    Såm over 13 years
    Dear Chris, thanks very much for your dedication! I am new to the community and already love it. Rephrased my entire question hope its much more clear. Curious to your new insights.
  • Philip
    Philip over 13 years
    @Sam, yep, got it now I think.
  • Såm
    Såm over 13 years
    Wauw looks prmising, before i check, i will just give you the well deserved points for a real answer, thanks so much! A note Chris, the language is always a two letter word (see in my question [a-z][a-z] which i believe covers that specific thing. While any actual page is a word, longer than two characters... Cant this information help separate the two sothat site.com/en/ or site.com/en both work without apache thinking /en is a page?
  • Såm
    Såm over 13 years
    Thanks Chris. With the new rules in place on my Apache/2.0.54 (Fedora) each and every of the rules crash :( no results come out. Strange! old rules work good, except the last wish. Boy i wished i spoke this exotic Apache more fluently sothat i could get this fixed... sigh
  • Philip
    Philip over 13 years
    @Sam, are there any error messages produced? It's all just perl regex and typical flow control (both of which take some getting used to).
  • Såm
    Såm over 13 years
    have tried to catch the errors but firefox timeouts.. I just had a marvelous idea! i could install your code, remember the time, and then when the errors come, check immediately in the log files in my plesk account! perhaps i can see the error message there, cause the browser wont give any specific error... will check back soon. Thanks for suggestions!