浏览代码

Add Plural Translation logic

joeybloggs 9 年之前
父节点
当前提交
3db554ccdd
共有 5 个文件被更改,包括 89 次插入48 次删除
  1. 16 14
      cmd/plurals/generate_plurals.go
  2. 2 2
      cmd/resources/generate_resources.go
  3. 11 0
      plurals.go
  4. 60 28
      translator.go
  5. 0 4
      ut.go

+ 16 - 14
cmd/plurals/generate_plurals.go

@@ -13,10 +13,11 @@ import (
 )
 
 type pluralInfo struct {
-	path      string
-	locale    string
-	plural    string
-	outputDir string
+	path               string
+	locale             string
+	localeNoUnderscore string
+	plural             string
+	outputFile         string
 }
 
 // rules downloaded/copied from download github.com/vube/i18n/data/rules
@@ -56,10 +57,11 @@ func main() {
 		locale = strings.Replace(locale, "-", "_", -1)
 
 		plurals = append(plurals, pluralInfo{
-			path:      path,
-			locale:    locale,
-			plural:    plural,
-			outputDir: "../../resources/locales/" + locale,
+			path:               path,
+			locale:             locale,
+			localeNoUnderscore: strings.ToLower(strings.Replace(locale, "_", "", -1)),
+			plural:             plural,
+			outputFile:         "../../zzz_generated_" + locale + "_plural.go",
 		})
 
 		if plural == "" {
@@ -93,18 +95,18 @@ func main() {
 			fmt.Println("Found")
 		}
 
-		if _, err := os.Stat(p.outputDir); err != nil {
-			fmt.Println(p.outputDir, "doesn't exist")
+		if _, err := os.Stat(p.outputFile); err != nil {
+			fmt.Println(p.outputFile, "doesn't exist")
 			continue
 		}
-		file, err := os.Create(p.outputDir + "/plural.go")
+		file, err := os.Create(p.outputFile)
 		if err != nil {
 			panic(err)
 		}
-		rawcodes := fmt.Sprintf(`package %s
+		rawcodes := fmt.Sprintf(`package ut
 
-		const pluralRule = %q
-		`, p.locale, p.plural)
+		const %spluralRule = %q
+		`, p.localeNoUnderscore, p.plural)
 
 		var codes []byte
 		if codes, err = format.Source([]byte(rawcodes)); err != nil {

+ 2 - 2
cmd/resources/generate_resources.go

@@ -91,7 +91,7 @@ func main() {
 			}
 		}
 		numbers[loc] = number
-		locs[loc] = strings.Replace(loc, "_", "", -1)
+		locs[loc] = strings.ToLower(strings.Replace(loc, "_", "", -1))
 
 		if ldml.Dates != nil && ldml.Dates.Calendars != nil {
 			var calendar i18n.Calendar
@@ -266,7 +266,7 @@ func main() {
 	for locale, number := range numbers {
 		go func(locale string, number i18n.Number) {
 
-			localeNoUnderscore := strings.Replace(locale, "_", "", -1)
+			localeNoUnderscore := strings.ToLower(strings.Replace(locale, "_", "", -1))
 			defer func() { wg.Done() }()
 			path := "../../zzz_generated_" + locale
 

+ 11 - 0
plurals.go

@@ -6,6 +6,8 @@ import "math"
 type PluralRule string
 
 // PluralRule types
+
+// TODO: change this to integer for efficiency and use stringify lib to generate string values.
 const (
 	PluralRuleZero  PluralRule = "zero"  // zero
 	PluralRuleOne              = "one"   // singular
@@ -53,6 +55,15 @@ var pluralRules = map[string]PluralRuler{
 	"6B": PluralRulerFunc(pluralRule6B),
 }
 
+// func getPluralFunc(code string) PluralRulerFunc {
+// 	fn, ok := pluralRules[code]
+// 	if !ok {
+// 		return PluralRuleOther
+// 	}
+
+// 	return fn
+// }
+
 // func RegisterPluralRule(locale string, ruler PluralRuler) {
 // 	pluralRules[locale] = ruler
 // }

+ 60 - 28
translator.go

@@ -1,23 +1,39 @@
 package ut
 
-import "fmt"
+import (
+	"fmt"
+	"log"
+)
 
 type translation struct {
-	singular  string
-	plural    string
-	hasPlural bool
+	text string
 }
 
+// map[key]map[plural type othe, many, few, single]*translation
+type translations map[PluralRule]map[string]*translation
+type groups map[string][]*translation
+
 // Translator holds the locale translation instance
 type Translator struct {
-	locale       *Locale
-	pluralFunc   PluralRulerFunc
-	translations map[string]*translation
-	groups       map[string][]*translation
+	Locale       *Locale
+	ruler        PluralRuler
+	translations translations
+	groups       groups
 }
 
 func newTranslator(locale string) (*Translator, error) {
-	return nil, nil
+
+	loc, err := GetLocale(locale)
+	if err != nil {
+		return nil, err
+	}
+
+	return &Translator{
+		Locale:       loc,
+		ruler:        pluralRules[loc.PluralRule],
+		translations: make(translations),
+		groups:       make(groups),
+	}, nil
 }
 
 // Add registers a new translation to the Translator using the
@@ -26,19 +42,17 @@ func newTranslator(locale string) (*Translator, error) {
 // for the "homepage" group
 // plural is optional, can be blank, but allows adding a plural translation
 // at the same time as a singular
-func (t *Translator) Add(group string, key string, singular string, plural string) {
+func (t *Translator) Add(rule PluralRule, group string, key string, text string) {
 
 	trans := &translation{
-		singular:  singular,
-		plural:    plural,
-		hasPlural: plural != "",
+		text: text,
 	}
 
-	if _, ok := t.translations[key]; ok {
+	if _, ok := t.translations[rule][key]; ok {
 		panic(fmt.Sprintf("Translation with key '%s' already exists", key))
 	}
 
-	t.translations[key] = trans
+	t.translations[rule][key] = trans
 
 	if _, ok := t.groups[group]; !ok {
 		t.groups[group] = make([]*translation, 0)
@@ -48,22 +62,40 @@ func (t *Translator) Add(group string, key string, singular string, plural strin
 }
 
 func (t *Translator) pluralRule(count NumberValue) (rule PluralRule) {
-	// l, ok := GetLocale(locale)
-	// if !ok {
-	// 	return PluralRuleOther
-	// }
-
-	// ruler, ok := pluralRules[t.locale.PluralRule]
-
-	// if !ok {
-	// 	return PluralRuleOther
-	// }
-	//  ruler.FindRule(count)
-	return t.pluralFunc(count)
+	return t.ruler.FindRule(count)
 }
 
 // T translates the text associated with the given key with the
 // arguments passed in
-func (t *Translator) T(key string, a ...interface{}) {
+func (t *Translator) T(key string, a ...interface{}) string {
+	return t.P(key, 0, a...)
+}
+
+// P translates the plural text associated with the given key with the
+// arguments passed in
+func (t *Translator) P(key string, count interface{}, a ...interface{}) string {
 
+	rule := t.ruler.FindRule(count)
+
+	trans, ok := t.translations[rule][key]
+	if !ok {
+		s := "***** WARNING:***** Translation Key " + key + " Not Found"
+		log.Println(s)
+		return s
+	}
+
+	return fmt.Sprintf(trans.text, a...)
 }
+
+// // TSafe translates the text associated with the given key with the
+// // arguments passed in just like T() but doesn't panic, but instead
+// // returns an error
+// func (t *Translator) TSafe(key string, a ...interface{}) (string, error) {
+
+// 	trans, ok := t.translations[key]
+// 	if !ok {
+// 		return "", errors.New("*** Translation Key " + key + " Not Found")
+// 	}
+
+// 	return fmt.Sprintf(trans.singular, a...), nil
+// }

+ 0 - 4
ut.go

@@ -1,7 +1,5 @@
 package ut
 
-// _ "github.com/go-playground/universal-translator/resources/locales"
-
 // UniversalTranslator holds all locale Translator instances
 type UniversalTranslator struct {
 	translators map[string]*Translator
@@ -34,8 +32,6 @@ func (ut *UniversalTranslator) LoadTranslator(locale string) (*Translator, error
 
 	ut.translators[locale] = t
 
-	// TODO: MUST set pluralFunc on local here to save lookup each translation in the future
-
 	// just to ensure it get's set to something
 	if ut.fallback == nil {
 		ut.fallback = t