@modern-js/plugin-i18n 2.69.7 → 3.0.0-alpha.1

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.
Files changed (151) hide show
  1. package/README.md +6 -0
  2. package/dist/cjs/cli/index.cjs +154 -0
  3. package/dist/cjs/runtime/I18nLink.cjs +68 -0
  4. package/dist/cjs/runtime/context.cjs +138 -0
  5. package/dist/cjs/runtime/hooks.cjs +189 -0
  6. package/dist/cjs/runtime/i18n/backend/config.cjs +39 -0
  7. package/dist/cjs/runtime/i18n/backend/defaults.cjs +56 -0
  8. package/dist/cjs/runtime/i18n/backend/defaults.node.cjs +56 -0
  9. package/dist/cjs/runtime/i18n/backend/index.cjs +108 -0
  10. package/dist/cjs/runtime/i18n/backend/middleware.cjs +54 -0
  11. package/dist/cjs/runtime/i18n/backend/middleware.common.cjs +105 -0
  12. package/dist/cjs/runtime/i18n/backend/middleware.node.cjs +58 -0
  13. package/dist/cjs/runtime/i18n/backend/sdk-backend.cjs +171 -0
  14. package/dist/cjs/runtime/i18n/detection/config.cjs +63 -0
  15. package/dist/cjs/runtime/i18n/detection/index.cjs +309 -0
  16. package/dist/cjs/runtime/i18n/detection/middleware.cjs +185 -0
  17. package/dist/cjs/runtime/i18n/detection/middleware.node.cjs +74 -0
  18. package/dist/cjs/runtime/i18n/index.cjs +43 -0
  19. package/dist/cjs/runtime/i18n/instance.cjs +132 -0
  20. package/dist/cjs/runtime/i18n/utils.cjs +185 -0
  21. package/dist/cjs/runtime/index.cjs +172 -0
  22. package/dist/cjs/runtime/types.cjs +18 -0
  23. package/dist/cjs/runtime/utils.cjs +134 -0
  24. package/dist/cjs/server/index.cjs +178 -0
  25. package/dist/cjs/shared/deepMerge.cjs +54 -0
  26. package/dist/cjs/shared/detection.cjs +105 -0
  27. package/dist/cjs/shared/type.cjs +18 -0
  28. package/dist/cjs/shared/utils.cjs +78 -0
  29. package/dist/esm/cli/index.js +106 -0
  30. package/dist/esm/runtime/I18nLink.js +31 -0
  31. package/dist/esm/runtime/context.js +101 -0
  32. package/dist/esm/runtime/hooks.js +146 -0
  33. package/dist/esm/runtime/i18n/backend/config.js +5 -0
  34. package/dist/esm/runtime/i18n/backend/defaults.js +19 -0
  35. package/dist/esm/runtime/i18n/backend/defaults.node.js +19 -0
  36. package/dist/esm/runtime/i18n/backend/index.js +74 -0
  37. package/dist/esm/runtime/i18n/backend/middleware.common.js +61 -0
  38. package/dist/esm/runtime/i18n/backend/middleware.js +7 -0
  39. package/dist/esm/runtime/i18n/backend/middleware.node.js +8 -0
  40. package/dist/esm/runtime/i18n/backend/sdk-backend.js +137 -0
  41. package/dist/esm/runtime/i18n/detection/config.js +26 -0
  42. package/dist/esm/runtime/i18n/detection/index.js +260 -0
  43. package/dist/esm/runtime/i18n/detection/middleware.js +132 -0
  44. package/dist/esm/runtime/i18n/detection/middleware.node.js +31 -0
  45. package/dist/esm/runtime/i18n/index.js +3 -0
  46. package/dist/esm/runtime/i18n/instance.js +77 -0
  47. package/dist/esm/runtime/i18n/utils.js +136 -0
  48. package/dist/esm/runtime/index.js +129 -0
  49. package/dist/esm/runtime/types.js +0 -0
  50. package/dist/esm/runtime/utils.js +82 -0
  51. package/dist/esm/server/index.js +168 -0
  52. package/dist/esm/shared/deepMerge.js +20 -0
  53. package/dist/esm/shared/detection.js +71 -0
  54. package/dist/esm/shared/type.js +0 -0
  55. package/dist/esm/shared/utils.js +35 -0
  56. package/dist/esm-node/cli/index.js +106 -0
  57. package/dist/esm-node/runtime/I18nLink.js +31 -0
  58. package/dist/esm-node/runtime/context.js +101 -0
  59. package/dist/esm-node/runtime/hooks.js +146 -0
  60. package/dist/esm-node/runtime/i18n/backend/config.js +5 -0
  61. package/dist/esm-node/runtime/i18n/backend/defaults.js +19 -0
  62. package/dist/esm-node/runtime/i18n/backend/defaults.node.js +19 -0
  63. package/dist/esm-node/runtime/i18n/backend/index.js +74 -0
  64. package/dist/esm-node/runtime/i18n/backend/middleware.common.js +61 -0
  65. package/dist/esm-node/runtime/i18n/backend/middleware.js +7 -0
  66. package/dist/esm-node/runtime/i18n/backend/middleware.node.js +8 -0
  67. package/dist/esm-node/runtime/i18n/backend/sdk-backend.js +137 -0
  68. package/dist/esm-node/runtime/i18n/detection/config.js +26 -0
  69. package/dist/esm-node/runtime/i18n/detection/index.js +260 -0
  70. package/dist/esm-node/runtime/i18n/detection/middleware.js +132 -0
  71. package/dist/esm-node/runtime/i18n/detection/middleware.node.js +31 -0
  72. package/dist/esm-node/runtime/i18n/index.js +3 -0
  73. package/dist/esm-node/runtime/i18n/instance.js +77 -0
  74. package/dist/esm-node/runtime/i18n/utils.js +136 -0
  75. package/dist/esm-node/runtime/index.js +129 -0
  76. package/dist/esm-node/runtime/types.js +0 -0
  77. package/dist/esm-node/runtime/utils.js +82 -0
  78. package/dist/esm-node/server/index.js +168 -0
  79. package/dist/esm-node/shared/deepMerge.js +20 -0
  80. package/dist/esm-node/shared/detection.js +71 -0
  81. package/dist/esm-node/shared/type.js +0 -0
  82. package/dist/esm-node/shared/utils.js +35 -0
  83. package/dist/types/cli/index.d.ts +21 -0
  84. package/dist/types/runtime/I18nLink.d.ts +8 -0
  85. package/dist/types/runtime/context.d.ts +38 -0
  86. package/dist/types/runtime/hooks.d.ts +28 -0
  87. package/dist/types/runtime/i18n/backend/config.d.ts +2 -0
  88. package/dist/types/runtime/i18n/backend/defaults.d.ts +13 -0
  89. package/dist/types/runtime/i18n/backend/defaults.node.d.ts +8 -0
  90. package/dist/types/runtime/i18n/backend/index.d.ts +3 -0
  91. package/dist/types/runtime/i18n/backend/middleware.common.d.ts +14 -0
  92. package/dist/types/runtime/i18n/backend/middleware.d.ts +12 -0
  93. package/dist/types/runtime/i18n/backend/middleware.node.d.ts +13 -0
  94. package/dist/types/runtime/i18n/backend/sdk-backend.d.ts +52 -0
  95. package/dist/types/runtime/i18n/detection/config.d.ts +11 -0
  96. package/dist/types/runtime/i18n/detection/index.d.ts +50 -0
  97. package/dist/types/runtime/i18n/detection/middleware.d.ts +24 -0
  98. package/dist/types/runtime/i18n/detection/middleware.node.d.ts +17 -0
  99. package/dist/types/runtime/i18n/index.d.ts +3 -0
  100. package/dist/types/runtime/i18n/instance.d.ts +93 -0
  101. package/dist/types/runtime/i18n/utils.d.ts +29 -0
  102. package/dist/types/runtime/index.d.ts +20 -0
  103. package/dist/types/runtime/types.d.ts +15 -0
  104. package/dist/types/runtime/utils.d.ts +33 -0
  105. package/dist/types/server/index.d.ts +8 -0
  106. package/dist/types/shared/deepMerge.d.ts +1 -0
  107. package/dist/types/shared/detection.d.ts +11 -0
  108. package/dist/types/shared/type.d.ts +156 -0
  109. package/dist/types/shared/utils.d.ts +5 -0
  110. package/package.json +100 -34
  111. package/rslib.config.mts +4 -0
  112. package/src/cli/index.ts +245 -0
  113. package/src/runtime/I18nLink.tsx +76 -0
  114. package/src/runtime/context.tsx +256 -0
  115. package/src/runtime/hooks.ts +274 -0
  116. package/src/runtime/i18n/backend/config.ts +10 -0
  117. package/src/runtime/i18n/backend/defaults.node.ts +31 -0
  118. package/src/runtime/i18n/backend/defaults.ts +37 -0
  119. package/src/runtime/i18n/backend/index.ts +181 -0
  120. package/src/runtime/i18n/backend/middleware.common.ts +116 -0
  121. package/src/runtime/i18n/backend/middleware.node.ts +32 -0
  122. package/src/runtime/i18n/backend/middleware.ts +28 -0
  123. package/src/runtime/i18n/backend/sdk-backend.ts +292 -0
  124. package/src/runtime/i18n/detection/config.ts +32 -0
  125. package/src/runtime/i18n/detection/index.ts +641 -0
  126. package/src/runtime/i18n/detection/middleware.node.ts +84 -0
  127. package/src/runtime/i18n/detection/middleware.ts +251 -0
  128. package/src/runtime/i18n/index.ts +8 -0
  129. package/src/runtime/i18n/instance.ts +227 -0
  130. package/src/runtime/i18n/utils.ts +333 -0
  131. package/src/runtime/index.tsx +281 -0
  132. package/src/runtime/types.ts +17 -0
  133. package/src/runtime/utils.ts +151 -0
  134. package/src/server/index.ts +336 -0
  135. package/src/shared/deepMerge.ts +38 -0
  136. package/src/shared/detection.ts +131 -0
  137. package/src/shared/type.ts +170 -0
  138. package/src/shared/utils.ts +82 -0
  139. package/tsconfig.json +12 -0
  140. package/dist/cjs/index.js +0 -73
  141. package/dist/cjs/languageDetector.js +0 -51
  142. package/dist/cjs/utils/index.js +0 -39
  143. package/dist/esm/index.js +0 -61
  144. package/dist/esm/languageDetector.js +0 -33
  145. package/dist/esm/utils/index.js +0 -16
  146. package/dist/esm-node/index.js +0 -49
  147. package/dist/esm-node/languageDetector.js +0 -26
  148. package/dist/esm-node/utils/index.js +0 -15
  149. package/dist/types/index.d.ts +0 -34
  150. package/dist/types/languageDetector.d.ts +0 -6
  151. package/dist/types/utils/index.d.ts +0 -5
