Ver código fonte

Update logic

joeybloggs 9 anos atrás
pai
commit
df047ce272
5 arquivos alterados com 329 adições e 123 exclusões
  1. 99 23
      calendar.go
  2. 11 13
      cmd/plurals/generate_plurals.go
  3. 80 49
      cmd/resources/generate_resources.go
  4. 80 21
      translator.go
  5. 59 17
      ut.go

+ 99 - 23
calendar.go

@@ -87,65 +87,141 @@ type datetimePatternComponent struct {
 }
 }
 
 
 // FmtDateFull formats the time with the current locales full date format
 // FmtDateFull formats the time with the current locales full date format
-func (c Calendar) FmtDateFull(t time.Time) (string, error) {
-	return c.Format(t, c.Formats.Date.Full)
+func (c Calendar) FmtDateFull(t time.Time) string {
+	s, _ := c.Format(t, c.Formats.Date.Full)
+	return s
 }
 }
 
 
 // FmtDateLong formats the time with the current locales long date format
 // FmtDateLong formats the time with the current locales long date format
-func (c Calendar) FmtDateLong(t time.Time) (string, error) {
-	return c.Format(t, c.Formats.Date.Long)
+func (c Calendar) FmtDateLong(t time.Time) string {
+	s, _ := c.Format(t, c.Formats.Date.Long)
+	return s
 }
 }
 
 
 // FmtDateMedium formats the time with the current locales medium date format
 // FmtDateMedium formats the time with the current locales medium date format
-func (c Calendar) FmtDateMedium(t time.Time) (string, error) {
-	return c.Format(t, c.Formats.Date.Medium)
+func (c Calendar) FmtDateMedium(t time.Time) string {
+	s, _ := c.Format(t, c.Formats.Date.Medium)
+	return s
 }
 }
 
 
 // FmtDateShort formats the time with the current locales short date format
 // FmtDateShort formats the time with the current locales short date format
-func (c Calendar) FmtDateShort(t time.Time) (string, error) {
-	return c.Format(t, c.Formats.Date.Short)
+func (c Calendar) FmtDateShort(t time.Time) string {
+	s, _ := c.Format(t, c.Formats.Date.Short)
+	return s
 }
 }
 
 
 // FmtTimeFull formats the time with the current locales full time format
 // FmtTimeFull formats the time with the current locales full time format
-func (c Calendar) FmtTimeFull(t time.Time) (string, error) {
-	return c.Format(t, c.Formats.Time.Full)
+func (c Calendar) FmtTimeFull(t time.Time) string {
+	s, _ := c.Format(t, c.Formats.Time.Full)
+	return s
 }
 }
 
 
 // FmtTimeLong formats the time with the current locales long time format
 // FmtTimeLong formats the time with the current locales long time format
-func (c Calendar) FmtTimeLong(t time.Time) (string, error) {
-	return c.Format(t, c.Formats.Time.Long)
+func (c Calendar) FmtTimeLong(t time.Time) string {
+	s, _ := c.Format(t, c.Formats.Time.Long)
+	return s
 }
 }
 
 
 // FmtTimeMedium formats the time with the current locales medium time format
 // FmtTimeMedium formats the time with the current locales medium time format
-func (c Calendar) FmtTimeMedium(t time.Time) (string, error) {
-	return c.Format(t, c.Formats.Time.Medium)
+func (c Calendar) FmtTimeMedium(t time.Time) string {
+	s, _ := c.Format(t, c.Formats.Time.Medium)
+	return s
 }
 }
 
 
 // FmtTimeShort formats the time with the current locales short time format
 // FmtTimeShort formats the time with the current locales short time format
-func (c Calendar) FmtTimeShort(t time.Time) (string, error) {
-	return c.Format(t, c.Formats.Time.Short)
+func (c Calendar) FmtTimeShort(t time.Time) string {
+	s, _ := c.Format(t, c.Formats.Time.Short)
+	return s
 }
 }
 
 
 // FmtDateTimeFull formats the time with the current locales full data & time format
 // FmtDateTimeFull formats the time with the current locales full data & time format
