zymeli/yii2-translate-manager

Yii 2的翻译管理扩展

安装: 13

依赖: 0

建议者: 0

安全: 0

星星: 1

关注者: 0

分支: 90

开放问题: 0

类型:yii2-extension

1.8.1.2 2023-07-04 14:14 UTC

This package is auto-updated.

Last update: 2024-09-06 03:13:35 UTC


README

Latest Version on Packagist Software License Total Downloads

Yii 2的翻译管理扩展

简介

此模块为项目中的多语言元素提供了一个简单的翻译界面。它可以自动检测新的语言元素(项目扫描)。在项目扫描过程中自动过滤重复项。可以一键从数据库中删除未使用的语言元素(数据库优化),并可以导入和导出翻译。还可以翻译客户端消息(存储在JavaScript文件中的消息),因为项目扫描还会收集要翻译的JavaScript文件中的语言元素。

它还允许您在不登录翻译界面的情况下翻译客户端(实时网页)上的文本。(前端翻译)。

在服务器端,它可以处理数据库或一维/多维数组元素以及Yii::t函数。您可以排除文件、文件夹或类别,以防止它们被翻译。

贡献

请阅读并遵循贡献指南中的说明。

安装

通过Composer

composer require zymeli/yii2-translate-manager

迁移

在终端中运行以下命令进行数据库迁移

yii migrate/up --migrationPath=@vendor/zymeli/yii2-translate-manager/migrations

或使用命名空间迁移(需要至少Yii 2.0.10)

// Add namespace to console config:
'controllerMap' => [
    'migrate' => [
        'class' => 'yii\console\controllers\MigrateController',
        'migrationNamespaces' => [
            'zymeli\TranslateManager\migrations\namespaced',
        ],
    ],
],

然后运行

yii migrate/up

配置

以下是一个简单的示例,说明如何开启Yii数据库多语言。

'language' => 'en-US',
'components' => [
    'i18n' => [
        'translations' => [
            '*' => [
                'class' => 'yii\i18n\DbMessageSource',
                'db' => 'db',
                'sourceLanguage' => 'xx-XX', // Developer language
                'sourceMessageTable' => '{{%language_source}}',
                'messageTable' => '{{%language_translate}}',
                'cachingDuration' => 86400,
                'enableCaching' => true,
            ],
        ],
    ],
],

开启TranslateManager模块

简单示例

'modules' => [
    'translatemanager' => [
        'class' => 'zymeli\TranslateManager\Module',
    ],
],

以下是一个更复杂的示例,包括具有多语言支持的数据库表

'modules' => [
    'translatemanager' => [
        'class' => 'zymeli\TranslateManager\Module',
        'root' => '@app',               // The root directory of the project scan.
        'scanRootParentDirectory' => true, // Whether scan the defined `root` parent directory, or the folder itself.
                                           // IMPORTANT: for detailed instructions read the chapter about root configuration.
        'layout' => 'language',         // Name of the used layout. If using own layout use 'null'.
        'allowedIPs' => ['127.0.0.1'],  // IP addresses from which the translation interface is accessible.
        'roles' => ['@'],               // For setting access levels to the translating interface.
        'tmpDir' => '@runtime',         // Writable directory for the client-side temporary language files.
                                        // IMPORTANT: must be identical for all applications (the AssetsManager serves the JavaScript files containing language elements from this directory).
        'phpTranslators' => ['::t'],    // list of the php function for translating messages.
        'jsTranslators' => ['lajax.t'], // list of the js function for translating messages.
        'patterns' => ['*.js', '*.php'],// list of file extensions that contain language elements.
        'ignoredCategories' => ['yii'], // these categories won't be included in the language database.
        'onlyCategories' => ['yii'],    // only these categories will be included in the language database (cannot be used together with "ignoredCategories").
        'ignoredItems' => ['config'],   // these files will not be processed.
        'scanTimeLimit' => null,        // increase to prevent "Maximum execution time" errors, if null the default max_execution_time will be used
        'searchEmptyCommand' => '!',    // the search string to enter in the 'Translation' search field to find not yet translated items, set to null to disable this feature
        'defaultExportStatus' => 1,     // the default selection of languages to export, set to 0 to select all languages by default
        'defaultExportFormat' => 'json',// the default format for export, can be 'json' or 'xml'
        'tables' => [                   // Properties of individual tables
            [
                'connection' => 'db',   // connection identifier
                'table' => '{{%language}}',         // table name
                'columns' => ['name', 'name_ascii'],// names of multilingual fields
                'category' => 'database-table-name',// the category is the database table name
            ]
        ],
        'scanners' => [ // define this if you need to override default scanners (below)
            '\zymeli\TranslateManager\services\scanners\ScannerPhpFunction',
            '\zymeli\TranslateManager\services\scanners\ScannerPhpArray',
            '\zymeli\TranslateManager\services\scanners\ScannerJavaScriptFunction',
            '\zymeli\TranslateManager\services\scanners\ScannerDatabase',
        ],
    ],
],

配置扫描根目录

根路径可以是别名或完整路径(例如@app/webroot/site/)。

