From 18a2bde62e10c2221445f13d5ade6424a70c6338 Mon Sep 17 00:00:00 2001 From: James Elliott Date: Sat, 1 Oct 2022 20:58:53 +1000 Subject: [PATCH] feat(web): i18n local storage detector (#3968) This adds a local storage detector to the language detector. It's a copy of the official localStorage detector without the ability to set the value. The advantage here is the official localStorage detector always sets the localStorage lookup, which means the most appropriate detected language will be set. If newer languages more appropriate appear this would represent a bad UX. --- web/src/i18n/detectors/localStorageCustom.ts | 41 ++++++++++++++++++++ web/src/i18n/index.ts | 10 ++++- 2 files changed, 49 insertions(+), 2 deletions(-) create mode 100644 web/src/i18n/detectors/localStorageCustom.ts diff --git a/web/src/i18n/detectors/localStorageCustom.ts b/web/src/i18n/detectors/localStorageCustom.ts new file mode 100644 index 000000000..6c48de244 --- /dev/null +++ b/web/src/i18n/detectors/localStorageCustom.ts @@ -0,0 +1,41 @@ +import { CustomDetector, DetectorOptions } from "i18next-browser-languagedetector"; + +let hasLocalStorageSupport: null | boolean = null; +const testKey = "authelia.test"; +const testValue = "foo"; + +const localStorageAvailable = () => { + if (hasLocalStorageSupport !== null) return hasLocalStorageSupport; + + if (typeof window !== "undefined" && window.localStorage !== null) { + hasLocalStorageSupport = true; + + try { + window.localStorage.setItem(testKey, testValue); + window.localStorage.removeItem(testKey); + } catch (e) { + hasLocalStorageSupport = false; + } + } + + return hasLocalStorageSupport; +}; + +const LocalStorageCustomDetector: CustomDetector = { + name: "localStorageCustom", + + lookup(options: DetectorOptions): string | undefined { + let found; + + if (options.lookupLocalStorage && localStorageAvailable()) { + const lng = window.localStorage.getItem(options.lookupLocalStorage); + if (lng && lng !== "") { + found = lng; + } + } + + return found; + }, +}; + +export default LocalStorageCustomDetector; diff --git a/web/src/i18n/index.ts b/web/src/i18n/index.ts index a5cad3724..63cfd5edf 100644 --- a/web/src/i18n/index.ts +++ b/web/src/i18n/index.ts @@ -9,17 +9,23 @@ import LanguageDetector from "i18next-browser-languagedetector"; import Backend from "i18next-http-backend"; import { initReactI18next } from "react-i18next"; +import LocalStorageCustomDetector from "@i18n/detectors/localStorageCustom"; import { getBasePath } from "@utils/BasePath"; const basePath = getBasePath(); +const CustomLanguageDetector = new LanguageDetector(); + +CustomLanguageDetector.addDetector(LocalStorageCustomDetector); + i18n.use(Backend) - .use(LanguageDetector) + .use(CustomLanguageDetector) .use(initReactI18next) .init({ detection: { - order: ["querystring", "navigator"], + order: ["querystring", "localStorageCustom", "navigator"], lookupQuerystring: "lng", + lookupLocalStorage: "lng", }, backend: { loadPath: basePath + "/locales/{{lng}}/{{ns}}.json",