Replace i18n by a custom implementation (#638)

There are two problems with the current localization strategy:
- We download the translations on-demand, which means that it does a serial roundtrip for nothing.
- withTranslation helper actually renders the app 3 times on startup, instead of once (I haven't tried to debug it)
This commit is contained in:
Christopher Chedeau 2020-01-31 21:06:06 +00:00 committed by GitHub
parent 637276301a
commit e4919e2e6c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
21 changed files with 101 additions and 167 deletions

View file

@ -1,36 +1,68 @@
import i18n from "i18next";
import { initReactI18next } from "react-i18next";
import Backend from "i18next-xhr-backend";
import LanguageDetector from "i18next-browser-languagedetector";
export const fallbackLng = "en";
export function parseDetectedLang(lng: string | undefined): string {
if (lng) {
const [lang] = i18n.language.split("-");
return lang;
}
return fallbackLng;
}
export const languages = [
{ lng: "de", label: "Deutsch" },
{ lng: "en", label: "English" },
{ lng: "es", label: "Español" },
{ lng: "fr", label: "Français" },
{ lng: "pt", label: "Português" },
{ lng: "ru", label: "Русский" },
{ lng: "en", label: "English", data: require("./locales/en.json") },
{ lng: "de", label: "Deutsch", data: require("./locales/de.json") },
{ lng: "es", label: "Español", data: require("./locales/es.json") },
{ lng: "fr", label: "Français", data: require("./locales/fr.json") },
{ lng: "pt", label: "Português", data: require("./locales/pt.json") },
{ lng: "ru", label: "Русский", data: require("./locales/ru.json") },
];
i18n
.use(Backend)
.use(LanguageDetector)
.use(initReactI18next)
.init({
fallbackLng,
react: { useSuspense: false },
load: "languageOnly",
});
let currentLanguage = languages[0];
const fallbackLanguage = languages[0];
export default i18n;
export function setLanguage(newLng: string | undefined) {
currentLanguage =
languages.find(language => language.lng === newLng) || fallbackLanguage;
languageDetector.cacheUserLanguage(currentLanguage.lng);
}
export function getLanguage() {
return currentLanguage.lng;
}
function findPartsForData(data: any, parts: string[]) {
for (var i = 0; i < parts.length; ++i) {
const part = parts[i];
if (data[part] === undefined) {
return undefined;
}
data = data[part];
}
if (typeof data !== "string") {
return undefined;
}
return data;
}
export function t(path: string, replacement?: { [key: string]: string }) {
const parts = path.split(".");
let translation =
findPartsForData(currentLanguage.data, parts) ||
findPartsForData(fallbackLanguage.data, parts);
if (translation === undefined) {
throw new Error("Can't find translation for " + path);
}
if (replacement) {
for (var key in replacement) {
translation = translation.replace("{{" + key + "}}", replacement[key]);
}
}
return translation;
}
const languageDetector = new LanguageDetector();
languageDetector.init({
languageUtils: {
formatLanguageCode: function(lng: string) {
return lng;
},
isWhitelisted: () => true,
},
checkWhitelist: false,
});
setLanguage(languageDetector.detect());