admad/cakephp-i18n

一个用于I18n相关工具的CakePHP插件。

资助包维护!
ADmad

安装: 23,048

依赖: 0

建议者: 0

安全: 0

星标: 43

关注者: 9

分支: 14

开放问题: 1

类型:cakephp-plugin

3.0.0 2023-09-29 06:08 UTC

This package is auto-updated.

Last update: 2024-08-29 08:08:54 UTC


README

Build Status Coverage Status Total Downloads License

简介

此插件提供

  • 用于生成和匹配带有语言前缀的URL的路由类。
  • 中间件,使用 I18n::setLocale() 设置区域设置,基于URL中的语言前缀,并在访问网站根目录时提供重定向到带有语言前缀的适当URL。
  • 用于检索存储在数据库中而不是po/mo文件中的翻译消息的类。
  • 用于自动翻译验证消息的验证类。
  • 用于生成带有时区标识符列表的选择框的插件。

安装

composer require admad/cakephp-i18n

使用

运行以下命令加载插件

bin/cake plugin load ADmad/I18n

该插件包含多个用于国际化的类。您可以挑选您需要的类。

I18nRoute

I18nRoutes 有助于生成样式为 /{lang}/{controller}/{action} 的语言前缀路由。

例如,您可以在 routes.php 中添加类似于以下所示的路线

$routes->scope('/', function ($routes) {
    $routes->connect(
        '/{controller}',
        ['action' => 'index'],
        ['routeClass' => 'ADmad/I18n.I18nRoute']
    );
    $routes->connect(
        '/{controller}/{action}/*',
        [],
        ['routeClass' => 'ADmad/I18n.I18nRoute']
    );
});

片段 /{lang} 将自动添加到路由中,允许匹配类似 /en/posts/en/posts/add 等URL。lang 元素会被保留,以便在生成URL时,如果您在URL数组中不提供 lang 键,它将根据当前URL自动添加。

连接路由时,您可以在选项中使用 lang 键来提供仅匹配您应用程序支持的语言的正则表达式。或者,您可以设置配置值 I18n.languages,该路由类将使用它来自动生成匹配 lang 元素的正则表达式。

Configure::write('I18n.languages', ['en', 'fr', 'de']);

注意:I18nRoute 扩展了核心的 DashedRoute,因此URL片段将相应地进行变位。

I18nMiddleware

虽然不是必需的,但通常在使用 I18nRoute 辅助语言前缀路由时也会使用 I18nMiddleware

您可以在 src/Application::middleware() 中设置 I18nMiddleware,如下所示

$middlware->add(new \ADmad\I18n\Middleware\I18nMiddleware([
    // If `true` will attempt to get matching languges in "languages" list based
    // on browser locale and redirect to that when going to site root.
    'detectLanguage' => true,
    // Default language for app. If language detection is disabled or no
    // matching language is found redirect to this language
    'defaultLanguage' => 'en',
    // Languages available in app. The keys should match the language prefix used
    // in URLs. Based on the language the locale will be also set.
    'languages' => [
        'en' => ['locale' => 'en_US'],
        'fr' => ['locale' => 'fr_FR']
    ],
]));

languages 数组的键是您在URL中使用的语言前缀。

为了确保 lang 路由参数可用,您必须在添加 CakePHP 的默认路由中间件(即 after -> add(new RoutingMiddleware($this)))之后添加此中间件。

中间件主要做两件事

  1. 当访问网站根目录 / 时,它将用户重定向到带有语言前缀的URL,例如 /en。重定向到的语言取决于上述的配置键 detectLanguagedefaultLanguage

    现在,为了防止 CakePHP 抱怨 / 路由丢失,您必须将一个路由连接到 /,该控制器动作永远不会被实际调用,因为中间件将拦截并重定向请求。

    例如,$routes -> connect('/', ['controller' => 'Foo']);

  2. 当访问任何带有语言前缀的URL时,它将根据前缀设置应用程序的区域设置。为此,它检查当前请求的参数中的 lang 路由元素。如果使用了 I18nRoute 连接了匹配的路由,则该路由元素将是可用的。

    使用提供的用于 languages 键的数组,通过 Configure::write() 设置 App.language 配置为语言前缀,而 locale 的值用于 I18n::setLocale() 调用。

DbMessagesLoader

默认情况下,CakePHP 使用 .po 文件来存储静态字符串翻译。如果出于任何原因你不想使用 .po 文件,你可以使用 DbMessagesLoader 类将翻译消息存储在数据库中。我个人认为,将消息存储在表中而不是 .po 文件中,使得制作用于管理翻译的网页界面变得更加容易。

要使用此类,首先使用插件 config 文件夹中提供的 SQL 文件创建数据库表。

在应用的 config/bootstrap.php 中添加以下类似的代码:

// NOTE: This is should be done below Cache config setup.

// Configure I18n to use DbMessagesLoader for default domain. You need to do
// this for each domain separately.
\Cake\I18n\I18n::config('default', function ($domain, $locale) {
    $loader = new \ADmad\I18n\I18n\DbMessagesLoader(
        $domain,
        $locale
    );

    return $loader();
});

你可以使用 admad/i18n extract 命令从代码文件中提取翻译消息,并填充翻译表。更新每个语言的数据库记录中的翻译消息由你决定。

bin/cake admad/i18n extract

现在你可以像平常一样使用翻译函数,如 __() 等。I18n 类将从一个数据库而不是 .po 文件中获取所需的翻译。

TimezoneWidget

在你的 AppView::initialize() 中配置 FormHelper 以使用 TimezoneWidget

// src/View/AppView.php
public function initialize(): void
{
    $this->loadHelper('Form', [
        'widgets' => [
            'timezone' => ['ADmad/I18n.Timezone']
        ]
    ]);
}

你可以生成一个带有时区标识符的 select box,如下所示:

// Generates select box with list of all timezone identifiers grouped by regions.
$this->Form->control('fieldname', ['type' => 'timezone']);

// Generates select box with list of timezone identifiers for specified regions.
$this->Form->control('fieldname', [
    'type' => 'timezone',
    'options' => [
        'Asia' => DateTimeZone::ASIA,
        'Europe' => DateTimeZone::EUROPE
    ]
]);

如上例所示,请注意,与普通 select box 不同,现在 options 是一个有效的时区区域的关联数组,其中的键将用作 select box 中的 optgroup