Skip to content

Commit

Permalink
cleanup
Browse files Browse the repository at this point in the history
  • Loading branch information
fullpipe committed Dec 18, 2024
1 parent 07e11ac commit 1f751e1
Show file tree
Hide file tree
Showing 9 changed files with 182 additions and 148 deletions.
12 changes: 5 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ Create translations bundle
```go
bundle, err := mf.NewBundle(
// If not possible to find a message for the specific language, fallback to English (EN)
mf.WithDefaulLangFallback(language.English),
mf.WithDefaultLangFallback(language.English),

// We could fine-tune fallbacks for some languages
mf.WithLangFallback(language.BritishEnglish, language.English),
Expand Down Expand Up @@ -125,7 +125,7 @@ var messagesDir embed.FS

func main() {
bundle, err := mf.NewBundle(
mf.WithDefaulLangFallback(language.English),
mf.WithDefaultLangFallback(language.English),

mf.WithLangFallback(language.BritishEnglish, language.English),
mf.WithLangFallback(language.Portuguese, language.Spanish),
Expand Down Expand Up @@ -199,7 +199,6 @@ tr.Trans("escape", mf.Arg("foo", "bar"))
// {foo} is 'bar'
```


## MessageFormat overview

### Placeholders
Expand Down Expand Up @@ -473,10 +472,10 @@ Additionally, there are four different formats: `short`, `medium`, `long`, and `
# translations/messages.en.yaml
vostok:
start: Vostok-1 start {start_date, datetime, long}.
landing: Vostok-1 landing time {land_time, time, medium}.
start: Vostok-1 start {start_date, datetime, long}.
landing: Vostok-1 landing time {land_time, time, medium}.
apollo:
step: First step on the Moon on {step_date, date, long}.
step: First step on the Moon on {step_date, date, long}.
```

```go
Expand All @@ -493,4 +492,3 @@ tr.Trans("vostok.landing", mf.Time("land_time", land))
tr.Trans("apollo.step", mf.Time("step_date", step))
// First step on the Moon on July 21, 1969.
```

2 changes: 1 addition & 1 deletion example/base/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ var messagesDir embed.FS

