rainlab/translate-plugin

October CMS的翻译插件

安装次数: 58,675

依赖项: 8

建议者: 0

安全: 0

星标: 125

关注者: 16

分支: 88

开放问题: 3

类型:october-plugin

v2.2.10 2024-06-14 11:01 UTC

README

启用多语言网站。

选择语言

可以在管理员面板中使用“设置 → 网站”区域设置不同的语言。每个网站应使用不同的区域设置才能被视为一种语言。

访客可以通过在URL前缀语言代码或使用专用主机名来选择语言。例如

  • http://website.tld/将显示默认语言网站
  • http://website.tld/ru/将显示俄语网站
  • http://website.tld/fr/将显示法语网站

许可证

此插件是October CMS平台的官方扩展,如果您有平台许可证,则可免费使用。有关更多详细信息,请参阅EULA许可证

安装

使用October CMS v3.1或更高版本安装

php artisan plugin:install rainlab.translate

使用October CMS v3.0及以下版本安装

php artisan plugin:install rainlab.translate --want="^1.0"

从v1升级到v2

如果您正在将此插件的版本从1升级,请查看升级指南

语言选择组件

访客可以使用包含在October CMS核心中的本地SitePicker组件选择他们选择的语言。此组件将显示一个简单的下拉列表,根据选择更改页面语言。

title = "Home"
url = "/"

[sitePicker]
==

<h3>{{ 'Please select your language:'|_ }}</h3>
<select class="form-control" onchange="window.location.assign(this.value)">
    {% for site in sitePicker.sites %}
        <option value="{{ site.url }}" {{ this.site.code == site.code ? 'selected' }}>{{ site.name }}</option>
    {% endfor %}
</select>

如果已翻译,上面的文本将显示为用户选择的任何语言。下拉列表非常基本,旨在重设样式。一个更简单的例子可能是

<p>
    Switch language to:

    {% for site in sitePicker.sites %}
        <a href="{{ site.url }}">{{ site.name }}</a>
    {% endfor %}
</p>

消息翻译

消息或字符串翻译是将整个网站中使用的临时字符串转换为其他语言的过程。可以带有参数翻译消息。

{{ 'site.name'|_ }}

{{ 'Welcome to our website!'|_ }}

{{ 'Hello :name!'|_({ name: 'Friend' }) }}

消息也可以为选择用途进行翻译。

{{ 'There are no apples|There are :number applies!'|__(2, { number: 'two' }) }}

或者您可以通过传递第二个参数手动设置区域。

{{ 'this is always english'|_({}, 'en') }}

主题可以通过在主题目录中定义theme.yaml文件中的translate键来为这些消息提供默认值。

name: My Theme
# [...]

translate:
    en:
        site.name: 'My Website'
        nav.home: 'Home'
        nav.video: 'Video'
        title.home: 'Welcome Home'
        title.video: 'Screencast Video'

您还可以在单独的文件中定义翻译,路径相对于主题。以下定义将从主题中的config/lang.yaml文件中获取默认消息。

name: My Theme
# [...]

translate: config/lang.yaml

以下是一个包含两种语言的config/lang.yaml文件示例

en:
    site.name: 'My Website'
    nav.home: 'Home'
    nav.video: 'Video'
    title.home: 'Welcome Home'
hr:
    site.name: 'Moje web stranice'
    nav.home: 'Početna'
    nav.video: 'Video'
    title.home: 'Dobrodošli'

您还可以为每个区域定义单独的翻译文件,路径相对于主题。以下定义将从主题中的config/lang-en.yaml文件为英语区域获取默认消息,并从config/lang-fr.yaml文件为法语区域获取消息。

name: My Theme
# [...]

translate:
    en: config/lang-en.yaml
    fr: config/lang-fr.yaml

以下是一个config/lang-en.yaml文件示例

site.name: 'My Website'
nav.home: 'Home'
nav.video: 'Video'
title.home: 'Welcome Home'

为了使这些默认值反映到您的前端网站上,请转到后端中的设置 -> 翻译消息,然后点击扫描消息。它们也会在激活主题时自动加载。

可以使用translate:scan artisan命令执行相同的操作。值得将其包含在部署脚本中,以自动获取更新的消息。

php artisan translate:scan

添加--purge选项以先清除旧消息

php artisan translate:scan --purge

内容 & 邮件模板翻译

此插件激活了CMS中的一个功能,允许内容 & 邮件模板文件使用语言后缀,例如

  • welcome.htm将包含默认语言的文本或邮件模板。
  • welcome-ru.htm 将包含俄语的文本或邮件模板。
  • welcome-fr.htm 将包含法语的文本或邮件模板。

模型翻译

可以使用 RainLab\Translate\Behaviors\TranslatableModel 行为,并在类中指定要翻译的属性来翻译模型的属性。

class User
{
    public $implement = [
        \RainLab\Translate\Behaviors\TranslatableModel::class
    ];

    public $translatable = ['name'];
}

属性将包含默认语言值,其他语言代码值可以通过使用 translateContext() 方法创建。

$user = User::first();

// Outputs the name in the default language
echo $user->name;

$user->translateContext('fr');

// Outputs the name in French
echo $user->name;

您可以使用相同的过程来设置值。

$user = User::first();

// Sets the name in the default language
$user->name = 'English';

$user->translateContext('fr');

// Sets the name in French
$user->name = 'Anglais';

lang() 方法是 translateContext() 的简写版本,并且也是可链的。

// Outputs the name in French
echo $user->lang('fr')->name;

这可以在 Twig 模板中使用。

{{ user.lang('fr').name }}

有方法可以在不更改上下文的情况下获取和设置属性。

