指南 · 迁移
从 i18next 迁移
已经在用 i18next 上线了?@sonenta/react-i18next 是 react-i18next 的直接替换(drop-in)——相同的 useTranslation() 和 t() API:你只需更换 provider,你的翻译就会从 CDN 实时送达。用一条命令将你已有的 locales/ 文件带入 Sonenta,然后让你的代码原样保留。导入会创建缺失的 key、upsert 每一条翻译,且完全幂等:你可以放心地从 CI 中重新运行它。这是完整的路径:安装、导入、发布、验证、接入 SDK。
开始之前
三样东西,然后你就可以开始导入了:
- 一个项目。在 dashboard 中创建一个,并复制它的
project_uuid。 - 一个
mcp:*scope 的 API key。CLI 通过 MCP surface 运行——限定到项目的 key 会返回403。CLI 参考文档介绍了如何生成一个。 - Node 18+ 以及你已有的 i18next 文件,按
<lang>/<namespace>.json布局排列(非常规布局也能处理)。
1. 安装并初始化
全局安装 CLI,脚手架生成一个指向你项目的配置,并导出你的 key。
terminal 1# one global install — gives you the `sonenta` command (Node >= 18)2npm i -g @sonenta/cli 4# scaffold sonenta.config.json and point it at your project5sonenta init --project <project_uuid> 7# the CLI talks to the MCP surface — use an mcp:* scoped key8export SONENTA_TOKEN=snt_live_<prefix>.<secret> sonenta init 会写入一个你可以提交的 sonenta.config.json。在 CI 中,跳过 init,改为传入 --project 加上 SONENTA_TOKEN 环境变量。sonenta 和 SONENTA_* 是规范用法;旧的 sonenta 命令和 SONENTA_* 变量在过渡期间仍然有效。
2. 先预览,再导入
导入器会读取每个文件的路径,以推断其语言和 namespace,因此一个常规的 locales/ 树无需任何选项。先做一次 dry-run 查看计划,然后去掉 --dry-run 来应用它。
your repo 1# the importer infers (language, namespace) from each path:2# <lang>/<namespace>.json3locales/4├─ en/5│ ├─ common.json → language en · namespace common6│ └─ checkout.json → language en · namespace checkout7└─ fr/8 ├─ common.json → language fr · namespace common9 └─ checkout.json → language fr · namespace checkout terminal 1# preview first — no writes, prints exactly what WOULD change2sonenta import "./locales/**/*.json" --dry-run 4# the real run — idempotent, safe to repeat5sonenta import "./locales/**/*.json" 7✓ common · checkout (en, fr)8 keys 312 created · 0 reused9 translations 624 created · 0 updated · 0 unchanged10 errors 0 · glossary 0 violations 12# non-standard layout? override the inference per file:13sonenta import strings.fr.json --language fr --namespace common 树可以是嵌套或扁平的——两者导入结果一致。--status 设置传入状态(draft 或 translated,默认 translated);--version 瞄准一个非默认版本。以 CLDR 字典({ one, other })表达的复数会被自动存储为复数形式。
3. 发布到 CDN
导入会填充项目;发布则使其可被服务。切出一个 release,bundle 就会传播到 SDK 读取的全球 CDN 上。
terminal 1# cut a CDN release so the SDK and your build can fetch it2sonenta releases publish 4→ released "main" · propagating to cdn.sonenta.com release 是某个版本的不可变快照。每当你导入新内容时就重新发布一次——SDK 和你的静态构建都会获取最新的 release。
4. 验证 bundle
确认内容已上线。一个已发布的 bundle 就是按语言和 namespace 划分的、公开的纯 JSON 文件——直接抓取一个,或在 dashboard 中打开该项目。
terminal 1# the published bundle is public — no auth needed2curl -s https://cdn.sonenta.com/p/<project_uuid>/main/latest/fr/common.json 某种语言返回 404?要么它还不在项目的语言列表中,要么 release 尚未传播——稍等几秒后重试。
5. 将你的 SDK 指向 Sonenta
将你的 i18next 后端替换为 Sonenta provider。你的 t() 调用、key 和 namespace 都保持不变——翻译现在来自你刚刚发布的 CDN bundle。
main.tsx 1// src/main.tsx — point @sonenta/react-i18next at the same project2import { SonentaProvider } from "@sonenta/react-i18next"; 4<SonentaProvider5 projectUuid="<project_uuid>"6 token={import.meta.env.VITE_SONENTA_TOKEN}7 defaultLocale="fr"8 namespaces={["common", "checkout"]}9>10 <App />11</SonentaProvider> key 中包含点号(版本号、价格、圣经经文引用)?设置 keySeparator={false} 并将项目切换到 flat——参见扁平 key 还是嵌套 key指南。否则嵌套默认值即可正常工作。
随时可重新运行
sonenta import 是幂等的:重新导入相同内容不会改变任何东西(0 已创建、0 已更新、N 未变更)。把它接入 CI,让 Sonenta 与你的仓库保持同步——它只会创建缺失的内容,只会更新真正发生变化的内容。
导入器能处理的内容
- 嵌套或扁平。 两种 JSON 形态都导入到相同的 key——无需预处理。
- 复数。 CLDR 复数字典(
{ one, other, … },其中other为必填)会自动变成复数 key。 - 按文件的容错。 未知的语言或 namespace 会作为按单元的错误上报——导入的其余部分仍会落地。
- glossary 检查。 导入的翻译会经过你的 glossary;违规项会被列出,并在严格强制模式下被跳过。
- 缺失 key 清理。 针对已导入 key 的未解决缺失 key 事件,会在值到达后自动解决。