-func (c Calendar) FmtDateTimeFull(t time.Time) (string, error) {
+func (c Calendar) FmtDateTimeFull(t time.Time) string {
 	pattern := getDateTimePattern(c.Formats.DateTime.Full, c.Formats.Date.Full, c.Formats.Time.Full)
 	pattern := getDateTimePattern(c.Formats.DateTime.Full, c.Formats.Date.Full, c.Formats.Time.Full)
-	return c.Format(t, pattern)
+	s, _ := c.Format(t, pattern)
+	return s
 }
 }
 
 
 // FmtDateTimeLong formats the time with the current locales long data & time format
 // FmtDateTimeLong formats the time with the current locales long data & time format
-func (c Calendar) FmtDateTimeLong(t time.Time) (string, error) {
+func (c Calendar) FmtDateTimeLong(t time.Time) string {
 	pattern := getDateTimePattern(c.Formats.DateTime.Long, c.Formats.Date.Long, c.Formats.Time.Long)
 	pattern := getDateTimePattern(c.Formats.DateTime.Long, c.Formats.Date.Long, c.Formats.Time.Long)
-	return c.Format(t, pattern)
+	s, _ := c.Format(t, pattern)
+	return s
 }
 }
 
 
 // FmtDateTimeMedium formats the time with the current locales medium data & time format
 // FmtDateTimeMedium formats the time with the current locales medium data & time format
-func (c Calendar) FmtDateTimeMedium(t time.Time) (string, error) {
+func (c Calendar) FmtDateTimeMedium(t time.Time) string {
 	pattern := getDateTimePattern(c.Formats.DateTime.Medium, c.Formats.Date.Medium, c.Formats.Time.Medium)
 	pattern := getDateTimePattern(c.Formats.DateTime.Medium, c.Formats.Date.Medium, c.Formats.Time.Medium)
-	return c.Format(t, pattern)
+	s, _ := c.Format(t, pattern)
+	return s
 }
 }
 
 
 // FmtDateTimeShort formats the time with the current locales short data & time format
 // FmtDateTimeShort formats the time with the current locales short data & time format
