summaryrefslogtreecommitdiff
path: root/vendor/golang.org/x/text/message/pipeline/message.go
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/golang.org/x/text/message/pipeline/message.go')
-rw-r--r--vendor/golang.org/x/text/message/pipeline/message.go241
1 files changed, 241 insertions, 0 deletions
diff --git a/vendor/golang.org/x/text/message/pipeline/message.go b/vendor/golang.org/x/text/message/pipeline/message.go
new file mode 100644
index 0000000..8e54700
--- /dev/null
+++ b/vendor/golang.org/x/text/message/pipeline/message.go
@@ -0,0 +1,241 @@
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package pipeline
+
+import (
+ "encoding/json"
+ "strings"
+
+ "golang.org/x/text/language"
+)
+
+// TODO: these definitions should be moved to a package so that the can be used
+// by other tools.
+
+// The file contains the structures used to define translations of a certain
+// messages.
+//
+// A translation may have multiple translations strings, or messages, depending
+// on the feature values of the various arguments. For instance, consider
+// a hypothetical translation from English to English, where the source defines
+// the format string "%d file(s) remaining".
+// See the examples directory for examples of extracted messages.
+
+// Config contains configuration for the translation pipeline.
+type Config struct {
+ SourceLanguage language.Tag
+
+ // Supported indicates the languages for which data should be generated.
+ // If unspecified, it will attempt to derive the set of supported languages
+ // from the context.
+ Supported []language.Tag
+
+ Packages []string
+
+ // TODO:
+ // - Printf-style configuration
+ // - Template-style configuration
+ // - Extraction options
+ // - Rewrite options
+ // - Generation options
+}
+
+// A Locale is used to store all information for a single locale. This type is
+// used both for extraction and injection.
+type Locale struct {
+ Language language.Tag `json:"language"`
+ Messages []Message `json:"messages"`
+ Macros map[string]Text `json:"macros,omitempty"`
+}
+
+// A Message describes a message to be translated.
+type Message struct {
+ // ID contains a list of identifiers for the message.
+ ID IDList `json:"id"`
+ // Key is the string that is used to look up the message at runtime.
+ Key string `json:"key"`
+ Meaning string `json:"meaning,omitempty"`
+ Message Text `json:"message"`
+ Translation Text `json:"translation"`
+
+ Comment string `json:"comment,omitempty"`
+ TranslatorComment string `json:"translatorComment,omitempty"`
+
+ Placeholders []Placeholder `json:"placeholders,omitempty"`
+
+ // TODO: default placeholder syntax is {foo}. Allow alternative escaping
+ // like `foo`.
+
+ // Extraction information.
+ Position string `json:"position,omitempty"` // filePosition:line
+}
+
+// Placeholder reports the placeholder for the given ID if it is defined or nil
+// otherwise.
+func (m *Message) Placeholder(id string) *Placeholder {
+ for _, p := range m.Placeholders {
+ if p.ID == id {
+ return &p
+ }
+ }
+ return nil
+}
+
+// Substitute replaces placeholders in msg with their original value.
+func (m *Message) Substitute(msg string) (sub string, err error) {
+ last := 0
+ for i := 0; i < len(msg); {
+ pLeft := strings.IndexByte(msg[i:], '{')
+ if pLeft == -1 {
+ break
+ }
+ pLeft += i
+ pRight := strings.IndexByte(msg[pLeft:], '}')
+ if pRight == -1 {
+ return "", errorf("unmatched '}'")
+ }
+ pRight += pLeft
+ id := strings.TrimSpace(msg[pLeft+1 : pRight])
+ i = pRight + 1
+ if id != "" && id[0] == '$' {
+ continue
+ }
+ sub += msg[last:pLeft]
+ last = i
+ ph := m.Placeholder(id)
+ if ph == nil {
+ return "", errorf("unknown placeholder %q in message %q", id, msg)
+ }
+ sub += ph.String
+ }
+ sub += msg[last:]
+ return sub, err
+}
+
+// A Placeholder is a part of the message that should not be changed by a
+// translator. It can be used to hide or prettify format strings (e.g. %d or
+// {{.Count}}), hide HTML, or mark common names that should not be translated.
+type Placeholder struct {
+ // ID is the placeholder identifier without the curly braces.
+ ID string `json:"id"`
+
+ // String is the string with which to replace the placeholder. This may be a
+ // formatting string (for instance "%d" or "{{.Count}}") or a literal string
+ // (<div>).
+ String string `json:"string"`
+
+ Type string `json:"type"`
+ UnderlyingType string `json:"underlyingType"`
+ // ArgNum and Expr are set if the placeholder is a substitution of an
+ // argument.
+ ArgNum int `json:"argNum,omitempty"`
+ Expr string `json:"expr,omitempty"`
+
+ Comment string `json:"comment,omitempty"`
+ Example string `json:"example,omitempty"`
+
+ // Features contains the features that are available for the implementation
+ // of this argument.
+ Features []Feature `json:"features,omitempty"`
+}
+
+// An argument contains information about the arguments passed to a message.
+type argument struct {
+ // ArgNum corresponds to the number that should be used for explicit argument indexes (e.g.
+ // "%[1]d").
+ ArgNum int `json:"argNum,omitempty"`
+
+ used bool // Used by Placeholder
+ Type string `json:"type"`
+ UnderlyingType string `json:"underlyingType"`
+ Expr string `json:"expr"`
+ Value string `json:"value,omitempty"`
+ Comment string `json:"comment,omitempty"`
+ Position string `json:"position,omitempty"`
+}
+
+// Feature holds information about a feature that can be implemented by
+// an Argument.
+type Feature struct {
+ Type string `json:"type"` // Right now this is only gender and plural.
+
+ // TODO: possible values and examples for the language under consideration.
+
+}
+
+// Text defines a message to be displayed.
+type Text struct {
+ // Msg and Select contains the message to be displayed. Msg may be used as
+ // a fallback value if none of the select cases match.
+ Msg string `json:"msg,omitempty"`
+ Select *Select `json:"select,omitempty"`
+
+ // Var defines a map of variables that may be substituted in the selected
+ // message.
+ Var map[string]Text `json:"var,omitempty"`
+
+ // Example contains an example message formatted with default values.
+ Example string `json:"example,omitempty"`
+}
+
+// IsEmpty reports whether this Text can generate anything.
+func (t *Text) IsEmpty() bool {
+ return t.Msg == "" && t.Select == nil && t.Var == nil
+}
+
+// rawText erases the UnmarshalJSON method.
+type rawText Text
+
+// UnmarshalJSON implements json.Unmarshaler.
+func (t *Text) UnmarshalJSON(b []byte) error {
+ if b[0] == '"' {
+ return json.Unmarshal(b, &t.Msg)
+ }
+ return json.Unmarshal(b, (*rawText)(t))
+}
+
+// MarshalJSON implements json.Marshaler.
+func (t *Text) MarshalJSON() ([]byte, error) {
+ if t.Select == nil && t.Var == nil && t.Example == "" {
+ return json.Marshal(t.Msg)
+ }
+ return json.Marshal((*rawText)(t))
+}
+
+// IDList is a set identifiers that each may refer to possibly different
+// versions of the same message. When looking up a messages, the first
+// identifier in the list takes precedence.
+type IDList []string
+
+// UnmarshalJSON implements json.Unmarshaler.
+func (id *IDList) UnmarshalJSON(b []byte) error {
+ if b[0] == '"' {
+ *id = []string{""}
+ return json.Unmarshal(b, &((*id)[0]))
+ }
+ return json.Unmarshal(b, (*[]string)(id))
+}
+
+// MarshalJSON implements json.Marshaler.
+func (id *IDList) MarshalJSON() ([]byte, error) {
+ if len(*id) == 1 {
+ return json.Marshal((*id)[0])
+ }
+ return json.Marshal((*[]string)(id))
+}
+
+// Select selects a Text based on the feature value associated with a feature of
+// a certain argument.
+type Select struct {
+ Feature string `json:"feature"` // Name of Feature type (e.g plural)
+ Arg string `json:"arg"` // The placeholder ID
+ Cases map[string]Text `json:"cases"`
+}
+
+// TODO: order matters, but can we derive the ordering from the case keys?
+// type Case struct {
+// Key string `json:"key"`
+// Value Text `json:"value"`
+// }