views:

369

answers:

2

I have a very long a unfriendly URL an I'm looking to make SEO better for the site:

http://www.site.com/sub-site/index.php?page=nameofpage&locale=en_EN

I would like to have this instead: http:// www.site.com/sub-site/en/nameofpage

all the URLS are hard coded in the links in the form of:

<a href="index.php?page=nameofpage&locale=en_EN">link</a>

What is the best way to achieve this with mod-rewrite? I find it particularly difficult to achieve:

  • combining both parameters, page and locale
  • Turning ISO locales EN_en to en in the URL
  • How should I write links? using the result URL or the index.php?page... controller scheme?

EDIT: I'm going mad! I can't make it work!! Feel so stupid... but, Could anyone help me with the exact .htaccess file I need to pull this off? Thanks!

A: 

EDIT: I went through and tested this out on one of my servers. This works fine for me:

RewriteEngine On
RewriteRule ^sub-site/([a-z_]+)/([a-z0-9_-]+)$ /sub-site/index.php?locale=$1&page=$2

This gets you most of the way there, but it doesn't do the locale translation (en => en_EN), it just delivers the locale as-is to the PHP script. Using mod_rewrite, I'd recommend RewriteMap; however, if you only have access to .htaccess (like on a shared host), you can't use RewriteMap.

So then, to accomplish the locale translation, I think you'd be best off doing it on the PHP side. You could either use one of the frameworks listed below, or just do it yourself.

In case you do have access to the virtual host configuration, you'd make a text file like:

en en_EN
fr fr_FR
ca fr_CA

If that file was located at /path/to/localemap.txt, you'd have:

RewriteMap locales txt:/path/to/localemap.txt
RewriteRule ^sub-site/([a-z_]+)/([a-z0-9_-]+)$ /sub-site/index.php?locale=${locales:$1|en_EN}&page=$2

This defaults to en_EN if nothing's found in the map.

Hope that helps!


If you're just using .htaccess, then mod_rewrite will easily do what you want.

You'd probably want to look into RewriteMap for your categories or locale, although you could just grab that part of the URL and use it as a parameter directly. Here's an example to get you started:

RewriteRule /sub-site/([a-z_]+)/([a-z0-9_]+) /sub-site/index.php?locale=$1&page=$2

You'd really want to narrow down the regular expressions used to make them more specific to your supported locales and categories, but I think it's a decent starting point.

Other PHP frameworks, especially those focused on MVC, also provide similar URL routing functionality. Examples:

Tim Ridgely
yes, I got to mod-rewrite a while ago but found it kind of tricky to set up. I would like to know which lines to add so that my URL can look like I want.
Landitus
Even with the frameworks you mention, then only way to get "clean" urls as specified by the OP is through mod_rewrite.
kurige
Not at all; the reason I mention the frameworks is that that you could avoid mod_rewrite use. Check out the Kohana doc for example, in the "Using regular expressions" section. He could easily take a regex there and map it to whatever he wanted. Obviously the locale and page are params to a PHP script now, so it'd be easy enough to put in a controller and call via routing.
Tim Ridgely
Ah, we're talking about the same thing. What I mean is that without mod_rewrite there is not way to remove `index.php` from the url, and therefore the url will not be "clean". No framework can do that for you.
kurige
A: 

mod_rewrite is an incredibly complex beast. This should get you started, though! Just read up on the documentation and play around with it. You'll get the hang of it soon enough!

<IfModule mod_rewrite.c>
    RewriteEngine On
    RewriteBase /

    # Checks to see if the user is attempting to access a valid file,
    # such as an image or css document. If this isn't true, it sends the
    # request to index.php
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteCond %{REQUEST_FILENAME} !-d

    RewriteRule ^(.*)/(.*)$ index.php?locale=$1&page=$2
    RewriteRule ^(.*)$      index.php?page=$1
</IfModule>

Edit: You should copy and paste this into a .htaccess file.

kurige
This may sound dumb, but... Do I have to redo all the site links now? If this works, should I replace all hardcoded links to the new URL scheme?
Landitus
The first thing I notice is that CSS stylesheets don't apply anymore. Moreover, I can't get URLs to work. I am really stuck!
Landitus
Soon as I get a chance I'll play around with it on a test server and see if I can't edit my post with a more exact `.htaccess` file.
kurige
Great! Cause I still can't get it to work.
Landitus