PYovchevski
PYovchevski

Reputation: 115

Multilanguage and mod_rewrite

I have a multilanguage website. I want the URL's to be like: http://example.com/en/blog_post/2 where blog_post is the name of the file blog_post.php and 2 is value of the parameter id.

I have this .htaccess code now

Options +FollowSymLinks
RewriteEngine On

RewriteRule ^(bg|en)/(.*)$ /$2?lang=$1 [L]
RewriteRule ^(bg|en)/(.*)/([^/.]+)$ /$2?lang=$1&id=$3 [L]

RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule (.*) $1.php [L]

I tried with this line, but it doesn't work:
RewriteRule ^(bg|en)/(.*)/([^/\.]+)$ /$2?lang=$1&id=$3 [L]

Can you help me please :)

Upvotes: 5

Views: 235

Answers (2)

MrWhite
MrWhite

Reputation: 45829

As mentioned above, the order of these directives is important. The more specific rules should come before the more general rules and this is a key problem with the above. However, the pattern also needs to be changed (made more specific) to prevent other malformed URLs triggering a 500 Internal Server Error and breaking your site. eg. /en/blog_post/2/3 (an additional - erroneous - /something) would still trigger a 500 error in the "fixed" code above.

So, this could be written as:

Options +FollowSymLinks
RewriteEngine On

RewriteRule ^(bg|en)/([^/.]+)$ /$2?lang=$1
RewriteRule ^(bg|en)/([^/.]+)/([^/.]+)$ /$2?lang=$1&id=$3

RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME}.php -f
RewriteRule (.*) /$1.php [L]

The generic (.*) pattern has been replaced with ([^/.]+) to only match path segments (excluding a slash). By doing this it also means that the order no longer matters and /en/blog_post/2/3 will simply result in a 404.

I've also removed the L flag on the initial RewriteRule directives, since you need to continue anyway to append the .php extension.

The RewriteRule substitutions should also be kept as root-relative, ie. starting with a slash. (Or you should include the RewriteBase directive.)

I've also added another RewriteCond directive to make sure that <file>.php actually exists before appending the file extension. If you don't do this and <file>.php does not exist then you will get another 500 error.

You could combine the two RewriteRules into one if you don't mind having an empty id= parameter (which presumably your script handles anyway):

RewriteRule ^(bg|en)/([^/.]+)(?:/([^/.]+))?$ /$2?lang=$1&id=$3

This handles both /en/blog_post and /en/blog_post/2 requests.

Upvotes: 1

PYovchevski
PYovchevski

Reputation: 115

I did it. It works with these lines. Thanks to everyone :)

Options +FollowSymLinks
RewriteEngine On

RewriteRule ^(bg|en)/post/([^/\.]+)$ blog_post.php?lang=$1&id=$2 [L]
RewriteRule ^(bg|en)/(.*)$ $2?lang=$1 [L]

RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule (.*) $1.php [L]

Upvotes: 1

Related Questions