github.com/asifdxtreme/cli@v6.1.3-0.20150123051144-9ead8700b4ae+incompatible/bin/remove-unused-translations.go (about)

     1  package main
     2  
     3  import (
     4  	"encoding/json"
     5  	"fmt"
     6  	"go/ast"
     7  	"go/parser"
     8  	"go/token"
     9  	"io/ioutil"
    10  	"os"
    11  	"path/filepath"
    12  )
    13  
    14  // NB: this assumes that translation strings are globally unique
    15  //     as of the day we wrote this, they are not unique
    16  func main() {
    17  	walkTranslationFilesAndPromptUser()
    18  }
    19  
    20  func walkTranslationFilesAndPromptUser() {
    21  	stringsFromCode := readSourceCode()
    22  
    23  	dir := "cf/i18n/resources"
    24  	filepath.Walk(dir, func(path string, info os.FileInfo, err error) error {
    25  		if err != nil {
    26  			panic(err.Error())
    27  		}
    28  
    29  		if info.IsDir() {
    30  			return nil
    31  		}
    32  
    33  		if filepath.Ext(info.Name()) != ".json" {
    34  			return nil
    35  		}
    36  
    37  		file, err := os.Open(path)
    38  		if err != nil {
    39  			panic(err.Error())
    40  		}
    41  		data, err := ioutil.ReadAll(file)
    42  		if err != nil {
    43  			panic(err.Error())
    44  		}
    45  		maps := []map[string]string{}
    46  		err = json.Unmarshal(data, &maps)
    47  		if err != nil {
    48  			panic(err.Error())
    49  		}
    50  
    51  		indicesToRemove := []int{}
    52  		for index, tmap := range maps {
    53  			str := tmap["id"]
    54  
    55  			foundStr := false
    56  			for _, codeStr := range stringsFromCode {
    57  				if codeStr == str {
    58  					foundStr = true
    59  					break
    60  				}
    61  			}
    62  
    63  			if !foundStr {
    64  				fmt.Printf("Did not find this string in the source code:\n")
    65  				fmt.Printf("'%s'\n", str)
    66  				println()
    67  
    68  				answer := ""
    69  				fmt.Printf("Would you like to delete it from %s? [y|n]", path)
    70  				fmt.Fscanln(os.Stdin, &answer)
    71  
    72  				if answer == "y" {
    73  					indicesToRemove = append(indicesToRemove, index)
    74  				}
    75  			}
    76  		}
    77  
    78  		if len(indicesToRemove) > 0 {
    79  			println("Removing", len(indicesToRemove), "translations from", path)
    80  
    81  			newMaps := []map[string]string{}
    82  			for i, mapp := range maps {
    83  
    84  				foundIndex := false
    85  				for _, index := range indicesToRemove {
    86  					if index == i {
    87  						foundIndex = true
    88  						break
    89  					}
    90  				}
    91  
    92  				if !foundIndex {
    93  					newMaps = append(newMaps, mapp)
    94  				}
    95  			}
    96  
    97  			bytes, err := json.Marshal(newMaps) // consider json.MarshalIndent
    98  			if err != nil {
    99  				panic(err.Error())
   100  			}
   101  
   102  			newFile, err := os.Create(path)
   103  			if err != nil {
   104  				panic(err.Error())
   105  			}
   106  
   107  			_, err = newFile.Write(bytes)
   108  			if err != nil {
   109  				panic(err.Error())
   110  			}
   111  		}
   112  
   113  		return nil
   114  	})
   115  }
   116  
   117  func readSourceCode() []string {
   118  	strings := []string{}
   119  
   120  	dir, err := os.Getwd()
   121  	if err != nil {
   122  		panic(err.Error())
   123  	}
   124  
   125  	filepath.Walk(dir, func(path string, info os.FileInfo, err error) error {
   126  		if err != nil {
   127  			panic(err.Error())
   128  		}
   129  
   130  		if info.IsDir() {
   131  			return nil
   132  		}
   133  
   134  		if filepath.Ext(info.Name()) != ".go" {
   135  			return nil
   136  		}
   137  
   138  		fileSet := token.NewFileSet()
   139  		astFile, err := parser.ParseFile(fileSet, path, nil, 0)
   140  		if err != nil {
   141  			panic(err.Error())
   142  		}
   143  
   144  		for _, declaration := range astFile.Decls {
   145  			ast.Inspect(declaration, func(node ast.Node) bool {
   146  				callExpr, ok := node.(*ast.CallExpr)
   147  				if !ok {
   148  					return true
   149  				}
   150  
   151  				funcNode, ok := callExpr.Fun.(*ast.Ident)
   152  				if !ok {
   153  					return true
   154  				}
   155  
   156  				if funcNode.Name != "T" {
   157  					return true
   158  				}
   159  
   160  				firstArg := callExpr.Args[0]
   161  
   162  				argAsString, ok := firstArg.(*ast.BasicLit)
   163  				if !ok {
   164  					return true
   165  				}
   166  
   167  				// remove quotes around string literal
   168  				end := len(argAsString.Value) - 1
   169  				strings = append(strings, argAsString.Value[1:end])
   170  				return true
   171  			})
   172  		}
   173  
   174  		return nil
   175  	})
   176  
   177  	return strings
   178  }