joeybloggs 9 anni fa
commit
cbb46634d9
100 ha cambiato i file con 4625 aggiunte e 0 eliminazioni
  1. 24 0
      .gitignore
  2. 178 0
      README.md
  3. 29 0
      af/af.go
  4. 29 0
      af_NA/af_NA.go
  5. 29 0
      af_ZA/af_ZA.go
  6. 25 0
      agq/agq.go
  7. 25 0
      agq_CM/agq_CM.go
  8. 29 0
      ak/ak.go
  9. 29 0
      ak_GH/ak_GH.go
  10. 29 0
      am/am.go
  11. 29 0
      am_ET/am_ET.go
  12. 29 0
      ar/ar.go
  13. 29 0
      ar_001/ar_001.go
  14. 29 0
      ar_AE/ar_AE.go
  15. 29 0
      ar_BH/ar_BH.go
  16. 29 0
      ar_DJ/ar_DJ.go
  17. 29 0
      ar_DZ/ar_DZ.go
  18. 29 0
      ar_EG/ar_EG.go
  19. 29 0
      ar_EH/ar_EH.go
  20. 29 0
      ar_ER/ar_ER.go
  21. 29 0
      ar_IL/ar_IL.go
  22. 29 0
      ar_IQ/ar_IQ.go
  23. 29 0
      ar_JO/ar_JO.go
  24. 29 0
      ar_KM/ar_KM.go
  25. 29 0
      ar_KW/ar_KW.go
  26. 29 0
      ar_LB/ar_LB.go
  27. 29 0
      ar_LY/ar_LY.go
  28. 29 0
      ar_MA/ar_MA.go
  29. 29 0
      ar_MR/ar_MR.go
  30. 29 0
      ar_OM/ar_OM.go
  31. 29 0
      ar_PS/ar_PS.go
  32. 29 0
      ar_QA/ar_QA.go
  33. 29 0
      ar_SA/ar_SA.go
  34. 29 0
      ar_SD/ar_SD.go
  35. 29 0
      ar_SO/ar_SO.go
  36. 29 0
      ar_SS/ar_SS.go
  37. 29 0
      ar_SY/ar_SY.go
  38. 29 0
      ar_TD/ar_TD.go
  39. 29 0
      ar_TN/ar_TN.go
  40. 29 0
      ar_YE/ar_YE.go
  41. 29 0
      as/as.go
  42. 29 0
      as_IN/as_IN.go
  43. 29 0
      asa/asa.go
  44. 29 0
      asa_TZ/asa_TZ.go
  45. 29 0
      ast/ast.go
  46. 29 0
      ast_ES/ast_ES.go
  47. 29 0
      az/az.go
  48. 29 0
      az_Cyrl/az_Cyrl.go
  49. 29 0
      az_Cyrl_AZ/az_Cyrl_AZ.go
  50. 29 0
      az_Latn/az_Latn.go
  51. 29 0
      az_Latn_AZ/az_Latn_AZ.go
  52. 25 0
      bas/bas.go
  53. 25 0
      bas_CM/bas_CM.go
  54. 29 0
      be/be.go
  55. 29 0
      be_BY/be_BY.go
  56. 29 0
      bem/bem.go
  57. 29 0
      bem_ZM/bem_ZM.go
  58. 29 0
      bez/bez.go
  59. 29 0
      bez_TZ/bez_TZ.go
  60. 29 0
      bg/bg.go
  61. 29 0
      bg_BG/bg_BG.go
  62. 25 0
      bm/bm.go
  63. 25 0
      bm_ML/bm_ML.go
  64. 29 0
      bn/bn.go
  65. 29 0
      bn_BD/bn_BD.go
  66. 29 0
      bn_IN/bn_IN.go
  67. 25 0
      bo/bo.go
  68. 25 0
      bo_CN/bo_CN.go
  69. 25 0
      bo_IN/bo_IN.go
  70. 29 0
      br/br.go
  71. 29 0
      br_FR/br_FR.go
  72. 29 0
      brx/brx.go
  73. 29 0
      brx_IN/brx_IN.go
  74. 29 0
      bs/bs.go
  75. 29 0
      bs_Cyrl/bs_Cyrl.go
  76. 29 0
      bs_Cyrl_BA/bs_Cyrl_BA.go
  77. 29 0
      bs_Latn/bs_Latn.go
  78. 29 0
      bs_Latn_BA/bs_Latn_BA.go
  79. 29 0
      ca/ca.go
  80. 29 0
      ca_AD/ca_AD.go
  81. 29 0
      ca_ES/ca_ES.go
  82. 29 0
      ca_ES_VALENCIA/ca_ES_VALENCIA.go
  83. 29 0
      ca_FR/ca_FR.go
  84. 29 0
      ca_IT/ca_IT.go
  85. 29 0
      ce/ce.go
  86. 29 0
      ce_RU/ce_RU.go
  87. 29 0
      cgg/cgg.go
  88. 29 0
      cgg_UG/cgg_UG.go
  89. 29 0
      chr/chr.go
  90. 29 0
      chr_US/chr_US.go
  91. 29 0
      ckb/ckb.go
  92. 29 0
      ckb_IQ/ckb_IQ.go
  93. 29 0
      ckb_IR/ckb_IR.go
  94. 3 0
      cmd/README.md
  95. 11 0
      cmd/currency.tmpl
  96. 4 0
      cmd/data/.gitignore
  97. 1694 0
      cmd/generate_resources.go
  98. 50 0
      cmd/translator.tmpl
  99. 29 0
      cs/cs.go
  100. 29 0
      cs_CZ/cs_CZ.go

+ 24 - 0
.gitignore

@@ -0,0 +1,24 @@
+# Compiled Object files, Static and Dynamic libs (Shared Objects)
+*.o
+*.a
+*.so
+
+# Folders
+_obj
+_test
+
+# Architecture specific extensions/prefixes
+*.[568vq]
+[568vq].out
+
+*.cgo1.go
+*.cgo2.c
+_cgo_defun.c
+_cgo_gotypes.go
+_cgo_export.*
+
+_testmain.go
+
+*.exe
+*.test
+*.prof

+ 178 - 0
README.md

