i18next / i18next-xhr-backend

[deprecated] can be replaced with i18next-http-backend
https://github.com/i18next/i18next-http-backend
MIT License
253 stars 75 forks source link

ReferenceError: XMLHttpRequest is not defined on SSR #281

Closed tavurth closed 6 years ago

tavurth commented 6 years ago
ReferenceError: XMLHttpRequest is not defined
    at Object.ajax (/code/frontend/node_modules/i18next-xhr-backend/dist/commonjs/ajax.js:46:5)
    at /code/frontend/node_modules/i18next-xhr-backend/dist/commonjs/index.js:110:24
    at Array.forEach (<anonymous>)
    at Backend.create (/code/frontend/node_modules/i18next-xhr-backend/dist/commonjs/index.js:107:17)
    at /code/frontend/node_modules/i18next-chained-backend/dist/commonjs/index.js:92:25
    at Array.forEach (<anonymous>)
    at Backend.create (/code/frontend/node_modules/i18next-chained-backend/dist/commonjs/index.js:91:21)
    at Connector.saveMissing (/code/frontend/node_modules/i18next/dist/commonjs/BackendConnector.js:295:20)
    at send (/code/frontend/node_modules/i18next/dist/commonjs/Translator.js:195:37)
    at Translator.translate (/code/frontend/node_modules/i18next/dist/commonjs/Translator.js:210:13)
    at I18n.t (/code/frontend/node_modules/i18next/dist/commonjs/i18next.js:356:73)
    at Interpolate.fixedT [as t] (/code/frontend/node_modules/i18next/dist/commonjs/i18next.js:342:21)
    at Interpolate.render (/code/frontend/node_modules/react-i18next/dist/commonjs/Interpolate.js:58:25)
    at d (/code/frontend/node_modules/react-dom/cjs/react-dom-server.node.production.min.js:28:211)
    at wa (/code/frontend/node_modules/react-dom/cjs/react-dom-server.node.production.min.js:28:493)
    at a.render (/code/frontend/node_modules/react-dom/cjs/react-dom-server.node.production.min.js:33:18)
i18n
    .use(Backend)
    .use(intervalPlural)
    .use(languageDetector)
    .use(reactI18nextModule)
    .init(
        {
            fallbackLng: false,
            saveMissing: true,
            appendNamespaceToCIMode: true,

            // allow keys to be phrases having `:`, `.`
            nsSeparator: false,
            keySeparator: false,

            // have a common namespace used around the full app
            ns: ['translations'],
            defaultNS: 'translations',

            debug: false,
            react: { wait: true },

            // Language detection
            detection: {
                // order and from where user language should be detected
                order: ['urlDetector', 'querystring', 'cookie', 'localStorage', 'navigator', 'htmlTag'],

                // keys or params to lookup language from
                lookupCookie: 'locale',
                lookupQuerystring: 'lng',
                lookupLocalStorage: 'i18nextLng',

                // cache user language on
                caches: ['localStorage', 'cookie'],
                excludeCacheFor: ['cimode'], // languages to not persist (cookie, localStorage)

                // optional expire and domain for set cookie
                // cookieMinutes: 10,
                // cookieDomain: 'myDomain',

                // optional htmlTag with lang attribute, the default is:
                // htmlTag: document.documentElement,
            },

            backend: {
                backends: [
                    XHR
                ],

                backendOptions: [
                    {
                        // path where resources get loaded from, or a function
                        loadPath: '/api/translations/{{lng}}/{{ns}}',

                        // path to post missing resources
                        addPath: '/api/translations/add/{{lng}}/{{ns}}',

                        // your backend server supports multiloading
                        // /locales/resources.json?lng=de+en&ns=ns1+ns2
                        allowMultiLoading: false, // set loadPath: '/locales/resources.json?lng={{lng}}&ns={{ns}}' to adapt to multiLoading

                        // allow cross domain requests
                        crossDomain: false,

                        // allow credentials on cross domain requests
                        withCredentials: false,
                    },
                ],
            },
        },
        error => {
            if (error) {
                logger.error(error);
            }
        }
    );
jamuhl commented 6 years ago

the xhr-backend is not "universal" you will need to use node-fs-backend on serverside to load translations from filesystem, see example:

nextjs: https://github.com/zeit/next.js/blob/canary/examples/with-react-i18next/server.js#L10 razzle: https://github.com/i18next/react-i18next/blob/master/example/razzle-ssr/src/server.js#L12

arsnl commented 6 years ago

xhr-backend is not "universal"

wat

arsnl commented 6 years ago

@tavurth

All you have to do is to define another "ajax" (https://github.com/i18next/i18next-xhr-backend/blob/0ec7d848236c379a90017fff53640380a4d0d46c/src/index.js#L11)

I suggest axios.

Eg

import i18next from 'i18next';
import XHR from 'i18next-xhr-backend';
import axios from 'axios';

i18next
  .use(XHR)
  .init({
    backend: {
        ajax: axios
        ...
    }
  });

Now you have a universal backend plugin.

jamuhl commented 6 years ago

The main goal of the backend is to be small - no need to pull in an axios module. There is already plenty backends: https://www.i18next.com/overview/plugins-and-utils#backends

On node.js server you will use fs-backend anyway.

Creating a own backend is very simple by the way: https://www.i18next.com/misc/creating-own-plugins#backend

You might create one based on axios for your case and share it with the community?

arsnl commented 6 years ago

I don't really see the point to pollute NPM more. This already do the trick perfectly for the ones who need a universal plugin.

https://github.com/i18next/i18next-xhr-backend/issues/281#issuecomment-416757169

jamuhl commented 6 years ago

can life with that...;) the only thing for sure is - i won't do it...

arsnl commented 6 years ago

¯_(ツ)_/¯

Vadorequest commented 5 years ago

It's actually worth recommending it for those already using Axios who don't want another dependency.

And, by the way, having a module named "backend" that cannot be used from the backend is somewhat a silly dev joke 😆

jamuhl commented 5 years ago

@Vadorequest hm...might rename it to i18next-xhr-access-module-that-uses-xhr-to-load-data-from-backend...but might live with the silly joke...

jamuhl commented 5 years ago

And what dependecy...this uses browser native XMLHttpRequest no axios or other big dependency for doing simple xhr

Vadorequest commented 5 years ago

I meant, I prefer to use Axios that is already a dependency in my case, rather than using a custom backend or another backend that is universal, to avoid an extra dependency.

So, the point of all this is, it was a good thing @arsnl mentioned it, despite the fact you weren't too fond of it. 😉

artur-bobrushko commented 4 years ago

I'm facing the same issue. Must I create a node backend? Is there any plug-in npm for gatsby.js?

adrai commented 4 years ago

@roooby There are several backends for node, like: https://github.com/i18next/i18next-node-fs-backend or https://github.com/i18next/i18next-node-remote-backend... it depends... https://www.i18next.com/overview/plugins-and-utils#backends