i18next + React + Webpack - getFixedT不是一个函数

问题描述 投票:0回答:1

我在使用React,i18next和Webpack时遇到了一些麻烦。我尝试过很多解决方案,但都没有。当我尝试构建我的应用程序时,它成功构建。但是,当我尝试打开它时,控制台显示错误。我的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 run build正常运行,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)

希望有人可以帮助我。

reactjs webpack i18next
1个回答
1
投票

我发现了我的问题。在i18next文档中说我应该在webpack.config.js中运行init。

The Problem

我最初的问题是加载语言环境。在构建之后,i18n找不到文件,因为webpack无法识别需要i18n-xhr-backend文件的.json。然后,在构建之后,没有翻译文件。然后,我试图让webpack处理i18n,我在下一段有另一个问题。

React需要将i18n实例添加到i18nextProvider。但是,在我正在做的方式上,没有i18n实例来反驳React内部。然后,它找不到翻译功能和其他任何东西。我也找到了i18nWebpackPlugin,但它也没有解决我的问题,因为它也没有提供访问内部的i18n实例的反应。最后,我有两个未解决的问题。

The Solution

我的解决方案非常简单。我已经为i18n env创建了一个新的development配置,并让webpack处理.json,在构建后将其复制到一个新文件夹。我会让我的配置文件低于webpack和i18n。我的步骤:

  • i18n.init()带回i18n/index.js
  • 为每个环境创建不同的选项
  • 配置webpack以复制翻译文件
  • 再次在App.js上导入i18n实例

现在,一切都像魅力一样。

OBS:要webpack识别.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;

国际化/ 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;
© www.soinside.com 2019 - 2024. All rights reserved.