optimize: i18n format

This commit is contained in:
XZB-1248
2022-10-14 19:49:13 +08:00
parent 126abef09e
commit 52c4b8f2bd
36 changed files with 476 additions and 456 deletions

View File

@@ -41,7 +41,7 @@ Authorization: Basic WFpCOjEyNDg=
```
{
"code": -1,
"msg": "${i18n|invalidParameter}"
"msg": "${i18n|COMMON.INVALID_PARAMETER}"
}
```
```
@@ -55,7 +55,7 @@ Authorization: Basic WFpCOjEyNDg=
```
{
"code": 1,
"msg": "${i18n|deviceNotExists}"
"msg": "${i18n|COMMON.DEVICE_NOT_EXIST}"
}
```
@@ -169,7 +169,7 @@ cmd=taskkill&args=%2Ff%20%2Fim%20regedit.exe&device=bc7e49f8f794f80ffb0032a4ba51
```
{
"code": 1,
"msg": "${i18n|noDisplayFound}"
"msg": "${i18n|DESKTOP.NO_DISPLAY_FOUND}"
}
```
@@ -188,7 +188,7 @@ cmd=taskkill&args=%2Ff%20%2Fim%20regedit.exe&device=bc7e49f8f794f80ffb0032a4ba51
```
{
"code": 1,
"msg": "${i18n|fileOrDirNotExist}"
"msg": "${i18n|EXPLORER.FILE_OR_DIR_NOT_EXIST}"
}
```
@@ -208,7 +208,7 @@ cmd=taskkill&args=%2Ff%20%2Fim%20regedit.exe&device=bc7e49f8f794f80ffb0032a4ba51
```
{
"code": 1,
"msg": "${i18n|fileOrDirNotExist}"
"msg": "${i18n|EXPLORER.FILE_OR_DIR_NOT_EXIST}"
}
```
@@ -249,7 +249,7 @@ Hello World.
```
{
"code": 1,
"msg": "${i18n|fileOrDirNotExist}"
"msg": "${i18n|EXPLORER.FILE_OR_DIR_NOT_EXIST}"
}
```
@@ -289,7 +289,7 @@ Hello World.
```
{
"code": 1,
"msg": "${i18n|fileOrDirNotExist}"
"msg": "${i18n|EXPLORER.FILE_OR_DIR_NOT_EXIST}"
}
```
@@ -343,6 +343,6 @@ Hello World.
```
{
"code": 1,
"msg": "${i18n|deviceNotExists}"
"msg": "${i18n|COMMON.DEVICE_NOT_EXIST}"
}
```

16
API.md
View File

@@ -39,7 +39,7 @@ All responses are JSON encoded.
```
{
"code": -1,
"msg": "${i18n|invalidParameter}"
"msg": "${i18n|COMMON.INVALID_PARAMETER}"
}
```
```
@@ -53,7 +53,7 @@ All responses are JSON encoded.
```
{
"code": 1,
"msg": "${i18n|deviceNotExists}"
"msg": "${i18n|COMMON.DEVICE_NOT_EXIST}"
}
```
@@ -166,7 +166,7 @@ If failed, then the following response are given.
```
{
"code": 1,
"msg": "${i18n|noDisplayFound}"
"msg": "${i18n|DESKTOP.NO_DISPLAY_FOUND}"
}
```
@@ -185,7 +185,7 @@ A zip file is given if multiple files (including directory) are given.
```
{
"code": 1,
"msg": "${i18n|fileOrDirNotExist}"
"msg": "${i18n|EXPLORER.FILE_OR_DIR_NOT_EXIST}"
}
```
@@ -205,7 +205,7 @@ If files exist and are deleted successfully, then `code` will be `0`.
```
{
"code": 1,
"msg": "${i18n|fileOrDirNotExist}"
"msg": "${i18n|EXPLORER.FILE_OR_DIR_NOT_EXIST}"
}
```
@@ -246,7 +246,7 @@ And `D:\Test.txt` will be created with the content of `Hello World.`.
```
{
"code": 1,
"msg": "${i18n|fileOrDirNotExist}"
"msg": "${i18n|EXPLORER.FILE_OR_DIR_NOT_EXIST}"
}
```
@@ -284,7 +284,7 @@ If `path` is empty, then it gives you volumes list (windows) or gives files on `
```
{
"code": 1,
"msg": "${i18n|fileOrDirNotExist}"
"msg": "${i18n|EXPLORER.FILE_OR_DIR_NOT_EXIST}"
}
```
@@ -337,6 +337,6 @@ Parameters: `pid` and `device` (device ID)
```
{
"code": 1,
"msg": "${i18n|deviceNotExists}"
"msg": "${i18n|COMMON.DEVICE_NOT_EXIST}"
}
```

View File

@@ -1,3 +1,13 @@
## v0.1.7
* Optimize: i18n format.
* Fix: won't kill shell process after exit.
* 优化:国际化格式。
* 修复:退出后不会自动结束 shell 进程。
## v0.1.6
* Optimize: potential crash problem of explorer.

View File

@@ -40,7 +40,7 @@ func (wsConn *Conn) SendData(data []byte) error {
Mutex.Lock()
defer Mutex.Unlock()
if WSConn == nil {
return errors.New(`${i18n|wsClosed}`)
return errors.New(`${i18n|COMMON.DISCONNECTED}`)
}
wsConn.SetWriteDeadline(utils.Now.Add(5 * time.Second))
defer wsConn.SetWriteDeadline(time.Time{})
@@ -66,7 +66,7 @@ func (wsConn *Conn) SendPack(pack any) error {
return err
}
if WSConn == nil {
return errors.New(`${i18n|wsClosed}`)
return errors.New(`${i18n|COMMON.DISCONNECTED}`)
}
wsConn.SetWriteDeadline(utils.Now.Add(5 * time.Second))
defer wsConn.SetWriteDeadline(time.Time{})

View File

@@ -106,7 +106,7 @@ func reportWS(wsConn *common.Conn) error {
return err
}
if pack.Code != 0 {
return errors.New(`${i18n|unknownError}`)
return errors.New(`${i18n|COMMON.UNKNOWN_ERROR}`)
}
return nil
}
@@ -126,7 +126,7 @@ func checkUpdate(wsConn *common.Conn) error {
return err
}
if resp == nil {
return errors.New(`${i18n|unknownError}`)
return errors.New(`${i18n|COMMON.UNKNOWN_ERROR}`)
}
if strings.HasPrefix(resp.GetContentType(), `application/octet-stream`) {
body := resp.Bytes()
@@ -192,7 +192,7 @@ func handleWS(wsConn *common.Conn) error {
func handleAct(pack modules.Packet, wsConn *common.Conn) {
if act, ok := handlers[pack.Act]; !ok {
wsConn.SendCallback(modules.Packet{Code: 1, Msg: `${i18n|actionNotImplemented}`}, pack)
wsConn.SendCallback(modules.Packet{Code: 1, Msg: `${i18n|COMMON.OPERATION_NOT_SUPPORTED}`}, pack)
} else {
defer func() {
if r := recover(); r != nil {

View File

@@ -119,7 +119,7 @@ func shutdown(pack modules.Packet, wsConn *common.Conn) {
func screenshot(pack modules.Packet, wsConn *common.Conn) {
var bridge string
if val, ok := pack.GetData(`bridge`, reflect.String); !ok {
wsConn.SendCallback(modules.Packet{Code: 1, Msg: `${i18n|invalidParameter}`}, pack)
wsConn.SendCallback(modules.Packet{Code: 1, Msg: `${i18n|COMMON.INVALID_PARAMETER}`}, pack)
return
} else {
bridge = val.(string)
@@ -171,19 +171,19 @@ func listFiles(pack modules.Packet, wsConn *common.Conn) {
func fetchFile(pack modules.Packet, wsConn *common.Conn) {
var path, filename, bridge string
if val, ok := pack.GetData(`path`, reflect.String); !ok {
wsConn.SendCallback(modules.Packet{Code: 1, Msg: `${i18n|fileOrDirNotExist}`}, pack)
wsConn.SendCallback(modules.Packet{Code: 1, Msg: `${i18n|EXPLORER.FILE_OR_DIR_NOT_EXIST}`}, pack)
return
} else {
path = val.(string)
}
if val, ok := pack.GetData(`file`, reflect.String); !ok {
wsConn.SendCallback(modules.Packet{Code: 1, Msg: `${i18n|invalidParameter}`}, pack)
wsConn.SendCallback(modules.Packet{Code: 1, Msg: `${i18n|COMMON.INVALID_PARAMETER}`}, pack)
return
} else {
filename = val.(string)
}
if val, ok := pack.GetData(`bridge`, reflect.String); !ok {
wsConn.SendCallback(modules.Packet{Code: 1, Msg: `${i18n|invalidParameter}`}, pack)
wsConn.SendCallback(modules.Packet{Code: 1, Msg: `${i18n|COMMON.INVALID_PARAMETER}`}, pack)
return
} else {
bridge = val.(string)
@@ -197,7 +197,7 @@ func fetchFile(pack modules.Packet, wsConn *common.Conn) {
func removeFiles(pack modules.Packet, wsConn *common.Conn) {
var files []string
if val, ok := pack.Data[`files`]; !ok {
wsConn.SendCallback(modules.Packet{Code: 1, Msg: `${i18n|fileOrDirNotExist}`}, pack)
wsConn.SendCallback(modules.Packet{Code: 1, Msg: `${i18n|EXPLORER.FILE_OR_DIR_NOT_EXIST}`}, pack)
return
} else {
slice := val.([]any)
@@ -208,7 +208,7 @@ func removeFiles(pack modules.Packet, wsConn *common.Conn) {
}
}
if len(files) == 0 {
wsConn.SendCallback(modules.Packet{Code: 1, Msg: `${i18n|fileOrDirNotExist}`}, pack)
wsConn.SendCallback(modules.Packet{Code: 1, Msg: `${i18n|EXPLORER.FILE_OR_DIR_NOT_EXIST}`}, pack)
return
}
}
@@ -227,7 +227,7 @@ func uploadFiles(pack modules.Packet, wsConn *common.Conn) {
bridge string
)
if val, ok := pack.Data[`files`]; !ok {
wsConn.SendCallback(modules.Packet{Code: 1, Msg: `${i18n|fileOrDirNotExist}`}, pack)
wsConn.SendCallback(modules.Packet{Code: 1, Msg: `${i18n|EXPLORER.FILE_OR_DIR_NOT_EXIST}`}, pack)
return
} else {
slice := val.([]any)
@@ -238,12 +238,12 @@ func uploadFiles(pack modules.Packet, wsConn *common.Conn) {
}
}
if len(files) == 0 {
wsConn.SendCallback(modules.Packet{Code: 1, Msg: `${i18n|fileOrDirNotExist}`}, pack)
wsConn.SendCallback(modules.Packet{Code: 1, Msg: `${i18n|EXPLORER.FILE_OR_DIR_NOT_EXIST}`}, pack)
return
}
}
if val, ok := pack.GetData(`bridge`, reflect.String); !ok {
wsConn.SendCallback(modules.Packet{Code: 1, Msg: `${i18n|invalidParameter}`}, pack)
wsConn.SendCallback(modules.Packet{Code: 1, Msg: `${i18n|COMMON.INVALID_PARAMETER}`}, pack)
return
} else {
bridge = val.(string)
@@ -273,13 +273,13 @@ func uploadFiles(pack modules.Packet, wsConn *common.Conn) {
func uploadTextFile(pack modules.Packet, wsConn *common.Conn) {
var path, bridge string
if val, ok := pack.GetData(`file`, reflect.String); !ok {
wsConn.SendCallback(modules.Packet{Code: 1, Msg: `${i18n|fileOrDirNotExist}`}, pack)
wsConn.SendCallback(modules.Packet{Code: 1, Msg: `${i18n|EXPLORER.FILE_OR_DIR_NOT_EXIST}`}, pack)
return
} else {
path = val.(string)
}
if val, ok := pack.GetData(`bridge`, reflect.String); !ok {
wsConn.SendCallback(modules.Packet{Code: 1, Msg: `${i18n|invalidParameter}`}, pack)
wsConn.SendCallback(modules.Packet{Code: 1, Msg: `${i18n|COMMON.INVALID_PARAMETER}`}, pack)
return
} else {
bridge = val.(string)
@@ -306,7 +306,7 @@ func killProcess(pack modules.Packet, wsConn *common.Conn) {
err error
)
if val, ok := pack.GetData(`pid`, reflect.Float64); !ok {
wsConn.SendCallback(modules.Packet{Code: 1, Msg: `${i18n|invalidParameter}`}, pack)
wsConn.SendCallback(modules.Packet{Code: 1, Msg: `${i18n|COMMON.INVALID_PARAMETER}`}, pack)
return
} else {
pid = int32(val.(float64))
@@ -344,13 +344,13 @@ func execCommand(pack modules.Packet, wsConn *common.Conn) {
var proc *exec.Cmd
var cmd, args string
if val, ok := pack.Data[`cmd`]; !ok {
wsConn.SendCallback(modules.Packet{Code: 1, Msg: `${i18n|invalidParameter}`}, pack)
wsConn.SendCallback(modules.Packet{Code: 1, Msg: `${i18n|COMMON.INVALID_PARAMETER}`}, pack)
return
} else {
cmd = val.(string)
}
if val, ok := pack.Data[`args`]; !ok {
wsConn.SendCallback(modules.Packet{Code: 1, Msg: `${i18n|invalidParameter}`}, pack)
wsConn.SendCallback(modules.Packet{Code: 1, Msg: `${i18n|COMMON.INVALID_PARAMETER}`}, pack)
return
} else {
args = val.(string)

View File

@@ -56,14 +56,14 @@ func init() {
}
func Lock() error {
return errors.New(`${i18n|operationNotSupported}`)
return errors.New(`${i18n|COMMON.OPERATION_NOT_SUPPORTED}`)
}
func Logoff() error {
if C.SendAppleEventToSystemProcess(C.kAEReallyLogOut) == C.noErr {
return nil
} else {
return errors.New(`${i18n|operationNotSupported}`)
return errors.New(`${i18n|COMMON.OPERATION_NOT_SUPPORTED}`)
}
}
@@ -71,12 +71,12 @@ func Hibernate() error {
if C.SendAppleEventToSystemProcess(C.kAESleep) == C.noErr {
return nil
} else {
return errors.New(`${i18n|operationNotSupported}`)
return errors.New(`${i18n|COMMON.OPERATION_NOT_SUPPORTED}`)
}
}
func Suspend() error {
return errors.New(`${i18n|operationNotSupported}`)
return errors.New(`${i18n|COMMON.OPERATION_NOT_SUPPORTED}`)
}
func Restart() error {

View File

@@ -12,11 +12,11 @@ func init() {
}
func Lock() error {
return errors.New(`${i18n|operationNotSupported}`)
return errors.New(`${i18n|COMMON.OPERATION_NOT_SUPPORTED}`)
}
func Logoff() error {
return errors.New(`${i18n|operationNotSupported}`)
return errors.New(`${i18n|COMMON.OPERATION_NOT_SUPPORTED}`)
}
func Hibernate() error {

View File

@@ -11,19 +11,19 @@ func init() {
}
func Lock() error {
return errors.New(`${i18n|operationNotSupported}`)
return errors.New(`${i18n|COMMON.OPERATION_NOT_SUPPORTED}`)
}
func Logoff() error {
return errors.New(`${i18n|operationNotSupported}`)
return errors.New(`${i18n|COMMON.OPERATION_NOT_SUPPORTED}`)
}
func Hibernate() error {
return errors.New(`${i18n|operationNotSupported}`)
return errors.New(`${i18n|COMMON.OPERATION_NOT_SUPPORTED}`)
}
func Suspend() error {
return errors.New(`${i18n|operationNotSupported}`)
return errors.New(`${i18n|COMMON.OPERATION_NOT_SUPPORTED}`)
}
func Restart() error {

View File

@@ -293,7 +293,7 @@ func InitDesktop(pack modules.Packet) error {
return err
}
if val, ok := pack.GetData(`desktop`, reflect.String); !ok {
return errors.New(`${i18n|invalidParameter}`)
return errors.New(`${i18n|COMMON.INVALID_PARAMETER}`)
} else {
uuid = val.(string)
}
@@ -302,18 +302,22 @@ func InitDesktop(pack modules.Packet) error {
rawEvent: rawEvent,
lastPack: utils.Unix,
escape: false,
channel: make(chan message, 4),
channel: make(chan message, 3),
lock: &sync.Mutex{},
}
{
// set resolution of desktop
var rect image.Rectangle
if screenshot.NumActiveDisplays() == 0 {
common.WSConn.SendCallback(modules.Packet{Act: `quitDesktop`, Msg: `${i18n|noDisplayFound}`}, pack)
return errors.New(`${i18n|noDisplayFound}`)
rect = screenshot.GetDisplayBounds(0)
if rect.Dx() == 0 || rect.Dy() == 0 {
common.WSConn.SendCallback(modules.Packet{Act: `quitDesktop`, Msg: `${i18n|DESKTOP.NO_DISPLAY_FOUND}`}, pack)
return errors.New(`${i18n|DESKTOP.NO_DISPLAY_FOUND}`)
}
} else {
rect = screenshot.GetDisplayBounds(0)
}
buf := append([]byte{34, 22, 19, 17, 20, 02}, rawEvent...)
data := make([]byte, 4)
rect := screenshot.GetDisplayBounds(0)
binary.BigEndian.PutUint16(data[:2], uint16(rect.Dx()))
binary.BigEndian.PutUint16(data[2:], uint16(rect.Dy()))
buf = append(buf, data...)

View File

@@ -135,7 +135,7 @@ func getTempFile(dir, file string) (string, os.FileMode) {
func RemoveFiles(files []string) error {
for i := 0; i < len(files); i++ {
if files[i] == `\` || files[i] == `/` || len(files[i]) == 0 {
return errors.New(`${i18n|fileOrDirNotExist}`)
return errors.New(`${i18n|EXPLORER.FILE_OR_DIR_NOT_EXIST}`)
}
err := os.RemoveAll(files[i])
if err != nil {
@@ -192,7 +192,7 @@ func uploadSingle(path string, start, end int64, writer *io.PipeWriter, req *req
`FileSize`: strconv.FormatInt(size, 10),
})
if size < end {
return errors.New(`${i18n|invalidFileSize}`)
return errors.New(`${i18n|EXPLORER.UPLOAD_FAILED}`)
}
if end == 0 {
req.RawRequest.ContentLength = size - start
@@ -400,7 +400,7 @@ func UploadTextFile(path, bridge string) error {
size := stat.Size()
// Check if size larger than 2MB.
if size > 2<<20 {
return errors.New(`${i18n|fileTooLarge}`)
return errors.New(`${i18n|EXPLORER.FILE_TOO_LARGE}`)
}
uploadReq.SetHeaders(map[string]string{
`FileName`: stat.Name(),
@@ -415,7 +415,7 @@ func UploadTextFile(path, bridge string) error {
return err
}
if !utf8.Valid(buf) {
return errors.New(`${i18n|fileEncodingUnsupported}`)
return errors.New(`${i18n|EXPLORER.UNSUPPORTED_ENCODING}`)
}
url := config.GetBaseURL(false) + `/api/bridge/push`

View File

@@ -15,7 +15,7 @@ func GetScreenshot(bridge string) error {
writer := new(bytes.Buffer)
num := screenshot.NumActiveDisplays()
if num == 0 {
err := errors.New(`${i18n|noDisplayFound}`)
err := errors.New(`${i18n|DESKTOP.NO_DISPLAY_FOUND}`)
return err
}
img, err := screenshot.CaptureDisplay(0)

View File

@@ -5,5 +5,5 @@ package screenshot
import "errors"
func GetScreenshot(bridge string) error {
return errors.New(`${i18n|operationNotSupported}`)
return errors.New(`${i18n|COMMON.OPERATION_NOT_SUPPORTED}`)
}

View File

@@ -75,7 +75,7 @@ func InputTerminal(pack modules.Packet) error {
termUUID := val.(string)
val, ok = terminals.Get(termUUID)
if !ok {
common.WSConn.SendCallback(modules.Packet{Act: `quitTerminal`, Msg: `${i18n|terminalSessionClosed}`}, pack)
common.WSConn.SendCallback(modules.Packet{Act: `quitTerminal`, Msg: `${i18n|TERMINAL.SESSION_CLOSED}`}, pack)
return nil
}
terminal := val.(*terminal)
@@ -103,7 +103,7 @@ func ResizeTerminal(pack modules.Packet) error {
termUUID := val.(string)
val, ok = terminals.Get(termUUID)
if !ok {
common.WSConn.SendCallback(modules.Packet{Act: `quitTerminal`, Msg: `${i18n|terminalSessionClosed}`}, pack)
common.WSConn.SendCallback(modules.Packet{Act: `quitTerminal`, Msg: `${i18n|TERMINAL.SESSION_CLOSED}`}, pack)
return nil
}
terminal := val.(*terminal)
@@ -122,7 +122,7 @@ func KillTerminal(pack modules.Packet) error {
termUUID := val.(string)
val, ok = terminals.Get(termUUID)
if !ok {
common.WSConn.SendCallback(modules.Packet{Act: `quitTerminal`, Msg: `${i18n|terminalSessionClosed}`}, pack)
common.WSConn.SendCallback(modules.Packet{Act: `quitTerminal`, Msg: `${i18n|TERMINAL.SESSION_CLOSED}`}, pack)
return nil
}
terminal := val.(*terminal)

View File

@@ -106,7 +106,7 @@ func InputTerminal(pack modules.Packet) error {
termUUID := val.(string)
val, ok = terminals.Get(termUUID)
if !ok {
common.WSConn.SendCallback(modules.Packet{Act: `quitTerminal`, Msg: `${i18n|terminalSessionClosed}`}, pack)
common.WSConn.SendCallback(modules.Packet{Act: `quitTerminal`, Msg: `${i18n|TERMINAL.SESSION_CLOSED}`}, pack)
return nil
}
terminal := val.(*terminal)
@@ -127,7 +127,7 @@ func KillTerminal(pack modules.Packet) error {
termUUID := val.(string)
val, ok = terminals.Get(termUUID)
if !ok {
common.WSConn.SendCallback(modules.Packet{Act: `quitTerminal`, Msg: `${i18n|terminalSessionClosed}`}, pack)
common.WSConn.SendCallback(modules.Packet{Act: `quitTerminal`, Msg: `${i18n|TERMINAL.SESSION_CLOSED}`}, pack)
return nil
}
terminal := val.(*terminal)

View File

@@ -62,12 +62,12 @@ func CheckBridge(ctx *gin.Context) *Bridge {
}
if err := ctx.ShouldBind(&form); err != nil {
golog.Error(err)
ctx.AbortWithStatusJSON(http.StatusBadRequest, modules.Packet{Code: -1, Msg: `${i18n|invalidParameter}`})
ctx.AbortWithStatusJSON(http.StatusBadRequest, modules.Packet{Code: -1, Msg: `${i18n|COMMON.INVALID_PARAMETER}`})
return nil
}
val, ok := bridges.Get(form.Bridge)
if !ok {
ctx.AbortWithStatusJSON(http.StatusBadRequest, modules.Packet{Code: -1, Msg: `${i18n|invalidBridgeID}`})
ctx.AbortWithStatusJSON(http.StatusBadRequest, modules.Packet{Code: -1, Msg: `${i18n|COMMON.INVALID_BRIDGE_ID}`})
return nil
}
return val.(*Bridge)
@@ -81,7 +81,7 @@ func BridgePush(ctx *gin.Context) {
bridge.lock.Lock()
if bridge.using || (bridge.Src != nil && bridge.Dst != nil) {
bridge.lock.Unlock()
ctx.AbortWithStatusJSON(http.StatusBadRequest, modules.Packet{Code: 1, Msg: `${i18n|bridgeAlreadyInUse}`})
ctx.AbortWithStatusJSON(http.StatusBadRequest, modules.Packet{Code: 1, Msg: `${i18n|COMMON.BRIDGE_IN_USE}`})
return
}
bridge.Src = ctx
@@ -135,7 +135,7 @@ func BridgePull(ctx *gin.Context) {
bridge.lock.Lock()
if bridge.using || (bridge.Src != nil && bridge.Dst != nil) {
bridge.lock.Unlock()
ctx.AbortWithStatusJSON(http.StatusBadRequest, modules.Packet{Code: 1, Msg: `${i18n|bridgeAlreadyInUse}`})
ctx.AbortWithStatusJSON(http.StatusBadRequest, modules.Packet{Code: 1, Msg: `${i18n|COMMON.BRIDGE_IN_USE}`})
return
}
bridge.Dst = ctx

View File

@@ -77,11 +77,11 @@ func desktopEventWrapper(desktop *desktop) common.EventCallback {
}
if pack.Act == `initDesktop` {
if pack.Code != 0 {
msg := `${i18n|desktopSessionCreationFailed}`
msg := `${i18n|DESKTOP.CREATE_SESSION_FAILED}`
if len(pack.Msg) > 0 {
msg += `: ` + pack.Msg
} else {
msg += `${i18n|unknownError}`
msg += `${i18n|COMMON.UNKNOWN_ERROR}`
}
sendPack(modules.Packet{Act: `quit`, Msg: msg}, desktop.srcConn)
common.RemoveEvent(desktop.uuid)
@@ -97,7 +97,7 @@ func desktopEventWrapper(desktop *desktop) common.EventCallback {
return
}
if pack.Act == `quitDesktop` {
msg := `${i18n|desktopSessionClosed}`
msg := `${i18n|DESKTOP.SESSION_CLOSED}`
if len(pack.Msg) > 0 {
msg = pack.Msg
}
@@ -115,19 +115,19 @@ func desktopEventWrapper(desktop *desktop) common.EventCallback {
func onDesktopConnect(session *melody.Session) {
device, ok := session.Get(`Device`)
if !ok {
sendPack(modules.Packet{Act: `warn`, Msg: `${i18n|desktopSessionCreationFailed}`}, session)
sendPack(modules.Packet{Act: `warn`, Msg: `${i18n|DESKTOP.CREATE_SESSION_FAILED}`}, session)
session.Close()
return
}
connUUID, ok := common.CheckDevice(device.(string), ``)
if !ok {
sendPack(modules.Packet{Act: `warn`, Msg: `${i18n|deviceNotExists}`}, session)
sendPack(modules.Packet{Act: `warn`, Msg: `${i18n|COMMON.DEVICE_NOT_EXIST}`}, session)
session.Close()
return
}
deviceConn, ok := common.Melody.GetSessionByUUID(connUUID)
if !ok {
sendPack(modules.Packet{Act: `warn`, Msg: `${i18n|deviceNotExists}`}, session)
sendPack(modules.Packet{Act: `warn`, Msg: `${i18n|COMMON.DEVICE_NOT_EXIST}`}, session)
session.Close()
return
}
@@ -238,7 +238,7 @@ func CloseSessionsByDevice(deviceID string) {
return true
}
if desktop.device == deviceID {
sendPack(modules.Packet{Act: `quit`, Msg: `${i18n|desktopSessionClosed}`}, desktop.srcConn)
sendPack(modules.Packet{Act: `quit`, Msg: `${i18n|DESKTOP.SESSION_CLOSED}`}, desktop.srcConn)
queue = append(queue, session)
return false
}

View File

@@ -28,7 +28,7 @@ func RemoveDeviceFiles(ctx *gin.Context) {
return
}
if len(form.Files) == 0 {
ctx.AbortWithStatusJSON(http.StatusBadRequest, modules.Packet{Code: -1, Msg: `${i18n|invalidParameter}`})
ctx.AbortWithStatusJSON(http.StatusBadRequest, modules.Packet{Code: -1, Msg: `${i18n|COMMON.INVALID_PARAMETER}`})
return
}
trigger := utils.GetStrUUID()
@@ -50,7 +50,7 @@ func RemoveDeviceFiles(ctx *gin.Context) {
common.Warn(ctx, `REMOVE_FILES`, `fail`, `timeout`, map[string]any{
`files`: form.Files,
})
ctx.AbortWithStatusJSON(http.StatusGatewayTimeout, modules.Packet{Code: 1, Msg: `${i18n|responseTimeout}`})
ctx.AbortWithStatusJSON(http.StatusGatewayTimeout, modules.Packet{Code: 1, Msg: `${i18n|COMMON.RESPONSE_TIMEOUT}`})
}
}
@@ -73,7 +73,7 @@ func ListDeviceFiles(ctx *gin.Context) {
}
}, target, trigger, 5*time.Second)
if !ok {
ctx.AbortWithStatusJSON(http.StatusGatewayTimeout, modules.Packet{Code: 1, Msg: `${i18n|responseTimeout}`})
ctx.AbortWithStatusJSON(http.StatusGatewayTimeout, modules.Packet{Code: 1, Msg: `${i18n|COMMON.RESPONSE_TIMEOUT}`})
}
}
@@ -89,7 +89,7 @@ func GetDeviceFiles(ctx *gin.Context) {
return
}
if len(form.Files) == 0 {
ctx.AbortWithStatusJSON(http.StatusBadRequest, modules.Packet{Code: -1, Msg: `${i18n|invalidParameter}`})
ctx.AbortWithStatusJSON(http.StatusBadRequest, modules.Packet{Code: -1, Msg: `${i18n|COMMON.INVALID_PARAMETER}`})
return
}
bridgeID := utils.GetStrUUID()
@@ -209,7 +209,7 @@ func GetDeviceFiles(ctx *gin.Context) {
common.Warn(ctx, `READ_FILES`, `fail`, `timeout`, map[string]any{
`files`: form.Files,
})
ctx.AbortWithStatusJSON(http.StatusGatewayTimeout, modules.Packet{Code: 1, Msg: `${i18n|responseTimeout}`})
ctx.AbortWithStatusJSON(http.StatusGatewayTimeout, modules.Packet{Code: 1, Msg: `${i18n|COMMON.RESPONSE_TIMEOUT}`})
} else {
<-wait
}
@@ -228,7 +228,7 @@ func GetDeviceTextFile(ctx *gin.Context) {
return
}
if len(form.File) == 0 {
ctx.AbortWithStatusJSON(http.StatusBadRequest, modules.Packet{Code: -1, Msg: `${i18n|invalidParameter}`})
ctx.AbortWithStatusJSON(http.StatusBadRequest, modules.Packet{Code: -1, Msg: `${i18n|COMMON.INVALID_PARAMETER}`})
return
}
bridgeID := utils.GetStrUUID()
@@ -286,7 +286,7 @@ func GetDeviceTextFile(ctx *gin.Context) {
common.Warn(ctx, `READ_TEXT_FILE`, `fail`, `timeout`, map[string]any{
`file`: form.File,
})
ctx.AbortWithStatusJSON(http.StatusGatewayTimeout, modules.Packet{Code: 1, Msg: `${i18n|responseTimeout}`})
ctx.AbortWithStatusJSON(http.StatusGatewayTimeout, modules.Packet{Code: 1, Msg: `${i18n|COMMON.RESPONSE_TIMEOUT}`})
} else {
<-wait
}
@@ -306,7 +306,7 @@ func UploadToDevice(ctx *gin.Context) {
return
}
if len(form.File) == 0 || len(form.Path) == 0 {
ctx.AbortWithStatusJSON(http.StatusBadRequest, modules.Packet{Code: -1, Msg: `${i18n|invalidParameter}`})
ctx.AbortWithStatusJSON(http.StatusBadRequest, modules.Packet{Code: -1, Msg: `${i18n|COMMON.INVALID_PARAMETER}`})
return
}
bridgeID := utils.GetStrUUID()
@@ -369,7 +369,7 @@ func UploadToDevice(ctx *gin.Context) {
`dest`: fileDest,
`size`: fileSize,
})
ctx.AbortWithStatusJSON(http.StatusGatewayTimeout, modules.Packet{Code: 1, Msg: `${i18n|responseTimeout}`})
ctx.AbortWithStatusJSON(http.StatusGatewayTimeout, modules.Packet{Code: 1, Msg: `${i18n|COMMON.RESPONSE_TIMEOUT}`})
}
} else {
<-wait

View File

@@ -40,12 +40,12 @@ func CheckClient(ctx *gin.Context) {
Secure string `json:"secure" yaml:"secure" form:"secure"`
}
if err := ctx.ShouldBind(&form); err != nil {
ctx.AbortWithStatusJSON(http.StatusBadRequest, modules.Packet{Code: -1, Msg: `${i18n|invalidParameter}`})
ctx.AbortWithStatusJSON(http.StatusBadRequest, modules.Packet{Code: -1, Msg: `${i18n|COMMON.INVALID_PARAMETER}`})
return
}
_, err := os.Stat(fmt.Sprintf(config.BuiltPath, form.OS, form.Arch))
if err != nil {
ctx.AbortWithStatusJSON(http.StatusNotFound, modules.Packet{Code: 1, Msg: `${i18n|osOrArchNotPrebuilt}`})
ctx.AbortWithStatusJSON(http.StatusNotFound, modules.Packet{Code: 1, Msg: `${i18n|GENERATOR.NO_PREBUILT_FOUND}`})
return
}
_, err = genConfig(clientCfg{
@@ -58,10 +58,10 @@ func CheckClient(ctx *gin.Context) {
})
if err != nil {
if err == ErrTooLargeEntity {
ctx.AbortWithStatusJSON(http.StatusRequestEntityTooLarge, modules.Packet{Code: 1, Msg: `${i18n|tooLargeConfig}`})
ctx.AbortWithStatusJSON(http.StatusRequestEntityTooLarge, modules.Packet{Code: 1, Msg: `${i18n|GENERATOR.CONFIG_TOO_LARGE}`})
return
}
ctx.AbortWithStatusJSON(http.StatusInternalServerError, modules.Packet{Code: 1, Msg: `${i18n|configGenerateFailed}`})
ctx.AbortWithStatusJSON(http.StatusInternalServerError, modules.Packet{Code: 1, Msg: `${i18n|GENERATOR.CONFIG_GENERATE_FAILED}`})
return
}
ctx.JSON(http.StatusOK, modules.Packet{Code: 0})
@@ -77,18 +77,18 @@ func GenerateClient(ctx *gin.Context) {
Secure string `json:"secure" yaml:"secure" form:"secure"`
}
if err := ctx.ShouldBind(&form); err != nil {
ctx.AbortWithStatusJSON(http.StatusBadRequest, modules.Packet{Code: -1, Msg: `${i18n|invalidParameter}`})
ctx.AbortWithStatusJSON(http.StatusBadRequest, modules.Packet{Code: -1, Msg: `${i18n|COMMON.INVALID_PARAMETER}`})
return
}
tpl, err := os.Open(fmt.Sprintf(config.BuiltPath, form.OS, form.Arch))
if err != nil {
ctx.AbortWithStatusJSON(http.StatusNotFound, modules.Packet{Code: 1, Msg: `${i18n|osOrArchNotPrebuilt}`})
ctx.AbortWithStatusJSON(http.StatusNotFound, modules.Packet{Code: 1, Msg: `${i18n|GENERATOR.NO_PREBUILT_FOUND}`})
return
}
clientUUID := utils.GetUUID()
clientKey, err := common.EncAES(clientUUID, config.Config.SaltBytes)
if err != nil {
ctx.AbortWithStatusJSON(http.StatusInternalServerError, modules.Packet{Code: 1, Msg: `${i18n|configGenerateFailed}`})
ctx.AbortWithStatusJSON(http.StatusInternalServerError, modules.Packet{Code: 1, Msg: `${i18n|GENERATOR.CONFIG_GENERATE_FAILED}`})
return
}
cfgBytes, err := genConfig(clientCfg{
@@ -101,10 +101,10 @@ func GenerateClient(ctx *gin.Context) {
})
if err != nil {
if err == ErrTooLargeEntity {
ctx.AbortWithStatusJSON(http.StatusRequestEntityTooLarge, modules.Packet{Code: 1, Msg: `${i18n|tooLargeConfig}`})
ctx.AbortWithStatusJSON(http.StatusRequestEntityTooLarge, modules.Packet{Code: 1, Msg: `${i18n|GENERATOR.CONFIG_TOO_LARGE}`})
return
}
ctx.AbortWithStatusJSON(http.StatusInternalServerError, modules.Packet{Code: 1, Msg: `${i18n|configGenerateFailed}`})
ctx.AbortWithStatusJSON(http.StatusInternalServerError, modules.Packet{Code: 1, Msg: `${i18n|GENERATOR.CONFIG_GENERATE_FAILED}`})
return
}
ctx.Header(`Accept-Ranges`, `none`)

View File

@@ -27,7 +27,7 @@ func ListDeviceProcesses(ctx *gin.Context) {
}
}, connUUID, trigger, 5*time.Second)
if !ok {
ctx.AbortWithStatusJSON(http.StatusGatewayTimeout, modules.Packet{Code: 1, Msg: `${i18n|responseTimeout}`})
ctx.AbortWithStatusJSON(http.StatusGatewayTimeout, modules.Packet{Code: 1, Msg: `${i18n|COMMON.RESPONSE_TIMEOUT}`})
}
}
@@ -57,7 +57,7 @@ func KillDeviceProcess(ctx *gin.Context) {
}
}, target, trigger, 5*time.Second)
if !ok {
ctx.AbortWithStatusJSON(http.StatusGatewayTimeout, modules.Packet{Code: 1, Msg: `${i18n|responseTimeout}`})
ctx.AbortWithStatusJSON(http.StatusGatewayTimeout, modules.Packet{Code: 1, Msg: `${i18n|COMMON.RESPONSE_TIMEOUT}`})
common.Warn(ctx, `KILL_PROCESS`, `fail`, `timeout`, map[string]any{
`pid`: form.Pid,
})

View File

@@ -49,7 +49,7 @@ func GetScreenshot(ctx *gin.Context) {
if !called {
bridge.RemoveBridge(bridgeID)
common.RemoveEvent(trigger)
ctx.AbortWithStatusJSON(http.StatusGatewayTimeout, modules.Packet{Code: 1, Msg: `${i18n|responseTimeout}`})
ctx.AbortWithStatusJSON(http.StatusGatewayTimeout, modules.Packet{Code: 1, Msg: `${i18n|COMMON.RESPONSE_TIMEOUT}`})
common.Warn(ctx, `TAKE_SCREENSHOT`, `fail`, `timeout`, nil)
} else {
<-wait

View File

@@ -68,11 +68,11 @@ func terminalEventWrapper(terminal *terminal) common.EventCallback {
return func(pack modules.Packet, device *melody.Session) {
if pack.Act == `initTerminal` {
if pack.Code != 0 {
msg := `${i18n|terminalSessionCreationFailed}`
msg := `${i18n|TERMINAL.CREATE_SESSION_FAILED}`
if len(pack.Msg) > 0 {
msg += `: ` + pack.Msg
} else {
msg += `${i18n|unknownError}`
msg += `${i18n|COMMON.UNKNOWN_ERROR}`
}
sendPack(modules.Packet{Act: `warn`, Msg: msg}, terminal.session)
common.RemoveEvent(terminal.uuid)
@@ -88,7 +88,7 @@ func terminalEventWrapper(terminal *terminal) common.EventCallback {
return
}
if pack.Act == `quitTerminal` {
msg := `${i18n|terminalSessionClosed}`
msg := `${i18n|TERMINAL.SESSION_CLOSED}`
if len(pack.Msg) > 0 {
msg = pack.Msg
}
@@ -116,19 +116,19 @@ func terminalEventWrapper(terminal *terminal) common.EventCallback {
func onTerminalConnect(session *melody.Session) {
device, ok := session.Get(`Device`)
if !ok {
sendPack(modules.Packet{Act: `warn`, Msg: `${i18n|terminalSessionCreationFailed}`}, session)
sendPack(modules.Packet{Act: `warn`, Msg: `${i18n|TERMINAL.CREATE_SESSION_FAILED}`}, session)
session.Close()
return
}
connUUID, ok := common.CheckDevice(device.(string), ``)
if !ok {
sendPack(modules.Packet{Act: `warn`, Msg: `${i18n|deviceNotExists}`}, session)
sendPack(modules.Packet{Act: `warn`, Msg: `${i18n|COMMON.DEVICE_NOT_EXIST}`}, session)
session.Close()
return
}
deviceConn, ok := common.Melody.GetSessionByUUID(connUUID)
if !ok {
sendPack(modules.Packet{Act: `warn`, Msg: `${i18n|deviceNotExists}`}, session)
sendPack(modules.Packet{Act: `warn`, Msg: `${i18n|COMMON.DEVICE_NOT_EXIST}`}, session)
session.Close()
return
}

View File

@@ -29,16 +29,16 @@ func CheckForm(ctx *gin.Context, form any) (string, bool) {
Device string `json:"device" yaml:"device" form:"device"`
}
if form != nil && ctx.ShouldBind(form) != nil {
ctx.AbortWithStatusJSON(http.StatusBadRequest, modules.Packet{Code: -1, Msg: `${i18n|invalidParameter}`})
ctx.AbortWithStatusJSON(http.StatusBadRequest, modules.Packet{Code: -1, Msg: `${i18n|COMMON.INVALID_PARAMETER}`})
return ``, false
}
if ctx.ShouldBind(&base) != nil || (len(base.Conn) == 0 && len(base.Device) == 0) {
ctx.AbortWithStatusJSON(http.StatusBadRequest, modules.Packet{Code: -1, Msg: `${i18n|invalidParameter}`})
ctx.AbortWithStatusJSON(http.StatusBadRequest, modules.Packet{Code: -1, Msg: `${i18n|COMMON.INVALID_PARAMETER}`})
return ``, false
}
connUUID, ok := common.CheckDevice(base.Device, base.Conn)
if !ok {
ctx.AbortWithStatusJSON(http.StatusBadGateway, modules.Packet{Code: 1, Msg: `${i18n|deviceNotExists}`})
ctx.AbortWithStatusJSON(http.StatusBadGateway, modules.Packet{Code: 1, Msg: `${i18n|COMMON.DEVICE_NOT_EXIST}`})
return ``, false
}
ctx.Request = ctx.Request.WithContext(context.WithValue(ctx.Request.Context(), `ConnUUID`, connUUID))
@@ -119,7 +119,7 @@ func CheckUpdate(ctx *gin.Context) {
Commit string `form:"commit" binding:"required"`
}
if err := ctx.ShouldBind(&form); err != nil {
ctx.AbortWithStatusJSON(http.StatusBadRequest, modules.Packet{Code: -1, Msg: `${i18n|invalidParameter}`})
ctx.AbortWithStatusJSON(http.StatusBadRequest, modules.Packet{Code: -1, Msg: `${i18n|COMMON.INVALID_PARAMETER}`})
return
}
if form.Commit == config.COMMIT {
@@ -136,7 +136,7 @@ func CheckUpdate(ctx *gin.Context) {
}
tpl, err := os.Open(fmt.Sprintf(config.BuiltPath, form.OS, form.Arch))
if err != nil {
ctx.AbortWithStatusJSON(http.StatusNotFound, modules.Packet{Code: 1, Msg: `${i18n|osOrArchNotPrebuilt}`})
ctx.AbortWithStatusJSON(http.StatusNotFound, modules.Packet{Code: 1, Msg: `${i18n|GENERATOR.NO_PREBUILT_FOUND}`})
common.Warn(ctx, `CLIENT_UPDATE`, `fail`, `no prebuild asset`, map[string]any{
`client`: map[string]any{
`os`: form.OS,
@@ -238,7 +238,7 @@ func ExecDeviceCmd(ctx *gin.Context) {
return
}
if len(form.Cmd) == 0 {
ctx.AbortWithStatusJSON(http.StatusBadRequest, modules.Packet{Code: -1, Msg: `${i18n|invalidParameter}`})
ctx.AbortWithStatusJSON(http.StatusBadRequest, modules.Packet{Code: -1, Msg: `${i18n|COMMON.INVALID_PARAMETER}`})
return
}
trigger := utils.GetStrUUID()
@@ -263,7 +263,7 @@ func ExecDeviceCmd(ctx *gin.Context) {
`cmd`: form.Cmd,
`args`: form.Args,
})
ctx.AbortWithStatusJSON(http.StatusGatewayTimeout, modules.Packet{Code: 1, Msg: `${i18n|responseTimeout}`})
ctx.AbortWithStatusJSON(http.StatusGatewayTimeout, modules.Packet{Code: 1, Msg: `${i18n|COMMON.RESPONSE_TIMEOUT}`})
}
}
@@ -282,7 +282,7 @@ func GetDevices(ctx *gin.Context) {
func CallDevice(ctx *gin.Context) {
act := ctx.Param(`act`)
if len(act) == 0 {
ctx.AbortWithStatusJSON(http.StatusBadRequest, modules.Packet{Code: -1, Msg: `${i18n|invalidParameter}`})
ctx.AbortWithStatusJSON(http.StatusBadRequest, modules.Packet{Code: -1, Msg: `${i18n|COMMON.INVALID_PARAMETER}`})
return
}
{
@@ -298,7 +298,7 @@ func CallDevice(ctx *gin.Context) {
common.Warn(ctx, `CALL_DEVICE`, `fail`, `invalid act`, map[string]any{
`act`: act,
})
ctx.AbortWithStatusJSON(http.StatusBadRequest, modules.Packet{Code: -1, Msg: `${i18n|invalidParameter}`})
ctx.AbortWithStatusJSON(http.StatusBadRequest, modules.Packet{Code: -1, Msg: `${i18n|COMMON.INVALID_PARAMETER}`})
return
}
}

View File

@@ -15,7 +15,7 @@ let ticker = 0;
let frames = 0;
let bytes = 0;
let ticks = 0;
let title = i18n.t('desktop');
let title = i18n.t('DESKTOP.TITLE');
function ScreenModal(props) {
const [bandwidth, setBandwidth] = useState(0);
const [fps, setFps] = useState(0);
@@ -58,16 +58,16 @@ function ScreenModal(props) {
ws.onclose = () => {
if (conn) {
conn = false;
message.warn(i18n.t('disconnected'));
message.warn(i18n.t('COMMON.DISCONNECTED'));
}
};
ws.onerror = (e) => {
console.error(e);
if (conn) {
conn = false;
message.warn(i18n.t('disconnected'));
message.warn(i18n.t('COMMON.DISCONNECTED'));
} else {
message.warn(i18n.t('connectFailed'));
message.warn(i18n.t('COMMON.CONNECTION_FAILED'));
}
};
clearInterval(ticker);
@@ -124,8 +124,14 @@ function ScreenModal(props) {
return;
}
if (op === 2) {
canvas.width = dv.getUint16(1, false);
canvas.height = dv.getUint16(3, false);
let width = dv.getUint16(1, false);
let height = dv.getUint16(3, false);
if (width === 0 || height === 0) {
message.warn(i18n.t('DESKTOP.NO_DISPLAY_FOUND'));
return;
}
canvas.width = width;
canvas.height = height;
return;
}
if (op === 0) frames++;
@@ -160,11 +166,11 @@ function ScreenModal(props) {
data = JSON.parse(data);
} catch (_) {}
if (data?.act === 'warn') {
message.warn(data.msg ? translate(data.msg) : i18n.t('unknownError'));
message.warn(data.msg ? translate(data.msg) : i18n.t('COMMON.UNKNOWN_ERROR'));
return;
}
if (data?.act === 'quit') {
message.warn(data.msg ? translate(data.msg) : i18n.t('unknownError'));
message.warn(data.msg ? translate(data.msg) : i18n.t('COMMON.UNKNOWN_ERROR'));
conn = false;
ws.close();
}

View File

@@ -52,14 +52,14 @@ function FileBrowser(props) {
const columns = [
{
key: 'Name',
title: i18n.t('fileName'),
title: i18n.t('EXPLORER.FILE_NAME'),
dataIndex: 'name',
ellipsis: true,
width: 180
},
{
key: 'Size',
title: i18n.t('fileSize'),
title: i18n.t('EXPLORER.FILE_SIZE'),
dataIndex: 'size',
ellipsis: true,
width: 60,
@@ -68,11 +68,11 @@ function FileBrowser(props) {
},
{
key: 'Time',
title: i18n.t('modifyTime'),
title: i18n.t('EXPLORER.MODIFY_TIME'),
dataIndex: 'time',
ellipsis: true,
width: 100,
renderText: (ts, file) => file.type === 0 ? dayjs.unix(ts).format(i18n.t('dateTimeFormat')) : '-'
renderText: (ts, file) => file.type === 0 ? dayjs.unix(ts).format(i18n.t('EXPLORER.DATE_TIME_FORMAT')) : '-'
},
{
key: 'Option',
@@ -99,16 +99,16 @@ function FileBrowser(props) {
}, []);
const alertOptionRenderer = () => (<Space size={16}>
<Popconfirm
title={i18n.t('downloadMultiConfirm')}
title={i18n.t('EXPLORER.DOWNLOAD_MULTI_CONFIRM')}
onConfirm={() => downloadFiles(selectedRowKeys)}
>
<a>{i18n.t('download')}</a>
<a>{i18n.t('EXPLORER.DOWNLOAD')}</a>
</Popconfirm>
<Popconfirm
title={i18n.t('deleteMultiConfirm')}
title={i18n.t('EXPLORER.DELETE_MULTI_CONFIRM')}
onConfirm={() => removeFiles(selectedRowKeys)}
>
<a>{i18n.t('delete')}</a>
<a>{i18n.t('EXPLORER.DELETE')}</a>
</Popconfirm>
</Space>);
useEffect(() => {
@@ -124,8 +124,8 @@ function FileBrowser(props) {
function renderOperation(file) {
let menus = [
{key: 'delete', name: i18n.t('delete')},
{key: 'editAsText', name: i18n.t('editAsText')},
{key: 'delete', name: i18n.t('EXPLORER.DELETE')},
{key: 'editAsText', name: i18n.t('EXPLORER.EDIT_AS_TEXT')},
];
if (file.type === 1) {
menus.pop();
@@ -140,7 +140,7 @@ function FileBrowser(props) {
key='download'
onClick={() => downloadFiles(file.name)}
>
{i18n.t('download')}
{i18n.t('EXPLORER.DOWNLOAD')}
</a>,
<TableDropdown
key='more'
@@ -152,11 +152,11 @@ function FileBrowser(props) {
function onDropdownSelect(key, file) {
switch (key) {
case 'delete':
let content = i18n.t('deleteConfirm');
let content = i18n.t('EXPLORER.DELETE_CONFIRM');
if (file.type === 0) {
content = content.replace('{0}', i18n.t('file'));
content = content.replace('{0}', i18n.t('EXPLORER.FILE'));
} else {
content = content.replace('{0}', i18n.t('folder'));
content = content.replace('{0}', i18n.t('EXPLORER.FOLDER'));
}
Modal.confirm({
icon: <QuestionCircleOutlined />,
@@ -220,7 +220,7 @@ function FileBrowser(props) {
function textEdit(file) {
// Only edit text file smaller than 2MB.
if (file.size > 2 << 20) {
message.warn(i18n.t('fileTooLarge'));
message.warn(i18n.t('EXPLORER.FILE_TOO_LARGE'));
return;
}
if (editingFile) return;
@@ -265,7 +265,7 @@ function FileBrowser(props) {
function uploadFile() {
if (path === '/' || path === '\\' || path.length === 0) {
if (props.isWindows) {
message.error(i18n.t('uploadInvalidPath'));
message.error(i18n.t('EXPLORER.UPLOAD_INVALID_PATH'));
return;
}
}
@@ -286,8 +286,8 @@ function FileBrowser(props) {
if (exists) {
Modal.confirm({
autoFocusButton: 'cancel',
content: i18n.t('fileOverwriteConfirm').replace('{0}', file.name),
okText: i18n.t('fileOverwrite'),
content: i18n.t('EXPLORER.OVERWRITE_CONFIRM').replace('{0}', file.name),
okText: i18n.t('EXPLORER.OVERWRITE'),
onOk: () => {
setUploading(file);
},
@@ -317,7 +317,7 @@ function FileBrowser(props) {
// It may take an extremely long time to archive volumes.
// So we don't allow to download volumes.
// Besides, archive volumes may throw an error.
message.error(i18n.t('downloadInvalidPath'));
message.error(i18n.t('EXPLORER.DOWNLOAD_VOLUMES_ERROR'));
return;
}
}
@@ -338,7 +338,7 @@ function FileBrowser(props) {
function removeFiles(items) {
if (path === '/' || path === '\\' || path.length === 0) {
if (props.isWindows) {
message.error(i18n.t('deleteInvalidPath'));
message.error(i18n.t('EXPLORER.DELETE_INVALID_PATH'));
return;
}
}
@@ -359,7 +359,7 @@ function FileBrowser(props) {
}).then(res => {
let data = res.data;
if (data.code === 0) {
message.success(i18n.t('deleteSuccess'));
message.success(i18n.t('EXPLORER.DELETE_SUCCESS'));
tableRef.current.reload();
}
});
@@ -413,7 +413,7 @@ function FileBrowser(props) {
draggable={draggable}
maskClosable={false}
destroyOnClose={true}
modalTitle={i18n.t('fileExplorer')}
modalTitle={i18n.t('EXPLORER.TITLE')}
footer={null}
width={830}
bodyStyle={{
@@ -442,7 +442,7 @@ function FileBrowser(props) {
alwaysShowAlert: true
}}
tableAlertRender={() =>
i18n.t('fileMultiSelectAlert').
i18n.t('EXPLORER.MULTI_SELECT_LABEL').
replace('{0}', String(selectedRowKeys.length)).
replace('{1}', String(fileList.length))
}
@@ -591,8 +591,8 @@ function TextEditor(props) {
const editorRef = useRef();
const fontMenu = (
<Menu onClick={onFontMenuClick}>
<Menu.Item key='enlarge'>{i18n.t('enlarge')}</Menu.Item>
<Menu.Item key='shrink'>{i18n.t('shrink')}</Menu.Item>
<Menu.Item key='enlarge'>{i18n.t('EXPLORER.ENLARGE')}</Menu.Item>
<Menu.Item key='shrink'>{i18n.t('EXPLORER.SHRINK')}</Menu.Item>
</Menu>
);
const editorThemes = {
@@ -643,7 +643,7 @@ function TextEditor(props) {
editorRef.current.editor.setFontSize(currentFontSize + 1);
} else if (e.key === 'shrink') {
if (currentFontSize <= 14) {
message.warn(i18n.t('minFontSize'));
message.warn(i18n.t('EXPLORER.REACHED_MIN_FONT_SIZE'));
return;
}
currentFontSize--;
@@ -703,11 +703,11 @@ function TextEditor(props) {
if (data.code === 0) {
fileStatus = 2;
window.onbeforeunload = null;
message.success(i18n.t('fileSaveSuccess'));
message.success(i18n.t('EXPLORER.FILE_SAVE_SUCCESSFULLY'));
if (typeof onSave === 'function') onSave();
}
}).catch(err => {
message.error(i18n.t('fileSaveFailed') + i18n.t('colon') + err.message);
message.error(i18n.t('EXPLORER.FILE_SAVE_FAILED') + i18n.t('COMMON.COLON') + err.message);
}).finally(() => {
setLoading(false);
});
@@ -731,19 +731,19 @@ function TextEditor(props) {
message={
<Space size={16}>
<a onClick={onConfirm}>
{i18n.t('save')}
{i18n.t('EXPLORER.SAVE')}
</a>
<a onClick={()=>editorRef.current.editor.execCommand('find')}>
{i18n.t('search')}
{i18n.t('EXPLORER.SEARCH')}
</a>
<a onClick={()=>editorRef.current.editor.execCommand('replace')}>
{i18n.t('replace')}
{i18n.t('EXPLORER.REPLACE')}
</a>
<Dropdown overlay={fontMenu}>
<a>{i18n.t('font')}</a>
<a>{i18n.t('EXPLORER.FONT')}</a>
</Dropdown>
<Dropdown overlay={themeMenu}>
<a>{i18n.t('theme')}</a>
<a>{i18n.t('EXPLORER.THEME')}</a>
</Dropdown>
</Space>
}
@@ -795,25 +795,25 @@ function TextEditor(props) {
key='cancel'
onClick={onExitCancel}
>
{i18n.t('cancel')}
{i18n.t('EXPLORER.CANCEL')}
</Button>,
<Button
type='danger'
key='doNotSave'
onClick={onForceCancel.bind(null, false)}
>
{i18n.t('fileDoNotSave')}
{i18n.t('EXPLORER.FILE_DO_NOT_SAVE')}
</Button>,
<Button
type='primary'
key='save'
onClick={onConfirm.bind(null, onForceCancel.bind(null, true))}
>
{i18n.t('save')}
{i18n.t('EXPLORER.SAVE')}
</Button>
]}
>
{i18n.t('fileNotSaveConfirm')}
{i18n.t('EXPLORER.NOT_SAVED_CONFIRM')}
</Modal>
</Modal>
);
@@ -887,7 +887,7 @@ function FileUploader(props) {
if (data.code === 0) {
uploadStatus = 2;
setStatus(2);
message.success(i18n.t('uploadSuccess'));
message.success(i18n.t('EXPLORER.UPLOAD_SUCCESS'));
} else {
uploadStatus = 3;
setStatus(3);
@@ -896,11 +896,11 @@ function FileUploader(props) {
if (axios.isCancel(err)) {
uploadStatus = 4;
setStatus(4);
message.error(i18n.t('uploadAborted'));
message.error(i18n.t('EXPLORER.UPLOAD_ABORTED'));
} else {
uploadStatus = 3;
setStatus(3);
message.error(i18n.t('uploadFailed') + i18n.t('colon') + err.message);
message.error(i18n.t('EXPLORER.UPLOAD_FAILED') + i18n.t('COMMON.COLON') + err.message);
}
}).finally(() => {
abortController = null;
@@ -924,7 +924,7 @@ function FileUploader(props) {
if (status === 1) {
Modal.confirm({
autoFocusButton: 'cancel',
content: i18n.t('uploadCancelConfirm'),
content: i18n.t('EXPLORER.UPLOAD_CANCEL_CONFIRM'),
onOk: () => {
abortController.abort();
},
@@ -945,13 +945,13 @@ function FileUploader(props) {
case 1:
return percent + '%';
case 2:
return i18n.t('uploadSuccess');
return i18n.t('EXPLORER.UPLOAD_SUCCESS');
case 3:
return i18n.t('uploadFailed');
return i18n.t('EXPLORER.UPLOAD_FAILED');
case 4:
return i18n.t('uploadAborted');
return i18n.t('EXPLORER.UPLOAD_ABORTED');
default:
return i18n.t('upload');
return i18n.t('EXPLORER.UPLOAD');
}
}

View File

@@ -52,7 +52,7 @@ function Generate(props) {
<ProFormText
width="md"
name="host"
label={i18n.t('host')}
label={i18n.t('GENERATOR.HOST')}
rules={[{
required: true
}]}
@@ -60,7 +60,7 @@ function Generate(props) {
<ProFormDigit
width="md"
name="port"
label={i18n.t('port')}
label={i18n.t('GENERATOR.PORT')}
min={1}
max={65535}
rules={[{
@@ -72,7 +72,7 @@ function Generate(props) {
<ProFormText
width="md"
name="path"
label={i18n.t('path')}
label={i18n.t('GENERATOR.PATH')}
rules={[{
required: true
}]}
@@ -80,7 +80,7 @@ function Generate(props) {
<ProFormCascader
width="md"
name="ArchOS"
label={i18n.t('osArch')}
label={i18n.t('GENERATOR.OS_ARCH')}
request={() => prebuilt}
rules={[{
required: true

View File

@@ -12,7 +12,7 @@ function ProcessMgr(props) {
const columns = [
{
key: 'Name',
title: i18n.t('procName'),
title: i18n.t('PROCMGR.PROCESS'),
dataIndex: 'name',
ellipsis: true,
width: 120
@@ -56,10 +56,10 @@ function ProcessMgr(props) {
return [
<Popconfirm
key='kill'
title={i18n.t('confirmKillProc')}
title={i18n.t('PROCMGR.KILL_PROCESS_CONFIRM')}
onConfirm={killProcess.bind(null, proc.pid)}
>
<a>{i18n.t('killProc')}</a>
<a>{i18n.t('PROCMGR.KILL_PROCESS')}</a>
</Popconfirm>
];
}
@@ -68,7 +68,7 @@ function ProcessMgr(props) {
request(`/api/device/process/kill`, {pid: pid, device: props.device}).then(res => {
let data = res.data;
if (data.code === 0) {
message.success(i18n.t('killProcSuccess'));
message.success(i18n.t('PROCMGR.KILL_PROCESS_SUCCESSFULLY'));
tableRef.current.reload();
}
});
@@ -95,7 +95,7 @@ function ProcessMgr(props) {
draggable={true}
maskClosable={false}
destroyOnClose={true}
modalTitle={i18n.t('processManager')}
modalTitle={i18n.t('PROCMGR.TITLE')}
footer={null}
width={400}
bodyStyle={{

View File

@@ -10,7 +10,7 @@ function Runner(props) {
let basePath = location.origin + location.pathname + 'api/device/';
request(basePath + 'exec', form).then(res => {
if (res.data.code === 0) {
message.success(i18n.t('executionSuccess'));
message.success(i18n.t('RUNNER.EXECUTION_SUCCESS'));
}
});
}
@@ -21,7 +21,7 @@ function Runner(props) {
destroyOnClose: true,
maskClosable: false,
}}
title={i18n.t('run')}
title={i18n.t('RUNNER.TITLE')}
width={380}
onFinish={onFinish}
onVisibleChange={visible => {
@@ -35,7 +35,7 @@ function Runner(props) {
<ProFormText
width="md"
name="cmd"
label={i18n.t('cmdPlaceholder')}
label={i18n.t('RUNNER.CMD_PLACEHOLDER')}
rules={[{
required: true
}]}
@@ -43,7 +43,7 @@ function Runner(props) {
<ProFormText
width="md"
name="args"
label={i18n.t('argsPlaceholder')}
label={i18n.t('RUNNER.ARGS_PLACEHOLDER')}
/>
</ModalForm>
)

View File

@@ -77,14 +77,14 @@ class TerminalModal extends React.Component {
return;
}
if (data?.act === 'warn') {
message.warn(data.msg ? translate(data.msg) : i18n.t('unknownError'));
message.warn(data.msg ? translate(data.msg) : i18n.t('COMMON.UNKNOWN_ERROR'));
}
}
}
this.ws.onclose = (e) => {
if (this.conn) {
this.conn = false;
this.term.write(`\n${i18n.t('disconnected')}\n`);
this.term.write(`\n${i18n.t('COMMON.DISCONNECTED')}\n`);
this.secret = CryptoJS.enc.Hex.parse(genRandHex(32));
}
}
@@ -92,10 +92,10 @@ class TerminalModal extends React.Component {
console.error(e);
if (this.conn) {
this.conn = false;
this.term.write(`\n${i18n.t('disconnected')}\n`);
this.term.write(`\n${i18n.t('COMMON.DISCONNECTED')}\n`);
this.secret = CryptoJS.enc.Hex.parse(genRandHex(32));
} else {
this.term.write(`\n${i18n.t('connectFailed')}\n`);
this.term.write(`\n${i18n.t('COMMON.CONNECTION_FAILED')}\n`);
}
}
return termEv;
@@ -117,7 +117,7 @@ class TerminalModal extends React.Component {
return function (e) {
if (!this.conn) {
if (e === '\r' || e === '\n' || e === ' ') {
this.term.write(`\n${i18n.t('reconnecting')}\n`);
this.term.write(`\n${i18n.t('COMMON.RECONNECTING')}\n`);
this.termEv = this.initialize(this.termEv);
}
return;
@@ -219,7 +219,7 @@ class TerminalModal extends React.Component {
return function (e) {
if (!this.conn) {
if (e === '\r' || e === ' ') {
this.term.write(`\n${i18n.t('reconnecting')}\n`);
this.term.write(`\n${i18n.t('COMMON.RECONNECTING')}\n`);
this.termEv = this.initialize(this.termEv);
}
return;
@@ -334,7 +334,7 @@ class TerminalModal extends React.Component {
<DraggableModal
draggable={true}
maskClosable={false}
modalTitle={i18n.t('terminal')}
modalTitle={i18n.t('TERMINAL.TITLE')}
visible={this.props.visible}
onCancel={this.props.onCancel}
destroyOnClose={false}

View File

@@ -29,7 +29,7 @@ axios.interceptors.response.use(async res => {
}, err => {
// console.error(err);
if (err.code === 'ECONNABORTED') {
message.error(i18n.t('requestTimeout'));
message.error(i18n.t('COMMON.REQUEST_TIMEOUT'));
return Promise.reject(err);
}
let res = err.response;

View File

@@ -1,125 +1,125 @@
{
"requestTimeout": "Request timeout",
"pageNotFound": "Page Not Found",
"unknownError": "Unknown error",
"invalidParameter": "Invalid parameter",
"COMMON.REQUEST_FAILED": "Request failed",
"COMMON.REQUEST_TIMEOUT": "Request timeout",
"COMMON.PAGE_NOT_FOUND": "Page Not Found",
"COMMON.UNKNOWN_ERROR": "Unknown error",
"COMMON.INVALID_PARAMETER": "Invalid parameter",
"COMMON.OPERATION_NOT_SUPPORTED": "Operation is not supported",
"COMMON.DEVICE_NOT_EXIST": "Device not exists or not online",
"COMMON.RESPONSE_TIMEOUT": "Response timeout",
"COMMON.RECONNECTING": "Reconnecting...",
"COMMON.DISCONNECTED": "Session disconnected",
"COMMON.CONNECTION_FAILED": "Connection failed",
"hostname": "Hostname",
"username": "Username",
"cpuUsage": "CPU Usage",
"cpuLogicalCores": "Logical Processors",
"cpuPhysicalCores": "Physical Processors",
"ramUsage": "RAM Usage",
"diskUsage": "Disk Usage",
"free": "Free",
"used": "Used",
"total": "Total",
"ram": "RAM",
"os": "OS",
"arch": "Arch",
"uptime": "Uptime",
"netStat": "Traffic",
"operations": "Operations",
"hours": "h",
"minutes": "m",
"terminal": "Terminal",
"procMgr": "ProcMgr",
"fileMgr": "Explorer",
"run": "Run",
"screenshot": "Screenshot",
"desktop": "Desktop",
"lock": "Lock",
"logoff": "Logoff",
"hibernate": "Hibernate",
"suspend": "Suspend",
"restart": "Restart",
"shutdown": "Shutdown",
"offline": "Offline",
"generate": "Generate client",
"requestFailed": "Request failed",
"operationConfirm": "Are you sure to {0} this device?",
"operationSuccess": "Operation executed",
"COMMON.HOURS": "h",
"COMMON.MINUTES": "m",
"COMMON.COLON": ": ",
"fileExplorer": "File Explorer",
"fileName": "Name",
"fileSize": "Size",
"modifyTime": "Modify Time",
"file": "file",
"folder": "folder",
"reload": "Reload",
"upload": "Upload",
"delete": "Delete",
"download": "Download",
"editAsText": "Edit as text",
"uploading": "Uploading...",
"uploadFailed": "Upload failed",
"uploadAborted": "Upload aborted",
"uploadSuccess": "Upload success",
"uploadInvalidPath": "Cannot upload here",
"uploadCancelConfirm": "Are you sure to cancel uploading?",
"downloadMultiConfirm": "It may take a long time, are you sure to continue?",
"downloadInvalidPath": "Can not archive volumes",
"deleteMultiConfirm": "Are you sure to delete these items?",
"deleteConfirm": "Are you sure to delete this {0}?",
"deleteSuccess": "File or folder deleted",
"deleteInvalidPath": "Cannot delete disk partitions",
"dateTimeFormat": "MMM D, YYYY h:mm A",
"fileMultiSelectAlert": "Selected {0} item(s), {1} item(s) in total",
"fileOrDirNotExist": "File or folder does not exist",
"fileOverwriteConfirm": "File [ {0} ] already exists, overwrite?",
"fileOverwrite": "Overwrite",
"fileTooLarge": "File is too large to read",
"fileEncodingUnsupported": "File encoding is not supported",
"fileNotSaveConfirm": "File is not saved, do you want to save it?",
"fileDoNotSave": "Don't save",
"fileSaveSuccess": "File saved successfully",
"fileSaveFailed": "Fail to save file",
"minFontSize": "Font size is already minimum",
"save": "Save",
"search": "Search",
"replace": "Replace",
"theme": "Theme",
"font": "Font",
"enlarge": "Enlarge",
"shrink": "Shrink",
"cancel": "Cancel",
"OVERVIEW.HOSTNAME": "Hostname",
"OVERVIEW.USERNAME": "Username",
"OVERVIEW.CPU_USAGE": "CPU Usage",
"OVERVIEW.CPU_LOGICAL_CORES": "Logical Cores",
"OVERVIEW.CPU_PHYSICAL_CORES": "Physical Cores",
"OVERVIEW.RAM_USAGE": "RAM Usage",
"OVERVIEW.DISK_USAGE": "Disk Usage",
"OVERVIEW.FREE": "Free",
"OVERVIEW.USED": "Used",
"OVERVIEW.TOTAL": "Total",
"OVERVIEW.RAM": "RAM",
"OVERVIEW.OS": "OS",
"OVERVIEW.ARCH": "Arch",
"OVERVIEW.UPTIME": "Uptime",
"OVERVIEW.NETWORK": "Network",
"OVERVIEW.OPERATIONS": "Operations",
"OVERVIEW.TERMINAL": "Terminal",
"OVERVIEW.PROC_MANAGER": "Process Manager",
"OVERVIEW.EXPLORER": "Explorer",
"OVERVIEW.RUN": "Run",
"OVERVIEW.SCREENSHOT": "Screenshot",
"OVERVIEW.DESKTOP": "Desktop",
"OVERVIEW.LOCK": "Lock",
"OVERVIEW.LOGOFF": "Logoff",
"OVERVIEW.HIBERNATE": "Hibernate",
"OVERVIEW.SUSPEND": "Suspend",
"OVERVIEW.RESTART": "Restart",
"OVERVIEW.SHUTDOWN": "Shutdown",
"OVERVIEW.OFFLINE": "Offline",
"OVERVIEW.GENERATE": "Generate client",
"OVERVIEW.OPERATION_CONFIRM": "Are you sure to {0} this device?",
"OVERVIEW.OPERATION_SUCCESS": "Operation executed",
"host": "Host",
"port": "Port",
"path": "Path",
"osArch": "OS / Arch",
"EXPLORER.TITLE": "File Explorer",
"EXPLORER.FILE_NAME": "Name",
"EXPLORER.FILE_SIZE": "Size",
"EXPLORER.MODIFY_TIME": "Modify Time",
"EXPLORER.FILE": "file",
"EXPLORER.FOLDER": "folder",
"EXPLORER.RELOAD": "Reload",
"EXPLORER.UPLOAD": "Upload",
"EXPLORER.DELETE": "Delete",
"EXPLORER.DOWNLOAD": "Download",
"EXPLORER.EDIT_AS_TEXT": "Edit as text",
"EXPLORER.UPLOADING": "Uploading...",
"EXPLORER.UPLOAD_FAILED": "Upload failed",
"EXPLORER.UPLOAD_ABORTED": "Upload aborted",
"EXPLORER.UPLOAD_SUCCESS": "Upload success",
"EXPLORER.UPLOAD_INVALID_PATH": "Cannot upload here",
"EXPLORER.UPLOAD_CANCEL_CONFIRM": "Are you sure to cancel uploading?",
"EXPLORER.DOWNLOAD_MULTI_CONFIRM": "It may take a long time, are you sure to continue?",
"EXPLORER.DOWNLOAD_VOLUMES_ERROR": "Can not archive volumes",
"EXPLORER.DELETE_MULTI_CONFIRM": "Are you sure to delete these items?",
"EXPLORER.DELETE_CONFIRM": "Are you sure to delete this {0}?",
"EXPLORER.DELETE_SUCCESS": "File or folder deleted",
"EXPLORER.DELETE_INVALID_PATH": "Cannot delete disk partitions",
"EXPLORER.DATE_TIME_FORMAT": "MMM D, YYYY h:mm A",
"EXPLORER.MULTI_SELECT_LABEL": "Selected {0} item(s), {1} item(s) in total",
"EXPLORER.FILE_OR_DIR_NOT_EXIST": "File or folder does not exist",
"EXPLORER.OVERWRITE_CONFIRM": "File [ {0} ] already exists, overwrite?",
"EXPLORER.OVERWRITE": "Overwrite",
"EXPLORER.FILE_TOO_LARGE": "File is too large to read",
"EXPLORER.UNSUPPORTED_ENCODING": "File encoding is not supported",
"EXPLORER.NOT_SAVED_CONFIRM": "File is not saved, do you want to save it?",
"EXPLORER.FILE_DO_NOT_SAVE": "Don't save",
"EXPLORER.FILE_SAVE_SUCCESSFULLY": "File saved successfully",
"EXPLORER.FILE_SAVE_FAILED": "Fail to save file",
"EXPLORER.REACHED_MIN_FONT_SIZE": "Font size is already minimum",
"EXPLORER.SAVE": "Save",
"EXPLORER.SEARCH": "Search",
"EXPLORER.REPLACE": "Replace",
"EXPLORER.THEME": "Theme",
"EXPLORER.FONT": "Font",
"EXPLORER.ENLARGE": "Enlarge",
"EXPLORER.SHRINK": "Shrink",
"EXPLORER.CANCEL": "Cancel",
"processManager": "Process Manager",
"procName": "Process",
"killProc": "Kill",
"confirmKillProc": "Are you sure to kill this process?",
"killProcSuccess": "Process killed",
"GENERATOR.HOST": "Host",
"GENERATOR.PORT": "Port",
"GENERATOR.PATH": "Path",
"GENERATOR.OS_ARCH": "OS / Arch",
"GENERATOR.NO_PREBUILT_FOUND": "The OS or Arch is not prebuilt",
"GENERATOR.CONFIG_GENERATE_FAILED": "Failed to generate client config",
"GENERATOR.CONFIG_TOO_LARGE": "Config is too large",
"reconnecting": "Reconnecting...",
"disconnected": "Session disconnected",
"connectFailed": "Connection failed",
"PROCMGR.TITLE": "Process Manager",
"PROCMGR.PROCESS": "Process",
"PROCMGR.KILL_PROCESS": "Kill",
"PROCMGR.KILL_PROCESS_CONFIRM": "Are you sure to kill this process?",
"PROCMGR.KILL_PROCESS_SUCCESSFULLY": "Process killed",
"terminalSessionCreationFailed": "Failed to create terminal session",
"deviceNotExists": "Device not exists or not online",
"responseTimeout": "Response timeout",
"terminalSessionClosed": "Terminal session closed",
"osOrArchNotPrebuilt": "The OS or Arch is not prebuilt",
"configGenerateFailed": "Failed to generate client config",
"tooLargeConfig": "Config is too large",
"fileUploadFailed": "Failed to upload file",
"invalidFileRange": "Invalid file range",
"operationNotSupported": "Operation is not supported",
"TERMINAL.TITLE": "Terminal",
"TERMINAL.CREATE_SESSION_FAILED": "Failed to create terminal session",
"TERMINAL.SESSION_CLOSED": "Terminal session closed",
"desktopSessionCreationFailed": "Failed to create desktop session",
"desktopSessionClosed": "Desktop session closed",
"fullscreenFailed": "Failed to enter fullscreen",
"screenshotFailed": "Failed to take screenshot",
"screenshotObtainFailed": "Failed to obtain screenshot",
"noDisplayFound": "No display found",
"DESKTOP.TITLE": "Desktop",
"DESKTOP.CREATE_SESSION_FAILED": "Failed to create desktop session",
"DESKTOP.SESSION_CLOSED": "Desktop session closed",
"DESKTOP.FULLSCREEN_FAILED": "Failed to enter fullscreen",
"DESKTOP.SCREENSHOT_FAILED": "Failed to take screenshot",
"DESKTOP.FETCH_IMAGE_FAILED": "Failed to fetch screenshot image",
"DESKTOP.NO_DISPLAY_FOUND": "No display found",
"executionSuccess": "Execution success",
"cmdPlaceholder": "Command",
"argsPlaceholder": "Arguments (separated by space)",
"colon": ": "
"RUNNER.TITLE": "Run",
"RUNNER.EXECUTION_SUCCESS": "Execution success",
"RUNNER.CMD_PLACEHOLDER": "Command",
"RUNNER.ARGS_PLACEHOLDER": "Arguments (separated by space)"
}

View File

@@ -17,7 +17,7 @@ for (const locale in locales) {
i18n.init({
lng: lang,
fallbackLng: 'en',
initImmediate: false,
initImmediate: true,
resources
});

View File

@@ -1,125 +1,125 @@
{
"requestTimeout": "请求超时",
"pageNotFound": "未找到该页面",
"unknownError": "未知错误",
"invalidParameter": "参数无效",
"COMMON.REQUEST_FAILED": "请求服务器失败",
"COMMON.REQUEST_TIMEOUT": "请求超时",
"COMMON.PAGE_NOT_FOUND": "未找到该页面",
"COMMON.UNKNOWN_ERROR": "未知错误",
"COMMON.INVALID_PARAMETER": "参数无效",
"COMMON.OPERATION_NOT_SUPPORTED": "不支持该操作",
"COMMON.DEVICE_NOT_EXIST": "设备不存在或已离线",
"COMMON.RESPONSE_TIMEOUT": "响应超时",
"COMMON.RECONNECTING": "正在重新连接...",
"COMMON.DISCONNECTED": "连接已断开",
"COMMON.CONNECTION_FAILED": "连接失败",
"hostname": "主机名",
"username": "用户名",
"cpuUsage": "CPU使用率",
"cpuLogicalCores": "逻辑核心数量",
"cpuPhysicalCores": "物理核心数量",
"ramUsage": "内存使用率",
"diskUsage": "磁盘使用率",
"free": "剩余",
"used": "已用",
"total": "总大小",
"ram": "RAM",
"os": "操作系统",
"arch": "架构",
"uptime": "运行时间",
"netStat": "网络状态",
"operations": "操作",
"hours": "小时",
"minutes": "分钟",
"terminal": "终端",
"procMgr": "进程",
"fileMgr": "文件",
"run": "运行",
"screenshot": "截屏",
"desktop": "桌面",
"lock": "锁屏",
"logoff": "注销",
"hibernate": "休眠",
"suspend": "睡眠",
"restart": "重启",
"shutdown": "关机",
"offline": "离线",
"generate": "生成客户端",
"requestFailed": "请求服务器失败",
"operationConfirm": "确定要{0}该设备吗?",
"operationSuccess": "操作已执行",
"COMMON.HOURS": "小时",
"COMMON.MINUTES": "分钟",
"COMMON.COLON": "",
"fileExplorer": "文件管理器",
"fileName": "文件名",
"fileSize": "大小",
"modifyTime": "修改时间",
"file": "文件",
"folder": "文件夹",
"reload": "刷新",
"upload": "上传",
"delete": "删除",
"download": "下载",
"editAsText": "编辑文本",
"uploading": "上传中...",
"uploadFailed": "上传失败",
"uploadAborted": "取消上传",
"uploadSuccess": "上传完成",
"uploadInvalidPath": "该路径无法上传文件",
"uploadCancelConfirm": "确定要取消上传吗?",
"downloadMultiConfirm": "该操作可能比较耗时,是否继续?",
"downloadInvalidPath": "无法压缩磁盘分区",
"deleteMultiConfirm": "确定要删除这些项目吗?",
"deleteConfirm": "确定要删除该{0}吗?",
"deleteSuccess": "文件或目录已删除",
"deleteInvalidPath": "无法删除磁盘分区",
"dateTimeFormat": "YYYY/MM/DD HH:mm",
"fileMultiSelectAlert": "已选择{0}项,总共{1}项",
"fileOrDirNotExist": "文件或目录不存在",
"fileOverwriteConfirm": "文件[ {0} ]已经存在,是否覆盖?",
"fileOverwrite": "覆盖",
"fileTooLarge": "文件太大,无法读取",
"fileEncodingUnsupported": "不支持该文件编码",
"fileNotSaveConfirm": "文件已修改,是否保存",
"fileDoNotSave": "不保存",
"fileSaveSuccess": "文件已保存",
"fileSaveFailed": "文件保存失败",
"minFontSize": "字体已经达到最小",
"save": "保存",
"search": "查找",
"replace": "替换",
"theme": "主题",
"font": "字体",
"enlarge": "放大",
"shrink": "缩小",
"cancel": "取消",
"OVERVIEW.HOSTNAME": "主机名",
"OVERVIEW.USERNAME": "用户名",
"OVERVIEW.CPU_USAGE": "CPU使用率",
"OVERVIEW.CPU_LOGICAL_CORES": "逻辑核心数量",
"OVERVIEW.CPU_PHYSICAL_CORES": "物理核心数量",
"OVERVIEW.RAM_USAGE": "内存使用率",
"OVERVIEW.DISK_USAGE": "磁盘使用率",
"OVERVIEW.FREE": "剩余",
"OVERVIEW.USED": "已用",
"OVERVIEW.TOTAL": "总大小",
"OVERVIEW.RAM": "RAM",
"OVERVIEW.OS": "操作系统",
"OVERVIEW.ARCH": "架构",
"OVERVIEW.UPTIME": "运行时间",
"OVERVIEW.NETWORK": "网络状态",
"OVERVIEW.OPERATIONS": "操作",
"OVERVIEW.TERMINAL": "终端",
"OVERVIEW.PROC_MANAGER": "进程",
"OVERVIEW.EXPLORER": "文件",
"OVERVIEW.RUN": "运行",
"OVERVIEW.SCREENSHOT": "截屏",
"OVERVIEW.DESKTOP": "桌面",
"OVERVIEW.LOCK": "锁屏",
"OVERVIEW.LOGOFF": "注销",
"OVERVIEW.HIBERNATE": "休眠",
"OVERVIEW.SUSPEND": "睡眠",
"OVERVIEW.RESTART": "重启",
"OVERVIEW.SHUTDOWN": "关机",
"OVERVIEW.OFFLINE": "离线",
"OVERVIEW.GENERATE": "生成客户端",
"OVERVIEW.OPERATION_CONFIRM": "确定要{0}该设备吗",
"OVERVIEW.OPERATION_SUCCESS": "操作已执行",
"host": "主机",
"port": "端口",
"path": "路径",
"osArch": "操作系统/架构",
"EXPLORER.TITLE": "文件管理器",
"EXPLORER.FILE_NAME": "文件名",
"EXPLORER.FILE_SIZE": "大小",
"EXPLORER.MODIFY_TIME": "修改时间",
"EXPLORER.FILE": "文件",
"EXPLORER.FOLDER": "文件夹",
"EXPLORER.RELOAD": "刷新",
"EXPLORER.UPLOAD": "上传",
"EXPLORER.DELETE": "删除",
"EXPLORER.DOWNLOAD": "下载",
"EXPLORER.EDIT_AS_TEXT": "编辑文本",
"EXPLORER.UPLOADING": "上传中...",
"EXPLORER.UPLOAD_FAILED": "上传失败",
"EXPLORER.UPLOAD_ABORTED": "取消上传",
"EXPLORER.UPLOAD_SUCCESS": "上传完成",
"EXPLORER.UPLOAD_INVALID_PATH": "该路径无法上传文件",
"EXPLORER.UPLOAD_CANCEL_CONFIRM": "确定要取消上传吗?",
"EXPLORER.DOWNLOAD_MULTI_CONFIRM": "该操作可能比较耗时,是否继续?",
"EXPLORER.DOWNLOAD_VOLUMES_ERROR": "无法压缩磁盘分区",
"EXPLORER.DELETE_MULTI_CONFIRM": "确定要删除这些项目吗?",
"EXPLORER.DELETE_CONFIRM": "确定要删除该{0}吗?",
"EXPLORER.DELETE_SUCCESS": "文件或目录已删除",
"EXPLORER.DELETE_INVALID_PATH": "无法删除磁盘分区",
"EXPLORER.DATE_TIME_FORMAT": "YYYY/MM/DD HH:mm",
"EXPLORER.MULTI_SELECT_LABEL": "已选择{0}项,总共{1}项",
"EXPLORER.FILE_OR_DIR_NOT_EXIST": "文件或目录不存在",
"EXPLORER.OVERWRITE_CONFIRM": "文件[ {0} ]已经存在,是否覆盖?",
"EXPLORER.OVERWRITE": "覆盖",
"EXPLORER.FILE_TOO_LARGE": "文件太大,无法读取",
"EXPLORER.UNSUPPORTED_ENCODING": "不支持该文件编码",
"EXPLORER.NOT_SAVED_CONFIRM": "文件已修改,是否保存?",
"EXPLORER.FILE_DO_NOT_SAVE": "不保存",
"EXPLORER.FILE_SAVE_SUCCESSFULLY": "文件已保存",
"EXPLORER.FILE_SAVE_FAILED": "文件保存失败",
"EXPLORER.REACHED_MIN_FONT_SIZE": "字体已经达到最小",
"EXPLORER.SAVE": "保存",
"EXPLORER.SEARCH": "查找",
"EXPLORER.REPLACE": "替换",
"EXPLORER.THEME": "主题",
"EXPLORER.FONT": "字体",
"EXPLORER.ENLARGE": "放大",
"EXPLORER.SHRINK": "缩小",
"EXPLORER.CANCEL": "取消",
"processManager": "进程管理器",
"procName": "进程名",
"killProc": "结束",
"confirmKillProc": "确定要结束该进程吗?",
"killProcSuccess": "进程已结束",
"GENERATOR.HOST": "主机",
"GENERATOR.PORT": "端口",
"GENERATOR.PATH": "路径",
"GENERATOR.OS_ARCH": "操作系统/架构",
"GENERATOR.NO_PREBUILT_FOUND": "该操作系统或架构的客户端未预编译",
"GENERATOR.CONFIG_GENERATE_FAILED": "配置文件生成失败",
"GENERATOR.CONFIG_TOO_LARGE": "配置文件过大",
"reconnecting": "正在重新连接...",
"disconnected": "连接已断开",
"connectFailed": "连接失败",
"PROCMGR.TITLE": "进程管理器",
"PROCMGR.PROCESS": "进程名",
"PROCMGR.KILL_PROCESS": "结束",
"PROCMGR.KILL_PROCESS_CONFIRM": "确定要结束该进程吗?",
"PROCMGR.KILL_PROCESS_SUCCESSFULLY": "进程已结束",
"terminalSessionCreationFailed": "终端会话创建失败",
"deviceNotExists": "设备不存在或已离线",
"responseTimeout": "响应超时",
"terminalSessionClosed": "终端会话已关闭",
"osOrArchNotPrebuilt": "该操作系统或架构的客户端未预编译",
"configGenerateFailed": "配置文件生成失败",
"tooLargeConfig": "配置文件过大",
"fileUploadFailed": "文件上传失败",
"invalidFileRange": "文件范围错误",
"operationNotSupported": "不支持该操作",
"TERMINAL.TITLE": "终端",
"TERMINAL.CREATE_SESSION_FAILED": "终端会话创建失败",
"TERMINAL.SESSION_CLOSED": "终端会话已关闭",
"desktopSessionCreationFailed": "桌面会话创建失败",
"desktopSessionClosed": "桌面会话已关闭",
"fullscreenFailed": "进入全屏失败",
"screenshotFailed": "屏失败",
"screenshotObtainFailed": "截屏读取失败",
"noDisplayFound": "设备未连接显示器",
"DESKTOP.TITLE": "桌面",
"DESKTOP.CREATE_SESSION_FAILED": "桌面会话创建失败",
"DESKTOP.SESSION_CLOSED": "桌面会话已关闭",
"DESKTOP.FULLSCREEN_FAILED": "进入全屏失败",
"DESKTOP.SCREENSHOT_FAILED": "截屏失败",
"DESKTOP.FETCH_IMAGE_FAILED": "截屏读取失败",
"DESKTOP.NO_DISPLAY_FOUND": "设备未连接显示器",
"executionSuccess": "执行成功",
"cmdPlaceholder": "命令",
"argsPlaceholder": "参数(以空格分隔)",
"colon": ""
"RUNNER.TITLE": "运行",
"RUNNER.EXECUTION_SUCCESS": "执行成功",
"RUNNER.CMD_PLACEHOLDER": "命令",
"RUNNER.ARGS_PLACEHOLDER": "参数(以空格分隔)"
}

View File

@@ -8,7 +8,7 @@ export default function () {
return (
<h1 style={{textAlign: 'center', userSelect: 'none'}}>
{i18n.t('pageNotFound')}
{i18n.t('COMMON.PAGE_NOT_FOUND')}
</h1>
);
}

View File

@@ -53,14 +53,14 @@ function overview(props) {
const columns = [
{
key: 'hostname',
title: i18n.t('hostname'),
title: i18n.t('OVERVIEW.HOSTNAME'),
dataIndex: 'hostname',
ellipsis: true,
width: 100
},
{
key: 'username',
title: i18n.t('username'),
title: i18n.t('OVERVIEW.USERNAME'),
dataIndex: 'username',
ellipsis: true,
width: 90
@@ -75,7 +75,7 @@ function overview(props) {
},
{
key: 'cpu_usage',
title: i18n.t('cpuUsage'),
title: i18n.t('OVERVIEW.CPU_USAGE'),
dataIndex: 'cpu_usage',
ellipsis: true,
render: (_, v) => <UsageBar title={renderCPUStat(v.cpu)} {...v.cpu} />,
@@ -83,7 +83,7 @@ function overview(props) {
},
{
key: 'ram_usage',
title: i18n.t('ramUsage'),
title: i18n.t('OVERVIEW.RAM_USAGE'),
dataIndex: 'ram_usage',
ellipsis: true,
render: (_, v) => <UsageBar title={renderRAMStat(v.ram)} {...v.ram} />,
@@ -91,7 +91,7 @@ function overview(props) {
},
{
key: 'disk_usage',
title: i18n.t('diskUsage'),
title: i18n.t('OVERVIEW.DISK_USAGE'),
dataIndex: 'disk_usage',
ellipsis: true,
render: (_, v) => <UsageBar title={renderDiskStat(v.disk)} {...v.disk} />,
@@ -99,21 +99,21 @@ function overview(props) {
},
{
key: 'os',
title: i18n.t('os'),
title: i18n.t('OVERVIEW.OS'),
dataIndex: 'os',
ellipsis: true,
width: 80
},
{
key: 'arch',
title: i18n.t('arch'),
title: i18n.t('OVERVIEW.ARCH'),
dataIndex: 'arch',
ellipsis: true,
width: 70
},
{
key: 'ram_total',
title: i18n.t('ram'),
title: i18n.t('OVERVIEW.RAM'),
dataIndex: 'ram_total',
ellipsis: true,
renderText: formatSize,
@@ -142,7 +142,7 @@ function overview(props) {
},
{
key: 'uptime',
title: i18n.t('uptime'),
title: i18n.t('OVERVIEW.UPTIME'),
dataIndex: 'uptime',
ellipsis: true,
renderText: tsToTime,
@@ -150,14 +150,14 @@ function overview(props) {
},
{
key: 'net_stat',
title: i18n.t('netStat'),
title: i18n.t('OVERVIEW.NETWORK'),
ellipsis: true,
renderText: (_, v) => renderNetworkIO(v),
width: 170
},
{
key: 'option',
title: i18n.t('operations'),
title: i18n.t('OVERVIEW.OPERATIONS'),
dataIndex: 'id',
valueType: 'option',
ellipsis: false,
@@ -218,11 +218,11 @@ function overview(props) {
>
{model}
</div>
{i18n.t('cpuUsage') + i18n.t('colon') + usage + '%'}
{i18n.t('OVERVIEW.CPU_USAGE') + i18n.t('COMMON.COLON') + usage + '%'}
<br />
{i18n.t('cpuLogicalCores') + i18n.t('colon') + cores.logical}
{i18n.t('OVERVIEW.CPU_LOGICAL_CORES') + i18n.t('COMMON.COLON') + cores.logical}
<br />
{i18n.t('cpuPhysicalCores') + i18n.t('colon') + cores.physical}
{i18n.t('OVERVIEW.CPU_PHYSICAL_CORES') + i18n.t('COMMON.COLON') + cores.physical}
</div>
);
}
@@ -231,13 +231,13 @@ function overview(props) {
usage = Math.round(usage * 100) / 100;
return (
<div>
{i18n.t('ramUsage') + i18n.t('colon') + usage + '%'}
{i18n.t('OVERVIEW.RAM_USAGE') + i18n.t('COMMON.COLON') + usage + '%'}
<br />
{i18n.t('free') + i18n.t('colon') + formatSize(total - used)}
{i18n.t('OVERVIEW.FREE') + i18n.t('COMMON.COLON') + formatSize(total - used)}
<br />
{i18n.t('used') + i18n.t('colon') + formatSize(used)}
{i18n.t('OVERVIEW.USED') + i18n.t('COMMON.COLON') + formatSize(used)}
<br />
{i18n.t('total') + i18n.t('colon') + formatSize(total)}
{i18n.t('OVERVIEW.TOTAL') + i18n.t('COMMON.COLON') + formatSize(total)}
</div>
);
}
@@ -246,13 +246,13 @@ function overview(props) {
usage = Math.round(usage * 100) / 100;
return (
<div>
{i18n.t('diskUsage') + i18n.t('colon') + usage + '%'}
{i18n.t('OVERVIEW.DISK_USAGE') + i18n.t('COMMON.COLON') + usage + '%'}
<br />
{i18n.t('free') + i18n.t('colon') + formatSize(total - used)}
{i18n.t('OVERVIEW.FREE') + i18n.t('COMMON.COLON') + formatSize(total - used)}
<br />
{i18n.t('used') + i18n.t('colon') + formatSize(used)}
{i18n.t('OVERVIEW.USED') + i18n.t('COMMON.COLON') + formatSize(used)}
<br />
{i18n.t('total') + i18n.t('colon') + formatSize(total)}
{i18n.t('OVERVIEW.TOTAL') + i18n.t('COMMON.COLON') + formatSize(total)}
</div>
);
}
@@ -273,25 +273,25 @@ function overview(props) {
}
function renderOperation(device) {
let menus = [
{key: 'run', name: i18n.t('run')},
{key: 'desktop', name: i18n.t('desktop')},
{key: 'screenshot', name: i18n.t('screenshot')},
{key: 'lock', name: i18n.t('lock')},
{key: 'logoff', name: i18n.t('logoff')},
{key: 'hibernate', name: i18n.t('hibernate')},
{key: 'suspend', name: i18n.t('suspend')},
{key: 'restart', name: i18n.t('restart')},
{key: 'shutdown', name: i18n.t('shutdown')},
{key: 'offline', name: i18n.t('offline')},
{key: 'run', name: i18n.t('OVERVIEW.RUN')},
{key: 'desktop', name: i18n.t('OVERVIEW.DESKTOP')},
{key: 'screenshot', name: i18n.t('OVERVIEW.SCREENSHOT')},
{key: 'lock', name: i18n.t('OVERVIEW.LOCK')},
{key: 'logoff', name: i18n.t('OVERVIEW.LOGOFF')},
{key: 'hibernate', name: i18n.t('OVERVIEW.HIBERNATE')},
{key: 'suspend', name: i18n.t('OVERVIEW.SUSPEND')},
{key: 'restart', name: i18n.t('OVERVIEW.RESTART')},
{key: 'shutdown', name: i18n.t('OVERVIEW.SHUTDOWN')},
{key: 'offline', name: i18n.t('OVERVIEW.OFFLINE')},
];
return [
<a key='terminal' onClick={setTerminal.bind(null, device)}>{i18n.t('terminal')}</a>,
<a key='procmgr' onClick={setProcMgr.bind(null, device.id)}>{i18n.t('procMgr')}</a>,
<a key='terminal' onClick={setTerminal.bind(null, device)}>{i18n.t('OVERVIEW.TERMINAL')}</a>,
<a key='procmgr' onClick={setProcMgr.bind(null, device.id)}>{i18n.t('OVERVIEW.PROC_MANAGER')}</a>,
<a key='explorer' onClick={() => {
setExplorer(device.id);
setIsWindows(device.os === 'windows');
}}>
{i18n.t('fileMgr')}
{i18n.t('OVERVIEW.EXPLORER')}
</a>,
<TableDropdown
key='more'
@@ -324,13 +324,13 @@ function overview(props) {
return;
}
Modal.confirm({
title: i18n.t('operationConfirm').replace('{0}', i18n.t(act).toUpperCase()),
title: i18n.t('OVERVIEW.OPERATION_CONFIRM').replace('{0}', i18n.t('OVERVIEW.'+act.toUpperCase())),
icon: <QuestionCircleOutlined/>,
onOk() {
request('/api/device/' + act, {device: device.id}).then(res => {
let data = res.data;
if (data.code === 0) {
message.success(i18n.t('operationSuccess'));
message.success(i18n.t('OVERVIEW.OPERATION_SUCCESS'));
tableRef.current.reload();
}
});
@@ -340,7 +340,7 @@ function overview(props) {
function toolBar() {
return (
<Button type='primary' onClick={setGenerate.bind(null, true)}>{i18n.t('generate')}</Button>
<Button type='primary' onClick={setGenerate.bind(null, true)}>{i18n.t('OVERVIEW.GENERATE')}</Button>
)
}

View File

@@ -47,7 +47,7 @@ function tsToTime(ts) {
let hours = Math.floor(ts / 3600);
ts %= 3600;
let minutes = Math.floor(ts / 60);
return `${String(hours) + i18n.t('hours') + ' ' + String(minutes) + i18n.t('minutes')}`;
return `${String(hours) + i18n.t('COMMON.HOURS') + ' ' + String(minutes) + i18n.t('COMMON.MINUTES')}`;
}
function getBaseURL(ws, suffix) {
@@ -93,7 +93,7 @@ function post(url, data, ext) {
}
function translate(text) {
return text.replace(/\$\{i18n\|([a-zA-Z0-9]+)\}/g, (match, key) => {
return text.replace(/\$\{i18n\|([a-zA-Z0-9_.]+)\}/g, (match, key) => {
return i18n.t(key);
});
}
@@ -113,7 +113,7 @@ function catchBlobReq(err) {
try {
data = JSON.parse(str);
} catch (e) { }
message.warn(data.msg ? translate(data.msg) : i18n.t('requestFailed'));
message.warn(data.msg ? translate(data.msg) : i18n.t('COMMON.REQUEST_FAILED'));
});
}
}