Skip to main content

strato-extract

CLI tool that scans your TypeScript/TSX source files, finds translatable strings on Strato components, and writes them to .po or .json translation files. New strings are appended; existing translations are preserved.

Synopsis

strato-extract [options] <src-pattern> [<output-glob> | <locale-dir> [locale...]]

Arguments

ArgumentDescription
src-patternGlob matching source files to scan. Default: src/**/*.{ts,tsx}
output-globA glob containing * — matched files are used as output targets. The locale is inferred from the directory name (e.g. locales/fr/messages.pofr).
locale-dirDirectory to write locale files into. Pass one or more locale codes as additional args.
locale...Locale codes to generate when using the locale-dir form. Default: en

Options

OptionShortDescription
--format <fmt>-fOutput format: po or json. Inferred from the file extension when not specified.
--config <path>Path to a custom strato-i18n.config.json. Defaults to ./strato-i18n.config.json.
--out-file <path>-oWrite all extracted messages to a single file. When used, only the first matched output file is written.
--locale <code>-lLocale code to use when --out-file is set.
--ignore <glob>-iExclude files matching this glob. May be repeated.

Examples

# Scan src/, write to locales/en/messages.po and locales/fr/messages.po
strato-extract --format=po "src/**/*.{ts,tsx}" "locales/*/messages.po"

# Scan src/, write JSON files for en and fr
strato-extract "src/**/*.{ts,tsx}" locales en fr

# Ignore generated files
strato-extract --format=po --ignore="src/**/*.generated.tsx" \
"src/**/*.{ts,tsx}" "locales/*/messages.po"

Output format

Each extracted string becomes a PO entry. The stable hash ID is stored in the #. id: comment; source file locations are stored in #: reference comments.

#: src/resources/products.tsx:29
#. id: 1kdfstp
msgid "Products"
msgstr ""

#: src/resources/products.tsx:32
#. id: 10kmuai
msgid "Edit Product - {name}"
msgstr ""

Translators fill in msgstr. The hash in #. id: must not be changed — it is the stable key used by the runtime.

Not classical Gettext

The message format inside msgid/msgstr is ICU, not Gettext. Pluralization is written as a single ICU string (e.g. {count, plural, one {# item} other {# items}}), not using Gettext's msgid_plural / msgstr[n] fields. Standard tools like Poedit can open these files but their plural helpers will not apply.

JSON

{
"1kdfstp": {
"defaultMessage": "Products",
"translation": "",
"locations": ["src/resources/products.tsx:29"]
}
}

<Message> and <RecordMessage>

These components are handled differently from other Strato components: the extractor reads their JSX children as the translatable string rather than a prop value.

Each supports three special props that control how the PO entry is generated:

PropPO effectRuntime key
(none)#. id: <hash(message)>hash(message)
id="action.save"#. id: action.save"action.save" (literal)
context="nav"msgctxt "nav" + #. id: <hash(nav\x04message)>hash("nav\x04message")

id takes priority over context when both are provided.

comment prop is written as a # translator note in the PO file:

<Message comment="Verb, not noun">Archive</Message>
#  Verb, not noun
#: src/components/Button.tsx:12
#. id: 1kdfstp
msgid "Archive"
msgstr ""
Static children only

Only string literal children are extracted — plain text or a {'string'} JSX expression. Dynamic values, variables, and template literals with embedded expressions are not extracted.

Default components

The extractor recognizes translatable props on these built-in Strato components:

ArrayField, AttributeEditor, AutocompleteInput, BooleanField, BulkDeleteButton, Button, Create, CreateButton, DateField, Edit, EditButton, FormField, List, NumberField, NumberInput, ReferenceField, ReferenceInput, ReferenceManyField, Resource, ResourceSchema, SaveButton, SelectInput, StatusIndicatorField.Label, Table, Table.Col, TextAreaInput, TextField, TextInput

Default translatable props

CategoryProps
Labelslabel, listLabel, createLabel, editLabel, detailLabel
Titlestitle, listTitle, createTitle, editTitle, detailTitle
Descriptionsdescription, listDescription, createDescription, editDescription, detailDescription
Formplaceholder, emptyText, helperText, constraintText, saveButtonLabel
FeedbacksuccessMessage, errorMessage

Configuration file

Create strato-i18n.config.json in your project root to extend the defaults with your own components and props. The built-in lists are merged with your additions — you do not need to repeat them.

{
"components": ["MyCustomButton", "HeroSection"],
"translatableProps": ["ctaText", "subheading"]
}

Pass a custom path with --config if the file is not at the project root.

translate() calls

In addition to JSX props, strato-extract also extracts calls to translate() and translateLabel(). This lets you translate strings that appear outside JSX:

// Extracted as a translatable string
const label = translate('Status');

// Extracted with an explicit stable key instead of a hash
const label = translate('my.explicit.key', { _: 'Status' });

When the second argument is { _: "Default Text" }, "Default Text" becomes the msgid and the first argument ("my.explicit.key") becomes the context (msgctxt), creating a stable key that won't change even if the default text is reworded.