Use expo-fs as a backend

This commit is contained in:
Zoe Roux 2025-02-25 22:07:18 +01:00
parent 14cf634815
commit 829497300e
No known key found for this signature in database
8 changed files with 44 additions and 65 deletions

View File

@ -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

View File

@ -1,4 +1,4 @@
import { supportedLanguages } from "~/providers/translations.ssr";
import { supportedLanguages } from "~/providers/translations.web.ssr";
export default (): Response => {
return Response.json(supportedLanguages);

View File

@ -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",

View File

@ -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 (

View File

@ -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<string | null>;
static type = "backend" as const;
constructor(_services: any, opts: { url: RefObject<string | null> }) {
this.url = opts.url;
}
init(_services: any, opts: { url: RefObject<string | null> }) {
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;
}, []);

View File

@ -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<HttpBackendOptions>({
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 <I18nextProvider i18n={val}>{children}</I18nextProvider>;
};

View File

@ -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<HttpBackendOptions>({
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 <I18nextProvider i18n={val}>{children}</I18nextProvider>;
};
export const { TranslationsProvider } =
typeof window === "undefined"
? await import("./translations.web.ssr")
: await import("./translations.web.client");