Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
71 changes: 71 additions & 0 deletions packages/core/src/i18n.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -476,6 +476,77 @@ describe("I18n", () => {
`)
})

describe("global custom formats", () => {
const i18n = setupI18n({
locale: "fr",
formats: {
myDateStyle: {
day: "numeric",
},
myNumberStyle: {
maximumFractionDigits: 2,
},
},
messages: { fr: {} },
})

const date = new Date("2014-12-06")

const number = 123.4567

it("._ should respect global custom date formats", () => {
expect(
i18n._("It starts on {someDate, date, myDateStyle}", {
someDate: date,
})
).toMatchInlineSnapshot(`"It starts on 6"`)
})

it("._ should respect global custom number formats", () => {
expect(
i18n._("Number is {someNumber, number, myNumberStyle}", {
someNumber: number,
})
).toMatchInlineSnapshot(`"Number is 123,46"`)
})

it("._ should override global custom date formats with local ones", () => {
expect(
i18n._(
"It starts on {someDate, date, myDateStyle}",
{
someDate: date,
},
{
formats: {
myDateStyle: {
day: "2-digit",
},
},
}
)
).toMatchInlineSnapshot(`"It starts on 06"`)
})

it("._ should override global custom number formats with local ones", () => {
expect(
i18n._(
"Number is {someNumber, number, myNumberStyle}",
{
someNumber: number,
},
{
formats: {
myNumberStyle: {
maximumFractionDigits: 3,
},
},
}
)
).toMatchInlineSnapshot(`"Number is 123,457"`)
})
})

describe("ICU date format", () => {
const i18n = setupI18n({
locale: "fr",
Expand Down
9 changes: 8 additions & 1 deletion packages/core/src/i18n.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,11 @@ export type I18nProps = {
*/
localeData?: AllLocaleData
missing?: MissingHandler
/**
* Global custom formats to be used in all `i18n._` calls.
* Additional passed formats in the `i18n._` call will be merged with the global ones.
*/
formats?: Formats
}

type Events = {
Expand All @@ -89,6 +94,7 @@ export class I18n extends EventEmitter<Events> {
private _localeData: AllLocaleData = {}
private _messages: AllMessages = {}
private _missing?: MissingHandler
private _formats: Formats = {}
private _messageCompiler?: MessageCompiler

constructor(params: I18nProps) {
Expand All @@ -104,6 +110,7 @@ export class I18n extends EventEmitter<Events> {
if (typeof params.locale === "string" || params.locales) {
this.activate(params.locale ?? defaultLocale, params.locales)
}
if (params.formats != null) this._formats = params.formats
}

get locale() {
Expand Down Expand Up @@ -304,7 +311,7 @@ Please compile your catalog first.
translation,
this._locale,
this._locales
)(values, options?.formats)
)(values, { ...this._formats, ...options?.formats })
}

/**
Expand Down
19 changes: 19 additions & 0 deletions website/docs/ref/core.md
Original file line number Diff line number Diff line change
Expand Up @@ -364,6 +364,25 @@ const i18n = setupI18n({ missing });
i18n._("missing translation"); // Triggers an alert
```

### `options.formats`

Custom format definitions for number, dates and times. An object where keys are format names and values are either `Intl.DateTimeFormatOptions` or `Intl.NumberFormatOptions`.

```tsx
import { setupI18n } from "@lingui/core";

const i18n = setupI18n({
formats: {
myDateStyle: {
day: "numeric",
},
}
});
i18n._("It starts on {someDate, date, myDateStyle}", {
someDate: new Date("2014-12-06"),
}) === "It starts on 6";
```

## AllMessages

The `AllMessages` parameter in the [`I18n.load`](#i18n.load) method is of the following type:
Expand Down
Loading