234 lines
9.9 KiB
Dart
234 lines
9.9 KiB
Dart
import 'package:flutter/foundation.dart';
|
||
import 'package:flutter/material.dart';
|
||
|
||
class AppLocalizations {
|
||
AppLocalizations(this.locale);
|
||
|
||
final Locale locale;
|
||
|
||
static const supportedLocales = <Locale>[Locale('en'), Locale('zh')];
|
||
|
||
static const LocalizationsDelegate<AppLocalizations> delegate =
|
||
_AppLocalizationsDelegate();
|
||
|
||
static AppLocalizations of(BuildContext context) =>
|
||
Localizations.of<AppLocalizations>(context, AppLocalizations)!;
|
||
|
||
static const _values = <String, Map<String, String>>{
|
||
'en': {
|
||
'appName': 'RemoteDesk',
|
||
'devices': 'Devices',
|
||
'noDevices': 'No remote devices',
|
||
'noDevicesHint': 'Add a Linux or Windows device to start remote control.',
|
||
'addDevice': 'Add device',
|
||
'editDevice': 'Edit device',
|
||
'deviceName': 'Device name',
|
||
'devicePlatform': 'Device platform',
|
||
'linux': 'Linux',
|
||
'windows': 'Windows',
|
||
'address': 'Address',
|
||
'addressHint': 'host.example.com:39500',
|
||
'windowsAddressHint': 'windows.example.com:39501',
|
||
'linuxUser': 'Linux user',
|
||
'certificate': 'TLS certificate SHA-256',
|
||
'certificateHint': '64 lowercase hexadecimal characters',
|
||
'useRelay': 'Use Edge relay',
|
||
'useRelayHint':
|
||
'Route the encrypted Agent connection through the relay server.',
|
||
'edgeApiUrl': 'Edge API address',
|
||
'edgeApiUrlHint': 'https://edge.example.com/',
|
||
'agentPublicKey': 'Agent public key',
|
||
'agentPublicKeyHint': 'Value shown by the Linux pairing command',
|
||
'directConnection': 'Direct',
|
||
'windowsPlainConnection': 'Windows Agent (WebRTC)',
|
||
'relayConnection': 'Edge relay',
|
||
'automaticConnection': 'Automatic (direct, then relay)',
|
||
'connectionMode': 'Connection mode',
|
||
'automatic': 'Automatic',
|
||
'direct': 'Direct',
|
||
'relay': 'Relay',
|
||
'automaticConnectionHint':
|
||
'Try the direct route first and use the encrypted relay only when the network route fails.',
|
||
'directConnectionHint': 'Connect only to the saved Agent address.',
|
||
'relayConnectionHint': 'Always connect through the Edge relay.',
|
||
'windowsPlainWarning':
|
||
'WebRTC encrypts video and input, but the TCP signaling channel does not authenticate the host. Use a trusted LAN or private VPN. TOTP remains required.',
|
||
'save': 'Save',
|
||
'cancel': 'Cancel',
|
||
'connect': 'Connect',
|
||
'pair': 'Pair',
|
||
'edit': 'Edit',
|
||
'delete': 'Delete',
|
||
'deleteDevice': 'Delete device?',
|
||
'deleteDeviceBody': 'This removes the saved connection settings.',
|
||
'pairingCode': 'Pairing code',
|
||
'pairingCodeHint': '8-digit code shown on the Linux device',
|
||
'totpCode': 'Authenticator code',
|
||
'totpCodeHint': '6-digit code from your authenticator app',
|
||
'continueAction': 'Continue',
|
||
'settings': 'Settings',
|
||
'language': 'Language',
|
||
'english': 'English',
|
||
'chinese': 'Simplified Chinese',
|
||
'resolution': 'Remote resolution',
|
||
'frameRate': 'Frame rate',
|
||
'fps': '{value} fps',
|
||
'connecting': 'Connecting...',
|
||
'switchingToRelay': 'Direct route unavailable. Switching to relay...',
|
||
'authenticating': 'Authenticating...',
|
||
'openingDesktop': 'Opening desktop...',
|
||
'waitingForFrame': 'Waiting for desktop image...',
|
||
'connected': 'Connected',
|
||
'disconnected': 'Disconnected',
|
||
'disconnect': 'Disconnect',
|
||
'showKeyboard': 'Show keyboard',
|
||
'hideKeyboard': 'Hide keyboard',
|
||
'keyboardInput': 'Type on the remote device',
|
||
'enter': 'Enter',
|
||
'backspace': 'Backspace',
|
||
'tab': 'Tab',
|
||
'escape': 'Escape',
|
||
'invalidName': 'Enter a device name.',
|
||
'invalidAddress': 'Enter a valid WSS host or host:port.',
|
||
'invalidWindowsAddress': 'Enter a valid Windows host or host:port.',
|
||
'invalidUser': 'Enter a Linux user.',
|
||
'invalidCertificate': 'Enter the full 64-character SHA-256 fingerprint.',
|
||
'invalidEdgeUrl': 'Enter a valid HTTPS Edge API origin.',
|
||
'invalidAgentPublicKey': 'Enter the Agent\'s canonical public key.',
|
||
'invalidPairingCode': 'Enter exactly 8 digits.',
|
||
'invalidTotpCode': 'Enter exactly 6 digits.',
|
||
'errorTitle': 'Connection failed',
|
||
'errorNetwork': 'Could not reach the remote device.',
|
||
'errorCertificate': 'The TLS certificate does not match this device.',
|
||
'errorProtocol': 'The remote device uses an incompatible protocol.',
|
||
'errorAuthentication': 'Authentication failed. Pair this device again.',
|
||
'errorTotp':
|
||
'The authenticator code is invalid, expired, or already used.',
|
||
'errorPermission': 'Desktop control is not permitted for this client.',
|
||
'errorDesktop': 'The remote desktop could not be opened.',
|
||
'errorFrame': 'The remote desktop sent an invalid video frame.',
|
||
'errorUnknown': 'The remote session ended unexpectedly.',
|
||
'retry': 'Retry',
|
||
'close': 'Close',
|
||
},
|
||
'zh': {
|
||
'appName': 'RemoteDesk',
|
||
'devices': '设备',
|
||
'noDevices': '暂无远程设备',
|
||
'noDevicesHint': '添加 Linux 或 Windows 设备以开始远程控制。',
|
||
'addDevice': '添加设备',
|
||
'editDevice': '编辑设备',
|
||
'deviceName': '设备名称',
|
||
'devicePlatform': '设备平台',
|
||
'linux': 'Linux',
|
||
'windows': 'Windows',
|
||
'address': '地址',
|
||
'addressHint': 'host.example.com:39500',
|
||
'windowsAddressHint': 'windows.example.com:39501',
|
||
'linuxUser': 'Linux 用户',
|
||
'certificate': 'TLS 证书 SHA-256',
|
||
'certificateHint': '64 位小写十六进制字符',
|
||
'useRelay': '使用 Edge 中转',
|
||
'useRelayHint': '通过中转服务器传输端到端加密的 Agent 连接。',
|
||
'edgeApiUrl': 'Edge API 地址',
|
||
'edgeApiUrlHint': 'https://edge.example.com/',
|
||
'agentPublicKey': 'Agent 公钥',
|
||
'agentPublicKeyHint': 'Linux 配对命令显示的公钥',
|
||
'directConnection': '直连',
|
||
'windowsPlainConnection': 'Windows Agent(WebRTC)',
|
||
'relayConnection': 'Edge 中转',
|
||
'automaticConnection': '自动(直连优先,中转回退)',
|
||
'connectionMode': '连接模式',
|
||
'automatic': '自动',
|
||
'direct': '直连',
|
||
'relay': '中转',
|
||
'automaticConnectionHint': '优先尝试直连,仅在网络路径失败时使用端到端加密中转。',
|
||
'directConnectionHint': '仅连接已保存的 Agent 地址。',
|
||
'relayConnectionHint': '始终通过 Edge 中转连接。',
|
||
'windowsPlainWarning':
|
||
'WebRTC 会加密画面与输入,但 TCP 信令不会验证主机身份。请仅使用可信局域网或私有 VPN;TOTP 仍为必填验证。',
|
||
'save': '保存',
|
||
'cancel': '取消',
|
||
'connect': '连接',
|
||
'pair': '配对',
|
||
'edit': '编辑',
|
||
'delete': '删除',
|
||
'deleteDevice': '删除设备?',
|
||
'deleteDeviceBody': '这会移除已保存的连接设置。',
|
||
'pairingCode': '配对码',
|
||
'pairingCodeHint': 'Linux 设备上显示的 8 位数字',
|
||
'totpCode': '身份验证器动态码',
|
||
'totpCodeHint': '身份验证器应用中的 6 位动态码',
|
||
'continueAction': '继续',
|
||
'settings': '设置',
|
||
'language': '语言',
|
||
'english': 'English',
|
||
'chinese': '简体中文',
|
||
'resolution': '远程分辨率',
|
||
'frameRate': '帧率',
|
||
'fps': '{value} 帧/秒',
|
||
'connecting': '正在连接...',
|
||
'switchingToRelay': '直连路径不可用,正在切换到中转...',
|
||
'authenticating': '正在认证...',
|
||
'openingDesktop': '正在打开桌面...',
|
||
'waitingForFrame': '正在等待桌面画面...',
|
||
'connected': '已连接',
|
||
'disconnected': '已断开',
|
||
'disconnect': '断开连接',
|
||
'showKeyboard': '显示键盘',
|
||
'hideKeyboard': '隐藏键盘',
|
||
'keyboardInput': '输入到远程设备',
|
||
'enter': '回车',
|
||
'backspace': '退格',
|
||
'tab': '制表符',
|
||
'escape': '退出键',
|
||
'invalidName': '请输入设备名称。',
|
||
'invalidAddress': '请输入有效的 WSS 主机或主机:端口。',
|
||
'invalidWindowsAddress': '请输入有效的 Windows 主机或主机:端口。',
|
||
'invalidUser': '请输入 Linux 用户。',
|
||
'invalidCertificate': '请输入完整的 64 位 SHA-256 指纹。',
|
||
'invalidEdgeUrl': '请输入有效的 HTTPS Edge API 地址。',
|
||
'invalidAgentPublicKey': '请输入规范格式的 Agent 公钥。',
|
||
'invalidPairingCode': '请输入恰好 8 位数字。',
|
||
'invalidTotpCode': '请输入恰好 6 位数字。',
|
||
'errorTitle': '连接失败',
|
||
'errorNetwork': '无法连接远程设备。',
|
||
'errorCertificate': 'TLS 证书与该设备不匹配。',
|
||
'errorProtocol': '远程设备使用了不兼容的协议。',
|
||
'errorAuthentication': '认证失败,请重新配对该设备。',
|
||
'errorTotp': '动态验证码无效、已过期或已被使用。',
|
||
'errorPermission': '此客户端没有桌面控制权限。',
|
||
'errorDesktop': '无法打开远程桌面。',
|
||
'errorFrame': '远程桌面发送了无效的视频帧。',
|
||
'errorUnknown': '远程会话意外结束。',
|
||
'retry': '重试',
|
||
'close': '关闭',
|
||
},
|
||
};
|
||
|
||
String text(String key, [Map<String, Object> values = const {}]) {
|
||
var result = (_values[locale.languageCode] ?? _values['en']!)[key] ?? key;
|
||
for (final entry in values.entries) {
|
||
result = result.replaceAll('{${entry.key}}', '${entry.value}');
|
||
}
|
||
return result;
|
||
}
|
||
}
|
||
|
||
class _AppLocalizationsDelegate
|
||
extends LocalizationsDelegate<AppLocalizations> {
|
||
const _AppLocalizationsDelegate();
|
||
|
||
@override
|
||
bool isSupported(Locale locale) => AppLocalizations.supportedLocales.any(
|
||
(supported) => supported.languageCode == locale.languageCode,
|
||
);
|
||
|
||
@override
|
||
Future<AppLocalizations> load(Locale locale) =>
|
||
SynchronousFuture(AppLocalizations(locale));
|
||
|
||
@override
|
||
bool shouldReload(_AppLocalizationsDelegate old) => false;
|
||
}
|