在Symfony中自定义i18n路由

时间:2013-06-12 07:32:30

标签: symfony internationalization routing

我正在使用JMS\I18nRoutingBundleGedmo\TranslatableGedmo\Sluggable。具有默认位置的路由也可以工作,但其他语言环境无需翻译slug。我的i18n路由具有以下设置:

# Doctrine extensions
stof_doctrine_extensions:
    default_locale: %locale%
    translation_fallback: true
    orm:
        default:
            #…
            sluggable:      true
            translatable:   true
            loggable:       false
            #…

jms_i18n_routing:
    default_locale: cs_CZ
    locales: [cs_CZ, en_US]
    strategy: custom
    hosts:
        cs_CZ: example.cz
        en_US: example.com
    redirect_to_host: true

当我设置这样的路线时:

hw_category:
    pattern: /category/{slug}
    defaults: { _controller: AcmeSiteBundle:Category:detail }
/**
 * @Template
 */
public function detailAction(Category $category)
{}

这条路线有效 example.cz/category/slug-in-czech
example.com/category/slug-in-czech

但我希望得到工作example.com/category/slug-in-english,它会抛出404异常object not found

3 个答案:

答案 0 :(得分:1)

正如我所知,您正在使用ParamConverter自动获取您的类别。

如果slug-in-english是数据库中的现有slug,但是doctrine拒绝获取它。

此时您可能没有将 TranslatableListener 添加到您的EntityManager中。

示例

$translatableListener = new \Gedmo\Translatable\TranslationListener();
$translatableListener->setTranslatableLocale('en_us');
$em->addEventSubscriber($translatableListener);

如果您使用 StofDoctrineExtensionsBundle

stof_doctrine_extensions:
    default_locale: en_US
    orm:
        default:
            # ...
            translatable: true

答案 1 :(得分:1)

在您的控制器中,您必须覆盖实体存储库中使用的方法:

/**
 * @Template
 * @ParamConverter(
 *     "category",
 *     class = "AcmeSiteBundle:Category",
 *     options = {
 *         "repository_method" = "findByTranslatedSlug"
 *     }
 *  )
 */
public function detailAction(Category $category)
{}

namespace Acme\Bundle\SiteBundle\Entity;

use Doctrine\ORM\EntityRepository;

class CategoryRepository extends EntityRepository
{
    public function findByTranslatedSlug($slug)
    {
        $qb = $this->createQueryBuilder('c')
            ->where('c.slug = :slug')
            ->setParameters($slug);

        $query = $qb->getQuery();
        // set the translation query hint
        $query->setHint(
            \Doctrine\ORM\Query::HINT_CUSTOM_OUTPUT_WALKER,
            'Gedmo\\Translatable\\Query\\TreeWalker\\TranslationWalker'
        );

        return $query->getOneOrNullResult();
    }
}

答案 2 :(得分:1)

我有同样的问题,并且按照jkucharovic的建议,您可以使用 Doctrine ParamConverter 将您的请求参数转换为对象

要从数据库中获取对象,Doctrine转换器默认使用find()方法。但由于我们使用Translatable,因此使用多个表,仅仅管理翻译是不够的,这就是我们需要定义自己的翻译的原因。这是findByTranslatedSlug。

/**
 * @Template
 * @ParamConverter(
 *     "category",
 *     class = "AcmeSiteBundle:Category",
 *     options = {
 *         "id" = "slug",
 *         "repository_method" = "findByTranslatedSlug"
 *     }
 *  )
 */
public function detailAction(Category $category)
{}

有关ParamConverter参数的一些细节:

  • 第一个参数“category”是指方法参数的名称(此处 $ category
  • “id”选项是指您要传递的路径占位符(此处为 {slug} )到自定义存储库方法(findByTranslatedSlug())。如果不设置此选项,则会抛出PDO异常。

namespace Acme\Bundle\SiteBundle\Entity;

use Doctrine\ORM\EntityRepository;

class CategoryRepository extends EntityRepository
{
    public function findByTranslatedSlug($slug)
    {
        $qb = $this->createQueryBuilder('c')
            ->where('c.slug = :slug')
            ->setParameter('slug',$slug);

        $query = $qb->getQuery();
        // set the translation query hint
        $query->setHint(
            \Doctrine\ORM\Query::HINT_CUSTOM_OUTPUT_WALKER,
            'Gedmo\\Translatable\\Query\\TreeWalker\\TranslationWalker'
        );
        // If you need to set manually the locale to en_US, you can set this query hint
        //$query->setHint(\Gedmo\Translatable\TranslatableListener::HINT_TRANSLATABLE_LOCALE, 'en_US');

        return $query->getOneOrNullResult();
    }
}

我希望这可以提供帮助

文档: