8

I am using i18next and react-i18next in a react native application, more specifically with input validation. I am trying to pass the t() as a parameter in a no component and i am receiving the error "TypeError: n is not a function. (In 'n('errorMessages.emailNoMatch')', 'n' is undefined)". any suggestions is highly appreciated since I am relatively new to coding and I have been searching for a couple days with this issue.

here is the i18n.js code:

import i18next from 'i18next';
import common_de from './translations/de/common.json';
import common_en from './translations/en/common.json';
import i18n from 'i18n-js';
import * as Localization from 'expo-localization';
// Set up translations
i18next.init({
  interpolation: { escapeValue: false }, // React already does escaping
  lng: 'en', // language to use
  resources: {
    de: {
      common: common_de, // 'common' is our custom namespace
    },
    en: {
      common: common_en,
    },
  },
  debug: true,
});
export default i18next;

a part of the RegisterValidator.js code where I am trying to pass the t() as a parameter, but it is not reading t as a parameter inside of the switch statement.:

import React from 'react';
import { useTranslation } from 'react-i18next';
// import { withTranslation } from 'react-i18next';

const RegisterValidator = (type, value, email, t) => {
  let validated = true;
  let warningMsg = [];
  switch (type) {
    case 'username':
      if (!value.includes(' ')) return [true, ''];
      else {
        warningMsg = t('errorMessages.username');
        return [false, warningMsg];
      }
    default:
      return [validated, ''];
  }
};
export default RegisterValidator;

and here is a part from the App.js

import React from 'react';
import './i18n';
import i18n from 'i18n-js';
import i18next from 'i18next';
import { I18nextProvider } from 'react-i18next';

function App() {
  return (
    <I18nextProvider i18n={i18next}>
      <Insert more code here />
    </I18nextProvider>
  );
}

export default App;
felixmosh
  • 32,615
  • 9
  • 69
  • 88
CornFedKorean
  • 125
  • 1
  • 1
  • 8
  • Where is the call to `RegisterValidator`? – felixmosh Dec 30 '20 at 15:46
  • It is called inside RegisterScreen.js, and also EditProfileScreen.js inside an Input element. however, the error only occurs inside of the RegisterValidator code that I posted. The t function works everywhere else, because I use functional components in the other files. – CornFedKorean Dec 30 '20 at 16:19

4 Answers4

4

What ended up working for me was calling the t function directly from i18next, and pass the namespace as a prefix to the t function.

import i18next from 'i18next;

const RegisterValidator = () => {
   return i18next.t('common: errorMessages.username')
}
CornFedKorean
  • 125
  • 1
  • 1
  • 8
1

You cant import the instance straight from the file where you initialize i18n.

import i18n from "./i18n";

...


i18n.t("required_field"); //and use it like this

My i18n init file

import i18n from "i18next";
import { initReactI18next } from "react-i18next";
import Backend from "i18next-http-backend";

import LanguageDetector from "i18next-browser-languagedetector";
import CustomLanguageDetector from "./CustomLanguageDetector";

const languageDetector = new LanguageDetector();
languageDetector.addDetector(CustomLanguageDetector);

i18n
  // detect user language
  // learn more: https://github.com/i18next/i18next-browser-languageDetector
  .use(languageDetector)
  // load translation using http -> see /public/locales (i.e. https://github.com/i18next/react-i18next/tree/master/example/react/public/locales)
  // learn more: https://github.com/i18next/i18next-http-backend
  .use(Backend)
  // pass the i18n instance to react-i18next.
  .use(initReactI18next)
  // init i18next
  // for all options read: https://www.i18next.com/overview/configuration-options
  .init({
    fallbackLng: "en",
    // debug: true,
    load: "languageOnly",
    backend: {
      loadPath: `/i18n/{{lng}}.json`,
    },
    react: { useSuspense: false },
    whitelist: ["pt", "en"],
    nonExplicitWhitelist: true,
    detection: {
      // order and from where user language should be detected
      order: ["CustomLanguageDetector"],
      lookupLocalStorage: "@AppName:language", //Change your appname here if you're storing the languge in local storage.
      caches: ["localStorage"],
      checkWhitelist: true,
    },
  });

export default i18n;
Thales Kenne
  • 2,705
  • 1
  • 12
  • 26
  • Thanks, this at least got me one step closer. at least it is processing the t() however now I am getting the error that 'i18next::translator: missingKey en translation errorMessages.username errorMessages.username' which means that the json files are not being processed correctly, even though on all of my other files it reads it with no problems. – CornFedKorean Dec 31 '20 at 13:48
  • I added my init file for comparison, that might help. Do you have that key in your translation file? – Thales Kenne Jan 02 '21 at 21:23
0

t() outside component won't work instead, send a message object to RegisterValidator and use that.

Example -

function Component() {
   // t is declared here
   const message = {
      error: t('errorMessage'),
      success: t('successMessage')
   }

   // and then send this message object to RegisterValidator
   RegisterValidator(.., .., .., message);
}
Jitesh Prajapati
  • 2,533
  • 4
  • 29
  • 51
Vaibhav Arora
  • 94
  • 1
  • 9
-1

You could also just export the t function that matters, such that you don't have to repeat i18n. everywhere:

i18n init file: translation/config

// Some configuration of i18n
export default i18n.t;

Some file using i18n

import t from 'translation/config';
t('localized-label1')
devgioele
  • 129
  • 2
  • 10