localize-react 1.6.0 → 2.0.0-next.0
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/README.md +141 -240
- package/dist/index.cjs +133 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +138 -0
- package/dist/index.d.ts +138 -0
- package/dist/index.mjs +127 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +143 -30
- package/.babelrc +0 -20
- package/dist/localize-react.js +0 -1
- package/index.d.ts +0 -39
- package/rollup.config.js +0 -24
package/dist/index.d.cts
ADDED
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
import * as react from 'react';
|
|
2
|
+
import { ReactNode, JSX } from 'react';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* A nested translation tree. Leaves are `string` (the localized text);
|
|
6
|
+
* branches are nested objects keyed by the next segment of a dot-path.
|
|
7
|
+
*
|
|
8
|
+
* @example
|
|
9
|
+
* ```ts
|
|
10
|
+
* const translations: Translations = {
|
|
11
|
+
* en: { greeting: { hello: 'Hi {{name}}!' } },
|
|
12
|
+
* fr: { greeting: { hello: 'Salut {{name}} !' } },
|
|
13
|
+
* };
|
|
14
|
+
* ```
|
|
15
|
+
*/
|
|
16
|
+
interface Translations {
|
|
17
|
+
readonly [key: string]: string | Translations;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Values to interpolate into a translation template. Keys correspond to
|
|
21
|
+
* `{{placeholder}}` tokens inside the translation string.
|
|
22
|
+
*
|
|
23
|
+
* Numbers are coerced to their `String()` form at render time.
|
|
24
|
+
*/
|
|
25
|
+
type TemplateValues = Readonly<Record<string, string | number>>;
|
|
26
|
+
/**
|
|
27
|
+
* Translate function returned by {@link useLocalize} and exposed on
|
|
28
|
+
* {@link LocalizationContext}.
|
|
29
|
+
*
|
|
30
|
+
* @param descriptor Translation key. Use dot-notation (`a.b.c`) to
|
|
31
|
+
* walk nested {@link Translations} trees.
|
|
32
|
+
* @param values Optional interpolation values for `{{name}}`-style
|
|
33
|
+
* mustaches inside the resolved translation.
|
|
34
|
+
* @param defaultMessage Fallback used when the descriptor cannot be
|
|
35
|
+
* resolved. If omitted, the descriptor itself is
|
|
36
|
+
* returned (preserving v1 behaviour).
|
|
37
|
+
* @returns The resolved, interpolated translation string.
|
|
38
|
+
*/
|
|
39
|
+
type Translate = (descriptor: string, values?: TemplateValues, defaultMessage?: string) => string;
|
|
40
|
+
/**
|
|
41
|
+
* Value carried by {@link LocalizationContext}. Available via
|
|
42
|
+
* {@link useLocalize}, {@link LocalizationConsumer}, or
|
|
43
|
+
* `static contextType` in class components.
|
|
44
|
+
*/
|
|
45
|
+
interface LocalizationContextValue {
|
|
46
|
+
/** Currently active locale, exactly as it was passed to the provider. */
|
|
47
|
+
readonly locale: string | undefined;
|
|
48
|
+
/** Translate a descriptor against the active locale. */
|
|
49
|
+
readonly translate: Translate;
|
|
50
|
+
/** The full translations tree, unmodified. */
|
|
51
|
+
readonly translations: Translations;
|
|
52
|
+
}
|
|
53
|
+
/** Props accepted by {@link LocalizationProvider}. */
|
|
54
|
+
interface LocalizationProviderProps {
|
|
55
|
+
/** Provider subtree. */
|
|
56
|
+
readonly children?: ReactNode;
|
|
57
|
+
/**
|
|
58
|
+
* Locale to look up inside {@link Translations}. If omitted, the
|
|
59
|
+
* `translations` object is treated as the flat translation map.
|
|
60
|
+
*
|
|
61
|
+
* Resolution order: exact match → `lower_case_with_underscores` →
|
|
62
|
+
* leading segment (`en_us` → `en`). A warning is logged if none match.
|
|
63
|
+
*/
|
|
64
|
+
readonly locale?: string;
|
|
65
|
+
/** Translation tree (per-locale or flat). Required. */
|
|
66
|
+
readonly translations: Translations;
|
|
67
|
+
/**
|
|
68
|
+
* Disable the internal LRU-free memo cache. Useful in dev when
|
|
69
|
+
* mutating translation objects in place. Defaults to `false`.
|
|
70
|
+
*/
|
|
71
|
+
readonly disableCache?: boolean;
|
|
72
|
+
}
|
|
73
|
+
/** Props accepted by {@link Message}. */
|
|
74
|
+
interface MessageProps {
|
|
75
|
+
/** Translation key — see {@link Translate}. */
|
|
76
|
+
readonly descriptor: string;
|
|
77
|
+
/** Interpolation values for `{{placeholder}}` tokens. */
|
|
78
|
+
readonly values?: TemplateValues;
|
|
79
|
+
/** Fallback string when `descriptor` cannot be resolved. */
|
|
80
|
+
readonly defaultMessage?: string;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* React context carrying the active translate function. Prefer
|
|
85
|
+
* {@link useLocalize} or {@link LocalizationConsumer} in new code;
|
|
86
|
+
* `static contextType = LocalizationContext` is supported for legacy
|
|
87
|
+
* class components.
|
|
88
|
+
*/
|
|
89
|
+
declare const LocalizationContext: react.Context<LocalizationContextValue>;
|
|
90
|
+
/**
|
|
91
|
+
* Provides translation data to descendants. Wrap the root of your app
|
|
92
|
+
* (or the subtree that needs translations) with this component.
|
|
93
|
+
*
|
|
94
|
+
* @example
|
|
95
|
+
* ```tsx
|
|
96
|
+
* <LocalizationProvider locale="en" translations={messages}>
|
|
97
|
+
* <App />
|
|
98
|
+
* </LocalizationProvider>
|
|
99
|
+
* ```
|
|
100
|
+
*/
|
|
101
|
+
declare function LocalizationProvider({ children, disableCache, locale, translations, }: LocalizationProviderProps): JSX.Element;
|
|
102
|
+
/**
|
|
103
|
+
* Render-prop consumer for {@link LocalizationContext}. Prefer
|
|
104
|
+
* {@link useLocalize} in function components.
|
|
105
|
+
*/
|
|
106
|
+
declare const LocalizationConsumer: react.Consumer<LocalizationContextValue>;
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* Read the current {@link LocalizationContextValue} from the nearest
|
|
110
|
+
* {@link LocalizationProvider}. Throws nothing if there is no provider —
|
|
111
|
+
* a no-op `translate` (returns the descriptor) is used instead.
|
|
112
|
+
*
|
|
113
|
+
* @example
|
|
114
|
+
* ```tsx
|
|
115
|
+
* function Greeting() {
|
|
116
|
+
* const { translate } = useLocalize();
|
|
117
|
+
* return <h1>{translate('greeting.hello', { name: 'World' })}</h1>;
|
|
118
|
+
* }
|
|
119
|
+
* ```
|
|
120
|
+
*/
|
|
121
|
+
declare function useLocalize(): LocalizationContextValue;
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* Render a translated string by descriptor.
|
|
125
|
+
*
|
|
126
|
+
* Equivalent to inlining `useLocalize().translate(descriptor, values,
|
|
127
|
+
* defaultMessage)`. Use this when you want a component instead of a
|
|
128
|
+
* hook call (e.g. inside `<button title={...} />` is not possible, but
|
|
129
|
+
* `<button title="..."><Message .../></button>` reads fine in JSX).
|
|
130
|
+
*
|
|
131
|
+
* @example
|
|
132
|
+
* ```tsx
|
|
133
|
+
* <Message descriptor="greeting.hello" values={{ name: 'Alex' }} />
|
|
134
|
+
* ```
|
|
135
|
+
*/
|
|
136
|
+
declare function Message({ defaultMessage, descriptor, values, }: MessageProps): string;
|
|
137
|
+
|
|
138
|
+
export { LocalizationConsumer, LocalizationContext, type LocalizationContextValue, LocalizationProvider, type LocalizationProviderProps, Message, type MessageProps, type TemplateValues, type Translate, type Translations, useLocalize };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
import * as react from 'react';
|
|
2
|
+
import { ReactNode, JSX } from 'react';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* A nested translation tree. Leaves are `string` (the localized text);
|
|
6
|
+
* branches are nested objects keyed by the next segment of a dot-path.
|
|
7
|
+
*
|
|
8
|
+
* @example
|
|
9
|
+
* ```ts
|
|
10
|
+
* const translations: Translations = {
|
|
11
|
+
* en: { greeting: { hello: 'Hi {{name}}!' } },
|
|
12
|
+
* fr: { greeting: { hello: 'Salut {{name}} !' } },
|
|
13
|
+
* };
|
|
14
|
+
* ```
|
|
15
|
+
*/
|
|
16
|
+
interface Translations {
|
|
17
|
+
readonly [key: string]: string | Translations;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Values to interpolate into a translation template. Keys correspond to
|
|
21
|
+
* `{{placeholder}}` tokens inside the translation string.
|
|
22
|
+
*
|
|
23
|
+
* Numbers are coerced to their `String()` form at render time.
|
|
24
|
+
*/
|
|
25
|
+
type TemplateValues = Readonly<Record<string, string | number>>;
|
|
26
|
+
/**
|
|
27
|
+
* Translate function returned by {@link useLocalize} and exposed on
|
|
28
|
+
* {@link LocalizationContext}.
|
|
29
|
+
*
|
|
30
|
+
* @param descriptor Translation key. Use dot-notation (`a.b.c`) to
|
|
31
|
+
* walk nested {@link Translations} trees.
|
|
32
|
+
* @param values Optional interpolation values for `{{name}}`-style
|
|
33
|
+
* mustaches inside the resolved translation.
|
|
34
|
+
* @param defaultMessage Fallback used when the descriptor cannot be
|
|
35
|
+
* resolved. If omitted, the descriptor itself is
|
|
36
|
+
* returned (preserving v1 behaviour).
|
|
37
|
+
* @returns The resolved, interpolated translation string.
|
|
38
|
+
*/
|
|
39
|
+
type Translate = (descriptor: string, values?: TemplateValues, defaultMessage?: string) => string;
|
|
40
|
+
/**
|
|
41
|
+
* Value carried by {@link LocalizationContext}. Available via
|
|
42
|
+
* {@link useLocalize}, {@link LocalizationConsumer}, or
|
|
43
|
+
* `static contextType` in class components.
|
|
44
|
+
*/
|
|
45
|
+
interface LocalizationContextValue {
|
|
46
|
+
/** Currently active locale, exactly as it was passed to the provider. */
|
|
47
|
+
readonly locale: string | undefined;
|
|
48
|
+
/** Translate a descriptor against the active locale. */
|
|
49
|
+
readonly translate: Translate;
|
|
50
|
+
/** The full translations tree, unmodified. */
|
|
51
|
+
readonly translations: Translations;
|
|
52
|
+
}
|
|
53
|
+
/** Props accepted by {@link LocalizationProvider}. */
|
|
54
|
+
interface LocalizationProviderProps {
|
|
55
|
+
/** Provider subtree. */
|
|
56
|
+
readonly children?: ReactNode;
|
|
57
|
+
/**
|
|
58
|
+
* Locale to look up inside {@link Translations}. If omitted, the
|
|
59
|
+
* `translations` object is treated as the flat translation map.
|
|
60
|
+
*
|
|
61
|
+
* Resolution order: exact match → `lower_case_with_underscores` →
|
|
62
|
+
* leading segment (`en_us` → `en`). A warning is logged if none match.
|
|
63
|
+
*/
|
|
64
|
+
readonly locale?: string;
|
|
65
|
+
/** Translation tree (per-locale or flat). Required. */
|
|
66
|
+
readonly translations: Translations;
|
|
67
|
+
/**
|
|
68
|
+
* Disable the internal LRU-free memo cache. Useful in dev when
|
|
69
|
+
* mutating translation objects in place. Defaults to `false`.
|
|
70
|
+
*/
|
|
71
|
+
readonly disableCache?: boolean;
|
|
72
|
+
}
|
|
73
|
+
/** Props accepted by {@link Message}. */
|
|
74
|
+
interface MessageProps {
|
|
75
|
+
/** Translation key — see {@link Translate}. */
|
|
76
|
+
readonly descriptor: string;
|
|
77
|
+
/** Interpolation values for `{{placeholder}}` tokens. */
|
|
78
|
+
readonly values?: TemplateValues;
|
|
79
|
+
/** Fallback string when `descriptor` cannot be resolved. */
|
|
80
|
+
readonly defaultMessage?: string;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* React context carrying the active translate function. Prefer
|
|
85
|
+
* {@link useLocalize} or {@link LocalizationConsumer} in new code;
|
|
86
|
+
* `static contextType = LocalizationContext` is supported for legacy
|
|
87
|
+
* class components.
|
|
88
|
+
*/
|
|
89
|
+
declare const LocalizationContext: react.Context<LocalizationContextValue>;
|
|
90
|
+
/**
|
|
91
|
+
* Provides translation data to descendants. Wrap the root of your app
|
|
92
|
+
* (or the subtree that needs translations) with this component.
|
|
93
|
+
*
|
|
94
|
+
* @example
|
|
95
|
+
* ```tsx
|
|
96
|
+
* <LocalizationProvider locale="en" translations={messages}>
|
|
97
|
+
* <App />
|
|
98
|
+
* </LocalizationProvider>
|
|
99
|
+
* ```
|
|
100
|
+
*/
|
|
101
|
+
declare function LocalizationProvider({ children, disableCache, locale, translations, }: LocalizationProviderProps): JSX.Element;
|
|
102
|
+
/**
|
|
103
|
+
* Render-prop consumer for {@link LocalizationContext}. Prefer
|
|
104
|
+
* {@link useLocalize} in function components.
|
|
105
|
+
*/
|
|
106
|
+
declare const LocalizationConsumer: react.Consumer<LocalizationContextValue>;
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* Read the current {@link LocalizationContextValue} from the nearest
|
|
110
|
+
* {@link LocalizationProvider}. Throws nothing if there is no provider —
|
|
111
|
+
* a no-op `translate` (returns the descriptor) is used instead.
|
|
112
|
+
*
|
|
113
|
+
* @example
|
|
114
|
+
* ```tsx
|
|
115
|
+
* function Greeting() {
|
|
116
|
+
* const { translate } = useLocalize();
|
|
117
|
+
* return <h1>{translate('greeting.hello', { name: 'World' })}</h1>;
|
|
118
|
+
* }
|
|
119
|
+
* ```
|
|
120
|
+
*/
|
|
121
|
+
declare function useLocalize(): LocalizationContextValue;
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* Render a translated string by descriptor.
|
|
125
|
+
*
|
|
126
|
+
* Equivalent to inlining `useLocalize().translate(descriptor, values,
|
|
127
|
+
* defaultMessage)`. Use this when you want a component instead of a
|
|
128
|
+
* hook call (e.g. inside `<button title={...} />` is not possible, but
|
|
129
|
+
* `<button title="..."><Message .../></button>` reads fine in JSX).
|
|
130
|
+
*
|
|
131
|
+
* @example
|
|
132
|
+
* ```tsx
|
|
133
|
+
* <Message descriptor="greeting.hello" values={{ name: 'Alex' }} />
|
|
134
|
+
* ```
|
|
135
|
+
*/
|
|
136
|
+
declare function Message({ defaultMessage, descriptor, values, }: MessageProps): string;
|
|
137
|
+
|
|
138
|
+
export { LocalizationConsumer, LocalizationContext, type LocalizationContextValue, LocalizationProvider, type LocalizationProviderProps, Message, type MessageProps, type TemplateValues, type Translate, type Translations, useLocalize };
|
package/dist/index.mjs
ADDED
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
import { createContext, useMemo, useEffect, useContext } from 'react';
|
|
2
|
+
import { jsx } from 'react/jsx-runtime';
|
|
3
|
+
|
|
4
|
+
// src/Provider.tsx
|
|
5
|
+
|
|
6
|
+
// src/helpers.ts
|
|
7
|
+
var NO_TRANSLATION_WARNING_MESSAGE = "[LOCALIZE-REACT]: There are no translations for specified locale";
|
|
8
|
+
var NO_TEMPLATE_VALUE_MESSAGE = "[LOCALIZE-REACT] Looks like template is being used, but no value passed for ";
|
|
9
|
+
var PARSE_TEMPLATE_REGEXP = /\{\{([^{}]+)\}\}/g;
|
|
10
|
+
var translationCache = /* @__PURE__ */ Object.create(null);
|
|
11
|
+
function sanitizeLocale(locale, translations) {
|
|
12
|
+
if (!locale) return null;
|
|
13
|
+
if (typeof translations[locale] === "object") return locale;
|
|
14
|
+
const normalized = locale.toLowerCase().replaceAll("-", "_");
|
|
15
|
+
if (typeof translations[normalized] === "object") return normalized;
|
|
16
|
+
const short = normalized.split("_")[0];
|
|
17
|
+
if (short && typeof translations[short] === "object") return short;
|
|
18
|
+
console.warn(NO_TRANSLATION_WARNING_MESSAGE, locale);
|
|
19
|
+
return locale;
|
|
20
|
+
}
|
|
21
|
+
function memoize(fn) {
|
|
22
|
+
return (descriptor, values, defaultMessage) => {
|
|
23
|
+
const cacheKey = values ? JSON.stringify(values) + descriptor + (defaultMessage ?? "") : descriptor + (defaultMessage ?? "");
|
|
24
|
+
const cached = translationCache[cacheKey];
|
|
25
|
+
if (cached !== void 0) return cached;
|
|
26
|
+
const output = fn(descriptor, values, defaultMessage);
|
|
27
|
+
translationCache[cacheKey] = output;
|
|
28
|
+
return output;
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
function clearCache() {
|
|
32
|
+
translationCache = /* @__PURE__ */ Object.create(null);
|
|
33
|
+
}
|
|
34
|
+
function transformToPairs(templates, values) {
|
|
35
|
+
return templates.map((token) => {
|
|
36
|
+
const placeholderKey = token.slice(2, -2);
|
|
37
|
+
if (Object.hasOwn(values, placeholderKey)) {
|
|
38
|
+
return [token, values[placeholderKey]];
|
|
39
|
+
}
|
|
40
|
+
console.warn(NO_TEMPLATE_VALUE_MESSAGE, token);
|
|
41
|
+
return [token, token];
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
function buildTranslation(source, values) {
|
|
45
|
+
if (!values) return source;
|
|
46
|
+
if (Object.keys(values).length === 0) return source;
|
|
47
|
+
const templates = source.match(PARSE_TEMPLATE_REGEXP);
|
|
48
|
+
if (!templates || templates.length === 0) return source;
|
|
49
|
+
const pairs = transformToPairs(templates, values);
|
|
50
|
+
let result = source;
|
|
51
|
+
for (const [token, value] of pairs) {
|
|
52
|
+
result = result.replaceAll(token, String(value));
|
|
53
|
+
}
|
|
54
|
+
return result;
|
|
55
|
+
}
|
|
56
|
+
var DEFAULT_CONTEXT_VALUE = {
|
|
57
|
+
locale: void 0,
|
|
58
|
+
translate: (descriptor, _values, defaultMessage) => defaultMessage ?? descriptor,
|
|
59
|
+
translations: {}
|
|
60
|
+
};
|
|
61
|
+
var LocalizationContext = createContext(
|
|
62
|
+
DEFAULT_CONTEXT_VALUE
|
|
63
|
+
);
|
|
64
|
+
LocalizationContext.displayName = "LocalizationContext";
|
|
65
|
+
function LocalizationProvider({
|
|
66
|
+
children,
|
|
67
|
+
disableCache = false,
|
|
68
|
+
locale,
|
|
69
|
+
translations = {}
|
|
70
|
+
}) {
|
|
71
|
+
const pureTranslations = useMemo(() => {
|
|
72
|
+
const sanitizedLocale = sanitizeLocale(locale, translations);
|
|
73
|
+
const localeTranslations = sanitizedLocale === null ? translations : translations[sanitizedLocale];
|
|
74
|
+
return localeTranslations && typeof localeTranslations === "object" ? localeTranslations : {};
|
|
75
|
+
}, [locale, translations]);
|
|
76
|
+
useEffect(() => {
|
|
77
|
+
clearCache();
|
|
78
|
+
}, [locale, translations]);
|
|
79
|
+
const translate = useMemo(() => {
|
|
80
|
+
const pureTranslate = (descriptor, values, defaultMessage) => {
|
|
81
|
+
if (!descriptor) return defaultMessage ?? descriptor;
|
|
82
|
+
const fallback = typeof defaultMessage === "string" ? defaultMessage : descriptor;
|
|
83
|
+
const direct = pureTranslations[descriptor];
|
|
84
|
+
if (typeof direct === "string") {
|
|
85
|
+
return values ? buildTranslation(direct, values) : direct;
|
|
86
|
+
}
|
|
87
|
+
const segments = descriptor.split(".");
|
|
88
|
+
if (segments.length === 1) {
|
|
89
|
+
return buildTranslation(fallback, values);
|
|
90
|
+
}
|
|
91
|
+
const resolved = resolveNestedKey(pureTranslations, segments);
|
|
92
|
+
return typeof resolved === "string" ? buildTranslation(resolved, values) : buildTranslation(fallback, values);
|
|
93
|
+
};
|
|
94
|
+
return disableCache ? pureTranslate : memoize(pureTranslate);
|
|
95
|
+
}, [disableCache, pureTranslations]);
|
|
96
|
+
const value = useMemo(
|
|
97
|
+
() => ({ locale, translate, translations }),
|
|
98
|
+
[locale, translate, translations]
|
|
99
|
+
);
|
|
100
|
+
return /* @__PURE__ */ jsx(LocalizationContext.Provider, { value, children });
|
|
101
|
+
}
|
|
102
|
+
var LocalizationConsumer = LocalizationContext.Consumer;
|
|
103
|
+
function resolveNestedKey(tree, segments) {
|
|
104
|
+
let cursor = tree;
|
|
105
|
+
for (const segment of segments) {
|
|
106
|
+
if (cursor === void 0 || typeof cursor === "string") return void 0;
|
|
107
|
+
cursor = cursor[segment];
|
|
108
|
+
}
|
|
109
|
+
return typeof cursor === "string" ? cursor : void 0;
|
|
110
|
+
}
|
|
111
|
+
function useLocalize() {
|
|
112
|
+
return useContext(LocalizationContext);
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
// src/Message.tsx
|
|
116
|
+
function Message({
|
|
117
|
+
defaultMessage,
|
|
118
|
+
descriptor,
|
|
119
|
+
values
|
|
120
|
+
}) {
|
|
121
|
+
const { translate } = useLocalize();
|
|
122
|
+
return translate(descriptor, values, defaultMessage);
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
export { LocalizationConsumer, LocalizationContext, LocalizationProvider, Message, useLocalize };
|
|
126
|
+
//# sourceMappingURL=index.mjs.map
|
|
127
|
+
//# sourceMappingURL=index.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/helpers.ts","../src/Provider.tsx","../src/use-localize.ts","../src/Message.tsx"],"names":[],"mappings":"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","file":"index.mjs","sourcesContent":["import type { TemplateValues, Translate, Translations } from './types.js';\n\n/** Warning logged when no locale entry matches the requested locale. */\nexport const NO_TRANSLATION_WARNING_MESSAGE =\n '[LOCALIZE-REACT]: There are no translations for specified locale';\n\n/** Warning logged when a `{{placeholder}}` has no matching value. */\nexport const NO_TEMPLATE_VALUE_MESSAGE =\n '[LOCALIZE-REACT] Looks like template is being used, but no value passed for ';\n\n/**\n * Pattern matching `{{name}}`-style mustaches. Anchored to avoid\n * consuming adjacent braces (`{{{a}}}` only matches `{{a}}`).\n */\nexport const PARSE_TEMPLATE_REGEXP = /\\{\\{([^{}]+)\\}\\}/g;\n\n/**\n * Module-scoped translation cache. Kept module-scoped (rather than\n * provider-scoped) for behavioural parity with v1.x; see ADR-008.\n */\nlet translationCache: Record<string, string> = Object.create(null) as Record<\n string,\n string\n>;\n\n/**\n * Normalize a locale string against the available translation keys.\n *\n * - Returns `null` if no locale was supplied.\n * - Returns the input as-is if `translations[locale]` is an object.\n * - Lowercases and replaces dashes with underscores, then retries.\n * - Falls back to the leading segment (`en_us` → `en`).\n * - If nothing matches, logs a warning and returns the original input.\n */\nexport function sanitizeLocale(\n locale: string | undefined,\n translations: Translations,\n): string | null {\n if (!locale) return null;\n\n if (typeof translations[locale] === 'object') return locale;\n\n const normalized = locale.toLowerCase().replaceAll('-', '_');\n if (typeof translations[normalized] === 'object') return normalized;\n\n const short = normalized.split('_')[0];\n if (short && typeof translations[short] === 'object') return short;\n\n console.warn(NO_TRANSLATION_WARNING_MESSAGE, locale);\n return locale;\n}\n\n/**\n * Returns a memoizing wrapper around {@link fn}. The cache key combines\n * the descriptor, the JSON-serialized values, and the default message.\n */\nexport function memoize(fn: Translate): Translate {\n return (descriptor, values, defaultMessage) => {\n const cacheKey = values\n ? JSON.stringify(values) + descriptor + (defaultMessage ?? '')\n : descriptor + (defaultMessage ?? '');\n\n const cached = translationCache[cacheKey];\n if (cached !== undefined) return cached;\n\n const output = fn(descriptor, values, defaultMessage);\n translationCache[cacheKey] = output;\n return output;\n };\n}\n\n/** Reset the module-level translation cache. */\nexport function clearCache(): void {\n translationCache = Object.create(null) as Record<string, string>;\n}\n\n/**\n * Pair each `{{key}}` template token with the matching value from\n * {@link values}. Tokens with no value are paired with themselves and\n * logged.\n */\nexport function transformToPairs(\n templates: readonly string[],\n values: TemplateValues,\n): readonly (readonly [string, string | number])[] {\n return templates.map((token) => {\n const placeholderKey = token.slice(2, -2);\n if (Object.hasOwn(values, placeholderKey)) {\n return [token, values[placeholderKey]!] as const;\n }\n console.warn(NO_TEMPLATE_VALUE_MESSAGE, token);\n return [token, token] as const;\n });\n}\n\n/**\n * Replace every `{{placeholder}}` token in {@link source} with its\n * corresponding entry from {@link values}. Uses literal string\n * replacement (not `new RegExp(token)`) so values containing regex\n * meta-characters are safe — see MIGRATION_PLAN.md risk R4.\n */\nexport function buildTranslation(\n source: string,\n values?: TemplateValues,\n): string {\n if (!values) return source;\n if (Object.keys(values).length === 0) return source;\n\n const templates = source.match(PARSE_TEMPLATE_REGEXP);\n if (!templates || templates.length === 0) return source;\n\n const pairs = transformToPairs(templates, values);\n\n let result = source;\n for (const [token, value] of pairs) {\n result = result.replaceAll(token, String(value));\n }\n return result;\n}\n","import { createContext, useEffect, useMemo } from 'react';\nimport type { JSX } from 'react';\n\nimport {\n buildTranslation,\n clearCache,\n memoize,\n sanitizeLocale,\n} from './helpers.js';\nimport type {\n LocalizationContextValue,\n LocalizationProviderProps,\n TemplateValues,\n Translate,\n Translations,\n} from './types.js';\n\nconst DEFAULT_CONTEXT_VALUE: LocalizationContextValue = {\n locale: undefined,\n translate: (descriptor, _values, defaultMessage) =>\n defaultMessage ?? descriptor,\n translations: {},\n};\n\n/**\n * React context carrying the active translate function. Prefer\n * {@link useLocalize} or {@link LocalizationConsumer} in new code;\n * `static contextType = LocalizationContext` is supported for legacy\n * class components.\n */\nexport const LocalizationContext = createContext<LocalizationContextValue>(\n DEFAULT_CONTEXT_VALUE,\n);\n\nLocalizationContext.displayName = 'LocalizationContext';\n\n/**\n * Provides translation data to descendants. Wrap the root of your app\n * (or the subtree that needs translations) with this component.\n *\n * @example\n * ```tsx\n * <LocalizationProvider locale=\"en\" translations={messages}>\n * <App />\n * </LocalizationProvider>\n * ```\n */\nexport function LocalizationProvider({\n children,\n disableCache = false,\n locale,\n translations = {},\n}: LocalizationProviderProps): JSX.Element {\n const pureTranslations = useMemo<Translations>(() => {\n const sanitizedLocale = sanitizeLocale(locale, translations);\n const localeTranslations: Translations | string | undefined =\n sanitizedLocale === null ? translations : translations[sanitizedLocale];\n return localeTranslations && typeof localeTranslations === 'object'\n ? localeTranslations\n : {};\n }, [locale, translations]);\n\n useEffect(() => {\n clearCache();\n }, [locale, translations]);\n\n const translate = useMemo<Translate>(() => {\n const pureTranslate: Translate = (descriptor, values, defaultMessage) => {\n if (!descriptor) return defaultMessage ?? descriptor;\n\n const fallback =\n typeof defaultMessage === 'string' ? defaultMessage : descriptor;\n\n const direct = pureTranslations[descriptor];\n if (typeof direct === 'string') {\n return values ? buildTranslation(direct, values) : direct;\n }\n\n const segments = descriptor.split('.');\n if (segments.length === 1) {\n return buildTranslation(fallback, values);\n }\n\n const resolved = resolveNestedKey(pureTranslations, segments);\n return typeof resolved === 'string'\n ? buildTranslation(resolved, values)\n : buildTranslation(fallback, values);\n };\n\n return disableCache ? pureTranslate : memoize(pureTranslate);\n }, [disableCache, pureTranslations]);\n\n const value = useMemo<LocalizationContextValue>(\n () => ({ locale, translate, translations }),\n [locale, translate, translations],\n );\n\n return (\n <LocalizationContext.Provider value={value}>\n {children}\n </LocalizationContext.Provider>\n );\n}\n\n/**\n * Render-prop consumer for {@link LocalizationContext}. Prefer\n * {@link useLocalize} in function components.\n */\nexport const LocalizationConsumer = LocalizationContext.Consumer;\n\nfunction resolveNestedKey(\n tree: Translations,\n segments: readonly string[],\n): string | undefined {\n let cursor: string | Translations | undefined = tree;\n for (const segment of segments) {\n if (cursor === undefined || typeof cursor === 'string') return undefined;\n cursor = cursor[segment];\n }\n return typeof cursor === 'string' ? cursor : undefined;\n}\n\n// `TemplateValues` re-export keeps the file self-contained for the\n// snapshot of the public type surface; do not remove without updating\n// `src/index.ts`.\nexport type { TemplateValues };\n","import { useContext } from 'react';\n\nimport { LocalizationContext } from './Provider.js';\nimport type { LocalizationContextValue } from './types.js';\n\n/**\n * Read the current {@link LocalizationContextValue} from the nearest\n * {@link LocalizationProvider}. Throws nothing if there is no provider —\n * a no-op `translate` (returns the descriptor) is used instead.\n *\n * @example\n * ```tsx\n * function Greeting() {\n * const { translate } = useLocalize();\n * return <h1>{translate('greeting.hello', { name: 'World' })}</h1>;\n * }\n * ```\n */\nexport function useLocalize(): LocalizationContextValue {\n return useContext(LocalizationContext);\n}\n","import type { MessageProps } from './types.js';\nimport { useLocalize } from './use-localize.js';\n\n/**\n * Render a translated string by descriptor.\n *\n * Equivalent to inlining `useLocalize().translate(descriptor, values,\n * defaultMessage)`. Use this when you want a component instead of a\n * hook call (e.g. inside `<button title={...} />` is not possible, but\n * `<button title=\"...\"><Message .../></button>` reads fine in JSX).\n *\n * @example\n * ```tsx\n * <Message descriptor=\"greeting.hello\" values={{ name: 'Alex' }} />\n * ```\n */\nexport function Message({\n defaultMessage,\n descriptor,\n values,\n}: MessageProps): string {\n const { translate } = useLocalize();\n return translate(descriptor, values, defaultMessage);\n}\n"]}
|
package/package.json
CHANGED
|
@@ -1,38 +1,151 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "localize-react",
|
|
3
|
-
"version": "
|
|
4
|
-
"description": "React
|
|
5
|
-
"
|
|
6
|
-
|
|
7
|
-
|
|
3
|
+
"version": "2.0.0-next.0",
|
|
4
|
+
"description": "Tiny, type-safe React i18n library built on Context and hooks — dual ESM + CJS, zero runtime deps.",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"react",
|
|
7
|
+
"i18n",
|
|
8
|
+
"l10n",
|
|
9
|
+
"localization",
|
|
10
|
+
"internationalization",
|
|
11
|
+
"translation",
|
|
12
|
+
"context",
|
|
13
|
+
"hooks",
|
|
14
|
+
"typescript"
|
|
15
|
+
],
|
|
16
|
+
"homepage": "https://github.com/yankouskia/localize-react#readme",
|
|
17
|
+
"bugs": {
|
|
18
|
+
"url": "https://github.com/yankouskia/localize-react/issues"
|
|
19
|
+
},
|
|
20
|
+
"repository": {
|
|
21
|
+
"type": "git",
|
|
22
|
+
"url": "git+https://github.com/yankouskia/localize-react.git"
|
|
23
|
+
},
|
|
8
24
|
"license": "MIT",
|
|
25
|
+
"author": {
|
|
26
|
+
"name": "Aliaksandr Yankouski",
|
|
27
|
+
"email": "aleksandr.yankovskiy@gmail.com",
|
|
28
|
+
"url": "https://github.com/yankouskia"
|
|
29
|
+
},
|
|
30
|
+
"funding": "https://github.com/sponsors/yankouskia",
|
|
31
|
+
"type": "module",
|
|
32
|
+
"sideEffects": false,
|
|
33
|
+
"exports": {
|
|
34
|
+
".": {
|
|
35
|
+
"import": {
|
|
36
|
+
"types": "./dist/index.d.ts",
|
|
37
|
+
"default": "./dist/index.mjs"
|
|
38
|
+
},
|
|
39
|
+
"require": {
|
|
40
|
+
"types": "./dist/index.d.cts",
|
|
41
|
+
"default": "./dist/index.cjs"
|
|
42
|
+
}
|
|
43
|
+
},
|
|
44
|
+
"./package.json": "./package.json"
|
|
45
|
+
},
|
|
46
|
+
"main": "./dist/index.cjs",
|
|
47
|
+
"module": "./dist/index.mjs",
|
|
48
|
+
"types": "./dist/index.d.ts",
|
|
49
|
+
"files": [
|
|
50
|
+
"dist",
|
|
51
|
+
"README.md",
|
|
52
|
+
"LICENSE",
|
|
53
|
+
"CHANGELOG.md"
|
|
54
|
+
],
|
|
9
55
|
"peerDependencies": {
|
|
10
|
-
"react": ">=16.8.0"
|
|
56
|
+
"react": ">=16.8.0 <20"
|
|
57
|
+
},
|
|
58
|
+
"engines": {
|
|
59
|
+
"node": ">=20.19.0"
|
|
11
60
|
},
|
|
61
|
+
"publishConfig": {
|
|
62
|
+
"access": "public",
|
|
63
|
+
"provenance": true
|
|
64
|
+
},
|
|
65
|
+
"simple-git-hooks": {
|
|
66
|
+
"pre-commit": "pnpm exec lint-staged"
|
|
67
|
+
},
|
|
68
|
+
"lint-staged": {
|
|
69
|
+
"*.{ts,tsx,js,jsx}": [
|
|
70
|
+
"eslint --fix",
|
|
71
|
+
"prettier --write"
|
|
72
|
+
],
|
|
73
|
+
"*.{json,md,yml,yaml}": [
|
|
74
|
+
"prettier --write"
|
|
75
|
+
]
|
|
76
|
+
},
|
|
77
|
+
"size-limit": [
|
|
78
|
+
{
|
|
79
|
+
"name": "ESM (full library)",
|
|
80
|
+
"path": "dist/index.mjs",
|
|
81
|
+
"limit": "2 kB",
|
|
82
|
+
"ignore": [
|
|
83
|
+
"react"
|
|
84
|
+
]
|
|
85
|
+
},
|
|
86
|
+
{
|
|
87
|
+
"name": "CJS (full library)",
|
|
88
|
+
"path": "dist/index.cjs",
|
|
89
|
+
"limit": "2.5 kB",
|
|
90
|
+
"ignore": [
|
|
91
|
+
"react"
|
|
92
|
+
]
|
|
93
|
+
}
|
|
94
|
+
],
|
|
12
95
|
"devDependencies": {
|
|
13
|
-
"@
|
|
14
|
-
"@
|
|
15
|
-
"@
|
|
16
|
-
"@
|
|
17
|
-
"
|
|
18
|
-
"
|
|
19
|
-
"
|
|
20
|
-
"
|
|
21
|
-
"
|
|
22
|
-
"react
|
|
23
|
-
"
|
|
24
|
-
"
|
|
25
|
-
"
|
|
26
|
-
"
|
|
27
|
-
"
|
|
28
|
-
"
|
|
29
|
-
"
|
|
96
|
+
"@arethetypeswrong/cli": "~0.18.2",
|
|
97
|
+
"@changesets/changelog-github": "0.5",
|
|
98
|
+
"@changesets/cli": "2.28",
|
|
99
|
+
"@eslint/js": "9",
|
|
100
|
+
"@microsoft/api-extractor": "7",
|
|
101
|
+
"@size-limit/preset-small-lib": "11",
|
|
102
|
+
"@testing-library/jest-dom": "^6.9.1",
|
|
103
|
+
"@testing-library/react": "16",
|
|
104
|
+
"@testing-library/user-event": "14",
|
|
105
|
+
"@types/react": "^19.2.15",
|
|
106
|
+
"@types/react-dom": "^19.2.3",
|
|
107
|
+
"@vitest/coverage-v8": "^4.1.6",
|
|
108
|
+
"eslint": "9",
|
|
109
|
+
"eslint-plugin-import-x": "4",
|
|
110
|
+
"eslint-plugin-n": "17",
|
|
111
|
+
"eslint-plugin-promise": "7",
|
|
112
|
+
"eslint-plugin-react": "7",
|
|
113
|
+
"eslint-plugin-react-hooks": "5",
|
|
114
|
+
"eslint-plugin-unicorn": "56",
|
|
115
|
+
"globals": "15",
|
|
116
|
+
"jsdom": "25",
|
|
117
|
+
"lint-staged": "15",
|
|
118
|
+
"prettier": "3",
|
|
119
|
+
"publint": "0.3",
|
|
120
|
+
"react": "^19.2.6",
|
|
121
|
+
"react-dom": "^19.2.6",
|
|
122
|
+
"rimraf": "6",
|
|
123
|
+
"simple-git-hooks": "2",
|
|
124
|
+
"size-limit": "11",
|
|
125
|
+
"tsup": "8",
|
|
126
|
+
"typedoc": "~0.28.19",
|
|
127
|
+
"typescript": "^6.0.3",
|
|
128
|
+
"typescript-eslint": "8",
|
|
129
|
+
"vite": "7",
|
|
130
|
+
"vitest": "^4.1.6"
|
|
30
131
|
},
|
|
31
132
|
"scripts": {
|
|
32
|
-
"build": "
|
|
33
|
-
"
|
|
34
|
-
"
|
|
35
|
-
"
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
133
|
+
"build": "tsup",
|
|
134
|
+
"clean": "rimraf dist coverage .tsbuildinfo",
|
|
135
|
+
"dev": "tsup --watch",
|
|
136
|
+
"format": "prettier --write .",
|
|
137
|
+
"format:check": "prettier --check .",
|
|
138
|
+
"lint": "eslint .",
|
|
139
|
+
"lint:fix": "eslint . --fix",
|
|
140
|
+
"pack:check": "publint --strict",
|
|
141
|
+
"pack:check:types": "attw --pack . --ignore-rules cjs-resolves-to-esm",
|
|
142
|
+
"test": "vitest",
|
|
143
|
+
"test:coverage": "vitest run --coverage",
|
|
144
|
+
"test:watch": "vitest",
|
|
145
|
+
"typecheck": "tsc --noEmit",
|
|
146
|
+
"release": "changeset publish",
|
|
147
|
+
"version": "changeset version",
|
|
148
|
+
"size": "size-limit",
|
|
149
|
+
"docs": "typedoc"
|
|
150
|
+
}
|
|
151
|
+
}
|
package/.babelrc
DELETED
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"plugins": [
|
|
3
|
-
"@babel/plugin-transform-object-assign",
|
|
4
|
-
],
|
|
5
|
-
"presets": [
|
|
6
|
-
[
|
|
7
|
-
"@babel/preset-env",
|
|
8
|
-
{
|
|
9
|
-
"targets": {
|
|
10
|
-
"browsers": [
|
|
11
|
-
"> 1%",
|
|
12
|
-
"safari >= 8",
|
|
13
|
-
"ie >= 11"
|
|
14
|
-
]
|
|
15
|
-
}
|
|
16
|
-
}
|
|
17
|
-
],
|
|
18
|
-
"@babel/preset-react"
|
|
19
|
-
]
|
|
20
|
-
}
|
package/dist/localize-react.js
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports,require("react")):"function"==typeof define&&define.amd?define(["exports","react"],t):t((e=e||self)["localize-react"]={},e.React)}(this,function(e,s){"use strict";var p="default"in s?s.default:s;function v(e){return(v="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e})(e)}var y={},d="[LOCALIZE-REACT]: There are no translations for specified locale",a="[LOCALIZE-REACT] Looks like template is being used, but no value passed for ",u=/{{([^{]+[^}])}}/g;function b(e,t){if(!t)return e;if(0===Object.keys(t).length)return e;var r,n,o,i=e.match(u);return i&&0!==i.length?(r=i,n=t,o=Object.keys(n),r.map(function(e){var t=Array.prototype.slice.call(e,2,-2).join(""),r=o.find(function(e){return e===t});return r?[e,n[r]]:(console.warn(a,e),[e,e])})).reduce(function(e,t){var r=new RegExp(t[0],"gi");return e.replace(r,t[1])},e):e}var g=p.createContext();var t=g.Consumer;function o(){return s.useContext(g)}e.LocalizationConsumer=t,e.LocalizationContext=g,e.LocalizationProvider=function(e){var t=e.children,r=e.disableCache,n=e.locale,o=e.translations,i=void 0===o?{}:o,a=function(e,t){if(!e)return null;if("object"===v(t[e]))return e;var r=e.toLowerCase().replace(/-/g,"_");if("object"===v(t[r]))return r;var n=r.split("_")[0];return"object"===v(t[n])?n:(console.warn(d,e),e)}(n,i),l=a?i[a]:i;function u(e,t,r){if(!l||!e)return r||e;var n="string"==typeof r?r:e,o=l[e];if("string"==typeof o)return t?b(o,t):o;var i=e.split(".");if(1===i.length)return b(n,t);for(var a=l[i[0]],u=1;u<i.length;u++)a=a&&a[i[u]];return b("string"==typeof a?a:n,t)}s.useEffect(function(){y={}},[n,i]);var c,f=r?u:(c=u,function(e,t,r){var n=2<arguments.length&&void 0!==r?r:"",o=t?JSON.stringify(t,null,"")+e+n:e+n;if(y[o])return y[o];var i=c(e,t,n);return y[o]=i});return p.createElement(g.Provider,{value:{locale:n,translate:f,translations:i}},t)},e.Message=function(e){var t=e.defaultMessage,r=e.descriptor,n=e.values;return(0,o().translate)(r,n,t)},e.useLocalize=o,Object.defineProperty(e,"__esModule",{value:!0})});
|