Lang.php 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265
  1. <?php
  2. // +----------------------------------------------------------------------
  3. // | ThinkPHP [ WE CAN DO IT JUST THINK ]
  4. // +----------------------------------------------------------------------
  5. // | Copyright (c) 2006~2018 http://thinkphp.cn All rights reserved.
  6. // +----------------------------------------------------------------------
  7. // | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
  8. // +----------------------------------------------------------------------
  9. // | Author: liu21st <liu21st@gmail.com>
  10. // +----------------------------------------------------------------------
  11. namespace think;
  12. class Lang
  13. {
  14. /**
  15. * 多语言信息
  16. * @var array
  17. */
  18. private $lang = [];
  19. /**
  20. * 当前语言
  21. * @var string
  22. */
  23. private $range = 'zh-cn';
  24. /**
  25. * 多语言自动侦测变量名
  26. * @var string
  27. */
  28. protected $langDetectVar = 'lang';
  29. /**
  30. * 多语言cookie变量
  31. * @var string
  32. */
  33. protected $langCookieVar = 'think_var';
  34. /**
  35. * 允许的多语言列表
  36. * @var array
  37. */
  38. protected $allowLangList = [];
  39. /**
  40. * Accept-Language转义为对应语言包名称 系统默认配置
  41. * @var string
  42. */
  43. protected $acceptLanguage = [
  44. 'zh-hans-cn' => 'zh-cn',
  45. ];
  46. // 设定当前的语言
  47. public function range($range = '')
  48. {
  49. if ('' == $range) {
  50. return $this->range;
  51. } else {
  52. $this->range = $range;
  53. }
  54. }
  55. /**
  56. * 设置语言定义(不区分大小写)
  57. * @access public
  58. * @param string|array $name 语言变量
  59. * @param string $value 语言值
  60. * @param string $range 语言作用域
  61. * @return mixed
  62. */
  63. public function set($name, $value = null, $range = '')
  64. {
  65. $range = $range ?: $this->range;
  66. // 批量定义
  67. if (!isset($this->lang[$range])) {
  68. $this->lang[$range] = [];
  69. }
  70. if (is_array($name)) {
  71. return $this->lang[$range] = array_change_key_case($name) + $this->lang[$range];
  72. } else {
  73. return $this->lang[$range][strtolower($name)] = $value;
  74. }
  75. }
  76. /**
  77. * 加载语言定义(不区分大小写)
  78. * @access public
  79. * @param string|array $file 语言文件
  80. * @param string $range 语言作用域
  81. * @return array
  82. */
  83. public function load($file, $range = '')
  84. {
  85. $range = $range ?: $this->range;
  86. if (!isset($this->lang[$range])) {
  87. $this->lang[$range] = [];
  88. }
  89. // 批量定义
  90. if (is_string($file)) {
  91. $file = [$file];
  92. }
  93. $lang = [];
  94. foreach ($file as $_file) {
  95. if (is_file($_file)) {
  96. // 记录加载信息
  97. Container::get('app')->log('[ LANG ] ' . $_file);
  98. $_lang = include $_file;
  99. if (is_array($_lang)) {
  100. $lang = array_change_key_case($_lang) + $lang;
  101. }
  102. }
  103. }
  104. if (!empty($lang)) {
  105. $this->lang[$range] = $lang + $this->lang[$range];
  106. }
  107. return $this->lang[$range];
  108. }
  109. /**
  110. * 获取语言定义(不区分大小写)
  111. * @access public
  112. * @param string|null $name 语言变量
  113. * @param string $range 语言作用域
  114. * @return bool
  115. */
  116. public function has($name, $range = '')
  117. {
  118. $range = $range ?: $this->range;
  119. return isset($this->lang[$range][strtolower($name)]);
  120. }
  121. /**
  122. * 获取语言定义(不区分大小写)
  123. * @access public
  124. * @param string|null $name 语言变量
  125. * @param array $vars 变量替换
  126. * @param string $range 语言作用域
  127. * @return mixed
  128. */
  129. public function get($name = null, $vars = [], $range = '')
  130. {
  131. $range = $range ?: $this->range;
  132. // 空参数返回所有定义
  133. if (empty($name)) {
  134. return $this->lang[$range];
  135. }
  136. $key = strtolower($name);
  137. $value = isset($this->lang[$range][$key]) ? $this->lang[$range][$key] : $name;
  138. // 变量解析
  139. if (!empty($vars) && is_array($vars)) {
  140. /**
  141. * Notes:
  142. * 为了检测的方便,数字索引的判断仅仅是参数数组的第一个元素的key为数字0
  143. * 数字索引采用的是系统的 sprintf 函数替换,用法请参考 sprintf 函数
  144. */
  145. if (key($vars) === 0) {
  146. // 数字索引解析
  147. array_unshift($vars, $value);
  148. $value = call_user_func_array('sprintf', $vars);
  149. } else {
  150. // 关联索引解析
  151. $replace = array_keys($vars);
  152. foreach ($replace as &$v) {
  153. $v = "{:{$v}}";
  154. }
  155. $value = str_replace($replace, $vars, $value);
  156. }
  157. }
  158. return $value;
  159. }
  160. /**
  161. * 自动侦测设置获取语言选择
  162. * @access public
  163. * @return string
  164. */
  165. public function detect()
  166. {
  167. // 自动侦测设置获取语言选择
  168. $langSet = '';
  169. if (isset($_GET[$this->langDetectVar])) {
  170. // url中设置了语言变量
  171. $langSet = strtolower($_GET[$this->langDetectVar]);
  172. } elseif (isset($_COOKIE[$this->langCookieVar])) {
  173. // Cookie中设置了语言变量
  174. $langSet = strtolower($_COOKIE[$this->langCookieVar]);
  175. } elseif (isset($_SERVER['HTTP_ACCEPT_LANGUAGE'])) {
  176. // 自动侦测浏览器语言
  177. preg_match('/^([a-z\d\-]+)/i', $_SERVER['HTTP_ACCEPT_LANGUAGE'], $matches);
  178. $langSet = strtolower($matches[1]);
  179. $acceptLangs = Container::get('config')->get('header_accept_lang');
  180. if (isset($acceptLangs[$langSet])) {
  181. $langSet = $acceptLangs[$langSet];
  182. } elseif (isset($this->acceptLanguage[$langSet])) {
  183. $langSet = $this->acceptLanguage[$langSet];
  184. }
  185. }
  186. if (empty($this->allowLangList) || in_array($langSet, $this->allowLangList)) {
  187. // 合法的语言
  188. $this->range = $langSet ?: $this->range;
  189. }
  190. return $this->range;
  191. }
  192. /**
  193. * 设置当前语言到Cookie
  194. * @access public
  195. * @param string $lang 语言
  196. * @return void
  197. */
  198. public function saveToCookie($lang = null)
  199. {
  200. $range = $lang ?: $this->range;
  201. $_COOKIE[$this->langCookieVar] = $range;
  202. }
  203. /**
  204. * 设置语言自动侦测的变量
  205. * @access public
  206. * @param string $var 变量名称
  207. * @return void
  208. */
  209. public function setLangDetectVar($var)
  210. {
  211. $this->langDetectVar = $var;
  212. }
  213. /**
  214. * 设置语言的cookie保存变量
  215. * @access public
  216. * @param string $var 变量名称
  217. * @return void
  218. */
  219. public function setLangCookieVar($var)
  220. {
  221. $this->langCookieVar = $var;
  222. }
  223. /**
  224. * 设置允许的语言列表
  225. * @access public
  226. * @param array $list 语言列表
  227. * @return void
  228. */
  229. public function setAllowLangList($list)
  230. {
  231. $this->allowLangList = $list;
  232. }
  233. }