@@ -0,0 +1,14 @@
1
+ import type { BaseBackendOptions, ChainedBackendConfig } from '../../../shared/type';
2
+ import type { I18nInstance } from '../instance';
3
+ type BackendConfigWithChained = BaseBackendOptions & Partial<ChainedBackendConfig>;
4
+ /**
5
+ * Common logic for using i18next backend
6
+ * This function handles the backend selection and chained backend configuration
7
+ *
8
+ * @param i18nInstance - The i18n instance to configure
9
+ * @param BackendWithSave - The wrapped backend class with save method (required for chained backend refresh logic)
10
+ * @param BackendBase - The base backend class (for non-chained use)
11
+ * @param backend - Optional backend configuration
12
+ */
13
+ export declare function useI18nextBackendCommon(i18nInstance: I18nInstance, BackendWithSave: new (...args: any[]) => any, BackendBase: new (...args: any[]) => any, backend?: BackendConfigWithChained): void;
14
+ export {};
@@ -0,0 +1,12 @@
1
+ import Backend from 'i18next-http-backend';
2
+ import type { ExtendedBackendOptions } from '../../../shared/type';
3
+ import type { I18nInstance } from '../instance';
4
+ /**
5
+ * Wrapper for HTTP backend to add a no-op save method
6
+ * This is required for i18next-chained-backend to trigger refresh logic
7
+ * when cacheHitMode is 'refresh' or 'refreshAndUpdateStore'
8
+ */
9
+ export declare class HttpBackendWithSave extends Backend {
10
+ save(_language: string, _namespace: string, _data: unknown): void;
11
+ }
12
+ export declare const useI18nextBackend: (i18nInstance: I18nInstance, backend?: ExtendedBackendOptions) => void;
@@ -0,0 +1,13 @@
1
+ import Backend from 'i18next-fs-backend';
2
+ import type { ExtendedBackendOptions } from '../../../shared/type';
3
+ import type { I18nInstance } from '../instance';
4
+ /**
5
+ * Wrapper for FS backend to add a no-op save method
6
+ * This is required for i18next-chained-backend to trigger refresh logic
7
+ * when cacheHitMode is 'refresh' or 'refreshAndUpdateStore'
8
+ */
9
+ export declare class FsBackendWithSave extends Backend {
10
+ save(_language: string, _namespace: string, _data: unknown): void;
11
+ }
12
+ export declare const HttpBackendWithSave: typeof FsBackendWithSave;
13
+ export declare const useI18nextBackend: (i18nInstance: I18nInstance, backend?: ExtendedBackendOptions) => void;
@@ -0,0 +1,52 @@
1
+ import type { I18nSdkLoader } from '../../../shared/type';
2
+ interface BackendOptions {
3
+ sdk?: I18nSdkLoader;
4
+ [key: string]: unknown;
5
+ }
6
+ interface I18nextServices {
7
+ resourceStore?: {
8
+ data?: {
9
+ [language: string]: {
10
+ [namespace: string]: Record<string, string>;
11
+ };
12
+ };
13
+ };
14
+ store?: {
15
+ data?: {
16
+ [language: string]: {
17
+ [namespace: string]: Record<string, string>;
18
+ };
19
+ };
20
+ };
21
+ [key: string]: any;
22
+ }
23
+ export declare class SdkBackend {
24
+ static type: string;
25
+ type: "backend";
26
+ sdk?: I18nSdkLoader;
27
+ private allResourcesCache;
28
+ private loadingPromises;
29
+ private services?;
30
+ constructor(_services: unknown, _options: Record<string, unknown>);
31
+ init(services: I18nextServices, backendOptions: BackendOptions, _i18nextOptions: unknown): void;
32
+ read(language: string, namespace: string, callback: (error: Error | null, data: unknown) => void): void;
33
+ create(_languages: string[], _namespace: string, _key: string, _fallbackValue: string): void;
34
+ isLoading(language: string, namespace: string): boolean;
35
+ getLoadingResources(): Array<{
36
+ language: string;
37
+ namespace: string;
38
+ }>;
39
+ hasLoadingResources(): boolean;
40
+ private getCacheKey;
41
+ private loadResource;
42
+ private handlePromise;
43
+ private normalizeError;
44
+ private callSdk;
45
+ private extractFromCache;
46
+ private updateCache;
47
+ private formatResources;
48
+ private isObject;
49
+ private mergeWithExistingResources;
50
+ private triggerI18nextUpdate;
51
+ }
52
+ export {};
@@ -0,0 +1,11 @@
1
+ import type { LanguageDetectorOptions } from '../instance';
2
+ export declare const DEFAULT_I18NEXT_DETECTION_OPTIONS: {
3
+ caches: string[];
4
+ order: string[];
5
+ cookieMinutes: number;
6
+ lookupQuerystring: string;
7
+ lookupCookie: string;
8
+ lookupLocalStorage: string;
9
+ lookupHeader: string;
10
+ };
11
+ export declare function mergeDetectionOptions(cliOptions?: LanguageDetectorOptions, userOptions?: LanguageDetectorOptions, defaultOptions?: LanguageDetectorOptions): LanguageDetectorOptions;
@@ -0,0 +1,50 @@
1
+ import { type TRuntimeContext } from '@modern-js/runtime';
2
+ import type { I18nInitOptions, I18nInstance, LanguageDetectorOptions } from '../instance';
3
+ import { cacheUserLanguage } from './middleware';
4
+ export { cacheUserLanguage };
5
+ export declare function exportServerLngToWindow(context: TRuntimeContext, lng: string): void;
6
+ export declare const getLanguageFromSSRData: (window: Window) => string | undefined;
7
+ export interface BaseLanguageDetectionOptions {
8
+ languages: string[];
9
+ fallbackLanguage: string;
10
+ localePathRedirect: boolean;
11
+ i18nextDetector: boolean;
12
+ detection?: LanguageDetectorOptions;
13
+ userInitOptions?: I18nInitOptions;
14
+ mergedBackend?: any;
15
+ }
16
+ export interface LanguageDetectionOptions extends BaseLanguageDetectionOptions {
17
+ pathname: string;
18
+ ssrContext?: any;
19
+ }
20
+ export interface LanguageDetectionResult {
21
+ detectedLanguage?: string;
22
+ finalLanguage: string;
23
+ }
24
+ /**
25
+ * Detect language with priority:
26
+ * Priority 1: SSR data (try window._SSR_DATA first, works for both SSR and CSR)
27
+ * Priority 2: Path detection
28
+ * Priority 3: i18next detector (reads from cookie/localStorage)
29
+ * Priority 4: User config language or fallback
30
+ */
31
+ export declare const detectLanguageWithPriority: (i18nInstance: I18nInstance, options: LanguageDetectionOptions) => Promise<LanguageDetectionResult>;
32
+ /**
33
+ * Options for building i18n init options
34
+ */
35
+ export interface BuildInitOptionsParams {
36
+ finalLanguage: string;
37
+ fallbackLanguage: string;
38
+ languages: string[];
39
+ userInitOptions?: I18nInitOptions;
40
+ mergedDetection?: any;
41
+ mergeBackend?: any;
42
+ }
43
+ /**
44
+ * Build i18n initialization options
45
+ */
46
+ export declare const buildInitOptions: (params: BuildInitOptionsParams) => I18nInitOptions;
47
+ /**
48
+ * Merge detection and backend options
49
+ */
50
+ export declare const mergeDetectionOptions: (i18nextDetector: boolean, detection?: LanguageDetectorOptions, localePathRedirect?: boolean, userInitOptions?: I18nInitOptions) => LanguageDetectorOptions;
@@ -0,0 +1,24 @@
1
+ import type { I18nInstance } from '../instance';
2
+ /**
3
+ * Register LanguageDetector plugin to i18n instance
4
+ * Must be called before init() to properly register the detector
5
+ * For wrapper instances, ensure detector is registered on the underlying i18next instance
6
+ */
7
+ export declare const useI18nextLanguageDetector: (i18nInstance: I18nInstance) => void | I18nInstance;
8
+ /**
9
+ * Read language directly from localStorage/cookie
10
+ * Fallback when detector is not available in services
11
+ */
12
+ export declare const readLanguageFromStorage: (detectionOptions?: any) => string | undefined;
13
+ /**
14
+ * Detect language using i18next-browser-languagedetector
15
+ * For initialized instances without detector in services, manually create a detector instance
16
+ * For wrapper instances, access the underlying i18next instance's services
17
+ */
18
+ export declare const detectLanguage: (i18nInstance: I18nInstance, _request?: any, detectionOptions?: any) => string | undefined;
19
+ /**
20
+ * Cache user language to localStorage/cookie
21
+ * Uses LanguageDetector's cacheUserLanguage method when available
22
+ * For wrapper instances, access the underlying i18next instance's services
23
+ */
24
+ export declare const cacheUserLanguage: (i18nInstance: I18nInstance, language: string, detectionOptions?: any) => void;
@@ -0,0 +1,17 @@
1
+ import type { I18nInstance } from '../instance';
2
+ export declare const cacheUserLanguage: (_i18nInstance: I18nInstance, _language: string, _detectionOptions?: any) => void;
3
+ /**
4
+ * Read language directly from storage (localStorage/cookie)
5
+ * Not available in Node.js environment, returns undefined
6
+ */
7
+ export declare const readLanguageFromStorage: (_detectionOptions?: any) => string | undefined;
8
+ /**
9
+ * Register LanguageDetector plugin to i18n instance
10
+ * Must be called before init() to properly register the detector
11
+ */
12
+ export declare const useI18nextLanguageDetector: (i18nInstance: I18nInstance) => void | I18nInstance;
13
+ /**
14
+ * Detect language using i18next-http-middleware LanguageDetector
15
+ * For initialized instances without detector in services, manually create a detector instance
16
+ */
17
+ export declare const detectLanguage: (i18nInstance: I18nInstance, request?: any, detectionOptions?: any) => string | undefined;
@@ -0,0 +1,3 @@
1
+ export type { I18nInstance, I18nInitOptions, } from './instance';
2
+ export { isI18nInstance, getI18nInstance } from './instance';
3
+ export { assertI18nInstance } from './utils';
@@ -0,0 +1,93 @@
1
+ import type { BaseBackendOptions } from '../../shared/type';
2
+ export interface I18nResourceStore {
3
+ data?: {
4
+ [language: string]: {
5
+ [namespace: string]: string | {
6
+ [key: string]: any;
7
+ };
8
+ };
9
+ };
10
+ addResourceBundle?: (language: string, namespace: string, resources: Record<string, string>, deep?: boolean, overwrite?: boolean) => void;
11
+ }
12
+ export declare function isI18nWrapperInstance(obj: any): boolean;
13
+ export declare function getI18nWrapperI18nextInstance(wrapperInstance: any): any;
14
+ export declare function getActualI18nextInstance(instance: I18nInstance | any): any;
15
+ export interface I18nInstance {
16
+ language: string;
17
+ isInitialized: boolean;
18
+ init: {
19
+ (callback?: (error: any, t: any) => void): Promise<any>;
20
+ (options: I18nInitOptions, callback?: (error: any, t: any) => void): Promise<any>;
21
+ };
22
+ changeLanguage?: (lng?: string, callback?: (error: any, t: any) => void) => Promise<any>;
23
+ setLang?: (lang: string) => void | Promise<void>;
24
+ use: (plugin: any) => void;
25
+ createInstance: (options?: I18nInitOptions) => I18nInstance;
26
+ cloneInstance?: () => I18nInstance;
27
+ store?: I18nResourceStore;
28
+ emit?: (event: string, ...args: any[]) => void;
29
+ reloadResources?: (language?: string, namespace?: string) => Promise<void>;
30
+ services?: {
31
+ languageDetector?: {
32
+ detect: (request?: any, options?: any) => string | string[] | undefined;
33
+ [key: string]: any;
34
+ };
35
+ resourceStore?: I18nResourceStore;
36
+ backend?: any;
37
+ [key: string]: any;
38
+ };
39
+ options?: {
40
+ backend?: BackendOptions;
41
+ [key: string]: any;
42
+ };
43
+ [key: string]: any;
44
+ }
45
+ type LanguageDetectorOrder = string[];
46
+ type LanguageDetectorCaches = boolean | string[];
47
+ export interface LanguageDetectorOptions {
48
+ order?: LanguageDetectorOrder;
49
+ lookupQuerystring?: string;
50
+ lookupCookie?: string;
51
+ lookupLocalStorage?: string;
52
+ lookupSession?: string;
53
+ lookupFromPathIndex?: number;
54
+ caches?: LanguageDetectorCaches;
55
+ cookieExpirationDate?: Date;
56
+ cookieDomain?: string;
57
+ lookupHeader?: string;
58
+ }
59
+ export interface BackendOptions extends Omit<BaseBackendOptions, 'enabled'> {
60
+ parse?: (data: string) => any;
61
+ stringify?: (data: any) => string;
62
+ [key: string]: any;
63
+ }
64
+ export interface Resources {
65
+ [lng: string]: {
66
+ [source: string]: string | Record<string, string>;
67
+ };
68
+ }
69
+ export type I18nInitOptions = {
70
+ lng?: string;
71
+ fallbackLng?: string;
72
+ supportedLngs?: string[];
73
+ initImmediate?: boolean;
74
+ detection?: LanguageDetectorOptions;
75
+ backend?: BackendOptions;
76
+ resources?: Resources;
77
+ ns?: string | string[];
78
+ defaultNS?: string | string[];
79
+ interpolation?: {
80
+ escapeValue?: boolean;
81
+ [key: string]: any;
82
+ };
83
+ react?: {
84
+ useSuspense?: boolean;
85
+ [key: string]: any;
86
+ };
87
+ };
88
+ export declare function isI18nInstance(obj: any): obj is I18nInstance;
89
+ export declare function getI18nextInstanceForProvider(instance: I18nInstance | any): any;
90
+ export declare function getI18nInstance(userInstance?: I18nInstance | any): Promise<I18nInstance>;
91
+ export declare function getInitReactI18next(): Promise<import("i18next").ThirdPartyModule | null>;
92
+ export declare function getI18nextProvider(): Promise<import("react").FunctionComponent<import("react-i18next").I18nextProviderProps> | null>;
93
+ export {};
@@ -0,0 +1,29 @@
1
+ import type { BaseBackendOptions } from '../../shared/type';
2
+ import type { I18nInitOptions, I18nInstance } from './instance';
3
+ export declare function assertI18nInstance(obj: any): asserts obj is I18nInstance;
4
+ /**
5
+ * Build initialization options for i18n instance
6
+ */
7
+ export declare const buildInitOptions: (finalLanguage: string, fallbackLanguage: string, languages: string[], mergedDetection: any, mergedBackend: any, userInitOptions?: I18nInitOptions, useSuspense?: boolean, i18nInstance?: I18nInstance) => Promise<I18nInitOptions>;
8
+ /**
9
+ * Ensure i18n instance language matches the final detected language
10
+ */
11
+ export declare const ensureLanguageMatch: (i18nInstance: I18nInstance, finalLanguage: string) => Promise<void>;
12
+ /**
13
+ * Change language for i18n instance in onBeforeRender hook
14
+ * This function can be used by other runtime plugins to change language
15
+ * @param i18nInstance - The i18n instance
16
+ * @param newLang - The new language code to switch to
17
+ * @param options - Optional configuration
18
+ */
19
+ export declare const changeI18nLanguage: (i18nInstance: I18nInstance, newLang: string, options?: {
20
+ detectionOptions?: any;
21
+ }) => Promise<void>;
22
+ /**
23
+ * Initialize i18n instance if not already initialized
24
+ */
25
+ export declare const initializeI18nInstance: (i18nInstance: I18nInstance, finalLanguage: string, fallbackLanguage: string, languages: string[], mergedDetection: any, mergedBackend: any, userInitOptions?: I18nInitOptions, useSuspense?: boolean) => Promise<void>;
26
+ /**
27
+ * Setup cloned instance for SSR with backend support
28
+ */
29
+ export declare const setupClonedInstance: (i18nInstance: I18nInstance, finalLanguage: string, fallbackLanguage: string, languages: string[], backendEnabled: boolean, backend: BaseBackendOptions | undefined, i18nextDetector: boolean, detection: any, localePathRedirect: boolean, userInitOptions: I18nInitOptions | undefined) => Promise<void>;
@@ -0,0 +1,20 @@
1
+ import { type RuntimePlugin } from '@modern-js/runtime';
2
+ import type { BaseBackendOptions, BaseLocaleDetectionOptions } from '../shared/type';
3
+ import type { I18nInitOptions, I18nInstance } from './i18n';
4
+ import './types';
5
+ export type { I18nSdkLoader, I18nSdkLoadOptions } from '../shared/type';
6
+ export type { Resources } from './i18n/instance';
7
+ export interface I18nPluginOptions {
8
+ entryName?: string;
9
+ localeDetection?: BaseLocaleDetectionOptions;
10
+ backend?: BaseBackendOptions;
11
+ i18nInstance?: I18nInstance;
12
+ changeLanguage?: (lang: string) => void;
13
+ initOptions?: I18nInitOptions;
14
+ htmlLangAttr?: boolean;
15
+ [key: string]: any;
16
+ }
17
+ export declare const i18nPlugin: (options: I18nPluginOptions) => RuntimePlugin;
18
+ export { useModernI18n } from './context';
19
+ export { I18nLink } from './I18nLink';
20
+ export default i18nPlugin;
@@ -0,0 +1,15 @@
1
+ import type { I18nInitOptions, I18nInstance } from './i18n';
2
+ declare module '@modern-js/runtime' {
3
+ interface RuntimeConfig {
4
+ i18n?: {
5
+ i18nInstance?: I18nInstance;
6
+ changeLanguage?: (lang: string) => void;
7
+ setLang?: (lang: string) => void;
8
+ initOptions?: I18nInitOptions;
9
+ };
10
+ }
11
+ interface TInternalRuntimeContext {
12
+ i18nInstance?: I18nInstance;
13
+ changeLanguage?: (lang: string) => Promise<void>;
14
+ }
15
+ }
@@ -0,0 +1,33 @@
1
+ import { type TInternalRuntimeContext } from '@modern-js/runtime/context';
2
+ export declare const getPathname: (context: TInternalRuntimeContext) => string;
3
+ export declare const getEntryPath: () => string;
4
+ /**
5
+ * Helper function to get language from current pathname
6
+ * @param pathname - The current pathname
7
+ * @param languages - Array of supported languages
8
+ * @param fallbackLanguage - Fallback language when no language is detected
9
+ * @returns The detected language or fallback language
10
+ */
11
+ export declare const getLanguageFromPath: (pathname: string, languages: string[], fallbackLanguage: string) => string;
12
+ /**
13
+ * Helper function to build localized URL
14
+ * @param pathname - The current pathname
15
+ * @param language - The target language
16
+ * @param languages - Array of supported languages
17
+ * @returns The localized URL path
18
+ */
19
+ export declare const buildLocalizedUrl: (pathname: string, language: string, languages: string[]) => string;
20
+ export declare const detectLanguageFromPath: (pathname: string, languages: string[], localePathRedirect: boolean) => {
21
+ detected: boolean;
22
+ language?: string;
23
+ };
24
+ /**
25
+ * Check if the given pathname should ignore automatic locale redirect
26
+ */
27
+ export declare const shouldIgnoreRedirect: (pathname: string, languages: string[], ignoreRedirectRoutes?: string[] | ((pathname: string) => boolean)) => boolean;
28
+ export declare const useRouterHooks: () => {
29
+ navigate: any;
30
+ location: any;
31
+ params: any;
32
+ hasRouter: boolean;
33
+ };
@@ -0,0 +1,8 @@
1
+ import type { ServerPlugin } from '@modern-js/server-runtime';
2
+ import type { LocaleDetectionOptions } from '../shared/type';
3
+ export interface I18nPluginOptions {
4
+ localeDetection: LocaleDetectionOptions;
5
+ staticRoutePrefixes: string[];
6
+ }
7
+ export declare const i18nServerPlugin: (options: I18nPluginOptions) => ServerPlugin;
8
+ export default i18nServerPlugin;
@@ -0,0 +1 @@
1
+ export declare function deepMerge<T extends Record<string, any>>(defaultOptions: T, userOptions?: Partial<T>): T;
@@ -0,0 +1,11 @@
1
+ import type { LanguageDetectorOptions } from '../runtime/i18n/instance';
2
+ /**
3
+ * Detect language from request using the same detection logic as i18next
4
+ * This ensures consistency between server-side and client-side detection
5
+ */
6
+ export declare function detectLanguageFromRequest(req: {
7
+ url: string;
8
+ headers: {
9
+ get: (name: string) => string | null;
10
+ } | Headers;
11
+ }, languages: string[], detectionOptions?: LanguageDetectorOptions): string | null;
@@ -0,0 +1,156 @@
1
+ import type { LanguageDetectorOptions, Resources } from '../runtime/i18n/instance';
2
+ export interface BaseLocaleDetectionOptions {
3
+ localePathRedirect?: boolean;
4
+ i18nextDetector?: boolean;
5
+ languages?: string[];
6
+ fallbackLanguage?: string;
7
+ detection?: LanguageDetectorOptions;
8
+ ignoreRedirectRoutes?: string[] | ((pathname: string) => boolean);
9
+ }
10
+ export interface LocaleDetectionOptions extends BaseLocaleDetectionOptions {
11
+ localeDetectionByEntry?: Record<string, BaseLocaleDetectionOptions>;
12
+ }
13
+ /**
14
+ * Options for loading i18n resources via SDK
15
+ */
16
+ export interface I18nSdkLoadOptions {
17
+ /** Single language code to load (e.g., 'en', 'zh') */
18
+ lng?: string;
19
+ /** Single namespace to load (e.g., 'translation', 'common') */
20
+ ns?: string;
21
+ /** Multiple language codes to load */
22
+ lngs?: string[];
23
+ /** Multiple namespaces to load */
24
+ nss?: string[];
25
+ /** Load all available languages and namespaces */
26
+ all?: boolean;
27
+ }
28
+ /**
29
+ * SDK function to load i18n resources
30
+ * Supports multiple loading modes:
31
+ * 1. Single resource: sdk({ lng: 'en', ns: 'translation' })
32
+ * 2. Batch by languages: sdk({ lngs: ['en', 'zh'], ns: 'translation' })
33
+ * 3. Batch by namespaces: sdk({ lng: 'en', nss: ['translation', 'common'] })
34
+ * 4. Batch by both: sdk({ lngs: ['en', 'zh'], nss: ['translation', 'common'] })
35
+ * 5. Load all: sdk({ all: true }) or sdk()
36
+ *
37
+ * @param options - Loading options
38
+ * @returns Promise that resolves to resources object or the resources object directly
39
+ * Resources format: { [lng]: { [ns]: { [key]: value } } }
40
+ */
41
+ export type I18nSdkLoader = (options: I18nSdkLoadOptions) => Promise<Resources> | Resources;
42
+ /**
43
+ * Chained backend configuration
44
+ * Used internally when both loadPath and sdk are provided
45
+ */
46
+ export interface ChainedBackendConfig {
47
+ _useChainedBackend: boolean;
48
+ _chainedBackendConfig: {
49
+ backendOptions: Array<Record<string, unknown>>;
50
+ };
51
+ cacheHitMode?: 'none' | 'refresh' | 'refreshAndUpdateStore';
52
+ }
53
+ /**
54
+ * Extended backend options that may include chained backend configuration
55
+ */
56
+ export type ExtendedBackendOptions = BaseBackendOptions & Partial<ChainedBackendConfig>;
57
+ export interface BaseBackendOptions {
58
+ enabled?: boolean;
59
+ loadPath?: string;
60
+ addPath?: string;
61
+ /**
62
+ * Cache hit mode for chained backend (only effective when both `loadPath` and `sdk` are provided)
63
+ *
64
+ * - `'none'` (default): If the first backend returns resources, stop and don't try the next backend
65
+ * - `'refresh'`: Try to refresh the cache by loading from the next backend and update the cache
66
+ * - `'refreshAndUpdateStore'`: Try to refresh the cache by loading from the next backend,
67
+ * update the cache and also update the i18next resource store. This allows FS/HTTP resources
68
+ * to be displayed first, then SDK resources will update them asynchronously.
69
+ *
70
+ * @default 'refreshAndUpdateStore' when both loadPath and sdk are provided
71
+ */
72
+ cacheHitMode?: 'none' | 'refresh' | 'refreshAndUpdateStore';
73
+ /**
74
+ * SDK function to load i18n resources dynamically
75
+ *
76
+ * **Important**: In `modern.config.ts`, you can only set this to `true` or any identifier
77
+ * to enable SDK mode. The actual SDK function must be provided in `modern.runtime.ts`
78
+ * via `initOptions.backend.sdk`.
79
+ *
80
+ * When both `loadPath` (or FS backend) and `sdk` are provided, the plugin will automatically
81
+ * use `i18next-chained-backend` to chain multiple backends. The order will be:
82
+ * 1. HTTP/FS backend (primary) - loads from `loadPath` or file system first for quick initial display
83
+ * 2. SDK backend (fallback/update) - loads from the SDK function to update/refresh translations
84
+ *
85
+ * With `cacheHitMode: 'refreshAndUpdateStore'` (default), FS/HTTP resources will be displayed
86
+ * immediately, then SDK resources will be loaded asynchronously to update the translations.
87
+ *
88
+ * If only `sdk` is provided, it will be used instead of the default HTTP/FS backend
89
+ *
90
+ * @example In modern.config.ts - enable SDK mode
91
+ * ```ts
92
+ * backend: {
93
+ * enabled: true,
94
+ * sdk: true, // or any identifier, just to enable SDK mode
95
+ * }
96
+ * ```
97
+ *
98
+ * @example In modern.runtime.ts - provide the actual SDK function
99
+ * ```ts
100
+ * export default defineRuntimeConfig({
101
+ * i18n: {
102
+ * initOptions: {
103
+ * backend: {
104
+ * sdk: async (options) => {
105
+ * // Your SDK implementation
106
+ * if (options.all) {
107
+ * return await mySdk.getAllResources();
108
+ * }
109
+ * if (options.lng && options.ns) {
110
+ * return await mySdk.getResource(options.lng, options.ns);
111
+ * }
112
+ * // Handle other cases...
113
+ * }
114
+ * }
115
+ * }
116
+ * }
117
+ * });
118
+ * ```
119
+ *
120
+ * @example Single resource loading
121
+ * ```ts
122
+ * sdk: async (options) => {
123
+ * if (options.lng && options.ns) {
124
+ * const response = await fetch(`/api/i18n/${options.lng}/${options.ns}`);
125
+ * return response.json();
126
+ * }
127
+ * }
128
+ * ```
129
+ *
130
+ * @example Load all resources at once
131
+ * ```ts
132
+ * sdk: async (options) => {
133
+ * if (options?.all) {
134
+ * // Load all languages and namespaces
135
+ * return await mySdk.getAllResources();
136
+ * }
137
+ * // Handle other cases...
138
+ * }
139
+ * ```
140
+ *
141
+ * @example Batch loading
142
+ * ```ts
143
+ * sdk: async (options) => {
144
+ * if (options?.lngs && options?.nss) {
145
+ * // Load multiple languages and namespaces
146
+ * return await mySdk.getBatchResources(options.lngs, options.nss);
147
+ * }
148
+ * // Handle single or other cases...
149
+ * }
150
+ * ```
151
+ */
152
+ sdk?: I18nSdkLoader | boolean | string;
153
+ }
154
+ export interface BackendOptions extends BaseBackendOptions {
155
+ backendOptionsByEntry?: Record<string, BaseBackendOptions>;
156
+ }
@@ -0,0 +1,5 @@
1
+ import type { BaseBackendOptions, BaseLocaleDetectionOptions } from './type';
2
+ export declare function getEntryConfig<T extends Record<string, any>>(entryName: string, config: T, entryKey: string): T | undefined;
3
+ export declare function removeEntryConfigKey<T extends Record<string, any>>(config: T, entryKey: string): Omit<T, typeof entryKey>;
4
+ export declare function getLocaleDetectionOptions(entryName: string, localeDetection: BaseLocaleDetectionOptions): BaseLocaleDetectionOptions;
5
+ export declare function getBackendOptions(entryName: string, backend: BaseBackendOptions): BaseBackendOptions;