-func (c Calendar) FmtDateTimeShort(t time.Time) (string, error) {
+func (c Calendar) FmtDateTimeShort(t time.Time) string {
+	pattern := getDateTimePattern(c.Formats.DateTime.Short, c.Formats.Date.Short, c.Formats.Time.Short)
+	s, _ := c.Format(t, pattern)
+	return s
+}
+
+// FmtDateFullSafe formats the time with the current locales full date format
+func (c Calendar) FmtDateFullSafe(t time.Time) (string, error) {
+	return c.Format(t, c.Formats.Date.Full)
+}
+
+// FmtDateLongSafe formats the time with the current locales long date format
+func (c Calendar) FmtDateLongSafe(t time.Time) (string, error) {
+	return c.Format(t, c.Formats.Date.Long)
+}
+
+// FmtDateMediumSafe formats the time with the current locales medium date format
+func (c Calendar) FmtDateMediumSafe(t time.Time) (string, error) {
+	return c.Format(t, c.Formats.Date.Medium)
+}
+
+// FmtDateShortSafe formats the time with the current locales short date format
+func (c Calendar) FmtDateShortSafe(t time.Time) (string, error) {
+	return c.Format(t, c.Formats.Date.Short)
+}
+
+// FmtTimeFullSafe formats the time with the current locales full time format
+func (c Calendar) FmtTimeFullSafe(t time.Time) (string, error) {
+	return c.Format(t, c.Formats.Time.Full)
+}
+
+// FmtTimeLongSafe formats the time with the current locales long time format
+func (c Calendar) FmtTimeLongSafe(t time.Time) (string, error) {
+	return c.Format(t, c.Formats.Time.Long)
+}
+
+// FmtTimeMediumSafe formats the time with the current locales medium time format
+func (c Calendar) FmtTimeMediumSafe(t time.Time) (string, error) {
+	return c.Format(t, c.Formats.Time.Medium)
+}
+
+// FmtTimeShortSafe formats the time with the current locales short time format
+func (c Calendar) FmtTimeShortSafe(t time.Time) (string, error) {
+	return c.Format(t, c.Formats.Time.Short)
+}
+
+// FmtDateTimeFullSafe formats the time with the current locales full data & time format
+func (c Calendar) FmtDateTimeFullSafe(t time.Time) (string, error) {
+	pattern := getDateTimePattern(c.Formats.DateTime.Full, c.Formats.Date.Full, c.Formats.Time.Full)
+	return c.Format(t, pattern)
+}
+
+// FmtDateTimeLongSafe formats the time with the current locales long data & time format
+func (c Calendar) FmtDateTimeLongSafe(t time.Time) (string, error) {
+	pattern := getDateTimePattern(c.Formats.DateTime.Long, c.Formats.Date.Long, c.Formats.Time.Long)
+	return c.Format(t, pattern)
+}
+
+// FmtDateTimeMediumSafe formats the time with the current locales medium data & time format
+func (c Calendar) FmtDateTimeMediumSafe(t time.Time) (string, error) {
+	pattern := getDateTimePattern(c.Formats.DateTime.Medium, c.Formats.Date.Medium, c.Formats.Time.Medium)
+	return c.Format(t, pattern)
+}
+
+// FmtDateTimeShortSafe formats the time with the current locales short data & time format
+func (c Calendar) FmtDateTimeShortSafe(t time.Time) (string, error) {
 	pattern := getDateTimePattern(c.Formats.DateTime.Short, c.Formats.Date.Short, c.Formats.Time.Short)
 	pattern := getDateTimePattern(c.Formats.DateTime.Short, c.Formats.Date.Short, c.Formats.Time.Short)
 	return c.Format(t, pattern)
 	return c.Format(t, pattern)
 }
 }

+ 11 - 13
cmd/plurals/generate_plurals.go

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

+ 80 - 49
cmd/resources/generate_resources.go

