Skip to content

Commit f10dbba

Browse files
authored
feat: Allow overriding typed Messages when using createTranslator (#1655)
Ref: https://x.com/ddunderfelt/status/1874403640515121642
1 parent 32dfcc2 commit f10dbba

File tree

2 files changed

+48
-43
lines changed

2 files changed

+48
-43
lines changed

packages/use-intl/src/core/IntlConfig.tsx

+41-39
Original file line numberDiff line numberDiff line change
@@ -8,49 +8,51 @@ import type TimeZone from './TimeZone.tsx';
88
* Should be used for entry points that configure the library.
99
*/
1010

11-
type IntlConfig<Messages = AbstractIntlMessages> = {
12-
/** A valid Unicode locale tag (e.g. "en" or "en-GB"). */
13-
locale: Locale;
14-
/** Global formats can be provided to achieve consistent
15-
* formatting across components. */
16-
formats?: Formats;
17-
/** A time zone as defined in [the tz database](https://en.wikipedia.org/wiki/List_of_tz_database_time_zones) which will be applied when formatting dates and times. If this is absent, the user time zone will be used. You can override this by supplying an explicit time zone to `formatDateTime`. */
18-
timeZone?: TimeZone;
19-
/** This callback will be invoked when an error is encountered during
20-
* resolving a message or formatting it. This defaults to `console.error` to
21-
* keep your app running. You can customize the handling by taking
22-
* `error.code` into account. */
23-
onError?(error: IntlError): void;
24-
/** Will be called when a message couldn't be resolved or formatting it led to
25-
* an error. This defaults to `${namespace}.${key}` You can use this to
26-
* customize what will be rendered in this case. */
27-
getMessageFallback?(info: {
28-
error: IntlError;
29-
key: string;
30-
namespace?: string;
31-
}): string;
32-
/**
33-
* Providing this value will have two effects:
34-
* 1. It will be used as the default for the `now` argument of
35-
* `useFormatter().formatRelativeTime` if no explicit value is provided.
36-
* 2. It will be returned as a static value from the `useNow` hook. Note
37-
* however that when `updateInterval` is configured on the `useNow` hook,
38-
* the global `now` value will only be used for the initial render, but
39-
* afterwards the current date will be returned continuously.
40-
*/
41-
now?: Date;
42-
/** All messages that will be available. */
43-
messages?: Messages;
44-
};
11+
type IntlConfig<Messages extends AbstractIntlMessages = AbstractIntlMessages> =
12+
{
13+
/** A valid Unicode locale tag (e.g. "en" or "en-GB"). */
14+
locale: Locale;
15+
/** Global formats can be provided to achieve consistent
16+
* formatting across components. */
17+
formats?: Formats;
18+
/** A time zone as defined in [the tz database](https://en.wikipedia.org/wiki/List_of_tz_database_time_zones) which will be applied when formatting dates and times. If this is absent, the user time zone will be used. You can override this by supplying an explicit time zone to `formatDateTime`. */
19+
timeZone?: TimeZone;
20+
/** This callback will be invoked when an error is encountered during
21+
* resolving a message or formatting it. This defaults to `console.error` to
22+
* keep your app running. You can customize the handling by taking
23+
* `error.code` into account. */
24+
onError?(error: IntlError): void;
25+
/** Will be called when a message couldn't be resolved or formatting it led to
26+
* an error. This defaults to `${namespace}.${key}` You can use this to
27+
* customize what will be rendered in this case. */
28+
getMessageFallback?(info: {
29+
error: IntlError;
30+
key: string;
31+
namespace?: string;
32+
}): string;
33+
/**
34+
* Providing this value will have two effects:
35+
* 1. It will be used as the default for the `now` argument of
36+
* `useFormatter().formatRelativeTime` if no explicit value is provided.
37+
* 2. It will be returned as a static value from the `useNow` hook. Note
38+
* however that when `updateInterval` is configured on the `useNow` hook,
39+
* the global `now` value will only be used for the initial render, but
40+
* afterwards the current date will be returned continuously.
41+
*/
42+
now?: Date;
43+
/** All messages that will be available. */
44+
messages?: Messages;
45+
};
4546

4647
/**
4748
* A stricter set of the configuration that should be used internally
4849
* once defaults are assigned to `IntlConfiguration`.
4950
*/
50-
export type InitializedIntlConfig<Messages = AbstractIntlMessages> =
51-
IntlConfig<Messages> & {
52-
onError: NonNullable<IntlConfig<Messages>['onError']>;
53-
getMessageFallback: NonNullable<IntlConfig<Messages>['getMessageFallback']>;
54-
};
51+
export type InitializedIntlConfig<
52+
Messages extends AbstractIntlMessages = AbstractIntlMessages
53+
> = IntlConfig<Messages> & {
54+
onError: NonNullable<IntlConfig<Messages>['onError']>;
55+
getMessageFallback: NonNullable<IntlConfig<Messages>['getMessageFallback']>;
56+
};
5557

5658
export default IntlConfig;

packages/use-intl/src/core/createTranslator.tsx

+7-4
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
import type {ReactNode} from 'react';
2-
import type {Messages} from './AppConfig.tsx';
32
import type Formats from './Formats.tsx';
43
import type ICUArgs from './ICUArgs.tsx';
54
import type ICUTags from './ICUTags.tsx';
@@ -62,8 +61,12 @@ type TranslateArgs<
6261
: [values: Prettify<Args>, formats?: Formats]
6362
: never;
6463

64+
// This type is slightly more loose than `AbstractIntlMessages`
65+
// in order to avoid a type error.
66+
type IntlMessages = Record<string, any>;
67+
6568
type NamespacedMessageKeys<
66-
TranslatorMessages extends Messages,
69+
TranslatorMessages extends IntlMessages,
6770
Namespace extends NamespaceKeys<
6871
TranslatorMessages,
6972
NestedKeyOf<TranslatorMessages>
@@ -82,7 +85,7 @@ type NamespacedMessageKeys<
8285
>;
8386

8487
type NamespacedValue<
85-
TranslatorMessages extends Messages,
88+
TranslatorMessages extends IntlMessages,
8689
Namespace extends NamespaceKeys<
8790
TranslatorMessages,
8891
NestedKeyOf<TranslatorMessages>
@@ -102,7 +105,7 @@ type NamespacedValue<
102105
* (e.g. `namespace.Component`).
103106
*/
104107
export default function createTranslator<
105-
const TranslatorMessages extends Messages = Messages,
108+
const TranslatorMessages extends IntlMessages,
106109
const Namespace extends NamespaceKeys<
107110
TranslatorMessages,
108111
NestedKeyOf<TranslatorMessages>

0 commit comments

Comments
 (0)