key 永远不会被切分——每个 key 都按字面存储和查找。当你的 key 含有点号或本身就是自然文本时选择它:版本号、价格、文件名、圣经或法律引用。App Version 6.3.8 就保持其原样。
指南 · key 嵌套
扁平 key 还是嵌套 key
默认情况下,Sonenta 会按 . 将你的 key 切分到 CDN bundle 中的一个嵌套 JSON 树里——这是经典的 i18next 形态。对于像 checkout.review.confirm 这样有组织的 key 很合适,但它会悄无声息地破坏那些文本中含有点号的 key。本指南介绍项目设置以及对应的 SDK 选项,以确保你的查找始终能解析成功。
带点号 key 的陷阱
key 不过是一个字符串。当该字符串包含一个字面点号时——比如像 App Version 6.3.8 这样的版本号、一个价格、一个文件名、像 Jean 3.16 这样的圣经经文引用——按 . 切分会把一个 key 变成一个意外的嵌套对象。翻译仍然被存储着,但 t("App Version 6.3.8") 再也找不到它了。
bundle.json 1// your source key — a literal label with dots in it2{ "App Version 6.3.8": "App Version 6.3.8" } 4// nested bundle (default) — split on "." → broken tree5{ "App Version 6": { "3": { "8": "App Version 6.3.8" } } } 7// flat bundle — the key stays literal, lookups just work8{ "App Version 6.3.8": "App Version 6.3.8" } 项目设置
两个项目级设置控制着 CDN bundle 的形态。默认值复现当前的 i18next 行为,因此在你显式选择启用之前,已有项目不受影响。
| 设置 | 取值 | 默认值 |
|---|---|---|
| bundle_key_style | nested | flat | nested |
| bundle_key_separator | string | "." |
在项目上设置它们——在你 dashboard 的项目设置中,或通过 projects API。所选的风格会被固化进每一个 release,且每个已发布的版本都会回报它,因此任何客户端都能自我配置。
versions/main 1# the version object reports the active key style2GET /v1/projects/<project_uuid>/versions/main 4{ "slug": "main", "key_style": "flat", "key_separator": "." } 选择扁平还是嵌套
key 会按分隔符切分到一个 JSON 树中——经典的 i18next 布局。为像 checkout.review.confirm 这样刻意做了 namespace 划分的 key 选择它。这是默认值。
在 SDK 中保持一致
@sonenta/react-i18next(>= 0.11.0)接受一个 keySeparator 选项:false 表示字面 / 扁平查找,字符串表示嵌套,默认 "."。还有 nsSeparator(默认 ":")。SDK 是字面优先的——它会在做任何切分之前先尝试精确的 bundle[key] 匹配,因此带点号的 key 即使在嵌套模式下也能解析成功。在 start() 时,它还会从已发布的版本中自动检测 key_style / key_separator(尽力而为)。
main.tsx 1// src/main.tsx — match the bundle in @sonenta/react-i18next >= 0.11.02import { SonentaProvider } from "@sonenta/react-i18next"; 4<SonentaProvider5 projectUuid="<project_uuid>"6 token={import.meta.env.VITE_SONENTA_TOKEN}7 keySeparator={false} // literal lookup — for dotted / natural-text keys8 nsSeparator=":" // default; set false to disable ns parsing too9>10 <App />11</SonentaProvider> 13// then t() treats the whole string as one key — no splitting14t("App Version 6.3.8"); // ✓ exact match 自动检测会读取版本元数据,并需要一个带 project:read 的 key。如果该读取被拒绝(403),SDK 会优雅地回退到它的默认值——所以拿不准时,请显式设置 keySeparator 以匹配你的 bundle,而不是依赖检测。
建议
- key 含有点号?在项目上设置
bundle_key_style: flat,并在 SDK 中设置keySeparator={false}。两端都按字面处理——没有意外。 - 干净地做了 namespace 划分的 key(
checkout.review.confirm)?保持嵌套默认值;无需改动。 - 正在迁移一个现有的 app?默认值会保留你当前的行为。仅在遇到带点号的 key 时才切换到 flat,然后重新发布并同时更新 SDK 选项。