From 82f308de933cf537a0ae20def1c909ca49f803ff Mon Sep 17 00:00:00 2001 From: "Sean E. Russell" Date: Fri, 1 May 2020 20:25:29 -0500 Subject: [PATCH 01/19] Translations for main.go, so mainly help --- cmd/gotop/main.go | 88 +++++++++++++++++++++++------------------ go.mod | 2 + go.sum | 8 ++++ translations/de_DE.toml | 44 +++++++++++++++++++++ translations/en_US.toml | 44 +++++++++++++++++++++ 5 files changed, 148 insertions(+), 38 deletions(-) create mode 100644 translations/de_DE.toml create mode 100644 translations/en_US.toml diff --git a/cmd/gotop/main.go b/cmd/gotop/main.go index bd00b66..7459a97 100644 --- a/cmd/gotop/main.go +++ b/cmd/gotop/main.go @@ -5,6 +5,7 @@ import ( "flag" "fmt" "io" + "io/ioutil" "log" "net/http" "os" @@ -17,9 +18,11 @@ import ( //_ "net/http/pprof" + jj "github.com/cloudfoundry-attic/jibber_jabber" ui "github.com/gizak/termui/v3" "github.com/prometheus/client_golang/prometheus/promhttp" "github.com/shibukawa/configdir" + "github.com/xxxserxxx/lingo" "github.com/xxxserxxx/opflag" "github.com/xxxserxxx/gotop/v4" @@ -50,6 +53,7 @@ var ( bar *w.StatusBar statusbar bool stderrLogger = log.New(os.Stderr, "", 0) + tr lingo.Translations ) func parseArgs() error { @@ -58,35 +62,27 @@ func parseArgs() error { for i, p := range cds { cpaths[i] = p.Path } - help := opflag.BoolP("help", "h", false, "Show this screen.") - color := opflag.StringP("color", "c", conf.Colorscheme.Name, "Set a colorscheme.") - opflag.IntVarP(&conf.GraphHorizontalScale, "graphscale", "S", conf.GraphHorizontalScale, "Graph scale factor, >0") - version := opflag.BoolP("version", "v", false, "Print version and exit.") - versioN := opflag.BoolP("", "V", false, "Print version and exit.") - opflag.BoolVarP(&conf.PercpuLoad, "percpu", "p", conf.PercpuLoad, "Show each CPU in the CPU widget.") - opflag.BoolVarP(&conf.AverageLoad, "averagecpu", "a", conf.AverageLoad, "Show average CPU in the CPU widget.") - fahrenheit := opflag.BoolP("fahrenheit", "f", conf.TempScale == 'F', "Show temperatures in fahrenheit.Show temperatures in fahrenheit.") - opflag.BoolVarP(&conf.Statusbar, "statusbar", "s", conf.Statusbar, "Show a statusbar with the time.") - opflag.DurationVarP(&conf.UpdateInterval, "rate", "r", conf.UpdateInterval, "Refresh frequency. Most time units accepted. `1m` = refresh every minute. `100ms` = refresh every 100ms.") - opflag.StringVarP(&conf.Layout, "layout", "l", conf.Layout, `Name of layout spec file for the UI. Use "-" to pipe.`) - opflag.StringVarP(&conf.NetInterface, "interface", "i", "all", "Select network interface. Several interfaces can be defined using comma separated values. Interfaces can also be ignored using `!`") - opflag.StringVarP(&conf.ExportPort, "export", "x", conf.ExportPort, "Enable metrics for export on the specified port.") - opflag.BoolVarP(&conf.Mbps, "mbps", "", conf.Mbps, "Show network rate as mbps.") - // FIXME Where did this go?? - //conf.Band = opflag.IntP("bandwidth", "B", 100, "Specify the number of bits per seconds.") - opflag.BoolVar(&conf.Test, "test", conf.Test, "Runs tests and exits with success/failure code.") - opflag.StringP("", "C", "", "Config file to use instead of default (MUST BE FIRST ARGUMENT)") - list := opflag.String("list", "", `List - devices: Prints out device names for filterable widgets - layouts: Lists build-in layouts - colorschemes: Lists built-in colorschemes - paths: List out configuration file search paths - widgets: Widgets that can be used in a layout - keys: Show the keyboard bindings.`) - wc := opflag.Bool("write-config", false, "Write out a default config file.") + help := opflag.BoolP("help", "h", false, tr.Value("args.help")) + color := opflag.StringP("color", "c", conf.Colorscheme.Name, tr.Value("args.color")) + opflag.IntVarP(&conf.GraphHorizontalScale, "graphscale", "S", conf.GraphHorizontalScale, tr.Value("args.scale")) + version := opflag.BoolP("version", "v", false, tr.Value("args.version")) + versioN := opflag.BoolP("", "V", false, tr.Value("args.version")) + opflag.BoolVarP(&conf.PercpuLoad, "percpu", "p", conf.PercpuLoad, tr.Value("args.percpu")) + opflag.BoolVarP(&conf.AverageLoad, "averagecpu", "a", conf.AverageLoad, tr.Value("args.cpuavg")) + fahrenheit := opflag.BoolP("fahrenheit", "f", conf.TempScale == 'F', tr.Value("args.temp")) + opflag.BoolVarP(&conf.Statusbar, "statusbar", "s", conf.Statusbar, tr.Value("args.statusbar")) + opflag.DurationVarP(&conf.UpdateInterval, "rate", "r", conf.UpdateInterval, tr.Value("args.rate")) + opflag.StringVarP(&conf.Layout, "layout", "l", conf.Layout, tr.Value("args.layout")) + opflag.StringVarP(&conf.NetInterface, "interface", "i", "all", tr.Value("args.net")) + opflag.StringVarP(&conf.ExportPort, "export", "x", conf.ExportPort, tr.Value("args.export")) + opflag.BoolVarP(&conf.Mbps, "mbps", "", conf.Mbps, tr.Value("args.mbps")) + opflag.BoolVar(&conf.Test, "test", conf.Test, tr.Value("args.test")) + opflag.StringP("", "C", "", tr.Value("args.conffile")) + list := opflag.String("list", "", tr.Value("args.list")) + wc := opflag.Bool("write-config", false, tr.Value("args.write")) opflag.SortFlags = false opflag.Usage = func() { - fmt.Fprintf(os.Stderr, "Usage: %s [options]\n\nOptions:\n", os.Args[0]) + fmt.Fprintf(os.Stderr, tr.Value("usage", os.Args[0])) opflag.PrintDefaults() } opflag.Parse() @@ -115,13 +111,14 @@ func parseArgs() error { case "colorschemes": fmt.Println(_colorschemes) case "paths": - fmt.Println("Loadable colorschemes & layouts, and the config file, are searched for, in order:") + fmt.Println(tr.Value("help.paths")) paths := make([]string, 0) for _, d := range conf.ConfigDir.QueryFolders(configdir.All) { paths = append(paths, d.Path) } fmt.Println(strings.Join(paths, "\n")) - fmt.Printf("\nThe log file is in %s\n", filepath.Join(conf.ConfigDir.QueryCacheFolder().Path, logging.LOGFILE)) + fmt.Println() + fmt.Println(tr.Value("help.log", filepath.Join(conf.ConfigDir.QueryCacheFolder().Path, logging.LOGFILE))) case "devices": listDevices() case "keys": @@ -129,7 +126,7 @@ func parseArgs() error { case "widgets": fmt.Println(_widgets) default: - fmt.Printf("Unknown option \"%s\"; try layouts, colorschemes, keys, paths, or devices\n", *list) + fmt.Printf(tr.Value("errors.unknownopt", *list)) os.Exit(1) } os.Exit(0) @@ -137,10 +134,10 @@ func parseArgs() error { if *wc { path, err := conf.Write() if err != nil { - fmt.Printf("Failed to write configuration file: %s\n", err) + fmt.Println(tr.Value("errors.writefail", err.Error())) os.Exit(1) } - fmt.Printf("Config written to %s\n", path) + fmt.Println(tr.Value("help.written", path)) os.Exit(0) } return nil @@ -348,38 +345,53 @@ func main() { ec := run() if ec > 0 { if ec < 2 { - fmt.Printf("errors encountered; check the log file %s\n", filepath.Join(conf.ConfigDir.QueryCacheFolder().Path, logging.LOGFILE)) + logpath := filepath.Join(conf.ConfigDir.QueryCacheFolder().Path, logging.LOGFILE) + fmt.Println(tr.Value("errors.checklog", logpath)) + fmt.Println(ioutil.ReadFile(logpath)) } } os.Exit(ec) } func run() int { + ling, err := lingo.New("en_US", "translations", nil) + if err != nil { + fmt.Printf("failed to load language files: %s\n", err) + return 2 + } + lang, err := jj.DetectIETF() + if err != nil { + fmt.Printf("failed to get language setting from environment: %s\n", err) + return 2 + } + lang = strings.Replace(lang, "-", "_", -1) + // Get the locale from the os + tr = ling.TranslationsForLocale(lang) conf = gotop.NewConfig() // Find the config file; look in (1) local, (2) user, (3) global // Check the last argument first fs := flag.NewFlagSet("config", flag.ContinueOnError) - cfg := fs.String("C", "", "Config file") + cfg := fs.String("C", "", tr.Value("configfile")) fs.SetOutput(bufio.NewWriter(nil)) fs.Parse(os.Args[1:]) if *cfg != "" { conf.ConfigFile = *cfg } - err := conf.Load() + err = conf.Load() if err != nil { - fmt.Printf("failed to parse config file: %s\n", err) + fmt.Println(tr.Value("errors.configparse", err.Error())) return 2 } // Override with command line arguments err = parseArgs() if err != nil { - fmt.Printf("parsing CLI args: %s\n", err) + fmt.Println(tr.Value("errors.cliparse", err.Error())) return 2 } logfile, err := logging.New(conf) if err != nil { - fmt.Printf("failed to setup log file: %v\n", err) + fmt.Println(tr.Value("logsetup", err.Error())) return 2 } defer logfile.Close() diff --git a/go.mod b/go.mod index 975ca3d..5fbdd2d 100644 --- a/go.mod +++ b/go.mod @@ -2,6 +2,7 @@ module github.com/xxxserxxx/gotop/v4 require ( github.com/StackExchange/wmi v0.0.0-20180116203802-5d049714c4a6 // indirect + github.com/cloudfoundry-attic/jibber_jabber v0.0.0-20151120183258-bcc4c8345a21 github.com/distatus/battery v0.9.0 github.com/docopt/docopt.go v0.0.0-20180111231733-ee0de3bc6815 github.com/gizak/termui/v3 v3.0.0 @@ -14,6 +15,7 @@ require ( github.com/shirou/w32 v0.0.0-20160930032740-bb4de0191aa4 // indirect github.com/stretchr/testify v1.4.0 github.com/xxxserxxx/iSMC v1.0.1 + github.com/xxxserxxx/lingo v1.0.1 github.com/xxxserxxx/opflag v1.0.5 golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a // indirect golang.org/x/tools v0.0.0-20200425043458-8463f397d07c // indirect diff --git a/go.sum b/go.sum index 2e2c454..5a3f852 100644 --- a/go.sum +++ b/go.sum @@ -14,6 +14,8 @@ github.com/cespare/xxhash/v2 v2.1.1 h1:6MnRN8NT7+YBpUIWxHtefFZOKTAPgGjpQSxqLNn0+ github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/cjbassi/drawille-go v0.0.0-20190126131713-27dc511fe6fd h1:XtfPmj9tQRilnrEmI1HjQhxXWRhEM+m8CACtaMJE/kM= github.com/cjbassi/drawille-go v0.0.0-20190126131713-27dc511fe6fd/go.mod h1:vjcQJUZJYD3MeVGhtZXSMnCHfUNZxsyYzJt90eCYxK4= +github.com/cloudfoundry-attic/jibber_jabber v0.0.0-20151120183258-bcc4c8345a21 h1:Yg2hDs4b13Evkpj42FU2idX2cVXVFqQSheXYKM86Qsk= +github.com/cloudfoundry-attic/jibber_jabber v0.0.0-20151120183258-bcc4c8345a21/go.mod h1:MgJyK38wkzZbiZSKeIeFankxxSA8gayko/nr5x5bgBA= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -40,6 +42,8 @@ github.com/google/go-cmp v0.4.0 h1:xsAVV57WRhGj6kEIi8ReJzQlHHqcBYCElAvkovg3B/4= github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= +github.com/jdkeke142/lingo-toml v0.0.0-20181017194727-b6051718cb18 h1:LBrIpegfXvxuUKys1QUbjkStyoQgOMocUu2MFcKXHek= +github.com/jdkeke142/lingo-toml v0.0.0-20181017194727-b6051718cb18/go.mod h1:jOyiHA3tuXflvGIObzfVCShTPCceouP/e6aTo6fvi3s= github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= @@ -115,6 +119,10 @@ github.com/xxxserxxx/gotop/v3 v3.5.1 h1:aBf++Oxg7qCZpKqYpPPnXKFOxT1KYLPtiEXRh57y github.com/xxxserxxx/gotop/v3 v3.5.1/go.mod h1:DGPTiAmUhqE21xvokK64BuMxW+EmnOptaxpdOlqiH6s= github.com/xxxserxxx/iSMC v1.0.1 h1:M9Gkwnnkl+evvnugoB5yRYrbUP+cRIVOPM+xrHZc3Hs= github.com/xxxserxxx/iSMC v1.0.1/go.mod h1:TGgNjU7BF2DZSuxiTft+BdzxzcujFJYqFfMCzcTl/aY= +github.com/xxxserxxx/lingo v1.0.1 h1:lPexOb0HEqYB50EaJdjaYFNATT8JhTcXljbQmCuXygE= +github.com/xxxserxxx/lingo v1.0.1/go.mod h1:C2teIFiBLAmEhpLzRkwk7wP5R0eOoveXVYqD+5KOkAs= +github.com/xxxserxxx/lingo-toml v0.0.0-20181017194727-b6051718cb18 h1:e00RDq5Gm5m22IuDG9/A7yF6AjAzoKbmQ+viQw5MUmI= +github.com/xxxserxxx/lingo-toml v0.0.0-20181017194727-b6051718cb18/go.mod h1:QStBWvZx2oKk5HLYs3xrxAFvCdn8poBdB4uhZTF6yrw= github.com/xxxserxxx/opflag v1.0.0 h1:NabxbubvejqcdzQUHnsU8pBMAiWM+a/Rh2IJe56moiU= github.com/xxxserxxx/opflag v1.0.0/go.mod h1:Zf9bGkOcA35ypGfN25KX0iujVpZB5XwauEFjcfSKcBo= github.com/xxxserxxx/opflag v1.0.2 h1:TanW4Ck/RNal4fP2VVAvhEu7eBq4z+9hhGq9Q8OTq68= diff --git a/translations/de_DE.toml b/translations/de_DE.toml new file mode 100644 index 0000000..4633352 --- /dev/null +++ b/translations/de_DE.toml @@ -0,0 +1,44 @@ +configfile="Config file" +usage="Usage: {0} [options]\n\nOptions:\n" + + +[help] +paths="Loadable colorschemes & layouts, and the config file, are searched for, in order:" +log="The log file is in {0}" +written="Config written to {0}" + + +[args] +help="Hilfetext anzeigen." +color="Ein Farbschema feststellen." +scale="Stellen den Skalierungsfaktor ein, >0" +version="Zeigen die Version aus und beenden." +percpu="Show each CPU in the CPU widget." +cpuavg="Show average CPU in the CPU widget." +temp="Show temperatures in fahrenheit.Show temperatures in fahrenheit." +statusbar="Show a statusbar with the time." +rate="Refresh frequency. Most time units accepted. \"1m\" = refresh every minute. \"100ms\" = refresh every 100ms." +layout="Name of layout spec file for the UI. Use \"-\" to pipe." +net="Select network interface. Several interfaces can be defined using comma separated values. Interfaces can also be ignored using \"!\"" +export="Enable metrics for export on the specified port." +mbps="Show network rate as mbps." +test="Runs tests and exits with success/failure code." +conffile="Config file to use instead of default (MUST BE FIRST ARGUMENT)" +list=""" +List + devices: Prints out device names for filterable widgets + layouts: Lists build-in layouts + colorschemes: Lists built-in colorschemes + paths: List out configuration file search paths + widgets: Widgets that can be used in a layout + keys: Show the keyboard bindings.""" +write="Write out a default config file." + + +[errors] +configparse="failed to parse config file: {0}" +cliparse="parsing CLI args: {0}" +logsetup="failed to setup log file: {0}" +unknownopt="Unknown option \"{0}\"; try layouts, colorschemes, keys, paths, or devices\n" +writefail="Failed to write configuration file: {0}" +checklog="errors encountered; from {0}:" diff --git a/translations/en_US.toml b/translations/en_US.toml new file mode 100644 index 0000000..05cde16 --- /dev/null +++ b/translations/en_US.toml @@ -0,0 +1,44 @@ +configfile="Config file" +usage="Usage: {0} [options]\n\nOptions:\n" + + +[help] +paths="Loadable colorschemes & layouts, and the config file, are searched for, in order:" +log="The log file is in {0}" +written="Config written to {0}" + + +[args] +help="Show this screen." +color="Set a colorscheme." +scale="Graph scale factor, >0" +version="Print version and exit." +percpu="Show each CPU in the CPU widget." +cpuavg="Show average CPU in the CPU widget." +temp="Show temperatures in fahrenheit.Show temperatures in fahrenheit." +statusbar="Show a statusbar with the time." +rate="Refresh frequency. Most time units accepted. \"1m\" = refresh every minute. \"100ms\" = refresh every 100ms." +layout="Name of layout spec file for the UI. Use \"-\" to pipe." +net="Select network interface. Several interfaces can be defined using comma separated values. Interfaces can also be ignored using \"!\"" +export="Enable metrics for export on the specified port." +mbps="Show network rate as mbps." +test="Runs tests and exits with success/failure code." +conffile="Config file to use instead of default (MUST BE FIRST ARGUMENT)" +list=""" +List + devices: Prints out device names for filterable widgets + layouts: Lists build-in layouts + colorschemes: Lists built-in colorschemes + paths: List out configuration file search paths + widgets: Widgets that can be used in a layout + keys: Show the keyboard bindings.""" +write="Write out a default config file." + + +[errors] +configparse="failed to parse config file: {0}" +cliparse="parsing CLI args: {0}" +logsetup="failed to setup log file: {0}" +unknownopt="Unknown option \"{0}\"; try layouts, colorschemes, keys, paths, or devices\n" +writefail="Failed to write configuration file: {0}" +checklog="errors encountered; from {0}:" From 444d2624ab6d5b054446a08ad6888126f9d3494c Mon Sep 17 00:00:00 2001 From: "Sean E. Russell" Date: Tue, 5 May 2020 08:13:25 -0500 Subject: [PATCH 02/19] More translation work. Incomplete. --- cmd/gotop/main.go | 15 ++++----- translations/en_US.toml | 74 +++++++++++++++++++++++++++++++++++++---- widgets/battery.go | 12 +++---- widgets/batterygauge.go | 6 ++-- widgets/cpu.go | 4 +-- widgets/disk.go | 12 +++---- widgets/help.go | 51 +++++----------------------- 7 files changed, 100 insertions(+), 74 deletions(-) diff --git a/cmd/gotop/main.go b/cmd/gotop/main.go index 7459a97..d1cffaa 100644 --- a/cmd/gotop/main.go +++ b/cmd/gotop/main.go @@ -30,7 +30,6 @@ import ( "github.com/xxxserxxx/gotop/v4/devices" "github.com/xxxserxxx/gotop/v4/layout" "github.com/xxxserxxx/gotop/v4/logging" - "github.com/xxxserxxx/gotop/v4/widgets" w "github.com/xxxserxxx/gotop/v4/widgets" ) @@ -122,11 +121,11 @@ func parseArgs() error { case "devices": listDevices() case "keys": - fmt.Println(widgets.KEYBINDS) + fmt.Println(tr.Value("widget.help")) case "widgets": fmt.Println(_widgets) default: - fmt.Printf(tr.Value("errors.unknownopt", *list)) + fmt.Printf(tr.Value("error.unknownopt", *list)) os.Exit(1) } os.Exit(0) @@ -134,7 +133,7 @@ func parseArgs() error { if *wc { path, err := conf.Write() if err != nil { - fmt.Println(tr.Value("errors.writefail", err.Error())) + fmt.Println(tr.Value("error.writefail", err.Error())) os.Exit(1) } fmt.Println(tr.Value("help.written", path)) @@ -346,7 +345,7 @@ func main() { if ec > 0 { if ec < 2 { logpath := filepath.Join(conf.ConfigDir.QueryCacheFolder().Path, logging.LOGFILE) - fmt.Println(tr.Value("errors.checklog", logpath)) + fmt.Println(tr.Value("error.checklog", logpath)) fmt.Println(ioutil.ReadFile(logpath)) } } @@ -379,13 +378,13 @@ func run() int { } err = conf.Load() if err != nil { - fmt.Println(tr.Value("errors.configparse", err.Error())) + fmt.Println(tr.Value("error.configparse", err.Error())) return 2 } // Override with command line arguments err = parseArgs() if err != nil { - fmt.Println(tr.Value("errors.cliparse", err.Error())) + fmt.Println(tr.Value("error.cliparse", err.Error())) return 2 } @@ -422,7 +421,7 @@ func run() int { defer ui.Close() setDefaultTermuiColors(conf) // done before initializing widgets to allow inheriting colors - help = w.NewHelpMenu() + help = w.NewHelpMenu(tr) if statusbar { bar = w.NewStatusBar() } diff --git a/translations/en_US.toml b/translations/en_US.toml index 05cde16..bd66458 100644 --- a/translations/en_US.toml +++ b/translations/en_US.toml @@ -35,10 +35,70 @@ List write="Write out a default config file." -[errors] -configparse="failed to parse config file: {0}" -cliparse="parsing CLI args: {0}" -logsetup="failed to setup log file: {0}" -unknownopt="Unknown option \"{0}\"; try layouts, colorschemes, keys, paths, or devices\n" -writefail="Failed to write configuration file: {0}" -checklog="errors encountered; from {0}:" +[error] +configparse="0: failed to parse config file: {0}" +cliparse="1: parsing CLI args: {0}" +logsetup="2: failed to setup log file: {0}" +unknownopt="3: Unknown option \"{0}\"; try layouts, colorschemes, keys, paths, or devices\n" +writefail="4: Failed to write configuration file: {0}" +checklog="5: errors encountered; from {0}:" +metricsetup="6: error setting up {0} metrics: {1}" +nometrics="7: no metrics for {0} {0}" +fatalfetch="8: fatal error fetching {0} info: {1}" +recovfetch="9: recoverable error fetching {0} info; skipping {0}: {0}" +nodevfound="10: no usable {0} found" +setuperr="11: error setting up {0}: {1}" + + +[widget] +disk=" Disk Usage " +cpu=" CPU Usage " +gauge=" Power Level " +battery=" Battery Status " +batt= +help=""" +Quit: q or + +Process navigation: + - k and : up + - j and : down + - : half page up + - : half page down + - : full page up + - : full page down + - gg and : jump to top + - G and : jump to bottom + +Process actions: + - : toggle process grouping + - dd: kill selected process or group of processes with SIGTERM (15) + - d3: kill selected process or group of processes with SIGQUIT (3) + - d9: kill selected process or group of processes with SIGKILL (9) + +Process sorting: + - c: CPU + - m: Mem + - p: PID + +Process filtering: + - /: start editing filter + - (while editing): + - : accept filter + - and : clear filter + +CPU and Mem graph scaling: + - h: scale in + - l: scale out + +Network: + - b: toggle between mbps and scaled bytes per second +""" + + +[widget.disk] +disk="Disk" +mount="Mount" +used="Used" +free="Free" +rs="R/s" +ws="W/s" diff --git a/widgets/battery.go b/widgets/battery.go index 7167668..dc21d60 100644 --- a/widgets/battery.go +++ b/widgets/battery.go @@ -24,7 +24,7 @@ func NewBatteryWidget(horizontalScale int) *BatteryWidget { LineGraph: ui.NewLineGraph(), updateInterval: time.Minute, } - self.Title = " Battery Status " + self.Title = tr.Value("widget.battery") self.HorizontalScale = horizontalScale // intentional duplicate @@ -46,7 +46,7 @@ func NewBatteryWidget(horizontalScale int) *BatteryWidget { func (b *BatteryWidget) EnableMetric() { bats, err := battery.GetAll() if err != nil { - log.Printf("error setting up metrics: %v", err) + log.Printf(tr.Value("error.metricsetup", "batt", err.Error())) return } b.metric = make([]prometheus.Gauge, len(bats)) @@ -63,7 +63,7 @@ func (b *BatteryWidget) EnableMetric() { } func makeID(i int) string { - return "Batt" + strconv.Itoa(i) + return tr.Value("widget.batt") + strconv.Itoa(i) } func (b *BatteryWidget) Scale(i int) { @@ -75,7 +75,7 @@ func (b *BatteryWidget) update() { if err != nil { switch errt := err.(type) { case battery.ErrFatal: - log.Printf("fatal error fetching battery info: %v", err) + log.Printf(tr.Value("error.fatalfetch", "batt", err.Error())) return case battery.Errors: batts := make([]*battery.Battery, 0) @@ -83,11 +83,11 @@ func (b *BatteryWidget) update() { if e == nil { batts = append(batts, batteries[i]) } else { - log.Printf("recoverable error fetching battery info; skipping battery: %v", e) + log.Printf(tr.Value("error.recovfetch"), "batt", e.Error()) } } if len(batts) < 1 { - log.Print("no usable batteries found") + log.Print(tr.Value("error.nodevfound", "batt")) return } batteries = batts diff --git a/widgets/batterygauge.go b/widgets/batterygauge.go index 968a63c..bb44e57 100644 --- a/widgets/batterygauge.go +++ b/widgets/batterygauge.go @@ -19,7 +19,7 @@ type BatteryGauge struct { func NewBatteryGauge() *BatteryGauge { self := &BatteryGauge{Gauge: termui.NewGauge()} - self.Title = " Power Level " + self.Title = tr.Value("widget.gauge") self.update() @@ -37,7 +37,7 @@ func NewBatteryGauge() *BatteryGauge { func (b *BatteryGauge) EnableMetric() { bats, err := battery.GetAll() if err != nil { - log.Printf("error setting up metrics: %v", err) + log.Printf(tr.Value("error.metricsetup", "power", err.Error())) return } mx := 0.0 @@ -60,7 +60,7 @@ func (b *BatteryGauge) update() { // FIXME: Getting a lot of these in the logs bats, err := battery.GetAll() if err != nil { - log.Printf("error setting up batteries: %v", err) + log.Printf(tr.Value("error.setup", "power", err.Error())) return } mx := 0.0 diff --git a/widgets/cpu.go b/widgets/cpu.go index 03346bf..8aaad7e 100644 --- a/widgets/cpu.go +++ b/widgets/cpu.go @@ -32,7 +32,7 @@ func NewCPUWidget(updateInterval time.Duration, horizontalScale int, showAverage ShowAverageLoad: showAverageLoad, ShowPerCPULoad: showPerCPULoad, } - self.Title = " CPU Usage " + self.Title = tr.Value("cpu") self.HorizontalScale = horizontalScale if !(self.ShowAverageLoad || self.ShowPerCPULoad) { @@ -129,7 +129,7 @@ func (cpu *CPUWidget) update() { cpu.Labels[key] = fmt.Sprintf("%d%%", percent) if cpu.metric != nil { if cpu.metric[key] == nil { - log.Printf("no metrics for %s", key) + log.Printf(tr.Value("error.nometrics", "cpu", key)) } else { cpu.metric[key].Set(float64(percent)) } diff --git a/widgets/disk.go b/widgets/disk.go index 0c86dc9..dd79832 100644 --- a/widgets/disk.go +++ b/widgets/disk.go @@ -38,8 +38,8 @@ func NewDiskWidget() *DiskWidget { updateInterval: time.Second, Partitions: make(map[string]*Partition), } - self.Title = " Disk Usage " - self.Header = []string{"Disk", "Mount", "Used", "Free", "R/s", "W/s"} + self.Title = tr.Value("widget.disk") + self.Header = []string{tr.Value("disk.disk"), tr.Value("disk.mount"), tr.Value("disk.used"), tr.Value("disk.free"), tr.Value("disk.rs"), tr.Value("disk.ws")} self.ColGap = 2 self.ColResizer = func() { self.ColWidths = []int{ @@ -80,7 +80,7 @@ func (disk *DiskWidget) EnableMetric() { func (disk *DiskWidget) update() { partitions, err := psDisk.Partitions(false) if err != nil { - log.Printf("failed to get disk partitions from gopsutil: %v", err) + log.Printf(tr.Value("error.setup", "disk-partitions", err.Error())) return } @@ -125,7 +125,7 @@ func (disk *DiskWidget) update() { for _, partition := range disk.Partitions { usage, err := psDisk.Usage(partition.MountPoint) if err != nil { - log.Printf("failed to get partition usage statistics from gopsutil: %v. partition: %v", err, partition) + log.Printf(tr.Value("error.recovfetch", "partition-"+partition.MountPoint+"-usage", err.Error())) continue } partition.UsedPercent = uint32(usage.UsedPercent + 0.5) @@ -134,7 +134,7 @@ func (disk *DiskWidget) update() { ioCounters, err := psDisk.IOCounters(partition.Device) if err != nil { - log.Printf("failed to get partition read/write info from gopsutil: %v. partition: %v", err, partition) + log.Printf(tr.Value("error.recovfetch", "partition-"+partition.Device+"-rw", err.Error())) continue } ioCounter := ioCounters[strings.Replace(partition.Device, "/dev/", "", -1)] @@ -176,7 +176,7 @@ func (disk *DiskWidget) update() { disk.Rows[i][5] = partition.BytesWrittenRecently if disk.metric != nil { if disk.metric[key] == nil { - log.Printf("ERROR: missing metric %s", key) + log.Printf(tr.Value("error.nometrics", "disk", key)) } else { disk.metric[key].Set(float64(partition.UsedPercent) / 100.0) } diff --git a/widgets/help.go b/widgets/help.go index a2c38e4..fff71a7 100644 --- a/widgets/help.go +++ b/widgets/help.go @@ -5,52 +5,19 @@ import ( "strings" ui "github.com/gizak/termui/v3" + "github.com/xxxserxxx/lingo" ) -// KEYBINDS is the help text for the in-program shortcuts -const KEYBINDS = ` -Quit: q or - -Process navigation: - - k and : up - - j and : down - - : half page up - - : half page down - - : full page up - - : full page down - - gg and : jump to top - - G and : jump to bottom - -Process actions: - - : toggle process grouping - - dd: kill selected process or group of processes with SIGTERM (15) - - d3: kill selected process or group of processes with SIGQUIT (3) - - d9: kill selected process or group of processes with SIGKILL (9) - -Process sorting: - - c: CPU - - m: Mem - - p: PID - -Process filtering: - - /: start editing filter - - (while editing): - - : accept filter - - and : clear filter - -CPU and Mem graph scaling: - - h: scale in - - l: scale out - -Network: - - b: toggle between mbps and scaled bytes per second -` +var tr lingo.Translations +var keyBinds string type HelpMenu struct { ui.Block } -func NewHelpMenu() *HelpMenu { +func NewHelpMenu(tra lingo.Translations) *HelpMenu { + tr = tra + keyBinds = tr.Value("widgets.help") return &HelpMenu{ Block: *ui.NewBlock(), } @@ -58,12 +25,12 @@ func NewHelpMenu() *HelpMenu { func (help *HelpMenu) Resize(termWidth, termHeight int) { textWidth := 53 - for _, line := range strings.Split(KEYBINDS, "\n") { + for _, line := range strings.Split(keyBinds, "\n") { if textWidth < len(line) { textWidth = len(line) + 2 } } - textHeight := strings.Count(KEYBINDS, "\n") + 1 + textHeight := strings.Count(keyBinds, "\n") + 1 x := (termWidth - textWidth) / 2 y := (termHeight - textHeight) / 2 @@ -73,7 +40,7 @@ func (help *HelpMenu) Resize(termWidth, termHeight int) { func (help *HelpMenu) Draw(buf *ui.Buffer) { help.Block.Draw(buf) - for y, line := range strings.Split(KEYBINDS, "\n") { + for y, line := range strings.Split(keyBinds, "\n") { for x, rune := range line { buf.SetCell( ui.NewCell(rune, ui.Theme.Default), From b6b75415247f23fda5c91db2d8065e045c97b625 Mon Sep 17 00:00:00 2001 From: "Sean E. Russell" Date: Thu, 18 Jun 2020 19:51:01 -0500 Subject: [PATCH 03/19] Expand translations --- cmd/gotop/main.go | 3 +- go.mod | 2 +- go.sum | 2 + translations/de_DE.toml | 95 +++++++++++++++++++++++++++- translations/en_US.toml | 61 ++++++++++++++---- translations/tt_TT.toml | 137 ++++++++++++++++++++++++++++++++++++++++ translations/zh_CN.toml | 121 +++++++++++++++++++++++++++++++---- widgets/battery.go | 4 +- widgets/batterygauge.go | 2 +- widgets/cpu.go | 2 +- widgets/disk.go | 2 +- widgets/mem.go | 2 +- widgets/net.go | 14 ++-- widgets/proc.go | 17 +++-- widgets/proc_linux.go | 8 +-- widgets/proc_other.go | 8 +-- widgets/proc_windows.go | 8 +-- widgets/temp.go | 2 +- 18 files changed, 428 insertions(+), 62 deletions(-) create mode 100644 translations/tt_TT.toml diff --git a/cmd/gotop/main.go b/cmd/gotop/main.go index da4ee41..5feb075 100644 --- a/cmd/gotop/main.go +++ b/cmd/gotop/main.go @@ -346,7 +346,8 @@ func main() { if ec < 2 { logpath := filepath.Join(conf.ConfigDir.QueryCacheFolder().Path, logging.LOGFILE) fmt.Println(tr.Value("error.checklog", logpath)) - fmt.Println(ioutil.ReadFile(logpath)) + bs, _ := ioutil.ReadFile(logpath) + fmt.Println(string(bs)) } } os.Exit(ec) diff --git a/go.mod b/go.mod index e708845..a8433f9 100644 --- a/go.mod +++ b/go.mod @@ -1,9 +1,9 @@ module github.com/xxxserxxx/gotop/v4 require ( - github.com/cloudfoundry-attic/jibber_jabber v0.0.0-20151120183258-bcc4c8345a21 github.com/StackExchange/wmi v0.0.0-20190523213315-cbe66965904d // indirect github.com/VictoriaMetrics/metrics v1.11.2 + github.com/cloudfoundry-attic/jibber_jabber v0.0.0-20151120183258-bcc4c8345a21 github.com/distatus/battery v0.9.0 github.com/gizak/termui/v3 v3.1.0 github.com/go-ole/go-ole v1.2.4 // indirect diff --git a/go.sum b/go.sum index d92f6cc..17ea783 100644 --- a/go.sum +++ b/go.sum @@ -43,6 +43,8 @@ github.com/xxxserxxx/opflag v1.0.5 h1:2H4Qtl1qe+dSkEcGt+fBe2mQ8z14MgkWPqcLaoa6k9 github.com/xxxserxxx/opflag v1.0.5/go.mod h1:GWZtb3/tGGj5W1GE/JTyJAuqgxDxl1+jqDGAGM+P/p4= golang.org/x/sys v0.0.0-20200316230553-a7d97aace0b0 h1:4Khi5GeNOkZS5DqSBRn4Sy7BE6GuxwOqARPqfurkdNk= golang.org/x/sys v0.0.0-20200316230553-a7d97aace0b0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1 h1:ogLJMz+qpzav7lGMh10LMvAkM/fAoGlaiiHYiFYdm80= +golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= diff --git a/translations/de_DE.toml b/translations/de_DE.toml index 4633352..06fac94 100644 --- a/translations/de_DE.toml +++ b/translations/de_DE.toml @@ -1,5 +1,6 @@ configfile="Config file" usage="Usage: {0} [options]\n\nOptions:\n" +total="Total" [help] @@ -35,10 +36,102 @@ List write="Write out a default config file." -[errors] +[error] configparse="failed to parse config file: {0}" cliparse="parsing CLI args: {0}" logsetup="failed to setup log file: {0}" unknownopt="Unknown option \"{0}\"; try layouts, colorschemes, keys, paths, or devices\n" writefail="Failed to write configuration file: {0}" checklog="errors encountered; from {0}:" +metricsetup="error setting up {0} metrics: {1}" +nometrics="no metrics for {0} {0}" +fatalfetch="fatal error fetching {0} info: {1}" +recovfetch="recoverable error fetching {0} info; skipping {0}: {0}" +nodevfound="no usable {0} found" +setuperr="error setting up {0}: {1}" + + +[widget.label] +disk=" Disk Usage " +cpu=" CPU Usage " +gauge=" Power Level " +battery=" Battery Status " +batt=" Battery " +temp=" Temperatures " +net=" Network Usage " +netint=" Network Usage: {0} " +mem=" Memory Usage " +help=""" +Quit: q or + +Process navigation: + - k and : up + - j and : down + - : half page up + - : half page down + - : full page up + - : full page down + - gg and : jump to top + - G and : jump to bottom + +Process actions: + - : toggle process grouping + - dd: kill selected process or group of processes with SIGTERM (15) + - d3: kill selected process or group of processes with SIGQUIT (3) + - d9: kill selected process or group of processes with SIGKILL (9) + +Process sorting: + - c: CPU + - m: Mem + - p: PID + +Process filtering: + - /: start editing filter + - (while editing): + - : accept filter + - and : clear filter + +CPU and Mem graph scaling: + - h: scale in + - l: scale out + +Network: + - b: toggle between mbps and scaled bytes per second +""" + + +[widget.net.err] +netactivity="failed to get network activity from gopsutil: {0}" +negvalrecv="error: negative value for recently received network data from gopsutil. recentBytesRecv: {0}" +negvalsent="error: negative value for recently sent network data from gopsutil. recentBytesSent: {0}" + + +[widget.disk] +disk="Disk" +mount="Mount" +used="Used" +free="Free" +rs="R/s" +ws="W/s" + + +[widget.proc] +filter=" Filter: " +label=" Processes " +[widget.proc.header] +count="Count" +command="Command" +cpu="CPU%" +mem="Mem%" +pid="PID" +[widget.proc.err] +count="failed to get CPU count from gopsutil: {0}" +retrieve="failed to retrieve processes: {0}" +ps="failed to execute 'ps' command: {0}" +gopsutil="failed to get processes from gopsutil: {0}" +pidconv="failed to convert PID to int: {0}. line: {1}" +cpuconv="failed to convert CPU usage to float: {0}. line: {1}" +memconv="failed to convert Mem usage to float: {0}. line: {1}" +getcmd="failed to get process command from gopsutil: {0}. psProc: {1}. i: {2}. pid: {3}" +cpupercent="failed to get process cpu usage from gopsutil: {0}. psProc: {1}. i: {2}. pid: {3}" +mempercent="failed to get process memeory usage from gopsutil: {0}. psProc: {1}. i: {2}. pid: {3}" diff --git a/translations/en_US.toml b/translations/en_US.toml index bd66458..4b56c84 100644 --- a/translations/en_US.toml +++ b/translations/en_US.toml @@ -1,5 +1,6 @@ configfile="Config file" usage="Usage: {0} [options]\n\nOptions:\n" +total="Total" [help] @@ -36,26 +37,30 @@ write="Write out a default config file." [error] -configparse="0: failed to parse config file: {0}" -cliparse="1: parsing CLI args: {0}" -logsetup="2: failed to setup log file: {0}" -unknownopt="3: Unknown option \"{0}\"; try layouts, colorschemes, keys, paths, or devices\n" -writefail="4: Failed to write configuration file: {0}" -checklog="5: errors encountered; from {0}:" -metricsetup="6: error setting up {0} metrics: {1}" -nometrics="7: no metrics for {0} {0}" -fatalfetch="8: fatal error fetching {0} info: {1}" -recovfetch="9: recoverable error fetching {0} info; skipping {0}: {0}" -nodevfound="10: no usable {0} found" -setuperr="11: error setting up {0}: {1}" +configparse="failed to parse config file: {0}" +cliparse="parsing CLI args: {0}" +logsetup="failed to setup log file: {0}" +unknownopt="Unknown option \"{0}\"; try layouts, colorschemes, keys, paths, or devices\n" +writefail="Failed to write configuration file: {0}" +checklog="errors encountered; from {0}:" +metricsetup="error setting up {0} metrics: {1}" +nometrics="no metrics for {0} {0}" +fatalfetch="fatal error fetching {0} info: {1}" +recovfetch="recoverable error fetching {0} info; skipping {0}: {0}" +nodevfound="no usable {0} found" +setuperr="error setting up {0}: {1}" -[widget] +[widget.label] disk=" Disk Usage " cpu=" CPU Usage " gauge=" Power Level " battery=" Battery Status " -batt= +batt=" Battery " +temp=" Temperatures " +net=" Network Usage " +netint=" Network Usage: {0} " +mem=" Memory Usage " help=""" Quit: q or @@ -95,6 +100,12 @@ Network: """ +[widget.net.err] +netactivity="failed to get network activity from gopsutil: {0}" +negvalrecv="error: negative value for recently received network data from gopsutil. recentBytesRecv: {0}" +negvalsent="error: negative value for recently sent network data from gopsutil. recentBytesSent: {0}" + + [widget.disk] disk="Disk" mount="Mount" @@ -102,3 +113,25 @@ used="Used" free="Free" rs="R/s" ws="W/s" + + +[widget.proc] +filter=" Filter: " +label=" Processes " +[widget.proc.header] +count="Count" +command="Command" +cpu="CPU%" +mem="Mem%" +pid="PID" +[widget.proc.err] +count="failed to get CPU count from gopsutil: {0}" +retrieve="failed to retrieve processes: {0}" +ps="failed to execute 'ps' command: {0}" +gopsutil="failed to get processes from gopsutil: {0}" +pidconv="failed to convert PID to int: {0}. line: {1}" +cpuconv="failed to convert CPU usage to float: {0}. line: {1}" +memconv="failed to convert Mem usage to float: {0}. line: {1}" +getcmd="failed to get process command from gopsutil: {0}. psProc: {1}. i: {2}. pid: {3}" +cpupercent="failed to get process cpu usage from gopsutil: {0}. psProc: {1}. i: {2}. pid: {3}" +mempercent="failed to get process memeory usage from gopsutil: {0}. psProc: {1}. i: {2}. pid: {3}" diff --git a/translations/tt_TT.toml b/translations/tt_TT.toml new file mode 100644 index 0000000..dc5c737 --- /dev/null +++ b/translations/tt_TT.toml @@ -0,0 +1,137 @@ +configfile="CFG FLE" +usage="egasU: {0} [snoitpo]\n\nsnoitpO:\n" +total="latoT" + + +[help] +paths="redro ni ,rof dehcraes era ,elif gifnoc eht dna ,stuoyal & semehcsroloc elbadaoL:" +log="ni si elif gol ehT {0}" +written="ot nettirw gifnoC {0}" + + +[args] +help=".neercs siht wohS" +color=".emehcsroloc a teS" +scale="0> ,rotcaf elacs hparG" +version=".tixe dna noisrev tnirP" +percpu=".tegdiw UPC eht ni UPC hcae wohS" +cpuavg=".tegdiw UPC eht ni UPC egareva wohS" +temp=".tiehnerhaf ni serutarepmet wohS.tiehnerhaf ni serutarepmet wohS" +statusbar=".emit eht htiw rabsutats a wohS" +rate=".sm001 yreve hserfer = \"sm001\" .etunim yreve hserfer = \"m1\" .detpecca stinu emit tsoM .ycneuqerf hserfeR" +layout="Name of layout spec file for the UI. Use \"-\" to pipe." +net="gnisu derongi eb osla nac secafretnI .seulav detarapes ammoc gnisu denifed eb nac secafretni lareveS .ecafretni krowten tceleS \"!\"" +export=".trop deificeps eht no tropxe rof scirtem elbanE" +mbps=".spbm sa etar krowten wohS" +test=".edoc eruliaf/sseccus htiw stixe dna stset snuR" +conffile=")TNEMUGRA TSRIF EB TSUM( tluafed fo daetsni esu ot elif gifnoC" +list=""" +>syek|shtap|semehcsroloc|stuoyal|secived< tsiL +stegdiw elbaretlif rof seman ecived tuo stnirP :secived +stuoyal ni-dliub stsiL :stuoyal +semehcsroloc ni-tliub stsiL :semehcsroloc +shtap hcraes elif noitarugifnoc tuo tsiL :shtap +tuoyal a ni desu eb nac taht stegdiW :stegdiw +.sgnidnib draobyek eht wohS :syek """ +write=".elif gifnoc tluafed a tuo etirW" + + +[error] +configparse="elif gifnoc esrap ot deliaf: {0}" +cliparse="sgra ILC gnisrap: {0}" +logsetup="elif gol putes ot deliaf: {0}" +unknownopt="noitpo nwonknU \"{0}\"; secived ro ,shtap ,syek ,semehcsroloc ,stuoyal yrt\n" +writefail="elif noitarugifnoc etirw ot deliaF: {0}" +checklog="morf ;deretnuocne srorre {0}:" +metricsetup="pu gnittes rorre {0} scirtem: {1}" +nometrics="rof scirtem on {0} {0}" +fatalfetch="gnihctef rorre lataf {0} ofni: {1}" +recovfetch="gnihctef rorre elbarevocer {0} gnippiks ;ofni {0}: {0}" +nodevfound="elbasu on {0} dnuof" +setuperr="pu gnittes rorre {0}: {1}" + + +[widget.label] +disk=" egasU ksiD " +cpu=" egasU UPC " +gauge=" leveL rewoP " +battery=" sutatS yrettaB " +batt=" yrettaB " +temp=" serutarepmeT " +net=" egasU krowteN " +netint=" egasU krowteN: {0} " +mem=" egasU yromeM " +help=""" +>c-C< ro q :tiuQ + +:noitagivan ssecorP +pu :>pU< dna k - +nwod :>nwoD< dna j - +pu egap flah :>u-C< - +nwod egap flah :>d-C< - +pu egap lluf :>b-C< - +nwod egap lluf :>f-C< - +pot ot pmuj :>emoH< dna gg - +mottob ot pmuj :>dnE< dna G - + +:snoitca ssecorP +gnipuorg ssecorp elggot :>baT< - +)51( MRETGIS htiw sessecorp fo puorg ro ssecorp detceles llik :dd - +)3( TIUQGIS htiw sessecorp fo puorg ro ssecorp detceles llik :3d - +)9( LLIKGIS htiw sessecorp fo puorg ro ssecorp detceles llik :9d - + +:gnitros ssecorP +UPC :c - +meM :m - +DIP :p - + +:gniretlif ssecorP +retlif gnitide trats :/ - +:)gnitide elihw( - +retlif tpecca :>retnE< - +retlif raelc :>epacsE< dna >c-C< - + +:gnilacs hparg meM dna UPC +ni elacs :h - +tuo elacs :l - + +:krowteN +dnoces rep setyb delacs dna spbm neewteb elggot :b - +""" + + +[widget.net.err] +netactivity="lituspog morf ytivitca krowten teg ot deliaf: {0}" +negvalrecv=":vceRsetyBtnecer .lituspog morf atad krowten deviecer yltnecer rof eulav evitagen :rorre {0}" +negvalsent=":tneSsetyBtnecer .lituspog morf atad krowten tnes yltnecer rof eulav evitagen :rorre {0}" + + +[widget.disk] +disk="ksiD" +mount="tnuoM" +used="desU" +free="eerF" +rs="s/R" +ws="s/W" + + +[widget.proc] +filter=" :retliF " +label=" sessecorP " +[widget.proc.header] +count="tnuoC" +command="dnammoC" +cpu="%UPC" +mem="%meM" +pid="DIP" +[widget.proc.err] +count=":lituspog morf tnuoc UPC teg ot deliaf {0}" +retrieve=":sessecorp eveirter ot deliaf {0}" +ps=":dnammoc 'sp' etucexe ot deliaf {0}" +gopsutil=":lituspog morf sessecorp teg ot deliaf {0}" +pidconv=":tni ot DIP trevnoc ot deliaf {0}. enil: {1}" +cpuconv=":taolf ot egasu UPC trevnoc ot deliaf {0}. :enil {1}" +memconv=":taolf ot egasu meM trevnoc ot deliaf {0}. :enil {1}" +getcmd=":lituspog morf dnammoc ssecorp teg ot deliaf {0}. corPsp: {1}. i: {2}. dip: {3}" +cpupercent="lituspog morf egasu upc ssecorp teg ot deliaf: {0}. corPsp: {1}. i: {2}. dip: {3}" +mempercent="spog morf egasu yroemem ssecorp teg ot deliafutil: {0}. corPsp: {1}. i: {2}. dip: {3}" diff --git a/translations/zh_CN.toml b/translations/zh_CN.toml index 141df26..aa20367 100644 --- a/translations/zh_CN.toml +++ b/translations/zh_CN.toml @@ -1,5 +1,6 @@ configfile="配置文件" usage="使用方法: {0} [选项]\n\n选项:\n" +total="Total" [help] @@ -26,19 +27,111 @@ test="执行测试并返回成功或失败码。" conffile="用于替代缺省参数的配置文件(必须是第一个参数)" list=""" List - devices: 显示可用于过滤的设备名 - layouts: 列出所有内置布局方案 - colorschemes: 列出所有内置配色方案 - paths: 列出配置文件的搜索路径 - widgets: 所有可被用于布局的组件 - keys: 显示所有热键。""" -write="将当前配置写入缺省配置文件。" + devices: Prints out device names for filterable widgets + layouts: Lists build-in layouts + colorschemes: Lists built-in colorschemes + paths: List out configuration file search paths + widgets: Widgets that can be used in a layout + keys: Show the keyboard bindings.""" +write="Write out a default config file." -[errors] -configparse="无法解析配置文件: {0}" -cliparse="解析命令行参数: {0}" -logsetup="无法创建日志文件: {0}" -unknownopt="不认识 \"{0}\"; 请使用 layouts, colorschemes, keys, paths, 或 devices\n" -writefail="无法写入配置文件: {0}" -checklog="出错了; 位于 {0}:" +[error] +configparse="failed to parse config file: {0}" +cliparse="parsing CLI args: {0}" +logsetup="failed to setup log file: {0}" +unknownopt="Unknown option \"{0}\"; try layouts, colorschemes, keys, paths, or devices\n" +writefail="Failed to write configuration file: {0}" +checklog="errors encountered; from {0}:" +metricsetup="error setting up {0} metrics: {1}" +nometrics="no metrics for {0} {0}" +fatalfetch="fatal error fetching {0} info: {1}" +recovfetch="recoverable error fetching {0} info; skipping {0}: {0}" +nodevfound="no usable {0} found" +setuperr="error setting up {0}: {1}" + + +[widget.label] +disk=" Disk Usage " +cpu=" CPU Usage " +gauge=" Power Level " +battery=" Battery Status " +batt=" Battery " +temp=" Temperatures " +net=" Network Usage " +netint=" Network Usage: {0} " +mem=" Memory Usage " +help=""" +Quit: q or + +Process navigation: + - k and : up + - j and : down + - : half page up + - : half page down + - : full page up + - : full page down + - gg and : jump to top + - G and : jump to bottom + +Process actions: + - : toggle process grouping + - dd: kill selected process or group of processes with SIGTERM (15) + - d3: kill selected process or group of processes with SIGQUIT (3) + - d9: kill selected process or group of processes with SIGKILL (9) + +Process sorting: + - c: CPU + - m: Mem + - p: PID + +Process filtering: + - /: start editing filter + - (while editing): + - : accept filter + - and : clear filter + +CPU and Mem graph scaling: + - h: scale in + - l: scale out + +Network: + - b: toggle between mbps and scaled bytes per second +""" + + +[widget.net.err] +netactivity="failed to get network activity from gopsutil: {0}" +negvalrecv="error: negative value for recently received network data from gopsutil. recentBytesRecv: {0}" +negvalsent="error: negative value for recently sent network data from gopsutil. recentBytesSent: {0}" + + +[widget.disk] +disk="Disk" +mount="Mount" +used="Used" +free="Free" +rs="R/s" +ws="W/s" + + +[widget.proc] +filter=" Filter: " +label=" Processes " +[widget.proc.header] +count="Count" +command="Command" +cpu="CPU%" +mem="Mem%" +pid="PID" +[widget.proc.err] +count="failed to get CPU count from gopsutil: {0}" +retrieve="failed to retrieve processes: {0}" +ps="failed to execute 'ps' command: {0}" +gopsutil="failed to get processes from gopsutil: {0}" +pidconv="failed to convert PID to int: {0}. line: {1}" +cpuconv="failed to convert CPU usage to float: {0}. line: {1}" +memconv="failed to convert Mem usage to float: {0}. line: {1}" +getcmd="failed to get process command from gopsutil: {0}. psProc: {1}. i: {2}. pid: {3}" +cpupercent="failed to get process cpu usage from gopsutil: {0}. psProc: {1}. i: {2}. pid: {3}" +mempercent="failed to get process memeory usage from gopsutil: {0}. psProc: {1}. i: {2}. pid: {3}" diff --git a/widgets/battery.go b/widgets/battery.go index 7bc9ca6..d8334bb 100644 --- a/widgets/battery.go +++ b/widgets/battery.go @@ -23,7 +23,7 @@ func NewBatteryWidget(horizontalScale int) *BatteryWidget { LineGraph: ui.NewLineGraph(), updateInterval: time.Minute, } - self.Title = tr.Value("widget.battery") + self.Title = tr.Value("widget.label.battery") self.HorizontalScale = horizontalScale // intentional duplicate @@ -60,7 +60,7 @@ func (b *BatteryWidget) EnableMetric() { } func makeID(i int) string { - return tr.Value("widget.batt") + strconv.Itoa(i) + return tr.Value("widget.label.batt") + strconv.Itoa(i) } func (b *BatteryWidget) Scale(i int) { diff --git a/widgets/batterygauge.go b/widgets/batterygauge.go index bec3c43..8dd681e 100644 --- a/widgets/batterygauge.go +++ b/widgets/batterygauge.go @@ -18,7 +18,7 @@ type BatteryGauge struct { func NewBatteryGauge() *BatteryGauge { self := &BatteryGauge{Gauge: termui.NewGauge()} - self.Title = tr.Value("widget.gauge") + self.Title = tr.Value("widget.label.gauge") self.update() diff --git a/widgets/cpu.go b/widgets/cpu.go index 207b231..4d2bc89 100644 --- a/widgets/cpu.go +++ b/widgets/cpu.go @@ -32,7 +32,7 @@ func NewCPUWidget(updateInterval time.Duration, horizontalScale int, showAverage ShowPerCPULoad: showPerCPULoad, cpuLoads: make(map[string]float64), } - self.Title = tr.Value("cpu") + self.Title = tr.Value("widget.label.cpu") self.HorizontalScale = horizontalScale if !(self.ShowAverageLoad || self.ShowPerCPULoad) { diff --git a/widgets/disk.go b/widgets/disk.go index 716e631..67f3bb6 100644 --- a/widgets/disk.go +++ b/widgets/disk.go @@ -37,7 +37,7 @@ func NewDiskWidget() *DiskWidget { updateInterval: time.Second, Partitions: make(map[string]*Partition), } - self.Title = tr.Value("widget.disk") + self.Title = tr.Value("widget.label.disk") self.Header = []string{tr.Value("disk.disk"), tr.Value("disk.mount"), tr.Value("disk.used"), tr.Value("disk.free"), tr.Value("disk.rs"), tr.Value("disk.ws")} self.ColGap = 2 self.ColResizer = func() { diff --git a/widgets/mem.go b/widgets/mem.go index b994276..19656bb 100644 --- a/widgets/mem.go +++ b/widgets/mem.go @@ -21,7 +21,7 @@ func NewMemWidget(updateInterval time.Duration, horizontalScale int) *MemWidget LineGraph: ui.NewLineGraph(), updateInterval: updateInterval, } - widg.Title = " Memory Usage " + widg.Title = tr.Value("widget.label.mem") widg.HorizontalScale = horizontalScale mems := make(map[string]devices.MemoryInfo) devices.UpdateMem(mems) diff --git a/widgets/net.go b/widgets/net.go index b76d6b4..f25f106 100644 --- a/widgets/net.go +++ b/widgets/net.go @@ -47,9 +47,9 @@ func NewNetWidget(netInterface string) *NetWidget { updateInterval: time.Second, NetInterface: strings.Split(netInterface, ","), } - self.Title = " Network Usage " + self.Title = tr.Value("widget.label.net") if netInterface != "all" { - self.Title = fmt.Sprintf(" Network Usage: %s ", netInterface) + self.Title = tr.Value("widget.label.netint", netInterface) } self.update() @@ -73,7 +73,7 @@ func (net *NetWidget) EnableMetric() { func (net *NetWidget) update() { interfaces, err := psNet.IOCounters(true) if err != nil { - log.Printf("failed to get network activity from gopsutil: %v", err) + log.Println(tr.Value("widget.net.err.netactivity", err.Error())) return } @@ -114,12 +114,14 @@ func (net *NetWidget) update() { recentBytesSent = totalBytesSent - net.totalBytesSent if int(recentBytesRecv) < 0 { - log.Printf("error: negative value for recently received network data from gopsutil. recentBytesRecv: %v", recentBytesRecv) + v := fmt.Sprintf("%d", recentBytesRecv) + log.Println(tr.Value("widget.net.err.negvalrecv", v)) // recover from error recentBytesRecv = 0 } if int(recentBytesSent) < 0 { - log.Printf("error: negative value for recently sent network data from gopsutil. recentBytesSent: %v", recentBytesSent) + v := fmt.Sprintf("%d", recentBytesSent) + log.Printf(tr.Value("widget.net.err.negvalsent", v)) // recover from error recentBytesSent = 0 } @@ -160,7 +162,7 @@ func (net *NetWidget) update() { recentConverted, unitRecent = utils.ConvertBytes(recent) } - net.Lines[i].Title1 = fmt.Sprintf(" Total %s: %5.1f %s", label, totalConverted, unitTotal) + net.Lines[i].Title1 = fmt.Sprintf(" %s %s: %5.1f %s", tr.Value("total"), label, totalConverted, unitTotal) net.Lines[i].Title2 = fmt.Sprintf(format, rate, recentConverted, unitRecent) } } diff --git a/widgets/proc.go b/widgets/proc.go index f47f646..ee94825 100644 --- a/widgets/proc.go +++ b/widgets/proc.go @@ -51,7 +51,7 @@ type ProcWidget struct { func NewProcWidget() *ProcWidget { cpuCount, err := psCPU.Counts(false) if err != nil { - log.Printf("failed to get CPU count from gopsutil: %v", err) + log.Println(tr.Value("error.proc.err.count", err.Error())) } self := &ProcWidget{ Table: ui.NewTable(), @@ -63,14 +63,14 @@ func NewProcWidget() *ProcWidget { } self.entry = &ui.Entry{ Style: self.TitleStyle, - Label: " Filter: ", + Label: tr.Value("widget.proc.filter"), Value: "", UpdateCallback: func(val string) { self.filter = val self.update() }, } - self.Title = " Processes " + self.Title = tr.Value("widget.proc.label") self.ShowCursor = true self.ShowLocation = true self.ColGap = 3 @@ -137,7 +137,7 @@ func (proc *ProcWidget) filterProcs(procs []Proc) []Proc { func (proc *ProcWidget) update() { procs, err := getProcs() if err != nil { - log.Printf("failed to retrieve processes: %v", err) + log.Printf(tr.Value("widget.proc.error.retrieve", err.Error())) return } @@ -157,10 +157,15 @@ func (proc *ProcWidget) update() { // sortProcs sorts either the grouped or ungrouped []Process based on the sortMethod. // Called with every update, when the sort method is changed, and when processes are grouped and ungrouped. func (proc *ProcWidget) sortProcs() { - proc.Header = []string{"Count", "Command", "CPU%", "Mem%"} + proc.Header = []string{ + tr.Value("widget.proc.header.count"), + tr.Value("widget.proc.header.command"), + tr.Value("widget.proc.header.cpu"), + tr.Value("widget.proc.header.mem"), + } if !proc.showGroupedProcs { - proc.Header[0] = "PID" + proc.Header[0] = tr.Value("widget.proc.header.pid") } var procs *[]Proc diff --git a/widgets/proc_linux.go b/widgets/proc_linux.go index 164319d..938e5c2 100644 --- a/widgets/proc_linux.go +++ b/widgets/proc_linux.go @@ -11,7 +11,7 @@ import ( func getProcs() ([]Proc, error) { output, err := exec.Command("ps", "-axo", "pid:10,comm:50,pcpu:5,pmem:5,args").Output() if err != nil { - return nil, fmt.Errorf("failed to execute 'ps' command: %v", err) + return nil, fmt.Errorf(tr.Value("widget.proc.err.ps", err.Error())) } // converts to []string, removing trailing newline and header @@ -21,15 +21,15 @@ func getProcs() ([]Proc, error) { for _, line := range linesOfProcStrings { pid, err := strconv.Atoi(strings.TrimSpace(line[0:10])) if err != nil { - log.Printf("failed to convert PID to int: %v. line: %v", err, line) + log.Println(tr.Value("widget.proc.err.pidconv", err.Error(), line)) } cpu, err := strconv.ParseFloat(strings.TrimSpace(line[63:68]), 64) if err != nil { - log.Printf("failed to convert CPU usage to float: %v. line: %v", err, line) + log.Println(tr.Value("widget.proc.err.cpuconv", err.Error(), line)) } mem, err := strconv.ParseFloat(strings.TrimSpace(line[69:74]), 64) if err != nil { - log.Printf("failed to convert Mem usage to float: %v. line: %v", err, line) + log.Println(tr.Value("widget.proc.err.memconv", err.Error(), line)) } proc := Proc{ Pid: pid, diff --git a/widgets/proc_other.go b/widgets/proc_other.go index b761431..a485c4f 100644 --- a/widgets/proc_other.go +++ b/widgets/proc_other.go @@ -23,7 +23,7 @@ func getProcs() ([]Proc, error) { keywords := fmt.Sprintf("pid=%s,comm=%s,pcpu=%s,pmem=%s,args", ten, fifty, five, five) output, err := exec.Command("ps", "-caxo", keywords).Output() if err != nil { - return nil, fmt.Errorf("failed to execute 'ps' command: %v", err) + return nil, fmt.Errorf(tr.Value("widget.proc.err.ps", err.Error())) } // converts to []string and removes the header @@ -33,15 +33,15 @@ func getProcs() ([]Proc, error) { for _, line := range linesOfProcStrings { pid, err := strconv.Atoi(strings.TrimSpace(line[0:10])) if err != nil { - log.Printf("failed to convert first field to int: %v. split: %v", err, line) + log.Println(tr.Value("widget.proc.err.pidconv", err.Error(), line)) } cpu, err := strconv.ParseFloat(utils.ConvertLocalizedString(strings.TrimSpace(line[63:68])), 64) if err != nil { - log.Printf("failed to convert third field to float: %v. split: %v", err, line) + log.Println(tr.Value("widget.proc.err.cpuconv", err.Error(), line)) } mem, err := strconv.ParseFloat(utils.ConvertLocalizedString(strings.TrimSpace(line[69:74])), 64) if err != nil { - log.Printf("failed to convert fourth field to float: %v. split: %v", err, line) + log.Println(tr.Value("widget.proc.err.memconv", err.Error(), line)) } proc := Proc{ Pid: pid, diff --git a/widgets/proc_windows.go b/widgets/proc_windows.go index 56590c7..d34ef5e 100644 --- a/widgets/proc_windows.go +++ b/widgets/proc_windows.go @@ -10,7 +10,7 @@ import ( func getProcs() ([]Proc, error) { psProcs, err := psProc.Processes() if err != nil { - return nil, fmt.Errorf("failed to get processes from gopsutil: %v", err) + return nil, fmt.Errorf(tr.Value("widget.proc.err.gopsutil", err.Error())) } procs := make([]Proc, len(psProcs)) @@ -18,15 +18,15 @@ func getProcs() ([]Proc, error) { pid := psProc.Pid command, err := psProc.Name() if err != nil { - log.Printf("failed to get process command from gopsutil: %v. psProc: %v. i: %v. pid: %v", err, psProc, i, pid) + log.Println(tr.Value("widget.proc.err.getcmd", err, psProc, i, pid)) } cpu, err := psProc.CPUPercent() if err != nil { - log.Printf("failed to get process cpu usage from gopsutil: %v. psProc: %v. i: %v. pid: %v", err, psProc, i, pid) + log.Println(tr.Value("widget.proc.err.cpupercent", err, psProc, i, pid)) } mem, err := psProc.MemoryPercent() if err != nil { - log.Printf("failed to get process memeory usage from gopsutil: %v. psProc: %v. i: %v. pid: %v", err, psProc, i, pid) + log.Println(tr.Value("widget.proc.err.mempercent", err, psProc, i, pid)) } procs[i] = Proc{ diff --git a/widgets/temp.go b/widgets/temp.go index 5a22897..f5632df 100644 --- a/widgets/temp.go +++ b/widgets/temp.go @@ -39,7 +39,7 @@ func NewTempWidget(tempScale TempScale, filter []string) *TempWidget { TempThreshold: 80, TempScale: tempScale, } - self.Title = " Temperatures " + self.Title = tr.Value("widget.label.temp") if len(filter) > 0 { for _, t := range filter { self.Data[t] = 0 From de187a89ae890c219e9baf376d74bc971f43ed28 Mon Sep 17 00:00:00 2001 From: "Sean E. Russell" Date: Thu, 18 Jun 2020 20:03:42 -0500 Subject: [PATCH 04/19] Added a dummy temperature widget label for testing --- translations/zh_CN.toml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/translations/zh_CN.toml b/translations/zh_CN.toml index aa20367..4a98186 100644 --- a/translations/zh_CN.toml +++ b/translations/zh_CN.toml @@ -57,7 +57,8 @@ cpu=" CPU Usage " gauge=" Power Level " battery=" Battery Status " batt=" Battery " -temp=" Temperatures " +# INSERTED JUST FOR TEST +temp=" 显示华氏温度。 " net=" Network Usage " netint=" Network Usage: {0} " mem=" Memory Usage " From aa828c579029a707b2cad77c77afa5ee8ebb0648 Mon Sep 17 00:00:00 2001 From: "Sean E. Russell" Date: Fri, 19 Jun 2020 10:01:26 -0500 Subject: [PATCH 05/19] Translation files are now bundled. --- README.md | 4 + cmd/gotop/main.go | 3 +- config.go | 3 + devices/smc.go | 28 +- devices/temp.go | 2 - go.mod | 2 +- go.sum | 2 + translations/dicts.go | 404 ++++++++++++++++++++++++++++ translations/{ => dicts}/de_DE.toml | 0 translations/{ => dicts}/en_US.toml | 0 translations/{ => dicts}/tt_TT.toml | 0 translations/{ => dicts}/zh_CN.toml | 0 12 files changed, 435 insertions(+), 13 deletions(-) create mode 100644 translations/dicts.go rename translations/{ => dicts}/de_DE.toml (100%) rename translations/{ => dicts}/en_US.toml (100%) rename translations/{ => dicts}/tt_TT.toml (100%) rename translations/{ => dicts}/zh_CN.toml (100%) diff --git a/README.md b/README.md index b8be2df..fd4a361 100644 --- a/README.md +++ b/README.md @@ -69,6 +69,10 @@ Move `gotop` to somewhere in your `$PATH`. If Go is not installed or is the wrong version, and you don't have root access or don't want to upgrade Go, a script is provided to download Go and the gotop sources, compile gotop, and then clean up. See `scripts/install_without_root.sh`. +#### go generate + +Apple SMC tags are embedded in a text file that is compiled into the executable; the same happens with the language translations. When the file `devices/data/sm.tsv` or any translations in `translations/dicts/` change, `go generate` should be re-run. + ## Usage Run with `-h` to get an extensive list of command line arguments. Many of these can be configured by creating a configuration file; see the next section for more information. Key bindings can be viewed while gotop is running by pressing the `?` key, or they can be printed out by using the `--list keys` command. diff --git a/cmd/gotop/main.go b/cmd/gotop/main.go index 5feb075..5e1cd09 100644 --- a/cmd/gotop/main.go +++ b/cmd/gotop/main.go @@ -30,6 +30,7 @@ import ( "github.com/xxxserxxx/gotop/v4/devices" "github.com/xxxserxxx/gotop/v4/layout" "github.com/xxxserxxx/gotop/v4/logging" + "github.com/xxxserxxx/gotop/v4/translations" w "github.com/xxxserxxx/gotop/v4/widgets" ) @@ -354,7 +355,7 @@ func main() { } func run() int { - ling, err := lingo.New("en_US", "translations", nil) + ling, err := lingo.New("en_US", "translations", translations.AssetFile()) if err != nil { fmt.Printf("failed to load language files: %s\n", err) return 2 diff --git a/config.go b/config.go index 5da6f32..16f053c 100644 --- a/config.go +++ b/config.go @@ -1,5 +1,8 @@ package gotop +//go:generate go-bindata -fs -pkg translations -prefix translations -o translations/dicts.go translations/dicts +//go:generate go-bindata -pkg devices -prefix devices/data -o devices/smc.go devices/data + import ( "bufio" "bytes" diff --git a/devices/smc.go b/devices/smc.go index 4701a07..21931c4 100644 --- a/devices/smc.go +++ b/devices/smc.go @@ -1,8 +1,7 @@ -// Code generated by go-bindata. -// sources: -// data/smc.tsv -// DO NOT EDIT! +// Code generated by go-bindata. (@generated) DO NOT EDIT. + //Package devices generated by go-bindata.// sources: +// devices/data/smc.tsv package devices import ( @@ -20,7 +19,7 @@ import ( func bindataRead(data []byte, name string) ([]byte, error) { gz, err := gzip.NewReader(bytes.NewBuffer(data)) if err != nil { - return nil, fmt.Errorf("Read %q: %v", name, err) + return nil, fmt.Errorf("read %q: %v", name, err) } var buf bytes.Buffer @@ -28,7 +27,7 @@ func bindataRead(data []byte, name string) ([]byte, error) { clErr := gz.Close() if err != nil { - return nil, fmt.Errorf("Read %q: %v", name, err) + return nil, fmt.Errorf("read %q: %v", name, err) } if clErr != nil { return nil, err @@ -49,21 +48,32 @@ type bindataFileInfo struct { modTime time.Time } +// Name return file name func (fi bindataFileInfo) Name() string { return fi.name } + +// Size return file size func (fi bindataFileInfo) Size() int64 { return fi.size } + +// Mode return file mode func (fi bindataFileInfo) Mode() os.FileMode { return fi.mode } + +// ModTime return file modify time func (fi bindataFileInfo) ModTime() time.Time { return fi.modTime } + +// IsDir return file whether a directory func (fi bindataFileInfo) IsDir() bool { - return false + return fi.mode&os.ModeDir != 0 } + +// Sys return file is sys mode func (fi bindataFileInfo) Sys() interface{} { return nil } @@ -83,7 +93,7 @@ func smcTsv() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "smc.tsv", size: 3398, mode: os.FileMode(420), modTime: time.Unix(1591711965, 0)} + info := bindataFileInfo{name: "smc.tsv", size: 3398, mode: os.FileMode(420), modTime: time.Unix(1592515411, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -182,6 +192,7 @@ type bintree struct { Func func() (*asset, error) Children map[string]*bintree } + var _bintree = &bintree{nil, map[string]*bintree{ "smc.tsv": &bintree{smcTsv, map[string]*bintree{}}, }} @@ -232,4 +243,3 @@ func _filePath(dir, name string) string { cannonicalName := strings.Replace(name, "\\", "/", -1) return filepath.Join(append([]string{dir}, strings.Split(cannonicalName, "/")...)...) } - diff --git a/devices/temp.go b/devices/temp.go index 247075a..bffd2e9 100644 --- a/devices/temp.go +++ b/devices/temp.go @@ -1,7 +1,5 @@ package devices -//go:generate go-bindata -pkg devices -prefix data -o smc.go data - import ( "log" ) diff --git a/go.mod b/go.mod index a8433f9..440df3c 100644 --- a/go.mod +++ b/go.mod @@ -12,7 +12,7 @@ require ( github.com/shibukawa/configdir v0.0.0-20170330084843-e180dbdc8da0 github.com/shirou/gopsutil v2.20.3+incompatible github.com/stretchr/testify v1.4.0 - github.com/xxxserxxx/lingo v1.0.1 + github.com/xxxserxxx/lingo v1.1.0 github.com/xxxserxxx/opflag v1.0.5 golang.org/x/sys v0.0.0-20200316230553-a7d97aace0b0 howett.net/plist v0.0.0-20200419221736-3b63eb3a43b5 // indirect diff --git a/go.sum b/go.sum index 17ea783..a29c978 100644 --- a/go.sum +++ b/go.sum @@ -39,6 +39,8 @@ github.com/valyala/histogram v1.0.1 h1:FzA7n2Tz/wKRMejgu3PV1vw3htAklTjjuoI6z3d4K github.com/valyala/histogram v1.0.1/go.mod h1:lQy0xA4wUz2+IUnf97SivorsJIp8FxsnRd6x25q7Mto= github.com/xxxserxxx/lingo v1.0.1 h1:lPexOb0HEqYB50EaJdjaYFNATT8JhTcXljbQmCuXygE= github.com/xxxserxxx/lingo v1.0.1/go.mod h1:C2teIFiBLAmEhpLzRkwk7wP5R0eOoveXVYqD+5KOkAs= +github.com/xxxserxxx/lingo v1.1.0 h1:UaA0oNyen0vGWNHD6eow+uCfBu7hhypwb28RxQSnprY= +github.com/xxxserxxx/lingo v1.1.0/go.mod h1:C2teIFiBLAmEhpLzRkwk7wP5R0eOoveXVYqD+5KOkAs= github.com/xxxserxxx/opflag v1.0.5 h1:2H4Qtl1qe+dSkEcGt+fBe2mQ8z14MgkWPqcLaoa6k90= github.com/xxxserxxx/opflag v1.0.5/go.mod h1:GWZtb3/tGGj5W1GE/JTyJAuqgxDxl1+jqDGAGM+P/p4= golang.org/x/sys v0.0.0-20200316230553-a7d97aace0b0 h1:4Khi5GeNOkZS5DqSBRn4Sy7BE6GuxwOqARPqfurkdNk= diff --git a/translations/dicts.go b/translations/dicts.go new file mode 100644 index 0000000..919285e --- /dev/null +++ b/translations/dicts.go @@ -0,0 +1,404 @@ +// Code generated by go-bindata. (@generated) DO NOT EDIT. + + //Package translations generated by go-bindata.// sources: +// translations/dicts/de_DE.toml +// translations/dicts/en_US.toml +// translations/dicts/tt_TT.toml +// translations/dicts/zh_CN.toml +package translations + +import ( + "bytes" + "compress/gzip" + "fmt" + "net/http" + "io" + "io/ioutil" + "os" + "path/filepath" + "strings" + "time" +) + +func bindataRead(data []byte, name string) ([]byte, error) { + gz, err := gzip.NewReader(bytes.NewBuffer(data)) + if err != nil { + return nil, fmt.Errorf("read %q: %v", name, err) + } + + var buf bytes.Buffer + _, err = io.Copy(&buf, gz) + clErr := gz.Close() + + if err != nil { + return nil, fmt.Errorf("read %q: %v", name, err) + } + if clErr != nil { + return nil, err + } + + return buf.Bytes(), nil +} + +type asset struct { + bytes []byte + info os.FileInfo +} + +type bindataFileInfo struct { + name string + size int64 + mode os.FileMode + modTime time.Time +} + +// Name return file name +func (fi bindataFileInfo) Name() string { + return fi.name +} + +// Size return file size +func (fi bindataFileInfo) Size() int64 { + return fi.size +} + +// Mode return file mode +func (fi bindataFileInfo) Mode() os.FileMode { + return fi.mode +} + +// ModTime return file modify time +func (fi bindataFileInfo) ModTime() time.Time { + return fi.modTime +} + +// IsDir return file whether a directory +func (fi bindataFileInfo) IsDir() bool { + return fi.mode&os.ModeDir != 0 +} + +// Sys return file is sys mode +func (fi bindataFileInfo) Sys() interface{} { + return nil +} + + +type assetFile struct { + *bytes.Reader + name string + childInfos []os.FileInfo + childInfoOffset int +} + +type assetOperator struct{} + +// Open implement http.FileSystem interface +func (f *assetOperator) Open(name string) (http.File, error) { + var err error + if len(name) > 0 && name[0] == '/' { + name = name[1:] + } + content, err := Asset(name) + if err == nil { + return &assetFile{name: name, Reader: bytes.NewReader(content)}, nil + } + children, err := AssetDir(name) + if err == nil { + childInfos := make([]os.FileInfo, 0, len(children)) + for _, child := range children { + childPath := filepath.Join(name, child) + info, errInfo := AssetInfo(filepath.Join(name, child)) + if errInfo == nil { + childInfos = append(childInfos, info) + } else { + childInfos = append(childInfos, newDirFileInfo(childPath)) + } + } + return &assetFile{name: name, childInfos: childInfos}, nil + } else { + // If the error is not found, return an error that will + // result in a 404 error. Otherwise the server returns + // a 500 error for files not found. + if strings.Contains(err.Error(), "not found") { + return nil, os.ErrNotExist + } + return nil, err + } +} + +// Close no need do anything +func (f *assetFile) Close() error { + return nil +} + +// Readdir read dir's children file info +func (f *assetFile) Readdir(count int) ([]os.FileInfo, error) { + if len(f.childInfos) == 0 { + return nil, os.ErrNotExist + } + if count <= 0 { + return f.childInfos, nil + } + if f.childInfoOffset+count > len(f.childInfos) { + count = len(f.childInfos) - f.childInfoOffset + } + offset := f.childInfoOffset + f.childInfoOffset += count + return f.childInfos[offset : offset+count], nil +} + +// Stat read file info from asset item +func (f *assetFile) Stat() (os.FileInfo, error) { + if len(f.childInfos) != 0 { + return newDirFileInfo(f.name), nil + } + return AssetInfo(f.name) +} + +// newDirFileInfo return default dir file info +func newDirFileInfo(name string) os.FileInfo { + return &bindataFileInfo{ + name: name, + size: 0, + mode: os.FileMode(2147484068), // equal os.FileMode(0644)|os.ModeDir + modTime: time.Time{}} +} + +// AssetFile return a http.FileSystem instance that data backend by asset +func AssetFile() http.FileSystem { + return &assetOperator{} +} + +var _dictsDe_deToml = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x9c\x17\xdb\x6e\x1c\xb7\xf5\x9d\x5f\x71\x4a\x20\x8d\x0d\x48\x1b\xb9\x46\x1f\x32\xf6\x08\xa8\x65\xd9\x11\x2a\xb9\x8a\x56\x5b\x03\xf5\xea\x81\x3b\x3c\x33\xc3\x2c\x87\x9c\xf0\xb2\xeb\xad\xed\x7f\x2f\x0e\xc9\xbd\xc8\x96\x9a\xc0\x4f\x43\x9e\xfb\xfd\x70\x1a\x6b\x5a\xd5\xb5\x4a\x63\xcd\xcf\xd2\x19\xe8\xc2\x59\xf4\xa2\xc3\x9a\xcf\xe8\x53\xc1\xa7\x93\x2f\xf0\xc1\x8e\x41\x59\xe3\xef\xe6\x66\x6e\xfe\x95\xcf\xd5\xdc\x70\x16\x6c\x10\xba\xe6\xb7\xf4\xe1\x8c\xb1\x0f\x3d\xea\xf1\x8e\x8d\x22\xf4\xbe\xe6\x97\x56\x48\xb1\xd0\x08\x8d\xd5\xd6\xf9\xa6\xc7\x01\x3d\xfc\x15\xb4\xd8\xd8\x18\xfc\x11\x08\x23\x21\xf4\x84\xdf\xa9\x3f\x02\xe1\x10\x3c\x0a\xd7\xf4\x28\xa1\xb5\xee\x08\x94\x01\xeb\x24\xba\x8a\x33\x6d\xbb\x9a\xdf\xf6\x08\xda\x66\x7a\x50\x9e\xf0\x9f\x4e\xbe\x70\xb6\x76\x2a\x04\x34\x3b\x77\xca\x1d\x82\xcd\x78\xc6\x3e\x08\xd7\xf9\x3b\x46\x56\xd6\xfc\x17\xa5\x5b\x0c\xf8\x31\x80\x30\xff\x45\xd5\xa1\x99\x70\x96\x4c\xad\xf9\xb9\x32\xf0\x46\xb8\x45\x32\x5a\x40\x8b\x3e\xf8\x80\x5a\x27\x1a\xdf\x08\x0a\xda\x34\x03\x40\xa2\x81\xe9\x52\x68\x85\x2e\x9a\xce\xb7\x62\x19\xac\x03\x54\xe6\x08\x4e\x4f\x38\x5b\xa1\xf3\xca\x9a\x9a\xff\x27\xe9\x00\xa9\x10\xfe\x9d\x61\x20\xa2\x87\x68\x24\x2c\x10\x8d\x4c\xb2\x47\x74\xcd\x18\x6b\x3e\xed\xed\x1a\x50\x34\x3d\x9c\x5d\xcf\xc8\x43\x8a\x13\x1d\xd7\x4a\x76\x18\xc8\xd2\x31\x8a\x55\x57\x28\xc5\x0a\x9d\xe8\xf0\x51\xe2\x80\xc3\x58\x48\xe9\x88\x4e\x84\xe8\x30\x85\xae\x15\xbd\x43\xd3\xa3\x0a\x93\x3f\xc2\x73\xe6\x83\x08\xd1\x2f\x84\xdb\xea\x85\x1d\x04\xd6\x2a\xf4\x49\x73\x50\x03\x4e\x38\x73\x22\x60\xcd\x6f\xb0\x75\xe8\x7b\x68\x1d\xfe\x1e\xd1\x34\x9b\x09\x5c\x59\x1f\x12\x11\x44\xa3\x82\x07\xd1\x34\x38\x06\x94\x13\x80\x39\x7f\x36\xcc\x39\xd4\xe0\x0a\x1b\xae\xd0\x6d\x60\x50\x26\x06\xcc\xf8\x93\x93\xc1\x3f\x40\x92\xe0\x13\xce\x72\x71\xd5\xfc\x9d\x18\x10\x6c\x5b\x8a\x0d\xfc\x88\x4d\x2e\x98\xd6\xba\x64\xe5\xec\x62\x02\x33\x8f\x30\xe7\xc7\x73\x4e\x35\x32\xaa\x91\xcc\x36\x18\x6a\x3e\x45\x8d\x4d\x00\x83\x61\x6d\xdd\x12\x94\x09\xe8\x5a\xd1\xe0\x04\xa6\xa4\x4e\xe8\x3d\xc8\x43\x23\x0c\x2c\x10\x24\xb6\xca\xa0\x84\xe8\x95\xe9\xa0\xb1\xc3\x20\xc0\xe3\x28\x28\x0e\x12\x56\x42\x47\xf4\x13\xb8\xb8\xcf\x27\xb4\xb7\xc4\xac\x3a\x63\xdd\x8e\x79\xce\xff\x32\xe7\x9c\xe1\xc7\xd1\xba\x50\xf3\x73\x93\xda\x68\xc0\xe0\x54\xe3\x93\x07\x19\x05\x36\xe7\x9a\xbc\x53\xad\x42\x09\x04\x9d\x70\x36\x2c\x46\x5f\x52\xb4\xf5\x81\xcc\x00\xe1\x81\x50\xa9\x22\x7c\xa8\xf9\x4d\x34\x1e\xe8\xe8\x53\x33\xe2\x47\xca\x47\x4a\xa4\x8f\x4d\x83\xde\xff\xd4\x0a\xa5\xa3\xa3\x1e\x95\x98\xfa\xc3\xb4\xdf\xcc\x0c\x8a\x5e\xf4\x08\xca\xf8\x80\x42\x52\xd8\x25\xb6\x22\xea\x00\x4f\xae\x66\xd3\x5b\x78\x75\x0e\x6f\x2e\x6e\xa6\xb7\xf0\x8f\x9b\xb7\xb3\xab\xf3\x77\xb7\x4f\x39\xd3\x8a\x0c\xe0\x9c\x5d\x2a\x1f\xe0\xa5\xc4\x95\x6a\xd0\x7f\x2e\xc3\xe1\xf3\xe1\xcc\xf8\x9c\x06\xca\xe7\x25\x6e\xfc\x29\x03\x80\x42\x5b\xc1\xb5\x53\x26\x78\xa0\x04\x67\x18\x18\x41\x33\x86\x22\xd4\x2a\x1d\xd0\xa5\xc0\xe5\x36\xf0\xc4\x5a\xc4\x57\x40\x5a\x3d\x2c\xa2\xd2\xf2\x58\x99\x2d\x9c\x48\x0e\x35\x1f\xd2\x05\xa2\x3b\x44\x12\x71\xb2\x2c\x53\x25\x33\xf2\x28\x8b\x4e\xd0\x90\xcc\xc1\xc9\xc3\x2c\x53\x12\x4b\xb1\xa6\x82\xf7\xf9\x00\xa1\x17\x61\x5b\x44\xd1\xa3\xa4\xae\x13\xc5\x22\x62\x20\xbf\x2b\xc8\xcd\xd9\x23\x5d\x17\x56\x38\x09\x0b\x65\xa4\x32\x9d\x9f\x50\x14\x69\xd8\x61\xcd\xdf\xd3\x27\x59\x22\x76\x39\x38\x18\xaf\x93\x34\x05\xd1\x39\xeb\xee\x58\x86\x8f\xc2\x79\xac\x39\xe5\x19\x65\xea\x03\x02\x1c\x32\x55\x79\x7c\x36\x5a\x15\x5a\xfa\x50\x99\x9e\x5d\x5e\x00\x4d\xd4\x42\xa0\x6d\xe7\x31\xc4\xf1\x50\x58\x02\xec\xa6\x75\x21\x8c\x66\x69\xec\xda\xd8\x31\xd4\x7c\x96\xcf\x90\x57\x0c\xcc\xf9\xa7\x93\x2f\x73\xfe\x02\x82\xdb\xec\x17\xc5\x61\xd4\x8f\x52\x3c\x8e\x72\x3c\x8f\xc0\xba\x6d\x39\xd0\x42\x4a\x51\x20\xed\x35\x7f\xb3\xb3\x21\x01\x1f\xc8\xcc\xd6\xaf\x1e\x9b\x65\x5a\x2c\x29\x2e\x1e\xd0\x34\x36\x52\x9b\xa2\x7c\x01\xad\xb3\x03\xd1\x55\x9c\x95\xfe\xcb\x2e\x26\x5a\x72\x2f\x50\x24\xe2\x98\x16\x65\xa1\xa8\xe0\xd3\xb3\x2f\x9c\x19\x5b\xee\x35\x37\xf6\x5e\xf7\x12\x6d\xd2\xdd\x8a\x20\x68\x0b\x35\x3d\x05\x2d\x08\x0d\x59\x6e\x02\x91\x60\xa2\x54\xa6\xb5\x45\xa4\xc3\xc6\xae\x0a\x7d\x3a\x97\x0a\x7f\x84\xeb\x05\xf8\xa5\x1a\xc7\x02\x2a\xfe\x1a\x2b\x71\xd5\xda\x68\x64\xb2\x2b\xfa\x24\x81\x58\x12\x90\xb3\xe4\x21\x3a\xf7\xb0\x93\xc5\x12\xc6\x3e\x94\xed\xa2\xc5\x02\xf5\x1d\x93\xca\x2f\x6b\x0e\xaf\x95\x5f\x42\x7a\x3b\x40\xda\x51\x35\x4f\x9b\x68\x0b\xe9\x44\xa4\xc7\x05\x5c\xdb\x35\x3a\xb8\xc4\x15\x6a\xe0\x6c\x21\x42\x40\xb7\xa9\x39\xbc\xca\x27\x98\xa6\xb5\x52\x50\x07\xf0\xed\x2a\x83\xdb\xc3\x35\x55\xa6\x36\xbc\x2b\xb3\x6e\xab\xcd\x60\x50\xe6\x1b\x44\x7e\xd4\x50\x3e\x87\x9a\xc3\x15\x0e\xd6\x6d\x76\x2c\xf9\x6d\xc0\x39\xfb\x35\xaa\x50\xc1\xef\x54\x60\x2f\xcf\x8e\x9b\x53\xc6\xae\x9d\xa5\x91\x08\x46\xac\x54\x97\xca\xa8\x62\x00\xc7\xb0\x4c\xb3\xf3\xe5\x6c\x3c\xad\x20\x8e\x09\xf4\x5b\x06\xbd\xb6\x6b\x73\x5a\x81\xb4\x6b\x93\xc0\x2f\xcf\x8e\xe3\x69\x05\xbd\xd0\x2d\x8c\xa4\xaf\x90\xbf\x3c\x3b\x96\xf7\xe0\x87\x1c\x8b\xd3\x0a\xda\xa8\xf5\xd7\x1c\xed\x3d\xf8\x8e\xa3\xeb\xb2\xee\x5f\xec\x80\xa7\x15\xfc\x16\x87\x91\x9a\x20\xd8\xcc\xf8\x36\x63\xcf\x8d\x3c\x40\x2e\x6c\x08\x76\xd8\x7b\x28\x9a\xfc\xc6\xcb\xaa\x6e\x05\x99\x10\x6c\xd7\x69\x84\xb1\x90\x74\xce\x46\x2a\xac\x44\x22\x65\x05\x4b\xa5\x35\xf8\xb4\x37\x69\x0f\x15\x32\xeb\x32\x25\xed\x84\x02\xc3\xb2\x61\xa6\x17\x6f\x6f\xcf\x6f\xae\xe0\xc9\xb3\xbf\x3f\xcd\x52\x9e\x7f\x9f\x94\x5f\x67\x17\xb7\xf0\xe4\x79\x11\xf2\xf3\xf7\x09\xf9\xe7\xc5\xe5\x25\x3c\xf9\xf9\xe9\x3e\x08\xde\x3a\x2a\xfb\x1c\x84\xa6\xa2\x32\x4e\xc7\xa1\xa2\x9a\x49\xc7\xb1\x82\xeb\x8b\xd7\x7b\x96\xbc\x73\x76\x4c\x3f\x55\xf4\x3c\x72\x01\x50\xaa\xd4\x41\x19\x9f\x70\x4f\xd6\x3d\x2d\x87\x82\x79\x4a\x0c\x29\xd8\xe7\x34\x78\x4e\xab\xf2\x28\xda\x73\x94\xa4\x37\xa7\x25\x7f\xbe\x11\x23\xe5\xb7\xd1\x28\xb6\xcb\x8e\x31\x6a\x35\xc2\x5f\xe1\x00\x9d\x13\x63\x0f\xf4\x58\xdd\x19\xd4\x57\xe9\x4e\x9b\x3a\xdd\xf5\xf6\x4e\x9b\x86\x95\x26\xc9\xa4\x8b\x5d\xc6\x17\x18\xd6\x88\x26\x3d\x1c\x92\xf0\xc4\x22\x61\xb1\x09\xe8\x61\x44\x1a\x10\x8d\x35\x92\x51\xd7\xec\xc7\x82\xc1\x30\x41\xe7\xee\xa8\x09\xa9\x9e\x56\x2a\x6c\x0e\x37\x43\x87\xfb\xf7\xd5\x16\x9f\xa7\x6d\x67\x47\x1f\x83\xd2\xdb\x79\x85\xdd\x4a\x68\x87\xcd\xaa\x0c\xa4\x0a\x0c\x52\xff\xad\x30\xbf\xaa\xd2\x48\x75\xd8\xa0\x09\x7a\x93\x0e\x6a\x85\x72\x27\x5c\x8a\x20\xee\x0b\x9e\x14\xea\x57\xe4\xc1\x0d\x36\xab\x7b\x9a\x3c\xd2\xc8\xf8\x13\x9a\x88\xf0\xcf\x6a\x99\xa2\x09\xd5\xee\x37\xa4\x84\x88\x46\xe6\x76\x70\xd2\xdc\xe4\x6c\xa0\xc5\x53\xf3\x2b\xfa\xd0\x9f\x18\x4a\xfa\x11\x43\xc9\x59\xeb\x10\x6b\xfe\xc6\x21\x72\xe6\x7c\xcd\x6f\x7e\xf2\x9c\xad\x7d\xcd\xdf\xd3\x61\x2f\x93\x2a\xfb\x8e\xe5\x7a\xa8\x39\xbc\x49\x87\x0a\xe8\x61\xbc\x40\x4d\x93\x77\x57\xfa\xfc\x1e\xd3\xa4\x47\x21\x31\x3d\x0b\x92\x0d\x67\xd9\x86\xf4\x8e\xa5\x55\x71\x96\x0f\x65\xa8\x9f\x5d\xcf\x7e\x28\x13\xf4\x0a\x87\x1f\x38\x1b\x95\xac\xf9\xf5\xc5\xeb\xaf\x84\xa6\x0a\x28\x12\xef\xe7\x9e\x4a\x35\x21\x1e\x4c\xba\xa3\x6d\x89\xab\x7b\x0f\x93\x2d\x6c\xdf\xbd\x85\x98\xde\xba\x7b\x32\xfc\x88\x4d\x0c\x08\x3f\x8e\xfe\x47\x28\xe6\x17\xc2\xad\x92\xaf\x6d\xd9\x8f\x83\x87\x6c\x19\x95\x6c\xac\x59\x1d\x32\xd1\x1d\x5d\xa0\xee\xa7\xab\x2a\xc9\x9d\x80\x56\x06\xcb\x86\x6c\xc6\xf8\x18\x1b\xf9\x9e\x7e\xb3\x09\xd8\x6a\x2b\x1e\x60\x1f\x70\x78\x8c\x9d\xba\xfb\x8f\xd8\x3b\x0c\xcd\x20\x1f\x71\x74\x1b\x96\x07\xdc\x9d\xc0\xe8\xa9\x44\x92\x98\x09\xa8\x0a\x3e\xfd\x8d\x80\x8a\x62\xf8\x3c\xbb\x45\x3f\xa9\xf8\x6d\x46\x77\xc2\xc7\x58\xcc\xfb\x0e\xf1\x43\xda\xeb\xff\x4f\xfc\x80\x03\xd2\xc6\xfe\x6e\x15\xff\x0b\x00\x00\xff\xff\xb1\x93\x63\x99\xfa\x10\x00\x00") + +func dictsDe_deTomlBytes() ([]byte, error) { + return bindataRead( + _dictsDe_deToml, + "dicts/de_DE.toml", + ) +} + +func dictsDe_deToml() (*asset, error) { + bytes, err := dictsDe_deTomlBytes() + if err != nil { + return nil, err + } + + info := bindataFileInfo{name: "dicts/de_DE.toml", size: 4346, mode: os.FileMode(420), modTime: time.Unix(1592527807, 0)} + a := &asset{bytes: bytes, info: info} + return a, nil +} + +var _dictsEn_usToml = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x9c\x17\x4d\x4f\x1c\x39\xf6\xee\x5f\xf1\xd6\xd2\xec\x10\x09\x7a\xc8\x46\x7b\x98\x0a\xd5\xd2\x86\x90\x2c\x5a\xc8\x32\x40\x2b\x87\x34\x07\xb7\xfd\xaa\xca\x83\xcb\xae\xb1\x5d\xdd\x69\x91\xfc\xf7\xd5\xb3\xdd\x1f\x24\xb0\x33\xca\xa9\xec\xf7\xfd\xfd\x5c\xd2\xd9\x46\xb7\x8d\x36\x58\xf3\xd3\x74\x06\xba\x70\x36\x06\xd1\x62\xcd\x67\xf4\xa9\xe0\xe1\xf8\x2b\x7c\x72\x43\xd4\xce\x86\xbb\xb9\x9d\xdb\xff\xe6\x73\x35\xb7\x9c\x45\x17\x85\xa9\xf9\x2d\x7d\x38\x63\xec\x53\x87\x66\xb8\x63\x83\x88\x5d\xa8\xf9\x85\x13\x4a\x2c\x0c\x82\x74\xc6\xf9\x20\x3b\xec\x31\xc0\xdf\xc1\x88\xb5\x1b\x63\x38\x04\x61\x15\xc4\x8e\xf0\x5b\xf5\x87\x20\x3c\x42\x40\xe1\x65\x87\x0a\x1a\xe7\x0f\x41\x5b\x70\x5e\xa1\xaf\x38\x33\xae\xad\xf9\x6d\x87\x60\x5c\xa6\x07\x1d\x08\xff\x70\xfc\x95\xb3\x95\xd7\x31\xa2\xdd\xba\x53\xee\x10\x5d\xc6\x33\xf6\x49\xf8\x36\xdc\x31\xb2\xb2\xe6\x37\x9d\x5b\x41\xec\x74\x80\x20\x3d\xa2\x9d\x70\x96\x0c\xad\xf9\x0d\x46\x10\xfb\x56\x4f\x38\x0b\x52\x50\xa4\xde\x7b\x31\x74\x90\x2e\xd0\x08\x19\xc9\xbe\xe9\x31\x67\x4b\xf4\x41\x3b\x5b\xf3\x2b\xaf\x6d\x84\x72\x4d\x1e\xe2\x67\x1d\x27\x9c\x0d\xe8\xe5\x30\x16\xb5\x28\x64\x07\xa7\x57\x33\xb2\x9d\x22\x40\xc7\x95\x56\x2d\x12\xa5\x1c\x46\xb1\x6c\x0b\xa5\x58\xa2\x17\x2d\x3e\x4b\x1c\xb1\xdf\xfa\x82\xfd\x80\x5e\xc4\xd1\x63\x0a\x4a\x23\x3a\x8f\xb6\x43\x1d\x27\x7f\x86\xe7\x2c\x44\x11\xc7\xb0\x10\x7e\xa3\x17\xb6\x10\x58\xe9\xd8\x25\xcd\x51\xa7\x58\x78\x11\xb1\xe6\xd7\xd8\x78\x0c\x1d\x34\x1e\xff\x18\xd1\xca\xf5\x04\x2e\x5d\x88\x89\x08\x46\xab\x63\x00\x21\x25\x0e\x11\xd5\x04\x60\xce\x5f\xf6\x73\x0e\x35\xf8\xc2\x86\x4b\xf4\x6b\xe8\xb5\x1d\x23\x66\xfc\xf1\x71\x1f\x9e\x20\x49\xf0\x09\x67\xb9\x6c\x6a\xfe\x41\xf4\x08\xae\x29\x65\x04\x61\x40\x99\x4b\xa1\x71\x3e\x59\x39\x3b\x9f\xc0\x2c\x20\xcc\xf9\xd1\x9c\x53\xf6\x07\x3d\x90\xd9\x16\x23\xe5\xd6\xa0\x8c\x60\x31\xae\x9c\xbf\x07\x6d\x23\xfa\x46\x48\x9c\xc0\x0d\xa9\x13\x66\x07\x0a\x20\x85\x85\x05\x82\xc2\x46\x5b\x54\x30\x06\x6d\x5b\x90\xae\xef\x05\x04\x1c\x04\xc5\x41\xc1\x52\x98\x11\xc3\x04\xce\x1f\xf3\x09\x13\x1c\x31\xeb\xd6\x3a\xbf\x65\x9e\xf3\xbf\xcd\x39\x67\xf8\x79\x70\x3e\xd6\xfc\xcc\xa6\x06\xe9\x31\x7a\x2d\x43\xf2\x20\xa3\xc0\xe5\x5c\x93\x77\xba\xd1\xa8\x80\xa0\x13\xce\xfa\xc5\x10\x4a\x8a\x36\x3e\x90\x19\x20\x02\x10\x2a\x55\x44\x88\x35\xbf\x1e\x6d\x00\x3a\x86\x6d\x11\x86\x9c\xc8\x30\x4a\x89\x21\xfc\xd2\x08\x6d\x46\x4f\xdd\xa7\x30\xd5\xbe\x6d\xbe\x9b\x06\x14\xbd\x31\x20\x68\x1b\x22\x0a\x45\x61\x57\xd8\x88\xd1\x44\x38\xb8\x9c\xdd\xdc\xc2\x9b\x33\x78\x77\x7e\x7d\x73\x0b\xff\xba\x7e\x3f\xbb\x3c\xfb\x70\xfb\x82\x33\xa3\xc9\x00\xce\xd9\x85\x0e\x11\x4e\x14\x2e\xb5\xc4\xf0\xa5\xb4\xfd\x97\xfd\x69\xf0\x25\x8d\x8a\x2f\xf7\xb8\x0e\x53\x06\x00\x85\xb6\x82\xd4\x46\x01\x28\xc1\x19\x06\x56\xd0\xf4\xa0\x08\x35\xda\x44\xf4\x29\x70\xb9\x0d\x02\xb1\x16\xf1\x15\x90\xd6\x00\x8b\x51\x1b\x75\xa4\xed\x06\x4e\x24\xfb\x9a\xf7\xe9\x22\xd1\xed\x23\x89\x38\x59\x96\xa9\x92\x19\x79\x48\x8d\x5e\xd0\xf8\xcb\xc1\xc9\x63\x2a\x53\x12\x4b\xb1\xa6\x82\x8f\xf9\x00\xb1\x13\x71\x53\x44\x63\x40\x45\x5d\x27\x8a\x45\xc4\x40\x7e\x57\x50\x06\x11\xd2\x75\xe1\x84\x57\xb0\xd0\x56\x69\xdb\x86\x09\x45\x91\xc6\x18\xd6\xfc\x23\x7d\x92\x25\x62\x9b\x83\xbd\xc1\x39\x49\xf3\x0d\xbd\x77\xfe\x8e\x65\xf8\x20\x7c\xc0\x9a\x53\x9e\x51\xa5\x3e\x20\xc0\x3e\x53\x95\x07\xa3\x34\xba\xd0\xd2\x87\xca\xf4\xf4\xe2\x1c\x68\x56\x16\x02\xe3\xda\x80\x71\x1c\xf6\x85\x25\xc0\x76\x0e\x17\xc2\xd1\xde\x5b\xb7\xb2\x6e\x88\x35\x9f\xe5\x33\xe4\xe5\x01\x73\xfe\x70\xfc\x75\xce\x5f\x43\xf4\xeb\xdd\x0a\xd8\x8f\xfa\x61\x8a\xc7\x61\x8e\xe7\x21\x38\xbf\x29\x07\x5a\x35\x29\x0a\xa4\xbd\xe6\xef\xb6\x36\x24\xe0\x13\x99\xd9\xf8\xd5\xa1\xbc\x4f\x2b\x23\xc5\x25\x00\x5a\xe9\x46\x6a\x53\x54\xaf\xa1\xf1\xae\x27\xba\x8a\xb3\xd2\x7f\xd9\xc5\x44\x4b\xee\x45\x8a\xc4\x38\xa4\x15\x58\x28\x2a\x78\x78\xf9\x95\x33\xeb\xca\xbd\xe6\xd6\x3d\xea\x5e\xa2\x4d\xba\x1b\x11\x85\x69\x30\xca\x8e\x82\x16\x85\x81\x2c\x37\x81\x48\x30\x51\x6a\xdb\xb8\x22\xd2\xa3\x74\xcb\x42\x9f\xce\xa5\xc2\x9f\xe1\x7a\x0d\xe1\x5e\x0f\x43\x01\x15\x7f\xad\x53\xb8\x6c\xdc\x68\x55\xb2\x6b\x0c\x49\x02\xb1\x24\x20\x67\xc9\x43\xf4\xfe\x69\x27\x8b\x25\x8c\x7d\x2a\xdb\xc5\x88\x05\x9a\x3b\xa6\x74\xb8\xaf\x39\xbc\xd5\xe1\x1e\xd2\xab\x00\xd2\x8e\xaa\x79\xda\x44\x1b\x48\x2b\x46\x7a\x36\xc0\x95\x5b\xa1\x87\x0b\x5c\xa2\x01\xce\x16\x22\x46\xf4\xeb\x9a\xc3\x9b\x7c\x82\x9b\xb4\x56\x0a\x6a\x0f\xbe\x59\x65\x70\xbb\xbf\xa6\xca\xd4\x86\x0f\x65\xd6\x6d\xb4\x59\x8c\xda\x7e\x87\xc8\xcf\x15\xca\x67\x5f\x73\xb8\xc4\xde\xf9\xf5\x96\x25\x6f\x7d\xce\xd9\x6f\xa3\x8e\x15\xfc\x41\x05\x76\x72\x7a\x24\xa7\x8c\x5d\x79\x47\x23\x11\xac\x58\xea\x36\x95\x51\xc5\x00\x8e\xe0\x3e\xcd\xce\x93\xd9\x30\xad\x60\x1c\x12\xe8\xf7\x0c\x7a\xeb\x56\x76\x5a\x81\x72\x2b\x9b\xc0\x27\xa7\x47\xe3\xb4\x82\x4e\x98\x06\x06\xd2\x57\xc8\x4f\x4e\x8f\xd4\x23\xf8\x3e\xc7\x62\x5a\x41\x33\x1a\xf3\x2d\x47\xf3\x08\xbe\xe5\x68\xdb\xac\xfb\xdf\xae\xc7\x69\x05\xbf\x8f\xfd\x40\x4d\x10\x5d\x66\x7c\x9f\xb1\x67\x56\xed\x21\x17\x2e\x46\xd7\xef\x3c\x14\x32\xbf\xde\xb2\xaa\x5b\x41\x26\x44\xd7\xb6\x06\x61\x28\x24\xad\x77\x23\x15\x56\x22\x51\xaa\x82\x7b\x6d\x0c\x84\xb4\x37\x69\x0f\x15\x32\xe7\x33\x25\xed\x84\x02\xc3\xb2\x61\x6e\xce\xdf\xdf\x9e\x5d\x5f\xc2\xc1\xcb\x7f\xbe\xc8\x52\x5e\xfd\x98\x94\xdf\x66\xe7\xb7\x70\xf0\xaa\x08\xf9\xf5\xc7\x84\xfc\xe7\xfc\xe2\x02\x0e\x7e\x7d\xb1\x0b\x42\x70\x9e\xca\x3e\x07\x41\x56\x54\xc6\xe9\xd8\x57\x54\x33\xe9\x38\x54\x70\x75\xfe\x76\xc7\x92\x77\xce\x96\xe9\x97\x8a\x9e\x47\x3e\x02\x2a\x9d\x3a\x28\xe3\x13\xee\x60\xd5\xd1\x72\x28\x98\x17\xc4\x90\x82\x7d\x46\x83\x67\x5a\x95\x47\xd1\x8e\xa3\x24\x5d\x4e\x4b\xfe\x82\x14\x03\xe5\x57\x1a\x14\x9b\x65\xc7\x18\xb5\x1a\xe1\x2f\xb1\x87\x76\xfb\x08\xdd\x1a\xd4\x55\xe5\x51\xaa\x73\xad\x98\xcd\x9d\x36\x0d\x2b\x4d\x92\x49\x17\xdb\x8c\x2f\x30\xae\x10\x6d\x7a\x38\x24\xe1\x89\x45\xc1\x62\x1d\x31\xc0\x80\x34\x20\xa4\xb3\x8a\x51\xd7\xec\xc6\x82\xc5\x38\x41\xef\xef\xa8\x09\xa9\x9e\x96\x3a\xae\xf7\x37\x43\x8b\xbb\xf7\xd5\x06\x9f\xa7\x6d\xeb\x86\x30\x46\x6d\x36\xf3\x0a\xdb\xa5\x30\x1e\xe5\xb2\x0c\xa4\x0a\x2c\x52\xff\x2d\x31\xbf\xaa\xd2\x48\xf5\x28\xd1\x46\xb3\x4e\x07\xbd\x44\xb5\x15\xae\x44\x14\x8f\x05\x4f\x0a\xf5\x1b\xf2\xe0\x1a\xe5\xf2\x91\xa6\x80\x34\x32\xfe\x82\x26\x22\xfc\xab\x5a\x6e\xd0\xc6\x6a\xfb\x83\x51\x42\x44\x23\x73\x33\x38\x69\x6e\x72\xd6\xd3\xe2\xa9\xf9\x25\x7d\xe8\x1f\x0b\x15\xfd\x62\xa1\xe2\xac\xf1\x88\x35\x7f\xe7\x11\x39\xf3\xa1\xe6\xd7\xbf\x04\xce\x56\xa1\xe6\x1f\xe9\xb0\x93\x49\x95\x7d\xc7\x72\x3d\xd4\x1c\xde\xa5\x43\x05\xf4\x30\x5e\xa0\xa1\xc9\xbb\x2d\x7d\xfe\x88\x69\xd2\xa1\x50\x98\x9e\x05\xc9\x86\xd3\x6c\x43\x7a\xc7\xd2\xaa\x38\xcd\x87\x32\xd4\x4f\xaf\x66\x3f\x95\x09\x7a\x89\xfd\x4f\x9c\x0d\x5a\xd5\xfc\xea\xfc\xed\x37\x42\x53\x05\x14\x89\x8f\x73\x4f\xa5\x9a\x10\x4f\x26\xdd\xd3\xb6\xc4\xe5\xa3\x87\xc9\x06\xb6\xeb\xde\x42\x4c\x6f\xdd\x1d\x19\x7e\x46\x39\x46\x84\x9f\x87\xf0\x33\x14\xf3\x0b\xe1\x46\xc9\xb7\xb6\xec\xc6\xc1\x53\xb6\x0c\x5a\x49\x67\x97\xfb\x4c\x74\x47\x1f\xa9\xfb\xe9\xaa\x4b\x72\x27\x60\xb4\xc5\xb2\x21\xe5\x30\x3e\xc7\x46\xbe\xa7\x1f\x68\x02\x36\xc6\x89\x27\xd8\x7b\xec\x9f\x63\xa7\xee\xfe\x33\xf6\x16\xa3\xec\xd5\x33\x8e\x6e\xc2\xf2\x84\xbb\x13\x18\x02\x95\x48\x12\x33\x01\x5d\xc1\xc3\x3f\x08\xa8\x29\x86\xaf\xb2\x5b\xf4\x93\x8a\xdf\x67\x74\x2b\x7c\x18\x8b\x79\x3f\x20\xbe\x4f\x7b\xfd\xff\x89\xef\xb1\x47\xda\xd8\x3f\xac\xe2\x7f\x01\x00\x00\xff\xff\xb8\x3c\x62\x18\xd4\x10\x00\x00") + +func dictsEn_usTomlBytes() ([]byte, error) { + return bindataRead( + _dictsEn_usToml, + "dicts/en_US.toml", + ) +} + +func dictsEn_usToml() (*asset, error) { + bytes, err := dictsEn_usTomlBytes() + if err != nil { + return nil, err + } + + info := bindataFileInfo{name: "dicts/en_US.toml", size: 4308, mode: os.FileMode(420), modTime: time.Unix(1592527521, 0)} + a := &asset{bytes: bytes, info: info} + return a, nil +} + +var _dictsTt_ttToml = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x9c\x57\x4d\x6f\xdc\x38\xd2\xbe\xf3\x57\xd4\x4b\x60\xde\xc9\x00\x4e\x4f\xb2\xc1\x1e\x46\x89\x0c\x6c\x1c\x3b\x6b\xac\x9d\xf5\xd8\x6e\xe4\x90\xf6\x81\x4d\x95\x24\x4e\x53\x24\x87\x2c\xa9\xd3\x48\xf2\xdf\x17\x45\x49\xed\x76\xe2\x60\x82\xb9\xa9\x59\xdf\x5f\x4f\x55\x6b\xef\x6a\xd3\xd4\xc6\x62\x29\x4f\xce\xde\xc2\xd9\xc5\xa9\x14\x7d\x52\x0d\x96\x12\x1b\x95\x96\x05\x7c\x7a\xf6\x05\x3e\x24\xe7\x0d\x05\x7f\xb7\x72\x2b\x37\x7e\xff\xb7\x58\x39\x29\xc8\x93\xb2\xa5\xb4\x8a\xfc\xad\x14\x42\x7c\x68\xd1\x86\x3b\x11\x14\xb5\xa9\x94\x11\xab\xe8\xc1\x19\x38\x8a\xbe\x86\x0a\x5b\x1d\x15\x26\xc0\xa8\xe0\x08\xad\xa9\xa1\x31\xb5\xf3\x1a\xb0\x25\xa8\x9c\x82\xa3\x44\xbd\xdf\x29\x0b\xff\x0f\x09\x3b\x6c\x75\x8a\xde\x32\xdd\xae\x55\xa5\xfc\x45\x21\x85\xf5\x4d\x29\x9d\x81\x64\x60\xd4\xe0\x2d\x60\x7b\xcb\x5e\x4a\xb1\x8d\x86\x08\x5d\x29\x3d\x81\x43\x22\x13\xb7\xa3\x89\x93\x91\x2e\xc4\x07\x15\x9b\x74\x27\xd8\xcb\x52\x2e\x1c\x62\xd4\x09\x92\x69\x09\xb6\xbe\xbd\x91\x42\x7b\xeb\x63\x29\x17\x87\xd6\x15\x10\xde\x48\x91\xb4\xe2\x2c\x3d\x3b\xe6\x68\x48\xab\x1a\xd0\x2a\x9d\xa0\x0d\x2a\xbe\x95\x62\xc0\x98\x8c\x77\xa5\x5c\x90\xf9\x88\x39\x1c\xe7\x4d\x8a\x38\x00\x39\x13\xaf\xa4\x08\x18\x75\xe8\x99\x01\x9b\xca\x6c\x61\x79\x75\x92\x23\x77\x26\x7f\xb6\x5a\xe1\xec\x45\xe8\xd5\xd0\x7c\x97\x13\x1b\x15\x71\x50\x13\x33\x61\x17\xb2\x55\x6c\x1d\xc6\x56\xd5\xcc\x96\x30\xf6\xa4\x22\x86\x0e\xc7\xd0\xfe\x8a\x2e\x45\x22\x45\x7d\x5a\xab\x31\x7c\x43\xd9\x62\x4b\x66\x0b\x51\xad\x53\x4f\x8a\x12\xcc\x36\xa3\x22\x2c\xe5\x22\x75\xcf\x9e\x3d\x87\x5d\xc4\x01\xa1\x4d\x18\x6b\x8c\x50\xc2\x4a\xe6\xf7\x95\x04\x58\x20\xf5\xce\x74\x8f\xb0\x74\x23\xbd\x42\x0a\xa8\xb5\x82\x44\xc6\xf5\x90\xed\x52\xf2\x97\xb0\xd8\x69\x87\xfd\x9f\x18\xeb\x49\xec\x5a\x0a\xab\x76\xbe\xa7\x52\xbe\x53\x1d\x82\xaf\x61\xfc\x0d\x29\xa0\x06\x6e\x61\xa8\x7d\x04\x6a\x11\x96\xe7\x0b\x58\x26\x84\x95\x7c\xba\x92\x40\x1e\x82\x09\xb8\x90\xc2\x21\x95\xb2\x71\x26\xf5\x50\x61\xf4\xae\x31\x80\x6b\xf0\xc9\x2a\x70\x4a\x43\x42\xad\xea\x88\xe4\xce\x61\x91\xb0\xb7\x6a\x80\x0a\x49\x45\x15\x30\x81\xea\x3a\xaf\x61\x16\x76\xa6\xc6\x8a\x85\x1f\xc8\x19\xb0\x5c\x19\xbc\x81\xc5\xfd\xd3\x26\xfa\x2d\xa1\x03\xd2\x68\xf1\x06\x56\xf2\xff\x56\x52\x0a\xfc\x18\x7c\x24\xae\x5b\xf4\x01\x2a\x34\xb5\xd1\x18\xd2\x58\x66\x0f\xfc\xfa\x11\x81\xc7\x26\x69\x13\x09\xbb\x3c\x04\xee\x54\x8a\x6e\x1d\x12\xe7\x3e\xac\x3b\x48\x0a\xd8\xc1\xbd\x8d\xb9\x23\x12\x6b\xc6\x8a\x47\x27\xf6\xd6\xa8\xfa\xd7\x94\x50\xeb\x3e\x8d\x05\x4d\xfb\x16\x4d\x94\x90\x20\xb9\xfe\x9a\x7b\xdf\xd5\x23\x12\xfc\x72\xfb\xee\xf4\x72\xf9\xf6\xfa\x5f\x70\x7b\x73\x7d\x7e\x06\xa7\xaf\xe1\xf6\x66\x79\xf9\x04\xc8\xf6\x8a\x03\xaf\x3d\x54\x0a\x29\x39\x03\x98\x7a\xf0\x04\xf7\xe3\x7c\x22\x85\x35\xec\x80\x94\xe2\x38\xed\x70\xf3\x39\xb5\xa4\xc2\xe7\xc3\x89\xfe\x3c\x0d\xfa\xe7\x84\xda\x0c\x58\xbd\x02\x4a\xe6\x42\xa4\xa9\xdf\x39\xd4\x88\xc4\x2a\x73\x06\xb0\x53\x0e\x46\x4e\xa0\xde\x43\xca\x13\x05\xc5\x24\x0d\x00\x62\x46\x0e\x67\x9e\x56\xd6\xf4\x6b\x8e\xcc\x5c\x40\x31\xbf\x33\xcb\xe1\x50\x3b\xf3\x94\x1e\xf0\x1d\x12\x99\x99\x7d\x86\x19\xb0\xd8\x13\x46\x3d\x15\xfb\x09\xb2\xd8\x8d\x49\x32\x73\x02\x88\xc9\x92\xe2\xf9\xaa\x38\x2d\x53\x7b\x90\x6a\x09\xc6\xd0\xde\xb3\x43\x63\x8c\x00\x62\x91\x1a\x67\x2a\x67\xd6\x50\x45\xe5\xd7\x3b\xdc\xe4\xf2\x73\x11\xa1\xe0\xcc\x01\x00\x67\x91\x61\x8d\xc7\xed\x10\x32\xe7\x4a\xa8\xec\x09\x92\x89\xef\x33\xbe\x61\x8c\x3e\xde\x89\x11\xd7\x83\x8a\x89\x81\xfc\x10\x6a\x53\x54\x81\x0b\x56\x21\xf7\x45\x31\x02\xa3\xb6\x66\xe2\x4d\x4d\x54\x70\x7e\x71\x92\x3b\x3d\xaa\x30\x31\x58\xdf\x24\xa4\x3e\xcc\xca\xbc\x85\xd0\x13\xa6\x6f\x34\xf5\x6e\xe3\xfc\xd6\xf9\x40\xa5\x1c\x77\x06\xb8\xad\x77\x1b\xb7\x84\x95\xfc\xf4\xec\xcb\x4a\xbe\x84\xb9\x6c\xd1\xc3\xd1\x98\xbd\xa3\x1c\xed\xd1\x83\x22\xec\x97\xc1\x2e\x12\xaf\x9a\x9c\x85\x5a\x19\x3b\xf9\xf0\xb0\x1e\x98\xc1\x7e\xf6\xe6\x6c\x8e\xab\x45\xbd\xc9\x2b\xa3\xf3\xb1\x86\x97\x15\xf2\x4c\xf6\x5e\x3b\x84\x14\x7d\x8c\xc8\x7c\x85\x14\x1d\x52\x34\x7a\x0a\x31\xf4\x1c\x3d\x71\x78\x7b\x9e\x79\x0c\x0b\xf8\xf4\xfc\x8b\x14\xce\x4f\x12\xa5\x3c\x9c\x51\xef\x32\x6f\xb6\x5d\x2b\x52\xb6\x46\xd2\x6d\xc6\x9c\x56\x13\xd6\x93\x3e\xab\x48\xd5\x99\xd3\xd7\xce\x4c\x2a\x23\x6a\x3f\x3c\xce\x3f\xce\xc3\xe0\x35\xc6\x2c\xd5\x38\x13\x82\xd9\x24\x78\xc9\xf2\x39\x84\xd1\xa6\xf3\x15\x0e\xb5\xef\x5d\xc5\x49\x5a\x2b\x9e\xcd\xd1\xa5\xca\xf5\xbe\x96\x22\x47\x88\x31\x3e\x1e\xe4\xe4\x89\x10\x1f\xb6\xa6\x6a\x90\x16\x56\xad\xd1\xde\x89\xca\xa4\x4d\x29\x21\x1f\x04\xb0\x49\xe6\x0d\xe4\x1d\xb5\x7f\xe2\xa5\x24\x45\xa3\x7a\x3e\x1b\xc0\xe2\x80\x17\x10\x71\xeb\xaf\x40\x8a\xb5\x22\xc2\xb8\x2b\x25\xe4\x1d\x72\xc3\xbb\x80\x48\xbd\x9e\x48\xa5\x3c\x78\x18\x57\xd9\xe1\x72\xba\x85\x09\xb5\x67\xe3\x19\xe8\xde\x8d\xaf\xc6\x7d\x43\x18\xcf\x15\xae\x67\xb7\x27\xed\xa2\xef\xf0\x12\xe4\xb4\xf5\x19\x96\xf4\xd3\x93\x57\xdc\x7e\x7f\x42\x41\xa6\xff\x5d\x88\x22\x77\x53\x63\x06\xe5\x80\xa1\xd2\xc7\x2b\x11\x7a\x28\x8e\xc3\xf2\x55\x06\xca\x0d\x3c\x05\x10\x6e\xeb\x2b\x28\x8e\xdd\xd6\xbf\x19\x9f\xff\xc8\xcf\xa1\x67\x53\x01\x6a\xab\x5a\x28\x8e\x7b\xd6\xbe\x67\x3f\xa4\x54\x33\x65\x96\xb0\xb6\xaf\xa1\x38\x5e\x7f\x2b\x31\x51\xea\xbd\x84\x27\x6e\xef\xd0\xf5\x7f\x40\x71\x8c\x9d\xff\xf7\xe8\x41\xd3\x64\x72\xe7\x89\xfc\xfa\x80\xa3\x72\xa7\x23\xc3\xdb\x4c\x17\x45\x3e\xdb\x78\xd3\x4e\xe1\x71\x13\xf5\x3e\x36\xd3\x43\x00\xb4\x4d\xe3\x89\xbd\x51\xb7\xa3\xcd\x5f\xfe\xf9\xfc\x09\x5c\x5e\x9f\xde\xbe\x3d\xbf\x99\x36\x07\xce\xdc\xb5\x87\x51\x3c\xfa\xbd\x86\x0a\xf3\x92\x4b\x60\xad\xd9\x40\x51\x55\xa3\x96\x17\x4f\xe0\xf6\x7c\xf9\xfb\xdf\x53\xf2\x62\x52\xf2\xdb\x13\xb8\xb8\x38\xff\xcf\xdf\x53\xf2\x5b\x35\x25\x81\x5b\x3e\xfa\xb4\x4f\x02\x77\x6e\xa1\xc7\x0c\xe2\x25\x14\x5d\xfe\x7c\x73\x7e\x05\x45\xb8\x17\x99\x76\xd1\x2c\x34\xfd\x64\x5d\xa6\x42\xa0\xc8\xa7\x51\xf1\x6b\xe6\x2f\x7e\x99\x9f\xd1\x9a\x76\xfb\x24\x3f\x4e\x02\xd3\xa9\x53\x1c\x33\x08\x9d\xe6\x14\xdf\x13\xa3\x42\xab\xb9\xb2\x41\xe9\x34\x95\x6e\xec\xd3\x91\x2d\x3b\xb2\x3f\x38\x1b\x60\x77\x99\x67\x79\x75\x22\x78\x0d\x67\x52\xd1\x66\x7b\x79\x25\x8c\x0f\x76\x8a\x62\x9a\x0f\x51\x39\xaf\x79\xe4\x31\x40\x42\xda\xad\x19\x2f\x99\x31\x1f\x03\x7c\x52\x38\xc4\x2d\xe1\x7a\xdf\x0d\xeb\xac\x80\xa7\xe6\x1e\x16\x1c\xd2\x02\x63\xbc\xe3\x21\x54\x9a\xcc\x60\x68\x57\x4a\x6b\xa8\x4f\xc1\x37\x90\xb1\x76\x97\x9f\xb5\xba\xbf\x7f\xb0\xf9\x66\x5b\x38\x6c\x06\x65\x23\xea\xa1\x94\xc5\xa0\xf1\x9a\x7d\x7a\x4d\x0e\x19\xe9\x16\x0f\x15\x2a\x52\xd5\x5e\x59\x85\x83\xc9\x4c\x3b\x3b\x71\x33\x0c\x8f\x37\x1b\x0e\x3c\xca\xe8\xa0\xd8\x03\xdb\x6c\x29\x21\x43\x46\x41\x0e\x6f\x7e\xd4\x12\x39\x4c\x3f\x6c\xe5\x3e\x45\x0c\x99\x33\x70\x32\x62\x4a\xd1\xf9\x9e\x8d\xf3\xfa\xb9\xe4\xff\x58\x58\x95\xb2\xc2\xb4\x94\xa2\x8e\xc8\x5b\x1a\xe3\x99\x14\x31\x95\x32\xfd\x7a\x2d\xc5\x36\x7f\xbc\x3f\xd4\x19\xa2\xd7\x77\xa2\x36\x96\x30\x96\x12\x8a\xdc\x39\x67\xc0\x87\xf1\x1a\x6d\x06\xce\xa9\x45\x41\x3e\x10\x5a\xb4\xa8\x2a\xcc\x67\xc1\xde\x87\x13\x3e\xf8\xba\x4e\xf1\xaa\xa8\x1c\x5f\xb7\x27\x13\xa8\xff\xb4\xbc\x3a\x99\x10\xf4\xa7\x0e\x2f\xa5\x08\xa6\x2a\xe5\x9b\xf3\xab\xaf\x94\xe6\x0e\x98\x34\x16\x0f\x33\x98\x77\x6c\x5e\x0b\x0f\xaa\x3e\x26\x29\xf2\xe6\xc4\x01\x4b\x59\xdc\x0f\x31\x0e\xc8\x2b\x34\x7e\xcd\xcc\xb7\x6e\x31\xfa\xa7\xe1\xe7\x14\x7e\x06\xa4\x5e\xe3\x47\xfc\x9a\xb1\xf1\x21\xf5\xc4\xd7\xc1\x57\xbe\xdc\xdb\x78\xc4\x97\x60\x2a\xed\xdd\x90\x7b\xc2\x30\x91\x47\x9f\x22\x0e\x7c\x53\x3c\xe0\x5d\x00\x3a\x63\xa7\x0d\xa9\x43\x3f\x8b\x29\x6f\xeb\x7c\x00\x37\xbc\x6d\x73\xc8\x8f\x8b\x17\x2c\x3f\x8a\x77\xd8\x3d\x2e\xce\x43\xfd\xd7\xe2\x0d\x92\xee\xaa\x6f\x02\x9d\xb3\xf4\xdd\x70\x17\xc0\xbd\x91\x42\x0e\x62\x01\x7c\x78\xfc\xe3\xcb\x02\x2a\xc3\x2f\x2f\xc6\xb0\xf8\x4f\x6a\x1e\x92\x87\xba\x47\xf7\xfa\xf0\x1d\xed\xc5\x0f\xa9\xef\xb0\xdb\xab\xff\x5a\xf5\x2e\x7a\xec\xb0\x7b\x5c\x3d\xd7\xf5\xc7\x4c\xfc\x2f\x00\x00\xff\xff\xc2\xd6\x81\x84\xd0\x10\x00\x00") + +func dictsTt_ttTomlBytes() ([]byte, error) { + return bindataRead( + _dictsTt_ttToml, + "dicts/tt_TT.toml", + ) +} + +func dictsTt_ttToml() (*asset, error) { + bytes, err := dictsTt_ttTomlBytes() + if err != nil { + return nil, err + } + + info := bindataFileInfo{name: "dicts/tt_TT.toml", size: 4304, mode: os.FileMode(420), modTime: time.Unix(1592527628, 0)} + a := &asset{bytes: bytes, info: info} + return a, nil +} + +var _dictsZh_cnToml = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x9c\x57\xdd\x73\xd4\x46\x12\x7f\xd7\x5f\xd1\x37\x57\xa9\x90\x2a\xec\x98\x4b\xdd\x43\x14\xcb\x0f\x31\x26\xe7\x3b\xc8\x39\xd8\xae\x3c\x60\x3f\x68\xa5\xde\x5d\xc5\x92\x46\xa7\x19\xed\xc6\x05\x54\x2d\x3e\x8c\x6d\xb0\xbd\x40\xcc\xc7\x19\x2e\xe0\x04\x1f\x1f\xe1\x30\xf9\x38\xb3\xfe\xc2\x7f\x0c\x2b\xad\xf7\x89\x7f\xe1\xaa\x47\xda\xf5\x9a\x98\x4a\x8a\x27\xcd\x74\xff\xba\xa7\xbf\xa6\x7b\x64\x71\x3f\xef\x14\xf2\x8e\x8b\x06\x6b\x4e\x2f\x34\x76\x9e\x25\x37\x67\xea\x5b\xeb\x4c\x8b\x84\x59\x40\x83\xd5\x77\x76\x1b\x4b\x8f\x92\x9b\x1b\xc9\xcf\x37\x74\x38\xdb\x73\x1e\xce\x34\x2b\x73\xcd\x95\x8d\xf1\x31\x7f\xcc\x4f\x97\xfa\x98\xcf\x34\xc9\xa5\xe9\x1a\x6c\x84\x3e\x4c\xd3\xb4\x33\x45\x74\x83\x71\x2d\x30\x65\x51\x18\x2c\x99\x9f\x6b\xae\x6c\xc6\x9b\xd5\xfa\xd6\x62\x7d\x6b\xb5\x5e\xbb\x52\xdf\xa1\xd3\xea\xdb\xb7\xe3\xe9\xd9\xbd\xb5\xad\xb8\x7a\xb3\x39\xbd\xb0\x37\xf7\x13\x1d\xb5\x32\xfb\xaa\x72\x21\xae\xfd\x33\xfe\xb1\x92\x6e\xe3\xeb\xf3\x9d\xd6\xe9\x4c\x73\x79\xc1\x60\xc9\xad\xd5\x78\xf7\x56\x4a\xab\xef\x2c\xd4\x37\x17\xc9\x42\xa6\x95\x43\x47\x4a\xf4\x0f\xba\x14\xbf\xf8\x29\xbe\xf4\xaf\x78\x7a\x35\xc5\x68\xda\x19\x33\x2c\x88\x71\x8d\xec\x34\x58\x72\xfb\x65\xe3\xc1\x66\xbc\xf3\x4d\x3c\xb7\x10\x5f\x9a\x8e\x9f\x6d\xbc\xaa\x4c\x31\xcd\xe2\x2e\x0f\x0d\x16\xcf\xae\xc7\xcf\x96\x0f\x1a\x38\xc5\x34\x61\x99\x14\xb8\xf8\xce\xcb\x78\xe7\xbb\xc6\xf6\xe3\x64\xe9\x65\xb2\xb6\x54\x7f\x79\xe5\xf5\xf6\x7c\x5f\x0f\xd3\x4a\x18\x0a\x87\xfb\x2d\xed\x8d\xb9\xd9\xe4\xee\xd3\x78\x63\xbd\x59\xa9\xc4\x33\x9b\x4a\x45\x80\xa1\x15\x44\x06\x8b\xef\x3e\x82\xfe\xa1\x51\x68\x6c\x5d\x24\x67\x6a\xff\x4d\x45\x92\xb5\x6a\xbd\xf6\x84\x38\xa9\x39\x41\x64\x96\x0a\x87\xa0\xe3\x8d\x9f\xe3\x7f\xcf\xb4\x71\x12\xbd\x7d\x9f\x16\x16\x93\xe7\xd5\xa4\xf6\x38\xde\xfc\x4f\x6a\xb5\x34\x65\x24\x72\x66\xd8\x42\x24\xb7\xd6\x9b\xb7\x7e\x69\x5c\x5e\x4f\x2a\x17\x92\xfb\x55\x05\x0a\x4d\x49\x9e\xcd\xbe\x48\x6e\x3e\x6f\x7e\x77\xad\xb1\x38\xf3\xaa\x32\x15\xd7\x6a\x7b\x0f\x2f\x34\x96\x2f\xa6\x12\xf1\xc2\x0d\xca\xe2\xf2\xa5\xb8\xba\xd6\x58\x7a\xf4\xaa\x32\x35\xc6\x8e\x79\x63\x0c\x0c\x48\xd6\xaa\xf1\xec\xa5\xe6\xf5\x7b\xa9\x86\x94\xd5\xd3\xe3\x89\x16\xf7\x58\x4f\x4f\xb2\xf6\x43\xe3\xe1\xf5\x36\x80\x69\xae\x39\xc9\x23\x69\xb0\x2c\xf3\xd5\xea\xde\xee\xf3\x2c\x77\x57\x17\x5e\x55\xa6\xd2\x5a\x84\x31\xd6\x35\xc6\x60\x6f\xf7\xdb\x64\x71\x55\xc9\xf9\x28\x0d\xd6\xac\xcc\x25\x57\x1e\x37\x76\xae\xc5\x0b\x2b\x64\xea\x83\xe5\x7a\xed\x49\xba\x6d\x2c\x3d\x6a\x56\x6e\xc5\xd5\x17\x64\xd2\xf2\x52\xa7\xa6\x3f\x8c\x31\x88\x77\x77\x1a\x37\x56\x93\xf9\x99\xf8\xd9\x72\x5b\x9e\x69\xf8\x75\xc0\x43\xa9\x62\x9d\xf1\x7e\x58\x8b\xab\xdf\xd7\x6b\x97\xe3\xab\xe4\x6e\x32\x3f\x93\xdc\x9f\xd9\x7b\xf9\x4d\x2b\x95\x5e\x2e\x10\xed\x54\xef\x5c\x6b\x56\xee\xd5\x6b\x9b\x40\xd4\x6e\xca\x88\x90\x06\x4b\xe6\x1e\xee\xad\xcc\x27\xff\xbb\xb2\xb7\x76\x23\xde\x58\xdf\xdb\x5d\x8a\xef\x7c\x9b\xcc\x5e\x8d\x2f\xdf\x4b\x66\x6f\xc6\x0f\x7e\xdc\xfb\x65\xb5\x71\xff\x42\x56\x7a\x7e\x3e\xbd\x98\x8d\xa5\x47\xf5\xcd\xc5\xe4\xce\x6e\x7d\xeb\xfb\xc6\xf6\x66\xe3\xee\x85\xb8\x3a\x95\xdc\x78\xde\x58\xbe\xd8\x59\xe0\xaf\xb7\x67\xe3\xdd\xe9\xe6\xca\x56\x72\x7b\xad\xf1\xf4\x69\xbd\x56\xa9\xd7\x9e\xa4\xc8\xd7\xdb\x73\x4c\x73\x1d\x32\x81\x31\xed\xa4\x23\x24\xf4\xda\x58\x72\x2c\x14\xe7\xd2\xa8\x8b\x73\xaa\xd4\x85\x55\x44\x0f\xc5\x39\x75\x6d\xcf\x4d\xe0\xa4\xe8\xd3\x00\x20\xc3\xea\x30\x14\x3a\xbe\x14\xc0\x23\x99\xd1\xc0\x37\x3d\x14\x90\xe7\x21\xe4\x1d\x57\x62\x68\xe6\x5c\x84\xb2\x63\x17\x50\x0a\x12\xcd\xd4\xeb\x40\xa7\x0a\xc8\x45\x8e\x6b\x77\x39\x7e\x8b\x4e\x90\xce\x93\x3b\x71\x92\x70\x9d\x4c\x02\x2b\xcb\x52\x94\x32\x23\xed\x60\x51\x68\x4a\x87\xfb\x64\x03\x82\x40\x33\xb4\x8a\x29\x92\x44\x32\x6b\x74\xf8\x32\x5d\x80\x2c\x9a\x12\x2c\xd3\x87\x1c\x42\x24\xd0\x06\xc7\x07\x33\xb3\x88\x04\xc8\x6f\x1d\x86\x8b\xbc\x0c\xb2\x88\xb4\xcd\x71\x33\xb4\x21\xe7\xf8\xb6\xe3\x17\x44\x37\x45\x91\x9a\x0c\x1a\xec\x4b\xfa\x28\x4b\x4c\xb0\x31\x6f\x46\x6e\xcb\x26\x65\x4c\xb7\xea\x34\x18\x86\x3c\x1c\xd7\x52\x7a\x60\x86\x02\x0d\x96\x37\x1d\x17\x6d\x90\x1c\x14\xa1\x53\x48\x4f\x5b\x94\xe5\x3a\x19\x96\x3e\x8e\x5f\x80\xfe\x93\x83\x40\x5d\x2b\x03\xb8\xbc\x20\x50\x46\x41\xa7\x32\x45\x00\x97\x1f\xd0\x14\xf9\x13\x3e\x2f\xfb\x3c\x90\x06\x1b\x4d\xd7\xc0\x03\x15\xb1\x31\x76\xb6\xe7\xfc\x18\xfb\x04\x64\x38\xd9\x4a\xca\xd1\x03\x51\x3f\xaa\xe2\x71\x34\x8d\xe7\x51\xe0\x61\xab\x1c\xa8\xed\xab\x28\xd0\xe9\x06\x3b\xd1\xb6\x41\x11\x0f\xc9\x4c\xcb\xaf\x22\x5a\x13\xaa\x81\xab\xb8\x08\x40\xdf\xe2\x91\x2f\x31\x44\xfb\x13\xc8\x87\xdc\x23\x9c\xce\x34\x0f\x65\xe8\x58\x99\x8b\x0a\x4b\xee\x49\x8a\x44\x14\xa8\x61\x94\x21\x74\x38\x7b\xec\x3c\xd3\x7c\x9e\xed\x0d\xe6\xf3\x16\x4f\xd5\x26\x61\xd5\xd9\x79\x53\x9a\x6e\x1e\xa5\x55\xa4\xa0\x49\xd3\x85\x54\xaf\x22\x91\x62\x42\x3a\x7e\x9e\x67\x2a\x43\xb4\x78\x29\xc3\xab\x75\x56\xe1\x6f\x91\xfa\x04\xc4\x84\x13\x04\x19\x29\xf3\xd7\xe7\x36\x96\xf2\x3c\xf2\x6d\x65\x57\x24\x94\x06\x12\x51\x44\xa6\x29\x0f\x31\x0c\x0f\x77\x32\xb3\x44\xd3\xce\xa4\x85\xdc\xed\x9a\x39\x74\xc7\x35\xdb\x11\x13\x06\x83\xe3\x8e\x98\x80\x51\x9a\xd6\xa0\x06\x84\xc1\xd4\x68\x68\x51\x0a\x66\x44\x73\x1c\x86\x78\x19\x43\x38\x89\x25\x74\x81\x69\x39\x53\x4a\x0c\x27\x0d\x06\x9f\xa6\x2b\x18\x56\x53\x21\x63\x75\xd0\x99\xf6\x47\x18\xfc\x7c\x78\xe0\xf4\xc8\xc0\x71\xf8\xeb\xe8\xf0\x08\x9c\xf8\xfb\x69\x18\x19\x18\x1e\xc9\xa6\x0c\x1c\x3a\x66\x20\x6b\xcb\xf0\x39\xca\x32\x0f\xf7\x2d\xf4\x51\x3a\xfe\xaf\x18\xe9\xd3\x82\x32\xee\x19\x0c\x4e\xa1\xc7\xc3\xc9\xb6\x48\x3a\xa1\x19\xd3\xbe\x88\x1c\xa9\xc3\x3f\xa8\x04\x7b\xfb\xbb\xac\x3e\x4d\x1b\x0a\xb9\x85\x42\x80\x6f\x96\x9c\x82\x2a\x34\x5d\x03\xe8\x82\x09\x30\x7d\x1b\x7a\x47\x83\x3e\x1d\xa2\x40\x91\xbe\x4a\x49\xc7\x79\xd9\xef\xd3\xc1\xe6\x65\x5f\x91\x7b\xfb\xbb\xa2\x3e\x1d\x8a\xa6\x9b\x87\x80\xce\xcb\xe0\xbd\xfd\x5d\xf6\x01\x7a\xa7\x44\xae\x4f\x87\x7c\xe4\xba\x6f\x4a\xe4\x0f\xd0\xdb\x12\x85\x42\x7a\xf6\x5f\xb8\x87\x7d\x3a\x7c\x15\x79\x01\x5d\x13\xc9\x53\xc1\xcf\x52\xee\x80\x6f\x77\x30\x73\x5c\x4a\xee\xed\x7b\x68\x5a\xe4\x9d\x48\xdd\xeb\x1d\x31\xc9\x04\xc9\x0b\x05\x17\x21\xc8\x20\x85\x90\x47\x54\x7a\x0a\x62\xdb\x3a\x4c\x38\xae\x0b\x02\x5d\xb4\x24\xda\x6d\x18\x0f\x53\x24\xf0\x7c\x8b\x86\x02\xca\x8e\x2c\xc2\xf0\xe0\x67\x23\x03\xa7\x4f\xc1\x91\x63\x7f\xfe\x20\xd5\xf2\xd1\xbb\x69\xf9\x62\x74\x70\x04\x8e\x7c\x94\x29\xf9\xf8\xdd\x94\xfc\x6d\xf0\xe4\x49\x38\xf2\xf1\x07\xfb\x41\x10\x3c\xa4\x8b\x91\x06\xc1\xd2\xa9\xd0\xd5\xd2\xd3\xa9\x66\xd4\x32\xd0\x61\x68\xf0\xf8\xbe\x48\x3a\x95\xda\x42\x1f\xea\x20\xa4\x19\x4a\x40\xdb\x51\x77\x2c\xe5\x2b\xde\x91\x72\x91\xc6\x47\xc6\xf9\x80\x04\x54\xb0\x07\xa8\x35\xf5\xe9\x60\x5a\x16\x06\x72\x5f\x22\x4b\xba\xd5\x97\xe5\x4f\x58\x66\x40\xf9\xb5\x5c\x34\x5b\xe3\x50\xd3\xe8\x32\x12\xff\x14\x7a\x50\x08\xcd\xa0\x08\xf4\x6c\x6c\x1b\x54\xd4\xd5\x1e\xc1\x49\x6b\xc5\x6d\xed\x69\x16\x69\xd9\x25\x49\xa1\xb9\x76\xc6\x73\x28\xcb\x88\xbe\x7a\x5c\x28\xe5\x4a\xc4\x86\xdc\xa4\x44\x01\x01\x52\x0b\xb1\xb8\x6f\x6b\x74\x6b\xf6\x1b\x87\x8f\xb2\x1b\xc3\x70\x9c\x2e\x21\xd5\x53\xc9\x91\x93\x9d\xb3\xa3\x80\x12\xfc\xec\x5a\xb6\xf8\x69\x3f\x2e\xf0\x40\x44\xd2\x71\x5b\x1d\x0d\x0b\x25\xd3\x0d\xd1\x2a\x65\x2d\x4b\x07\x1f\xe9\xfe\x95\x10\x4a\xa6\x1b\xa1\x6a\xba\x21\x5a\xe8\x4b\x77\x52\x2d\x9c\x12\xda\x6d\xe5\xb6\x29\xcd\x83\x8a\xbb\x33\xf4\xa7\xe4\xc1\x69\xb4\x4a\x07\x4e\x12\x48\x2d\xe3\x77\x9c\x44\xc0\xdf\x7b\xca\x30\xfa\x52\x6f\xff\x0c\x64\x21\xa2\xa6\xda\x6a\xad\xd4\x59\x99\xe6\xd1\x68\x32\xd8\x29\xfa\xd0\x6f\x11\xda\x06\x1b\x15\x68\x33\x2d\x1f\x22\x1a\xec\x44\x88\xc8\xb4\x50\x18\xec\xf4\x87\x82\x69\x65\x61\xb0\x2f\x69\xb1\xaf\x93\x2a\x7b\x5c\x4b\xeb\xc1\x60\x70\x42\x2d\x74\xa0\x07\x6f\x0e\x5d\xea\xcd\xed\xd2\x67\x07\x84\xba\x8b\x68\xda\xa8\x1e\x0e\xca\x86\xfe\xd4\x06\x8b\x7b\x9e\x49\xc3\xa4\x3f\x5d\x64\x6d\xbf\x7f\x68\xf4\xbd\xac\x83\x9e\x42\xef\x3d\xa6\x05\x8e\x6d\xb0\xa1\xc1\xe3\x6f\x28\x55\x15\x90\x69\x3c\x98\x7b\x2a\x55\xc5\x38\x34\xe9\x21\xcd\x53\x2c\x1d\x78\xba\xb4\x68\xfb\xb7\x37\x03\xd3\x53\x78\x1f\x86\x5f\xa3\x15\x49\x84\xf7\x03\xf1\x3e\x64\xe6\x67\xc0\xd6\x21\x6f\xda\xb2\xdf\x0e\x0e\xb3\x25\x70\x6c\x8b\xfb\xa5\x4e\x21\xda\x63\x28\xe9\xf6\xd3\xd6\xc9\x92\xdb\x0d\xae\xe3\x63\x36\x43\xad\x20\x7a\x9b\x18\xf9\xae\xfe\x79\x89\x98\x77\xb9\x79\x88\xb8\x87\xde\xdb\xc4\xe9\x76\xff\x96\x78\x01\xa5\xe5\xd9\x6f\x71\xb4\x15\x96\x43\xdc\xed\x86\x40\x50\x89\x28\x35\xdd\xe0\xe8\x70\xf6\x4f\x44\x74\x28\x86\x1f\xa5\x6e\xd1\x7f\x24\xfe\x3a\xa3\x6d\xe5\x41\x94\x99\xf7\x0e\xea\x3d\xf4\x7e\x43\xbd\x87\x1e\xd2\xc4\x7e\xe7\x23\xfe\x1f\x00\x00\xff\xff\xd6\x01\x02\x19\x88\x10\x00\x00") + +func dictsZh_cnTomlBytes() ([]byte, error) { + return bindataRead( + _dictsZh_cnToml, + "dicts/zh_CN.toml", + ) +} + +func dictsZh_cnToml() (*asset, error) { + bytes, err := dictsZh_cnTomlBytes() + if err != nil { + return nil, err + } + + info := bindataFileInfo{name: "dicts/zh_CN.toml", size: 4232, mode: os.FileMode(420), modTime: time.Unix(1592528537, 0)} + a := &asset{bytes: bytes, info: info} + return a, nil +} + +// Asset loads and returns the asset for the given name. +// It returns an error if the asset could not be found or +// could not be loaded. +func Asset(name string) ([]byte, error) { + cannonicalName := strings.Replace(name, "\\", "/", -1) + if f, ok := _bindata[cannonicalName]; ok { + a, err := f() + if err != nil { + return nil, fmt.Errorf("Asset %s can't read by error: %v", name, err) + } + return a.bytes, nil + } + return nil, fmt.Errorf("Asset %s not found", name) +} + +// MustAsset is like Asset but panics when Asset would return an error. +// It simplifies safe initialization of global variables. +func MustAsset(name string) []byte { + a, err := Asset(name) + if err != nil { + panic("asset: Asset(" + name + "): " + err.Error()) + } + + return a +} + +// AssetInfo loads and returns the asset info for the given name. +// It returns an error if the asset could not be found or +// could not be loaded. +func AssetInfo(name string) (os.FileInfo, error) { + cannonicalName := strings.Replace(name, "\\", "/", -1) + if f, ok := _bindata[cannonicalName]; ok { + a, err := f() + if err != nil { + return nil, fmt.Errorf("AssetInfo %s can't read by error: %v", name, err) + } + return a.info, nil + } + return nil, fmt.Errorf("AssetInfo %s not found", name) +} + +// AssetNames returns the names of the assets. +func AssetNames() []string { + names := make([]string, 0, len(_bindata)) + for name := range _bindata { + names = append(names, name) + } + return names +} + +// _bindata is a table, holding each asset generator, mapped to its name. +var _bindata = map[string]func() (*asset, error){ + "dicts/de_DE.toml": dictsDe_deToml, + "dicts/en_US.toml": dictsEn_usToml, + "dicts/tt_TT.toml": dictsTt_ttToml, + "dicts/zh_CN.toml": dictsZh_cnToml, +} + +// AssetDir returns the file names below a certain +// directory embedded in the file by go-bindata. +// For example if you run go-bindata on data/... and data contains the +// following hierarchy: +// data/ +// foo.txt +// img/ +// a.png +// b.png +// then AssetDir("data") would return []string{"foo.txt", "img"} +// AssetDir("data/img") would return []string{"a.png", "b.png"} +// AssetDir("foo.txt") and AssetDir("notexist") would return an error +// AssetDir("") will return []string{"data"}. +func AssetDir(name string) ([]string, error) { + node := _bintree + if len(name) != 0 { + cannonicalName := strings.Replace(name, "\\", "/", -1) + pathList := strings.Split(cannonicalName, "/") + for _, p := range pathList { + node = node.Children[p] + if node == nil { + return nil, fmt.Errorf("Asset %s not found", name) + } + } + } + if node.Func != nil { + return nil, fmt.Errorf("Asset %s not found", name) + } + rv := make([]string, 0, len(node.Children)) + for childName := range node.Children { + rv = append(rv, childName) + } + return rv, nil +} + +type bintree struct { + Func func() (*asset, error) + Children map[string]*bintree +} + +var _bintree = &bintree{nil, map[string]*bintree{ + "dicts": &bintree{nil, map[string]*bintree{ + "de_DE.toml": &bintree{dictsDe_deToml, map[string]*bintree{}}, + "en_US.toml": &bintree{dictsEn_usToml, map[string]*bintree{}}, + "tt_TT.toml": &bintree{dictsTt_ttToml, map[string]*bintree{}}, + "zh_CN.toml": &bintree{dictsZh_cnToml, map[string]*bintree{}}, + }}, +}} + +// RestoreAsset restores an asset under the given directory +func RestoreAsset(dir, name string) error { + data, err := Asset(name) + if err != nil { + return err + } + info, err := AssetInfo(name) + if err != nil { + return err + } + err = os.MkdirAll(_filePath(dir, filepath.Dir(name)), os.FileMode(0755)) + if err != nil { + return err + } + err = ioutil.WriteFile(_filePath(dir, name), data, info.Mode()) + if err != nil { + return err + } + err = os.Chtimes(_filePath(dir, name), info.ModTime(), info.ModTime()) + if err != nil { + return err + } + return nil +} + +// RestoreAssets restores an asset under the given directory recursively +func RestoreAssets(dir, name string) error { + children, err := AssetDir(name) + // File + if err != nil { + return RestoreAsset(dir, name) + } + // Dir + for _, child := range children { + err = RestoreAssets(dir, filepath.Join(name, child)) + if err != nil { + return err + } + } + return nil +} + +func _filePath(dir, name string) string { + cannonicalName := strings.Replace(name, "\\", "/", -1) + return filepath.Join(append([]string{dir}, strings.Split(cannonicalName, "/")...)...) +} diff --git a/translations/de_DE.toml b/translations/dicts/de_DE.toml similarity index 100% rename from translations/de_DE.toml rename to translations/dicts/de_DE.toml diff --git a/translations/en_US.toml b/translations/dicts/en_US.toml similarity index 100% rename from translations/en_US.toml rename to translations/dicts/en_US.toml diff --git a/translations/tt_TT.toml b/translations/dicts/tt_TT.toml similarity index 100% rename from translations/tt_TT.toml rename to translations/dicts/tt_TT.toml diff --git a/translations/zh_CN.toml b/translations/dicts/zh_CN.toml similarity index 100% rename from translations/zh_CN.toml rename to translations/dicts/zh_CN.toml From 342efdd29a7526a63c20b03edce07d177abc64b3 Mon Sep 17 00:00:00 2001 From: Yaojun Feng Date: Sat, 20 Jun 2020 13:26:35 +0800 Subject: [PATCH 06/19] Update the translation of Mandarin Chinese --- translations/zh_CN.toml | 119 ++++++++++++++++++++-------------------- 1 file changed, 59 insertions(+), 60 deletions(-) diff --git a/translations/zh_CN.toml b/translations/zh_CN.toml index 4a98186..6f58df4 100644 --- a/translations/zh_CN.toml +++ b/translations/zh_CN.toml @@ -1,6 +1,6 @@ -configfile="配置文件" +configfile=" 配置文件" usage="使用方法: {0} [选项]\n\n选项:\n" -total="Total" +total="总计" [help] @@ -11,8 +11,8 @@ written="配置文件已写入 {0}" [args] help="显示当前内容。" -color="制定配色方案。" -scale="图形缩放比例,>0" +color="配色方案。" +scale="图形比例尺度,>0" version="显示版本并退出。" percpu="在 CPU 组件中显示每个 CPU。" cpuavg="在 CPU 组件中平均 CPU。" @@ -22,18 +22,18 @@ rate="刷新频率。常见的时间单位皆可用。\"1m\" = 每分钟刷新 layout="布局描述文件名。使用 \"-\" 连接。" net="选择网卡。多个网卡用逗号分隔。使用 \"!\" 忽略指定网卡。" export="在指定端口上启用指标输出。" -mbps="显示网速为 mbps." +mbps="显示网速为 mbps。" test="执行测试并返回成功或失败码。" conffile="用于替代缺省参数的配置文件(必须是第一个参数)" list=""" List - devices: Prints out device names for filterable widgets - layouts: Lists build-in layouts - colorschemes: Lists built-in colorschemes - paths: List out configuration file search paths - widgets: Widgets that can be used in a layout - keys: Show the keyboard bindings.""" -write="Write out a default config file." + devices: 显示可用于过滤的设备名 + layouts: 列出所有内置布局方案 + colorschemes: 列出所有内置配色方案 + paths: 列出配置文件的搜索路径 + widgets: 所有可被用于布局的组件 + keys: 显示所有热键。""" +write="将当前配置写入缺省配置文件。" [error] @@ -52,52 +52,51 @@ setuperr="error setting up {0}: {1}" [widget.label] -disk=" Disk Usage " -cpu=" CPU Usage " -gauge=" Power Level " -battery=" Battery Status " -batt=" Battery " -# INSERTED JUST FOR TEST -temp=" 显示华氏温度。 " -net=" Network Usage " -netint=" Network Usage: {0} " -mem=" Memory Usage " +disk=" 磁盘使用率 " +cpu=" CPU 使用率 " +gauge=" 功率 " +battery=" 电池状态 " +batt=" 电池 " +temp=" 温度 " +net=" 网络使用率 " +netint=" 网络使用率: {0} " +mem=" 内存使用率 " help=""" -Quit: q or +退出: q or -Process navigation: - - k and : up - - j and : down - - : half page up - - : half page down - - : full page up - - : full page down - - gg and : jump to top - - G and : jump to bottom +进程导航: + - k 或 : 上一行 + - j 或 : 下一行 + - : 上半页 + - : 下半页 + - : 上一页 + - : 下一页 + - gg 或 : 到顶部 + - G 或 : 到底部 -Process actions: - - : toggle process grouping - - dd: kill selected process or group of processes with SIGTERM (15) - - d3: kill selected process or group of processes with SIGQUIT (3) - - d9: kill selected process or group of processes with SIGKILL (9) +进程操作: + - : 切换进程组 + - dd: 发送信号 SIGTERM (15) 终止进程或进程组 + - d3: 发送信号 SIGTERM (3) 终止进程或进程组 + - d9: 发送信号 SIGTERM (9) 终止进程或进程组 -Process sorting: +进程排序: - c: CPU - - m: Mem - - p: PID + - m: 内存 + - p: 进程标识 -Process filtering: - - /: start editing filter - - (while editing): - - : accept filter - - and : clear filter +进程过滤: + - /: 开始编辑过滤器 + - (编辑时): + - : 保存过滤器 + - : 清除过滤器 -CPU and Mem graph scaling: - - h: scale in - - l: scale out +CPU 和内存图形缩放: + - h: 放大比例 + - l: 缩小比例 -Network: - - b: toggle between mbps and scaled bytes per second +网络: + - b: 在 mbps 和 每秒字节数 之间切换 """ @@ -108,23 +107,23 @@ negvalsent="error: negative value for recently sent network data from gopsutil. [widget.disk] -disk="Disk" -mount="Mount" -used="Used" -free="Free" +disk="磁盘" +mount="文件系统" +used="已使用" +free="空闲" rs="R/s" ws="W/s" [widget.proc] -filter=" Filter: " -label=" Processes " +filter=" 过滤器: " +label=" 进程 " [widget.proc.header] -count="Count" -command="Command" +count="个数" +command="命令" cpu="CPU%" -mem="Mem%" -pid="PID" +mem="内存%" +pid="进程标识" [widget.proc.err] count="failed to get CPU count from gopsutil: {0}" retrieve="failed to retrieve processes: {0}" From 90c273c9deef31fe4087fd92aedbcf3441ca0ef0 Mon Sep 17 00:00:00 2001 From: Yaojun Feng Date: Sat, 20 Jun 2020 14:07:32 +0800 Subject: [PATCH 07/19] Correct the wording of 'scale'. --- translations/zh_CN.toml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/translations/zh_CN.toml b/translations/zh_CN.toml index 6f58df4..a43e007 100644 --- a/translations/zh_CN.toml +++ b/translations/zh_CN.toml @@ -1,4 +1,4 @@ -configfile=" 配置文件" +configfile="配置文件" usage="使用方法: {0} [选项]\n\n选项:\n" total="总计" @@ -91,7 +91,7 @@ help=""" - : 保存过滤器 - : 清除过滤器 -CPU 和内存图形缩放: +CPU 和内存图形比例: - h: 放大比例 - l: 缩小比例 From 9a56571373eb5a9ea9261afb39bebaf7ddeb700f Mon Sep 17 00:00:00 2001 From: "Sean E. Russell" Date: Sat, 20 Jun 2020 08:33:01 -0500 Subject: [PATCH 08/19] Fixes the help text issue. Moved some hard-coded strings to the translation files. --- cmd/gotop/main.go | 32 ++---------- go.mod | 4 +- go.sum | 6 +-- translations/dicts/en_US.toml | 95 +++++++++++++++++++++-------------- translations/dicts/tt_TT.toml | 95 +++++++++++++++++++++-------------- translations/dicts/zh_CN.toml | 74 +++++++++++++-------------- widgets/help.go | 4 +- 7 files changed, 165 insertions(+), 145 deletions(-) diff --git a/cmd/gotop/main.go b/cmd/gotop/main.go index 5e1cd09..2d718bd 100644 --- a/cmd/gotop/main.go +++ b/cmd/gotop/main.go @@ -21,8 +21,8 @@ import ( "github.com/VictoriaMetrics/metrics" jj "github.com/cloudfoundry-attic/jibber_jabber" ui "github.com/gizak/termui/v3" + "github.com/jdkeke142/lingo-toml" "github.com/shibukawa/configdir" - "github.com/xxxserxxx/lingo" "github.com/xxxserxxx/opflag" "github.com/xxxserxxx/gotop/v4" @@ -107,9 +107,9 @@ func parseArgs() error { if *list != "" { switch *list { case "layouts": - fmt.Println(_layouts) + fmt.Println(tr.Value("help.layouts")) case "colorschemes": - fmt.Println(_colorschemes) + fmt.Println(tr.Value("help.colorschemes")) case "paths": fmt.Println(tr.Value("help.paths")) paths := make([]string, 0) @@ -122,9 +122,9 @@ func parseArgs() error { case "devices": listDevices() case "keys": - fmt.Println(tr.Value("widget.help")) + fmt.Println(tr.Value("help.help")) case "widgets": - fmt.Println(_widgets) + fmt.Println(tr.Value("help.widgets")) default: fmt.Printf(tr.Value("error.unknownopt", *list)) os.Exit(1) @@ -508,25 +508,3 @@ func listDevices() { } } } - -const _layouts = `Built-in layouts: - default - minimal - battery - kitchensink` -const _colorschemes = `Built-in colorschemes: - default - default-dark (for white background) - solarized - solarized16-dark - solarized16-light - monokai - vice` -const _widgets = `Widgets that can be used in layouts: - cpu - CPU load graph - mem - Physical & swap memory use graph - temp - Sensor temperatures - disk - Physical disk partition use - power - A battery bar - net - Network load - procs - Interactive process list` diff --git a/go.mod b/go.mod index 440df3c..1f39414 100644 --- a/go.mod +++ b/go.mod @@ -7,15 +7,17 @@ require ( github.com/distatus/battery v0.9.0 github.com/gizak/termui/v3 v3.1.0 github.com/go-ole/go-ole v1.2.4 // indirect + github.com/jdkeke142/lingo-toml v0.0.0-20200508150411-0ad65ccb786d github.com/mattn/go-runewidth v0.0.4 github.com/nsf/termbox-go v0.0.0-20200418040025-38ba6e5628f1 github.com/shibukawa/configdir v0.0.0-20170330084843-e180dbdc8da0 github.com/shirou/gopsutil v2.20.3+incompatible github.com/stretchr/testify v1.4.0 - github.com/xxxserxxx/lingo v1.1.0 github.com/xxxserxxx/opflag v1.0.5 golang.org/x/sys v0.0.0-20200316230553-a7d97aace0b0 howett.net/plist v0.0.0-20200419221736-3b63eb3a43b5 // indirect ) go 1.14 + +replace github.com/jdkeke142/lingo-toml => github.com/xxxserxxx/lingo v0.0.0-20200619152803-440e0ec753ec diff --git a/go.sum b/go.sum index a29c978..59dcc33 100644 --- a/go.sum +++ b/go.sum @@ -37,10 +37,8 @@ github.com/valyala/fastrand v1.0.0 h1:LUKT9aKer2dVQNUi3waewTbKV+7H17kvWFNKs2Obdk github.com/valyala/fastrand v1.0.0/go.mod h1:HWqCzkrkg6QXT8V2EXWvXCoow7vLwOFN002oeRzjapQ= github.com/valyala/histogram v1.0.1 h1:FzA7n2Tz/wKRMejgu3PV1vw3htAklTjjuoI6z3d4KDg= github.com/valyala/histogram v1.0.1/go.mod h1:lQy0xA4wUz2+IUnf97SivorsJIp8FxsnRd6x25q7Mto= -github.com/xxxserxxx/lingo v1.0.1 h1:lPexOb0HEqYB50EaJdjaYFNATT8JhTcXljbQmCuXygE= -github.com/xxxserxxx/lingo v1.0.1/go.mod h1:C2teIFiBLAmEhpLzRkwk7wP5R0eOoveXVYqD+5KOkAs= -github.com/xxxserxxx/lingo v1.1.0 h1:UaA0oNyen0vGWNHD6eow+uCfBu7hhypwb28RxQSnprY= -github.com/xxxserxxx/lingo v1.1.0/go.mod h1:C2teIFiBLAmEhpLzRkwk7wP5R0eOoveXVYqD+5KOkAs= +github.com/xxxserxxx/lingo v0.0.0-20200619152803-440e0ec753ec h1:72Kid6wRHf4IZq0oJyJZGo4FuIyJeKqN4n9MEh2l744= +github.com/xxxserxxx/lingo v0.0.0-20200619152803-440e0ec753ec/go.mod h1:Kji1cjs9t6xDSLWuz6vP6ockOTT1rIdMLnNryfHXVuw= github.com/xxxserxxx/opflag v1.0.5 h1:2H4Qtl1qe+dSkEcGt+fBe2mQ8z14MgkWPqcLaoa6k90= github.com/xxxserxxx/opflag v1.0.5/go.mod h1:GWZtb3/tGGj5W1GE/JTyJAuqgxDxl1+jqDGAGM+P/p4= golang.org/x/sys v0.0.0-20200316230553-a7d97aace0b0 h1:4Khi5GeNOkZS5DqSBRn4Sy7BE6GuxwOqARPqfurkdNk= diff --git a/translations/dicts/en_US.toml b/translations/dicts/en_US.toml index 4b56c84..33bcc55 100644 --- a/translations/dicts/en_US.toml +++ b/translations/dicts/en_US.toml @@ -7,6 +7,64 @@ total="Total" paths="Loadable colorschemes & layouts, and the config file, are searched for, in order:" log="The log file is in {0}" written="Config written to {0}" +help=""" +Quit: q or + +Process navigation: + - k and : up + - j and : down + - : half page up + - : half page down + - : full page up + - : full page down + - gg and : jump to top + - G and : jump to bottom + +Process actions: + - : toggle process grouping + - dd: kill selected process or group of processes with SIGTERM (15) + - d3: kill selected process or group of processes with SIGQUIT (3) + - d9: kill selected process or group of processes with SIGKILL (9) + +Process sorting: + - c: CPU + - m: Mem + - p: PID + +Process filtering: + - /: start editing filter + - (while editing): + - : accept filter + - and : clear filter + +CPU and Mem graph scaling: + - h: scale in + - l: scale out + +Network: + - b: toggle between mbps and scaled bytes per second +""" +layouts = """Built-in layouts: + default + minimal + battery + kitchensink""" +colorschemes = """Built-in colorschemes: + default + default-dark (for white background) + solarized + solarized16-dark + solarized16-light + monokai + vice""" +widgets = """Widgets that can be used in layouts: + cpu - CPU load graph + mem - Physical & swap memory use graph + temp - Sensor temperatures + disk - Physical disk partition use + power - A battery bar + net - Network load + procs - Interactive process list""" [args] @@ -61,43 +119,6 @@ temp=" Temperatures " net=" Network Usage " netint=" Network Usage: {0} " mem=" Memory Usage " -help=""" -Quit: q or - -Process navigation: - - k and : up - - j and : down - - : half page up - - : half page down - - : full page up - - : full page down - - gg and : jump to top - - G and : jump to bottom - -Process actions: - - : toggle process grouping - - dd: kill selected process or group of processes with SIGTERM (15) - - d3: kill selected process or group of processes with SIGQUIT (3) - - d9: kill selected process or group of processes with SIGKILL (9) - -Process sorting: - - c: CPU - - m: Mem - - p: PID - -Process filtering: - - /: start editing filter - - (while editing): - - : accept filter - - and : clear filter - -CPU and Mem graph scaling: - - h: scale in - - l: scale out - -Network: - - b: toggle between mbps and scaled bytes per second -""" [widget.net.err] diff --git a/translations/dicts/tt_TT.toml b/translations/dicts/tt_TT.toml index dc5c737..bf8e5cd 100644 --- a/translations/dicts/tt_TT.toml +++ b/translations/dicts/tt_TT.toml @@ -7,6 +7,64 @@ total="latoT" paths="redro ni ,rof dehcraes era ,elif gifnoc eht dna ,stuoyal & semehcsroloc elbadaoL:" log="ni si elif gol ehT {0}" written="ot nettirw gifnoC {0}" +help=""" +>c-C< ro q :tiuQ + +:noitagivan ssecorP +pu :>pU< dna k - +nwod :>nwoD< dna j - +pu egap flah :>u-C< - +nwod egap flah :>d-C< - +pu egap lluf :>b-C< - +nwod egap lluf :>f-C< - +pot ot pmuj :>emoH< dna gg - +mottob ot pmuj :>dnE< dna G - + +:snoitca ssecorP +gnipuorg ssecorp elggot :>baT< - +)51( MRETGIS htiw sessecorp fo puorg ro ssecorp detceles llik :dd - +)3( TIUQGIS htiw sessecorp fo puorg ro ssecorp detceles llik :3d - +)9( LLIKGIS htiw sessecorp fo puorg ro ssecorp detceles llik :9d - + +:gnitros ssecorP +UPC :c - +meM :m - +DIP :p - + +:gniretlif ssecorP +retlif gnitide trats :/ - +:)gnitide elihw( - +retlif tpecca :>retnE< - +retlif raelc :>epacsE< dna >c-C< - + +:gnilacs hparg meM dna UPC +ni elacs :h - +tuo elacs :l - + +:krowteN +dnoces rep setyb delacs dna spbm neewteb elggot :b - +""" +layouts = """stuoyal ni-tliuB: + tluafed + laminim + yrettab + knisnehctik""" +colorschemes = """semehcsroloc ni-tliuB: + tluafed + )dnuorgkcab etihw rof( krad-tluafed + deziralos + krad-61deziralos + thgil-61deziralos + iakonom + eciv""" +widgets = """stuoyal ni desu eb nac taht stegdiW: + hparg daol UPC - upc + hparg esu yromem paws & lacisyhP - mem + serutarepmet rosneS - pmet + esu noititrap ksid lacisyhP - ksid + rab yrettab A - rewop + daol krowteN - ten + tsil ssecorp evitcaretnI - scorp""" [args] @@ -61,43 +119,6 @@ temp=" serutarepmeT " net=" egasU krowteN " netint=" egasU krowteN: {0} " mem=" egasU yromeM " -help=""" ->c-C< ro q :tiuQ - -:noitagivan ssecorP -pu :>pU< dna k - -nwod :>nwoD< dna j - -pu egap flah :>u-C< - -nwod egap flah :>d-C< - -pu egap lluf :>b-C< - -nwod egap lluf :>f-C< - -pot ot pmuj :>emoH< dna gg - -mottob ot pmuj :>dnE< dna G - - -:snoitca ssecorP -gnipuorg ssecorp elggot :>baT< - -)51( MRETGIS htiw sessecorp fo puorg ro ssecorp detceles llik :dd - -)3( TIUQGIS htiw sessecorp fo puorg ro ssecorp detceles llik :3d - -)9( LLIKGIS htiw sessecorp fo puorg ro ssecorp detceles llik :9d - - -:gnitros ssecorP -UPC :c - -meM :m - -DIP :p - - -:gniretlif ssecorP -retlif gnitide trats :/ - -:)gnitide elihw( - -retlif tpecca :>retnE< - -retlif raelc :>epacsE< dna >c-C< - - -:gnilacs hparg meM dna UPC -ni elacs :h - -tuo elacs :l - - -:krowteN -dnoces rep setyb delacs dna spbm neewteb elggot :b - -""" [widget.net.err] diff --git a/translations/dicts/zh_CN.toml b/translations/dicts/zh_CN.toml index a43e007..68e5f5e 100644 --- a/translations/dicts/zh_CN.toml +++ b/translations/dicts/zh_CN.toml @@ -7,6 +7,43 @@ total="总计" paths="按顺序从以下位置优先读取配色方案、布局方案和配置文件:" log="日志文件位于 {0}" written="配置文件已写入 {0}" +help=""" +退出: q or + +进程导航: + - k 或 : 上一行 + - j 或 : 下一行 + - : 上半页 + - : 下半页 + - : 上一页 + - : 下一页 + - gg 或 : 到顶部 + - G 或 : 到底部 + +进程操作: + - : 切换进程组 + - dd: 发送信号 SIGTERM (15) 终止进程或进程组 + - d3: 发送信号 SIGTERM (3) 终止进程或进程组 + - d9: 发送信号 SIGTERM (9) 终止进程或进程组 + +进程排序: + - c: CPU + - m: 内存 + - p: 进程标识 + +进程过滤: + - /: 开始编辑过滤器 + - (编辑时): + - : 保存过滤器 + - : 清除过滤器 + +CPU 和内存图形比例: + - h: 放大比例 + - l: 缩小比例 + +网络: + - b: 在 mbps 和 每秒字节数 之间切换 +""" [args] @@ -61,43 +98,6 @@ temp=" 温度 " net=" 网络使用率 " netint=" 网络使用率: {0} " mem=" 内存使用率 " -help=""" -退出: q or - -进程导航: - - k 或 : 上一行 - - j 或 : 下一行 - - : 上半页 - - : 下半页 - - : 上一页 - - : 下一页 - - gg 或 : 到顶部 - - G 或 : 到底部 - -进程操作: - - : 切换进程组 - - dd: 发送信号 SIGTERM (15) 终止进程或进程组 - - d3: 发送信号 SIGTERM (3) 终止进程或进程组 - - d9: 发送信号 SIGTERM (9) 终止进程或进程组 - -进程排序: - - c: CPU - - m: 内存 - - p: 进程标识 - -进程过滤: - - /: 开始编辑过滤器 - - (编辑时): - - : 保存过滤器 - - : 清除过滤器 - -CPU 和内存图形比例: - - h: 放大比例 - - l: 缩小比例 - -网络: - - b: 在 mbps 和 每秒字节数 之间切换 -""" [widget.net.err] diff --git a/widgets/help.go b/widgets/help.go index fff71a7..d98fecd 100644 --- a/widgets/help.go +++ b/widgets/help.go @@ -5,7 +5,7 @@ import ( "strings" ui "github.com/gizak/termui/v3" - "github.com/xxxserxxx/lingo" + lingo "github.com/jdkeke142/lingo-toml" ) var tr lingo.Translations @@ -17,7 +17,7 @@ type HelpMenu struct { func NewHelpMenu(tra lingo.Translations) *HelpMenu { tr = tra - keyBinds = tr.Value("widgets.help") + keyBinds = tr.Value("help.help") return &HelpMenu{ Block: *ui.NewBlock(), } From 23364aa754c836b8a5fbc69adbdbd49abd183a57 Mon Sep 17 00:00:00 2001 From: "Sean E. Russell" Date: Sat, 20 Jun 2020 16:47:48 -0500 Subject: [PATCH 09/19] More strings moved to translations --- cmd/gotop/main.go | 4 +- colorschemes/registry.go | 14 ++- config.go | 29 +++--- devices/devices.go | 6 ++ devices/temp.go | 2 +- devices/temp_freebsd.go | 6 +- layout/layout.go | 6 +- layout/parser.go | 9 +- logging/logging.go | 5 +- termui/table.go | 7 +- translations/dicts/de_DE.toml | 177 +++++++++++++++++++++------------- translations/dicts/en_US.toml | 74 +++++++++----- translations/dicts/tt_TT.toml | 74 +++++++++----- translations/dicts/zh_CN.toml | 107 ++++++++++++++------ widgets/disk.go | 1 + widgets/proc_freebsd.go | 10 +- widgets/statusbar.go | 2 +- 17 files changed, 347 insertions(+), 186 deletions(-) diff --git a/cmd/gotop/main.go b/cmd/gotop/main.go index 2d718bd..1f9f0a5 100644 --- a/cmd/gotop/main.go +++ b/cmd/gotop/main.go @@ -368,7 +368,9 @@ func run() int { lang = strings.Replace(lang, "-", "_", -1) // Get the locale from the os tr = ling.TranslationsForLocale(lang) + colorschemes.SetTr(tr) conf = gotop.NewConfig() + conf.Tr = tr // Find the config file; look in (1) local, (2) user, (3) global // Check the last argument first fs := flag.NewFlagSet("config", flag.ContinueOnError) @@ -483,7 +485,7 @@ func getLayout(conf gotop.Config) (io.Reader, error) { for _, d := range conf.ConfigDir.QueryFolders(configdir.Existing) { paths = append(paths, d.Path) } - return nil, fmt.Errorf("unable find layout file %s in %s", conf.Layout, strings.Join(paths, ", ")) + return nil, fmt.Errorf(tr.Value("error.findlayout", conf.Layout, strings.Join(paths, ", "))) } lo, err := folder.ReadFile(conf.Layout) if err != nil { diff --git a/colorschemes/registry.go b/colorschemes/registry.go index baa4bda..84b2e89 100644 --- a/colorschemes/registry.go +++ b/colorschemes/registry.go @@ -6,6 +6,7 @@ import ( "path/filepath" "strings" + "github.com/jdkeke142/lingo-toml" "github.com/shibukawa/configdir" ) @@ -17,6 +18,13 @@ func init() { } } +var tr lingo.Translations + +// Set the translation library +func SetTr(tra lingo.Translations) { + tr = tra +} + // FromName loads a Colorscheme by name; confDir is used to search // directories for a scheme matching the name. The search order // is the same as for config files. @@ -46,15 +54,15 @@ func getCustomColorscheme(confDir configdir.ConfigDir, name string) (Colorscheme for _, d := range confDir.QueryFolders(configdir.Existing) { paths = append(paths, d.Path) } - return cs, fmt.Errorf("failed to find colorscheme file %s in %s", fn, strings.Join(paths, ", ")) + return cs, fmt.Errorf(tr.Value("error.colorschemefile", fn, strings.Join(paths, ", "))) } dat, err := folder.ReadFile(fn) if err != nil { - return cs, fmt.Errorf("failed to read colorscheme file %s: %v", filepath.Join(folder.Path, fn), err) + return cs, fmt.Errorf(tr.Value("error.colorschemeload", filepath.Join(folder.Path, fn), err.Error())) } err = json.Unmarshal(dat, &cs) if err != nil { - return cs, fmt.Errorf("failed to parse colorscheme file: %v", err) + return cs, fmt.Errorf(tr.Value("error.colorschemeparse", err.Error())) } return cs, nil } diff --git a/config.go b/config.go index 16f053c..e37f184 100644 --- a/config.go +++ b/config.go @@ -16,6 +16,7 @@ import ( "strings" "time" + "github.com/jdkeke142/lingo-toml" "github.com/shibukawa/configdir" "github.com/xxxserxxx/gotop/v4/colorschemes" "github.com/xxxserxxx/gotop/v4/widgets" @@ -43,6 +44,7 @@ type Config struct { Test bool ExtensionVars map[string]string ConfigFile string + Tr lingo.Translations } func NewConfig() Config { @@ -100,18 +102,15 @@ func load(in io.Reader, conf *Config) error { } kv := strings.Split(l, "=") if len(kv) != 2 { - return fmt.Errorf("bad config file syntax; should be KEY=VALUE, was %s", l) + return fmt.Errorf(conf.Tr.Value("config.err.configsyntax", l)) } key := strings.ToLower(kv[0]) + ln := strconv.Itoa(lineNo) switch key { default: conf.ExtensionVars[key] = kv[1] - case "configdir": - log.Printf("configdir is deprecated. Ignored configdir=%s", kv[1]) - case "logdir": - log.Printf("logdir is deprecated. Ignored logdir=%s", kv[1]) - case "logfile": - log.Printf("logfile is deprecated. Ignored logfile=%s", kv[1]) + case "configdir", "logdir", "logfile": + log.Printf(conf.Tr.Value("config.err.deprecation", ln, key, kv[1])) case graphhorizontalscale: iv, err := strconv.Atoi(kv[1]) if err != nil { @@ -121,31 +120,31 @@ func load(in io.Reader, conf *Config) error { case helpvisible: bv, err := strconv.ParseBool(kv[1]) if err != nil { - return fmt.Errorf("line %d: %v", lineNo, err) + return fmt.Errorf(conf.Tr.Value("config.err.line", ln, err.Error())) } conf.HelpVisible = bv case colorscheme: cs, err := colorschemes.FromName(conf.ConfigDir, kv[1]) if err != nil { - return fmt.Errorf("line %d: %v", lineNo, err) + return fmt.Errorf(conf.Tr.Value("config.err.line", ln, err.Error())) } conf.Colorscheme = cs case updateinterval: iv, err := strconv.Atoi(kv[1]) if err != nil { - return err + return fmt.Errorf(conf.Tr.Value("config.err.line", ln, err.Error())) } conf.UpdateInterval = time.Duration(iv) case averagecpu: bv, err := strconv.ParseBool(kv[1]) if err != nil { - return fmt.Errorf("line %d: %v", lineNo, err) + return fmt.Errorf(conf.Tr.Value("config.err.line", ln, err.Error())) } conf.AverageLoad = bv case percpuload: bv, err := strconv.ParseBool(kv[1]) if err != nil { - return fmt.Errorf("line %d: %v", lineNo, err) + return fmt.Errorf(conf.Tr.Value("config.err.line", ln, err.Error())) } conf.PercpuLoad = bv case tempscale: @@ -156,12 +155,12 @@ func load(in io.Reader, conf *Config) error { conf.TempScale = 'F' default: conf.TempScale = 'C' - return fmt.Errorf("invalid TempScale value %s", kv[1]) + return fmt.Errorf(conf.Tr.Value("config.err.tempscale", kv[1])) } case statusbar: bv, err := strconv.ParseBool(kv[1]) if err != nil { - return fmt.Errorf("line %d: %v", lineNo, err) + return fmt.Errorf(conf.Tr.Value("config.err.line", ln, err.Error())) } conf.Statusbar = bv case netinterface: @@ -171,7 +170,7 @@ func load(in io.Reader, conf *Config) error { case maxlogsize: iv, err := strconv.Atoi(kv[1]) if err != nil { - return err + return fmt.Errorf(conf.Tr.Value("config.err.line", ln, err.Error())) } conf.MaxLogSize = int64(iv) case export: diff --git a/devices/devices.go b/devices/devices.go index 7360578..8873ae5 100644 --- a/devices/devices.go +++ b/devices/devices.go @@ -2,6 +2,7 @@ package devices import ( "log" + "github.com/jdkeke142/lingo-toml" ) const ( @@ -15,6 +16,7 @@ var _shutdownFuncs []func() error var _devs map[string][]string var _defaults map[string][]string var _startup []func(map[string]string) error +var tr lingo.Translations // RegisterShutdown stores a function to be called by gotop on exit, allowing // extensions to properly release resources. Extensions should register a @@ -86,3 +88,7 @@ func Devices(domain string, all bool) []string { } return _defaults[domain] } + +func SetTr(tra lingo.Translations) { + tr = tra +} diff --git a/devices/temp.go b/devices/temp.go index bffd2e9..87f534f 100644 --- a/devices/temp.go +++ b/devices/temp.go @@ -17,7 +17,7 @@ func UpdateTemps(temps map[string]int) { errs := f(temps) if errs != nil { for k, e := range errs { - log.Printf("error updating temp for %s: %s", k, e) + log.Printf(tr.Value("error.recovfetch", "temp", k, e.Error())) } } } diff --git a/devices/temp_freebsd.go b/devices/temp_freebsd.go index 3e659be..e87dcb3 100644 --- a/devices/temp_freebsd.go +++ b/devices/temp_freebsd.go @@ -13,7 +13,7 @@ import ( func init() { if len(devs()) == 0 { - log.Println("temp: no thermal sensors found") + log.Println(tr.Value("error.nodevfound", "thermal sensors")) return } RegisterTemp(update) @@ -58,13 +58,13 @@ func devs() []string { // Check that thermal sensors are really available; they aren't in VMs bs, err := exec.Command("sysctl", "-a").Output() if err != nil { - log.Printf("temp: failure to get system information %s", err.Error()) + log.Printf(tr.Value("error.fatalfetch", "temp", err.Error())) return []string{} } for k, _ := range sensorOIDS { idx := strings.Index(string(bs), k) if idx < 0 { - log.Printf("temp: no device %s found", k) + log.Printf(tr.Value("error.nodevfound", k)) } else { rv = append(rv, k) } diff --git a/layout/layout.go b/layout/layout.go index b4343b4..645e490 100644 --- a/layout/layout.go +++ b/layout/layout.go @@ -3,7 +3,9 @@ package layout import ( "log" "sort" + "strings" + "github.com/jdkeke142/lingo-toml" "github.com/xxxserxxx/gotop/v4" "github.com/xxxserxxx/gotop/v4/widgets" @@ -28,8 +30,10 @@ type MyGrid struct { } var widgetNames []string = []string{"cpu", "disk", "mem", "temp", "net", "procs", "batt"} +var tr lingo.Translations func Layout(wl layout, c gotop.Config) (*MyGrid, error) { + tr = c.Tr rowDefs := wl.Rows uiRows := make([][]interface{}, 0) numRows := countNumRows(wl.Rows) @@ -197,7 +201,7 @@ func makeWidget(c gotop.Config, widRule widgetRule) interface{} { b.BarColor = ui.Color(c.Colorscheme.ProcCursor) w = b default: - log.Printf("Invalid widget name %s. Must be one of %v", widRule.Widget, widgetNames) + log.Printf(tr.Value("layout.error.widget", widRule.Widget, strings.Join(widgetNames, ","))) return ui.NewBlock() } if c.ExportPort != "" { diff --git a/layout/parser.go b/layout/parser.go index b747eae..b922067 100644 --- a/layout/parser.go +++ b/layout/parser.go @@ -83,7 +83,8 @@ func ParseLayout(i io.Reader) layout { if len(rs) > 1 { v, e := strconv.Atoi(rs[0]) if e != nil { - log.Printf("Layout error on line %d: format must be INT:STRING/INT. Error parsing %s as a int. Word was %s. Using a row height of 1.", lineNo, rs[0], w) + ln := strconv.Itoa(lineNo) + log.Printf(tr.Value("layout.error.format", "INT:STRING/INT", ln, rs[0], w)) v = 1 } if v < 1 { @@ -99,7 +100,8 @@ func ParseLayout(i io.Reader) layout { if len(ks) > 1 { weight, e := strconv.Atoi(ks[1]) if e != nil { - log.Printf("Layout error on line %d: format must be STRING/INT. Error parsing %s as a int. Word was %s. Using a weight of 1 for widget.", lineNo, ks[1], w) + ln := strconv.Itoa(lineNo) + log.Printf(tr.Value("layout.error.format", "STRING/INT", ln, ks[1], w)) weight = 1 } if weight < 1 { @@ -107,7 +109,8 @@ func ParseLayout(i io.Reader) layout { } wr.Weight = float64(weight) if len(ks) > 2 { - log.Printf("Layout warning on line %d: too many '/' in word %s; ignoring extra junk.", lineNo, w) + ln := strconv.Itoa(lineNo) + log.Printf(tr.Value("layout.error.slashes", ln, w)) } weightTotal += weight } else { diff --git a/logging/logging.go b/logging/logging.go index 5195b82..20a0134 100644 --- a/logging/logging.go +++ b/logging/logging.go @@ -8,6 +8,7 @@ import ( "path/filepath" "sync" + "github.com/jdkeke142/lingo-toml" "github.com/xxxserxxx/gotop/v4" ) @@ -29,6 +30,7 @@ func New(c gotop.Config) (io.WriteCloser, error) { w := &RotateWriter{ filename: filepath.Join(cache.Path, LOGFILE), maxLogSize: c.MaxLogSize, + tr: c.Tr, } err = w.rotate() if err != nil { @@ -48,6 +50,7 @@ type RotateWriter struct { filename string // should be set to the actual filename fp *os.File maxLogSize int64 + tr lingo.Translations } func (w *RotateWriter) Close() error { @@ -103,7 +106,7 @@ func (w *RotateWriter) rotate() (err error) { // open the log file w.fp, err = os.OpenFile(w.filename, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, 0660) if err != nil { - return fmt.Errorf("failed to open log file %s: %v", w.filename, err) + return fmt.Errorf(w.tr.Value("error.logopen", w.filename, err.Error())) } return nil diff --git a/termui/table.go b/termui/table.go index e587839..a879489 100644 --- a/termui/table.go +++ b/termui/table.go @@ -5,8 +5,10 @@ import ( "image" "log" "strings" + "strconv" . "github.com/gizak/termui/v3" + "github.com/jdkeke142/lingo-toml" ) type Table struct { @@ -30,6 +32,8 @@ type Table struct { TopRow int // used to indicate where in the table we are scrolled at ColResizer func() + + Tr lingo.Translations } // NewTable returns a new Table instance @@ -79,7 +83,8 @@ func (self *Table) Draw(buf *Buffer) { } if self.TopRow < 0 { - log.Printf("table widget TopRow value less than 0. TopRow: %v", self.TopRow) + r := strconv.Itoa(self.TopRow) + log.Printf(self.Tr.Value("error.table", r)) return } diff --git a/translations/dicts/de_DE.toml b/translations/dicts/de_DE.toml index 06fac94..d717083 100644 --- a/translations/dicts/de_DE.toml +++ b/translations/dicts/de_DE.toml @@ -7,60 +7,6 @@ total="Total" paths="Loadable colorschemes & layouts, and the config file, are searched for, in order:" log="The log file is in {0}" written="Config written to {0}" - - -[args] -help="Hilfetext anzeigen." -color="Ein Farbschema feststellen." -scale="Stellen den Skalierungsfaktor ein, >0" -version="Zeigen die Version aus und beenden." -percpu="Show each CPU in the CPU widget." -cpuavg="Show average CPU in the CPU widget." -temp="Show temperatures in fahrenheit.Show temperatures in fahrenheit." -statusbar="Show a statusbar with the time." -rate="Refresh frequency. Most time units accepted. \"1m\" = refresh every minute. \"100ms\" = refresh every 100ms." -layout="Name of layout spec file for the UI. Use \"-\" to pipe." -net="Select network interface. Several interfaces can be defined using comma separated values. Interfaces can also be ignored using \"!\"" -export="Enable metrics for export on the specified port." -mbps="Show network rate as mbps." -test="Runs tests and exits with success/failure code." -conffile="Config file to use instead of default (MUST BE FIRST ARGUMENT)" -list=""" -List - devices: Prints out device names for filterable widgets - layouts: Lists build-in layouts - colorschemes: Lists built-in colorschemes - paths: List out configuration file search paths - widgets: Widgets that can be used in a layout - keys: Show the keyboard bindings.""" -write="Write out a default config file." - - -[error] -configparse="failed to parse config file: {0}" -cliparse="parsing CLI args: {0}" -logsetup="failed to setup log file: {0}" -unknownopt="Unknown option \"{0}\"; try layouts, colorschemes, keys, paths, or devices\n" -writefail="Failed to write configuration file: {0}" -checklog="errors encountered; from {0}:" -metricsetup="error setting up {0} metrics: {1}" -nometrics="no metrics for {0} {0}" -fatalfetch="fatal error fetching {0} info: {1}" -recovfetch="recoverable error fetching {0} info; skipping {0}: {0}" -nodevfound="no usable {0} found" -setuperr="error setting up {0}: {1}" - - -[widget.label] -disk=" Disk Usage " -cpu=" CPU Usage " -gauge=" Power Level " -battery=" Battery Status " -batt=" Battery " -temp=" Temperatures " -net=" Network Usage " -netint=" Network Usage: {0} " -mem=" Memory Usage " help=""" Quit: q or @@ -98,12 +44,108 @@ CPU and Mem graph scaling: Network: - b: toggle between mbps and scaled bytes per second """ +# TRANSLATORS: Please don't translate the layout **names** +layouts = """Built-in layouts: + default + minimal + battery + kitchensink""" +# TRANSLATORS: Please don't translate the colorcheme **names** +colorschemes = """Built-in colorschemes: + default + default-dark (for white background) + solarized + solarized16-dark + solarized16-light + monokai + vice""" +# TRANSLATORS: Please don't translate the widget **names** +widgets = """Widgets that can be used in layouts: + cpu - CPU load graph + mem - Physical & swap memory use graph + temp - Sensor temperatures + disk - Physical disk partition use + power - A battery bar + net - Network load + procs - Interactive process list""" + + +[args] +help="Hilfetext anzeigen." +color="Ein Farbschema feststellen." +scale="Stellen den Skalierungsfaktor ein, >0" +version="Zeigen die Version aus und beenden." +percpu="Show each CPU in the CPU widget." +cpuavg="Show average CPU in the CPU widget." +temp="Show temperatures in fahrenheit.Show temperatures in fahrenheit." +statusbar="Show a statusbar with the time." +rate="Refresh frequency. Most time units accepted. \"1m\" = refresh every minute. \"100ms\" = refresh every 100ms." +layout="Name of layout spec file for the UI. Use \"-\" to pipe." +net="Select network interface. Several interfaces can be defined using comma separated values. Interfaces can also be ignored using \"!\"" +export="Enable metrics for export on the specified port." +mbps="Show network rate as mbps." +test="Runs tests and exits with success/failure code." +conffile="Config file to use instead of default (MUST BE FIRST ARGUMENT)" +list=""" +List + devices: Prints out device names for filterable widgets + layouts: Lists build-in layouts + colorschemes: Lists built-in colorschemes + paths: List out configuration file search paths + widgets: Widgets that can be used in a layout + keys: Show the keyboard bindings.""" +write="Write out a default config file." + + +[config.err] +configsyntax="0| bad config file syntax; should be KEY=VALUE, was {0}" +deprecation="1| line {0}: '{1}' is deprecated. Ignored {1}={2}" +line="2| line #{0}: {1}" +tempscale="3| invalid TempScale value {0}" + + +[error] +configparse="4| failed to parse config file: {0}" +cliparse="5| parsing CLI args: {0}" +logsetup="6| failed to setup log file: {0}" +unknownopt="7| Unknown option \"{0}\"; try layouts, colorschemes, keys, paths, or devices\n" +writefail="8| Failed to write configuration file: {0}" +checklog="9| errors encountered; from {0}:" +metricsetup="10| error setting up {0} metrics: {1}" +nometrics="11| no metrics for {0} {1}" +fatalfetch="12| fatal error fetching {0} info: {1}" +recovfetch="13| recoverable error fetching {0} info; skipping {0}: {1}" +nodevfound="14| no usable {0} found" +setuperr="15| error setting up {0}: {1}" +colorschemefile="16| failed to find colorscheme file {0} in {1}" +colorschemeread="17| failed to read colorscheme file {0}: {1}" +colorschemeparse="18| failed to parse colorscheme file: {0}" +findlayout="19| failed to read colorscheme file {0}: {1}" +logopen="20| failed to open log file {0}: {1}" +table="21| table widget TopRow value less than 0. TopRow: {0}" +nohostname="22| could not get hostname: {0}" + +[layout.error] +widget="23| Invalid widget name {0}. Must be one of {1}" +format="24| Layout error on line {0}: format must be {1}. Error parsing {2} as a int. Word was {3}. Using a row height of 1." +slashes="25| Layout warning on line {0}: too many '/' in word {1}; ignoring extra junk." + +[widget.label] +disk=" Disk Usage " +cpu=" CPU Usage " +gauge=" Power Level " +battery=" Battery Status " +batt=" Battery " +temp=" Temperatures " +net=" Network Usage " +netint=" Network Usage: {0} " +mem=" Memory Usage " [widget.net.err] -netactivity="failed to get network activity from gopsutil: {0}" -negvalrecv="error: negative value for recently received network data from gopsutil. recentBytesRecv: {0}" -negvalsent="error: negative value for recently sent network data from gopsutil. recentBytesSent: {0}" +netactivity="26| failed to get network activity from gopsutil: {0}" +negvalrecv="27| error: negative value for recently received network data from gopsutil. recentBytesRecv: {0}" +negvalsent="28| error: negative value for recently sent network data from gopsutil. recentBytesSent: {0}" [widget.disk] @@ -125,13 +167,14 @@ cpu="CPU%" mem="Mem%" pid="PID" [widget.proc.err] -count="failed to get CPU count from gopsutil: {0}" -retrieve="failed to retrieve processes: {0}" -ps="failed to execute 'ps' command: {0}" -gopsutil="failed to get processes from gopsutil: {0}" -pidconv="failed to convert PID to int: {0}. line: {1}" -cpuconv="failed to convert CPU usage to float: {0}. line: {1}" -memconv="failed to convert Mem usage to float: {0}. line: {1}" -getcmd="failed to get process command from gopsutil: {0}. psProc: {1}. i: {2}. pid: {3}" -cpupercent="failed to get process cpu usage from gopsutil: {0}. psProc: {1}. i: {2}. pid: {3}" -mempercent="failed to get process memeory usage from gopsutil: {0}. psProc: {1}. i: {2}. pid: {3}" +count="29| failed to get CPU count from gopsutil: {0}" +retrieve="30| failed to retrieve processes: {0}" +ps="31| failed to execute 'ps' command: {0}" +gopsutil="32| failed to get processes from gopsutil: {0}" +pidconv="33| failed to convert PID to int: {0}. line: {1}" +cpuconv="34| failed to convert CPU usage to float: {0}. line: {1}" +memconv="35| failed to convert Mem usage to float: {0}. line: {1}" +getcmd="36| failed to get process command from gopsutil: {0}. psProc: {1}. i: {2}. pid: {3}" +cpupercent="37| failed to get process cpu usage from gopsutil: {0}. psProc: {1}. i: {2}. pid: {3}" +mempercent="38| failed to get process memeory usage from gopsutil: {0}. psProc: {1}. i: {2}. pid: {3}" +parse="39| failed to parse output: {0}" diff --git a/translations/dicts/en_US.toml b/translations/dicts/en_US.toml index 33bcc55..131ec1c 100644 --- a/translations/dicts/en_US.toml +++ b/translations/dicts/en_US.toml @@ -44,11 +44,13 @@ CPU and Mem graph scaling: Network: - b: toggle between mbps and scaled bytes per second """ +# TRANSLATORS: Please don't translate the layout **names** layouts = """Built-in layouts: default minimal battery kitchensink""" +# TRANSLATORS: Please don't translate the colorcheme **names** colorschemes = """Built-in colorschemes: default default-dark (for white background) @@ -57,6 +59,7 @@ colorschemes = """Built-in colorschemes: solarized16-light monokai vice""" +# TRANSLATORS: Please don't translate the widget **names** widgets = """Widgets that can be used in layouts: cpu - CPU load graph mem - Physical & swap memory use graph @@ -94,21 +97,39 @@ List write="Write out a default config file." -[error] -configparse="failed to parse config file: {0}" -cliparse="parsing CLI args: {0}" -logsetup="failed to setup log file: {0}" -unknownopt="Unknown option \"{0}\"; try layouts, colorschemes, keys, paths, or devices\n" -writefail="Failed to write configuration file: {0}" -checklog="errors encountered; from {0}:" -metricsetup="error setting up {0} metrics: {1}" -nometrics="no metrics for {0} {0}" -fatalfetch="fatal error fetching {0} info: {1}" -recovfetch="recoverable error fetching {0} info; skipping {0}: {0}" -nodevfound="no usable {0} found" -setuperr="error setting up {0}: {1}" +[config.err] +configsyntax="0| bad config file syntax; should be KEY=VALUE, was {0}" +deprecation="1| line {0}: '{1}' is deprecated. Ignored {1}={2}" +line="2| line #{0}: {1}" +tempscale="3| invalid TempScale value {0}" +[error] +configparse="4| failed to parse config file: {0}" +cliparse="5| parsing CLI args: {0}" +logsetup="6| failed to setup log file: {0}" +unknownopt="7| Unknown option \"{0}\"; try layouts, colorschemes, keys, paths, or devices\n" +writefail="8| Failed to write configuration file: {0}" +checklog="9| errors encountered; from {0}:" +metricsetup="10| error setting up {0} metrics: {1}" +nometrics="11| no metrics for {0} {1}" +fatalfetch="12| fatal error fetching {0} info: {1}" +recovfetch="13| recoverable error fetching {0} info; skipping {0}: {1}" +nodevfound="14| no usable {0} found" +setuperr="15| error setting up {0}: {1}" +colorschemefile="16| failed to find colorscheme file {0} in {1}" +colorschemeread="17| failed to read colorscheme file {0}: {1}" +colorschemeparse="18| failed to parse colorscheme file: {0}" +findlayout="19| failed to read colorscheme file {0}: {1}" +logopen="20| failed to open log file {0}: {1}" +table="21| table widget TopRow value less than 0. TopRow: {0}" +nohostname="22| could not get hostname: {0}" + +[layout.error] +widget="23| Invalid widget name {0}. Must be one of {1}" +format="24| Layout error on line {0}: format must be {1}. Error parsing {2} as a int. Word was {3}. Using a row height of 1." +slashes="25| Layout warning on line {0}: too many '/' in word {1}; ignoring extra junk." + [widget.label] disk=" Disk Usage " cpu=" CPU Usage " @@ -122,9 +143,9 @@ mem=" Memory Usage " [widget.net.err] -netactivity="failed to get network activity from gopsutil: {0}" -negvalrecv="error: negative value for recently received network data from gopsutil. recentBytesRecv: {0}" -negvalsent="error: negative value for recently sent network data from gopsutil. recentBytesSent: {0}" +netactivity="26| failed to get network activity from gopsutil: {0}" +negvalrecv="27| error: negative value for recently received network data from gopsutil. recentBytesRecv: {0}" +negvalsent="28| error: negative value for recently sent network data from gopsutil. recentBytesSent: {0}" [widget.disk] @@ -146,13 +167,14 @@ cpu="CPU%" mem="Mem%" pid="PID" [widget.proc.err] -count="failed to get CPU count from gopsutil: {0}" -retrieve="failed to retrieve processes: {0}" -ps="failed to execute 'ps' command: {0}" -gopsutil="failed to get processes from gopsutil: {0}" -pidconv="failed to convert PID to int: {0}. line: {1}" -cpuconv="failed to convert CPU usage to float: {0}. line: {1}" -memconv="failed to convert Mem usage to float: {0}. line: {1}" -getcmd="failed to get process command from gopsutil: {0}. psProc: {1}. i: {2}. pid: {3}" -cpupercent="failed to get process cpu usage from gopsutil: {0}. psProc: {1}. i: {2}. pid: {3}" -mempercent="failed to get process memeory usage from gopsutil: {0}. psProc: {1}. i: {2}. pid: {3}" +count="29| failed to get CPU count from gopsutil: {0}" +retrieve="30| failed to retrieve processes: {0}" +ps="31| failed to execute 'ps' command: {0}" +gopsutil="32| failed to get processes from gopsutil: {0}" +pidconv="33| failed to convert PID to int: {0}. line: {1}" +cpuconv="34| failed to convert CPU usage to float: {0}. line: {1}" +memconv="35| failed to convert Mem usage to float: {0}. line: {1}" +getcmd="36| failed to get process command from gopsutil: {0}. psProc: {1}. i: {2}. pid: {3}" +cpupercent="37| failed to get process cpu usage from gopsutil: {0}. psProc: {1}. i: {2}. pid: {3}" +mempercent="38| failed to get process memeory usage from gopsutil: {0}. psProc: {1}. i: {2}. pid: {3}" +parse="39| failed to parse output: {0}" diff --git a/translations/dicts/tt_TT.toml b/translations/dicts/tt_TT.toml index bf8e5cd..ad7c2e4 100644 --- a/translations/dicts/tt_TT.toml +++ b/translations/dicts/tt_TT.toml @@ -44,11 +44,13 @@ tuo elacs :l - :krowteN dnoces rep setyb delacs dna spbm neewteb elggot :b - """ +# TRANSLATORS: Please don't translate the layout **names** layouts = """stuoyal ni-tliuB: tluafed laminim yrettab knisnehctik""" +# TRANSLATORS: Please don't translate the colorcheme **names** colorschemes = """semehcsroloc ni-tliuB: tluafed )dnuorgkcab etihw rof( krad-tluafed @@ -57,6 +59,7 @@ colorschemes = """semehcsroloc ni-tliuB: thgil-61deziralos iakonom eciv""" +# TRANSLATORS: Please don't translate the widget **names** widgets = """stuoyal ni desu eb nac taht stegdiW: hparg daol UPC - upc hparg esu yromem paws & lacisyhP - mem @@ -94,21 +97,39 @@ tuoyal a ni desu eb nac taht stegdiW :stegdiw write=".elif gifnoc tluafed a tuo etirW" -[error] -configparse="elif gifnoc esrap ot deliaf: {0}" -cliparse="sgra ILC gnisrap: {0}" -logsetup="elif gol putes ot deliaf: {0}" -unknownopt="noitpo nwonknU \"{0}\"; secived ro ,shtap ,syek ,semehcsroloc ,stuoyal yrt\n" -writefail="elif noitarugifnoc etirw ot deliaF: {0}" -checklog="morf ;deretnuocne srorre {0}:" -metricsetup="pu gnittes rorre {0} scirtem: {1}" -nometrics="rof scirtem on {0} {0}" -fatalfetch="gnihctef rorre lataf {0} ofni: {1}" -recovfetch="gnihctef rorre elbarevocer {0} gnippiks ;ofni {0}: {0}" -nodevfound="elbasu on {0} dnuof" -setuperr="pu gnittes rorre {0}: {1}" +[config.err] +configsyntax="0| saw ,EULAV=YEK eb dluohs ;xatnys elif gifnoc dab {0}" +deprecation="1| enil {0}: '{1}' derongI .detacerped si {1}={2}" +line="2| enil #{0}: {1}" +tempscale="3| eulav elacSpmeT dilavni {0}" +[error] +configparse="4| elif gifnoc esrap ot deliaf: {0}" +cliparse="8| sgra ILC gnisrap: {0}" +logsetup="9| elif gol putes ot deliaf: {0}" +unknownopt="10| noitpo nwonknU \"{0}\"; secived ro ,shtap ,syek ,semehcsroloc ,stuoyal yrt\n" +writefail="11| elif noitarugifnoc etirw ot deliaF: {0}" +checklog="12| morf ;deretnuocne srorre {0}:" +metricsetup="13| pu gnittes rorre {0} scirtem: {1}" +nometrics="14| rof scirtem on {0} {1}" +fatalfetch="15| gnihctef rorre lataf {0} ofni: {1}" +recovfetch="16| gnihctef rorre elbarevocer {0} gnippiks ;ofni {0}: {1}" +nodevfound="17| elbasu on {0} dnuof" +setuperr="18| pu gnittes rorre {0}: {1}" +colorschemefile="19| elif emehcsroloc dnif ot deliaf {0} ni {1}" +colorschemeread="20| elif emehcsroloc daer ot deliaf {0}: {1}" +colorschemeparse="21| elif emehcsroloc esrap ot deliaf: {0}" +findlayout="22| elif emehcsroloc daer ot deliaf {0}: {1}" +logopen="22| elif gol nepo ot deliaf {0}: {1}" +table="22| woRpoT .0 naht ssel eulav woRpoT tegdiw elbat: {0}" +nohostname="22| emantsoh teg ton dluoc: {0}" + +[layout.error] +widget="23| eman tegdiw dilavnI {0}. fo eno eb tsuM {1}" +format="24| enil no rorre tuoyaL {0}: eb tsum tamrof {1}. gnisrap rorrE {2} saw droW .tni a sa {3}. 1 fo thgieh wor a gnisU." +slashes="25| enil no gninraw tuoyaL {0}: drow ni '/' ynam oot {1}; knuj artxe gnirongi." + [widget.label] disk=" egasU ksiD " cpu=" egasU UPC " @@ -122,9 +143,9 @@ mem=" egasU yromeM " [widget.net.err] -netactivity="lituspog morf ytivitca krowten teg ot deliaf: {0}" -negvalrecv=":vceRsetyBtnecer .lituspog morf atad krowten deviecer yltnecer rof eulav evitagen :rorre {0}" -negvalsent=":tneSsetyBtnecer .lituspog morf atad krowten tnes yltnecer rof eulav evitagen :rorre {0}" +netactivity="26| lituspog morf ytivitca krowten teg ot deliaf: {0}" +negvalrecv="27| :vceRsetyBtnecer .lituspog morf atad krowten deviecer yltnecer rof eulav evitagen :rorre {0}" +negvalsent="28| :tneSsetyBtnecer .lituspog morf atad krowten tnes yltnecer rof eulav evitagen :rorre {0}" [widget.disk] @@ -146,13 +167,14 @@ cpu="%UPC" mem="%meM" pid="DIP" [widget.proc.err] -count=":lituspog morf tnuoc UPC teg ot deliaf {0}" -retrieve=":sessecorp eveirter ot deliaf {0}" -ps=":dnammoc 'sp' etucexe ot deliaf {0}" -gopsutil=":lituspog morf sessecorp teg ot deliaf {0}" -pidconv=":tni ot DIP trevnoc ot deliaf {0}. enil: {1}" -cpuconv=":taolf ot egasu UPC trevnoc ot deliaf {0}. :enil {1}" -memconv=":taolf ot egasu meM trevnoc ot deliaf {0}. :enil {1}" -getcmd=":lituspog morf dnammoc ssecorp teg ot deliaf {0}. corPsp: {1}. i: {2}. dip: {3}" -cpupercent="lituspog morf egasu upc ssecorp teg ot deliaf: {0}. corPsp: {1}. i: {2}. dip: {3}" -mempercent="spog morf egasu yroemem ssecorp teg ot deliafutil: {0}. corPsp: {1}. i: {2}. dip: {3}" +count="29| :lituspog morf tnuoc UPC teg ot deliaf {0}" +retrieve="30| :sessecorp eveirter ot deliaf {0}" +ps="31| :dnammoc 'sp' etucexe ot deliaf {0}" +gopsutil="32| :lituspog morf sessecorp teg ot deliaf {0}" +pidconv="33| :tni ot DIP trevnoc ot deliaf {0}. enil: {1}" +cpuconv="34| :taolf ot egasu UPC trevnoc ot deliaf {0}. :enil {1}" +memconv="35| :taolf ot egasu meM trevnoc ot deliaf {0}. :enil {1}" +getcmd="36| :lituspog morf dnammoc ssecorp teg ot deliaf {0}. corPsp: {1}. i: {2}. dip: {3}" +cpupercent="37| lituspog morf egasu upc ssecorp teg ot deliaf: {0}. corPsp: {1}. i: {2}. dip: {3}" +mempercent="38| spog morf egasu yroemem ssecorp teg ot deliafutil: {0}. corPsp: {1}. i: {2}. dip: {3}" +parse="39| tuptuo esrap ot deliaf: {0}" diff --git a/translations/dicts/zh_CN.toml b/translations/dicts/zh_CN.toml index 68e5f5e..acaf7da 100644 --- a/translations/dicts/zh_CN.toml +++ b/translations/dicts/zh_CN.toml @@ -44,6 +44,30 @@ CPU 和内存图形比例: 网络: - b: 在 mbps 和 每秒字节数 之间切换 """ +# TRANSLATORS: Please don't translate the layout **names** +layouts = """Built-in layouts: + default + minimal + battery + kitchensink""" +# TRANSLATORS: Please don't translate the colorcheme **names** +colorschemes = """Built-in colorschemes: + default + default-dark (for white background) + solarized + solarized16-dark + solarized16-light + monokai + vice""" +# TRANSLATORS: Please don't translate the widget **names** +widgets = """Widgets that can be used in layouts: + cpu - CPU load graph + mem - Physical & swap memory use graph + temp - Sensor temperatures + disk - Physical disk partition use + power - A battery bar + net - Network load + procs - Interactive process list""" [args] @@ -64,29 +88,47 @@ test="执行测试并返回成功或失败码。" conffile="用于替代缺省参数的配置文件(必须是第一个参数)" list=""" List - devices: 显示可用于过滤的设备名 - layouts: 列出所有内置布局方案 - colorschemes: 列出所有内置配色方案 - paths: 列出配置文件的搜索路径 - widgets: 所有可被用于布局的组件 - keys: 显示所有热键。""" -write="将当前配置写入缺省配置文件。" + devices: Prints out device names for filterable widgets + layouts: Lists build-in layouts + colorschemes: Lists built-in colorschemes + paths: List out configuration file search paths + widgets: Widgets that can be used in a layout + keys: Show the keyboard bindings.""" +write="Write out a default config file." + + +[config.err] +configsyntax="0| bad config file syntax; should be KEY=VALUE, was {0}" +deprecation="1| line {0}: '{1}' is deprecated. Ignored {1}={2}" +line="2| line #{0}: {1}" +tempscale="3| invalid TempScale value {0}" [error] -configparse="failed to parse config file: {0}" -cliparse="parsing CLI args: {0}" -logsetup="failed to setup log file: {0}" -unknownopt="Unknown option \"{0}\"; try layouts, colorschemes, keys, paths, or devices\n" -writefail="Failed to write configuration file: {0}" -checklog="errors encountered; from {0}:" -metricsetup="error setting up {0} metrics: {1}" -nometrics="no metrics for {0} {0}" -fatalfetch="fatal error fetching {0} info: {1}" -recovfetch="recoverable error fetching {0} info; skipping {0}: {0}" -nodevfound="no usable {0} found" -setuperr="error setting up {0}: {1}" +configparse="4| failed to parse config file: {0}" +cliparse="5| parsing CLI args: {0}" +logsetup="6| failed to setup log file: {0}" +unknownopt="7| Unknown option \"{0}\"; try layouts, colorschemes, keys, paths, or devices\n" +writefail="8| Failed to write configuration file: {0}" +checklog="9| errors encountered; from {0}:" +metricsetup="10| error setting up {0} metrics: {1}" +nometrics="11| no metrics for {0} {1}" +fatalfetch="12| fatal error fetching {0} info: {1}" +recovfetch="13| recoverable error fetching {0} info; skipping {0}: {1}" +nodevfound="14| no usable {0} found" +setuperr="15| error setting up {0}: {1}" +colorschemefile="16| failed to find colorscheme file {0} in {1}" +colorschemeread="17| failed to read colorscheme file {0}: {1}" +colorschemeparse="18| failed to parse colorscheme file: {0}" +findlayout="19| failed to read colorscheme file {0}: {1}" +logopen="20| failed to open log file {0}: {1}" +table="21| table widget TopRow value less than 0. TopRow: {0}" +nohostname="22| could not get hostname: {0}" +[layout.error] +widget="23| Invalid widget name {0}. Must be one of {1}" +format="24| Layout error on line {0}: format must be {1}. Error parsing {2} as a int. Word was {3}. Using a row height of 1." +slashes="25| Layout warning on line {0}: too many '/' in word {1}; ignoring extra junk." [widget.label] disk=" 磁盘使用率 " @@ -101,9 +143,9 @@ mem=" 内存使用率 " [widget.net.err] -netactivity="failed to get network activity from gopsutil: {0}" -negvalrecv="error: negative value for recently received network data from gopsutil. recentBytesRecv: {0}" -negvalsent="error: negative value for recently sent network data from gopsutil. recentBytesSent: {0}" +netactivity="26| failed to get network activity from gopsutil: {0}" +negvalrecv="27| error: negative value for recently received network data from gopsutil. recentBytesRecv: {0}" +negvalsent="28| error: negative value for recently sent network data from gopsutil. recentBytesSent: {0}" [widget.disk] @@ -125,13 +167,14 @@ cpu="CPU%" mem="内存%" pid="进程标识" [widget.proc.err] -count="failed to get CPU count from gopsutil: {0}" -retrieve="failed to retrieve processes: {0}" -ps="failed to execute 'ps' command: {0}" -gopsutil="failed to get processes from gopsutil: {0}" -pidconv="failed to convert PID to int: {0}. line: {1}" -cpuconv="failed to convert CPU usage to float: {0}. line: {1}" -memconv="failed to convert Mem usage to float: {0}. line: {1}" -getcmd="failed to get process command from gopsutil: {0}. psProc: {1}. i: {2}. pid: {3}" -cpupercent="failed to get process cpu usage from gopsutil: {0}. psProc: {1}. i: {2}. pid: {3}" -mempercent="failed to get process memeory usage from gopsutil: {0}. psProc: {1}. i: {2}. pid: {3}" +count="29| failed to get CPU count from gopsutil: {0}" +retrieve="30| failed to retrieve processes: {0}" +ps="31| failed to execute 'ps' command: {0}" +gopsutil="32| failed to get processes from gopsutil: {0}" +pidconv="33| failed to convert PID to int: {0}. line: {1}" +cpuconv="34| failed to convert CPU usage to float: {0}. line: {1}" +memconv="35| failed to convert Mem usage to float: {0}. line: {1}" +getcmd="36| failed to get process command from gopsutil: {0}. psProc: {1}. i: {2}. pid: {3}" +cpupercent="37| failed to get process cpu usage from gopsutil: {0}. psProc: {1}. i: {2}. pid: {3}" +mempercent="38| failed to get process memeory usage from gopsutil: {0}. psProc: {1}. i: {2}. pid: {3}" +parse="39| failed to parse output: {0}" diff --git a/widgets/disk.go b/widgets/disk.go index 67f3bb6..726e629 100644 --- a/widgets/disk.go +++ b/widgets/disk.go @@ -37,6 +37,7 @@ func NewDiskWidget() *DiskWidget { updateInterval: time.Second, Partitions: make(map[string]*Partition), } + self.Table.Tr = tr self.Title = tr.Value("widget.label.disk") self.Header = []string{tr.Value("disk.disk"), tr.Value("disk.mount"), tr.Value("disk.used"), tr.Value("disk.free"), tr.Value("disk.rs"), tr.Value("disk.ws")} self.ColGap = 2 diff --git a/widgets/proc_freebsd.go b/widgets/proc_freebsd.go index 34fee18..a938636 100644 --- a/widgets/proc_freebsd.go +++ b/widgets/proc_freebsd.go @@ -26,13 +26,13 @@ type processList struct { func getProcs() ([]Proc, error) { output, err := exec.Command("ps", "-axo pid,comm,%cpu,%mem,args", "--libxo", "json").Output() if err != nil { - return nil, fmt.Errorf("failed to execute 'ps' command: %v", err) + return nil, fmt.Errorf(tr.Value("widget.proc.err.ps", err.Error())) } list := processList{} err = json.Unmarshal(output, &list) if err != nil { - return nil, fmt.Errorf("failed to unmarshal json. %s", err) + return nil, fmt.Errorf(tr.Value("widget.proc.err.parse", err.Error())) } procs := []Proc{} @@ -42,15 +42,15 @@ func getProcs() ([]Proc, error) { } pid, err := strconv.Atoi(strings.TrimSpace(process.Pid)) if err != nil { - log.Printf("failed to convert first field to int: %v. split: %v", err, process) + log.Printf(tr.Value("widget.proc.err.pidconv", err.Error(), process)) } cpu, err := strconv.ParseFloat(utils.ConvertLocalizedString(process.CPU), 32) if err != nil { - log.Printf("failed to convert third field to float: %v. split: %v", err, process) + log.Printf(tr.Value("widget.proc.err.cpuconv", err.Error(), process)) } mem, err := strconv.ParseFloat(utils.ConvertLocalizedString(process.Mem), 32) if err != nil { - log.Printf("failed to convert fourth field to float: %v. split: %v", err, process) + log.Printf(tr.Value("widget.proc.err.memconv", err.Error(), process)) } proc := Proc{ Pid: pid, diff --git a/widgets/statusbar.go b/widgets/statusbar.go index 2242414..4727960 100644 --- a/widgets/statusbar.go +++ b/widgets/statusbar.go @@ -24,7 +24,7 @@ func (sb *StatusBar) Draw(buf *ui.Buffer) { hostname, err := os.Hostname() if err != nil { - log.Printf("could not get hostname: %v", err) + log.Printf(tr.Value("error.nohostname", err.Error())) return } buf.SetString( From fd91f5b44587e67a6ee317f5e27f024e2cc5a2c2 Mon Sep 17 00:00:00 2001 From: Tigerfyj Date: Sun, 21 Jun 2020 11:23:05 +0800 Subject: [PATCH 10/19] Add 3 translation line of the [help] section. --- translations/dicts/zh_CN.toml | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/translations/dicts/zh_CN.toml b/translations/dicts/zh_CN.toml index acaf7da..01a1a0c 100644 --- a/translations/dicts/zh_CN.toml +++ b/translations/dicts/zh_CN.toml @@ -45,29 +45,29 @@ CPU 和内存图形比例: - b: 在 mbps 和 每秒字节数 之间切换 """ # TRANSLATORS: Please don't translate the layout **names** -layouts = """Built-in layouts: +layouts = """内建布局方案: default minimal battery kitchensink""" # TRANSLATORS: Please don't translate the colorcheme **names** -colorschemes = """Built-in colorschemes: +colorschemes = """内建配色方案: default - default-dark (for white background) + default-dark (用于白色背景) solarized solarized16-dark solarized16-light monokai vice""" # TRANSLATORS: Please don't translate the widget **names** -widgets = """Widgets that can be used in layouts: - cpu - CPU load graph - mem - Physical & swap memory use graph - temp - Sensor temperatures - disk - Physical disk partition use - power - A battery bar - net - Network load - procs - Interactive process list""" +widgets = """可被用于布局方案的组件名: + cpu - CPU 负载图 + mem - 物理内存和交换内存使用率图 + temp - 传感器温度 + disk - 物理磁盘和分区使用率 + power - 电池状态 + net - 网络负载 + procs - 可交互进程列表""" [args] From b49c7c9a60e2912839c6d6ed1729e7269768d9c8 Mon Sep 17 00:00:00 2001 From: "Sean E. Russell" Date: Sun, 21 Jun 2020 10:14:18 -0500 Subject: [PATCH 11/19] Revert to English if jibber_jabber can't detect the language; revert accidental removal of two zh_CN translations. --- cmd/gotop/main.go | 3 +-- translations/dicts/zh_CN.toml | 14 +++++++------- 2 files changed, 8 insertions(+), 9 deletions(-) diff --git a/cmd/gotop/main.go b/cmd/gotop/main.go index 1f9f0a5..9c228b8 100644 --- a/cmd/gotop/main.go +++ b/cmd/gotop/main.go @@ -362,8 +362,7 @@ func run() int { } lang, err := jj.DetectIETF() if err != nil { - fmt.Printf("failed to get language setting from environment: %s\n", err) - return 2 + lang = "en_US" } lang = strings.Replace(lang, "-", "_", -1) // Get the locale from the os diff --git a/translations/dicts/zh_CN.toml b/translations/dicts/zh_CN.toml index acaf7da..8bd65dc 100644 --- a/translations/dicts/zh_CN.toml +++ b/translations/dicts/zh_CN.toml @@ -88,13 +88,13 @@ test="执行测试并返回成功或失败码。" conffile="用于替代缺省参数的配置文件(必须是第一个参数)" list=""" List - devices: Prints out device names for filterable widgets - layouts: Lists build-in layouts - colorschemes: Lists built-in colorschemes - paths: List out configuration file search paths - widgets: Widgets that can be used in a layout - keys: Show the keyboard bindings.""" -write="Write out a default config file." + devices: 显示可用于过滤的设备名 + layouts: 列出所有内置布局方案 + colorschemes: 列出所有内置配色方案 + paths: 列出配置文件的搜索路径 + widgets: 所有可被用于布局的组件 + keys: 显示所有热键。""" +write="将当前配置写入缺省配置文件。" [config.err] From 81424fb000eaf1b6cd8c1d5bb4d476cb4b3b32db Mon Sep 17 00:00:00 2001 From: "Sean E. Russell" Date: Sun, 21 Jun 2020 11:49:04 -0500 Subject: [PATCH 12/19] Fix windows compile errors. --- go.sum | 1 + widgets/proc_windows.go | 20 +++++++++++++++----- 2 files changed, 16 insertions(+), 5 deletions(-) diff --git a/go.sum b/go.sum index 59dcc33..4fe67f1 100644 --- a/go.sum +++ b/go.sum @@ -13,6 +13,7 @@ github.com/distatus/battery v0.9.0 h1:8NS5o00/j3Oh2xgocA6pQROTp5guoR+s8CZlWzHC4Q github.com/distatus/battery v0.9.0/go.mod h1:gGO7GxHTi1zlRT+cAj8uGG0/8HFiqAeH0TJvoipnuPs= github.com/gizak/termui/v3 v3.1.0 h1:ZZmVDgwHl7gR7elfKf1xc4IudXZ5qqfDh4wExk4Iajc= github.com/gizak/termui/v3 v3.1.0/go.mod h1:bXQEBkJpzxUAKf0+xq9MSWAvWZlE7c+aidmyFlkYTrY= +github.com/go-ole/go-ole v1.2.4 h1:nNBDSCOigTSiarFpYE9J/KtEA1IOW4CNeqT9TQDqCxI= github.com/go-ole/go-ole v1.2.4/go.mod h1:XCwSNxSkXRo4vlyPy93sltvi/qJq0jqQhjqQNIwKuxM= github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= diff --git a/widgets/proc_windows.go b/widgets/proc_windows.go index d34ef5e..1d8bffc 100644 --- a/widgets/proc_windows.go +++ b/widgets/proc_windows.go @@ -3,12 +3,13 @@ package widgets import ( "fmt" "log" + "strconv" - psProc "github.com/shirou/gopsutil/process" + "github.com/shirou/gopsutil/process" ) func getProcs() ([]Proc, error) { - psProcs, err := psProc.Processes() + psProcs, err := process.Processes() if err != nil { return nil, fmt.Errorf(tr.Value("widget.proc.err.gopsutil", err.Error())) } @@ -18,15 +19,24 @@ func getProcs() ([]Proc, error) { pid := psProc.Pid command, err := psProc.Name() if err != nil { - log.Println(tr.Value("widget.proc.err.getcmd", err, psProc, i, pid)) + sps := fmt.Sprintf("%v", psProc) + si := strconv.Itoa(i) + spid := fmt.Sprintf("%d", pid) + log.Println(tr.Value("widget.proc.err.getcmd", err.Error(), sps, si, spid)) } cpu, err := psProc.CPUPercent() if err != nil { - log.Println(tr.Value("widget.proc.err.cpupercent", err, psProc, i, pid)) + sps := fmt.Sprintf("%v", psProc) + si := strconv.Itoa(i) + spid := fmt.Sprintf("%d", pid) + log.Println(tr.Value("widget.proc.err.cpupercent", err.Error(), sps, si, spid)) } mem, err := psProc.MemoryPercent() if err != nil { - log.Println(tr.Value("widget.proc.err.mempercent", err, psProc, i, pid)) + sps := fmt.Sprintf("%v", psProc) + si := strconv.Itoa(i) + spid := fmt.Sprintf("%d", pid) + log.Println(tr.Value("widget.proc.err.mempercent", err.Error(), sps, si, spid)) } procs[i] = Proc{ From cc42059b2e5ae5062bb29288e39f133f0868dd2a Mon Sep 17 00:00:00 2001 From: Tiger Feng Date: Mon, 22 Jun 2020 22:49:03 +0800 Subject: [PATCH 13/19] Add more translation. --- translations/dicts/zh_CN.toml | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/translations/dicts/zh_CN.toml b/translations/dicts/zh_CN.toml index 01a1a0c..1b9fe84 100644 --- a/translations/dicts/zh_CN.toml +++ b/translations/dicts/zh_CN.toml @@ -88,13 +88,13 @@ test="执行测试并返回成功或失败码。" conffile="用于替代缺省参数的配置文件(必须是第一个参数)" list=""" List - devices: Prints out device names for filterable widgets - layouts: Lists build-in layouts - colorschemes: Lists built-in colorschemes - paths: List out configuration file search paths - widgets: Widgets that can be used in a layout - keys: Show the keyboard bindings.""" -write="Write out a default config file." + devices: 显示可用于过滤的设备名 + layouts: 列出所有内置布局方案 + colorschemes: 列出所有内置配色方案 + paths: 列出配置文件的搜索路径 + widgets: 所有可被用于布局的组件 + keys: 显示所有热键。""" +write="将当前配置写入缺省配置文件。" [config.err] @@ -153,8 +153,8 @@ disk="磁盘" mount="文件系统" used="已使用" free="空闲" -rs="R/s" -ws="W/s" +rs="读/秒" +ws="写/秒" [widget.proc] From 8ef3011b94fcc5f3f031377faad02808d91587f5 Mon Sep 17 00:00:00 2001 From: Tiger Feng Date: Mon, 22 Jun 2020 23:01:13 +0800 Subject: [PATCH 14/19] Translate the 'list' --- translations/dicts/zh_CN.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/translations/dicts/zh_CN.toml b/translations/dicts/zh_CN.toml index 1b9fe84..88ad76d 100644 --- a/translations/dicts/zh_CN.toml +++ b/translations/dicts/zh_CN.toml @@ -87,7 +87,7 @@ mbps="显示网速为 mbps。" test="执行测试并返回成功或失败码。" conffile="用于替代缺省参数的配置文件(必须是第一个参数)" list=""" -List +列出 devices: 显示可用于过滤的设备名 layouts: 列出所有内置布局方案 colorschemes: 列出所有内置配色方案 From ccf7a6822f217c84f4feb9d860cb6c9ffeb7688b Mon Sep 17 00:00:00 2001 From: "Sean E. Russell" Date: Mon, 22 Jun 2020 10:23:10 -0500 Subject: [PATCH 15/19] Fix build errors on FreeBSD --- widgets/proc_freebsd.go | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/widgets/proc_freebsd.go b/widgets/proc_freebsd.go index a938636..1df0c66 100644 --- a/widgets/proc_freebsd.go +++ b/widgets/proc_freebsd.go @@ -42,15 +42,18 @@ func getProcs() ([]Proc, error) { } pid, err := strconv.Atoi(strings.TrimSpace(process.Pid)) if err != nil { - log.Printf(tr.Value("widget.proc.err.pidconv", err.Error(), process)) + sp := fmt.Sprintf("%v", process) + log.Printf(tr.Value("widget.proc.err.pidconv", err.Error(), sp)) } cpu, err := strconv.ParseFloat(utils.ConvertLocalizedString(process.CPU), 32) if err != nil { - log.Printf(tr.Value("widget.proc.err.cpuconv", err.Error(), process)) + sp := fmt.Sprintf("%v", process) + log.Printf(tr.Value("widget.proc.err.cpuconv", err.Error(), sp)) } mem, err := strconv.ParseFloat(utils.ConvertLocalizedString(process.Mem), 32) if err != nil { - log.Printf(tr.Value("widget.proc.err.memconv", err.Error(), process)) + sp := fmt.Sprintf("%v", process) + log.Printf(tr.Value("widget.proc.err.memconv", err.Error(), sp)) } proc := Proc{ Pid: pid, From 19884d1868373a10aed03dd7dcbe3bb9e9fcfa26 Mon Sep 17 00:00:00 2001 From: Tiger Feng Date: Thu, 9 Jul 2020 22:16:28 +0800 Subject: [PATCH 16/19] Correct the translation of 'gauge'. --- go.sum | 1 + translations/dicts/zh_CN.toml | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/go.sum b/go.sum index 4fe67f1..d87578a 100644 --- a/go.sum +++ b/go.sum @@ -50,4 +50,5 @@ gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8 gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +howett.net/plist v0.0.0-20200419221736-3b63eb3a43b5 h1:AQkaJpH+/FmqRjmXZPELom5zIERYZfwTjnHpfoVMQEc= howett.net/plist v0.0.0-20200419221736-3b63eb3a43b5/go.mod h1:vMygbs4qMhSZSc4lCUl2OEE+rDiIIJAIdR4m7MiMcm0= diff --git a/translations/dicts/zh_CN.toml b/translations/dicts/zh_CN.toml index 88ad76d..8c8b44b 100644 --- a/translations/dicts/zh_CN.toml +++ b/translations/dicts/zh_CN.toml @@ -133,7 +133,7 @@ slashes="25| Layout warning on line {0}: too many '/' in word {1}; ignoring extr [widget.label] disk=" 磁盘使用率 " cpu=" CPU 使用率 " -gauge=" 功率 " +gauge=" 电量 " battery=" 电池状态 " batt=" 电池 " temp=" 温度 " From 2c811064dd8484d86ddc684cc79f304dc221c0f1 Mon Sep 17 00:00:00 2001 From: "Sean E. Russell" Date: Fri, 24 Jul 2020 08:38:56 -0500 Subject: [PATCH 17/19] Adds Esperanto (incomplete) --- translations/dicts/eo.toml | 180 +++++++++++++++++++++++++++++++++++++ 1 file changed, 180 insertions(+) create mode 100644 translations/dicts/eo.toml diff --git a/translations/dicts/eo.toml b/translations/dicts/eo.toml new file mode 100644 index 0000000..131ec1c --- /dev/null +++ b/translations/dicts/eo.toml @@ -0,0 +1,180 @@ +configfile="Config file" +usage="Usage: {0} [options]\n\nOptions:\n" +total="Total" + + +[help] +paths="Loadable colorschemes & layouts, and the config file, are searched for, in order:" +log="The log file is in {0}" +written="Config written to {0}" +help=""" +Quit: q or + +Process navigation: + - k and : up + - j and : down + - : half page up + - : half page down + - : full page up + - : full page down + - gg and : jump to top + - G and : jump to bottom + +Process actions: + - : toggle process grouping + - dd: kill selected process or group of processes with SIGTERM (15) + - d3: kill selected process or group of processes with SIGQUIT (3) + - d9: kill selected process or group of processes with SIGKILL (9) + +Process sorting: + - c: CPU + - m: Mem + - p: PID + +Process filtering: + - /: start editing filter + - (while editing): + - : accept filter + - and : clear filter + +CPU and Mem graph scaling: + - h: scale in + - l: scale out + +Network: + - b: toggle between mbps and scaled bytes per second +""" +# TRANSLATORS: Please don't translate the layout **names** +layouts = """Built-in layouts: + default + minimal + battery + kitchensink""" +# TRANSLATORS: Please don't translate the colorcheme **names** +colorschemes = """Built-in colorschemes: + default + default-dark (for white background) + solarized + solarized16-dark + solarized16-light + monokai + vice""" +# TRANSLATORS: Please don't translate the widget **names** +widgets = """Widgets that can be used in layouts: + cpu - CPU load graph + mem - Physical & swap memory use graph + temp - Sensor temperatures + disk - Physical disk partition use + power - A battery bar + net - Network load + procs - Interactive process list""" + + +[args] +help="Show this screen." +color="Set a colorscheme." +scale="Graph scale factor, >0" +version="Print version and exit." +percpu="Show each CPU in the CPU widget." +cpuavg="Show average CPU in the CPU widget." +temp="Show temperatures in fahrenheit.Show temperatures in fahrenheit." +statusbar="Show a statusbar with the time." +rate="Refresh frequency. Most time units accepted. \"1m\" = refresh every minute. \"100ms\" = refresh every 100ms." +layout="Name of layout spec file for the UI. Use \"-\" to pipe." +net="Select network interface. Several interfaces can be defined using comma separated values. Interfaces can also be ignored using \"!\"" +export="Enable metrics for export on the specified port." +mbps="Show network rate as mbps." +test="Runs tests and exits with success/failure code." +conffile="Config file to use instead of default (MUST BE FIRST ARGUMENT)" +list=""" +List + devices: Prints out device names for filterable widgets + layouts: Lists build-in layouts + colorschemes: Lists built-in colorschemes + paths: List out configuration file search paths + widgets: Widgets that can be used in a layout + keys: Show the keyboard bindings.""" +write="Write out a default config file." + + +[config.err] +configsyntax="0| bad config file syntax; should be KEY=VALUE, was {0}" +deprecation="1| line {0}: '{1}' is deprecated. Ignored {1}={2}" +line="2| line #{0}: {1}" +tempscale="3| invalid TempScale value {0}" + + +[error] +configparse="4| failed to parse config file: {0}" +cliparse="5| parsing CLI args: {0}" +logsetup="6| failed to setup log file: {0}" +unknownopt="7| Unknown option \"{0}\"; try layouts, colorschemes, keys, paths, or devices\n" +writefail="8| Failed to write configuration file: {0}" +checklog="9| errors encountered; from {0}:" +metricsetup="10| error setting up {0} metrics: {1}" +nometrics="11| no metrics for {0} {1}" +fatalfetch="12| fatal error fetching {0} info: {1}" +recovfetch="13| recoverable error fetching {0} info; skipping {0}: {1}" +nodevfound="14| no usable {0} found" +setuperr="15| error setting up {0}: {1}" +colorschemefile="16| failed to find colorscheme file {0} in {1}" +colorschemeread="17| failed to read colorscheme file {0}: {1}" +colorschemeparse="18| failed to parse colorscheme file: {0}" +findlayout="19| failed to read colorscheme file {0}: {1}" +logopen="20| failed to open log file {0}: {1}" +table="21| table widget TopRow value less than 0. TopRow: {0}" +nohostname="22| could not get hostname: {0}" + +[layout.error] +widget="23| Invalid widget name {0}. Must be one of {1}" +format="24| Layout error on line {0}: format must be {1}. Error parsing {2} as a int. Word was {3}. Using a row height of 1." +slashes="25| Layout warning on line {0}: too many '/' in word {1}; ignoring extra junk." + +[widget.label] +disk=" Disk Usage " +cpu=" CPU Usage " +gauge=" Power Level " +battery=" Battery Status " +batt=" Battery " +temp=" Temperatures " +net=" Network Usage " +netint=" Network Usage: {0} " +mem=" Memory Usage " + + +[widget.net.err] +netactivity="26| failed to get network activity from gopsutil: {0}" +negvalrecv="27| error: negative value for recently received network data from gopsutil. recentBytesRecv: {0}" +negvalsent="28| error: negative value for recently sent network data from gopsutil. recentBytesSent: {0}" + + +[widget.disk] +disk="Disk" +mount="Mount" +used="Used" +free="Free" +rs="R/s" +ws="W/s" + + +[widget.proc] +filter=" Filter: " +label=" Processes " +[widget.proc.header] +count="Count" +command="Command" +cpu="CPU%" +mem="Mem%" +pid="PID" +[widget.proc.err] +count="29| failed to get CPU count from gopsutil: {0}" +retrieve="30| failed to retrieve processes: {0}" +ps="31| failed to execute 'ps' command: {0}" +gopsutil="32| failed to get processes from gopsutil: {0}" +pidconv="33| failed to convert PID to int: {0}. line: {1}" +cpuconv="34| failed to convert CPU usage to float: {0}. line: {1}" +memconv="35| failed to convert Mem usage to float: {0}. line: {1}" +getcmd="36| failed to get process command from gopsutil: {0}. psProc: {1}. i: {2}. pid: {3}" +cpupercent="37| failed to get process cpu usage from gopsutil: {0}. psProc: {1}. i: {2}. pid: {3}" +mempercent="38| failed to get process memeory usage from gopsutil: {0}. psProc: {1}. i: {2}. pid: {3}" +parse="39| failed to parse output: {0}" From df2da8a250ac9d64d45688a82014d0216dfc050c Mon Sep 17 00:00:00 2001 From: "Sean E. Russell" Date: Mon, 24 Aug 2020 14:31:29 -0500 Subject: [PATCH 18/19] Closes #147. --- LICENSE | 44 ++++++++++++++++++++------------------------ 1 file changed, 20 insertions(+), 24 deletions(-) diff --git a/LICENSE b/LICENSE index 0a126e1..abb389e 100644 --- a/LICENSE +++ b/LICENSE @@ -1,29 +1,25 @@ -The MIT License (MIT) +The MIT License (Festival variant) -Copyright (c) 2020 Sean E. Russell 87651D71 +Permission is hereby granted, free of charge, to use and distribute this +software and its documentation without restriction, including without +limitation the rights to use, copy, modify, merge, publish, distribute, +sublicense, and/or sell copies of this work, and to permit persons to whom +this work is furnished to do so, subject to the following conditions: -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: +1. The codemust retain the above copyright notice, this list of conditions + and the following disclaimer. +2. Any modifications must be clearly marked as such. +3. Original authors' names are not deleted. +4. The authors' names are not used to endorse or promote products derived + from this software without specific prior written permission. -1. Redistributions of source code must retain the above copyright notice, -this list of conditions and the following disclaimer. +THE COPYRIGHT HOLDERS AND THE CONTRIBUTORS TO THIS WORK DISCLAIM ALL +WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS NOR THE +CONTRIBUTORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES +OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, +WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -2. Redistributions in binary form must reproduce the above copyright -notice, this list of conditions and the following disclaimer in the -documentation and/or other materials provided with the distribution. -3. Neither the name of the copyright holder nor the names of its -contributors may be used to endorse or promote products derived from this -software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS -IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, -THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR -CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, -EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +https://fedoraproject.org/wiki/Licensing:MIT?rd=Licensing/MIT#Festival_variant From edf0c2a3a8edd43a685ef91c2e3f9f3ea7d5bc23 Mon Sep 17 00:00:00 2001 From: "Sean E. Russell" Date: Tue, 25 Aug 2020 08:23:42 -0500 Subject: [PATCH 19/19] Fixes bad label keys in disk widget; finishes Esperanto translation. --- translations/dicts/eo.toml | 250 +++++++++++++++++++------------------ widgets/disk.go | 2 +- 2 files changed, 127 insertions(+), 125 deletions(-) diff --git a/translations/dicts/eo.toml b/translations/dicts/eo.toml index 131ec1c..51cc768 100644 --- a/translations/dicts/eo.toml +++ b/translations/dicts/eo.toml @@ -1,180 +1,182 @@ -configfile="Config file" -usage="Usage: {0} [options]\n\nOptions:\n" -total="Total" +configfile="Argododosiero" +usage="Uzado: {0} [ebloj]\n\nEbloj:\n" +total="Sumo" [help] -paths="Loadable colorschemes & layouts, and the config file, are searched for, in order:" -log="The log file is in {0}" -written="Config written to {0}" +paths="Ŝarĝebla kloraj skemoj & enpaĝigoj, kaj la argododosiero, estas orda serĉatigis:" +log="Logodosiero troviĝas ĉe {0}" +written="Argordo skribiĝis ĉe {0}" help=""" -Quit: q or +Eliri: q aŭ -Process navigation: - - k and : up - - j and : down - - : half page up - - : half page down - - : full page up - - : full page down - - gg and : jump to top - - G and : jump to bottom +Proceza navigadoj: + - k kaj : supren + - j kaj : malsupren + - : duona paĝo supren + - : duona paĝo malsupren + - : plena paĝo supren + - : plena paĝo malsupren + - gg kaj : salti al supron + - G kaj : salti al malsupron -Process actions: - - : toggle process grouping - - dd: kill selected process or group of processes with SIGTERM (15) - - d3: kill selected process or group of processes with SIGQUIT (3) - - d9: kill selected process or group of processes with SIGKILL (9) +Proceza agoj: + - : alterni procezon grupigi + - dd: fini la elektitajn procezojn aŭ procezon grupigon kun SIGTERM (15) + - d3: fini la elektitajn procezojn aŭ procezon grupigon kun SIGQUIT (3) + - d9: fini la elektitajn procezojn aŭ procezon grupigon kun SIGKILL (9) -Process sorting: +Proceza ordigoj: - c: CPU - - m: Mem + - m: Memoro - p: PID -Process filtering: - - /: start editing filter - - (while editing): - - : accept filter - - and : clear filter +Proceza filtradoj: + - /: komenci redakti filtrilon + - (dum redaktadi): + - : akcepti filtrilon + - kaj : eliri filtrilon -CPU and Mem graph scaling: - - h: scale in - - l: scale out +CPU kaj Memora grafilo skali: + - h: zomi + - l: malzomi -Network: - - b: toggle between mbps and scaled bytes per second +Reto: + - b: alterni inter mbps kaj skale bajtoj por dua """ # TRANSLATORS: Please don't translate the layout **names** -layouts = """Built-in layouts: +layouts = """Enkonstruitaj enpaĝigoj: default minimal battery kitchensink""" -# TRANSLATORS: Please don't translate the colorcheme **names** -colorschemes = """Built-in colorschemes: +# TRANSLATORS: Please don't translate the colorscheme **names** +colorschemes = """Enkonstruitaj kloraj skemoj: default - default-dark (for white background) + default-dark (por blanka fono) solarized solarized16-dark solarized16-light monokai vice""" # TRANSLATORS: Please don't translate the widget **names** -widgets = """Widgets that can be used in layouts: - cpu - CPU load graph - mem - Physical & swap memory use graph - temp - Sensor temperatures - disk - Physical disk partition use - power - A battery bar - net - Network load - procs - Interactive process list""" +widgets = """Enpaĝigaj Fenestraĵoj: + cpu - CPU ŝarĝa grafilo + mem - Fizika kay interŝanĝa memora grafilo + temp - Temperatura sensiloj + disk - Fizikaj diskdispartigaj uzadilo + power - Bateria mezurilo + net - Retuzadilo + procs - Interaga proceza listo""" [args] -help="Show this screen." -color="Set a colorscheme." -scale="Graph scale factor, >0" -version="Print version and exit." -percpu="Show each CPU in the CPU widget." -cpuavg="Show average CPU in the CPU widget." -temp="Show temperatures in fahrenheit.Show temperatures in fahrenheit." -statusbar="Show a statusbar with the time." -rate="Refresh frequency. Most time units accepted. \"1m\" = refresh every minute. \"100ms\" = refresh every 100ms." -layout="Name of layout spec file for the UI. Use \"-\" to pipe." -net="Select network interface. Several interfaces can be defined using comma separated values. Interfaces can also be ignored using \"!\"" -export="Enable metrics for export on the specified port." -mbps="Show network rate as mbps." -test="Runs tests and exits with success/failure code." -conffile="Config file to use instead of default (MUST BE FIRST ARGUMENT)" +help="Ĉi tiun informoj." +color="Agordi kloraj skemoj." +scale="Agordi grafilan skalon, >0" +version="Montri version kaj eliri." +percpu="Montri ĉiun CPU en la CPU-fenestraĵo." +cpuavg="Montri duonan CPU en la CPU-fenestraĵo." +temp="Montri temperaturojn en fahrenheit." +statusbar="Montri statusbarbaron kun la tempo." +rate="Refreŝiga ofteco. Plej multaj unuoj akceptitaj. \"1m\" = refreŝigi ĉiun minuton. \"100ms\" = refreŝigi ĉiun dekonon minuton." +layout="Nomo de aranĝa specifa dosiero por la UI. Uzu \"-\" por pipi." +net="Elekti retinterfacon. Multaj interfacoj povas esti difinitaj per komparaj valoroj. Interfacoj ankaŭ povas esti ignorataj per \"!\"" +export="Ebligu metrikojn por eksportado en la specifita haveno." +mbps="Montri reta takson kiel mbps." +test="Ekzekutas testojn kaj forirojn kun sukceso / fiaska kodo." +conffile="Agordi dosiero por uzi anstataŭ defaŭlte (DEVAS ESTI UNUA ARGUMENTO)" +# TRANSLATORS: Please don't translate the list entries list=""" List - devices: Prints out device names for filterable widgets - layouts: Lists build-in layouts - colorschemes: Lists built-in colorschemes - paths: List out configuration file search paths - widgets: Widgets that can be used in a layout - keys: Show the keyboard bindings.""" -write="Write out a default config file." + devices: Montras nomojn de aparatoj por filteblaj fenestraĵoj + layouts: Listigas enkonstruajn aranĝojn + colorschemes: Listas enkonstruitajn kloraj skemoj + paths: Enlistigu agordajn serĉajn vojojn de agordo + widgets: Fenestraĵoj uzeblaj en aranĝo + keys: Montri la klavarajn ligojn.""" +write="Skribu defaŭltan agordan dosieron." [config.err] -configsyntax="0| bad config file syntax; should be KEY=VALUE, was {0}" -deprecation="1| line {0}: '{1}' is deprecated. Ignored {1}={2}" -line="2| line #{0}: {1}" -tempscale="3| invalid TempScale value {0}" +configsyntax="0| malbona agordo dosiero-sintakso; estu ŜLOSI=VALORO, estis {0}" +deprecation="1| linio {0}: '{1}' malakceptas. Ignorita {1}={2}" +line="2| linio #{0}: {1}" +tempscale="3| malvalida TempScale-valoro {0}" [error] -configparse="4| failed to parse config file: {0}" -cliparse="5| parsing CLI args: {0}" -logsetup="6| failed to setup log file: {0}" -unknownopt="7| Unknown option \"{0}\"; try layouts, colorschemes, keys, paths, or devices\n" -writefail="8| Failed to write configuration file: {0}" -checklog="9| errors encountered; from {0}:" -metricsetup="10| error setting up {0} metrics: {1}" -nometrics="11| no metrics for {0} {1}" -fatalfetch="12| fatal error fetching {0} info: {1}" -recovfetch="13| recoverable error fetching {0} info; skipping {0}: {1}" -nodevfound="14| no usable {0} found" -setuperr="15| error setting up {0}: {1}" -colorschemefile="16| failed to find colorscheme file {0} in {1}" -colorschemeread="17| failed to read colorscheme file {0}: {1}" -colorschemeparse="18| failed to parse colorscheme file: {0}" -findlayout="19| failed to read colorscheme file {0}: {1}" -logopen="20| failed to open log file {0}: {1}" -table="21| table widget TopRow value less than 0. TopRow: {0}" -nohostname="22| could not get hostname: {0}" +configparse="4| malsukcesis pari agordi dosiero: {0}" +cliparse="5| analizante CLI-argumentojn: {0}" +logsetup="6| malsukcesis agordi registro dosiero: {0}" +unknownopt="7| Nekonata opcio \"{0}\"; provu layouts, colorschemes, keys, paths, aŭ devices" +writefail="8| Malsukcesis skribi agordan dosieron: {0}" +checklog="9| eraroj renkontitaj; de {0}:" +metricsetup="10| eraro agordante {0} metrikojn: {1}" +nometrics="11| neniuj metrikoj por {0} {1}" +fatalfetch="12| fatala eraro elprenanta {0} info: {1}" +recovfetch="13| reakirebla eraro elprenanta {0} info; saltante {0}: {1}" +nodevfound="14| neniu uzebla {0} trovita" +setuperr="15| eraro agordante {0}: {1}" +colorschemefile="16| malsukcesis trovi kloraj skemoj dosiero {0} en {1}" +colorschemeread="17| malsukcesis legi kloraj skemoj dosiero {0}: {1}" +colorschemeparse="18| Fiaskis analizi kloraj skemoj dosiero: {0}" +findlayout="19| malsukcesis legi kloraj skemoj dosiero {0}: {1}" +logopen="20| malsukcesis malfermi enskribi dosieron {0}: {1}" +table="21| Tabla fenestraĵo TopRow-valoro malpli ol 0. TopRow: {0}" +nohostname="22| Ne povis akiri hostname: {0}" [layout.error] -widget="23| Invalid widget name {0}. Must be one of {1}" -format="24| Layout error on line {0}: format must be {1}. Error parsing {2} as a int. Word was {3}. Using a row height of 1." -slashes="25| Layout warning on line {0}: too many '/' in word {1}; ignoring extra junk." +widget="23| Malvalida fenestra nomo {0}. Devas esti unu el {1}" +format="24| Eraro pri aranĝo sur linio {0}: formato devas esti {1}. Eraro analizante {2} kiel int. Vorto estis {3}. Uzante vicon alteco de 1." +slashes="25| Averto pri aranĝo sur linio {0}: tro multaj '/' en vorto {1}; ignorante kroman rubon." [widget.label] -disk=" Disk Usage " -cpu=" CPU Usage " -gauge=" Power Level " -battery=" Battery Status " -batt=" Battery " -temp=" Temperatures " -net=" Network Usage " -netint=" Network Usage: {0} " -mem=" Memory Usage " +disk=" Disk Usado " +cpu=" CPU Usado " +gauge=" Potencnivelo " +battery=" Bateria Statuso " +batt=" Baterio " +temp=" Temperaturoj " +net=" Reta Usado " +netint=" Reta Usado: {0} " +mem=" Memoro Usado " [widget.net.err] -netactivity="26| failed to get network activity from gopsutil: {0}" -negvalrecv="27| error: negative value for recently received network data from gopsutil. recentBytesRecv: {0}" -negvalsent="28| error: negative value for recently sent network data from gopsutil. recentBytesSent: {0}" +netactivity="26| malsukcesis ricevi retactiveco de gopsutil: {0}" +negvalrecv="27| eraro: negativa valoro por ĵus ricevitaj retdatumoj de gopsutil. RecentBytesRecv: {0}" +negvalsent="28| eraro: negativa valoro por ĵus senditaj retdatumoj de gopsutil. RecentBytesSent: {0}" [widget.disk] -disk="Disk" -mount="Mount" -used="Used" -free="Free" +disk="Disko" +mount="Monto" +used="Uzita" +free="Senpaga" rs="R/s" ws="W/s" [widget.proc] -filter=" Filter: " -label=" Processes " +filter=" Filtrilo: " +label=" Procezoj " [widget.proc.header] -count="Count" -command="Command" +count="Kalkulo" +command="Komando" cpu="CPU%" mem="Mem%" pid="PID" + [widget.proc.err] -count="29| failed to get CPU count from gopsutil: {0}" -retrieve="30| failed to retrieve processes: {0}" -ps="31| failed to execute 'ps' command: {0}" -gopsutil="32| failed to get processes from gopsutil: {0}" -pidconv="33| failed to convert PID to int: {0}. line: {1}" -cpuconv="34| failed to convert CPU usage to float: {0}. line: {1}" -memconv="35| failed to convert Mem usage to float: {0}. line: {1}" -getcmd="36| failed to get process command from gopsutil: {0}. psProc: {1}. i: {2}. pid: {3}" -cpupercent="37| failed to get process cpu usage from gopsutil: {0}. psProc: {1}. i: {2}. pid: {3}" -mempercent="38| failed to get process memeory usage from gopsutil: {0}. psProc: {1}. i: {2}. pid: {3}" -parse="39| failed to parse output: {0}" +count="29| malsukcesis akiri CPU-kalkuladon de gopsutil: {0}" +retrieve="30| ne sukcesis akiri procezojn: {0}" +ps="31| malsukcesis plenumi komandon 'ps': {0}" +gopsutil="32| malsukcesis akiri procezojn de gopsutilo: {0}" +pidconv="33| malsukcesis konverti PID al int: {0}. linio: {1}" +cpuconv="34| malsukcesis konverti CPU-uzon al flosilo: {0}. linio: {1}" +memconv="35| malsukcesis konverti Mem-uzon al flosilo: {0}. linio: {1}" +getcmd="36| malsukcesis akiri procezan komandon de gopsutil: {0}. psProc: {1}. i: {2}. pid: {3}" +cpupercent="37| malsukcesis ricevi uzadon de proceso cpu de gopsutil: {0}. psProc: {1}. i: {2}. pid: {3}" +mempercent="38| malsukcesis ricevi uzadon de proceza memoro de gopsutil: {0}. psProc: {1}. i: {2}. pid: {3}" +parse="39| ne sukcesis analizi eliron: {0}" diff --git a/widgets/disk.go b/widgets/disk.go index 726e629..9df3c3b 100644 --- a/widgets/disk.go +++ b/widgets/disk.go @@ -39,7 +39,7 @@ func NewDiskWidget() *DiskWidget { } self.Table.Tr = tr self.Title = tr.Value("widget.label.disk") - self.Header = []string{tr.Value("disk.disk"), tr.Value("disk.mount"), tr.Value("disk.used"), tr.Value("disk.free"), tr.Value("disk.rs"), tr.Value("disk.ws")} + self.Header = []string{tr.Value("widget.disk.disk"), tr.Value("widget.disk.mount"), tr.Value("widget.disk.used"), tr.Value("widget.disk.free"), tr.Value("widget.disk.rs"), tr.Value("widget.disk.ws")} self.ColGap = 2 self.ColResizer = func() { self.ColWidths = []int{