Skip to content

Commit

Permalink
➕ example and partial support l10n
Browse files Browse the repository at this point in the history
  • Loading branch information
skillcoder committed Nov 29, 2020
1 parent 9e9bcd3 commit 6baeb7d
Show file tree
Hide file tree
Showing 12 changed files with 463 additions and 17 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
*.dll
*.so
*.dylib
example/example

# Test binary, built with `go test -c`
*.test
Expand Down
14 changes: 14 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@

all:

extract:
goi18n extract -sourceLanguage en-us -outdir l10n -format toml

translate:
ifeq ($(lang),)
echo "use: make translate lang=de-DE"
exit
else
touch translate.$(lang).toml
goi18n merge -sourceLanguage en-us l10n/active.en-US.toml translate.$(lang).toml
endif
47 changes: 45 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,49 @@
Library for make **h**uman **r**eadable **r**ecurrence **rule**s from iCalendar RRULE (RFC5545) in Golang
It supports serialization of recurrence rules to natural language, with internationalisation!

🚧 Under construction 🚧
It is a partial port of the rrule module from [rrule.js](https://github.com/jakubroztocil/rrule) library.

It is a partial port of the rrule module from [rrule.js](https://github.com/jakubroztocil/rrule) library.
## Using
```
package main
import (
"fmt"
"log"
"github.com/nicksnyder/go-i18n/v2/i18n"
"golang.org/x/text/language"
"github.com/skillcoder/hrrule-go"
)
func main() {
hRule, err := hrrule.New(i18n.NewBundle(language.AmericanEnglish))
if err != nil {
log.Fatalf("filed to init rrule humanizer: %v", err)
}
rOption, err := hrrule.StrToROption("FREQ=MONTHLY;INTERVAL=1;BYDAY=-1FR;UNTIL=20241229T155400Z")
if err != nil {
log.Fatalf("rrule string to option: %v", err)
}
nlString, err := hRule.Humanize(rOption, "en-US")
if err != nil {
log.Fatalf("humanize rrule to string: %v", err)
}
fmt.Println(nlString)
}
```

## Translation to new language
See docs in https://github.com/nicksnyder/go-i18n
1. `touch l10n/translate.ru.toml`
2. `goi18n merge l10n/active.en-US.toml translate.ru.toml`
3. After `translate.ru.toml` has been translated, move it to `l10n/active.ru-RU.toml`.

🚧 It is necessary to agreement on the declension, cases and kind in the languages in which they exist 🚧

## TODO
* Day of the week translation support
* Months translation support
24 changes: 14 additions & 10 deletions date_formatter.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,13 +70,13 @@ func (df *formatterImpl) MonthName(month time.Month) string {
}

// Nth return int with suffix
// TODO: implement me
func (df *formatterImpl) Nth(i int) string {
var last string

if i < 0 {
last = df.loc.MustLocalize(&i18n.LocalizeConfig{DefaultMessage: &i18n.Message{
ID: "Last",
Description: "The last for Nth return int with suffix",
Other: "last",
}})
}
Expand All @@ -91,23 +91,27 @@ func (df *formatterImpl) Nth(i int) string {
switch nPos {
case 1, 21, 31:
nth.WriteString(df.loc.MustLocalize(&i18n.LocalizeConfig{DefaultMessage: &i18n.Message{
ID: "Suffix for 1, 21, 31",
Other: "st",
ID: "First",
Description: "Suffix for 1, 21, 31",
Other: "st",
}}))
case 2, 22:
nth.WriteString(df.loc.MustLocalize(&i18n.LocalizeConfig{DefaultMessage: &i18n.Message{
ID: "Suffix for 2, 22",
Other: "nd",
ID: "Second",
Description: "Suffix for 2, 22",
Other: "nd",
}}))
case 3, 23:
nth.WriteString(df.loc.MustLocalize(&i18n.LocalizeConfig{DefaultMessage: &i18n.Message{
ID: "Suffix for 3, 23",
Other: "rd",
ID: "Third",
Description: "Suffix for 3, 23",
Other: "rd",
}}))
default:
nth.WriteString(df.loc.MustLocalize(&i18n.LocalizeConfig{DefaultMessage: &i18n.Message{
ID: "Suffix for other numbers",
Other: "th",
ID: "ThOther",
Description: "Suffix for other numbers",
Other: "th",
}}))
}

Expand Down Expand Up @@ -153,4 +157,4 @@ func abs(n int) int {
}

return n
}
}
31 changes: 31 additions & 0 deletions example/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package main

import (
"fmt"
"log"

"github.com/skillcoder/hrrule-go"
)

func main() {
bundle, err := hrrule.NewI18NBundle("../l10n")
if err != nil {
log.Fatalf("filed to init i18n bundle: %v", err)
}

hRule, err := hrrule.New(bundle)
if err != nil {
log.Fatalf("filed to init rrule humanizer: %v", err)
}

rOption, err := hrrule.StrToROption("FREQ=MONTHLY;INTERVAL=1;BYDAY=-1FR;UNTIL=20241229T155400Z")
if err != nil {
log.Fatalf("rrule string to option: %v", err)
}

nlString, err := hRule.Humanize(rOption, "en-US")
if err != nil {
log.Fatalf("humanize rrule to string: %v", err)
}
fmt.Println(nlString)
}
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,5 @@ require (
github.com/nicksnyder/go-i18n/v2 v2.1.1
github.com/teambition/rrule-go v1.6.2
golang.org/x/text v0.3.4
gopkg.in/yaml.v2 v2.4.0 // indirect
)
3 changes: 3 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/nicksnyder/go-i18n v1.10.1 h1:isfg77E/aCD7+0lD/D00ebR2MV5vgeQ276WYyDaCRQc=
github.com/nicksnyder/go-i18n/v2 v2.1.1 h1:ATCOanRDlrfKVB4WHAdJnLEqZtDmKYsweqsOUYflnBU=
github.com/nicksnyder/go-i18n/v2 v2.1.1/go.mod h1:d++QJC9ZVf7pa48qrsRWhMJ5pSHIPmS3OLqK1niyLxs=
github.com/teambition/rrule-go v1.6.2 h1:keZiiijltBxYUuhQaySAEGyIFR0UOkAd7i+u6FM5/+I=
Expand All @@ -12,3 +13,5 @@ gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU=
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
2 changes: 1 addition & 1 deletion humanize.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ type HRRule struct {
func New(bundle *i18n.Bundle) (Humanizer, error) {
if bundle == nil {
var err error
bundle, err = NewI18NBundle()
bundle, err = NewI18NBundle("./l10n")
if err != nil {
return nil, err
}
Expand Down
9 changes: 8 additions & 1 deletion humanize_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,9 +61,16 @@ func TestHRRule_Humanize(t *testing.T) {
want: "every year on the 256th day for 10 times",
wantErr: false,
},
{
name: "every month on the last Friday until 29 December 2024",
lang: "en-US",
inputRRule: "FREQ=MONTHLY;INTERVAL=1;BYDAY=-1FR;UNTIL=20241229T155400Z",
want: "every month on the last Friday until 29 December 2024",
wantErr: false,
},
}

bundle, err := NewI18NBundle()
bundle, err := NewI18NBundle("./l10n")
if err != nil {
t.Fatalf("create bundle: %v", err)
}
Expand Down
6 changes: 3 additions & 3 deletions i18n.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,11 @@ import (
"golang.org/x/text/language"
)

func NewI18NBundle() (*i18n.Bundle, error) {
bundle := i18n.NewBundle(language.English)
func NewI18NBundle(path string) (*i18n.Bundle, error) {
bundle := i18n.NewBundle(language.AmericanEnglish)
bundle.RegisterUnmarshalFunc("toml", toml.Unmarshal)

err := filepath.Walk("l10n", getWalkFunc(bundle))
err := filepath.Walk(path, getWalkFunc(bundle))
if err != nil {
return nil, err
}
Expand Down
158 changes: 158 additions & 0 deletions l10n/active.en-US.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,158 @@
Approximately = "(~ approximate)"
Every = "every"
Until = "until"

[And]
description = "Used for final delimiter in list"
other = "and"

[At]
description = "Used before hour list"
other = "at"

[ByYearDay]
description = "Used after by year day"
other = "day"

[CountWeekNo]
description = "Used before WeekNo list"
few = "weeks"
many = "weeks"
one = "week"
other = "weeks"
two = "weeks"

[First]
description = "Suffix for 1, 21, 31"
other = "st"

[In]
description = "Used before by month count"
other = "in"

[InWeekNo]
description = "Used before by week no"
other = "in"

[IntervalCountDay]
description = "Used after interval count"
few = "days"
many = "days"
one = "day"
other = "days"
two = "days"

[IntervalCountDays]
description = "Used after interval count if every day"
few = "days"
many = "days"
one = "day"
other = "days"
two = "days"

[IntervalCountMonths]
description = "Used for months by month"
few = "{{.Interval}} months in"
many = "{{.Interval}} months in"
one = "{{.Interval}} month"
other = "{{.Interval}} months in"
two = "{{.Interval}} months in"

[IntervalCountWeekday]
description = "Used after interval count"
few = "weekdays"
many = "weekdays"
one = "weekday"
other = "weekdays"
two = "weekdays"

[IntervalCountWeekdays]
description = "Used before weekdays"
few = "weekdays"
many = "weekdays"
one = "weekday"
other = "weekdays"
two = "weekdays"

[IntervalCountWeeks]
description = "Used after interval count"
few = "weeks"
many = "weeks"
one = "week"
other = "weeks"
two = "weeks"

[IntervalMonths]
description = "Used after interval monthly"
few = "months"
many = "months"
one = "month"
other = "months"
two = "months"

[IntervalYearlyByMonth]
description = "Used for years by month"
few = "{{.Interval}} years"
many = "{{.Interval}} years"
one = "{{.Interval}} year"
other = "{{.Interval}} years"
two = "{{.Interval}} years"

[IntervalYears]
description = "Used after interval yearly"
few = "years"
many = "years"
one = "year"
other = "years"
two = "years"

[Last]
description = "The last for Nth return int with suffix"
other = "last"

[OnAllWeeks]
description = "Used before all weeks list"
other = "on"

[OnThe]
description = "Used before list bymonthday, byweekday, byyearday and someWeeks"
other = "on the"

[OnWeekday]
description = "Used before by weekday list"
other = "on"

[OnWeekdays]
description = "Used if on every work weekdays on week"
other = "on weekdays"

[Or]
description = "Used for final delimiter in list"
other = "or"

[Second]
description = "Suffix for 2, 22"
other = "nd"

[ThOther]
description = "Suffix for other numbers"
other = "th"

[TheAllWeeks]
description = "Used between all weeks list and bymonthday"
other = "the"

[Third]
description = "Suffix for 3, 23"
other = "rd"

[TimeCount]
few = "for {{.Count}} times"
many = "for {{.Count}} times"
one = "for {{.Count}} time"
other = "for {{.Count}} times"
two = "for {{.Count}} times"

[Week]
description = "Used after interval count"
other = "week"
Loading

0 comments on commit 6baeb7d

Please sign in to comment.