Mass URL aliasing
Drupal also comes with user defined mass URL aliasing capabilities. You might like to see completely different URLs used by Drupal, or even URLs translated to the visitors' native language, in which case this feature is handy. Only an administrator with access to the website source code can set up this kind of aliases. You can define a function somewhere in your code (even in settings.php), following this example:
<?php
// Example for Drupal 4.6.x
function conf_url_rewrite($path, $mode = 'incoming') {
if ($mode == 'incoming') { // URL coming from a client
return preg_replace('!^display/(\d+)$!', 'node/\1', $path);
}
elseif ($mode == 'outgoing') { // URL going out to a client
return preg_replace('!^node/(\d+)$!', 'display/\1', $path);
}
}
?><?php
// Example for Drupal 4.7.x and up
function custom_url_rewrite($type, $path, $original) {
// This path was already aliased, skip rewriting it
if ($path != $original) {
return $path;
}
if ($type == 'source') { // URL coming from a client
return preg_replace('!^display/(\d+)$!', 'node/\1', $path);
}
elseif ($type == 'alias') { // URL going out to a client
return preg_replace('!^node/(\d+)$!', 'display/\1', $path);
}
}
?>This function will shorten every node/$node_id type of URL to display/$node_id. Individual URL aliases defined on the browser interface of Drupal take precedence, so if you have a 'contact' page alias for example, then the display/3 alias will not be effective when outgoing links are created. Incoming URLs however always work with the mass URL aliased variant. Only two modes are supposed to be supported by your custom function.
You cannot only use this feature to shorten the URLs, or to translate them to you own language, but also to add completely new subURLs to an already existing module's URL space, or to compose a bunch of existing stuff together to a common URL space. You can create a news section for example aliasing nodes and taxonomy overview pages falling under a 'news' vocabulary, thus having news/15 and news/sections/3 instead of node/15 and taxonomy/term/3. You need extensive knowledge of Drupal's inner workings and regular expressions though to make such advanced aliases.

Settings.php
I think it is important to note that (at least for 4.6 - I haven't seen 4.7 on this yet) you must put this function in your settings.php file.
I tried to put it in a module, but was met with some very confusing results (outgoing translations worked like a charm, incoming translations were horribly broken).
Here's why you need custom_url_rewrite in settings.php
Looking at the core drupal code (4.7.4), here's why custom_url_rewrite needs to be in settings.php.
API documentation
Karoly just documented it at api.drupal.org:
http://api.drupal.org/api/HEAD/function/custom_url_rewrite
With more examples.
--
http://www.reuniting.info/
Healing with Sexual Relationships.
http://www.wechange.org/
We live in a world of solutions.
Updated links
Ironically, this alias doesn't work anymore :)
Documentation for Drupal 5.x:
http://api.drupal.org/api/function/custom_url_rewrite/5
Documentation for Drupal 6.x:
http://api.drupal.org/api/function/custom_url_rewrite_outbound/6
http://api.drupal.org/api/function/custom_url_rewrite_inbound/6
openflows.com
My custom_url_rewrite
I looked in to the example in http://api.drupal.org/api/function/custom_url_rewrite/5
I change some thing and I get off the fourth arg "$path_language" because I got an error msg.
Finally, my function is:
<?phpfunction custom_url_rewrite($op, $result, $path) {
//global $user;
$items = array(
array( 'source'=>'node', 'alias'=>'articulo', 'patron'=>'/^%item%(.*)$/', 'result'=>'%item%\1'),
array( 'source'=>'taxonomy', 'alias'=>'categoria', 'patron'=>'/^%item%(.*)$/', 'result'=>'%item%\1'),
array( 'source'=>'term', 'alias'=>'termino', 'patron'=>'/\/%item%\//', 'result'=>'/%item%/'),
array( 'source'=>'user', 'alias'=>'usuario', 'patron'=>'/^%item%(.*)$/', 'result'=>'%item%\1'),
array( 'source'=>'blog', 'alias'=>'blog', 'patron'=>'/^%item%(.*)$/', 'result'=>'%item%\1'),
array( 'source'=>'forum', 'alias'=>'foro', 'patron'=>'/^%item%(.*)$/', 'result'=>'%item%\1'),
array( 'source'=>'image', 'alias'=>'imagen', 'patron'=>'/^%item%(.*)$/', 'result'=>'%item%\1'),
array( 'source'=>'aggregator', 'alias'=>'noticias', 'patron'=>'/^%item%(.*)$/', 'result'=>'%item%\1')
);
if ($op == 'alias') {
// source to alias. Ej: node -> articulo
$reemplazos = array();
foreach( $items AS $item ) {
$key = str_replace('%item%',$item['source'],$item['patron']);
$value = str_replace('%item%',$item['alias'],$item['result']);
$reemplazos[$key] = $value;
}
return preg_replace(array_keys($reemplazos), array_values($reemplazos), $path);
}
if ($op == 'source') {
// alias to source. Ej: articulo -> node
$reemplazos = array();
foreach( $items AS $item ) {
$key = str_replace('%item%',$item['alias'],$item['patron']);
$value = str_replace('%item%',$item['source'],$item['result']);
$reemplazos[$key] = $value;
}
return preg_replace(array_keys($reemplazos), array_values($reemplazos), $path);
}
// Return the default result
return $result;
}
?>
As you can see, you can specify a pattern for each item.
The most common pattern is
'/^%item%(.*)$/', that only get the item if is in the beginning, but you may be interested in other patterns: "term" (like intaxonomy/term/3) is not at the beginning of the string, so it will not work with the most common pattern, this item will need a pattern like'/\/%item%\//'.Yo can add as many items as you want, and you can also write a module to put them all through the admin.