... and that's why [R=301] must always be accompanied by [L]. It may seem intuitively obvious that when you redirect, the new URL gets kicked outside to start all over again. But in fact it doesn't; it carries on through mod_rewrite, possibly being exposed to further rewrites or redirects.
# www consolidation
RewriteCond %{HTTP_HOST} !^www\.example\.com [NC]
RewriteRule ^(.*)$ http://www.example.com/$1 [R=301]
# remove trailing slash
RewriteCond %{HTTP_HOST} ^(www.)?example\.com$ [NC]
RewriteRule ^(.+)/$ http://www.example.com/$1 [R=301,L]
OK, stop right there. You rewrote to with-www in the first rule, so why are you suddenly including (www.)? in the second rule? There should no longer
be any without-www forms. (Incidentally the literal period should be escaped-- but if there is anything other than a period in that location, it would never reach your domain anyway.)
In fact the rewrite should cover
all possibilities:
%{HTTP_HOST} !(^www\.example\.com$)?
meaning "exactly www.example.com or exactly nothing" (
the "or nothing" is something involving http 1.0 that you can look up if you want to) to make sure you also intercept weird requests containing a port number. And this should be your very last redirect, to pick up only those requests that have not already been redirected for other reasons.
It works with the exception of the URL below. It's not rewritten properly.
example.com/en/hello == to ==> www.example.com/en/hello
It becomes http://www.example.com/http://www.example.com/en/hello//hello
That isn't the only exception. It's just the only one you happened to find while testing. By rule #1, example.com/en/hello becomes www.example.com/en/hello. But it doesn't leave your htaccess yet; it continues through all your other Rules. Rule#2 doesn't apply, since there is no trailing slash. But anything could be lurking in the rest of the Rules.
RewriteRule ^/en$ /en/index [L]
Why it gives me 404 error?
Whew. That's the easy one. Because there is no such page as www.example.com//en --and that's what your Pattern looks for. Leave off the leading slash.
But why are you
rewriting to a filename ending in /index without extension ? That's not a "real" page, so you're going to have to rewrite and/or redirect all over again in order to end up at something that can serve content.
Incidentally, ^(.*)$ is always redundant. By default, Regular Expressions start as soon as they can and continue as long as they can. The opening and/or closing anchors are only necessary when you are matching some specific text in the beginning or ending location.