
replexica new-compiler 翻译工具链完全指南伪本地化与磁盘缓存的工程化实践【免费下载链接】replexicaOpen-source localization engineering tools. Connects to Lingo.dev localization engineering platform for consistent, quality translations.项目地址: https://gitcode.com/GitHub_Trending/re/replexicareplexica连接 Lingo.dev 本地化工程平台的翻译工具集在其新一代编译器packages/new-compiler中提供了一套面向 React Server Components 的翻译工具模块lingo.dev/compiler-beta/translate。本文以 translators/README.md 为主线系统讲解该模块的两大核心能力——伪本地化Pseudolocalization与翻译缓存Caching从「一行配置自动开启」到「手动接管翻译流程」再到缓存落盘的目录结构并结合仓库源码PseudoTranslator、LocalTranslationCache、TranslationService等剖析其底层实现原理。读完本文你将掌握在 Next.js/Turbopack 项目中快速验证 i18n 布局、为任何翻译函数叠加磁盘缓存、以及深入定制翻译管线的完整方法。模块概览lingo.dev/compiler-beta/translate提供了什么翻译工具模块是编译器的「翻译层」统一了「翻译器Translator」与「缓存Cache」两类抽象。从 index.ts 的导出可以看到其核心 API 组成翻译器实现PseudoTranslator伪本地化用于开发测试、LingoTranslator真实 AI 翻译接入 Lingo.dev 或自定义 LLM Provider编排器TranslationService负责在 metadata、cache、translator 之间协调完整翻译工作流缓存抽象TranslationCache接口与createCache工厂当前支持本地磁盘缓存local类型类型定义Translator、TranslatableEntry、DictionarySchema、LocalCacheConfig等。所有翻译器统一实现TranslatorConfig接口见 api.tsexport interface TranslatorConfig { config: Config; translate: ( locale: LocaleCode, entriesMap: Recordstring, TranslatableEntry, ) PromiseRecordstring, string; }其中TranslatableEntry { text: string; context: Recordstring, any }。该接口支持批量翻译——一次调用可以传入一个或多个条目翻译结果以hash - translated text的扁平映射返回。这是理解后续所有用法的基础无论是伪翻译、AI 翻译还是自定义翻译器都遵循同一套契约因此可以方便地叠加统一的缓存包装器。伪本地化不花一分钱 API 也能测试国际化布局伪本地化Pseudolocalization是把源语言文本替换成「看似外语、实则保留原词形」的变体字符如Hello World→Ĥéĺĺó Ŵóŕĺḍ并人为拉长文本长度。它的价值在于在真实翻译接入之前提前暴露 UI 布局问题文本变长导致的换行、溢出、截断以及硬编码字符串等 i18n 隐患都能在开发阶段暴露出来。仓库中的PseudoTranslatorpseudotranslator/index.ts正是为此设计——它的注释明确写道「Pseudotranslator for testing without actual translation APIs」。它内部维护了一张PSEUDO_MAP字符映射表a→á、l→ĺ、o→ó……A→Á、Z→Ẑ把可见字符逐一替换为带重音/变音符的等价字符。推荐方式通过 Loader 配置一键开启README 推荐的最简方式是在 Next.js 的 Turbopack 配置中通过 loader 配置启用// next.config.ts export default { turbopack: { rules: { *.{tsx,jsx}: { loaders: [ { loader: lingo.dev/compiler-beta/loader, options: { sourceRoot: ./app, lingoDir: .lingo, sourceLocale: en, translator: pseudo, // Enable automatic pseudolocalization }, }, ], as: *.tsx, }, }, }, };各选项含义如下选项示例值作用loaderlingo.dev/compiler-beta/loader编译期 loader 入口负责对 TSX/JSX 做静态转换sourceRoot./app源代码根目录也是 metadata 与缓存文件的相对基准lingoDir.lingo存放 metadata 与缓存的目录名sourceLocaleen源语言 locale 代码translatorpseudo翻译器选择设为pseudo即启用自动伪本地化当translator: pseudo被设置后编译器会自动完成三件事导入并初始化带缓存的伪翻译器cached pseudotranslator将其注入到所有 Server Components的翻译调用链中把翻译结果缓存到.lingo/cache/目录避免重复计算。示例输出README 给出的转换效果Hello World→[Ĥéĺĺó Ŵóŕĺḍ ]Welcome→[Ŵéĺçóṁé ]说明文档示例中统一以方括号包裹输出以便辨识当前源码实现中pseudolocalize的返回值为「伪本地化字符 约 30% 长度的空格填充」详见下文源码剖析。手动伪本地化高级用法如果你不使用 loader 配置也可以手动把pseudoTranslate当作翻译函数直接传入import { pseudoTranslate } from lingo.dev/compiler-beta/translate; // Use as translation function const t await getServerTranslations({ metadata: __lingoMetadata, sourceLocale: en, translate: pseudoTranslate, });这里getServerTranslations来自 react/server-only/index.ts它返回一个t(hash, sourceText, params?)函数当translations[hash]缺失时回退到sourceText并支持富文本参数渲染。手动方式适合需要完全掌控翻译来源、或把伪翻译与真实翻译器动态切换的场景。为翻译函数叠加磁盘缓存createCachedTranslator无论使用哪种翻译器都可以用createCachedTranslator包一层让「已翻译过的 hash 直接命中缓存不再重复调用翻译器」import { createCachedTranslator, pseudoTranslate, } from lingo.dev/compiler-beta/translate; // Create cached version const cachedTranslate createCachedTranslator(pseudoTranslate, { cacheDir: .lingo, sourceRoot: ./app, }); // Use in server components const t await getServerTranslations({ metadata: __lingoMetadata, sourceLocale: en, translate: cachedTranslate, // Will use cache/.json files });createCachedTranslator返回的仍是Translator接口因此可以无缝替换任何位置的翻译函数。其缓存实现由 cache-factory.ts 的createCache(config)工厂创建目前仅支持cacheType: local对应LocalTranslationCache若传入其他类型会抛出Unknown cache type错误——这是 TypeScript 类型与运行时双重保障的设计。服务端缓存的直接管理ServerTranslationCache如果需要在 Server Component 中手动读写缓存例如预取某语言、主动清理缓存可以直接使用ServerTranslationCacheimport { ServerTranslationCache } from lingo.dev/compiler-beta/translate; const cache new ServerTranslationCache({ cacheDir: .lingo, sourceRoot: ./app, }); // Check if cached const hasFrench await cache.has(fr); // Get translations const translations await cache.getTranslations(fr); // Set translations await cache.set(fr, dictionarySchema); // Clear cache await cache.clear(fr); await cache.clearAll();这套 API 对应 cache.ts 中定义的TranslationCache接口的完整能力get支持按 hash 列表部分获取、update合并式更新不覆盖已有条目、set整体替换某 locale 的缓存、has、clear清单个 locale与clearAll清空全部。自动转换示例一行配置编译器替你生成全部样板代码README 用一个「前后对比」直观展示了配置驱动模式下的魔法。原始代码// app/page.tsx - Your original code export default function Home() { return h1Hello World/h1; }编译器将其自动转换为// Transformed (automatic, no manual changes needed) import { getServerTranslations } from lingo.dev/compiler-beta/react/server; import { createCachedTranslator, pseudoTranslate } from lingo.dev/compiler-beta/translate; import __lingoMetadata from ./.lingo/metadata.json; const __lingoTranslate createCachedTranslator(pseudoTranslate, { cacheDir: .lingo, sourceRoot: ./app, }); export default async function Home() { const t await getServerTranslations({ metadata: __lingoMetadata, sourceLocale: en, translate: __lingoTranslate, }); return h1{t(63b8a9ec9544)}/h1; // [Ĥéĺĺó Ŵóŕĺḍ ] }可以看到转换的完整链路硬编码文案Hello World被提取为 hash 键63b8a9ec9544hash 来源于源文本并注入getServerTranslations、createCachedTranslator(pseudoTranslate, …)与.lingo/metadata.json导入。这条「提取 → 注入翻译函数 → 按 hash 取词」的路径正是编译期 loader 的核心工作。与之对应的转换逻辑在编译插件的 transform 管线中实现参见 transform/transform.test.ts 中大量关于「注入 getServerTranslations 与 hash 数组」的断言。手动设置示例布局级别的翻译注入在需要手动控制例如把翻译注入根布局时README 给出如下模板// app/layout.tsx import { getServerTranslations } from lingo.dev/compiler-beta/react/server; import { createCachedTranslator, pseudoTranslate } from lingo.dev/compiler-beta/translate; import __lingoMetadata from ./.lingo/metadata.json; // Create cached translator const translate createCachedTranslator(pseudoTranslate, { cacheDir: .lingo, sourceRoot: ./app, }); export default async function RootLayout({ children }) { const t await getServerTranslations({ metadata: __lingoMetadata, sourceLocale: en, translate, // Pseudolocalize with caching }); return ( html body{children}/body /html ); }要点getServerTranslations是 async APIReact Server Component 中可直接awaitcreateCachedTranslator接收缓存配置并返回翻译函数metadata 从.lingo/metadata.json导入。整个流程不需要任何运行时翻译服务即可工作。缓存结构.lingo/cache/locale.json所有翻译结果缓存在sourceRoot/cacheDir/cache/locale.jsonREADME 给出的目录示意app/ .lingo/ metadata.json # Source strings cache/ en.json # English (source) fr.json # French translations pseudo.json # Pseudolocalizedmetadata.json保存源字符串含 context 等元信息是 hash 与源文本的对应表cache/en.json等按 locale 命名是该语言的hash - 译文映射。磁盘缓存的落盘实现在 local-cache.tsgetDictionary读取cacheDir/locale.json并JSON.parsesetDictionary先fs.mkdir(cacheDir, { recursive: true })确保目录存在再以JSON.stringify(dictionary, null, 2)写入。所有文件 I/O 都被 utils/timeout.ts 的withTimeout包裹默认DEFAULT_TIMEOUTS.FILE_IO即 10 秒防止缓存读写导致构建/请求无限挂起。缓存文件结构遵循DictionarySchema见 api.ts{ version, locale, entries }其中entries即 hash 到译文的扁平映射。值得注意的合并语义update()采用「读旧值 → 合并新值 → 整体写回」的策略local-cache.ts的update方法即新增翻译不会清空已有缓存而set()则整体替换。clearAll()只删除目录下以.json结尾的文件忽略其他内容。客户端组件的不同处理方式伪本地化与磁盘缓存主要面向 Server ComponentsNode 运行时允许 fs 操作。对于客户端组件README 明确指出翻译机制不同使用useTranslation()hook由编译器自动注入翻译通过 API 或打包资源加载浏览器端缓存可考虑 IndexedDB尚未实现属计划能力勿当作既有功能。这一点也从测试中可以得到印证transform 测试中客户端组件断言「使用统一 hook 导入而不是 getServerTranslations / await getServerTranslations」见 transform.test.ts。源码纵深三个关键实现的原理剖析1.pseudolocalize保留占位符的字符级替换pseudolocalizepseudotranslator/index.ts是伪本地化的核心函数实现要点跳过纯空白与纯变量文本!text.trim()或整体匹配^{.*}$时原样返回保留正则/(\{\w}|\/?\w\/?)/g匹配{name}变量占位符与a0//a0组件标签将这些片段标记为preserve: true不参与字符替换——这一点对 React 富文本至关重要因为标签一旦被破坏会导致渲染错误只对可翻译片段做字符映射逐字符查PSEUDO_MAP未收录字符如数字、标点原样保留按源文本长度追加约 30% 空格 .repeat(Math.ceil(text.length * 0.3))用于模拟真实翻译后的文本膨胀。配套测试 pseudotranslator/index.test.ts 覆盖了纯文本、单/多变量占位符、单/多组件标签、混合场景与纯空白等用例例如断言pseudolocalize(Hello {name})同时包含{name}与Ĥéĺĺó。2.LocalTranslationCache与MemoryTranslationCache两种缓存实现local-cache.ts 是磁盘实现每次get都读文件并解析 JSON读取失败文件不存在返回{}而不是抛错has用fs.access判断文件存在性clear对不存在的文件静默忽略错误。memory-cache.ts 是内存实现内部用MapLocaleCode, Mapstring, string适合一次性进程内会话如伪翻译的开发回退场景。3.TranslationService缓存优先的编排器translation-service.ts 的translate(locale, metadata, requestedHashes?)完整展示了 README「Cache is checked before calling translate function」的实现确定本次需要处理的 hash 集合未传时取 metadata 全部键先查缓存得到cachedTranslations过滤出未命中的 hashuncachedHashes若全部命中则直接返回cached: N, translated: 0对未命中条目处理复数化若启用pluralization服务检查每个条目的overrides[locale]有覆盖值则直接用覆盖值不调用翻译器对仍需翻译的条目调用translator.translate(locale, entriesToTranslate)源 locale 直接返回可能经过复数化的sourceText不调用翻译器处理PartialTranslationError的部分失败结果已付费的翻译不丢弃见 api.ts成功翻译写入缓存cache.update合并缓存写失败不阻断请求汇总stats: { total, cached, translated, failed }与errors返回。此外构造器里有一套清晰的降级策略开发环境下若dev.usePseudotranslator为 true或创建LingoTranslator失败如缺少 API Key都会自动回退到PseudoTranslator({ delayMedian: 100 })MemoryTranslationCache生产环境则直接抛错避免静默降级。4. 真实翻译LingoTranslator与自定义翻译器伪本地化之外同一套Translator接口也服务于真实 AI 翻译LingoTranslator见 lingo/README.md支持models: lingo.dev官方引擎或自定义模型映射如en:es: google:gemini-2.0-flash、*:*: openrouter:...并通过环境变量提供密钥LINGODOTDEV_API_KEY或GOOGLE_API_KEY、GROQ_API_KEY、OPENROUTER_API_KEY、MISTRAL_API_KEY等。你也可以实现自定义Translator并用createCachedTranslator包装完整示例见同目录的 USAGE.md含旧TranslateFunctionAPI 的迁移对照。注意事项与最佳实践README 末尾的 Notes 是实践中最重要的约束逐条整理如下Server Components可使用磁盘缓存允许 fs 操作这是createCachedTranslator/ServerTranslationCache的适用场景Client Components需要浏览器侧缓存方案IndexedDB、API endpoints当前未实现请勿依赖缓存优先翻译前先查缓存命中则跳过翻译函数——这是避免重复翻译、节省 API 费用的关键设计文本膨胀伪本地化会把文本长度拉长约 30%这是有意为之的布局压力测试手段不是缺陷——正是靠它提前发现 UI 溢出问题生产环境不要依赖伪翻译translator: pseudo仅用于开发验证正式发布请切换到LingoTranslator或自定义翻译器并正确配置 API Key。综合来看lingo.dev/compiler-beta/translate模块提供了「配置驱动优先、手动控制兜底」的两级使用模式日常开发用translator: pseudo一条配置完成伪本地化 缓存闭环进阶场景用createCachedTranslator/ServerTranslationCache精细管理翻译与缓存生命周期。配合Translator统一接口无论是伪翻译、Lingo.dev 还是自定义 LLM都能以一致的姿势接入这正是该模块在工程可维护性上的核心价值。【免费下载链接】replexicaOpen-source localization engineering tools. Connects to Lingo.dev localization engineering platform for consistent, quality translations.项目地址: https://gitcode.com/GitHub_Trending/re/replexica创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考