More strings moved to translations

This commit is contained in:
Sean E. Russell 2020-06-20 16:47:48 -05:00
parent 9a56571373
commit 23364aa754
17 changed files with 347 additions and 186 deletions

View File

@ -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 {

View File

@ -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
}

View File

@ -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:

View File

@ -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
}

View File

@ -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()))
}
}
}

View File

@ -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)
}

View File

@ -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 != "" {

View File

@ -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 {

View File

@ -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

View File

@ -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
}

View File

@ -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|layouts|colorschemes|paths|keys>
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 <C-c>
@ -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|layouts|colorschemes|paths|keys>
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}"

View File

@ -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 <devices|layouts|colorschemes|paths|keys>
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}"

View File

@ -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}"

View File

@ -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|keys>
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}"

View File

@ -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

View File

@ -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,

View File

@ -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(