i18next react load namespaces only when needed - i18next

I have the following code that loads i18n translations. The l.json file exists only in a few pages but it is loaded always (based on the http requests that I see from the browser). How can I prevent it so that these are loaded only when needed?
import i18n from "i18next";
import { initReactI18next } from "react-i18next";
import LanguageDetector from "i18next-browser-languagedetector";
import ChainedBackend from 'i18next-chained-backend';
import HttpBackend from 'i18next-http-backend';
i18n
.use(LanguageDetector)
.use(initReactI18next)
.use(ChainedBackend)
.init({
debug: true,
fallbackLng: "en-US",
supportedLngs: ['en-US', 'en-GB'],
ns: ['l', 't'],
defaultNS: 't',
interpolation: {
escapeValue: false, // not needed for react as it escapes by default
},
backend: {
backends: [
HttpBackend,
],
backendOptions: [
{
loadPath: 'https://example.com/{{lng}}/{{ns}}.json'
}
]
}
});

Related

Sub routes inside the vue3 + vite micro frontend

I am using vue3 + vite and a plugin
#originjs/vite-plugin-federation
to build a micro frontend. One app will be the host and one will be the remote, both will have their own routing. Is there a way to navigate remote app inside the host app.
If I export a single component from the remote app it is working, but if I export App.js with routing it is not working, can anybody provide general guidelines to this problem.
vite config of remote:
import { fileURLToPath, URL } from "node:url";
import { defineConfig } from "vite";
import vue from "#vitejs/plugin-vue";
import vueJsx from "#vitejs/plugin-vue-jsx";
import federation from "#originjs/vite-plugin-federation";
const dependencies = require("./package.json").dependencies;
// https://vitejs.dev/config/
export default defineConfig({
plugins: [
vue(),
vueJsx(),
federation({
name: "remote-app",
filename: "remoteEntry.js",
exposes: {
"./Test": "./src/App.vue",
},
shared: [{ ...dependencies }, "vue", "vue-router"],
}),
],
resolve: {
alias: {
"#": fileURLToPath(new URL("./src", import.meta.url)),
},
},
});
vite.config of host:
import { fileURLToPath, URL } from "node:url";
import { defineConfig } from "vite";
import vue from "#vitejs/plugin-vue";
import vueJsx from "#vitejs/plugin-vue-jsx";
import federation from "#originjs/vite-plugin-federation";
// https://vitejs.dev/config/
export default defineConfig({
plugins: [
vue(),
vueJsx(),
federation({
name: "host-app",
remotes: {
remote: "http://127.0.0.1:5173/dist/assets/remoteEntry.js",
},
shared: ["vue"],
}),
],
resolve: {
alias: {
"#": fileURLToPath(new URL("./src", import.meta.url)),
},
},
});

Vite: vue-i18n build fail

Everything work fine in dev mode, but when try to npm run build, Unexpected token error in vue-i18n
import { createI18n } from 'vue-i18n';
import messages from '#intlify/vite-plugin-vue-i18n/messages'
const i18n = createI18n({
locale: 'en',
legacy: false,
fallbackLocale: 'en',
globalInjection: true,
messages
})
export default i18n;
//vite.config.js
import { defineConfig } from 'vite'
import vue from '#vitejs/plugin-vue'
import path from 'path'
import vueI18n from '#intlify/vite-plugin-vue-i18n'
export default defineConfig({
plugins: [
vue(),
vueI18n({
// if you want to use Vue I18n Legacy API, you need to set `compositionOnly: false`
// compositionOnly: false,
// you need to set i18n resource including paths !
include: path.resolve(__dirname, './src/locales/**'),
}),
],
resolve: {
alias: {
'#': path.resolve(__dirname, './src'),
},
},
})
Error:
[commonjs--resolver] Unexpected token (249:14) in E:/Work/Vue/vue-sample/node_modules/vue-i18n/dist/vue-i18n.runtime.esm-bundler.js
247: if (locales.length) {
248: locales.forEach(locale => {
249: global.mergeLocaleMessage(locale, messages[locale]);
^
250: });
251: }

How to use publicRuntimeConfig on nuxt plugins

I create vue socket io plugins #/plugins/socket-io.js
import Vue from 'vue'
import VueSocketIO from 'vue-socket.io'
Vue.use(
new VueSocketIO({
debug: true,
connection: process.env.SOCKET_IO_CONNECTION,
})
)
how to change that to use publicRuntimeConfig
my nuxt.config.js
publicRuntimeConfig: {
peerServerHost: process.env.PEER_SERVER_HOST,
peerServerPort: process.env.PEER_SERVER_PORT,
peerServerPath: process.env.PEER_SERVER_PATH,
},
privateRuntimeConfig: {
signalServerKey: process.env.SIGNAL_SERVER_KEY,
signalServerCert: process.env.SIGNAL_SERVER_CERT,
socketIOConnection: process.env.SOCKET_IO_CONNECTION,
},
I found the way,
move socketIOConnection to publicRuntimeConfig
then in #/plugins/socket-io.js
import Vue from 'vue'
import VueSocketIO from 'vue-socket.io'
export default function ({ $config }) {
Vue.use(
new VueSocketIO({
debug: true,
connection: $config.socketIOConnection,
})
)
}

