adding test
parent
8da5f2b4a6
commit
8308aa5156
|
@ -38,8 +38,8 @@ import (
|
||||||
// A list of strings to explicitly omit from translation files.
|
// A list of strings to explicitly omit from translation files.
|
||||||
var blacklist = []string{"%s: %v"}
|
var blacklist = []string{"%s: %v"}
|
||||||
|
|
||||||
// currentState is a struct that represent the current state of the extraction process
|
// state is a struct that represent the current state of the extraction process
|
||||||
type currentState struct {
|
type state struct {
|
||||||
// The list of functions to check for
|
// The list of functions to check for
|
||||||
funcs map[string]struct{}
|
funcs map[string]struct{}
|
||||||
|
|
||||||
|
@ -60,7 +60,7 @@ type currentState struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
// newExtractor initializes state for extraction
|
// newExtractor initializes state for extraction
|
||||||
func newExtractor(functionsToCheck []string) *currentState {
|
func newExtractor(functionsToCheck []string) *state {
|
||||||
funcs := make(map[string]struct{})
|
funcs := make(map[string]struct{})
|
||||||
fs := stack.New()
|
fs := stack.New()
|
||||||
|
|
||||||
|
@ -69,7 +69,7 @@ func newExtractor(functionsToCheck []string) *currentState {
|
||||||
fs.Push(f)
|
fs.Push(f)
|
||||||
}
|
}
|
||||||
|
|
||||||
return ¤tState{
|
return &state{
|
||||||
funcs: funcs,
|
funcs: funcs,
|
||||||
fs: fs,
|
fs: fs,
|
||||||
translations: make(map[string]interface{}),
|
translations: make(map[string]interface{}),
|
||||||
|
@ -78,6 +78,16 @@ func newExtractor(functionsToCheck []string) *currentState {
|
||||||
|
|
||||||
// TranslatableStrings finds all strings to that need to be translated in paths and prints them out to all json files in output
|
// TranslatableStrings finds all strings to that need to be translated in paths and prints them out to all json files in output
|
||||||
func TranslatableStrings(paths []string, functions []string, output string) {
|
func TranslatableStrings(paths []string, functions []string, output string) {
|
||||||
|
cwd, err := os.Getwd()
|
||||||
|
if err != nil {
|
||||||
|
exit.WithError("Getting current working directory", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if strings.Contains(cwd, "cmd") {
|
||||||
|
fmt.Println("Run extract.go from the minikube root directory.")
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
e := newExtractor(functions)
|
e := newExtractor(functions)
|
||||||
|
|
||||||
fmt.Println("Compiling translation strings...")
|
fmt.Println("Compiling translation strings...")
|
||||||
|
@ -100,7 +110,7 @@ func TranslatableStrings(paths []string, functions []string, output string) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
err := writeStringsToFiles(e, output)
|
err = writeStringsToFiles(e, output)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
exit.WithError("Writing translation files", err)
|
exit.WithError("Writing translation files", err)
|
||||||
|
@ -114,7 +124,7 @@ func shouldCheckFile(path string) bool {
|
||||||
}
|
}
|
||||||
|
|
||||||
// inspectFile goes through the given file line by line looking for translatable strings
|
// inspectFile goes through the given file line by line looking for translatable strings
|
||||||
func inspectFile(e *currentState) error {
|
func inspectFile(e *state) error {
|
||||||
fset := token.NewFileSet()
|
fset := token.NewFileSet()
|
||||||
r, err := ioutil.ReadFile(e.filename)
|
r, err := ioutil.ReadFile(e.filename)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -163,7 +173,7 @@ func inspectFile(e *currentState) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
// checkStmt checks each line to see if it's a call to print a string out to the console
|
// checkStmt checks each line to see if it's a call to print a string out to the console
|
||||||
func checkStmt(stmt ast.Stmt, e *currentState) {
|
func checkStmt(stmt ast.Stmt, e *state) {
|
||||||
//fmt.Printf("%s: %s\n", stmt, reflect.TypeOf(stmt))
|
//fmt.Printf("%s: %s\n", stmt, reflect.TypeOf(stmt))
|
||||||
|
|
||||||
// If this line is an expression, see if it's a function call
|
// If this line is an expression, see if it's a function call
|
||||||
|
@ -185,7 +195,7 @@ func checkStmt(stmt ast.Stmt, e *currentState) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// checkIfStmt does if-statement-specific checks, especially relating to else stmts
|
// checkIfStmt does if-statement-specific checks, especially relating to else stmts
|
||||||
func checkIfStmt(stmt *ast.IfStmt, e *currentState) {
|
func checkIfStmt(stmt *ast.IfStmt, e *state) {
|
||||||
for _, s := range stmt.Body.List {
|
for _, s := range stmt.Body.List {
|
||||||
checkStmt(s, e)
|
checkStmt(s, e)
|
||||||
}
|
}
|
||||||
|
@ -206,7 +216,7 @@ func checkIfStmt(stmt *ast.IfStmt, e *currentState) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// checkCallExpression takes a function call, and checks its arguments for strings
|
// checkCallExpression takes a function call, and checks its arguments for strings
|
||||||
func checkCallExpression(expr *ast.ExprStmt, e *currentState) {
|
func checkCallExpression(expr *ast.ExprStmt, e *state) {
|
||||||
s, ok := expr.X.(*ast.CallExpr)
|
s, ok := expr.X.(*ast.CallExpr)
|
||||||
|
|
||||||
// This line isn't a function call
|
// This line isn't a function call
|
||||||
|
@ -253,7 +263,7 @@ func checkCallExpression(expr *ast.ExprStmt, e *currentState) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// checkIdentForStringValye takes a identifier and sees if it's a variable assigned to a string
|
// checkIdentForStringValye takes a identifier and sees if it's a variable assigned to a string
|
||||||
func checkIdentForStringValue(i *ast.Ident, e *currentState) bool {
|
func checkIdentForStringValue(i *ast.Ident, e *state) bool {
|
||||||
// This identifier is nil
|
// This identifier is nil
|
||||||
if i.Obj == nil {
|
if i.Obj == nil {
|
||||||
return false
|
return false
|
||||||
|
@ -281,7 +291,7 @@ func checkIdentForStringValue(i *ast.Ident, e *currentState) bool {
|
||||||
}
|
}
|
||||||
|
|
||||||
// addStringToList takes a string, makes sure it's meant to be translated then adds it to the list if so
|
// addStringToList takes a string, makes sure it's meant to be translated then adds it to the list if so
|
||||||
func addStringToList(s string, e *currentState) bool {
|
func addStringToList(s string, e *state) bool {
|
||||||
// Empty strings don't need translating
|
// Empty strings don't need translating
|
||||||
if len(s) <= 2 {
|
if len(s) <= 2 {
|
||||||
return false
|
return false
|
||||||
|
@ -319,7 +329,7 @@ func addStringToList(s string, e *currentState) bool {
|
||||||
}
|
}
|
||||||
|
|
||||||
// writeStringsToFiles writes translations to all translation files in output
|
// writeStringsToFiles writes translations to all translation files in output
|
||||||
func writeStringsToFiles(e *currentState, output string) error {
|
func writeStringsToFiles(e *state, output string) error {
|
||||||
err := filepath.Walk(output, func(path string, info os.FileInfo, err error) error {
|
err := filepath.Walk(output, func(path string, info os.FileInfo, err error) error {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, "accessing path")
|
return errors.Wrap(err, "accessing path")
|
||||||
|
@ -327,6 +337,9 @@ func writeStringsToFiles(e *currentState, output string) error {
|
||||||
if info.Mode().IsDir() {
|
if info.Mode().IsDir() {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
if !strings.HasSuffix(path, ".json") {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
fmt.Printf("Writing to %s\n", filepath.Base(path))
|
fmt.Printf("Writing to %s\n", filepath.Base(path))
|
||||||
var currentTranslations map[string]interface{}
|
var currentTranslations map[string]interface{}
|
||||||
f, err := ioutil.ReadFile(path)
|
f, err := ioutil.ReadFile(path)
|
||||||
|
@ -361,7 +374,7 @@ func writeStringsToFiles(e *currentState, output string) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
// addParentFuncToList adds the current parent function to the list of functions to inspect more closely.
|
// addParentFuncToList adds the current parent function to the list of functions to inspect more closely.
|
||||||
func addParentFuncToList(e *currentState) {
|
func addParentFuncToList(e *state) {
|
||||||
if _, ok := e.funcs[e.parentFunc]; !ok {
|
if _, ok := e.funcs[e.parentFunc]; !ok {
|
||||||
e.funcs[e.parentFunc] = struct{}{}
|
e.funcs[e.parentFunc] = struct{}{}
|
||||||
e.fs.Push(e.parentFunc)
|
e.fs.Push(e.parentFunc)
|
||||||
|
|
|
@ -0,0 +1,42 @@
|
||||||
|
package extract
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"io/ioutil"
|
||||||
|
"reflect"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestExtract(t *testing.T) {
|
||||||
|
// The file to scan
|
||||||
|
paths := []string{"testdata/sample_file.go"}
|
||||||
|
|
||||||
|
// The function we care about
|
||||||
|
functions := []string{"PrintToScreen"}
|
||||||
|
|
||||||
|
// The directory where the sample translation file is in
|
||||||
|
output := "testdata/"
|
||||||
|
|
||||||
|
expected := map[string]interface{}{
|
||||||
|
"Hint: This is not a URL, come on.": "",
|
||||||
|
"Holy cow I'm in a loop!": "Something else",
|
||||||
|
"This is a variable with a string assigned": "",
|
||||||
|
"This was a choice: %s": "Something",
|
||||||
|
"Wow another string: %s": "",
|
||||||
|
}
|
||||||
|
|
||||||
|
TranslatableStrings(paths, functions, output)
|
||||||
|
|
||||||
|
var got map[string]interface{}
|
||||||
|
f, err := ioutil.ReadFile("testdata/en-US.json")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Reading json file: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
json.Unmarshal(f, &got)
|
||||||
|
|
||||||
|
if !reflect.DeepEqual(expected, got) {
|
||||||
|
t.Fatalf("Translation JSON not equal: expected %v, got %v", expected, got)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,4 @@
|
||||||
|
{
|
||||||
|
"Holy cow I'm in a loop!": "Something else",
|
||||||
|
"This was a choice: %s": "Something"
|
||||||
|
}
|
|
@ -0,0 +1,48 @@
|
||||||
|
package extract
|
||||||
|
|
||||||
|
import "fmt"
|
||||||
|
|
||||||
|
func DoSomeStuff() {
|
||||||
|
// Test with a URL
|
||||||
|
PrintToScreenNoInterface("http://kubernetes.io")
|
||||||
|
|
||||||
|
// Test with something that Go thinks looks like a URL
|
||||||
|
PrintToScreenNoInterface("Hint: This is not a URL, come on.")
|
||||||
|
|
||||||
|
// Try with an integer
|
||||||
|
PrintToScreenNoInterface("5")
|
||||||
|
|
||||||
|
// Try with a sudo command
|
||||||
|
path := "."
|
||||||
|
PrintToScreen("sudo ls %s", path)
|
||||||
|
|
||||||
|
DoSomeOtherStuff(true, 4, "I think this should work")
|
||||||
|
|
||||||
|
v := "This is a variable with a string assigned"
|
||||||
|
PrintToScreenNoInterface(v)
|
||||||
|
}
|
||||||
|
|
||||||
|
func DoSomeOtherStuff(choice bool, i int, s string) {
|
||||||
|
|
||||||
|
// Let's try an if statement
|
||||||
|
if choice {
|
||||||
|
PrintToScreen("This was a choice: %s", s)
|
||||||
|
} else if i > 5 {
|
||||||
|
PrintToScreen("Wow another string: %s", i)
|
||||||
|
} else {
|
||||||
|
for i > 10 {
|
||||||
|
PrintToScreenNoInterface("Holy cow I'm in a loop!")
|
||||||
|
i = i + 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func PrintToScreenNoInterface(s string) {
|
||||||
|
PrintToScreen(s, nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
// This will be the function we'll focus the extractor on
|
||||||
|
func PrintToScreen(s string, i interface{}) {
|
||||||
|
fmt.Printf(s, i)
|
||||||
|
}
|
Loading…
Reference in New Issue