@let-value/translate-react 1.0.6-beta.2

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/index.cjs ADDED
@@ -0,0 +1,177 @@
1
+ //#region rolldown:runtime
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __copyProps = (to, from, except, desc) => {
9
+ if (from && typeof from === "object" || typeof from === "function") for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
10
+ key = keys[i];
11
+ if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, {
12
+ get: ((k) => from[k]).bind(null, key),
13
+ enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
14
+ });
15
+ }
16
+ return to;
17
+ };
18
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", {
19
+ value: mod,
20
+ enumerable: true
21
+ }) : target, mod));
22
+
23
+ //#endregion
24
+ let __let_value_translate = require("@let-value/translate");
25
+ __let_value_translate = __toESM(__let_value_translate);
26
+ let react = require("react");
27
+ react = __toESM(react);
28
+
29
+ //#region src/context.ts
30
+ const localeContext = (0, react.createContext)(void 0);
31
+ const translatorContext = (0, react.createContext)(void 0);
32
+
33
+ //#endregion
34
+ //#region src/components/LocaleProvider.ts
35
+ function LocaleProvider({ locale, children }) {
36
+ return (0, react.createElement)(localeContext.Provider, { value: locale }, children);
37
+ }
38
+
39
+ //#endregion
40
+ //#region src/hooks/useTranslations.ts
41
+ /** @deprecated replace with `use` from react */
42
+ function getPromiseState(promise) {
43
+ switch (promise.status) {
44
+ case "pending": return { status: "pending" };
45
+ case "fulfilled": return {
46
+ status: "fulfilled",
47
+ value: promise.value
48
+ };
49
+ case "rejected": return {
50
+ status: "rejected",
51
+ reason: promise.reason
52
+ };
53
+ default:
54
+ promise.status = "pending";
55
+ promise.then((value) => {
56
+ promise.status = "fulfilled";
57
+ promise.value = value;
58
+ });
59
+ promise.catch((reason) => {
60
+ promise.status = "rejected";
61
+ promise.reason = reason;
62
+ });
63
+ return getPromiseState(promise);
64
+ }
65
+ }
66
+ function useTranslations(locale) {
67
+ const requestedLocale = locale ?? (0, react.use)(localeContext) ?? "unknown";
68
+ const translator = (0, react.use)(translatorContext);
69
+ if (!translator) throw new Error("TranslationsProvider is missing");
70
+ const resource = translator.fetchLocale(requestedLocale);
71
+ if (!(resource instanceof Promise)) return resource;
72
+ const state = getPromiseState(resource);
73
+ if (state.status === "pending") throw resource;
74
+ if (state.status === "rejected") throw state.reason;
75
+ if (state.status === "fulfilled") return state.value;
76
+ return (0, react.use)(resource);
77
+ }
78
+
79
+ //#endregion
80
+ //#region src/utils.ts
81
+ function buildTemplateFromChildren(children) {
82
+ const strings = [""];
83
+ const values = [];
84
+ react.Children.forEach(children, (child) => {
85
+ if (typeof child === "string" || typeof child === "number") strings[strings.length - 1] += String(child);
86
+ else if (child != null) {
87
+ values.push(child);
88
+ strings.push("");
89
+ }
90
+ });
91
+ return {
92
+ strings,
93
+ values
94
+ };
95
+ }
96
+
97
+ //#endregion
98
+ //#region src/components/Message.ts
99
+ function Message({ context, children }) {
100
+ const translator = useTranslations();
101
+ const { strings, values } = buildTemplateFromChildren(children);
102
+ if (values.length === 0) {
103
+ const input = strings.join("");
104
+ if (context) return translator.context(context).message(input);
105
+ return translator.message(input);
106
+ }
107
+ const tokens = values.map((_, i) => `\u0000${i}\u0000`);
108
+ const built = (0, __let_value_translate.message)(strings, ...tokens);
109
+ const translated = context ? translator.context(context).message(built) : translator.message(built);
110
+ const parts = translated.split(/\u0000(\d+)\u0000/);
111
+ const result = [];
112
+ for (let i = 0; i < parts.length; i += 2) {
113
+ result.push(parts[i]);
114
+ const idx = parts[i + 1];
115
+ if (idx !== void 0) result.push(values[Number(idx)]);
116
+ }
117
+ return (0, react.createElement)(react.Fragment, null, ...result);
118
+ }
119
+
120
+ //#endregion
121
+ //#region src/components/Plural.ts
122
+ function Plural({ number, forms, context }) {
123
+ const translator = useTranslations();
124
+ const built = forms.map((child, i) => {
125
+ const { strings, values } = buildTemplateFromChildren(child);
126
+ const tokens = values.map((_, j) => `\u0000${i}-${j}\u0000`);
127
+ return {
128
+ message: (0, __let_value_translate.message)(strings, ...tokens),
129
+ values
130
+ };
131
+ });
132
+ const messages = built.map((b) => b.message);
133
+ const input = (0, __let_value_translate.plural)(...messages, number);
134
+ const translated = context ? translator.context(context).plural(input) : translator.plural(input);
135
+ const parts = translated.split(/\u0000(\d+)-(\d+)\u0000/);
136
+ const result = [];
137
+ for (let i = 0; i < parts.length;) {
138
+ result.push(parts[i]);
139
+ if (i + 2 < parts.length) {
140
+ const formIndex = Number(parts[i + 1]);
141
+ const valueIndex = Number(parts[i + 2]);
142
+ result.push(built[formIndex].values[valueIndex]);
143
+ }
144
+ i += 3;
145
+ }
146
+ return (0, react.createElement)(react.Fragment, null, ...result);
147
+ }
148
+
149
+ //#endregion
150
+ //#region src/components/TranslationsProvider.ts
151
+ function TranslationsProvider({ translations = {}, children }) {
152
+ const parent = (0, react.use)(translatorContext);
153
+ const translator = (0, react.useMemo)(() => {
154
+ return new __let_value_translate.Translator(translations, parent);
155
+ }, [parent, translations]);
156
+ return (0, react.createElement)(translatorContext.Provider, { value: translator }, (0, react.createElement)(react.Suspense, null, children));
157
+ }
158
+
159
+ //#endregion
160
+ //#region src/hooks/useLocale.ts
161
+ function useLocale() {
162
+ return (0, react.use)(localeContext);
163
+ }
164
+
165
+ //#endregion
166
+ exports.LocaleProvider = LocaleProvider;
167
+ exports.Message = Message;
168
+ exports.Plural = Plural;
169
+ exports.TranslationsProvider = TranslationsProvider;
170
+ exports.useLocale = useLocale;
171
+ exports.useTranslations = useTranslations;
172
+ Object.keys(__let_value_translate).forEach(function (k) {
173
+ if (k !== 'default' && !Object.prototype.hasOwnProperty.call(exports, k)) Object.defineProperty(exports, k, {
174
+ enumerable: true,
175
+ get: function () { return __let_value_translate[k]; }
176
+ });
177
+ });
@@ -0,0 +1,64 @@
1
+ import { Locale, LocaleTranslator, Translator } from "@let-value/translate";
2
+ import * as react1 from "react";
3
+ import { ReactNode } from "react";
4
+ import { GetTextTranslations } from "gettext-parser";
5
+ export * from "@let-value/translate";
6
+
7
+ //#region src/components/LocaleProvider.d.ts
8
+ interface LocaleProviderProps {
9
+ locale: Locale;
10
+ children?: ReactNode;
11
+ }
12
+ declare function LocaleProvider({
13
+ locale,
14
+ children
15
+ }: LocaleProviderProps): react1.FunctionComponentElement<react1.ProviderProps<any>>;
16
+ //#endregion
17
+ //#region src/components/Message.d.ts
18
+ interface MessageProps {
19
+ context?: string;
20
+ children: ReactNode;
21
+ }
22
+ declare function Message({
23
+ context,
24
+ children
25
+ }: MessageProps): string | react1.FunctionComponentElement<react1.FragmentProps>;
26
+ //#endregion
27
+ //#region src/components/Plural.d.ts
28
+ interface PluralProps {
29
+ number: number;
30
+ forms: readonly ReactNode[];
31
+ context?: string;
32
+ }
33
+ declare function Plural({
34
+ number,
35
+ forms,
36
+ context
37
+ }: PluralProps): react1.FunctionComponentElement<react1.FragmentProps>;
38
+ //#endregion
39
+ //#region src/components/TranslationsProvider.d.ts
40
+ type TranslationLoader = () => Promise<GetTextTranslations>;
41
+ type TranslationEntry = GetTextTranslations | TranslationLoader;
42
+ interface TranslationsProviderProps {
43
+ translations?: Partial<Record<Locale, TranslationEntry>>;
44
+ children?: ReactNode;
45
+ }
46
+ declare function TranslationsProvider({
47
+ translations,
48
+ children
49
+ }: TranslationsProviderProps): react1.FunctionComponentElement<react1.ProviderProps<Translator<Partial<Record<PluralFormsLocale, (GetTextTranslations | {
50
+ default: GetTextTranslations;
51
+ }) | Promise<GetTextTranslations | {
52
+ default: GetTextTranslations;
53
+ }> | (() => Promise<GetTextTranslations | {
54
+ default: GetTextTranslations;
55
+ }>)>>> | undefined>>;
56
+ //#endregion
57
+ //#region src/hooks/useLocale.d.ts
58
+ declare function useLocale(): Locale | undefined;
59
+ //#endregion
60
+ //#region src/hooks/useTranslations.d.ts
61
+ declare function useTranslations(locale?: Locale): LocaleTranslator;
62
+ //#endregion
63
+ export { LocaleProvider, Message, Plural, TranslationsProvider, useLocale, useTranslations };
64
+ //# sourceMappingURL=index.d.cts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.cts","names":[],"sources":["../src/components/LocaleProvider.ts","../src/components/Message.ts","../src/components/Plural.ts","../src/components/TranslationsProvider.ts","../src/hooks/useLocale.ts","../src/hooks/useTranslations.ts"],"sourcesContent":[],"mappings":";;;;;;;UAIiB,mBAAA;UACL;aACG;;iBAGC,cAAA;;;GAAqC,sBAAmB,MAAA,CAAA,yBAAA,MAAA,CAAA;;;UCHvD,YAAA;;YAEH;;iBAGE,OAAA;;;GAA+B,wBAAY,MAAA,CAAA,yBAAA,MAAA,CAAA,aAAA;;;UCL1C,WAAA;;kBAEG;;;iBAIJ,MAAA;;;;GAAmC,cAAW,MAAA,CAAA,yBAAA,MAAA,CAAA,aAAA;;;KCNzD,iBAAA,SAA0B,QAAQ;KAClC,gBAAA,GAAmB,sBAAsB;UAE7B,yBAAA;iBACE,QAAQ,OAAO,QAAQ;EHNzB,QAAA,CAAA,EGOF,SHPE;;AACL,iBGSI,oBAAA,CHTJ;EAAA,YAAA;EAAA;AAAA,CAAA,EGS0D,yBHT1D,CAAA,EGSmF,MAAA,CAAA,wBHTnF,CGSmF,MAAA,CAAA,aHTnF,CGSmF,UHTnF,CGSmF,OHTnF,CGSmF,MHTnF,CGSmF,iBHTnF,EAAA,CGSmF,mBHTnF,GAAA;SACG,qBAAA;;EAGC,OAAA,qBAAc;CAAA,CAAA,GAAA,CAAA,GAAA,UAAA,oBAAA,GAAA;SAAG,qBAAA;SAAQ,SAAA,CAAA,CAAA;;;iBILzB,SAAA,CAAA,GAAa;;;iBC0Bb,eAAA,UAAyB,SAAS"}
@@ -0,0 +1,64 @@
1
+ import { Locale, LocaleTranslator, Translator } from "@let-value/translate";
2
+ import * as react1 from "react";
3
+ import { ReactNode } from "react";
4
+ import { GetTextTranslations } from "gettext-parser";
5
+ export * from "@let-value/translate";
6
+
7
+ //#region src/components/LocaleProvider.d.ts
8
+ interface LocaleProviderProps {
9
+ locale: Locale;
10
+ children?: ReactNode;
11
+ }
12
+ declare function LocaleProvider({
13
+ locale,
14
+ children
15
+ }: LocaleProviderProps): react1.FunctionComponentElement<react1.ProviderProps<any>>;
16
+ //#endregion
17
+ //#region src/components/Message.d.ts
18
+ interface MessageProps {
19
+ context?: string;
20
+ children: ReactNode;
21
+ }
22
+ declare function Message({
23
+ context,
24
+ children
25
+ }: MessageProps): string | react1.FunctionComponentElement<react1.FragmentProps>;
26
+ //#endregion
27
+ //#region src/components/Plural.d.ts
28
+ interface PluralProps {
29
+ number: number;
30
+ forms: readonly ReactNode[];
31
+ context?: string;
32
+ }
33
+ declare function Plural({
34
+ number,
35
+ forms,
36
+ context
37
+ }: PluralProps): react1.FunctionComponentElement<react1.FragmentProps>;
38
+ //#endregion
39
+ //#region src/components/TranslationsProvider.d.ts
40
+ type TranslationLoader = () => Promise<GetTextTranslations>;
41
+ type TranslationEntry = GetTextTranslations | TranslationLoader;
42
+ interface TranslationsProviderProps {
43
+ translations?: Partial<Record<Locale, TranslationEntry>>;
44
+ children?: ReactNode;
45
+ }
46
+ declare function TranslationsProvider({
47
+ translations,
48
+ children
49
+ }: TranslationsProviderProps): react1.FunctionComponentElement<react1.ProviderProps<Translator<Partial<Record<PluralFormsLocale, (GetTextTranslations | {
50
+ default: GetTextTranslations;
51
+ }) | Promise<GetTextTranslations | {
52
+ default: GetTextTranslations;
53
+ }> | (() => Promise<GetTextTranslations | {
54
+ default: GetTextTranslations;
55
+ }>)>>> | undefined>>;
56
+ //#endregion
57
+ //#region src/hooks/useLocale.d.ts
58
+ declare function useLocale(): Locale | undefined;
59
+ //#endregion
60
+ //#region src/hooks/useTranslations.d.ts
61
+ declare function useTranslations(locale?: Locale): LocaleTranslator;
62
+ //#endregion
63
+ export { LocaleProvider, Message, Plural, TranslationsProvider, useLocale, useTranslations };
64
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","names":[],"sources":["../src/components/LocaleProvider.ts","../src/components/Message.ts","../src/components/Plural.ts","../src/components/TranslationsProvider.ts","../src/hooks/useLocale.ts","../src/hooks/useTranslations.ts"],"sourcesContent":[],"mappings":";;;;;;;UAIiB,mBAAA;UACL;aACG;;iBAGC,cAAA;;;GAAqC,sBAAmB,MAAA,CAAA,yBAAA,MAAA,CAAA;;;UCHvD,YAAA;;YAEH;;iBAGE,OAAA;;;GAA+B,wBAAY,MAAA,CAAA,yBAAA,MAAA,CAAA,aAAA;;;UCL1C,WAAA;;kBAEG;;;iBAIJ,MAAA;;;;GAAmC,cAAW,MAAA,CAAA,yBAAA,MAAA,CAAA,aAAA;;;KCNzD,iBAAA,SAA0B,QAAQ;KAClC,gBAAA,GAAmB,sBAAsB;UAE7B,yBAAA;iBACE,QAAQ,OAAO,QAAQ;EHNzB,QAAA,CAAA,EGOF,SHPE;;AACL,iBGSI,oBAAA,CHTJ;EAAA,YAAA;EAAA;AAAA,CAAA,EGS0D,yBHT1D,CAAA,EGSmF,MAAA,CAAA,wBHTnF,CGSmF,MAAA,CAAA,aHTnF,CGSmF,UHTnF,CGSmF,OHTnF,CGSmF,MHTnF,CGSmF,iBHTnF,EAAA,CGSmF,mBHTnF,GAAA;SACG,qBAAA;;EAGC,OAAA,qBAAc;CAAA,CAAA,GAAA,CAAA,GAAA,UAAA,oBAAA,GAAA;SAAG,qBAAA;SAAQ,SAAA,CAAA,CAAA;;;iBILzB,SAAA,CAAA,GAAa;;;iBC0Bb,eAAA,UAAyB,SAAS"}
package/dist/index.js ADDED
@@ -0,0 +1,144 @@
1
+ import { Translator, message, plural } from "@let-value/translate";
2
+ import { Children, Fragment, Suspense, createContext, createElement, use, useMemo } from "react";
3
+
4
+ export * from "@let-value/translate"
5
+
6
+ //#region src/context.ts
7
+ const localeContext = createContext(void 0);
8
+ const translatorContext = createContext(void 0);
9
+
10
+ //#endregion
11
+ //#region src/components/LocaleProvider.ts
12
+ function LocaleProvider({ locale, children }) {
13
+ return createElement(localeContext.Provider, { value: locale }, children);
14
+ }
15
+
16
+ //#endregion
17
+ //#region src/hooks/useTranslations.ts
18
+ /** @deprecated replace with `use` from react */
19
+ function getPromiseState(promise) {
20
+ switch (promise.status) {
21
+ case "pending": return { status: "pending" };
22
+ case "fulfilled": return {
23
+ status: "fulfilled",
24
+ value: promise.value
25
+ };
26
+ case "rejected": return {
27
+ status: "rejected",
28
+ reason: promise.reason
29
+ };
30
+ default:
31
+ promise.status = "pending";
32
+ promise.then((value) => {
33
+ promise.status = "fulfilled";
34
+ promise.value = value;
35
+ });
36
+ promise.catch((reason) => {
37
+ promise.status = "rejected";
38
+ promise.reason = reason;
39
+ });
40
+ return getPromiseState(promise);
41
+ }
42
+ }
43
+ function useTranslations(locale) {
44
+ const requestedLocale = locale ?? use(localeContext) ?? "unknown";
45
+ const translator = use(translatorContext);
46
+ if (!translator) throw new Error("TranslationsProvider is missing");
47
+ const resource = translator.fetchLocale(requestedLocale);
48
+ if (!(resource instanceof Promise)) return resource;
49
+ const state = getPromiseState(resource);
50
+ if (state.status === "pending") throw resource;
51
+ if (state.status === "rejected") throw state.reason;
52
+ if (state.status === "fulfilled") return state.value;
53
+ return use(resource);
54
+ }
55
+
56
+ //#endregion
57
+ //#region src/utils.ts
58
+ function buildTemplateFromChildren(children) {
59
+ const strings = [""];
60
+ const values = [];
61
+ Children.forEach(children, (child) => {
62
+ if (typeof child === "string" || typeof child === "number") strings[strings.length - 1] += String(child);
63
+ else if (child != null) {
64
+ values.push(child);
65
+ strings.push("");
66
+ }
67
+ });
68
+ return {
69
+ strings,
70
+ values
71
+ };
72
+ }
73
+
74
+ //#endregion
75
+ //#region src/components/Message.ts
76
+ function Message({ context, children }) {
77
+ const translator = useTranslations();
78
+ const { strings, values } = buildTemplateFromChildren(children);
79
+ if (values.length === 0) {
80
+ const input = strings.join("");
81
+ if (context) return translator.context(context).message(input);
82
+ return translator.message(input);
83
+ }
84
+ const tokens = values.map((_, i) => `\u0000${i}\u0000`);
85
+ const built = message(strings, ...tokens);
86
+ const translated = context ? translator.context(context).message(built) : translator.message(built);
87
+ const parts = translated.split(/\u0000(\d+)\u0000/);
88
+ const result = [];
89
+ for (let i = 0; i < parts.length; i += 2) {
90
+ result.push(parts[i]);
91
+ const idx = parts[i + 1];
92
+ if (idx !== void 0) result.push(values[Number(idx)]);
93
+ }
94
+ return createElement(Fragment, null, ...result);
95
+ }
96
+
97
+ //#endregion
98
+ //#region src/components/Plural.ts
99
+ function Plural({ number, forms, context }) {
100
+ const translator = useTranslations();
101
+ const built = forms.map((child, i) => {
102
+ const { strings, values } = buildTemplateFromChildren(child);
103
+ const tokens = values.map((_, j) => `\u0000${i}-${j}\u0000`);
104
+ return {
105
+ message: message(strings, ...tokens),
106
+ values
107
+ };
108
+ });
109
+ const messages = built.map((b) => b.message);
110
+ const input = plural(...messages, number);
111
+ const translated = context ? translator.context(context).plural(input) : translator.plural(input);
112
+ const parts = translated.split(/\u0000(\d+)-(\d+)\u0000/);
113
+ const result = [];
114
+ for (let i = 0; i < parts.length;) {
115
+ result.push(parts[i]);
116
+ if (i + 2 < parts.length) {
117
+ const formIndex = Number(parts[i + 1]);
118
+ const valueIndex = Number(parts[i + 2]);
119
+ result.push(built[formIndex].values[valueIndex]);
120
+ }
121
+ i += 3;
122
+ }
123
+ return createElement(Fragment, null, ...result);
124
+ }
125
+
126
+ //#endregion
127
+ //#region src/components/TranslationsProvider.ts
128
+ function TranslationsProvider({ translations = {}, children }) {
129
+ const parent = use(translatorContext);
130
+ const translator = useMemo(() => {
131
+ return new Translator(translations, parent);
132
+ }, [parent, translations]);
133
+ return createElement(translatorContext.Provider, { value: translator }, createElement(Suspense, null, children));
134
+ }
135
+
136
+ //#endregion
137
+ //#region src/hooks/useLocale.ts
138
+ function useLocale() {
139
+ return use(localeContext);
140
+ }
141
+
142
+ //#endregion
143
+ export { LocaleProvider, Message, Plural, TranslationsProvider, useLocale, useTranslations };
144
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","names":["strings: string[]","values: ReactNode[]","result: ReactNode[]","result: ReactNode[]"],"sources":["../src/context.ts","../src/components/LocaleProvider.ts","../src/hooks/useTranslations.ts","../src/utils.ts","../src/components/Message.ts","../src/components/Plural.ts","../src/components/TranslationsProvider.ts","../src/hooks/useLocale.ts"],"sourcesContent":["import type { Locale, Translator } from \"@let-value/translate\";\nimport { createContext } from \"react\";\n\nexport const localeContext = createContext<Locale | undefined>(undefined);\nexport const translatorContext = createContext<Translator | undefined>(undefined);\n","import type { Locale } from \"@let-value/translate\";\nimport { createElement, type ReactNode } from \"react\";\nimport { localeContext } from \"../context.ts\";\n\nexport interface LocaleProviderProps {\n locale: Locale;\n children?: ReactNode;\n}\n\nexport function LocaleProvider({ locale, children }: LocaleProviderProps) {\n return createElement(localeContext.Provider, { value: locale }, children);\n}\n","import type { Locale, LocaleTranslator } from \"@let-value/translate\";\nimport { use } from \"react\";\n\nimport { localeContext, translatorContext } from \"../context.ts\";\n\n/** @deprecated replace with `use` from react */\n// biome-ignore lint/suspicious/noExplicitAny: we need to decorate the promise\nfunction getPromiseState(promise: any) {\n switch (promise.status) {\n case \"pending\":\n return { status: \"pending\" };\n case \"fulfilled\":\n return { status: \"fulfilled\", value: promise.value };\n case \"rejected\":\n return { status: \"rejected\", reason: promise.reason };\n default: {\n promise.status = \"pending\";\n promise.then((value: unknown) => {\n promise.status = \"fulfilled\";\n promise.value = value;\n });\n promise.catch((reason: unknown) => {\n promise.status = \"rejected\";\n promise.reason = reason;\n });\n return getPromiseState(promise);\n }\n }\n}\n\nexport function useTranslations(locale?: Locale): LocaleTranslator {\n const requestedLocale = locale ?? use(localeContext) ?? \"unknown\";\n const translator = use(translatorContext);\n if (!translator) {\n throw new Error(\"TranslationsProvider is missing\");\n }\n\n const resource = translator.fetchLocale(requestedLocale);\n if (!(resource instanceof Promise)) {\n return resource;\n }\n\n const state = getPromiseState(resource);\n if (state.status === \"pending\") {\n throw resource;\n }\n if (state.status === \"rejected\") {\n throw state.reason;\n }\n if (state.status === \"fulfilled\") {\n return state.value;\n }\n\n return use(resource);\n}\n","import { Children, type ReactNode } from \"react\";\n\nexport function buildTemplateFromChildren(children: ReactNode): {\n strings: string[];\n values: ReactNode[];\n} {\n const strings: string[] = [\"\"];\n const values: ReactNode[] = [];\n Children.forEach(children, (child) => {\n if (typeof child === \"string\" || typeof child === \"number\") {\n strings[strings.length - 1] += String(child);\n } else if (child != null) {\n values.push(child);\n strings.push(\"\");\n }\n });\n return { strings, values };\n}\n","import { message } from \"@let-value/translate\";\nimport { createElement, Fragment, type ReactNode } from \"react\";\n\nimport { useTranslations } from \"../hooks/useTranslations.ts\";\nimport { buildTemplateFromChildren } from \"../utils.ts\";\n\nexport interface MessageProps {\n context?: string;\n children: ReactNode;\n}\n\nexport function Message({ context, children }: MessageProps) {\n const translator = useTranslations();\n const { strings, values } = buildTemplateFromChildren(children);\n\n if (values.length === 0) {\n const input = strings.join(\"\");\n if (context) {\n return translator.context(context as \"\").message(input as never);\n }\n return translator.message(input as never);\n }\n\n const tokens = values.map((_, i) => `\\u0000${i}\\u0000`);\n const built = message(strings as unknown as TemplateStringsArray, ...tokens);\n const translated = context ? translator.context(context as \"\").message(built) : translator.message(built);\n\n // biome-ignore lint/suspicious/noControlCharactersInRegex: using null separators\n const parts = translated.split(/\\u0000(\\d+)\\u0000/);\n const result: ReactNode[] = [];\n for (let i = 0; i < parts.length; i += 2) {\n result.push(parts[i]);\n const idx = parts[i + 1];\n if (idx !== undefined) {\n result.push(values[Number(idx)]);\n }\n }\n\n return createElement(Fragment, null, ...result);\n}\n","import { message, plural } from \"@let-value/translate\";\nimport { createElement, Fragment, type ReactNode } from \"react\";\n\nimport { useTranslations } from \"../hooks/useTranslations.ts\";\nimport { buildTemplateFromChildren } from \"../utils.ts\";\n\nexport interface PluralProps {\n number: number;\n forms: readonly ReactNode[];\n context?: string;\n}\n\nexport function Plural({ number, forms, context }: PluralProps) {\n const translator = useTranslations();\n\n const built = forms.map((child, i) => {\n const { strings, values } = buildTemplateFromChildren(child);\n const tokens = values.map((_, j) => `\\u0000${i}-${j}\\u0000`);\n return { message: message(strings as unknown as TemplateStringsArray, ...tokens), values };\n });\n\n const messages = built.map((b) => b.message);\n const input = plural(...messages, number);\n\n const translated = context ? translator.context(context as \"\").plural(input) : translator.plural(input);\n\n // biome-ignore lint/suspicious/noControlCharactersInRegex: using null separators\n const parts = translated.split(/\\u0000(\\d+)-(\\d+)\\u0000/);\n const result: ReactNode[] = [];\n for (let i = 0; i < parts.length; ) {\n result.push(parts[i]);\n if (i + 2 < parts.length) {\n const formIndex = Number(parts[i + 1]);\n const valueIndex = Number(parts[i + 2]);\n result.push(built[formIndex].values[valueIndex]);\n }\n i += 3;\n }\n\n return createElement(Fragment, null, ...result);\n}\n","import type { Locale } from \"@let-value/translate\";\nimport { Translator } from \"@let-value/translate\";\nimport type { GetTextTranslations } from \"gettext-parser\";\nimport { createElement, type ReactNode, Suspense, use, useMemo } from \"react\";\nimport { translatorContext } from \"../context.ts\";\n\ntype TranslationLoader = () => Promise<GetTextTranslations>;\ntype TranslationEntry = GetTextTranslations | TranslationLoader;\n\nexport interface TranslationsProviderProps {\n translations?: Partial<Record<Locale, TranslationEntry>>;\n children?: ReactNode;\n}\n\nexport function TranslationsProvider({ translations = {}, children }: TranslationsProviderProps) {\n const parent = use(translatorContext);\n\n const translator = useMemo(() => {\n // Create a nested Translator that inherits from parent and merges entries\n return new Translator(translations, parent);\n }, [parent, translations]);\n\n return createElement(translatorContext.Provider, { value: translator }, createElement(Suspense, null, children));\n}\n","import type { Locale } from \"@let-value/translate\";\nimport { use } from \"react\";\nimport { localeContext } from \"../context.ts\";\n\nexport function useLocale(): Locale | undefined {\n return use(localeContext);\n}\n"],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,42 @@
1
+ {
2
+ "name": "@let-value/translate-react",
3
+ "version": "1.0.6-beta.2",
4
+ "type": "module",
5
+ "main": "dist/index.cjs",
6
+ "module": "dist/index.js",
7
+ "types": "dist/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "types": "./dist/index.d.ts",
11
+ "import": "./dist/index.js",
12
+ "require": "./dist/index.cjs"
13
+ },
14
+ "./package.json": "./package.json"
15
+ },
16
+ "files": [
17
+ "dist"
18
+ ],
19
+ "scripts": {
20
+ "build": "tsdown",
21
+ "check": "biome check .",
22
+ "format": "biome check --write .",
23
+ "typecheck": "tsc --build",
24
+ "test": "node --test"
25
+ },
26
+ "dependencies": {
27
+ "@let-value/translate": "1.0.6-beta.2",
28
+ "radash": "^12.1.1"
29
+ },
30
+ "devDependencies": {
31
+ "@types/gettext-parser": "8.0.0",
32
+ "@types/react": "19.1.12",
33
+ "@types/react-dom": "19.1.9",
34
+ "react": "19.1.1",
35
+ "react-dom": "19.1.1",
36
+ "tsdown": "0.14.2",
37
+ "typescript": "5.9.2"
38
+ },
39
+ "peerDependencies": {
40
+ "react": ">=19"
41
+ }
42
+ }