Skip to content

Commit

Permalink
chore: updated translation
Browse files Browse the repository at this point in the history
  • Loading branch information
Aerex committed Jun 28, 2024
1 parent bad255d commit 1907228
Show file tree
Hide file tree
Showing 19 changed files with 1,977 additions and 2,964 deletions.
67 changes: 34 additions & 33 deletions i18n4go/cmds/checkup.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ import (
"github.com/spf13/cobra"

"github.com/maximilien/i18n4go/i18n4go/common"
"github.com/maximilien/i18n4go/i18n4go/i18n"
)

type Checkup struct {
Expand All @@ -50,16 +51,16 @@ func NewCheckup(options *common.Options) *Checkup {
// NewCheckupCommand implements 'i18n4go checkup' command
func NewCheckupCommand(options *common.Options) *cobra.Command {
checkupCmd := &cobra.Command{
Use: T("checkup"),
Short: T("Checks the transated files"),
Use: "checkup",
Short: i18n.T("Checks the transated files"),
RunE: func(cmd *cobra.Command, args []string) error {
return NewCheckup(options).Run()
},
}

checkupCmd.Flags().StringVarP(&options.QualifierFlag, T("qualifier"), T("q"), T(""), T("[optional] the qualifier string that is used when using the T(...) function, default to nothing but could be set to `i18n` so that all calls would be: i18n.T(...)"))
checkupCmd.Flags().StringVarP(&options.QualifierFlag, "qualifier", "q", "", i18n.T("[optional] the qualifier string that is used when using the i18n.T(...) function, default to nothing but could be set to `i18n` so that all calls would be: i18n.T(...)"))
// TODO: Optional flags shouldn't have set defaults. We should look into removing the default
checkupCmd.Flags().StringVar(&options.IgnoreRegexpFlag, T("ignore-regexp"), T(".*test.*"), T("recursively extract strings from all files in the same directory as filename or dirName"))
checkupCmd.Flags().StringVar(&options.IgnoreRegexpFlag, "ignore-regexp", ".*test.*", i18n.T("recursively extract strings from all files in the same directory as filename or dirName"))
return checkupCmd
}

Expand Down Expand Up @@ -88,44 +89,44 @@ func (cu *Checkup) Run() error {
sourceStrings, err := cu.findSourceStrings()

if err != nil {
cu.Println(fmt.Sprintf(T("Couldn't find any source strings: {{.Arg0}}", map[string]interface{}{"Arg0": err.Error()})))
cu.Println(i18n.T("Couldn't find any source strings: {{.Arg0}}", map[string]interface{}{"Arg0": err.Error()}))
return err
}

locales := findTranslationFiles(T("."), cu.IgnoreRegexp, false)
locales := findTranslationFiles(".", cu.IgnoreRegexp, false)

englishFiles := locales[T("en_US")]
englishFiles := locales["en_US"]
if englishFiles == nil {
cu.Println(T("Could not find an i18n file for locale: en_US"))
return errors.New(T("Could not find an i18n file for locale: en_US"))
cu.Println(i18n.T("Could not find an i18n file for locale: en_US"))
return errors.New(i18n.T("Could not find an i18n file for locale: en_US"))
}

englishStrings, err := cu.findI18nStrings(englishFiles)

if err != nil {
cu.Println(fmt.Sprintf(T("Couldn't find the english strings: {{.Arg0}}", map[string]interface{}{"Arg0": err.Error()})))
cu.Println(i18n.T("Couldn't find the english strings: {{.Arg0}}", map[string]interface{}{"Arg0": err.Error()}))
return err
}

err = cu.diffStrings(T("the code"), T("en_US"), sourceStrings, englishStrings)
err = cu.diffStrings(i18n.T("the code"), "en_US", sourceStrings, englishStrings)

for locale, i18nFiles := range locales {
if locale == T("en_US") {
if locale == "en_US" {
continue
}

translatedStrings, err := cu.findI18nStrings(i18nFiles)

if err != nil {
cu.Println(fmt.Sprintf(T("Couldn't get the strings from {{.Arg0}}: {{.Arg1}}", map[string]interface{}{"Arg0": locale, "Arg1": err.Error()})))
cu.Println(i18n.T("Couldn't get the strings from {{.Arg0}}: {{.Arg1}}", map[string]interface{}{"Arg0": locale, "Arg1": err.Error()}))
return err
}

err = cu.diffStrings(T("en_US"), locale, englishStrings, translatedStrings)
err = cu.diffStrings("en_US", locale, englishStrings, translatedStrings)
}

if err == nil {
cu.Printf(T("OK"))
cu.Printf(i18n.T("OK"))
}

return err
Expand All @@ -138,7 +139,7 @@ func getGoFiles(dir string) (files []string) {
if !fileInfo.IsDir() {
name := fileInfo.Name()

if strings.HasSuffix(name, T(".go")) && !strings.HasSuffix(name, T("_test.go")) {
if strings.HasSuffix(name, ".go") && !strings.HasSuffix(name, "_test.go") {
files = append(files, filepath.Join(dir, fileInfo.Name()))
}
} else {
Expand Down Expand Up @@ -212,16 +213,16 @@ func (cu *Checkup) inspectCallExpr(translatedStrings []string, stmtMap map[strin
case *ast.Ident:
funName := node.Fun.(*ast.Ident).Name
// inspect any T() or t() method calls
if funName == T("T") || funName == T("t") {
if funName == "T" || funName == "t" {
translatedStrings = cu.inspectTFunc(translatedStrings, stmtMap, *node)
}

case *ast.SelectorExpr:
expr := node.Fun.(*ast.SelectorExpr)
if ident, ok := expr.X.(*ast.Ident); ok {
funName := expr.Sel.Name
// inspect any <MODULE>.T() or <MODULE>.t() method calls (eg. i18n.T())
if ident.Name == cu.options.QualifierFlag && (funName == T("T") || funName == T("t")) {
// inspect any <MODULE>.i18n.T() or <MODULE>.t() method calls (eg. i18n.T())
if ident.Name == cu.options.QualifierFlag && (funName == "T" || funName == "t") {
translatedStrings = cu.inspectTFunc(translatedStrings, stmtMap, *node)
}
}
Expand Down Expand Up @@ -264,12 +265,12 @@ func (cu *Checkup) inspectFile(file string) (translatedStrings []string, err err

func (cu *Checkup) findSourceStrings() (sourceStrings map[string]string, err error) {
sourceStrings = make(map[string]string)
files := getGoFiles(T("."))
files := getGoFiles(".")

for _, file := range files {
fileStrings, err := cu.inspectFile(file)
if err != nil {
cu.Println(T("Error when inspecting go file: "), file)
cu.Println(i18n.T("Error when inspecting go file: "), file)
return sourceStrings, err
}

Expand All @@ -293,14 +294,14 @@ func getI18nFile(locale, dir string) (filePath string) {
name := fileInfo.Name()

// assume the file path is a json file and the path contains the locale
if strings.HasSuffix(name, T(".json")) && strings.Contains(name, fmt.Sprintf(T("{{.Arg0}}.", map[string]interface{}{"Arg0": locale}))) {
if strings.HasSuffix(name, ".json") && strings.Contains(name, fmt.Sprintf("{{.Arg0}}.", map[string]interface{}{"Arg0": locale})) {
filePath = filepath.Join(dir, fileInfo.Name())
break
}
} else {
filePath = getI18nFile(locale, filepath.Join(dir, fileInfo.Name()))

if filePath != T("") {
if filePath != "" {
break
}
}
Expand All @@ -317,19 +318,19 @@ func findTranslationFiles(dir string, ignoreRegexp *regexp.Regexp, verbose bool)
if !fileInfo.IsDir() {
name := fileInfo.Name()

if strings.HasSuffix(name, T(".json")) {
parts := strings.Split(name, T("."))
if strings.HasSuffix(name, ".json") {
parts := strings.Split(name, ".")
var locale string

for _, part := range parts {
invalidLangRegexp, _ := regexp.Compile(T("excluded|json|all"))
invalidLangRegexp, _ := regexp.Compile("excluded|json|all")
if !invalidLangRegexp.MatchString(part) {
locale = part
}
}

// No locale found so skipping
if locale == T("") {
if locale == "" {
continue
}

Expand Down Expand Up @@ -378,16 +379,16 @@ func (cu *Checkup) findI18nStrings(i18nFiles []string) (i18nStrings map[string]s

func (cu *Checkup) diffStrings(sourceNameOne, sourceNameTwo string, stringsOne, stringsTwo map[string]string) (err error) {
for key, _ := range stringsOne {
if stringsTwo[key] == T("") {
cu.Printf(T("\"{{.Arg0}}\" exists in {{.Arg1}}, but not in {{.Arg2}}\n", map[string]interface{}{"Arg0": key, "Arg1": sourceNameOne, "Arg2": sourceNameTwo}))
err = errors.New(T("Strings don't match"))
if stringsTwo[key] == "" {
cu.Printf(i18n.T("\"{{.Arg0}}\" exists in {{.Arg1}}, but not in {{.Arg2}}\n", map[string]interface{}{"Arg0": key, "Arg1": sourceNameOne, "Arg2": sourceNameTwo}))
err = errors.New(i18n.T("Strings don't match"))
}
}

for key, _ := range stringsTwo {
if stringsOne[key] == T("") {
cu.Printf(T("\"{{.Arg0}}\" exists in {{.Arg1}}, but not in {{.Arg2}}\n", map[string]interface{}{"Arg0": key, "Arg1": sourceNameTwo, "Arg2": sourceNameOne}))
err = errors.New(T("Strings don't match"))
if stringsOne[key] == "" {
cu.Printf(i18n.T("\"{{.Arg0}}\" exists in {{.Arg1}}, but not in {{.Arg2}}\n", map[string]interface{}{"Arg0": key, "Arg1": sourceNameTwo, "Arg2": sourceNameOne}))
err = errors.New(i18n.T("Strings don't match"))
}
}

Expand Down
53 changes: 28 additions & 25 deletions i18n4go/cmds/create_translations.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import (
"github.com/spf13/cobra"

"github.com/maximilien/i18n4go/i18n4go/common"
"github.com/maximilien/i18n4go/i18n4go/i18n"
)

type createTranslations struct {
Expand Down Expand Up @@ -74,19 +75,19 @@ func NewCreateTranslations(options *common.Options) *createTranslations {
func NewCreateTranslationsCommand(options *common.Options) *cobra.Command {
createTranslationsCmd := &cobra.Command{
Use: "create-translations",
Short: "Creates the transation files",
Short: i18n.T("Creates the transation files"),
RunE: func(cmd *cobra.Command, args []string) error {
return NewCreateTranslations(options).Run()
},
}

// TODO: --google-translate-api-key is too long of an optional flag
// might want to shorten it or add an alias for usability
createTranslationsCmd.Flags().StringVar(&options.GoogleTranslateApiKeyFlag, "google-translate-api-key", "", "[optional] your public Google Translate API key which is used to generate translations (charge is applicable)")
createTranslationsCmd.Flags().StringVarP(&options.SourceLanguageFlag, "source-language", "s", "en", "the source language of the file, typically also part of the file name, e.g., \"en_US\"")
createTranslationsCmd.Flags().StringVarP(&options.FilenameFlag, "file", "f", "", "the source translation file")
createTranslationsCmd.Flags().StringVarP(&options.LanguagesFlag, "languages", "l", "", "a comma separated list of valid languages with optional territory, e.g., \"en, en_US, fr_FR, es\"")
createTranslationsCmd.Flags().StringVarP(&options.OutputDirFlag, "output", "o", "", "the output directory where the newly created translation files will be placed")
createTranslationsCmd.Flags().StringVar(&options.GoogleTranslateApiKeyFlag, "google-translate-api-key", "", i18n.T("[optional] your public Google Translate API key which is used to generate translations (charge is applicable)"))
createTranslationsCmd.Flags().StringVarP(&options.SourceLanguageFlag, "source-language", "s", "en", i18n.T("the source language of the file, typically also part of the file name, e.g., \"en_US\""))
createTranslationsCmd.Flags().StringVarP(&options.FilenameFlag, "file", "f", "", i18n.T("the source translation file"))
createTranslationsCmd.Flags().StringVarP(&options.LanguagesFlag, "languages", "l", "", i18n.T("a comma separated list of valid languages with optional territory, e.g., \"en, en_US, fr_FR, es\""))
createTranslationsCmd.Flags().StringVarP(&options.OutputDirFlag, "output", "o", "", i18n.T("the output directory where the newly created translation files will be placed"))

return createTranslationsCmd

Expand All @@ -113,24 +114,24 @@ func (ct *createTranslations) Printf(msg string, a ...interface{}) (int, error)
}

func (ct *createTranslations) Run() error {
ct.Println("i18n4go: creating translation files for:", ct.Filename)
ct.Println(i18n.T("i18n4go: creating translation files for:"), ct.Filename)
ct.Println()

for _, language := range ct.Languages {
ct.Println("i18n4go: creating translation file copy for language:", language)
ct.Println(i18n.T("i18n4go: creating translation file copy for language:"), language)

if ct.options.GoogleTranslateApiKeyFlag != "" {
destFilename, err := ct.createTranslationFileWithGoogleTranslate(language)
if err != nil {
return fmt.Errorf("i18n4go: could not create translation file for language: %s with Google Translate", language)
return fmt.Errorf(i18n.T("i18n4go: could not create translation file for language: {{.Arg0}} with Google Translate", map[string]interface{}{"Arg0": language}))
}
ct.Println("i18n4go: created translation file with Google Translate:", destFilename)
ct.Println(i18n.T("i18n4go: created translation file with Google Translate:"), destFilename)
} else {
destFilename, err := ct.createTranslationFile(ct.Filename, language)
if err != nil {
return fmt.Errorf("i18n4go: could not create default translation file for language: %s\nerr:%s", language, err.Error())
return fmt.Errorf(i18n.T("i18n4go: could not create default translation file for language: {{.Arg0}}\nerr:{{.Arg1}}", map[string]interface{}{"Arg0": language, "Arg1": err.Error()}))
}
ct.Println("i18n4go: created default translation file:", destFilename)
ct.Println(i18n.T("i18n4go: created default translation file:"), destFilename)
}
}

Expand All @@ -148,27 +149,27 @@ func (ct *createTranslations) createTranslationFileWithGoogleTranslate(language
err = common.CreateOutputDirsIfNeeded(ct.OutputDirname)
if err != nil {
ct.Println(err)
return "", fmt.Errorf("i18n4go: could not create output directory: %s", ct.OutputDirname)
return "", fmt.Errorf(i18n.T("i18n4go: could not create output directory: {{.Arg0}}", map[string]interface{}{"Arg0": ct.OutputDirname}))
}

destFilename := filepath.Join(ct.OutputDirname, strings.Replace(fileName, ct.options.SourceLanguageFlag, language, -1))

i18nStringInfos, err := common.LoadI18nStringInfos(ct.Filename)
if err != nil {
ct.Println(err)
return "", fmt.Errorf("i18n4go: could not load i18n strings from file: %s", ct.Filename)
return "", fmt.Errorf(i18n.T("i18n4go: could not load i18n strings from file: {{.Arg0}}", map[string]interface{}{"Arg0": ct.Filename}))
}

if len(i18nStringInfos) == 0 {
return "", fmt.Errorf("i18n4go: input file: %s is empty", ct.Filename)
return "", fmt.Errorf(i18n.T("i18n4go: input file: {{.Arg0}} is empty", map[string]interface{}{"Arg0": ct.Filename}))
}

ct.Println("i18n4go: attempting to use Google Translate to translate source strings in: ", language)
ct.Println(i18n.T("i18n4go: attempting to use Google Translate to translate source strings in: "), language)
modifiedI18nStringInfos := make([]common.I18nStringInfo, len(i18nStringInfos))
for i, i18nStringInfo := range i18nStringInfos {
translation, _, err := ct.googleTranslate(i18nStringInfo.Translation, language)
if err != nil {
ct.Println("i18n4go: error invoking Google Translate for string:", i18nStringInfo.Translation)
ct.Println(i18n.T("i18n4go: error invoking Google Translate for string:"), i18nStringInfo.Translation)
} else {
modifiedI18nStringInfos[i] = common.I18nStringInfo{ID: i18nStringInfo.ID, Translation: translation}
}
Expand All @@ -177,15 +178,15 @@ func (ct *createTranslations) createTranslationFileWithGoogleTranslate(language
err = common.SaveI18nStringInfos(ct, ct.Options(), modifiedI18nStringInfos, destFilename)
if err != nil {
ct.Println(err)
return "", fmt.Errorf("i18n4go: could not save Google Translate i18n strings to file: %s", destFilename)
return "", fmt.Errorf(i18n.T("i18n4go: could not save Google Translate i18n strings to file: {{.Arg0}}", map[string]interface{}{"Arg0": destFilename}))
}

if ct.options.PoFlag {
poFilename := destFilename[:len(destFilename)-len(".json")] + ".po"
err = common.SaveI18nStringsInPo(ct, ct.Options(), modifiedI18nStringInfos, poFilename)
if err != nil {
ct.Println(err)
return "", fmt.Errorf("i18n4go: could not save PO file: %s", poFilename)
return "", fmt.Errorf(i18n.T("i18n4go: could not save PO file: {{.Arg0}}", map[string]interface{}{"Arg0": poFilename}))
}
}

Expand All @@ -203,15 +204,15 @@ func (ct *createTranslations) createTranslationFile(sourceFilename string, langu
i18nStringInfos, err := common.LoadI18nStringInfos(sourceFilename)
if err != nil {
ct.Println(err)
return "", fmt.Errorf("i18n4go: could not load i18n strings from file: %s", sourceFilename)
return "", fmt.Errorf(i18n.T("i18n4go: could not load i18n strings from file: {{.Arg0}}", map[string]interface{}{"Arg0": sourceFilename}))
}

if len(i18nStringInfos) == 0 {
return "", fmt.Errorf("i18n4go: input file: %s is empty", sourceFilename)
return "", fmt.Errorf(i18n.T("i18n4go: input file: {{.Arg0}} is empty", map[string]interface{}{"Arg0": sourceFilename}))
}

destFilename := filepath.Join(ct.OutputDirname, strings.Replace(fileName, ct.options.SourceLanguageFlag, language, -1))
ct.Println("i18n4go: creating translation file:", destFilename)
ct.Println(i18n.T("i18n4go: creating translation file:"), destFilename)

return destFilename, common.CopyFileContents(sourceFilename, destFilename)
}
Expand All @@ -220,24 +221,26 @@ func (ct *createTranslations) googleTranslate(translateString string, language s
escapedTranslateString := url.QueryEscape(translateString)
googleTranslateUrl := "https://www.googleapis.com/language/translate/v2?key=" + ct.options.GoogleTranslateApiKeyFlag + "&target=" + language + "&q=" + escapedTranslateString

// REMOVEME: Do not commit
fmt.Printf("\ngoogleTranslateUrl: %s\n", googleTranslateUrl)
response, err := http.Get(googleTranslateUrl)
if err != nil {
ct.Println("i18n4go: ERROR invoking Google Translate: ", googleTranslateUrl)
ct.Println(i18n.T("i18n4go: ERROR invoking Google Translate: "), googleTranslateUrl)
return "", "", err
}

defer response.Body.Close()

body, err := ioutil.ReadAll(response.Body)
if err != nil {
ct.Println("i18n4go: ERROR parsing Google Translate response body")
ct.Println(i18n.T("i18n4go: ERROR parsing Google Translate response body"))
return "", "", err
}

var googleTranslateData GoogleTranslateData
err = json.Unmarshal(body, &googleTranslateData)
if err != nil {
ct.Println("i18n4go: ERROR parsing Google Translate response body")
ct.Println(i18n.T("i18n4go: ERROR parsing Google Translate response body"))
return "", "", err
}

Expand Down
Loading

0 comments on commit 1907228

Please sign in to comment.