Documentation
¶
Overview ¶
Package srvtext is the catalogue of every sentence the SERVER writes to a person: e-mails, the no-JavaScript pages behind a share or drop link, the Apps install review's permission descriptions, the NOT.txt beside a drop.
⚠⚠ Why it exists. Language packs (wasmplugin langpack.go) translate everything the BROWSER draws, from two catalogues it owns. What the server composed knew two languages, as `if lang == "tr"` pairs scattered over the handlers — and a third language fell through to whichever branch was the `else`. Measured 2026-09-22 with a Spanish pack on the account and the explorer sending `locale: "es"`: the share-link e-mail arrived in TURKISH (mail_templates.go's default branch), the drop notice to the owner too, and the drop page a Spanish browser opened said "Send files".
One catalogue now answers every one of them:
- built-ins: locales/en.json and locales/tr.json, flat dotted keys under `server.` — the exact shape of one language of a pack's `ui_locales`;
- packs: a pack's `ui_locales[<lang>]` carries `server.*` keys beside the interface's own (ONE namespace, one file per language for a translator; docs/PLUGIN-KIT.md "Writing a language pack" → "Text the server writes");
- every key a pack lacks falls back to English, never to a raw key and never to the other built-in language.
THE GRAMMAR (the translator's contract; scripts/i18n-validate.mjs checks it and Text re-checks it at run time):
- `{name}` — a placeholder: ASCII letters, digits and `_` between braces. Replaced verbatim (HTML-escaped by the page when the text lands in HTML). A translation must carry EXACTLY the placeholders its English carries: not one fewer (the link, the PIN or the address would silently vanish from an e-mail) and not one more (it would print as written).
- plurals by CLDR category: `<key>_zero|_one|_two|_few|_many`, the plain `<key>` being `other` and the fallback — plural.go has the rules.
- nothing else is syntax: `@`, `|`, `%`, `{{`, and a brace that does not close around a name are ordinary characters.
⚠ It is a package-level catalogue on purpose: the language of a mail is decided in a dozen handlers, a queue worker and a plugin host call, and threading one more dependency through each constructor would be a dozen chances to forget it. SetPacks and SetDefault are called once at start-up (server.go); tests swap them and restore.
Index ¶
- Constants
- func Builtin(lang string) map[string]string
- func BuiltinLanguages() []string
- func Bytes(lang string, n int64) string
- func Categories(lang string) []string
- func Category(lang string, n int) string
- func Fill(tpl string, vars Vars) string
- func FromAcceptLanguage(h string) string
- func Has(key string) bool
- func IsRTL(lang string) bool
- func Keys() []string
- func Number(lang string, n int64) string
- func Offered(tag string) (string, bool)
- func Pick(candidates ...string) string
- func Placeholders(s string) []string
- func Plural(lang, key string, count int, vars Vars) string
- func Reader(ctx context.Context) string
- func Resolve(tag string) string
- func SetDefault(tag string)
- func SetPacks(p Packs)
- func Table(lang, prefix string) map[string]string
- func Template(lang, key string) string
- func TemplateN(lang, key string, count int) string
- func Text(lang, key string, vars Vars) string
- func WithReader(ctx context.Context, lang string) context.Context
- type Packs
- type StaticPacks
- type Vars
Constants ¶
const Prefix = "server."
Prefix starts every key of this catalogue — the namespace a pack's `ui_locales` shares with the interface's own keys.
Variables ¶
This section is empty.
Functions ¶
func Builtin ¶
Builtin returns a copy of one shipped language's table (en or tr), for tests and tooling; nil for any other tag.
func BuiltinLanguages ¶
func BuiltinLanguages() []string
BuiltinLanguages is the languages filex ships, sorted: ["en", "tr"].
func Bytes ¶
Bytes writes a byte count the way the interface does — the explorer's formatByteSize (packages/core/src/composables/useLocale.ts): base 1000, whole bytes, two decimals below 10 and one above (trailing zeros dropped), the language's own decimal mark, and the catalogue's unit words.
⚠ There were two server copies, both base 1024 with a Go "%.1f" (a dot in every language, English letters): the share e-mail and the no-JavaScript folder page. A file the listing called "1.5 MB" arrived in the mail as "1.4 MB", and the share dialog copied the server's rounding on purpose so the two would at least agree with each other (QA, 2026-09-21). One definition of a size now, on both sides of the wire.
func Categories ¶
Categories lists the plural categories lang has, in CLDR order (English: one, other; Arabic: zero, one, two, few, many, other).
func Category ¶
Category is the CLDR cardinal category of the integer n in lang ("one", "few", "other"…). An unknown tag reads by its base language, then as English.
func Fill ¶
Fill replaces every `{name}` whose name is in vars. ⚠ A placeholder vars does not name is LEFT AS WRITTEN — a visible defect a test catches — rather than deleted into a sentence with a hole in it.
func FromAcceptLanguage ¶
FromAcceptLanguage is the first tag of an Accept-Language header that an offered language serves, or "". Browsers list their preference first, so q-values are ignored (the public pages always read it this way).
func Has ¶ added in v0.54.0
Has reports whether key is a key of the catalogue - the English table carries it. A caller that composes a sentence out of optional parts (a notification's variant wording, internal/notify say.go) asks this before Template, which answers a missing key with the key itself.
func IsRTL ¶
IsRTL reports a right-to-left language (wire.IsRTL: the one list the install review, the validator and the mail's Content-Language share).
func Number ¶ added in v0.54.0
Number writes a count the way the interface does: the language's own digit grouping ("48,211" in English, "48.211" in Turkish) — the explorer's toLocaleString. Plural fills `{count}` with bare digits; a caller that wants them grouped passes this as the `count` var. A sentence about a count (a trash of 61,844 items) fills its `{count}` with this rather than the bare digits Plural writes.
func Offered ¶ added in v0.49.0
Offered reports whether tag names a language filex offers as-is — one it ships or one a running language pack adds — and returns the tag in the form the catalogue keys it (lower case, "-" for "_"). Unlike Resolve it never falls back to a nearby language: what an administrator STORES under a language (a role's name in it) must name that language, not a neighbour.
func Pick ¶
Pick is the first of the candidates that Resolve serves; then the instance default; then English. Callers list the candidates in the order THEIR flow decides (the recipient's account, the sender's choice, the request…) — this only answers which of them the catalogue can speak.
func Placeholders ¶
Placeholders lists the distinct `{name}` placeholders of s, sorted.
func Plural ¶
Plural is Text for a sentence about count things: the form of count's CLDR category in lang (see plural.go), and `{count}` is always filled with the number.
func Reader ¶ added in v0.46.0
Reader is the reader's language WithReader put on ctx, or "" when nobody said (a background caller: the worker, the scheduler).
func Resolve ¶
Resolve turns a language tag into the offered language that serves it, or "" when nothing does: the tag itself (`es`, `pt-br`), else its primary subtag (`es-MX` → `es`), else the one regional variant on offer (`pt` → `pt-br`) — the same matching the browser's picker does (packages/core lib/uiLocales), so a mail and the screen agree.
func SetDefault ¶
func SetDefault(tag string)
SetDefault records the instance's default language (FILEX_DEFAULT_LOCALE): the answer Pick falls back to before English.
func SetPacks ¶
func SetPacks(p Packs)
SetPacks wires the language packs. nil unwires them (built-ins only).
func Table ¶
Table is every key under prefix in lang, with the prefix taken off — the shape a page template indexes (`{{.T.pin_title}}`). Placeholders are left unfilled.
A sentence about a count also gets one entry per category lang HAS (`drop_done_sub_few`…; the plain entry is `other`), each already resolved through the fallbacks for a number of that category — so a page script picks `T[key + "_" + Intl.PluralRules(lang).select(n)] || T[key]` and never has to know the rules. English's `_one` is only listed when lang has a `one` category.
func Template ¶
Template is key's text in lang with its placeholders unfilled — for a page script that fills them in the browser.
Types ¶
type Packs ¶
type Packs interface {
// UIString is one key of one language, first running app (by name) wins;
// ok=false when no running app carries a non-empty value for it.
UIString(code, key string) (string, bool)
// UILocaleCodes lists the languages the running apps add, sorted.
UILocaleCodes() []string
}
Packs is what the running language packs add: the app registry (wasmplugin.Registry) satisfies it.
type StaticPacks ¶
StaticPacks is a fixed set of pack languages ({lang: {key: text}}) — what tests and tools hand SetPacks instead of a running registry.
func (StaticPacks) UILocaleCodes ¶
func (s StaticPacks) UILocaleCodes() []string
UILocaleCodes implements Packs.