i18next + React + Webpack - getFixedT 不是函数
i18next + React + Webpack - getFixedT is not a function
我在使用 React、i18next 和 Webpack 时遇到了一些问题。我尝试了很多解决方案,但其中 none 行得通。当我尝试构建我的应用程序时,它构建成功。但是,当我尝试打开它时,控制台显示错误。我的 webpack.config 和错误堆栈跟踪如下。
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 i18nPlugin = require("i18n-webpack-plugin")
const options = require("../src/controllers/i18n").options
const locales = require("../src/controllers/i18n/locales")
options.backend.loadPath = "." + options.backend.loadPath
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")
}
},
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"
}, {
loader: "i18next-loader"
}]
},
{
test: /\.css$/,
use: [
miniCSSExtractPlugin.loader,
{
loader: "css-loader",
}
]
}, {
test: /\.(png|jpg|gif)$/,
use: [{
loader: 'file-loader?name=images/[hash].[ext]',
options: {
name: "assets/images/[hash].[ext]"
}
}]
}, {
test: /\.(ttf|woff(2)|eof|svg)$/,
use: [{
loader: "file-loader",
options: {
name: "assets/fonts/[hash].[ext]",
}
}]
}
],
},
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
}),
new i18nPlugin(locales,{
functionName: "t",
nested: true
},true)
]
};
module.exports = config;
npm 运行 构建 运行s 正常,没有关于 i18next 的错误。然后,当我打开应用程序时,出现此错误:
bundle.js:33 TypeError: r.getFixedT is not a function
at L (bundle.js:12)
at bundle.js:12
at Xo (bundle.js:33)
at Ia (bundle.js:33)
at qi (bundle.js:33)
at $i (bundle.js:33)
at jl (bundle.js:33)
at Cl (bundle.js:33)
at Pl (bundle.js:33)
at Ji (bundle.js:33)
希望有人能帮助我。
我发现了我的问题所在。在 i18next 文档中说我应该 运行 webpack.config.js
.
中的 init
问题
我最初的问题是加载语言环境。构建后 i18n 找不到文件,因为 webpack 无法识别需要 .json
文件的 i18n-xhr-backend
。然后,在构建之后,没有翻译文件。然后,我试图让 webpack
处理 i18n,但我在下一段遇到了另一个问题。
React 需要将 i18n 实例添加到 i18nextProvider
。但是,在我这样做的过程中,React 中没有要引用的 i18n 实例。然后,它找不到翻译功能和其他任何功能。我也找到了 i18nWebpackPlugin,但它也没有解决我的问题,因为它也不允许访问 react 中的 i18n
实例。最后,我有两个未解决的问题。
解决方案
我的解决方案非常简单。我已经为 development
env 创建了一个新的 i18n
配置,并让 webpack 处理 .json
,在构建后将其复制到一个新文件夹。我将在下面列出我的 webpack 和 i18n 的配置文件。我的步骤:
- 将
i18n.init()
带回i18n/index.js
- 为每个环境创建不同的选项
- 配置webpack复制翻译文件
- 再次在
App.js
上导入 i18n 实例
现在,一切都像魅力一样。
OBS: To webpack recognize the .json
files, you need to import it somewhere. I did inside the resources.js
file.
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;
我在使用 React、i18next 和 Webpack 时遇到了一些问题。我尝试了很多解决方案,但其中 none 行得通。当我尝试构建我的应用程序时,它构建成功。但是,当我尝试打开它时,控制台显示错误。我的 webpack.config 和错误堆栈跟踪如下。
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 i18nPlugin = require("i18n-webpack-plugin")
const options = require("../src/controllers/i18n").options
const locales = require("../src/controllers/i18n/locales")
options.backend.loadPath = "." + options.backend.loadPath
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")
}
},
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"
}, {
loader: "i18next-loader"
}]
},
{
test: /\.css$/,
use: [
miniCSSExtractPlugin.loader,
{
loader: "css-loader",
}
]
}, {
test: /\.(png|jpg|gif)$/,
use: [{
loader: 'file-loader?name=images/[hash].[ext]',
options: {
name: "assets/images/[hash].[ext]"
}
}]
}, {
test: /\.(ttf|woff(2)|eof|svg)$/,
use: [{
loader: "file-loader",
options: {
name: "assets/fonts/[hash].[ext]",
}
}]
}
],
},
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
}),
new i18nPlugin(locales,{
functionName: "t",
nested: true
},true)
]
};
module.exports = config;
npm 运行 构建 运行s 正常,没有关于 i18next 的错误。然后,当我打开应用程序时,出现此错误:
bundle.js:33 TypeError: r.getFixedT is not a function
at L (bundle.js:12)
at bundle.js:12
at Xo (bundle.js:33)
at Ia (bundle.js:33)
at qi (bundle.js:33)
at $i (bundle.js:33)
at jl (bundle.js:33)
at Cl (bundle.js:33)
at Pl (bundle.js:33)
at Ji (bundle.js:33)
希望有人能帮助我。
我发现了我的问题所在。在 i18next 文档中说我应该 运行 webpack.config.js
.
问题
我最初的问题是加载语言环境。构建后 i18n 找不到文件,因为 webpack 无法识别需要 .json
文件的 i18n-xhr-backend
。然后,在构建之后,没有翻译文件。然后,我试图让 webpack
处理 i18n,但我在下一段遇到了另一个问题。
React 需要将 i18n 实例添加到 i18nextProvider
。但是,在我这样做的过程中,React 中没有要引用的 i18n 实例。然后,它找不到翻译功能和其他任何功能。我也找到了 i18nWebpackPlugin,但它也没有解决我的问题,因为它也不允许访问 react 中的 i18n
实例。最后,我有两个未解决的问题。
解决方案
我的解决方案非常简单。我已经为 development
env 创建了一个新的 i18n
配置,并让 webpack 处理 .json
,在构建后将其复制到一个新文件夹。我将在下面列出我的 webpack 和 i18n 的配置文件。我的步骤:
- 将
i18n.init()
带回i18n/index.js
- 为每个环境创建不同的选项
- 配置webpack复制翻译文件
- 再次在
App.js
上导入 i18n 实例
现在,一切都像魅力一样。
OBS: To webpack recognize the
.json
files, you need to import it somewhere. I did inside theresources.js
file.
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;