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)[]; // children(子内容)
    i?: number; // 元素的 GT ID
    d?: {
        b?: Record<string, Element | Variable | string>; // 分支
        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>; // 样式
    };
}
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[]; // children(子内容)
    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: "世界", 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 会按深度优先的顺序依次分配给 JSX 树中的元素和变量,起始编号为 1。
当存在诸如 <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": "这位客户", "i": 2 }, " 很开心 ", { "c": "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,则会优先使用它而非哈希值。
{ "example": "你好,世界" }这份指南怎么样?

