rainlab/translate-plugin 问题修复 & 功能扩展

解决BUG、新增功能、兼容多环境部署,快速响应你的开发需求

邮箱:yvsm@zunyunkeji.com | QQ:316430983 | 微信:yvsm316

rainlab/translate-plugin

Composer 安装命令:

composer require rainlab/translate-plugin

包简介

Translate plugin for October CMS

README 文档

README

Enables multi-lingual sites.

Selecting a Language

Different languages can be set up in the admin panel using the Settings → Sites area. Each site should use a different locale to be considered a language.

The visitor can select a language by prefixing the language code to the URL or using a dedicated hostname. For example:

  • http://website.tld/ will display the site in the default language
  • http://website.tld/ru/ will display the site in Russian
  • http://website.tld/fr/ will display the site in French

License

This plugin is an official extension of the October CMS platform and is free to use if you have a platform license. See EULA license for more details.

Installation

To install using October CMS v3.1 or above:

php artisan plugin:install rainlab.translate

To install using October CMS v3.0 and below:

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

Upgrading from v1 to v2

If you are upgrading from version 1 of this plugin, view the upgrade guide.

Language Picker Component

A visitor can select their chosen language using the native SitePicker component that is included in the October CMS core. This component will display a simple dropdown that changes the page language depending on the selection.

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>

If translated, the text above will appear as whatever language is selected by the user. The dropdown is very basic and is intended to be restyled. A simpler example might be:

<p>
    Switch language to:

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

Message Translation

Message or string translation is the conversion of adhoc strings used throughout the site. A message can be translated with parameters.

{{ 'site.name'|_ }}

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

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

A message can also be translated for a choice usage.

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

Or you set a locale manually by passing a second argument.

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

Themes can provide default values for these messages by defining a translate key in the theme.yaml file, located in the theme directory.

name: My Theme
# [...]

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

You may also define the translations in a separate file, where the path is relative to the theme. The following definition will source the default messages from the file config/lang.yaml inside the theme.

name: My Theme
# [...]

translate: config/lang.yaml

This is an example of config/lang.yaml file with two languages:

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'

You may also define the translations in a separate file per locale, where the path is relative to the theme. The following definition will source the default messages from the file config/lang-en.yaml inside the theme for the english locale and from the file config/lang-fr.yaml for the french locale.

name: My Theme
# [...]

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

This is an example for the config/lang-en.yaml file:

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

In order to make these default values reflected to your frontend site, go to Settings -> Translate messages in the backend and hit Scan for messages. They will also be loaded automatically when the theme is activated.

The same operation can be performed with the translate:scan artisan command. It may be worth including it in a deployment script to automatically fetch updated messages:

php artisan translate:scan

Add the --purge option to clear old messages first:

php artisan translate:scan --purge

Content & Mail Template Translation

This plugin activates a feature in the CMS that allows content & mail template files to use language suffixes, for example:

  • welcome.htm will contain the content or mail template in the default language.
  • welcome-ru.htm will contain the content or mail template in Russian.
  • welcome-fr.htm will contain the content or mail template in French.

Model Translation

Models can have their attributes translated by using the RainLab\Translate\Behaviors\TranslatableModel behavior and specifying which attributes to translate in the class.

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

    public $translatable = ['name'];
}

The attribute will then contain the default language value and other language code values can be created by using the translateContext() method.

$user = User::first();

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

$user->translateContext('fr');

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

You may use the same process for setting values.

$user = User::first();

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

$user->translateContext('fr');

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

The lang() method is a shorthand version of translateContext() and is also chainable.

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

This can be useful inside a Twig template.

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

There are ways to get and set attributes without changing the context.

// 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');

Theme Data Translation

It is also possible to translate theme customisation options. Just mark your form fields with translatable property and the plugin will take care about everything else:

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

Fallback Attribute Values

By default, untranslated attributes will fall back to the default locale. This behavior can be disabled by calling the noFallbackLocale method when reading the value.

$user = User::first();

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

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

When writing the value, the fallback value is determined when the translated value matches the default value. In these cases, the translated value is considered untranslated and not stored.

Locale Attribute Value Is Stored
en title Hello World Yes (Default)
fr title Hello World No
de title Hallo Welt Yes

For example, if the en default locale stores the message as "Hello World" and the fr locale value is also "Hello World", then the fr value is not stored. The fr value is accessed using the fallback value taken from en.

You may disable this behavior by passing the $transatable attribute value as an array. The first value is the attribute name, the other values represent options, in this case setting the option fallback to false.

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

