map 是运行时多语言键值缓存容器,通过 language code 为 key 缓存动态加载的语言包对象,配合 import() 按需加载、loadingpromises 去重、t() 翻译函数及 setlang 切换实现轻量级国际化。

JavaScript 中的 Map 本身不直接支持国际化(i18n)或动态加载语言包,但它非常适合用作**运行时多语言键值缓存容器**。真正实现“动态加载 + 国际化”需要结合模块加载(如 import())、语言包管理、以及 Map 的高效查找能力。核心思路是:用 Map 存储已加载的语言资源,按语言标识(如 'zh-CN'、'en-US')索引,避免重复加载,同时支持异步按需加载。
用 Map 缓存已加载的语言包
每个语言包是一个普通对象(如 { greeting: '你好', logout: '退出' }),我们用 Map 以语言码为 key、资源对象为 value 进行缓存。这样后续切换语言时,若已加载过,可直接取用,无需再次请求。
示例:
const langMap = new Map();
// 加载并缓存中文包
async function loadZh() {
const zh = await import('./locales/zh-CN.js');
langMap.set('zh-CN', zh.default);
}
// 加载并缓存英文包
async function loadEn() {
const en = await import('./locales/en-US.js');
langMap.set('en-US', en.default);
}
封装 getLang 方法实现按需加载 + 缓存复用
对外提供一个统一入口,自动判断是否已加载某语言;未加载则触发动态导入,并存入 Map;已加载则直接返回。支持 Promise 链式调用,也兼容同步场景(如服务端渲染时预置)。
建议写法:
Java项目代码review工具。分析Git变更+完整调用链路上下文,推断业务需求,进行多维度评分和分类汇总,生成完整PRD文档。包含细粒度Java代码审查清单(Null安全、异常处理、Streams、并发、equals/hashCode、资源管理、API设计、性能、MyBatis/ORM、事务边界、SQL/DD...
const langMap = new Map();
const loadingPromises = new Map(); // 避免同一语言多次并发加载
export async function getLang(langCode) {
if (langMap.has(langCode)) {
return langMap.get(langCode);
}
if (loadingPromises.has(langCode)) {
return loadingPromises.get(langCode);
}
const promise = import(`./locales/${langCode}.js`)
.then(module => {
const messages = module.default || {};
langMap.set(langCode, messages);
return messages;
})
.catch(err => {
console.warn(`Failed to load language: ${langCode}`, err);
throw err;
});
loadingPromises.set(langCode, promise);
return promise;
}
配合 i18n 工具函数使用(如 t() 翻译函数)
有了语言包缓存,就可以构建轻量级翻译函数。它不依赖框架,只依赖当前激活语言和 Map 中的资源。
关键点:
- 维护一个当前语言状态(如全局变量
currentLang = 'zh-CN'或用Ref) -
t(key, options?)函数内部从langMap.get(currentLang)取对象,再查 key - 支持嵌套路径(如
'user.profile.name')可借助简单工具函数解析
示例 t() 实现:
let currentLang = 'zh-CN';
export function t(key, params = {}) {
const langObj = langMap.get(currentLang) || {};
// 支持 a.b.c 形式取值
const getValue = (obj, path) =>
path.split('.').reduce((o, k) => o?.[k], obj);
let text = getValue(langObj, key) || key;
// 简单插值:{name} → params.name
if (typeof text === 'string' && Object.keys(params).length) {
text = text.replace(/\{(\w+)\}/g, (m, p1) => params[p1] ?? m);
}
return text;
}
// 切换语言并刷新翻译
export async function setLang(langCode) {
await getLang(langCode);
currentLang = langCode;
// 可触发 UI 重绘(如 dispatch event / 更新响应式状态)
}
注意事项与优化建议
实际项目中要注意以下细节,才能稳定支撑动态 i18n:
-
文件命名规范:确保
import(`./locales/${langCode}.js`)路径存在,推荐统一小写、用短横线(zh-CN),避免大小写或下划线歧义 -
兜底机制:当目标语言包加载失败时,应降级到默认语言(如
en-US),而不是留空 -
Tree-shaking 友好:动态
import()让打包工具能自动分割语言包为独立 chunk,但需确认构建配置(如 Webpack/Vite)未禁用代码分割 -
服务端渲染(SSR)适配:Node.js 环境不支持原生
import()字符串模板,需用require()或预编译处理,或在 SSR 时只加载必需语言
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










