需求文档:UI文案国际化(i18n)
引言
《坦克探险》微信小游戏需要支持中英文双语UI。根据用户所在区域自动展示对应语言的文案,中文地区显示中文,其他地区显示英文。
技术方案
1. i18n 模块结构
在 js/i18n/ 目录下创建以下文件:
I18n.js — 核心管理器,负责语言检测和文案获取
zh.js — 中文语言包
en.js — 英文语言包
2. 语言检测
通过微信 wx.getSystemInfoSync().language 自动检测:
zh_CN、zh_TW、zh_HK 等以 zh 开头 → 使用中文
- 其他 → 使用英文(默认 fallback)
3. 使用方式
各场景文件通过 const { t } = require('../i18n/I18n'); 引入翻译函数:
- 简单文案:
t('menu.title') → '坦克探险' / 'Tank Adventure'
- 带参数模板:
t('pvp.hp', { count: 3 }) → '生命 x3' / 'HP x3'
4. Key 命名规范
按场景分组,使用点号分隔:
menu.* — 主菜单
room.* — 双人对战房间
teamRoom.* — 3v3团队房间
pvp.* — 双人对战游戏
team.* — 3v3团队游戏
pvpResult.* — 双人对战结算
teamResult.* — 3v3团队结算
game.* — 经典模式
common.* — 通用文案
需求
需求 1:创建 i18n 核心模块
用户故事: 作为开发者,我需要一个 i18n 模块来管理多语言文案,支持自动语言检测和带参数的文案模板。
验收标准
- 创建
js/i18n/I18n.js,提供 t(key, params) 函数
- 创建
js/i18n/zh.js,包含所有中文文案
- 创建
js/i18n/en.js,包含所有英文文案
- 通过
wx.getSystemInfoSync().language 自动检测语言
- 支持
{variable} 占位符插值
- 缺失 key 时 fallback 到英文,仍缺失则返回 key 本身
验收标准
| Key |
中文 |
英文 |
menu.title |
坦克探险 |
Tank Adventure |
menu.subtitle |
经典坦克对战 |
TANK WAR |
menu.classic |
经典模式 |
Classic |
menu.endless |
无尽模式 |
Endless |
menu.pvp |
双人对战 |
PVP |
menu.team3v3 |
3v3 对战 |
3v3 Battle |
menu.ranking |
排行榜 |
Ranking |
menu.settings |
设置 |
Settings |
需求 3:双人对战房间场景(RoomScene)i18n 化
验收标准
| Key |
中文 |
英文 |
room.title |
双人对战 |
PVP Battle |
room.idleHint |
创建房间或输入房间号加入 |
Create a room or join with a code |
room.create |
创建房间 |
Create Room |
room.join |
加入房间 |
Join Room |
room.connecting |
连接中{dots} |
Connecting{dots} |
room.roomCode |
房间号: |
Room Code: |
room.waiting |
等待对手加入{dots} |
Waiting for opponent{dots} |
room.shareHint |
将房间号分享给好友 |
Share the room code with your friend |
room.inputCode |
输入房间号: |
Enter Room Code: |
room.opponentFound |
对手已找到! |
Opponent found! |
room.starting |
即将开始... |
Game starting... |
room.tapBack |
点击任意位置返回 |
Tap anywhere to go back |
common.back |
← 返回 |
← Back |
common.joinBtn |
加入 |
Join |
common.cannotConnect |
无法连接服务器 |
Cannot connect to server |
common.connectFailed |
连接失败 |
Connection failed |
common.disconnected |
与服务器断开连接 |
Disconnected from server |
需求 4:3v3 团队房间场景(TeamRoomScene)i18n 化
验收标准
| Key |
中文 |
英文 |
teamRoom.title |
3v3 团队对战 |
3v3 Team Battle |
teamRoom.chooseMode |
选择游戏方式 |
Choose how to play |
teamRoom.createTeam |
🎮 组队开黑 |
🎮 Create Team |
teamRoom.soloMatch |
⚡ 快速匹配 |
⚡ Quick Match |
teamRoom.teamId |
队伍:{id} |
Team: {id} |
teamRoom.leader |
队长 |
Leader |
teamRoom.ready |
✓ 已准备 |
✓ Ready |
teamRoom.notReady |
未准备 |
Not Ready |
teamRoom.emptySlot |
空位 |
Empty |
teamRoom.invite |
📨 邀请好友 |
📨 Invite |
teamRoom.startMatch |
🔍 开始匹配 |
🔍 Start Match |
teamRoom.disband |
解散队伍 |
Disband |
teamRoom.readyBtn |
✓ 准备 |
✓ Ready |
teamRoom.cancelReady |
取消准备 |
Cancel Ready |
teamRoom.leaveTeam |
退出队伍 |
Leave Team |
teamRoom.matching |
匹配中{dots} |
Matching{dots} |
teamRoom.waitTime |
已等待 {seconds} 秒 |
Waited {seconds}s |
teamRoom.cancelMatch |
取消匹配 |
Cancel Match |
teamRoom.matchFound |
对手已找到! |
Match found! |
teamRoom.enterBattle |
即将进入战斗... |
Entering battle... |
teamRoom.tapBack |
点击任意位置返回 |
Tap anywhere to go back |
teamRoom.shareTitle |
坦克3v3,速来开黑! |
Tank 3v3, join the battle! |
common.kicked |
你已被踢出队伍 |
You have been kicked from the team |
需求 5:双人对战游戏场景(PvpGameScene)i18n 化
验收标准
| Key |
中文 |
英文 |
pvp.playerLabel |
P{slot} (我方) |
P{slot} (You) |
pvp.hp |
生命 x{count} |
HP x{count} |
pvp.kills |
击杀:{count} |
Kills: {count} |
common.paused |
暂停 |
PAUSED |
common.tapContinue |
点击继续 |
Tap to continue |
pvp.youWin |
你赢了! |
YOU WIN! |
pvp.draw |
平局 |
DRAW |
pvp.youLose |
你输了 |
YOU LOSE |
需求 6:3v3 团队对战游戏场景(TeamGameScene)i18n 化
验收标准
| Key |
中文 |
英文 |
team.teamA |
A队 |
Team A |
team.teamB |
B队 |
Team B |
team.myTeam |
我方:{team}队 |
You: {team} Team |
team.killDeath |
杀:{kills} 亡:{deaths} |
K:{kills} D:{deaths} |
team.respawn |
{seconds}秒后重生 |
Respawning in {seconds}s |
team.victory |
胜利! |
VICTORY! |
team.defeat |
失败 |
DEFEAT |
team.baseHpSummary |
A队:{hpA} 生命 | B队:{hpB} 生命 |
Team A: {hpA} HP | Team B: {hpB} HP |
team.disconnectTitle |
⚠ 连接断开 |
⚠ Connection Lost |
team.reconnecting |
重连中{dots} ({attempts}/{max}) |
Reconnecting{dots} ({attempts}/{max}) |
team.reconnectHint |
请稍候,您的坦克将由AI代管 |
Please wait, your tank will be controlled by AI |
需求 7:双人对战结算场景(PvpResultScene)i18n 化
验收标准
| Key |
中文 |
英文 |
pvpResult.title |
对战结果 |
MATCH RESULT |
pvpResult.victory |
🏆 胜利! |
🏆 VICTORY! |
pvpResult.draw |
⚔️ 平局 |
⚔️ DRAW |
pvpResult.defeat |
💀 失败 |
💀 DEFEAT |
pvpResult.kills |
击杀 |
Kills |
pvpResult.lives |
生命 |
Lives |
pvpResult.timeRemaining |
剩余时间:{time} |
Time remaining: {time} |
pvpResult.rematch |
再来一局 |
Rematch |
pvpResult.backMenu |
返回菜单 |
Back to Menu |
需求 8:3v3 团队结算场景(TeamResultScene)i18n 化
验收标准
| Key |
中文 |
英文 |
teamResult.title |
3v3 对战结果 |
3v3 MATCH RESULT |
teamResult.victory |
🏆 胜利! |
🏆 VICTORY! |
teamResult.defeat |
💀 失败 |
💀 DEFEAT |
teamResult.teamAHp |
A队:{hp} 生命 |
Team A: {hp} HP |
teamResult.teamBHp |
B队:{hp} 生命 |
Team B: {hp} HP |
teamResult.baseDestroyed |
基地被摧毁 |
Base Destroyed |
teamResult.disconnectedReason |
断线 |
Disconnected |
teamResult.teamAHeader |
A队 |
Team A |
teamResult.teamBHeader |
B队 |
Team B |
teamResult.myTeamSuffix |
(我方) |
(You) |
teamResult.player |
玩家 |
Player |
teamResult.k |
杀 |
K |
teamResult.d |
亡 |
D |
teamResult.a |
助 |
A |
teamResult.dmg |
伤害 |
DMG |
teamResult.bot |
🤖 机器人 |
🤖 Bot |
teamResult.duration |
对战时长:{time} |
Match duration: {time} |
teamResult.mvp |
⭐ MVP:{name}({kills} 击杀) |
⭐ MVP: {name} ({kills} kills) |
teamResult.rankUp |
📈 积分 +{points} |
📈 Rank +{points} |
teamResult.mvpBonus |
(MVP加成 +5) |
(MVP bonus +5) |
teamResult.rankDown |
📉 积分 -{points} |
📉 Rank -{points} |
teamResult.rematch |
再来一局 |
Rematch |
teamResult.backMenu |
返回菜单 |
Back to Menu |
需求 9:经典模式游戏场景(GameScene)i18n 化
验收标准
| Key |
中文 |
英文 |
game.level |
第 {level} 关 |
Level {level} |
game.hp |
生命 x{count} |
HP x{count} |
game.fireLevel |
LV{level} |
LV{level} |
game.enemies |
敌人: {count} |
Enemies: {count} |
game.score |
{score}分 |
{score}pts |
game.gameOver |
游戏结束 |
GAME OVER |
game.stageClear |
关卡通过! |
STAGE CLEAR! |
边界情况与技术约束
边界情况
- 中文字体渲染:Canvas 中使用
'Arial' 字体渲染中文时,微信小游戏环境下系统会自动 fallback 到系统中文字体,无需额外处理。
- 文案长度变化:中英文文案长度不同,替换后需确认UI布局不会溢出或错位。
GameScene 中的字符串比较:text === '游戏结束' 改为 text === t('game.gameOver'),确保逻辑不受语言影响。
- 错误消息来源:部分错误消息可能来自服务端(如
data.message),本次仅替换客户端硬编码的文案。
技术约束
- 所有文案替换涉及
js/scenes/ 目录下的场景文件和新建的 js/i18n/ 模块。
- 替换操作不应影响游戏逻辑,仅修改展示层的字符串。
- 不需要在设置页面增加语言切换选项,完全依赖微信系统语言自动检测。
成功标准
- 中文区域用户看到全中文UI,非中文区域用户看到全英文UI。
- 替换后游戏功能正常,无因文案修改导致的逻辑错误。
- 文案在各场景中布局合理,无溢出或错位现象。