Routing URLs with language in Laravel - php

I want to add a localization information to my routes.
Currently my route definitions are:
Route::controller('browse');
Route::controller('search');
Route::controller('support');
Route::controller('filter');
I want to change URLs from /url/browse to /url/en/browse etc.
If language is missing from the URL then the application should redirect to the same route with default language. This means accessing the old /url/browse would redirect to /url/default/browse.
I tried to make or find some simple solution with filters, unsuccessfully.
Thanks for help!

Try to use the Default Application Language and Supported Languages array in config.
If you put a language in the supported languages any route starting with that segment will set the current language and that will be considered the root url.
One difference from your requirements is instead of a redirection the default language will be accepted without the language in the url.
Edit: A filter which may help you with the redirect.
Route::filter('pattern: *', array('name' => 'langredirect', function()
{
$uri = Request::server('request_uri');
$segments = explode('/', $uri);
if ( ! array_get(Config::get('application.languages'), $segments[1]) )
{
return Redirect::to(URL::base() . '/' . Config::get('application.language') . $uri);
}
}));

Related

Translate Laravel route param

I'm using Laravel 5.6 and trying to sort out what's the best method to translate a route.
I use top level domain to sort the locale so
mydomain.pt -> locale pt
mydomain.es -> locale es
mydomain.com -> locale en
I created a middleware to handle this
class Language
{
public function handle($request, Closure $next)
{
$url_array = explode('.', parse_url($request->url(), PHP_URL_HOST));
$top_domain = end($url_array);
if(!empty($top_domain)){
App::setLocale($top_domain);
}
}
}
This is working fine and the translated strings within the respective files work when i switch domain.
However i want to be able, for SEO purposes, to have links like this
mydomain.pt/dynamic/perto-de-mim
mydomain.es/dynamic/cerca-de-mi
mydomain.com/dynamic/near-me
What's the best approach in laravel to get my route
Route::get('{category}/near-me/', 'ServicesController#nearMe');
To work with all the examples above?
Thank you
Laravel allow you to provide translation string :
/resources
/lang
/en
routes.json
/es
routes.json
In resources/lang/es/routes.json :
{
"near-me": "cerca-de-mi"
}
And your route become :
Route::get('{category}/' . __('routes.near-me') . '/', 'ServicesController#nearMe');
You could see here the use of the Laravel helper method __() to retrieve the translation from the xx/routes.json files.

Generating language changing urls in laravel

