Я использую Silex и Twig для веб-сайта, и я хочу, чтобы пользователь мог изменить язык сайта.

Моя проблема

Прямо сейчас, это работает, если я изменю локаль в URL:

/my-account: содержимое моей страницы на английском языке (по умолчанию _locale)

/fr/my-account: содержание моей страницы на французском

/en/my-account: содержание моей страницы на английском языке

Как я могу сделать то же самое, нажав на элемент HTML?

Я ищу какую-то идею, чтобы решить мою проблему, и хорошую практику, чтобы сделать этот «правильный путь», если это возможно.

Мой код

Вот компонент Silex, который я использую для управления мультиязычностью:

// 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;
});

Вот мой HTML для пользователя, чтобы изменить язык:

<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>

Теперь мой jQuery, чтобы получить значение:

$(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);
            }
        });
    });
});

Мой контроллер Ajax:

$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');

Если я сделаю это, мой успех Ajax console.log(resp); даст мне en, как я хочу.

Некоторые идеи / вопросы о том, как это сделать

  1. Это хорошая идея сделать это с помощью вызова Ajax?
  2. Если я изменю fr на en в моем URL, это сработает, будет ли хорошей идеей попытаться сделать это в javascript, используя window.location.href, например? (Думаю нет но все же спрашиваю)
  3. Я нашел это решение для другой проблемы и пробовал в своем контроллере, но я получаю это ошибка: 500 (Internal Server Error) (я сделал то же самое, с $new_langue вместо $app['defaultLanguage'] и с правильным именем для моей домашней страницы).

Это первый раз, когда я создаю полноценный сайт с Silex, и я начинаю с php framework, так что если кто-то может помочь достичь того, чего я хочу ... спасибо заранее!

РЕДАКТИРОВАТЬ:

Согласно полученному ответу и того, чего я хочу достичь, возможно ли изменить локаль и остаться на одной странице с Silex / Twig?

Например, это даст мне текущий маршрут: global.request.get('_route'), а global.request.get('_locale') даст мне локаль.

Если я возьму пример моей домашней страницы, то вот как мой контроллер выглядит сейчас (я просто показываю шаблон):

$app->match('/', function (Request $request) use ($app) {
    return $app['twig']->render('home.html.twig');
})->bind('home');

Как видите, в моем URL нет параметра {_locale}. Так можно ли сохранить этот "чистый URL-адрес" без {_locale} и сделать клик, который останется на той же странице + изменить текущий язык?

Я хотел бы сделать что-то вроде этого: <a href="{{ path(global.request.get('_route')), global.request.set('_locale', 'FR') }}">FR</a>

Но это не сработает наверняка ... я могу это сделать?

4
Mickaël Leger 1 Мар 2018 в 20:15

4 ответа

Лучший ответ

Наконец-то я нашел решение сделать то, что хочу, используя pmaxs/silex-locale (https: // github. ком / pmaxs / кремнезем - локаль ) .

Как я уже сказал в своем вопросе, я уже использовал его для своего перевода, но я не использовал «генерацию URL», как я должен ... Итак, вот резюме того, как его использовать (прочитайте документацию, если вы используете Silex v1 .Икс):

1 / поставщик загрузки

$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 / Использование

Вот мой домашний контроллер маршрута:

// 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');

Как видите, у меня нет переменной {_locale} в моей маршрутизации, но я все еще могу использовать ее для изменения языка моей страницы.

3 / Генератор URL

Теперь, как я меняю свой язык:

{% 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>

Я использую «Генератор URL», он работает так: locale_generate('es', $name, $parameters = array(), $referenceType = UrlGeneratorInterface::ABSOLUTE_PATH) (подробнее в документации).

Таким образом, когда я захожу на свой веб-сайт, я на английском языке (мой язык по умолчанию) с моим «чистым URL» /. Затем, нажав FR, мой URL становится /fr/, и мой контент переводится на французский язык с новым меню выбора (current-langue = FR, и я могу выбрать «EN»).

0
Mickaël Leger 12 Мар 2018 в 12:43

В вашем случае это просто вопрос добавления надлежащих ссылок, чтобы пользователи могли переключать язык. Остальная часть работы уже сделана вами. Раскрывающийся список языковых переключателей должен содержать все поддерживаемые языки, включая английский. См. Ниже пример изображения.

enter image description here

Вместо перенаправления пользователей на http://yourwebsite.com/[fr]/my-account вы должны перенаправить на специальный метод, такой как http://www.yourwebsite.com/language_change?lang=fr. Вы получите HTTP_REFERRER в переменной $_SERVER, чтобы вы могли перенаправить пользователей обратно на исходную страницу, на которой они находились. Таким образом, вы можете сохранить текущую страницу посетителя / URL.

Во-вторых, Ajax vs Redirect: лучше использовать редирект вместо AJAX. Если вы используете AJAX, вы увеличите соучастие для себя.

При работе с многоязычным веб-сайтом мы должны следовать этим рекомендациям.

  • Конкретные маршруты для каждого языка

  • Меню, ярлыки и формы

  • Содержание сайта

  • Дополнительно: перевод FOSUserBundle

1
elegant-user 5 Мар 2018 в 06:45

Здесь простая идея: как ваше приложение определяет язык, который будет использоваться для визуализации страниц.

решение # 1 (ваше текущее решение) , основанное на параметре URL (это _locale), и откат к некоторому значению по умолчанию, если URL-параметр не указан.
Таким образом, в этом решении компонент перевода всегда ищет выбранный язык в пакете параметров, подготовленном компонентом маршрутизатора.

Решение № 2 поместите ваш языковой идентификатор в переменную сеанса. Ваша /new-langue страница должна будет установить эту переменную сеанса со значением, которое она получает. и ваш маршрутизатор заполнит параметр _locale из этой переменной сеанса.

Возможно, я смогу предоставить некоторые фрагменты кода чуть позже.

0
Ahmad Tawila 11 Мар 2018 в 15:29

Итак, из вашего сообщения я могу извлечь вашу цель - разрешить изменение языка при нажатии на элемент HTML .

Использование тега a определяет гиперссылку, которая используется для ссылки с одной страницы на другую и может использоваться для достижения того, что вы хотите.

Ранее я занимался многоязычными сайтами, и вы можете достичь этого различными способами.

/////////////////////////////// Метод 1: определить местоположение в атрибуте HTML href

В своем HTML-коде вы использовали хеш - # внутри гиперссылки.

Для гиперссылок требуется свойство href, поскольку оно указывает местоположение.

Глядя на ваш код, у вас есть тег, но в нем отсутствует ссылка на конкретное место, куда вы хотите перенаправить пользователя.

Допустим, вы хотите, чтобы он перешел на my-account страницу по-французски.

Итак, ваш HTML-код должен быть:

<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>

Обратите внимание: замените yourwebsite.com доменом своего веб-сайта.

/////////////////////////////// конец метода 1

В своем HTML-коде вы упоминаете // Could be nice to change the langue staying on the same page.

Это можно сделать с помощью AJAX, да.

Но я не советую вам этого делать, потому что, глядя на крупные компании, которые также имеют веб-сайты на нескольких языках, таких как SAP или Apple все они перенаправляют на другую страницу.

/////////////////////////////// ОБНОВЛЕНИЕ: ответ до сих пор был создан, потому что я думал, что ваш нужно было просто позволить языку быть измененным при нажатии на элемент HTML.

Видимо, ваша цель немного сложнее, чем это.

Согласно документации Silex, использование _locale - это путь.

В этом вопросе вы можете увидеть рабочий код:

<?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();
4
molecoder 11 Мар 2018 в 15:42