我正在使用 React-i18next
^15.1.0
和 Typescript ^5.6.3
并尝试使自动完成功能正常工作。我已经遵循了教程(https://locize.com/blog/i18next-typescript/)和(https://www.i18next.com/overview/typescript)。
通过在
i18next.d.ts
文件中导入翻译资源的简单配置不起作用后,我决定尝试更复杂的方法来使用 i18next-resources-for-ts interface -i ./locales/en -o ./@types/resources.d.ts
命令行,以生成涵盖更多用例的界面。
现在我的自动完成功能几乎可以工作了,但我只获得了默认命名空间的自动完成功能,但其他命名空间不可用。不仅自动补全不起作用,而且我现在还收到 TS 错误:
t("timesheet:placeholder.What are you working on")
Type '"timesheet:placeholder.What are you working on"' is not assignable to type '"common.Case" | "common.Code" | "common.Price" | "common.Qty" | "common.Select Case" | "common.Select Code" | "common.Total" | "common.Unit" | TemplateStringsArray | ("common.Case" | ... 7 more ... | TemplateStringsArray)[]'
另一个奇怪的行为是,如果我将
defaultNS
更改为 timesheet
,那么我只有 timesheet
命名空间工作,而不是 translation
命名空间。
为了让所有命名空间都可用作类型,我缺少什么?
这是我的配置:
i18n.ts
import i18n from "i18next";
import LanguageDetector from "i18next-browser-languagedetector";
import { initReactI18next } from "react-i18next";
import TIMESHEET_DE from "@/locales/de/timesheet.json";
import TRANSLATION_DE from "@/locales/de/translation.json";
import TIMESHEET_EN from "@/locales/en/timesheet.json";
import TRANSLATION_EN from "@/locales/en/translation.json";
import TIMESHEET_FR from "@/locales/fr/timesheet.json";
import TRANSLATION_FR from "@/locales/fr/translation.json";
import TIMESHEET_IT from "@/locales/it/timesheet.json";
import TRANSLATION_IT from "@/locales/it/translation.json";
const resources = {
en: {
translation: TRANSLATION_EN,
timesheet: TIMESHEET_EN,
},
fr: {
translation: TRANSLATION_FR,
timesheet: TIMESHEET_FR,
},
it: {
translation: TRANSLATION_IT,
timesheet: TIMESHEET_IT,
},
de: {
translation: TRANSLATION_DE,
timesheet: TIMESHEET_DE,
},
} as const;
const defaultNS = "translation";
const ns = ["translation", "timesheet"];
i18n
// detect user language
// learn more: https://github.com/i18next/i18next-browser-languageDetector
.use(LanguageDetector)
.use(initReactI18next)
// for all options read: https://www.i18next.com/overview/configuration-options
.init({
returnEmptyString: false,
debug: import.meta.env.DEV,
fallbackLng: "en",
lng: "en",
defaultNS,
ns,
interpolation: {
escapeValue: false, // not needed for react as it escapes by default
},
resources: resources,
});
export default i18n;
export { defaultNS, ns, resources };
i18next.d.ts
import type Resources from "./resources";
import { defaultNS, ns } from "@/i18n";
declare module "i18next" {
interface CustomTypeOptions {
resources: Resources;
defaultNS: typeof defaultNS;
ns: typeof ns;
}
}
resources.d.ts
interface Resources {
"timesheet": {
"placeholder": {
"What are you working on": ""
}
},
"translation": {
"common": {
"Case": "Case",
"Code": "Code",
"Price": "Price",
"Qty": "Qty",
"Select Case": "Select Case",
"Select Code": "Select Code",
"Total": "Total",
"Unit": "Unit"
}
}
}
export default Resources;
我实际上会回答我自己的问题,因为我已经找到了答案。
棘手的部分实际上在本教程中的某个地方。
解决问题的部分是:
在新的react-i18next版本中,当加载多个命名空间时,t函数将推断并接受第一个命名空间的键。所以现在这种模式被接受了:
const {t} = useTranslation(['ns1', 'ns2']);
所以实际上我们必须告诉
useTranslation
我们要使用哪个命名空间,以便 t
能够正确键入。