【问题标题】:Silex : allow user to change langage by clicking on html element and keeping clean URLSilex:允许用户通过单击 html 元素并保持干净的 URL 来更改语言
【发布时间】:2018-03-01 17:15:48
【问题描述】:

我正在为网站使用 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. 如果我在我的 url 中将 fr 更改为 en 它可以工作,那么尝试在 JavaScript 中使用 window.location.href 进行更改是个好主意吗? (我认为没有,但仍在询问)
  3. 我看到 this solution 有其他问题,并在我的控制器中尝试它,但我收到此错误:500 (Internal Server Error)(我也这样做了,使用 $new_langue 而不是 $app['defaultLanguage'],并且我的主页名称正确)。

这是我第一次使用 Silex 创建一个完整的网站,而且我是 php 框架的初学者,所以如果有人可以帮助实现我想要的......在此先感谢!

编辑:

根据我得到的答案和我想要实现的目标,是否可以更改语言环境并与 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} 参数。 那么我可以在不使用 {_locale} 的情况下保留这个“干净的 URL”,并在同一页面上进行点击 + 更改当前语言吗?

我想做这样的事情:&lt;a href="{{ path(global.request.get('_route')), global.request.set('_locale', 'FR') }}"&gt;FR&lt;/a&gt;

但这肯定行不通...我可以这样做吗?

【问题讨论】:

    标签: php ajax symfony silex


    【解决方案1】:

    所以,从您的消息中,我可以得出您的目标是允许在您单击 HTML 元素时更改语言

    a标签的用法定义了一个超链接,用来从一个页面链接到另一个页面,可以用来实现你想要的。

    我之前做过多语言网站,您可以通过多种方式实现这一目标。

    //////////////////////////方法一:在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替换为您网站的域名。

    ///////////////////////////方法一结束

    在您的 HTML 代码中,您提到了// Could be nice to change the langue staying on the same page

    这可以使用 AJAX 来完成,是的。

    但我不建议您这样做,因为从那些也拥有多种语言的网站(例如 SAPApple)的大公司来看,它们都会重定向到不同的页面。

    ////////////////////////////////////更新:到目前为止的答案是因为我认为您的需要只是允许在单击 HTML 元素时更改语言。

    显然,您的目标比这稍微复杂一些。

    根据 Silex 文档,_locale 的用法是 the way to go

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

    【讨论】:

    • 好的,你的答案是:只需更改 URL 中的语言环境?我明天上班试试!我不确定这是不是最好的做法,但它应该可以肯定:)
    • 正如我在另一条评论中所说,我使用 Twig(我没有说清楚对不起,我的 Ajax url 中的 path() 函数还不够),我将我的问题编辑为更准确地了解我尝试做的事情!
    • Mickael,这个问题真的很混乱,需要编辑清楚
    • 正如我在上次编辑中所说,我的控制器中的路由没有_locale 变量。我想用你的想法+保持我的 URL 干净来改变语言。我可以单击并停留在同一页面上,但在不使用此语言环境变量的情况下,我无法解决切换语言的问题...所以我想知道这是否可能,或者我是否需要添加 @987654331 @ ?
    • 我不确定你的编辑是否能 100% 解决我的问题,但你仍然给了我最好的建议,我对如何做我想做的事情有了更好的了解,所以我会给你赏金:) 感谢您的宝贵时间!
    【解决方案2】:

    在您的情况下,只需添加适当的链接以允许用户切换语言。其余的工作已经由您完成。语言切换器下拉菜单必须包含所有支持的语言,包括英语。请参阅下面的示例图片。

    您必须重定向到像http://www.yourwebsite.com/language_change?lang=fr 这样的特殊方法,而不是将用户重定向到http://yourwebsite.com/[fr]/my-account。您将在$_SERVER 变量中获得HTTP_REFERRER,因此您可以将用户重定向回他们所在的原始页面。这样您就可以保留用户当前访问的页面/网址。

    其次,Ajax 与重定向:最好使用重定向而不是 AJAX。如果你使用 AJAX,你会增加自己的同谋。

    在使用多语言网站时,我们必须遵循这些最佳做法。

    • 每种语言的具体路线

    • 菜单、标签和表单

    • 网站内容

    • 额外:翻译 FOSUserBundle

    【讨论】:

    • 我没有说出来(我编辑了我的问题,抱歉)但我使用的是 Twig(我的 Ajax url 中的 {{path()}} 可能是一个线索!),所以我使用href="{{path('my_route_name'}}", so no lang=fr`(这样我就知道如何用一些会话变量来做到这一点。我根据我得到的答案编辑了我想做的事情!
    • @MickaelLeger - 很高兴听到。我发布了我的答案,因为想引起您的注意,即在更改语言时必须保留用户当前的 url。 :)
    • 当然,正如我在问题介绍中所说,我的翻译工作正常:/my-page/en/my-page = 英文内容和/fr/my-page = 法文内容。我的控制器在路径中没有/{_locale},所以我不能做href={{ path(global.request.get('_route'), {_locale : 'fr'} ) }},知道怎么做并且仍然有/my-page,但是使用用户选择的语言环境变量?
    • 是的,我看到了,我试过了,但我的 URL 末尾有 ?_locale=fr 并且仍然是相同的内容语言......我想我必须保留这个解决方案并添加 @987654336 @ 在我的路由中使其正常工作
    • 我认为你是对的。也检查这个。 phpbeginnertoadvanced.blogspot.in/2016/09/…
    【解决方案3】:

    这里的简单想法是:您的应用程序如何确定用于呈现页面的语言。

    解决方案 #1 (您当前的解决方案) 基于 URL 参数(即 _locale ),并在没有给出 URL 参数的情况下回退到某个默认值.
    因此,在此解决方案中,翻译组件始终在路由器组件准备的参数包中查找所选语言。

    解决方案 #2 将您的语言标识符放在会话变量中。 您的/new-langue 页面必须使用它接收到的值来设置这个会话变量。并且您的路由器将从该会话变量中填充_locale 参数。

    稍后我可能会提供一些代码 sn-ps。

    【讨论】:

      【解决方案4】:

      我终于找到了一个解决方案来做我想做的事,使用pmaxs/silex-locale (https://github.com/pmaxs/silex-locale)。

      正如我在我的问题中所说,我已经将它用于我的翻译,但我没有使用我应该使用的“Url generation”......所以这里是如何使用它的回顾(如果你阅读文档使用 Silex v1.x):

      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/ 网址生成器

      现在,这是我更改语言的方法:

      {% 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 Generator”,它的工作原理是这样的:locale_generate('es', $name, $parameters = array(), $referenceType = UrlGeneratorInterface::ABSOLUTE_PATH)(更多详细信息在文档中)。

      这样,当我进入我的网站时,我使用的是英语(我的默认语言环境)和我的“干净 URL”/。然后点击FR,我的网址变成/fr/,我的内容被翻译成法语,带有一个新的选择菜单(当前语言= FR,我可以选择“EN”)。

      【讨论】:

        猜你喜欢
        • 2019-11-22
        • 2021-10-15
        • 2017-05-26
        • 1970-01-01
        • 1970-01-01
        • 2022-01-23
        • 1970-01-01
        • 2017-10-09
        • 1970-01-01
        相关资源
        最近更新 更多