// Gets a single translated attribute for a language
$user->getAttributeTranslated('name', 'fr');

// Sets a single translated attribute for a language
$user->setAttributeTranslated('name', 'Jean-Claude', 'fr');

主题数据翻译

还可以翻译主题自定义选项。只需用 translatable 属性标记您的表单字段,插件就会处理其他所有事情。

tabs:
    fields:
        website_name:
            tab: Info
            label: Website Name
            type: text
            default: Your website name
            translatable: true

回退属性值

默认情况下,未翻译的属性将回退到默认区域设置。可以通过在读取值时调用 noFallbackLocale 方法来禁用此行为。

$user = User::first();

$user->noFallbackLocale()->lang('fr');

// Returns NULL if there is no French translation
$user->name;

在写入值时,回退值是在翻译的值与默认值匹配时确定的。在这些情况下,翻译的值被视为未翻译的值,并不会存储。

例如,如果 en 默认区域设置将消息存储为 "Hello World" 并且 fr 区域设置的值也是 "Hello World",那么 fr 值将不会存储。使用从 en 取得的回退值来访问 fr 值。

您可以通过传递一个包含 $transatable 属性值的数组来禁用此行为。第一个值是属性名,其他值代表选项,在这种情况下将选项 fallback 设置为 false

public $translatable = [
    ['title', 'fallback' => false]
];

上述定义将强制 title 属性值在所有区域设置中重复并存储。

索引属性

可以通过将 $transatable 属性值作为数组传递来将可翻译模型属性声明为索引。第一个值是属性名,其他值代表选项,在这种情况下将选项 index 设置为 true

public $translatable = [
    'name',
    ['slug', 'index' => true]
];

一旦一个属性被索引,就可以使用 transWhere 方法对模型应用基本查询。

Post::transWhere('slug', 'hello-world')->first();

transWhere 方法接受一个第三个参数来明确传递一个区域值,否则它将从环境中检测。

Post::transWhere('slug', 'hello-world', 'en')->first();

URL 翻译

CMS 中的页面支持翻译 URL 属性。假设您已设置了 3 种语言

  • en: 英语
  • fr: 法语
  • ru: 俄语

有一个包含以下内容的页面

url = "/contact"

[viewBag]
localeUrl[ru] = "/контакт"
==
<p>Page content</p>

法语中 "Contact" 这个词是一样的,因此没有提供或需要翻译的 URL。如果页面未指定 URL 覆盖,则将使用默认 URL。对于给定的语言,页面不会重复。

  • /fr/contact - 法语页面
  • /en/contact - 英语页面
  • /ru/контакт - 俄语页面
  • /ru/contact - 404

在 Twig 中翻译 URL

localeUrl 方法将替换一个 URL 上的路由前缀以从一个区域设置转换为另一个区域设置。例如,将当前请求 URL 从 en 转换为 de

{{ this.request.url|localeUrl('de') }}

localePage 将返回 CMS 页面的翻译 URL。它接受一个区域(第一个参数)和页面参数(第二个参数)。

{{ 'blog/post'|localePage('de', { slug: 'foobar' }) }}

URL 参数翻译

可以通过监听在发现语言 URL 时触发的 cms.sitePicker.overrideParams 事件来翻译 URL 参数。

Event::listen('cms.sitePicker.overrideParams', function($page, $params, $oldSite, $newSite) {
    if ($page->baseFileName == 'your-page-filename') {
        return MyModel::translateParams($params, $oldSite->hard_locale, $newSite->hard_locale);
    }
});

MyModel 中,一个可能的实现可能如下所示

public static function translateParams($params, $oldLocale, $newLocale)
{
    $newParams = $params;
    foreach ($params as $paramName => $paramValue) {
        $records = self::transWhere($paramName, $paramValue, $oldLocale)->first();
        if ($records) {
            $records->translateContext($newLocale);
            $newParams[$paramName] = $records->$paramName;
        }
    }
    return $newParams;
}

查询字符串翻译

可以通过监听在切换语言时触发的 cms.sitePicker.overrideQuery 事件来翻译查询字符串参数。

Event::listen('cms.sitePicker.overrideQuery', function($page, $params, $oldSite, $newSite) {
    if ($page->baseFileName == 'your-page-filename') {
        return MyModel::translateParams($params, $oldSite->hard_locale, $newSite->hard_locale);
    }
});

关于 MyModel::translateParams 方法的可能实现,请参考上方的 URL参数翻译 中的示例。

扩展主题扫描

Event::listen('rainlab.translate.themeScanner.afterScan', function (ThemeScanner $scanner) {
    // ...
});

设置模型翻译

可以像其他模型一样翻译设置模型。要检索翻译后的值,请使用

Settings::instance()->getAttributeTranslated('your_attribute_name');

有条件地扩展插件

模型

可以通过在行为定义前放置一个 @ 符号来有条件地扩展插件模型以支持翻译。这是一个软实现,只有当安装了 Translate 插件时才会使用 TranslatableModel,否则不会引发任何错误。

/**
 * Post Model for the blog
 */
class Post extends Model
{
    // [...]

    /**
     * @var array implement the TranslatableModel behavior softly.
     */
    public $implement = ['@'.\RainLab\Translate\Behaviors\TranslatableModel::class];

    /**
     * @var array translatable attributes, if available.
     */
    public $translatable = ['title'];

    // [...]
}

后端表单将自动检测可翻译字段的存在,并替换它们的控件为多语言等效控件。

用户界面

切换区域设置

用户可以通过点击后端面板中的站点选择菜单来在区域设置之间切换。这将向 URL 添加一个 _site_id 查询值,允许使用多个浏览器标签。