Skip to content

Commit 46fbe74

Browse files
committed
feat: defind detection config and use middleware
1 parent cf31981 commit 46fbe74

File tree

4 files changed

+109
-0
lines changed

4 files changed

+109
-0
lines changed
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
import type { RuntimeContext } from '@modern-js/runtime';
2+
import { deepMerge } from '../../../shared/deepMerge';
3+
import type { LanguageDetectorOptions } from '../instance';
4+
5+
export const DEFAULT_I18NEXT_DETECTION_OPTIONS = {
6+
caches: ['cookie', 'localStorage'],
7+
order: [
8+
'querystring',
9+
'cookie',
10+
'localStorage',
11+
'header',
12+
'navigator',
13+
'htmlTag',
14+
'path',
15+
'subdomain',
16+
],
17+
cookieMinutes: 60 * 24 * 365,
18+
lookupQuerystring: 'lng',
19+
lookupCookie: 'i18next',
20+
lookupLocalStorage: 'i18nextLng',
21+
lookupHeader: 'accept-language',
22+
};
23+
24+
export function mergeDetectionOptions(
25+
userOptions?: LanguageDetectorOptions,
26+
defaultOptions: LanguageDetectorOptions = DEFAULT_I18NEXT_DETECTION_OPTIONS,
27+
): LanguageDetectorOptions {
28+
return deepMerge(defaultOptions, userOptions);
29+
}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
import { LanguageDetector } from 'i18next-http-middleware';
2+
import type { I18nInstance } from '../instance';
3+
4+
export const useI18nextLanguageDetector = (i18nInstance: I18nInstance) => {
5+
return i18nInstance.use(LanguageDetector);
6+
};
7+
8+
export const detectLanguage = (
9+
i18nInstance: I18nInstance,
10+
request?: any,
11+
): string | undefined => {
12+
const detector = i18nInstance.services?.languageDetector;
13+
if (detector && typeof detector.detect === 'function' && request) {
14+
try {
15+
const result = detector.detect(request, {});
16+
// detector.detect() can return string | string[] | undefined
17+
if (typeof result === 'string') {
18+
return result;
19+
}
20+
if (Array.isArray(result) && result.length > 0) {
21+
return result[0];
22+
}
23+
return undefined;
24+
} catch (error) {
25+
return undefined;
26+
}
27+
}
28+
return undefined;
29+
};
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
import LanguageDetector from 'i18next-browser-languagedetector';
2+
import type { I18nInstance } from '../instance';
3+
4+
export const useI18nextLanguageDetector = (i18nInstance: I18nInstance) => {
5+
return i18nInstance.use(LanguageDetector);
6+
};
7+
8+
export const detectLanguage = (
9+
i18nInstance: I18nInstance,
10+
_request?: any,
11+
): string | undefined => {
12+
// Access the detector from i18next services
13+
// The detector is registered via useI18nextLanguageDetector() and initialized in init()
14+
const detector = i18nInstance.services?.languageDetector;
15+
if (detector && typeof detector.detect === 'function') {
16+
try {
17+
const result = detector.detect();
18+
// detector.detect() can return string | string[] | undefined
19+
if (typeof result === 'string') {
20+
return result;
21+
}
22+
if (Array.isArray(result) && result.length > 0) {
23+
return result[0];
24+
}
25+
} catch (error) {
26+
return undefined;
27+
}
28+
}
29+
return undefined;
30+
};

packages/runtime/plugin-i18n/src/runtime/i18n/instance.ts

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,34 @@ export interface I18nInstance {
77
use: (plugin: any) => void;
88
createInstance: (options?: I18nInitOptions) => I18nInstance;
99
cloneInstance?: () => I18nInstance; // ssr need
10+
services?: {
11+
languageDetector?: {
12+
detect: (request?: any, options?: any) => string | string[] | undefined;
13+
[key: string]: any;
14+
};
15+
[key: string]: any;
16+
};
17+
}
18+
19+
type LanguageDetectorOrder = string[];
20+
type LanguageDetectorCaches = boolean | string[];
21+
export interface LanguageDetectorOptions {
22+
order?: LanguageDetectorOrder;
23+
lookupQuerystring?: string;
24+
lookupCookie?: string;
25+
lookupSession?: string;
26+
lookupFromPathIndex?: number;
27+
caches?: LanguageDetectorCaches;
28+
cookieExpirationDate?: Date;
29+
cookieDomain?: string;
1030
}
1131

1232
export type I18nInitOptions = {
1333
lng?: string;
1434
fallbackLng?: string;
1535
supportedLngs?: string[];
1636
initImmediate?: boolean;
37+
detection?: LanguageDetectorOptions;
1738
};
1839

1940
export function isI18nInstance(obj: any): obj is I18nInstance {

0 commit comments

Comments
 (0)