good day everyone, I'm struggling to solve a redirection but without any success.
I changed the URLs of my site forcing a default language, before it was site.com/help/ and now it's site.com/en/help/
Thanks to anubhava I made the redirection, but then i faced a new problem with the AMP pages: site.com/amp/help/ are now redirected to site.com/en/amp/help/ while they are supposed to be site.com/amp/en/help/.
Again, thanks to Anubhava, I changed the structure of URLs to site.com/en/help/amp/ (amp always at the end). To achieve this, I had to delete the .php extention I had in some pages and also decided to remove the trailing slash.
I'm now facing 2 new issues: the 301 redirection to a non .php page and URLs with trailing slashes to a non trailing slash don't work :( bellow is my htaccess code
RewriteEngine on
# amp
RewriteRule ^(.*/)?amp/(.+?)/?$ /$1$2/amp [R=301,NC,L]
## redirect to default language (fr)
RewriteCond %{ENV:REDIRECT_STATUS} !200
RewriteCond %{REQUEST_URI} !/inc
RewriteCond %{REQUEST_URI} !/ajax/
RewriteCond %{REQUEST_URI} !/img/
RewriteRule ^(?![a-z]{2}(?:[/-]|$))(.*)$ /fr/$1 [R=301,L,NE]
## Unless directory, remove trailing slash
RewriteCond %{ENV:REDIRECT_STATUS} !200
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.+)/$ /$1 [R=301,NE,L]
## add trailing slash in front of directories
RewriteCond %{DOCUMENT_ROOT}/$1 -d
RewriteRule ^[a-z]{2}(?:-[a-z]{2})?/(.+)$ /$1/ [L]
# remove .php
RewriteCond %{ENV:REDIRECT_STATUS} !200
RewriteCond %{REQUEST_FILENAME} !global.js
RewriteCond %{REQUEST_URI} !/ajax/
RewriteCond %{REQUEST_URI} !results.php
RewriteRule ^(.+)\.php(.*)$ /$1$2 [R=301,NC,NE,L]
## amp pages
RewriteRule ^(.*)/amp$ /$1?amp=1 [NC,QSA,L]
## folders of languages
#RewriteRule ^([a-z]{2}(?:-[a-z]{2})?)/(.*)$ /$2?lang=$1 [QSA,L]
RewriteRule ^([a-z]{2}|[a-z]{2}-[a-z]{2})$ /$2?lang=$1 [QSA,L]
RewriteRule ^([a-z]{2}|[a-z]{2}-[a-z]{2})/(.*)$ /$2?lang=$1 [QSA,L]
## hide .php extention
RewriteCond %{REQUEST_FILENAME}.php -f
RewriteCond %{REQUEST_FILENAME} !global.js
RewriteRule ^(.+?)/?$ $1.php [L]
Have it this way:
RewriteEngine on
# changed amp URLs
RewriteRule ^(.*/)?amp/(.+?)/?$ /$1$2/amp/ [R=301,NC,L]
## redirect to default language (en)
RewriteCond %{ENV:REDIRECT_STATUS} !200
RewriteCond %{REQUEST_URI} !/img/
RewriteRule ^(?![a-z]{2}(?:[/-]|$))(.*)$ /en/$1 [R=301,L,NE]
## Unless directory, remove trailing slash
RewriteCond %{ENV:REDIRECT_STATUS} !200
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_URI} !/amp/$ [NC]
RewriteRule ^(.+)/$ /$1 [R=301,NE,L]
## add trailing slash in front of directories after lang rewrite
RewriteCond %{DOCUMENT_ROOT}/$1 -d
RewriteRule ^[a-z]{2}(?:-[a-z]{2})?/(.+[^/])$ /$0/ [L]
# remove .php
RewriteCond %{ENV:REDIRECT_STATUS} !200
RewriteRule ^(.+)\.php$ /$1/ [R=301,NC,NE,L]
## amp pages
RewriteRule ^(.+/)amp/?$ /$1?amp=1 [NC,QSA,L]
## folders of languages
RewriteRule ^([a-z]{2}(?:-[a-z]{2})?)/(.*)$ /$2?lang=$1 [QSA,L]
## hide .php extention
RewriteCond %{REQUEST_FILENAME}.php -f
RewriteCond %{REQUEST_FILENAME} !global.js
RewriteRule ^(.+?)/?$ $1.php [L]
Explanation of this trailing slash rule:
## add trailing slash in front of directories after lang rewrite
RewriteCond %{DOCUMENT_ROOT}/$1 -d
RewriteRule ^[a-z]{2}(?:-[a-z]{2})?/(.+[^/])$ /$0/ [L]
Take an example URI: /fr/cart
.
In a later rule we remove lang
component from URL and pass it as lang=<fr|en>
query parameter. Part after lang
parameter e.g. /cart
doesn't have a trailing slash and if it is a real directory then /cart?lang=fr
will be redirected to /cart/?lang=fr
by Apache's mod_dir
module and your internal URL will be exposed in browser.
So in this current rule we capture part after lang
component and check if we don't have a trailing slash and it is a directory then this rule internally rewrites to /fr/cart/
with a trailing slash. Later rule then rewrites it to /cart/?lang=fr
and mod_dir
doesn't redirect anymore.
as usual, thank you very much @anubhava for your time and precious help, I swear i would buy you a beer to thank you if we were in the same city :)
Your solution works perfectly well except for one little case: /fr/amp/page.php
redirects to /fr/page.php/amp
, i had to make some changed to your code and managed to make it work. Bellow is your updated code with small changes i made:
1- removed some slashes at the end of some rules as i don't need them anymore
2- removed this rule RewriteCond %{REQUEST_URI} !/amp/$ [NC]
3- I absolutely didn't understand what "add trailing slash in front of directories" is for, would you mind explaining it to me please?
4- I have noticed that you replaced (?![a-z]{2}/|[a-z]{2}-[a-z]{2}/)(.*)$
by (?![a-z]{2}(?:[/-]|$))(.*)
, what's the difference? just to be more clear and accurate, the folder of languages can be something like site.com/be-fr (french for belgium)
5- same for ([a-z]{2}|[a-z]{2}-[a-z]{2})
that has been replaced by ([a-z]{2}(?:-[a-z]{2})?)
i'll need to capture the whole string (be-fr), so should I use ([a-z]{2}(-[a-z]{2})?)/(.*)
or simply back to ([a-z]{2}|[a-z]{2}-[a-z]{2})
6- to fix the .php problem, i replaced RewriteRule ^(.+)\.php$ /$1/ [R=301,NC,NE,L]
by RewriteRule ^(.+)\.php(.*)$ /$1$2 [R=301,NC,NE,L]
is that okay?
7- just realized a second problem that i didn't manage to fix, it comes from ## folders of languages. site.com/fr returns a 404, it's because probably because of the slash in the rule :/
RewriteEngine on
## changed amp URLs
RewriteRule ^(.*/)?amp/(.+?)/?$ /$1$2/amp [R=301,NC,L]
## redirect to default language (en)
RewriteCond %{ENV:REDIRECT_STATUS} !200
RewriteCond %{REQUEST_URI} !/img/
RewriteRule ^(?![a-z]{2}(?:[/-]|$))(.*)$ /en/$1 [R=301,L,NE]
## Unless directory, remove trailing slash
RewriteCond %{ENV:REDIRECT_STATUS} !200
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.+)/$ /$1 [R=301,NE,L]
## add trailing slash in front of directories
RewriteCond %{DOCUMENT_ROOT}/$1 -d
RewriteRule ^[a-z]{2}(?:-[a-z]{2})?/(.+)$ /$1/ [L]
# remove .php
RewriteCond %{ENV:REDIRECT_STATUS} !200
RewriteRule ^(.+)\.php(.*)$ /$1$2 [R=301,NC,NE,L]
## amp pages
RewriteRule ^(.+/)amp$ /$1?amp=1 [NC,QSA,L]
## folders of languages
RewriteRule ^([a-z]{2}(?:-[a-z]{2})?)/(.*)$ /$2?lang=$1 [QSA,L]
## hide .php extention
RewriteCond %{REQUEST_FILENAME}.php -f
RewriteCond %{REQUEST_FILENAME} !global.js
RewriteRule ^(.+?)/?$ $1.php [L]