Repository navigation
Description
I have an complex server side project .. express server that serves pages render on it and hydrated via react on client .. and sometimes send an html files that fully render in client by react ... so i have 2 folders one for client and another for server and each folder has its own package.json and webpack-config.json .. i implement the webpack-dev-middleware in my express server to serve the static files via memory and implenting the hot reloading via webpack-hot-middleware .. then i implementing the localization in client and server via i18next ..
the issue: when changes occur in the locales files it doesn't trigger HMR
note: [I18NextHMR] Client HMR has started" logged in browser for the first time my app run and when changing the json files no logs related to "I18NextHMR" appear at all
this my setup of i18next and i18next-hmr in my server folder:
import path from 'path';
import i18n, { use, InitOptions } from 'i18next';
import Backend from 'i18next-fs-backend';
import { initReactI18next } from 'react-i18next';
import { LanguageDetector } from 'i18next-http-middleware';
import { setI18nConfig } from 'app/i18n/config';
import { HMRPlugin } from 'i18next-hmr/plugin';
const cookieDetector = {
name: 'cookieDetector',
lookup(req: any) {
if (req.headers.cookie) {
const cookieMatch = req.headers.cookie.match(/(?:^|; )language=([^;]*)/);
return cookieMatch ? cookieMatch[1] : null;
}
return null;
}
};
use(Backend)
.use(LanguageDetector)
.use(initReactI18next)
.use(
new HMRPlugin({
webpack: {
server: true
}
})
)
.init({
...(setI18nConfig(['guest']) as InitOptions),
lng: 'en',
preload: ['en', 'ar'],
backend: {
loadPath: path.join(__dirname, 'public', 'locales', '{{lng}}', '{{ns}}.json'),
addPath: '/locales/{{lng}}/{{ns}}.json'
},
detection: {
order: ['cookieDetector', 'header'],
caches: false,
detectors: [cookieDetector]
// lookupCookie: 'language'
},
debug: false
});
export default i18n;and this my setup of i18next and i18next-hmr in my client folder:
import { InitOptions, createInstance } from 'i18next';
import Backend from 'i18next-http-backend';
import { initReactI18next } from 'react-i18next';
import LanguageDetector from 'i18next-browser-languagedetector';
import { HMRPlugin } from 'i18next-hmr/plugin';
import { setI18nConfig } from 'app/i18n/config';
const languageDetector = new LanguageDetector();
export const createI18nInstance = async (lng: string, namespaces: string[] = [], defaultNS: string = 'guest') => {
const instance = createInstance();
instance
.use(
new HMRPlugin({
webpack: {
client: true
}
})
)
.use(languageDetector)
.use(Backend)
.use(initReactI18next);
await instance.init({
...(setI18nConfig(namespaces, defaultNS) as InitOptions),
lng,
interpolation: { escapeValue: false },
backend: {
loadPath: '/locales/{{lng}}/{{ns}}.json',
crossDomain: true,
requestOptions: {
cache: 'default',
credentials: 'same-origin'
}
},
initImmediate: false,
partialBundledLanguages: true,
returnObjects: true,
joinArrays: '\n',
parseMissingKeyHandler(key) {
if (process.env.NODE_ENV === 'development') {
// eslint-disable-next-line no-console
console.warn(`Missing translation for key: ${key}`);
}
return key;
}
});
return instance;
};and in webpack-config.js in client and server i added the plugin:
productionBuild ? null : new I18NextHMRPlugin({ localesDir: path.resolve(rootDir, 'server/src/public/locales') }),and cause i using node-externals i put the "i18next-hmr" in allowedList as bellow:
module.exports = {
mode: process.env.NODE_ENV || 'production',
target: 'node',
node: false,
externals: [
webpackNodeExternals({
allowlist: [/^i18next-hmr(\/.*)?$/]
})
],
Activity
felixmosh commentedon Aug 25, 2025
Hi, I'm not familer with some issue related to
webpack-dev-middleware.It should work.
Your i18next-hmr setup looks ok to me.
The only thing that pops into my eyes, is
allowlist: [/^i18next-hmr(\/.*)?$/]which I'm not sure that nodeExternals is using import path the absolute path (I guess that absolute path)Can you build a small repo that reproduces your setup?
felixmosh commentedon Oct 14, 2026
ping?