func main() {
bundle, err := mf.NewBundle(
mf.WithDefaulLangFallback(language.English),
mf.WithDefaultLangFallback(language.English),

mf.WithLangFallback(language.BritishEnglish, language.English),
mf.WithLangFallback(language.Portuguese, language.Spanish),
Expand Down
6 changes: 4 additions & 2 deletions example/htmx-templ/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,17 @@ go 1.23.2
require (
github.com/a-h/templ v0.2.793
github.com/alexedwards/scs/v2 v2.8.0
github.com/fullpipe/icu-mf v0.0.0-20241030155633-222b9dc7894e
github.com/fullpipe/icu-mf v0.99.99
golang.org/x/text v0.17.0
)

replace github.com/fullpipe/icu-mf => ../..

require (
github.com/alecthomas/participle/v2 v2.1.1 // indirect
github.com/kr/text v0.2.0 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/rogpeppe/go-internal v1.13.1 // indirect
golang.org/x/exp v0.0.0-20240823005443-9b4947da3948 // indirect
golang.org/x/text v0.17.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)
2 changes: 0 additions & 2 deletions example/htmx-templ/go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,6 @@ github.com/alexedwards/scs/v2 v2.8.0/go.mod h1:ToaROZxyKukJKT/xLcVQAChi5k6+Pn1Gv
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/fullpipe/icu-mf v0.0.0-20241030155633-222b9dc7894e h1:Lzyy1SCTPeRaESgj4Q7AFbnxmgEkYr4E/vjcX9FQMfs=
github.com/fullpipe/icu-mf v0.0.0-20241030155633-222b9dc7894e/go.mod h1:+Ss+eRPcJwWykGqZ3Yth/7+7D1zKgFY+vyV97n8lsoU=
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/hexops/gotextdiff v1.0.3 h1:gitA9+qJrrTCsiCl7+kh75nPqQt1cx4ZkudSTLoUqJM=
Expand Down
2 changes: 1 addition & 1 deletion example/htmx-templ/tr/tr.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ func init() {
var err error

bundle, err = mf.NewBundle(
mf.WithDefaulLangFallback(language.English),
mf.WithDefaultLangFallback(language.English),

mf.WithLangFallback(language.BritishEnglish, language.English),
mf.WithLangFallback(language.Portuguese, language.Spanish),
Expand Down
143 changes: 55 additions & 88 deletions message/build.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,95 +14,84 @@ func Build(in parse.Message, lang language.Tag) (Evalable, error) {
return buildFragment(*in.Fragments[0], lang)
}

root := Message{
root := &Message{
fragments: make([]Evalable, 0, len(in.Fragments)),
}

for _, f := range in.Fragments {
eval, err := buildFragment(*f, lang)
if err != nil {
// TODO: collect errors
return nil, err
}

root.fragments = append(root.fragments, eval)
}

return &root, nil
return root, nil
}

func buildFragment(f parse.Fragment, lang language.Tag) (Evalable, error) {
if len(f.Escaped) > 0 {
switch {
case len(f.Escaped) > 0:
return Content(f.Escaped[1:]), nil
}

if len(f.Text) > 0 {
case len(f.Text) > 0:
return Content(f.Text), nil
}

if f.Octothorpe {
case f.Octothorpe:
return PlainArg("#"), nil
}

if f.PlainArg != nil {
case f.PlainArg != nil:
return PlainArg(f.PlainArg.Name), nil
}

if f.Func != nil {
switch f.Func.Func {
case "number":
return buildNumber(f.Func, lang)
case "date", "time", "datetime":
return buildDatetime(f.Func, lang)
default:
return nil, errors.New("empty fragment")
}
}

if f.Expr == nil {
case f.Func != nil:
return buildFunc(f.Func, lang)
case f.Expr != nil:
return buildExpr(f.Expr, lang)
default:
return nil, errors.New("empty fragment")
}
}

e := f.Expr

if e.Name != "" && e.Func == "select" {
return buildSelect(e, lang)
}

if e.Name != "" && e.Func == "plural" {
return buildPlural(e, lang)
func buildFunc(f *parse.Func, lang language.Tag) (Evalable, error) {
switch f.Func {
case "number":
return buildNumber(f, lang)
case "date", "time", "datetime":
return buildDatetime(f, lang)
default:
return nil, fmt.Errorf("unsupported function: %s", f.Func)
}
}

if e.Name != "" && e.Func == "selectordinal" {
func buildExpr(e *parse.Expr, lang language.Tag) (Evalable, error) {
switch e.Func {
case "select":
return buildSelect(e, lang)
case "plural", "selectordinal":
return buildPlural(e, lang)
default:
return nil, fmt.Errorf("unsupported expression: %s", e.Func)
}

return nil, errors.New("empty fragment")
}

func buildSelect(e *parse.Expr, lang language.Tag) (Evalable, error) {
if e == nil || e.Name == "" || e.Func != "select" {
return nil, errors.New("no a select expresion")
return nil, errors.New("invalid select expression")
}

if len(e.Cases) == 0 {
return nil, errors.New("empty select cases")
}

eval := Select{
eval := &Select{
ArgName: e.Name,
Cases: make(map[string]Evalable, len(e.Cases)),
}
hasDefaultCase := false

hasDefaultCase := false
for _, c := range e.Cases {
if c.Name == DefaultCase {
hasDefaultCase = true
}

caseEval, err := Build(*c.Message, lang)
if err != nil {
// TODO: collect errors
return nil, err
}

Expand All @@ -113,12 +102,12 @@ func buildSelect(e *parse.Expr, lang language.Tag) (Evalable, error) {
return nil, errors.New("no 'other' case in select")
}

return &eval, nil
return eval, nil
}

func buildPlural(e *parse.Expr, lang language.Tag) (Evalable, error) {
if e == nil || e.Name == "" || (e.Func != "plural" && e.Func != "selectordinal") {
return nil, errors.New("no a select expresion")
return nil, errors.New("invalid plural expression")
}

if len(e.Cases) == 0 {
Expand All @@ -140,81 +129,59 @@ func buildPlural(e *parse.Expr, lang language.Tag) (Evalable, error) {
}

hasDefaultCase := false

for _, c := range e.Cases {
if c.Name == DefaultCase {
hasDefaultCase = true
}

caseEval, err := Build(*c.Message, lang)
if err != nil {
// TODO: collect errors
return nil, err
}

form, ok := strToFormMap[c.Name]
if ok {
if form, ok := strToFormMap[c.Name]; ok {
eval.Cases[form] = caseEval
continue
}

if c.Name[0] != '=' {
} else if c.Name[0] == '=' {
caseNum, err := strconv.ParseUint(c.Name[1:], 10, 64)
if err != nil {
return nil, err
}
eval.EqCases[caseNum] = caseEval
} else {
return nil, fmt.Errorf("invalid plural case %s", c.Name)
}

caseNum, err := strconv.ParseUint(c.Name[1:], 10, 64)
if err != nil {
// TODO: collect errors
return nil, err
}

eval.EqCases[caseNum] = caseEval
}

if !hasDefaultCase {
return nil, errors.New("no 'other' case in plural")
}

return eval, nil

}

func buildNumber(e *parse.Func, lang language.Tag) (Evalable, error) {
if e == nil || e.Func != "number" {
return nil, errors.New("no a number function")
}

// format, ok := strToNumberFormatMap[e.Param]
format, ok := strToNumberFormatMap[e.Param]
func buildNumber(f *parse.Func, lang language.Tag) (Evalable, error) {
format, ok := strToNumberFormatMap[f.Param]
if !ok {
return nil, fmt.Errorf("number format %s not supported", e.Param)
return nil, fmt.Errorf("number format %s not supported", f.Param)
}

return NewNumber(e.ArgName, format, lang), nil
return NewNumber(f.ArgName, format, lang), nil
}

func buildDatetime(e *parse.Func, lang language.Tag) (Evalable, error) {
if e == nil {
return nil, errors.New("empty expresiion")
}

if e.Func != "date" && e.Func != "time" && e.Func != "datetime" {
return nil, errors.New("not a date function")
}

format, ok := strToDatetimeFormatMap[e.Param]
func buildDatetime(f *parse.Func, lang language.Tag) (Evalable, error) {
format, ok := strToDatetimeFormatMap[f.Param]
if !ok {
return nil, fmt.Errorf("date format %s not supported", e.Param)
return nil, fmt.Errorf("date format %s not supported", f.Param)
}

switch e.Func {
switch f.Func {
case "date":
return NewDate(e.ArgName, format, lang), nil
return NewDate(f.ArgName, format, lang), nil
case "time":
return NewTime(e.ArgName, format, lang), nil
return NewTime(f.ArgName, format, lang), nil
case "datetime":
return NewDatetime(e.ArgName, format, lang), nil
return NewDatetime(f.ArgName, format, lang), nil
default:
return nil, fmt.Errorf("unsupported datetime function: %s", f.Func)
}

return nil, errors.New("not a date function")
}
Loading

0 comments on commit 1f751e1

Please sign in to comment.