95 lines
2.4 KiB
Go
95 lines
2.4 KiB
Go
|
package main
|
||
|
|
||
|
import (
|
||
|
"reflect"
|
||
|
"regexp"
|
||
|
|
||
|
"github.com/pkg/errors"
|
||
|
"github.com/sirupsen/logrus"
|
||
|
|
||
|
"github.com/Luzifer/go_helpers/v2/str"
|
||
|
)
|
||
|
|
||
|
var langKeyFormat = regexp.MustCompile(`^[a-z]{2}(-[A-Z]{2})?$`)
|
||
|
|
||
|
func verify(tf translationFile) error {
|
||
|
var (
|
||
|
err error
|
||
|
keys []string
|
||
|
keyType = map[string]reflect.Type{}
|
||
|
)
|
||
|
|
||
|
for k, v := range tf.Reference.Translations {
|
||
|
keys = append(keys, k)
|
||
|
keyType[k] = reflect.TypeOf(v)
|
||
|
}
|
||
|
|
||
|
if !langKeyFormat.MatchString(tf.Reference.LanguageKey) {
|
||
|
return errors.New("reference contains invalid languageKey")
|
||
|
}
|
||
|
|
||
|
if len(keys) == 0 {
|
||
|
return errors.New("reference does not contain translations")
|
||
|
}
|
||
|
|
||
|
logrus.Infof("found %d translation keys in reference", len(keys))
|
||
|
|
||
|
if tf.Reference.FormalTranslations != nil {
|
||
|
if verifyTranslationKeys(logrus.NewEntry(logrus.StandardLogger()), tf.Reference.FormalTranslations, keys, keyType, false); err != nil {
|
||
|
return errors.New("reference contains error in formalTranslations")
|
||
|
}
|
||
|
}
|
||
|
|
||
|
var hadErrors bool
|
||
|
for lk, tm := range tf.Translations {
|
||
|
logger := logrus.WithField("lang", lk)
|
||
|
logger.Info("validating language...")
|
||
|
|
||
|
if !langKeyFormat.MatchString(lk) {
|
||
|
hadErrors = true
|
||
|
logger.Error("language key is invalid")
|
||
|
}
|
||
|
|
||
|
if tm.DeeplLanguage == "" {
|
||
|
logger.Info("no deeplLanguage is set")
|
||
|
}
|
||
|
|
||
|
hadErrors = hadErrors || verifyTranslationKeys(logger, tm.Translations, keys, keyType, true)
|
||
|
hadErrors = hadErrors || verifyTranslationKeys(logger, tm.FormalTranslations, keys, keyType, false)
|
||
|
}
|
||
|
|
||
|
if hadErrors {
|
||
|
return errors.New("translation file has errors")
|
||
|
}
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
func verifyTranslationKeys(logger *logrus.Entry, t translation, keys []string, keyType map[string]reflect.Type, warnMissing bool) (hadErrors bool) {
|
||
|
var seenKeys []string
|
||
|
|
||
|
for k, v := range t {
|
||
|
keyLogger := logger.WithField("translation_key", k)
|
||
|
if !str.StringInSlice(k, keys) {
|
||
|
// Contains extra key, is error
|
||
|
hadErrors = true
|
||
|
keyLogger.Error("extra key found")
|
||
|
continue // No further checks for that key
|
||
|
}
|
||
|
|
||
|
seenKeys = append(seenKeys, k)
|
||
|
if kt := reflect.TypeOf(v); keyType[k] != kt {
|
||
|
// Type mismatches (i.e. string vs []string)
|
||
|
hadErrors = true
|
||
|
keyLogger.Errorf("key has invalid type %s != %s", kt, keyType[k])
|
||
|
}
|
||
|
}
|
||
|
|
||
|
for _, k := range keys {
|
||
|
if warnMissing && !str.StringInSlice(k, seenKeys) {
|
||
|
logger.WithField("translation_key", k).Warn("missing translation")
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return hadErrors
|
||
|
}
|