本地化
本地化是使您的应用和组件支持多种语言和地区的流程。Lit 通过@lit/localize
库提供了一流的本地化支持,该库拥有许多优势,使其成为优于第三方本地化库的选择。
对本地化模板内的表达式和 HTML 标记的原生支持。无需新的语法和插值运行时进行变量替换 - 只需使用您现有的模板。
当语言环境切换时,Lit 组件会自动重新渲染。
仅 1.27 KiB(压缩后最小化)的额外 JavaScript。
可以选择为每个语言环境编译,将额外 JavaScript 减少到 0 KiB。
安装@lit/localize
客户端库和@lit/localize-tools
命令行界面。
npm i @lit/localize
npm i -D @lit/localize-tools
快速入门
“快速入门” 的永久链接- 将字符串或模板包装在
msg
函数中(详情)。 - 创建一个
lit-localize.json
配置文件(详情)。 - 运行
lit-localize extract
以生成一个 XLIFF 文件(详情)。 - 编辑生成的 XLIFF 文件以添加
<target>
翻译标签(详情)。 - 运行
lit-localize build
以输出字符串和模板的本地化版本(详情)。
使字符串和模板可本地化
“使字符串和模板可本地化” 的永久链接要使字符串或 Lit 模板可本地化,请将其包装在msg
函数中。msg
函数返回给定字符串或模板的版本,无论当前激活的是哪个语言环境。
在您拥有任何可用翻译之前,msg
只返回原始字符串或模板,因此即使您尚未准备好实际本地化,也可以安全使用。
import {html, LitElement} from 'lit';
import {customElement, property} from 'lit/decorators.js';
import {msg} from '@lit/localize';
@customElement('my-greeter')
class MyGreeter extends LitElement {
@property()
who = 'World';
render() {
return msg(html`Hello <b>${this.who}</b>`);
}
}
import {html, LitElement} from 'lit';
import {msg} from '@lit/localize';
class MyGreeter extends LitElement {
static properties = {
who: {},
};
constructor() {
super();
this.who = 'World';
}
render() {
return msg(html`Hello <b>${this.who}</b>`);
}
}
customElements.define('my-greeter', MyGreeter);
消息类型
“消息类型” 的永久链接您可以将任何您通常使用 Lit 渲染的字符串或模板本地化,包括包含动态表达式和 HTML 标记的字符串或模板。
纯字符串
msg('Hello World');
带表达式的纯字符串(有关str
的详细信息,请参阅带表达式的字符串)。
msg(str`Hello ${name}`);
HTML 模板
msg(html`Hello <b>World</b>`);
带表达式的 HTML 模板
msg(html`Hello <b>${name}</b>`);
本地化消息也可以嵌套在 HTML 模板内
html`<button>${msg('Hello World')}</button>`;
带表达式的字符串
“带表达式的字符串” 的永久链接包含表达式的字符串必须用html
或str
标记才能本地化。当您的字符串不包含任何 HTML 标记时,您应该优先使用str
而不是html
,因为它具有更少的性能开销。如果您忘记在包含表达式的字符串上添加html
或str
标记,则在运行lit-localize
命令时会引发错误。
错误
import {msg} from '@lit/localize';
msg(`Hello ${name}`);
正确
import {msg, str} from '@lit/localize';
msg(str`Hello ${name}`);
在这些情况下需要str
标记,因为未标记的模板字符串字面量在被msg
函数接收之前会被评估为普通字符串,这意味着否则无法捕获动态表达式值并将它们替换为字符串的本地化版本。
语言代码
“语言代码” 的永久链接语言代码是一个字符串,用于标识人类语言,有时还会包含地区、脚本或其他变体。
Lit Localize 并不强制使用任何特定的语言代码系统,但强烈建议使用BCP 47 语言标签标准。以下是一些 BCP 47 语言标签的示例
- en: 英语
- es-419: 拉丁美洲西班牙语
- zh-Hans: 简体中文
Lit Localize 定义了一些用于引用语言代码的术语。这些术语在本文档、Lit Localize 配置文件中和 Lit Localize API 中使用
- 源语言环境
用于在源代码中编写字符串和模板的语言环境。
- 目标语言环境
您可以将字符串和模板翻译成的语言环境。
- 活动语言环境
当前显示的全局语言环境。
输出模式
“输出模式” 的永久链接Lit Localize 支持两种输出模式
运行时模式使用 Lit Localize 的 API 在运行时加载本地化消息。
转换模式通过为每个语言环境构建单独的 JavaScript 包来消除 Lit Localize 运行时代码。
不确定使用哪种模式?从运行时模式开始。稍后切换模式很容易,因为核心msg
API 是相同的。
运行时模式
“运行时模式” 的永久链接在运行时模式下,为您的每个语言环境生成一个 JavaScript 或 TypeScript 模块。每个模块都包含该语言环境的本地化模板。当活动语言环境切换时,该语言环境的模块会被导入,所有本地化组件都会重新渲染。
运行时模式使切换语言环境变得非常快,因为不需要页面重新加载。但是,与转换模式相比,渲染性能会略有下降。
示例生成输出
“示例生成输出” 的永久链接// locales/es-419.ts
export const templates = {
hf71d669027554f48: html`Hola <b>Mundo</b>`,
};
有关运行时模式的完整信息,请参阅运行时模式页面。
转换模式
“转换模式” 的永久链接在转换模式下,为每个语言环境生成一个单独的文件夹。每个文件夹都包含该语言环境的应用程序的完整独立构建版本,其中已完全删除了msg
包装器和所有其他 Lit Localize 运行时代码。
转换模式不需要额外的 JavaScript,并且渲染速度极快。但是,切换语言环境需要重新加载页面,以便加载新的 JavaScript 包。
示例生成输出
“示例生成输出” 的永久链接// locales/en/my-element.js
render() {
return html`Hello <b>World</b>`;
}
// locales/es-419/my-element.js
render() {
return html`Hola <b>Mundo</b>`;
}
有关转换模式的完整信息,请参阅转换模式页面。
运行时模式 | 转换模式 | |
---|---|---|
输出 | 每个目标语言环境的动态加载模块。 | 每个语言环境的独立应用程序构建版本。 |
切换语言环境 | 调用setLocale() | 重新加载页面 |
JS 字节 | 1.27 KiB(压缩后最小化) | 0 KiB |
使模板可本地化 | msg() | msg() |
配置 | configureLocalization() | configureTransformLocalization() |
优势 |
|
|
配置文件
“配置文件” 的永久链接lit-localize
命令行工具会在当前目录中查找名为lit-localize.json
的配置文件。复制粘贴以下示例以快速入门,并参阅CLI 和配置页面以获取所有选项的完整参考。
如果您正在编写 JavaScript,请将inputFiles
属性设置为您的.js
源文件的位置。如果您正在编写 TypeScript,请将tsConfig
属性设置为您的tsconfig.json
文件的位置,并将inputFiles
保留为空。
{
"$schema": "https://raw.githubusercontent.com/lit/lit/main/packages/localize-tools/config.schema.json",
"sourceLocale": "en",
"targetLocales": ["es-419", "zh-Hans"],
"tsConfig": "./tsconfig.json",
"output": {
"mode": "runtime",
"outputDir": "./src/generated/locales",
"localeCodesModule": "./src/generated/locale-codes.ts"
},
"interchange": {
"format": "xliff",
"xliffDir": "./xliff/"
}
}
{
"$schema": "https://raw.githubusercontent.com/lit/lit/main/packages/localize-tools/config.schema.json",
"sourceLocale": "en",
"targetLocales": ["es-419", "zh-Hans"],
"inputFiles": [
"src/**/*.js"
],
"output": {
"mode": "runtime",
"outputDir": "./src/generated/locales",
"localeCodesModule": "./src/generated/locale-codes.js"
},
"interchange": {
"format": "xliff",
"xliffDir": "./xliff/"
}
}
提取消息
“提取消息” 的永久链接运行lit-localize extract
以针对每个目标语言环境生成一个XLIFF文件。XLIFF 是一种 XML 格式,大多数本地化工具和服务都支持这种格式。XLIFF 文件将被写入interchange.xliffDir
配置选项指定的目录。
lit-localize extract
例如,给定源
msg('Hello World');
msg(str`Hello ${name}`);
msg(html`Hello <b>World</b>`);
然后,将针对每个目标语言环境生成一个<xliffDir>/<locale>.xlf
文件
<!-- xliff/es-419.xlf -->
<trans-unit id="s3d58dee72d4e0c27">
<source>Hello World</source>
</trans-unit>
<trans-unit id="saed7d3734ce7f09d">
<source>Hello <x equiv-text="${name}"/></source>
</trans-unit>
<trans-unit id="hf71d669027554f48">
<source>Hello <x equiv-text="<b>"/>World<x equiv-text="</b>"/></source>
</trans-unit>
使用 XLIFF 翻译
“使用 XLIFF 翻译” 的永久链接XLIFF 文件可以手动编辑,但更常见的是将它们发送到第三方翻译服务,在那里它们会由使用专业工具的语言专家编辑。
将您的 XLIFF 文件上传到您选择的翻译服务后,您最终会收到新的 XLIFF 文件作为回复。新的 XLIFF 文件看起来与您上传的文件完全一样,但在每个<trans-unit>
中都插入了<target>
标签。
当您收到新的翻译 XLIFF 文件时,请将它们保存到您配置的interchange.xliffDir
目录中,覆盖原始版本。
<!-- xliff/es-419.xlf -->
<trans-unit id="s3d58dee72d4e0c27">
<source>Hello World</source>
<target>Hola Mundo</target>
</trans-unit>
<trans-unit id="saed7d3734ce7f09d">
<source>Hello <x equiv-text="${name}"/></source>
<target>Hola <x equiv-text="${name}"/></target>
</trans-unit>
<trans-unit id="hf71d669027554f48">
<source>Hello <x equiv-text="<b>"/>World<x equiv-text="</b>"/></source>
<target>Hola <x equiv-text="<b>"/>Mundo<x equiv-text="</b>"/></target>
</trans-unit>
构建本地化模板
“构建本地化模板” 的永久链接使用lit-localize build
命令将翻译合并回您的应用程序。此命令的行为取决于您配置的输出模式。
lit-localize build
有关在每种模式下构建的详细信息,请参阅运行时模式和转换模式页面。
消息描述
“消息描述” 的永久链接对msg
函数使用desc
选项来为您的字符串和模板提供人类可读的描述。大多数翻译工具会将这些描述显示给翻译人员,并且强烈建议使用它们来帮助解释和说明消息的含义。
render() {
return html`<button>
${msg("Launch", {
desc: "Button that begins rocket launch sequence.",
})}
</button>`;
}
描述在 XLIFF 文件中使用<note>
元素表示。
<trans-unit id="s512957aa09384646">
<source>Launch</source>
<note from="lit-localize">Button that begins rocket launch sequence.</note>
</trans-unit>
消息 ID
“消息 ID” 的永久链接Lit Localize 会为每个msg
调用自动生成一个 ID,该 ID 使用字符串的哈希值计算得出。
如果两个msg
调用共享相同的 ID,则它们被视为同一个消息,这意味着它们将被作为单个单元进行翻译,并且相同的翻译将在两个地方被替换。
例如,这两个msg
调用位于两个不同的文件中,但由于它们具有相同的内容,因此将被视为一条消息。
// file1.js
msg('Hello World');
// file2.js
msg('Hello World');
ID 生成
指向“ID 生成”的永久链接以下内容会影响 ID 生成
- 字符串内容
- HTML 标记
- 表达式的 位置
- 字符串是否用
html
标记
以下内容**不会**影响 ID 生成
- 表达式内的代码
- 表达式的计算值
- 文件位置
例如,所有这些消息都共享相同的 ID
msg(html`Hello <b>${name}</b>`);
msg(html`Hello <b>${this.name}</b>`);
但此消息具有不同的 ID
msg(html`Hello <i>${name}</i>`);
注意,虽然提供描述不会影响 ID 生成,但多个具有相同 ID 但描述不同的消息将在分析期间产生错误,以避免提取的翻译单元中的歧义。以下是**无效**的
msg(html`Hello <b>${name}</b>`);
msg(html`Hello <b>${name}</b>`, {desc: 'A friendly greeting'});
确保所有具有相同 ID 的消息也具有相同的描述。
覆盖 ID
指向“覆盖 ID”的永久链接可以通过为msg
函数指定id
选项来覆盖消息 ID。在某些情况下这可能是必要的,例如当相同字符串具有多个含义时,因为每个含义都可能在另一种语言中以不同的方式编写。
msg('Buffalo', {id: 'buffalo-animal-singular'});
msg('Buffalo', {id: 'buffalo-animal-plural'});
msg('Buffalo', {id: 'buffalo-city'});
msg('Buffalo', {id: 'buffalo-verb'});