-
Notifications
You must be signed in to change notification settings - Fork 9
/
index.ts
95 lines (81 loc) · 3.83 KB
/
index.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
import { isBrowser } from '@unly/utils';
import I18next from 'i18next';
import I18nextBrowserLanguageDetector from 'i18next-browser-languagedetector';
import includes from 'lodash.includes';
import get from 'lodash.get';
import AcceptLanguageDetector from './serverDetectors/acceptLanguage';
import ServerCookieDetector from './serverDetectors/serverCookie';
import FallbackDetector from './universalDetectors/fallback';
import { ErrorHandler } from './utils/error';
/**
* Lookup key that contains the value of the user's selected language
*
* @see https://github.com/i18next/i18next-browser-languageDetector#detector-options
*
* @type {string}
*/
export const COOKIE_LOOKUP_KEY_LANG = 'i18next';
/**
* Detects the user's language, universally (browser + server)
* Internally relies on i18next to help resolve the language
*
* Language lookup:
* - On the server, relies on cookies (provided), then on the accept-language header
* - On the browser, relies on cookies (global), then navigator's language
*
* @param props
* @return {string}
*/
export const universalLanguageDetect = (props: {
supportedLanguages: string[];
fallbackLanguage: string;
acceptLanguageHeader?: string | undefined;
serverCookies?: object | undefined;
errorHandler?: ErrorHandler | undefined;
}): string => {
const {
supportedLanguages,
fallbackLanguage,
acceptLanguageHeader = undefined,
serverCookies = undefined,
errorHandler = undefined,
} = props;
if(!get(supportedLanguages, 'length')){
throw new Error(`universal-language-detector is misconfigured. Your "supportedLanguages" should be an array containing at least one language (eg: ['en']).`);
}
if(!includes(supportedLanguages, fallbackLanguage)){
throw new Error(`universal-language-detector is misconfigured. Your "fallbackLanguage" (value: "${fallbackLanguage}") should be within your "supportedLanguages" array.`);
}
// Init may be async, but it doesn't matter here, because we just want to init the services (which is sync) so that we may use them
I18next.init({
whitelist: supportedLanguages, // Filter out unsupported languages (i.e: when using "navigator" detector) - See https://www.i18next.com/overview/configuration-options#languages-namespaces-resources
nonExplicitWhitelist: true, // We only provide "simple" supported languages ("en", "fr", etc.) - This option ensures en-US and alike are still matched and not ignored - See https://www.i18next.com/overview/configuration-options#languages-namespaces-resources
});
const i18nextServices = I18next.services;
const i18nextUniversalLanguageDetector = new I18nextBrowserLanguageDetector();
// Add common detectors between the browser and the server
const fallbackDetector = FallbackDetector(fallbackLanguage);
i18nextUniversalLanguageDetector.addDetector(fallbackDetector);
if (isBrowser()) {
// Rely on native i18next detectors
i18nextUniversalLanguageDetector.init(i18nextServices, {
order: ['cookie', 'navigator', fallbackDetector.name],
lookupCookie: COOKIE_LOOKUP_KEY_LANG,
});
} else {
// Use our own detectors
const serverCookieDetector = ServerCookieDetector(serverCookies);
const acceptLanguageDetector = AcceptLanguageDetector(supportedLanguages, acceptLanguageHeader, errorHandler);
i18nextUniversalLanguageDetector.addDetector(serverCookieDetector);
i18nextUniversalLanguageDetector.addDetector(acceptLanguageDetector);
i18nextUniversalLanguageDetector.init(i18nextServices, {
order: [serverCookieDetector.name, acceptLanguageDetector.name, fallbackDetector.name],
lookupCookie: COOKIE_LOOKUP_KEY_LANG,
});
}
// Transform potential localised language into non-localised language:
// "en-US" > "en"
// "en" > "en"
return (i18nextUniversalLanguageDetector.detect() as string).split('-')[0];
};
export default universalLanguageDetect;