@bleedingdev/modern-js-i18n-integration 3.9.0-ultramodern.9 → 3.9.3-ultramodern.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.
@@ -1,399 +0,0 @@
1
- import {
2
- I18nNavigationProvider,
3
- type I18nRouterAdapter,
4
- type I18nRouterLinkTarget,
5
- useNativeI18nRouterAdapter,
6
- } from '@modern-js/plugin-i18n/runtime/no-react-i18next';
7
- import { isBrowser, RuntimeContext } from '@modern-js/runtime';
8
- import {
9
- InternalRuntimeContext,
10
- type TInternalRuntimeContext,
11
- type TRuntimeContext,
12
- } from '@modern-js/runtime/context';
13
- import { getRouterRuntimeState } from '@modern-js/runtime-extensions/router-state';
14
- import type React from 'react';
15
- import { useCallback, useContext, useSyncExternalStore } from 'react';
16
-
17
- type I18nRouterFramework = 'react-router' | 'tanstack' | string;
18
-
19
- interface I18nRouterLocation {
20
- pathname: string;
21
- search: string;
22
- hash: string;
23
- }
24
-
25
- interface I18nRouterNavigateOptions {
26
- replace?: boolean;
27
- state?: unknown;
28
- }
29
-
30
- type I18nRouterNavigate = (
31
- href: string,
32
- options?: I18nRouterNavigateOptions,
33
- ) => void | Promise<void>;
34
-
35
- type I18nRouterLink = React.ComponentType<{
36
- to: string;
37
- children?: React.ReactNode;
38
- [key: string]: unknown;
39
- }>;
40
-
41
- type RuntimeContextWithRouter = TRuntimeContext & {
42
- router?: {
43
- useInRouterContext?: () => boolean;
44
- useRouter?: (options?: { warn?: boolean }) => unknown;
45
- useLocation?: () => unknown;
46
- useNavigate?: () => I18nRouterNavigate;
47
- useParams?: () => Record<string, string>;
48
- useHref?: () => unknown;
49
- Link?: I18nRouterLink;
50
- };
51
- };
52
-
53
- type InternalRuntimeContextWithRouter = TInternalRuntimeContext & {
54
- router?: RuntimeContextWithRouter['router'];
55
- };
56
-
57
- type RouterInstance = {
58
- navigate?: (...args: any[]) => unknown;
59
- state?: {
60
- location?: unknown;
61
- matches?: Array<{ params?: Record<string, string> }>;
62
- };
63
- stores?: {
64
- location?: {
65
- get?: () => unknown;
66
- subscribe?: (listener: () => void) => () => void;
67
- };
68
- matches?: {
69
- get?: () => Array<{ params?: Record<string, string> }>;
70
- };
71
- };
72
- subscribe?:
73
- | ((listener: () => void) => () => void)
74
- | ((eventType: string, listener: () => void) => () => void);
75
- };
76
-
77
- const normalizeUrlPart = (value: unknown, prefix: '?' | '#'): string => {
78
- if (typeof value !== 'string' || !value) {
79
- return '';
80
- }
81
- return value.startsWith(prefix) ? value : `${prefix}${value}`;
82
- };
83
-
84
- const normalizeLocation = (location: unknown): I18nRouterLocation | null => {
85
- if (!location || typeof location !== 'object') {
86
- return null;
87
- }
88
-
89
- const locationValue = location as {
90
- pathname?: unknown;
91
- search?: unknown;
92
- searchStr?: unknown;
93
- hash?: unknown;
94
- };
95
-
96
- if (typeof locationValue.pathname !== 'string') {
97
- return null;
98
- }
99
-
100
- return {
101
- pathname: locationValue.pathname,
102
- search: normalizeUrlPart(
103
- typeof locationValue.search === 'string'
104
- ? locationValue.search
105
- : locationValue.searchStr,
106
- '?',
107
- ),
108
- hash: normalizeUrlPart(locationValue.hash, '#'),
109
- };
110
- };
111
-
112
- const getWindowLocation = (): I18nRouterLocation | null => {
113
- if (!isBrowser()) {
114
- return null;
115
- }
116
-
117
- return {
118
- pathname: window.location.pathname,
119
- search: window.location.search,
120
- hash: window.location.hash,
121
- };
122
- };
123
-
124
- const getRouterFramework = (
125
- runtimeContext: RuntimeContextWithRouter,
126
- internalContext: InternalRuntimeContextWithRouter,
127
- inReactRouter: boolean,
128
- ): I18nRouterFramework | undefined => {
129
- const framework =
130
- getRouterRuntimeState(internalContext)?.framework ||
131
- getRouterRuntimeState(runtimeContext)?.framework;
132
-
133
- if (framework) {
134
- return framework;
135
- }
136
-
137
- if (internalContext.router?.useRouter || runtimeContext.router?.useRouter) {
138
- return 'tanstack';
139
- }
140
-
141
- if (
142
- internalContext.router?.useLocation ||
143
- internalContext.router?.useHref ||
144
- runtimeContext.router?.useLocation ||
145
- runtimeContext.router?.useHref
146
- ) {
147
- return 'react-router';
148
- }
149
-
150
- if (inReactRouter) {
151
- return 'react-router';
152
- }
153
-
154
- return undefined;
155
- };
156
-
157
- const getRouterInstance = (
158
- internalContext: InternalRuntimeContextWithRouter,
159
- contextRouter?: RouterInstance | null,
160
- ): RouterInstance | null => {
161
- if (contextRouter) {
162
- return contextRouter;
163
- }
164
-
165
- const router = getRouterRuntimeState(internalContext)?.instance;
166
- if (!router || typeof router !== 'object') {
167
- return null;
168
- }
169
- return router as RouterInstance;
170
- };
171
-
172
- const getRouterStateLocation = (
173
- internalContext: InternalRuntimeContextWithRouter,
174
- contextRouter?: RouterInstance | null,
175
- ): I18nRouterLocation | null => {
176
- const router = getRouterInstance(internalContext, contextRouter);
177
- return (
178
- normalizeLocation(router?.stores?.location?.get?.()) ||
179
- normalizeLocation(router?.state?.location)
180
- );
181
- };
182
-
183
- const getRouterParams = (
184
- internalContext: InternalRuntimeContextWithRouter,
185
- contextRouter?: RouterInstance | null,
186
- ): Record<string, string> => {
187
- const router = getRouterInstance(internalContext, contextRouter);
188
- const matches = router?.stores?.matches?.get?.() || router?.state?.matches;
189
- if (!Array.isArray(matches)) {
190
- return {};
191
- }
192
-
193
- return matches.reduce<Record<string, string>>((params, match) => {
194
- if (match?.params) {
195
- Object.assign(params, match.params);
196
- }
197
- return params;
198
- }, {});
199
- };
200
-
201
- const getRouterSnapshot = (
202
- internalContext: InternalRuntimeContextWithRouter,
203
- contextRouter?: RouterInstance | null,
204
- ) => {
205
- const location = getRouterStateLocation(internalContext, contextRouter);
206
- const params = getRouterParams(internalContext, contextRouter);
207
- return JSON.stringify([
208
- location?.pathname ?? '',
209
- location?.search ?? '',
210
- location?.hash ?? '',
211
- Object.entries(params).sort(([left], [right]) => left.localeCompare(right)),
212
- ]);
213
- };
214
-
215
- const useIntegratedRouterAdapter = (): I18nRouterAdapter => {
216
- const runtimeContext = useContext(RuntimeContext) as RuntimeContextWithRouter;
217
- const internalContext = useContext(
218
- InternalRuntimeContext,
219
- ) as InternalRuntimeContextWithRouter;
220
- const routerApi = internalContext.router || runtimeContext.router;
221
- const native = useNativeI18nRouterAdapter();
222
- const inReactRouter = native.hasRouter;
223
- const reactRouterNavigate = native.navigate;
224
- const reactRouterLocation = inReactRouter ? native.location : null;
225
- const reactRouterParams = native.params;
226
- const framework = getRouterFramework(
227
- runtimeContext,
228
- internalContext,
229
- inReactRouter,
230
- );
231
- const contextUseRouter =
232
- !inReactRouter && framework === 'tanstack'
233
- ? internalContext.router?.useRouter || runtimeContext.router?.useRouter
234
- : undefined;
235
- const contextRouter = contextUseRouter
236
- ? (contextUseRouter({ warn: false }) as RouterInstance | null)
237
- : null;
238
- const hasRouter =
239
- framework === 'tanstack' ||
240
- framework === 'react-router' ||
241
- Boolean(reactRouterNavigate);
242
-
243
- const subscribeToRouter = useCallback(
244
- (update: () => void) => {
245
- const router = getRouterInstance(internalContext, contextRouter);
246
- if (!router) {
247
- return () => undefined;
248
- }
249
-
250
- const unsubscribers: Array<() => void> = [];
251
-
252
- if (
253
- framework === 'react-router' &&
254
- !inReactRouter &&
255
- typeof router.subscribe === 'function'
256
- ) {
257
- const subscribe = router.subscribe as (
258
- this: RouterInstance,
259
- listener: () => void,
260
- ) => () => void;
261
- const unsubscribe = subscribe.call(router, update);
262
- if (typeof unsubscribe === 'function') {
263
- unsubscribers.push(unsubscribe);
264
- }
265
- }
266
-
267
- if (
268
- framework === 'tanstack' &&
269
- typeof router.stores?.location?.subscribe === 'function'
270
- ) {
271
- const unsubscribe = router.stores.location.subscribe(update);
272
- if (typeof unsubscribe === 'function') {
273
- unsubscribers.push(unsubscribe);
274
- }
275
- }
276
-
277
- if (framework === 'tanstack' && typeof router.subscribe === 'function') {
278
- const subscribe = router.subscribe as (
279
- this: RouterInstance,
280
- eventType: string,
281
- listener: () => void,
282
- ) => () => void;
283
- for (const eventType of ['onBeforeNavigate', 'onBeforeLoad']) {
284
- const unsubscribe = subscribe.call(router, eventType, update);
285
- if (typeof unsubscribe === 'function') {
286
- unsubscribers.push(unsubscribe);
287
- }
288
- }
289
- }
290
-
291
- return () => {
292
- for (const unsubscribe of unsubscribers) {
293
- unsubscribe();
294
- }
295
- };
296
- },
297
- [contextRouter, framework, inReactRouter, internalContext],
298
- );
299
- const getSnapshot = useCallback(
300
- () => getRouterSnapshot(internalContext, contextRouter),
301
- [contextRouter, internalContext],
302
- );
303
- useSyncExternalStore(subscribeToRouter, getSnapshot, getSnapshot);
304
-
305
- const navigate = useCallback<I18nRouterNavigate>(
306
- (href, options) => {
307
- const router = getRouterInstance(internalContext, contextRouter);
308
- const activeFramework = getRouterFramework(
309
- runtimeContext,
310
- internalContext,
311
- inReactRouter,
312
- );
313
-
314
- if (activeFramework === 'tanstack') {
315
- if (typeof router?.navigate === 'function') {
316
- return router.navigate({
317
- to: href,
318
- replace: options?.replace,
319
- ...(options?.state === undefined ? {} : { state: options.state }),
320
- }) as void | Promise<void>;
321
- }
322
- throw new Error('TanStack router instance is not available.');
323
- }
324
-
325
- if (reactRouterNavigate) {
326
- return reactRouterNavigate(href, options);
327
- }
328
-
329
- if (activeFramework === 'react-router') {
330
- if (typeof router?.navigate === 'function') {
331
- return router.navigate(href, options) as void | Promise<void>;
332
- }
333
- throw new Error('React Router instance is not available.');
334
- }
335
- },
336
- [
337
- contextRouter,
338
- internalContext,
339
- inReactRouter,
340
- reactRouterNavigate,
341
- runtimeContext,
342
- ],
343
- );
344
-
345
- const location =
346
- (reactRouterLocation
347
- ? normalizeLocation(reactRouterLocation)
348
- : getRouterStateLocation(internalContext, contextRouter)) ||
349
- getWindowLocation();
350
- const params = inReactRouter
351
- ? (reactRouterParams as Record<string, string>)
352
- : getRouterParams(internalContext, contextRouter);
353
- const Link =
354
- framework === 'tanstack'
355
- ? internalContext.router?.Link || runtimeContext.router?.Link || null
356
- : framework === 'react-router' || inReactRouter
357
- ? (routerApi?.Link ?? null)
358
- : null;
359
-
360
- return {
361
- framework,
362
- hasRouter,
363
- location,
364
- navigate: hasRouter ? navigate : null,
365
- Link,
366
- params,
367
- ...(framework === 'tanstack'
368
- ? { createLinkProps: createTanstackLinkProps }
369
- : {}),
370
- };
371
- };
372
-
373
- const createTanstackLinkProps = (target: I18nRouterLinkTarget) => {
374
- const preload =
375
- target.preload !== undefined
376
- ? target.preload
377
- : target.prefetch === 'none'
378
- ? false
379
- : target.prefetch;
380
- return {
381
- to: target.pathname,
382
- ...(target.search ? { search: target.search } : {}),
383
- ...(target.hash ? { hash: target.hash } : {}),
384
- ...(target.hashScrollIntoView === undefined
385
- ? {}
386
- : { hashScrollIntoView: target.hashScrollIntoView }),
387
- ...(preload === undefined ? {} : { preload }),
388
- };
389
- };
390
-
391
- /** Supplies the actual selected router; native links still render its Link. */
392
- export const I18nRouterNavigationProvider = ({
393
- children,
394
- }: React.PropsWithChildren) => {
395
- const value = useIntegratedRouterAdapter();
396
- return (
397
- <I18nNavigationProvider value={value}>{children}</I18nNavigationProvider>
398
- );
399
- };
package/src/server.ts DELETED
@@ -1,27 +0,0 @@
1
- import { getLocaleDetectionOptions } from '@modern-js/plugin-i18n/config';
2
- import { i18nServerPlugin as nativeI18nServerPlugin } from '@modern-js/plugin-i18n/server';
3
- import type {
4
- I18nServerPluginOptions,
5
- IntegratedLocaleDetectionOptions,
6
- } from './options';
7
- import { createI18nUrlStrategy } from './urlStrategy';
8
-
9
- export const i18nServerPlugin = (options: I18nServerPluginOptions) =>
10
- nativeI18nServerPlugin({
11
- ...options,
12
- resolveUrlStrategy:
13
- options.resolveUrlStrategy ??
14
- (entryName =>
15
- createI18nUrlStrategy(
16
- options.localeDetection
17
- ? (
18
- getLocaleDetectionOptions(
19
- entryName,
20
- options.localeDetection,
21
- ) as IntegratedLocaleDetectionOptions
22
- ).localisedUrls
23
- : undefined,
24
- )),
25
- });
26
-
27
- export default i18nServerPlugin;