Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 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 | 633x 633x 633x 633x 645x 633x 1486x 633x | import i18next from "i18next";
import languageDetector from "i18next-browser-languagedetector";
import { initReactI18next } from "react-i18next";
import { Locale } from "shared/types/locale";
import { translationEN } from "client/locales/en";
import { translationFI } from "client/locales/fi";
export const defaultNS = "ns1";
const fallbackLanguage = Locale.EN;
export const resources = {
en: {
ns1: translationEN,
},
fi: {
ns1: translationFI,
},
};
// The document declares a language in its markup, which is only right for
// whichever language happens to render first. A browser that finds the content
// in a different language than the one declared offers to translate the page,
// and the translation replaces React's text nodes, so the next commit throws on
// nodes that have moved. Registered before init so the language i18next
// resolves during startup is applied too.
i18next.on("languageChanged", () => {
document.documentElement.lang = i18next.resolvedLanguage ?? fallbackLanguage;
});
// eslint-disable-next-line @typescript-eslint/no-floating-promises
i18next
.use(languageDetector)
.use(initReactI18next)
.init({
resources,
fallbackLng: fallbackLanguage, // use if detected lng is not available
interpolation: {
escapeValue: false, // react escapes by default -> safe from xss
},
// Without this a Finnish browser lands on the English UI, and users reach
// for the browser's translate button instead of the language selector.
// Browser translation rewrites the DOM under React, which breaks the next
// commit outright, so the default language is what keeps the app standing.
supportedLngs: [Locale.EN, Locale.FI],
detection: {
order: ["localStorage", "navigator"],
// The rest of the app compares against the bare language codes and the
// stored value is parsed strictly against them, so a region-tagged
// "fi-FI" has to be narrowed before it is used or cached
convertDetectedLanguage: (language) => language.split("-", 1)[0],
},
defaultNS,
returnNull: false,
});
// https://dev.to/pffigueiredo/typescript-utility-keyof-nested-object-2pa3
type NestedKeyOf<ObjectType extends object> = {
[Key in keyof ObjectType & (string | number)]: ObjectType[Key] extends object
? `${Key}` | `${Key}.${NestedKeyOf<ObjectType[Key]>}`
: `${Key}`;
}[keyof ObjectType & (string | number)];
type Equals<X, Y> = [X, Y] extends [Y, X] ? true : false;
/* eslint-disable @typescript-eslint/no-unused-vars */
// If following gives type error, EN and FI language files don't match
const expectLocalesToMatch: Equals<
NestedKeyOf<typeof translationEN>,
NestedKeyOf<typeof translationFI>
> = true;
/* eslint-enable @typescript-eslint/no-unused-vars */
|