4.3 模板多语言与 i18n 语言包
把界面文案从模板里抽出来,一套模板跑中英两种界面。
4.3.1 先分清两套语言包
X5.0 里有两套语言包,作用范围完全不同,混了就会串词。
系统语言包在 source/language/ 下,给 Discuz 自身界面用,模板里用 {lang key} 调用。这套是框架级的,你一般不碰。
模板语言包在 /template/i18n/SC_UTF8/lang_template.php,专门服务于模板作者写的文案,机制和插件语言包一致:定义一个 $lang 数组,键是英文,值是显示文字。SC_UTF8 是简体 UTF-8 的目录代号,站内语言就是它。
4.3.2 建模板语言包
新建 /template/i18n/SC_UTF8/lang_template.php:
<?php
$lang = [
'nice' => '不错!',
'login_tip' => '登录后查看更多内容',
'readmore' => '阅读全文',
];
老式的 array() 写法同样有效:
<?php
$lang = array(
'nice' => '不错!',
'login_tip' => '登录后查看更多内容',
'readmore' => '阅读全文',
);
想让别的代码直接引用这个文件时稳妥些,加个守卫。IN_DISCUZ 是 class_core.php 在正常加载流程里定义的系统常量,文件被浏览器直接访问时它不存在,守卫会挡住:
<?php
if (!defined('IN_DISCUZ')) {
exit('Access Denied');
}
$lang = [
'nice' => '不错!',
'readmore' => '阅读全文',
];
4.3.3 模板里怎么调用
用 {lang key} 调用,key 就是 $lang 的键:
<!-- template/你的标识/forum/viewthread.htm -->
<div class="post-actions">
<a href="javascript:;" class="act-like">{lang nice}</a>
<a href="$readmoreurl" class="act-more">{lang readmore}</a>
</div>
键名建议统一加前缀,避免和系统语言包撞名。撞名的后果是 {lang xxx} 拿到了别的词条,页面显示莫名其妙的中文或英文。模板叫 news,键名就全写成 news_nice、news_login_tip。
自定义描述文字也能走语言包,语言包里对应位置用 %s 占位,模板里写 {lang news_topic_count}。占位符的具体写法以你版本的语言包约定为准:
<?php
$lang = [
'news_topic_count' => '今日主题数:%s',
];
4.3.4 哪些文本能写进语言包
不止模板正文,导出的 XML 里有一批字段同样支持写进 $lang:
| 字段 | 含义 | 多语言价值 |
|---|---|---|
name |
模板名称 | 后台模板列表里显示 |
tplname |
模板标识名 | 部分界面展示 |
copyright |
版权信息 | 前台页脚、后台详情页 |
version |
版本号 | 一般不用翻译 |
var.title |
变量的标题 | 站长在后台看到的输入框名称 |
var.description |
变量的说明文字 | 后台提示文本 |
var.extra |
变量的附加配置 | 视内容而定 |
var.title 和 var.description 能翻译是 X5.0 很实用的改进:面向海外站长的模板包,后台设置页也是英文的,站长不用截图问你每个框是干嘛的。语言包按层级对应即可:
<?php
$lang = [
'templatename' => '资讯模板',
'templatecopyright' => '你的团队',
'news_sitetitle' => '站点副标题',
'news_sitetitle_desc' => '显示在浏览器标题和页头横幅右侧',
];
4.3.5 i18n 多语言扩展
SC_UTF8 是默认简体语言。想支持英文,X5.0 提供的兼容扩展路径是在 i18n/ 下按语言代码建子目录,一个语言一个目录,各放一个 lang_template.php,键名与 SC_UTF8 下完全一致,值换成对应语言:
<?php
// /template/xxx/i18n/en/lang_template.php
$lang = [
'nice' => 'Nice!',
'readmore' => 'Read more',
];
系统的 i18n() 函数用来设置自定义语言包目录,把 mylang 指向站点下的 en 目录即可。站点切语言靠用户组语言设置加浏览器语言协商,这部分由系统处理,模板侧只需保证每个语言目录里键名齐全——漏一个键,那个词就会退回默认语言显示。日文等语言同理,建 /template/xxx/i18n/jp/ 放同名文件即可。
4.3.6 模板 JS 语言包
模板里的 JS 也要出文案,别把中文直接写进 .js。思路和插件的 JS 语言包一致:JS 里留占位符,启动时从语言包取值替换。PHP 侧把文案输出成 JSON:
<?php
$langjs = isset($lang) ? $lang : array();
?>
<script>
window.DISCUZLANG = <?php echo json_encode($langjs, JSON_UNESCAPED_UNICODE); ?>;
</script>
JS 侧这样用,好处是语言包换了语言文案跟着变,不用动 .js 文件本身。注意输出 JSON 时用 JSON_UNESCAPED_UNICODE,否则中文会被转成 \uXXXX,虽然能正常解析,但排查时很难看:
function t(key, fallback) {
var dict = window.DISCUZLANG || {};
return dict[key] || fallback || key;
}
document.getElementById('submit-btn').textContent = t('news_submit', '提交');
4.3.7 一份模板支持中英两种界面
| 序号 | 做什么 | 完成标志 |
|---|---|---|
| 1 | 建 /template/i18n/SC_UTF8/lang_template.php |
键名齐全,中文 |
| 2 | 扫模板,把硬编码文案换成 {lang key} |
模板里搜不到中文字符串 |
| 3 | 给键名加模板前缀 | 无键名与系统语言包冲突 |
| 4 | 建 /template/xxx/i18n/en/lang_template.php |
键名与 SC_UTF8 完全一致 |
| 5 | 处理 XML 字段 | 模板名、变量标题都有译文 |
| 6 | 输出 JS 语言包 | DISCUZLANG 可用 |
| 7 | JS 侧改成取值 | .js 里无硬编码文案 |
| 8 | 更新缓存测试 | 中英文各切一次 |
| 9 | 核对漏键 | 无退回默认语言的词 |
第 2 步最费劲。经验做法:先用编辑器的全项目搜索把 .htm 里的中文全找出来,逐条判断是文案还是内容。用户发的帖子、公告正文是内容,不该进语言包,只有界面固定文案才进。判断标准很简单——这个中文在英文站上也应该存在吗?不应该,它就是语言包条目。
第 4 步要特别小心:复制完英文包又新增了中文条目,忘了同步英文。漏键是运行时才暴露的,静态检查查不出来,建议写个十行的键名校验脚本比人工比对快得多。
到这里模板就具备了打包给海外用户的能力。但站长拿到包后第二个需求通常不是改文案,而是「把这块区域挪一挪」——这要靠 DIY,而 DIY 想让用户有东西可拖,模板就得提供页面组件和模块组件。
