documentation/resource-text.md
ResourceText is the type Seelen UI uses everywhere a resource needs to show text to the user: display names,
descriptions, widget setting labels, tooltips, context menu entries, shortcut labels, theme config labels, etc. This
guide explains what it is, everywhere it shows up, and how to translate it with the slu CLI.
slu CLIResourceText is a field that accepts either:
A plain string, which is treated as English (en) only:
label: My Setting
A map of language code to translated string:
label:
en: My Setting
es: Mi Ajuste
de: Meine Einstellung
At render time, Seelen UI looks up the text for the user's current language and falls back to en if that language is
missing. Because of this fallback, en must always be present whenever you use the map form — a resource missing
the en entry fails validation on publish.
There is no need to decide up front which form to use: start with a plain string while developing, then convert it to a
map once you (or the slu CLI) add translations. Both forms are accepted anywhere a ResourceText field appears.
ResourceText is not limited to metadata.displayName / metadata.description. It is the standard type for any
user-visible text across all resource kinds:
| Resource kind | Fields using ResourceText |
|---|---|
| All resources | metadata.displayName, metadata.description |
| Widget | Setting group label / description, setting label / description / tip, select-option label |
| Theme | Config group header, config variable label / description / tip |
| Plugin | Context menu item label (for Submenu and other entries) |
| Shortcuts | Shortcut label / description |
In short: wherever you see a label, description, or tip field in a resource schema, assume it is a ResourceText
and can be localized the same way displayName is.
For a short label, write it inline:
label:
en: Enable Feature
es: Activar Función
For anything longer (a resource's displayName/description, or many settings with many languages), split each text
into its own file under i18n/ and pull it in with !extend, exactly like described in the
Extended YAML section of the resource guidelines:
# metadata.yml
metadata:
displayName: !extend i18n/display_name.yml
description: !extend i18n/description.yml
# i18n/display_name.yml
en: My Dark Theme
es: Mi Tema Oscuro
This keeps metadata.yml readable and gives each translated field its own file that the slu CLI can translate
independently (see next section).
slu CLISeelen UI ships a slu resource translate command that fills in every supported language for a ResourceText YAML
file, using Google Translate under the hood.
slu resource translate <path/to/file.yml> [source_lang]
<path/to/file.yml> — a YAML file containing a ResourceText value (either a plain string or a language map).[source_lang] — the language code your source text is written in. Defaults to en.source_lang. If it's missing, the command fails — write
your source text first.Example:
slu resource translate i18n/display_name.yml
[01/68] English (Afrikaans) => "Speel Rekenaar"
[02/68] Amharic => "ጨዋታ ኮምፒተር"
...
[14/68] English => Skipped
...
If your source text is not in English, pass the language code explicitly:
slu resource translate i18n/description.yml es
metadata.yml.
If you split translations across many files under i18n/ (as recommended in
section 3), run it once for each.en is mandatory once you use the map form. A resource whose displayName or description map has no en key
fails Resource::verify and cannot be published.en. label: My Setting and label: { en: My Setting } are equivalent — the CLI
and the UI treat them identically.zh and pt are not valid target codes — Seelen UI only ships zh-CN/zh-TW and pt-BR/pt-PT. The translate
command already maps these internally when calling Google Translate, so you don't need to worry about it, but don't
hand-write a bare zh: or pt: key yourself — it will never match the running app's language and will silently never
be shown.en has an entry, the resource text renders
as an empty span in Settings (or !? if read directly on the Rust side) — always keep en filled in.