@@ -285,11 +285,19 @@ func main() {
 	for locale, number := range numbers {
 	for locale, number := range numbers {
 		go func(locale string, number i18n.Number) {
 		go func(locale string, number i18n.Number) {
 
 
-			localeNoUnderscore := strings.ToLower(strings.Replace(locale, "_", "", -1))
+			// localeNoUnderscore := strings.ToLower(strings.Replace(locale, "_", "", -1))
 			defer func() { wg.Done() }()
 			defer func() { wg.Done() }()
-			path := "../../zzz_generated_" + locale
+			path := "../../resources/locales/" + locale
 
 
-			mainFile, err := os.Create(path + ".go")
+			if _, err := os.Stat(path); err != nil {
+				if err = os.MkdirAll(path, 0777); err != nil {
+					panic(err)
+				}
+			}
+
+			path += "/"
+
+			mainFile, err := os.Create(path + "main.go")
 			if err != nil {
 			if err != nil {
 				panic(err)
 				panic(err)
 			}
 			}
@@ -297,59 +305,89 @@ func main() {
 
 
 			calendar := calendars[locale]
 			calendar := calendars[locale]
 
 
-			mainCodes, err := format.Source([]byte(fmt.Sprintf(`package ut
-
-			// new returns a new instance of the locale
-			func new%s() *Locale {
-				return &Locale {
-					Locale: %q,
-					Number: Number {
-						Symbols: new%sSymbols(),
-						Formats: new%sFormats(),
-						Currencies: new%sCurrencies(),
-					},
-					Calendar: new%sCalendar(),
-					PluralRule: %spluralRule,
-				}
+			mainCodes, err := format.Source([]byte(fmt.Sprintf(`package %s
+			import "github.com/go-playground/universal-translator"
+
+			var locale = &ut.Locale{
+				Locale: %q,
+				Number: ut.Number{
+					Symbols: symbols,
+					Formats: formats,
+					Currencies: currencies,
+				},
+				Calendar: calendar,
+				PluralRule:   pluralRule,
 			}
 			}
 
 
-			func new%sSymbols() Symbols {
-				return %# v
+			func init() {
+				ut.RegisterLocale(locale)
 			}
 			}
+		`, locale, locale)))
 
 
-			func new%sFormats() NumberFormats {
-				return %# v
+			if err != nil {
+				panic(err)
 			}
 			}
 
 
-			func new%sCurrencies() CurrencyFormatValue {
-				return %# v
+			fmt.Fprintf(mainFile, "%s", mainCodes)
+
+			numberFile, err := os.Create(path + "number.go")
+			if err != nil {
+				panic(err)
+			}
+			defer numberFile.Close()
+
+			numberCodes, err := format.Source([]byte(fmt.Sprintf(`package %s
+			import "github.com/go-playground/universal-translator"
+			var (
+				symbols = %#v
+				formats = %#v
+			)
+		`, locale, number.Symbols, number.Formats)))
+			if err != nil {
+				panic(err)
 			}
 			}
+			fmt.Fprintf(numberFile, "%s", numberCodes)
 
 
-			func new%sCalendar() Calendar {
-				return %#v
+			currencyFile, err := os.Create(path + "currency.go")
+			if err != nil {
+				panic(err)
 			}
 			}
+			defer currencyFile.Close()
 
 
-		`, localeNoUnderscore, locale, localeNoUnderscore, localeNoUnderscore, localeNoUnderscore, localeNoUnderscore, localeNoUnderscore,
-				localeNoUnderscore, number.Symbols, localeNoUnderscore, number.Formats, localeNoUnderscore,
-				number.Currencies, localeNoUnderscore, calendar)))
+			currencyCodes, err := format.Source([]byte(fmt.Sprintf(`package %s
+			import "github.com/go-playground/universal-translator"
+			var currencies = %# v
+		`, locale, number.Currencies)))
+			if err != nil {
+				panic(err)
+			}
+			fmt.Fprintf(currencyFile, "%s", currencyCodes)
 
 
+			calendarFile, err := os.Create(path + "calendar.go")
 			if err != nil {
 			if err != nil {
 				panic(err)
 				panic(err)
 			}
 			}
+			defer calendarFile.Close()
 
 
-			mainCodes = []byte(strings.Replace(string(mainCodes), "ut.", "", -1))
-			fmt.Fprintf(mainFile, "%s", mainCodes)
+			calendarCodes, err := format.Source([]byte(fmt.Sprintf(`package %s
+			import "github.com/go-playground/universal-translator"
+			var calendar = %#v
+		`, locale, calendar)))
+			if err != nil {
+				panic(err)
+			}
+			fmt.Fprintf(calendarFile, "%s", calendarCodes)
 
 
-			pluralFile, err := os.Create(path + "_plural.go")
+			pluralFile, err := os.Create(path + "plural.go")
 			if err != nil {
 			if err != nil {
 				panic(err)
 				panic(err)
 			}
 			}
 			defer pluralFile.Close()
 			defer pluralFile.Close()
 
 
-			pluralCodes, err := format.Source([]byte(fmt.Sprintf(`package ut
+			pluralCodes, err := format.Source([]byte(fmt.Sprintf(`package %s
 
 
-			var %spluralRule = "1"
-		`, localeNoUnderscore)))
+			var pluralRule = "1"
+		`, locale)))
 			if err != nil {
 			if err != nil {
 				panic(err)
 				panic(err)
 			}
 			}
@@ -360,28 +398,21 @@ func main() {
 	wg.Wait()
 	wg.Wait()
 
 
 	// TODO: make switch with all of the locales + function to return new!
 	// TODO: make switch with all of the locales + function to return new!
-	localesFile, err := os.Create("../../zzz_generated_locales.go")
+	localesFile, err := os.Create("../../resources/locales/all.go")
 	if err != nil {
 	if err != nil {
 		panic(err)
 		panic(err)
 	}
 	}
 	defer localesFile.Close()
 	defer localesFile.Close()
 
 
-	tmpl, err := template.New("").Parse(`package ut
-
-		import "errors"
+	tmpl, err := template.New("").Parse(`package locales
 
 
-		// GetLocale returns the Locale instance associated with
-		// the provided locale string, or returns an error when not found.
-		func GetLocale(locale string) (*Locale, error) {
-			switch locale {
-			{{range $locale, $val := .}}case "{{$locale}}":
-				return new{{$val}}(), nil
-			{{end}}
-			default:
-				return nil, errors.New("Unknown locale '" + locale + "'")
-			}
-		}
+		// Imports for all locales
+		import (
+			{{range $locale, $_ := .}}// Locale "{{$locale}}" import that automatically registers itslef with the universal-translator package
+			_ "github.com/go-playground/universal-translator/resources/locales/{{$locale}}"
+		{{end}})
 	`)
 	`)
+
 	if err != nil {
 	if err != nil {
 		panic(err)
 		panic(err)
 	}
 	}

+ 80 - 21
translator.go

@@ -23,19 +23,14 @@ type Translator struct {
 	groups       groups
 	groups       groups
 }
 }
 
 
-func newTranslator(locale string) (*Translator, error) {
-
-	loc, err := GetLocale(locale)
-	if err != nil {
-		return nil, err
-	}
+func newTranslator(loc *Locale) *Translator {
 
 
 	return &Translator{
 	return &Translator{
 		locale:       loc,
 		locale:       loc,
 		ruler:        pluralRules[loc.PluralRule],
 		ruler:        pluralRules[loc.PluralRule],
 		translations: make(translations),
 		translations: make(translations),
 		groups:       make(groups),
 		groups:       make(groups),
-	}, nil
+	}
 }
 }
 
 
 // Add registers a new translation to the Translator using the
 // Add registers a new translation to the Translator using the
@@ -50,6 +45,10 @@ func (t *Translator) Add(rule PluralRule, group string, key string, text string)
 		text: text,
 		text: text,
 	}
 	}
 
 
+	if _, ok := t.translations[rule]; !ok {
+		t.translations[rule] = make(map[string]*translation)
+	}
+
 	if _, ok := t.translations[rule][key]; ok {
 	if _, ok := t.translations[rule][key]; ok {
 		panic(fmt.Sprintf("Translation with key '%s' already exists", key))
 		panic(fmt.Sprintf("Translation with key '%s' already exists", key))
 	}
 	}
@@ -70,13 +69,13 @@ func (t *Translator) pluralRule(count NumberValue) (rule PluralRule) {
 // T translates the text associated with the given key with the
 // T translates the text associated with the given key with the
 // arguments passed in
 // arguments passed in
 func (t *Translator) T(key string, a ...interface{}) string {
 func (t *Translator) T(key string, a ...interface{}) string {
-	return t.P(key, 0, a...)
+	return t.P(key, 1, a...)
 }
 }
 
 
 // TSafe translates the text associated with the given key with the
 // TSafe translates the text associated with the given key with the
 // arguments passed in, if the key or rule cannot be found it returns an error
 // arguments passed in, if the key or rule cannot be found it returns an error
 func (t *Translator) TSafe(key string, a ...interface{}) (string, error) {
 func (t *Translator) TSafe(key string, a ...interface{}) (string, error) {
-	return t.PSafe(key, 0, a...)
+	return t.PSafe(key, 1, a...)
 }
 }
 
 
 // P translates the plural text associated with the given key with the
 // P translates the plural text associated with the given key with the
@@ -106,63 +105,123 @@ func (t *Translator) PSafe(key string, count interface{}, a ...interface{}) (str
 	return fmt.Sprintf(trans.text, a...), nil
 	return fmt.Sprintf(trans.text, a...), nil
 }
 }
 
 
+// FmtDateFullSafe formats the time with the current locales full date format
+func (t *Translator) FmtDateFullSafe(dt time.Time) (string, error) {
+	return t.locale.Calendar.FmtDateFullSafe(dt)
+}
+
+// FmtDateLongSafe formats the time with the current locales long date format
+func (t *Translator) FmtDateLongSafe(dt time.Time) (string, error) {
+	return t.locale.Calendar.FmtDateLongSafe(dt)
+}
+
+// FmtDateMediumSafe formats the time with the current locales medium date format
+func (t *Translator) FmtDateMediumSafe(dt time.Time) (string, error) {
+	return t.locale.Calendar.FmtDateMediumSafe(dt)
+}
+
+// FmtDateShortSafe formats the time with the current locales short date format
+func (t *Translator) FmtDateShortSafe(dt time.Time) (string, error) {
+	return t.locale.Calendar.FmtDateShortSafe(dt)
+}
+
+// FmtDateTimeFullSafe formats the time with the current locales full data & time format
+func (t *Translator) FmtDateTimeFullSafe(dt time.Time) (string, error) {
+	return t.locale.Calendar.FmtDateTimeFullSafe(dt)
+}
+
+// FmtDateTimeLongSafe formats the time with the current locales long data & time format
+func (t *Translator) FmtDateTimeLongSafe(dt time.Time) (string, error) {
+	return t.locale.Calendar.FmtDateTimeLongSafe(dt)
+}
+
+// FmtDateTimeMediumSafe formats the time with the current locales medium data & time format
+func (t *Translator) FmtDateTimeMediumSafe(dt time.Time) (string, error) {
+	return t.locale.Calendar.FmtDateTimeMediumSafe(dt)
+}
+
+// FmtDateTimeShortSafe formats the time with the current locales short data & time format
+func (t *Translator) FmtDateTimeShortSafe(dt time.Time) (string, error) {
+	return t.locale.Calendar.FmtDateTimeShortSafe(dt)
+}
+
+// FmtTimeFullSafe formats the time with the current locales full time format
+func (t *Translator) FmtTimeFullSafe(dt time.Time) (string, error) {
+	return t.locale.Calendar.FmtTimeFullSafe(dt)
+}
+
+// FmtTimeLongSafe formats the time with the current locales long time format
+func (t *Translator) FmtTimeLongSafe(dt time.Time) (string, error) {
+	return t.locale.Calendar.FmtTimeLongSafe(dt)
+}
+
+// FmtTimeMediumSafe formats the time with the current locales medium time format
+func (t *Translator) FmtTimeMediumSafe(dt time.Time) (string, error) {
+	return t.locale.Calendar.FmtTimeMediumSafe(dt)
+}
+
+// FmtTimeShortSafe formats the time with the current locales short time format
+func (t *Translator) FmtTimeShortSafe(dt time.Time) (string, error) {
+	return t.locale.Calendar.FmtTimeShortSafe(dt)
+}
+
 // FmtDateFull formats the time with the current locales full date format
 // FmtDateFull formats the time with the current locales full date format
-func (t *Translator) FmtDateFull(dt time.Time) (string, error) {
+func (t *Translator) FmtDateFull(dt time.Time) string {
 	return t.locale.Calendar.FmtDateFull(dt)
 	return t.locale.Calendar.FmtDateFull(dt)
 }
 }
 
 
 // FmtDateLong formats the time with the current locales long date format
 // FmtDateLong formats the time with the current locales long date format
-func (t *Translator) FmtDateLong(dt time.Time) (string, error) {
+func (t *Translator) FmtDateLong(dt time.Time) string {
 	return t.locale.Calendar.FmtDateLong(dt)
 	return t.locale.Calendar.FmtDateLong(dt)
 }
 }
 
 
 // FmtDateMedium formats the time with the current locales medium date format
 // FmtDateMedium formats the time with the current locales medium date format
-func (t *Translator) FmtDateMedium(dt time.Time) (string, error) {
+func (t *Translator) FmtDateMedium(dt time.Time) string {
 	return t.locale.Calendar.FmtDateMedium(dt)
 	return t.locale.Calendar.FmtDateMedium(dt)
 }
 }
 
 
 // FmtDateShort formats the time with the current locales short date format
 // FmtDateShort formats the time with the current locales short date format
-func (t *Translator) FmtDateShort(dt time.Time) (string, error) {
+func (t *Translator) FmtDateShort(dt time.Time) string {
 	return t.locale.Calendar.FmtDateShort(dt)
 	return t.locale.Calendar.FmtDateShort(dt)
 }
 }
 
 
 // FmtDateTimeFull formats the time with the current locales full data & time format
 // FmtDateTimeFull formats the time with the current locales full data & time format
-func (t *Translator) FmtDateTimeFull(dt time.Time) (string, error) {
+func (t *Translator) FmtDateTimeFull(dt time.Time) string {
 	return t.locale.Calendar.FmtDateTimeFull(dt)
 	return t.locale.Calendar.FmtDateTimeFull(dt)
 }
 }
 
 
 // FmtDateTimeLong formats the time with the current locales long data & time format
 // FmtDateTimeLong formats the time with the current locales long data & time format
-func (t *Translator) FmtDateTimeLong(dt time.Time) (string, error) {
+func (t *Translator) FmtDateTimeLong(dt time.Time) string {
 	return t.locale.Calendar.FmtDateTimeLong(dt)
 	return t.locale.Calendar.FmtDateTimeLong(dt)
 }
 }
 
 
 // FmtDateTimeMedium formats the time with the current locales medium data & time format
 // FmtDateTimeMedium formats the time with the current locales medium data & time format
-func (t *Translator) FmtDateTimeMedium(dt time.Time) (string, error) {
+func (t *Translator) FmtDateTimeMedium(dt time.Time) string {
 	return t.locale.Calendar.FmtDateTimeMedium(dt)
 	return t.locale.Calendar.FmtDateTimeMedium(dt)
 }
 }
 
 
 // FmtDateTimeShort formats the time with the current locales short data & time format
 // FmtDateTimeShort formats the time with the current locales short data & time format
-func (t *Translator) FmtDateTimeShort(dt time.Time) (string, error) {
+func (t *Translator) FmtDateTimeShort(dt time.Time) string {
 	return t.locale.Calendar.FmtDateTimeShort(dt)
 	return t.locale.Calendar.FmtDateTimeShort(dt)
 }
 }
 
 
 // FmtTimeFull formats the time with the current locales full time format
 // FmtTimeFull formats the time with the current locales full time format
-func (t *Translator) FmtTimeFull(dt time.Time) (string, error) {
+func (t *Translator) FmtTimeFull(dt time.Time) string {
 	return t.locale.Calendar.FmtTimeFull(dt)
 	return t.locale.Calendar.FmtTimeFull(dt)
 }
 }
 
 
 // FmtTimeLong formats the time with the current locales long time format
 // FmtTimeLong formats the time with the current locales long time format
-func (t *Translator) FmtTimeLong(dt time.Time) (string, error) {
+func (t *Translator) FmtTimeLong(dt time.Time) string {
 	return t.locale.Calendar.FmtTimeLong(dt)
 	return t.locale.Calendar.FmtTimeLong(dt)
 }
 }
 
 
 // FmtTimeMedium formats the time with the current locales medium time format
 // FmtTimeMedium formats the time with the current locales medium time format
-func (t *Translator) FmtTimeMedium(dt time.Time) (string, error) {
+func (t *Translator) FmtTimeMedium(dt time.Time) string {
 	return t.locale.Calendar.FmtTimeMedium(dt)
 	return t.locale.Calendar.FmtTimeMedium(dt)
 }
 }
 
 
 // FmtTimeShort formats the time with the current locales short time format
 // FmtTimeShort formats the time with the current locales short time format
-func (t *Translator) FmtTimeShort(dt time.Time) (string, error) {
+func (t *Translator) FmtTimeShort(dt time.Time) string {
 	return t.locale.Calendar.FmtTimeShort(dt)
 	return t.locale.Calendar.FmtTimeShort(dt)
 }
 }
 
 

+ 59 - 17
ut.go

@@ -1,41 +1,83 @@
 package ut
 package ut
 
 
+import (
+	"errors"
+	"sync"
+)
+
+var utrans *UniversalTranslator
+var once sync.Once
+
+type translators map[string]*Translator
+
 // UniversalTranslator holds all locale Translator instances
 // UniversalTranslator holds all locale Translator instances
 type UniversalTranslator struct {
 type UniversalTranslator struct {
 	translators map[string]*Translator
 	translators map[string]*Translator
 	fallback    *Translator
 	fallback    *Translator
 }
 }
 
 
-// New creates a new UniversalTranslator instance.
-func New() *UniversalTranslator {
-	return &UniversalTranslator{}
+// newUniversalTranslator creates a new UniversalTranslator instance.
+func newUniversalTranslator() *UniversalTranslator {
+	return &UniversalTranslator{
+		translators: make(translators),
+	}
 }
 }
 
 
 // SetFallback registers the fallback Translator instance when no matching Translator
 // SetFallback registers the fallback Translator instance when no matching Translator
 // can be found via a given locale
 // can be found via a given locale
-func (ut *UniversalTranslator) SetFallback(translator *Translator) {
-	ut.fallback = translator
+func SetFallback(translator *Translator) {
+	utrans.fallback = translator
+}
+
+// GetFallback return the universal translators fallback translation
+func GetFallback() *Translator {
+	return utrans.fallback
+}
+
+// FindTranslator trys to find a Translator based on an array of locales
+// and returns the first one it can find, otherwise returns the
+// fallback translator
+func FindTranslator(locales []string) *Translator {
+
+	for _, locale := range locales {
+
+		if t, ok := utrans.translators[locale]; ok {
+			return t
+		}
+	}
+
+	return utrans.fallback
 }
 }
 
 
-// LoadTranslator instantiates, if not already exists, the specified translator
-// for the given locale
-func (ut *UniversalTranslator) LoadTranslator(locale string) (*Translator, error) {
+// GetTranslator returns the specified translator for the given locale,
+// or error if not found
+func GetTranslator(locale string) (*Translator, error) {
 
 
-	if t, ok := ut.translators[locale]; ok {
+	if t, ok := utrans.translators[locale]; ok {
 		return t, nil
 		return t, nil
 	}
 	}
 
 
-	t, err := newTranslator(locale)
-	if err != nil {
-		return nil, err
+	return nil, errors.New("Translator with locale '" + locale + "' counld not be found.")
+}
+
+// RegisterLocale registers the a locale with ut
+// initializes singleton + sets initial fallback language
+func RegisterLocale(loc *Locale) {
+	once.Do(func() {
+		utrans = newUniversalTranslator()
+	})
+
+	if _, ok := utrans.translators[loc.Locale]; ok {
+		return
 	}
 	}
 
 
-	ut.translators[locale] = t
+	t := newTranslator(loc)
 
 
-	// just to ensure it get's set to something
-	if ut.fallback == nil {
-		ut.fallback = t
+	if utrans.fallback == nil {
+		utrans.fallback = t
 	}
 	}
 
 
-	return t, nil
+	utrans.translators[loc.Locale] = t
+
+	// have do once initialize singleton ut instance.
 }
 }