Lang.php 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290
  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. * 应用对象
  48. * @var App
  49. */
  50. protected $app;
  51. public function __construct(App $app)
  52. {
  53. $this->app = $app;
  54. }
  55. // 设定当前的语言
  56. public function range($range = '')
  57. {
  58. if ('' == $range) {
  59. return $this->range;
  60. } else {
  61. $this->range = $range;
  62. }
  63. }
  64. /**
  65. * 设置语言定义(不区分大小写)
  66. * @access public
  67. * @param string|array $name 语言变量
  68. * @param string $value 语言值
  69. * @param string $range 语言作用域
  70. * @return mixed
  71. */
  72. public function set($name, $value = null, $range = '')
  73. {
  74. $range = $range ?: $this->range;
  75. // 批量定义
  76. if (!isset($this->lang[$range])) {
  77. $this->lang[$range] = [];
  78. }
  79. if (is_array($name)) {
  80. return $this->lang[$range] = array_change_key_case($name) + $this->lang[$range];
  81. }
  82. return $this->lang[$range][strtolower($name)] = $value;
  83. }
  84. /**
  85. * 加载语言定义(不区分大小写)
  86. * @access public
  87. * @param string|array $file 语言文件
  88. * @param string $range 语言作用域
  89. * @return array
  90. */
  91. public function load($file, $range = '')
  92. {
  93. $range = $range ?: $this->range;
  94. if (!isset($this->lang[$range])) {
  95. $this->lang[$range] = [];
  96. }
  97. // 批量定义
  98. if (is_string($file)) {
  99. $file = [$file];
  100. }
  101. $lang = [];
  102. foreach ($file as $_file) {
  103. if (is_file($_file)) {
  104. // 记录加载信息
  105. $this->app->log('[ LANG ] ' . $_file);
  106. $_lang = include $_file;
  107. if (is_array($_lang)) {
  108. $lang = array_change_key_case($_lang) + $lang;
  109. }
  110. }
  111. }
  112. if (!empty($lang)) {
  113. $this->lang[$range] = $lang + $this->lang[$range];
  114. }
  115. return $this->lang[$range];
  116. }
  117. /**
  118. * 获取语言定义(不区分大小写)
  119. * @access public
  120. * @param string|null $name 语言变量
  121. * @param string $range 语言作用域
  122. * @return bool
  123. */
  124. public function has($name, $range = '')
  125. {
  126. $range = $range ?: $this->range;
  127. return isset($this->lang[$range][strtolower($name)]);
  128. }
  129. /**
  130. * 获取语言定义(不区分大小写)
  131. * @access public
  132. * @param string|null $name 语言变量
  133. * @param array $vars 变量替换
  134. * @param string $range 语言作用域
  135. * @return mixed
  136. */
  137. public function get($name = null, $vars = [], $range = '')
  138. {
  139. $range = $range ?: $this->range;
  140. // 空参数返回所有定义
  141. if (is_null($name)) {
  142. return $this->lang[$range];
  143. }
  144. $key = strtolower($name);
  145. $value = isset($this->lang[$range][$key]) ? $this->lang[$range][$key] : $name;
  146. // 变量解析
  147. if (!empty($vars) && is_array($vars)) {
  148. /**
  149. * Notes:
  150. * 为了检测的方便,数字索引的判断仅仅是参数数组的第一个元素的key为数字0
  151. * 数字索引采用的是系统的 sprintf 函数替换,用法请参考 sprintf 函数
  152. */
  153. if (key($vars) === 0) {
  154. // 数字索引解析
  155. array_unshift($vars, $value);
  156. $value = call_user_func_array('sprintf', $vars);
  157. } else {
  158. // 关联索引解析
  159. $replace = array_keys($vars);
  160. foreach ($replace as &$v) {
  161. $v = "{:{$v}}";
  162. }
  163. $value = str_replace($replace, $vars, $value);
  164. }
  165. }
  166. return $value;
  167. }
  168. /**
  169. * 自动侦测设置获取语言选择
  170. * @access public
  171. * @return string
  172. */
  173. public function detect()
  174. {
  175. // 自动侦测设置获取语言选择
  176. $langSet = '';
  177. if (isset($_GET[$this->langDetectVar])) {
  178. // url中设置了语言变量
  179. $langSet = strtolower($_GET[$this->langDetectVar]);
  180. } elseif (isset($_COOKIE[$this->langCookieVar])) {
  181. // Cookie中设置了语言变量
  182. $langSet = strtolower($_COOKIE[$this->langCookieVar]);
  183. } elseif (isset($_SERVER['HTTP_ACCEPT_LANGUAGE'])) {
  184. // 自动侦测浏览器语言
  185. preg_match('/^([a-z\d\-]+)/i', $_SERVER['HTTP_ACCEPT_LANGUAGE'], $matches);
  186. $langSet = strtolower($matches[1]);
  187. if (isset($this->acceptLanguage[$langSet])) {
  188. $langSet = $this->acceptLanguage[$langSet];
  189. }
  190. }
  191. if (preg_match('/^([a-z\d\-]+)/i', $langSet, $matches)) {
  192. $langSet = strtolower($matches[1]);
  193. } else {
  194. $langSet = $this->range;
  195. }
  196. if (empty($this->allowLangList) || in_array($langSet, $this->allowLangList)) {
  197. // 合法的语言
  198. $this->range = $langSet ?: $this->range;
  199. }
  200. return $this->range;
  201. }
  202. /**
  203. * 设置当前语言到Cookie
  204. * @access public
  205. * @param string $lang 语言
  206. * @return void
  207. */
  208. public function saveToCookie($lang = null)
  209. {
  210. $range = $lang ?: $this->range;
  211. $_COOKIE[$this->langCookieVar] = $range;
  212. }
  213. /**
  214. * 设置语言自动侦测的变量
  215. * @access public
  216. * @param string $var 变量名称
  217. * @return void
  218. */
  219. public function setLangDetectVar($var)
  220. {
  221. $this->langDetectVar = $var;
  222. }
  223. /**
  224. * 设置语言的cookie保存变量
  225. * @access public
  226. * @param string $var 变量名称
  227. * @return void
  228. */
  229. public function setLangCookieVar($var)
  230. {
  231. $this->langCookieVar = $var;
  232. }
  233. /**
  234. * 设置允许的语言列表
  235. * @access public
  236. * @param array $list 语言列表
  237. * @return void
  238. */
  239. public function setAllowLangList(array $list)
  240. {
  241. $this->allowLangList = $list;
  242. }
  243. /**
  244. * 设置转义的语言列表
  245. * @access public
  246. * @param array $list 语言列表
  247. * @return void
  248. */
  249. public function setAcceptLanguage(array $list)
  250. {
  251. $this->acceptLanguage = array_merge($this->acceptLanguage, $list);
  252. }
  253. }