Tell me more ×
Stack Overflow is a question and answer site for professional and enthusiast programmers. It's 100% free, no registration required.

I'm looking for a regulair expression for a .htaccess file inside my PHP server.

What I want is that it detects the language from the first directory as parameter:

  • nl
  • en
  • be
  • de

Any other options must be treated as a directory or filename. The language must be given as parameter without corrupting any other parameters.

Also I want the last / replaced by .php.

Some examples:

host.com/nl/index/ -> host.com/index.php?lang=nl
host.com/de/test/abc/ -> host.com/test/abc.php?lang=de
host.com/be/a/b/c/?t=23 -> host.com/a/b/c.php?lang=be&t=23

Is this possible? I can't get it to work, I hope someone will help me out!

<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME}.php -f
RewriteRule >>> requested expression and replacing pattern <<<
</IfModule>
share|improve this question
Do the language directories (nl etc.) actually exist? – Ravi Thapliyal Jul 17 at 17:15
@Ravi Well, for now. But I want to get rid of those. If you meant if there would exists any directory called nl, de, be or en: no, I will prevent that, especially if needed. – Tim Jul 17 at 17:16

3 Answers

up vote 2 down vote accepted
RewriteRule ^/([a-z]{2})(/.+)/?$ $2.php?lang=$1 [QSA]

Regexes are easiest to interpret by considering a piece at a time. Let's break that down:

  • ^ - start of URL
  • / - match first slash
  • ([a-z]{2}) - match and capture 2 letters (goes into the $1 variable)
  • ( - begin capture group (goes into $2)
  • / - match a slash
  • .+ - match zero or more characters
  • ) - end capture group ($2)
  • /? - match an OPTIONAL end slash of the "file path" (but don't capture it)
  • $ - end of URL

So, you're capturing two things:

1. the language (capture group $1):

([a-z]{2})

2. the file path, starting with a slash (capture group $2), followed by an optional slash:

(/.+)/?

Finally, the QSA flag at the end appends your original query string (if there was one) to your rewritten URL. If you'd like to make your regex match case-insensitive (i.e. allow URLs like host.com/NL/index/), you can add the NC flag too: [QSA,NC]. Alternatively, you could explicitly allow capital letters by using [A-Za-z] instead of [a-z] in your regex.

share|improve this answer
Thanks for the clear and working answer. I basically already understood regular expressions, but this one was a bit too hard for me since I don't know how it coöperates which the .htaccess script. Can you tell me which kind of regex it uses? Also my index file won't work anymore. – Tim Jul 17 at 18:46
Also it can't figure out why this is working with multiple directories. Does the (/.+) capture more than one / for the .? Seems weird to me. – Tim Jul 17 at 18:49
Think of them separately. The / has nothing to do with the .. / matches a slash. . matches "any character". + means "one or more of the previous". So, /.+ matches a slash followed by one or more characters (ANY characters). That means it would match /hello or /hello/ or /hello/how/are/you or even /hello$'()/whatever/. If you'd like to make that rule more restrictive, instead of ., you could use [\w/], which matches any word character OR slash. so /[\w/]+ would match /hello and /hello/how and /hello/how/are/ but not /hello/hfo$'()/ – sgroves Jul 17 at 19:01
@sgroves Thanks, that part sounds as easy as you say it is. But how can it match the last / while it should already being matched by the .? – Tim Jul 17 at 19:06
@Tim short answer: that's just how the regex engine works. because i explicitly tell the regex to match a / AFTER the .+, the + won't match the last / in the string. it will, however, match any previous slashes because it's a greedy quantifier. @anubhava correct - this answer does not try to match the query string – sgroves Jul 17 at 19:11
show 1 more comment

Enable mod_rewrite and .htaccess through httpd.conf and then put this code in your .htaccess under DOCUMENT_ROOT directory:

Options +FollowSymLinks -MultiViews
# Turn mod_rewrite on
RewriteEngine On
RewriteBase /

RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{DOCUMENT_ROOT}/$2.php -f
RewriteRule ^([a-z]{2})/(.+?)/?$ /$2.php?lang=$1 [L,QSA,NC]
share|improve this answer
Thanks for your answer. What are the options doing and why must the base directory be set the /? Also, could you provide me a link where I can get information about [L,QSA,NC]? – Tim Jul 17 at 18:51
Check this official guide: httpd.apache.org/docs/current/rewrite/flags.html Pls try out this answer and see if this works. If it does I will add more explanation answering all your questions. – anubhava Jul 17 at 19:04
RewriteBase sets the path to which %{REQUEST_FILENAME} is relative. (By default, %{REQUEST_FILENAME} is relative to your file system root, which is almost definitely not what you want. That's why people use RewriteBase /. Here, / is the root of the directory containing your .htaccess file. – sgroves Jul 17 at 19:15

Try this

RewriteRule ^([a-z]{2})/(.+)/?$ /$2.php?lang=$1 [QSA]
share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.