Created
December 11, 2023 00:54
-
-
Save konifar/b8bc780038bd28dfbf51e3b0795f7eb5 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package main | |
import ( | |
"flag" | |
"fmt" | |
mapset "github.com/deckarep/golang-set/v2" | |
"log" | |
"os" | |
"path/filepath" | |
"regexp" | |
"strings" | |
"github.com/BurntSushi/toml" | |
) | |
var ( | |
localeFileDir string | |
) | |
func init() { | |
flag.StringVar(&localeFileDir, "localeFileDir", ".", "Localeファイルのあるディレクトリ") | |
} | |
// go run scripts/i18n_locale_file_checker/main.go -localeFileDir=helpers/i18n | |
func main() { | |
flag.Parse() | |
jaFilePath := filepath.Join(localeFileDir, "ja.toml") | |
jaKeyMap, err := readLocaleKeyMap(jaFilePath) | |
if err != nil { | |
log.Fatal(err) | |
} | |
// 問題のあるファイルがあるかどうか | |
existInvalidFiles := false | |
fmt.Println("ja.tomlファイルのチェック開始...") | |
// mapのバリューに%s、%v、%q、%dが含まれていないかのチェック | |
existInvalidFiles = !checkTemplateString(jaKeyMap) | |
// ディレクトリ内の他のtomlファイルをひとつずつチェック | |
err = filepath.Walk(localeFileDir, func(path string, info os.FileInfo, err error) error { | |
if info.IsDir() || filepath.Ext(path) != ".toml" || path == jaFilePath { | |
return nil | |
} | |
lang := strings.TrimSuffix(filepath.Base(path), filepath.Ext(path)) // 拡張子(.toml)を除いたファイル名を言語コードとして取得 | |
fmt.Printf("%s.tomlファイルのチェック開始...\n", lang) | |
foreignKeyMap, err := readLocaleKeyMap(path) | |
if err != nil { | |
log.Fatal(err) | |
} | |
// キーが過不足ないかどうかのチェック | |
existInvalidFiles = !checkKeysCount(jaKeyMap, foreignKeyMap) | |
// mapのバリューに%s、%v、%q、%dが含まれていないかのチェック | |
existInvalidFiles = !checkTemplateString(foreignKeyMap) | |
// テンプレート文字列 {{}} のキーが一致するかのチェック | |
existInvalidFiles = !checkTemplateKeys(jaKeyMap, foreignKeyMap, lang) | |
return nil | |
}) | |
if err != nil { | |
log.Fatal(err) | |
} | |
if existInvalidFiles { | |
os.Exit(1) | |
} | |
} | |
// 2つのmapのキーが過不足ある場合にfalseを返す | |
func checkKeysCount(jaKeyMap map[string]string, foreignKeyMap map[string]string) bool { | |
jaKeySet := convertMapToSet(jaKeyMap) | |
foreignKeySet := convertMapToSet(foreignKeyMap) | |
missingKeys := foreignKeySet.Difference(jaKeySet).ToSlice() // 他の言語ファイルにのみ含まれるキー | |
extraKeys := jaKeySet.Difference(foreignKeySet).ToSlice() // ja.tomlにのみ含まれるキー | |
if len(missingKeys) > 0 { | |
fmt.Println(" 以下のキーが含まれていません") | |
for _, key := range missingKeys { | |
fmt.Printf(" - %s\n", key) | |
} | |
return false | |
} | |
if len(extraKeys) > 0 { | |
fmt.Println(" 以下のキーが余分に含まれています") | |
for _, key := range extraKeys { | |
fmt.Printf(" - %s\n", key) | |
} | |
return false | |
} | |
if len(missingKeys) == 0 && len(extraKeys) == 0 { | |
fmt.Println(" キーは過不足なく一致しています") | |
} | |
return true | |
} | |
// テンプレート文字列 {{}} のキー一覧を抽出する | |
func extractTemplateKeys(s string) mapset.Set[string] { | |
re := regexp.MustCompile(`{{\.(.*?)}}`) | |
matches := re.FindAllStringSubmatch(s, -1) | |
keys := mapset.NewSet[string]() | |
for _, match := range matches { | |
if len(match) > 1 { | |
keys.Add(strings.TrimSpace(match[1])) | |
} | |
} | |
return keys | |
} | |
// テンプレート文字列 {{}} のキーが一致するかをチェック | |
func checkTemplateKeys(jaKeyMap map[string]string, foreignKeyMap map[string]string, lang string) bool { | |
validTemplateKeys := true | |
for key, value := range jaKeyMap { | |
jaTemplateKeys := extractTemplateKeys(value) | |
foreignValue := foreignKeyMap[key] | |
foreignTemplateKeys := extractTemplateKeys(foreignValue) | |
if !jaTemplateKeys.Equal(foreignTemplateKeys) { | |
validTemplateKeys = false | |
fmt.Printf(" key:%s のテンプレート文字列が ja.toml と違います, ja: %v, %s: %v\n", key, jaTemplateKeys, lang, foreignTemplateKeys) | |
} | |
} | |
return validTemplateKeys | |
} | |
// mapのバリューに%s、%v、%q、%dが含まれていないかをチェック | |
func checkTemplateString(keyMap map[string]string) bool { | |
substrings := []string{"%s", "%v", "%q", "%d"} | |
validTemplateString := true | |
for key, value := range keyMap { | |
for _, sub := range substrings { | |
if strings.Contains(value, sub) { | |
validTemplateString = false | |
fmt.Printf(" key:%s に %s が含まれています, value: %s\n", key, sub, value) | |
} | |
} | |
} | |
return validTemplateString | |
} | |
// Localeファイルからキーと値の一覧を取得 | |
func readLocaleKeyMap(filename string) (map[string]string, error) { | |
keys := make(map[string]string) | |
_, err := toml.DecodeFile(filename, &keys) | |
if err != nil { | |
return nil, err | |
} | |
return keys, nil | |
} | |
func convertMapToSet(stringMap map[string]string) mapset.Set[string] { | |
set := mapset.NewSet[string]() | |
for key := range stringMap { | |
set.Add(key) | |
} | |
return set | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment