Uncaught TypeError: i18next.init is not a function

Uncaught TypeError: i18next.init is not a function

我正在为我的项目使用打字稿,并使用 i18next 进行内部化。

打字稿:v2.1.4

i18next: v2.3.4

@types/i18next: v2.3.35

在我的文件中:

import * as i18next from 'i18next';

i18next.init({
    lng: 'en',
    resources: {
        en: {
            translation: {
                "key": "hello world"
            }
        }
    }
}, (err, t) => {
    // initialized and ready to go!
    const hw = i18next.t('key'); // hw = 'hello world'
});

然而,在浏览器中显示:

Uncaught TypeError: i18next.init is not a function

如果我记录 i18next 对象,它看起来像:

并在控制台中

i18n.default.init

效果很好。

如果像文档一样导入

import i18next from 'i18next';

在 visual studio 中的代码会报错:

我的.tsconfig

{
    "compileOnSave": true,
    "compilerOptions": {
        "removeComments": false,
        "baseUrl": "./src",
        "target": "es6",
        "moduleResolution": "node",
        "experimentalDecorators": true,
        "emitDecoratorMetadata": true,
        "noImplicitAny": true,
        "strictNullChecks": true,
        "jsx": "preserve",
        "lib": [
            "es2017",
            "dom"
        ],
        "typeRoots": [
            "./node_modules/@types"
        ],
        "types": [
            "node",
            "poly2tri",
            "three",
            "i18next"
        ]
    }
}

我的 webpack.config.js 太长了,读不下去。

我想知道是否与文档有关:http://www.typescriptlang.org/docs/handbook/declaration-files/templates/module-class-d-ts.html

/*~ Note that ES6 modules cannot directly export class objects.
 *~ This file should be imported using the CommonJS-style:
 *~   import x = require('someLibrary');
 *~
 *~ Refer to the documentation to understand common
 *~ workarounds for this limitation of ES6 modules.
 */

您遇到的问题与

有关

https://github.com/Microsoft/TypeScript/issues/7398

https://github.com/Microsoft/TypeScript/issues/8687

https://github.com/systemjs/systemjs/issues/1587

TypeScript 中的模块解析语法与 Babel/NodeJS 不同。

在Babel/NodeJS(最新草案)中,使用语法导入 CommonJS 模块:

import i18n from 'i18next'

即CommonJS 模块被移动到 ES6 模块的 default 导出。

然而,TypeScript 并不遵循这条路线:

import * as i18n from 'i18next'

因此,当tsc编译为es6时,这个导入语句保持原样。 因此 Babel 做了错误的事情。

请在上述问题中大声疾呼,以引起团队的更多关注。

这个问题真的应该是 P1 并尽快修复。

目前,一种解决方案是通过 tsc 将您的代码编译为 es5。

TL;DR

i18next 版本 17.0.0+ 中,您必须这样导入它:

import { default as i18n } from 'i18next';

tsconfig.js 中设置 "esModuleInterop": true 使其与 jest 一起使用。

我的 tsconfig.js 中的其他模块选项(不确定是否需要所有模块才能使其工作):

"allowSyntheticDefaultImports": true,
"esModuleInterop": true,
"module": "es6",
"moduleResolution": "node",
"target": "es6",

说明

In v17.0.0 i18next changed how the module is exported:

  • removes named exports in main file - avoids issues in mixed exports makes usage better in commonjs scenarios (node.js) - no strange const i18next = require('i18next').default;
  • impact you can't no longer import { changeLanguage } from 'i18next'; changeLanguage('de'); you will have to import i18next from 'i18next'; i18next.changeLanguage('de');