文件扫描器将扫描配置的文件夹以查找可翻译元素。以下两个选项确定扫描根目录:rootscanRootParentDirectory。这些选项默认为适用于Yii 2高级项目模板的值。如果您使用基本模板,则需要修改这些设置。

root选项指定项目扫描的根文件夹。它可以是单个目录(字符串),也可以是多个目录(数组中)。

scanRootParentDirectory仅在指定单个根目录时使用。

重要:更改这些选项可能会导致翻译项丢失,因为优化操作会删除缺失的项目。因此,请务必仔细检查您的配置!

a) 单个根目录

可以在root选项中定义一个字符串形式的单个根目录。在这种情况下,将使用scanRootParentDirectory确定要扫描的实际目录。

如果将scanRootParentDirectory设置为true(这是默认值),则扫描将在父目录上运行。在高级模板中,这是期望的行为,因为@app是当前应用程序的根,它是项目中的一个子目录(因此项目的整个根目录是@app的父目录)。

对于基本模板,@app也是整个项目的根。由于这个原因,使用默认值scanRootParentDirectory,扫描将在项目文件夹之外运行。这不是期望的行为,将值更改为false可以解决这个问题。

重要:scanRootParentDirectorytrue更改为false可能会导致翻译项丢失,因为根目录将不同。

例如

b) 多个根目录

可以在数组中定义多个根目录。在这种情况下,所有项都必须指向确切的目录,因为 scanRootParentDirectory 将被省略

例如

'root' => [
    '@frontend',
    '@vendor',
    '/some/external/folder',
],

使用 authManager

示例

PhpManager

'components' => [
    'authManager' => [
        'class' => 'yii\rbac\PhpManager',
    ],
    // ...
],

DbManager

'components' => [
    'authManager' => [
        'class' => 'yii\rbac\DbManager',
    ],
    // ...
],

前端翻译

'bootstrap' => ['translatemanager'],
'components' => [
    'translatemanager' => [
        'class' => 'zymeli\TranslateManager\Component'
    ]
]

用法

注册客户端脚本

要将 JavaScript 文件中的静态消息翻译,需要注册这些文件。

要注册您的脚本,在每个动作中调用以下方法

\zymeli\TranslateManager\helpers\Language::registerAssets();

在每次页面加载时调用上述方法的简单示例

namespace common\controllers;

use zymeli\TranslateManager\helpers\Language;

// IMPORTANT: all Controllers must originate from this Controller!
class Controller extends \yii\web\Controller {

    public function init() {
        Language::registerAssets();
        parent::init();
    }
}

切换翻译按钮

显示一个按钮以切换到前端翻译模式的简单示例。(按钮只会为具有翻译所需权限的用户显示!)

\zymeli\TranslateManager\widgets\ToggleTranslate::widget();

显示按钮的更复杂示例

\zymeli\TranslateManager\widgets\ToggleTranslate::widget([
 'position' => \zymeli\TranslateManager\widgets\ToggleTranslate::POSITION_TOP_RIGHT,
 'template' => '<a href="javascript:void(0);" id="toggle-translate" class="{position}" data-language="{language}" data-url="{url}"><i></i> {text}</a><div id="translate-manager-div"></div>',
 'frontendTranslationAsset' => 'zymeli\TranslateManager\bundles\FrontendTranslationAsset',
 'frontendTranslationPluginAsset' => 'zymeli\TranslateManager\bundles\FrontendTranslationPluginAsset',
]);

在源代码中放置多语言元素。

JavaScript

lajax.t('Apple');
lajax.t('Hello {name}!', {name:'World'});
lajax.t("Don't be so upset.");

PHP 方法

Yii::t('category', 'Apple');
Yii::t('category', 'Hello {name}!', ['name' => 'World']);
Yii::t('category', "Don't be so upset.");

用于前端翻译的 PHP 函数

use zymeli\TranslateManager\helpers\Language as Lx;

Lx::t('category', 'Apple');
Lx::t('category', 'Hello {name}!', ['name' => 'World']);
Lx::t('category', "Don't be so upset.");

重要:zymeli\TranslateManager\helpers\Language::t()(Lx::t())函数目前不支持翻译 HTML 属性

PHP 数组

/**
 * @translate
 */
private $_STATUSES = [
    self::STATUS_INACTIVE => 'Inactive',
    self::STATUS_ACTIVE => 'Active',
    self::STATUS_DELETED => 'Deleted'
];

/**
 * Returning the 'status' array on the site's own language.
 * return array
 */
public function getStatuses() {
    return \zymeli\TranslateManager\helpers\Language::a($this->_STATUSES);
}

/**
 * @translate
 */
private $_GENDERS = ['Male', 'Female'];

/**
 * Returning the 'genders' array in German
 * return array
 */
public function getGenders() {
    return \zymeli\TranslateManager\helpers\Language::a($this->_GENDERS, 'de-DE');
}

PHP 数据库

  • 带有新属性
namespace common\models;

use zymeli\TranslateManager\helpers\Language;

/**
 * This is the model class for table "category".
 *
 * @property string $category_id
 * @property string $name
 * @property string $description
 */
class Category extends \yii\db\ActiveRecord {