This above definition will force the title attribute value to be duplicated and stored across all locales.

Indexed Attributes

Translatable model attributes can also be declared as an index by passing the $transatable attribute value as an array. The first value is the attribute name, the other values represent options, in this case setting the option index to true.

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

Once an attribute is indexed, you may use the transWhere method to apply a basic query to the model.

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

The transWhere method accepts a third argument to explicitly pass a locale value, otherwise it will be detected from the environment.

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

URL Translation

Pages in the CMS support translating the URL property. Assuming you have 3 languages set up:

  • en: English
  • fr: French
  • ru: Russian

There is a page with the following content:

url = "/contact"

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

The word "Contact" in French is the same so a translated URL is not given, or needed. If the page has no URL override specified, then the default URL will be used. Pages will not be duplicated for a given language.

  • /fr/contact - Page in French
  • /en/contact - Page in English
  • /ru/контакт - Page in Russian
  • /ru/contact - 404

Translating URLs in Twig

The localeUrl method will replace the route prefix on a URL from one locale to another. For example, converting the current request URL from en to de.

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

The localePage will return a translated URL for a CMS page. It takes a locale (first argument) and page parameters (second argument).

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

URL Parameter Translation

It's possible to translate URL parameters by listening to the cms.sitePicker.overrideParams event, which is fired when discovering language URLs.

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);
    }
});

In MyModel, one possible implementation might look like this:

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;
}

Query String Translation

It's possible to translate query string parameters by listening to the cms.sitePicker.overrideQuery event, which is fired when switching languages.

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);
    }
});

For a possible implementation of the MyModel::translateParams method look at the example under URL parameter translation from above.

Extend Theme Scan

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

Settings Model Translation

It's possible to translate your settings model like any other model. To retrieve translated values use:

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

Conditionally Extending Plugins

Models

It is possible to conditionally extend a plugin's models to support translation by placing an @ symbol before the behavior definition. This is a soft implement will only use TranslatableModel if the Translate plugin is installed, otherwise it will not cause any errors.

/**
 * 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'];

    // [...]
}

The back-end forms will automatically detect the presence of translatable fields and replace their controls for multilingual equivalents.

User Interface

Switching Locales

Users can switch between locales by clicking on the site selection menu in the backend panel. This will add a _site_id query value to the URL, allowing for multiple browser tabs to be used.

rainlab/translate-plugin 适用场景与选型建议

rainlab/translate-plugin 是一款 基于 PHP 开发的 Composer 扩展包,目前已累计 68.65k 次下载、GitHub Stars 达 126, 最近一次更新时间为 2016 年 07 月 16 日, 在 PHP 生态内属于活跃度较高的组件。

它主要适用于以下技术方向: 「translate」 「october」 「octobercms」 等业务场景。在实际项目中,围绕这些方向常见需要落地的问题包括:接口对接、性能调优、并发安全、与既有框架(Laravel / ThinkPHP / Yii / Webman 等)的兼容适配,以及生产环境的日志埋点与稳定性保障。

我们在过去多个企业项目中使用过 rainlab/translate-plugin 或与其功能相近的方案,如果你在选型或落地过程中遇到问题,例如 版本兼容、二次改造、私有化封装、与内部系统对接、生产 BUG 排查,欢迎联系我们协助评估。

围绕 rainlab/translate-plugin 我们能提供哪些服务?
定制开发 / 二次开发

基于 rainlab/translate-plugin 在你已有业务上做功能扩展、字段裁剪、UI 适配、与内部账号 / 权限 / 日志系统的深度对接。

BUG 修复 & 性能优化

线上偶发问题、内存泄漏、慢查询、并发异常等排查修复;针对高流量场景做缓存、队列、索引层面的调优。

项目外包 & 长期维护

承接完整的项目从需求 → 设计 → 开发 → 上线 → 长期运维;也可按月提供技术保姆服务。

yvsm@zunyunkeji.com QQ:316430983 微信:yvsm316 西安尊云信息科技 · 专注 PHP / Go / 分布式系统研发

统计信息

  • 总下载量: 68.65k
  • 月度下载量: 0
  • 日度下载量: 0
  • 收藏数: 126
  • 点击次数: 16
  • 依赖项目数: 8
  • 推荐数: 0

GitHub 信息

  • Stars: 126
  • Watchers: 14
  • Forks: 90
  • 开发语言: PHP

其他信息

  • 授权协议: MIT
  • 更新时间: 2016-07-16