1 // Copyright 2015 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
5 package message // import "golang.org/x/text/message"
11 "golang.org/x/text/language"
12 "golang.org/x/text/message/catalog"
15 // TODO: allow more than one goroutine per printer. This will allow porting from
16 // fmt much less error prone.
18 // A Printer implements language-specific formatted I/O analogous to the fmt
19 // package. Only one goroutine may use a Printer at the same time.
21 // Wrap the fields in a hidden type to hide some of the implemented methods.
24 // NOTE: limiting one goroutine per Printer allows for many optimizations
25 // and simplifications. We can consider removing this restriction down the
26 // road if it the benefits do not seem to outweigh the disadvantages.
32 // - allow %s to print integers in written form (tables are likely too large
33 // to enable this by default).
38 // An Option defines an option of a Printer.
39 type Option func(o *options)
41 // Catalog defines the catalog to be used.
42 func Catalog(c *catalog.Catalog) Option {
43 return func(o *options) { o.cat = c }
46 // NewPrinter returns a Printer that formats messages tailored to language t.
47 func NewPrinter(t language.Tag, opts ...Option) *Printer {
51 for _, o := range opts {
54 p := &Printer{printer{
57 p.printer.toDecimal.InitDecimal(t)
58 p.printer.toScientific.InitScientific(t)
59 p.printer.catContext = options.cat.Context(t, &p.printer)
63 // Sprint is like fmt.Sprint, but using language-specific formatting.
64 func (p *Printer) Sprint(a ...interface{}) string {
67 return p.printer.String()
70 // Fprint is like fmt.Fprint, but using language-specific formatting.
71 func (p *Printer) Fprint(w io.Writer, a ...interface{}) (n int, err error) {
74 n64, err := io.Copy(w, &p.printer.Buffer)
78 // Print is like fmt.Print, but using language-specific formatting.
79 func (p *Printer) Print(a ...interface{}) (n int, err error) {
80 return p.Fprint(os.Stdout, a...)
83 // Sprintln is like fmt.Sprintln, but using language-specific formatting.
84 func (p *Printer) Sprintln(a ...interface{}) string {
86 p.printer.doPrintln(a)
87 return p.printer.String()
90 // Fprintln is like fmt.Fprintln, but using language-specific formatting.
91 func (p *Printer) Fprintln(w io.Writer, a ...interface{}) (n int, err error) {
93 p.printer.doPrintln(a)
94 n64, err := io.Copy(w, &p.printer.Buffer)
98 // Println is like fmt.Println, but using language-specific formatting.
99 func (p *Printer) Println(a ...interface{}) (n int, err error) {
100 return p.Fprintln(os.Stdout, a...)
103 // Sprintf is like fmt.Sprintf, but using language-specific formatting.
104 func (p *Printer) Sprintf(key Reference, a ...interface{}) string {
105 lookupAndFormat(p, key, a)
106 return p.printer.String()
109 // Fprintf is like fmt.Fprintf, but using language-specific formatting.
110 func (p *Printer) Fprintf(w io.Writer, key Reference, a ...interface{}) (n int, err error) {
111 lookupAndFormat(p, key, a)
112 return w.Write(p.printer.Bytes())
115 // Printf is like fmt.Printf, but using language-specific formatting.
116 func (p *Printer) Printf(key Reference, a ...interface{}) (n int, err error) {
117 lookupAndFormat(p, key, a)
118 return os.Stdout.Write(p.printer.Bytes())
121 func lookupAndFormat(p *Printer, r Reference, a []interface{}) {
125 switch v := r.(type) {
129 id, msg = v.id, v.fallback
131 panic("key argument is not a Reference")
134 if p.printer.catContext.Execute(id) == catalog.ErrNotFound {
135 if p.printer.catContext.Execute(msg) == catalog.ErrNotFound {
136 p.printer.Render(msg)
142 // Arg implements catmsg.Renderer.
143 func (p *printer) Arg(i int) interface{} { // TODO, also return "ok" bool
145 if uint(i) < uint(len(p.args)) {
151 // Render implements catmsg.Renderer.
152 func (p *printer) Render(msg string) {
156 // A Reference is a string or a message reference.
157 type Reference interface {
158 // TODO: also allow []string
161 // Key creates a message Reference for a message where the given id is used for
162 // message lookup and the fallback is returned when no matches are found.
163 func Key(id string, fallback string) Reference {
164 return key{id, fallback}