    // afterFind & beforeSave:

    /**
     * @var Returning the 'name' attribute on the site's own language.
     */
    public $name_t;

    /**
     * @var Returning the 'description' attribute on the site's own language.
     */
    public $description_t;

    /* ... */

    public function afterFind() {
        $this->name_t = Language::d($this->name);
        $this->description_t = Language::d($this->descrioption);

        // or If the category is the database table name.
        // $this->name_t = Language::t(static::tableName(), $this->name);
        // $this->description_t = Language::t(static::tableName(), $this->description);
        parent::afterFind();
    }

    public function beforeSave($insert) {
        if (parent::beforeSave($insert)) {
            Language::saveMessage($this->name);
            Language::saveMessage($this->description);

            // or If the category is the database table name.
            // Language::saveMessage($this->name, static::tableName());
            // Language::saveMessage($this->description, static::tableName());

            return true;
        }

        return false;
    }

    // or GETTERS:

    /**
     * @return string Returning the 'name' attribute on the site's own language.
     */
    public function getName($params = [], $language = null) {
        return Language::d($this->name, $params, $language);

        // or If the category is the database table name.
        // return Language::t(static::tableName(), $this->name, $params, $language);
    }

    /**
     * @return string Returning the 'description' attribute on the site's own language.
     */
    public function getDescription($params = [], $language = null) {
        return Language::d($this->description, $params, $language);

        // or If the category is the database table name.
        // return Language::t(static::tableName(), $this->description, $params, $language);
    }
}
  • 带有行为(自 1.5.3 以来)

    此行为执行以下操作

    • 在模型加载后替换指定的属性为翻译。
    • 保存属性值作为
      1. 源消息,如果当前语言是源语言。
      2. 翻译,如果当前语言不同于源语言。这样,数据库中存储的值不会被翻译覆盖。

    注意:如果模型应作为翻译保存,但源消息尚未在数据库中存在,则无论当前语言是否为源语言,消息都保存为源消息。为了避免这种情况,在第一次使用行为时扫描数据库中的现有消息,并且仅在当前语言是源语言时保存新记录。

namespace common\models;

/**
 * This is the model class for table "category".
 *
 * @property string $category_id
 * @property string $name
 * @property string $description
 */
class Category extends \yii\db\ActiveRecord {

    // TranslateBehavior

    public function behaviors()
    {
        return [
            [
                'class' => \zymeli\TranslateManager\behaviors\TranslateBehavior::className(),
                'translateAttributes' => ['name', 'description'],
            ],

            // or If the category is the database table name.
            // [
            //     'class' => \zymeli\TranslateManager\behaviors\TranslateBehavior::className(),
            //     'translateAttributes' => ['name', 'description'],
            //     'category' => static::tableName(),
            // ],
        ];
    }

}

URLs

翻译工具的 URL

/translatemanager/language/list         // List of languages and modifying their status
/translatemanager/language/create       // Create languages
/translatemanager/language/scan         // Scan the project for new multilingual elements
/translatemanager/language/optimizer    // Optimise the database

将 Yii2 菜单的实现集成到您自己的菜单中的示例。

$menuItems = [
    ['label' => Yii::t('language', 'Language'), 'items' => [
            ['label' => Yii::t('language', 'List of languages'), 'url' => ['/translatemanager/language/list']],
            ['label' => Yii::t('language', 'Create'), 'url' => ['/translatemanager/language/create']],
        ]
    ],
    ['label' => Yii::t('language', 'Scan'), 'url' => ['/translatemanager/language/scan']],
    ['label' => Yii::t('language', 'Optimize'), 'url' => ['/translatemanager/language/optimizer']],
    ['label' => Yii::t('language', 'Im-/Export'), 'items' => [
        ['label' => Yii::t('language', 'Import'), 'url' => ['/translatemanager/language/import']],
        ['label' => Yii::t('language', 'Export'), 'url' => ['/translatemanager/language/export']],
    ]
];

控制台命令

注册命令

'controllerMap' => [
    'translate' => \zymeli\TranslateManager\commands\TranslatemanagerController::className()
],

使用 Yii CLI 使用它

./yii translate/scan
./yii translate/optimize

已知问题

  • 扫描器正在扫描父根目录 #12

    您可以使用 scanRootParentDirectory 选项覆盖此行为。(有关详细信息,请参阅配置部分。)

  • 在隐藏标签中翻译字符串会损坏 HTML。 #45

编码风格

项目使用 PSR-2 编码标准。

可以使用以下命令修复编码风格问题

composer cs-fix

您可以检查代码,而不会影响它

composer cs-fix-dry-run

更改日志

请参阅 CHANGELOG 以获取有关最近更改的更多信息。

许可证

MIT 许可证(MIT)。请参阅 许可证文件 以获取更多信息。

屏幕截图

语言列表

translate-manager-0 2-screen-1

扫描项目

translate-manager-0 2-screen-2

优化数据库

translate-manager-0 2-screen-3

在管理界面中翻译

translate-manager-0 2-screen-4

翻译模式的前端

translate-manager-0 2-screen-6

在前端翻译

translate-manager-0 2-screen-7

链接