GT JSX 数据格式
General Translation JSX 精简数据格式参考
GT JSX 数据格式是 General Translation 库使用的一种精简数据格式,用于在你的 React 应用中表示翻译后的 UI。
介绍:JSX 树
React 将 JSX 树表示为具有以下结构的对象:
type Element = {
type: string;
props: {
children: JSXTree[] | JSXTree;
// ...其他 props
};
// ...其他属性
};
type JSXTree = Element | string;GT JSX 是该 JSX 树结构的压缩表示,General Translation 的库使用它在你的 React 应用中呈现已翻译的 UI。
参考
type Element = {
t?: string; // 标签名
c?: (Element | Variable | string)[]; // 子节点
i?: number; // 元素的 GT ID
d?: {
b?: Record<string, Element | Variable | string>; // 分支
t?: "p" | "b"; // 分支转换类型(复数或分支)
pl?: string; // 占位符
ti?: string; // 标题
alt?: string; // 替代文本
arl?: string; // aria-label
arb?: string; // aria-labelledby
ard?: string; // aria-describedby
s?: Record<string, string>; // 样式
};
}
type Variable = {
k: string; // 键
v?: "v" | "n" | "c" | "d"; // 类型
i?: number; // GT ID
}
type GTJSXTree = Element | Variable | string | (Element | Variable | string)[];GT JSX:字符串
GT JSX 最简单的形式是字符串,表示一段静态文本。
例如:
<T>你好,世界!</T>在 GT 的 JSX 中表示为:
"你好,世界!"字符串数组也可作为有效的 GT JSX:
["你好,", "世界!"]GT JSX:元素
GT 可以通过两种方式表示 JSX 的 Element 类型。
变量
第一种是变量,它是一个包含键和可选类型的简单对象。用于表示可在运行时变化的变量。
type Variable = {
k: string; // `k` 表示键,即变量的名称
v?: ( // 表示变量的类型,如果省略则默认为 `v`
"v" | // `v`,通用变量
"n" | // `n`,数值变量
"c" | // `c`,货币变量
"d" // `d`,日期时间变量
);
i?: number; // 变量的 GT ID
}示例 1:Var
<T>你好,<Var>{name}</Var>!</T>在 GT JSX 中表示为:
["你好,", { k: "_gt_var_1", i: 1 }, "!"]未包含 name 属性的变量会根据其 GT ID 被分配唯一的内部名称
示例 2:Num
<T>计数为 <Num>{count}</Num></T>在 GT 的 JSX 中表示为:
["计数为 ", { k: "count", v: "n", i: 1 }]示例 3:使用 name 属性
<T>此产品售价为 <Currency name="cost">{amount}</Currency></T>在 GT JSX 中表示为:
["此产品售价 ", { k: "cost", v: "c", i: 1 }]元素
非变量元素使用以下数据结构表示:
请注意,这些属性均为可选。
一个空对象表示在与其原始对应项相同的位置有一个已翻译的元素,且其后代中不包含任何可翻译内容。
在实际使用中,i 始终会被包含。
type Element = {
t?: string; // 标签名称
c?: GTJSXTree | GTJSXTree[]; // 子元素
i?: number; // 元素的 GT ID
d?: { // data-_gt 属性
b?: Record<string, GTJSXTree | GTJSXTree[]>; // 分支
t?: "p" | "b"; // 分支转换类型(复数或分支)
pl?: string; // 占位符
ti?: string; // 标题
alt?: string; // alt 属性
arl?: string; // aria-label 属性
arb?: string; // aria-labelledby 属性
ard?: string; // aria-describedby 属性
s?: Record<string, string>; // 样式
}
}示例 1:基础标签
<T>你好,<b>世界</b>!</T>在 GT 的 JSX 中表示为:
["你好,", { c: "world", i: 1 }, "!"]示例 2:嵌套,带变量
<T><b>你好</b>,我叫<i><Var>{name}</Var></i></T>可在 GT JSX 中表示为:
[
{ t: "b", c: "你好", i: 1 },
",我叫 ",
{
t: "i",
c: { k: "_gt_var_3", i: 3 },
i: 2
}
]示例 3:带复数
<T>
<Plural
n={count}
one={<>我有 <Num>{count}</Num> 项</>}
other={<>我有 <Num>{count}</Num> 项</>}
/>
</T>在 GT JSX 中可表示为:
{
i: 1,
d: {
t: "p",
b: {
one: {
c: ["我有", { k: "_gt_num_4", v: "n", i: 3 }, "个项目"],
i: 2
},
other: {
c: ["我有", { k: "_gt_num_4", v: "n", i: 3 }, "个项目"],
i: 2 // 注意:并行分支使用相同的 ID
}
}
}
}GTJSX 类型
type GTJSXTree = Element | Variable | string | (Element | Variable | string)[];GT ID
GT ID 会按照深度优先、顺序遍历的方式,从 1 开始依次分配给 JSX 树中的元素和变量。
当存在 <Branch> 或 <Plural> 等分支组件时,并行分支会被分配相同的 GT ID。这样即使某种语言的分支数多于另一种语言(例如某些语言有更多复数形式),也能创建具有正确 props 和逻辑的元素。
GT JSX JSON 文件
每棵 JSX 树都表示一个 <T> 组件的 children。
这些组件被集中存放在翻译用的 JSON 文件中。
这些文件中存放的 JSON 对象类型对应于:
type GTJSXFile = {
[key: string]: GTJSXTree;
}其中,key 可以是用户自定义的,也可以是原始语言 GTJSXTree 的哈希值;GTJSXTree 指的是上文所述的 GT JSX 树的类型。
完整示例
所编写的 JSX:
<T>
<b>Alice 的</b>满意<i>客户</i>
</T>将表示为如下 JSX 树:
[
{
type: "b",
"props": {
"children": "Alice的"
}
},
" 满意的 ",
{
type: "i",
"props": {
"children": "客户"
}
}
]这将被最小化为 GT JSX:
[{ t: "b", c: "Alice 的", i: 1 }, " 开心的 ", { t: "i", c: "顾客", i: 2 }]翻译成西班牙语后,GT JSX 将为:
[{ c: "客户", i: 2 }, " 开心 ", { c: "Alice 的", i: 1 }]它会被存储在一个如下所示的文件中:
{ "abc123": [{ "c": "El cliente", "i": 2 }, " feliz ", { "c": "de Alice", "i": 1 }] }abc123 是原始英文 GT JSX 树的哈希,而非西班牙语译文的哈希。当西班牙语译文与原始 JSX 树对齐后,将得到如下结果:
[
{
type: "i",
"props": {
"children": "客户"
}
},
"快乐的",
{
type: "b",
"props": {
"children": "Alice的"
}
}
]随后即可按预期的界面呈现:
<><i>客户</i> 快乐 <b>属于 Alice</b></>哈希
哈希算法、哈希长度待定
在运行时避免使用哈希
为避免在运行时计算哈希,这些库提供了可选的 fallback 机制,允许用户指定一个 ID。
<T id="example">
你好,世界
</T>如果翻译 JSON 文件中包含该 ID,将优先使用该 ID,而不是哈希值。
{ "example": "你好,世界" }本指南如何?