RewriteCond %{HTTP_HOST} ^(www\.)?example.com$ [NC]
RewriteCond %{REQUEST_URI} !^/fr/.*$
RewriteRule ^(.*)$ /fr/$1 [L,R=301,NC]
These directives don't simply redirect "http://www.example.com
to http://example.com/fr
". They redirect http://www.example.com/<anything>
to http://www.example.com/fr/<anything>
.
But it slows down my website like crazy...
There is nothing particularly wrong with the directives you have posted, but...
My guess is that you are linking to other pages/resources without the /fr/
path segment. Which is then resulting in multiple external redirects for each page view - this could potentially slow down your site (although these are 301 redirects so should be cached by the browser).
If this is the case, then you either need to fix your internal links to include this /fr/
path segment. Or, perhaps exclude static resources from this redirect (if the URL is still valid without the /fr/
path segment)?
For example, to exclude all static resources, modify your directives like:
RewriteCond %{HTTP_HOST} ^(www\.)?example\.com$ [NC]
RewriteCond %{REQUEST_URI} /(.*)
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule !^fr/ /fr/%1 [R=301,L]
This will now prevent static resources (physical files) from being redirected (whether that is still valid I don't know).
I've also optimised your directives slightly (nothing that will cause a major speed up though). I've moved the negated check for /fr/
to the RewriteRule
pattern, rather than using a RewriteCond
directive for this. The RewriteRule
pattern is processed first, so it is better to include your first check here if you can (otherwise every URL will be processed). The URL is then grabbed from the condition instead (%1
instead of $1
backreference in the RewriteRule
substitution). No need to use the NC
(NOCASE
) flag if it's not explicitly needed.
UPDATE#1:
example.com/fr
(without the trailing slash at the end), [...] redirects to example.com/fr/fr
To resolve this, you can change the RewriteRule
pattern to exclude an exact match for /fr
or a URL that starts /fr/
, for example:
RewriteRule !^fr(/|$) /fr/%1 [R=301,L]
This will now prevent example.com/fr
from being redirected. (However, is that a valid URL? You now have two URLs: example.com/fr
and example.com/fr/
presumably accessing the same resource?)
Here is my complete code
:
RewriteCond %{REQUEST_FILENAME} -f [OR]
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^ - [L]
:
Since you've added your "complete code" to your question I see that you already have an "exception" block (the 3 directives above) that excludes static resources from be rewritten - it's just that it's in the wrong place, now that you've added the additional directives above.
You should move these 3 directives to directly below the RewriteBase
directive (ie. at the top). Although you'll need to exclude the document root from this (by changing ^
to !^$
- see below) in order to allow /
to be redirected to /fr/
- since the document root is also a directory. You can then remove the RewriteCond %{REQUEST_FILENAME} !-f
directive from the block above (in the first part of this answer).
UPDATE#2 So, in summary...
(Updated to include the canonical www to non-www redirect at the start. This then allows us to simplify the later condition that checks against HTTP_HOST
.)
Options +FollowSymLinks
RewriteEngine on
RewriteBase /
# Canonical www to non-www redirect
RewriteCond %{HTTP_HOST} ^www\.(example\.com)$ [NC]
RewriteRule (.*) http://%1/$1 [R=301,L]
# Exception: Exclude files and directories (except the document root)
RewriteCond %{REQUEST_FILENAME} -f [OR]
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule !^$ - [L]
RewriteRule ^index\.php$ - [L]
# Redirect all requests to /fr/ subdirectory
RewriteCond %{HTTP_HOST} =example.com [NC]
RewriteCond %{REQUEST_URI} /(.*)
RewriteRule !^fr(/|$) /fr/%1 [R=301,L]
RewriteRule ^([_0-9a-zA-Z-]+/)?wp-admin$ $1wp-admin/ [R=301,L]
RewriteRule ^([_0-9a-zA-Z-]+/)?(wp-(content|admin|includes).*) $2 [L]
RewriteRule ^([_0-9a-zA-Z-]+/)?(.*\.php)$ $2 [L]
RewriteRule . index.php [L]