You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

294 lines
9.7 KiB

<?php
if (!defined('__TYPECHO_ROOT_DIR__')) exit;
/**
* I18n.php
* Author : hewro
* Date : 2017/04/23
* Version :
* Description:
*/
class I18n{
private static $instance;//一个实例
private $locale;//语言格式
private $loadedLangs;//加载语言
private $dateFormat;//时间格式
private $isSettingsPage = false;
private $loaded = false; //
private $loadSucceed = false;
private function loadLangIfNotLoad() {//loaded == false时候执行该语句
if (!$this->loaded) {
if (empty($this->locale)) {
$this->locale = $this->acceptLocale();
}
$this->loadedLangs = array();
$this->loadLang($this->locale);
$this->loaded = true;
}
}
private function setLocale($locale){
$this->locale = $locale;
}
private function setIsSettingPages($is){
$this->isSettingPage = $is;
}
private function acceptLocale(){//获取本地配置
$accepts = mb_split(',', @$_SERVER['HTTP_ACCEPT_LANGUAGE']);//判断浏览器语言
$acceptLocales = array();//本地配置数组
foreach ($accepts as $lang) {
$q = "1.0";
if(preg_match('/^([a-zA-Z0-9\-\_]+);q=([0-9\.]+)$/i', $lang, $matched)) {
$q = $matched[2];
$acceptLocales[$q] = $matched[1];
} elseif (preg_match('/^([a-zA-Z0-9\-\_]+)$/i', $lang, $matched)) {
$acceptLocales[$q] = $lang;
} else {
continue;
}
$locale = str_replace('-','_',$acceptLocales[$q]);//转换字符串,变成标准的Locale Code,如 zh_CN
$parts = mb_split('_',$locale, 2);
if(count($parts) == 2){
$locale = strtolower($parts[0]) . '_' . strtoupper($parts[1]);
}
$acceptLocales[$q] = $locale;
}//foreach结束
if(count($acceptLocales) > 1){
$keys = array_keys($acceptLocales);//返回本地配置的数组的键名称
rsort($keys, SORT_NUMERIC); #降序排序
$langs = I18n_Options::listLocaleFiles();//检查本地配置文件
foreach ($keys as $key) {
$locale = $acceptLocales[$key];
if(in_array($locale, $langs)){//检查数组中是否存在某个值
$resultLocale = $locale;
break;
}else {
$parts = mb_split('_', $locale, 2);
if(in_array($parts[0], $langs)){
$resultLocale = $parts[0];
break;
}
}
}
}else {
$resultLocale = array_shift($acceptLocales);
}
if (empty($resultLocale)) {
$resultLocale = "en";
}
return $resultLocale;
}
private function loadLang($locale){
if ($this->isSettingsPage) {
$this->doLoadLang($locale, "lang/settings");
}else {
$this->doLoadLang($locale, "lang");
$this->doLoadLang($locale, "usr/lang");
}
}
private function doLoadLang($locale, $path) {
$file = dirname(__DIR__) . "/{$path}/{$locale}.php";
if (file_exists($file)) {
$className = str_replace('/', '_', $path) . '_' . $locale;
if (!class_exists($className)) {
require_once($file);
}
if (class_exists($className)) {
$lang = new $className();
} else {
$lang = null;
}
if (is_subclass_of($lang, "Lang")) {
if (method_exists($lang, "translated")) {
$translated = $lang->translated();
if (is_array($translated)) {
$this->loadedLangs = array_merge($this->loadedLangs, $translated);
$this->loadSucceed = true;
}
}
if (method_exists($lang, "dateFormat")) {
$format = $lang->dateFormat();
if (empty($format) && empty($this->dateFormat)) {
$format = mget()->postDateFormat;
}
$this->dateFormat = $format;
}
}
}
}
private function doTranslate($string){
$this->loadLangIfNotLoad();
if (@array_key_exists($string, $this->loadedLangs)) {
$translated = $this->loadedLangs[$string];
}else {
$translated = _t($string);
}
return $translated;
}
private static function Instance(){//新建一个I18n的实例
if (self::$instance == null) {
self::$instance = new self();
}
return self::$instance;
}
/*begain*/
public static function setLang($locale){
$instance = self::Instance();
$instance->setLocale($locale);
}
public static function loadAsSettingsPage($is){
$instance = self::Instance();
$instance->setIsSettingPages($is);
}
public static function translate($string){
$instance = self::Instance();
return $instance->doTranslate($string);
}
public static function dateFormat(){
$instance = self::Instance();
return $instance->dateFormat;
}
}
//国际化语言后台配置类
class I18n_Options{
private static function doListLocalFiles($path){
$dir = dirname(__DIR__) . "/{$path}";
if(!file_exists($dir)){
return array();
}
$it = new RecursiveIteratorIterator(
new RecursiveDirectoryIterator($dir, FilesystemIterator::SKIP_DOTS),
RecursiveIteratorIterator::SELF_FIRST
);
$it->setMaxDepth(1);//递归获取目录下面的文件名称
$langs = array();
foreach ($it as $fileInfo) {
if ($fileInfo->isFile()) {
$filename = $fileInfo->getFilename();
$filename = str_replace('.php', '', $filename);
$langs[] = $filename;
}
}
return $langs;
}
private static function doListLangs($path){//获取具体路径下的语言文件,并返回语言种类
$dir = dirname(__DIR__) . "/{$path}";
if(!file_exists($dir)){
return array();
}
$it = new RecursiveIteratorIterator(
new RecursiveDirectoryIterator($dir, FilesystemIterator::SKIP_DOTS),
RecursiveIteratorIterator::SELF_FIRST
);
$it->setMaxDepth(1);//递归获取目录下面的文件名称
$langs = array();
foreach ($it as $fileInfo) {
if($fileInfo->isFile()){
$file = $fileInfo -> getPathname();
$filename = $fileInfo->getFilename();
//echo $file ;
$filename = str_replace('.php', '', $filename);
if(is_readable($file)){
//echo " is readable";
$className = str_replace('/', '_', $path) . '_' . $filename;
//echo " " . $className . '<br />';
if (!class_exists($className)) {//如果找不到该类名称,则将该类对应的class文件引进
//echo "yes ";
require_once($file);
}
if(class_exists($className)){
$lang = new $className();
//echo "require OK !";
}else {
$lang = null;
//echo "reqire failed!";
}
if(is_subclass_of($lang, "Lang")){
if(method_exists($lang, "locale")){
$locale = $lang->locale();
if(!empty($locale) && method_exists($lang, "name")){
$name = $lang->name();
if(!empty($name)){
$langs[$locale] = $name;
}
}
}
}
}
}
}
return $langs;
}
public static function listLangs(){//返回后台配置中显示的可使用的语言种类列表
$lang = array('auto' => 'Auto');
$langs = array_merge($lang, self::doListLangs("lang"), self::doListLangs("usr/lang"));
return $langs;
}
public static function listLocaleFiles($isSettingsPage = false){
$lang = array();
if ($isSettingsPage) {//合并需要导入的文件的数组
$langs = array_merge($lang, self::doListLocalFiles("lang/settings"));
}else {
$langs = array_merge($lang,self::doListLocalFiles("lang"),self::doListLocalFiles("usr/lang"));
}
return array_unique($langs);//移除数组中重复的值
}
}
function _mt($string){
if (func_num_args() <= 1) {//只有一个参数
return I18n::translate($string);
//echo "次浏览";
}else {
$args = func_get_args();//返回一个包含函数参数列表的数组
array_shift($args);//将数组开头的单元移出数组
return vsprintf(I18n::translate($string), $args);
}
//func_get_arg() 和 func_num_args() 一起使用,使得用户自定义函数可以接受自定义个数的参数列表。
}
function _me(){
$args = func_get_args();
echo call_user_func_array('_mt', $args);
//将$args数组的值作为_mt函数的参数值回调_mt函数
//echo "次浏览";
}
function _mn($single, $plural, $number){
return $number > 1 ? I18n::translate($plural) : I18n::translate($single);
}