gt-react@10.18.0
Overview
This release adds support for derivable context values in gt-react. When translating content, there isn't always a one-to-one mapping between source text and its translations — a single English phrase might need multiple translations in another language. Context derivation solves this by letting you generate multiple translation entries from a single source string.
Background: How GT translations work
In GT's translation system, you wrap translatable strings with gt():
import { useGT } from 'gt-react';
function Greeting() {
const gt = useGT();
return <p>{gt("Hello, world!")}</p>;
}Each call to gt() creates a source entry — a piece of text that gets translated. Normally, one source entry produces one translation per language.
What is derive?
The derive() function tells the GT CLI to register multiple translation entries from a single gt() call based on different runtime values. Instead of writing separate gt() calls for each variant, you use derive() to express all the variants in one place, and the CLI generates the appropriate source entries at build time.
For example, English doesn't distinguish gender in "The boy/girl is playing," but Spanish does ("El niño está jugando" vs "La niña está jugando"). With derive(), you can handle this in a single gt() call:
const subject = isBoy ? "boy" : "girl";
gt(`The ${derive(subject)} is playing.`);The CLI sees the derive() call and registers two source entries — one for "The boy is playing." and one for "The girl is playing." — each getting its own translation with correct Spanish agreement.
The problem: one-to-many mappings
Consider three cases for how source entries map to translation entries:
Case 1: One-to-one mapping
Each source entry maps to exactly one translation entry. This is the straightforward case.
| Source entries | Translation entries |
|---|---|
| The boy is beautiful. | El niño es hermoso. |
| The girl is beautiful. | La niña es hermosa. |
Case 2: Many-to-one mapping
Multiple source entries collapse into a single translation. For example, English has plural forms but Mandarin does not:
| Source entries | Translation entries |
|---|---|
I have {n} cat. | 我有{n}只猫。 |
I have {n} cats. |
Case 3: One-to-many mapping
A single source entry requires multiple translations. For example, Spanish has gendered adjective agreement where English does not:
| Source entries | Translation entries |
|---|---|
| I am tired | Estoy cansado |
| Estoy cansada |
This is the case that was not supported before this release. GT previously assumed a one-to-one mapping between source entries and translations.
Solution: derive with $context
GT's $context option lets you disambiguate between translation entries for the same source text. Combined with derive(), you can express this at the call site:
import { useGT, derive } from 'gt-react';
function StatusMessage({ isMasculine }) {
const gt = useGT();
return (
<p>
{gt("I am tired", {
$context: derive(
isMasculine ? "inflect as masculine" : "inflect as feminine"
)
})}
</p>
);
}At build time, the CLI sees the derive() call and registers two separate source entries, each producing its own translation:
"I am tired" ($context: "inflect as masculine") → "Estoy cansado"
"I am tired" ($context: "inflect as feminine") → "Estoy cansada"
At runtime, the correct translation is selected based on the value of isMasculine.
Without derive(), you would need to write this as two separate calls:
// Without derive — more verbose, duplicated source text
const message = isMasculine
? gt("I am tired", { $context: "inflect as masculine" })
: gt("I am tired", { $context: "inflect as feminine" });derive() achieves the same result with less duplication and makes the intent clearer.
Why not just use a conditional?
Like content strings, $context values must be static — the CLI needs to resolve them at build time. You can't pass a runtime expression directly as $context because the CLI wouldn't know what values it could take. derive() solves this by tracing through the call stack to resolve all possible static strings that could be passed, letting the CLI register a source entry for each one.
In summary
Context derivation addresses a fundamental gap in the translation model: the inability to represent one-to-many mappings between source and translation entries. By combining derive() with $context, a single gt() call can produce multiple translations that are disambiguated at runtime.