@@ -0,0 +1,178 @@
+## universal-translator
+<img align="right" src="https://raw.githubusercontent.com/go-playground/universal-translator/master/logo.png">
+![Project status](https://img.shields.io/badge/version-0.9-green.svg)
+[![Build Status](https://semaphoreci.com/api/v1/joeybloggs/universal-translator/branches/master/badge.svg)](https://semaphoreci.com/joeybloggs/universal-translator)
+[![Coverage Status](https://coveralls.io/repos/github/go-playground/universal-translator/badge.svg?branch=master)](https://coveralls.io/github/go-playground/universal-translator?branch=master)
+[![Go Report Card](https://goreportcard.com/badge/github.com/go-playground/universal-translator)](https://goreportcard.com/report/github.com/go-playground/universal-translator)
+[![GoDoc](https://godoc.org/github.com/go-playground/universal-translator?status.svg)](https://godoc.org/github.com/go-playground/universal-translator)
+![License](https://img.shields.io/dub/l/vibe-d.svg)
+
+Universal Translator is an i18n Translator for Go/Golang using CLDR data + pluralization rules
+
+Why another i18n library?
+--------------------------
+I noticed that most libraries out there use static files for translations, which I'm not against just there is not option for coding it inline, 
+as well as having formats which do not handle all plural rules, or are overcomplicated. There is also very little in the way of helping the user
+know about what plural translations are needed for each language, no easy grouping to say, display all translations for a page...
+
+Features
+--------
+- [x] Rules added from [CLDR](http://cldr.unicode.org/index/downloads) data
+- [x] Use fmt.Sprintf() for translation string parsing
+- [x] Add Translations in code
+- [x] Prints the supported plural rules for a given translators locale using translator.PrintPluralRules()
+- [x] Plural Translations
+- [x] Date, Time & DateTime formatting
+- [x] Number, Whole Number formatting
+- [x] Currency both standard & accounting, formatting i.e. -$1,234.50 vs ($1,234.50)
+- [x] Handles BC and AD Dates. i.e. January 2, 300 BC
+- [ ] Support loading translations from files
+- [ ] Exporting translations to file, mainly for getting them professionally translated
+- [ ] Code Generation for translation files -> Go code.. i.e. after it has been professionally translated
+- [ ] Printing of grouped translations, i.e. all transations for the homepage
+- [ ] Tests for all languages, I need help with this one see below
+
+Full Language tests
+--------------------
+I could sure use your help adding tests for every language, it is a huge undertaking and I just don't have the free time to do it all at the moment;
+any help would be **greatly appreciated!!!!** please see [issue](https://github.com/go-playground/universal-translator/issues/1) for details.
+
+Installation
+-----------
+
+Use go get 
+
+```go
+go get github.com/go-playground/universal-translator
+``` 
+
+or to update
+
+```go
+go get -u github.com/go-playground/universal-translator
+``` 
+
+Usage
+-------
+```go
+package main
+
+import (
+	"fmt"
+	"time"
+
+	"github.com/go-playground/universal-translator"
+
+	// DONE this way to avoid huge compile times + memory for all languages, although it would
+	// be nice for all applications to support all languages... that's not reality
+	_ "github.com/go-playground/universal-translator/resources/locales"
+)
+
+func main() {
+	trans, _ := ut.GetTranslator("en")
+
+	trans.PrintPluralRules()
+	// OUTPUT:
+	// Translator locale 'en' supported rules:
+	//- PluralRuleOne
+	//- PluralRuleOther
+
+	// add a singular translation
+	trans.Add(ut.PluralRuleOne, "homepage", "welcome_msg", "Welcome to site %s")
+
+	// add singular + plural translation(s)
+	trans.Add(ut.PluralRuleOne, "homepage", "day_warning", "You only have %d day left in your trial")
+	trans.Add(ut.PluralRuleOther, "homepage", "day_warning", "You only have %d day's left in your trial")
+
+	// translate singular
+	translated := trans.T("welcome_msg", "Joey Bloggs")
+	fmt.Println(translated)
+	// OUTPUT: Welcome to site Joey Bloggs
+
+	// What if something went wrong? then translated would output "" (blank)
+	// How do I catch errors?
+	translated, err := trans.TSafe("welcome_m", "Joey Bloggs")
+	fmt.Println(translated)
+	// OUTPUT: ""
+	fmt.Println(err)
+	// OUTPUT: ***** WARNING:***** Translation Key 'welcome_m' Not Found
+
+	// NOTE: there is a Safe variant of most of the Translation and Formatting functions if you need them,
+	// for brevity will be using the non safe ones for the rest of this example
+
+	// The second parameter below, count, is needed as the final variable is a varadic and would not
+	// know which one to use in applying the plural rules.
+	// translate singular/plural
+	translated = trans.P("day_warning", 3, 3)
+	fmt.Println(translated)
+	// OUTPUT: You only have 3 day's left in your trial
+
+	translated = trans.P("day_warning", 1, 1)
+	fmt.Println(translated)
+	// OUTPUT: You only have 1 day left in your trial
+
+	// There are Full, Long, Medium and Short function for each of the following
+	dtString := "Jan 2, 2006 at 3:04:05pm"
+	dt, _ := time.Parse(dtString, dtString)
+
+	formatted := trans.FmtDateFull(dt)
+	fmt.Println(formatted)
+	// OUTPUT: Monday, January 2, 2006
+
+	formatted = trans.FmtDateShort(dt)
+	fmt.Println(formatted)
+	// OUTPUT: 1/2/06
+
+	formatted = trans.FmtTimeFull(dt)
+	fmt.Println(formatted)
+	// OUTPUT: 3:04:05 PM
+
+	formatted = trans.FmtDateTimeFull(dt)
+	fmt.Println(formatted)
+	// OUTPUT: Monday, January 2, 2006 at 3:04:05 PM
+
+	formatted = trans.FmtCurrency(ut.CurrencyStandard, "USD", 1234.50)
+	fmt.Println(formatted)
+	// OUTPUT: $1,234.50
+
+	formatted = trans.FmtCurrency(ut.CurrencyStandard, "USD", -1234.50)
+	fmt.Println(formatted)
+	// OUTPUT: -$1,234.50
+
+	formatted = trans.FmtCurrency(ut.CurrencyAccounting, "USD", -1234.50)
+	fmt.Println(formatted)
+	// OUTPUT: ($1,234.50)
+
+	formatted = trans.FmtCurrencyWhole(ut.CurrencyStandard, "USD", -1234.50)
+	fmt.Println(formatted)
+	// OUTPUT: -$1,234
+
+	formatted = trans.FmtNumber(1234.50)
+	fmt.Println(formatted)
+	// OUTPUT: 1,234.5
+
+	formatted = trans.FmtNumberWhole(1234.50)
+	fmt.Println(formatted)
+	// OUTPUT: 1,234
+}
+```
+
+Help With Tests
+---------------
+To anyone interesting in helping or contributing, I sure could use some help creating tests for each language.
+Please see issue [here](https://github.com/go-playground/universal-translator/issues/1) for details.
+
+Thanks to some help, the following languages have tests:
+
+- [x] en - English US
+- [x] th - Thai thanks to @prideloki
+
+Special Thanks
+--------------
+Special thanks to the following libraries that not only inspired, but that I borrowed a bunch of code from to create this.. ultimately there were many changes made and more to come, but without them would have taken forever to just get started.
+* [cldr](https://github.com/theplant/cldr) - A golang i18n tool using CLDR data
+* [i18n](https://github.com/vube/i18n) - golang package for basic i18n features, including message translation and number formatting
+
+Misc
+-------
+Library is not at 1.0 yet, but don't forsee any major API changes; will raise to 1.0 once I've used it completely in at least one project without issue.

File diff suppressed because it is too large
+ 29 - 0
af/af.go


File diff suppressed because it is too large
+ 29 - 0
af_NA/af_NA.go


File diff suppressed because it is too large
+ 29 - 0
af_ZA/af_ZA.go


File diff suppressed because it is too large
+ 25 - 0
agq/agq.go


File diff suppressed because it is too large
+ 25 - 0
agq_CM/agq_CM.go


File diff suppressed because it is too large
+ 29 - 0
ak/ak.go


File diff suppressed because it is too large
+ 29 - 0
ak_GH/ak_GH.go


File diff suppressed because it is too large
+ 29 - 0
am/am.go


File diff suppressed because it is too large
+ 29 - 0
am_ET/am_ET.go


File diff suppressed because it is too large
+ 29 - 0
ar/ar.go


File diff suppressed because it is too large
+ 29 - 0
ar_001/ar_001.go


File diff suppressed because it is too large
+ 29 - 0
ar_AE/ar_AE.go


File diff suppressed because it is too large
+ 29 - 0
ar_BH/ar_BH.go


File diff suppressed because it is too large
+ 29 - 0
ar_DJ/ar_DJ.go


File diff suppressed because it is too large
+ 29 - 0
ar_DZ/ar_DZ.go


File diff suppressed because it is too large
+ 29 - 0
ar_EG/ar_EG.go


File diff suppressed because it is too large
+ 29 - 0
ar_EH/ar_EH.go


File diff suppressed because it is too large
+ 29 - 0
ar_ER/ar_ER.go


File diff suppressed because it is too large
+ 29 - 0
ar_IL/ar_IL.go


File diff suppressed because it is too large
+ 29 - 0
ar_IQ/ar_IQ.go


File diff suppressed because it is too large
+ 29 - 0
ar_JO/ar_JO.go


File diff suppressed because it is too large
+ 29 - 0
ar_KM/ar_KM.go


File diff suppressed because it is too large
+ 29 - 0
ar_KW/ar_KW.go


File diff suppressed because it is too large
+ 29 - 0
ar_LB/ar_LB.go


File diff suppressed because it is too large
+ 29 - 0
ar_LY/ar_LY.go


File diff suppressed because it is too large
+ 29 - 0
ar_MA/ar_MA.go


File diff suppressed because it is too large
+ 29 - 0
ar_MR/ar_MR.go


File diff suppressed because it is too large
+ 29 - 0
ar_OM/ar_OM.go


File diff suppressed because it is too large
+ 29 - 0
ar_PS/ar_PS.go


File diff suppressed because it is too large
+ 29 - 0
ar_QA/ar_QA.go


File diff suppressed because it is too large
+ 29 - 0
ar_SA/ar_SA.go


File diff suppressed because it is too large
+ 29 - 0
ar_SD/ar_SD.go


File diff suppressed because it is too large
+ 29 - 0
ar_SO/ar_SO.go


File diff suppressed because it is too large
+ 29 - 0
ar_SS/ar_SS.go


File diff suppressed because it is too large
+ 29 - 0
ar_SY/ar_SY.go


File diff suppressed because it is too large
+ 29 - 0
ar_TD/ar_TD.go


File diff suppressed because it is too large
+ 29 - 0
ar_TN/ar_TN.go


File diff suppressed because it is too large
+ 29 - 0
ar_YE/ar_YE.go


File diff suppressed because it is too large
+ 29 - 0
as/as.go


File diff suppressed because it is too large
+ 29 - 0
as_IN/as_IN.go


File diff suppressed because it is too large
+ 29 - 0
asa/asa.go


File diff suppressed because it is too large
+ 29 - 0
asa_TZ/asa_TZ.go


File diff suppressed because it is too large
+ 29 - 0
ast/ast.go


File diff suppressed because it is too large
+ 29 - 0
ast_ES/ast_ES.go


File diff suppressed because it is too large
+ 29 - 0
az/az.go


File diff suppressed because it is too large
+ 29 - 0
az_Cyrl/az_Cyrl.go


File diff suppressed because it is too large
+ 29 - 0
az_Cyrl_AZ/az_Cyrl_AZ.go


File diff suppressed because it is too large
+ 29 - 0
az_Latn/az_Latn.go


File diff suppressed because it is too large
+ 29 - 0
az_Latn_AZ/az_Latn_AZ.go


File diff suppressed because it is too large
+ 25 - 0
bas/bas.go


File diff suppressed because it is too large
+ 25 - 0
bas_CM/bas_CM.go


File diff suppressed because it is too large
+ 29 - 0
be/be.go


File diff suppressed because it is too large
+ 29 - 0
be_BY/be_BY.go


File diff suppressed because it is too large
+ 29 - 0
bem/bem.go


File diff suppressed because it is too large
+ 29 - 0
bem_ZM/bem_ZM.go


File diff suppressed because it is too large
+ 29 - 0
bez/bez.go


File diff suppressed because it is too large
+ 29 - 0
bez_TZ/bez_TZ.go


File diff suppressed because it is too large
+ 29 - 0
bg/bg.go


File diff suppressed because it is too large
+ 29 - 0
bg_BG/bg_BG.go


File diff suppressed because it is too large
+ 25 - 0
bm/bm.go


File diff suppressed because it is too large
+ 25 - 0
bm_ML/bm_ML.go


File diff suppressed because it is too large
+ 29 - 0
bn/bn.go


File diff suppressed because it is too large
+ 29 - 0
bn_BD/bn_BD.go


File diff suppressed because it is too large
+ 29 - 0
bn_IN/bn_IN.go


File diff suppressed because it is too large
+ 25 - 0
bo/bo.go


File diff suppressed because it is too large
+ 25 - 0
bo_CN/bo_CN.go


File diff suppressed because it is too large
+ 25 - 0
bo_IN/bo_IN.go


File diff suppressed because it is too large
+ 29 - 0
br/br.go


File diff suppressed because it is too large
+ 29 - 0
br_FR/br_FR.go


File diff suppressed because it is too large
+ 29 - 0
brx/brx.go


File diff suppressed because it is too large
+ 29 - 0
brx_IN/brx_IN.go


File diff suppressed because it is too large
+ 29 - 0
bs/bs.go


File diff suppressed because it is too large
+ 29 - 0
bs_Cyrl/bs_Cyrl.go


File diff suppressed because it is too large
+ 29 - 0
bs_Cyrl_BA/bs_Cyrl_BA.go


File diff suppressed because it is too large
+ 29 - 0
bs_Latn/bs_Latn.go


File diff suppressed because it is too large
+ 29 - 0
bs_Latn_BA/bs_Latn_BA.go


File diff suppressed because it is too large
+ 29 - 0
ca/ca.go


File diff suppressed because it is too large
+ 29 - 0
ca_AD/ca_AD.go


File diff suppressed because it is too large
+ 29 - 0
ca_ES/ca_ES.go


File diff suppressed because it is too large
+ 29 - 0
ca_ES_VALENCIA/ca_ES_VALENCIA.go


File diff suppressed because it is too large
+ 29 - 0
ca_FR/ca_FR.go


File diff suppressed because it is too large
+ 29 - 0
ca_IT/ca_IT.go


File diff suppressed because it is too large
+ 29 - 0
ce/ce.go


File diff suppressed because it is too large
+ 29 - 0
ce_RU/ce_RU.go


File diff suppressed because it is too large
+ 29 - 0
cgg/cgg.go


File diff suppressed because it is too large
+ 29 - 0
cgg_UG/cgg_UG.go


File diff suppressed because it is too large
+ 29 - 0
chr/chr.go


File diff suppressed because it is too large
+ 29 - 0
chr_US/chr_US.go


File diff suppressed because it is too large
+ 29 - 0
ckb/ckb.go


File diff suppressed because it is too large
+ 29 - 0
ckb_IQ/ckb_IQ.go


File diff suppressed because it is too large
+ 29 - 0
ckb_IR/ckb_IR.go


+ 3 - 0
cmd/README.md

@@ -0,0 +1,3 @@
+Resources can be downloaded from [http://cldr.unicode.org/index/downloads](http://cldr.unicode.org/index/downloads)
+
+extract them under the data folder

+ 11 - 0
cmd/currency.tmpl

@@ -0,0 +1,11 @@
+{{ define "currencies" }}
+package currency
+
+// Currency is the type associated with the locales currency enum
+type Currency int
+
+// locale currencies
+const (
+	{{ . }}
+)
+{{ end }}

+ 4 - 0
cmd/data/.gitignore

@@ -0,0 +1,4 @@
+# Ignore everything in this directory
+*
+# Except this file
+!.gitignore

+ 1694 - 0
cmd/generate_resources.go

@@ -0,0 +1,1694 @@
+package main
+
+import (
+	"fmt"
+	"log"
+	"os"
+	"os/exec"
+	"sort"
+	"strings"
+
+	"github.com/go-playground/locales"
+
+	"golang.org/x/text/unicode/cldr"
+
+	"text/template"
+)
+
+const (
+	locDir      = "../%s"
+	locFilename = locDir + "/%s.go"
+)
+
+var (
+	prVarFuncs = map[string]string{
+		"n": "n := math.Abs(num)\n",
+		"i": "i := int64(n)\n",
+		// "v": "v := ...", // inherently available as argument
+		"w": "w := locales.W(n, v)\n",
+		"f": "f := locales.F(n, v)\n",
+		"t": "t := locales.T(n, v)\n",
+	}
+
+	translators         = make(map[string]*translator)
+	baseTranslators     = make(map[string]*translator)
+	globalCurrenciesMap = make(map[string]struct{}) // ["USD"] = "$" currency code, just all currencies for mapping to enum
+	globCurrencyIdxMap  = make(map[string]int)      // ["USD"] = 0
+	globalCurrencies    = make([]string, 0, 100)    // array of currency codes index maps to enum
+	tmpl                *template.Template
+)
+
+type translator struct {
+	Locale       string
+	BaseLocale   string
+	Plurals      string
+	CardinalFunc string
+	Decimal      string
+	Group        string
+	Minus        string
+	Percent      string
+	PerMille     string
+	Currencies   string
+}
+
+func main() {
+
+	var err error
+
+	// load template
+	tmpl, err = template.ParseGlob("*.tmpl")
+	if err != nil {
+		log.Fatal(err)
+	}
+
+	// load CLDR recourses
+	var decoder cldr.Decoder
+
+	cldr, err := decoder.DecodePath("data/core")
+	if err != nil {
+		panic(err)
+	}
+
+	preProcess(cldr)
+	postProcess(cldr)
+
+	var currencies string
+
+	for i, curr := range globalCurrencies {
+
+		if i == 0 {
+			currencies = curr + " Currency = iota\n"
+			continue
+		}
+
+		currencies += curr + "\n"
+	}
+
+	if err = os.MkdirAll(fmt.Sprintf(locDir, "currency"), 0777); err != nil {
+		log.Fatal(err)
+	}
+
+	filename := fmt.Sprintf(locFilename, "currency", "currency")
+
+	output, err := os.Create(filename)
+	if err != nil {
+		log.Fatal(err)
+	}
+	defer output.Close()
+
+	if err := tmpl.ExecuteTemplate(output, "currencies", currencies); err != nil {
+		log.Fatal(err)
+	}
+
+	output.Close()
+
+	// after file written run gofmt on file to ensure best formatting
+	cmd := exec.Command("goimports", "-w", filename)
+	if err = cmd.Run(); err != nil {
+		log.Panic(err)
+	}
+
+	for _, trans := range translators {
+
+		fmt.Println("Writing Data:", trans.Locale)
+
+		if err = os.MkdirAll(fmt.Sprintf(locDir, trans.Locale), 0777); err != nil {
+			log.Fatal(err)
+		}
+
+		filename = fmt.Sprintf(locFilename, trans.Locale, trans.Locale)
+
+		output, err := os.Create(filename)
+		if err != nil {
+			log.Fatal(err)
+		}
+		defer output.Close()
+
+		if err := tmpl.ExecuteTemplate(output, "translator", trans); err != nil {
+			log.Fatal(err)
+		}
+
+		output.Close()
+
+		// after file written run gofmt on file to ensure best formatting
+		cmd := exec.Command("goimports", "-w", filename)
+		if err = cmd.Run(); err != nil {
+			log.Panic(err)
+		}
+	}
+}
+
+func postProcess(cldr *cldr.CLDR) {
+
+	var base *translator
+	var found bool
+
+	for _, trans := range translators {
+
+		fmt.Println("Post Processing:", trans.Locale)
+
+		// plural rules
+		trans.CardinalFunc, trans.Plurals = parseCardinalPluralRuleFunc(cldr, trans.BaseLocale)
+
+		// ignore base locales
+		if trans.BaseLocale == trans.Locale {
+			found = false
+		} else {
+
+			base, found = baseTranslators[trans.BaseLocale]
+		}
+
+		// Numbers
+
+		if len(trans.Decimal) == 0 {
+
+			if found {
+				trans.Decimal = base.Decimal
+			}
+
+			if len(trans.Decimal) == 0 {
+				trans.Decimal = "[]byte{}"
+			}
+		}
+
+		if len(trans.Group) == 0 {
+
+			if found {
+				trans.Group = base.Group
+			}
+
+			if len(trans.Group) == 0 {
+				trans.Group = "[]byte{}"
+			}
+		}
+
+		if len(trans.Minus) == 0 {
+
+			if found {
+				trans.Minus = base.Minus
+			}
+
+			if len(trans.Minus) == 0 {
+				trans.Minus = "[]byte{}"
+			}
+		}
+
+		if len(trans.Percent) == 0 {
+
+			if found {
+				trans.Percent = base.Percent
+			}
+
+			if len(trans.Percent) == 0 {
+				trans.Percent = "[]byte{}"
+			}
+		}
+
+		if len(trans.PerMille) == 0 {
+
+			if found {
+				trans.PerMille = base.PerMille
+			}
+
+			if len(trans.PerMille) == 0 {
+				trans.PerMille = "[]byte{}"
+			}
+		}
+
+		// Currency
+
+		// number values
+		ldml := cldr.RawLDML(trans.Locale)
+
+		currencies := make([][]byte, len(globalCurrencies), len(globalCurrencies))
+
+		for k, v := range globCurrencyIdxMap {
+			currencies[v] = []byte(k)
+		}
+
+		// some just have no data...
+		if ldml.Numbers != nil && ldml.Numbers.Currencies != nil {
+
+			for _, currency := range ldml.Numbers.Currencies.Currency {
+
+				if len(currency.Symbol) == 0 {
+					continue
+				}
+
+				if len(currency.Symbol[0].Data()) == 0 {
+					continue
+				}
+
+				if len(currency.Type) == 0 {
+					continue
+				}
+
+				currencies[globCurrencyIdxMap[currency.Type]] = []byte(currency.Symbol[0].Data())
+			}
+		}
+
+		trans.Currencies = fmt.Sprintf("%#v", currencies)
+	}
+}
+
+// preprocesses maps, array etc... just requires multiple passes no choice....
+func preProcess(cldr *cldr.CLDR) {
+
+	for _, l := range cldr.Locales() {
+
+		fmt.Println("Pre Processing:", l)
+
+		split := strings.SplitN(l, "_", 2)
+		baseLocale := split[0]
+
+		trans := &translator{
+			Locale:     l,
+			BaseLocale: baseLocale,
+		}
+
+		// if is a base locale
+		if len(split) == 1 {
+			baseTranslators[baseLocale] = trans
+		}
+
+		translators[l] = trans
+
+		// get number, currency and datetime symbols
+
+		// number values
+		ldml := cldr.RawLDML(l)
+
+		// some just have no data...
+		if ldml.Numbers != nil && len(ldml.Numbers.Symbols) > 0 {
+
+			symbol := ldml.Numbers.Symbols[0]
+
+			if len(symbol.Decimal) > 0 {
+				trans.Decimal = fmt.Sprintf("%#v", []byte(symbol.Decimal[0].Data()))
+			}
+			if len(symbol.Group) > 0 {
+				trans.Group = fmt.Sprintf("%#v", []byte(symbol.Group[0].Data()))
+			}
+			if len(symbol.MinusSign) > 0 {
+				trans.Minus = fmt.Sprintf("%#v", []byte(symbol.MinusSign[0].Data()))
+			}
+			if len(symbol.PercentSign) > 0 {
+				trans.Percent = fmt.Sprintf("%#v", []byte(symbol.PercentSign[0].Data()))
+			}
+			if len(symbol.PerMille) > 0 {
+				trans.PerMille = fmt.Sprintf("%#v", []byte(symbol.PerMille[0].Data()))
+			}
+
+			if ldml.Numbers.Currencies != nil {
+
+				for _, currency := range ldml.Numbers.Currencies.Currency {
+
+					if len(strings.TrimSpace(currency.Type)) == 0 {
+						continue
+					}
+
+					globalCurrenciesMap[currency.Type] = struct{}{}
+				}
+			}
+
+			// var decimalFormat, currencyFormat, currencyAccountingFormat, percentageFormat string
+
+			// if len(ldml.Numbers.DecimalFormats) > 0 && len(ldml.Numbers.DecimalFormats[0].DecimalFormatLength) > 0 {
+			// 	decimalFormat = ldml.Numbers.DecimalFormats[0].DecimalFormatLength[0].DecimalFormat[0].Pattern[0].Data()
+			// }
+
+			// if len(ldml.Numbers.CurrencyFormats) > 0 && len(ldml.Numbers.CurrencyFormats[0].CurrencyFormatLength) > 0 {
+
+			// 	currencyFormat = ldml.Numbers.CurrencyFormats[0].CurrencyFormatLength[0].CurrencyFormat[0].Pattern[0].Data()
+			// 	currencyAccountingFormat = currencyFormat
+
+			// 	if len(ldml.Numbers.CurrencyFormats[0].CurrencyFormatLength[0].CurrencyFormat) > 1 {
+			// 		currencyAccountingFormat = ldml.Numbers.CurrencyFormats[0].CurrencyFormatLength[0].CurrencyFormat[1].Pattern[0].Data()
+			// 	}
+			// }
+
+			// if len(ldml.Numbers.PercentFormats) > 0 && len(ldml.Numbers.PercentFormats[0].PercentFormatLength) > 0 {
+			// 	percentageFormat = ldml.Numbers.PercentFormats[0].PercentFormatLength[0].PercentFormat[0].Pattern[0].Data()
+			// }
+
+			// // parse Number values
+			// parseNumbers(decimal, group, minus, percent, permille, decimalFormat, currencyFormat, currencyAccountingFormat, percentageFormat)
+
+			// end number values
+		}
+	}
+
+	for k := range globalCurrenciesMap {
+		globalCurrencies = append(globalCurrencies, k)
+	}
+
+	sort.Strings(globalCurrencies)
+
+	for i, loc := range globalCurrencies {
+		globCurrencyIdxMap[loc] = i
+	}
+}
+
+// func parseNumbers(decimal, group, minus, percent, permille, decimalFormat, currencyFormat, currencyAccountingFormat, percentageFormat string) {
+
+// 	if includeDecimalDigits {
+
+// 		nfMutex.RLock()
+
+// 		if format, exists := numberFormats[pattern]; exists {
+// 			nfMutex.RUnlock()
+// 			return format
+// 		}
+
+// 		nfMutex.RUnlock()
+
+// 	} else {
+
+// 		nfndMutex.RLock()
+
+// 		if format, exists := numberFormatsNoDecimals[pattern]; exists {
+// 			nfndMutex.RUnlock()
+// 			return format
+// 		}
+
+// 		nfndMutex.RUnlock()
+// 	}
+
+// 	format := new(numberFormat)
+// 	patterns := strings.Split(pattern, ";")
+
+// 	matches := prefixSuffixRegex.FindAllStringSubmatch(patterns[0], -1)
+// 	if len(matches) > 0 {
+// 		if len(matches[0]) > 1 {
+// 			format.positivePrefix = matches[0][1]
+// 		}
+// 		if len(matches[0]) > 2 {
+// 			format.positiveSuffix = matches[0][2]
+// 		}
+// 	}
+
+// 	// default values for negative prefix & suffix
+// 	format.negativePrefix = string(n.Symbols.Negative) + string(format.positivePrefix)
+// 	format.negativeSuffix = format.positiveSuffix
+
+// 	// see if they are in the pattern
+// 	if len(patterns) > 1 {
+// 		matches = prefixSuffixRegex.FindAllStringSubmatch(patterns[1], -1)
+
+// 		if len(matches) > 0 {
+// 			if len(matches[0]) > 1 {
+// 				format.negativePrefix = matches[0][1]
+// 			}
+// 			if len(matches[0]) > 2 {
+// 				format.negativeSuffix = matches[0][2]
+// 			}
+// 		}
+// 	}
+
+// 	pat := patterns[0]
+
+// 	if strings.Index(pat, "%") != -1 {
+// 		format.multiplier = 100
+// 	} else if strings.Index(pat, "‰") != -1 {
+// 		format.multiplier = 1000
+// 	} else {
+// 		format.multiplier = 1
+// 	}
+
+// 	pos := strings.Index(pat, ".")
+
+// 	if pos != -1 {
+// 		pos2 := strings.LastIndex(pat, "0")
+// 		if pos2 > pos {
+// 			format.minDecimalDigits = pos2 - pos
+// 		}
+
+// 		pos3 := strings.LastIndex(pat, "#")
+// 		if pos3 >= pos2 {
+// 			format.maxDecimalDigits = pos3 - pos
+// 		} else {
+// 			format.maxDecimalDigits = format.minDecimalDigits
+// 		}
+
+// 		pat = pat[0:pos]
+// 	}
+
+// 	p := strings.Replace(pat, ",", "", -1)
+// 	pos = strings.Index(p, "0")
+// 	if pos != -1 {
+// 		format.minIntegerDigits = strings.LastIndex(p, "0") - pos + 1
+// 	}
+
+// 	p = strings.Replace(pat, "#", "0", -1)
+// 	pos = strings.LastIndex(pat, ",")
+// 	if pos != -1 {
+// 		format.groupSizeFinal = strings.LastIndex(p, "0") - pos
+// 		pos2 := strings.LastIndex(p[0:pos], ",")
+// 		if pos2 != -1 {
+// 			format.groupSizeMain = pos - pos2 - 1
+// 		} else {
+// 			format.groupSizeMain = format.groupSizeFinal
+// 		}
+// 	}
+
+// 	if includeDecimalDigits {
+// 		nfMutex.Lock()
+// 		numberFormats[pattern] = format
+// 		nfMutex.Unlock()
+// 		return format
+// 	}
+
+// 	format.maxDecimalDigits = 0
+// 	format.minDecimalDigits = 0
+// 	nfndMutex.Lock()
+// 	numberFormatsNoDecimals[pattern] = format
+// 	nfndMutex.Unlock()
+// 	return format
+// }
+
+type sortRank struct {
+	Rank  uint8
+	Value string
+}
+
+type ByRank []sortRank
+
+func (a ByRank) Len() int           { return len(a) }
+func (a ByRank) Swap(i, j int)      { a[i], a[j] = a[j], a[i] }
+func (a ByRank) Less(i, j int) bool { return a[i].Rank < a[j].Rank }
+
+// TODO: cleanup function logic perhaps write a lexer... but it's working right now, and
+// I'm already farther down the rabbit hole than I'd like and so pulling the chute here.
+func parseCardinalPluralRuleFunc(current *cldr.CLDR, baseLocale string) (results string, plurals string) {
+
+	var prCardinal *struct {
+		cldr.Common
+		Locales    string "xml:\"locales,attr\""
+		PluralRule []*struct {
+			cldr.Common
+			Count string "xml:\"count,attr\""
+		} "xml:\"pluralRule\""
+	}
+
+	var pluralArr []locales.PluralRule
+
+	for _, p := range current.Supplemental().Plurals {
+
+		for _, pr := range p.PluralRules {
+
+			locs := strings.Split(pr.Locales, " ")
+
+			for _, loc := range locs {
+
+				if loc == baseLocale {
+					prCardinal = pr
+				}
+			}
+		}
+	}
+
+	// no plural rules for locale
+	if prCardinal == nil {
+		plurals = "nil"
+		results = "return locales.PluralRuleUnknown"
+		return
+	}
+
+	vals := make(map[string]struct{})
+	first := true
+
+	// pre parse for variables
+	for _, rule := range prCardinal.PluralRule {
+
+		ps1 := pluralStringToString(rule.Count)
+		psI := pluralStringToInt(rule.Count)
+		pluralArr = append(pluralArr, psI)
+
+		data := strings.Replace(strings.Replace(strings.Replace(strings.TrimSpace(strings.SplitN(rule.Common.Data(), "@", 2)[0]), " = ", " == ", -1), " or ", " || ", -1), " and ", " && ", -1)
+
+		if len(data) == 0 {
+			if len(prCardinal.PluralRule) == 1 {
+
+				results = "return locales." + ps1
+
+			} else {
+
+				results += "\n\nreturn locales." + ps1
+				// results += "else {\nreturn locales." + locales.PluralStringToString(rule.Count) + ", nil\n}"
+			}
+
+			continue
+		}
+
+		// // All need n, so always add
+		// if strings.Contains(data, "n") {
+		// 	vals[prVarFuncs["n"]] = struct{}{}
+		// }
+
+		if strings.Contains(data, "i") {
+			vals[prVarFuncs["i"]] = struct{}{}
+		}
+
+		// v is inherently avaialable as an argument
+		// if strings.Contains(data, "v") {
+		// 	vals[prVarFuncs["v"]] = struct{}{}
+		// }
+
+		if strings.Contains(data, "w") {
+			vals[prVarFuncs["w"]] = struct{}{}
+		}
+
+		if strings.Contains(data, "f") {
+			vals[prVarFuncs["f"]] = struct{}{}
+		}
+
+		if strings.Contains(data, "t") {
+			vals[prVarFuncs["t"]] = struct{}{}
+		}
+
+		if first {
+			results += "if "
+			first = false
+		} else {
+			results += "else if "
+		}
+
+		stmt := ""
+
+		// real work here
+		//
+		// split by 'or' then by 'and' allowing to better
+		// determine bracketing for formula
+
+		ors := strings.Split(data, "||")
+
+		for _, or := range ors {
+
+			stmt += "("
+
+			ands := strings.Split(strings.TrimSpace(or), "&&")
+
+			for _, and := range ands {
+
+				inArg := false
+				pre := ""
+				lft := ""
+				preOperator := ""
+				args := strings.Split(strings.TrimSpace(and), " ")
+
+				for _, a := range args {
+
+					if inArg {
+						// check to see if is a value range 2..9
+
+						multiRange := strings.Count(a, "..") > 1
+						cargs := strings.Split(strings.TrimSpace(a), ",")
+						hasBracket := len(cargs) > 1
+						bracketAdded := false
+						lastWasRange := false
+
+						for _, carg := range cargs {
+
+							if rng := strings.Split(carg, ".."); len(rng) > 1 {
+
+								if multiRange {
+									pre += " ("
+								} else {
+									pre += " "
+								}
+
+								switch preOperator {
+								case "==":
+									pre += lft + " >= " + rng[0] + " && " + lft + "<=" + rng[1]
+								case "!=":
+									pre += lft + " < " + rng[0] + " && " + lft + " > " + rng[1]
+								}
+
+								if multiRange {
+									pre += ") || "
+								} else {
+									pre += " || "
+								}
+
+								lastWasRange = true
+								continue
+							}
+
+							if lastWasRange {
+								pre = strings.TrimRight(pre, " || ") + " && "
+							}
+
+							lastWasRange = false
+
+							if hasBracket && !bracketAdded {
+								pre += "("
+								bracketAdded = true
+							}
+
+							// single comma separated values
+							switch preOperator {
+							case "==":
+								pre += " " + lft + preOperator + carg + " || "
+							case "!=":
+								pre += " " + lft + preOperator + carg + " && "
+							}
+
+						}
+
+						pre = strings.TrimRight(pre, " || ")
+						pre = strings.TrimRight(pre, " && ")
+						pre = strings.TrimRight(pre, " || ")
+
+						if hasBracket && bracketAdded {
+							pre += ")"
+						}
+
+						continue
+					}
+
+					if strings.Contains(a, "=") || a == ">" || a == "<" {
+						inArg = true
+						preOperator = a
+						continue
+					}
+
+					lft += a
+				}
+
+				stmt += pre + " && "
+			}
+
+			stmt = strings.TrimRight(stmt, " && ") + ") || "
+		}
+
+		stmt = strings.TrimRight(stmt, " || ")
+
+		results += stmt
+
+		results += " {\n"
+
+		// return plural rule here
+		results += "return locales." + ps1 + "\n"
+
+		results += "}"
+	}
+
+	pre := "\n"
+
+	// always needed
+	vals[prVarFuncs["n"]] = struct{}{}
+
+	sorted := make([]sortRank, 0, len(vals))
+
+	for k := range vals {
+		switch k[:1] {
+		case "n":
+			sorted = append(sorted, sortRank{
+				Value: prVarFuncs["n"],
+				Rank:  1,
+			})
+		case "i":
+			sorted = append(sorted, sortRank{
+				Value: prVarFuncs["i"],
+				Rank:  2,
+			})
+		case "w":
+			sorted = append(sorted, sortRank{
+				Value: prVarFuncs["w"],
+				Rank:  3,
+			})
+		case "f":
+			sorted = append(sorted, sortRank{
+				Value: prVarFuncs["f"],
+				Rank:  4,
+			})
+		case "t":
+			sorted = append(sorted, sortRank{
+				Value: prVarFuncs["t"],
+				Rank:  5,
+			})
+		}
+	}
+
+	sort.Sort(ByRank(sorted))
+
+	for _, k := range sorted {
+		pre += k.Value
+	}
+
+	pre += "\n"
+
+	if len(results) == 0 {
+		results = "return locales.PluralRuleUnknown"
+	} else {
+
+		if !strings.HasPrefix(results, "return") {
+			results = pre + results
+		}
+	}
+
+	if len(pluralArr) == 0 {
+		plurals = "nil"
+	} else {
+		plurals = fmt.Sprintf("%#v", pluralArr)
+	}
+
+	return
+}
+
+// pluralStringToInt returns the enum value of 'plural' provided
+func pluralStringToInt(plural string) locales.PluralRule {
+
+	switch plural {
+	case "zero":
+		return locales.PluralRuleZero
+	case "one":
+		return locales.PluralRuleOne
+	case "two":
+		return locales.PluralRuleTwo
+	case "few":
+		return locales.PluralRuleFew
+	case "many":
+		return locales.PluralRuleMany
+	case "other":
+		return locales.PluralRuleOther
+	default:
+		return locales.PluralRuleUnknown
+	}
+}
+
+func pluralStringToString(pr string) string {
+
+	pr = strings.TrimSpace(pr)
+
+	switch pr {
+	case "zero":
+		return "PluralRuleZero"
+	case "one":
+		return "PluralRuleOne"
+	case "two":
+		return "PluralRuleTwo"
+	case "few":
+		return "PluralRuleFew"
+	case "many":
+		return "PluralRuleMany"
+	case "other":
+		return "PluralRuleOther"
+	default:
+		return "PluralRuleUnknown"
+	}
+}
+
+// //plurals
+// rules := "data/rules"
+// plurals := map[string]*pluralInfo{}
+// basePlurals := map[string]string{}
+
+// err := filepath.Walk(rules, func(path string, info os.FileInfo, err error) error {
+
+// 	if err != nil {
+// 		panic(err)
+// 	}
+
+// 	if info.IsDir() {
+// 		return nil
+// 	}
+
+// 	in, err := ioutil.ReadFile(path)
+// 	if err != nil {
+// 		panic(err)
+// 	}
+
+// 	var out yaml.MapSlice
+// 	if err = yaml.Unmarshal(in, &out); err != nil {
+// 		panic(err)
+// 	}
+
+// 	var plural string
+// 	for _, item := range out {
+// 		if item.Key == "plural" {
+// 			plural = item.Value.(string)
+// 		}
+// 	}
+
+// 	locale := strings.Replace(info.Name(), filepath.Ext(info.Name()), "", 1)
+// 	locale = strings.ToLower(strings.Replace(locale, "-", "_", -1))
+
+// 	plurals[locale] = &pluralInfo{
+// 		path:   path,
+// 		locale: locale,
+// 		plural: plural,
+// 	}
+
+// 	if plural == "" {
+// 		return nil
+// 	}
+
+// 	basePlurals[locale] = plural
+
+// 	return nil
+// })
+
+// if err != nil {
+// 	panic(err)
+// }
+
+// for _, p := range plurals {
+
+// 	if p.plural == "" {
+
+// 		var ok bool
+
+// 		fmt.Print("can't find plurals in ", p.path, " attempting to locate base language plural rules...")
+
+// 		base := strings.SplitN(p.locale, "_", 2)
+
+// 		p.plural, ok = basePlurals[base[0]]
+// 		if !ok {
+// 			fmt.Println("Not Found")
+// 			continue
+// 		}
+
+// 		fmt.Println("Found")
+// 	}
+// }
+
+// cldr
+
+// var decoder cldr.Decoder
+// cldr, err := decoder.DecodePath("data/core")
+// if err != nil {
+// 	panic(err)
+// }
+
+// 	locs := map[string]string{}
+// 	numbers := map[string]i18n.Number{}
+// 	calendars := map[string]i18n.Calendar{}
+// 	locales := cldr.Locales()
+// 	for _, loc := range locales {
+
+// 		ldml := cldr.RawLDML(loc)
+// 		if ldml.Numbers == nil {
+// 			continue
+// 		}
+// 		var number i18n.Number
+
+// 		number.Currencies = make(i18n.CurrencyFormatValue)
+
+// 		if len(ldml.Numbers.Symbols) > 0 {
+// 			symbol := ldml.Numbers.Symbols[0]
+// 			if len(symbol.Decimal) > 0 {
+// 				number.Symbols.Decimal = symbol.Decimal[0].Data()
+// 			}
+// 			if len(symbol.Group) > 0 {
+// 				number.Symbols.Group = symbol.Group[0].Data()
+// 			}
+// 			if len(symbol.MinusSign) > 0 {
+// 				number.Symbols.Negative = symbol.MinusSign[0].Data()
+// 			}
+// 			if len(symbol.PercentSign) > 0 {
+// 				number.Symbols.Percent = symbol.PercentSign[0].Data()
+// 			}
+// 			if len(symbol.PerMille) > 0 {
+// 				number.Symbols.PerMille = symbol.PerMille[0].Data()
+// 			}
+// 		}
+// 		if len(ldml.Numbers.DecimalFormats) > 0 && len(ldml.Numbers.DecimalFormats[0].DecimalFormatLength) > 0 {
+// 			number.Formats.Decimal = ldml.Numbers.DecimalFormats[0].DecimalFormatLength[0].DecimalFormat[0].Pattern[0].Data()
+// 		}
+
+// 		if len(ldml.Numbers.CurrencyFormats) > 0 && len(ldml.Numbers.CurrencyFormats[0].CurrencyFormatLength) > 0 {
+
+// 			number.Formats.Currency = ldml.Numbers.CurrencyFormats[0].CurrencyFormatLength[0].CurrencyFormat[0].Pattern[0].Data()
+// 			number.Formats.CurrencyAccounting = number.Formats.Currency
+
+// 			if len(ldml.Numbers.CurrencyFormats[0].CurrencyFormatLength[0].CurrencyFormat) > 1 {
+// 				number.Formats.CurrencyAccounting = ldml.Numbers.CurrencyFormats[0].CurrencyFormatLength[0].CurrencyFormat[1].Pattern[0].Data()
+// 			}
+// 		}
+// 		if len(ldml.Numbers.PercentFormats) > 0 && len(ldml.Numbers.PercentFormats[0].PercentFormatLength) > 0 {
+// 			number.Formats.Percent = ldml.Numbers.PercentFormats[0].PercentFormatLength[0].PercentFormat[0].Pattern[0].Data()
+// 		}
+// 		if ldml.Numbers.Currencies != nil {
+
+// 			for _, currency := range ldml.Numbers.Currencies.Currency {
+
+// 				var c i18n.Currency
+
+// 				c.Currency = currency.Type
+
+// 				if len(currency.DisplayName) > 0 {
+// 					c.DisplayName = currency.DisplayName[0].Data()
+// 				}
+
+// 				if len(currency.Symbol) > 0 {
+// 					c.Symbol = currency.Symbol[0].Data()
+// 				}
+
+// 				number.Currencies[c.Currency] = c
+// 			}
+// 		}
+// 		numbers[loc] = number
+// 		locs[loc] = strings.ToLower(strings.Replace(loc, "_", "", -1))
+
+// 		if ldml.Dates != nil && ldml.Dates.Calendars != nil {
+
+// 			var calendar i18n.Calendar
+// 			ldmlCar := ldml.Dates.Calendars.Calendar[0]
+
+// 			for _, cal := range ldml.Dates.Calendars.Calendar {
+// 				if cal.Type == "gregorian" {
+// 					ldmlCar = cal
+// 				}
+// 			}
+
+// 			if ldmlCar.DateFormats != nil {
+// 				for _, datefmt := range ldmlCar.DateFormats.DateFormatLength {
+// 					switch datefmt.Type {
+// 					case "full":
+// 						calendar.Formats.DateEra.BC.Full = datefmt.DateFormat[0].Pattern[0].Data()
+// 						calendar.Formats.DateEra.AD.Full = calendar.Formats.DateEra.BC.Full
+
+// 					case "long":
+// 						calendar.Formats.DateEra.BC.Long = datefmt.DateFormat[0].Pattern[0].Data()
+// 						calendar.Formats.DateEra.AD.Long = calendar.Formats.DateEra.BC.Long
+
+// 						// Overrides TODO: Split Each Section into separate function, getting to big to maintain
+
+// 					case "medium":
+// 						calendar.Formats.DateEra.BC.Medium = datefmt.DateFormat[0].Pattern[0].Data()
+// 						calendar.Formats.DateEra.AD.Medium = calendar.Formats.DateEra.BC.Medium
+// 					case "short":
+// 						calendar.Formats.DateEra.BC.Short = datefmt.DateFormat[0].Pattern[0].Data()
+// 						calendar.Formats.DateEra.AD.Short = calendar.Formats.DateEra.BC.Short
+// 					}
+// 				}
+
+// 				// Overrides TODO: Split Each Section into separate function, getting to big to maintain
+// 				switch loc {
+// 				case "th":
+// 					calendar.Formats.DateEra.BC.Full = "EEEEที่ d MMMM y GGGG"
+// 					calendar.Formats.DateEra.AD.Full = "EEEEที่ d MMMM GGGG y"
+// 					calendar.Formats.DateEra.BC.Long = "d MMMM y GG"
+// 					calendar.Formats.DateEra.AD.Long = "d MMMM GG y"
+// 				case "en":
+// 					calendar.Formats.DateEra.BC.Full = "EEEE, MMMM d, y GGGG"
+// 					calendar.Formats.DateEra.BC.Long = "MMMM d, y GG"
+// 					// calendar.Formats.DateEra.BC.Medium = "MMM d, y GG"
+// 					// calendar.Formats.DateEra.BC.Short = "M/d/yy G"
+// 				}
+// 			}
+
+// 			if ldmlCar.TimeFormats != nil {
+// 				for _, datefmt := range ldmlCar.TimeFormats.TimeFormatLength {
+// 					switch datefmt.Type {
+// 					case "full":
+// 						calendar.Formats.Time.Full = datefmt.TimeFormat[0].Pattern[0].Data()
+// 					case "long":
+// 						calendar.Formats.Time.Long = datefmt.TimeFormat[0].Pattern[0].Data()
+// 					case "medium":
+// 						calendar.Formats.Time.Medium = datefmt.TimeFormat[0].Pattern[0].Data()
+// 					case "short":
+// 						calendar.Formats.Time.Short = datefmt.TimeFormat[0].Pattern[0].Data()
+// 					}
+// 				}
+// 			}
+// 			if ldmlCar.DateTimeFormats != nil {
+// 				for _, datefmt := range ldmlCar.DateTimeFormats.DateTimeFormatLength {
+// 					switch datefmt.Type {
+// 					case "full":
+// 						calendar.Formats.DateTime.Full = datefmt.DateTimeFormat[0].Pattern[0].Data()
+// 					case "long":
+// 						calendar.Formats.DateTime.Long = datefmt.DateTimeFormat[0].Pattern[0].Data()
+// 					case "medium":
+// 						calendar.Formats.DateTime.Medium = datefmt.DateTimeFormat[0].Pattern[0].Data()
+// 					case "short":
+// 						calendar.Formats.DateTime.Short = datefmt.DateTimeFormat[0].Pattern[0].Data()
+// 					}
+// 				}
+// 			}
+// 			if ldmlCar.Months != nil {
+
+// 				for _, monthctx := range ldmlCar.Months.MonthContext {
+
+// 					for _, months := range monthctx.MonthWidth {
+
+// 						i18nMonth := make(i18n.CalendarMonthFormatNameValue)
+
+// 						for _, m := range months.Month {
+// 							switch m.Type {
+// 							case "1":
+// 								i18nMonth[time.January] = m.Data()
+// 							case "2":
+// 								i18nMonth[time.February] = m.Data()
+// 							case "3":
+// 								i18nMonth[time.March] = m.Data()
+// 							case "4":
+// 								i18nMonth[time.April] = m.Data()
+// 							case "5":
+// 								i18nMonth[time.May] = m.Data()
+// 							case "6":
+// 								i18nMonth[time.June] = m.Data()
+// 							case "7":
+// 								i18nMonth[time.July] = m.Data()
+// 							case "8":
+// 								i18nMonth[time.August] = m.Data()
+// 							case "9":
+// 								i18nMonth[time.September] = m.Data()
+// 							case "10":
+// 								i18nMonth[time.October] = m.Data()
+// 							case "11":
+// 								i18nMonth[time.November] = m.Data()
+// 							case "12":
+// 								i18nMonth[time.December] = m.Data()
+// 							}
+// 						}
+// 						switch months.Type {
+// 						case "abbreviated":
+// 							calendar.FormatNames.Months.Abbreviated = i18nMonth
+// 						case "narrow":
+// 							calendar.FormatNames.Months.Narrow = i18nMonth
+// 						case "short":
+// 							calendar.FormatNames.Months.Short = i18nMonth
+// 						case "wide":
+// 							calendar.FormatNames.Months.Wide = i18nMonth
+// 						}
+// 					}
+// 				}
+// 			}
+// 			if ldmlCar.Days != nil {
+// 				for _, dayctx := range ldmlCar.Days.DayContext {
+
+// 					for _, days := range dayctx.DayWidth {
+
+// 						i18nDay := make(i18n.CalendarDayFormatNameValue)
+
+// 						for _, d := range days.Day {
+
+// 							switch d.Type {
+// 							case "sun":
+// 								i18nDay[time.Sunday] = d.Data()
+// 							case "mon":
+// 								i18nDay[time.Monday] = d.Data()
+// 							case "tue":
+// 								i18nDay[time.Tuesday] = d.Data()
+// 							case "wed":
+// 								i18nDay[time.Wednesday] = d.Data()
+// 							case "thu":
+// 								i18nDay[time.Thursday] = d.Data()
+// 							case "fri":
+// 								i18nDay[time.Friday] = d.Data()
+// 							case "sat":
+// 								i18nDay[time.Saturday] = d.Data()
+// 							}
+// 						}
+
+// 						switch days.Type {
+// 						case "abbreviated":
+// 							calendar.FormatNames.Days.Abbreviated = i18nDay
+// 						case "narrow":
+// 							calendar.FormatNames.Days.Narrow = i18nDay
+// 						case "short":
+// 							calendar.FormatNames.Days.Short = i18nDay
+// 						case "wide":
+// 							calendar.FormatNames.Days.Wide = i18nDay
+// 						}
+// 					}
+// 				}
+// 			}
+
+// 			if ldmlCar.DayPeriods != nil {
+
+// 				for _, ctx := range ldmlCar.DayPeriods.DayPeriodContext {
+
+// 					for _, width := range ctx.DayPeriodWidth {
+
+// 						// var i18nPeriod i18n.CalendarPeriodFormatNameValue
+// 						i18nPeriod := make(i18n.CalendarPeriodFormatNameValue)
+
+// 						for _, d := range width.DayPeriod {
+
+// 							if _, ok := i18nPeriod[d.Type]; !ok {
+// 								i18nPeriod[d.Type] = d.Data()
+// 							}
+// 						}
+
+// 						switch width.Type {
+// 						case "abbreviated":
+// 							calendar.FormatNames.Periods.Abbreviated = i18nPeriod
+// 						case "narrow":
+// 							calendar.FormatNames.Periods.Narrow = i18nPeriod
+// 						case "short":
+// 							calendar.FormatNames.Periods.Short = i18nPeriod
+// 						case "wide":
+// 							calendar.FormatNames.Periods.Wide = i18nPeriod
+// 						}
+// 					}
+// 				}
+// 				// var empty i18n.CalendarPeriodFormatNameValue
+// 				// if calendar.FormatNames.Periods.Abbreviated == empty {
+// 				// 	calendar.FormatNames.Periods.Abbreviated = calendar.FormatNames.Periods.Wide
+// 				// }
+// 			}
+
+// 			if ldmlCar.Eras != nil {
+
+// 				var eras i18n.Eras
+
+// 				if ldmlCar.Eras.EraNames != nil && len(ldmlCar.Eras.EraNames.Era) > 0 {
+// 					eras.BC.Full = ldmlCar.Eras.EraNames.Era[0].Data()
+// 				}
+
+// 				if ldmlCar.Eras.EraAbbr != nil && len(ldmlCar.Eras.EraAbbr.Era) > 0 {
+// 					eras.BC.Abbrev = ldmlCar.Eras.EraAbbr.Era[0].Data()
+// 				}
+
+// 				if ldmlCar.Eras.EraNarrow != nil && len(ldmlCar.Eras.EraNarrow.Era) > 0 {
+// 					eras.BC.Narrow = ldmlCar.Eras.EraNarrow.Era[0].Data()
+// 				}
+
+// 				if ldmlCar.Eras.EraNames != nil && len(ldmlCar.Eras.EraNames.Era) > 2 {
+// 					eras.AD.Full = ldmlCar.Eras.EraNames.Era[2].Data()
+// 				}
+
+// 				if ldmlCar.Eras.EraAbbr != nil && len(ldmlCar.Eras.EraAbbr.Era) > 2 {
+// 					eras.AD.Abbrev = ldmlCar.Eras.EraAbbr.Era[2].Data()
+// 				}
+
+// 				if ldmlCar.Eras.EraNarrow != nil && len(ldmlCar.Eras.EraNarrow.Era) > 2 {
+// 					eras.AD.Narrow = ldmlCar.Eras.EraNarrow.Era[2].Data()
+// 				}
+
+// 				calendar.FormatNames.Eras = eras
+// 			}
+
+// 			calendars[loc] = calendar
+// 		}
+// 	}
+
+// 	for locale := range locs {
+
+// 		if !strings.Contains(locale, "_") {
+// 			continue
+// 		}
+
+// 		calendar := calendars[locale]
+
+// 		bString := strings.SplitN(locale, "_", 2)
+// 		base := bString[0]
+
+// 		baseCal := calendars[base]
+
+// 		// copy base calendar objects
+
+// 		// Dates
+// 		if calendar.Formats.DateEra.AD.Full == "" {
+// 			calendar.Formats.DateEra.BC.Full = baseCal.Formats.DateEra.BC.Full
+// 			calendar.Formats.DateEra.AD.Full = baseCal.Formats.DateEra.AD.Full
+// 		}
+
+// 		if calendar.Formats.DateEra.AD.Long == "" {
+// 			calendar.Formats.DateEra.BC.Long = baseCal.Formats.DateEra.BC.Long
+// 			calendar.Formats.DateEra.AD.Long = baseCal.Formats.DateEra.AD.Long
+// 		}
+
+// 		if calendar.Formats.DateEra.AD.Medium == "" {
+// 			calendar.Formats.DateEra.BC.Medium = baseCal.Formats.DateEra.BC.Medium
+// 			calendar.Formats.DateEra.AD.Medium = baseCal.Formats.DateEra.AD.Medium
+// 		}
+
+// 		if calendar.Formats.DateEra.AD.Short == "" {
+// 			calendar.Formats.DateEra.BC.Short = baseCal.Formats.DateEra.BC.Short
+// 			calendar.Formats.DateEra.AD.Short = baseCal.Formats.DateEra.AD.Short
+// 		}
+
+// 		// times
+// 		if calendar.Formats.Time.Full == "" {
+// 			calendar.Formats.Time.Full = baseCal.Formats.Time.Full
+// 		}
+
+// 		if calendar.Formats.Time.Long == "" {
+// 			calendar.Formats.Time.Long = baseCal.Formats.Time.Long
+// 		}
+
+// 		if calendar.Formats.Time.Medium == "" {
+// 			calendar.Formats.Time.Medium = baseCal.Formats.Time.Medium
+// 		}
+
+// 		if calendar.Formats.Time.Short == "" {
+// 			calendar.Formats.Time.Short = baseCal.Formats.Time.Short
+// 		}
+
+// 		// date & times
+// 		if calendar.Formats.DateTime.Full == "" {
+// 			calendar.Formats.DateTime.Full = baseCal.Formats.DateTime.Full
+// 		}
+
+// 		if calendar.Formats.DateTime.Long == "" {
+// 			calendar.Formats.DateTime.Long = baseCal.Formats.DateTime.Long
+// 		}
+
+// 		if calendar.Formats.DateTime.Medium == "" {
+// 			calendar.Formats.DateTime.Medium = baseCal.Formats.DateTime.Medium
+// 		}
+
+// 		if calendar.Formats.DateTime.Short == "" {
+// 			calendar.Formats.DateTime.Short = baseCal.Formats.DateTime.Short
+// 		}
+
+// 		// months
+
+// 		if calendar.FormatNames.Months.Abbreviated == nil {
+// 			calendar.FormatNames.Months.Abbreviated = make(i18n.CalendarMonthFormatNameValue)
+// 		}
+
+// 		if calendar.FormatNames.Months.Narrow == nil {
+// 			calendar.FormatNames.Months.Narrow = make(i18n.CalendarMonthFormatNameValue)
+// 		}
+
+// 		if calendar.FormatNames.Months.Short == nil {
+// 			calendar.FormatNames.Months.Short = make(i18n.CalendarMonthFormatNameValue)
+// 		}
+
+// 		if calendar.FormatNames.Months.Wide == nil {
+// 			calendar.FormatNames.Months.Wide = make(i18n.CalendarMonthFormatNameValue)
+// 		}
+
+// 		for k, v := range baseCal.FormatNames.Months.Abbreviated {
+
+// 			val, ok := calendar.FormatNames.Months.Abbreviated[k]
+// 			if !ok {
+// 				calendar.FormatNames.Months.Abbreviated[k] = v
+// 				continue
+// 			}
+
+// 			if val == "" {
+// 				calendar.FormatNames.Months.Abbreviated[k] = v
+// 			}
+// 		}
+
+// 		for k, v := range baseCal.FormatNames.Months.Narrow {
+
+// 			val, ok := calendar.FormatNames.Months.Narrow[k]
+// 			if !ok {
+// 				calendar.FormatNames.Months.Narrow[k] = v
+// 				continue
+// 			}
+
+// 			if val == "" {
+// 				calendar.FormatNames.Months.Narrow[k] = v
+// 			}
+// 		}
+
+// 		for k, v := range baseCal.FormatNames.Months.Short {
+
+// 			val, ok := calendar.FormatNames.Months.Short[k]
+// 			if !ok {
+// 				calendar.FormatNames.Months.Short[k] = v
+// 				continue
+// 			}
+
+// 			if val == "" {
+// 				calendar.FormatNames.Months.Short[k] = v
+// 			}
+// 		}
+
+// 		for k, v := range baseCal.FormatNames.Months.Wide {
+
+// 			val, ok := calendar.FormatNames.Months.Wide[k]
+// 			if !ok {
+// 				calendar.FormatNames.Months.Wide[k] = v
+// 				continue
+// 			}
+
+// 			if val == "" {
+// 				calendar.FormatNames.Months.Wide[k] = v
+// 			}
+// 		}
+
+// 		// days
+
+// 		if calendar.FormatNames.Days.Abbreviated == nil {
+// 			calendar.FormatNames.Days.Abbreviated = make(i18n.CalendarDayFormatNameValue)
+// 		}
+
+// 		if calendar.FormatNames.Days.Narrow == nil {
+// 			calendar.FormatNames.Days.Narrow = make(i18n.CalendarDayFormatNameValue)
+// 		}
+
+// 		if calendar.FormatNames.Days.Short == nil {
+// 			calendar.FormatNames.Days.Short = make(i18n.CalendarDayFormatNameValue)
+// 		}
+
+// 		if calendar.FormatNames.Days.Wide == nil {
+// 			calendar.FormatNames.Days.Wide = make(i18n.CalendarDayFormatNameValue)
+// 		}
+
+// 		for k, v := range baseCal.FormatNames.Days.Abbreviated {
+
+// 			val, ok := calendar.FormatNames.Days.Abbreviated[k]
+// 			if !ok {
+// 				calendar.FormatNames.Days.Abbreviated[k] = v
+// 				continue
+// 			}
+
+// 			if val == "" {
+// 				calendar.FormatNames.Days.Abbreviated[k] = v
+// 			}
+// 		}
+
+// 		for k, v := range baseCal.FormatNames.Days.Narrow {
+
+// 			val, ok := calendar.FormatNames.Days.Narrow[k]
+// 			if !ok {
+// 				calendar.FormatNames.Days.Narrow[k] = v
+// 				continue
+// 			}
+
+// 			if val == "" {
+// 				calendar.FormatNames.Days.Narrow[k] = v
+// 			}
+// 		}
+
+// 		for k, v := range baseCal.FormatNames.Days.Short {
+
+// 			val, ok := calendar.FormatNames.Days.Short[k]
+// 			if !ok {
+// 				calendar.FormatNames.Days.Short[k] = v
+// 				continue
+// 			}
+
+// 			if val == "" {
+// 				calendar.FormatNames.Days.Short[k] = v
+// 			}
+// 		}
+
+// 		for k, v := range baseCal.FormatNames.Days.Wide {
+
+// 			val, ok := calendar.FormatNames.Days.Wide[k]
+// 			if !ok {
+// 				calendar.FormatNames.Days.Wide[k] = v
+// 				continue
+// 			}
+
+// 			if val == "" {
+// 				calendar.FormatNames.Days.Wide[k] = v
+// 			}
+// 		}
+
+// 		// periods
+// 		if calendar.FormatNames.Periods.Abbreviated == nil {
+// 			calendar.FormatNames.Periods.Abbreviated = make(i18n.CalendarPeriodFormatNameValue)
+// 		}
+
+// 		if calendar.FormatNames.Periods.Narrow == nil {
+// 			calendar.FormatNames.Periods.Narrow = make(i18n.CalendarPeriodFormatNameValue)
+// 		}
+
+// 		if calendar.FormatNames.Periods.Short == nil {
+// 			calendar.FormatNames.Periods.Short = make(i18n.CalendarPeriodFormatNameValue)
+// 		}
+
+// 		if calendar.FormatNames.Periods.Wide == nil {
+// 			calendar.FormatNames.Periods.Wide = make(i18n.CalendarPeriodFormatNameValue)
+// 		}
+
+// 		for k, v := range baseCal.FormatNames.Periods.Abbreviated {
+
+// 			val, ok := calendar.FormatNames.Periods.Abbreviated[k]
+// 			if !ok {
+// 				calendar.FormatNames.Periods.Abbreviated[k] = v
+// 				continue
+// 			}
+
+// 			if val == "" {
+// 				calendar.FormatNames.Periods.Abbreviated[k] = v
+// 			}
+// 		}
+
+// 		for k, v := range baseCal.FormatNames.Periods.Narrow {
+
+// 			val, ok := calendar.FormatNames.Periods.Narrow[k]
+// 			if !ok {
+// 				calendar.FormatNames.Periods.Narrow[k] = v
+// 				continue
+// 			}
+
+// 			if val == "" {
+// 				calendar.FormatNames.Periods.Narrow[k] = v
+// 			}
+// 		}
+
+// 		for k, v := range baseCal.FormatNames.Periods.Short {
+
+// 			val, ok := calendar.FormatNames.Periods.Short[k]
+// 			if !ok {
+// 				calendar.FormatNames.Periods.Short[k] = v
+// 				continue
+// 			}
+
+// 			if val == "" {
+// 				calendar.FormatNames.Periods.Short[k] = v
+// 			}
+// 		}
+
+// 		for k, v := range baseCal.FormatNames.Periods.Wide {
+
+// 			val, ok := calendar.FormatNames.Periods.Wide[k]
+// 			if !ok {
+// 				calendar.FormatNames.Periods.Wide[k] = v
+// 				continue
+// 			}
+
+// 			if val == "" {
+// 				calendar.FormatNames.Periods.Wide[k] = v
+// 			}
+// 		}
+
+// 		calendars[locale] = calendar
+
+// 		number := numbers[locale]
+// 		baseNum := numbers[base]
+
+// 		// symbols
+// 		if number.Symbols.Decimal == "" {
+// 			number.Symbols.Decimal = baseNum.Symbols.Decimal
+// 		}
+
+// 		if number.Symbols.Group == "" {
+// 			number.Symbols.Group = baseNum.Symbols.Group
+// 		}
+
+// 		if number.Symbols.Negative == "" {
+// 			number.Symbols.Negative = baseNum.Symbols.Negative
+// 		}
+
+// 		if number.Symbols.Percent == "" {
+// 			number.Symbols.Percent = baseNum.Symbols.Percent
+// 		}
+
+// 		if number.Symbols.PerMille == "" {
+// 			number.Symbols.PerMille = baseNum.Symbols.PerMille
+// 		}
+
+// 		// formats
+// 		if number.Formats.Decimal == "" {
+// 			number.Formats.Decimal = baseNum.Formats.Decimal
+// 		}
+
+// 		if number.Formats.Currency == "" {
+// 			number.Formats.Currency = baseNum.Formats.Currency
+// 		}
+
+// 		if number.Formats.CurrencyAccounting == "" {
+// 			number.Formats.CurrencyAccounting = baseNum.Formats.CurrencyAccounting
+// 		}
+
+// 		if number.Formats.Percent == "" {
+// 			number.Formats.Percent = baseNum.Formats.Percent
+// 		}
+
+// 		// currency
+// 		for k, v := range baseNum.Currencies {
+
+// 			val, ok := number.Currencies[k]
+// 			if !ok {
+// 				// number.Currencies[k] = v
+// 				continue
+// 			}
+
+// 			if val.Currency == "" {
+// 				val.Currency = v.Currency
+// 			}
+
+// 			if val.DisplayName == "" {
+// 				val.DisplayName = v.DisplayName
+// 			}
+
+// 			if val.Symbol == "" {
+// 				val.Symbol = v.Symbol
+// 			}
+
+// 			number.Currencies[k] = val
+// 		}
+
+// 		numbers[locale] = number
+// 	}
+
+// 	var wg sync.WaitGroup
+// 	wg.Add(len(numbers))
+// 	for locale, number := range numbers {
+// 		go func(locale string, number i18n.Number) {
+
+// 			localeLowercase := strings.ToLower(locale)
+
+// 			defer func() { wg.Done() }()
+// 			path := "../../resources/locales/" + locale
+
+// 			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 {
+// 				panic(err)
+// 			}
+// 			defer mainFile.Close()
+
+// 			calendar := calendars[locale]
+
+// 			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 init() {
+// 				ut.RegisterLocale(locale)
+// 			}
+// 		`, locale, locale)))
+
+// 			if err != nil {
+// 				panic(err)
+// 			}
+
+// 			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)
+
+// 			currencyFile, err := os.Create(path + "currency.go")
+// 			if err != nil {
+// 				panic(err)
+// 			}
+// 			defer currencyFile.Close()
+
+// 			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 {
+// 				panic(err)
+// 			}
+// 			defer calendarFile.Close()
+
+// 			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)
+
+// 			var ok bool
+// 			pluralCode := "1"
+
+// 			pInfo, ok := plurals[localeLowercase]
+// 			if ok && pInfo.plural != "" {
+// 				pluralCode = pInfo.plural
+// 			}
+
+// 			pluralFile, err := os.Create(path + "plural.go")
+// 			if err != nil {
+// 				panic(err)
+// 			}
+// 			defer pluralFile.Close()
+
+// 			pluralCodes, err := format.Source([]byte(fmt.Sprintf(`package %s
+
+// 			var pluralRule = %q
+// 		`, locale, pluralCode)))
+// 			if err != nil {
+// 				panic(err)
+// 			}
+// 			fmt.Fprintf(pluralFile, "%s", pluralCodes)
+// 		}(locale, number)
+// 	}
+
+// 	wg.Wait()
+
+// 	localesFile, err := os.Create("../../resources/locales/all.go")
+// 	if err != nil {
+// 		panic(err)
+// 	}
+// 	defer localesFile.Close()
+
+// 	tmpl, err := template.New("").Parse(`package locales
+
+// 		// 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 {
+// 		panic(err)
+// 	}
+// 	var buf bytes.Buffer
+// 	if err := tmpl.Execute(&buf, locs); err != nil {
+// 		panic(err)
+// 	}
+// 	allCodes, err := format.Source(buf.Bytes())
+// 	if err != nil {
+// 		panic(err)
+// 	}
+// 	_, err = localesFile.Write(allCodes)
+// 	if err != nil {
+// 		panic(err)
+// 	}
+// }

+ 50 - 0
cmd/translator.tmpl

@@ -0,0 +1,50 @@
+{{ define "translator" }}
+package {{ .Locale }}
+
+import (
+	"math"
+
+	"github.com/go-playground/locales"
+)
+
+type {{ .Locale }} struct {
+	locale     string
+	plurals    []locales.PluralRule
+	decimal    []byte
+	group      []byte
+	minus      []byte
+	percent    []byte
+	perMille   []byte
+	currencies [][]byte // idx = enum of currency code
+}
+
+// New returns a new instance of translator for the '{{ .Locale }}' locale
+func New() locales.Translator {
+	return &{{ .Locale }}{
+		locale:   		"{{ .Locale }}",
+		plurals:  		{{ .Plurals }},
+		decimal:  		{{ .Decimal }},
+		group:    		{{ .Group }},
+		minus:    		{{ .Minus }},
+		percent:  		{{ .Percent }},
+		perMille:       {{ .PerMille }},
+		currencies:     {{ .Currencies }},
+	}
+}
+
+// Locale returns the current translators string locale
+func(t *{{ .Locale }}) Locale() string {
+	return t.locale
+}
+
+// Plurals returns the list of plurals associated with '{{ .Locale }}'
+func(t *{{ .Locale }}) Plurals() []locales.PluralRule {
+	return t.plurals
+}
+
+// cardinalPluralRule returns the PluralRule given 'num' and digits/precision of 'v' for '{{ .Locale }}'
+func(t *{{ .Locale }}) cardinalPluralRule(num float64, v uint64) locales.PluralRule {
+	{{ .CardinalFunc }}
+}
+
+{{ end }}

File diff suppressed because it is too large
+ 29 - 0
cs/cs.go


File diff suppressed because it is too large
+ 29 - 0
cs_CZ/cs_CZ.go


Some files were not shown because too many files changed in this diff