I'm using laravel and mcamara/laravel-localization package to manage a bilingual site (french/english).
In the package documention https://github.com/mcamara/laravel-localization
they don't explain how to point an URL to the right view depending on which language is set as local.
For example, if the URL is /en/contact load the view en.contact (en is the subdirectory for views written in english) and id the URL is /fr/contact load the view from the subdirectory fr.
The same for the URL that needs translation /en/products for english needs to load /fr/produits when the local language is set to french.
Disclaimer: I have never used the package...
That's because the package (and also the localization of laravel) assume that you are using Laravel's translations. So the package basically only worries about setting the application locale right and Laravel does the rest of the job.
However if you need different views (or don't want to use translations) you can just retrieve the current locale and use it to build the name of the view
View::make(App::getLocale().'.contact');
You have to change the view-path dynamically, so you dont have to prefix your views by hand.
Just create a new Middleware and register it in Kernel.php.
I've created a gist for that.
https://gist.github.com/vanderb/80dea9a8039dd60962c5cb291eae7b75
Now, all you have to do is to reference the view-name, without adding the lang-code every time.
I also recommend to use named-routes
https://laravel.com/docs/5.4/routing#named-routes
I don't see why you would want to use different views for each language. That would double your code. Just use one view with Laravels own translation features to translate your strings. The package handles the naming of routes (/products vs /produits). The views should stay the same.
If you really want different views for different languages, #lukasgeiter has the answer. Sounds like a code-duplication, though.
Side-note: Laravel 5.4s new JSON translation feature together with langman is really great.
Related
I'm trying to make a reusable Dashboard for my apps, so I decided to put everything in a folder like app/Dashboard. I've managed to have routes, controller, middlewares, etc. But, now I'd like to have views also in that folder. I added the path in config/view.php, the problem with that is that if I have two views with the same name in app/Dashboard/Views and in the default resources/views, of course the view in the default path would be loaded.
Do you have a better idea? Can I do something like return view('dashboard:login') in my controller using only the Laravel standard tools?
Look at this part of the documentation https://laravel.com/docs/5.5/packages#views. You are almost right, but you need to use two colons
return view('dashboard::login');
Coming from a straight PHP and Drupal background, I am recently learning the Symfony2 framework. Currently I am in the routing chapter of the book. This is probably a simple question.
What are some real world use cases for why one would want to generate URLs in a Symfony app? I understand the code but I'm having a bit of trouble determining its practical applications.
I'm referring to this section should you need a refresher.
As always, thank you!
P.S. Symfony is amazing. :)
Basically, you need to generate a URL whenever you need to link to anywhere in your application.
Let's say that you have an application that needs to manage some users. This means that you will probably have URLs like /user/create, /user/edit/(user id) and /user/remove/(user id).
Whenever you display a link to edit a user you need to know on what URL you can find the page that allows you to edit a user. So you need to link to /user/edit/(user id). One solution would be to have this as a fixed link so that in your code you could just write
edit this user
But what if you want to change this URL scheme? Let's say someone is unhappy with the term "user", after all the humans managed by this system are not only users, they are actually "person"s! So now you need to change all the URLs containing "user". Probably there are quite a few places in your app where you have had to hardcode these URLs and now you will need to find and change all of them. Eugh.
But fear not, for Symfony routing comes to the rescue!
Instead of hardcoding these URLs, we can simply let the Symfony router generate them for us. This means that we first need to tell Symfony which routes we have, e.g. by adding the following YAML code to our routes config file:
user_edit:
path: /user/edit/{userId}
defaults: { _controller: AppBundle:User:edit }
requirements:
userId: \d+
This tells our application "Okay, whenever somebody requests a page that looks like /user/edit/{userId}, then you need to call the editAction method in our UserController class in the AppBundle namespace and you need to pass the userId as a parameter. Oh, and also you should only call the controller if userId is a valid integer with at least one number."
So this is how Symfony knows how to map URLs to controllers. But the goodness that comes along with it is that we can use this information for the reverse way as well.
Usually, in our application we do not really care about what the URL looks like for a certain action we want to perform. All we know is that when clicking a certain link, then the browser should jump to a page that allows me to edit a user. And since we just defined a route that takes us right there, we can have Symfony generate the correct URL to achieve just that.
So in your view you can now discard the hardcoded URL from earlier and instead replace it with a route generated by the Symfony router:
edit this user
Now whenever you need to change what the URL actually looks like all you need to do is edit your routing config and not a lot of separate views.
Because, imagine you want to change a given page URL and you've hardcoded it in 10 Twig templates. You will have to modify all these files. On the opposite, when using the routing component:
You would only have to change the URL where the route is defined.
The routing component "takes" care of the current environment you are using (dev, prod...)
Also note that is a bad practice to "switch environment", a typical issue is to hardcode an URL in a Javascript. In this case you can expose your Symfony2 routes in the Javascript by using a bundle like FOSJsRoutingBundle.
I almost immediately realized their use and now I feel silly. :) For those who stop by this question in the future:
Notes about Generating URLs:
Similar to the Drupal l() function, sometimes you need to generate links inside your application based on a variety of parameters.
You don't always want to hardcode your links in case you decide to change paths sometime down the line.
In summary: Think of this as an alternative to using straight anchor tags with href elements all over the app and, instead, keeping things dynamic.
Use case
In the project I'm working I use generateUrl to redirect the user
after creating, editing an entity.
For example after creating a Service entity, I redirect the user to the view
of the just created Service.
Controller
return $this->redirect($this->generateUrl('myentity_view', array('id'=> $id)));
Additional note
In twig files, you can use the path function which call the routing component and generate url with given route name and parameters.
DO I UNDERSTAND MVC CORRECTLY?
I've read many posts by the user teresko and I think I finally understand the real concept of modern MVC. I made a diagram of how I understand it to be, I'm hoping somebody can confirm this for me and that maybe this diagram will help some other users.
IS MY PLANNED DIRECTORY STRUCTURE "SMART"?
Also I'd like to get into folder structure. I'm not too sure that I plan on using a very smart/efficient way of structuring them. In my root directory I have 4 folders. The model folder contains 3 subdirectories called data_mappers, domain_objects and services. The presentation folder contains 2 subdirectories naturally called views and controllers. The 3rd folder in my root directory is one of the ones I'm less sure on called lib and contains another 3 sub-folders, scripts, themes, and templates (is this a good place for templates that will be called by view?). And the last folder which I have is called config (if anybody can think of a better name suggestions are welcomed). This is where I will place the router and base classes and any files of that type. I'm not just going for functionality with my framework, I want it to be technically sound, any suggestions/advise are welcome, I want to make sure my understanding up to this point is correct before I start making the index and router etc so I don't have to start over once again. Thanks
IS THIS A GOOD WAY TO GO ABOUT MULTI-LANGUAGE SUPPORT IN MVC?
(A little off topic, but I need to incorporate this into planning my MVC framework, it may be helpful to other users, and in order to answer the question clearly and concisely the structure of the website needs to be understood and it happens to be described in detail in the above)
My website must be available in English and French, both of which I happen to speak. I plan to create two more sub-folders within the templates folder, one called en and and another fr and simply place all of the English templates in en folder and translate them into French and place them in fr folder and set up the website so www.mywebsite.com/en/home shows the template in English and www.mywebsite.com/fr/home shows the template in French.
There will be a main language selection page that will redirect you to either en or fr. Then, I plan to store the 2 letter language code in a $_SESSION variable. The view will use this $_SESSION variable to pick which template to display. This is the way I had done it on the old version of my website. Is this a good way of accomplishing multi-language support in MVC or is there some better way?
What if I want to make the url also appear in French? If I put the view files inside more subfolders and instead of naming them like this: "/presentation/views/news/news.php" name them like this: "/pre
sentation/views/news_nouvelles/news.php" and then make the router (urls and routing is one of my weaknesses, but I will learn on my own ;) store everything before the "_" in a variable corresponding to the English url, and everything after corresponding to the French url. This is just a theory and I have not attempted what is in this last paragraph yet, the multi-language support is more for discussion than a question, although once again, it is relevant because a thorough understanding of my framework is needed to answer/discuss language support.
This really isn't all that related to MVC.
When you are implementing multilingual URLs, it's all about routing.
Routing
Basically, by the time your code gets to calling stuff on controller, you should have fully initialized request instance, that has recognized language from the URL and translated all the parts of input into something useful for creating instances.
$request = new Request($query);
$router = new Router;
$router->import('/path/to/routes.json');
$router->route( $request );
At this point you would have split the user's query (from example: '/presentation/view/dernières/nouvelles') into recognized segments, based on pattern that was recognized.
Lets take for example, that matted pattern was in config defined as:
/presentation[[/:action[/:filter]]/:resource]
And the produced result is:
resource >> 'nouvelles'
action >> 'view'
filter >> 'dernières'
Internationalization
The translations will usually be stored either in database or in some configuration file.
If your service factory is already initialized at this point, then you can dip into that for facilitating the interaction with this stored config:
$normalizer = new Normalizer( $serviceFactory->create('translation') );
$normalizer->adjust($request);
What you would collect from stored config by translating it would be
translation of the value that user provided in query
language in which that query fragment was written
title which corresponds to the fragment
The data that you get back would look something like:
translation | language | label
-------------------------------------
view | en | view
dernières | fr | latest
nouvelles | fr | news
Note: if you return also the queried value, then you can perform such operations with a single SQL query using .. WHERE translation IN ( <the list> ), which let you collect all in a single request.
These entries are used for two tasks:
actually translating the request so that the matched parameter will actually have classes/methods that correspond to them
for determining, which language user might expect
By the end of this you should have a translated ll the parameters in the Request instance and, based on some criteria, determined and added language parameter to that request.
Note: browser also sends some language-related information to you in the headers. Depending on your setup, you could user Accepted-Language header for figuring out which language user might prefer.
my 2 cents
CI looks for Segment[1] for controller (in controller dir) and Segment[2] for Method. Now, I have specific requirement by business application which needs that I do not want CI to look or by force go to controller dir to load but I will have something like this "domainURL/module_identifier_id/controller/method/".
Here, every request will be coming along with its associated Module's Identifier ID which will have complete module's configuration and other data (controller files, module location where it was uploaded, all menus and their URLs which will have same URL mechanism which we want to design for developers to develop modules and upload) stored in DB.
We need to get this ID and play with it to fetch relevent records and point CI to load controller from where we want it and indeed rest for methods etc every thing needs to be working as it is.
I hope you understand what we are looking for that we have our own main controller type file where all of the requests will be coming with customizing protocol as described above and developers will be following it by all means, that there must be module identifier first and then controller, method etc...
Let me know if you have any query to be cleared on?
I think I would just use routes for this:
$route[(:any)/(:any)/(:any)] = '$2/$3/$1';
This should just rearrange your segments the way you want, without completely changing the way the native routing system works.
I have to manage a multilingual routing as part of a Symfony2 project.
In order to get the whole URL translated i have to access the EntityManager from the PHP routing file to get the proper translation and the translated slugs.
Does anyone know how to do that ?
Thanking you,
Antoine.
May be you have to make separate third-level domain for each language (ru.site.com, fr.site.com) and generate routes using your database translation table from template?
What I could suggest you is to check the JMSI18nRoutingBundle. This bundle let you define localized routes. Here ta copy of the overview text for the bundle taken from the documentation:
Overview
This bundle allows you to create i18n routes. Key points:
uses the Translation component; translate URLs just like you would translate any other text on your website
allows you to use different hosts per locale
does not require you to change your development processes
can translate all routes whether they are coming from third-party bundles, or your own application
I did not use it myself and I'm not the developer of this bundle and I don't know if it will work for your slug. But I hope this will help you in some ways.
Regards,
Matt