构建 Laravel 翻译包 - 处理缺失的翻译键
发布于 作者 Joe Dixon
在本系列的上一期中,我们讨论了构建前端翻译管理工具。在本篇文章中,我们将从前端转向,介绍构建另一个后端功能的过程。
在 Laravel 应用程序中,翻译管理最令人沮丧的事情之一就是忘记在相应的语言文件中添加翻译。这会导致翻译键或默认语言在页面上渲染,而不是当前语言的翻译。

为了缓解这个问题,Laravel 翻译包提供了一种方法来扫描项目以查找在应用程序支持的所有语言的翻译文件中不存在的翻译。
我们通过递归地遍历所有已配置目录的所有文件来实现此过程的扫描部分,以查找任何Laravel 翻译检索方法(例如 __()
、trans()
)的实例。这些方法使用正则表达式捕获,并提取翻译字符串。这些字符串可以与现有的翻译进行比较,以查看它们是否存在或是否需要创建。
配置
在包配置中,定义了两个键,以使扫描仪更灵活、更高效。
'translation_methods' => ['trans', '__']
translation_methods
选项允许用户提供一个包含扫描仪用于查找键的翻译检索方法的数组。
'scan_paths' => [app_path(), resource_path()]
scan_paths
键允许用户定义一个包含扫描仪在搜索翻译键时要遍历的目录的数组。
当然,可以在这里使用 base_path()
来搜索整个项目,但是只定义你期望找到翻译的目录,会为扫描过程带来显著的加速。
实现
扫描功能由单个类处理。此类接受 Laravel 的 Illuminate\Filesystem\Filesystem
的实例,它使用该实例来遍历目录和与文件交互,以及上面提到的翻译方法和扫描路径的数组。
该类包含一个名为 findTranslations
的方法,它负责执行任务。它利用以下正则表达式,该表达式受到 Barry vd. Heuvel’s 的 Laravel 翻译管理器 包和 Mohamed Said’s 的 Laravel 语言管理器 包中找到的正则表达式的组合影响。
$matchingPattern = '[^\w]'. // Must not start with any alphanum or _ '(?<!->)'. // Must not start with -> '('.implode('|', $this->translationMethods).')'. // Must start with one of the functions "\(". // Match opening parentheses "[\'\"]". // Match " or ' '('. // Start a new group to match: '.+'. // Must start with group ')'. // Close group "[\'\"]". // Closing quote "[\),]"; // Close parentheses or new parameter
该方法使用正则表达式递归地遍历所提供目录中的所有文件,以查找所提供翻译检索方法的实例,并返回所有匹配项的数组。
在每个匹配项上,都会执行额外的检查,以确定匹配项是组翻译(php 数组样式)还是单个翻译(JSON 样式)。这可以通过简单地检查匹配项是否包含句点来完成。如果是,则句点之前的部分是文件,句点之后的部分是键(例如,你可以通过从 validation.php
文件中获取 accepted
键来找到 validation.accepted
的翻译)。
最后,我们得到一个类似于下面的数组
[ 'single' => [ 'Welcome' => 'Welcome' ], 'group' => [ 'validation' => [ 'accepted' => 'The :attribute must be accepted.', ... ], ],];
当然,这样做会得到在配置路径中找到的所有翻译,那么我们如何确定哪些是缺失的呢?很简单,我们现在在数组中拥有了应用程序中所有标记的翻译,并且可以使用我们在本系列的早期创建的文件驱动程序以数组格式获取语言文件中的所有翻译。
不仅如此,这两个数组的格式也将相同,所以我们只需要对它们进行比较即可。我们可以得出结论,在从应用程序扫描中收集到的翻译数组中,语言文件翻译中没有出现的任何内容都需要添加到相关的语言文件中。
为此,我们只需遍历缺失的翻译,并利用文件驱动程序中已经内置的方法来添加它们。
$missingTranslations = $this->findMissingTranslations($language); if (isset($missingTranslations['single'])) { foreach ($missingTranslations['single'] as $key => $value) { $this->addSingleTranslation($language, $key); }} if (isset($missingTranslations['group'])) { foreach ($missingTranslations['group'] as $group => $keys) { foreach ($keys as $key => $value) { $this->addGroupTranslation($language, "{$group}.{$key}"); } }}
本文介绍了翻译包的基于文件的功能。下次,我们将利用已经建立的基础来启动我们的数据库驱动程序。下次再见,和往常一样,如果您有任何问题,请随时通过Twitter与我联系。