web-dev-qa-db-ja.com

すべてのルートにロケールと要件を追加する-Symfony2

翻訳を目的としないアプリケーションを作成しましたが、この機能を追加することにしました。問題は、すべてのルートが次のようになっていることです。

goodbye:
    pattern: /goodbye
    defaults: { _controller: AcmeBudgetTrackerBundle:Goodbye:goodbye }

そして私はそれらを今このようにしたいと思います:

goodbye:
    pattern: /goodbye/{_locale}
    defaults: { _controller: AcmeBudgetTrackerBundle:Goodbye:goodbye, _locale: en }
    requirements:
        _locale: en|bg

私は本当にこれを行う必要があり、よりグローバルまたは自動で行う方法はありますか、または少なくとも1回だけ要件を追加する方法はありますか?それらはすべてのURLで同じであるためですか?よろしくお願いします!

10
Faery

この目的には JMS18nRoutingBundleドキュメント )を使用します。カスタムローダーもコーディングもありません...

バンドルは、バンドルの一部の構成を除いて何も変更せずに、すべてのルートにロケールのプレフィックスを付けることができます。それはあなたが始めるための最も速い(そして私の推奨する)解決策です。

さまざまなロケールの既存のルートを変換することもできます。

簡単な紹介は このコーダーウォールの投稿 にあります。

17

グローバル構成ファイルで、このように行うことができます

customsite:
  resource: "@CustomSiteBundle/Resources/config/routing.yml"
  prefix:   /{_locale}
  requirements:
    _locale: fr|en
  defaults: { _locale: fr}

反応はかなり遅いですが、同様の問題がいくつかありました。

リソースをインポートするときに{_locale}プレフィックスを削除することもできます。次に、すべての特定のルートに{_locale}を追加する必要があります。

このようにして、要件とデフォルトを書き直すことなく、バンドル内からロケールなしでwww.domain.comをキャッチできます。

ただし、グローバルルーティング構成で常にwww.domain.comルートを定義できます。

13
Chris B.

すべてのルートまたはグローバルスコープに要件を設定する代わりに、より良い解決策は、EventListenerを使用して、ユーザーを同じルートにリダイレクトすることですが、サポートされているロケールを使用します。例:

<?php

namespace Selly\WebappLandingBundle\EventListener;

use Symfony\Component\HttpFoundation\RedirectResponse;

use Symfony\Component\Routing\RouterInterface;
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
use Symfony\Component\HttpKernel\KernelEvents;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;

class LocaleInParamListener implements EventSubscriberInterface
{
    /**
     * @var Symfony\Component\Routing\RouterInterface
     */
    private $router;

    /**
     * @var string
     */
    private $defaultLocale;

    /**
     * @var array
     */
    private $supportedLocales;

    /**
     * @var string
     */
    private $localeRouteParam;

    public function __construct(RouterInterface $router, $defaultLocale = 'en_US', array $supportedLocales = array('en_US'), $localeRouteParam = '_locale')
    {
        $this->router = $router;
        $this->defaultLocale = $defaultLocale;
        $this->supportedLocales = $supportedLocales;
        $this->localeRouteParam = $localeRouteParam;
    }

    public function isLocaleSupported($locale) {
        return in_array($locale, $this->supportedLocales);
    }

    public function onKernelRequest(GetResponseEvent $event)
    {
        $request = $event->getRequest();
        $locale = $request->get($this->localeRouteParam);

        if(null !== $locale) {
            $routeName = $request->get('_route');

            if(!$this->isLocaleSupported($locale)) {
                $routeParams = $request->get('_route_params');

                if (!$this->isLocaleSupported($this->defaultLocale))
                    throw \Exception("Default locale is not supported.");

                $routeParams[$this->localeRouteParam] = $this->defaultLocale;
                $url = $this->router->generate($routeName, $routeParams);

                $event->setResponse(new RedirectResponse($url));
            }
        }
    }

    public static function getSubscribedEvents()
    {
        return array(
            // must be registered before the default Locale listener
            KernelEvents::REQUEST => array(array('onKernelRequest', 17)),
        );
    }
}

そしてservices.yml

services:
    selly_webapp_landing.listeners.localeInParam_listener:
        class: Selly\WebappLandingBundle\EventListener\LocaleInParamListener
        arguments: [@router, "%kernel.default_locale%", "%locale_supported%"]
        tags:
            - { name: kernel.event_subscriber }

parameters.ymlサポートされているロケールを指定できます。

locale_supported: ['en_US', 'pl_PL']
3
Athlan

ローカリゼーションのためにsymfonyを設定します:

セッションにローカリゼーションを追加します(規則は/ locale/actionであることに注意してください):

goodbye:

    pattern: /{_locale}/goodbye
    defaults: { _controller: AcmeBudgetTrackerBundle:Goodbye:goodbye, _locale: en }
    requirements:
        _locale: en|bg

または、ロケールを手動で設定することもできます:

$this->get('session')->set('_locale', 'en_US');

app/config/config.yml

framework:
    translator: { fallback: en }

あなたの応答で:

use Symfony\Component\HttpFoundation\Response;

public function indexAction()
{
    $translated = $this->get('translator')->trans('Symfony2 is great');

    return new Response($translated);
}

ローカリゼーションメッセージのローカライズされたファイルを構成します。

messages.bg

<?xml version="1.0"?>
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
    <file source-language="en" datatype="plaintext" original="file.ext">
        <body>
            <trans-unit id="1">
                <source>Symfony2 is great</source>
                <target>Symfony2 е супер</target>
            </trans-unit>
            <trans-unit id="2">
                <source>symfony2.great</source>
                <target>Symfony2 е супер</target>
            </trans-unit>
        </body>
    </file>
</xliff>

messages.fr

<?xml version="1.0"?>
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
    <file source-language="en" datatype="plaintext" original="file.ext">
        <body>
            <trans-unit id="1">
                <source>Symfony2 is great</source>
                <target>J'aime Symfony2</target>
            </trans-unit>
            <trans-unit id="2">
                <source>symfony2.great</source>
                <target>J'aime Symfony2</target>
            </trans-unit>
        </body>
    </file>
</xliff>

トピックの詳細: 公式のsymfonyドキュメント

3
Sam Aleksov

クラシックな設定ローダー(Symfony\Component\Config\Loader\Loader)を拡張してパターンを操作するカスタムローダーが必要だと思います

http://symfony.com/doc/current/cookbook/routing/custom_route_loader.html

最初の例を確認してください。まだ試していませんが、問題に合うと確信しています。

1
ROLO

あなたはこの解決策を見ることができます: https://stackoverflow.com/a/37168304/6321297

ルートの{_local}パラメータをすべてのルートに適用する場合は、app/configルーティングファイルに含める必要があります。

このソリューションは、URLに{_local}がない場合、イベントリスナーを使用して適切なURLにリダイレクトします。yoursite.com/your/routeyoursite.com/{_locale}/your/routeに変更します。

パラメータの有無にかかわらず機能します。

0