你正在查看 Lit 的旧版本文档。点击 这里查看最新版本。

本地化最佳实践

每次调用 msg 函数时,它返回给定字符串或 Lit 模板在当前活动语言区域的版本。但是,这个结果只是一个普通的字符串或模板;它本身并不具备在语言区域更改时重新渲染自身的能力。

因此,重要的是以确保每次 Lit render 方法运行时 msg 调用都会被重新求值的方式编写。这样,当语言区域更改时,将返回最新语言区域的正确字符串或模板。

在本地化属性默认值时很容易犯错。看起来很自然地这样写:

// 不要这样做!
label = msg('Default label')

render() {
return html`<button>${this.label}</button>`;
}

然而,上述模式在语言区域更改时没有机会更新默认标签。默认值将停留在元素实例化时恰好活动的语言区域版本。

一个简单的修复方法是将默认值回退直接移到 render 方法中:

render() {
return html`<button>${this.label ?? msg('Default label')}</button>`;
}

或者,可以使用自定义 getter/setter 来创建更自然的接口:

private _label?: string;

@property()
get label() {
return this._label ?? msg('Default label');
}

set label(label: string) {
this._label = label;
}

render() {
return html`<button>${this.label}</button>`;
}
static properties = {
label: {}
};

get label() {
return this._label ?? msg('Default label');
}

set label(label) {
this._label = label;
}

render() {
return html`<button>${this.label}</button>`;
}

虽然 @lit/localize 完全支持在本地化模板中嵌入 HTML 标记,但最好尽可能避免这样做。原因是:

  1. 翻译人员更容易处理简单的字符串短语,而不是包含嵌入标记的短语。

  2. 避免在标记更改时产生不必要的重新翻译工作,例如在添加仅影响外观而不改变含义的 class 时。

  3. 切换语言区域通常会更快,因为 DOM 中需要更新的部分更少。同时,你的包中包含的 JavaScript 也会更少,因为公共标记不需要复制到每个翻译中。

不推荐:

render() {
// 不要这样做!没有理由在这个本地化模板中包含 <button> 标签。
return msg(html`<button>Launch rocket</button>`);
}

推荐:

render() {
// 这样好多了!现在短语 "Launch rocket" 可以更容易地被独立翻译。
return html`<button>${msg('Launch rocket')}</button>`;
}

将模板拆分为更小的部分也会有所帮助:

render() {
// 不要这样做!
return msg(html`
<p>The red button makes the rocket go up.</p>
<p>The green button makes the rocket do a flip.</p>
`);
}
render() {
// 这样更好!翻译人员无需处理标记,每个句子可以独立翻译。
return html`
<p>${msg('The red button makes the rocket go up.')}</p>
<p>${msg('The green button makes the rocket do a flip.')}</p>
`;
}

使用转换模式时,模板将被自动扁平化以使其尽可能小且高效。转换后,上述示例不会有任何占位符,因为它知道字符串可以直接合并到 HTML 模板中。

有些情况下 HTML 应该 包含在本地化模板中。例如,当短语中间需要 HTML 标签时:

render() {
return msg(html`Lift off in <b>T-${this.countdown}</b> seconds`);
}

安全地重新导出或重新赋值本地化 API

Permalink to "安全地重新导出或重新赋值本地化 API"

静态分析用于确定你何时调用 @lit/localizemsg 函数和其他 API,而不是同名的其他函数。

可以重新导出或重新赋值 msg 函数和其他 API,大多数情况下这都能正常工作。

但是,某些模式可能过于复杂,静态分析无法理解。如果消息未能被提取,而你又重新赋值或重新导出了 msg 函数,这可能是原因所在。

要强制将函数分析为 @lit/localize API,你可以在 JavaScript 中使用 JSDoc @type 注释,或在 TypeScript 中使用类型转换:

const myMsg = ... as typeof import('@lit/localize').msg;
/** @type import('@lit/localize').msg */
const myMsg = ...;