React Native i18next Backend not loading json files

Hi I am using i18next with React Native for translations, but am getting the following error when trying to load json files:
i18next::backendConnector: lloading namespace translation for language en failed failed loading ./locales/en/translation.json
and also
i18next::translator: missingKey en translation screens.login.header screens.login.header
app/i18n.js
import i18n from 'i18next';
import { initReactI18next } from 'react-i18next';
import Fetch from 'i18next-fetch-backend';
const languageDetector = {
type: 'languageDetector',
async: true,
detect: cb => cb('en'),
init: () => {},
cacheUserLanguage: () => {},
};
i18n
.use(Fetch)
.use(languageDetector)
.use(initReactI18next)
.init({
lng: 'en',
debug: true,
interpolation: {
escapeValue: false,
formatSeparator: ',',
},
keySeparator: '.',
whitelist: ['en'],
nonExplicitWhitelist: true,
fallbackLng: 'en',
backend: {
loadPath: './locales/{{lng}}/{{ns}}.json',
allowMultiLoading: true,
},
react: {
wait: true,
},
});
export default i18n;
app/locales/en/translation.json
{
"screens": {
"login": {
"header": "Login to your your account",
"loginButton": "Login"
}
}
}
app/screens/auth/LoginScreen.js
{t('screens.login.header')}
Has anyone had any success using this library with React Native?

How to test react-native components which are using react-i18next?

I'm trying to use jest to start testing an established RN app. The majority of the components are wrapped in withNamespaces provided by react-i18next.
When i run tests i have this error:
FAIL tests/setting.test.js
● Test suite failed to run
TypeError: Cannot read property 'type' of undefined
4 |
5 | i18n
> 6 | .use(initReactI18next)
| ^
7 | .init({
8 | fallbackLng: 'en',
9 | resources: {
at I18n.use (node_modules/i18next/dist/commonjs/i18next.js:260:16)
at Object.<anonymous> (config/i18nForTest.js:6:1)
at Object.<anonymous> (tests/setting.test.js:5:43)
I followed the doc example and what i've done basically is :
made i18n config for tests :
import i18n from 'i18next';
import { initReactI18next } from 'react-i18next';
i18n
.use(initReactI18next)
.init({
fallbackLng: 'en',
resources: {
en: {},
fr: {}
},
// have a common namespace used around the full app
ns: ['translations'],
defaultNS: 'translations',
debug: true,
interpolation: {
escapeValue: false, // not needed for react!!
},
});
export default i18n;
then wrote some tests:
import 'react-native';
import React from 'react';
import renderer from 'react-test-renderer';
import {I18nextProvider} from 'react-i18next';
import i18n from 'config/i18nForTest';
import Settings from 'containers/Settings';
it('Does Settings renders correctly?', () => {
const tree = renderer
.create(
<I18nextProvider i18n={i18n}>
<Settings t= {key => key} />
</I18nextProvider>,
)
.toJSON();
expect(tree).toMatchSnapshot();
});
you can find here my jest config in package.json:
"jest": {
"setupFiles": ["<rootDir>/jest.setup.js"],
"preset": "react-native",
"testMatch": [
"<rootDir>/tests/**/*.test.js?(x)",
"<rootDir>/src/**/*.test.js"
],
"transformIgnorePatterns": ["node_modules/(?!(#react-native-community|react-navigation|react-native))"
],
"transform": {
"^.+\\.(js)$": "<rootDir>/node_modules/react-native/jest/preprocessor.js"
}
},
THANKS!
I finally found a solution for my problem.
I think the testing example provided in the doc is for v10 and i'm using v9.
So i have modified the i18n config test to use reactI18nextModule so its like this now:
import i18n from 'i18next';
import { initReactI18next } from 'react-i18next';
import { reactI18nextModule } from 'react-i18next';
i18n
.use(reactI18nextModule)
.init({
fallbackLng: 'en',
resources: {
en: {},
fr: {}
},
// have a common namespace used around the full app
ns: ['translations'],
defaultNS: 'translations',
debug: true,
interpolation: {
escapeValue: false, // not needed for react!!
},
});
export default i18n;
after that now i can omit i18nProvider in the testing components like this:
import 'react-native';
import React from 'react';
import renderer from 'react-test-renderer';
import {I18nextProvider} from 'react-i18next';
import i18n from 'config/i18nForTest';
import {Settings} from 'containers/Settings'; // to get redux connected component import Setting without {}
it('Does Settings renders correctly?', () => {
const tree = renderer
.create(
<Settings t={key => key} />
)
.toJSON();
expect(tree).toMatchSnapshot();
});