Skip to content

Commit

Permalink
Plural-Forms formula support. Headers parsing. Multiline strings supp…
Browse files Browse the repository at this point in the history
…ort.
  • Loading branch information
leonelquinteros committed Jul 15, 2016
1 parent af70714 commit 74daa24
Show file tree
Hide file tree
Showing 8 changed files with 424 additions and 54 deletions.
9 changes: 9 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
language: go
script: go test -v -race ./...

go:
- 1.3
- 1.4
- 1.5
- 1.6
- tip
26 changes: 18 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,17 @@

[GNU gettext utilities](https://www.gnu.org/software/gettext) for Go.

Version: [v1.0.1](https://github.com/leonelquinteros/gotext/releases/tag/v1.0.1)
Version: [v1.1.0](https://github.com/leonelquinteros/gotext/releases/tag/v1.1.0)


# Features

- Implements GNU gettext support in native Go.
- Complete support for [PO files](https://www.gnu.org/software/gettext/manual/html_node/PO-Files.html).
- Support for [pluralization rules](https://www.gnu.org/software/gettext/manual/html_node/Plural-forms.html).
- Support for [message context](https://www.gnu.org/software/gettext/manual/html_node/Contexts.html).
- Support for variables inside translation strings using Go's [fmt package syntax](https://golang.org/pkg/fmt/).
- Complete support for [PO files](https://www.gnu.org/software/gettext/manual/html_node/PO-Files.html) including:
- Support for multiline strings and headers.
- Support for variables inside translation strings using Go's [fmt syntax](https://golang.org/pkg/fmt/).
- Support for [pluralization rules](https://www.gnu.org/software/gettext/manual/html_node/Translating-plural-forms.html).
- Support for [message contexts](https://www.gnu.org/software/gettext/manual/html_node/Contexts.html).
- Thread-safe: This package is safe for concurrent use across multiple goroutines.
- It works with UTF-8 encoding as it's the default for Go language.
- Unit tests available.
Expand Down Expand Up @@ -256,13 +257,23 @@ msgstr "This one sets the var: %s"
## Use plural forms of translations

PO format supports defining one or more plural forms for the same translation.
Relying on the PO file headers, a Plural-Forms formula can be set on the translation file
as defined in (https://www.gnu.org/savannah-checkouts/gnu/gettext/manual/html_node/Plural-forms.html)

Plural formulas are parsed and evaluated using [Anko](https://github.com/mattn/anko)

```go
import "github.com/leonelquinteros/gotext"

func main() {
// Set PO content
str := `
msgid ""
msgstr ""
# Header below
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
msgid "Translate this"
msgstr "Translated text"
Expand All @@ -273,15 +284,14 @@ msgid "One with var: %s"
msgid_plural "Several with vars: %s"
msgstr[0] "This one is the singular: %s"
msgstr[1] "This one is the plural: %s"
msgstr[2] "And this is the second plural form: %s"
`

// Create Po object
po := new(Po)
po.Parse(str)

println(po.GetN("One with var: %s", "Several with vars: %s", 2, v))
// "And this is the second plural form: Variable"
println(po.GetN("One with var: %s", "Several with vars: %s", 54, v))
// "This one is the plural: Variable"
}
```

Expand Down
14 changes: 6 additions & 8 deletions gotext.go
Original file line number Diff line number Diff line change
Expand Up @@ -100,8 +100,7 @@ func Get(str string, vars ...interface{}) string {
return GetD(domain, str, vars...)
}

// GetN retrieves the (N)th plural form translation for the given string in the "default" domain.
// If n == 0, usually the singular form of the string is returned as defined in the PO file.
// GetN retrieves the (N)th plural form of translation for the given string in the "default" domain.
// Supports optional parameters (vars... interface{}) to be inserted on the formatted string using the fmt.Printf syntax.
func GetN(str, plural string, n int, vars ...interface{}) string {
return GetND("default", str, plural, n, vars...)
Expand All @@ -110,10 +109,10 @@ func GetN(str, plural string, n int, vars ...interface{}) string {
// GetD returns the corresponding translation in the given domain for a given string.
// Supports optional parameters (vars... interface{}) to be inserted on the formatted string using the fmt.Printf syntax.
func GetD(dom, str string, vars ...interface{}) string {
return GetND(dom, str, str, 0, vars...)
return GetND(dom, str, str, 1, vars...)
}

// GetND retrieves the (N)th plural form translation in the given domain for a given string.
// GetND retrieves the (N)th plural form of translation in the given domain for a given string.
// Supports optional parameters (vars... interface{}) to be inserted on the formatted string using the fmt.Printf syntax.
func GetND(dom, str, plural string, n int, vars ...interface{}) string {
// Try to load default package Locale storage
Expand All @@ -129,8 +128,7 @@ func GetC(str, ctx string, vars ...interface{}) string {
return GetDC(domain, str, ctx, vars...)
}

// GetNC retrieves the (N)th plural form translation for the given string in the given context in the "default" domain.
// If n == 0, usually the singular form of the string is returned as defined in the PO file.
// GetNC retrieves the (N)th plural form of translation for the given string in the given context in the "default" domain.
// Supports optional parameters (vars... interface{}) to be inserted on the formatted string using the fmt.Printf syntax.
func GetNC(str, plural string, n int, ctx string, vars ...interface{}) string {
return GetNDC("default", str, plural, n, ctx, vars...)
Expand All @@ -139,10 +137,10 @@ func GetNC(str, plural string, n int, ctx string, vars ...interface{}) string {
// GetDC returns the corresponding translation in the given domain for the given string in the given context.
// Supports optional parameters (vars... interface{}) to be inserted on the formatted string using the fmt.Printf syntax.
func GetDC(dom, str, ctx string, vars ...interface{}) string {
return GetNDC(dom, str, str, 0, ctx, vars...)
return GetNDC(dom, str, str, 1, ctx, vars...)
}

// GetNDC retrieves the (N)th plural form translation in the given domain for a given string.
// GetNDC retrieves the (N)th plural form of translation in the given domain for a given string.
// Supports optional parameters (vars... interface{}) to be inserted on the formatted string using the fmt.Printf syntax.
func GetNDC(dom, str, plural string, n int, ctx string, vars ...interface{}) string {
// Try to load default package Locale storage
Expand Down
18 changes: 14 additions & 4 deletions gotext_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,17 @@ func TestGettersSetters(t *testing.T) {

func TestPackageFunctions(t *testing.T) {
// Set PO content
str := `# Some comment
str := `
msgid ""
msgstr ""
# Initial comment
# Headers below
"Language: en\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
# Some comment
msgid "My text"
msgstr "Translated text"
Expand Down Expand Up @@ -109,8 +119,8 @@ msgstr "More translation"

// Test plural
tr = GetN("One with var: %s", "Several with vars: %s", 2, v)
if tr != "And this is the second plural form: Variable" {
t.Errorf("Expected 'And this is the second plural form: Variable' but got '%s'", tr)
if tr != "This one is the plural: Variable" {
t.Errorf("Expected 'This one is the plural: Variable' but got '%s'", tr)
}

// Test context translations
Expand All @@ -125,7 +135,7 @@ msgstr "More translation"
t.Errorf("Expected 'This one is the singular in a Ctx context: Variable' but got '%s'", tr)
}

tr = GetNC("One with var: %s", "Several with vars: %s", 1, "Ctx", v)
tr = GetNC("One with var: %s", "Several with vars: %s", 19, "Ctx", v)
if tr != "This one is the plural in a Ctx context: Variable" {
t.Errorf("Expected 'This one is the plural in a Ctx context: Variable' but got '%s'", tr)
}
Expand Down
16 changes: 6 additions & 10 deletions locale.go
Original file line number Diff line number Diff line change
Expand Up @@ -107,8 +107,7 @@ func (l *Locale) Get(str string, vars ...interface{}) string {
return l.GetD("default", str, vars...)
}

// GetN retrieves the (N)th plural form translation for the given string in the "default" domain.
// If n == 0, usually the singular form of the string is returned as defined in the PO file.
// GetN retrieves the (N)th plural form of translation for the given string in the "default" domain.
// Supports optional parameters (vars... interface{}) to be inserted on the formatted string using the fmt.Printf syntax.
func (l *Locale) GetN(str, plural string, n int, vars ...interface{}) string {
return l.GetND("default", str, plural, n, vars...)
Expand All @@ -117,11 +116,10 @@ func (l *Locale) GetN(str, plural string, n int, vars ...interface{}) string {
// GetD returns the corresponding translation in the given domain for the given string.
// Supports optional parameters (vars... interface{}) to be inserted on the formatted string using the fmt.Printf syntax.
func (l *Locale) GetD(dom, str string, vars ...interface{}) string {
return l.GetND(dom, str, str, 0, vars...)
return l.GetND(dom, str, str, 1, vars...)
}

// GetND retrieves the (N)th plural form translation in the given domain for the given string.
// If n == 0, usually the singular form of the string is returned as defined in the PO file.
// GetND retrieves the (N)th plural form of translation in the given domain for the given string.
// Supports optional parameters (vars... interface{}) to be inserted on the formatted string using the fmt.Printf syntax.
func (l *Locale) GetND(dom, str, plural string, n int, vars ...interface{}) string {
// Sync read
Expand All @@ -146,8 +144,7 @@ func (l *Locale) GetC(str, ctx string, vars ...interface{}) string {
return l.GetDC("default", str, ctx, vars...)
}

// GetNC retrieves the (N)th plural form translation for the given string in the given context in the "default" domain.
// If n == 0, usually the singular form of the string is returned as defined in the PO file.
// GetNC retrieves the (N)th plural form of translation for the given string in the given context in the "default" domain.
// Supports optional parameters (vars... interface{}) to be inserted on the formatted string using the fmt.Printf syntax.
func (l *Locale) GetNC(str, plural string, n int, ctx string, vars ...interface{}) string {
return l.GetNDC("default", str, plural, n, ctx, vars...)
Expand All @@ -156,11 +153,10 @@ func (l *Locale) GetNC(str, plural string, n int, ctx string, vars ...interface{
// GetDC returns the corresponding translation in the given domain for the given string in the given context.
// Supports optional parameters (vars... interface{}) to be inserted on the formatted string using the fmt.Printf syntax.
func (l *Locale) GetDC(dom, str, ctx string, vars ...interface{}) string {
return l.GetNDC(dom, str, str, 0, ctx, vars...)
return l.GetNDC(dom, str, str, 1, ctx, vars...)
}

// GetNDC retrieves the (N)th plural form translation in the given domain for the given string in the given context.
// If n == 0, usually the singular form of the string is returned as defined in the PO file.
// GetNDC retrieves the (N)th plural form of translation in the given domain for the given string in the given context.
// Supports optional parameters (vars... interface{}) to be inserted on the formatted string using the fmt.Printf syntax.
func (l *Locale) GetNDC(dom, str, plural string, n int, ctx string, vars ...interface{}) string {
// Sync read
Expand Down
20 changes: 15 additions & 5 deletions locale_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,17 @@ import (

func TestLocale(t *testing.T) {
// Set PO content
str := `# Some comment
str := `
msgid ""
msgstr ""
# Initial comment
# Headers below
"Language: en\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
# Some comment
msgid "My text"
msgstr "Translated text"
Expand Down Expand Up @@ -91,9 +101,9 @@ msgstr "More translation"
}

// Test plural
tr = l.GetND("my_domain", "One with var: %s", "Several with vars: %s", 2, v)
if tr != "And this is the second plural form: Variable" {
t.Errorf("Expected 'And this is the second plural form: Variable' but got '%s'", tr)
tr = l.GetND("my_domain", "One with var: %s", "Several with vars: %s", 7, v)
if tr != "This one is the plural: Variable" {
t.Errorf("Expected 'This one is the plural: Variable' but got '%s'", tr)
}

// Test non-existent "deafult" domain responses
Expand Down Expand Up @@ -137,7 +147,7 @@ msgstr "More translation"
}

// Test plural
tr = l.GetNDC("my_domain", "One with var: %s", "Several with vars: %s", 1, "Ctx", v)
tr = l.GetNDC("my_domain", "One with var: %s", "Several with vars: %s", 3, "Ctx", v)
if tr != "This one is the plural in a Ctx context: Test" {
t.Errorf("Expected 'This one is the plural in a Ctx context: Test' but got '%s'", tr)
}
Expand Down
Loading

0 comments on commit 74daa24

Please sign in to comment.