个性化阅读
专注于IT技术分析

如何使用BeSimpleI18nRoutingBundle在Symfony 3中处理路由国际化

本文概述

如今, 许多公司需要为来自世界各地的客户提供支持。可惜的是, 并不是每个人都说相同的语言, 所以这是一个小限制, 但是对于市场和开发人员来说却不是。创建国际化和本地化的应用程序绝非易事, 因此, 还有许多工具可为你提供简便的方法来为网站和应用程序添加多语言支持。但是, 为你提供国际化网站路由的工具并不多, 因此它们也可以从SEO中受益。 BeSimpleI18nRoutingBundle是一个有用的工具, 可帮助你避免针对不同语言的路线进行复制和粘贴。另外, 它允许使用Symfony转换器或基于Doctrine DBAL(+ Cache)的后端在Router#match和UrlGenerator#generate中的语言之间转换给定的路由参数。

尽管本文中对这种方法的解释可能无法满足非常复杂的应用程序(捆绑软件可以满足的要求)的所有要求, 但对于仅使用Symfony创建不需要非常复杂的路由定义的网站或应用程序的人来说, 它还是很有用的。但是, 请不要忘记该捆绑包确实支持复杂的模式, 例如使用你自己的数据库翻译子句, 因此请务必阅读该库的文档。

1.安装BeSimpleI18nRoutingBundle

使用运行以下命令的composer安装捆绑软件:

composer require besimple/i18n-routing-bundle

安装捆绑软件后, 你将能够配置路由。有关此捆绑包和文档的更多信息, 请访问Github上的官方存储库。

2.在你的应用程序上配置默认语言环境

第二步, 你需要定义哪些语言将支持应用程序的路由。我们将在项目的config.yml文件中定义2个参数, 其中包含2个名称, 即语言环境(通常已经定义了语言环境)和语言环境, 这些语言环境指定了你的应用程序支持的语言环境, 因为你显然不会重定向到具有俄语语言环境的页面如果你不支持该语言。在此示例中, 我们将提供对英语, 法语, 西班牙语和德语的支持, 因此请在config.yml中定义参数:

parameters:
    locale: en
    locales: en|fr|es|de

此外, 你还需要确保对问题”如果尚未确定用户的语言环境怎么办?”给出答案。通过提供与默认语言环境相同的定义作为默认语言环境(以及config.yml):

framework:
    # Set those properties with the locale parameter
    translator: { fallbacks: ['%locale%'] }
    default_locale: '%locale%'

使用此配置, 如果URL中未提供用户语言环境, 我们的应用程序将始终使用英语作为默认语言环境。最后, 你需要在be_simple_i18n_routing的受支持属性中以相同的语言环境指定相同的语言环境:

# app/config/config.yml
be_simple_i18n_routing:
    locales:
        supported: ['en', 'es', 'fr', 'de']
        filter: true
        strict: true

该捆绑包在Symfony的旧版本中也能正常工作, 因此, 如果在安装捆绑包后或配置后的某个时候遇到以下异常:

[Symfony\Component\Config\Exception\FileLoaderLoadException]                                                                                                                    
    Warning: trim() expects parameter 1 to be string, array given in /app/config/routing.yml (which is being imported from "/app/config/routing_dev.yml").           

请修改你的routing_dev.yml文件, 并将type参数添加到_main属性中:

_main:
    resource: routing.yml
    type: be_simple_i18n

这将解决你的问题, 并且你将能够继续进行路由配置。

3.配置基本路由

作为一种预期的行为, 每个URL都将以语言环境作为前缀, 甚至包括应用程序的默认语言(例如英语)。但是, 如果你在配置基本路由后尝试从主域(例如www.yourapp.com)访问应用程序, 则会看到一条错误消息, 指出/路由未定义。发生这种情况是因为实际上, 不会使用任何路由来定义你的域的根地址, 因为我们将在每个路由上使用语言环境作为前缀。对于用户而言, 这将意味着一个问题, 因为他或她将需要使用区域设置(例如www.yourapp.com/en)来写URL, 这显然很烦人, 因此, 用户的预期行为将通过重定向到其首页。默认语言环境。因此, 你需要在主路由文件(app / config / routing.yml)中定义根参数, 该根参数将使用框架包的urlRedirect操作将用户使用区域设置参数重定向到上述URL。然后创建一个路由定义器, 在这种情况下将是app_main并在其中定义前缀(遵循语言环境模式)。该定义器将定位到另一个路由文件, 在此示例中, 该文件位于AppBundle / Resources / config / routing / routing.yml(如果需要, 可以明显更改文件路径), 然后我们将在下一步中创建该文件:

# app/config/routing.yml
# Entry point of your application that redirects the user to the main routing
# using a locale, that means If the user goes to:
# www.yourapp.com
# Is redirected automatically to:
# www.yourapp.com/en/
root:
    pattern: /
    defaults:
        _controller: FrameworkBundle:Redirect:urlRedirect
        path: /%locale%/
        permanent: true
    requirements:
        _locale: "%locales%"

# The main routing of your application whose content will be defined on
# the next step !
app_main:
    resource: "@AppBundle/Resources/config/routing/routing.yml"
    type: "be_simple_i18n"
    # Add the locale prefix to every URL
    # e.g Contact page English : /en/contact
    #     Homepage French      : /fr/
    #     Services page Spanish: /es/servicios
    #     Contact page German  : /de/kontakt
    prefix:
        en: "/en"
        fr: "/fr"
        es: "/es"
        de: "/de"

4.创建主路由

