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

运行时本地化模式

在 Lit Localize 运行时模式下,为每个语言区域生成一个 JavaScript 或 TypeScript 模块。每个生成的模块包含该语言区域的本地化模板。当你的应用切换语言区域时,会导入该语言区域的模块,并重新渲染所有本地化组件。

有关 Lit Localize 输出模式的比较,请参阅输出模式

// locales/es-419.ts
export const templates = {
h3c44aff2d5f5ef6b: html`Hola <b>Mundo!</b>`,
};

以下示例演示了一个使用 Lit Localize 运行时模式构建的应用:

Lit GitHub 仓库包含 Lit Localize 运行时模式的完整可运行示例(JavaScriptTypeScript),你可以将其作为模板使用。

在你的 lit-localize.json 配置中,将 output.mode 属性设置为 runtime,并将 output.outputDir 属性设置为你希望生成本地化模板模块的位置。更多详情请参阅运行时模式设置

接下来,将 output.localeCodesModule 设置为你选择的文件路径。Lit Localize 将在此处生成一个 .js.ts 模块,该模块将配置文件中的 sourceLocaletargetLocales 设置导出为变量。生成的模块大致如下:

export const sourceLocale = 'en';
export const targetLocales = ['es-419', 'zh-Hans'];
export const allLocales = ['en', 'es-419', 'zh-Hans'];

最后,在你的 JavaScript 或 TypeScript 项目中,调用 configureLocalization,传入一个包含以下属性的对象:

  • sourceLocale: string:你生成的 output.localeCodesModule 模块导出的 sourceLocale 变量。

  • targetLocales: string[]:你生成的 output.localeCodesModule 模块导出的 targetLocales 变量。

  • loadLocale: (locale: string) => Promise<LocaleModule>:加载本地化模板的函数。返回一个 Promise,解析为给定语言区域代码对应的生成的本地化模板模块。有关你可以在此处使用的函数示例,请参阅加载语言区域模块的方式

configureLocalization 返回一个包含以下属性的对象:

  • getLocale:返回活动语言区域代码的函数。如果新的语言区域已开始加载,getLocale 将继续返回之前的语言区域代码,直到新语言区域加载完成。

  • setLocale:开始将活动语言区域切换到给定代码的函数,返回一个在新语言区域加载完成时解析的 Promise。用法示例:

例如:

import {configureLocalization} from '@lit/localize';
// 通过 output.localeCodesModule 生成
import {sourceLocale, targetLocales} from './generated/locales.js';

export const {getLocale, setLocale} = configureLocalization({
sourceLocale,
targetLocales,
loadLocale: (locale) => import(`/locales/${locale}.js`),
});

要在每次活动语言区域切换时自动触发组件的重新渲染,在使用 JavaScript 时请在 constructor 中应用 updateWhenLocaleChanges 函数,或在使用 TypeScript 时为你的类应用 @localized 装饰器。

import {LitElement, html} from 'lit';
import {customElement} from 'lit/decorators.js';
import {msg, localized} from '@lit/localize';

@customElement('my-element');
@localized()
class MyElement extends LitElement {
render() {
// 每当调用 setLocale(),且该语言区域的模板加载完成后,
// 此 render() 函数将被重新调用。
return msg(html`Hello <b>World!</b>`);
}
}
import {LitElement, html} from 'lit';
import {msg, updateWhenLocaleChanges} from '@lit/localize';

class MyElement extends LitElement {
constructor() {
super();
updateWhenLocaleChanges(this);
}

render() {
// 每当调用 setLocale(),且该语言区域的模板加载完成后,
// 此 render() 函数将被重新调用。
return msg(html`Hello <b>World!</b>`);
}
}
customElements.define('my-element', MyElement);

lit-localize-status 事件在语言区域切换开始、完成或失败时在 window 上触发。你可以使用此事件来:

  • 在无法使用 @localized 装饰器时重新渲染(例如直接使用 Lit 的 render 函数时)。

  • 在语言区域切换开始时立即渲染,即使尚未加载完成(例如加载指示器)。

  • 执行其他本地化相关任务(例如设置语言区域偏好 cookie)。

detail.status 字符串属性告诉你发生了哪种状态变化,可以是 loadingreadyerror

loading

新的语言区域已开始加载。

detail 对象包含:

  • loadingLocale: string:已开始加载的语言区域代码。

如果在第一个语言区域加载完成之前请求了第二个语言区域, 将会分派新的 loading 事件,而第一个请求不会分派 readyerror 事件。

loading 状态后面可以是 readyerrorloading 状态。

ready

新的语言区域已成功加载并准备好进行渲染。

detail 对象包含:

  • readyLocale: string:已成功加载的语言区域代码。

ready 状态后面只能是 loading 状态。

error

新的语言区域加载失败。

detail 对象包含:

  • errorLocale: string:加载失败的语言区域代码。
  • errorMessage: string:语言区域加载失败的错误消息。

error 状态后面只能是 loading 状态。

// 在加载新语言区域时显示/隐藏进度指示器,
// 并在每次新语言区域成功加载时重新渲染应用。
window.addEventListener('lit-localize-status', (event) => {
const spinner = document.querySelector('#spinner');

if (event.detail.status === 'loading') {
console.log(`Loading new locale: ${event.detail.loadingLocale}`);
spinner.removeAttribute('hidden');
} else if (event.detail.status === 'ready') {
console.log(`Loaded new locale: ${event.detail.readyLocale}`);
spinner.setAttribute('hidden', '');
renderApplication();
} else if (event.detail.status === 'error') {
console.error(
`Error loading locale ${event.detail.errorLocale}: ` +
event.detail.errorMessage
);
spinner.setAttribute('hidden', '');
}
});

Lit Localize 允许你以任何方式加载语言区域模块,因为你可以将任何函数作为 loadLocale 选项传入。以下是一些常见模式:

使用动态导入仅在语言区域变为活动状态时加载。这是一个好的默认方式,因为它最大限度地减少了用户需要下载和执行的代码量。

import {configureLocalization} from '@lit/localize';
import {sourceLocale, targetLocales} from './generated/locales.js';

const {getLocale, setLocale} = configureLocalization({
sourceLocale,
targetLocales,
loadLocale: (locale) => import(`/locales/${locale}.js`),
});

在页面加载时开始预加载所有语言区域。仍然使用动态导入以确保在获取语言区域模块时不会阻塞页面上其余的脚本。

import {configureLocalization} from '@lit/localize';
import {sourceLocale, targetLocales} from './generated/locales.js';

const localizedTemplates = new Map(
targetLocales.map((locale) => [locale, import(`/locales/${locale}.js`)])
);

const {getLocale, setLocale} = configureLocalization({
sourceLocale,
targetLocales,
loadLocale: async (locale) => localizedTemplates.get(locale),
});

使用静态导入以阻塞页面上其他脚本的方式预加载所有语言区域。

通常不推荐此方式,因为它会导致在页面上其余脚本可以执行之前获取和执行超过必要量的代码,从而阻塞交互性。仅在你的应用非常小、必须分发在单个 JavaScript 文件中、或有其他限制导致无法使用动态导入时才使用此方式。

import {configureLocalization} from '@lit/localize';
import {sourceLocale, targetLocales} from './generated/locales.js';

import * as templates_es_419 from './locales/es-419.js';
import * as templates_zh_hans from './locales/zh-Hans.js';
...

const localizedTemplates = new Map([
['es-419', templates_es_419],
['zh-Hans', templates_zh_hans],
...
]);

const {getLocale, setLocale} = configureLocalization({
sourceLocale,
targetLocales,
loadLocale: async (locale) => localizedTemplates.get(locale),
});