i18next / next-i18next

The easiest way to translate your NextJs apps.
https://next.i18next.com
MIT License
5.57k stars 762 forks source link

Fetch Translations from API #739

Closed GainorB closed 4 years ago

GainorB commented 4 years ago

Describe the bug

I am using a backend plugin to fetch translations from an external API. I am getting the translations from the API but I am getting a CORS error in the client and the data isn't being set/sent to the client, even though I am able to parse it on the sever.

For the sake of testing, I am only sending 1 namespace, 'common' and only one locale, 'en'. Not sure if this will affect my outcomes.

Occurs in next-i18next version

"next-i18next": "^4.4.2"

Steps to reproduce

i18n.ts

  1. If loading from a backend, do I need localePath set in the config object? or what should it be set to instead?
import isNode from 'detect-node';
import Backend from 'i18next-http-backend';
import {NextComponentType, NextPageContext} from 'next';
import NextI18Next, {InitConfig} from 'next-i18next';
import {useTranslation as originalUseTranslation} from 'react-i18next';
import {DEFAULT_LANGUAGE, LOCALE_SUBPATHS} from '../../utils';
import BackendOptions from './backend';

export enum Namespaces {
  _error = '_error',
  common = 'common',
  home = 'home',
  assets = 'assets',
  newsroom = 'newsroom',
  article = 'article',
  'release-schedule' = 'release-schedule',
}

const isServer = isNode && !(process as any).browser;

const config: InitConfig = {
  ns: [
    Namespaces._error,
    Namespaces.common,
    Namespaces.home,
    Namespaces.assets,
    Namespaces.newsroom,
    Namespaces.article,
    Namespaces['release-schedule'],
  ],
  defaultNS: Namespaces.common,
  load: 'currentOnly',
  lowerCaseLng: true,
  cleanCode: true,
  defaultLanguage: DEFAULT_LANGUAGE,
  preload: [DEFAULT_LANGUAGE],
  fallbackLng: DEFAULT_LANGUAGE,
  saveMissing: false,
  keySeparator: false,
  otherLanguages: ['ar', 'zh_cn', 'zh_tw', 'th', 'ja', 'ko'],
  whitelist: ['en', 'ar', 'zh_cn', 'zh_tw', 'th', 'ja', 'ko'],
  localePath: isServer ? 'public/locales' : 'locales',
  localeSubpaths: LOCALE_SUBPATHS,
  interpolation: {
    escapeValue: false,
  },
  browserLanguageDetection: true,
  serverLanguageDetection: true,
  debug: false,
  strictMode: false,
  use: [Backend],
  backend: BackendOptions,
};

const NextI18NextInstance = new NextI18Next(config);

export const useTranslation = originalUseTranslation;
export const {appWithTranslation, withTranslation, Link, i18n, Trans} = NextI18NextInstance;

export const includeDefaultNamespaces = (namespaces: string[]) => [
  Namespaces.common,
  Namespaces._error,
  ...namespaces,
];

export type I18nPage<P = {}> = NextComponentType<
  NextPageContext,
  {namespacesRequired: string[]},
  P & {namespacesRequired?: string[]}
>;

export default NextI18NextInstance;

backend.ts

import axios from 'axios';
import get from 'lodash/get';

const nameSpace = 'press-site';

export default {
  crossDomain: true,
  withCredentials: true,
  allowMultiLoading: false,
  loadPath: (languages, namespace) => ({
    languages,
    namespace,
  }),
  request: async (_options, languageNamespace, _payload, callback) => {
    try {
      const {languages, namespace} = languageNamespace;
      const language = languages[0];
      const responseKey = `${nameSpace}$press-site-${namespace}`;

      const data = {
        bundleKeys: [
          {
            nameSpaceName: nameSpace,
            bundleName: `${nameSpace}-${namespace}`,
          },
        ],
        languages: [language],
      };

      const config = {
        headers: {
          'Content-Type': 'application/json',
        },
      };

      const response = await axios.put(
        'api-url.com',
        JSON.stringify(data),
        config
      );

      const translations = get(response, `data.response.${responseKey}.strings.${language}`, null);

      if (translations) {
        console.log('translations', translations);
        return callback(null, {status: 200, data: translations});
      } else {
        return callback(false, null);
      }
    } catch (error) {
      return callback(false, null);
    }
  },
};

Expected behaviour

Inside of the translations condition, I am able to successfully log the returned namespace translations, and send them to the callback as instructed, but on my FE, when I log i18n, and inspect the store, the common bundle is empty.

Screen Shot 2020-06-18 at 1 02 53 PM Screen Shot 2020-06-18 at 12 59 19 PM

OS (please complete the following information)

isaachinman commented 4 years ago

Can you provide a reproducible repo?