Попробую "разжевать" всё как для школьника

К примеру, имеем ссылку вида index.php?option=com_adsmanager&view=details&id=5&catid=3&Itemid=120. После включения SEF ссылка разбивается на части (параметр=значение) и записывается в ассоциативный массив $query, где в качестве ключа выступает имя параметра, а в качестве значения - значение параметра соответственно. Т.о. после передачи ссылки в JRoute имеем массив:
$query["option"]=>"com_adsmanager"
$query["view"]=>"details"
$query["id"]=>"5"
$query["catid"]=>"3"
$query["Itemid"]=>"120"
Как раз с таким массивом Joomla предлагает работать разработчику роутера компонента! Для работы с SEF разработчику предлагаются 2 функции:
1. для построения (билдинга) ЧПУ-ссылки, имя функции имеет вид ComponentNameBuildRoute, где ComponentName - название компонента, в качестве аргумента для функции выступает вышеописанный массив $query. Возвращает движку массив $segments для построения новой "красивой" ссылки! Если пункт меню указывает на компонент и настроен aliac, то из новой ссылки автоматически уберутся параметры option и Itemid, а если включен mod_rewrite, то уберётся ещё и index.php
2. для разбора (парсинга) ЧПУ-ссылки, имя функции имеет вид ComponentNameParseRoute, в качестве аргумента для функции выступает полученный ранее массив $segments!
Возвращает движку массив $vars для возврата ссылки к исходному виду.
Но это всё только теория, давайте рассмотрим на конкретном примере с adsmanager'ом и категориями:
Открываем файл роутера и смотрим в функцию AdsmanagerBuildRoute(&$query) и видим строку преобразования категории
$segments[] = $query["catid"]."-".getAdsmanagerRouteCategory($query["catid"]);
Функция getAdsmanagerRouteCategory посылает запрос в БД на выборку имени категории по её id и возвращает это имя в "безопасном" виде (строка $result= JFilterOutput::stringURLSafe($result)

, но нам не нужно транслитить имя категории, поэтому нужно либо переписать функцию stringURLSafe либо написать свою и заменить на неё вызов из класса JFilterOutput. Теперь удалим из ссылки id категории, т.е. приведём к виду
$segments[] = getAdsmanagerRouteCategory($query["catid"]);
. Т.о. получаем красивую ссылку, но теперь функция AdsmanagerParseRoute не знает id категории и везде "перебрасывает" на "Все объявления", а чтобы получить id нужно написать функцию противоположную функции getAdsmanagerRouteCategory, т.е. по названию категории получить её id запросом к БД. Затем в функции AdsmanagerParseRoute заменить все
$catid = explode( ':', $segments[0] );
$vars['catid'] = (int) $catid[0];
на
$vars['catid'] = (int) Ваша_функция($segments[0]);
Таким же макаром делаем и для других параметров ссылки (если надо)! Надеюсь, что понятно изложил, аж замучился печатать