more zh, for configuration and installation and upgrade, and flutter,
not test yet
This commit is contained in:
parent
0c35437531
commit
6b6ffb3f17
@ -2,6 +2,73 @@ import 'package:flutter/material.dart';
|
|||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
import 'package:flutter_easyloading/flutter_easyloading.dart';
|
import 'package:flutter_easyloading/flutter_easyloading.dart';
|
||||||
import 'package:tuple/tuple.dart';
|
import 'package:tuple/tuple.dart';
|
||||||
|
import 'dart:io';
|
||||||
|
|
||||||
|
final bool isZh = Platform.localeName == "zh_CN";
|
||||||
|
|
||||||
|
final langs = <String, Map<String, String>>{
|
||||||
|
'zh': <String, String>{
|
||||||
|
'Remote ID': '远程',
|
||||||
|
'ID/Relay Server': 'ID/中继服务器',
|
||||||
|
'About': '关于',
|
||||||
|
'Mute': '静音',
|
||||||
|
'ID Server': 'ID服务器',
|
||||||
|
'Relay Server': '中继服务器',
|
||||||
|
'Invalid IP': '无效IP',
|
||||||
|
'Invalid format': '无效格式',
|
||||||
|
'Cancel': '取消',
|
||||||
|
'Close': '关闭',
|
||||||
|
'Retry': '再试',
|
||||||
|
'OK': '确认',
|
||||||
|
'Password Required': '需要密码',
|
||||||
|
'Please enter your password': '请输入密码',
|
||||||
|
'Remember password': '记住密码',
|
||||||
|
'Wrong Password': '密码错误',
|
||||||
|
'Do you want to enter again?': '还想输入一次吗?',
|
||||||
|
'Connection Error': '连接错误',
|
||||||
|
'Error': '错误',
|
||||||
|
'Reset by the peer': '连接被对方关闭',
|
||||||
|
'Connecting...': '正在连接...',
|
||||||
|
'Connection in progress. Please wait.': '连接进行中,请稍等。',
|
||||||
|
'Please try 1 minute later': '一分钟后再试',
|
||||||
|
'Login Error': '登录错误',
|
||||||
|
'Successful': '成功',
|
||||||
|
'Connected, waiting for image...': '已连接,等待画面传输...',
|
||||||
|
'Custom Image Quality': '设置画面质量',
|
||||||
|
'Privacy mode': '隐私模式',
|
||||||
|
'Remove': '删除',
|
||||||
|
'Adjust Window': '调节窗口',
|
||||||
|
'Good image quality': '好画质',
|
||||||
|
'Balanced': '一般画质',
|
||||||
|
'Optimize reaction time': '优化反应时间',
|
||||||
|
'Custom': '自定义画质',
|
||||||
|
'Show remote cursor': '显示远程光标',
|
||||||
|
'Disable clipboard': '禁止剪贴板',
|
||||||
|
'Lock after session end': '断开后锁定远程电脑',
|
||||||
|
'Insert': '插入',
|
||||||
|
'Insert Lock': '锁定远程电脑',
|
||||||
|
'Refresh': '刷新画面',
|
||||||
|
'ID not exist': 'ID不存在',
|
||||||
|
'Failed to connect to rendezvous server': '连接服务器失败',
|
||||||
|
'Remote desktop is offline': '远程电脑不在线',
|
||||||
|
'Key mismatch': 'Key不匹配',
|
||||||
|
'Timeout': '连接超时',
|
||||||
|
'Failed to connect to relay server': '无法连接到中继服务器',
|
||||||
|
'Failed to connect via rendezvous server': '无法通过服务器建立连接',
|
||||||
|
'Failed to make direct connection to remote desktop': '无法建立直接连接',
|
||||||
|
'OS Password': '操作系统密码',
|
||||||
|
'Paste': '粘贴',
|
||||||
|
'Logging in...': '正在登录...',
|
||||||
|
'Are you sure to close the connection?': '是否确认关闭连接?',
|
||||||
|
},
|
||||||
|
'en': <String, String>{}
|
||||||
|
};
|
||||||
|
|
||||||
|
String translate(name) {
|
||||||
|
final tmp = isZh ? langs['zh'] : langs['en'];
|
||||||
|
final v = tmp[name];
|
||||||
|
return v != null ? v : name;
|
||||||
|
}
|
||||||
|
|
||||||
class MyTheme {
|
class MyTheme {
|
||||||
MyTheme._();
|
MyTheme._();
|
||||||
@ -83,7 +150,7 @@ void msgbox(String type, String title, String text, BuildContext context,
|
|||||||
}
|
}
|
||||||
final buttons = [
|
final buttons = [
|
||||||
Expanded(child: Container()),
|
Expanded(child: Container()),
|
||||||
wrap('OK', () {
|
wrap(translate('OK'), () {
|
||||||
dismissLoading();
|
dismissLoading();
|
||||||
Navigator.pop(context);
|
Navigator.pop(context);
|
||||||
})
|
})
|
||||||
@ -94,7 +161,7 @@ void msgbox(String type, String title, String text, BuildContext context,
|
|||||||
if (hasCancel) {
|
if (hasCancel) {
|
||||||
buttons.insert(
|
buttons.insert(
|
||||||
1,
|
1,
|
||||||
wrap('Cancel', () {
|
wrap(translate('Cancel'), () {
|
||||||
dismissLoading();
|
dismissLoading();
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
@ -102,9 +169,9 @@ void msgbox(String type, String title, String text, BuildContext context,
|
|||||||
Column(
|
Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
Text(title, style: TextStyle(fontSize: 21)),
|
Text(translate(title), style: TextStyle(fontSize: 21)),
|
||||||
SizedBox(height: 20),
|
SizedBox(height: 20),
|
||||||
Text(text, style: TextStyle(fontSize: 15)),
|
Text(translate(text), style: TextStyle(fontSize: 15)),
|
||||||
SizedBox(height: 20),
|
SizedBox(height: 20),
|
||||||
Row(
|
Row(
|
||||||
children: buttons,
|
children: buttons,
|
||||||
|
@ -49,9 +49,11 @@ class _HomePageState extends State<HomePage> {
|
|||||||
position: RelativeRect.fromLTRB(3000, 70, 3000, 70),
|
position: RelativeRect.fromLTRB(3000, 70, 3000, 70),
|
||||||
items: [
|
items: [
|
||||||
PopupMenuItem<String>(
|
PopupMenuItem<String>(
|
||||||
child: Text('ID/Relay Server'), value: 'server'),
|
child: Text(translate('ID/Relay Server')),
|
||||||
|
value: 'server'),
|
||||||
PopupMenuItem<String>(
|
PopupMenuItem<String>(
|
||||||
child: Text('About RustDesk'), value: 'about'),
|
child: Text(translate('About') + ' RustDesk'),
|
||||||
|
value: 'about'),
|
||||||
],
|
],
|
||||||
elevation: 8,
|
elevation: 8,
|
||||||
);
|
);
|
||||||
@ -154,7 +156,7 @@ class _HomePageState extends State<HomePage> {
|
|||||||
color: Color(0xFF00B6F0),
|
color: Color(0xFF00B6F0),
|
||||||
),
|
),
|
||||||
decoration: InputDecoration(
|
decoration: InputDecoration(
|
||||||
labelText: 'Remote ID',
|
labelText: translate('Remote ID'),
|
||||||
// hintText: 'Enter your remote ID',
|
// hintText: 'Enter your remote ID',
|
||||||
border: InputBorder.none,
|
border: InputBorder.none,
|
||||||
helperStyle: TextStyle(
|
helperStyle: TextStyle(
|
||||||
@ -227,7 +229,8 @@ class _HomePageState extends State<HomePage> {
|
|||||||
position: RelativeRect.fromLTRB(x, y, x, y),
|
position: RelativeRect.fromLTRB(x, y, x, y),
|
||||||
items: [
|
items: [
|
||||||
PopupMenuItem<String>(
|
PopupMenuItem<String>(
|
||||||
child: Text('Remove'), value: 'remove'),
|
child: Text(translate('Remove')),
|
||||||
|
value: 'remove'),
|
||||||
],
|
],
|
||||||
elevation: 8,
|
elevation: 8,
|
||||||
);
|
);
|
||||||
@ -260,7 +263,7 @@ void showServer(BuildContext context) {
|
|||||||
showAlertDialog(
|
showAlertDialog(
|
||||||
context,
|
context,
|
||||||
(setState) => Tuple3(
|
(setState) => Tuple3(
|
||||||
Text('ID/Relay Server'),
|
Text(translate('ID/Relay Server')),
|
||||||
Form(
|
Form(
|
||||||
key: formKey,
|
key: formKey,
|
||||||
child:
|
child:
|
||||||
@ -268,7 +271,7 @@ void showServer(BuildContext context) {
|
|||||||
TextFormField(
|
TextFormField(
|
||||||
initialValue: id0,
|
initialValue: id0,
|
||||||
decoration: InputDecoration(
|
decoration: InputDecoration(
|
||||||
labelText: 'ID Server',
|
labelText: translate('ID Server'),
|
||||||
),
|
),
|
||||||
validator: validate,
|
validator: validate,
|
||||||
onSaved: (String value) {
|
onSaved: (String value) {
|
||||||
@ -278,7 +281,7 @@ void showServer(BuildContext context) {
|
|||||||
TextFormField(
|
TextFormField(
|
||||||
initialValue: relay0,
|
initialValue: relay0,
|
||||||
decoration: InputDecoration(
|
decoration: InputDecoration(
|
||||||
labelText: 'Relay Server',
|
labelText: translate('Relay Server'),
|
||||||
),
|
),
|
||||||
validator: validate,
|
validator: validate,
|
||||||
onSaved: (String value) {
|
onSaved: (String value) {
|
||||||
@ -316,7 +319,7 @@ void showServer(BuildContext context) {
|
|||||||
Navigator.pop(context);
|
Navigator.pop(context);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
child: Text('OK'),
|
child: Text(translate('OK')),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
));
|
));
|
||||||
|
@ -179,7 +179,7 @@ class FfiModel with ChangeNotifier {
|
|||||||
_pi.sasEnabled = evt['sas_enabled'] == "true";
|
_pi.sasEnabled = evt['sas_enabled'] == "true";
|
||||||
_pi.currentDisplay = int.parse(evt['current_display']);
|
_pi.currentDisplay = int.parse(evt['current_display']);
|
||||||
List<dynamic> displays = json.decode(evt['displays']);
|
List<dynamic> displays = json.decode(evt['displays']);
|
||||||
_pi.displays = List<Display>();
|
_pi.displays = [];
|
||||||
for (int i = 0; i < displays.length; ++i) {
|
for (int i = 0; i < displays.length; ++i) {
|
||||||
Map<String, dynamic> d0 = displays[i];
|
Map<String, dynamic> d0 = displays[i];
|
||||||
var d = Display();
|
var d = Display();
|
||||||
|
@ -47,7 +47,7 @@ class _RemotePageState extends State<RemotePage> {
|
|||||||
FFI.connect(widget.id);
|
FFI.connect(widget.id);
|
||||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||||
SystemChrome.setEnabledSystemUIOverlays([]);
|
SystemChrome.setEnabledSystemUIOverlays([]);
|
||||||
showLoading('Connecting...', context);
|
showLoading(translate('Connecting...'), context);
|
||||||
_interval =
|
_interval =
|
||||||
Timer.periodic(Duration(milliseconds: 30), (timer) => interval());
|
Timer.periodic(Duration(milliseconds: 30), (timer) => interval());
|
||||||
});
|
});
|
||||||
@ -113,7 +113,7 @@ class _RemotePageState extends State<RemotePage> {
|
|||||||
_timer?.cancel();
|
_timer?.cancel();
|
||||||
_timer = Timer(Duration(seconds: _reconnects), () {
|
_timer = Timer(Duration(seconds: _reconnects), () {
|
||||||
FFI.reconnect();
|
FFI.reconnect();
|
||||||
showLoading('Connecting...', context);
|
showLoading(translate('Connecting...'), context);
|
||||||
});
|
});
|
||||||
_reconnects *= 2;
|
_reconnects *= 2;
|
||||||
} else {
|
} else {
|
||||||
@ -579,7 +579,7 @@ void enterPasswordDialog(String id, BuildContext context) {
|
|||||||
showAlertDialog(
|
showAlertDialog(
|
||||||
context,
|
context,
|
||||||
(setState) => Tuple3(
|
(setState) => Tuple3(
|
||||||
Text('Password required'),
|
Text(translate('Password required')),
|
||||||
Column(mainAxisSize: MainAxisSize.min, children: [
|
Column(mainAxisSize: MainAxisSize.min, children: [
|
||||||
PasswordWidget(controller: controller),
|
PasswordWidget(controller: controller),
|
||||||
CheckboxListTile(
|
CheckboxListTile(
|
||||||
@ -587,7 +587,7 @@ void enterPasswordDialog(String id, BuildContext context) {
|
|||||||
dense: true,
|
dense: true,
|
||||||
controlAffinity: ListTileControlAffinity.leading,
|
controlAffinity: ListTileControlAffinity.leading,
|
||||||
title: Text(
|
title: Text(
|
||||||
'Remember password',
|
translate('Remember password'),
|
||||||
),
|
),
|
||||||
value: remember,
|
value: remember,
|
||||||
onChanged: (v) {
|
onChanged: (v) {
|
||||||
@ -602,7 +602,7 @@ void enterPasswordDialog(String id, BuildContext context) {
|
|||||||
Navigator.pop(context);
|
Navigator.pop(context);
|
||||||
Navigator.pop(context);
|
Navigator.pop(context);
|
||||||
},
|
},
|
||||||
child: Text('Cancel'),
|
child: Text(translate('Cancel')),
|
||||||
),
|
),
|
||||||
FlatButton(
|
FlatButton(
|
||||||
textColor: MyTheme.accent,
|
textColor: MyTheme.accent,
|
||||||
@ -610,10 +610,10 @@ void enterPasswordDialog(String id, BuildContext context) {
|
|||||||
var text = controller.text.trim();
|
var text = controller.text.trim();
|
||||||
if (text == '') return;
|
if (text == '') return;
|
||||||
FFI.login(text, remember);
|
FFI.login(text, remember);
|
||||||
showLoading('Logging in...', null);
|
showLoading(translate('Logging in...'), null);
|
||||||
Navigator.pop(context);
|
Navigator.pop(context);
|
||||||
},
|
},
|
||||||
child: Text('OK'),
|
child: Text(translate('OK')),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
));
|
));
|
||||||
@ -622,22 +622,22 @@ void enterPasswordDialog(String id, BuildContext context) {
|
|||||||
void wrongPasswordDialog(String id, BuildContext context) {
|
void wrongPasswordDialog(String id, BuildContext context) {
|
||||||
showAlertDialog(
|
showAlertDialog(
|
||||||
context,
|
context,
|
||||||
(_) =>
|
(_) => Tuple3(Text(translate('Wrong Password')),
|
||||||
Tuple3(Text('Wrong Password'), Text('Do you want to enter again?'), [
|
Text(translate('Do you want to enter again?')), [
|
||||||
FlatButton(
|
FlatButton(
|
||||||
textColor: MyTheme.accent,
|
textColor: MyTheme.accent,
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
Navigator.pop(context);
|
Navigator.pop(context);
|
||||||
Navigator.pop(context);
|
Navigator.pop(context);
|
||||||
},
|
},
|
||||||
child: Text('Cancel'),
|
child: Text(translate('Cancel')),
|
||||||
),
|
),
|
||||||
FlatButton(
|
FlatButton(
|
||||||
textColor: MyTheme.accent,
|
textColor: MyTheme.accent,
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
enterPasswordDialog(id, context);
|
enterPasswordDialog(id, context);
|
||||||
},
|
},
|
||||||
child: Text('Retry'),
|
child: Text(translate('Retry')),
|
||||||
),
|
),
|
||||||
]));
|
]));
|
||||||
}
|
}
|
||||||
@ -691,7 +691,7 @@ void showOptions(BuildContext context) {
|
|||||||
FFI.setByName('toggle_option', 'disable-audio');
|
FFI.setByName('toggle_option', 'disable-audio');
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
title: Text('Mute')));
|
title: Text(translate('Mute'))));
|
||||||
}
|
}
|
||||||
if (FFI.ffiModel.permissions['keyboard'] != false) {
|
if (FFI.ffiModel.permissions['keyboard'] != false) {
|
||||||
more.add(CheckboxListTile(
|
more.add(CheckboxListTile(
|
||||||
@ -702,7 +702,7 @@ void showOptions(BuildContext context) {
|
|||||||
FFI.setByName('toggle_option', 'lock-after-session-end');
|
FFI.setByName('toggle_option', 'lock-after-session-end');
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
title: Text('Lock after session end')));
|
title: Text(translate('Lock after session end'))));
|
||||||
}
|
}
|
||||||
return Tuple3(
|
return Tuple3(
|
||||||
null,
|
null,
|
||||||
@ -712,7 +712,7 @@ void showOptions(BuildContext context) {
|
|||||||
<Widget>[
|
<Widget>[
|
||||||
RadioListTile<String>(
|
RadioListTile<String>(
|
||||||
controlAffinity: ListTileControlAffinity.trailing,
|
controlAffinity: ListTileControlAffinity.trailing,
|
||||||
title: const Text('Good image quality'),
|
title: Text(translate('Good image quality')),
|
||||||
value: 'best',
|
value: 'best',
|
||||||
groupValue: quality,
|
groupValue: quality,
|
||||||
onChanged: (String value) {
|
onChanged: (String value) {
|
||||||
@ -724,7 +724,7 @@ void showOptions(BuildContext context) {
|
|||||||
),
|
),
|
||||||
RadioListTile<String>(
|
RadioListTile<String>(
|
||||||
controlAffinity: ListTileControlAffinity.trailing,
|
controlAffinity: ListTileControlAffinity.trailing,
|
||||||
title: const Text('Balanced'),
|
title: Text(translate('Balanced')),
|
||||||
value: 'balanced',
|
value: 'balanced',
|
||||||
groupValue: quality,
|
groupValue: quality,
|
||||||
onChanged: (String value) {
|
onChanged: (String value) {
|
||||||
@ -736,7 +736,7 @@ void showOptions(BuildContext context) {
|
|||||||
),
|
),
|
||||||
RadioListTile<String>(
|
RadioListTile<String>(
|
||||||
controlAffinity: ListTileControlAffinity.trailing,
|
controlAffinity: ListTileControlAffinity.trailing,
|
||||||
title: const Text('Optimize reaction time'),
|
title: Text(translate('Optimize reaction time')),
|
||||||
value: 'low',
|
value: 'low',
|
||||||
groupValue: quality,
|
groupValue: quality,
|
||||||
onChanged: (String value) {
|
onChanged: (String value) {
|
||||||
@ -756,7 +756,7 @@ void showOptions(BuildContext context) {
|
|||||||
FFI.setByName('toggle_option', 'show-remote-cursor');
|
FFI.setByName('toggle_option', 'show-remote-cursor');
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
title: Text('Show remote cursor')),
|
title: Text(translate('Show remote cursor'))),
|
||||||
] +
|
] +
|
||||||
more),
|
more),
|
||||||
null);
|
null);
|
||||||
@ -769,11 +769,13 @@ void showActions(BuildContext context) {
|
|||||||
final y = size.height;
|
final y = size.height;
|
||||||
final more = <PopupMenuItem<String>>[];
|
final more = <PopupMenuItem<String>>[];
|
||||||
if (FFI.ffiModel.pi.version.isNotEmpty) {
|
if (FFI.ffiModel.pi.version.isNotEmpty) {
|
||||||
more.add(PopupMenuItem<String>(child: Text('Refresh'), value: 'refresh'));
|
more.add(PopupMenuItem<String>(
|
||||||
|
child: Text(translate('Refresh')), value: 'refresh'));
|
||||||
}
|
}
|
||||||
if (FFI.ffiModel.permissions['keyboard'] != false &&
|
if (FFI.ffiModel.permissions['keyboard'] != false &&
|
||||||
FFI.ffiModel.permissions['clipboard'] != false) {
|
FFI.ffiModel.permissions['clipboard'] != false) {
|
||||||
more.add(PopupMenuItem<String>(child: Text('Paste'), value: 'paste'));
|
more.add(
|
||||||
|
PopupMenuItem<String>(child: Text(translate('Paste')), value: 'paste'));
|
||||||
}
|
}
|
||||||
more.add(PopupMenuItem<String>(
|
more.add(PopupMenuItem<String>(
|
||||||
child: Row(
|
child: Row(
|
||||||
@ -795,8 +797,10 @@ void showActions(BuildContext context) {
|
|||||||
position: RelativeRect.fromLTRB(x, y, x, y),
|
position: RelativeRect.fromLTRB(x, y, x, y),
|
||||||
items: [
|
items: [
|
||||||
PopupMenuItem<String>(
|
PopupMenuItem<String>(
|
||||||
child: Text('Insert Ctrl + Alt + Del'), value: 'cad'),
|
child: Text(translate('Insert') + ' Ctrl + Alt + Del'),
|
||||||
PopupMenuItem<String>(child: Text('Insert Lock'), value: 'lock'),
|
value: 'cad'),
|
||||||
|
PopupMenuItem<String>(
|
||||||
|
child: Text(translate('Insert Lock')), value: 'lock'),
|
||||||
] +
|
] +
|
||||||
more,
|
more,
|
||||||
elevation: 8,
|
elevation: 8,
|
||||||
@ -841,7 +845,7 @@ void showSetOSPassword(BuildContext context) async {
|
|||||||
showAlertDialog(
|
showAlertDialog(
|
||||||
context,
|
context,
|
||||||
(setState) => Tuple3(
|
(setState) => Tuple3(
|
||||||
Text('Password required'),
|
Text(translate('Password required')),
|
||||||
Column(mainAxisSize: MainAxisSize.min, children: [
|
Column(mainAxisSize: MainAxisSize.min, children: [
|
||||||
PasswordWidget(controller: controller),
|
PasswordWidget(controller: controller),
|
||||||
]),
|
]),
|
||||||
@ -851,7 +855,7 @@ void showSetOSPassword(BuildContext context) async {
|
|||||||
onPressed: () {
|
onPressed: () {
|
||||||
Navigator.pop(context);
|
Navigator.pop(context);
|
||||||
},
|
},
|
||||||
child: Text('Cancel'),
|
child: Text(translate('Cancel')),
|
||||||
),
|
),
|
||||||
FlatButton(
|
FlatButton(
|
||||||
textColor: MyTheme.accent,
|
textColor: MyTheme.accent,
|
||||||
@ -860,7 +864,7 @@ void showSetOSPassword(BuildContext context) async {
|
|||||||
savePassword(FFI.id, text);
|
savePassword(FFI.id, text);
|
||||||
Navigator.pop(context);
|
Navigator.pop(context);
|
||||||
},
|
},
|
||||||
child: Text('OK'),
|
child: Text(translate('OK')),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
));
|
));
|
||||||
|
Loading…
x
Reference in New Issue
Block a user