@intlayer/react-intl 9.0.0-canary.2 → 9.0.0-canary.21
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/esm/createIntlObject.mjs +9 -14
- package/dist/esm/createIntlObject.mjs.map +1 -1
- package/dist/esm/dictionaryIntlShape.mjs +0 -0
- package/dist/esm/index.mjs +3 -1
- package/dist/esm/plugin/index.mjs +3 -36
- package/dist/esm/plugin/index.mjs.map +1 -1
- package/dist/esm/typedMessageIds.mjs +0 -0
- package/dist/esm/useDictionary.mjs +45 -0
- package/dist/esm/useDictionary.mjs.map +1 -0
- package/dist/esm/useDictionaryDynamic.mjs +27 -0
- package/dist/esm/useDictionaryDynamic.mjs.map +1 -0
- package/dist/types/FormattedComponents.d.ts +0 -1
- package/dist/types/FormattedComponents.d.ts.map +1 -1
- package/dist/types/FormattedMessage.d.ts +0 -1
- package/dist/types/FormattedMessage.d.ts.map +1 -1
- package/dist/types/IntlProvider.d.ts +0 -1
- package/dist/types/IntlProvider.d.ts.map +1 -1
- package/dist/types/context.d.ts +0 -1
- package/dist/types/context.d.ts.map +1 -1
- package/dist/types/createIntl.d.ts +0 -1
- package/dist/types/createIntl.d.ts.map +1 -1
- package/dist/types/createIntlObject.d.ts +5 -2
- package/dist/types/createIntlObject.d.ts.map +1 -1
- package/dist/types/defineMessages.d.ts +0 -1
- package/dist/types/defineMessages.d.ts.map +1 -1
- package/dist/types/dictionaryIntlShape.d.ts +53 -0
- package/dist/types/dictionaryIntlShape.d.ts.map +1 -0
- package/dist/types/errors.d.ts.map +1 -1
- package/dist/types/index.d.ts +5 -1
- package/dist/types/plugin/index.d.ts +0 -1
- package/dist/types/plugin/index.d.ts.map +1 -1
- package/dist/types/typedMessageIds.d.ts +25 -0
- package/dist/types/typedMessageIds.d.ts.map +1 -0
- package/dist/types/useDictionary.d.ts +30 -0
- package/dist/types/useDictionary.d.ts.map +1 -0
- package/dist/types/useDictionaryDynamic.d.ts +14 -0
- package/dist/types/useDictionaryDynamic.d.ts.map +1 -0
- package/dist/types/useIntl.d.ts +0 -1
- package/dist/types/useIntl.d.ts.map +1 -1
- package/package.json +15 -17
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Fragment } from "react";
|
|
2
2
|
import { getIntlayer } from "@intlayer/core/interpreter";
|
|
3
|
-
import { parseTaggedMessage, resolveMessage } from "@intlayer/core/messageFormat";
|
|
3
|
+
import { navigatePath, parseTaggedMessage, resolveMessage } from "@intlayer/core/messageFormat";
|
|
4
4
|
import { Fragment as Fragment$1, jsx } from "react/jsx-runtime";
|
|
5
5
|
|
|
6
6
|
//#region src/createIntlObject.tsx
|
|
@@ -16,16 +16,6 @@ const splitId = (id) => {
|
|
|
16
16
|
path: id.slice(dotIndex + 1)
|
|
17
17
|
};
|
|
18
18
|
};
|
|
19
|
-
const navigatePath = (object, path) => {
|
|
20
|
-
if (!path) return object;
|
|
21
|
-
const parts = path.split(".");
|
|
22
|
-
let current = object;
|
|
23
|
-
for (const part of parts) {
|
|
24
|
-
if (current === null || current === void 0 || typeof current !== "object") return;
|
|
25
|
-
current = current[part];
|
|
26
|
-
}
|
|
27
|
-
return current;
|
|
28
|
-
};
|
|
29
19
|
/** Looks up a message value by full dotted id; first segment = dictionary key. */
|
|
30
20
|
const lookupMessage = (id, locale) => {
|
|
31
21
|
const { dictionaryKey, path } = splitId(id);
|
|
@@ -62,16 +52,21 @@ const isRichValues = (values) => Object.values(values).some((value) => typeof va
|
|
|
62
52
|
* - Translation ids use the first dot-path segment as the dictionary key.
|
|
63
53
|
* - Full ICU MessageFormat syntax is supported via `@intlayer/core/messageFormat`.
|
|
64
54
|
* - Rich text tags (`<b>chunks</b>`) are resolved through render functions in `values`.
|
|
55
|
+
*
|
|
56
|
+
* @param locale - The locale messages are resolved for.
|
|
57
|
+
* @param lookupOverride - Optional message lookup replacing the registry-based
|
|
58
|
+
* id resolution; used by the dictionary-bound `useDictionary` variant.
|
|
65
59
|
*/
|
|
66
|
-
const createIntlObject = (locale) => {
|
|
60
|
+
const createIntlObject = (locale, lookupOverride) => {
|
|
67
61
|
const localeString = locale;
|
|
68
62
|
const formatMessage = (descriptor, values) => {
|
|
69
63
|
const { id = "", defaultMessage } = descriptor;
|
|
70
|
-
const rawValue = lookupMessage(id, locale);
|
|
64
|
+
const rawValue = lookupOverride ? lookupOverride(id) : lookupMessage(id, locale);
|
|
71
65
|
const messageTemplate = rawValue !== void 0 && rawValue !== null ? rawValue : typeof defaultMessage === "string" ? defaultMessage : id;
|
|
72
66
|
if (!values || !isRichValues(values)) return resolveMessage(messageTemplate, values ?? {}, locale, "icu") ?? id;
|
|
73
67
|
const { scalarValues, renderers } = splitRichValues(values);
|
|
74
|
-
|
|
68
|
+
const message = resolveMessage(messageTemplate, scalarValues, locale, "icu") ?? id;
|
|
69
|
+
return renderRichTokens(parseTaggedMessage(message), renderers);
|
|
75
70
|
};
|
|
76
71
|
const toDate = (value) => value instanceof Date ? value : new Date(value);
|
|
77
72
|
const formatDate = (value, options) => {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"createIntlObject.mjs","names":[],"sources":["../../src/createIntlObject.tsx"],"sourcesContent":["import { getIntlayer } from '@intlayer/core/interpreter';\nimport {\n type MessageValues,\n parseTaggedMessage,\n resolveMessage,\n type TaggedMessageToken,\n} from '@intlayer/core/messageFormat';\nimport type {\n DictionaryKeys,\n LocalesValues,\n} from '@intlayer/types/module_augmentation';\nimport { Fragment, type ReactNode } from 'react';\nimport type { IntlShape, MessageDescriptor } from 'react-intl';\n\ntype RichRenderer = (chunks: ReactNode) => ReactNode;\n\n/** Splits a full dotted id into the dictionary key and remaining path. */\nconst splitId = (id: string): { dictionaryKey: string; path: string } => {\n const dotIndex = id.indexOf('.');\n if (dotIndex === -1) return { dictionaryKey: id, path: '' };\n return {\n dictionaryKey: id.slice(0, dotIndex),\n path: id.slice(dotIndex + 1),\n };\n};\n\nconst navigatePath = (object: unknown, path: string): unknown => {\n if (!path) return object;\n const parts = path.split('.');\n let current: unknown = object;\n for (const part of parts) {\n if (\n current === null ||\n current === undefined ||\n typeof current !== 'object'\n ) {\n return undefined;\n }\n current = (current as Record<string, unknown>)[part];\n }\n return current;\n};\n\n/** Looks up a message value by full dotted id; first segment = dictionary key. */\nconst lookupMessage = (id: string, locale: LocalesValues): unknown => {\n const { dictionaryKey, path } = splitId(id);\n if (!dictionaryKey) return undefined;\n try {\n const dictionary = getIntlayer(dictionaryKey as DictionaryKeys, locale);\n return navigatePath(dictionary, path);\n } catch {\n return undefined;\n }\n};\n\n/** Maps tagged tokens to React nodes using the provided renderer functions. */\nconst renderRichTokens = (\n tokens: TaggedMessageToken[],\n renderers: Record<string, unknown>\n): ReactNode[] =>\n tokens.map((token, tokenIndex) => {\n if (typeof token === 'string') return token;\n const children = renderRichTokens(token.children, renderers);\n const renderer = renderers[token.tag];\n if (typeof renderer === 'function') {\n return (\n <Fragment key={tokenIndex}>\n {(renderer as RichRenderer)(<>{children}</>)}\n </Fragment>\n );\n }\n return <Fragment key={tokenIndex}>{children}</Fragment>;\n });\n\n/** Partitions values into scalar interpolation params and tag renderers. */\nconst splitRichValues = (\n values: Record<string, unknown>\n): { scalarValues: MessageValues; renderers: Record<string, unknown> } => {\n const scalarValues: MessageValues = {};\n const renderers: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(values)) {\n if (typeof value === 'function') renderers[key] = value;\n else scalarValues[key] = value as MessageValues[string];\n }\n return { scalarValues, renderers };\n};\n\nconst isRichValues = (values: Record<string, unknown>): boolean =>\n Object.values(values).some((value) => typeof value === 'function');\n\n/**\n * Builds an intlayer-backed `IntlShape` object for the given locale.\n *\n * - Translation ids use the first dot-path segment as the dictionary key.\n * - Full ICU MessageFormat syntax is supported via `@intlayer/core/messageFormat`.\n * - Rich text tags (`<b>chunks</b>`) are resolved through render functions in `values`.\n */\nexport const createIntlObject = (locale: LocalesValues): IntlShape => {\n const localeString = locale as string;\n\n const formatMessage = (\n descriptor: MessageDescriptor,\n values?: Record<string, unknown>\n ): string | ReactNode[] => {\n const { id = '', defaultMessage } = descriptor;\n const rawValue = lookupMessage(id, locale);\n const messageTemplate =\n rawValue !== undefined && rawValue !== null\n ? (rawValue as string)\n : typeof defaultMessage === 'string'\n ? defaultMessage\n : id;\n\n if (!values || !isRichValues(values)) {\n return (\n resolveMessage(\n messageTemplate,\n (values ?? {}) as MessageValues,\n locale,\n 'icu'\n ) ?? id\n );\n }\n\n const { scalarValues, renderers } = splitRichValues(values);\n const message =\n resolveMessage(messageTemplate, scalarValues, locale, 'icu') ?? id;\n return renderRichTokens(parseTaggedMessage(message), renderers);\n };\n\n const toDate = (value: Date | number | string): Date =>\n value instanceof Date ? value : new Date(value);\n\n const formatDate = (\n value: string | number | Date | undefined,\n options?: Intl.DateTimeFormatOptions\n ): string => {\n if (value === undefined || value === null) return '';\n return new Intl.DateTimeFormat(localeString, options).format(toDate(value));\n };\n\n const formatNumber = (\n value: number | bigint,\n options?: Intl.NumberFormatOptions\n ): string => new Intl.NumberFormat(localeString, options).format(value);\n\n const formatPlural = (\n value: number,\n options?: Intl.PluralRulesOptions\n ): Intl.LDMLPluralRule =>\n new Intl.PluralRules(localeString, options).select(value);\n\n const formatList = (\n list: Iterable<unknown> | readonly unknown[],\n options?: Intl.ListFormatOptions\n ): string => {\n const strings = Array.from(list).filter(\n (item): item is string => typeof item === 'string'\n );\n return new Intl.ListFormat(localeString, options).format(strings);\n };\n\n const formatListToParts = (\n list: Iterable<unknown> | readonly unknown[],\n options?: Intl.ListFormatOptions\n ): ReturnType<Intl.ListFormat['formatToParts']> => {\n const strings = Array.from(list).filter(\n (item): item is string => typeof item === 'string'\n );\n return new Intl.ListFormat(localeString, options).formatToParts(strings);\n };\n\n const formatDisplayName = (\n value: string,\n options?: Intl.DisplayNamesOptions\n ): string | undefined =>\n new Intl.DisplayNames([localeString], options ?? { type: 'language' }).of(\n value\n );\n\n const formatRelativeTime = (\n value: number,\n unit?: Intl.RelativeTimeFormatUnit,\n options?: Intl.RelativeTimeFormatOptions\n ): string =>\n new Intl.RelativeTimeFormat(localeString, {\n numeric: 'auto',\n ...options,\n }).format(value, unit ?? 'second');\n\n const formatDateTimeRange = (\n from: Date | number,\n to: Date | number,\n options?: Intl.DateTimeFormatOptions\n ): string =>\n new Intl.DateTimeFormat(localeString, options).formatRange(\n toDate(from),\n toDate(to)\n );\n\n const formatDateToParts = (\n value: Parameters<Intl.DateTimeFormat['format']>[0] | string,\n options?: Intl.DateTimeFormatOptions\n ): Intl.DateTimeFormatPart[] =>\n new Intl.DateTimeFormat(localeString, options).formatToParts(\n typeof value === 'string' ? new Date(value) : value\n );\n\n const formatNumberToParts = (\n value: number | bigint,\n options?: Intl.NumberFormatOptions\n ): Intl.NumberFormatPart[] =>\n new Intl.NumberFormat(localeString, options).formatToParts(value);\n\n /** Alias of `formatMessage` — provided for `@formatjs/intl` v4 compatibility. */\n const $t = formatMessage as IntlShape['$t'];\n\n return {\n locale: localeString,\n defaultLocale: localeString,\n messages: {},\n formats: {},\n defaultFormats: {},\n timeZone: undefined,\n textComponent: Fragment,\n wrapRichTextChunksInFragment: false,\n fallbackOnEmptyString: true,\n onError: () => {},\n onWarn: () => {},\n formatters: {} as IntlShape['formatters'],\n formatMessage: formatMessage as IntlShape['formatMessage'],\n $t,\n formatDate,\n formatTime: formatDate,\n formatNumber,\n formatPlural,\n formatList: formatList as IntlShape['formatList'],\n formatListToParts: formatListToParts as IntlShape['formatListToParts'],\n formatDisplayName: formatDisplayName as IntlShape['formatDisplayName'],\n formatRelativeTime,\n formatDateTimeRange,\n formatDateToParts: formatDateToParts as IntlShape['formatDateToParts'],\n formatTimeToParts: formatDateToParts as IntlShape['formatTimeToParts'],\n formatNumberToParts:\n formatNumberToParts as IntlShape['formatNumberToParts'],\n } as unknown as IntlShape;\n};\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"createIntlObject.mjs","names":[],"sources":["../../src/createIntlObject.tsx"],"sourcesContent":["import { getIntlayer } from '@intlayer/core/interpreter';\nimport {\n type MessageValues,\n navigatePath,\n parseTaggedMessage,\n resolveMessage,\n type TaggedMessageToken,\n} from '@intlayer/core/messageFormat';\nimport type {\n DictionaryKeys,\n LocalesValues,\n} from '@intlayer/types/module_augmentation';\nimport { Fragment, type ReactNode } from 'react';\nimport type { IntlShape, MessageDescriptor } from 'react-intl';\n\ntype RichRenderer = (chunks: ReactNode) => ReactNode;\n\n/** Splits a full dotted id into the dictionary key and remaining path. */\nconst splitId = (id: string): { dictionaryKey: string; path: string } => {\n const dotIndex = id.indexOf('.');\n if (dotIndex === -1) return { dictionaryKey: id, path: '' };\n return {\n dictionaryKey: id.slice(0, dotIndex),\n path: id.slice(dotIndex + 1),\n };\n};\n\n/** Looks up a message value by full dotted id; first segment = dictionary key. */\nconst lookupMessage = (id: string, locale: LocalesValues): unknown => {\n const { dictionaryKey, path } = splitId(id);\n if (!dictionaryKey) return undefined;\n try {\n const dictionary = getIntlayer(dictionaryKey as DictionaryKeys, locale);\n return navigatePath(dictionary, path);\n } catch {\n return undefined;\n }\n};\n\n/** Maps tagged tokens to React nodes using the provided renderer functions. */\nconst renderRichTokens = (\n tokens: TaggedMessageToken[],\n renderers: Record<string, unknown>\n): ReactNode[] =>\n tokens.map((token, tokenIndex) => {\n if (typeof token === 'string') return token;\n const children = renderRichTokens(token.children, renderers);\n const renderer = renderers[token.tag];\n if (typeof renderer === 'function') {\n return (\n <Fragment key={tokenIndex}>\n {(renderer as RichRenderer)(<>{children}</>)}\n </Fragment>\n );\n }\n return <Fragment key={tokenIndex}>{children}</Fragment>;\n });\n\n/** Partitions values into scalar interpolation params and tag renderers. */\nconst splitRichValues = (\n values: Record<string, unknown>\n): { scalarValues: MessageValues; renderers: Record<string, unknown> } => {\n const scalarValues: MessageValues = {};\n const renderers: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(values)) {\n if (typeof value === 'function') renderers[key] = value;\n else scalarValues[key] = value as MessageValues[string];\n }\n return { scalarValues, renderers };\n};\n\nconst isRichValues = (values: Record<string, unknown>): boolean =>\n Object.values(values).some((value) => typeof value === 'function');\n\n/**\n * Builds an intlayer-backed `IntlShape` object for the given locale.\n *\n * - Translation ids use the first dot-path segment as the dictionary key.\n * - Full ICU MessageFormat syntax is supported via `@intlayer/core/messageFormat`.\n * - Rich text tags (`<b>chunks</b>`) are resolved through render functions in `values`.\n *\n * @param locale - The locale messages are resolved for.\n * @param lookupOverride - Optional message lookup replacing the registry-based\n * id resolution; used by the dictionary-bound `useDictionary` variant.\n */\nexport const createIntlObject = (\n locale: LocalesValues,\n lookupOverride?: (id: string) => unknown\n): IntlShape => {\n const localeString = locale as string;\n\n const formatMessage = (\n descriptor: MessageDescriptor,\n values?: Record<string, unknown>\n ): string | ReactNode[] => {\n const { id = '', defaultMessage } = descriptor;\n const rawValue = lookupOverride\n ? lookupOverride(id)\n : lookupMessage(id, locale);\n const messageTemplate =\n rawValue !== undefined && rawValue !== null\n ? (rawValue as string)\n : typeof defaultMessage === 'string'\n ? defaultMessage\n : id;\n\n if (!values || !isRichValues(values)) {\n return (\n resolveMessage(\n messageTemplate,\n (values ?? {}) as MessageValues,\n locale,\n 'icu'\n ) ?? id\n );\n }\n\n const { scalarValues, renderers } = splitRichValues(values);\n const message =\n resolveMessage(messageTemplate, scalarValues, locale, 'icu') ?? id;\n return renderRichTokens(parseTaggedMessage(message), renderers);\n };\n\n const toDate = (value: Date | number | string): Date =>\n value instanceof Date ? value : new Date(value);\n\n const formatDate = (\n value: string | number | Date | undefined,\n options?: Intl.DateTimeFormatOptions\n ): string => {\n if (value === undefined || value === null) return '';\n return new Intl.DateTimeFormat(localeString, options).format(toDate(value));\n };\n\n const formatNumber = (\n value: number | bigint,\n options?: Intl.NumberFormatOptions\n ): string => new Intl.NumberFormat(localeString, options).format(value);\n\n const formatPlural = (\n value: number,\n options?: Intl.PluralRulesOptions\n ): Intl.LDMLPluralRule =>\n new Intl.PluralRules(localeString, options).select(value);\n\n const formatList = (\n list: Iterable<unknown> | readonly unknown[],\n options?: Intl.ListFormatOptions\n ): string => {\n const strings = Array.from(list).filter(\n (item): item is string => typeof item === 'string'\n );\n return new Intl.ListFormat(localeString, options).format(strings);\n };\n\n const formatListToParts = (\n list: Iterable<unknown> | readonly unknown[],\n options?: Intl.ListFormatOptions\n ): ReturnType<Intl.ListFormat['formatToParts']> => {\n const strings = Array.from(list).filter(\n (item): item is string => typeof item === 'string'\n );\n return new Intl.ListFormat(localeString, options).formatToParts(strings);\n };\n\n const formatDisplayName = (\n value: string,\n options?: Intl.DisplayNamesOptions\n ): string | undefined =>\n new Intl.DisplayNames([localeString], options ?? { type: 'language' }).of(\n value\n );\n\n const formatRelativeTime = (\n value: number,\n unit?: Intl.RelativeTimeFormatUnit,\n options?: Intl.RelativeTimeFormatOptions\n ): string =>\n new Intl.RelativeTimeFormat(localeString, {\n numeric: 'auto',\n ...options,\n }).format(value, unit ?? 'second');\n\n const formatDateTimeRange = (\n from: Date | number,\n to: Date | number,\n options?: Intl.DateTimeFormatOptions\n ): string =>\n new Intl.DateTimeFormat(localeString, options).formatRange(\n toDate(from),\n toDate(to)\n );\n\n const formatDateToParts = (\n value: Parameters<Intl.DateTimeFormat['format']>[0] | string,\n options?: Intl.DateTimeFormatOptions\n ): Intl.DateTimeFormatPart[] =>\n new Intl.DateTimeFormat(localeString, options).formatToParts(\n typeof value === 'string' ? new Date(value) : value\n );\n\n const formatNumberToParts = (\n value: number | bigint,\n options?: Intl.NumberFormatOptions\n ): Intl.NumberFormatPart[] =>\n new Intl.NumberFormat(localeString, options).formatToParts(value);\n\n /** Alias of `formatMessage` — provided for `@formatjs/intl` v4 compatibility. */\n const $t = formatMessage as IntlShape['$t'];\n\n return {\n locale: localeString,\n defaultLocale: localeString,\n messages: {},\n formats: {},\n defaultFormats: {},\n timeZone: undefined,\n textComponent: Fragment,\n wrapRichTextChunksInFragment: false,\n fallbackOnEmptyString: true,\n onError: () => {},\n onWarn: () => {},\n formatters: {} as IntlShape['formatters'],\n formatMessage: formatMessage as IntlShape['formatMessage'],\n $t,\n formatDate,\n formatTime: formatDate,\n formatNumber,\n formatPlural,\n formatList: formatList as IntlShape['formatList'],\n formatListToParts: formatListToParts as IntlShape['formatListToParts'],\n formatDisplayName: formatDisplayName as IntlShape['formatDisplayName'],\n formatRelativeTime,\n formatDateTimeRange,\n formatDateToParts: formatDateToParts as IntlShape['formatDateToParts'],\n formatTimeToParts: formatDateToParts as IntlShape['formatTimeToParts'],\n formatNumberToParts:\n formatNumberToParts as IntlShape['formatNumberToParts'],\n } as unknown as IntlShape;\n};\n"],"mappings":"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"}
|
|
File without changes
|
package/dist/esm/index.mjs
CHANGED
|
@@ -8,5 +8,7 @@ import { InvalidConfigError, MessageFormatError, MissingDataError, MissingTransl
|
|
|
8
8
|
import { defineMessage, defineMessages } from "./defineMessages.mjs";
|
|
9
9
|
import { createIntl, createIntlCache } from "./createIntl.mjs";
|
|
10
10
|
import { FormattedMessage } from "./FormattedMessage.mjs";
|
|
11
|
+
import { useDictionary } from "./useDictionary.mjs";
|
|
12
|
+
import { useDictionaryDynamic } from "./useDictionaryDynamic.mjs";
|
|
11
13
|
|
|
12
|
-
export { FormattedDate, FormattedDateParts, FormattedDateTimeRange, FormattedDisplayName, FormattedList, FormattedListParts, FormattedMessage, FormattedNumber, FormattedNumberParts, FormattedPlural, FormattedRelativeTime, FormattedTime, FormattedTimeParts, IntlContext, IntlProvider, InvalidConfigError, MessageFormatError, MissingDataError, MissingTranslationError, RawIntlProvider, ReactIntlError, ReactIntlErrorCode, UnsupportedFormatterError, createIntl, createIntlCache, defineMessage, defineMessages, useIntl };
|
|
14
|
+
export { FormattedDate, FormattedDateParts, FormattedDateTimeRange, FormattedDisplayName, FormattedList, FormattedListParts, FormattedMessage, FormattedNumber, FormattedNumberParts, FormattedPlural, FormattedRelativeTime, FormattedTime, FormattedTimeParts, IntlContext, IntlProvider, InvalidConfigError, MessageFormatError, MissingDataError, MissingTranslationError, RawIntlProvider, ReactIntlError, ReactIntlErrorCode, UnsupportedFormatterError, createIntl, createIntlCache, defineMessage, defineMessages, useDictionary, useDictionaryDynamic, useIntl };
|
|
@@ -1,46 +1,13 @@
|
|
|
1
1
|
import * as ANSIColors from "@intlayer/config/colors";
|
|
2
2
|
import { colorize, getAppLogger } from "@intlayer/config/logger";
|
|
3
3
|
import { join } from "node:path";
|
|
4
|
-
import {
|
|
4
|
+
import { REACT_INTL_CALLERS } from "@intlayer/config/callers";
|
|
5
5
|
import { getConfiguration } from "@intlayer/config/node";
|
|
6
|
+
import { runOnce } from "@intlayer/engine/utils";
|
|
6
7
|
import { intlayer } from "vite-intlayer";
|
|
7
8
|
|
|
8
9
|
//#region src/plugin/index.ts
|
|
9
10
|
/**
|
|
10
|
-
* Caller configurations for react-intl's two message APIs.
|
|
11
|
-
*
|
|
12
|
-
* react-intl encodes both the dictionary key and the field path in a single
|
|
13
|
-
* dotted id string, so the `path-first-segment` namespace source extracts the
|
|
14
|
-
* first segment as the dictionary key and `translationFunction: 'self'` records
|
|
15
|
-
* the second segment as the consumed field:
|
|
16
|
-
*
|
|
17
|
-
* `'home.title'` → dictionaryKey='home', field='title'
|
|
18
|
-
* `'greeting'` → dictionaryKey='greeting', field='all' (single segment)
|
|
19
|
-
* dynamic id → unresolvable → skipped (all fields kept)
|
|
20
|
-
*
|
|
21
|
-
* Both call sites are tracked:
|
|
22
|
-
* - `intl.formatMessage({ id })` — matched as a method on any object.
|
|
23
|
-
* - `<FormattedMessage id />` — matched as a JSX element (import-gated).
|
|
24
|
-
*
|
|
25
|
-
* The JSX form is mandatory: the prune context is shared across all files, so
|
|
26
|
-
* tracking only `formatMessage` would let a field referenced solely from
|
|
27
|
-
* `<FormattedMessage>` be pruned away whenever the same dictionary is also read
|
|
28
|
-
* through `formatMessage`.
|
|
29
|
-
*/
|
|
30
|
-
const REACT_INTL_COMPAT_CALLERS = [{
|
|
31
|
-
callerName: "formatMessage",
|
|
32
|
-
importSources: ["react-intl", "@intlayer/react-intl"],
|
|
33
|
-
matchAsMethod: true,
|
|
34
|
-
namespace: { from: "path-first-segment" },
|
|
35
|
-
translationFunction: "self"
|
|
36
|
-
}, {
|
|
37
|
-
callerName: "FormattedMessage",
|
|
38
|
-
importSources: ["react-intl", "@intlayer/react-intl"],
|
|
39
|
-
jsxIdAttribute: "id",
|
|
40
|
-
namespace: { from: "path-first-segment" },
|
|
41
|
-
translationFunction: "self"
|
|
42
|
-
}];
|
|
43
|
-
/**
|
|
44
11
|
* A Vite plugin for react-intl compat that wraps vite-intlayer
|
|
45
12
|
* and injects a resolve alias mapping `react-intl` to
|
|
46
13
|
* `@intlayer/react-intl`.
|
|
@@ -63,7 +30,7 @@ const reactIntlVitePlugin = (options) => {
|
|
|
63
30
|
}, { cacheTimeoutMs: 1e3 * 60 * 60 });
|
|
64
31
|
const basePlugins = intlayer({
|
|
65
32
|
...options,
|
|
66
|
-
compatCallers: [...options?.compatCallers ?? [], ...
|
|
33
|
+
compatCallers: [...options?.compatCallers ?? [], ...REACT_INTL_CALLERS]
|
|
67
34
|
});
|
|
68
35
|
const compatPlugin = {
|
|
69
36
|
name: "vite-react-intl-compat-plugin",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.mjs","names":[],"sources":["../../../src/plugin/index.ts"],"sourcesContent":["import { join } from 'node:path';\nimport {
|
|
1
|
+
{"version":3,"file":"index.mjs","names":[],"sources":["../../../src/plugin/index.ts"],"sourcesContent":["import { join } from 'node:path';\nimport { REACT_INTL_CALLERS } from '@intlayer/config/callers';\nimport * as ANSIColors from '@intlayer/config/colors';\nimport { colorize, getAppLogger } from '@intlayer/config/logger';\nimport { getConfiguration } from '@intlayer/config/node';\nimport { runOnce } from '@intlayer/engine/utils';\nimport type { PluginOption } from 'vite';\nimport { intlayer } from 'vite-intlayer';\n\n/**\n * A Vite plugin for react-intl compat that wraps vite-intlayer\n * and injects a resolve alias mapping `react-intl` to\n * `@intlayer/react-intl`.\n *\n * @example\n * ```ts\n * // vite.config.ts\n * import reactIntlVitePlugin from '@intlayer/react-intl/plugin';\n *\n * export default defineConfig({\n * plugins: [reactIntlVitePlugin()],\n * });\n * ```\n */\nexport const reactIntlVitePlugin = (\n options?: Parameters<typeof intlayer>[0]\n): PluginOption[] => {\n const intlayerConfig = getConfiguration();\n const appLogger = getAppLogger(intlayerConfig);\n\n runOnce(\n join(\n intlayerConfig.system.baseDir,\n '.intlayer',\n 'cache',\n 'intlayer-issues-invitation.lock'\n ),\n () => {\n appLogger([\n colorize(\n 'Please report any issues you met on GitHub:',\n ANSIColors.GREY\n ),\n colorize(\n 'https://github.com/aymericzip/intlayer/issues',\n ANSIColors.GREY_LIGHT\n ),\n ]);\n },\n {\n cacheTimeoutMs: 1000 * 60 * 60, // 1 hour\n }\n );\n\n const basePlugins = intlayer({\n ...options,\n compatCallers: [...(options?.compatCallers ?? []), ...REACT_INTL_CALLERS],\n });\n\n const compatPlugin: PluginOption = {\n name: 'vite-react-intl-compat-plugin',\n config: () => ({\n resolve: {\n alias: {\n 'react-intl': '@intlayer/react-intl',\n },\n },\n }),\n };\n\n return [\n ...(Array.isArray(basePlugins) ? basePlugins : [basePlugins]),\n compatPlugin,\n ];\n};\n\nexport default reactIntlVitePlugin;\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;AAwBA,MAAa,uBACX,YACmB;CACnB,MAAM,iBAAiB,iBAAiB;CACxC,MAAM,YAAY,aAAa,cAAc;CAE7C,QACE,KACE,eAAe,OAAO,SACtB,aACA,SACA,iCACF,SACM;EACJ,UAAU,CACR,SACE,+CACA,WAAW,IACb,GACA,SACE,iDACA,WAAW,UACb,CACF,CAAC;CACH,GACA,EACE,gBAAgB,MAAO,KAAK,GAC9B,CACF;CAEA,MAAM,cAAc,SAAS;EAC3B,GAAG;EACH,eAAe,CAAC,GAAI,SAAS,iBAAiB,CAAC,GAAI,GAAG,kBAAkB;CAC1E,CAAC;CAED,MAAM,eAA6B;EACjC,MAAM;EACN,eAAe,EACb,SAAS,EACP,OAAO,EACL,cAAc,uBAChB,EACF,EACF;CACF;CAEA,OAAO,CACL,GAAI,MAAM,QAAQ,WAAW,IAAI,cAAc,CAAC,WAAW,GAC3D,YACF;AACF"}
|
|
File without changes
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import { createIntlObject } from "./createIntlObject.mjs";
|
|
4
|
+
import { useMemo } from "react";
|
|
5
|
+
import { useDictionary as useDictionary$1, useLocale } from "react-intlayer";
|
|
6
|
+
import { navigatePath } from "@intlayer/core/messageFormat";
|
|
7
|
+
|
|
8
|
+
//#region src/useDictionary.ts
|
|
9
|
+
/**
|
|
10
|
+
* Builds the id lookup of a dictionary-bound intl object.
|
|
11
|
+
*
|
|
12
|
+
* react-intl ids encode the dictionary key as their first dot-segment
|
|
13
|
+
* (`'home.title'` → dictionary `home`, field `title`). When the content is
|
|
14
|
+
* supplied directly, the leading `<dictionaryKey>.` is stripped so both the
|
|
15
|
+
* absolute (`'home.title'`) and relative (`'title'`) forms resolve.
|
|
16
|
+
*/
|
|
17
|
+
const createDictionaryLookup = (dictionaryKey, content) => (id) => {
|
|
18
|
+
return navigatePath(content, id.startsWith(`${dictionaryKey}.`) ? id.slice(dictionaryKey.length + 1) : id === dictionaryKey ? "" : id);
|
|
19
|
+
};
|
|
20
|
+
/**
|
|
21
|
+
* Dictionary-accepting variant of `useIntl`.
|
|
22
|
+
*
|
|
23
|
+
* Returns an `IntlShape` whose `formatMessage` resolves ids inside the
|
|
24
|
+
* supplied dictionary instead of the runtime registry, enabling tree-shaking
|
|
25
|
+
* of unused locale content. All `Intl`-backed formatters (`formatNumber`,
|
|
26
|
+
* `formatDate`, …) behave exactly like `useIntl()`.
|
|
27
|
+
*
|
|
28
|
+
* @example
|
|
29
|
+
* import _abc from '.intlayer/dictionaries/home.json' with { type: 'json' };
|
|
30
|
+
* const intl = useDictionary(_abc);
|
|
31
|
+
* intl.formatMessage({ id: 'home.title' }); // or { id: 'title' } — both typed
|
|
32
|
+
*/
|
|
33
|
+
const useDictionary = (dictionary) => {
|
|
34
|
+
const content = useDictionary$1(dictionary);
|
|
35
|
+
const { locale } = useLocale();
|
|
36
|
+
return useMemo(() => createIntlObject(locale, createDictionaryLookup(dictionary.key, content)), [
|
|
37
|
+
locale,
|
|
38
|
+
dictionary.key,
|
|
39
|
+
content
|
|
40
|
+
]);
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
//#endregion
|
|
44
|
+
export { createDictionaryLookup, useDictionary };
|
|
45
|
+
//# sourceMappingURL=useDictionary.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useDictionary.mjs","names":["useDictionaryBase"],"sources":["../../src/useDictionary.ts"],"sourcesContent":["'use client';\n\nimport { navigatePath } from '@intlayer/core/messageFormat';\nimport type { Dictionary } from '@intlayer/types/dictionary';\nimport type {\n DictionaryKeys,\n LocalesValues,\n} from '@intlayer/types/module_augmentation';\nimport { useMemo } from 'react';\nimport { useDictionary as useDictionaryBase, useLocale } from 'react-intlayer';\nimport { createIntlObject } from './createIntlObject';\nimport type { DictionaryIntlShape } from './dictionaryIntlShape';\n\n/**\n * Builds the id lookup of a dictionary-bound intl object.\n *\n * react-intl ids encode the dictionary key as their first dot-segment\n * (`'home.title'` → dictionary `home`, field `title`). When the content is\n * supplied directly, the leading `<dictionaryKey>.` is stripped so both the\n * absolute (`'home.title'`) and relative (`'title'`) forms resolve.\n */\nexport const createDictionaryLookup =\n (dictionaryKey: string, content: unknown) =>\n (id: string): unknown => {\n const relativePath = id.startsWith(`${dictionaryKey}.`)\n ? id.slice(dictionaryKey.length + 1)\n : id === dictionaryKey\n ? ''\n : id;\n return navigatePath(content, relativePath);\n };\n\n/**\n * Dictionary-accepting variant of `useIntl`.\n *\n * Returns an `IntlShape` whose `formatMessage` resolves ids inside the\n * supplied dictionary instead of the runtime registry, enabling tree-shaking\n * of unused locale content. All `Intl`-backed formatters (`formatNumber`,\n * `formatDate`, …) behave exactly like `useIntl()`.\n *\n * @example\n * import _abc from '.intlayer/dictionaries/home.json' with { type: 'json' };\n * const intl = useDictionary(_abc);\n * intl.formatMessage({ id: 'home.title' }); // or { id: 'title' } — both typed\n */\nexport const useDictionary = <T extends Dictionary>(\n dictionary: T\n): DictionaryIntlShape<T['key'] & DictionaryKeys> => {\n const content = useDictionaryBase(dictionary);\n const { locale } = useLocale();\n\n return useMemo(\n () =>\n createIntlObject(\n locale as LocalesValues,\n createDictionaryLookup(dictionary.key, content)\n ) as DictionaryIntlShape<T['key'] & DictionaryKeys>,\n [locale, dictionary.key, content]\n );\n};\n"],"mappings":";;;;;;;;;;;;;;;;AAqBA,MAAa,0BACV,eAAuB,aACvB,OAAwB;CAMvB,OAAO,aAAa,SALC,GAAG,WAAW,GAAG,cAAc,EAAE,IAClD,GAAG,MAAM,cAAc,SAAS,CAAC,IACjC,OAAO,gBACL,KACA,EACmC;AAC3C;;;;;;;;;;;;;;AAeF,MAAa,iBACX,eACmD;CACnD,MAAM,UAAUA,gBAAkB,UAAU;CAC5C,MAAM,EAAE,WAAW,UAAU;CAE7B,OAAO,cAEH,iBACE,QACA,uBAAuB,WAAW,KAAK,OAAO,CAChD,GACF;EAAC;EAAQ,WAAW;EAAK;CAAO,CAClC;AACF"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import { createIntlObject } from "./createIntlObject.mjs";
|
|
4
|
+
import { createDictionaryLookup } from "./useDictionary.mjs";
|
|
5
|
+
import { useMemo } from "react";
|
|
6
|
+
import { useDictionaryDynamic as useDictionaryDynamic$1, useLocale } from "react-intlayer";
|
|
7
|
+
|
|
8
|
+
//#region src/useDictionaryDynamic.ts
|
|
9
|
+
/**
|
|
10
|
+
* Dynamic dictionary-accepting variant of `useIntl`.
|
|
11
|
+
*
|
|
12
|
+
* Counterpart to {@link useDictionary} for dictionaries imported lazily per
|
|
13
|
+
* locale. Used internally by the build-time optimization.
|
|
14
|
+
*/
|
|
15
|
+
const useDictionaryDynamic = (dictionaryPromise, key) => {
|
|
16
|
+
const content = useDictionaryDynamic$1(dictionaryPromise, key);
|
|
17
|
+
const { locale } = useLocale();
|
|
18
|
+
return useMemo(() => createIntlObject(locale, createDictionaryLookup(key, content)), [
|
|
19
|
+
locale,
|
|
20
|
+
key,
|
|
21
|
+
content
|
|
22
|
+
]);
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
//#endregion
|
|
26
|
+
export { useDictionaryDynamic };
|
|
27
|
+
//# sourceMappingURL=useDictionaryDynamic.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useDictionaryDynamic.mjs","names":["useDictionaryDynamicBase"],"sources":["../../src/useDictionaryDynamic.ts"],"sourcesContent":["'use client';\n\nimport type { Dictionary } from '@intlayer/types/dictionary';\nimport type {\n DictionaryKeys,\n LocalesValues,\n StrictModeLocaleMap,\n} from '@intlayer/types/module_augmentation';\nimport { useMemo } from 'react';\nimport {\n useDictionaryDynamic as useDictionaryDynamicBase,\n useLocale,\n} from 'react-intlayer';\nimport { createIntlObject } from './createIntlObject';\nimport type { DictionaryIntlShape } from './dictionaryIntlShape';\nimport { createDictionaryLookup } from './useDictionary';\n\n/**\n * Dynamic dictionary-accepting variant of `useIntl`.\n *\n * Counterpart to {@link useDictionary} for dictionaries imported lazily per\n * locale. Used internally by the build-time optimization.\n */\nexport const useDictionaryDynamic = <\n const T extends Dictionary,\n const K extends DictionaryKeys,\n>(\n dictionaryPromise: StrictModeLocaleMap<() => Promise<T>>,\n key: K\n): DictionaryIntlShape<K> => {\n const content = useDictionaryDynamicBase<T, K>(dictionaryPromise, key);\n const { locale } = useLocale();\n\n return useMemo(\n () =>\n createIntlObject(\n locale as LocalesValues,\n createDictionaryLookup(key, content)\n ) as DictionaryIntlShape<K>,\n [locale, key, content]\n );\n};\n"],"mappings":";;;;;;;;;;;;;;AAuBA,MAAa,wBAIX,mBACA,QAC2B;CAC3B,MAAM,UAAUA,uBAA+B,mBAAmB,GAAG;CACrE,MAAM,EAAE,WAAW,UAAU;CAE7B,OAAO,cAEH,iBACE,QACA,uBAAuB,KAAK,OAAO,CACrC,GACF;EAAC;EAAQ;EAAK;CAAO,CACvB;AACF"}
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { FormattedDate as FormattedDate$1, FormattedDateParts as FormattedDateParts$1, FormattedDateTimeRange as FormattedDateTimeRange$1, FormattedDisplayName as FormattedDisplayName$1, FormattedList as FormattedList$1, FormattedListParts as FormattedListParts$1, FormattedNumber as FormattedNumber$1, FormattedNumberParts as FormattedNumberParts$1, FormattedPlural as FormattedPlural$1, FormattedRelativeTime as FormattedRelativeTime$1, FormattedTime as FormattedTime$1, FormattedTimeParts as FormattedTimeParts$1 } from "react-intl";
|
|
2
|
-
|
|
3
2
|
//#region src/FormattedComponents.d.ts
|
|
4
3
|
/**
|
|
5
4
|
* Drop-in for react-intl's `<FormattedDate>`.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FormattedComponents.d.ts","names":[],"sources":["../../src/FormattedComponents.tsx"],"mappings":";;;;;
|
|
1
|
+
{"version":3,"file":"FormattedComponents.d.ts","names":[],"sources":["../../src/FormattedComponents.tsx"],"mappings":";;;;;;cA8Ba,sBAAsB;;;;;cAkBtB,sBAAsB;;;;;cAkBtB,wBAAwB;;;;;cAkBxB,sBAAsB;;;;;cAatB,6BAA6B;;;;;;cAiB7B,8BAA8B;;;;;cAmB9B,wBAAwB;;;;;cAmCxB,+BAA+B;;;;;cAkB/B,2BAA2B;;;;;cAkB3B,2BAA2B;;;;;cAkB3B,6BAA6B;;;;;cAe7B,2BAA2B"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FormattedMessage.d.ts","names":[],"sources":["../../src/FormattedMessage.tsx"],"mappings":"
|
|
1
|
+
{"version":3,"file":"FormattedMessage.d.ts","names":[],"sources":["../../src/FormattedMessage.tsx"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;cA2Ba,yBAAyB"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"IntlProvider.d.ts","names":[],"sources":["../../src/IntlProvider.tsx"],"mappings":"
|
|
1
|
+
{"version":3,"file":"IntlProvider.d.ts","names":[],"sources":["../../src/IntlProvider.tsx"],"mappings":";;;;;;;;;;;cAqBa,qBAAqB"}
|
package/dist/types/context.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"context.d.ts","names":[],"sources":["../../src/context.tsx"],"mappings":"
|
|
1
|
+
{"version":3,"file":"context.d.ts","names":[],"sources":["../../src/context.tsx"],"mappings":";;;;;;cAOa,6BAAW,QAAA;;cAKX,iCAAe,SAAA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"createIntl.d.ts","names":[],"sources":["../../src/createIntl.ts"],"mappings":"
|
|
1
|
+
{"version":3,"file":"createIntl.d.ts","names":[],"sources":["../../src/createIntl.ts"],"mappings":";;;;;;;;;;;;cAoBa,wBAAwB;;;;;;;;;;;;;;;;;;cA4BxB,mBAAmB"}
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { IntlShape } from "react-intl";
|
|
2
2
|
import { LocalesValues } from "@intlayer/types/module_augmentation";
|
|
3
|
-
|
|
4
3
|
//#region src/createIntlObject.d.ts
|
|
5
4
|
/**
|
|
6
5
|
* Builds an intlayer-backed `IntlShape` object for the given locale.
|
|
@@ -8,8 +7,12 @@ import { LocalesValues } from "@intlayer/types/module_augmentation";
|
|
|
8
7
|
* - Translation ids use the first dot-path segment as the dictionary key.
|
|
9
8
|
* - Full ICU MessageFormat syntax is supported via `@intlayer/core/messageFormat`.
|
|
10
9
|
* - Rich text tags (`<b>chunks</b>`) are resolved through render functions in `values`.
|
|
10
|
+
*
|
|
11
|
+
* @param locale - The locale messages are resolved for.
|
|
12
|
+
* @param lookupOverride - Optional message lookup replacing the registry-based
|
|
13
|
+
* id resolution; used by the dictionary-bound `useDictionary` variant.
|
|
11
14
|
*/
|
|
12
|
-
declare const createIntlObject: (locale: LocalesValues) => IntlShape;
|
|
15
|
+
declare const createIntlObject: (locale: LocalesValues, lookupOverride?: (id: string) => unknown) => IntlShape;
|
|
13
16
|
//#endregion
|
|
14
17
|
export { createIntlObject };
|
|
15
18
|
//# sourceMappingURL=createIntlObject.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"createIntlObject.d.ts","names":[],"sources":["../../src/createIntlObject.tsx"],"mappings":"
|
|
1
|
+
{"version":3,"file":"createIntlObject.d.ts","names":[],"sources":["../../src/createIntlObject.tsx"],"mappings":";;;;;;;;;;;;;;cAqFa,mBAAgB,QACnB,eAAa,kBACH,2BACjB"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"defineMessages.d.ts","names":[],"sources":["../../src/defineMessages.ts"],"mappings":";;;;;
|
|
1
|
+
{"version":3,"file":"defineMessages.d.ts","names":[],"sources":["../../src/defineMessages.ts"],"mappings":";;;;;;;;cAWa,uBAAuB;;;;;cAMvB,sBAAsB"}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { IntlShape, MessageDescriptor, PrimitiveType } from "react-intl";
|
|
2
|
+
import { DictionaryKeys } from "@intlayer/types/module_augmentation";
|
|
3
|
+
import { GetNestingResult } from "@intlayer/core/interpreter";
|
|
4
|
+
import { ValidDotPathsFor } from "@intlayer/core/transpiler";
|
|
5
|
+
import { ReactNode } from "react";
|
|
6
|
+
//#region src/dictionaryIntlShape.d.ts
|
|
7
|
+
/**
|
|
8
|
+
* The interpreter-resolved content type at dot-path `P` of dictionary `N` —
|
|
9
|
+
* the same type strength as the base `useIntlayer` hook.
|
|
10
|
+
*/
|
|
11
|
+
type ContentAtPath<N extends DictionaryKeys, P> = GetNestingResult<N, P>;
|
|
12
|
+
/**
|
|
13
|
+
* The value returned by `formatMessage` for the path `P` of dictionary `N`:
|
|
14
|
+
* string literals declared in the dictionary keep their literal type, every
|
|
15
|
+
* other node resolves to `string` at runtime.
|
|
16
|
+
*/
|
|
17
|
+
type TranslatedValue<N extends DictionaryKeys, P> = ContentAtPath<N, P> extends string ? ContentAtPath<N, P> : string;
|
|
18
|
+
/**
|
|
19
|
+
* Ids accepted by a dictionary-bound intl object: the dictionary's dot-paths,
|
|
20
|
+
* either relative (`'title'`) or absolute (`'home.title'`).
|
|
21
|
+
*/
|
|
22
|
+
type DictionaryMessageIds<N extends DictionaryKeys> = ValidDotPathsFor<N> | `${N & string}.${ValidDotPathsFor<N> & string}`;
|
|
23
|
+
/**
|
|
24
|
+
* Resolves the translated value type for an id: the absolute form strips the
|
|
25
|
+
* leading `<dictionaryKey>.` first, matching the runtime lookup.
|
|
26
|
+
*/
|
|
27
|
+
type MessageValueForId<N extends DictionaryKeys, Id extends string> = Id extends `${N & string}.${infer RelativePath}` ? TranslatedValue<N, RelativePath> : TranslatedValue<N, Id>;
|
|
28
|
+
/**
|
|
29
|
+
* `formatMessage` bound to dictionary `N`: ids are validated against the
|
|
30
|
+
* dictionary's dot-paths and the return type is resolved from the content at
|
|
31
|
+
* that path. With rich-text render functions in `values`, React nodes are
|
|
32
|
+
* returned.
|
|
33
|
+
*/
|
|
34
|
+
type TypedFormatMessage<N extends DictionaryKeys> = {
|
|
35
|
+
<Id extends DictionaryMessageIds<N> & string>(descriptor: Omit<MessageDescriptor, 'id'> & {
|
|
36
|
+
id: Id;
|
|
37
|
+
}, values?: Record<string, PrimitiveType>): MessageValueForId<N, Id>;
|
|
38
|
+
<Id extends DictionaryMessageIds<N> & string>(descriptor: Omit<MessageDescriptor, 'id'> & {
|
|
39
|
+
id: Id;
|
|
40
|
+
}, values?: Record<string, ReactNode | PrimitiveType | ((chunks: ReactNode) => ReactNode)>): string | ReactNode[];
|
|
41
|
+
};
|
|
42
|
+
/**
|
|
43
|
+
* `IntlShape` whose `formatMessage` / `$t` are typed against the dictionary
|
|
44
|
+
* `N`. Returned by the dictionary-bound `useDictionary` /
|
|
45
|
+
* `useDictionaryDynamic` variants.
|
|
46
|
+
*/
|
|
47
|
+
type DictionaryIntlShape<N extends DictionaryKeys> = Omit<IntlShape, 'formatMessage' | '$t'> & {
|
|
48
|
+
formatMessage: TypedFormatMessage<N>;
|
|
49
|
+
$t: TypedFormatMessage<N>;
|
|
50
|
+
};
|
|
51
|
+
//#endregion
|
|
52
|
+
export { DictionaryIntlShape, DictionaryMessageIds, MessageValueForId, TypedFormatMessage };
|
|
53
|
+
//# sourceMappingURL=dictionaryIntlShape.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dictionaryIntlShape.d.ts","names":[],"sources":["../../src/dictionaryIntlShape.ts"],"mappings":";;;;;;;;;;KAUK,cAAc,UAAU,gBAAgB,KAAK,iBAAiB,GAAG;;;;;;KAOjE,gBAAgB,UAAU,gBAAgB,KAC7C,cAAc,GAAG,oBAAoB,cAAc,GAAG;;;;;KAM5C,qBAAqB,UAAU,kBACvC,iBAAiB,QACd,cAAc,iBAAiB;;;;;KAM1B,kBACV,UAAU,gBACV,qBACE,cAAc,oBAAoB,iBAClC,gBAAgB,GAAG,gBACnB,gBAAgB,GAAG;;;;;;;KAQX,mBAAmB,UAAU;GACtC,WAAW,qBAAqB,aAC/B,YAAY,KAAK;IAA6B,IAAI;KAClD,SAAS,eAAe,iBACvB,kBAAkB,GAAG;GACvB,WAAW,qBAAqB,aAC/B,YAAY,KAAK;IAA6B,IAAI;KAClD,SAAS,eAEP,YAAY,kBAAkB,QAAQ,cAAc,uBAE5C;;;;;;;KAQF,oBAAoB,UAAU,kBAAkB,KAC1D;EAGA,eAAe,mBAAmB;EAClC,IAAI,mBAAmB"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"errors.d.ts","names":[],"sources":["../../src/errors.ts"],"mappings":"
|
|
1
|
+
{"version":3,"file":"errors.d.ts","names":[],"sources":["../../src/errors.ts"],"mappings":";;;;;;;aAMY;EACV;EACA;EACA;EACA;EACA;;;;;;;cAQW,uBAAuB;WAClB,MAAM;EAEtB,YAAY,MAAM,oBAAoB;;;;;cAU3B,2BAA2B;EACtC,YAAY;;;;;cASD,2BAA2B;EACtC,YAAY;;;;;cASD,yBAAyB;EACpC,YAAY;;;;;cASD,gCAAgC;EAC3C,YAAY;;;;;cASD,kCAAkC;EAC7C,YAAY"}
|
package/dist/types/index.d.ts
CHANGED
|
@@ -4,7 +4,11 @@ import { IntlProvider } from "./IntlProvider.js";
|
|
|
4
4
|
import { IntlContext, RawIntlProvider } from "./context.js";
|
|
5
5
|
import { createIntl, createIntlCache } from "./createIntl.js";
|
|
6
6
|
import { defineMessage, defineMessages } from "./defineMessages.js";
|
|
7
|
+
import { DictionaryIntlShape, DictionaryMessageIds, MessageValueForId, TypedFormatMessage } from "./dictionaryIntlShape.js";
|
|
7
8
|
import { InvalidConfigError, MessageFormatError, MissingDataError, MissingTranslationError, ReactIntlError, ReactIntlErrorCode, UnsupportedFormatterError } from "./errors.js";
|
|
9
|
+
import { RootMessageIds } from "./typedMessageIds.js";
|
|
10
|
+
import { useDictionary } from "./useDictionary.js";
|
|
11
|
+
import { useDictionaryDynamic } from "./useDictionaryDynamic.js";
|
|
8
12
|
import { useIntl } from "./useIntl.js";
|
|
9
13
|
import { CustomFormats, FormatDateOptions, FormatDisplayNameOptions, FormatListOptions, FormatNumberOptions, FormatPluralOptions, FormatRelativeTimeOptions, Formatters, IntlCache, IntlConfig, IntlFormatters, IntlShape, MessageDescriptor, MessageFormatElement, PrimitiveType, ResolvedIntlConfig } from "react-intl";
|
|
10
|
-
export { type CustomFormats, type FormatDateOptions, type FormatDisplayNameOptions, type FormatListOptions, type FormatNumberOptions, type FormatPluralOptions, type FormatRelativeTimeOptions, FormattedDate, FormattedDateParts, FormattedDateTimeRange, FormattedDisplayName, FormattedList, FormattedListParts, FormattedMessage, FormattedNumber, FormattedNumberParts, FormattedPlural, FormattedRelativeTime, FormattedTime, FormattedTimeParts, type Formatters, type IntlCache, type IntlConfig, IntlContext, type IntlFormatters, IntlProvider, type IntlShape, InvalidConfigError, type MessageDescriptor, type MessageFormatElement, MessageFormatError, MissingDataError, MissingTranslationError, type PrimitiveType, RawIntlProvider, ReactIntlError, ReactIntlErrorCode, type ResolvedIntlConfig, UnsupportedFormatterError, createIntl, createIntlCache, defineMessage, defineMessages, useIntl };
|
|
14
|
+
export { type CustomFormats, type DictionaryIntlShape, type DictionaryMessageIds, type FormatDateOptions, type FormatDisplayNameOptions, type FormatListOptions, type FormatNumberOptions, type FormatPluralOptions, type FormatRelativeTimeOptions, FormattedDate, FormattedDateParts, FormattedDateTimeRange, FormattedDisplayName, FormattedList, FormattedListParts, FormattedMessage, FormattedNumber, FormattedNumberParts, FormattedPlural, FormattedRelativeTime, FormattedTime, FormattedTimeParts, type Formatters, type IntlCache, type IntlConfig, IntlContext, type IntlFormatters, IntlProvider, type IntlShape, InvalidConfigError, type MessageDescriptor, type MessageFormatElement, MessageFormatError, type MessageValueForId, MissingDataError, MissingTranslationError, type PrimitiveType, RawIntlProvider, ReactIntlError, ReactIntlErrorCode, type ResolvedIntlConfig, type RootMessageIds, type TypedFormatMessage, UnsupportedFormatterError, createIntl, createIntlCache, defineMessage, defineMessages, useDictionary, useDictionaryDynamic, useIntl };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","names":[],"sources":["../../../src/plugin/index.ts"],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.d.ts","names":[],"sources":["../../../src/plugin/index.ts"],"mappings":";;;;;;;;;;;;;;;;;;cAwBa,sBAAmB,UACpB,kBAAkB,iBAC3B"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { DictionaryKeys } from "@intlayer/types/module_augmentation";
|
|
2
|
+
import { ValidDotPathsFor } from "@intlayer/core/transpiler";
|
|
3
|
+
//#region src/typedMessageIds.d.ts
|
|
4
|
+
/**
|
|
5
|
+
* Every valid react-intl message id: `<dictionaryKey>.<dotPath>`, where the
|
|
6
|
+
* first segment designates the intlayer dictionary. Falls back to `string`
|
|
7
|
+
* when no dictionary registry is declared (e.g. before the first build).
|
|
8
|
+
*/
|
|
9
|
+
type RootMessageIds = string extends DictionaryKeys ? string : { [K in DictionaryKeys]: `${K & string}.${ValidDotPathsFor<K> & string}`; }[DictionaryKeys];
|
|
10
|
+
declare global {
|
|
11
|
+
namespace FormatjsIntl {
|
|
12
|
+
interface Message {
|
|
13
|
+
/**
|
|
14
|
+
* Types every react-intl message id (`formatMessage`,
|
|
15
|
+
* `<FormattedMessage>`, `defineMessages`, …) against the intlayer
|
|
16
|
+
* dictionary registry — the same strength as the base `useIntlayer`
|
|
17
|
+
* hook.
|
|
18
|
+
*/
|
|
19
|
+
ids: RootMessageIds;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
//#endregion
|
|
24
|
+
export { RootMessageIds };
|
|
25
|
+
//# sourceMappingURL=typedMessageIds.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"typedMessageIds.d.ts","names":[],"sources":["../../src/typedMessageIds.ts"],"mappings":";;;;;;;;KAQY,gCAAgC,6BAGrC,KAAK,oBAAoB,cAAc,iBAAiB,iBACzD;QAEE;YACI;cACE;;;;;;;MAOR,KAAK"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { DictionaryIntlShape } from "./dictionaryIntlShape.js";
|
|
2
|
+
import { DictionaryKeys } from "@intlayer/types/module_augmentation";
|
|
3
|
+
import { Dictionary } from "@intlayer/types/dictionary";
|
|
4
|
+
//#region src/useDictionary.d.ts
|
|
5
|
+
/**
|
|
6
|
+
* Builds the id lookup of a dictionary-bound intl object.
|
|
7
|
+
*
|
|
8
|
+
* react-intl ids encode the dictionary key as their first dot-segment
|
|
9
|
+
* (`'home.title'` → dictionary `home`, field `title`). When the content is
|
|
10
|
+
* supplied directly, the leading `<dictionaryKey>.` is stripped so both the
|
|
11
|
+
* absolute (`'home.title'`) and relative (`'title'`) forms resolve.
|
|
12
|
+
*/
|
|
13
|
+
declare const createDictionaryLookup: (dictionaryKey: string, content: unknown) => (id: string) => unknown;
|
|
14
|
+
/**
|
|
15
|
+
* Dictionary-accepting variant of `useIntl`.
|
|
16
|
+
*
|
|
17
|
+
* Returns an `IntlShape` whose `formatMessage` resolves ids inside the
|
|
18
|
+
* supplied dictionary instead of the runtime registry, enabling tree-shaking
|
|
19
|
+
* of unused locale content. All `Intl`-backed formatters (`formatNumber`,
|
|
20
|
+
* `formatDate`, …) behave exactly like `useIntl()`.
|
|
21
|
+
*
|
|
22
|
+
* @example
|
|
23
|
+
* import _abc from '.intlayer/dictionaries/home.json' with { type: 'json' };
|
|
24
|
+
* const intl = useDictionary(_abc);
|
|
25
|
+
* intl.formatMessage({ id: 'home.title' }); // or { id: 'title' } — both typed
|
|
26
|
+
*/
|
|
27
|
+
declare const useDictionary: <T extends Dictionary>(dictionary: T) => DictionaryIntlShape<T['key'] & DictionaryKeys>;
|
|
28
|
+
//#endregion
|
|
29
|
+
export { createDictionaryLookup, useDictionary };
|
|
30
|
+
//# sourceMappingURL=useDictionary.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useDictionary.d.ts","names":[],"sources":["../../src/useDictionary.ts"],"mappings":";;;;;;;;;;;;cAqBa,yBAAsB,uBACX,sBAAkB;;;;;;;;;;;;;;cAuB7B,gBAAiB,UAAU,YAAU,YACpC,MACX,oBAAoB,WAAW"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { DictionaryIntlShape } from "./dictionaryIntlShape.js";
|
|
2
|
+
import { DictionaryKeys, StrictModeLocaleMap } from "@intlayer/types/module_augmentation";
|
|
3
|
+
import { Dictionary } from "@intlayer/types/dictionary";
|
|
4
|
+
//#region src/useDictionaryDynamic.d.ts
|
|
5
|
+
/**
|
|
6
|
+
* Dynamic dictionary-accepting variant of `useIntl`.
|
|
7
|
+
*
|
|
8
|
+
* Counterpart to {@link useDictionary} for dictionaries imported lazily per
|
|
9
|
+
* locale. Used internally by the build-time optimization.
|
|
10
|
+
*/
|
|
11
|
+
declare const useDictionaryDynamic: <const T extends Dictionary, const K extends DictionaryKeys>(dictionaryPromise: StrictModeLocaleMap<() => Promise<T>>, key: K) => DictionaryIntlShape<K>;
|
|
12
|
+
//#endregion
|
|
13
|
+
export { useDictionaryDynamic };
|
|
14
|
+
//# sourceMappingURL=useDictionaryDynamic.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useDictionaryDynamic.d.ts","names":[],"sources":["../../src/useDictionaryDynamic.ts"],"mappings":";;;;;;;;;;cAuBa,6BACL,UAAU,kBACV,UAAU,gBAAc,mBAEX,0BAA0B,QAAQ,KAAG,KACnD,MACJ,oBAAoB"}
|
package/dist/types/useIntl.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useIntl.d.ts","names":[],"sources":["../../src/useIntl.ts"],"mappings":"
|
|
1
|
+
{"version":3,"file":"useIntl.d.ts","names":[],"sources":["../../src/useIntl.ts"],"mappings":";;;;;;;;;;;;;;;;cAuBa,gBAAgB"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@intlayer/react-intl",
|
|
3
|
-
"version": "9.0.0-canary.
|
|
3
|
+
"version": "9.0.0-canary.21",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "react-intl API adapter for intlayer — drop-in compatibility layer",
|
|
6
6
|
"keywords": [
|
|
@@ -34,17 +34,15 @@
|
|
|
34
34
|
"exports": {
|
|
35
35
|
".": {
|
|
36
36
|
"types": "./dist/types/index.d.ts",
|
|
37
|
-
"require": "./dist/cjs/index.cjs",
|
|
38
37
|
"import": "./dist/esm/index.mjs"
|
|
39
38
|
},
|
|
40
39
|
"./plugin": {
|
|
41
40
|
"types": "./dist/types/plugin/index.d.ts",
|
|
42
|
-
"require": "./dist/cjs/plugin/index.cjs",
|
|
43
41
|
"import": "./dist/esm/plugin/index.mjs"
|
|
44
42
|
},
|
|
45
43
|
"./package.json": "./package.json"
|
|
46
44
|
},
|
|
47
|
-
"main": "dist/
|
|
45
|
+
"main": "dist/esm/index.mjs",
|
|
48
46
|
"module": "dist/esm/index.mjs",
|
|
49
47
|
"types": "dist/types/index.d.ts",
|
|
50
48
|
"typesVersions": {
|
|
@@ -76,26 +74,26 @@
|
|
|
76
74
|
"typecheck": "tsc --noEmit --project tsconfig.types.json"
|
|
77
75
|
},
|
|
78
76
|
"dependencies": {
|
|
79
|
-
"@intlayer/
|
|
80
|
-
"@intlayer/
|
|
81
|
-
"@intlayer/
|
|
82
|
-
"@intlayer/
|
|
83
|
-
"@intlayer/types": "9.0.0-canary.
|
|
84
|
-
"react-intlayer": "9.0.0-canary.
|
|
85
|
-
"vite-intlayer": "9.0.0-canary.
|
|
77
|
+
"@intlayer/config": "9.0.0-canary.21",
|
|
78
|
+
"@intlayer/core": "9.0.0-canary.21",
|
|
79
|
+
"@intlayer/dictionaries-entry": "9.0.0-canary.21",
|
|
80
|
+
"@intlayer/engine": "9.0.0-canary.21",
|
|
81
|
+
"@intlayer/types": "9.0.0-canary.21",
|
|
82
|
+
"react-intlayer": "9.0.0-canary.21",
|
|
83
|
+
"vite-intlayer": "9.0.0-canary.21"
|
|
86
84
|
},
|
|
87
85
|
"devDependencies": {
|
|
88
|
-
"@types/node": "
|
|
86
|
+
"@types/node": "26.1.1",
|
|
89
87
|
"@types/react": "19.1.8",
|
|
90
88
|
"@utils/ts-config": "1.0.4",
|
|
91
89
|
"@utils/ts-config-types": "1.0.4",
|
|
92
90
|
"@utils/tsdown-config": "1.0.4",
|
|
93
|
-
"react-intl": "^10.1.
|
|
91
|
+
"react-intl": "^10.1.18",
|
|
94
92
|
"rimraf": "6.1.3",
|
|
95
|
-
"tsdown": "0.22.
|
|
96
|
-
"typescript": "
|
|
97
|
-
"vite": "8.
|
|
98
|
-
"vitest": "4.1.
|
|
93
|
+
"tsdown": "0.22.12",
|
|
94
|
+
"typescript": "7.0.2",
|
|
95
|
+
"vite": "8.1.5",
|
|
96
|
+
"vitest": "4.1.10"
|
|
99
97
|
},
|
|
100
98
|
"peerDependencies": {
|
|
101
99
|
"react": ">=16.0.0",
|