我最近成功地使用react-18next 实现了我的应用程序内的本地化需求。我有一个小包,其中包含本地化文件、react-i18next 设置,并导出另一个应用程序中引用的类以获取 i18n 实例并将其传递给包装我的组件的类。
这已部署并按预期工作。
我偶然发现了这里的文档(https://react.i18next.com/latest/typescript#create-a-declaration-file),它说你能够使 t 函数完全类型安全。我很想实现这个,这样我就能够在编译时捕获不匹配的关键错误,而不是需要在应用程序中寻找每个案例。
不过,我在实现这种所需的类型安全方面遇到了一些麻烦,并且不确定这是否是我做错了,或者可能是打字中的错误(我假设是前者,因为其他人似乎没有任何问题就可以安全工作) ).
版本:
Repo 结构(不包括 package.json、tsconfig.json 等):
翻译文件不使用任何嵌套字符串,并按语言分隔(“_en”与“_es”)。每种语言都有其本地化格式的所有所需字符串。文件格式如下:
{
"string1": "First string",
"string2": "Second string"
}
在我的实时(工作)设置中,这就是我初始化实例的方式:
import translationEN from "./translations/translations_en.json";
export class MyTranslationManager {
private readonly i18nInstance: i18nType;
constructor() {
this.i18nInstance = i18n.createInstance();
const defaultResources = {
en: { translation: { ...translationEN } },
};
this.language = "en";
this.i18nInstance
.use(initReactI18next)
.init({
resources: defaultResources,
lng: "en",
keySeparator: false, // we do not use nested translation resources
interpolation: {
escapeValue: false, // React already prevents XSS
},
});
}
// 致力于类型安全
按照文档中的指示,我创建一个react-i18next.d.s 文件来重新声明“react-i18next”模块 - 特别是 CustomTypeOptions 接口:
import "react-i18next";
import translationEN from "./translations/translations_en.json";
declare module "react-i18next" {
interface CustomTypeOptions {
resources: typeof translationEN;
}
}
我没有为 CustomTypeOptions 声明“defaultNS”选项,因为我依赖于默认命名空间“translation”。
当我尝试使用上述代码编译项目时,出现以下 TS2344 问题:
node_modules/react-i18next/ts4.1/index.d.ts:203:25 - error TS2344:
Type 'string' does not satisfy the constraint 'Namespace<"btn_cancel" | "btn_save" | ... 86 more ... | "msg_unsavedChanges">'.
203 N extends Namespace = DefaultNamespace,
react-i18next/ts4.1/index.d.ts 中尝试设置 Namespace = DefaultNamespace 的每一行都会抛出错误。
我将index.d.ts中尽可能多的代码复制到Typescript Playground中,尝试深入了解这里发生的情况,并且我能够重现编译错误。
将鼠标悬停在 Typescript 游乐场中的以下项目上可以提供一些有趣的见解:
我的问题是,为什么语言文件的键被设置为命名空间?这是设计使然吗?我是否以错误的方式导入资源?
我注意到这里的示例(https://github.com/i18next/react-i18next/blob/master/example/react-typescript4.1/no-namespaces/%40types/react-i18next/index.d。 ts)仅显示文档指向的旧版本,即使用 DefaultResources 类型而不是 CustomTypeOptions。任何关于使用没有命名空间的新方法的指导将不胜感激:)
对于任何使用
[email protected]
和 [email protected]
的人来说,遵循此处的文档对我来说是成功的(截至发布本文时):
https://www.i18next.com/overview/typescript
我现在正在
t()
函数中获取翻译类型
我经常遇到这个问题,因此我创建了一个非常轻量级的包,旨在确保 100% 类型安全的国际化。随意使用它。访问我的
i18n-type-safe
GitHub 存储库。
按照简单的设置说明进行操作。你就一切准备就绪了!