Summary#
One file per language per project — an app's or a kit's — at locales/<language>.osy. It is SOURCE: it rides every
compile, test and deploy with the rest of the project, a kit's archive carries its own, and a mistake in it is a compile
error at its line. osy translate writes it (osy translate — the request for any model, and its answer read back); the words are yours to edit.
Signature#
translations sv {
/// Checkout · /checkout · a button's label · at most ~16 characters
button "Check out" => "Till kassan";
/// BagPage · /bag · placeholders: {count} = count (int) — {count} is a count
text "{count} items in your bag" => { one: "{count} vara i din kasse", other: "{count} varor i din kasse" };
text "Open" key "shop-status-open" => "Öppet";
title "Your shopping bag" => null was "Your bag" => "Din kasse";
}Description#
An entry is keyed exactly as a message is (Which words are translated — the compiler finds every text a reader sees): its ROLE, its source TEXT and, rarely, a key.
Its value is a text, one text per plural category ({ one: …, other: … }, A count's plural forms — one text per CLDR category), or null — not
translated yet, so the reader sees the source text. The /// lines above it are its context — where it is, what it
is, how long it may be, what its placeholders hold, what sits beside it — written by osy translate for whoever
translates the file cold.
Kept in step, never regenerated. A text the file translates keeps its translation. A new text arrives as => null.
A text whose source changed (so its identity did) is matched to the entry it replaced — the same role in the same
component — and written STALE: => null was "old source" => "old translation", so the old words are right there as a
hint. A text no longer in the source is dropped.
What the compile refuses, at the translation's line, on the server and in osy validate alike:
| refusal | why |
|---|---|
| a placeholder the source does not have, or a source placeholder left out | the hole would show as {name} or the value would vanish |
| plural forms for a text with no count | nothing chooses between them |
| a plural form the language lacks, or one it needs missing | Swedish has one and other; Polish one, few, many, other |
| the same text translated twice in one language | which one wins would be an accident |
markup — <b>, <img …>, <!-- | a translation is TEXT, and is always shown as text |
Precedence. A kit ships locales/*.osy of its own words; an app's file carries its own words and, for a language
a kit does not speak, the kit's words too (osy translate puts them there, marked with the kit's name). By identity,
the app's entry wins — so an app overrides a kit's word by translating the same text and role itself.
The languages an app speaks are its source language (English, unless app.SourceLanguage says otherwise —
app.SourceLanguage — the language the app is written in) and every language it has its OWN file for; a kit's extra languages are not offered on their
own, because the app's words would still be in its source language.
Examples#
[Route("/")]
[AllowAnonymous]
component Home() {
int count = 2;
action Pay() { Navigation.Go("/"); }
render {
Stack {
Text("Your bag is empty.");
Text($"{count} items in your bag");
Button("Check out", onPress: Pay);
}
}
}
translations sv {
text "Your bag is empty." => "Din kasse är tom.";
text "{count} items in your bag" => { one: "{count} vara i din kasse", other: "{count} varor i din kasse" };
button "Check out" => "Till kassan";
}See also#
- osy translate — the request for any model, and its answer read back — how the file is written and filled
- A count's plural forms — one text per CLDR category — the forms a count takes
- Which words are translated — the compiler finds every text a reader sees — which texts have entries