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 一個數組