国际化与长文本适配
国际化与长文本适配 · 阅读后完成下方实验与检查题,再用「标记完成」记录进度。
学习目标
读完你能把界面文案与逻辑分离成消息表,用 Intl 处理日期、数字与百分比的本地化,并让界面在长文本(德语长单词、长标题)和窄屏下不破版;核心是清除代码里「写死」的假设:语序、格式、文字长度、屏幕宽度。
问题场景
课程卡片写死了「共 12 课时 · 更新于 2026/10/26」:换成英语界面,拼出来的句子语法别扭;日期格式硬编码,不同地区用户看着别扭;德语 Veranstaltungskalender 这样的长单词直接把按钮撑破;手机上标题、时长、按钮挤成三行。每个问题背后都是一个被写死的假设。
核心解释
**第一步:文案与逻辑分离。**所有界面文字进消息表;句子里需要嵌值的地方用占位符,由格式化函数填入。不要用字符串拼接造句子——不同语言的语序不同:
const messages = {
"zh-CN": { courseMeta: "共 {count} 课时 · 更新于 {date}", enroll: "立即报名" },
"en-US": { courseMeta: "{count} lessons · updated {date}", enroll: "Enroll" },
};
function t(locale, key, vars) {
return messages[locale][key].replace(/\{(\w+)\}/g, (_, k) => vars[k]);
}
**第二步:日期数字交给 Intl。**时区、补零、分隔符的坑它都踩平了,不要重复发明:
new Intl.DateTimeFormat("de-DE", { dateStyle: "medium" }).format(new Date());
// "26.10.2026" —— 顺序、分隔符全部自动正确
new Intl.NumberFormat("de-DE", { style: "percent" }).format(0.86); // "86 %"
**第三步:布局为文字长度留弹性。**CSS 三件套:overflow-wrap: anywhere 让超长单词可断行;flex 子项加 min-width: 0 防止内容撑爆弹性布局;次要信息用 text-overflow: ellipsis 截断并保留 title 提示。验证方式:实验区切换四种语言(含德语长词、阿拉伯语方向)与窄屏模式,逐个组合检查:卡片不破版、日期数字随语言变化、句子语法正确、方向翻转正常。
示例拆解
实验区课程卡片组:
- 语言切换:zh-CN / en-US / de-DE / ar-EG;ar-EG 同时把容器切到 dir=rtl,观察方向翻转;
- 卡片上的课时数、更新日期、完成百分比分别经 t() 与 Intl 输出,同一段代码四种语言四种长相;
- 德语界面配一个故意超长的课程标题,观察按词断行而不是溢出;
- 「窄屏(320px)」开关模拟手机宽度:信息折行、按钮可换行不破版;
- 验证:逐个「语言 × 屏宽」组合走查,记录任何一处破版。
动手任务
打开本课实验区:
- 新增 ja-JP 消息表与日期格式,并调整占位符顺序(把 {date} 放最前),验证填充仍然正确。
- 给报名按钮加最小宽度与可断行,验证德语长文案下按钮不破。
- 把「更新于」改成 Intl.RelativeTimeFormat 的相对时间(「3 天前」/ "3 days ago")。
常见错误
- 字符串拼接造句子:
"共 " + n + " 课时"在英语里语序全错;占位符交给翻译自由重排。 - 手写日期数字格式:时区、补零、千分位的坑 Intl 都已踩平;手写必错。
- 假设文字长度:按钮按中文两字设计,德语一上来就溢出;布局从第一天就按「会很长」设计。
- 忘记 RTL:只测了从左到右的语言,阿拉伯语界面图标、间距方向全反;至少开一次 dir="rtl" 走查。
检查与复盘
自查清单:
- 界面文字全部走消息表,代码里搜不到硬编码的界面文案
- 日期、数字、百分比全部经 Intl 输出
- 四语言 × 窄屏走查过,无破版无溢出,RTL 至少检查过一次
参考资料
- MDN:Intl 对象 —— 国际化 API 总览
- MDN:Intl.DateTimeFormat —— 日期本地化
- MDN:Intl.NumberFormat —— 数字与百分比本地化
读完这一课了?
标记完成后,工作台会安排接下来的学习。