GT JSX Data Format

Reference for the minified General Translation JSX data format

The GT JSX data format is an minified data format used by the General Translation libraries to represent translated UI in your React application.

Introduction: JSX Trees

React represents JSX trees as objects with the following structure:

type Element = {
    type: string;
    props: {
        children: JSXTree[] | JSXTree;
        // ...other props
    };
    // ...other attributes
};
type JSXTree = Element | string;

GT JSX is a compressed version of this JSX tree structure that is used by the General Translation libraries to represent translated UI in your React application.

Reference

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: Strings

The simplest form of GT JSX is a string, which represents a static string of text.

For example:

<T>Hello, world!</T>

Would be represented in GT JSX as:

"Hello, world!"

Arrays of strings are also valid GT JSX:

["Hello, ", "world!"]

GT JSX: Elements

GT represents JSX Element types in two possible ways.

Variables

The first is a variable, a simple object that contains a key and an optional type. This is used for representing variables that can change at runtime.

type Variable = {
    k: string; // `k` represents key, the name of the variable
    v?: ( // represents the type of the variable, if left out is assumed as `v`
        "v" | // `v`, a generic variable
        "n" | // `n`, a number variable
        "c" | // `c`, a currency variable
        "d" // `d`, a datetime variable
    );
    i?: number; // GT ID of the variable
}

Example 1: Var

<T>Hello, <Var>{name}</Var>!</T>

Would be represented in GT JSX as:

["Hello, ", { k: "_gt_var_1", i: 1 }, "!"]

Variables without a name prop are assigned unique internal names based on their GT ID

Example 2: Num

<T>The count is <Num>{count}</Num></T>

Would be represented in GT JSX as:

["The count is ", { k: "count", v: "n", i: 1 }]

Example 3: With Name Prop

<T>This product costs <Currency name="cost">{amount}</Currency></T>

Would be represented in GT JSX as:

["This product costs ", { k: "cost", v: "c", i: 1 }]

Elements

Elements which are not variable are represented using the following data structure:

Note that all of these attributes are optional. An empty object would represent a translated element in the same position as its original counterpart, with no translatable content among its descendants. In practice, i is always included.

type Element = {
    t?: string; // tag name
    c?: GTJSXTree | GTJSXTree[]; // children
    i?: number; // GT ID of the element
    d?: { // data-_gt prop
        b?: Record<string, GTJSXTree | GTJSXTree[]>; // 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
    }
}

Example 1: Simple Tags

<T>Hello, <b>world</b>!</T>

Would be represented in GT JSX as:

["Hello, ", { c: "world", i: 1 }, "!"]

Example 2: Nested, with variables

<T><b>Hello</b>, my name is <i><Var>{name}</Var></i></T>

Would be represented in GT JSX as:

[
    { t: "b", c: "Hello", i: 1 },
    ", my name is ",
    { 
        t: "i",
        c: { k: "_gt_var_3", i: 3 }, 
        i: 2 
    }
]

Example 3: With Plural

<T>
    <Plural 
        n={count} 
        one={<>I have <Num>{count}</Num> item</>} 
        other={<>I have <Num>{count}</Num> items</>}
    />
</T>

Would be represented in GT JSX as:

{ 
    i: 1,
    d: {
        t: "p",
        b: {
            one: {
                c: ["I have", { k: "_gt_num_4", v: "n", i: 3 }, "item"],
                i: 2 
            },
            other: {
                c: ["I have", { k: "_gt_num_4", v: "n", i: 3 }, "items"],
                i: 2 // note the same ID is used for parallel branches
            }
        }
    }
}

GTJSX Type

type GTJSXTree = Element | Variable | string | (Element | Variable | string)[];

GT IDs

GT IDs are assigned to elements and variables in a JSX tree depth-first and sequentially, starting from 1.

When there are branch components like <Branch> or <Plural>, the same GT IDs are assigned to parallel branches. This is so that if there are more branches in one language than in another (e.g. languages where there more plural forms), elements with the right props and logic can still be created.

GT JSX JSON Files

Each JSX Tree represents the children of a <T> component. Components are stored together in translation JSON files. The type of the JSON object stored in these files corresponds to:

type GTJSXFile = {
    [key: string]: GTJSXTree;
}

Where key is either user-defined or the hash of the original language GTJSXTree, and GTJSXTree is the type of the GT JSX tree described above.

Complete example

The written JSX:

<T>
    <b>Alice's</b> happy <i>customer</i>
</T>

Would be represented as the following JSX tree:

[
    {
        type: "b",
        "props": {
            "children": "Alice's"
        }
    },
    " happy ",
    {
        type: "i",
        "props": {
            "children": "customer"
        }
    }
]

This would be minified into GT JSX as:

[{ t: "b", c: "Alice's", i: 1 }, " happy ", { t: "i", c: "customer", i: 2 }]

When translated into Spanish, the GT JSX would be:

[{ c: "El cliente", i: 2 }, " feliz ", { c: "de Alice", i: 1 }]

It would be stored in a file which looks like:

{ "abc123": [{ "c": "El cliente", "i": 2 }, " feliz ", { "c": "de Alice", "i": 1 }] }
abc123 is the hash of the original English GT JSX tree, not the Spanish translation.

When the Spanish translation is reconciled with the original JSX tree, the following would be produced:

[
    {
        type: "i",
        "props": {
            "children": "El cliente"
        }
    },
    " feliz ",
    {
        type: "b",
        "props": {
            "children": "de Alice"
        }
    }
]

Which can then be displayed as the intended UI:

<><i>El cliente</i> feliz <b>de Alice</b></>

Hashes

Hashing algorithm, hash length TBD

Avoiding hashes at runtime

To avoid computing hashes at runtime, the libraries have an optional fallback mechanism where the user can specify an ID.

<T id="example">
    Hello, world
</T>

If the ID is present in the translation JSON file, it will be used instead of the hash.

{ "example": "Hello, world" }

How is this guide?