Формат данных GT JSX
Справочник по минифицированному формату данных JSX от General Translation
Минифицированный формат данных GT JSX используется библиотеками General Translation для представления переведённого интерфейса в вашем приложении React.
Введение: деревья JSX
React представляет деревья JSX в виде объектов со следующей структурой:
type Element = {
type: string;
props: {
children: JSXTree[] | JSXTree;
// ...other props
};
// ...other attributes
};
type JSXTree = Element | string;GT JSX — это компактное представление дерева JSX, которое библиотеки General Translation используют для отображения переведённого UI в вашем приложении React.
Справочные материалы
type Element = {
t?: string; // tag name
c?: (Element | Variable | string)[]; // children
i?: number; // GT ID of the element
d?: {
b?: Record<string, Element | Variable | string>; // branches
t?: "p" | "b"; // branch transformation type (plural or branch)
pl?: string; // placeholder
ti?: string; // title
alt?: string; // alt
arl?: string; // aria-label
arb?: string; // aria-labelledby
ard?: string; // aria-describedby
s?: Record<string, string>; // style
};
}
type Variable = {
k: string; // key
v?: "v" | "n" | "c" | "d"; // type
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: "мир", 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 // note the same ID is used for parallel branches
}
}
}
}Тип GTJSX
type GTJSXTree = Element | Variable | string | (Element | Variable | string)[];GT IDs
GT IDs назначаются элементам и переменным в дереве JSX в порядке обхода в глубину и последовательно, начиная с 1.
Когда используются разветвляющие компоненты, такие как <Branch> или <Plural>, одинаковые GT IDs назначаются параллельным ветвям. Это нужно для того, чтобы даже если в одном языке ветвей больше, чем в другом (например, в языках с большим количеством форм множественного числа), можно было создать элементы с корректными пропсами и логикой.
JSON‑файлы GT JSX
Каждое дерево JSX представляет собой дочерние элементы компонента <T>.
Компоненты хранятся вместе в JSON‑файлах переводов.
Тип объекта JSON, сохраняемого в этих файлах, соответствует:
type GTJSXFile = {
[key: string]: GTJSXTree;
}Где key — это либо заданное пользователем значение, либо хеш исходного языкового GTJSXTree,
а GTJSXTree — это тип дерева GT JSX, описанного выше.
Полный пример
Исходный JSX:
<T>
довольный <i>клиент</i> <b>Элис</b>
</T>Будет представлено следующим деревом JSX:
[
{
type: "b",
"props": {
"children": "Элис"
}
},
" довольна ",
{
type: "i",
"props": {
"children": "клиентка"
}
}
]Это будет минифицировано в GT JSX следующим образом:
[{ c: "клиент", i: 2 }, " счастлив ", { c: "Элис", i: 1 }]При переводе на испанский GT JSX будет таким:
[{ c: "Клиент", i: 2 }, " доволен ", { c: "Алисы", i: 1 }]Он будет храниться в файле следующего вида:
{ "abc123": [{ "c": "Клиент", "i": 2 }, " доволен ", { "c": "Алисы", "i": 1 }] }abc123 — это хеш исходного английского дерева GT JSX, а не испанского перевода.После согласования испанского перевода с исходным деревом JSX будет получен следующий результат:
[
{
type: "i",
"props": {
"children": "Клиент"
}
},
" счастлив ",
{
type: "b",
"props": {
"children": "Алисы"
}
}
]Который затем можно отобразить как задуманный интерфейс:
<><i>Счастливый клиент</i> <b>Алисы</b></>Хеши
Алгоритм хеширования и длина хеша будут определены позже
Избежание вычисления хешей во время выполнения
Чтобы не вычислять хеши на этапе выполнения, в библиотеках предусмотрен необязательный резервный механизм, позволяющий пользователю указать идентификатор.
<T id="example">
Привет, мир!
</T>Если ID присутствует в JSON‑файле перевода, он будет использован вместо хэша.
{ "example": "Привет, мир!" }Насколько полезно это руководство?