Silex : allow user to change langage by clicking on html element and keeping clean URL

前端 未结 4 815
一生所求
一生所求 2021-01-19 07:18

I am using Silex and Twig for a website and I want to allow the user to change the langage of the site.

My problem

Right now, it works if I change the loca

相关标签:
4条回答
  • 2021-01-19 07:44

    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").

    0 讨论(0)
  • 2021-01-19 07:53

    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.

    0 讨论(0)
  • 2021-01-19 07:58

    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();
    
    0 讨论(0)
  • 2021-01-19 07:59

    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

    0 讨论(0)
提交回复
热议问题