Documentation
¶
Overview ¶
Package pwmsg reads message catalogs and generates the typed Go package a template's message reference resolves against.
It is a host-side tool: it runs during pw generate and never in a served process. See .knowledge decision:message-code-shape.
Index ¶
- func ExportPO(catalog *Catalog, locale string) []byte
- func ExtractMarks(filename string, source []byte) ([]Mark, []MarkProblem, error)
- func Holes(pieces []Piece) []string
- func Placeholders(pieces []Piece) []string
- func ProposeID(text string, element string, ordinal int) (id string, derived bool)
- func RenameEntry(source []byte, from, to string) ([]byte, bool)
- func RenderEntry(id, text string, locales []string, sourceLocale string) string
- func Rewrite(source []byte, marks []Mark, ids []string) ([]byte, error)
- type Catalog
- type Category
- type Diagnostic
- type Entry
- type Generated
- type Mark
- type MarkProblem
- type POEntry
- type Param
- type Piece
- type PluralRule
- type Route
- type Routing
- type Scope
- type Severity
- type Symbol
- type Text
- type UnknownPluralLocale
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func ExportPO ¶
ExportPO renders one locale as a gettext PO catalog.
PO rather than XLIFF because the mapping is exact and the format is line-based: msgctxt carries the message ID, msgid the source text, and msgstr the translation. That is the same asymmetry decision:message-source-of-truth records — the source is shown to the translator and is not theirs to edit — so nothing has to be invented to express it.
The source text comes from the declared source locale, so a translator sees what they are translating from rather than an identifier.
func ExtractMarks ¶
func ExtractMarks(filename string, source []byte) ([]Mark, []MarkProblem, error)
ExtractMarks reports every marked string in one template.
A mark on an element whose children are not one run of text is declined rather than guessed at: that shape is rich text, whose holes name markup the template supplies, and a tool inventing hole names would produce translations no translator can check. It is reported so the author converts it by hand.
func Placeholders ¶
Placeholders returns the placeholder names a parsed translation uses, sorted.
func ProposeID ¶
ProposeID derives a message ID from source text.
It is best effort by design: a slug from Latin text is mechanical, and a slug from kanji needs readings this build deliberately does not ship. A text it cannot slug produces a positional name the author renames, which costs what naming a variable costs. See .knowledge decision:message-id-assignment.
func RenameEntry ¶
RenameEntry rewrites one scope file so an ID becomes another.
It edits the key line textually rather than re-marshalling, so the comments, the ordering, and the formatting a translator put in the file survive. A rename is one line changing; nothing else about the file should move.
func RenderEntry ¶
RenderEntry renders one catalog entry as YAML, ready to append to a scope file.
It is appended as text rather than written by re-marshalling the file, because re-marshalling drops the comments and the ordering a translator put there and this tool has no business rewriting what it did not add.
Types ¶
type Catalog ¶
type Catalog struct {
Locales []string
Default string
Scopes []Scope
// Routing is the locale mode per path prefix, the display labels, and
// whether the default locale carries a prefix. It is generated into the
// message package because all of it is build configuration the served
// process cannot otherwise know. See .knowledge decision:locale-url-modes.
Routing Routing
}
Catalog is every message a project declares, read from the directory named by i18n.catalog.
One file is one scope, because decision:message-scope-declaration makes the scope a template writes the natural sharding key: two translators working on separate features do not contend on one file.
type Category ¶
type Category string
Category is a CLDR plural category. The set is closed and ordered so a generated table row can be addressed by position.
type Diagnostic ¶
Diagnostic is one finding against a catalog.
func Validate ¶
func Validate(catalog *Catalog, missing Severity) []Diagnostic
Validate checks a catalog against the declared locale set.
missing is the severity of a locale that supplies no translation for a message, which data:i18n-config leaves to the project: a build that must ship complete fails, and a build still being translated reports and falls back. Every other finding here has a fixed severity, because a placeholder that does not match its declaration renders wrong text in a way no fallback repairs.
func (Diagnostic) String ¶
func (d Diagnostic) String() string
type Entry ¶
type Entry struct {
// ID is the bare name within the scope. Qualified() joins it to the scope.
ID string
Params []Param
// Plural names the parameter driving category selection, empty for a
// message with no plural variation.
Plural string
// Rich marks a message whose translations carry holes, which renders
// through the segment path of policy:message-rich-text rather than as a
// string.
Rich bool
// Snapshot is the source text recorded when the ID was assigned. It is
// written by tooling and compared, never edited by hand: a source text
// differing from it is what marks every other locale stale, per
// decision:message-id-assignment.
Snapshot string
Texts map[string]Text
// Line is where the entry starts in its file, for diagnostics.
Line int
}
Entry is one message.
type Generated ¶
type Generated struct {
// Source is the formatted Go file.
Source []byte
// Symbols maps a resolved message ID to the symbol a reference calls.
Symbols map[string]Symbol
}
Generated is the output of one generation run.
type Mark ¶
type Mark struct {
// Text is the source text that becomes the message.
Text string
// Start and End are the byte range the reference replaces. The range is
// source rather than content, so replacing it also replaces any escape the
// text contained.
Start, End int
// AttributeRange is the range of the i18n attribute itself, removed by the
// same rewrite.
AttributeStart, AttributeEnd int
// Element names what carried the mark, used when a slug cannot be derived
// from the text.
Element string
// Attribute names the attribute whose value was marked, empty for element
// text.
Attribute string
// Line is where the mark is, for reporting.
Line int
}
Mark is one piece of source text an author flagged for extraction.
The flag is an ordinary HTML attribute, so it needs no grammar of its own and is removed by the rewrite. See .knowledge decision:message-id-assignment.
type MarkProblem ¶
MarkProblem is a mark this extractor declines to act on.
type POEntry ¶
POEntry is one translated unit read back from a PO file.
type Piece ¶
type Piece struct {
// Hole is the hole this piece sits inside, empty at the top level.
Hole string
// Arg names the placeholder this piece renders, empty for a literal run.
Arg string
// Lit is the literal text, used when Arg is empty.
Lit string
}
Piece is one parsed span of a translation.
A translation is plain text: the only markup it may carry is a hole name, and a hole stands for an element the template supplies. See .knowledge policy:message-rich-text.
func ParseText ¶
ParseText splits a translation into pieces.
Placeholders are written {name}. A literal brace is written {{ or }}, matching the template language rather than inventing a second escape for the same character.
Holes are written <name>text</name> and are recognised only when rich is set, so a translation in an ordinary message may contain angle brackets as text. That matters because a message is escaped by the template for its position, so "a < b" is legitimate content.
type PluralRule ¶
type PluralRule struct {
// Categories are the ones this locale uses, in categoryOrder.
Categories []Category
// Selector is Go statements over the parameter n returning the position of
// the matching category within Categories.
//
// It is statements rather than an expression because Go has no conditional
// expression, and the expression forms that imitate one — a map literal
// indexed by a bool, a slice indexed by a converted bool — allocate or
// bounds-check on a path every rendered message crosses.
//
// Empty means the locale has one category, where generation writes a
// constant instead.
Selector string
}
PluralRule is the cardinal plural behaviour of one locale: which categories it distinguishes, and the Go expression selecting one for a value.
Only declared locales are generated, so a single-locale Japanese project emits a selector that is a constant. See .knowledge decision:message-code-shape.
func RuleFor ¶
func RuleFor(tag string) (PluralRule, bool)
RuleFor returns the cardinal rule of a locale, matching the base language subtag so pt-BR follows pt.
A locale with no known rule reports the single-category rule and false, which is correct for a catalog that declares no variants and is what the caller turns into UnknownPluralLocale when it declares some.
type Routing ¶
type Routing struct {
// Routes are prefix and mode pairs, the mode being "path", "cookie", or
// "header".
Routes []Route
// Labels is the display name of each locale, written in that locale.
Labels map[string]string
// PrefixDefault decides whether the default locale carries a path prefix.
PrefixDefault bool
}
Routing is the build-time locale routing declaration.
type Severity ¶
type Severity int
Severity separates what stops a build from what a reader should see and decide about.
type Symbol ¶
type Symbol struct {
// Name is the exported Go function.
Name string
// Params are the argument names in declaration order, excluding the leading
// locale the implicit binding supplies.
Params []string
// Rich marks a message whose function returns segments rather than a
// string.
Rich bool
}
Symbol is what one resolved message ID calls. It is the downstream half of the table system:tinybind is given, per decision:upstream-message-surface.
type Text ¶
Text is one locale's translation: either a single form, or one per plural category the locale distinguishes.
func (*Text) UnmarshalYAML ¶
UnmarshalYAML accepts either a scalar or a mapping of category to scalar, so a locale with no plural variation reads as the string it is.
type UnknownPluralLocale ¶
type UnknownPluralLocale struct {
Tag string
}
UnknownPluralLocale is reported for a locale whose rule this build cannot state. It is an error only when the catalog declares plural variation for that locale: a locale using one form throughout needs no rule.
func (UnknownPluralLocale) Error ¶
func (e UnknownPluralLocale) Error() string