FastRoute
FastRoute copied to clipboard
remove defualt language from url
I have Multi language CMS For Front and Admin Page.
For English language(defualt without en
):
example.com/articles/
For France Language(with fr
):
example.com/fr/articles/
Now, for my url Like This code:
$dispatcher = FastRoute\simpleDispatcher(function(FastRoute\RouteCollector $r) {
$r->addRoute('GET', '/{lang:(?:en|fr)}/articles', 'get_all_users_handler');
});
$httpMethod = $_SERVER['REQUEST_METHOD'];
$uri = $_SERVER['REQUEST_URI'];
// Strip query string (?foo=bar) and decode URI
if (false !== $pos = strpos($uri, '?')) {
$uri = substr($uri, 0, $pos);
}
$uri = rawurldecode($uri);
$routeInfo = $dispatcher->dispatch($httpMethod, $uri);
switch ($routeInfo[0]) {
case FastRoute\Dispatcher::NOT_FOUND:
echo 'BAd';
break;
case FastRoute\Dispatcher::METHOD_NOT_ALLOWED:
$allowedMethods = $routeInfo[1];
// ... 405 Method Not Allowed
break;
case FastRoute\Dispatcher::FOUND:
$handler = $routeInfo[1];
$vars = $routeInfo[2];
echo 'Found Found';
break;
}
My Url Routed And Work With (fr
and en
) path method:
example.com/en/articles
and example.com/fr/articles
.
But I need to remove default language from url. How do fix this problem ?!
From my experience, it is better to remove the language from the URI before using it with FastRoute.
// ...
$uri = rawurldecode($uri);
$parts = explode('/', ltrim($uri, '/'));
$lang = array_shift($parts);
$uriWithoutLang = implode('/', $parts);
$routeInfo = $dispatcher->dispatch($httpMethod, $uriWithoutLang );
// ...
:warning: Note: the piece of code above doesn't work properly if a URL is called without any language (example.com/articles), you have to set the default language and process the URI correctly.
My Problem Exactly this: I need to Call Url for default language(en) Without language
example.com/articles/
And Call For Another Language With fr
example.com/fr/articles/
there are various ways to manage a default language. This could be the topic of en whole article... so basically our starting point is this: your website is multilingual and accepts a limited set of languages (for example : "en", "fr", "es", "de") and you have a default language (for example "en"). Here's the code:
// ...
// this is list of languages my site accepts
$languages = ['en', 'fr', 'es', 'de'];
// this is my default language
$defaultLang = 'en';
// $currentLang is the language I'll use to show the contents
$currentLang = $defaultLang;
$uri = ltrim(rawurldecode($uri), '/');
$parts = explode('/', $uri);
if( ! empty($parts) && in_array(strtolower($parts[0]), $languages)) {
$currentLang = array_shift($parts);
}
// routableUri is the URI you'll provide to FastRoute
$routableUri = implode('/', $parts);
// ...
You can go further... for example, if no language is found in the URI, you can look into the request headers (the "accept" header).
You test This Code?! I change your code for test to the function like this:
function urlss(){
$uri = $_SERVER['REQUEST_URI'];
$languages = ['en', 'fr', 'es', 'de'];
// this is my default language
$defaultLang = 'en';
// $currentLang is the language I'll use to show the contents
$currentLang = $defaultLang;
$uri = ltrim(rawurldecode($uri), '/');
$parts = explode('/', $uri);
if( ! empty($parts) && in_array(strtolower($parts[0]), $languages)) {
$currentLang = array_shift($parts);
}
// routableUri is the URI you'll provide to FastRoute
$routableUri = implode('/', $parts);
return $routableUri;
}]
Now, test in my localhost:
localhost/cms/users
echo $routableUri;
And output is:
cms/users
this output not true for your idea and not work true. can u check your idea in full code and then share it. Thanks
The easiest way would be to move the language after the "articles" bit, so that you could have an /{section}[/{lang}]
route definition. You could also write a second route with the same handler but without the lang part, and you'd be settled.
@perspolise : no I didn't test the code I sent. It wasn't meant to be taken "as-is". The idea was more to give a track/hint. I think it's difficult to provide a code you can simply copy/paste and push the button to get it run (a dream we all share to save time and go running in fields of flowers). My main point is to invite you thinking of a strategy to manage the languages for your application. My basic suggestion is:
- define a list of available languages for your application,
- define a default language you'll use when, a. there is no language provided (localhost/cms/users), b. the provided language is unknown (localhost/ru/cms/users).
- in your code, get the currentLanguage (ex: en) and the routableURI, a URI without any language in it (ex: cms/users): this is exactly what the purpose of the code I provided in my previous message.
- call FastRoute (indeed we're in a thread related to that repository) using the routableURI and store the currentLanguage somewhere so that you'll be able to use it in your route handler.
I hope I was clear enough and good luck to you!
@perspolise I had the same issue a couple of weeks a go, I was trying to implement exactly what you need for a website built with Slim framework
domain.com
domain.com/es
domain.com/es/about
domain.com/about
but, this is not possible :(
$r->get('/{lang}/{page}')
I found a (possible) solution building a dispatcher using FastRoute and parsing my url manually.
Url parsing (pseudo code):
$langs = ['en', 'es'];
$url = '/es/about';
if ($url string has any of $langs) then
remove url id from url
define('lang', 'es') so, now I can use the selected language from anywhere in my page code
My new url after removing the language:
$url = '/about';
You can see the working code here
Now I only had to build a dispatcher for my well formatted url (without language id on it)
// New RouteCollector
$router = new \FastRoute\RouteCollector(
new \FastRoute\RouteParser\Std,
new \FastRoute\DataGenerator\GroupCountBased
);
// Building routes for website
$router->get('/', 'landing');
$router->get('/about/', 'about');
// Create new dispatcher object
$dispatcher = new \FastRoute\Dispatcher\GroupCountBased($router->getData());
// Dispatch for the current route
// remember that at this point my $url is "/about" and my language is in a defined constant
$dispatcher = $dispatcher->dispatch('GET', $url);
// Website found HTTP_OK
if ($dispatcher[0] === \FastRoute\Dispatcher::FOUND) {
// code to show my website
}
You can see the working code here
This is just an experiment just to solve the problem with the optional language parameter in url, I'm working so hard testing this "framework" to migrate my websites from Slim framework some point in the future.
Any comments are always welcomed :)
@ldonis : Working code link is not found. please update
Personal preference:
$dispatcher = FastRoute\simpleDispatcher(function(FastRoute\RouteCollector $r) {
$r->addRoute('GET', '/{lang:(?:en|fr)}/articles', 'get_all_users_handler');
$r->addRoute('GET', '/articles', 'get_all_users_handler');
});
Where lang is defined as: $lang = $args['lang'] ?? $default_lang;