I am using Silex and Twig for a website and I want to allow the user to change the langage of the site.
Right now, it works if I change the loca
I finally find a solution to do what I want, using pmaxs/silex-locale
(https://github.com/pmaxs/silex-locale).
As I said in my question, I already used it for my translation but I didn't used the "Url generation" as I should...So here is a recap of how to use it (read the documentation if you use Silex v1.x):
1/ Loading Provider
$app->register(new \Pmaxs\Silex\Locale\Provider\LocaleServiceProvider(), [
'locale.locales' => ['en', 'fr'], //I want to translate my site in English and French
'locale.default_locale' => 'en', // By default, the locale is "en"
'locale.resolve_by_host' => false,
'locale.exclude_routes' => ['^_']
]);
$app->register(new Silex\Provider\LocaleServiceProvider());
2/ Usage
Here is my home route controller :
// this page is accessible by urls '/', '/fr/' or '/en/'
$app->match('/', function (Request $request) use ($app) {
// my code
return $app['twig']->render('home.html.twig');
})->bind('home');
As you can see, I have no {_locale}
variable in my routing, but still can use it to change the langage of my page.
3/ Url generator
Now, here is how I change my langage :
{% set locale_list = ["en", "fr"] %} // the list of all langage in my website
{% set current_locale = global.request.getLocale() %} // the current langage of my page
<li id="drop-langue">
// I display the current langage
<span id="current-lg">{{ current_locale|upper }}</span>
<div class="drop-langue">
<div id="list_langue">
{% for locale in locale_list %}
{% if locale != current_locale %}
// I create one link to change the langage according to all the langage I want, minus the current langage
<a class="change_langue" href="{{ locale_generate(locale , global.request.get('_route')) }}" >
<span>{{ locale|upper }}</span>
</a>
{% endif %}
{% endfor %}
</div>
</div>
</li>
I'm using the "Url Generator", it works like this : locale_generate('es', $name, $parameters = array(), $referenceType = UrlGeneratorInterface::ABSOLUTE_PATH)
(more details in the documentation).
This way, when I come in my website I'm in english (my default locale) with my "clean Url" /
. Then by clicking on FR
my url become /fr/
and my content is translate in French with a new selection menu (current-langue = FR and I can select "EN").
The simple idea here is: how your application determines the language to be used to render the pages.
solution #1 (your current solution) based on a URL parameter (that's _locale
), and fallback to some default value in case no URL-parameter given.
So in this solution the translation component always looks for the selected language in the parameters bag prepared by the router component.
Solution #2 put your language identifier inside a session variable.
Your /new-langue
page will have to set this session variable with the value it receives. and your router will populate the _locale
parameter from that session variable.
I may be able to provide some code snippets a bit later.
So, from your message, i can extract your goal is to allow the language to be changed when you click on an HTML element.
The usage of the a tag defines a hyperlink, which is used to link from one page to another and can be used to achieve what you want.
I've done multilang sites previously and you can achieve this in a variety of ways.
///////////////////////////////Method 1: define the location in the HTML attribute href
In your HTML code you've used hash - # within the hyperlink .
Hyperlinks require the href property, because it specifies a location.
Looking at your code, you have the tag but it's missing the link to the specific location you want to redirect the user to.
Let's say you want it to go to my-account
page in french.
So, your HTML code should be:
<li id="drop-langue" data-lg="en">
<span id="current-lg">EN</span> // My current langue
<div class="drop-langue">
// The list of langage the user can choose : here ONE -> FR
<div id="list_langue">
<a class="change_langue" href="http://yourwebsite.com/fr/my-account" data-lg="fr"><span>FR</span></a>
</div>
</div>
</li>
To note: substitute yourwebsite.com with your website's domain.
///////////////////////////////end of Method 1
In your HTML code you mention // Could be nice to change the langue staying on the same page
.
That can be done using AJAX, yes.
But I don't suggest you to do that because from looking at bigger companies that also have websites in multiple languages such as SAP or Apple they all redirect to a different page.
///////////////////////////////UPDATE: the answer until now was created because I thought your need was simply to allow the language to be changed when you click on an HTML element.
Apparently, your goal is slightly more complex than that.
Accordingly to Silex documentation, the usage of _locale
is the way to go.
In this question you can see working code:
<?php
require_once __DIR__.'/../vendor/autoload.php';
$app = new Silex\Application();
$app['debug'] = true;
$app->register(new Silex\Provider\UrlGeneratorServiceProvider());
$app->register(new Silex\Provider\TwigServiceProvider(), array(
'twig.path' => __DIR__.'/../views',
));
$app->register(new Silex\Provider\TranslationServiceProvider(array(
'locale_fallbacks' => array('hr'),
)));
$app['translator'] = $app->share($app->extend('translator', function($translator) {
$translator->addLoader('xlf', new \Symfony\Component\Translation\Loader\XliffFileLoader());
$translator->addResource('xlf', __DIR__.'/../locales/hr.xlf', 'hr');
$translator->addResource('xlf', __DIR__.'/../locales/en.xlf', 'en');
$translator->addResource('xlf', __DIR__.'/../locales/sl.xlf', 'sl');
return $translator;
}));
$app->get('/', function () use ($app) {
$app['translator']->setLocale('hr');
return $app['twig']->render('home.twig', array('d' => $app['translator']->getLocale()));
});
$app->get('/{_locale}/', function() use ($app) {
$app['translator']->setLocale($app['request']->get('locale'));
return $app['twig']->render('home.twig', array('d' => $app['translator']->getLocale()));
});
$app->run();
In you case its just the matter of adding proper links to allow users so they can switch language. Rest of the work is already done by you. The language switcher dropdown must contain all supported languages including English. See below am example image.
Instead of redirecting the users to http://yourwebsite.com/[fr]/my-account
you must redirect to a special method like http://www.yourwebsite.com/language_change?lang=fr
. You will get HTTP_REFERRER
in $_SERVER
variable so you can redirect users back to the original page they were at. This way you can preserve users current visiting page/url.
Secondly, Ajax vs Redirect: Its better to use a redirect instead of AJAX. If you use AJAX you will increase the complicity to yourself.
When working with multilingual website, we must follow these best practices.
Specific routes per language
Menus, labels and forms
The content of the website
Extra: translate FOSUserBundle