lucinda / internationalization
高性能API,通过JSON文件为PHP应用程序执行国际化本地化
Requires
- php: ^8.1
- ext-simplexml: *
Requires (Dev)
- lucinda/unit-testing: ^2.0
README
目录
关于
此API是一个非常轻量级的平台,允许根据用户区域设置自动翻译展示逻辑(视图)(请参阅如何检测区域设置)。为了实现这一点,它期望视图的文本部分被细分为细粒度单元(理想情况下不包含HTML),每个单元由一个唯一的关键字标识,并存储在主题+区域特定字典文件中(请参阅如何存储翻译)。
这样,您的HTML视图就变成了一个网络,这些单元在编译时预期会被翻译,如下例所示
<html> <body> <h1>__("title")</h2> <p>__("description")</p> </body> </html>
由于视图渲染/编译的逻辑是MVC API的关注点,而不是根据检测到的区域设置在响应中执行关键字替换并基于翻译进行,API为开发者提供了一个平台,该平台能够根据以下步骤自动检测用户区域设置以及设置/获取基于以下步骤的翻译
- 配置:设置一个XML文件,其中API已配置用于区域设置检测和翻译存储
- 执行:根据上述内容创建一个Lucinda\Internationalization\Wrapper实例,以通过关键字获取/设置翻译
API完全符合PSR-4规范,仅需要PHP 8.1+解释器和SimpleXML扩展。要快速了解它的工作原理,请检查
- 安装:描述了如何在计算机上安装API,根据上述步骤
- 单元测试:API具有100%的单元测试覆盖率,使用UnitTest API而不是PHPUnit以获得更大的灵活性
- 示例:展示了基于单元测试的Lucinda\Internationalization\Wrapper功能的一个深入示例
如何检测区域设置
此API将区域设置理解为两位数字的小写ISO语言代码和两位数字的大写ISO国家代码(例如:en_US)的组合,由下划线连接。API能够根据以下机制检测用户区域设置
- header:通过请求头中Accept-Language的值(例如:$_SERVER["HTTP_ACCEPT_LANGUAGE"]= "fr-FR, fr;q=0.9, en;q=0.8, de;q=0.7, *;q=0.5");
- request:通过请求中locale查询字符串参数的值(例如:$_GET["locale"] = "fr_FR");
- session:通过会话中locale参数的值(例如:$_SESSION["locale"] = "fr_FR");
如果无法检测到区域设置,则将使用默认值(特定于您的应用程序)。
如何存储翻译
API期望将翻译存储在JSON文件中。每个JSON文件都位于磁盘上的folder/locale/domain.extension路径中,其中
- folder:存放翻译的应用程序根目录中的文件夹。默认:"locale"
- locale:查找翻译的locale/language。例如:"fr_FR"
- domain:翻译文件的名称。默认:"messages"
- extension:翻译文件的扩展名。默认:"json"
该文件的结构是一个字典,其中键是标识每个待翻译单元的短关键词,值是将在视图编译时替换关键词的翻译文本。这意味着对于每个域,JSON文件必须包含相同的关键词,但具有特定于locale/language的不同值。如果关键词在JSON文件中没有匹配的翻译,它将按原样出现在视图编译时(与GETTEXT标准一致)。
示例
- locale/en_US/greetings.json
{"hello":"Hello!", "welcome":"Welcome to my site, %0!"}
- locale/ro_RO/greetings.json
{"hello":"Salut!", "welcome":"Bun venit pe situl meu, %0!"}
配置
要配置此API,您必须有一个包含国际化标签的XML文件,其语法如下
<internationalization method="..." folder="..." locale="..." domain="..." extension="..."/>
其中
- method:(强制)标识如何检测locale(参见如何检测locale)。可以是:header,request,session!
- folder:(可选)存放翻译的应用程序根目录中的文件夹(参见如何存储翻译)。如果没有设置,则假定"locale"。
- locale:(强制)默认的locale,其中将查找翻译(参见如何存储翻译)。例如:en_US
- domain:(可选)翻译文件的名称(参见如何存储翻译)。如果没有设置,则假定"messages"。
- extension:(可选)翻译文件的扩展名(参见如何存储翻译)。如果没有设置,则假定"json"。
执行
现在XML已配置,您可以使用Lucinda\Internationalization\Wrapper初始化API
$object = new Lucinda\Internationalization\Wrapper(simplexml_load_file(XML_FILE_NAME), $_GET, getallheaders());
此类读取XML和用户请求,编译国际化设置,并使以下公共方法能够设置和获取基于以下方法的翻译
一旦创建了实例,就可以使用以下方法操作单元翻译
- getReader:获取一个Lucinda\Internationalization\Reader对象,该对象能够根据检测到的locale从存储中检索翻译
- getWriter:获取一个Lucinda\Internationalization\Writer对象,该对象能够根据检测到的locale使用存储保存/删除翻译
安装
首先选择一个文件夹,将其与一个域关联,然后在控制台中在其文件夹中写入以下命令
composer require lucinda/internationalization
然后创建一个包含配置设置的configuration.xml文件(参见上面的配置)和一个在项目根目录中的index.php文件,其中包含以下代码
require(__DIR__."/vendor/autoload.php"); $request = new Lucinda\Internationalization\Wrapper(); $reader = $request->getReader();
然后在响应渲染之前进行干预,以将单元关键词替换为翻译。例如,如果您的HTML是
<html> <body> <h1>__("title")</h2> <p>__("description")</p> </body> </html>
则此正则表达式将执行检测到的locale特定的翻译替换
$response = preg_replace_callback('/__\("([^"]+)"\)/', function($matches) use ($reader) { return $reader->getTranslation($matches[1]); }, $response);
单元测试
有关测试和示例,请检查API源中的以下文件/文件夹
- test.php:在控制台中运行单元测试
- unit-tests.xml:设置单元测试
- tests:来自 src 文件夹的类单元测试
参考指南
类 Reader
Lucinda\Internationalization\Reader 封装从 存储 中检索单元翻译,并定义以下相关公共方法
类 Writer
Lucinda\Internationalization\Writer 封装向 存储 中添加/更新/删除单元翻译,并定义以下相关公共方法