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 locale in the URL :
/my-account
: my page content is in English (default _locale)
/fr/my-account
: my page content is in French
/en/my-account
: my page content is in English
How can I do the do the same by clicking on an html element?
I am looking for some idea to solve my problem and some good practice to do this "the right way" if possible.
Here is the Silex component I use to manage the multilangue :
// TRANSLATION
$app->register(new Silex\Provider\LocaleServiceProvider());
$app->register(new Silex\Provider\TranslationServiceProvider());
$app->register(new \Pmaxs\Silex\Locale\Provider\LocaleServiceProvider(), [
'locale.locales' => ['en', 'fr'],
'locale.default_locale' => 'en',
'locale.resolve_by_host' => false,
'locale.exclude_routes' => ['^_']
]);
$app->extend('translator', function($translator, $app) {
$translator->addLoader('yaml', new YamlFileLoader());
$translator->addResource('yaml', __DIR__.'/../src/locales/en.yml', 'en');
$translator->addResource('yaml', __DIR__.'/../src/locales/fr.yml', 'fr');
return $translator;
});
Here is my html for the user to change the langage:
<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="#" data-lg="fr"> <span>FR</span></a> // Could be nice to change the langue staying on the same page
</div>
</div>
</li>
Now my jQuery to get the value :
$(document).ready(function() {
$(".change_langue").on("click", function() {
var new_langue = $(this).data("lg");
$.ajax({
url: "{{ path('new-langue') }}",
type: 'POST',
data: {'langue': new_langue},
success: function (resp) {
console.log(resp);
},
error: function (resp) {
console.log(resp);
}
});
});
});
My Ajax controller :
$app->match('/new-langue', function (Request $request) use ($app) {
$new_langue = $request->get('langue');
// some code to change the langage
return New Response($new_langue);
})->bind('new-langue');
If I do this, my Ajax success console.log(resp);
give me en
as I want.
fr
by en
in my url it works, is it a good idea to try to do it in javascript using window.location.href
for example? (I think not but still asking)500 (Internal Server Error)
(I did the same, with $new_langue
instead of $app['defaultLanguage']
and with the right name for my homepage).It's the first time I create a full website with Silex and I'm beginner with php framework so if someone can help to achieve what I want...thanks by advance !
EDIT :
According to the anwser I get and what I want to achieve, is it possible to change the locale and staying in the same page with Silex / Twig?
For example, this give me the current route : global.request.get('_route')
and this global.request.get('_locale')
give me the locale.
If I take the example of my Home Page, this is how my controller look right now (I just show the template) :
$app->match('/', function (Request $request) use ($app) {
return $app['twig']->render('home.html.twig');
})->bind('home');
As you can see, I have no {_locale} param in my URL. So can I keep this "clean URL" without the {_locale} and make a click that stay in the same page + change the current langage?
I'd like to make somehting like this : <a href="{{ path(global.request.get('_route')), global.request.set('_locale', 'FR') }}">FR</a>
But it won't work for sure...can I do this?
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").