使用i18next-resources-for-ts生成文件引发Vite告警问题求助
问题背景
执行i18next-resources-for-ts toc命令生成的ressources.ts文件直接从/public目录导入JSON资源,触发Vite告警:
Assets in public directory cannot be imported from JavaScript.
If you intend to import that asset, put the file in the src directory, and use /src/locales/en/translations.json instead of /public/locales/en/translations.json.
If you intend to use the URL of that asset, use /locales/en/translations.json?url.
生成的ressources.ts代码:
import units from "../../public/locales/en/units.json"; const resources = { units, } as const; export default resources;
当前i18n配置已使用i18next-http-backend动态加载资源:
import i18next from "i18next"; import { initReactI18next } from "react-i18next"; import LanguageDetector from "i18next-browser-languagedetector"; import Backend from "i18next-http-backend"; i18next .use(initReactI18next) .use(LanguageDetector) .use(Backend) .init({ supportedLngs: ["en"], detection: { convertDetectedLanguage: (lng) => lng.slice(0, 2), }, load: "languageOnly", defaultNS: "terms", fallbackLng: ["en"], backend: { loadPath: `${window.location.pathname}locales/{{lng}}/{{ns}}.json`, cache: "no-cache", }, }) .then(() => { someFunc(i18next); }); export default i18next;
解决方案
方案一:迁移资源到src目录(推荐)
Vite明确禁止从JS/TS中直接导入public目录下的资源,最合理的解决方式是调整资源目录结构:
- 将
/public/locales目录整体移动到/src目录下,变为/src/locales。 - 修改
i18next-resources-for-ts的命令配置,让它扫描/src/locales目录生成ressources.ts,生成后的导入路径会自动指向src下的文件,示例:import units from "../../src/locales/en/units.json"; const resources = { units, } as const; export default resources; - 同步调整i18n配置中的
backend.loadPath:backend: { loadPath: "/locales/{{lng}}/{{ns}}.json", cache: "no-cache", },
方案二:移除静态导入,完全依赖http-backend动态加载
如果你不想移动资源目录,且当前已经配置了i18next-http-backend,可以直接删除自动生成的ressources.ts文件——http-backend会通过网络请求动态加载public目录下的资源,不需要提前静态导入,这样既解决了Vite告警,也能正常加载翻译资源。
方案三:保留public目录的静态导入(不推荐)
如果因特殊需求必须从public导入,可按照Vite提示在导入路径后加?url,但这种方式只能获取资源URL,需要额外处理JSON内容:
import unitsUrl from "../../public/locales/en/units.json?url"; // 手动fetch加载JSON const loadResources = async () => { const units = await fetch(unitsUrl).then(res => res.json()); return { units }; }; // 在i18next初始化时注入资源 i18next.init({ // ...其他配置 resources: await loadResources(), });
这种方式需要修改初始化逻辑,且失去了静态导入的类型提示优势,不推荐使用。
内容的提问来源于stack exchange,提问作者Pazu

