mistralys / application-localization
PHP和JavaScript本地化库。
Requires
- php: >=7.3
- ext-json: *
- ext-mbstring: *
- mistralys/application-utils: >=1.2.0
- mistralys/jtokenizer: >=1.0.1
Requires (Dev)
- phpstan/phpstan: ^0.12
- phpunit/phpunit: 8.2.5
README
应用本地化
PHP和JavaScript本地化库,用PHP编写。它是一个简单但强大的本地化层,将翻译的字符串存储在ini文件中。
亮点
- 易于调整以适应应用程序的文件结构
- 内置的翻译UI,可以集成到现有的UI中
- 使用自动生成的包含文件进行客户端翻译
- 为翻译者提供带有或没有翻译上下文信息的翻译
安装
只需通过composer要求该包
composer require mistralys/application-localization
也可以查看Packagist页面。
配置
1) 添加地区
本地应用程序的地区应为英语。任何额外的地区都可以这样添加
use AppLocalize\Localization; Localization::addAppLocale('de_DE'); Localization::addAppLocale('fr_FR');
注意:该包尚未与非拉丁语脚本(如汉字、日语、韩语、越南语或梵语(印度、藏语、泰语、老挝语))进行测试。
2) 添加文件源文件夹
这定义了在哪些文件夹中搜索PHP或JavaScript文件。这些文件将被分析以找到所有翻译函数调用的地方。
按如下方式注册要查找的每个文件夹
use AppLocalize\Localization; $source = Localization::addSourceFolder( 'source-slug', // Must be unique: used in file names and to access the source programmatically 'Source label', // Human readable label 'Group label', // Group labels are used to group sources in the UI '/path/to/ini/files/', // The localization files will be stored here '/path/to/source/files/' // The PHP and JavaScript source files to search through are here );
排除文件和文件夹
出于性能原因,建议排除任何不需要分析的文件或文件夹。特别是JavaScript分析仍然有与压缩库文件(如jQuery或Bootstrap)相关的问题,因此它们应该被排除。
按名称排除文件夹或文件
$source->excludeFolder('foldername'); $source->excludeFile('jquery'); // any file with "jquery" in its name $source->excludeFile('jquery-ui.min.js'); // by exact file name match
注意:无需指定绝对路径或文件名,只要名称是唯一的即可。
3) 主要配置设置
注意:必须在定义地区和源之后完成此操作。
use AppLocalize\Localization; Localization::configure( '/path/to/analysis/cache.json', // Where the text information cache may be saved '/path/to/javascript/includes/' // Where the clientside files should be stored (Optional) );
如果没有指定客户端包含路径,则将禁用它们。
4) 选择目标地区
默认地区为英语,您可以使用此操作随时切换地区
use AppLocalize\Localization; Localization::selectAppLocale('de_DE');
注意:您的应用程序逻辑必须处理选择哪个地区使用的决策。
包含客户端库(可选)
本地化库会自动在您在步骤3中指定的文件夹中创建必要的JavaScript包含文件。在您的应用程序中包含以下文件以启用翻译函数
locale-xx.js
md5.min.js
translator.js
其中xx
是目标语言的两位字母ISO代码。对于您添加的每个地区,都有一个。
一旦写入了JavaScript包含文件,它们仅在本地化编辑器UI中更新文本时刷新。我们建议使用缓存键(见下文)。
使用缓存键更新库
库缓存键是一个可以设置的任意字符串。每当它更改时,JavaScript包含文件都会自动刷新。保持它们更新的好方法是使用您应用程序的版本号作为缓存键。
$myAppVersion = 'v1.5.1'; Localization::setClientLibrariesCacheKey($myAppVersion);
应用程序每次发布时都会自动刷新库。
使用翻译函数
服务器端设置
要使用翻译函数,您必须添加所需的use语句
use function AppLocalize\t; use function AppLocalize\pt; use function AppLocalize\pts; use function AppLocalize\tex; use function AppLocalize\ptex; use function AppLocalize\ptexs;
《t()`函数
无论是服务器端还是客户端,您都可以使用《t()`函数将文本自动翻译为目标地区。只需将任何原生英语文本包装在函数调用中即可。
PHP
$text = t('Text to translate here');
JavaScript
var text = t('Text to translate here');
《pt()`和《pts()`函数
注意:此功能仅适用于服务器端。
这些与 t()
相同,但它们会回显翻译后的字符串。这对于模板来说非常有用
<title><?php pt('Page title') ?></title>
pts()
函数会在翻译后的字符串后添加一个空格,这样在链式拼接多个字符串时,您就无需手动添加空格
<div> <?php pts('First sentence here.'); pts('Second sentence here.'); ?> </div>
使用占位符
翻译函数接受任意数量的附加参数,这些参数会通过 sprintf PHP 函数注入到翻译后的字符串中。这意味着您可以使用如下占位符
$amount = 50; $text = t('We found %1$s entries.', $amount);
客户端,您可以使用相同的语法
var amount = 50; var text = t('We found %1$s entries.', amount);
使用占位符时,我们建议系统地使用编号占位符,如
%1$s
或%02d
。主要是因为占位符的顺序在翻译文本中经常发生变化,同时也是为了避免翻译人员混淆。
提供翻译上下文信息
在某些情况下,知道文本在哪个上下文中使用对于正确翻译至关重要。上下文风格的翻译函数提供了一个用于添加此上下文信息的第二个参数。
t()
->tex()
pt()
->ptex()
pts()
->ptexs()
use function AppLocalize\ptex; // Context information comes directly after the text. ptex( 'Text to translate', 'Context explanation for translators.' ); // Placeholder values come after the context information. ptex( '%1$s records', 'The placeholder contains the amount of records.', 42 );
上下文文本必须是一个字符串,就像要翻译的文本一样。允许换行和字符串连接,但不允许变量或函数,因为这是在离线提取的,而不是在运行时评估。
提示:可以使用基本的 HTML 标签进行格式化。
技巧与最佳实践
拆分句子
在一个典型的应用程序中,可翻译文本的数量可能会迅速增长。尽可能将文本拆分成可管理的块,将较长的文本拆分成更短的句子。这还有一个额外的优点,就是可以在其他地方重用一些这些文本块。
使用编号占位符
尽管语法比简单的 %s
更繁琐,但使用编号占位符对于允许根据语言的不同而改变句子结构至关重要。在另一种语言中,放在句子末尾的占位符可能需要移动到文本的开头。使用编号占位符可以轻松实现这一点。
注意:占位符在本地化 UI 中被突出显示,这样复杂的文本仍然可读。
将 HTML 标签放在占位符中
虽然将像 <strong>
或 <em>
这样的标签包含在要翻译的文本中是无害的选择,但仍应避免这样做。HTML 属于布局领域,原则上不应由翻译人员处理。
所以理想情况下,带有标记的文本应该看起来像这样
use function AppLocalize\t; $text = t('This is %1$sbold%2$s text.', '<strong>', '</strong>');
这样,应用程序不仅可以决定使用哪个标签,还可以在将来需要时添加类 - 而无需触及任何翻译文本。
例如,对文本链接也采用同样的方法
use function AppLocalize\t; $textWithLink = t( 'Please refer to the %1$sdocumentation%2$s for further details.', '<a href="http://...">', '</a>' );
模板文本
要多次使用翻译文本作为模板,只需将占位符替换为占位符即可。
听起来很奇怪?看看这个例子
use function AppLocalize\t; $template = t('Entry number %1$s', '%1$s');
翻译成德语后,变量 $template
中的文本会看起来像这样
Eintrag Nummer %1$s
这意味着现在您可以使用模板多次,而无需每次都调用翻译函数,只需使用 sprintf
PHP 函数即可
for($i=1; $i <= 10; $i++) { echo sprintf($template, $i); }
更进一步
Application Utils 包含一个字符串构建类,用于连接字符串,并且默认支持此包。使用这个类,可以轻松构建复杂句子,包括在 HTML 上下文中。
示例
use function AppUtils\sb; $html = (string)sb() ->bold(t('Easy string concatenation')) ->nl() ->t('For more information, see here:') ->link(t('Application Utils'), 'https://github.com/Mistralys/application-utils');
事件
当活动区域更改时
当在运行时选择不同的区域时,会触发 LocaleChanged
事件。可以为此事件添加监听器,并响应区域更改。
以下是一个示例
use AppLocalize\Localization; use AppLocalize\Localization_Event_LocaleChanged; Localization::addEventListener(Localization::EVENT_LOCALE_CHANGED, 'listenerFunction'); function listenerFunction(Localization_Event_LocaleChanged $event) : void { // do something }
示例
要运行示例编辑器 UI,只需在包文件夹中运行 composer update
,然后在浏览器中打开 example
文件夹(假设包位于您的 web 服务器根目录中)。
起源
其他地方有其他本地化库,但这个库在历史上被集成到几个应用程序中。为了便于维护,它被移动到一个独立的包中。它并不与任何现有的i18n库竞争。