Я нашел, в чем была моя проблема. В документации i18next говорится, что я должен запустить init внутри webpack.config.js
.
Проблема
Моей первоначальной проблемой была загрузка локалей. I18n не смог найти файлы после сборки, потому что веб-пакет не распознает i18n-xhr-backend
, требующий .json
файлы. Тогда после сборки не было файлов перевода. Затем я попытался разрешить webpack
разобраться с i18n, и у меня возникла другая проблема, в следующем абзаце.
В React требуется добавить экземпляр i18n в i18nextProvider
. Но по дороге, которой я занимался, в React не было ни одного экземпляра для защиты. Тогда он не может найти функцию перевода и все остальное. Я также нашел i18nWebpackPlugin, но он также не решил мою проблему, потому что он также не дает доступа к экземпляру i18n
внутри реакции. В итоге у меня возникли две нерешенные проблемы.
Решение
Мое решение было довольно простым. Я создал новую конфигурацию i18n
для development
env и позволил веб-пакету разобраться с .json
, скопировав его в новую папку после сборки. Я приведу ниже мои файлы конфигурации для веб-пакета и i18n. Мои шаги, где:
- Верните
i18n.init()
обратно i18n/index.js
- Создание разных параметров для каждой среды
- Настройка веб-пакета для копирования файлов перевода
- Импорт экземпляра i18n на
App.js
снова
Теперь все работает как шарм.
OBS: Чтобы веб-пакет распознал файлы .json
, его необходимо импортировать куда-нибудь. Я сделал внутри resources.js
файла.
webpack.prod.config.js
const webpack = require("webpack");
const path = require("path");
const htmlWebpackPlugin = require("html-webpack-plugin");
const miniCSSExtractPlugin = require("mini-css-extract-plugin");
const terserPlugin = require("terser-webpack-plugin");
const OptimizeCSSAssetsPlugin = require("optimize-css-assets-webpack-plugin");
const cleanWebpackPlugin = require("clean-webpack-plugin");
const config = {
mode: "production",
output: {
path: path.resolve(__dirname, "../dist"),
publicPath: "./",
filename: "bundle.js"
},
resolve: {
extensions: [" ", ".js", ".jsx"],
alias: {
"@components": path.resolve(__dirname, "../src/components"),
"@views": path.resolve(__dirname, "../src/views"),
"@static": path.resolve(__dirname, "../src/static")
}
},
optimization: {
minimizer: [
new terserPlugin({
cache: true,
parallel: true,
include: /\.(js|jsx)$/
}),
new OptimizeCSSAssetsPlugin({})
]
},
module: {
rules: [
{
test: /\.(js|jsx)$/,
exclude: /node_modules/,
use: [
{
loader: "babel-loader"
}
]
},
{
test: /\.css$/,
use: [
miniCSSExtractPlugin.loader,
{
loader: "css-loader"
}
]
},
{
test: /\.(png|jpg|gif|ico)$/,
use: [
{
loader: "file-loader?name=images/[hash].[ext]",
options: {
name: "assets/images/[hash].[ext]"
}
}
]
},
{
test: /\.(ttf|woff2?|eo(f|t)|svg)$/,
use: [
{
loader: "file-loader",
options: {
name: "assets/fonts/[hash].[ext]"
}
}
]
},
{
test: /\.(json)$/,
type: "javascript/auto",
use: [
{
loader: "file-loader",
options: {
name: "[folder]/[name].[ext]",
outputPath: "assets/locales/"
}
}
]
}
]
},
plugins: [
new htmlWebpackPlugin({
template: path.join(__dirname, "..", "public", "index.html")
}),
new miniCSSExtractPlugin({
filename: "[name].css",
chunkFilename: "[id].css"
}),
new cleanWebpackPlugin("../dist/*", {
root: __dirname + "../",
allowExternal: true
})
]
};
module.exports = config;
i18n / index.js
const i18n = require("i18next");
const initReactI18next = require("react-i18next").initReactI18next;
const langDetector = require("i18next-browser-languagedetector");
const backend = require("i18next-xhr-backend");
const moment = require("moment");
const resources = require("../../static/locales");
/*
Other codes...
*/
i18n.use(langDetector).use(initReactI18next);
var options;
switch (process.env.NODE_ENV) {
case "test":
options = {
whitelist: ["en", "pt"],
fallbackLng: "en",
resources,
ns: "translation",
defaultNS: "translation",
interpolation: {
format: function(value, format, lng) {
if (value instanceof Date) return moment(value).format(format);
return value.toString();
}
}
};
break;
case "production":
i18n.use(backend);
options = {
whitelist: ["en-US", "pt-BR"],
fallbackLng: {
pt: ["pt-BR"],
en: ["en-US"],
default: ["en"]
},
ns: ["button", "common", "lng", "info"],
defaultNS: "common",
backend: {
loadPath: "./assets/locales/{{lng}}/{{ns}}.json"
},
detection: {
order: ["querystring", "cookie", "navigator", "localStorage"]
},
lookupQuerystring: "lng",
caches: ["localStorage", "cookie"],
react: {
wait: true
},
interpolation: {
format: function(value, format, lng) {
if (format === "uppercase") return value.toUpperCase();
if (value instanceof Date) return moment(value).format(format);
return value;
}
}
};
break;
case "development":
i18n.use(backend);
options = {
whitelist: ["en-US", "pt-BR"],
fallbackLng: {
pt: ["pt-BR"],
en: ["en-US"],
default: ["en"]
},
ns: ["button", "common", "lng", "info"],
defaultNS: "common",
backend: {
loadPath: "./src/static/locales/{{lng}}/{{ns}}.json"
},
detection: {
order: ["querystring", "cookie", "navigator", "localStorage"]
},
lookupQuerystring: "lng",
caches: ["localStorage", "cookie"],
react: {
wait: true
},
interpolation: {
format: function(value, format, lng) {
if (format === "uppercase") return value.toUpperCase();
if (value instanceof Date) return moment(value).format(format);
return value;
}
}
};
break;
}
i18n.init(options);
module.exports = i18n;