@sheet-i18n/react 1.6.1 → 1.6.2-canary.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/dist/index.mjs CHANGED
@@ -1,3 +1,554 @@
1
+ "use client";
2
+ var __defProp = Object.defineProperty;
3
+ var __defProps = Object.defineProperties;
4
+ var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
5
+ var __getOwnPropSymbols = Object.getOwnPropertySymbols;
6
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
7
+ var __propIsEnum = Object.prototype.propertyIsEnumerable;
8
+ var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
9
+ var __spreadValues = (a, b) => {
10
+ for (var prop in b || (b = {}))
11
+ if (__hasOwnProp.call(b, prop))
12
+ __defNormalProp(a, prop, b[prop]);
13
+ if (__getOwnPropSymbols)
14
+ for (var prop of __getOwnPropSymbols(b)) {
15
+ if (__propIsEnum.call(b, prop))
16
+ __defNormalProp(a, prop, b[prop]);
17
+ }
18
+ return a;
19
+ };
20
+ var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
21
+
1
22
  // src/index.ts
2
- export * from "@sheet-i18n/react-core";
3
- export * from "@sheet-i18n/react-client";
23
+ export * from "@sheet-i18n/core";
24
+
25
+ // src/createI18nContext.tsx
26
+ import { validator as validator5 } from "@sheet-i18n/shared-utils";
27
+ import { I18nStore } from "@sheet-i18n/core";
28
+
29
+ // src/Provider/IntlProvider.tsx
30
+ import { IntlProvider as ReactIntlProvider } from "react-intl";
31
+ import { useEffect } from "react";
32
+
33
+ // src/hooks/useDynamicLocale.ts
34
+ import { validator as validator2 } from "@sheet-i18n/shared-utils";
35
+ import { useLayoutEffect, useState } from "react";
36
+
37
+ // src/Service/IntlInstanceCache.ts
38
+ import { createIntl, createIntlCache, useIntl } from "react-intl";
39
+ import { validator } from "@sheet-i18n/shared-utils";
40
+ var intlCache = createIntlCache();
41
+ var IntlInstanceCache = class _IntlInstanceCache {
42
+ constructor() {
43
+ this.cache = {};
44
+ this.getCachedIntlInstance = (sheetTitle, i18nStore, environment = "client") => {
45
+ const currentLocale = i18nStore.getCurrentLocale();
46
+ const cachedIntlInstance = this.cache[sheetTitle];
47
+ const sameLocale = (cachedIntlInstance == null ? void 0 : cachedIntlInstance.locale) === currentLocale;
48
+ if (cachedIntlInstance && sameLocale) {
49
+ return cachedIntlInstance.intlInstance;
50
+ }
51
+ return environment === "client" ? this.createClientIntlInstance(sheetTitle, i18nStore) : this.createServerIntlInstance(sheetTitle, i18nStore);
52
+ };
53
+ this.getTotalCache = () => {
54
+ return this.cache;
55
+ };
56
+ this.resetTotalCache = () => {
57
+ this.cache = {};
58
+ };
59
+ this.createClientIntlInstance = (sheetTitle, i18nStore) => {
60
+ const currentIntl = useIntl();
61
+ const currentLocale = i18nStore.getCurrentLocale();
62
+ const targetMessages = i18nStore.getTargetMessages(sheetTitle);
63
+ const newIntl = createIntl(
64
+ __spreadProps(__spreadValues({}, currentIntl), { messages: targetMessages }),
65
+ intlCache
66
+ );
67
+ if (currentLocale) {
68
+ this.setCachedIntlInstance(sheetTitle, currentLocale, newIntl);
69
+ }
70
+ return newIntl;
71
+ };
72
+ this.createServerIntlInstance = (sheetTitle, i18nStore) => {
73
+ const currentLocale = i18nStore.getCurrentLocale();
74
+ const targetMessages = i18nStore.getTargetMessages(sheetTitle);
75
+ if (!i18nStore || !currentLocale) {
76
+ return null;
77
+ }
78
+ const newIntl = createIntl(
79
+ { locale: currentLocale, messages: targetMessages },
80
+ intlCache
81
+ );
82
+ if (currentLocale) {
83
+ this.setCachedIntlInstance(sheetTitle, currentLocale, newIntl);
84
+ }
85
+ return newIntl;
86
+ };
87
+ }
88
+ static init() {
89
+ if (!_IntlInstanceCache.instance) {
90
+ _IntlInstanceCache.instance = new _IntlInstanceCache();
91
+ }
92
+ return _IntlInstanceCache.instance;
93
+ }
94
+ setCachedIntlInstance(sheetTitle, currentLocale, intlInstance) {
95
+ if (validator.isNullish(this.cache[sheetTitle])) {
96
+ this.cache[sheetTitle] = {
97
+ locale: currentLocale,
98
+ intlInstance
99
+ };
100
+ }
101
+ }
102
+ };
103
+ var intlInstanceCache = IntlInstanceCache.init();
104
+
105
+ // src/hooks/useDynamicLocale.ts
106
+ function useDynamicLocale(useDynamicLocaleProps) {
107
+ const { i18nStore } = useDynamicLocaleProps != null ? useDynamicLocaleProps : {};
108
+ const currentLocale = i18nStore == null ? void 0 : i18nStore.getCurrentLocale();
109
+ const [isLoading, setIsLoading] = useState(false);
110
+ useLayoutEffect(() => {
111
+ var _a;
112
+ if (validator2.isNullish(currentLocale)) return;
113
+ const dynamicLoaders = (_a = i18nStore == null ? void 0 : i18nStore.dynamicLoaders) != null ? _a : useDynamicLocaleProps == null ? void 0 : useDynamicLocaleProps.dynamicLoaders;
114
+ if (!dynamicLoaders) return;
115
+ const targetDynamicLoader = dynamicLoaders[currentLocale];
116
+ if (!targetDynamicLoader) return;
117
+ const currentLocaleSet = i18nStore == null ? void 0 : i18nStore.localeSet;
118
+ const targetLocaleData = currentLocaleSet == null ? void 0 : currentLocaleSet[currentLocale];
119
+ if (targetLocaleData) return;
120
+ setIsLoading(true);
121
+ targetDynamicLoader == null ? void 0 : targetDynamicLoader().then((res) => {
122
+ const { default: localeData } = res;
123
+ i18nStore == null ? void 0 : i18nStore.mergeLocaleSet(currentLocale, localeData);
124
+ intlInstanceCache.resetTotalCache();
125
+ setIsLoading(false);
126
+ }).catch((err) => {
127
+ console.log(`\u26A0\uFE0F dynamic loader error:
128
+ ${err}`);
129
+ setIsLoading(false);
130
+ });
131
+ }, [currentLocale]);
132
+ return {
133
+ isLoading
134
+ };
135
+ }
136
+
137
+ // src/Provider/IntlProvider.tsx
138
+ import { jsx } from "react/jsx-runtime";
139
+ function IntlProvider({
140
+ i18nStore,
141
+ currentLocale,
142
+ children: childrenFromProps
143
+ }) {
144
+ const { locale } = useIntlLocale({ i18nStore, currentLocale });
145
+ const onIntlError = (err) => {
146
+ const typeSafe = i18nStore.typeSafe;
147
+ if (typeSafe) {
148
+ console.error(err);
149
+ }
150
+ };
151
+ const { isLoading } = useDynamicLocale({ i18nStore });
152
+ const children = typeof childrenFromProps === "function" ? childrenFromProps(locale) : childrenFromProps;
153
+ return /* @__PURE__ */ jsx(
154
+ ReactIntlProvider,
155
+ {
156
+ locale,
157
+ messages: i18nStore == null ? void 0 : i18nStore.localeSet[locale],
158
+ onError: onIntlError,
159
+ children: !isLoading && children
160
+ },
161
+ `sheet-i18n-locale-${locale}`
162
+ );
163
+ }
164
+ function useIntlLocale({
165
+ i18nStore,
166
+ currentLocale
167
+ }) {
168
+ const locale = currentLocale || detectClientLanguage(i18nStore) || i18nStore.defaultLocale;
169
+ i18nStore.setCurrentLocale(locale);
170
+ useEffect(() => {
171
+ i18nStore.setCurrentLocale(locale);
172
+ }, [locale]);
173
+ return {
174
+ locale
175
+ };
176
+ }
177
+ function detectClientLanguage(i18nStore) {
178
+ const { defaultLocale, supportedLocales } = i18nStore;
179
+ if (typeof navigator !== "undefined" && (navigator == null ? void 0 : navigator.languages)) {
180
+ const preferredLocale = navigator.languages.find(
181
+ (lang) => supportedLocales == null ? void 0 : supportedLocales.includes(lang)
182
+ );
183
+ return preferredLocale != null ? preferredLocale : defaultLocale;
184
+ }
185
+ return defaultLocale != null ? defaultLocale : "";
186
+ }
187
+
188
+ // src/Service/TranslationService.ts
189
+ import { validator as validator3 } from "@sheet-i18n/shared-utils";
190
+ var TranslationService = class {
191
+ constructor(intlInstance) {
192
+ this.intlInstance = intlInstance;
193
+ }
194
+ translate(id, values, opts, _descriptor) {
195
+ const descriptor = this.createDescriptor(id, _descriptor);
196
+ const targetTranslation = this.findTargetTranslation(id, {
197
+ descriptor,
198
+ values,
199
+ opts
200
+ });
201
+ return targetTranslation;
202
+ }
203
+ /** helpers */
204
+ createDescriptor(id, _descriptor) {
205
+ var _a;
206
+ return __spreadProps(__spreadValues({}, _descriptor != null ? _descriptor : {}), {
207
+ id,
208
+ defaultMessage: (_a = _descriptor == null ? void 0 : _descriptor.defaultMessage) != null ? _a : id
209
+ });
210
+ }
211
+ findTargetTranslation(id, $tParams) {
212
+ var _a, _b, _c, _d, _e;
213
+ const targetTranslation = (_b = (_a = this == null ? void 0 : this.intlInstance) == null ? void 0 : _a.messages) == null ? void 0 : _b[id];
214
+ if (validator3.isNullish(targetTranslation)) {
215
+ return id;
216
+ }
217
+ if (typeof targetTranslation === "string" && targetTranslation.trim() === "") {
218
+ return "";
219
+ }
220
+ if (!$tParams || !($tParams == null ? void 0 : $tParams.descriptor)) {
221
+ return "";
222
+ }
223
+ return (_e = (_d = (_c = this.intlInstance) == null ? void 0 : _c.$t) == null ? void 0 : _d.call(
224
+ _c,
225
+ $tParams.descriptor,
226
+ $tParams.values,
227
+ $tParams.opts
228
+ )) != null ? _e : "";
229
+ }
230
+ };
231
+
232
+ // src/hooks/useTranslation.ts
233
+ function useTranslation({
234
+ sheetTitle,
235
+ i18nStore,
236
+ rules
237
+ }) {
238
+ const intlInstance = intlInstanceCache.getCachedIntlInstance(
239
+ sheetTitle,
240
+ i18nStore
241
+ );
242
+ const translationService = new TranslationService(intlInstance);
243
+ const t = (id, values, opts, _descriptor) => {
244
+ return translationService.translate(id, values, opts, _descriptor);
245
+ };
246
+ t.dynamic = (id, values, opts, _descriptor) => {
247
+ return translationService.translate(id, values, opts, _descriptor);
248
+ };
249
+ t.rule = (ruleKey, values) => {
250
+ const ruleFn = rules == null ? void 0 : rules[ruleKey];
251
+ if (!ruleFn) return ruleKey;
252
+ const messageId = ruleFn(values, {});
253
+ return translationService.translate(messageId, values);
254
+ };
255
+ return { t };
256
+ }
257
+
258
+ // src/Errors.ts
259
+ import { CustomError } from "@sheet-i18n/errors";
260
+ var InvalidI18nContextStateError = class extends CustomError {
261
+ };
262
+ var IsNotInstanceOfI18nStoreError = class extends CustomError {
263
+ };
264
+
265
+ // src/hooks/getTranslation.ts
266
+ function getTranslation({
267
+ sheetTitle,
268
+ i18nStore
269
+ }) {
270
+ const t = (id, values, opts, _descriptor) => {
271
+ const intlInstance = intlInstanceCache.getCachedIntlInstance(
272
+ sheetTitle,
273
+ i18nStore,
274
+ "server"
275
+ );
276
+ const translationService = new TranslationService(intlInstance);
277
+ return translationService.translate(id, values, opts, _descriptor);
278
+ };
279
+ t.dynamic = (id, values, opts, _descriptor) => {
280
+ const intlInstance = intlInstanceCache.getCachedIntlInstance(
281
+ sheetTitle,
282
+ i18nStore,
283
+ "server"
284
+ );
285
+ const translationService = new TranslationService(intlInstance);
286
+ return translationService.translate(id, values, opts, _descriptor);
287
+ };
288
+ t.promise = (id, values, opts, _descriptor) => {
289
+ const intlInitPromise = new Promise((resolve) => {
290
+ setTimeout(() => {
291
+ const intlInstance = intlInstanceCache.getCachedIntlInstance(
292
+ sheetTitle,
293
+ i18nStore,
294
+ "server"
295
+ );
296
+ resolve(intlInstance);
297
+ }, 1);
298
+ });
299
+ return new Promise((resolve) => {
300
+ intlInitPromise.then((intlInstance) => {
301
+ const translationService = new TranslationService(intlInstance);
302
+ resolve(translationService.translate(id, values, opts, _descriptor));
303
+ });
304
+ });
305
+ };
306
+ return { t };
307
+ }
308
+
309
+ // src/Service/StorageService.ts
310
+ import { ObserverManager } from "@sheet-i18n/shared-utils";
311
+ var StorageService = class {
312
+ constructor(storage) {
313
+ this.storage = null;
314
+ this.isClientSide = typeof window !== "undefined";
315
+ if (storage) {
316
+ this.storage = this.validateStorage(storage);
317
+ } else if (this.isClientSide) {
318
+ this.storage = this.initializeWindowLocalStorage();
319
+ }
320
+ }
321
+ validateStorage(storage) {
322
+ const requiredMethods = [
323
+ "getItem",
324
+ "setItem",
325
+ "removeItem",
326
+ "clear"
327
+ ];
328
+ try {
329
+ for (const method of requiredMethods) {
330
+ if (typeof storage[method] !== "function") {
331
+ throw new Error(
332
+ `Invalid storage object: missing required method '${method}'`
333
+ );
334
+ }
335
+ }
336
+ return storage;
337
+ } catch (error) {
338
+ console.error(error);
339
+ return null;
340
+ }
341
+ }
342
+ initializeWindowLocalStorage() {
343
+ try {
344
+ const testKey = "__storage_test__";
345
+ localStorage.setItem(testKey, "test");
346
+ localStorage.removeItem(testKey);
347
+ return localStorage;
348
+ } catch (error) {
349
+ console.warn("Window LocalStorage is not available:", error);
350
+ return null;
351
+ }
352
+ }
353
+ getItem(key) {
354
+ if (!this.storage || !key) {
355
+ return "";
356
+ }
357
+ try {
358
+ return this.storage.getItem(key);
359
+ } catch (error) {
360
+ console.error(`Failed to get item with key "${key}":`, error);
361
+ return "";
362
+ }
363
+ }
364
+ setItem(key, value) {
365
+ if (!this.storage || !key) {
366
+ return false;
367
+ }
368
+ try {
369
+ this.storage.setItem(key, value);
370
+ return true;
371
+ } catch (error) {
372
+ console.error(`Failed to set item with key "${key}":`, error);
373
+ return false;
374
+ }
375
+ }
376
+ removeItem(key) {
377
+ if (!this.storage || !key) {
378
+ return false;
379
+ }
380
+ try {
381
+ this.storage.removeItem(key);
382
+ return true;
383
+ } catch (error) {
384
+ console.error(`Failed to remove item with key "${key}":`, error);
385
+ return false;
386
+ }
387
+ }
388
+ clear() {
389
+ if (!this.storage) {
390
+ return false;
391
+ }
392
+ try {
393
+ this.storage.clear();
394
+ return true;
395
+ } catch (error) {
396
+ console.error("Failed to clear storage:", error);
397
+ return false;
398
+ }
399
+ }
400
+ };
401
+ var LocaleStorageManager = class {
402
+ constructor(storageService, i18nStore, localeStorageKey = "sheet-i18n-locale") {
403
+ this.storageService = storageService;
404
+ this.i18nStore = i18nStore;
405
+ this.localeStorageKey = localeStorageKey;
406
+ this.observerManager = new ObserverManager();
407
+ this.initializeCurrentLocale = () => {
408
+ var _a, _b;
409
+ const storedLocale = this.storageService.getItem(this.localeStorageKey);
410
+ if (!storedLocale || storedLocale === "") {
411
+ const defaultLocale = this.i18nStore.currentLocale || this.i18nStore.defaultLocale;
412
+ this.storageService.setItem(this.localeStorageKey, defaultLocale);
413
+ }
414
+ (_b = (_a = this.i18nStore) == null ? void 0 : _a.observerManager) == null ? void 0 : _b.addListener({
415
+ listenerId: this.localeStorageKey,
416
+ listener: (newLocale) => {
417
+ this.storageService.setItem(this.localeStorageKey, newLocale);
418
+ }
419
+ });
420
+ };
421
+ this.getLocale = () => {
422
+ const stored = this.storageService.getItem(this.localeStorageKey);
423
+ if (!stored || stored === "") {
424
+ return this.i18nStore.defaultLocale;
425
+ }
426
+ return stored;
427
+ };
428
+ this.setLocale = (locale) => {
429
+ this.storageService.setItem(this.localeStorageKey, locale);
430
+ this.observerManager.notify(locale);
431
+ };
432
+ this.initializeCurrentLocale();
433
+ }
434
+ };
435
+ var getLocaleStorageManager = (i18nStore, storage) => {
436
+ const localeStorageService = new StorageService(storage);
437
+ const localeStorageManager = new LocaleStorageManager(
438
+ localeStorageService,
439
+ i18nStore
440
+ );
441
+ return localeStorageManager;
442
+ };
443
+
444
+ // src/hooks/useLocaleStorage.ts
445
+ import { useEffect as useEffect2, useState as useState2 } from "react";
446
+ var LISTENER_ID = "LOCALE_STORAGE_LISTENER_ID";
447
+ function useLocaleStorage(localeStorageManager) {
448
+ const [locale, setLocale] = useState2();
449
+ useEffect2(() => {
450
+ const storedLocale = localeStorageManager.getLocale();
451
+ setLocale(storedLocale);
452
+ }, []);
453
+ useEffect2(() => {
454
+ var _a;
455
+ (_a = localeStorageManager == null ? void 0 : localeStorageManager.observerManager) == null ? void 0 : _a.addListener({
456
+ listenerId: LISTENER_ID,
457
+ listener: (newLocale) => {
458
+ setLocale(newLocale);
459
+ }
460
+ });
461
+ return () => {
462
+ var _a2;
463
+ (_a2 = localeStorageManager == null ? void 0 : localeStorageManager.observerManager) == null ? void 0 : _a2.removeListener(LISTENER_ID);
464
+ };
465
+ }, []);
466
+ return { locale };
467
+ }
468
+
469
+ // src/Provider/StorageBasedIntlProvider.tsx
470
+ import { validator as validator4 } from "@sheet-i18n/shared-utils";
471
+ import { jsx as jsx2 } from "react/jsx-runtime";
472
+ function StorageBasedIntlProvider({
473
+ i18nStore,
474
+ storageManager,
475
+ fallbackUI = null,
476
+ children: childrenFromProps
477
+ }) {
478
+ const { locale } = useLocaleStorage(storageManager);
479
+ if (validator4.isNullish(locale)) {
480
+ return fallbackUI;
481
+ }
482
+ const children = typeof childrenFromProps === "function" ? childrenFromProps(locale) : childrenFromProps;
483
+ return /* @__PURE__ */ jsx2(IntlProvider, { currentLocale: locale, i18nStore, children });
484
+ }
485
+
486
+ // src/createI18nContext.tsx
487
+ import { jsx as jsx3 } from "react/jsx-runtime";
488
+ function createI18nContext(i18nStore, plugins) {
489
+ if (validator5.isNullish(i18nStore)) {
490
+ throw new InvalidI18nContextStateError(
491
+ "\u26A0\uFE0F no i18nStore provided. To use createI18nContext, you must provide an i18nStore as a parameter"
492
+ );
493
+ }
494
+ if (i18nStore instanceof I18nStore !== true) {
495
+ throw new IsNotInstanceOfI18nStoreError(
496
+ "\u26A0\uFE0F The provided i18nStore is invalid. Please ensure a store instance you passed is an instance of I18nStore."
497
+ );
498
+ }
499
+ const { rules } = plugins != null ? plugins : {};
500
+ const IntlProviderImpl = ({
501
+ currentLocale,
502
+ children
503
+ }) => /* @__PURE__ */ jsx3(
504
+ IntlProvider,
505
+ {
506
+ currentLocale,
507
+ i18nStore,
508
+ children
509
+ }
510
+ );
511
+ const StorageBasedIntlProviderImpl = ({
512
+ storageManager,
513
+ children
514
+ }) => /* @__PURE__ */ jsx3(
515
+ StorageBasedIntlProvider,
516
+ {
517
+ i18nStore,
518
+ storageManager,
519
+ children
520
+ }
521
+ );
522
+ const useTranslationImpl = (sheetTitle) => useTranslation({ sheetTitle, i18nStore, rules });
523
+ const getTranslationImpl = (sheetTitle) => getTranslation({ sheetTitle, i18nStore });
524
+ const getLocaleStorageManagerImpl = (storageService) => {
525
+ return getLocaleStorageManager(i18nStore, storageService);
526
+ };
527
+ return {
528
+ IntlProvider: IntlProviderImpl,
529
+ StorageBasedIntlProvider: StorageBasedIntlProviderImpl,
530
+ useTranslation: useTranslationImpl,
531
+ getTranslation: getTranslationImpl,
532
+ getLocaleStorageManager: getLocaleStorageManagerImpl,
533
+ useLocaleStorage
534
+ };
535
+ }
536
+
537
+ // src/Service/RuleService.ts
538
+ var RuleService = class {
539
+ constructor(i18nStore) {
540
+ this.i18nStore = i18nStore;
541
+ this.createRule = (ruleFn) => {
542
+ const currentLocaleSet = this.i18nStore.getCurrentLocaleSet();
543
+ return (values) => ruleFn(values, currentLocaleSet);
544
+ };
545
+ }
546
+ };
547
+ var ruleFactory = (i18nStore) => {
548
+ return new RuleService(i18nStore);
549
+ };
550
+ export {
551
+ LocaleStorageManager,
552
+ createI18nContext,
553
+ ruleFactory
554
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sheet-i18n/react",
3
- "version": "1.6.1",
3
+ "version": "1.6.2-canary.0",
4
4
  "description": "i18n client logic based on react",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.mjs",
@@ -29,11 +29,16 @@
29
29
  "license": "ISC",
30
30
  "devDependencies": {
31
31
  "@swc/core": "^1.10.2",
32
+ "@types/react": "^19.0.2",
33
+ "@types/react-dom": "^19.0.2",
34
+ "react": "^19.0.0",
32
35
  "@sheet-i18n/typescript-config": "1.8.1"
33
36
  },
34
37
  "dependencies": {
35
- "@sheet-i18n/react-client": "1.6.1",
36
- "@sheet-i18n/react-core": "1.6.0"
38
+ "react-intl": "^7.0.4",
39
+ "@sheet-i18n/core": "1.6.1-canary.0",
40
+ "@sheet-i18n/errors": "1.8.1",
41
+ "@sheet-i18n/shared-utils": "1.8.2"
37
42
  },
38
43
  "peerDependencies": {
39
44
  "react": "^18 || ^19 || ^20 || ^21",