dojo dragon main logo

高级格式化

消息格式

基本的标记替换

Dojo 的 i18n 框架支持 ICU 消息格式化,也支持基本的标记替换。

接下来两个小节中的消息格式化示例会使用包含一个 guestInfo 消息的消息包,如下所示:

nls/main.ts

export default {
    messages: {
        guestInfo: '{host} invites {guest} to the party.'
    }
};

在部件中替换标记

支持 i18n 的部件可使用 i18n 中间件的 localize 方法返回的 format 函数在其消息中执行简单的标记替换。

可直接使用 format 渲染 guestInfo 消息:

widgets/MyI18nWidget.tsx

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

import nlsBundle from '../nls/main';

const factory = create({ i18n });

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

    return (
        <div>
            {format('guestInfo', {
                host: 'Margaret Mead',
                guest: 'Laura Nader'
            })}
        </div>
        // Will render as 'Margaret Mead invites Laura Nader to the party.'
    );
});

直接使用标记替换的格式化功能

i18n 模块的 localizeBundle 函数返回的对象中,有一个用于处理消息格式化的 format 方法:

import { localizeBundle } from '@dojo/framework/i18n/i18n';
import bundle from 'nls/main';

localizeBundle(bundle, { locale: 'en' }).then(({ format }) => {
    const message = format('guestInfo', {
        host: 'Margaret Mead',
        guest: 'Laura Nader'
    });
    console.log(message); // "Margaret Mead invites Laura Nader to the party."
});

ICU 消息格式化

@dojo/framework/i18n 使用 Globalize.js 进行 ICU 消息格式化,因此 Globalize.js 提供的所有功能都可以通过 @dojo/framework/i18n 访问。

接下来两个小节的消失格式化示例中将使用已更新了 guestInfo 消息的消息包,如下所示:

nls/main.ts

export default {
    messages: {
        guestInfo: `{gender, select,
            female {
                {guestCount, plural, offset:1
                =0 {{host} does not give a party.}
                =1 {{host} invites {guest} to her party.}
                =2 {{host} invites {guest} and one other person to her party.}
                other {{host} invites {guest} and # other people to her party.}}}
            male {
                {guestCount, plural, offset:1
                =0 {{host} does not give a party.}
                =1 {{host} invites {guest} to his party.}
                =2 {{host} invites {guest} and one other person to his party.}
                other {{host} invites {guest} and # other people to his party.}}}
            other {
                {guestCount, plural, offset:1
                =0 {{host} does not give a party.}
                =1 {{host} invites {guest} to their party.}
                =2 {{host} invites {guest} and one other person to their party.}
                other {{host} invites {guest} and # other people to their party.}}}}`
    }
};

在部件中使用 ICU 消息格式化功能

支持 i18n 的部件可使用 localizeBundle 方法返回的 format 函数来执行 ICU 消息格式化,这与上述的简单标记替换相同。

ICU 格式的 guestInfo 消息会被渲染为:

widgets/MyI18nWidget.tsx

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

import nlsBundle from '../nls/main';

const factory = create({ i18n });

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

    return (
        <div>
            {
            format('guestInfo', {
                host: 'Margaret Mead',
                gender: 'female',
                guest: 'Laura Nader',
                guestCount: 20
            })
            }
        </div>
        ]); // Will render as 'Margaret Mead invites Laura Nader and 19 other people to her party.'
    );
});

直接使用 ICU 消息格式化功能

可以使用 localizeBundle 返回的 format 方法直接转换 ICU 格式的 guestInfo 消息。

import { localizeBundle } from '@dojo/framework/i18n/i18n';
import bundle from 'nls/main';

// 1. Load the messages for the locale.
localizeBundle(bundle, { locale: 'en' }).then(({ format }) => {
    const message = format('guestInfo', {
        host: 'Margaret Mead',
        gender: 'female',
        guest: 'Laura Nader',
        guestCount: 20
    });
    console.log(message); // "Margaret Mead invites Laura Nader and 19 other people to her party."

    console.log(
        format('guestInfo', {
            host: 'Marshall Sahlins',
            gender: 'male',
            guest: 'Bronisław Malinowski'
        })
    ); // "Marshall Sahlins invites Bronisław Malinowski to his party."
});

格式化日期和数字

跟文本消息格式化功能一样,@dojo/framework/i18n 使用 Globalize.js 为日期、时间、货币、数字和单位提供特定区域的格式化。格式化工具本身是对 Globalize.js 相应函数的轻量级封装,这有助于确保 Dojo 生态系统的一致性,并避免直接使用 Globalize 对象。与文本消息的格式化不同,日期、数字和单位格式化不会缓存,因为它们有一组更加复杂的选项。因此,多次使用相同的输入执行各种“获取格式化函数”的方法不会返回完全相同的函数对象。

@dojo/framework/i18n 对各种格式化函数进行分组:日期和时间格式化(@dojo/framework/i18n/date);数字、货币和多元化的格式化(@dojo/framework/i18n/number);单位格式化(@dojo/framework/i18n/unit)。每个方法都与 Globalize.js 中的方法一一对应(见下文),每个方法都遵循相同的基本格式:最后一个参数是可选的区域,倒数第二个参数是一个方法选项。如果指定了区域,但没有方法选项,则为 options 参数传入 null。如果没有提供区域设置,则假定使用当前区域(i18n.locale)。

import { formatDate, getDateFormatter, formatRelativeTime } from '@dojo/framework/i18n/date';
import { formatCurrency, getCurrencyFormatter } from '@dojo/framework/i18n/number';
import { formatUnit, getUnitFormatter } from '@dojo/framework/i18n/unit';

const date = new Date(1815, 11, 10, 11, 27);

// Assume the current locale is "en"
const enDateFormatter = getDateFormatter({ datetime: 'medium' });
enDateFormatter(date); // Dec 10, 1815, 11:27:00 AM
formatDate(date, { date: 'short' }); // 12/10/15

const frDateFormatter = getDateFormatter({ datetime: 'medium' }, 'fr');
frDateFormatter(date); // 10 déc. 1815 à 11:27:00
formatDate(date, { date: 'short' }, 'fr'); // 10/12/1815

formatRelativeTime(-1, 'week'); // "last week"
formatRelativeTime(-1, 'week', { form: 'short' }); // "last wk."
formatRelativeTime(-3, 'week', null, 'fr'); // "il y a 3 semaines"
formatRelativeTime(-3, 'week', { form: 'short' }, 'fr'); // "il y a 3 sem."

const enCurrencyFormatter = getCurrencyFormatter('USD', { style: 'code' });
enCurrencyFormatter(1234.56); // "1,234.56 USD"
formatCurrency(12345.56, 'USD', { style: 'code' }); // "1,234.56 USD"

const frCurrencyFormatter = getCurrencyFormatter('EUR', { style: 'code' }, 'fr');
frCurrencyFormatter(1234.56); // "1 234,56 EUR"
formatCurrency(12345.56, 'EUR', { style: 'code' }, 'fr'); // "1 234,56 EUR"

const enUnitFormatter = getUnitFormatter('feet', { form: 'narrow' });
enUnitFormatter(5280); // 5,280′
formatUnit(5280, 'feet', { form: 'narrow' }); // 5,280′

const frUnitFormatter = getUnitFormatter('meter', null, 'fr');
frUnitFormatter(1000); // 1 000 mètres'
formatUnit(1000, 'meter', null, 'fr); // 1 000 mètres'

@dojo/framework/i18n/date 方法:

@dojo/framework/i18n/number 方法:

@dojo/framework/i18n/unit 方法: