diff --git a/front/app/_middleware.ts b/front/app/_middleware.ts index 2bd53614..206a0032 100644 --- a/front/app/_middleware.ts +++ b/front/app/_middleware.ts @@ -1,5 +1,5 @@ import { createMiddleware, setServerData } from "one"; -import { supportedLanguages } from "~/providers/translations.ssr"; +import { supportedLanguages } from "~/providers/translations.web.ssr"; export default createMiddleware(({ request, next }) => { const systemLanguage = request.headers diff --git a/front/app/translations+api.ts b/front/app/translations+api.ts index c0ba2251..c33b4273 100644 --- a/front/app/translations+api.ts +++ b/front/app/translations+api.ts @@ -1,4 +1,4 @@ -import { supportedLanguages } from "~/providers/translations.ssr"; +import { supportedLanguages } from "~/providers/translations.web.ssr"; export default (): Response => { return Response.json(supportedLanguages); diff --git a/front/package.json b/front/package.json index 78374423..ff2ba729 100644 --- a/front/package.json +++ b/front/package.json @@ -24,8 +24,6 @@ "expo-build-properties": "^0.13.2", "expo-localization": "^16.0.1", "expo-updates": "~0.26.19", - "i18next-async-storage-backend": "^1.0.2", - "i18next-chained-backend": "^4.6.2", "i18next-fs-backend": "^2.6.0", "i18next-http-backend": "^3.0.2", "jotai": "^2.12.0", diff --git a/front/src/providers/index.tsx b/front/src/providers/index.tsx index 2e96311c..8844466d 100644 --- a/front/src/providers/index.tsx +++ b/front/src/providers/index.tsx @@ -1,19 +1,14 @@ import { HydrationBoundary, QueryClientProvider } from "@tanstack/react-query"; import { getServerData } from "one"; -import { type ReactNode, useMemo, useState } from "react"; +import { type ReactNode, useState } from "react"; // import { useUserTheme } from "@kyoo/models"; import { ThemeSelector } from "~/primitives/theme"; import { createQueryClient } from "~/query"; import { AccountProvider } from "./account-provider"; import { ErrorConsumer } from "./error-consumer"; import { ErrorProvider } from "./error-provider"; -import { TranslationsProvider } from "./translations.web"; +import { TranslationsProvider } from "./translations"; -// const { TranslationsProvider } = -// typeof window === "undefined" -// ? await import("./translations.ssr") -// : await import("./translations"); -// const QueryProvider = ({ children }: { children: ReactNode }) => { const [queryClient] = useState(() => createQueryClient()); return ( diff --git a/front/src/providers/translations.tsx b/front/src/providers/translations.tsx index cf614552..fcc911df 100644 --- a/front/src/providers/translations.tsx +++ b/front/src/providers/translations.tsx @@ -1,32 +1,17 @@ +import * as fs from "expo-file-system"; import i18next from "i18next"; -import ChainedBackend, { type ChainedBackendOptions } from "i18next-chained-backend"; -import HttpApi, { type HttpBackendOptions } from "i18next-http-backend"; -import { getServerData } from "one"; -import type { RefObject } from "react"; import { type ReactNode, useMemo } from "react"; import { I18nextProvider } from "react-i18next"; -import { storage } from "./settings"; + +export const supportedLanguages = ( + await fs.readDirectoryAsync(`${fs.bundleDirectory}/translations/`) +).map((x) => x.replace(".json", "")); class Backend { - private url: RefObject; static type = "backend" as const; - constructor(_services: any, opts: { url: RefObject }) { - this.url = opts.url; - } - - init(_services: any, opts: { url: RefObject }) { - this.url = opts.url; - } - - async read(language: string, namespace: string) { - const key = `translation.${namespace}.${language}`; - const cached = storage.getString(key); - if (cached) return JSON.parse(cached); - const ghUrl = "https://raw.githubusercontent.com/zoriya/Kyoo/refs/heads/master/front/public"; - const data = await fetch(`${this.url.current ?? ghUrl}/translations/${language}.json`); - storage.set(key, JSON.stringify(await data.json())); - return data; + async read(language: string, _namespace: string) { + return await fs.readAsStringAsync(`${fs.bundleDirectory}/translations/${language}.json`); } } @@ -40,10 +25,7 @@ export const TranslationsProvider = ({ children }: { children: ReactNode }) => { returnEmptyString: false, fallbackLng: "en", load: "currentOnly", - supportedLngs: getServerData("supportedLngs"), - backend: { - url, - }, + supportedLngs: supportedLanguages, }); return i18n; }, []); diff --git a/front/src/providers/translations.web.client.tsx b/front/src/providers/translations.web.client.tsx new file mode 100644 index 00000000..175430e1 --- /dev/null +++ b/front/src/providers/translations.web.client.tsx @@ -0,0 +1,28 @@ +import i18next from "i18next"; +import HttpApi, { type HttpBackendOptions } from "i18next-http-backend"; +import { getServerData } from "one"; +import { type ReactNode, useMemo } from "react"; +import { I18nextProvider } from "react-i18next"; + +export const TranslationsProvider = ({ children }: { children: ReactNode }) => { + const val = useMemo(() => { + const i18n = i18next.createInstance(); + // TODO: use https://github.com/i18next/i18next-browser-languageDetector + i18n.use(HttpApi).init({ + interpolation: { + escapeValue: false, + }, + returnEmptyString: false, + fallbackLng: "en", + load: "currentOnly", + supportedLngs: getServerData("supportedLngs"), + // we don't need to cache resources since we always get a fresh one from ssr + backend: { + loadPath: "/translations/{{lng}}.json", + }, + }); + i18n.services.resourceStore.data = getServerData("translations"); + return i18n; + }, []); + return {children}; +}; diff --git a/front/src/providers/translations.ssr.tsx b/front/src/providers/translations.web.ssr.tsx similarity index 100% rename from front/src/providers/translations.ssr.tsx rename to front/src/providers/translations.web.ssr.tsx diff --git a/front/src/providers/translations.web.tsx b/front/src/providers/translations.web.tsx index 175430e1..0df3db11 100644 --- a/front/src/providers/translations.web.tsx +++ b/front/src/providers/translations.web.tsx @@ -1,28 +1,4 @@ -import i18next from "i18next"; -import HttpApi, { type HttpBackendOptions } from "i18next-http-backend"; -import { getServerData } from "one"; -import { type ReactNode, useMemo } from "react"; -import { I18nextProvider } from "react-i18next"; - -export const TranslationsProvider = ({ children }: { children: ReactNode }) => { - const val = useMemo(() => { - const i18n = i18next.createInstance(); - // TODO: use https://github.com/i18next/i18next-browser-languageDetector - i18n.use(HttpApi).init({ - interpolation: { - escapeValue: false, - }, - returnEmptyString: false, - fallbackLng: "en", - load: "currentOnly", - supportedLngs: getServerData("supportedLngs"), - // we don't need to cache resources since we always get a fresh one from ssr - backend: { - loadPath: "/translations/{{lng}}.json", - }, - }); - i18n.services.resourceStore.data = getServerData("translations"); - return i18n; - }, []); - return {children}; -}; +export const { TranslationsProvider } = + typeof window === "undefined" + ? await import("./translations.web.ssr") + : await import("./translations.web.client");