dojo dragon main logo

使用消息包

Dojo 的消息包概念是一个 Map 对象,其中存储用 key 标识的文本消息,每个 key 标识的消息内容可以用一到多种语言表示。

当需要向最终用户显示消息时,Dojo 应用程序使用 key 来引用该消息。这就避免了在代码中硬编码某一种语言的文本,而是提供了一门或多门语言的外部消息集,这些消息集能独立于应用程序的代码单独维护。

在渲染时,根据部件中引用消息 key 时的当前区域设置,Dojo 的 i18n 框架使用指定语言的文本内容替换掉消息 key。

Dojo 应用程序可以选择在整个应用程序中只使用一个消息包;也可以将消息进一步拆分的更细,接近于一个部件对应一个消息包,最终得到一个包含多个消息包的应用程序。

包的默认语言

每个消息包中都会包含多门语言的翻译。其中一门语言需要作为其余语言包的默认模块。这个默认的语言模块用于导入(或引用)包,主要实现两个需求:

  • 提供一组完整的消息 key 及对应的内容(使用默认语言),如果包中的其他语言没有覆写某一个 key,则回退使用这些 key 和内容
  • 列出包中支持的其他语言,以及每一个支持的语言模块消息集的加载机制

TypeScript 结构

包中的每一种语言都是一个 TypeScript 模块,该模块必须要默认导出一个 Map 对象,该对象用于描述指定语言中的 key 和对应的翻译文本。

例如,包中的法语模块:

nls/fr/main.ts

export default {
	hello: 'Bonjour',
	goodbye: 'Au revoir'
};

默认的语言模块

选定作为包的默认语言模块的格式与其他语言模块略有不同。默认模块需要导出具有以下属性的对象

  • messages
    • 包含消息 key 和默认语言文本的 Map 对象,其结构与包中其他语言的导出对象相同。这里描述的是包支持的、规范化的消息 key。应用程序的区域设置为默认值时,解析消息 key 时就会从这些 messages 中查找。当设置的区域不是默认语言时,则包中的其他语言模块没有包含的 key 时,都会回退使用这些 messages
  • locales
    • 一个可选属性,是包含区域标识符和对应函数的 Map,这个函数用于加载包支持的每种语言(或区域)的消息集。

例如,将英语作为默认语言的包也支持法语、阿拉伯语和日语:

nls/main.ts

export default {
	locales: {
		fr: () => import('./fr/main'),
		ar: () => import('./ar/main'),
		ja: () => import('./ja/main')
	},
	messages: {
		hello: 'Hello',
		goodbye: 'Goodbye'
	}
};

导入和使用包

当部件需要使用包含在包中的消息集时,可按照与导入其他 TypeScript 模块相同的方式导入包默认语言模块。

例如,假定存在以下默认包:

nls/en/MyI18nWidget.ts

export default {
	messages: {
		hello: 'Hello',
		welcome: 'Welcome to your application'
	}
};

可在部件中按如下方式导入或引用此模块:

widgets/MyI18nWidget.tsx

import { create, tsx } from '@dojo/framework/core/vdom';
import i18n from '@dojo/framework/core/middleware/i18n';

import myWidgetMessageBundle from '../nls/en/MyI18nWidget';

const factory = create({ i18n });

export default factory(function MyI18nWidget({ middleware: { i18n } }) {
	const { messages } = i18n.localize(myWidgetMessageBundle);

	return <div title={messages.hello}>{messages.welcome}</div>;
});

由于此示例使用 i18n 中间件的 .localize 方法加载消息,所以当在包的默认语言模块 nls/en/MyI18nWidget.ts 中引入新的语言时,依然能正常工作。如果当前配置的语言可用,则用户会看到 MyI18nWidget 实例使用本地化消息。

应用程序要覆盖用户的默认语言,并允许在应用程序中更改区域设置,则需要额外设置,在国际化 Dojo 应用程序一节有详细介绍。

延迟加载与静态加载

推荐在默认语言的 locales 中使用函数来加载其他语言的翻译模块,因为这样可以延迟加载本地化的消息包(如果需要的话)。

但有些应用程序可能希望与包的默认语言模块一起静态加载某一种语言,并能通过直接返回兼容的对象结构来实现。

一个包中包含两种加载类型的示例:

import fr from './fr/main';

export default {
	locales: {
		// Locale providers can load translations lazily...
		ar: () => import('./ar/main'),
		'ar-JO': () => import('./ar-JO/main'),

		// ... or return references directly.
		fr
	},
	// Default/fallback messages
	messages: {
		hello: 'Hello',
		goodbye: 'Goodbye'
	}
};