[▲ Vercel Community](/) · [Categories](/categories) · [Latest](/latest) · [Top](/top) · [Live](/live) [Feedback](/c/feedback/8) # Solution for i18next on server on vercel 156 views · 0 likes · 3 posts Mazurro1 (@mazurro1) · 2024-12-11 Hey! I have sollution for i18next on server on vercel. if you want more details on how to solve this problem with transactions on the server side, write, I will write a solution that does not cause an error :) Pauline P. Narvas (@pawlean) · 2024-12-11 Hey, @mazurro1! I'm sure folks will find this interesting. Feel free to share :smile: Mazurro1 (@mazurro1) · 2024-12-11 All you need to do is fetch the transactions and everything starts working :) The rest of the code from the official remix site: https://remix.run/resources/remix-i18next entry.servet.tsx: ``` import { PassThrough } from "node:stream"; import { createReadableStreamFromReadable, type EntryContext, } from "@remix-run/node"; import { RemixServer } from "@remix-run/react"; import { createInstance } from "i18next"; import { isbot } from "isbot"; import { renderToPipeableStream } from "react-dom/server"; import { I18nextProvider, initReactI18next } from "react-i18next"; import { cookiesKey } from "./constants/cookies"; import { E_Language } from "./constants/languages"; import { getCookieValue } from "./data/cookies.server"; import i18n from "./i18n"; import i18next from "./i18next.server"; const ABORT_DELAY = 5000; const checkFileExists = async (url: string): Promise<boolean> => { try { const response = await fetch(url, { method: "HEAD" }); return response.ok; } catch (error) { console.error(`Error checking file existence at ${url}:`, error); return false; } }; // eslint-disable-next-line @typescript-eslint/no-explicit-any const fetchFile = async (url: string): Promise<any> => { try { const response = await fetch(url); if (!response.ok) { throw new Error(`Failed to load ${url}: ${response.statusText}`); } return await response.json(); } catch (error) { throw new Error(`Error fetching ${url}: ${error}`); } }; export default async function handleRequest( request: Request, responseStatusCode: number, responseHeaders: Headers, remixContext: EntryContext, ) { const callbackName = isbot(request.headers.get("user-agent")) ? "onAllReady" : "onShellReady"; const instance = createInstance(); const ns = i18next.getRouteNamespaces(remixContext); const CustomBackend = { read: (language: string, namespace: string, callback: Function) => { const protocol = request.headers.get("x-forwarded-proto") || "http"; const host = request.headers.get("host"); const baseUrl = process.env.NODE_ENV === "development" ? "https://your-url-prd.com" : `${protocol}://${host}`; const url = `${baseUrl}/locales/${language}/${namespace}.json`; const handleRequest = async () => { try { const exists = await checkFileExists(url); if (!exists) { callback(new Error(`File not found: ${url}`), false); return; } const data = await fetchFile(url); callback(null, data); } catch (error) { console.error(error); callback(error, false); } }; handleRequest(); }, type: "backend", }; await instance .use(initReactI18next) // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-ignore .use(CustomBackend) .use(LanguageDetector) .init({ ...i18n, ns, }); return new Promise((resolve, reject) => { let didError = false; const { abort, pipe } = renderToPipeableStream( <I18nextProvider i18n={instance}> <RemixServer context={remixContext} url={request.url} /> </I18nextProvider>, { [callbackName]: () => { const body = new PassThrough(); const stream = createReadableStreamFromReadable(body); responseHeaders.set("Content-Type", "text/html"); resolve( new Response(stream, { headers: responseHeaders, status: didError ? 500 : responseStatusCode, }), ); pipe(body); }, onError(error: unknown) { didError = true; console.error(error); }, onShellError(error: unknown) { reject(error); }, }, ); setTimeout(abort, ABORT_DELAY); }); } ```