Translations
The web UI reads its text from a message catalog, so a new language is a JSON file rather than a fork of the UI. English (web/marmot/messages/en.json) is the source and the fallback, so a partial translation is still usable.
Adding a language
- Copy
messages/en.jsontomessages/<tag>.json(es.json,pt-BR.json). - Translate the values, leaving the keys untouched.
- Add the tag to
localesinweb/marmot/project.inlang/settings.json. - Run
pnpm run i18n:compile && pnpm run devinweb/marmotto see it.
Keep every placeholder spelled exactly as in English, such as {name}.
Counted messages use one variant per plural category. English needs one and other, other languages may add zero, two, few or many:
{
"assets_match_count": [
{
"declarations": ["input count", "local countPlural = count: plural"],
"selectors": ["countPlural"],
"match": {
"countPlural=one": "{count} matched asset",
"countPlural=other": "{count} matched assets"
}
}
]
}
Adding UI strings
Add a message rather than a literal:
<script lang="ts">
import { m } from '$lib/paraglide/messages';
</script>
<h2>{m.assets_heading()}</h2>
Keys are lowercase and namespaced by area (nav_, login_, assets_, teams_). Keep a whole sentence in one message and pass values as placeholders, never join translated fragments, because word order differs between languages. The marmot/no-untranslated-strings lint rule reports hard-coded text in templates.