forked from apps/featurer
		
	Add vendor to improve building speed.
This also adds ability to be built in network-constrained environment.
This commit is contained in:
		
							
								
								
									
										25
									
								
								vendor/github.com/go-playground/universal-translator/.gitignore
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								vendor/github.com/go-playground/universal-translator/.gitignore
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,25 @@ | ||||
| # 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 | ||||
| *.coverprofile | ||||
							
								
								
									
										27
									
								
								vendor/github.com/go-playground/universal-translator/.travis.yml
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								vendor/github.com/go-playground/universal-translator/.travis.yml
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,27 @@ | ||||
| language: go | ||||
| go: | ||||
|   - 1.13.4 | ||||
|   - tip | ||||
| matrix: | ||||
|   allow_failures: | ||||
|     - go: tip | ||||
|  | ||||
| notifications: | ||||
|   email: | ||||
|     recipients: dean.karn@gmail.com | ||||
|     on_success: change | ||||
|     on_failure: always | ||||
|  | ||||
| before_install: | ||||
|   - go install github.com/mattn/goveralls | ||||
|  | ||||
| # Only clone the most recent commit. | ||||
| git: | ||||
|   depth: 1 | ||||
|  | ||||
| script: | ||||
|   - go test -v -race -covermode=atomic -coverprofile=coverage.coverprofile ./... | ||||
|  | ||||
| after_success: | | ||||
|   [ $TRAVIS_GO_VERSION = 1.13.4 ] && | ||||
|   goveralls -coverprofile=coverage.coverprofile -service travis-ci -repotoken $COVERALLS_TOKEN | ||||
							
								
								
									
										21
									
								
								vendor/github.com/go-playground/universal-translator/LICENSE
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								vendor/github.com/go-playground/universal-translator/LICENSE
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,21 @@ | ||||
| The MIT License (MIT) | ||||
|  | ||||
| Copyright (c) 2016 Go Playground | ||||
|  | ||||
| Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
| of this software and associated documentation files (the "Software"), to deal | ||||
| in the Software without restriction, including without limitation the rights | ||||
| to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||||
| copies of the Software, and to permit persons to whom the Software is | ||||
| furnished to do so, subject to the following conditions: | ||||
|  | ||||
| The above copyright notice and this permission notice shall be included in all | ||||
| copies or substantial portions of the Software. | ||||
|  | ||||
| THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||||
| IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||||
| FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||||
| AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||||
| LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||||
| OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||||
| SOFTWARE. | ||||
							
								
								
									
										18
									
								
								vendor/github.com/go-playground/universal-translator/Makefile
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								vendor/github.com/go-playground/universal-translator/Makefile
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,18 @@ | ||||
| GOCMD=GO111MODULE=on go | ||||
|  | ||||
| linters-install: | ||||
| 	@golangci-lint --version >/dev/null 2>&1 || { \ | ||||
| 		echo "installing linting tools..."; \ | ||||
| 		curl -sfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh| sh -s v1.41.1; \ | ||||
| 	} | ||||
|  | ||||
| lint: linters-install | ||||
| 	golangci-lint run | ||||
|  | ||||
| test: | ||||
| 	$(GOCMD) test -cover -race ./... | ||||
|  | ||||
| bench: | ||||
| 	$(GOCMD) test -bench=. -benchmem ./... | ||||
|  | ||||
| .PHONY: test lint linters-install | ||||
							
								
								
									
										87
									
								
								vendor/github.com/go-playground/universal-translator/README.md
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										87
									
								
								vendor/github.com/go-playground/universal-translator/README.md
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,87 @@ | ||||
| ## universal-translator | ||||
| <img align="right" src="https://raw.githubusercontent.com/go-playground/universal-translator/master/logo.png"> | ||||
| [](https://coveralls.io/github/go-playground/universal-translator) | ||||
| [](https://goreportcard.com/report/github.com/go-playground/universal-translator) | ||||
| [](https://godoc.org/github.com/go-playground/universal-translator) | ||||
|  | ||||
|  | ||||
| Universal Translator is an i18n Translator for Go/Golang using CLDR data + pluralization rules | ||||
|  | ||||
| Why another i18n library? | ||||
| -------------------------- | ||||
| Because none of the plural rules seem to be correct out there, including the previous implementation of this package, | ||||
| so I took it upon myself to create [locales](https://github.com/go-playground/locales) for everyone to use; this package  | ||||
| is a thin wrapper around [locales](https://github.com/go-playground/locales) in order to store and translate text for  | ||||
| use in your applications. | ||||
|  | ||||
| Features | ||||
| -------- | ||||
| - [x] Rules generated from the [CLDR](http://cldr.unicode.org/index/downloads) data, v36.0.1 | ||||
| - [x] Contains Cardinal, Ordinal and Range Plural Rules | ||||
| - [x] Contains Month, Weekday and Timezone translations built in | ||||
| - [x] Contains Date & Time formatting functions | ||||
| - [x] Contains Number, Currency, Accounting and Percent formatting functions | ||||
| - [x] Supports the "Gregorian" calendar only ( my time isn't unlimited, had to draw the line somewhere ) | ||||
| - [x] Support loading translations from files | ||||
| - [x] Exporting translations to file(s), mainly for getting them professionally translated | ||||
| - [ ] Code Generation for translation files -> Go code.. i.e. after it has been professionally translated | ||||
| - [ ] Tests for all languages, I need help with this, please see [here](https://github.com/go-playground/locales/issues/1) | ||||
|  | ||||
| Installation | ||||
| ----------- | ||||
|  | ||||
| Use go get  | ||||
|  | ||||
| ```shell | ||||
| go get github.com/go-playground/universal-translator | ||||
| ``` | ||||
|  | ||||
| Usage & Documentation | ||||
| ------- | ||||
|  | ||||
| Please see https://godoc.org/github.com/go-playground/universal-translator for usage docs | ||||
|  | ||||
| ##### Examples: | ||||
|  | ||||
| - [Basic](https://github.com/go-playground/universal-translator/tree/master/_examples/basic) | ||||
| - [Full - no files](https://github.com/go-playground/universal-translator/tree/master/_examples/full-no-files) | ||||
| - [Full - with files](https://github.com/go-playground/universal-translator/tree/master/_examples/full-with-files) | ||||
|  | ||||
| File formatting | ||||
| -------------- | ||||
| All types, Plain substitution, Cardinal, Ordinal and Range translations can all be contained within the same file(s); | ||||
| they are only separated for easy viewing. | ||||
|  | ||||
| ##### Examples: | ||||
|  | ||||
| - [Formats](https://github.com/go-playground/universal-translator/tree/master/_examples/file-formats) | ||||
|  | ||||
| ##### Basic Makeup | ||||
| NOTE: not all fields are needed for all translation types, see [examples](https://github.com/go-playground/universal-translator/tree/master/_examples/file-formats) | ||||
| ```json | ||||
| { | ||||
|     "locale": "en", | ||||
|     "key": "days-left", | ||||
|     "trans": "You have {0} day left.", | ||||
|     "type": "Cardinal", | ||||
|     "rule": "One", | ||||
|     "override": false | ||||
| } | ||||
| ``` | ||||
| |Field|Description| | ||||
| |---|---| | ||||
| |locale|The locale for which the translation is for.| | ||||
| |key|The translation key that will be used to store and lookup each translation; normally it is a string or integer.| | ||||
| |trans|The actual translation text.| | ||||
| |type|The type of translation Cardinal, Ordinal, Range or "" for a plain substitution(not required to be defined if plain used)| | ||||
| |rule|The plural rule for which the translation is for eg. One, Two, Few, Many or Other.(not required to be defined if plain used)| | ||||
| |override|If you wish to override an existing translation that has already been registered, set this to 'true'. 99% of the time there is no need to define it.| | ||||
|  | ||||
| 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/locales/issues/1) for details. | ||||
|  | ||||
| License | ||||
| ------ | ||||
| Distributed under MIT License, please see license file in code for more details. | ||||
							
								
								
									
										148
									
								
								vendor/github.com/go-playground/universal-translator/errors.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										148
									
								
								vendor/github.com/go-playground/universal-translator/errors.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,148 @@ | ||||
| package ut | ||||
|  | ||||
| import ( | ||||
| 	"errors" | ||||
| 	"fmt" | ||||
|  | ||||
| 	"github.com/go-playground/locales" | ||||
| ) | ||||
|  | ||||
| var ( | ||||
| 	// ErrUnknowTranslation indicates the translation could not be found | ||||
| 	ErrUnknowTranslation = errors.New("Unknown Translation") | ||||
| ) | ||||
|  | ||||
| var _ error = new(ErrConflictingTranslation) | ||||
| var _ error = new(ErrRangeTranslation) | ||||
| var _ error = new(ErrOrdinalTranslation) | ||||
| var _ error = new(ErrCardinalTranslation) | ||||
| var _ error = new(ErrMissingPluralTranslation) | ||||
| var _ error = new(ErrExistingTranslator) | ||||
|  | ||||
| // ErrExistingTranslator is the error representing a conflicting translator | ||||
| type ErrExistingTranslator struct { | ||||
| 	locale string | ||||
| } | ||||
|  | ||||
| // Error returns ErrExistingTranslator's internal error text | ||||
| func (e *ErrExistingTranslator) Error() string { | ||||
| 	return fmt.Sprintf("error: conflicting translator for locale '%s'", e.locale) | ||||
| } | ||||
|  | ||||
| // ErrConflictingTranslation is the error representing a conflicting translation | ||||
| type ErrConflictingTranslation struct { | ||||
| 	locale string | ||||
| 	key    interface{} | ||||
| 	rule   locales.PluralRule | ||||
| 	text   string | ||||
| } | ||||
|  | ||||
| // Error returns ErrConflictingTranslation's internal error text | ||||
| func (e *ErrConflictingTranslation) Error() string { | ||||
|  | ||||
| 	if _, ok := e.key.(string); !ok { | ||||
| 		return fmt.Sprintf("error: conflicting key '%#v' rule '%s' with text '%s' for locale '%s', value being ignored", e.key, e.rule, e.text, e.locale) | ||||
| 	} | ||||
|  | ||||
| 	return fmt.Sprintf("error: conflicting key '%s' rule '%s' with text '%s' for locale '%s', value being ignored", e.key, e.rule, e.text, e.locale) | ||||
| } | ||||
|  | ||||
| // ErrRangeTranslation is the error representing a range translation error | ||||
| type ErrRangeTranslation struct { | ||||
| 	text string | ||||
| } | ||||
|  | ||||
| // Error returns ErrRangeTranslation's internal error text | ||||
| func (e *ErrRangeTranslation) Error() string { | ||||
| 	return e.text | ||||
| } | ||||
|  | ||||
| // ErrOrdinalTranslation is the error representing an ordinal translation error | ||||
| type ErrOrdinalTranslation struct { | ||||
| 	text string | ||||
| } | ||||
|  | ||||
| // Error returns ErrOrdinalTranslation's internal error text | ||||
| func (e *ErrOrdinalTranslation) Error() string { | ||||
| 	return e.text | ||||
| } | ||||
|  | ||||
| // ErrCardinalTranslation is the error representing a cardinal translation error | ||||
| type ErrCardinalTranslation struct { | ||||
| 	text string | ||||
| } | ||||
|  | ||||
| // Error returns ErrCardinalTranslation's internal error text | ||||
| func (e *ErrCardinalTranslation) Error() string { | ||||
| 	return e.text | ||||
| } | ||||
|  | ||||
| // ErrMissingPluralTranslation is the error signifying a missing translation given | ||||
| // the locales plural rules. | ||||
| type ErrMissingPluralTranslation struct { | ||||
| 	locale          string | ||||
| 	key             interface{} | ||||
| 	rule            locales.PluralRule | ||||
| 	translationType string | ||||
| } | ||||
|  | ||||
| // Error returns ErrMissingPluralTranslation's internal error text | ||||
| func (e *ErrMissingPluralTranslation) Error() string { | ||||
|  | ||||
| 	if _, ok := e.key.(string); !ok { | ||||
| 		return fmt.Sprintf("error: missing '%s' plural rule '%s' for translation with key '%#v' and locale '%s'", e.translationType, e.rule, e.key, e.locale) | ||||
| 	} | ||||
|  | ||||
| 	return fmt.Sprintf("error: missing '%s' plural rule '%s' for translation with key '%s' and locale '%s'", e.translationType, e.rule, e.key, e.locale) | ||||
| } | ||||
|  | ||||
| // ErrMissingBracket is the error representing a missing bracket in a translation | ||||
| // eg. This is a {0 <-- missing ending '}' | ||||
| type ErrMissingBracket struct { | ||||
| 	locale string | ||||
| 	key    interface{} | ||||
| 	text   string | ||||
| } | ||||
|  | ||||
| // Error returns ErrMissingBracket error message | ||||
| func (e *ErrMissingBracket) Error() string { | ||||
| 	return fmt.Sprintf("error: missing bracket '{}', in translation. locale: '%s' key: '%v' text: '%s'", e.locale, e.key, e.text) | ||||
| } | ||||
|  | ||||
| // ErrBadParamSyntax is the error representing a bad parameter definition in a translation | ||||
| // eg. This is a {must-be-int} | ||||
| type ErrBadParamSyntax struct { | ||||
| 	locale string | ||||
| 	param  string | ||||
| 	key    interface{} | ||||
| 	text   string | ||||
| } | ||||
|  | ||||
| // Error returns ErrBadParamSyntax error message | ||||
| func (e *ErrBadParamSyntax) Error() string { | ||||
| 	return fmt.Sprintf("error: bad parameter syntax, missing parameter '%s' in translation. locale: '%s' key: '%v' text: '%s'", e.param, e.locale, e.key, e.text) | ||||
| } | ||||
|  | ||||
| // import/export errors | ||||
|  | ||||
| // ErrMissingLocale is the error representing an expected locale that could | ||||
| // not be found aka locale not registered with the UniversalTranslator Instance | ||||
| type ErrMissingLocale struct { | ||||
| 	locale string | ||||
| } | ||||
|  | ||||
| // Error returns ErrMissingLocale's internal error text | ||||
| func (e *ErrMissingLocale) Error() string { | ||||
| 	return fmt.Sprintf("error: locale '%s' not registered.", e.locale) | ||||
| } | ||||
|  | ||||
| // ErrBadPluralDefinition is the error representing an incorrect plural definition | ||||
| // usually found within translations defined within files during the import process. | ||||
| type ErrBadPluralDefinition struct { | ||||
| 	tl translation | ||||
| } | ||||
|  | ||||
| // Error returns ErrBadPluralDefinition's internal error text | ||||
| func (e *ErrBadPluralDefinition) Error() string { | ||||
| 	return fmt.Sprintf("error: bad plural definition '%#v'", e.tl) | ||||
| } | ||||
							
								
								
									
										274
									
								
								vendor/github.com/go-playground/universal-translator/import_export.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										274
									
								
								vendor/github.com/go-playground/universal-translator/import_export.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,274 @@ | ||||
| package ut | ||||
|  | ||||
| import ( | ||||
| 	"encoding/json" | ||||
| 	"fmt" | ||||
| 	"os" | ||||
| 	"path/filepath" | ||||
|  | ||||
| 	"io" | ||||
|  | ||||
| 	"github.com/go-playground/locales" | ||||
| ) | ||||
|  | ||||
| type translation struct { | ||||
| 	Locale           string      `json:"locale"` | ||||
| 	Key              interface{} `json:"key"` // either string or integer | ||||
| 	Translation      string      `json:"trans"` | ||||
| 	PluralType       string      `json:"type,omitempty"` | ||||
| 	PluralRule       string      `json:"rule,omitempty"` | ||||
| 	OverrideExisting bool        `json:"override,omitempty"` | ||||
| } | ||||
|  | ||||
| const ( | ||||
| 	cardinalType = "Cardinal" | ||||
| 	ordinalType  = "Ordinal" | ||||
| 	rangeType    = "Range" | ||||
| ) | ||||
|  | ||||
| // ImportExportFormat is the format of the file import or export | ||||
| type ImportExportFormat uint8 | ||||
|  | ||||
| // supported Export Formats | ||||
| const ( | ||||
| 	FormatJSON ImportExportFormat = iota | ||||
| ) | ||||
|  | ||||
| // Export writes the translations out to a file on disk. | ||||
| // | ||||
| // NOTE: this currently only works with string or int translations keys. | ||||
| func (t *UniversalTranslator) Export(format ImportExportFormat, dirname string) error { | ||||
|  | ||||
| 	_, err := os.Stat(dirname) | ||||
| 	if err != nil { | ||||
|  | ||||
| 		if !os.IsNotExist(err) { | ||||
| 			return err | ||||
| 		} | ||||
|  | ||||
| 		if err = os.MkdirAll(dirname, 0744); err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	// build up translations | ||||
| 	var trans []translation | ||||
| 	var b []byte | ||||
| 	var ext string | ||||
|  | ||||
| 	for _, locale := range t.translators { | ||||
|  | ||||
| 		for k, v := range locale.(*translator).translations { | ||||
| 			trans = append(trans, translation{ | ||||
| 				Locale:      locale.Locale(), | ||||
| 				Key:         k, | ||||
| 				Translation: v.text, | ||||
| 			}) | ||||
| 		} | ||||
|  | ||||
| 		for k, pluralTrans := range locale.(*translator).cardinalTanslations { | ||||
|  | ||||
| 			for i, plural := range pluralTrans { | ||||
|  | ||||
| 				// leave enough for all plural rules | ||||
| 				// but not all are set for all languages. | ||||
| 				if plural == nil { | ||||
| 					continue | ||||
| 				} | ||||
|  | ||||
| 				trans = append(trans, translation{ | ||||
| 					Locale:      locale.Locale(), | ||||
| 					Key:         k.(string), | ||||
| 					Translation: plural.text, | ||||
| 					PluralType:  cardinalType, | ||||
| 					PluralRule:  locales.PluralRule(i).String(), | ||||
| 				}) | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 		for k, pluralTrans := range locale.(*translator).ordinalTanslations { | ||||
|  | ||||
| 			for i, plural := range pluralTrans { | ||||
|  | ||||
| 				// leave enough for all plural rules | ||||
| 				// but not all are set for all languages. | ||||
| 				if plural == nil { | ||||
| 					continue | ||||
| 				} | ||||
|  | ||||
| 				trans = append(trans, translation{ | ||||
| 					Locale:      locale.Locale(), | ||||
| 					Key:         k.(string), | ||||
| 					Translation: plural.text, | ||||
| 					PluralType:  ordinalType, | ||||
| 					PluralRule:  locales.PluralRule(i).String(), | ||||
| 				}) | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 		for k, pluralTrans := range locale.(*translator).rangeTanslations { | ||||
|  | ||||
| 			for i, plural := range pluralTrans { | ||||
|  | ||||
| 				// leave enough for all plural rules | ||||
| 				// but not all are set for all languages. | ||||
| 				if plural == nil { | ||||
| 					continue | ||||
| 				} | ||||
|  | ||||
| 				trans = append(trans, translation{ | ||||
| 					Locale:      locale.Locale(), | ||||
| 					Key:         k.(string), | ||||
| 					Translation: plural.text, | ||||
| 					PluralType:  rangeType, | ||||
| 					PluralRule:  locales.PluralRule(i).String(), | ||||
| 				}) | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 		switch format { | ||||
| 		case FormatJSON: | ||||
| 			b, err = json.MarshalIndent(trans, "", "    ") | ||||
| 			ext = ".json" | ||||
| 		} | ||||
|  | ||||
| 		if err != nil { | ||||
| 			return err | ||||
| 		} | ||||
|  | ||||
| 		err = os.WriteFile(filepath.Join(dirname, fmt.Sprintf("%s%s", locale.Locale(), ext)), b, 0644) | ||||
| 		if err != nil { | ||||
| 			return err | ||||
| 		} | ||||
|  | ||||
| 		trans = trans[0:0] | ||||
| 	} | ||||
|  | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| // Import reads the translations out of a file or directory on disk. | ||||
| // | ||||
| // NOTE: this currently only works with string or int translations keys. | ||||
| func (t *UniversalTranslator) Import(format ImportExportFormat, dirnameOrFilename string) error { | ||||
|  | ||||
| 	fi, err := os.Stat(dirnameOrFilename) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	processFn := func(filename string) error { | ||||
|  | ||||
| 		f, err := os.Open(filename) | ||||
| 		if err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| 		defer f.Close() | ||||
|  | ||||
| 		return t.ImportByReader(format, f) | ||||
| 	} | ||||
|  | ||||
| 	if !fi.IsDir() { | ||||
| 		return processFn(dirnameOrFilename) | ||||
| 	} | ||||
|  | ||||
| 	// recursively go through directory | ||||
| 	walker := func(path string, info os.FileInfo, err error) error { | ||||
|  | ||||
| 		if info.IsDir() { | ||||
| 			return nil | ||||
| 		} | ||||
|  | ||||
| 		switch format { | ||||
| 		case FormatJSON: | ||||
| 			// skip non JSON files | ||||
| 			if filepath.Ext(info.Name()) != ".json" { | ||||
| 				return nil | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 		return processFn(path) | ||||
| 	} | ||||
|  | ||||
| 	return filepath.Walk(dirnameOrFilename, walker) | ||||
| } | ||||
|  | ||||
| // ImportByReader imports the the translations found within the contents read from the supplied reader. | ||||
| // | ||||
| // NOTE: generally used when assets have been embedded into the binary and are already in memory. | ||||
| func (t *UniversalTranslator) ImportByReader(format ImportExportFormat, reader io.Reader) error { | ||||
|  | ||||
| 	b, err := io.ReadAll(reader) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	var trans []translation | ||||
|  | ||||
| 	switch format { | ||||
| 	case FormatJSON: | ||||
| 		err = json.Unmarshal(b, &trans) | ||||
| 	} | ||||
|  | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	for _, tl := range trans { | ||||
|  | ||||
| 		locale, found := t.FindTranslator(tl.Locale) | ||||
| 		if !found { | ||||
| 			return &ErrMissingLocale{locale: tl.Locale} | ||||
| 		} | ||||
|  | ||||
| 		pr := stringToPR(tl.PluralRule) | ||||
|  | ||||
| 		if pr == locales.PluralRuleUnknown { | ||||
|  | ||||
| 			err = locale.Add(tl.Key, tl.Translation, tl.OverrideExisting) | ||||
| 			if err != nil { | ||||
| 				return err | ||||
| 			} | ||||
|  | ||||
| 			continue | ||||
| 		} | ||||
|  | ||||
| 		switch tl.PluralType { | ||||
| 		case cardinalType: | ||||
| 			err = locale.AddCardinal(tl.Key, tl.Translation, pr, tl.OverrideExisting) | ||||
| 		case ordinalType: | ||||
| 			err = locale.AddOrdinal(tl.Key, tl.Translation, pr, tl.OverrideExisting) | ||||
| 		case rangeType: | ||||
| 			err = locale.AddRange(tl.Key, tl.Translation, pr, tl.OverrideExisting) | ||||
| 		default: | ||||
| 			return &ErrBadPluralDefinition{tl: tl} | ||||
| 		} | ||||
|  | ||||
| 		if err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| func stringToPR(s string) locales.PluralRule { | ||||
|  | ||||
| 	switch s { | ||||
| 	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 | ||||
| 	} | ||||
|  | ||||
| } | ||||
							
								
								
									
										
											BIN
										
									
								
								vendor/github.com/go-playground/universal-translator/logo.png
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								vendor/github.com/go-playground/universal-translator/logo.png
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| After Width: | Height: | Size: 16 KiB | 
							
								
								
									
										420
									
								
								vendor/github.com/go-playground/universal-translator/translator.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										420
									
								
								vendor/github.com/go-playground/universal-translator/translator.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,420 @@ | ||||
| package ut | ||||
|  | ||||
| import ( | ||||
| 	"fmt" | ||||
| 	"strconv" | ||||
| 	"strings" | ||||
|  | ||||
| 	"github.com/go-playground/locales" | ||||
| ) | ||||
|  | ||||
| const ( | ||||
| 	paramZero          = "{0}" | ||||
| 	paramOne           = "{1}" | ||||
| 	unknownTranslation = "" | ||||
| ) | ||||
|  | ||||
| // Translator is universal translators | ||||
| // translator instance which is a thin wrapper | ||||
| // around locales.Translator instance providing | ||||
| // some extra functionality | ||||
| type Translator interface { | ||||
| 	locales.Translator | ||||
|  | ||||
| 	// adds a normal translation for a particular language/locale | ||||
| 	// {#} is the only replacement type accepted and are ad infinitum | ||||
| 	// eg. one: '{0} day left' other: '{0} days left' | ||||
| 	Add(key interface{}, text string, override bool) error | ||||
|  | ||||
| 	// adds a cardinal plural translation for a particular language/locale | ||||
| 	// {0} is the only replacement type accepted and only one variable is accepted as | ||||
| 	// multiple cannot be used for a plural rule determination, unless it is a range; | ||||
| 	// see AddRange below. | ||||
| 	// eg. in locale 'en' one: '{0} day left' other: '{0} days left' | ||||
| 	AddCardinal(key interface{}, text string, rule locales.PluralRule, override bool) error | ||||
|  | ||||
| 	// adds an ordinal plural translation for a particular language/locale | ||||
| 	// {0} is the only replacement type accepted and only one variable is accepted as | ||||
| 	// multiple cannot be used for a plural rule determination, unless it is a range; | ||||
| 	// see AddRange below. | ||||
| 	// eg. in locale 'en' one: '{0}st day of spring' other: '{0}nd day of spring' | ||||
| 	// - 1st, 2nd, 3rd... | ||||
| 	AddOrdinal(key interface{}, text string, rule locales.PluralRule, override bool) error | ||||
|  | ||||
| 	// adds a range plural translation for a particular language/locale | ||||
| 	// {0} and {1} are the only replacement types accepted and only these are accepted. | ||||
| 	// eg. in locale 'nl' one: '{0}-{1} day left' other: '{0}-{1} days left' | ||||
| 	AddRange(key interface{}, text string, rule locales.PluralRule, override bool) error | ||||
|  | ||||
| 	// creates the translation for the locale given the 'key' and params passed in | ||||
| 	T(key interface{}, params ...string) (string, error) | ||||
|  | ||||
| 	// creates the cardinal translation for the locale given the 'key', 'num' and 'digit' arguments | ||||
| 	//  and param passed in | ||||
| 	C(key interface{}, num float64, digits uint64, param string) (string, error) | ||||
|  | ||||
| 	// creates the ordinal translation for the locale given the 'key', 'num' and 'digit' arguments | ||||
| 	// and param passed in | ||||
| 	O(key interface{}, num float64, digits uint64, param string) (string, error) | ||||
|  | ||||
| 	//  creates the range translation for the locale given the 'key', 'num1', 'digit1', 'num2' and | ||||
| 	//  'digit2' arguments and 'param1' and 'param2' passed in | ||||
| 	R(key interface{}, num1 float64, digits1 uint64, num2 float64, digits2 uint64, param1, param2 string) (string, error) | ||||
|  | ||||
| 	// VerifyTranslations checks to ensures that no plural rules have been | ||||
| 	// missed within the translations. | ||||
| 	VerifyTranslations() error | ||||
| } | ||||
|  | ||||
| var _ Translator = new(translator) | ||||
| var _ locales.Translator = new(translator) | ||||
|  | ||||
| type translator struct { | ||||
| 	locales.Translator | ||||
| 	translations        map[interface{}]*transText | ||||
| 	cardinalTanslations map[interface{}][]*transText // array index is mapped to locales.PluralRule index + the locales.PluralRuleUnknown | ||||
| 	ordinalTanslations  map[interface{}][]*transText | ||||
| 	rangeTanslations    map[interface{}][]*transText | ||||
| } | ||||
|  | ||||
| type transText struct { | ||||
| 	text    string | ||||
| 	indexes []int | ||||
| } | ||||
|  | ||||
| func newTranslator(trans locales.Translator) Translator { | ||||
| 	return &translator{ | ||||
| 		Translator:          trans, | ||||
| 		translations:        make(map[interface{}]*transText), // translation text broken up by byte index | ||||
| 		cardinalTanslations: make(map[interface{}][]*transText), | ||||
| 		ordinalTanslations:  make(map[interface{}][]*transText), | ||||
| 		rangeTanslations:    make(map[interface{}][]*transText), | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // Add adds a normal translation for a particular language/locale | ||||
| // {#} is the only replacement type accepted and are ad infinitum | ||||
| // eg. one: '{0} day left' other: '{0} days left' | ||||
| func (t *translator) Add(key interface{}, text string, override bool) error { | ||||
|  | ||||
| 	if _, ok := t.translations[key]; ok && !override { | ||||
| 		return &ErrConflictingTranslation{locale: t.Locale(), key: key, text: text} | ||||
| 	} | ||||
|  | ||||
| 	lb := strings.Count(text, "{") | ||||
| 	rb := strings.Count(text, "}") | ||||
|  | ||||
| 	if lb != rb { | ||||
| 		return &ErrMissingBracket{locale: t.Locale(), key: key, text: text} | ||||
| 	} | ||||
|  | ||||
| 	trans := &transText{ | ||||
| 		text: text, | ||||
| 	} | ||||
|  | ||||
| 	var idx int | ||||
|  | ||||
| 	for i := 0; i < lb; i++ { | ||||
| 		s := "{" + strconv.Itoa(i) + "}" | ||||
| 		idx = strings.Index(text, s) | ||||
| 		if idx == -1 { | ||||
| 			return &ErrBadParamSyntax{locale: t.Locale(), param: s, key: key, text: text} | ||||
| 		} | ||||
|  | ||||
| 		trans.indexes = append(trans.indexes, idx) | ||||
| 		trans.indexes = append(trans.indexes, idx+len(s)) | ||||
| 	} | ||||
|  | ||||
| 	t.translations[key] = trans | ||||
|  | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| // AddCardinal adds a cardinal plural translation for a particular language/locale | ||||
| // {0} is the only replacement type accepted and only one variable is accepted as | ||||
| // multiple cannot be used for a plural rule determination, unless it is a range; | ||||
| // see AddRange below. | ||||
| // eg. in locale 'en' one: '{0} day left' other: '{0} days left' | ||||
| func (t *translator) AddCardinal(key interface{}, text string, rule locales.PluralRule, override bool) error { | ||||
|  | ||||
| 	var verified bool | ||||
|  | ||||
| 	// verify plural rule exists for locale | ||||
| 	for _, pr := range t.PluralsCardinal() { | ||||
| 		if pr == rule { | ||||
| 			verified = true | ||||
| 			break | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	if !verified { | ||||
| 		return &ErrCardinalTranslation{text: fmt.Sprintf("error: cardinal plural rule '%s' does not exist for locale '%s' key: '%v' text: '%s'", rule, t.Locale(), key, text)} | ||||
| 	} | ||||
|  | ||||
| 	tarr, ok := t.cardinalTanslations[key] | ||||
| 	if ok { | ||||
| 		// verify not adding a conflicting record | ||||
| 		if len(tarr) > 0 && tarr[rule] != nil && !override { | ||||
| 			return &ErrConflictingTranslation{locale: t.Locale(), key: key, rule: rule, text: text} | ||||
| 		} | ||||
|  | ||||
| 	} else { | ||||
| 		tarr = make([]*transText, 7) | ||||
| 		t.cardinalTanslations[key] = tarr | ||||
| 	} | ||||
|  | ||||
| 	trans := &transText{ | ||||
| 		text:    text, | ||||
| 		indexes: make([]int, 2), | ||||
| 	} | ||||
|  | ||||
| 	tarr[rule] = trans | ||||
|  | ||||
| 	idx := strings.Index(text, paramZero) | ||||
| 	if idx == -1 { | ||||
| 		tarr[rule] = nil | ||||
| 		return &ErrCardinalTranslation{text: fmt.Sprintf("error: parameter '%s' not found, may want to use 'Add' instead of 'AddCardinal'. locale: '%s' key: '%v' text: '%s'", paramZero, t.Locale(), key, text)} | ||||
| 	} | ||||
|  | ||||
| 	trans.indexes[0] = idx | ||||
| 	trans.indexes[1] = idx + len(paramZero) | ||||
|  | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| // AddOrdinal adds an ordinal plural translation for a particular language/locale | ||||
| // {0} is the only replacement type accepted and only one variable is accepted as | ||||
| // multiple cannot be used for a plural rule determination, unless it is a range; | ||||
| // see AddRange below. | ||||
| // eg. in locale 'en' one: '{0}st day of spring' other: '{0}nd day of spring' - 1st, 2nd, 3rd... | ||||
| func (t *translator) AddOrdinal(key interface{}, text string, rule locales.PluralRule, override bool) error { | ||||
|  | ||||
| 	var verified bool | ||||
|  | ||||
| 	// verify plural rule exists for locale | ||||
| 	for _, pr := range t.PluralsOrdinal() { | ||||
| 		if pr == rule { | ||||
| 			verified = true | ||||
| 			break | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	if !verified { | ||||
| 		return &ErrOrdinalTranslation{text: fmt.Sprintf("error: ordinal plural rule '%s' does not exist for locale '%s' key: '%v' text: '%s'", rule, t.Locale(), key, text)} | ||||
| 	} | ||||
|  | ||||
| 	tarr, ok := t.ordinalTanslations[key] | ||||
| 	if ok { | ||||
| 		// verify not adding a conflicting record | ||||
| 		if len(tarr) > 0 && tarr[rule] != nil && !override { | ||||
| 			return &ErrConflictingTranslation{locale: t.Locale(), key: key, rule: rule, text: text} | ||||
| 		} | ||||
|  | ||||
| 	} else { | ||||
| 		tarr = make([]*transText, 7) | ||||
| 		t.ordinalTanslations[key] = tarr | ||||
| 	} | ||||
|  | ||||
| 	trans := &transText{ | ||||
| 		text:    text, | ||||
| 		indexes: make([]int, 2), | ||||
| 	} | ||||
|  | ||||
| 	tarr[rule] = trans | ||||
|  | ||||
| 	idx := strings.Index(text, paramZero) | ||||
| 	if idx == -1 { | ||||
| 		tarr[rule] = nil | ||||
| 		return &ErrOrdinalTranslation{text: fmt.Sprintf("error: parameter '%s' not found, may want to use 'Add' instead of 'AddOrdinal'. locale: '%s' key: '%v' text: '%s'", paramZero, t.Locale(), key, text)} | ||||
| 	} | ||||
|  | ||||
| 	trans.indexes[0] = idx | ||||
| 	trans.indexes[1] = idx + len(paramZero) | ||||
|  | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| // AddRange adds a range plural translation for a particular language/locale | ||||
| // {0} and {1} are the only replacement types accepted and only these are accepted. | ||||
| // eg. in locale 'nl' one: '{0}-{1} day left' other: '{0}-{1} days left' | ||||
| func (t *translator) AddRange(key interface{}, text string, rule locales.PluralRule, override bool) error { | ||||
|  | ||||
| 	var verified bool | ||||
|  | ||||
| 	// verify plural rule exists for locale | ||||
| 	for _, pr := range t.PluralsRange() { | ||||
| 		if pr == rule { | ||||
| 			verified = true | ||||
| 			break | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	if !verified { | ||||
| 		return &ErrRangeTranslation{text: fmt.Sprintf("error: range plural rule '%s' does not exist for locale '%s' key: '%v' text: '%s'", rule, t.Locale(), key, text)} | ||||
| 	} | ||||
|  | ||||
| 	tarr, ok := t.rangeTanslations[key] | ||||
| 	if ok { | ||||
| 		// verify not adding a conflicting record | ||||
| 		if len(tarr) > 0 && tarr[rule] != nil && !override { | ||||
| 			return &ErrConflictingTranslation{locale: t.Locale(), key: key, rule: rule, text: text} | ||||
| 		} | ||||
|  | ||||
| 	} else { | ||||
| 		tarr = make([]*transText, 7) | ||||
| 		t.rangeTanslations[key] = tarr | ||||
| 	} | ||||
|  | ||||
| 	trans := &transText{ | ||||
| 		text:    text, | ||||
| 		indexes: make([]int, 4), | ||||
| 	} | ||||
|  | ||||
| 	tarr[rule] = trans | ||||
|  | ||||
| 	idx := strings.Index(text, paramZero) | ||||
| 	if idx == -1 { | ||||
| 		tarr[rule] = nil | ||||
| 		return &ErrRangeTranslation{text: fmt.Sprintf("error: parameter '%s' not found, are you sure you're adding a Range Translation? locale: '%s' key: '%v' text: '%s'", paramZero, t.Locale(), key, text)} | ||||
| 	} | ||||
|  | ||||
| 	trans.indexes[0] = idx | ||||
| 	trans.indexes[1] = idx + len(paramZero) | ||||
|  | ||||
| 	idx = strings.Index(text, paramOne) | ||||
| 	if idx == -1 { | ||||
| 		tarr[rule] = nil | ||||
| 		return &ErrRangeTranslation{text: fmt.Sprintf("error: parameter '%s' not found, a Range Translation requires two parameters. locale: '%s' key: '%v' text: '%s'", paramOne, t.Locale(), key, text)} | ||||
| 	} | ||||
|  | ||||
| 	trans.indexes[2] = idx | ||||
| 	trans.indexes[3] = idx + len(paramOne) | ||||
|  | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| // T creates the translation for the locale given the 'key' and params passed in | ||||
| func (t *translator) T(key interface{}, params ...string) (string, error) { | ||||
|  | ||||
| 	trans, ok := t.translations[key] | ||||
| 	if !ok { | ||||
| 		return unknownTranslation, ErrUnknowTranslation | ||||
| 	} | ||||
|  | ||||
| 	b := make([]byte, 0, 64) | ||||
|  | ||||
| 	var start, end, count int | ||||
|  | ||||
| 	for i := 0; i < len(trans.indexes); i++ { | ||||
| 		end = trans.indexes[i] | ||||
| 		b = append(b, trans.text[start:end]...) | ||||
| 		b = append(b, params[count]...) | ||||
| 		i++ | ||||
| 		start = trans.indexes[i] | ||||
| 		count++ | ||||
| 	} | ||||
|  | ||||
| 	b = append(b, trans.text[start:]...) | ||||
|  | ||||
| 	return string(b), nil | ||||
| } | ||||
|  | ||||
| // C creates the cardinal translation for the locale given the 'key', 'num' and 'digit' arguments and param passed in | ||||
| func (t *translator) C(key interface{}, num float64, digits uint64, param string) (string, error) { | ||||
|  | ||||
| 	tarr, ok := t.cardinalTanslations[key] | ||||
| 	if !ok { | ||||
| 		return unknownTranslation, ErrUnknowTranslation | ||||
| 	} | ||||
|  | ||||
| 	rule := t.CardinalPluralRule(num, digits) | ||||
|  | ||||
| 	trans := tarr[rule] | ||||
|  | ||||
| 	b := make([]byte, 0, 64) | ||||
| 	b = append(b, trans.text[:trans.indexes[0]]...) | ||||
| 	b = append(b, param...) | ||||
| 	b = append(b, trans.text[trans.indexes[1]:]...) | ||||
|  | ||||
| 	return string(b), nil | ||||
| } | ||||
|  | ||||
| // O creates the ordinal translation for the locale given the 'key', 'num' and 'digit' arguments and param passed in | ||||
| func (t *translator) O(key interface{}, num float64, digits uint64, param string) (string, error) { | ||||
|  | ||||
| 	tarr, ok := t.ordinalTanslations[key] | ||||
| 	if !ok { | ||||
| 		return unknownTranslation, ErrUnknowTranslation | ||||
| 	} | ||||
|  | ||||
| 	rule := t.OrdinalPluralRule(num, digits) | ||||
|  | ||||
| 	trans := tarr[rule] | ||||
|  | ||||
| 	b := make([]byte, 0, 64) | ||||
| 	b = append(b, trans.text[:trans.indexes[0]]...) | ||||
| 	b = append(b, param...) | ||||
| 	b = append(b, trans.text[trans.indexes[1]:]...) | ||||
|  | ||||
| 	return string(b), nil | ||||
| } | ||||
|  | ||||
| // R creates the range translation for the locale given the 'key', 'num1', 'digit1', 'num2' and 'digit2' arguments | ||||
| // and 'param1' and 'param2' passed in | ||||
| func (t *translator) R(key interface{}, num1 float64, digits1 uint64, num2 float64, digits2 uint64, param1, param2 string) (string, error) { | ||||
|  | ||||
| 	tarr, ok := t.rangeTanslations[key] | ||||
| 	if !ok { | ||||
| 		return unknownTranslation, ErrUnknowTranslation | ||||
| 	} | ||||
|  | ||||
| 	rule := t.RangePluralRule(num1, digits1, num2, digits2) | ||||
|  | ||||
| 	trans := tarr[rule] | ||||
|  | ||||
| 	b := make([]byte, 0, 64) | ||||
| 	b = append(b, trans.text[:trans.indexes[0]]...) | ||||
| 	b = append(b, param1...) | ||||
| 	b = append(b, trans.text[trans.indexes[1]:trans.indexes[2]]...) | ||||
| 	b = append(b, param2...) | ||||
| 	b = append(b, trans.text[trans.indexes[3]:]...) | ||||
|  | ||||
| 	return string(b), nil | ||||
| } | ||||
|  | ||||
| // VerifyTranslations checks to ensures that no plural rules have been | ||||
| // missed within the translations. | ||||
| func (t *translator) VerifyTranslations() error { | ||||
|  | ||||
| 	for k, v := range t.cardinalTanslations { | ||||
|  | ||||
| 		for _, rule := range t.PluralsCardinal() { | ||||
|  | ||||
| 			if v[rule] == nil { | ||||
| 				return &ErrMissingPluralTranslation{locale: t.Locale(), translationType: "plural", rule: rule, key: k} | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	for k, v := range t.ordinalTanslations { | ||||
|  | ||||
| 		for _, rule := range t.PluralsOrdinal() { | ||||
|  | ||||
| 			if v[rule] == nil { | ||||
| 				return &ErrMissingPluralTranslation{locale: t.Locale(), translationType: "ordinal", rule: rule, key: k} | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	for k, v := range t.rangeTanslations { | ||||
|  | ||||
| 		for _, rule := range t.PluralsRange() { | ||||
|  | ||||
| 			if v[rule] == nil { | ||||
| 				return &ErrMissingPluralTranslation{locale: t.Locale(), translationType: "range", rule: rule, key: k} | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	return nil | ||||
| } | ||||
							
								
								
									
										113
									
								
								vendor/github.com/go-playground/universal-translator/universal_translator.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										113
									
								
								vendor/github.com/go-playground/universal-translator/universal_translator.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,113 @@ | ||||
| package ut | ||||
|  | ||||
| import ( | ||||
| 	"strings" | ||||
|  | ||||
| 	"github.com/go-playground/locales" | ||||
| ) | ||||
|  | ||||
| // UniversalTranslator holds all locale & translation data | ||||
| type UniversalTranslator struct { | ||||
| 	translators map[string]Translator | ||||
| 	fallback    Translator | ||||
| } | ||||
|  | ||||
| // New returns a new UniversalTranslator instance set with | ||||
| // the fallback locale and locales it should support | ||||
| func New(fallback locales.Translator, supportedLocales ...locales.Translator) *UniversalTranslator { | ||||
|  | ||||
| 	t := &UniversalTranslator{ | ||||
| 		translators: make(map[string]Translator), | ||||
| 	} | ||||
|  | ||||
| 	for _, v := range supportedLocales { | ||||
|  | ||||
| 		trans := newTranslator(v) | ||||
| 		t.translators[strings.ToLower(trans.Locale())] = trans | ||||
|  | ||||
| 		if fallback.Locale() == v.Locale() { | ||||
| 			t.fallback = trans | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	if t.fallback == nil && fallback != nil { | ||||
| 		t.fallback = newTranslator(fallback) | ||||
| 	} | ||||
|  | ||||
| 	return t | ||||
| } | ||||
|  | ||||
| // 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 (t *UniversalTranslator) FindTranslator(locales ...string) (trans Translator, found bool) { | ||||
|  | ||||
| 	for _, locale := range locales { | ||||
|  | ||||
| 		if trans, found = t.translators[strings.ToLower(locale)]; found { | ||||
| 			return | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	return t.fallback, false | ||||
| } | ||||
|  | ||||
| // GetTranslator returns the specified translator for the given locale, | ||||
| // or fallback if not found | ||||
| func (t *UniversalTranslator) GetTranslator(locale string) (trans Translator, found bool) { | ||||
|  | ||||
| 	if trans, found = t.translators[strings.ToLower(locale)]; found { | ||||
| 		return | ||||
| 	} | ||||
|  | ||||
| 	return t.fallback, false | ||||
| } | ||||
|  | ||||
| // GetFallback returns the fallback locale | ||||
| func (t *UniversalTranslator) GetFallback() Translator { | ||||
| 	return t.fallback | ||||
| } | ||||
|  | ||||
| // AddTranslator adds the supplied translator, if it already exists the override param | ||||
| // will be checked and if false an error will be returned, otherwise the translator will be | ||||
| // overridden; if the fallback matches the supplied translator it will be overridden as well | ||||
| // NOTE: this is normally only used when translator is embedded within a library | ||||
| func (t *UniversalTranslator) AddTranslator(translator locales.Translator, override bool) error { | ||||
|  | ||||
| 	lc := strings.ToLower(translator.Locale()) | ||||
| 	_, ok := t.translators[lc] | ||||
| 	if ok && !override { | ||||
| 		return &ErrExistingTranslator{locale: translator.Locale()} | ||||
| 	} | ||||
|  | ||||
| 	trans := newTranslator(translator) | ||||
|  | ||||
| 	if t.fallback.Locale() == translator.Locale() { | ||||
|  | ||||
| 		// because it's optional to have a fallback, I don't impose that limitation | ||||
| 		// don't know why you wouldn't but... | ||||
| 		if !override { | ||||
| 			return &ErrExistingTranslator{locale: translator.Locale()} | ||||
| 		} | ||||
|  | ||||
| 		t.fallback = trans | ||||
| 	} | ||||
|  | ||||
| 	t.translators[lc] = trans | ||||
|  | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| // VerifyTranslations runs through all locales and identifies any issues | ||||
| // eg. missing plural rules for a locale | ||||
| func (t *UniversalTranslator) VerifyTranslations() (err error) { | ||||
|  | ||||
| 	for _, trans := range t.translators { | ||||
| 		err = trans.VerifyTranslations() | ||||
| 		if err != nil { | ||||
| 			return | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	return | ||||
| } | ||||
		Reference in New Issue
	
	Block a user