helper for easy translations check in transports

This commit is contained in:
Pavel 2019-11-20 14:18:40 +03:00
parent 41e873016f
commit 87b694bc08
2 changed files with 174 additions and 0 deletions

View File

@ -0,0 +1,114 @@
package core
import (
"errors"
"io/ioutil"
"os"
"path/filepath"
"sort"
"strings"
"github.com/gobuffalo/packr/v2"
"gopkg.in/yaml.v2"
)
// TranslationsExtractor is a tool to load raw translations data from files or from box.
// It is feasible to be used in tests in order to check translation files correctness.
// The easiest way to check correctness is to check keys in translations.
// TranslationsExtractor IS NOT supposed to check correctness of translations - it's just an extractor.
// Translations can be checked manually, or via external library like https://github.com/google/go-cmp
type TranslationsExtractor struct {
fileNameTemplate string
TranslationsBox *packr.Box
TranslationsPath string
}
// TranslationsExtractor constructor. Use "translate.{}.yml" as template if your translations are named like "translate.en.yml"
func NewTranslationsExtractor(fileNameTemplate string) *TranslationsExtractor {
return &TranslationsExtractor{fileNameTemplate: fileNameTemplate}
}
// unmarshalToMap returns map with unmarshaled data or error
func (t *TranslationsExtractor) unmarshalToMap(in []byte) (map[string]interface{}, error) {
var dataMap map[string]interface{}
if err := yaml.Unmarshal(in, &dataMap); err == nil {
return dataMap, nil
} else {
return dataMap, err
}
}
// loadYAMLBox loads YAML from box
func (t *TranslationsExtractor) loadYAMLBox(fileName string) (map[string]interface{}, error) {
var dataMap map[string]interface{}
if data, err := t.TranslationsBox.Find(fileName); err == nil {
return t.unmarshalToMap(data)
} else {
return dataMap, err
}
}
// loadYAMLFile loads YAML from file
func (t *TranslationsExtractor) loadYAMLFile(fileName string) (map[string]interface{}, error) {
var dataMap map[string]interface{}
if info, err := os.Stat(fileName); err == nil {
if !info.IsDir() {
if path, err := filepath.Abs(fileName); err == nil {
if source, err := ioutil.ReadFile(path); err == nil {
return t.unmarshalToMap(source)
} else {
return dataMap, err
}
} else {
return dataMap, err
}
} else {
return dataMap, errors.New("directory provided instead of file")
}
} else {
return dataMap, err
}
}
// loadYAML loads YAML from filesystem or from packr box - depends on what was configured. Can return error.
func (t *TranslationsExtractor) loadYAML(fileName string) (map[string]interface{}, error) {
if t.TranslationsBox != nil {
return t.loadYAMLBox(fileName)
} else if t.TranslationsPath != "" {
return t.loadYAMLFile(fileName)
} else {
return map[string]interface{}{}, errors.New("nor box nor translations directory was provided")
}
}
// GetMapKeys returns sorted map keys from map[string]interface{} - useful to check keys in several translation files
func (t *TranslationsExtractor) GetMapKeys(data map[string]interface{}) []string {
keys := make([]string, len(data))
i := 0
for k := range data {
keys[i] = k
i++
}
sort.Strings(keys)
return keys
}
// LoadLocale returns translation file data with provided locale
func (t *TranslationsExtractor) LoadLocale(locale string) (map[string]interface{}, error) {
return t.loadYAML(strings.Replace(t.fileNameTemplate, "{}", locale, 1))
}
// LoadLocaleKeys returns only sorted keys from translation file
func (t *TranslationsExtractor) LoadLocaleKeys(locale string) ([]string, error) {
if data, err := t.LoadLocale(locale); err == nil {
return t.GetMapKeys(data), nil
} else {
return []string{}, err
}
}

View File

@ -0,0 +1,60 @@
package core
import (
"io/ioutil"
"os"
"reflect"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/stretchr/testify/suite"
"gopkg.in/yaml.v2"
)
type TranslationsExtractorTest struct {
suite.Suite
extractor *TranslationsExtractor
}
func (t *TranslationsExtractorTest) SetupSuite() {
translation := map[string]string{
"test": "first",
"another": "second",
}
data, _ := yaml.Marshal(translation)
errWrite := ioutil.WriteFile("/tmp/translate.en.yml", data, os.ModePerm)
require.NoError(t.T(), errWrite)
t.extractor = NewTranslationsExtractor("translate.{}.yml")
t.extractor.TranslationsPath = "/tmp"
}
func (t *TranslationsExtractorTest) Test_LoadLocale() {
data, err := t.extractor.LoadLocale("en")
require.NoError(t.T(), err)
assert.Contains(t.T(), data, "test")
}
func (t *TranslationsExtractorTest) Test_GetMapKeys() {
testMap := map[string]interface{}{
"a": 1,
"b": 2,
"c": 3,
}
keys := []string{"a", "b", "c"}
mapKeys := t.extractor.GetMapKeys(testMap)
assert.True(t.T(), reflect.DeepEqual(keys, mapKeys))
}
func (t *TranslationsExtractorTest) Test_unmarshalToMap() {
translation := map[string]string{
"test": "first",
"another": "second",
}
data, _ := yaml.Marshal(translation)
mapData, err := t.extractor.unmarshalToMap(data)
require.NoError(t.T(), err)
assert.True(t.T(), reflect.DeepEqual(translation, mapData))
}