@@ -11,8 +11,9 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
var re = regexp.MustCompile(`%\(([a-zA-Z0-9_]+)\)[.0-9]*[xsvTtbcdoqXxUeEfFgGp]`)
|
var re = regexp.MustCompile(`%\(([a-zA-Z0-9_]+)\)[.0-9]*[svTtbcdoqXxUeEfFgGp]`)
|
||||||
|
|
||||||
|
// SimplifiedLocale simplified locale like " en_US"/"de_DE "/en_US.UTF-8/zh_CN/zh_TW/el_GR@euro/... to en_US, de_DE, zh_CN, el_GR...
|
||||||
func SimplifiedLocale(lang string) string {
|
func SimplifiedLocale(lang string) string {
|
||||||
// en_US/en_US.UTF-8/zh_CN/zh_TW/el_GR@euro/...
|
// en_US/en_US.UTF-8/zh_CN/zh_TW/el_GR@euro/...
|
||||||
if idx := strings.Index(lang, ":"); idx != -1 {
|
if idx := strings.Index(lang, ":"); idx != -1 {
|
||||||
@@ -27,7 +28,7 @@ func SimplifiedLocale(lang string) string {
|
|||||||
return strings.TrimSpace(lang)
|
return strings.TrimSpace(lang)
|
||||||
}
|
}
|
||||||
|
|
||||||
// printf applies text formatting only when needed to parse variables.
|
// Printf applies text formatting only when needed to parse variables.
|
||||||
func Printf(str string, vars ...interface{}) string {
|
func Printf(str string, vars ...interface{}) string {
|
||||||
if len(vars) > 0 {
|
if len(vars) > 0 {
|
||||||
return fmt.Sprintf(str, vars...)
|
return fmt.Sprintf(str, vars...)
|
||||||
@@ -36,8 +37,8 @@ func Printf(str string, vars ...interface{}) string {
|
|||||||
return str
|
return str
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// NPrintf support named format
|
// NPrintf support named format
|
||||||
|
// NPrintf("%(name)s is Type %(type)s", map[string]interface{}{"name": "Gotext", "type": "struct"})
|
||||||
func NPrintf(format string, params map[string]interface{}) {
|
func NPrintf(format string, params map[string]interface{}) {
|
||||||
f, p := parseSprintf(format, params)
|
f, p := parseSprintf(format, params)
|
||||||
fmt.Printf(f, p...)
|
fmt.Printf(f, p...)
|
||||||
|
|||||||
@@ -152,13 +152,13 @@ func (l *Locale) SetDomain(dom string) {
|
|||||||
// Get uses a domain "default" to return the corresponding Translation of a given string.
|
// Get uses a domain "default" to return the corresponding Translation of a given string.
|
||||||
// Supports optional parameters (vars... interface{}) to be inserted on the formatted string using the fmt.Printf syntax.
|
// Supports optional parameters (vars... interface{}) to be inserted on the formatted string using the fmt.Printf syntax.
|
||||||
func (l *Locale) Get(str string, vars ...interface{}) string {
|
func (l *Locale) Get(str string, vars ...interface{}) string {
|
||||||
return l.GetD(l.defaultDomain, str, vars...)
|
return l.GetD(l.GetDomain(), str, vars...)
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetN retrieves the (N)th plural form of Translation for the given string in the "default" domain.
|
// 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.
|
// 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 {
|
func (l *Locale) GetN(str, plural string, n int, vars ...interface{}) string {
|
||||||
return l.GetND(l.defaultDomain, str, plural, n, vars...)
|
return l.GetND(l.GetDomain(), str, plural, n, vars...)
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetD returns the corresponding Translation in the given domain for the given string.
|
// GetD returns the corresponding Translation in the given domain for the given string.
|
||||||
@@ -189,13 +189,13 @@ func (l *Locale) GetND(dom, str, plural string, n int, vars ...interface{}) stri
|
|||||||
// GetC uses a domain "default" to return the corresponding Translation of the given string in the given context.
|
// GetC uses a domain "default" to return the corresponding Translation of the given string in the given context.
|
||||||
// Supports optional parameters (vars... interface{}) to be inserted on the formatted string using the fmt.Printf syntax.
|
// Supports optional parameters (vars... interface{}) to be inserted on the formatted string using the fmt.Printf syntax.
|
||||||
func (l *Locale) GetC(str, ctx string, vars ...interface{}) string {
|
func (l *Locale) GetC(str, ctx string, vars ...interface{}) string {
|
||||||
return l.GetDC(l.defaultDomain, str, ctx, vars...)
|
return l.GetDC(l.GetDomain(), str, ctx, vars...)
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetNC retrieves the (N)th plural form of Translation for the given string in the given context in the "default" domain.
|
// 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.
|
// 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 {
|
func (l *Locale) GetNC(str, plural string, n int, ctx string, vars ...interface{}) string {
|
||||||
return l.GetNDC(l.defaultDomain, str, plural, n, ctx, vars...)
|
return l.GetNDC(l.GetDomain(), str, plural, n, ctx, vars...)
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetDC returns the corresponding Translation in the given domain for the given string in the given context.
|
// GetDC returns the corresponding Translation in the given domain for the given string in the given context.
|
||||||
|
|||||||
38
mo.go
38
mo.go
@@ -20,12 +20,13 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
MoMagicLittleEndian = 0x950412de
|
MoMagicLittleEndian = 0x950412de // MoMagicLittleEndian encoding
|
||||||
MoMagicBigEndian = 0xde120495
|
MoMagicBigEndian = 0xde120495 // MoMagicBigEndian encoding
|
||||||
|
|
||||||
EotSeparator = "\x04" // msgctxt and msgid separator
|
EotSeparator = "\x04" // msgctxt and msgid separator
|
||||||
NulSeparator = "\x00" // msgid and msgstr separator
|
NulSeparator = "\x00" // msgid and msgstr separator
|
||||||
)
|
)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Mo parses the content of any MO file and provides all the Translation functions needed.
|
Mo parses the content of any MO file and provides all the Translation functions needed.
|
||||||
It's the base object used by all package methods.
|
It's the base object used by all package methods.
|
||||||
@@ -77,6 +78,7 @@ type Mo struct {
|
|||||||
ctxBuffer string
|
ctxBuffer string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NewMoTranslator creates a new Mo object with the Translator interface
|
||||||
func NewMoTranslator() Translator {
|
func NewMoTranslator() Translator {
|
||||||
return new(Mo)
|
return new(Mo)
|
||||||
}
|
}
|
||||||
@@ -135,8 +137,8 @@ func (mo *Mo) Parse(buf []byte) {
|
|||||||
var header struct {
|
var header struct {
|
||||||
MajorVersion uint16
|
MajorVersion uint16
|
||||||
MinorVersion uint16
|
MinorVersion uint16
|
||||||
MsgIdCount uint32
|
MsgIDCount uint32
|
||||||
MsgIdOffset uint32
|
MsgIDOffset uint32
|
||||||
MsgStrOffset uint32
|
MsgStrOffset uint32
|
||||||
HashSize uint32
|
HashSize uint32
|
||||||
HashOffset uint32
|
HashOffset uint32
|
||||||
@@ -154,30 +156,30 @@ func (mo *Mo) Parse(buf []byte) {
|
|||||||
// return fmt.Errorf("gettext: %v", "invalid version number")
|
// return fmt.Errorf("gettext: %v", "invalid version number")
|
||||||
}
|
}
|
||||||
|
|
||||||
msgIdStart := make([]uint32, header.MsgIdCount)
|
msgIDStart := make([]uint32, header.MsgIDCount)
|
||||||
msgIdLen := make([]uint32, header.MsgIdCount)
|
msgIDLen := make([]uint32, header.MsgIDCount)
|
||||||
if _, err := r.Seek(int64(header.MsgIdOffset), 0); err != nil {
|
if _, err := r.Seek(int64(header.MsgIDOffset), 0); err != nil {
|
||||||
return
|
return
|
||||||
// return fmt.Errorf("gettext: %v", err)
|
// return fmt.Errorf("gettext: %v", err)
|
||||||
}
|
}
|
||||||
for i := 0; i < int(header.MsgIdCount); i++ {
|
for i := 0; i < int(header.MsgIDCount); i++ {
|
||||||
if err := binary.Read(r, bo, &msgIdLen[i]); err != nil {
|
if err := binary.Read(r, bo, &msgIDLen[i]); err != nil {
|
||||||
return
|
return
|
||||||
// return fmt.Errorf("gettext: %v", err)
|
// return fmt.Errorf("gettext: %v", err)
|
||||||
}
|
}
|
||||||
if err := binary.Read(r, bo, &msgIdStart[i]); err != nil {
|
if err := binary.Read(r, bo, &msgIDStart[i]); err != nil {
|
||||||
return
|
return
|
||||||
// return fmt.Errorf("gettext: %v", err)
|
// return fmt.Errorf("gettext: %v", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
msgStrStart := make([]int32, header.MsgIdCount)
|
msgStrStart := make([]int32, header.MsgIDCount)
|
||||||
msgStrLen := make([]int32, header.MsgIdCount)
|
msgStrLen := make([]int32, header.MsgIDCount)
|
||||||
if _, err := r.Seek(int64(header.MsgStrOffset), 0); err != nil {
|
if _, err := r.Seek(int64(header.MsgStrOffset), 0); err != nil {
|
||||||
return
|
return
|
||||||
// return fmt.Errorf("gettext: %v", err)
|
// return fmt.Errorf("gettext: %v", err)
|
||||||
}
|
}
|
||||||
for i := 0; i < int(header.MsgIdCount); i++ {
|
for i := 0; i < int(header.MsgIDCount); i++ {
|
||||||
if err := binary.Read(r, bo, &msgStrLen[i]); err != nil {
|
if err := binary.Read(r, bo, &msgStrLen[i]); err != nil {
|
||||||
return
|
return
|
||||||
// return fmt.Errorf("gettext: %v", err)
|
// return fmt.Errorf("gettext: %v", err)
|
||||||
@@ -188,12 +190,12 @@ func (mo *Mo) Parse(buf []byte) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for i := 0; i < int(header.MsgIdCount); i++ {
|
for i := 0; i < int(header.MsgIDCount); i++ {
|
||||||
if _, err := r.Seek(int64(msgIdStart[i]), 0); err != nil {
|
if _, err := r.Seek(int64(msgIDStart[i]), 0); err != nil {
|
||||||
return
|
return
|
||||||
// return fmt.Errorf("gettext: %v", err)
|
// return fmt.Errorf("gettext: %v", err)
|
||||||
}
|
}
|
||||||
msgIdData := make([]byte, msgIdLen[i])
|
msgIdData := make([]byte, msgIDLen[i])
|
||||||
if _, err := r.Read(msgIdData); err != nil {
|
if _, err := r.Read(msgIdData); err != nil {
|
||||||
return
|
return
|
||||||
// return fmt.Errorf("gettext: %v", err)
|
// return fmt.Errorf("gettext: %v", err)
|
||||||
@@ -333,9 +335,9 @@ func (mo *Mo) pluralForm(n int) int {
|
|||||||
/* Use the Germanic plural rule. */
|
/* Use the Germanic plural rule. */
|
||||||
if n == 1 {
|
if n == 1 {
|
||||||
return 0
|
return 0
|
||||||
} else {
|
|
||||||
return 1
|
|
||||||
}
|
}
|
||||||
|
return 1
|
||||||
|
|
||||||
}
|
}
|
||||||
return mo.pluralforms.Eval(uint32(n))
|
return mo.pluralforms.Eval(uint32(n))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,10 @@
|
|||||||
* Copyright (c) 2018 DeineAgentur UG https://www.deineagentur.com. All rights reserved.
|
* Copyright (c) 2018 DeineAgentur UG https://www.deineagentur.com. All rights reserved.
|
||||||
* Licensed under the MIT License. See LICENSE file in the project root for full license information.
|
* Licensed under the MIT License. See LICENSE file in the project root for full license information.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
Package plurals is the pluralform compiler to get the correct translation id of the plural string
|
||||||
|
*/
|
||||||
package plurals
|
package plurals
|
||||||
|
|
||||||
import (
|
import (
|
||||||
@@ -19,10 +23,6 @@ type match struct {
|
|||||||
|
|
||||||
var pat = regexp.MustCompile(`(\?|:|\|\||&&|==|!=|>=|>|<=|<|%|\d+|n)`)
|
var pat = regexp.MustCompile(`(\?|:|\|\||&&|==|!=|>=|>|<=|<|%|\d+|n)`)
|
||||||
|
|
||||||
type exprToken interface {
|
|
||||||
compile(tokens []string) (expr Expression, err error)
|
|
||||||
}
|
|
||||||
|
|
||||||
type testToken interface {
|
type testToken interface {
|
||||||
compile(tokens []string) (test test, err error)
|
compile(tokens []string) (test test, err error)
|
||||||
}
|
}
|
||||||
@@ -47,18 +47,18 @@ func (ternaryStruct) compile(tokens []string) (expr Expression, err error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return expr, err
|
return expr, err
|
||||||
}
|
}
|
||||||
true_action, err := compileExpression(strings.Join(actions.Left, ""))
|
trueAction, err := compileExpression(strings.Join(actions.Left, ""))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return expr, err
|
return expr, err
|
||||||
}
|
}
|
||||||
false_action, err := compileExpression(strings.Join(actions.Right, ""))
|
falseAction, err := compileExpression(strings.Join(actions.Right, ""))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return expr, nil
|
return expr, nil
|
||||||
}
|
}
|
||||||
return ternary{
|
return ternary{
|
||||||
test: test,
|
test: test,
|
||||||
trueExpr: true_action,
|
trueExpr: trueAction,
|
||||||
falseExpr: false_action,
|
falseExpr: falseAction,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -180,9 +180,9 @@ func compileEquality(tokens []string, sep string, builder cmpTestBuilder) (test
|
|||||||
return builder(i, true), nil
|
return builder(i, true), nil
|
||||||
} else if contains(split.Left, "n") && contains(split.Left, "%") {
|
} else if contains(split.Left, "n") && contains(split.Left, "%") {
|
||||||
return subPipe(split.Left, split.Right, builder, false)
|
return subPipe(split.Left, split.Right, builder, false)
|
||||||
} else {
|
|
||||||
return test, errors.New("equality test must have 'n' as one of the two tests")
|
|
||||||
}
|
}
|
||||||
|
return test, errors.New("equality test must have 'n' as one of the two tests")
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var eqToken eqStruct
|
var eqToken eqStruct
|
||||||
@@ -405,9 +405,8 @@ func compileExpression(s string) (expr Expression, err error) {
|
|||||||
tokens := tokenize(s)
|
tokens := tokenize(s)
|
||||||
if contains(tokens, "?") {
|
if contains(tokens, "?") {
|
||||||
return ternaryToken.compile(tokens)
|
return ternaryToken.compile(tokens)
|
||||||
} else {
|
|
||||||
return constToken.compile(tokens)
|
|
||||||
}
|
}
|
||||||
|
return constToken.compile(tokens)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Compiles a test (comparison)
|
// Compiles a test (comparison)
|
||||||
@@ -425,7 +424,6 @@ func parseUint32(s string) (ui uint32, err error) {
|
|||||||
i, err := strconv.ParseUint(s, 10, 32)
|
i, err := strconv.ParseUint(s, 10, 32)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return ui, err
|
return ui, err
|
||||||
} else {
|
}
|
||||||
return uint32(i), nil
|
return uint32(i), nil
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|||||||
@@ -35,10 +35,9 @@ func (t ternary) Eval(n uint32) int {
|
|||||||
return -1
|
return -1
|
||||||
}
|
}
|
||||||
return t.trueExpr.Eval(n)
|
return t.trueExpr.Eval(n)
|
||||||
} else {
|
}
|
||||||
if t.falseExpr == nil {
|
if t.falseExpr == nil {
|
||||||
return -1
|
return -1
|
||||||
}
|
}
|
||||||
return t.falseExpr.Eval(n)
|
return t.falseExpr.Eval(n)
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|||||||
@@ -42,9 +42,8 @@ type lt struct {
|
|||||||
func (e lt) test(n uint32) bool {
|
func (e lt) test(n uint32) bool {
|
||||||
if e.flipped {
|
if e.flipped {
|
||||||
return e.value < n
|
return e.value < n
|
||||||
} else {
|
|
||||||
return n < e.value
|
|
||||||
}
|
}
|
||||||
|
return n < e.value
|
||||||
}
|
}
|
||||||
|
|
||||||
type gte struct {
|
type gte struct {
|
||||||
@@ -55,9 +54,8 @@ type gte struct {
|
|||||||
func (e gte) test(n uint32) bool {
|
func (e gte) test(n uint32) bool {
|
||||||
if e.flipped {
|
if e.flipped {
|
||||||
return e.value >= n
|
return e.value >= n
|
||||||
} else {
|
|
||||||
return n >= e.value
|
|
||||||
}
|
}
|
||||||
|
return n >= e.value
|
||||||
}
|
}
|
||||||
|
|
||||||
type lte struct {
|
type lte struct {
|
||||||
@@ -68,9 +66,8 @@ type lte struct {
|
|||||||
func (e lte) test(n uint32) bool {
|
func (e lte) test(n uint32) bool {
|
||||||
if e.flipped {
|
if e.flipped {
|
||||||
return e.value <= n
|
return e.value <= n
|
||||||
} else {
|
|
||||||
return n <= e.value
|
|
||||||
}
|
}
|
||||||
|
return n <= e.value
|
||||||
}
|
}
|
||||||
|
|
||||||
type and struct {
|
type and struct {
|
||||||
@@ -81,9 +78,8 @@ type and struct {
|
|||||||
func (e and) test(n uint32) bool {
|
func (e and) test(n uint32) bool {
|
||||||
if !e.left.test(n) {
|
if !e.left.test(n) {
|
||||||
return false
|
return false
|
||||||
} else {
|
|
||||||
return e.right.test(n)
|
|
||||||
}
|
}
|
||||||
|
return e.right.test(n)
|
||||||
}
|
}
|
||||||
|
|
||||||
type or struct {
|
type or struct {
|
||||||
@@ -94,9 +90,8 @@ type or struct {
|
|||||||
func (e or) test(n uint32) bool {
|
func (e or) test(n uint32) bool {
|
||||||
if e.left.test(n) {
|
if e.left.test(n) {
|
||||||
return true
|
return true
|
||||||
} else {
|
|
||||||
return e.right.test(n)
|
|
||||||
}
|
}
|
||||||
|
return e.right.test(n)
|
||||||
}
|
}
|
||||||
|
|
||||||
type pipe struct {
|
type pipe struct {
|
||||||
|
|||||||
1
po.go
1
po.go
@@ -78,6 +78,7 @@ const (
|
|||||||
msgStr
|
msgStr
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// NewPoTranslator creates a new Po object with the Translator interface
|
||||||
func NewPoTranslator() Translator {
|
func NewPoTranslator() Translator {
|
||||||
return new(Po)
|
return new(Po)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,12 +5,14 @@
|
|||||||
|
|
||||||
package gotext
|
package gotext
|
||||||
|
|
||||||
|
// Translation is the struct for the Translations parsed via Po or Mo files and all coming parsers
|
||||||
type Translation struct {
|
type Translation struct {
|
||||||
ID string
|
ID string
|
||||||
PluralID string
|
PluralID string
|
||||||
Trs map[int]string
|
Trs map[int]string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NewTranslation returns the Translation object and initialized it.
|
||||||
func NewTranslation() *Translation {
|
func NewTranslation() *Translation {
|
||||||
tr := new(Translation)
|
tr := new(Translation)
|
||||||
tr.Trs = make(map[int]string)
|
tr.Trs = make(map[int]string)
|
||||||
@@ -18,6 +20,7 @@ func NewTranslation() *Translation {
|
|||||||
return tr
|
return tr
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Get returns the string of the translation
|
||||||
func (t *Translation) Get() string {
|
func (t *Translation) Get() string {
|
||||||
// Look for Translation index 0
|
// Look for Translation index 0
|
||||||
if _, ok := t.Trs[0]; ok {
|
if _, ok := t.Trs[0]; ok {
|
||||||
@@ -30,6 +33,7 @@ func (t *Translation) Get() string {
|
|||||||
return t.ID
|
return t.ID
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Get returns the string of the plural translation
|
||||||
func (t *Translation) GetN(n int) string {
|
func (t *Translation) GetN(n int) string {
|
||||||
// Look for Translation index
|
// Look for Translation index
|
||||||
if _, ok := t.Trs[n]; ok {
|
if _, ok := t.Trs[n]; ok {
|
||||||
|
|||||||
Reference in New Issue
Block a user