i18next::backendConnector: TypeError: Only absolute URLs are supported

Viewed 1375

I'm using i18next to translate my NextJs application. Translations load perfectly fine in my browser but I still see few errors in my console.

i18next: hasLoadedNamespace: i18next was not initialized undefined
i18next::translator: key "resources.welcome_string.value" for languages "en-US" won't get resolved as namespace "myStrings" was not yet loaded This means something IS WRONG in your setup. You access the t function before i18next.init / i18next.loadNamespace / i18next.changeLanguage was done. Wait for the callback or Promise to resolve before accessing it!!!
i18next::translator: missingKey undefined myStrings resources.welcome_string.value resources.welcome_string.value
i18next::backendConnector: loading namespace myStrings for language en-US failed TypeError: Only absolute URLs are supported

This is what my i18next config looks like (src/i18n/i18n.ts):

import i18next from 'i18next';
import {initReactI18next} from 'react-i18next';
import httpApi from 'i18next-http-backend';

i18next
  .use(initReactI18next)
  .use(httpApi)
  .init({
    debug: process.env.NODE_ENV !== 'production',
    lng: 'en-US',
    ns: ['myStrings'],
    fallbackNS: 'myStrings',
    defaultNS: 'myStrings',
    fallbackLng:'en-US',
    preload: ['en-US', 'de-DE', 'es-ES'],
    interpolation: {
      prefix: "{{",
      suffix: "}}"
    },
    load: "currentOnly",
    supportedLngs: ['en-US', 'de-DE', 'es-ES'],
    backend: {
      loadPath: 'translations/{{ns}}-{{lng}}.json',
      crossDomain: true
    },
    detection: {
      order: ['cookie', 'htmlTag'],
    },
    react: {
      useSuspense: false
    },
  });

export default i18next;

This is how I'm accessing it (src/pages/localization.tsx):

import React from "react";
import Head from "next/head";
import { NextPage } from "next";
import "../i18n/i18n";
import {Trans, useTranslation} from 'react-i18next';

const Home: NextPage = (props: any) => {

  const { t, i18n } = useTranslation("myStrings");

  return (
    <div>
      <Head>
        <title>Home</title>
      </Head>
      <div>
          <kat-flag size="small" country="us" onClick={() => i18n.changeLanguage("en-US")}> US </kat-flag>
          <kat-flag size="small" country="de" onClick={() => i18n.changeLanguage("de-DE")}> DE </kat-flag>
          <kat-flag size="small" country="es" onClick={() => i18n.changeLanguage("es-ES")}> ES </kat-flag>
          <hr/>
          <hr/>
          <div> {t("resources.welcome_string.value")} </div>
      </div>
    </div>
  );
};

export default Home;

I probably understand the error that it's loading my code localization.tsx before initializing i18next in i18n.ts.

My questions are:

  1. How can I fix this? how can I make i18next.init load first
  2. I'm currently using i18next-http-backend so my translation strings must be in public folder. Is there a way I can keep my translations in a non-public folder (parallel to src and public) and load it from there.
2 Answers
  1. It depends a bit on your architecture - i18next.init() returns a promise, you can simply export it and wait for it somewhere in your code. Alternatively you can establish a listener via i18next.on('initialized',()=>...)

  2. The translations must be in the public folder because this folder gets bundled as-is during your build process (so files don't get renamed). In theory you could use a different folder, you'd just have to make sure it gets included in your bundle afterwards.

Related