使用您最喜欢的AI助手总结文档,并引用此页面和AI提供商
版本历史
- "添加 GitHub 明星对比"v8.9.82026/5/18
- "初始化基准"v8.7.122026/1/6
此页面的内容已使用 AI 翻译。
查看英文原文的最新版本If you have an idea for improving this documentation, please feel free to contribute by submitting a pull request on GitHub.
GitHub link to the documentationCopy doc Markdown to clipboard
Solid i18n 库 - 2026 基准报告
此页面是 Solid 上 i18n 解决方案的基准报告。
目录
交互式基准
结果参考:
查看完整的基准测试数据
查看完整的基准仓库 此处。
简介
国际化解决方案是 Solid 应用中最重的依赖项之一。主要风险是发送不必要的内容:单个路由包中包含其他页面和其他语言的翻译。
随着应用增长,这个问题会迅速增加发送到客户端의 JavaScript,并减慢导航速度。
实际上,对于优化最差的实现,国际化页面的重量可能是非 i18n 版本的几倍。
另一个影响是开发者体验(DX):如何声明内容、类型、命名空间组织、动态加载以及语言更改时的反应性。
TL;DR
- Intlayer: 需要高级功能和优化的专业 Solid 应用的推荐选择(v8.7.12)。
- @solid-primitives/i18n: 简单项目的绝佳轻量级替代方案,但缺乏延迟加载等高级功能。
- solid-i18next: 标准但沉重的选项(约为 Intlayer 的 4.7 倍),具有与 React i18next 相同的缺点。
- Paraglide: 创新的方法,但在某些设置中 DX 复杂且存在 tree-shaking 问题。
测试您的应用
为了快速发现 i18n 泄漏问题,我建立了一个免费扫描仪,可在 此处 试用。
问题所在
限制多语言应用成本有两个关键杠杆:
- 按页面 / 命名空间拆分内容,这样在不需要时就不会加载整个字典
- 仅在需要时动态加载正确的语言
了解这些方案的技术限制:
动态加载
如果没有动态加载,大多数解决方案会从首次渲染开始将消息保留在内存中,这对于具有许多路由和语言的应用会产生显著开销。
使用动态加载,您接受一个权衡:减少初始 JS,但有时在切换语言时会有额外的请求。
内容拆分
围绕 t('a.b.c') 构建的语法非常方便,但往往鼓励在运行时保留大型 JSON 对象。这种模式使 tree-shaking 变得困难,除非库提供真正的按页面拆分策略。
研究方法
在此基准测试中,我们比较了以下库:
Base App(无 i18n 库)solid-intlayer(v8.7.12)@solid-primitives/i18n(v2.2.1)solid-i18next(v17.0.2)@inlang/paraglide-js(v2.17.0)
框架是 Solid,应用包含 10 个页面 和 10 种语言。
我们比较了 四种加载策略:
在弹窗中打开表格以清晰地查看所有数据
| 策略 | 无命名空间(全局) | 具有命名空间(分层/scoped) |
|---|---|---|
| 静态加载 | Static: 启动时所有内容都在内存中。 | Scoped static: 按命名空间拆分;启动时加载所有内容。 |
| 动态加载 | Dynamic: 按需按语言加载。 | Scoped dynamic: 按命名空间和语言进行细粒度加载。 |
策略摘要
- 静态 (Static): 简单;初始加载后无网络延迟。缺点:包体积大。
- 动态 (Dynamic): 减轻初始重量(懒加载)。当您有多种语言时非常理想。
- 分层静态 (Scoped static): 保持代码有序(逻辑分离),无需复杂的额外网络请求。
- 分层动态 (Scoped dynamic): 代码拆分 和性能的最佳方法。通过仅加载当前视图和活动语言所需的内容来最小化内存使用。
我测量的内容:
我在实际浏览器中为每个技术栈运行相同的多语言应用,然后记录了实际显示的内容和花费的时间。大小是在正常 Web 压缩后报告的,因为这更接近人们下载的内容,而不是原始源代码计数。
国际化库大小:在捆绑、树形摇晃和最小化后,i18n 库的大小是空组件中提供程序 + hooks/基元代码的大小。它不包括加载翻译文件。它回答了在您的内容进入之前库的成本。
每页 JavaScript:对于每个基准测试路由,浏览器在该访问中提取的脚本量,在套件中的页面之间平均(以及在报告汇总的语言之间)。沉重的页面是缓慢的页面。
来自其他语言的泄漏:这是同一页面但以另一种语言显示的内容,会被错误地加载到已审核页面中。此内容是不必要的,应该避免。(例如
/fr/about页面内容在/en/about页面包中)来自其他路由的泄漏:对于应用中的其他屏幕也是相同的概念:当您只打开一个页面时,它们的副本是否会随之而来。(例如
/en/about页面内容在/en/contact页面包中)。高分数表示分割较弱或包过于宽泛。平均组件包大小:常见的 UI 部分被一次一个测量,而不是隐藏在一个巨大的应用数字中。它显示国际化是否悄悄地增加了日常组件的大小。例如,如果您的组件重新渲染,它将从内存加载所有该数据。将一个巨大的 JSON 附加到任何组件就像连接一个大量未使用数据的仓库,这会减慢您组件的性能。
语言切换响应性:我使用应用自己的控件翻转语言,并计时直到页面明显切换需要多长时间,这是访问者会注意到的,而不是实验室微步骤。
语言更改后的渲染工作:一个更狭隘的后续:界面为新语言重新绘制需要花费多少工作量,一旦切换进行中。当"感知"时间和框架成本不同时很有用。
初始页面加载时间:从导航到浏览器认为页面对我测试的场景完全加载。适合比较冷启动。
水合时间:当应用公开它时,客户端花费多长时间将服务器 HTML 转换为您实际可以点击的内容。表格中的破折号表示该实现在此基准测试中没有提供可靠的水合数据。
GitHub 星数
GitHub 星数是项目受欢迎程度、社区信任和长期相关性的有力指标。虽然星数不是技术质量的直接衡量标准,但它们反映了有多少开发人员发现该项目有用、关注其进展并可能采用它。在评估项目价值时,星数有助于比较不同方案的吸引力,并提供对生态系统增长的见解。
结果详情
1 - 应当避免的解决方案
Solid 生态系统中没有明确应当避免的解决方案。
2 - 可接受的解决方案
(solid-i18next) (solid-i18next@17.0.2):
solid-i18next 可能是最受欢迎的选项,因为它是最早满足 JavaScript 应用 i18n 需求的解决方案之一。它还拥有一套广泛的社区插件来解决特定问题。
该包很重(~14.6kb,约为 solid-intlayer 的 4.7 倍)。
尽管如此,它与基于 t('a.b.c') 构建的栈具有相同的主要缺点:优化是可能的,但非常耗时,且大型项目面临不良实践(命名空间 + 动态加载 + 类型)的风险。
(@solid-primitives/i18n) (@solid-primitives/i18n@2.2.1):
Solid primitive 非常轻量且高效,我推荐将其用于轻量级项目,但对于包含 cookie 管理、代理重定向、格式化器等在内的专业解决方案,它可能会迅速显现功能不足。 它还缺乏延迟加载和分层命名空间以进行页面大小优化。
(Paraglide) (@inlang/paraglide-js@2.17.0):
Paraglide 提供了一种创新且深思熟虑的方法。尽管如此,在此基准测试中,他们宣传的 tree-shaking 在我的实现中没有按预期工作。工作流程和 DX 也比其他选项更复杂。
我个人不喜欢在每次推送前重新生成 JS 文件,这会通过 PR 在开发者之间造成持续的合并冲突风险。
最后,与其他解决方案相比,Paraglide 不使用 store(例如 Solid signal)来检索当前语言以渲染内容。对于解析的每个节点,它都会从 localStorage / cookie 等请求语言。这导致执行不必要的逻辑,从而影响组件的反应性。
3 - 建议
(Intlayer) (solid-intlayer@8.7.12):
出于客观性考虑,我个人不会对 solid-intlayer 做出评价,因为它是我的个人解决方案。
个人笔记
此笔记仅代表个人观点,不影响基准测试结果。尽管如此,在 i18n 领域,您经常会看到围绕 const t = useTranslation('xx') + <>{t('xx.xx')}</> 模式的翻译内容共识。
在 Solid 应用中,将函数作为 JSX.Element 注入在我的观点中是一种反模式。它还增加了可避免的复杂性和 JavaScript 执行开销(即使几乎察觉不到)。