I have decided to prefix all my routes with a $locale-variable. This is code found from googling:
$locale = Request::segment(1);
if (in_array($locale, Config::get('app.available_locales'))) {
App::setLocale($locale);
} else {
$locale = null;
}
Route::group(array('prefix' => $locale), function() {
//All my routes
});
Now, I would like to generate URL:s dynamically for jumping between locales. I want a way to generate the current url or route, but replace the $locale-parameter. You should be able to write something similar to this pseudocode:
route(Route::Current(), [$locale => 'foo'])
Question:
I want to take my current URL and replace one argument in it. How do I do that?
Update 1:
Giving my route a name, I'm able to do this:
route('index', 'foo') //Gives mywebsite.com?foo
This however, does not produce the wanted result, mywebsite.com/foo. It instead generates mywebsite.com?foo. My guess is that route doesn't understand that this route is nested and prefixed with a fragment, so it treats my argument as a parameter instead. Specifying that it is the locale I want to change does not help:
route('index', ['locale' => 'foo']) //Gives mywebsite.com?locale=foo
Update 2:
Changing the prefix to instead say:
Route::group(array('prefix' => '{locale?}'), function() {
Makes route() work:
route('index', ['locale' => 'foo']) //Gives mywebsite.com/foo
It does however ruin some url:s inside the group, as some of them start with variables. The following route inside the route-group stops working:
Route::get('/{id}', 'FooController#showFoo');
As routes.php interprets the url mywebsite.com/foo as 'foo' now being the language. If there is some way to set a default value in routes.php for locale so that you could write it as {route} instead of {route?} and have it redirect to a default locale if it was missing, the problem would be solved.
Update 3:
Moving in the direction of having 'prefix' => '{locale?}' instead leads into way too many sub-problems to be worth pursuing. The issue comes back to generating urls from the current url but inserting language into the url. I am currently considering doing this with just a regex replacement because it is the most straight-forward solution.
I didn't test this, but you could try to do it like this way.
If no parameter is given, you can easily redirect to the default locale route. If first parameter is given, you need to check if it's a correct locale.
use Illuminate\Support\Facades\Request;
$defaultLocale = 'en';
Route::get('/', function() use ($defaultLocale) {
return redirect('/' . $defaultLocale);
});
Route::group(array('prefix' => '{locale}'), function($locale) use ($defaultLocale) {
if(!in_array($locale, Config::get('app.available_locales'))) {
return redirect('/' . $defaultLocale . '/' . Request::path());
}
// All your routes
});
So I ended up not solving this with laravel magic, I wrote my own code.
The Route::Group remains the same, the code I use to create URL:s to different languages looks like this:
<a href="{{ change_locale_url('en') }}"</a>
The change_locale_url-function is just a regex function which uses URL::Current to get the current url and then either inserts or replaces the input string as a language parameter in the url.
When I'm on mywebsite.com/about, the function outputs mywebsite.com/en/about
When I'm on www.mywebsite.com/de/about, the function outputs www.mywebsite.com/en/about
When I'm on http://mywebsite.com, the function outputs http://mywebsite.com/en
As a reminder, when using this route group you need to create links using action('HomeController#index') to have the locale follow you to the next link. Linking to /about will remove any language currently selected.

Is there any built-in convenient mechanism to generate relative URLs?

1- Laravel url function generates a fully qualified URL to the given path. I need to generate relative path and only prepend them the site base url. I seems unlike other well-known framework it does not have a config to set the base URL. What is the correct way to generate relative paths?
2- On the other hand, if, for example, the user requests http://url/base/user/1/edit url, how to only get the user/1/edit part?
I don't remember
$uri = Request::path();
or $url = $request->path();
You can try. Hope this help
You may use URL::to('/'); anywhere in your app to refer to the base url and to get the part of the url you can use :
public function someFunction(Request $request)
{
$firstpart = $request->segment(1);
$secondpart = $request->segment(2);
// and so on
}

Remapping Codeigniter Controller

I've been playing with Codeigniter lately, and I came to know that you can remap a function inside a Controller so that you can have dynamic pretty URL.
I just want to know can the same be done with controllers? I mean If I call http://example.com/stack, it'll look for a controller named stack and if not found, it'll call a fixed/remapped controller where I can take care of it.
Can this be done?
Maybe this can help you:
function _remap( $method )
{
/// $method contains the second segment of your URI
switch( $method )
{
case 'about-me':
$this->about_me();
break;
case 'successful':
$this->display_successful_message();
break;
default:
$this->page_not_found();
break;
}
}
Yes, it can be done, you achieve it by using uri routing.
In your application/config/routes.php you can set your custom routes to remapping URIs.
There are already 2 provided, the default one (in case no controller is called) and the 404 error routing.
Now, if you want to add custom routes, you just add them UNDER those 2 defaults, keeping in mind that they're executed in the order they're presented.
Say, for example, you want to remap 'stack' to another controller, just use:
$routes['stack'] = 'othercontroller';
In this way, whenever you access 'stack' it will be automatically mapped to 'othercontroller', and if that doesn't exists..well, you get the same 404 error.
If you're hiding index.php from the URL with .htaccess remember to insert it into the $config['index_page'] = 'index.php';.
If what you're trying to achieve, instead, is a custom error message when a controller is not found, just override the 404 route as already suggested by #Juris Malinens, using your custom default controller to handle that situation
$route['404_override'] = 'customcontroller';
You can use .htaccess to do this or config/routes.php- Codeigniter is very flexible ;-)
If controller is not found use $route['404_override']; in config/routes.php
The application/config/routes.php file would be the appropriate place to do this. The 404_override mentioned by Juris is only available in CI 2.x just in case you have an older version (I don't know, you may be working on a legacy system, or may have to in the future).
Note, you can do more than just "remap" controllers with this. The routes accept regex patterns like htaccess rewrite rules; there are also some CI patterns which are basically just more human readable alias for regexes. Say you had an Articles controller with category, search and article functions, you might have routes that looked like:
$route["category/(:any)"] = "articles/category/$1";
$route["search/(:any)"] = "articles/search/$1";
$route["(:any)"] = "articles/article/$1';
You see how you can use routes to completely remove the controller name from you URLs? These rules would fall back to assuming the page is an article if the URL doesn't specifically say it's a category page or a search query. You could then check if you had an article for the URL and display a 404 as appropriate.

Zend Framework application with login and signup pages on one domain and other pages on the subdomain

We develop a zend framework application and want that signup pages and login pages were on our domain for example http://domain.com (now all pages are on http://domain.com) and other pages (where you have to be redirected after authentification) on subdomain: http://subdomain.domain.com.
Could you please tell how to solve it?
Thank you for any ideas.
I've done this kind of thing in a major ZF app of mine. It's a complicated 3-part question, but hopefully this will get you started in the right direction.
First is the session cookie. You'll need to use a wildcard domain parameter when you set the session cookie. In your Bootstrap or somewhere prior to when you would normally start your session, include a line such as:
Zend_Session::start(array('cookie_domain' => '.domain.com'));
Note the dot (".") prior to "domain.com". This makes the cookie applicable for domain.com as well as all subdomains under it.
Second is the URL's throughout your site. You can use the Redirector action helper's gotoUrl() method. At the end of an action method when you want to redirect the user, use a line like this:
$this->_redirector->gotoUrl('http://domain.com/somewhere/else');
Of course, you may want to assemble the URL string by other means such as storing the domain in a configuration parameter and concatenating the path using one of ZF's native methods of generating a URL path. See the documentation for Zend_Controller_Action_Helper_Redirector for more. You'll also need to be careful about all URL's on your site and make sure the right domain is included in each link.
Third is how your app interprets routes when subdomains are involved. There are a few ways to accomplish this, but one is to create a module within your app that corresponds to each subdomain you want to use. Then use a Controller Plugin to intercept ZF's normal routing mechanism and set the module name appropriately based on the subdomain. Something like:
class My_Controller_Plugin_RouteMySubdomains extends Zend_Controller_Plugin_Abstract {
public function routeShutdown(Zend_Controller_Request_Abstract $request) {
$hostname = $request->getHttpHost();
if (strlen($hostname) > strlen('domain.com')) {
$moduleName = preg_replace("/\.domain\.com$/", '', $hostname);
$request->setModuleName($moduleName);
}
}
}
You'll need to tell ZF to use this plugin. If you're using Zend_Application with an application.ini file for basic configuration, you'll need to add a line like this:
resources.frontController.plugins.routeMySubdomains = "My_Controller_Plugin_RouteMySubdomains"
Good luck!

Categories