laravel 的本地化 locale,用起来感觉很别扭,不能像其他框架一样,按照控制器等自动加载语言包。
结合文档,并查看了源码,简单总结下 laravel 本地化的使用:
1>支持引入 2 类文件:
1.php 文件(php 文件 return 一个数组)
不同语言包目录下,根据用途,可创建多个 xx.php,例如:
en
messages.php
other.php
zh-cn
messages.php
<?php
return [
'name' => '姓名',
'gender' => '性别',
];
other.php
使用:
__('message.name')
2.json 文件(必须是json格式)
不同语言包,只能是以 '不同语言' 命名的 json 文件
/path1/en.json
/path1/zh-cn.json
{
'name': '姓名',
'gender': '性别'
}
但是允许我们添加多个路径
/path2/en.json
/path2/zh-cn.json
使用:
__('name')
但多个路径,对于我们项目组织语言包目录结构,貌似没啥用...
2>一般使用 2 个函数:
__('messages.name') 或 trans('messages.name'),__() 是 trans() 别名
trans_choice('messages.minutes', 10) - 对于复数形式的处理
3>关于 key 参数:
当引入的 php 文件,必须使用 '文件名.键名',文档中提到的 '使用短键'
当引入的 json 文件,只使用 '键名',文档中提到的 '使用翻译字符串作为键'
4>重写扩展包的语言文件
laravel 的语言包,还支持使用 '命名空间',应该是 key 可以是
'namespace::message.name'
部分扩展包可能会附带自己的语言文件,我们可以在 resources/lang/vendor/{package}/{locale} 下放置语言包文件,来重写
5>总结,laravel 的语言包的 key,通过 '::' 和 '.' 进行解析,从而得到:
namespace::group.item
然后来进行字符串的替换
里面还有一些其他使用原则,例如:
json 文件的引用,我们可以添加过个 json 路径:
use Lang;
Lang::addJsonPath('path1');
Lang::addJsonPath('path2');
namespce 的引用,我们得先添加 namespace:
use Lang;
Lang::addNamespace('namespace1');
Lang::addNamespace('namespace2');
好了,简单的介绍到这,写的有点乱,有些东西不好描述。最好是分析下源码
接下来继续我们的主题,我们想按照 '控制器' 自动加载语言包(或者可以说是,任意加载不同的语言包文件):
改造:
vendor/laravel/framework/src/Illuminate/Translation/Translator.php
文件末尾,添加 addCustomFile() 方法:
/**
* 添加自定义文件
*/
public function addCustomFile($file)
{
$this->loader->addCustomFile($file);
}
vendor/laravel/framework/src/Illuminate/Translation/FileLoader.php
属性末尾,添加 $customFiles 属性
/**
* 所有的自定义文件
*/
protected $customFiles = [];
修改 load() 方法:
public function load($locale, $group, $namespace = null)
{
if ($group === '*' && $namespace === '*') {
// return $this->loadJsonPaths($locale);
/*
这里我们进行重构,额外支持加载自定义的语言包路径
*/
$jsonFileMessages = $this->loadJsonPaths($locale);
$customFileMessages = $this->loadCustomFiles($locale);
return array_merge($jsonFileMessages, $customFileMessages);
}
if (is_null($namespace) || $namespace === '*') {
return $this->loadPath($this->path, $locale, $group);
}
return $this->loadNamespaced($locale, $group, $namespace);
}
文件末尾,添加 loadCustomFiles(), addCustomFile() 方法:
/**
* 从给定的文件中加载语言包
*/
protected function loadCustomFiles($locale)
{
return collect($this->customFiles)
->reduce(function ($output, $file) use ($locale) {
if ($this->files->exists($file)) {
$messages = $this->files->getRequire($file);
$output = array_merge($output, $messages);
}
return $output;
}, []);
}
/**
* 添加自定义文件
*/
public function addCustomFile($file)
{
$this->customFiles[] = $file;
}
使用:
lang/zh-cn/admin/admin.php
<?php
return [
'name' => '姓名',
'avatar' => '头像',
];
/*
对于未改造前,我们想得到 name 的中文,laravel 其实是不支持的,laravel 默认只能是 zh-cn/ 的文件,不能再嵌套目录。
查看源码,其实有种手法也可以实现,key 带上文件目录层级:
__('admin/admin.name')
*/
改造后:
use Lang;
Lang::addCustomFile(resource_path('lang/zh-cn/admin/admin.php'));
__('name')
注意:
可添加任意的绝对文件路径,必须是 .php 文件,同时 return 一个数组