如上一步所述, app_main定义程序的目标是另一个路由文件, 该文件将处理应用程序本身的路由。我们的应用程序只有3条路由, 即/(主页), / services和/ contact。它们都会自然地翻译成用户语言, 因此我们可以进行用户友好的路由。创建3条路线以使它们可以使用3种不同语言的内容如下:

# AppBundle/Resources/config/routing/routing.yml
main_homepage:
    locales:
        en: "/"
        fr: "/"
        es: "/"
        de: "/"
    defaults: { _controller: AppBundle:Default:homepage }
    methods:  [GET]
    requirements:
        _locale: "%locales%"

main_services:
    locales: 
        en: "/services"
        fr: "/services"
        es: "/servicios"
        de: "/dienstleistungen"
    defaults: { _controller: AppBundle:Default:contact }
    methods:  [GET]
    requirements:
        _locale: "%locales%"

main_contact:
    locales: 
        en: "/contact"
        fr: "/contact"
        es: "/contacto"
        de: "/kontakt"
    defaults: { _controller: AppBundle:Default:services }
    methods:  [GET]
    requirements:
        _locale: "%locales%"

如你所见, 我们为每个语言环境定义了一种不同的路由模式, 易于理解。即使对于不费吹灰之力阅读另一个文件来查看每条路由等信息的程序员, 这也非常好。请注意, 我们需要为每条路由设置_locale要求, 因为这会在会话中更新用户语言环境自动。

5.创建路由控制器

正如你在上一步中所看到的, 即使具有不同的语言环境, 我们也为每条路线使用相同的控制器。这就是为什么这个捆绑包非常棒的原因, 你不需要为每种语言编写必要的逻辑, 因为你可以和平地使用翻译器模块或根据语言环境在控制器中返回不同的视图。在这种情况下, 我们的控制器非常简单并返回一个视图, 总共有3个动作(在主路由文件上定义):

注意

我们返回的视图与我们希望使用翻译模块来翻译视图上的内容相同, 但是这不属于本教程。

<?php
// AppBundle/Controller/DefaultController.php

namespace AppBundle\Controller;

use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\Request;

class DefaultController extends Controller
{
    public function homepageAction(Request $request)
    {
        return $this->render("default/homepage.html.twig");
    }

    public function servicesAction(Request $request)
    {
        return $this->render("default/services.html.twig");
    }

    public function contactAction(Request $request)
    {
        return $this->render("default/contact.html.twig");
    }
}

如前所述, 如果需要, 你可以使用语言环境在控制器中进行过滤以返回其他文件:

<?php

namespace AppBundle\Controller;

use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\Request;

class DefaultController extends Controller
{
    public function homepageAction(Request $request)
    {
        // Switch locale and return a file according to your needs
        switch($request->getLocale()){
            case "es":
                return $this->render("default/homepage_spanish.html.twig");
            case "fr":
                return $this->render("default/homepage_french.html.twig");
            case "de":
                return $this->render("default/homepage_german.html.twig");
            case "en":
            default:
                return $this->render("default/homepage_english.html.twig");
        }
    }
}

但是, 在我们看来, 与维护多个文件相比, 实现symfony转换器可能更简洁, 更简单。

6.在视图上创建重定向链接

至此, 你的应用程序(如果具有提到的控制器和路由)现在应该能够响应/ en / homepage, / es / contacto, / de / dienstleistungen之类的路由, 直接在浏览器导航栏中添加它们。但是, 用户需要能够单击某些链接来浏览你的网站, 因此请确保在视图中创建它们。例如, 可以使用用户的默认语言环境创建我们的某些路由:

{# /en/ #}
{{ path('main_homepage') }}

{# /en/services #}
{{ path('main_services') }}

{# /en/conctact #}
{{ path('main_contact') }}

但是, 如果你想重定向到某些特殊的语言环境, 例如以其他语言查看此视图​​, 则也可以强制使用语言环境:

{#
    Redirect to the homepage in english
    /en/
#}
{{ path('main_homepage.en') }}
{{ path('main_homepage', { 'locale': 'en' }) }}

{#
    Redirect to the homepage in french
    /fr/
#}
{{ path('main_homepage.fr') }}
{{ path('main_homepage', { 'locale': 'fr' }) }}

{#
    Redirect to the homepage in German 
    /de/
#}
{{ path('main_homepage.de') }}
{{ path('main_homepage', { 'locale': 'de' }) }}

7.在测试之前, 使用cache:clear命令清除项目缓存。

最后一步, 最重要的是使用命令行清除项目的缓存。我将重复使用Symfony的cache:clear命令清除缓存, 这非常非常重要, 否则, 如果仅手动删除缓存文件夹, 则不会清除语言环境, 你可能会感到沮丧。为确保一切正常, 请使用以下命令清除项目的缓存:

专家提示

手动清除缓存后, 打开Goog​​le Chrome的隐身窗口对于进行测试非常有用, 因为浏览器是从头开始并且没有存储任何内容, 因此, 如果有问题, 它不在浏览器中, 而在你的代码中。

php bin/console cache:clear

还要记住, 正如我们根据任何URL的要求定义的那样, 特殊参数_locale会在用户每次将URL区域设置从/ en(英语)更改为/ es(西班牙语)时自动更新用户的区域设置, 因此你可以轻松实现创建一个语言切换器, 该语言切换器将简单地重定向到具有所需语言环境的main_homepage路由, 仅此而已, 用户将被重定向到具有所需语言并保留在语言环境中的主页。有关此方法的更多信息, 请阅读Symfony文档中有关语言环境和URL的更多信息。

编码愉快!

赞(0)
未经允许不得转载:srcmini » 如何使用BeSimpleI18nRoutingBundle在Symfony 3中处理路由国际化

评论 抢沙发

评论前必须登录!