mirror of
https://github.com/rustdesk/rustdesk.git
synced 2026-03-14 16:51:04 +03:00
Merge branch 'rustdesk:master' into master
This commit is contained in:
72
src/cli.rs
72
src/cli.rs
@@ -1,9 +1,12 @@
|
||||
use crate::client::*;
|
||||
use hbb_common::{
|
||||
config::PeerConfig,
|
||||
config::READ_TIMEOUT,
|
||||
futures::{SinkExt, StreamExt},
|
||||
log,
|
||||
message_proto::*,
|
||||
protobuf::Message as _,
|
||||
rendezvous_proto::ConnType,
|
||||
tokio::{self, sync::mpsc},
|
||||
Stream,
|
||||
};
|
||||
@@ -33,14 +36,18 @@ impl Session {
|
||||
.lc
|
||||
.write()
|
||||
.unwrap()
|
||||
.initialize(id.to_owned(), false, true);
|
||||
.initialize(id.to_owned(), ConnType::PORT_FORWARD);
|
||||
session
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl Interface for Session {
|
||||
fn msgbox(&self, msgtype: &str, title: &str, text: &str) {
|
||||
fn get_login_config_handler(&self) -> Arc<RwLock<LoginConfigHandler>> {
|
||||
return self.lc.clone();
|
||||
}
|
||||
|
||||
fn msgbox(&self, msgtype: &str, title: &str, text: &str, link: &str) {
|
||||
if msgtype == "input-password" {
|
||||
self.sender
|
||||
.send(Data::Login((self.password.clone(), true)))
|
||||
@@ -57,16 +64,15 @@ impl Interface for Session {
|
||||
}
|
||||
|
||||
fn handle_login_error(&mut self, err: &str) -> bool {
|
||||
self.lc.write().unwrap().handle_login_error(err, self)
|
||||
handle_login_error(self.lc.clone(), err, self)
|
||||
}
|
||||
|
||||
fn handle_peer_info(&mut self, pi: PeerInfo) {
|
||||
let username = self.lc.read().unwrap().get_username(&pi);
|
||||
self.lc.write().unwrap().handle_peer_info(username, pi);
|
||||
self.lc.write().unwrap().handle_peer_info(&pi);
|
||||
}
|
||||
|
||||
async fn handle_hash(&mut self, hash: Hash, peer: &mut Stream) {
|
||||
handle_hash(self.lc.clone(), hash, self, peer).await;
|
||||
async fn handle_hash(&mut self, pass: &str, hash: Hash, peer: &mut Stream) {
|
||||
handle_hash(self.lc.clone(), &pass, hash, self, peer).await;
|
||||
}
|
||||
|
||||
async fn handle_login_from_ui(&mut self, password: String, remember: bool, peer: &mut Stream) {
|
||||
@@ -82,6 +88,42 @@ impl Interface for Session {
|
||||
}
|
||||
}
|
||||
|
||||
#[tokio::main(flavor = "current_thread")]
|
||||
pub async fn connect_test(id: &str, key: String, token: String) {
|
||||
let (sender, mut receiver) = mpsc::unbounded_channel::<Data>();
|
||||
let handler = Session::new(&id, sender);
|
||||
match crate::client::Client::start(id, &key, &token, ConnType::PORT_FORWARD, handler).await {
|
||||
Err(err) => {
|
||||
log::error!("Failed to connect {}: {}", &id, err);
|
||||
}
|
||||
Ok((mut stream, direct)) => {
|
||||
log::info!("direct: {}", direct);
|
||||
// rpassword::prompt_password("Input anything to exit").ok();
|
||||
loop {
|
||||
tokio::select! {
|
||||
res = hbb_common::timeout(READ_TIMEOUT, stream.next()) => match res {
|
||||
Err(_) => {
|
||||
log::error!("Timeout");
|
||||
break;
|
||||
}
|
||||
Ok(Some(Ok(bytes))) => {
|
||||
let msg_in = Message::parse_from_bytes(&bytes).unwrap();
|
||||
match msg_in.union {
|
||||
Some(message::Union::Hash(hash)) => {
|
||||
log::info!("Got hash");
|
||||
break;
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[tokio::main(flavor = "current_thread")]
|
||||
pub async fn start_one_port_forward(
|
||||
id: String,
|
||||
@@ -95,9 +137,19 @@ pub async fn start_one_port_forward(
|
||||
crate::common::test_nat_type();
|
||||
let (sender, mut receiver) = mpsc::unbounded_channel::<Data>();
|
||||
let handler = Session::new(&id, sender);
|
||||
handler.lc.write().unwrap().port_forward = (remote_host, remote_port);
|
||||
if let Err(err) =
|
||||
crate::port_forward::listen(handler.id.clone(), port, handler.clone(), receiver, &key, &token).await
|
||||
if let Err(err) = crate::port_forward::listen(
|
||||
handler.id.clone(),
|
||||
handler.password.clone(),
|
||||
port,
|
||||
handler.clone(),
|
||||
receiver,
|
||||
&key,
|
||||
&token,
|
||||
handler.lc.clone(),
|
||||
remote_host,
|
||||
remote_port,
|
||||
)
|
||||
.await
|
||||
{
|
||||
log::error!("Failed to listen on {}: {}", port, err);
|
||||
}
|
||||
|
||||
175
src/client.rs
175
src/client.rs
@@ -6,8 +6,6 @@ use cpal::{
|
||||
};
|
||||
use magnum_opus::{Channels::*, Decoder as AudioDecoder};
|
||||
use sha2::{Digest, Sha256};
|
||||
#[cfg(any(target_os = "android", target_os = "ios", feature = "flutter"))]
|
||||
use std::sync::atomic::Ordering;
|
||||
use std::{
|
||||
collections::HashMap,
|
||||
net::SocketAddr,
|
||||
@@ -49,10 +47,7 @@ pub use super::lang::*;
|
||||
pub mod file_trait;
|
||||
pub mod helper;
|
||||
pub mod io_loop;
|
||||
use crate::{
|
||||
server::video_service::{SCRAP_X11_REF_URL, SCRAP_X11_REQUIRED},
|
||||
ui_session_interface::global_save_keyboard_mode,
|
||||
};
|
||||
use crate::server::video_service::{SCRAP_X11_REF_URL, SCRAP_X11_REQUIRED};
|
||||
pub static SERVER_KEYBOARD_ENABLED: AtomicBool = AtomicBool::new(true);
|
||||
pub static SERVER_FILE_TRANSFER_ENABLED: AtomicBool = AtomicBool::new(true);
|
||||
pub static SERVER_CLIPBOARD_ENABLED: AtomicBool = AtomicBool::new(true);
|
||||
@@ -172,12 +167,10 @@ impl Client {
|
||||
interface: impl Interface,
|
||||
) -> ResultType<(Stream, bool)> {
|
||||
// to-do: remember the port for each peer, so that we can retry easier
|
||||
let any_addr = Config::get_any_listen_addr();
|
||||
if crate::is_ip(peer) {
|
||||
if hbb_common::is_ip_str(peer) {
|
||||
return Ok((
|
||||
socket_client::connect_tcp(
|
||||
crate::check_port(peer, RELAY_PORT + 1),
|
||||
any_addr,
|
||||
RENDEZVOUS_TIMEOUT,
|
||||
)
|
||||
.await?,
|
||||
@@ -185,13 +178,12 @@ impl Client {
|
||||
));
|
||||
}
|
||||
let (mut rendezvous_server, servers, contained) = crate::get_rendezvous_server(1_000).await;
|
||||
let mut socket =
|
||||
socket_client::connect_tcp(&*rendezvous_server, any_addr, RENDEZVOUS_TIMEOUT).await;
|
||||
let mut socket = socket_client::connect_tcp(&*rendezvous_server, RENDEZVOUS_TIMEOUT).await;
|
||||
debug_assert!(!servers.contains(&rendezvous_server));
|
||||
if socket.is_err() && !servers.is_empty() {
|
||||
log::info!("try the other servers: {:?}", servers);
|
||||
for server in servers {
|
||||
socket = socket_client::connect_tcp(&*server, any_addr, RENDEZVOUS_TIMEOUT).await;
|
||||
socket = socket_client::connect_tcp(&*server, RENDEZVOUS_TIMEOUT).await;
|
||||
if socket.is_ok() {
|
||||
rendezvous_server = server;
|
||||
break;
|
||||
@@ -208,7 +200,7 @@ impl Client {
|
||||
let mut relay_server = "".to_owned();
|
||||
|
||||
let start = std::time::Instant::now();
|
||||
let mut peer_addr = any_addr;
|
||||
let mut peer_addr = Config::get_any_listen_addr(true);
|
||||
let mut peer_nat_type = NatType::UNKNOWN_NAT;
|
||||
let my_nat_type = crate::get_nat_type(100).await;
|
||||
let mut is_local = false;
|
||||
@@ -269,9 +261,15 @@ impl Client {
|
||||
rr.relay_server
|
||||
);
|
||||
signed_id_pk = rr.pk().into();
|
||||
let mut conn =
|
||||
Self::create_relay(peer, rr.uuid, rr.relay_server, key, conn_type)
|
||||
.await?;
|
||||
let mut conn = Self::create_relay(
|
||||
peer,
|
||||
rr.uuid,
|
||||
rr.relay_server,
|
||||
key,
|
||||
conn_type,
|
||||
my_addr.is_ipv4(),
|
||||
)
|
||||
.await?;
|
||||
Self::secure_connection(
|
||||
peer,
|
||||
signed_id_pk,
|
||||
@@ -378,7 +376,8 @@ impl Client {
|
||||
log::info!("peer address: {}, timeout: {}", peer, connect_timeout);
|
||||
let start = std::time::Instant::now();
|
||||
// NOTICE: Socks5 is be used event in intranet. Which may be not a good way.
|
||||
let mut conn = socket_client::connect_tcp(peer, local_addr, connect_timeout).await;
|
||||
let mut conn =
|
||||
socket_client::connect_tcp_local(peer, Some(local_addr), connect_timeout).await;
|
||||
let mut direct = !conn.is_err();
|
||||
if interface.is_force_relay() || conn.is_err() {
|
||||
if !relay_server.is_empty() {
|
||||
@@ -422,7 +421,7 @@ impl Client {
|
||||
key: &str,
|
||||
conn: &mut Stream,
|
||||
direct: bool,
|
||||
mut interface: impl Interface,
|
||||
interface: impl Interface,
|
||||
) -> ResultType<()> {
|
||||
let rs_pk = get_rs_pk(if key.is_empty() {
|
||||
hbb_common::config::RS_PUB_KEY
|
||||
@@ -511,16 +510,16 @@ impl Client {
|
||||
token: &str,
|
||||
conn_type: ConnType,
|
||||
) -> ResultType<Stream> {
|
||||
let any_addr = Config::get_any_listen_addr();
|
||||
let mut succeed = false;
|
||||
let mut uuid = "".to_owned();
|
||||
let mut ipv4 = true;
|
||||
for i in 1..=3 {
|
||||
// use different socket due to current hbbs implement requiring different nat address for each attempt
|
||||
let mut socket =
|
||||
socket_client::connect_tcp(rendezvous_server, any_addr, RENDEZVOUS_TIMEOUT)
|
||||
.await
|
||||
.with_context(|| "Failed to connect to rendezvous server")?;
|
||||
let mut socket = socket_client::connect_tcp(rendezvous_server, RENDEZVOUS_TIMEOUT)
|
||||
.await
|
||||
.with_context(|| "Failed to connect to rendezvous server")?;
|
||||
|
||||
ipv4 = socket.local_addr().is_ipv4();
|
||||
let mut msg_out = RendezvousMessage::new();
|
||||
uuid = Uuid::new_v4().to_string();
|
||||
log::info!(
|
||||
@@ -555,7 +554,7 @@ impl Client {
|
||||
if !succeed {
|
||||
bail!("Timeout");
|
||||
}
|
||||
Self::create_relay(peer, uuid, relay_server, key, conn_type).await
|
||||
Self::create_relay(peer, uuid, relay_server, key, conn_type, ipv4).await
|
||||
}
|
||||
|
||||
/// Create a relay connection to the server.
|
||||
@@ -565,10 +564,10 @@ impl Client {
|
||||
relay_server: String,
|
||||
key: &str,
|
||||
conn_type: ConnType,
|
||||
ipv4: bool,
|
||||
) -> ResultType<Stream> {
|
||||
let mut conn = socket_client::connect_tcp(
|
||||
crate::check_port(relay_server, RELAY_PORT),
|
||||
Config::get_any_listen_addr(),
|
||||
socket_client::ipv4_to_ipv6(crate::check_port(relay_server, RELAY_PORT), ipv4),
|
||||
CONNECT_TIMEOUT,
|
||||
)
|
||||
.await
|
||||
@@ -897,6 +896,8 @@ pub struct LoginConfigHandler {
|
||||
pub supported_encoding: Option<(bool, bool)>,
|
||||
pub restarting_remote_device: bool,
|
||||
pub force_relay: bool,
|
||||
pub direct: Option<bool>,
|
||||
pub received: bool,
|
||||
}
|
||||
|
||||
impl Deref for LoginConfigHandler {
|
||||
@@ -934,6 +935,8 @@ impl LoginConfigHandler {
|
||||
self.supported_encoding = None;
|
||||
self.restarting_remote_device = false;
|
||||
self.force_relay = !self.get_option("force-always-relay").is_empty();
|
||||
self.direct = None;
|
||||
self.received = false;
|
||||
}
|
||||
|
||||
/// Check if the client should auto login.
|
||||
@@ -989,6 +992,17 @@ impl LoginConfigHandler {
|
||||
self.save_config(config);
|
||||
}
|
||||
|
||||
/// Save keyboard mode to the current config.
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `value` - The view style to be saved.
|
||||
pub fn save_keyboard_mode(&mut self, value: String) {
|
||||
let mut config = self.load_config();
|
||||
config.keyboard_mode = value;
|
||||
self.save_config(config);
|
||||
}
|
||||
|
||||
/// Save scroll style to the current config.
|
||||
///
|
||||
/// # Arguments
|
||||
@@ -1332,32 +1346,6 @@ impl LoginConfigHandler {
|
||||
}
|
||||
}
|
||||
|
||||
/// Handle login error.
|
||||
/// Return true if the password is wrong, return false if there's an actual error.
|
||||
pub fn handle_login_error(&mut self, err: &str, interface: &impl Interface) -> bool {
|
||||
if err == "Wrong Password" {
|
||||
self.password = Default::default();
|
||||
interface.msgbox("re-input-password", err, "Do you want to enter again?", "");
|
||||
true
|
||||
} else if err == "No Password Access" {
|
||||
self.password = Default::default();
|
||||
interface.msgbox(
|
||||
"wait-remote-accept-nook",
|
||||
"Prompt",
|
||||
"Please wait for the remote side to accept your session request...",
|
||||
"",
|
||||
);
|
||||
true
|
||||
} else {
|
||||
if err.contains(SCRAP_X11_REQUIRED) {
|
||||
interface.msgbox("error", "Login Error", err, SCRAP_X11_REF_URL);
|
||||
} else {
|
||||
interface.msgbox("error", "Login Error", err, "");
|
||||
}
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
/// Get user name.
|
||||
/// Return the name of the given peer. If the peer has no name, return the name in the config.
|
||||
///
|
||||
@@ -1382,9 +1370,6 @@ impl LoginConfigHandler {
|
||||
if !pi.version.is_empty() {
|
||||
self.version = hbb_common::get_version_number(&pi.version);
|
||||
}
|
||||
if hbb_common::get_version_number(&pi.version) < hbb_common::get_version_number("1.2.0") {
|
||||
global_save_keyboard_mode("legacy".to_owned());
|
||||
}
|
||||
self.features = pi.features.clone().into_option();
|
||||
let serde = PeerInfoSerde {
|
||||
username: pi.username.clone(),
|
||||
@@ -1407,6 +1392,14 @@ impl LoginConfigHandler {
|
||||
log::debug!("remove password of {}", self.id);
|
||||
}
|
||||
}
|
||||
if config.keyboard_mode == "" {
|
||||
if hbb_common::get_version_number(&pi.version) < hbb_common::get_version_number("1.2.0")
|
||||
{
|
||||
config.keyboard_mode = "legacy".to_string();
|
||||
} else {
|
||||
config.keyboard_mode = "map".to_string();
|
||||
}
|
||||
}
|
||||
self.conn_id = pi.conn_id;
|
||||
// no matter if change, for update file time
|
||||
self.save_config(config);
|
||||
@@ -1489,6 +1482,19 @@ impl LoginConfigHandler {
|
||||
msg_out.set_misc(misc);
|
||||
msg_out
|
||||
}
|
||||
|
||||
pub fn set_force_relay(&mut self, direct: bool, received: bool) {
|
||||
self.force_relay = false;
|
||||
if direct && !received {
|
||||
let errno = errno::errno().0;
|
||||
log::info!("errno is {}", errno);
|
||||
// TODO: check mac and ios
|
||||
if cfg!(windows) && errno == 10054 || !cfg!(windows) && errno == 104 {
|
||||
self.force_relay = true;
|
||||
self.set_option("force-always-relay".to_owned(), "Y".to_owned());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Media data.
|
||||
@@ -1715,6 +1721,36 @@ fn _input_os_password(p: String, activate: bool, interface: impl Interface) {
|
||||
interface.send(Data::Message(msg_out));
|
||||
}
|
||||
|
||||
/// Handle login error.
|
||||
/// Return true if the password is wrong, return false if there's an actual error.
|
||||
pub fn handle_login_error(
|
||||
lc: Arc<RwLock<LoginConfigHandler>>,
|
||||
err: &str,
|
||||
interface: &impl Interface,
|
||||
) -> bool {
|
||||
if err == "Wrong Password" {
|
||||
lc.write().unwrap().password = Default::default();
|
||||
interface.msgbox("re-input-password", err, "Do you want to enter again?", "");
|
||||
true
|
||||
} else if err == "No Password Access" {
|
||||
lc.write().unwrap().password = Default::default();
|
||||
interface.msgbox(
|
||||
"wait-remote-accept-nook",
|
||||
"Prompt",
|
||||
"Please wait for the remote side to accept your session request...",
|
||||
"",
|
||||
);
|
||||
true
|
||||
} else {
|
||||
if err.contains(SCRAP_X11_REQUIRED) {
|
||||
interface.msgbox("error", "Login Error", err, SCRAP_X11_REF_URL);
|
||||
} else {
|
||||
interface.msgbox("error", "Login Error", err, "");
|
||||
}
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
/// Handle hash message sent by peer.
|
||||
/// Hash will be used for login.
|
||||
///
|
||||
@@ -1803,17 +1839,23 @@ pub trait Interface: Send + Clone + 'static + Sized {
|
||||
fn msgbox(&self, msgtype: &str, title: &str, text: &str, link: &str);
|
||||
fn handle_login_error(&mut self, err: &str) -> bool;
|
||||
fn handle_peer_info(&mut self, pi: PeerInfo);
|
||||
fn set_force_relay(&mut self, direct: bool, received: bool);
|
||||
fn is_file_transfer(&self) -> bool;
|
||||
fn is_port_forward(&self) -> bool;
|
||||
fn is_rdp(&self) -> bool;
|
||||
fn on_error(&self, err: &str) {
|
||||
self.msgbox("error", "Error", err, "");
|
||||
}
|
||||
fn is_force_relay(&self) -> bool;
|
||||
async fn handle_hash(&mut self, pass: &str, hash: Hash, peer: &mut Stream);
|
||||
async fn handle_login_from_ui(&mut self, password: String, remember: bool, peer: &mut Stream);
|
||||
async fn handle_test_delay(&mut self, t: TestDelay, peer: &mut Stream);
|
||||
|
||||
fn get_login_config_handler(&self) -> Arc<RwLock<LoginConfigHandler>>;
|
||||
fn set_force_relay(&self, direct: bool, received: bool) {
|
||||
self.get_login_config_handler()
|
||||
.write()
|
||||
.unwrap()
|
||||
.set_force_relay(direct, received);
|
||||
}
|
||||
fn is_force_relay(&self) -> bool {
|
||||
self.get_login_config_handler().read().unwrap().force_relay
|
||||
}
|
||||
}
|
||||
|
||||
/// Data used by the client interface.
|
||||
@@ -1979,11 +2021,10 @@ lazy_static::lazy_static! {
|
||||
/// * `title` - The title of the message.
|
||||
/// * `text` - The text of the message.
|
||||
#[inline]
|
||||
pub fn check_if_retry(msgtype: &str, title: &str, text: &str) -> bool {
|
||||
pub fn check_if_retry(msgtype: &str, title: &str, text: &str, retry_for_relay: bool) -> bool {
|
||||
msgtype == "error"
|
||||
&& title == "Connection Error"
|
||||
&& (text.contains("10054")
|
||||
|| text.contains("104")
|
||||
&& ((text.contains("10054") || text.contains("104")) && retry_for_relay
|
||||
|| (!text.to_lowercase().contains("offline")
|
||||
&& !text.to_lowercase().contains("exist")
|
||||
&& !text.to_lowercase().contains("handshake")
|
||||
@@ -1991,7 +2032,8 @@ pub fn check_if_retry(msgtype: &str, title: &str, text: &str) -> bool {
|
||||
&& !text.to_lowercase().contains("resolve")
|
||||
&& !text.to_lowercase().contains("mismatch")
|
||||
&& !text.to_lowercase().contains("manually")
|
||||
&& !text.to_lowercase().contains("not allowed")))
|
||||
&& !text.to_lowercase().contains("not allowed")
|
||||
&& !text.to_lowercase().contains("reset by the peer")))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
@@ -2024,8 +2066,3 @@ fn decode_id_pk(signed: &[u8], key: &sign::PublicKey) -> ResultType<(String, [u8
|
||||
bail!("Wrong public length");
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(any(target_os = "android", target_os = "ios", feature = "flutter"))]
|
||||
pub fn disable_keyboard_listening() {
|
||||
crate::ui_session_interface::KEYBOARD_HOOKED.store(true, Ordering::SeqCst);
|
||||
}
|
||||
|
||||
@@ -22,7 +22,7 @@ pub trait FileManager: Interface {
|
||||
|
||||
#[cfg(any(target_os = "android", target_os = "ios", feature = "cli"))]
|
||||
fn read_dir(&self, path: &str, include_hidden: bool) -> String {
|
||||
use crate::flutter::make_fd_to_json;
|
||||
use crate::common::make_fd_to_json;
|
||||
match fs::read_dir(&fs::get_path(path), include_hidden) {
|
||||
Ok(fd) => make_fd_to_json(fd.id, fd.path, &fd.entries),
|
||||
Err(_) => "".into(),
|
||||
|
||||
@@ -107,6 +107,7 @@ impl<T: InvokeUiSession> Remote<T> {
|
||||
SERVER_CLIPBOARD_ENABLED.store(true, Ordering::SeqCst);
|
||||
SERVER_FILE_TRANSFER_ENABLED.store(true, Ordering::SeqCst);
|
||||
self.handler.set_connection_type(peer.is_secured(), direct); // flutter -> connection_ready
|
||||
self.handler.set_connection_info(direct, false);
|
||||
|
||||
// just build for now
|
||||
#[cfg(not(windows))]
|
||||
@@ -144,7 +145,10 @@ impl<T: InvokeUiSession> Remote<T> {
|
||||
}
|
||||
Ok(ref bytes) => {
|
||||
last_recv_time = Instant::now();
|
||||
received = true;
|
||||
if !received {
|
||||
received = true;
|
||||
self.handler.set_connection_info(direct, true);
|
||||
}
|
||||
self.data_count.fetch_add(bytes.len(), Ordering::Relaxed);
|
||||
if !self.handle_msg_from_peer(bytes, &mut peer).await {
|
||||
break
|
||||
@@ -986,7 +990,7 @@ impl<T: InvokeUiSession> Remote<T> {
|
||||
self.video_sender.send(MediaData::Reset).ok();
|
||||
if s.width > 0 && s.height > 0 {
|
||||
self.handler
|
||||
.set_display(s.x, s.y, s.width, s.height, s.cursor_embeded);
|
||||
.set_display(s.x, s.y, s.width, s.height, s.cursor_embedded);
|
||||
}
|
||||
}
|
||||
Some(misc::Union::CloseReason(c)) => {
|
||||
|
||||
119
src/common.rs
119
src/common.rs
@@ -3,6 +3,14 @@ use std::{
|
||||
sync::{Arc, Mutex},
|
||||
};
|
||||
|
||||
#[derive(Debug, Eq, PartialEq)]
|
||||
pub enum GrabState {
|
||||
Ready,
|
||||
Run,
|
||||
Wait,
|
||||
Exit,
|
||||
}
|
||||
|
||||
#[cfg(not(any(target_os = "android", target_os = "ios")))]
|
||||
pub use arboard::Clipboard as ClipboardContext;
|
||||
|
||||
@@ -10,8 +18,7 @@ pub use arboard::Clipboard as ClipboardContext;
|
||||
use hbb_common::compress::decompress;
|
||||
use hbb_common::{
|
||||
allow_err,
|
||||
anyhow::bail,
|
||||
compress::{compress as compress_func},
|
||||
compress::compress as compress_func,
|
||||
config::{self, Config, COMPRESS_LEVEL, RENDEZVOUS_TIMEOUT},
|
||||
get_version_number, log,
|
||||
message_proto::*,
|
||||
@@ -285,15 +292,7 @@ async fn test_nat_type_() -> ResultType<bool> {
|
||||
let start = std::time::Instant::now();
|
||||
let (rendezvous_server, _, _) = get_rendezvous_server(1_000).await;
|
||||
let server1 = rendezvous_server;
|
||||
let tmp: Vec<&str> = server1.split(":").collect();
|
||||
if tmp.len() != 2 {
|
||||
bail!("Invalid server address: {}", server1);
|
||||
}
|
||||
let port: u16 = tmp[1].parse()?;
|
||||
if port == 0 {
|
||||
bail!("Invalid server address: {}", server1);
|
||||
}
|
||||
let server2 = format!("{}:{}", tmp[0], port - 1);
|
||||
let server2 = crate::increase_port(&server1, -1);
|
||||
let mut msg_out = RendezvousMessage::new();
|
||||
let serial = Config::get_serial();
|
||||
msg_out.set_test_nat_request(TestNatRequest {
|
||||
@@ -302,21 +301,18 @@ async fn test_nat_type_() -> ResultType<bool> {
|
||||
});
|
||||
let mut port1 = 0;
|
||||
let mut port2 = 0;
|
||||
let server1 = socket_client::get_target_addr(&server1)?;
|
||||
let server2 = socket_client::get_target_addr(&server2)?;
|
||||
let mut addr = Config::get_any_listen_addr();
|
||||
for i in 0..2 {
|
||||
let mut socket = socket_client::connect_tcp(
|
||||
if i == 0 {
|
||||
server1.clone()
|
||||
} else {
|
||||
server2.clone()
|
||||
},
|
||||
addr,
|
||||
if i == 0 { &*server1 } else { &*server2 },
|
||||
RENDEZVOUS_TIMEOUT,
|
||||
)
|
||||
.await?;
|
||||
addr = socket.local_addr();
|
||||
if i == 0 {
|
||||
Config::set_option(
|
||||
"local-ip-addr".to_owned(),
|
||||
socket.local_addr().ip().to_string(),
|
||||
);
|
||||
}
|
||||
socket.send(&msg_out).await?;
|
||||
if let Some(Ok(bytes)) = socket.next_timeout(RENDEZVOUS_TIMEOUT).await {
|
||||
if let Ok(msg_in) = RendezvousMessage::parse_from_bytes(&bytes) {
|
||||
@@ -339,7 +335,6 @@ async fn test_nat_type_() -> ResultType<bool> {
|
||||
break;
|
||||
}
|
||||
}
|
||||
Config::set_option("local-ip-addr".to_owned(), addr.ip().to_string());
|
||||
let ok = port1 > 0 && port2 > 0;
|
||||
if ok {
|
||||
let t = if port1 == port2 {
|
||||
@@ -360,13 +355,7 @@ pub async fn get_rendezvous_server(ms_timeout: u64) -> (String, Vec<String>, boo
|
||||
let (mut a, mut b) = get_rendezvous_server_(ms_timeout).await;
|
||||
let mut b: Vec<String> = b
|
||||
.drain(..)
|
||||
.map(|x| {
|
||||
if !x.contains(":") {
|
||||
format!("{}:{}", x, config::RENDEZVOUS_PORT)
|
||||
} else {
|
||||
x
|
||||
}
|
||||
})
|
||||
.map(|x| socket_client::check_port(x, config::RENDEZVOUS_PORT))
|
||||
.collect();
|
||||
let c = if b.contains(&a) {
|
||||
b = b.drain(..).filter(|x| x != &a).collect();
|
||||
@@ -416,7 +405,6 @@ async fn test_rendezvous_server_() {
|
||||
let tm = std::time::Instant::now();
|
||||
if socket_client::connect_tcp(
|
||||
crate::check_port(&host, RENDEZVOUS_PORT),
|
||||
Config::get_any_listen_addr(),
|
||||
RENDEZVOUS_TIMEOUT,
|
||||
)
|
||||
.await
|
||||
@@ -473,11 +461,12 @@ pub fn username() -> String {
|
||||
|
||||
#[inline]
|
||||
pub fn check_port<T: std::string::ToString>(host: T, port: i32) -> String {
|
||||
let host = host.to_string();
|
||||
if !host.contains(":") {
|
||||
return format!("{}:{}", host, port);
|
||||
}
|
||||
return host;
|
||||
hbb_common::socket_client::check_port(host, port)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn increase_port<T: std::string::ToString>(host: T, offset: i32) -> String {
|
||||
hbb_common::socket_client::increase_port(host, offset)
|
||||
}
|
||||
|
||||
pub const POSTFIX_SERVICE: &'static str = "_service";
|
||||
@@ -516,10 +505,9 @@ pub fn check_software_update() {
|
||||
async fn check_software_update_() -> hbb_common::ResultType<()> {
|
||||
sleep(3.).await;
|
||||
|
||||
let rendezvous_server =
|
||||
socket_client::get_target_addr(&format!("rs-sg.rustdesk.com:{}", config::RENDEZVOUS_PORT))?;
|
||||
let mut socket =
|
||||
socket_client::new_udp(Config::get_any_listen_addr(), RENDEZVOUS_TIMEOUT).await?;
|
||||
let rendezvous_server = format!("rs-sg.rustdesk.com:{}", config::RENDEZVOUS_PORT);
|
||||
let (mut socket, rendezvous_server) =
|
||||
socket_client::new_udp_for(&rendezvous_server, RENDEZVOUS_TIMEOUT).await?;
|
||||
|
||||
let mut msg_out = RendezvousMessage::new();
|
||||
msg_out.set_software_update(SoftwareUpdate {
|
||||
@@ -559,12 +547,6 @@ pub fn get_full_name() -> String {
|
||||
)
|
||||
}
|
||||
|
||||
pub fn is_ip(id: &str) -> bool {
|
||||
hbb_common::regex::Regex::new(r"^\d+\.\d+\.\d+\.\d+(:\d+)?$")
|
||||
.unwrap()
|
||||
.is_match(id)
|
||||
}
|
||||
|
||||
pub fn is_setup(name: &str) -> bool {
|
||||
name.to_lowercase().ends_with("install.exe")
|
||||
}
|
||||
@@ -595,29 +577,24 @@ pub fn get_api_server(api: String, custom: String) -> String {
|
||||
return lic.api.clone();
|
||||
}
|
||||
}
|
||||
let s = get_custom_rendezvous_server(custom);
|
||||
if !s.is_empty() {
|
||||
if s.contains(':') {
|
||||
let tmp: Vec<&str> = s.split(":").collect();
|
||||
if tmp.len() == 2 {
|
||||
let port: u16 = tmp[1].parse().unwrap_or(0);
|
||||
if port > 2 {
|
||||
return format!("http://{}:{}", tmp[0], port - 2);
|
||||
}
|
||||
}
|
||||
let s0 = get_custom_rendezvous_server(custom);
|
||||
if !s0.is_empty() {
|
||||
let s = crate::increase_port(&s0, -2);
|
||||
if s == s0 {
|
||||
format!("http://{}:{}", s, config::RENDEZVOUS_PORT - 2);
|
||||
} else {
|
||||
return format!("http://{}:{}", s, config::RENDEZVOUS_PORT - 2);
|
||||
format!("http://{}", s);
|
||||
}
|
||||
}
|
||||
"https://admin.rustdesk.com".to_owned()
|
||||
}
|
||||
|
||||
pub fn get_audit_server(api: String, custom: String) -> String {
|
||||
pub fn get_audit_server(api: String, custom: String, typ: String) -> String {
|
||||
let url = get_api_server(api, custom);
|
||||
if url.is_empty() || url.contains("rustdesk.com") {
|
||||
return "".to_owned();
|
||||
}
|
||||
format!("{}/api/audit", url)
|
||||
format!("{}/api/audit/{}", url, typ)
|
||||
}
|
||||
|
||||
pub async fn post_request(url: String, body: String, header: &str) -> ResultType<String> {
|
||||
@@ -661,7 +638,7 @@ pub async fn post_request(url: String, body: String, header: &str) -> ResultType
|
||||
if !res.is_empty() {
|
||||
return Ok(res);
|
||||
}
|
||||
bail!(String::from_utf8_lossy(&output.stderr).to_string());
|
||||
hbb_common::bail!(String::from_utf8_lossy(&output.stderr).to_string());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -691,3 +668,27 @@ lazy_static::lazy_static! {
|
||||
lazy_static::lazy_static! {
|
||||
pub static ref IS_X11: Mutex<bool> = Mutex::new("x11" == hbb_common::platform::linux::get_display_server());
|
||||
}
|
||||
|
||||
pub fn make_fd_to_json(id: i32, path: String, entries: &Vec<FileEntry>) -> String {
|
||||
use serde_json::json;
|
||||
let mut fd_json = serde_json::Map::new();
|
||||
fd_json.insert("id".into(), json!(id));
|
||||
fd_json.insert("path".into(), json!(path));
|
||||
|
||||
let mut entries_out = vec![];
|
||||
for entry in entries {
|
||||
let mut entry_map = serde_json::Map::new();
|
||||
entry_map.insert("entry_type".into(), json!(entry.entry_type.value()));
|
||||
entry_map.insert("name".into(), json!(entry.name));
|
||||
entry_map.insert("size".into(), json!(entry.size));
|
||||
entry_map.insert("modified_time".into(), json!(entry.modified_time));
|
||||
entries_out.push(entry_map);
|
||||
}
|
||||
fd_json.insert("entries".into(), json!(entries_out));
|
||||
serde_json::to_string(&fd_json).unwrap_or("".into())
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test_common {
|
||||
use super::*;
|
||||
}
|
||||
|
||||
@@ -38,6 +38,17 @@ pub fn core_main() -> Option<Vec<String>> {
|
||||
}
|
||||
i += 1;
|
||||
}
|
||||
#[cfg(target_os = "linux")]
|
||||
#[cfg(feature = "flutter")]
|
||||
{
|
||||
crate::platform::linux::register_breakdown_handler();
|
||||
let (k, v) = ("LIBGL_ALWAYS_SOFTWARE", "true");
|
||||
if !hbb_common::config::Config::get_option("allow-always-software-render").is_empty() {
|
||||
std::env::set_var(k, v);
|
||||
} else {
|
||||
std::env::remove_var(k);
|
||||
}
|
||||
}
|
||||
#[cfg(feature = "flutter")]
|
||||
if _is_flutter_connect {
|
||||
return core_main_invoke_new_connection(std::env::args());
|
||||
@@ -173,7 +184,7 @@ pub fn core_main() -> Option<Vec<String>> {
|
||||
crate::start_os_service();
|
||||
return None;
|
||||
} else if args[0] == "--server" {
|
||||
log::info!("start --server");
|
||||
log::info!("start --server with user {}", crate::username());
|
||||
#[cfg(target_os = "windows")]
|
||||
{
|
||||
crate::start_server(true);
|
||||
@@ -182,6 +193,7 @@ pub fn core_main() -> Option<Vec<String>> {
|
||||
#[cfg(target_os = "macos")]
|
||||
{
|
||||
std::thread::spawn(move || crate::start_server(true));
|
||||
crate::platform::macos::hide_dock();
|
||||
crate::tray::make_tray();
|
||||
return None;
|
||||
}
|
||||
@@ -238,6 +250,8 @@ pub fn core_main() -> Option<Vec<String>> {
|
||||
#[cfg(feature = "flutter")]
|
||||
crate::flutter::connection_manager::start_listen_ipc_thread();
|
||||
crate::ui_interface::start_option_status_sync();
|
||||
#[cfg(target_os = "macos")]
|
||||
crate::platform::macos::hide_dock();
|
||||
}
|
||||
}
|
||||
//_async_logger_holder.map(|x| x.flush());
|
||||
@@ -312,7 +326,7 @@ fn core_main_invoke_new_connection(mut args: std::env::Args) -> Option<Vec<Strin
|
||||
let res = crate::platform::send_message_to_hnwd(
|
||||
"FLUTTER_RUNNER_WIN32_WINDOW",
|
||||
"RustDesk",
|
||||
(WM_USER + 2) as _, // refered from unilinks desktop pub
|
||||
(WM_USER + 2) as _, // referred from unilinks desktop pub
|
||||
uni_links.as_str(),
|
||||
true,
|
||||
);
|
||||
|
||||
@@ -156,7 +156,7 @@ impl InvokeUiSession for FlutterHandler {
|
||||
}
|
||||
|
||||
/// unused in flutter, use switch_display or set_peer_info
|
||||
fn set_display(&self, _x: i32, _y: i32, _w: i32, _h: i32, _cursor_embeded: bool) {}
|
||||
fn set_display(&self, _x: i32, _y: i32, _w: i32, _h: i32, _cursor_embedded: bool) {}
|
||||
|
||||
fn update_privacy_mode(&self) {
|
||||
self.push_event("update_privacy_mode", [].into());
|
||||
@@ -242,7 +242,7 @@ impl InvokeUiSession for FlutterHandler {
|
||||
self.push_event(
|
||||
"file_dir",
|
||||
vec![
|
||||
("value", &make_fd_to_json(id, path, entries)),
|
||||
("value", &crate::common::make_fd_to_json(id, path, entries)),
|
||||
("is_local", "false"),
|
||||
],
|
||||
);
|
||||
@@ -296,7 +296,7 @@ impl InvokeUiSession for FlutterHandler {
|
||||
h.insert("y", d.y);
|
||||
h.insert("width", d.width);
|
||||
h.insert("height", d.height);
|
||||
h.insert("cursor_embeded", if d.cursor_embeded { 1 } else { 0 });
|
||||
h.insert("cursor_embedded", if d.cursor_embedded { 1 } else { 0 });
|
||||
displays.push(h);
|
||||
}
|
||||
let displays = serde_json::ser::to_string(&displays).unwrap_or("".to_owned());
|
||||
@@ -324,6 +324,8 @@ impl InvokeUiSession for FlutterHandler {
|
||||
);
|
||||
}
|
||||
|
||||
fn on_connected(&self, _conn_type: ConnType) {}
|
||||
|
||||
fn msgbox(&self, msgtype: &str, title: &str, text: &str, link: &str, retry: bool) {
|
||||
let has_retry = if retry { "true" } else { "" };
|
||||
self.push_event(
|
||||
@@ -355,7 +357,7 @@ impl InvokeUiSession for FlutterHandler {
|
||||
("y", &display.y.to_string()),
|
||||
("width", &display.width.to_string()),
|
||||
("height", &display.height.to_string()),
|
||||
("cursor_embeded", &{if display.cursor_embeded {1} else {0}}.to_string()),
|
||||
("cursor_embedded", &{if display.cursor_embedded {1} else {0}}.to_string()),
|
||||
],
|
||||
);
|
||||
}
|
||||
@@ -422,8 +424,6 @@ pub fn session_start_(id: &str, event_stream: StreamSink<EventToUI>) -> ResultTy
|
||||
*session.event_stream.write().unwrap() = Some(event_stream);
|
||||
let session = session.clone();
|
||||
std::thread::spawn(move || {
|
||||
// if flutter : disable keyboard listen
|
||||
crate::client::disable_keyboard_listening();
|
||||
io_loop(session);
|
||||
});
|
||||
Ok(())
|
||||
@@ -545,24 +545,6 @@ pub fn get_session_id(id: String) -> String {
|
||||
};
|
||||
}
|
||||
|
||||
pub fn make_fd_to_json(id: i32, path: String, entries: &Vec<FileEntry>) -> String {
|
||||
let mut fd_json = serde_json::Map::new();
|
||||
fd_json.insert("id".into(), json!(id));
|
||||
fd_json.insert("path".into(), json!(path));
|
||||
|
||||
let mut entries_out = vec![];
|
||||
for entry in entries {
|
||||
let mut entry_map = serde_json::Map::new();
|
||||
entry_map.insert("entry_type".into(), json!(entry.entry_type.value()));
|
||||
entry_map.insert("name".into(), json!(entry.name));
|
||||
entry_map.insert("size".into(), json!(entry.size));
|
||||
entry_map.insert("modified_time".into(), json!(entry.modified_time));
|
||||
entries_out.push(entry_map);
|
||||
}
|
||||
fd_json.insert("entries".into(), json!(entries_out));
|
||||
serde_json::to_string(&fd_json).unwrap_or("".into())
|
||||
}
|
||||
|
||||
pub fn make_fd_flutter(id: i32, entries: &Vec<FileEntry>, only_count: bool) -> String {
|
||||
let mut m = serde_json::Map::new();
|
||||
m.insert("id".into(), json!(id));
|
||||
|
||||
@@ -17,11 +17,10 @@ use hbb_common::{
|
||||
|
||||
use crate::flutter::{self, SESSIONS};
|
||||
use crate::ui_interface::{self, *};
|
||||
#[cfg(not(any(target_os = "android", target_os = "ios")))]
|
||||
use crate::ui_session_interface::CUR_SESSION;
|
||||
use crate::{
|
||||
client::file_trait::FileManager,
|
||||
flutter::{make_fd_to_json, session_add, session_start_},
|
||||
common::make_fd_to_json,
|
||||
flutter::{session_add, session_start_},
|
||||
};
|
||||
fn initialize(app_dir: &str) {
|
||||
*config::APP_DIR.write().unwrap() = app_dir.to_owned();
|
||||
@@ -183,6 +182,14 @@ pub fn set_local_flutter_config(k: String, v: String) {
|
||||
ui_interface::set_local_flutter_config(k, v);
|
||||
}
|
||||
|
||||
pub fn get_local_kb_layout_type() -> SyncReturn<String> {
|
||||
SyncReturn(ui_interface::get_kb_layout_type())
|
||||
}
|
||||
|
||||
pub fn set_local_kb_layout_type(kb_layout_type: String) {
|
||||
ui_interface::set_kb_layout_type(kb_layout_type)
|
||||
}
|
||||
|
||||
pub fn session_get_view_style(id: String) -> Option<String> {
|
||||
if let Some(session) = SESSIONS.read().unwrap().get(&id) {
|
||||
Some(session.get_view_style())
|
||||
@@ -225,6 +232,20 @@ pub fn session_set_image_quality(id: String, value: String) {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn session_get_keyboard_mode(id: String) -> Option<String> {
|
||||
if let Some(session) = SESSIONS.read().unwrap().get(&id) {
|
||||
Some(session.get_keyboard_mode())
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
pub fn session_set_keyboard_mode(id: String, value: String) {
|
||||
if let Some(session) = SESSIONS.write().unwrap().get_mut(&id) {
|
||||
session.save_keyboard_mode(value);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn session_get_custom_image_quality(id: String) -> Option<Vec<i32>> {
|
||||
if let Some(session) = SESSIONS.read().unwrap().get(&id) {
|
||||
Some(session.get_custom_image_quality())
|
||||
@@ -279,10 +300,9 @@ pub fn session_enter_or_leave(id: String, enter: bool) {
|
||||
#[cfg(not(any(target_os = "android", target_os = "ios")))]
|
||||
if let Some(session) = SESSIONS.read().unwrap().get(&id) {
|
||||
if enter {
|
||||
*CUR_SESSION.lock().unwrap() = Some(session.clone());
|
||||
crate::keyboard::set_cur_session(session.clone());
|
||||
session.enter();
|
||||
} else {
|
||||
*CUR_SESSION.lock().unwrap() = None;
|
||||
session.leave();
|
||||
}
|
||||
}
|
||||
@@ -299,12 +319,14 @@ pub fn session_input_key(
|
||||
command: bool,
|
||||
) {
|
||||
if let Some(session) = SESSIONS.read().unwrap().get(&id) {
|
||||
// #[cfg(any(target_os = "android", target_os = "ios"))]
|
||||
session.input_key(&name, down, press, alt, ctrl, shift, command);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn session_input_string(id: String, value: String) {
|
||||
if let Some(session) = SESSIONS.read().unwrap().get(&id) {
|
||||
// #[cfg(any(target_os = "android", target_os = "ios"))]
|
||||
session.input_string(&value);
|
||||
}
|
||||
}
|
||||
@@ -329,19 +351,6 @@ pub fn session_get_peer_option(id: String, name: String) -> String {
|
||||
"".to_string()
|
||||
}
|
||||
|
||||
pub fn session_get_keyboard_name(id: String) -> String {
|
||||
if let Some(session) = SESSIONS.read().unwrap().get(&id) {
|
||||
return session.get_keyboard_mode();
|
||||
}
|
||||
"legacy".to_string()
|
||||
}
|
||||
|
||||
pub fn session_set_keyboard_mode(id: String, keyboard_mode: String) {
|
||||
if let Some(session) = SESSIONS.read().unwrap().get(&id) {
|
||||
session.save_keyboard_mode(keyboard_mode);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn session_input_os_password(id: String, value: String) {
|
||||
if let Some(session) = SESSIONS.read().unwrap().get(&id) {
|
||||
session.input_os_password(value, true);
|
||||
@@ -876,9 +885,11 @@ pub fn session_send_mouse(id: String, msg: String) {
|
||||
}
|
||||
if let Some(buttons) = m.get("buttons") {
|
||||
mask |= match buttons.as_str() {
|
||||
"left" => 1,
|
||||
"right" => 2,
|
||||
"wheel" => 4,
|
||||
"left" => 0x01,
|
||||
"right" => 0x02,
|
||||
"wheel" => 0x04,
|
||||
"back" => 0x08,
|
||||
"forward" => 0x10,
|
||||
_ => 0,
|
||||
} << 3;
|
||||
}
|
||||
@@ -894,9 +905,9 @@ pub fn session_restart_remote_device(id: String) {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn session_get_audit_server_sync(id: String) -> SyncReturn<String> {
|
||||
pub fn session_get_audit_server_sync(id: String, typ: String) -> SyncReturn<String> {
|
||||
let res = if let Some(session) = SESSIONS.read().unwrap().get(&id) {
|
||||
session.get_audit_server()
|
||||
session.get_audit_server(typ)
|
||||
} else {
|
||||
"".to_owned()
|
||||
};
|
||||
@@ -1083,8 +1094,7 @@ pub fn main_is_installed() -> SyncReturn<bool> {
|
||||
}
|
||||
|
||||
pub fn main_start_grab_keyboard() {
|
||||
#[cfg(not(any(target_os = "android", target_os = "ios")))]
|
||||
crate::ui_session_interface::global_grab_keyboard();
|
||||
crate::keyboard::client::start_grab_loop();
|
||||
}
|
||||
|
||||
pub fn main_is_installed_lower_version() -> SyncReturn<bool> {
|
||||
@@ -1103,6 +1113,10 @@ pub fn main_is_can_screen_recording(prompt: bool) -> SyncReturn<bool> {
|
||||
SyncReturn(is_can_screen_recording(prompt))
|
||||
}
|
||||
|
||||
pub fn main_is_can_input_monitoring(prompt: bool) -> SyncReturn<bool> {
|
||||
SyncReturn(is_can_input_monitoring(prompt))
|
||||
}
|
||||
|
||||
pub fn main_is_share_rdp() -> SyncReturn<bool> {
|
||||
SyncReturn(is_share_rdp())
|
||||
}
|
||||
|
||||
12
src/ipc.rs
12
src/ipc.rs
@@ -78,7 +78,7 @@ pub enum FS {
|
||||
WriteError {
|
||||
id: i32,
|
||||
file_num: i32,
|
||||
err: String
|
||||
err: String,
|
||||
},
|
||||
WriteOffset {
|
||||
id: i32,
|
||||
@@ -111,7 +111,7 @@ pub enum DataKeyboardResponse {
|
||||
GetKeyState(bool),
|
||||
}
|
||||
|
||||
#[cfg(not(any(target_os = "android", target_os = "ios", feature = "cli")))]
|
||||
#[cfg(not(any(target_os = "android", target_os = "ios")))]
|
||||
#[derive(Debug, Serialize, Deserialize, Clone)]
|
||||
#[serde(tag = "t", content = "c")]
|
||||
pub enum DataMouse {
|
||||
@@ -195,11 +195,11 @@ pub enum Data {
|
||||
ClipboardFileEnabled(bool),
|
||||
PrivacyModeState((i32, PrivacyModeState)),
|
||||
TestRendezvousServer,
|
||||
#[cfg(not(any(target_os = "android", target_os = "ios", feature = "cli")))]
|
||||
#[cfg(not(any(target_os = "android", target_os = "ios")))]
|
||||
Keyboard(DataKeyboard),
|
||||
#[cfg(not(any(target_os = "android", target_os = "ios", feature = "cli")))]
|
||||
#[cfg(not(any(target_os = "android", target_os = "ios")))]
|
||||
KeyboardResponse(DataKeyboardResponse),
|
||||
#[cfg(not(any(target_os = "android", target_os = "ios", feature = "cli")))]
|
||||
#[cfg(not(any(target_os = "android", target_os = "ios")))]
|
||||
Mouse(DataMouse),
|
||||
Control(DataControl),
|
||||
Theme(String),
|
||||
@@ -544,7 +544,7 @@ async fn check_pid(postfix: &str) {
|
||||
}
|
||||
}
|
||||
}
|
||||
hbb_common::allow_err!(std::fs::remove_file(&Config::ipc_path(postfix)));
|
||||
std::fs::remove_file(&Config::ipc_path(postfix)).ok();
|
||||
}
|
||||
|
||||
#[inline]
|
||||
|
||||
655
src/keyboard.rs
Normal file
655
src/keyboard.rs
Normal file
@@ -0,0 +1,655 @@
|
||||
#[cfg(not(any(target_os = "android", target_os = "ios")))]
|
||||
use crate::client::get_key_state;
|
||||
use crate::common::GrabState;
|
||||
#[cfg(feature = "flutter")]
|
||||
use crate::flutter::FlutterHandler;
|
||||
#[cfg(not(any(feature = "flutter", feature = "cli")))]
|
||||
use crate::ui::remote::SciterHandler;
|
||||
use crate::ui_session_interface::Session;
|
||||
use hbb_common::{log, message_proto::*};
|
||||
use rdev::{Event, EventType, Key};
|
||||
#[cfg(any(target_os = "windows", target_os = "macos"))]
|
||||
use std::sync::atomic::{AtomicBool, Ordering};
|
||||
use std::{
|
||||
collections::{HashMap, HashSet},
|
||||
sync::{Arc, Mutex},
|
||||
time::SystemTime,
|
||||
};
|
||||
|
||||
#[cfg(windows)]
|
||||
static mut IS_ALT_GR: bool = false;
|
||||
|
||||
#[cfg(any(target_os = "windows", target_os = "macos"))]
|
||||
static KEYBOARD_HOOKED: AtomicBool = AtomicBool::new(false);
|
||||
|
||||
#[cfg(feature = "flutter")]
|
||||
lazy_static::lazy_static! {
|
||||
static ref CUR_SESSION: Arc<Mutex<Option<Session<FlutterHandler>>>> = Default::default();
|
||||
}
|
||||
|
||||
#[cfg(not(any(feature = "flutter", feature = "cli")))]
|
||||
lazy_static::lazy_static! {
|
||||
static ref CUR_SESSION: Arc<Mutex<Option<Session<SciterHandler>>>> = Default::default();
|
||||
}
|
||||
|
||||
lazy_static::lazy_static! {
|
||||
static ref TO_RELEASE: Arc<Mutex<HashSet<Key>>> = Arc::new(Mutex::new(HashSet::<Key>::new()));
|
||||
static ref MODIFIERS_STATE: Mutex<HashMap<Key, bool>> = {
|
||||
let mut m = HashMap::new();
|
||||
m.insert(Key::ShiftLeft, false);
|
||||
m.insert(Key::ShiftRight, false);
|
||||
m.insert(Key::ControlLeft, false);
|
||||
m.insert(Key::ControlRight, false);
|
||||
m.insert(Key::Alt, false);
|
||||
m.insert(Key::AltGr, false);
|
||||
m.insert(Key::MetaLeft, false);
|
||||
m.insert(Key::MetaRight, false);
|
||||
Mutex::new(m)
|
||||
};
|
||||
}
|
||||
|
||||
#[cfg(feature = "flutter")]
|
||||
pub fn set_cur_session(session: Session<FlutterHandler>) {
|
||||
*CUR_SESSION.lock().unwrap() = Some(session);
|
||||
}
|
||||
|
||||
#[cfg(not(any(feature = "flutter", feature = "cli")))]
|
||||
pub fn set_cur_session(session: Session<SciterHandler>) {
|
||||
*CUR_SESSION.lock().unwrap() = Some(session);
|
||||
}
|
||||
|
||||
pub mod client {
|
||||
use super::*;
|
||||
|
||||
pub fn get_keyboard_mode() -> String {
|
||||
#[cfg(not(feature = "cli"))]
|
||||
if let Some(handler) = CUR_SESSION.lock().unwrap().as_ref() {
|
||||
return handler.get_keyboard_mode();
|
||||
}
|
||||
"legacy".to_string()
|
||||
}
|
||||
|
||||
pub fn start_grab_loop() {
|
||||
super::start_grab_loop();
|
||||
}
|
||||
|
||||
pub fn change_grab_status(state: GrabState) {
|
||||
match state {
|
||||
GrabState::Ready => {}
|
||||
GrabState::Run => {
|
||||
#[cfg(any(target_os = "windows", target_os = "macos"))]
|
||||
KEYBOARD_HOOKED.swap(true, Ordering::SeqCst);
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
rdev::enable_grab();
|
||||
}
|
||||
GrabState::Wait => {
|
||||
release_remote_keys();
|
||||
|
||||
#[cfg(any(target_os = "windows", target_os = "macos"))]
|
||||
KEYBOARD_HOOKED.swap(false, Ordering::SeqCst);
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
rdev::disable_grab();
|
||||
}
|
||||
GrabState::Exit => {
|
||||
#[cfg(target_os = "linux")]
|
||||
rdev::exit_grab_listen();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn process_event(event: &Event) {
|
||||
if is_long_press(&event) {
|
||||
return;
|
||||
}
|
||||
if let Some(key_event) = event_to_key_event(&event) {
|
||||
send_key_event(&key_event);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_modifiers_state(
|
||||
alt: bool,
|
||||
ctrl: bool,
|
||||
shift: bool,
|
||||
command: bool,
|
||||
) -> (bool, bool, bool, bool) {
|
||||
let modifiers_lock = MODIFIERS_STATE.lock().unwrap();
|
||||
let ctrl = *modifiers_lock.get(&Key::ControlLeft).unwrap()
|
||||
|| *modifiers_lock.get(&Key::ControlRight).unwrap()
|
||||
|| ctrl;
|
||||
let shift = *modifiers_lock.get(&Key::ShiftLeft).unwrap()
|
||||
|| *modifiers_lock.get(&Key::ShiftRight).unwrap()
|
||||
|| shift;
|
||||
let command = *modifiers_lock.get(&Key::MetaLeft).unwrap()
|
||||
|| *modifiers_lock.get(&Key::MetaRight).unwrap()
|
||||
|| command;
|
||||
let alt = *modifiers_lock.get(&Key::Alt).unwrap()
|
||||
|| *modifiers_lock.get(&Key::AltGr).unwrap()
|
||||
|| alt;
|
||||
|
||||
(alt, ctrl, shift, command)
|
||||
}
|
||||
|
||||
pub fn legacy_modifiers(
|
||||
key_event: &mut KeyEvent,
|
||||
alt: bool,
|
||||
ctrl: bool,
|
||||
shift: bool,
|
||||
command: bool,
|
||||
) {
|
||||
if alt
|
||||
&& !crate::is_control_key(&key_event, &ControlKey::Alt)
|
||||
&& !crate::is_control_key(&key_event, &ControlKey::RAlt)
|
||||
{
|
||||
key_event.modifiers.push(ControlKey::Alt.into());
|
||||
}
|
||||
if shift
|
||||
&& !crate::is_control_key(&key_event, &ControlKey::Shift)
|
||||
&& !crate::is_control_key(&key_event, &ControlKey::RShift)
|
||||
{
|
||||
key_event.modifiers.push(ControlKey::Shift.into());
|
||||
}
|
||||
if ctrl
|
||||
&& !crate::is_control_key(&key_event, &ControlKey::Control)
|
||||
&& !crate::is_control_key(&key_event, &ControlKey::RControl)
|
||||
{
|
||||
key_event.modifiers.push(ControlKey::Control.into());
|
||||
}
|
||||
if command
|
||||
&& !crate::is_control_key(&key_event, &ControlKey::Meta)
|
||||
&& !crate::is_control_key(&key_event, &ControlKey::RWin)
|
||||
{
|
||||
key_event.modifiers.push(ControlKey::Meta.into());
|
||||
}
|
||||
}
|
||||
|
||||
pub fn lock_screen() {
|
||||
let mut key_event = KeyEvent::new();
|
||||
key_event.set_control_key(ControlKey::LockScreen);
|
||||
key_event.down = true;
|
||||
key_event.mode = KeyboardMode::Legacy.into();
|
||||
send_key_event(&key_event);
|
||||
}
|
||||
|
||||
pub fn ctrl_alt_del() {
|
||||
let mut key_event = KeyEvent::new();
|
||||
if get_peer_platform() == "Windows" {
|
||||
key_event.set_control_key(ControlKey::CtrlAltDel);
|
||||
key_event.down = true;
|
||||
} else {
|
||||
key_event.set_control_key(ControlKey::Delete);
|
||||
legacy_modifiers(&mut key_event, true, true, false, false);
|
||||
key_event.press = true;
|
||||
}
|
||||
key_event.mode = KeyboardMode::Legacy.into();
|
||||
send_key_event(&key_event);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn start_grab_loop() {
|
||||
#[cfg(any(target_os = "windows", target_os = "macos"))]
|
||||
std::thread::spawn(move || {
|
||||
let try_handle_keyboard = move |event: Event, key: Key, is_press: bool| -> Option<Event> {
|
||||
// fix #2211:CAPS LOCK don't work
|
||||
if key == Key::CapsLock || key == Key::NumLock {
|
||||
return Some(event);
|
||||
}
|
||||
if KEYBOARD_HOOKED.load(Ordering::SeqCst) {
|
||||
client::process_event(&event);
|
||||
if is_press {
|
||||
return None;
|
||||
} else {
|
||||
return Some(event);
|
||||
}
|
||||
} else {
|
||||
return Some(event);
|
||||
}
|
||||
};
|
||||
let func = move |event: Event| match event.event_type {
|
||||
EventType::KeyPress(key) => try_handle_keyboard(event, key, true),
|
||||
EventType::KeyRelease(key) => try_handle_keyboard(event, key, false),
|
||||
_ => Some(event),
|
||||
};
|
||||
if let Err(error) = rdev::grab(func) {
|
||||
log::error!("rdev Error: {:?}", error)
|
||||
}
|
||||
});
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
if let Err(err) = rdev::start_grab_listen(move |event: Event| match event.event_type {
|
||||
EventType::KeyPress(key) | EventType::KeyRelease(key) => {
|
||||
if let Key::Unknown(keycode) = key {
|
||||
log::error!("rdev get unknown key, keycode is : {:?}", keycode);
|
||||
} else {
|
||||
client::process_event(&event);
|
||||
}
|
||||
None
|
||||
}
|
||||
_ => Some(event),
|
||||
}) {
|
||||
log::error!("Failed to init rdev grab thread: {:?}", err);
|
||||
};
|
||||
}
|
||||
|
||||
pub fn is_long_press(event: &Event) -> bool {
|
||||
let keys = MODIFIERS_STATE.lock().unwrap();
|
||||
match event.event_type {
|
||||
EventType::KeyPress(k) => {
|
||||
if let Some(&state) = keys.get(&k) {
|
||||
if state == true {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
};
|
||||
return false;
|
||||
}
|
||||
|
||||
pub fn release_remote_keys() {
|
||||
// todo!: client quit suddenly, how to release keys?
|
||||
let to_release = TO_RELEASE.lock().unwrap().clone();
|
||||
TO_RELEASE.lock().unwrap().clear();
|
||||
for key in to_release {
|
||||
let event_type = EventType::KeyRelease(key);
|
||||
let event = event_type_to_event(event_type);
|
||||
client::process_event(&event);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_keyboard_mode_enum() -> KeyboardMode {
|
||||
match client::get_keyboard_mode().as_str() {
|
||||
"map" => KeyboardMode::Map,
|
||||
"translate" => KeyboardMode::Translate,
|
||||
_ => KeyboardMode::Legacy,
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(any(target_os = "android", target_os = "ios")))]
|
||||
pub fn add_numlock_capslock_status(key_event: &mut KeyEvent) {
|
||||
if get_key_state(enigo::Key::CapsLock) {
|
||||
key_event.modifiers.push(ControlKey::CapsLock.into());
|
||||
}
|
||||
if get_key_state(enigo::Key::NumLock) {
|
||||
key_event.modifiers.push(ControlKey::NumLock.into());
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(any(target_os = "android", target_os = "ios")))]
|
||||
pub fn convert_numpad_keys(key: Key) -> Key {
|
||||
if get_key_state(enigo::Key::NumLock) {
|
||||
return key;
|
||||
}
|
||||
match key {
|
||||
Key::Kp0 => Key::Insert,
|
||||
Key::KpDecimal => Key::Delete,
|
||||
Key::Kp1 => Key::End,
|
||||
Key::Kp2 => Key::DownArrow,
|
||||
Key::Kp3 => Key::PageDown,
|
||||
Key::Kp4 => Key::LeftArrow,
|
||||
Key::Kp5 => Key::Clear,
|
||||
Key::Kp6 => Key::RightArrow,
|
||||
Key::Kp7 => Key::Home,
|
||||
Key::Kp8 => Key::UpArrow,
|
||||
Key::Kp9 => Key::PageUp,
|
||||
_ => key,
|
||||
}
|
||||
}
|
||||
|
||||
fn update_modifiers_state(event: &Event) {
|
||||
// for mouse
|
||||
let mut keys = MODIFIERS_STATE.lock().unwrap();
|
||||
match event.event_type {
|
||||
EventType::KeyPress(k) => {
|
||||
if keys.contains_key(&k) {
|
||||
keys.insert(k, true);
|
||||
}
|
||||
}
|
||||
EventType::KeyRelease(k) => {
|
||||
if keys.contains_key(&k) {
|
||||
keys.insert(k, false);
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
};
|
||||
}
|
||||
|
||||
pub fn event_to_key_event(event: &Event) -> Option<KeyEvent> {
|
||||
let mut key_event = KeyEvent::new();
|
||||
update_modifiers_state(event);
|
||||
|
||||
match event.event_type {
|
||||
EventType::KeyPress(key) => {
|
||||
TO_RELEASE.lock().unwrap().insert(key);
|
||||
}
|
||||
EventType::KeyRelease(key) => {
|
||||
TO_RELEASE.lock().unwrap().remove(&key);
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
||||
let keyboard_mode = get_keyboard_mode_enum();
|
||||
key_event.mode = keyboard_mode.into();
|
||||
let mut key_event = match keyboard_mode {
|
||||
KeyboardMode::Map => map_keyboard_mode(event, key_event)?,
|
||||
KeyboardMode::Translate => translate_keyboard_mode(event, key_event)?,
|
||||
_ => {
|
||||
#[cfg(not(any(target_os = "android", target_os = "ios")))]
|
||||
{
|
||||
legacy_keyboard_mode(event, key_event)?
|
||||
}
|
||||
#[cfg(any(target_os = "android", target_os = "ios"))]
|
||||
{
|
||||
None?
|
||||
}
|
||||
}
|
||||
};
|
||||
#[cfg(not(any(target_os = "android", target_os = "ios")))]
|
||||
add_numlock_capslock_status(&mut key_event);
|
||||
|
||||
return Some(key_event);
|
||||
}
|
||||
|
||||
pub fn event_type_to_event(event_type: EventType) -> Event {
|
||||
Event {
|
||||
event_type,
|
||||
time: SystemTime::now(),
|
||||
name: None,
|
||||
code: 0,
|
||||
scan_code: 0,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn send_key_event(key_event: &KeyEvent) {
|
||||
#[cfg(not(feature = "cli"))]
|
||||
if let Some(handler) = CUR_SESSION.lock().unwrap().as_ref() {
|
||||
handler.send_key_event(key_event);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_peer_platform() -> String {
|
||||
#[cfg(not(feature = "cli"))]
|
||||
if let Some(handler) = CUR_SESSION.lock().unwrap().as_ref() {
|
||||
return handler.peer_platform();
|
||||
}
|
||||
"Windows".to_string()
|
||||
}
|
||||
|
||||
#[cfg(not(any(target_os = "android", target_os = "ios")))]
|
||||
pub fn legacy_keyboard_mode(event: &Event, mut key_event: KeyEvent) -> Option<KeyEvent> {
|
||||
// legacy mode(0): Generate characters locally, look for keycode on other side.
|
||||
let (mut key, down_or_up) = match event.event_type {
|
||||
EventType::KeyPress(key) => (key, true),
|
||||
EventType::KeyRelease(key) => (key, false),
|
||||
_ => {
|
||||
return None;
|
||||
}
|
||||
};
|
||||
|
||||
let peer = get_peer_platform();
|
||||
let is_win = peer == "Windows";
|
||||
if is_win {
|
||||
key = convert_numpad_keys(key);
|
||||
}
|
||||
|
||||
let alt = get_key_state(enigo::Key::Alt);
|
||||
#[cfg(windows)]
|
||||
let ctrl = {
|
||||
let mut tmp = get_key_state(enigo::Key::Control) || get_key_state(enigo::Key::RightControl);
|
||||
unsafe {
|
||||
if IS_ALT_GR {
|
||||
if alt || key == Key::AltGr {
|
||||
if tmp {
|
||||
tmp = false;
|
||||
}
|
||||
} else {
|
||||
IS_ALT_GR = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
tmp
|
||||
};
|
||||
#[cfg(not(windows))]
|
||||
let ctrl = get_key_state(enigo::Key::Control) || get_key_state(enigo::Key::RightControl);
|
||||
let shift = get_key_state(enigo::Key::Shift) || get_key_state(enigo::Key::RightShift);
|
||||
#[cfg(windows)]
|
||||
let command = crate::platform::windows::get_win_key_state();
|
||||
#[cfg(not(windows))]
|
||||
let command = get_key_state(enigo::Key::Meta);
|
||||
let control_key = match key {
|
||||
Key::Alt => Some(ControlKey::Alt),
|
||||
Key::AltGr => Some(ControlKey::RAlt),
|
||||
Key::Backspace => Some(ControlKey::Backspace),
|
||||
Key::ControlLeft => {
|
||||
// when pressing AltGr, an extra VK_LCONTROL with a special
|
||||
// scancode with bit 9 set is sent, let's ignore this.
|
||||
#[cfg(windows)]
|
||||
if (event.scan_code >> 8) == 0xE0 {
|
||||
unsafe {
|
||||
IS_ALT_GR = true;
|
||||
}
|
||||
return None;
|
||||
}
|
||||
Some(ControlKey::Control)
|
||||
}
|
||||
Key::ControlRight => Some(ControlKey::RControl),
|
||||
Key::DownArrow => Some(ControlKey::DownArrow),
|
||||
Key::Escape => Some(ControlKey::Escape),
|
||||
Key::F1 => Some(ControlKey::F1),
|
||||
Key::F10 => Some(ControlKey::F10),
|
||||
Key::F11 => Some(ControlKey::F11),
|
||||
Key::F12 => Some(ControlKey::F12),
|
||||
Key::F2 => Some(ControlKey::F2),
|
||||
Key::F3 => Some(ControlKey::F3),
|
||||
Key::F4 => Some(ControlKey::F4),
|
||||
Key::F5 => Some(ControlKey::F5),
|
||||
Key::F6 => Some(ControlKey::F6),
|
||||
Key::F7 => Some(ControlKey::F7),
|
||||
Key::F8 => Some(ControlKey::F8),
|
||||
Key::F9 => Some(ControlKey::F9),
|
||||
Key::LeftArrow => Some(ControlKey::LeftArrow),
|
||||
Key::MetaLeft => Some(ControlKey::Meta),
|
||||
Key::MetaRight => Some(ControlKey::RWin),
|
||||
Key::Return => Some(ControlKey::Return),
|
||||
Key::RightArrow => Some(ControlKey::RightArrow),
|
||||
Key::ShiftLeft => Some(ControlKey::Shift),
|
||||
Key::ShiftRight => Some(ControlKey::RShift),
|
||||
Key::Space => Some(ControlKey::Space),
|
||||
Key::Tab => Some(ControlKey::Tab),
|
||||
Key::UpArrow => Some(ControlKey::UpArrow),
|
||||
Key::Delete => {
|
||||
if is_win && ctrl && alt {
|
||||
client::ctrl_alt_del();
|
||||
return None;
|
||||
}
|
||||
Some(ControlKey::Delete)
|
||||
}
|
||||
Key::Apps => Some(ControlKey::Apps),
|
||||
Key::Cancel => Some(ControlKey::Cancel),
|
||||
Key::Clear => Some(ControlKey::Clear),
|
||||
Key::Kana => Some(ControlKey::Kana),
|
||||
Key::Hangul => Some(ControlKey::Hangul),
|
||||
Key::Junja => Some(ControlKey::Junja),
|
||||
Key::Final => Some(ControlKey::Final),
|
||||
Key::Hanja => Some(ControlKey::Hanja),
|
||||
Key::Hanji => Some(ControlKey::Hanja),
|
||||
Key::Convert => Some(ControlKey::Convert),
|
||||
Key::Print => Some(ControlKey::Print),
|
||||
Key::Select => Some(ControlKey::Select),
|
||||
Key::Execute => Some(ControlKey::Execute),
|
||||
Key::PrintScreen => Some(ControlKey::Snapshot),
|
||||
Key::Help => Some(ControlKey::Help),
|
||||
Key::Sleep => Some(ControlKey::Sleep),
|
||||
Key::Separator => Some(ControlKey::Separator),
|
||||
Key::KpReturn => Some(ControlKey::NumpadEnter),
|
||||
Key::Kp0 => Some(ControlKey::Numpad0),
|
||||
Key::Kp1 => Some(ControlKey::Numpad1),
|
||||
Key::Kp2 => Some(ControlKey::Numpad2),
|
||||
Key::Kp3 => Some(ControlKey::Numpad3),
|
||||
Key::Kp4 => Some(ControlKey::Numpad4),
|
||||
Key::Kp5 => Some(ControlKey::Numpad5),
|
||||
Key::Kp6 => Some(ControlKey::Numpad6),
|
||||
Key::Kp7 => Some(ControlKey::Numpad7),
|
||||
Key::Kp8 => Some(ControlKey::Numpad8),
|
||||
Key::Kp9 => Some(ControlKey::Numpad9),
|
||||
Key::KpDivide => Some(ControlKey::Divide),
|
||||
Key::KpMultiply => Some(ControlKey::Multiply),
|
||||
Key::KpDecimal => Some(ControlKey::Decimal),
|
||||
Key::KpMinus => Some(ControlKey::Subtract),
|
||||
Key::KpPlus => Some(ControlKey::Add),
|
||||
Key::CapsLock | Key::NumLock | Key::ScrollLock => {
|
||||
return None;
|
||||
}
|
||||
Key::Home => Some(ControlKey::Home),
|
||||
Key::End => Some(ControlKey::End),
|
||||
Key::Insert => Some(ControlKey::Insert),
|
||||
Key::PageUp => Some(ControlKey::PageUp),
|
||||
Key::PageDown => Some(ControlKey::PageDown),
|
||||
Key::Pause => Some(ControlKey::Pause),
|
||||
_ => None,
|
||||
};
|
||||
if let Some(k) = control_key {
|
||||
key_event.set_control_key(k);
|
||||
} else {
|
||||
let mut chr = match event.name {
|
||||
Some(ref s) => {
|
||||
if s.len() <= 2 {
|
||||
// exclude chinese characters
|
||||
s.chars().next().unwrap_or('\0')
|
||||
} else {
|
||||
'\0'
|
||||
}
|
||||
}
|
||||
_ => '\0',
|
||||
};
|
||||
if chr == '·' {
|
||||
// special for Chinese
|
||||
chr = '`';
|
||||
}
|
||||
if chr == '\0' {
|
||||
chr = match key {
|
||||
Key::Num1 => '1',
|
||||
Key::Num2 => '2',
|
||||
Key::Num3 => '3',
|
||||
Key::Num4 => '4',
|
||||
Key::Num5 => '5',
|
||||
Key::Num6 => '6',
|
||||
Key::Num7 => '7',
|
||||
Key::Num8 => '8',
|
||||
Key::Num9 => '9',
|
||||
Key::Num0 => '0',
|
||||
Key::KeyA => 'a',
|
||||
Key::KeyB => 'b',
|
||||
Key::KeyC => 'c',
|
||||
Key::KeyD => 'd',
|
||||
Key::KeyE => 'e',
|
||||
Key::KeyF => 'f',
|
||||
Key::KeyG => 'g',
|
||||
Key::KeyH => 'h',
|
||||
Key::KeyI => 'i',
|
||||
Key::KeyJ => 'j',
|
||||
Key::KeyK => 'k',
|
||||
Key::KeyL => 'l',
|
||||
Key::KeyM => 'm',
|
||||
Key::KeyN => 'n',
|
||||
Key::KeyO => 'o',
|
||||
Key::KeyP => 'p',
|
||||
Key::KeyQ => 'q',
|
||||
Key::KeyR => 'r',
|
||||
Key::KeyS => 's',
|
||||
Key::KeyT => 't',
|
||||
Key::KeyU => 'u',
|
||||
Key::KeyV => 'v',
|
||||
Key::KeyW => 'w',
|
||||
Key::KeyX => 'x',
|
||||
Key::KeyY => 'y',
|
||||
Key::KeyZ => 'z',
|
||||
Key::Comma => ',',
|
||||
Key::Dot => '.',
|
||||
Key::SemiColon => ';',
|
||||
Key::Quote => '\'',
|
||||
Key::LeftBracket => '[',
|
||||
Key::RightBracket => ']',
|
||||
Key::Slash => '/',
|
||||
Key::BackSlash => '\\',
|
||||
Key::Minus => '-',
|
||||
Key::Equal => '=',
|
||||
Key::BackQuote => '`',
|
||||
_ => '\0',
|
||||
}
|
||||
}
|
||||
if chr != '\0' {
|
||||
if chr == 'l' && is_win && command {
|
||||
client::lock_screen();
|
||||
return None;
|
||||
}
|
||||
key_event.set_chr(chr as _);
|
||||
} else {
|
||||
log::error!("Unknown key {:?}", &event);
|
||||
return None;
|
||||
}
|
||||
}
|
||||
let (alt, ctrl, shift, command) = client::get_modifiers_state(alt, ctrl, shift, command);
|
||||
client::legacy_modifiers(&mut key_event, alt, ctrl, shift, command);
|
||||
|
||||
if down_or_up == true {
|
||||
key_event.down = true;
|
||||
}
|
||||
Some(key_event)
|
||||
}
|
||||
|
||||
pub fn map_keyboard_mode(event: &Event, mut key_event: KeyEvent) -> Option<KeyEvent> {
|
||||
match event.event_type {
|
||||
EventType::KeyPress(..) => {
|
||||
key_event.down = true;
|
||||
}
|
||||
EventType::KeyRelease(..) => {
|
||||
key_event.down = false;
|
||||
}
|
||||
_ => return None,
|
||||
};
|
||||
|
||||
let mut peer = get_peer_platform().to_lowercase();
|
||||
peer.retain(|c| !c.is_whitespace());
|
||||
|
||||
#[cfg(target_os = "windows")]
|
||||
let keycode = match peer.as_str() {
|
||||
"windows" => event.scan_code,
|
||||
"macos" => {
|
||||
if hbb_common::config::LocalConfig::get_kb_layout_type() == "ISO" {
|
||||
rdev::win_scancode_to_macos_iso_code(event.scan_code)?
|
||||
} else {
|
||||
rdev::win_scancode_to_macos_code(event.scan_code)?
|
||||
}
|
||||
}
|
||||
_ => rdev::win_scancode_to_linux_code(event.scan_code)?,
|
||||
};
|
||||
#[cfg(target_os = "macos")]
|
||||
let keycode = match peer.as_str() {
|
||||
"windows" => rdev::macos_code_to_win_scancode(event.code as _)?,
|
||||
"macos" => event.code as _,
|
||||
_ => rdev::macos_code_to_linux_code(event.code as _)?,
|
||||
};
|
||||
#[cfg(target_os = "linux")]
|
||||
let keycode = match peer.as_str() {
|
||||
"windows" => rdev::linux_code_to_win_scancode(event.code as _)?,
|
||||
"macos" => {
|
||||
if hbb_common::config::LocalConfig::get_kb_layout_type() == "ISO" {
|
||||
rdev::linux_code_to_macos_iso_code(event.code as _)?
|
||||
} else {
|
||||
rdev::linux_code_to_macos_code(event.code as _)?
|
||||
}
|
||||
}
|
||||
_ => event.code as _,
|
||||
};
|
||||
#[cfg(any(target_os = "android", target_os = "ios"))]
|
||||
let keycode = 0;
|
||||
|
||||
key_event.set_chr(keycode);
|
||||
Some(key_event)
|
||||
}
|
||||
|
||||
pub fn translate_keyboard_mode(_event: &Event, mut _key_event: KeyEvent) -> Option<KeyEvent> {
|
||||
None
|
||||
}
|
||||
@@ -28,6 +28,9 @@ mod ca;
|
||||
mod gr;
|
||||
mod sv;
|
||||
mod sq;
|
||||
mod sr;
|
||||
mod th;
|
||||
mod sl;
|
||||
|
||||
lazy_static::lazy_static! {
|
||||
pub static ref LANGS: Value =
|
||||
@@ -59,6 +62,9 @@ lazy_static::lazy_static! {
|
||||
("gr", "Ελληνικά"),
|
||||
("sv", "Svenska"),
|
||||
("sq", "Shqip"),
|
||||
("sr", "Srpski"),
|
||||
("th", "ภาษาไทย"),
|
||||
("sl", "Slovenščina"),
|
||||
]);
|
||||
}
|
||||
|
||||
@@ -114,6 +120,9 @@ pub fn translate_locale(name: String, locale: &str) -> String {
|
||||
"gr" => gr::T.deref(),
|
||||
"sv" => sv::T.deref(),
|
||||
"sq" => sq::T.deref(),
|
||||
"sr" => sr::T.deref(),
|
||||
"th" => th::T.deref(),
|
||||
"sl" => sl::T.deref(),
|
||||
_ => en::T.deref(),
|
||||
};
|
||||
if let Some(v) = m.get(&name as &str) {
|
||||
|
||||
@@ -39,6 +39,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Change ID", "Canviar ID"),
|
||||
("Website", "Lloc web"),
|
||||
("About", "Sobre"),
|
||||
("Slogan_tip", ""),
|
||||
("Privacy Statement", ""),
|
||||
("Mute", "Silenciar"),
|
||||
("Audio Input", "Entrada d'àudio"),
|
||||
("Enhancements", "Millores"),
|
||||
@@ -208,6 +210,11 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Always connect via relay", "Connecta sempre a través de relay"),
|
||||
("whitelist_tip", ""),
|
||||
("Login", "Inicia sessió"),
|
||||
("Verify", ""),
|
||||
("Remember me", ""),
|
||||
("Trust this device", ""),
|
||||
("Verification code", ""),
|
||||
("verification_tip", ""),
|
||||
("Logout", "Sortir"),
|
||||
("Tags", ""),
|
||||
("Search ID", "Cerca ID"),
|
||||
@@ -331,21 +338,19 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Scale original", "Escala original"),
|
||||
("Scale adaptive", "Escala adaptativa"),
|
||||
("General", ""),
|
||||
("Security", "Seguritat"),
|
||||
("Account", "Compte"),
|
||||
("Security", "Seguretat"),
|
||||
("Theme", "Tema"),
|
||||
("Dark Theme", "Tema Fosc"),
|
||||
("Dark", "Fosc"),
|
||||
("Light", "Clar"),
|
||||
("Follow System", "Tema del sistema"),
|
||||
("Enable hardware codec", "Habilitar còdec per hardware"),
|
||||
("Unlock Security Settings", "Desbloquejar ajustaments de seguritat"),
|
||||
("Unlock Security Settings", "Desbloquejar ajustaments de seguretat"),
|
||||
("Enable Audio", "Habilitar àudio"),
|
||||
("Unlock Network Settings", "Desbloquejar Ajustaments de Xarxa"),
|
||||
("Server", "Servidor"),
|
||||
("Direct IP Access", "Accés IP Directe"),
|
||||
("Proxy", ""),
|
||||
("Port", ""),
|
||||
("Apply", "Aplicar"),
|
||||
("Disconnect all devices?", "Desconnectar tots els dispositius?"),
|
||||
("Clear", "Netejar"),
|
||||
@@ -374,7 +379,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Other", "Altre"),
|
||||
("Confirm before closing multiple tabs", "Confirmar abans de tancar múltiples pestanyes"),
|
||||
("Keyboard Settings", "Ajustaments de teclat"),
|
||||
("Custom", "Personalitzat"),
|
||||
("Full Access", "Acces complet"),
|
||||
("Screen Share", "Compartir pantalla"),
|
||||
("Wayland requires Ubuntu 21.04 or higher version.", "Wayland requereix Ubuntu 21.04 o una versió superior."),
|
||||
@@ -399,6 +403,15 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("hide_cm_tip", ""),
|
||||
("wayland_experiment_tip", ""),
|
||||
("Right click to select tabs", ""),
|
||||
("Skipped", ""),
|
||||
("Add to Address Book", ""),
|
||||
("Group", ""),
|
||||
("Search", ""),
|
||||
("Closed manually by the web console", ""),
|
||||
("Local keyboard type", ""),
|
||||
("Select local keyboard type", ""),
|
||||
("software_render_tip", ""),
|
||||
("Always use software rendering", ""),
|
||||
("config_input", ""),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Password", "密码"),
|
||||
("Ready", "就绪"),
|
||||
("Established", "已建立"),
|
||||
("connecting_status", "正在接入RustDesk网络..."),
|
||||
("connecting_status", "正在接入 RustDesk 网络..."),
|
||||
("Enable Service", "允许服务"),
|
||||
("Start Service", "启动服务"),
|
||||
("Service is running", "服务正在运行"),
|
||||
@@ -39,6 +39,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Change ID", "改变ID"),
|
||||
("Website", "网站"),
|
||||
("About", "关于"),
|
||||
("Slogan_tip", ""),
|
||||
("Privacy Statement", ""),
|
||||
("Mute", "静音"),
|
||||
("Audio Input", "音频输入"),
|
||||
("Enhancements", "增强功能"),
|
||||
@@ -116,7 +118,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Good image quality", "好画质"),
|
||||
("Balanced", "一般画质"),
|
||||
("Optimize reaction time", "优化反应时间"),
|
||||
("Custom", "自定义画质"),
|
||||
("Custom", "自定义"),
|
||||
("Show remote cursor", "显示远程光标"),
|
||||
("Show quality monitor", "显示质量监测"),
|
||||
("Disable clipboard", "禁止剪贴板"),
|
||||
@@ -136,13 +138,13 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Failed to make direct connection to remote desktop", "无法建立直接连接"),
|
||||
("Set Password", "设置密码"),
|
||||
("OS Password", "操作系统密码"),
|
||||
("install_tip", "你正在运行未安装版本,由于UAC限制,作为被控端,会在某些情况下无法控制鼠标键盘,或者录制屏幕,请点击下面的按钮将RustDesk安装到系统,从而规避上述问题。"),
|
||||
("install_tip", "你正在运行未安装版本,由于UAC限制,作为被控端,会在某些情况下无法控制鼠标键盘,或者录制屏幕,请点击下面的按钮将 RustDesk 安装到系统,从而规避上述问题。"),
|
||||
("Click to upgrade", "点击这里升级"),
|
||||
("Click to download", "点击这里下载"),
|
||||
("Click to update", "点击这里更新"),
|
||||
("Configure", "配置"),
|
||||
("config_acc", "为了能够远程控制你的桌面, 请给予RustDesk\"辅助功能\" 权限。"),
|
||||
("config_screen", "为了能够远程访问你的桌面, 请给予RustDesk\"屏幕录制\" 权限。"),
|
||||
("config_acc", "为了能够远程控制你的桌面, 请给予 RustDesk \"辅助功能\" 权限。"),
|
||||
("config_screen", "为了能够远程访问你的桌面, 请给予 RustDesk \"屏幕录制\" 权限。"),
|
||||
("Installing ...", "安装 ..."),
|
||||
("Install", "安装"),
|
||||
("Installation", "安装"),
|
||||
@@ -208,6 +210,11 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Always connect via relay", "强制走中继连接"),
|
||||
("whitelist_tip", "只有白名单里的ip才能访问我"),
|
||||
("Login", "登录"),
|
||||
("Verify", "验证"),
|
||||
("Remember me", "记住我"),
|
||||
("Trust this device", "信任此设备"),
|
||||
("Verification code", "验证码"),
|
||||
("verification_tip", "检测到新设备登录,已向注册邮箱发送了登录验证码,输入验证码继续登录"),
|
||||
("Logout", "登出"),
|
||||
("Tags", "标签"),
|
||||
("Search ID", "查找ID"),
|
||||
@@ -219,7 +226,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Network error", "网络错误"),
|
||||
("Username missed", "用户名没有填写"),
|
||||
("Password missed", "密码没有填写"),
|
||||
("Wrong credentials", "用户名或者密码错误"),
|
||||
("Wrong credentials", "提供的登入信息错误"),
|
||||
("Edit Tag", "修改标签"),
|
||||
("Unremember Password", "忘掉密码"),
|
||||
("Favorites", "收藏"),
|
||||
@@ -271,14 +278,14 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Do you accept?", "是否接受?"),
|
||||
("Open System Setting", "打开系统设置"),
|
||||
("How to get Android input permission?", "如何获取安卓的输入权限?"),
|
||||
("android_input_permission_tip1", "為了讓遠程設備通過鼠標或者觸屏控制您的安卓設備,你需要允許RustDesk使用\"無障礙\"服務。"),
|
||||
("android_input_permission_tip1", "为了让远程设备通过鼠标或触屏控制您的安卓设备,你需要允許RustDesk使用\"无障碍\"服务。"),
|
||||
("android_input_permission_tip2", "请在接下来的系统设置页面里,找到并进入 [已安装的服务] 页面,将 [RustDesk Input] 服务开启。"),
|
||||
("android_new_connection_tip", "收到新的连接控制请求,对方想要控制你当前的设备。"),
|
||||
("android_service_will_start_tip", "开启录屏权限将自动开启服务,允许其他设备向此设备请求建立连接。"),
|
||||
("android_stop_service_tip", "关闭服务将自动关闭所有已建立的连接。"),
|
||||
("android_version_audio_tip", "当前安卓版本不支持音频录制,请升级至安卓10或更高。"),
|
||||
("android_start_service_tip", "点击 [启动服务] 或打开 [屏幕录制] 权限开启手机屏幕共享服务。"),
|
||||
("Account", "账号"),
|
||||
("Account", "账户"),
|
||||
("Overwrite", "覆盖"),
|
||||
("This file exists, skip or overwrite this file?", "这个文件/文件夹已存在,跳过/覆盖?"),
|
||||
("Quit", "退出"),
|
||||
@@ -296,9 +303,9 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("In privacy mode", "进入隐私模式"),
|
||||
("Out privacy mode", "退出隐私模式"),
|
||||
("Language", "语言"),
|
||||
("Keep RustDesk background service", "保持RustDesk后台服务"),
|
||||
("Keep RustDesk background service", "保持 RustDesk 后台服务"),
|
||||
("Ignore Battery Optimizations", "忽略电池优化"),
|
||||
("android_open_battery_optimizations_tip", "如需关闭此功能,请在接下来的RustDesk应用设置页面中,找到并进入 [电源] 页面,取消勾选 [不受限制]"),
|
||||
("android_open_battery_optimizations_tip", "如需关闭此功能,请在接下来的 RustDesk 应用设置页面中,找到并进入 [电源] 页面,取消勾选 [不受限制]"),
|
||||
("Connection not allowed", "对方不允许连接"),
|
||||
("Legacy mode", "传统模式"),
|
||||
("Map mode", "1:1传输"),
|
||||
@@ -332,7 +339,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Scale adaptive", "适应窗口"),
|
||||
("General", "常规"),
|
||||
("Security", "安全"),
|
||||
("Account", "账户"),
|
||||
("Theme", "主题"),
|
||||
("Dark Theme", "暗黑主题"),
|
||||
("Dark", "黑暗"),
|
||||
@@ -345,7 +351,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Server", "服务器"),
|
||||
("Direct IP Access", "IP直接访问"),
|
||||
("Proxy", "代理"),
|
||||
("Port", "端口"),
|
||||
("Apply", "应用"),
|
||||
("Disconnect all devices?", "断开所有远程连接?"),
|
||||
("Clear", "清空"),
|
||||
@@ -374,14 +379,13 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Other", "其他"),
|
||||
("Confirm before closing multiple tabs", "关闭多个标签页时向您确认"),
|
||||
("Keyboard Settings", "键盘设置"),
|
||||
("Custom", "自定义"),
|
||||
("Full Access", "完全访问"),
|
||||
("Screen Share", "仅共享屏幕"),
|
||||
("Wayland requires Ubuntu 21.04 or higher version.", "Wayland 需要 Ubuntu 21.04 或更高版本。"),
|
||||
("Wayland requires higher version of linux distro. Please try X11 desktop or change your OS.", "Wayland 需要更高版本的 linux 发行版。 请尝试 X11 桌面或更改您的操作系统。"),
|
||||
("JumpLink", "查看"),
|
||||
("Please Select the screen to be shared(Operate on the peer side).", "请选择要分享的画面(对端操作)。"),
|
||||
("Show RustDesk", "显示rustdesk"),
|
||||
("Show RustDesk", "显示 RustDesk"),
|
||||
("This PC", "此电脑"),
|
||||
("or", "或"),
|
||||
("Continue with", "使用"),
|
||||
@@ -401,5 +405,13 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Right click to select tabs", "右键选择选项卡"),
|
||||
("Skipped", "已跳过"),
|
||||
("Add to Address Book", "添加到地址簿"),
|
||||
("Group", "小组"),
|
||||
("Search", "搜索"),
|
||||
("Closed manually by the web console", "被web控制台手动关闭"),
|
||||
("Local keyboard type", "本地键盘类型"),
|
||||
("Select local keyboard type", "请选择本地键盘类型"),
|
||||
("software_render_tip", "如果你使用英伟达显卡, 并且远程窗口在会话建立后会立刻关闭, 那么安装nouveau驱动并且选择使用软件渲染可能会有帮助。重启软件后生效。"),
|
||||
("Always use software rendering", "使用软件渲染"),
|
||||
("config_input", "为了能够通过键盘控制远程桌面, 请给予 RustDesk \"输入监控\" 权限。"),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
||||
@@ -39,6 +39,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Change ID", "Změnit identifikátor"),
|
||||
("Website", "Webové stránky"),
|
||||
("About", "O aplikaci"),
|
||||
("Slogan_tip", ""),
|
||||
("Privacy Statement", ""),
|
||||
("Mute", "Ztlumit"),
|
||||
("Audio Input", "Vstup zvuku"),
|
||||
("Enhancements", ""),
|
||||
@@ -208,6 +210,11 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Always connect via relay", "Vždy se spojovat prostřednictvím brány pro předávání (relay)"),
|
||||
("whitelist_tip", "Přístup je umožněn pouze z IP adres, nacházejících se na seznamu povolených"),
|
||||
("Login", "Přihlásit se"),
|
||||
("Verify", ""),
|
||||
("Remember me", ""),
|
||||
("Trust this device", ""),
|
||||
("Verification code", ""),
|
||||
("verification_tip", ""),
|
||||
("Logout", "Odhlásit se"),
|
||||
("Tags", "Štítky"),
|
||||
("Search ID", "Hledat identifikátor"),
|
||||
@@ -332,7 +339,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Scale adaptive", "Měřítko adaptivní"),
|
||||
("General", ""),
|
||||
("Security", ""),
|
||||
("Account", ""),
|
||||
("Theme", ""),
|
||||
("Dark Theme", ""),
|
||||
("Dark", ""),
|
||||
@@ -345,7 +351,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Server", ""),
|
||||
("Direct IP Access", ""),
|
||||
("Proxy", ""),
|
||||
("Port", ""),
|
||||
("Apply", ""),
|
||||
("Disconnect all devices?", ""),
|
||||
("Clear", ""),
|
||||
@@ -374,7 +379,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Other", ""),
|
||||
("Confirm before closing multiple tabs", ""),
|
||||
("Keyboard Settings", ""),
|
||||
("Custom", ""),
|
||||
("Full Access", ""),
|
||||
("Screen Share", ""),
|
||||
("Wayland requires Ubuntu 21.04 or higher version.", "Wayland vyžaduje Ubuntu 21.04 nebo vyšší verzi."),
|
||||
@@ -399,6 +403,15 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("hide_cm_tip", ""),
|
||||
("wayland_experiment_tip", ""),
|
||||
("Right click to select tabs", ""),
|
||||
("Skipped", ""),
|
||||
("Add to Address Book", ""),
|
||||
("Group", ""),
|
||||
("Search", ""),
|
||||
("Closed manually by the web console", ""),
|
||||
("Local keyboard type", ""),
|
||||
("Select local keyboard type", ""),
|
||||
("software_render_tip", ""),
|
||||
("Always use software rendering", ""),
|
||||
("config_input", ""),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
||||
@@ -39,6 +39,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Change ID", "Ændre ID"),
|
||||
("Website", "Hjemmeside"),
|
||||
("About", "Omkring"),
|
||||
("Slogan_tip", ""),
|
||||
("Privacy Statement", ""),
|
||||
("Mute", "Sluk for mikrofonen"),
|
||||
("Audio Input", "Lydindgang"),
|
||||
("Enhancements", ""),
|
||||
@@ -208,6 +210,11 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Always connect via relay", "Forbindelse via relæ-server"),
|
||||
("whitelist_tip", "Kun IP'er på udgivelseslisten kan få adgang til mig"),
|
||||
("Login", "Login"),
|
||||
("Verify", ""),
|
||||
("Remember me", ""),
|
||||
("Trust this device", ""),
|
||||
("Verification code", ""),
|
||||
("verification_tip", ""),
|
||||
("Logout", "logger af"),
|
||||
("Tags", "Nøgleord"),
|
||||
("Search ID", "Søg ID"),
|
||||
@@ -332,7 +339,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Scale adaptive", "Skaler adaptiv"),
|
||||
("General", "Generelt"),
|
||||
("Security", "Sikkerhed"),
|
||||
("Account", "Konto"),
|
||||
("Theme", "Thema"),
|
||||
("Dark Theme", "Mørk Tema"),
|
||||
("Dark", "Mørk"),
|
||||
@@ -345,7 +351,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Server", "Server"),
|
||||
("Direct IP Access", "Direkte IP Adgang"),
|
||||
("Proxy", "Proxy"),
|
||||
("Port", "Port"),
|
||||
("Apply", "Anvend"),
|
||||
("Disconnect all devices?", "Afbryd alle enheder?"),
|
||||
("Clear", "Nulstil"),
|
||||
@@ -374,7 +379,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Other", ""),
|
||||
("Confirm before closing multiple tabs", ""),
|
||||
("Keyboard Settings", ""),
|
||||
("Custom", ""),
|
||||
("Full Access", ""),
|
||||
("Screen Share", ""),
|
||||
("Wayland requires Ubuntu 21.04 or higher version.", "Wayland kræver Ubuntu 21.04 eller nyere version."),
|
||||
@@ -399,6 +403,15 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("hide_cm_tip", ""),
|
||||
("wayland_experiment_tip", ""),
|
||||
("Right click to select tabs", ""),
|
||||
("Skipped", ""),
|
||||
("Add to Address Book", ""),
|
||||
("Group", ""),
|
||||
("Search", ""),
|
||||
("Closed manually by the web console", ""),
|
||||
("Local keyboard type", ""),
|
||||
("Select local keyboard type", ""),
|
||||
("software_render_tip", ""),
|
||||
("Always use software rendering", ""),
|
||||
("config_input", ""),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
||||
119
src/lang/de.rs
119
src/lang/de.rs
@@ -9,21 +9,21 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Established", "Verbunden"),
|
||||
("connecting_status", "Verbinden mit dem RustDesk-Netzwerk..."),
|
||||
("Enable Service", "Vermittlungsdienst aktivieren"),
|
||||
("Start Service", "Starte Vermittlungsdienst"),
|
||||
("Start Service", "Vermittlungsdienst starten"),
|
||||
("Service is running", "Vermittlungsdienst aktiv"),
|
||||
("Service is not running", "Vermittlungsdienst deaktiviert"),
|
||||
("not_ready_status", "Nicht bereit. Bitte überprüfen Sie Ihre Netzwerkverbindung"),
|
||||
("not_ready_status", "Nicht bereit. Bitte überprüfen Sie Ihre Netzwerkverbindung."),
|
||||
("Control Remote Desktop", "Entfernten PC steuern"),
|
||||
("Transfer File", "Datei übertragen"),
|
||||
("Connect", "Verbinden"),
|
||||
("Recent Sessions", "Letzte Sitzungen"),
|
||||
("Address Book", "Adressbuch"),
|
||||
("Confirmation", "Bestätigung"),
|
||||
("TCP Tunneling", "TCP Tunneln"),
|
||||
("TCP Tunneling", "TCP-Tunnelung"),
|
||||
("Remove", "Entfernen"),
|
||||
("Refresh random password", "Zufälliges Passwort erzeugen"),
|
||||
("Set your own password", "Eigenes Passwort setzen"),
|
||||
("Enable Keyboard/Mouse", "Tastatur/Maus aktivieren"),
|
||||
("Enable Keyboard/Mouse", "Tastatur und Maus aktivieren"),
|
||||
("Enable Clipboard", "Zwischenablage aktivieren"),
|
||||
("Enable File Transfer", "Dateiübertragung aktivieren"),
|
||||
("Enable TCP Tunneling", "TCP-Tunnel aktivieren"),
|
||||
@@ -35,10 +35,12 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Export server configuration successfully", "Serverkonfiguration erfolgreich exportiert"),
|
||||
("Invalid server configuration", "Ungültige Serverkonfiguration"),
|
||||
("Clipboard is empty", "Zwischenablage ist leer"),
|
||||
("Stop service", "Vermittlungsdienst deaktivieren"),
|
||||
("Stop service", "Vermittlungsdienst stoppen"),
|
||||
("Change ID", "ID ändern"),
|
||||
("Website", "Webseite"),
|
||||
("About", "Über"),
|
||||
("Slogan_tip", "Mit Herzblut programmiert - in einer Welt, die im Chaos versinkt"),
|
||||
("Privacy Statement", "Datenschutz"),
|
||||
("Mute", "Stummschalten"),
|
||||
("Audio Input", "Audioeingang"),
|
||||
("Enhancements", "Verbesserungen"),
|
||||
@@ -51,22 +53,22 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Invalid IP", "Ungültige IP-Adresse"),
|
||||
("id_change_tip", "Nur die Zeichen a-z, A-Z, 0-9 und _ (Unterstrich) sind erlaubt. Der erste Buchstabe muss a-z, A-Z sein und die Länge zwischen 6 und 16 Zeichen betragen."),
|
||||
("Invalid format", "Ungültiges Format"),
|
||||
("server_not_support", "Diese Funktion wird noch nicht vom Server unterstützt"),
|
||||
("server_not_support", "Diese Funktion wird noch nicht vom Server unterstützt."),
|
||||
("Not available", "Nicht verfügbar"),
|
||||
("Too frequent", "Zu häufig"),
|
||||
("Cancel", "Abbrechen"),
|
||||
("Skip", "Überspringen"),
|
||||
("Close", "Sitzung beenden"),
|
||||
("Close", "Schließen"),
|
||||
("Retry", "Erneut versuchen"),
|
||||
("OK", "OK"),
|
||||
("Password Required", "Passwort erforderlich"),
|
||||
("Please enter your password", "Bitte geben Sie das Passwort der Gegenstelle ein"),
|
||||
("Please enter your password", "Bitte geben Sie Ihr Passwort ein"),
|
||||
("Remember password", "Passwort merken"),
|
||||
("Wrong Password", "Falsches Passwort"),
|
||||
("Do you want to enter again?", "Erneut verbinden?"),
|
||||
("Connection Error", "Verbindungsfehler"),
|
||||
("Error", "Fehler"),
|
||||
("Reset by the peer", "Verbindung wurde von der Gegenstelle zurückgesetzt"),
|
||||
("Reset by the peer", "Verbindung wurde von der Gegenstelle zurückgesetzt."),
|
||||
("Connecting...", "Verbindung wird hergestellt..."),
|
||||
("Connection in progress. Please wait.", "Die Verbindung wird hergestellt. Bitte warten..."),
|
||||
("Please try 1 minute later", "Bitte versuchen Sie es später erneut"),
|
||||
@@ -92,7 +94,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Select All", "Alles auswählen"),
|
||||
("Unselect All", "Alles abwählen"),
|
||||
("Empty Directory", "Leerer Ordner"),
|
||||
("Not an empty directory", "Ordner ist nicht leer"),
|
||||
("Not an empty directory", "Ordner ist nicht leer."),
|
||||
("Are you sure you want to delete this file?", "Sind Sie sicher, dass Sie diese Datei löschen wollen?"),
|
||||
("Are you sure you want to delete this empty directory?", "Sind Sie sicher, dass Sie diesen leeren Ordner löschen möchten?"),
|
||||
("Are you sure you want to delete the file of this directory?", "Sind Sie sicher, dass Sie die Datei dieses Ordners löschen möchten?"),
|
||||
@@ -111,7 +113,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Original", "Original"),
|
||||
("Shrink", "Verkleinern"),
|
||||
("Stretch", "Strecken"),
|
||||
("Scrollbar", "Scrollleiste"),
|
||||
("Scrollbar", "Scroll-Leiste"),
|
||||
("ScrollAuto", "Automatisch scrollen"),
|
||||
("Good image quality", "Hohe Bildqualität"),
|
||||
("Balanced", "Ausgeglichen"),
|
||||
@@ -124,11 +126,11 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Insert", "Einfügen"),
|
||||
("Insert Lock", "Win+L (Sperren) senden"),
|
||||
("Refresh", "Aktualisieren"),
|
||||
("ID does not exist", "Diese ID existiert nicht"),
|
||||
("ID does not exist", "Diese ID existiert nicht."),
|
||||
("Failed to connect to rendezvous server", "Verbindung zum Vermittlungsserver fehlgeschlagen"),
|
||||
("Please try later", "Bitte versuchen Sie es später erneut"),
|
||||
("Remote desktop is offline", "Entfernter PC ist offline"),
|
||||
("Key mismatch", "Schlüssel stimmt nicht überein"),
|
||||
("Please try later", "Bitte versuchen Sie es später erneut."),
|
||||
("Remote desktop is offline", "Entfernter PC ist offline."),
|
||||
("Key mismatch", "Schlüssel stimmen nicht überein."),
|
||||
("Timeout", "Zeitüberschreitung"),
|
||||
("Failed to connect to relay server", "Verbindung zum Vermittlungsserver fehlgeschlagen"),
|
||||
("Failed to connect via rendezvous server", "Verbindung über Vermittlungsserver ist fehlgeschlagen"),
|
||||
@@ -136,34 +138,34 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Failed to make direct connection to remote desktop", "Direkte Verbindung zum entfernten PC fehlgeschlagen"),
|
||||
("Set Password", "Passwort festlegen"),
|
||||
("OS Password", "Betriebssystem-Passwort"),
|
||||
("install_tip", "Aufgrund der Benutzerkontensteuerung (UAC) kann RustDesk in manchen Fällen nicht ordnungsgemäß funktionieren. Um die Benutzerkontensteuerung zu umgehen, klicken Sie bitte auf die Schaltfläche unten, um RustDesk auf dem System zu installieren"),
|
||||
("install_tip", "Aufgrund der Benutzerkontensteuerung (UAC) kann RustDesk in manchen Fällen nicht ordnungsgemäß funktionieren. Um die Benutzerkontensteuerung zu umgehen, klicken Sie bitte auf die Schaltfläche unten und installieren RustDesk auf dem System."),
|
||||
("Click to upgrade", "Upgrade"),
|
||||
("Click to download", "Zum Herunterladen klicken"),
|
||||
("Click to update", "Update"),
|
||||
("Configure", "Konfigurieren"),
|
||||
("config_acc", "Um Ihren PC aus der Ferne zu steuern, müssen Sie RustDesk Zugriffsrechte erteilen."),
|
||||
("config_screen", "Um aus der Ferne auf Ihren PC zugreifen zu können, müssen Sie RustDesk \"Bildschirm-Aufnahme\"-Berechtigung erteilen."),
|
||||
("config_screen", "Um aus der Ferne auf Ihren PC zugreifen zu können, müssen Sie RustDesk die Berechtigung \"Bildschirmaufnahme\" erteilen."),
|
||||
("Installing ...", "Installiere..."),
|
||||
("Install", "Installieren"),
|
||||
("Installation", "Installation"),
|
||||
("Installation Path", "Installationspfad"),
|
||||
("Create start menu shortcuts", "Verknüpfung im Startmenü erstellen"),
|
||||
("Create desktop icon", "Desktop-Verknüpfung erstellen"),
|
||||
("agreement_tip", "Durch die Installation akzeptieren Sie die Lizenzvereinbarung"),
|
||||
("agreement_tip", "Durch die Installation akzeptieren Sie die Lizenzvereinbarung."),
|
||||
("Accept and Install", "Akzeptieren und Installieren"),
|
||||
("End-user license agreement", "Lizenzvereinbarung für Endbenutzer"),
|
||||
("Generating ...", "Wird generiert..."),
|
||||
("Your installation is lower version.", "Ihre Version ist veraltet."),
|
||||
("not_close_tcp_tip", "Schließen Sie dieses Fenster nicht, solange Sie den Tunnel benutzen."),
|
||||
("Listening ...", "Lausche..."),
|
||||
("Listening ...", "Lauschen..."),
|
||||
("Remote Host", "Entfernter PC"),
|
||||
("Remote Port", "Entfernter Port"),
|
||||
("Action", "Aktion"),
|
||||
("Add", "Hinzufügen"),
|
||||
("Local Port", "Lokaler Port"),
|
||||
("Local Address", "Lokale Addresse"),
|
||||
("Local Address", "Lokale Adresse"),
|
||||
("Change Local Port", "Lokalen Port ändern"),
|
||||
("setup_server_tip", "für eine schnellere Verbindung richten Sie bitte Ihren eigenen Verbindungsserver ein."),
|
||||
("setup_server_tip", "für eine schnellere Verbindung richten Sie bitte Ihren eigenen Server ein."),
|
||||
("Too short, at least 6 characters.", "Zu kurz, mindestens 6 Zeichen."),
|
||||
("The confirmation is not identical.", "Die Passwörter stimmen nicht überein."),
|
||||
("Permissions", "Berechtigungen"),
|
||||
@@ -183,7 +185,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Enter your password", "Geben Sie Ihr Passwort ein"),
|
||||
("Logging in...", "Anmelden..."),
|
||||
("Enable RDP session sharing", "RDP-Sitzungsfreigabe aktivieren"),
|
||||
("Auto Login", "Automatisch anmelden (nur gültig, wenn Sie \"Sperren nach Sitzungsende\" aktiviert haben)"),
|
||||
("Auto Login", "Automatisch anmelden (nur gültig, wenn Sie \"Nach Sitzungsende sperren\" aktiviert haben)"),
|
||||
("Enable Direct IP Access", "Direkten IP-Zugang aktivieren"),
|
||||
("Rename", "Umbenennen"),
|
||||
("Space", "Speicherplatz"),
|
||||
@@ -193,7 +195,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Please enter the folder name", "Bitte geben Sie den Ordnernamen ein"),
|
||||
("Fix it", "Reparieren"),
|
||||
("Warning", "Warnung"),
|
||||
("Login screen using Wayland is not supported", "Anmeldebildschirm wird mit Wayland nicht unterstützt"),
|
||||
("Login screen using Wayland is not supported", "Anmeldebildschirm mit Wayland wird nicht unterstützt."),
|
||||
("Reboot required", "Neustart erforderlich"),
|
||||
("Unsupported display server ", "Nicht unterstützter Display-Server"),
|
||||
("x11 expected", "X11 erwartet"),
|
||||
@@ -206,12 +208,17 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Run without install", "Ohne Installation ausführen"),
|
||||
("Always connected via relay", "Immer über Relay-Server verbunden"),
|
||||
("Always connect via relay", "Immer über Relay-Server verbinden"),
|
||||
("whitelist_tip", "Nur IPs auf der Whitelist können zugreifen"),
|
||||
("whitelist_tip", "Nur IPs auf der Whitelist können zugreifen."),
|
||||
("Login", "Anmelden"),
|
||||
("Verify", ""),
|
||||
("Remember me", ""),
|
||||
("Trust this device", ""),
|
||||
("Verification code", ""),
|
||||
("verification_tip", ""),
|
||||
("Logout", "Abmelden"),
|
||||
("Tags", "Schlagworte"),
|
||||
("Search ID", "Suche ID"),
|
||||
("Current Wayland display server is not supported", "Der aktuelle Wayland-Anzeigeserver wird nicht unterstützt"),
|
||||
("Current Wayland display server is not supported", "Der aktuelle Wayland-Anzeigeserver wird nicht unterstützt."),
|
||||
("whitelist_sep", "Getrennt durch Komma, Semikolon, Leerzeichen oder Zeilenumbruch"),
|
||||
("Add ID", "ID hinzufügen"),
|
||||
("Add Tag", "Stichwort hinzufügen"),
|
||||
@@ -227,17 +234,17 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Remove from Favorites", "Aus Favoriten entfernen"),
|
||||
("Empty", "Keine Einträge"),
|
||||
("Invalid folder name", "Ungültiger Ordnername"),
|
||||
("Socks5 Proxy", "Socks5 Proxy"),
|
||||
("Socks5 Proxy", "SOCKS5-Proxy"),
|
||||
("Hostname", "Hostname"),
|
||||
("Discovered", "Im LAN erkannt"),
|
||||
("install_daemon_tip", "Um mit System zu starten, muss der Systemdienst installiert sein"),
|
||||
("install_daemon_tip", "Um mit System zu starten, muss der Systemdienst installiert sein."),
|
||||
("Remote ID", "Entfernte ID"),
|
||||
("Paste", "Einfügen"),
|
||||
("Paste here?", "Hier einfügen?"),
|
||||
("Are you sure to close the connection?", "Möchten Sie diese Verbindung wirklich trennen?"),
|
||||
("Download new version", "Neue Version herunterladen"),
|
||||
("Touch mode", "Touch-Modus"),
|
||||
("Mouse mode", "Maus-Modus"),
|
||||
("Mouse mode", "Mausmodus"),
|
||||
("One-Finger Tap", "1-Finger-Tipp"),
|
||||
("Left Mouse", "Linksklick"),
|
||||
("One-Long Tap", "1-Finger-Halten"),
|
||||
@@ -253,8 +260,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Pinch to Zoom", "2-Finger-Zoom"),
|
||||
("Canvas Zoom", "Sichtfeld-Zoom"),
|
||||
("Reset canvas", "Sichtfeld zurücksetzen"),
|
||||
("No permission of file transfer", "Keine Berechtigung für den Dateizugriff"),
|
||||
("Note", "Anmerkung"),
|
||||
("No permission of file transfer", "Keine Berechtigung für die Dateiübertragung"),
|
||||
("Note", "Hinweis"),
|
||||
("Connection", "Verbindung"),
|
||||
("Share Screen", "Bildschirm freigeben"),
|
||||
("CLOSE", "DEAKTIV."),
|
||||
@@ -271,8 +278,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Do you accept?", "Verbindung zulassen?"),
|
||||
("Open System Setting", "Systemeinstellung öffnen"),
|
||||
("How to get Android input permission?", "Wie erhalte ich eine Android-Eingabeberechtigung?"),
|
||||
("android_input_permission_tip1", "Damit ein Remote-Gerät Ihr Android-Gerät steuern kann, müssen Sie RustDesk erlauben, den Dienst \"Barrierefreiheit\" zu verwenden."),
|
||||
("android_input_permission_tip2", "Bitte gehen Sie zur nächsten Systemeinstellungsseite, suchen und geben Sie [Installierte Dienste] ein, schalten Sie den Dienst [RustDesk Input] ein."),
|
||||
("android_input_permission_tip1", "Damit ein entferntes Gerät Ihr Android-Gerät steuern kann, müssen Sie RustDesk erlauben, den Dienst \"Barrierefreiheit\" zu verwenden."),
|
||||
("android_input_permission_tip2", "Bitte gehen Sie zur nächsten Systemeinstellungsseite, suchen Sie [Installierte Dienste] und schalten Sie den Dienst [RustDesk Input] ein."),
|
||||
("android_new_connection_tip", "möchte ihr Gerät steuern."),
|
||||
("android_service_will_start_tip", "Durch das Aktivieren der Bildschirmfreigabe wird der Dienst automatisch gestartet, sodass andere Geräte dieses Android-Gerät steuern können."),
|
||||
("android_stop_service_tip", "Durch das Deaktivieren des Dienstes werden automatisch alle hergestellten Verbindungen getrennt."),
|
||||
@@ -288,20 +295,20 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Succeeded", "Erfolgreich"),
|
||||
("Someone turns on privacy mode, exit", "Jemand hat den Datenschutzmodus aktiviert, beende..."),
|
||||
("Unsupported", "Nicht unterstützt"),
|
||||
("Peer denied", "Die Gegenstelle hat die Verbindung abgelehnt"),
|
||||
("Peer denied", "Die Gegenstelle hat die Verbindung abgelehnt."),
|
||||
("Please install plugins", "Bitte installieren Sie Plugins"),
|
||||
("Peer exit", "Die Gegenstelle hat die Verbindung getrennt"),
|
||||
("Peer exit", "Die Gegenstelle hat die Verbindung getrennt."),
|
||||
("Failed to turn off", "Ausschalten fehlgeschlagen"),
|
||||
("Turned off", "Ausgeschaltet"),
|
||||
("In privacy mode", "Datenschutzmodus aktivieren"),
|
||||
("Out privacy mode", "Datenschutzmodus deaktivieren"),
|
||||
("Language", "Sprache"),
|
||||
("Keep RustDesk background service", "RustDesk im Hintergrund ausführen"),
|
||||
("Ignore Battery Optimizations", "Batterieoptimierung ignorieren"),
|
||||
("android_open_battery_optimizations_tip", "Möchten Sie die Einstellungen zur Batterieopimierung öffnen?"),
|
||||
("Ignore Battery Optimizations", "Akkuoptimierung ignorieren"),
|
||||
("android_open_battery_optimizations_tip", "Möchten Sie die Einstellungen zur Akkuoptimierung öffnen?"),
|
||||
("Connection not allowed", "Verbindung abgelehnt"),
|
||||
("Legacy mode", "Kompatibilitätsmodus"),
|
||||
("Map mode", ""), //Muss noch angepasst wer"),
|
||||
("Map mode", "Kartenmodus"),
|
||||
("Translate mode", "Übersetzungsmodus"),
|
||||
("Use permanent password", "Permanentes Passwort verwenden"),
|
||||
("Use both passwords", "Beide Passwörter verwenden"),
|
||||
@@ -328,16 +335,15 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Relay Connection", "Relaisverbindung"),
|
||||
("Secure Connection", "Sichere Verbindung"),
|
||||
("Insecure Connection", "Unsichere Verbindung"),
|
||||
("Scale original", "Keine Saklierung"),
|
||||
("Scale adaptive", "Automatische Saklierung"),
|
||||
("Scale original", "Keine Skalierung"),
|
||||
("Scale adaptive", "Automatische Skalierung"),
|
||||
("General", "Allgemein"),
|
||||
("Security", "Sicherheit"),
|
||||
("Account", "Konto"),
|
||||
("Theme", "Farbgebung"),
|
||||
("Dark Theme", "dunkle Farbgebung"),
|
||||
("Dark Theme", "Dunkle Farbgebung"),
|
||||
("Dark", "Dunkel"),
|
||||
("Light", "Hell"),
|
||||
("Follow System", "System-Standard"),
|
||||
("Follow System", "Systemstandard"),
|
||||
("Enable hardware codec", "Hardware-Codec aktivieren"),
|
||||
("Unlock Security Settings", "Sicherheitseinstellungen entsperren"),
|
||||
("Enable Audio", "Audio aktivieren"),
|
||||
@@ -345,7 +351,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Server", "Server"),
|
||||
("Direct IP Access", "Direkter IP-Zugriff"),
|
||||
("Proxy", "Proxy"),
|
||||
("Port", "Port"),
|
||||
("Apply", "Anwenden"),
|
||||
("Disconnect all devices?", "Alle Geräte trennen?"),
|
||||
("Clear", "Zurücksetzen"),
|
||||
@@ -358,7 +363,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Unpin menubar", "Menüleiste lösen"),
|
||||
("Recording", "Aufnahme"),
|
||||
("Directory", "Verzeichnis"),
|
||||
("Automatically record incoming sessions", "Automatische Aufzeichnung eingehender Sitzungen"),
|
||||
("Automatically record incoming sessions", "Eingehende Sitzungen automatisch aufzeichnen"),
|
||||
("Change", "Ändern"),
|
||||
("Start session recording", "Sitzungsaufzeichnung starten"),
|
||||
("Stop session recording", "Sitzungsaufzeichnung beenden"),
|
||||
@@ -367,14 +372,13 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Enable LAN Discovery", "LAN-Erkennung aktivieren"),
|
||||
("Deny LAN Discovery", "LAN-Erkennung verbieten"),
|
||||
("Write a message", "Nachricht schreiben"),
|
||||
("Prompt", ""), //Aufforderu"),
|
||||
("Prompt", "Meldung"),
|
||||
("Please wait for confirmation of UAC...", "Bitte auf die Bestätigung des Nutzers warten..."),
|
||||
("elevated_foreground_window_tip", ""),
|
||||
("elevated_foreground_window_tip", "Das aktuell geöffnete Fenster des ferngesteuerten Computers benötigt höhere Rechte. Deshalb ist es derzeit nicht möglich, die Maus und die Tastatur zu verwenden. Bitten Sie den Nutzer, dessen Computer Sie fernsteuern, das Fenster zu minimieren oder die Rechte zu erhöhen. Um dieses Problem zukünftig zu vermeiden, wird empfohlen, die Software auf dem ferngesteuerten Computer zu installieren."),
|
||||
("Disconnected", "Verbindung abgebrochen"),
|
||||
("Other", "Weitere Einstellungen"),
|
||||
("Confirm before closing multiple tabs", "Nachfragen, wenn mehrere Tabs geschlossen werden"),
|
||||
("Keyboard Settings", "Tastatureinstellungen"),
|
||||
("Custom", "Individuell"),
|
||||
("Full Access", "Vollzugriff"),
|
||||
("Screen Share", "Bildschirmfreigabe"),
|
||||
("Wayland requires Ubuntu 21.04 or higher version.", "Wayland erfordert Ubuntu 21.04 oder eine höhere Version."),
|
||||
@@ -389,16 +393,25 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Zoom cursor", "Cursor zoomen"),
|
||||
("Accept sessions via password", "Sitzung mit Passwort bestätigen"),
|
||||
("Accept sessions via click", "Sitzung mit einem Klick bestätigen"),
|
||||
("Accept sessions via both", "Sitzung durch Klick und Passwort bestätigen"),
|
||||
("Please wait for the remote side to accept your session request...", "Bitte warten Sie auf die Gegenstelle, dass diese Ihre Sitzungsanfrage bestätigt..."),
|
||||
("Accept sessions via both", "Sitzung mit Klick und Passwort bestätigen"),
|
||||
("Please wait for the remote side to accept your session request...", "Bitte warten Sie, bis die Gegenseite Ihre Sitzungsanfrage akzeptiert hat..."),
|
||||
("One-time Password", "Einmalpasswort"),
|
||||
("Use one-time password", "Einmalpasswort verwenden"),
|
||||
("One-time password length", "Länge des Einmalpassworts"),
|
||||
("Request access to your device", "Zugriff zu Ihrem Gerät erbitten"),
|
||||
("Hide connection management window", "Fenster zur Verwaltung der Verbindung verstecken"),
|
||||
("hide_cm_tip", "Dies ist nur möglich, wenn der Zugriff nur über ein permanentes Passwort erfolgt."), // Sehr unklar. Muss noch angepasst werden. Original: Allow hiding only if accepting sessions via password and using pernament passw"),
|
||||
("wayland_experiment_tip", ""),
|
||||
("Right click to select tabs", ""),
|
||||
("Add to Address Book", ""),
|
||||
("hide_cm_tip", "Dies ist nur möglich, wenn der Zugriff über ein permanentes Passwort erfolgt."),
|
||||
("wayland_experiment_tip", "Die Unterstützung von Wayland ist nur experimentell. Bitte nutzen Sie X11, wenn Sie einen unbeaufsichtigten Zugriff benötigen."),
|
||||
("Right click to select tabs", "Register mit rechtem Mausklick auswählen"),
|
||||
("Skipped", "Übersprungen"),
|
||||
("Add to Address Book", "Zum Adressbuch hinzufügen"),
|
||||
("Group", "Gruppe"),
|
||||
("Search", "Suchen"),
|
||||
("Closed manually by the web console", "Manuell über die Webkonsole beendet"),
|
||||
("Local keyboard type", "Lokaler Tastaturtyp"),
|
||||
("Select local keyboard type", "Lokalen Tastaturtyp auswählen"),
|
||||
("software_render_tip", "Wenn Sie eine Nvidia-Grafikkarte haben und sich das entfernte Fenster sofort nach dem Herstellen der Verbindung schließt, kann es helfen, den Nouveau-Treiber zu installieren und Software-Rendering zu verwenden. Ein Neustart der Software ist erforderlich."),
|
||||
("Always use software rendering", "Software-Rendering immer verwenden"),
|
||||
("config_input", "Um den entfernten Desktop mit der Tastatur steuern zu können, müssen Sie RustDesk \"Input Monitoring\"-Rechte erteilen."),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
||||
@@ -35,5 +35,9 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Stop service", "Stop Service"),
|
||||
("hide_cm_tip", "Allow hiding only if accepting sessions via password and using permanent password"),
|
||||
("wayland_experiment_tip", "Wayland support is in experimental stage, please use X11 if you require unattended access."),
|
||||
("Slogan_tip", "Made with heart in this chaotic world!"),
|
||||
("verification_tip", "A new device has been detected, and a verification code has been sent to the registered email address, enter the verification code to continue logging in."),
|
||||
("software_render_tip", "If you have an Nvidia graphics card and the remote window closes immediately after connecting, installing the nouveau driver and choosing to use software rendering may help. A software restart is required."),
|
||||
("config_input", "In order to control remote desktop with keyboard, you need to grant RustDesk \"Input Monitoring\" permissions."),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
||||
@@ -39,6 +39,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Change ID", "Ŝanĝi identigilon"),
|
||||
("Website", "Retejo"),
|
||||
("About", "Pri"),
|
||||
("Slogan_tip", ""),
|
||||
("Privacy Statement", ""),
|
||||
("Mute", "Muta"),
|
||||
("Audio Input", "Aŭdia enigo"),
|
||||
("Enhancements", ""),
|
||||
@@ -208,6 +210,11 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Always connect via relay", "Ĉiam konekti per relajso"),
|
||||
("whitelist_tip", "Nur la IP en la blanka listo povas kontroli mian komputilon"),
|
||||
("Login", "Konekti"),
|
||||
("Verify", ""),
|
||||
("Remember me", ""),
|
||||
("Trust this device", ""),
|
||||
("Verification code", ""),
|
||||
("verification_tip", ""),
|
||||
("Logout", "Malkonekti"),
|
||||
("Tags", "Etikedi"),
|
||||
("Search ID", "Serĉi ID"),
|
||||
@@ -332,7 +339,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Scale adaptive", "Skalo adapta"),
|
||||
("General", ""),
|
||||
("Security", ""),
|
||||
("Account", ""),
|
||||
("Theme", ""),
|
||||
("Dark Theme", ""),
|
||||
("Dark", ""),
|
||||
@@ -345,7 +351,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Server", ""),
|
||||
("Direct IP Access", ""),
|
||||
("Proxy", ""),
|
||||
("Port", ""),
|
||||
("Apply", ""),
|
||||
("Disconnect all devices?", ""),
|
||||
("Clear", ""),
|
||||
@@ -374,7 +379,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Other", ""),
|
||||
("Confirm before closing multiple tabs", ""),
|
||||
("Keyboard Settings", ""),
|
||||
("Custom", ""),
|
||||
("Full Access", ""),
|
||||
("Screen Share", ""),
|
||||
("Wayland requires Ubuntu 21.04 or higher version.", "Wayland postulas Ubuntu 21.04 aŭ pli altan version."),
|
||||
@@ -399,6 +403,15 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("hide_cm_tip", ""),
|
||||
("wayland_experiment_tip", ""),
|
||||
("Right click to select tabs", ""),
|
||||
("Skipped", ""),
|
||||
("Add to Address Book", ""),
|
||||
("Group", ""),
|
||||
("Search", ""),
|
||||
("Closed manually by the web console", ""),
|
||||
("Local keyboard type", ""),
|
||||
("Select local keyboard type", ""),
|
||||
("software_render_tip", ""),
|
||||
("Always use software rendering", ""),
|
||||
("config_input", ""),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
||||
@@ -17,7 +17,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Transfer File", "Transferir archivo"),
|
||||
("Connect", "Conectar"),
|
||||
("Recent Sessions", "Sesiones recientes"),
|
||||
("Address Book", "Directorio"),
|
||||
("Address Book", "Libreta de direcciones"),
|
||||
("Confirmation", "Confirmación"),
|
||||
("TCP Tunneling", "Túnel TCP"),
|
||||
("Remove", "Quitar"),
|
||||
@@ -39,6 +39,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Change ID", "Cambiar ID"),
|
||||
("Website", "Sitio web"),
|
||||
("About", "Acerca de"),
|
||||
("Slogan_tip", "Hecho con corazón en este mundo caótico!"),
|
||||
("Privacy Statement", ""),
|
||||
("Mute", "Silenciar"),
|
||||
("Audio Input", "Entrada de audio"),
|
||||
("Enhancements", "Mejoras"),
|
||||
@@ -208,6 +210,11 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Always connect via relay", "Conéctese siempre a través de relay"),
|
||||
("whitelist_tip", "Solo las direcciones IP autorizadas pueden conectarse a este escritorio"),
|
||||
("Login", "Iniciar sesión"),
|
||||
("Verify", ""),
|
||||
("Remember me", ""),
|
||||
("Trust this device", ""),
|
||||
("Verification code", ""),
|
||||
("verification_tip", ""),
|
||||
("Logout", "Salir"),
|
||||
("Tags", "Tags"),
|
||||
("Search ID", "Buscar ID"),
|
||||
@@ -332,7 +339,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Scale adaptive", "Escala adaptativa"),
|
||||
("General", ""),
|
||||
("Security", "Seguridad"),
|
||||
("Account", "Cuenta"),
|
||||
("Theme", "Tema"),
|
||||
("Dark Theme", "Tema Oscuro"),
|
||||
("Dark", "Oscuro"),
|
||||
@@ -345,7 +351,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Server", "Servidor"),
|
||||
("Direct IP Access", "Acceso IP Directo"),
|
||||
("Proxy", ""),
|
||||
("Port", "Puerto"),
|
||||
("Apply", "Aplicar"),
|
||||
("Disconnect all devices?", "¿Desconectar todos los dispositivos?"),
|
||||
("Clear", "Borrar"),
|
||||
@@ -374,7 +379,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Other", "Otro"),
|
||||
("Confirm before closing multiple tabs", "Confirmar antes de cerrar múltiples pestañas"),
|
||||
("Keyboard Settings", "Ajustes de teclado"),
|
||||
("Custom", "Personalizado"),
|
||||
("Full Access", "Acceso completo"),
|
||||
("Screen Share", "Compartir pantalla"),
|
||||
("Wayland requires Ubuntu 21.04 or higher version.", "Wayland requiere Ubuntu 21.04 o una versión superior."),
|
||||
@@ -399,6 +403,15 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("hide_cm_tip", "Permitir ocultar solo si se aceptan sesiones a través de contraseña y usando contraseña permanente"),
|
||||
("wayland_experiment_tip", "El soporte para Wayland está en fase experimental, por favor, use X11 si necesita acceso desatendido."),
|
||||
("Right click to select tabs", "Clic derecho para seleccionar pestañas"),
|
||||
("Skipped", ""),
|
||||
("Add to Address Book", "Añadir a la libreta de direcciones"),
|
||||
("Group", "Grupo"),
|
||||
("Search", "Búsqueda"),
|
||||
("Closed manually by the web console", "Cerrado manualmente por la consola web"),
|
||||
("Local keyboard type", "Tipo de teclado local"),
|
||||
("Select local keyboard type", "Seleccionar tipo de teclado local"),
|
||||
("software_render_tip", "Si tienes una gráfica Nvidia y la ventana remota se cierra inmediatamente, instalar el driver nouveau y elegir renderizado por software podría ayudar. Se requiere reiniciar la aplicación."),
|
||||
("Always use software rendering", "Usar siempre renderizado por software"),
|
||||
("config_input", "Para controlar el escritorio remoto con el teclado necesitas dar a RustDesk permisos de \"Monitorización de entrada\"."),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
||||
199
src/lang/fa.rs
199
src/lang/fa.rs
@@ -9,22 +9,22 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Established", "اتصال برقرار شد"),
|
||||
("connecting_status", "...در حال برقراری ارتباط با سرور"),
|
||||
("Enable Service", "فعالسازی سرویس"),
|
||||
("Start Service", "اجرا سرویس"),
|
||||
("Start Service", "اجرای سرویس"),
|
||||
("Service is running", "سرویس در حال اجرا است"),
|
||||
("Service is not running", "سرویس اجرا نشده"),
|
||||
("not_ready_status", "ارتباط برقرار نشد. لطفا شبکه خود را بررسی کنید"),
|
||||
("Control Remote Desktop", "کنترل دسکتاپ میزبان"),
|
||||
("Transfer File", "جابه جایی فایل"),
|
||||
("Transfer File", "انتقال فایل"),
|
||||
("Connect", "اتصال"),
|
||||
("Recent Sessions", "جلسات اخیر"),
|
||||
("Address Book", "دفترچه آدرس"),
|
||||
("Confirmation", "تایید"),
|
||||
("TCP Tunneling", "TCP تانل"),
|
||||
("Remove", "حذف"),
|
||||
("Refresh random password", "رمز عبور تصادفی را بروز کنید"),
|
||||
("Refresh random password", "بروزرسانی رمز عبور تصادفی"),
|
||||
("Set your own password", "!رمز عبور دلخواه بگذارید"),
|
||||
("Enable Keyboard/Mouse", "Keyboard/Mouse فعالسازی"),
|
||||
("Enable Clipboard", "Clipboard فعالسازی"),
|
||||
("Enable Keyboard/Mouse", " فعالسازی ماوس/صفحه کلید"),
|
||||
("Enable Clipboard", "فعال سازی کلیپبورد"),
|
||||
("Enable File Transfer", "انتقال فایل را فعال کنید"),
|
||||
("Enable TCP Tunneling", "را فعال کنید TCP تانل"),
|
||||
("IP Whitelisting", "های مجاز IP لیست"),
|
||||
@@ -34,11 +34,13 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Import server configuration successfully", "تنظیمات سرور با فایل کانفیگ با موفقیت انجام شد"),
|
||||
("Export server configuration successfully", "ایجاد فایل کانفیگ از تنظیمات فعلی با موفقیت انجام شد"),
|
||||
("Invalid server configuration", "تنظیمات سرور نامعتبر است"),
|
||||
("Clipboard is empty", "خالی است Clipboard"),
|
||||
("Clipboard is empty", "کلیپبورد خالی است"),
|
||||
("Stop service", "توقف سرویس"),
|
||||
("Change ID", "تعویض شناسه"),
|
||||
("Website", "وب سایت"),
|
||||
("About", "درباره"),
|
||||
("Slogan_tip", ""),
|
||||
("Privacy Statement", ""),
|
||||
("Mute", "بستن صدا"),
|
||||
("Audio Input", "ورودی صدا"),
|
||||
("Enhancements", "بهبودها"),
|
||||
@@ -50,10 +52,10 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("invalid_http", "شروع شود http:// یا https:// باید با"),
|
||||
("Invalid IP", "نامعتبر است IP آدرس"),
|
||||
("id_change_tip", "شناسه باید طبق این شرایط باشد : حروف کوچک و بزرگ انگلیسی و اعداد از 0 تا 9، _ و همچنین حرف اول آن فقط حروف بزرگ یا کوچک انگلیسی و طول آن بین 6 الی 16 کاراکتر باشد"),
|
||||
("Invalid format", "فرمت نادرس است"),
|
||||
("Invalid format", "فرمت نادرست است"),
|
||||
("server_not_support", "هنوز توسط سرور مورد نظر پشتیبانی نمی شود"),
|
||||
("Not available", "در دسترسی نیست"),
|
||||
("Too frequent", "تعداد زیاد"),
|
||||
("Too frequent", "خیلی رایج"),
|
||||
("Cancel", "لغو"),
|
||||
("Skip", "رد کردن"),
|
||||
("Close", "بستن"),
|
||||
@@ -72,7 +74,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Please try 1 minute later", "لطفا بعد از 1 دقیقه مجددا تلاش کنید"),
|
||||
("Login Error", "ورود ناموفق بود"),
|
||||
("Successful", "ورود با موفقیت انجام شد"),
|
||||
("Connected, waiting for image...", "ارتباط وصل شد. برای دریافت تصویر دسکتاپ میزبان منتظر بمانید..."),
|
||||
("Connected, waiting for image...", "...ارتباط برقرار شد. انتظار برای دریافت تصاویر"),
|
||||
("Name", "نام"),
|
||||
("Type", "نوع فایل"),
|
||||
("Modified", "تاریخ تغییر"),
|
||||
@@ -84,20 +86,20 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Local", "محلی"),
|
||||
("Remote", "از راه دور"),
|
||||
("Remote Computer", "سیستم میزبان"),
|
||||
("Local Computer", "سیستم از راه دور"),
|
||||
("Confirm Delete", "حذف را تایید کنید"),
|
||||
("Local Computer", "سیستم راه دور"),
|
||||
("Confirm Delete", "تایید حذف"),
|
||||
("Delete", "حذف"),
|
||||
("Properties", "Properties"),
|
||||
("Multi Select", "انتخاب همزمان"),
|
||||
("Properties", "مشخصات"),
|
||||
("Multi Select", "انتخاب دسته ای"),
|
||||
("Select All", "انتخاب همه"),
|
||||
("Unselect All", "عدم انتخاب همه"),
|
||||
("Unselect All", "لغو انتخاب همه"),
|
||||
("Empty Directory", "پوشه خالی"),
|
||||
("Not an empty directory", "پوشه خالی نیست"),
|
||||
("Are you sure you want to delete this file?", "از حذف این فایل مطمئن هستید؟"),
|
||||
("Are you sure you want to delete this empty directory?", "از حذف این پوشه خالی مطمئن هستید؟"),
|
||||
("Are you sure you want to delete the file of this directory?", "از حذف فایل موجود در این پوشه مطمئن هستید؟"),
|
||||
("Do this for all conflicts", "این عمل را برای همه ی تضادها انجام شود"),
|
||||
("This is irreversible!", "این برگشت ناپذیر است!"),
|
||||
("Do this for all conflicts", "این عمل برای همه ی تضادها انجام شود"),
|
||||
("This is irreversible!", "این اقدام برگشت ناپذیر است!"),
|
||||
("Deleting", "در حال حذف"),
|
||||
("files", "فایل ها"),
|
||||
("Waiting", "انتظار"),
|
||||
@@ -105,21 +107,21 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Speed", "سرعت"),
|
||||
("Custom Image Quality", "سفارشی سازی کیفیت تصاویر"),
|
||||
("Privacy mode", "حالت حریم خصوصی"),
|
||||
("Block user input", "ورودی کاربر را مسدود کنید"),
|
||||
("Unblock user input", "قفل ورودی کاربر را باز کنید"),
|
||||
("Adjust Window", "پنجره را تنظیم کنید"),
|
||||
("Block user input", "بلاک کردن ورودی کاربر"),
|
||||
("Unblock user input", "آنبلاک کردن ورودی کاربر"),
|
||||
("Adjust Window", "تنظیم پنجره"),
|
||||
("Original", "اصل"),
|
||||
("Shrink", ""),
|
||||
("Stretch", ""),
|
||||
("Scrollbar", ""),
|
||||
("ScrollAuto", ""),
|
||||
("Shrink", "کوچک کردن"),
|
||||
("Stretch", "کشیدن تصویر"),
|
||||
("Scrollbar", "اسکرول بار"),
|
||||
("ScrollAuto", "پیمایش/اسکرول خودکار"),
|
||||
("Good image quality", "کیفیت خوب تصویر"),
|
||||
("Balanced", "متعادل"),
|
||||
("Optimize reaction time", "زمان واکنش را بهینه کنید"),
|
||||
("Optimize reaction time", "بهینه سازی زمان واکنش"),
|
||||
("Custom", "سفارشی"),
|
||||
("Show remote cursor", "نمایش مکان نما موس میزبان"),
|
||||
("Show quality monitor", "نمایش کیفیت مانیتور"),
|
||||
("Disable clipboard", "Clipboard غیرفعالسازی"),
|
||||
("Disable clipboard", " غیرفعالسازی کلیپبورد"),
|
||||
("Lock after session end", "قفل کردن حساب کاربری سیستم عامل پس از پایان جلسه"),
|
||||
("Insert", "افزودن"),
|
||||
("Insert Lock", "افزودن قفل"),
|
||||
@@ -127,23 +129,23 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("ID does not exist", "شناسه وجود ندارد"),
|
||||
("Failed to connect to rendezvous server", "اتصال به سرور تولید شناسه انجام نشد"),
|
||||
("Please try later", "لطفا بعدا تلاش کنید"),
|
||||
("Remote desktop is offline", "دسکتاپ از راه دور خاموش است"),
|
||||
("Remote desktop is offline", "دسکتاپ راه دور آفلاین است"),
|
||||
("Key mismatch", "عدم تطابق کلید"),
|
||||
("Timeout", "زمان انتظار به پایان رسید"),
|
||||
("Failed to connect to relay server", "سرور وصل نشد Relay به"),
|
||||
("Failed to connect via rendezvous server", "اتصال از طریق سرور تولید شناسه انجام نشد"),
|
||||
("Failed to connect via relay server", "انجام نشد Relay اتصال از طریق سرور"),
|
||||
("Failed to make direct connection to remote desktop", "اتصال مستقیم به دسکتاپ از راه دور با موفقیت انجام نشد"),
|
||||
("Set Password", "اختصاص رمزعبور"),
|
||||
("Failed to make direct connection to remote desktop", "اتصال مستقیم به دسکتاپ راه دور انجام نشد"),
|
||||
("Set Password", "تنظیم رمزعبور"),
|
||||
("OS Password", "رمز عیور سیستم عامل"),
|
||||
("install_tip", "لطفا برنامه را نصب کنید UAC و جلوگیری از خطای RustDesk برای راحتی در استفاده از نرم افزار"),
|
||||
("Click to upgrade", "برای ارتقا کلیک کنید"),
|
||||
("Click to download", "برای دانلود کلیک کنید"),
|
||||
("Click to update", "برای به روز رسانی کلیک کنید"),
|
||||
("Configure", "تنظیم"),
|
||||
("config_acc", "برای کنترل از راه دور دسکتاپ، باید به RustDesk مجوز \"access\" بدهید"),
|
||||
("config_screen", "برای دسترسی از راه دور به دسکتاپ خود، باید به RustDesk مجوزهای \"screenshot\" بدهید."),
|
||||
("Installing ...", "در حال نصب..."),
|
||||
("config_acc", "بدهید \"access\" مجوز RustDesk برای کنترل از راه دور دسکتاپ باید به"),
|
||||
("config_screen", "بدهید \"screenshot\" مجوز RustDesk برای کنترل از راه دور دسکتاپ باید به"),
|
||||
("Installing ...", "...در حال نصب"),
|
||||
("Install", "نصب"),
|
||||
("Installation", "نصب و راه اندازی"),
|
||||
("Installation Path", "محل نصب"),
|
||||
@@ -152,28 +154,28 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("agreement_tip", "با شروع نصب، شرایط توافق نامه مجوز را می پذیرید"),
|
||||
("Accept and Install", "قبول و شروع نصب"),
|
||||
("End-user license agreement", "قرارداد مجوز کاربر نهایی"),
|
||||
("Generating ...", "پدید آوردن..."),
|
||||
("Your installation is lower version.", "نسخه قبلی نصب شده است"),
|
||||
("Generating ...", "...در حال تولید"),
|
||||
("Your installation is lower version.", "نسخه قدیمی تری نصب شده است"),
|
||||
("not_close_tcp_tip", "هنگام استفاده از تونل این پنجره را نبندید"),
|
||||
("Listening ...", "انتظار..."),
|
||||
("Remote Host", "دستگاه از راه دور"),
|
||||
("Listening ...", "...انتظار"),
|
||||
("Remote Host", "هاست راه دور"),
|
||||
("Remote Port", "پورت راه دور"),
|
||||
("Action", "عملیات"),
|
||||
("Add", "افزودن"),
|
||||
("Local Port", "پورت محلی"),
|
||||
("Local Address", "آدرس محلی"),
|
||||
("Change Local Port", "تغییر پورت محلی"),
|
||||
("setup_server_tip", "برای اتصال سریعتر، سرور اتصال خود را راه اندازی کنید"),
|
||||
("setup_server_tip", "برای اتصال سریعتر، سرور اتصال ضخصی خود را راه اندازی کنید"),
|
||||
("Too short, at least 6 characters.", "بسیار کوتاه حداقل 6 کاراکتر مورد نیاز است"),
|
||||
("The confirmation is not identical.", "تأیید ناموفق بود."),
|
||||
("Permissions", "دسترسی ها"),
|
||||
("Accept", "پذیرفتن"),
|
||||
("Dismiss", "رد کردن"),
|
||||
("Disconnect", "قطع اتصال"),
|
||||
("Allow using keyboard and mouse", "اجازه استفاده از صفحه کلید و ماوس را بدهید"),
|
||||
("Allow using clipboard", "را بدهید Clipboard اجازه استفاده از"),
|
||||
("Allow hearing sound", "اجازه شنیدن صدا را بدهید"),
|
||||
("Allow file copy and paste", "اجازه کپی و چسباندن فایل را بدهید"),
|
||||
("Allow using keyboard and mouse", "مجاز بودن استفاده از صفحه کلید و ماوس"),
|
||||
("Allow using clipboard", "مجاز بودن استفاده از کلیپبورد"),
|
||||
("Allow hearing sound", "مجاز بودن شنیدن صدا"),
|
||||
("Allow file copy and paste", "مجاز بودن کپی و چسباندن فایل"),
|
||||
("Connected", "متصل شده"),
|
||||
("Direct and encrypted connection", "اتصال مستقیم و رمزگذاری شده"),
|
||||
("Relayed and encrypted connection", "و رمزگذاری شده Relay اتصال از طریق"),
|
||||
@@ -181,7 +183,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Relayed and unencrypted connection", "و رمزگذاری نشده Relay اتصال از طریق"),
|
||||
("Enter Remote ID", "شناسه از راه دور را وارد کنید"),
|
||||
("Enter your password", "زمر عبور خود را وارد کنید"),
|
||||
("Logging in...", "در حال ورود..."),
|
||||
("Logging in...", "...در حال ورود"),
|
||||
("Enable RDP session sharing", "اشتراک گذاری جلسه RDP را فعال کنید"),
|
||||
("Auto Login", "ورود خودکار"),
|
||||
("Enable Direct IP Access", "دسترسی مستقیم IP را فعال کنید"),
|
||||
@@ -193,7 +195,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Please enter the folder name", "نام پوشه را وارد کنید"),
|
||||
("Fix it", "بازسازی"),
|
||||
("Warning", "هشدار"),
|
||||
("Login screen using Wayland is not supported", "ورود به سیستم با استفاده از Wayland پشتیبانی نمی شود"),
|
||||
("Login screen using Wayland is not supported", "پشتیبانی نمی شود Wayland ورود به سیستم با استفاده از "),
|
||||
("Reboot required", "راه اندازی مجدد مورد نیاز است"),
|
||||
("Unsupported display server ", "سرور تصویر پشتیبانی نشده است"),
|
||||
("x11 expected", ""),
|
||||
@@ -202,16 +204,21 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Username", "نام کاربری"),
|
||||
("Invalid port", "پورت نامعتبر است"),
|
||||
("Closed manually by the peer", "به صورت دستی توسط میزبان بسته شد"),
|
||||
("Enable remote configuration modification", "تغییرات پیکربندی از راه دور را مجاز کنید"),
|
||||
("Enable remote configuration modification", "فعال بودن اعمال تغییرات پیکربندی از راه دور"),
|
||||
("Run without install", "بدون نصب اجرا شود"),
|
||||
("Always connected via relay", "متصل است Relay همیشه با"),
|
||||
("Always connect via relay", "برای اتصال استفاده کنید Relay از"),
|
||||
("whitelist_tip", "فقط آدرس های IP مجاز می توانند به این دسکتاپ متصل شوند"),
|
||||
("Always connect via relay", "برای اتصال استفاده شود Relay از"),
|
||||
("whitelist_tip", "های مجاز می توانند به این دسکتاپ متصل شوند IP فقط"),
|
||||
("Login", "ورود"),
|
||||
("Verify", ""),
|
||||
("Remember me", ""),
|
||||
("Trust this device", ""),
|
||||
("Verification code", ""),
|
||||
("verification_tip", ""),
|
||||
("Logout", "خروج"),
|
||||
("Tags", "برچسب ها"),
|
||||
("Search ID", "جستجوی شناسه"),
|
||||
("Current Wayland display server is not supported", "سرور نمای فعلی Wayland پشتیبانی نمی شود"),
|
||||
("Current Wayland display server is not supported", "پشتیبانی نمی شود Wayland سرور نمایش فعلی"),
|
||||
("whitelist_sep", "با کاما، نقطه ویرگول، فاصله یا خط جدید از هم جدا می شوند"),
|
||||
("Add ID", "افزودن شناسه"),
|
||||
("Add Tag", "افزودن برچسب"),
|
||||
@@ -220,19 +227,19 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Username missed", "نام کاربری وجود ندارد"),
|
||||
("Password missed", "رمزعبور وجود ندارد"),
|
||||
("Wrong credentials", "اعتبارنامه نادرست است"),
|
||||
("Edit Tag", "برچسب را تغییر دهید"),
|
||||
("Unremember Password", "رمز عبور را ذخیره نکنید"),
|
||||
("Favorites", "موارد دلخواه"),
|
||||
("Edit Tag", "ویرایش برچسب"),
|
||||
("Unremember Password", "رمز عبور ذخیره نشود"),
|
||||
("Favorites", "اتصالات دلخواه"),
|
||||
("Add to Favorites", "افزودن به علاقه مندی ها"),
|
||||
("Remove from Favorites", "از علاقه مندی ها حذف شود"),
|
||||
("Empty", "موردی وجود ندارد"),
|
||||
("Invalid folder name", "نام پوشه نامعتبر است"),
|
||||
("Socks5 Proxy", "Socks5 Proxy"),
|
||||
("Hostname", "Hostname"),
|
||||
("Hostname", "نام هاست"),
|
||||
("Discovered", "پیدا شده"),
|
||||
("install_daemon_tip", "برای شروع در هنگام راه اندازی، باید سرویس سیستم را نصب کنید"),
|
||||
("Remote ID", "شناسه از راه دور"),
|
||||
("Paste", "درج کنید"),
|
||||
("Remote ID", "شناسه راه دور"),
|
||||
("Paste", "درج"),
|
||||
("Paste here?", "اینجا درج شود؟"),
|
||||
("Are you sure to close the connection?", "آیا مطمئن هستید که می خواهید اتصال را پایان دهید؟"),
|
||||
("Download new version", "دانلود نسخه جدید"),
|
||||
@@ -241,7 +248,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("One-Finger Tap", "با یک انگشت لمس کنید"),
|
||||
("Left Mouse", "دکمه سمت چپ ماوس"),
|
||||
("One-Long Tap", "لمس طولانی با یک انگشت"),
|
||||
("Two-Finger Tap", "با دو انگشت لمس کنید"),
|
||||
("Two-Finger Tap", "لمس دو انگشتی"),
|
||||
("Right Mouse", "دکمه سمت راست ماوس"),
|
||||
("One-Finger Move", "با یک انگشت حرکت کنید"),
|
||||
("Double Tap & Move", "دو ضربه سریع بزنید و حرکت دهید"),
|
||||
@@ -250,7 +257,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Mouse Wheel", "چرخ ماوس"),
|
||||
("Two-Finger Move", "با دو انگشت حرکت کنید"),
|
||||
("Canvas Move", ""),
|
||||
("Pinch to Zoom", "زوم را کوچک کنید"),
|
||||
("Pinch to Zoom", "با دو انگشت بکشید تا زوم شود"),
|
||||
("Canvas Zoom", ""),
|
||||
("Reset canvas", ""),
|
||||
("No permission of file transfer", "مجوز انتقال فایل داده نشده"),
|
||||
@@ -261,14 +268,14 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("OPEN", "باز کردن"),
|
||||
("Chat", "چت"),
|
||||
("Total", "مجموع"),
|
||||
("items", "موارد"),
|
||||
("items", "آیتم ها"),
|
||||
("Selected", "انتخاب شده"),
|
||||
("Screen Capture", "ضبط صفحه"),
|
||||
("Input Control", "کنترل ورودی"),
|
||||
("Audio Capture", "ضبط صدا"),
|
||||
("File Connection", "ارتباط فایل"),
|
||||
("Screen Connection", "ارتباط صفحه"),
|
||||
("Do you accept?", "شما می پذیرید؟"),
|
||||
("Do you accept?", "آیا می پذیرید؟"),
|
||||
("Open System Setting", "باز کردن تنظیمات سیستم"),
|
||||
("How to get Android input permission?", "چگونه مجوز ورود به سیستم اندروید را دریافت کنیم؟"),
|
||||
("android_input_permission_tip1", "برای اینکه یک دستگاه راه دور بتواند دستگاه Android شما را از طریق ماوس یا لمسی کنترل کند، باید به RustDesk اجازه دهید از ویژگی \"Accessibility\" استفاده کند."),
|
||||
@@ -280,7 +287,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("android_start_service_tip", "برای شروع سرویس اشتراکگذاری صفحه، روی مجوز \"شروع مرحلهبندی سرور\" یا OPEN \"Screen Capture\" کلیک کنید."),
|
||||
("Account", "حساب کاربری"),
|
||||
("Overwrite", "بازنویسی"),
|
||||
("This file exists, skip or overwrite this file?", "این فایل وجود دارد، از فایل رد شود یا بازنویسی شود؟"),
|
||||
("This file exists, skip or overwrite this file?", "این فایل وجود دارد، از فایل رد شود یا آن را بازنویسی کند؟"),
|
||||
("Quit", "خروج"),
|
||||
("doc_mac_permission", "https://rustdesk.com/docs/en/manual/mac/#enable-permissions"),
|
||||
("Help", "راهنما"),
|
||||
@@ -291,27 +298,27 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Peer denied", "توسط میزبان راه دور رد شد"),
|
||||
("Please install plugins", "لطفا افزونه ها را نصب کنید"),
|
||||
("Peer exit", "میزبان خارج شد"),
|
||||
("Failed to turn off", "خاموش کردن با موفقیت انجام نشد"),
|
||||
("Failed to turn off", "خاموش کردن انجام نشد"),
|
||||
("Turned off", "خاموش شد"),
|
||||
("In privacy mode", "در حالت حریم خصوصی"),
|
||||
("Out privacy mode", "خارج از حالت حریم خصوصی"),
|
||||
("Language", "زبان"),
|
||||
("Keep RustDesk background service", "سرویس RustDesk را در پس زمینه نگه دارید"),
|
||||
("Ignore Battery Optimizations", "بهینه سازی باتری را نادیده بگیرید"),
|
||||
("Keep RustDesk background service", "را در پس زمینه نگه دارید RustDesk سرویس"),
|
||||
("Ignore Battery Optimizations", "بهینه سازی باتری نادیده گرفته شود"),
|
||||
("android_open_battery_optimizations_tip", "به صفحه تنظیمات بعدی بروید"),
|
||||
("Connection not allowed", "اتصال مجاز نیست"),
|
||||
("Legacy mode", "پشتیبانی موارد قدیمی"),
|
||||
("Map mode", "حالت نقشه"),
|
||||
("Legacy mode", "legacy حالت"),
|
||||
("Map mode", "map حالت"),
|
||||
("Translate mode", "حالت ترجمه"),
|
||||
("Use permanent password", "از رمز عبور دائمی استفاده کنید"),
|
||||
("Use both passwords", "از هر دو رمز عبور استفاده کنید"),
|
||||
("Set permanent password", "یک رمز عبور دائمی تنظیم کنید"),
|
||||
("Enable Remote Restart", "فعال کردن راهاندازی مجدد از راه دور"),
|
||||
("Allow remote restart", "اجازه راه اندازی مجدد از راه دور"),
|
||||
("Restart Remote Device", "راهاندازی مجدد دستگاه از راه دور"),
|
||||
("Use permanent password", "از رمز عبور دائمی استفاده شود"),
|
||||
("Use both passwords", "از هر دو رمز عبور استفاده شود"),
|
||||
("Set permanent password", "یک رمز عبور دائمی تنظیم شود"),
|
||||
("Enable Remote Restart", "فعال کردن قابلیت ریستارت از راه دور"),
|
||||
("Allow remote restart", "مجاز بودن ریستارت از راه دور"),
|
||||
("Restart Remote Device", "ریستارت کردن از راه دور"),
|
||||
("Are you sure you want to restart", "ایا مطمئن هستید میخواهید راه اندازی مجدد انجام بدید؟"),
|
||||
("Restarting Remote Device", "راه اندازی مجدد یک دستگاه راه دور"),
|
||||
("remote_restarting_tip", "دستگاه راه دور دوباره راه اندازی می شود. این پیام را ببندید و پس از مدتی با استفاده از یک رمز عبور دائمی دوباره وصل شوید."),
|
||||
("Restarting Remote Device", "در حال راه اندازی مجدد دستگاه راه دور"),
|
||||
("remote_restarting_tip", "دستگاه راه دور در حال راه اندازی مجدد است. این پیام را ببندید و پس از مدتی با استفاده از یک رمز عبور دائمی دوباره وصل شوید."),
|
||||
("Copied", "کپی شده است"),
|
||||
("Exit Fullscreen", "از حالت تمام صفحه خارج شوید"),
|
||||
("Fullscreen", "تمام صفحه"),
|
||||
@@ -332,30 +339,28 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Scale adaptive", "مقیاس تطبیقی"),
|
||||
("General", "عمومی"),
|
||||
("Security", "امنیت"),
|
||||
("Account", "حساب کاربری"),
|
||||
("Theme", "نمایه"),
|
||||
("Dark Theme", "نمایه تیره"),
|
||||
("Dark", "تیره"),
|
||||
("Light", "روشن"),
|
||||
("Follow System", "سیستم را دنبال کنید"),
|
||||
("Enable hardware codec", "از کدک سخت افزاری استفاده کنید"),
|
||||
("Unlock Security Settings", "تنظیمات امنیتی را باز کنید"),
|
||||
("Enable Audio", "صدا را روشن کنید"),
|
||||
("Unlock Network Settings", "باز کردن قفل تنظیمات شبکه"),
|
||||
("Follow System", "پیروی از سیستم"),
|
||||
("Enable hardware codec", "فعال سازی کدک سخت افزاری"),
|
||||
("Unlock Security Settings", "آنلاک شدن تنظیمات امنیتی"),
|
||||
("Enable Audio", "فعال شدن صدا"),
|
||||
("Unlock Network Settings", "آنلاک شدن تنظیمات شبکه"),
|
||||
("Server", "سرور"),
|
||||
("Direct IP Access", "دسترسی مستقیم به IP"),
|
||||
("Direct IP Access", "IP دسترسی مستقیم "),
|
||||
("Proxy", "پروکسی"),
|
||||
("Port", "پورت"),
|
||||
("Apply", "ثبت"),
|
||||
("Disconnect all devices?", "همه دستگاه ها را غیرفعال کنید؟"),
|
||||
("Disconnect all devices?", "همه دستگاه ها قطع شوند؟"),
|
||||
("Clear", "پاک کردن"),
|
||||
("Audio Input Device", "منبع صدا"),
|
||||
("Deny remote access", "دسترسی از راه دور را رد کنید"),
|
||||
("Use IP Whitelisting", "از لیست سفید IP استفاده کنید"),
|
||||
("Use IP Whitelisting", "های مجاز IP استفاده از"),
|
||||
("Network", "شبکه"),
|
||||
("Enable RDP", "RDP را فعال کنید"),
|
||||
("Pin menubar", "نوار منو ثابت کنید"),
|
||||
("Unpin menubar", "پین نوار منو را بردارید"),
|
||||
("Enable RDP", "RDP فعال شدن"),
|
||||
("Pin menubar", "پین کردن نوار منو"),
|
||||
("Unpin menubar", "آنپین کردن نوار منو"),
|
||||
("Recording", "در حال ضبط"),
|
||||
("Directory", "مسیر"),
|
||||
("Automatically record incoming sessions", "ضبط خودکار جلسات ورودی"),
|
||||
@@ -363,7 +368,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Start session recording", "شروع ضبط جلسه"),
|
||||
("Stop session recording", "توقف ضبط جلسه"),
|
||||
("Enable Recording Session", "فعالسازی ضبط جلسه"),
|
||||
("Allow recording session", "مجوز ضبط جلسه"),
|
||||
("Allow recording session", "مجومجاز بودن ضبط جلسه"),
|
||||
("Enable LAN Discovery", "فعالسازی جستجو در شبکه"),
|
||||
("Deny LAN Discovery", "غیر فعالسازی جستجو در شبکه"),
|
||||
("Write a message", "یک پیام بنویسید"),
|
||||
@@ -371,26 +376,25 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Please wait for confirmation of UAC...", ""),
|
||||
("elevated_foreground_window_tip", ""),
|
||||
("Disconnected", "قطع ارتباط"),
|
||||
("Other", "دیگر"),
|
||||
("Confirm before closing multiple tabs", "بستن چندین برگه را تأیید کنید"),
|
||||
("Other", "سایر"),
|
||||
("Confirm before closing multiple tabs", "تایید بستن دسته ای برگه ها"),
|
||||
("Keyboard Settings", "تنظیمات صفحه کلید"),
|
||||
("Custom", "سفارشی"),
|
||||
("Full Access", "دسترسی کامل"),
|
||||
("Screen Share", "اشتراک گذاری صفحه"),
|
||||
("Wayland requires Ubuntu 21.04 or higher version.", ""),
|
||||
("Wayland requires higher version of linux distro. Please try X11 desktop or change your OS.", ""),
|
||||
("Wayland requires Ubuntu 21.04 or higher version.", "نیازمند اوبونتو نسخه 21.04 یا بالاتر است Wayland"),
|
||||
("Wayland requires higher version of linux distro. Please try X11 desktop or change your OS.", "استفاده کنید و یا سیستم عامل خود را تغییر دهید X11 نیازمند نسخه بالاتری از توزیع لینوکس است. لطفا از دسکتاپ با سیستم"),
|
||||
("JumpLink", ""),
|
||||
("Please Select the screen to be shared(Operate on the peer side).", "لطفاً صفحهای را برای اشتراکگذاری انتخاب کنید (در سمت همتا به همتا کار کنید)."),
|
||||
("Show RustDesk", "RustDesk را نشان دهید"),
|
||||
("Show RustDesk", "RustDesk نمایش"),
|
||||
("This PC", "This PC"),
|
||||
("or", "یا"),
|
||||
("Continue with", "ادامه با"),
|
||||
("Elevate", ""),
|
||||
("Zoom cursor", "نشانگر بزرگنمایی"),
|
||||
("Elevate", "افزایش سطح"),
|
||||
("Zoom cursor", " بزرگنمایی نشانگر ماوس"),
|
||||
("Accept sessions via password", "قبول درخواست با رمز عبور"),
|
||||
("Accept sessions via click", "قبول درخواست با کلیک موس"),
|
||||
("Accept sessions via both", "قبول درخواست با هر دو"),
|
||||
("Please wait for the remote side to accept your session request...", "لطفا صبر کنید تا میزبان درخواست شما را قبول کند..."),
|
||||
("Please wait for the remote side to accept your session request...", "...لطفا صبر کنید تا میزبان درخواست شما را قبول کند"),
|
||||
("One-time Password", "رمز عبور یکبار مصرف"),
|
||||
("Use one-time password", "استفاده از رمز عبور یکبار مصرف"),
|
||||
("One-time password length", "طول رمز عبور یکبار مصرف"),
|
||||
@@ -399,6 +403,15 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("hide_cm_tip", "فقط در صورت پذیرفتن جلسات از طریق رمز عبور و استفاده از رمز عبور دائمی، مخفی شدن مجاز است"),
|
||||
("wayland_experiment_tip", "پشتیبانی Wayland در مرحله آزمایشی است، لطفاً در صورت نیاز به دسترسی بدون مراقبت از X11 استفاده کنید."),
|
||||
("Right click to select tabs", "برای انتخاب تب ها راست کلیک کنید"),
|
||||
("Skipped", ""),
|
||||
("Add to Address Book", "افزودن به دفترچه آدرس"),
|
||||
("Group", ""),
|
||||
("Search", ""),
|
||||
("Closed manually by the web console", ""),
|
||||
("Local keyboard type", ""),
|
||||
("Select local keyboard type", ""),
|
||||
("software_render_tip", ""),
|
||||
("Always use software rendering", ""),
|
||||
("config_input", ""),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
||||
@@ -39,6 +39,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Change ID", "Changer d'ID"),
|
||||
("Website", "Site Web"),
|
||||
("About", "À propos de"),
|
||||
("Slogan_tip", "Fait avec cœur dans ce monde chaotique!"),
|
||||
("Privacy Statement", "Déclaration de confidentialité"),
|
||||
("Mute", "Muet"),
|
||||
("Audio Input", "Entrée audio"),
|
||||
("Enhancements", "Améliorations"),
|
||||
@@ -172,7 +174,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Disconnect", "Déconnecter"),
|
||||
("Allow using keyboard and mouse", "Autoriser l'utilisation du clavier et de la souris"),
|
||||
("Allow using clipboard", "Autoriser l'utilisation du presse-papier"),
|
||||
("Allow hearing sound", "Autoriser l'audition du son"),
|
||||
("Allow hearing sound", "Autoriser l'envoi du son"),
|
||||
("Allow file copy and paste", "Autoriser le copier-coller de fichiers"),
|
||||
("Connected", "Connecté"),
|
||||
("Direct and encrypted connection", "Connexion directe chiffrée"),
|
||||
@@ -181,7 +183,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Relayed and unencrypted connection", "Connexion relais non chiffrée"),
|
||||
("Enter Remote ID", "Entrer l'ID de l'appareil à distance"),
|
||||
("Enter your password", "Entrer votre mot de passe"),
|
||||
("Logging in...", "Se connecter..."),
|
||||
("Logging in...", "En cours de connexion ..."),
|
||||
("Enable RDP session sharing", "Activer le partage de session RDP"),
|
||||
("Auto Login", "Connexion automatique (le verrouillage ne sera effectif qu'après la désactivation du premier paramètre)"),
|
||||
("Enable Direct IP Access", "Autoriser l'accès direct par IP"),
|
||||
@@ -194,7 +196,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Fix it", "Réparer"),
|
||||
("Warning", "Avertissement"),
|
||||
("Login screen using Wayland is not supported", "L'écran de connexion utilisant Wayland n'est pas pris en charge"),
|
||||
("Reboot required", "Redémarrage pour prendre effet"),
|
||||
("Reboot required", "Redémarrage requis"),
|
||||
("Unsupported display server ", "Le serveur d'affichage actuel n'est pas pris en charge"),
|
||||
("x11 expected", "x11 requis"),
|
||||
("Port", "Port"),
|
||||
@@ -208,6 +210,11 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Always connect via relay", "Forcer la connexion relais"),
|
||||
("whitelist_tip", "Seul l'IP dans la liste blanche peut accéder à mon appareil"),
|
||||
("Login", "Connexion"),
|
||||
("Verify", ""),
|
||||
("Remember me", ""),
|
||||
("Trust this device", ""),
|
||||
("Verification code", ""),
|
||||
("verification_tip", ""),
|
||||
("Logout", "Déconnexion"),
|
||||
("Tags", "Étiqueter"),
|
||||
("Search ID", "Rechercher un ID"),
|
||||
@@ -217,11 +224,11 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Add Tag", "Ajouter une balise"),
|
||||
("Unselect all tags", "Désélectionner toutes les balises"),
|
||||
("Network error", "Erreur réseau"),
|
||||
("Username missed", "Nom d'utilisateur manqué"),
|
||||
("Password missed", "Mot de passe manqué"),
|
||||
("Username missed", "Nom d'utilisateur manquant"),
|
||||
("Password missed", "Mot de passe manquant"),
|
||||
("Wrong credentials", "Identifiant ou mot de passe erroné"),
|
||||
("Edit Tag", "Modifier la balise"),
|
||||
("Unremember Password", "Mot de passe oublié"),
|
||||
("Unremember Password", "Oublier le Mot de passe"),
|
||||
("Favorites", "Favoris"),
|
||||
("Add to Favorites", "Ajouter aux Favoris"),
|
||||
("Remove from Favorites", "Retirer des favoris"),
|
||||
@@ -316,7 +323,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Exit Fullscreen", "Quitter le mode plein écran"),
|
||||
("Fullscreen", "Plein écran"),
|
||||
("Mobile Actions", "Actions mobiles"),
|
||||
("Select Monitor", "Sélectionnez Moniteur"),
|
||||
("Select Monitor", "Sélection du Moniteur"),
|
||||
("Control Actions", "Actions de contrôle"),
|
||||
("Display Settings", "Paramètres d'affichage"),
|
||||
("Ratio", "Rapport"),
|
||||
@@ -328,11 +335,10 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Relay Connection", "Connexion relais"),
|
||||
("Secure Connection", "Connexion sécurisée"),
|
||||
("Insecure Connection", "Connexion non sécurisée"),
|
||||
("Scale original", "Échelle d'origine"),
|
||||
("Scale adaptive", "Échelle adaptative"),
|
||||
("Scale original", "Échelle 100%"),
|
||||
("Scale adaptive", "Mise à l'échelle Auto"),
|
||||
("General", "Général"),
|
||||
("Security", "Sécurité"),
|
||||
("Account", "Compte"),
|
||||
("Theme", "Thème"),
|
||||
("Dark Theme", "Thème somble"),
|
||||
("Dark", "Sombre"),
|
||||
@@ -345,7 +351,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Server", "Serveur"),
|
||||
("Direct IP Access", "Accès IP direct"),
|
||||
("Proxy", "Proxy"),
|
||||
("Port", "Port"),
|
||||
("Apply", "Appliquer"),
|
||||
("Disconnect all devices?", "Déconnecter tous les appareils"),
|
||||
("Clear", "Effacer"),
|
||||
@@ -360,8 +365,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Directory", "Répertoire"),
|
||||
("Automatically record incoming sessions", "Enregistrement automatique des session entrantes"),
|
||||
("Change", "Modifier"),
|
||||
("Start session recording", "Commerce l'enregistrement"),
|
||||
("Stop session recording", "Stoper l'enregistrement"),
|
||||
("Start session recording", "Commencer l'enregistrement"),
|
||||
("Stop session recording", "Stopper l'enregistrement"),
|
||||
("Enable Recording Session", "Activer l'enregistrement de session"),
|
||||
("Allow recording session", "Autoriser l'enregistrement de session"),
|
||||
("Enable LAN Discovery", "Activer la découverte réseau local"),
|
||||
@@ -374,7 +379,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Other", "Divers"),
|
||||
("Confirm before closing multiple tabs", "Confirmer avant de fermer plusieurs onglets"),
|
||||
("Keyboard Settings", "Configuration clavier"),
|
||||
("Custom", "Personnalisé"),
|
||||
("Full Access", "Accès total"),
|
||||
("Screen Share", "Partage d'écran"),
|
||||
("Wayland requires Ubuntu 21.04 or higher version.", "Wayland nécessite Ubuntu 21.04 ou une version supérieure."),
|
||||
@@ -397,8 +401,17 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Request access to your device", "Demande d'accès à votre appareil"),
|
||||
("Hide connection management window", "Masquer la fenêtre de gestion des connexions"),
|
||||
("hide_cm_tip", "Autoriser le masquage uniquement si vous acceptez des sessions via un mot de passe et utilisez un mot de passe permanent"),
|
||||
("wayland_experiment_tip", ""),
|
||||
("Right click to select tabs", ""),
|
||||
("Add to Address Book", ""),
|
||||
("wayland_experiment_tip", "Le support Wayland est en phase expérimentale, veuillez utiliser X11 si vous avez besoin d'un accès sans surveillance."),
|
||||
("Right click to select tabs", "Clique droit pour selectionner les onglets"),
|
||||
("Skipped", "Ignoré"),
|
||||
("Add to Address Book", "Ajouter au carnet d'adresses"),
|
||||
("Group", "Groupe"),
|
||||
("Search", "Rechercher"),
|
||||
("Closed manually by the web console", "Fermé manuellement par la console Web"),
|
||||
("Local keyboard type", "Disposition du clavier local"),
|
||||
("Select local keyboard type", "Selectionner la disposition du clavier local"),
|
||||
("software_render_tip", ""),
|
||||
("Always use software rendering", ""),
|
||||
("config_input", ""),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
||||
@@ -39,6 +39,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Change ID", "Αλλαγή αναγνωριστικού ID"),
|
||||
("Website", "Ιστότοπος"),
|
||||
("About", "Πληροφορίες"),
|
||||
("Slogan_tip", ""),
|
||||
("Privacy Statement", ""),
|
||||
("Mute", "Σίγαση"),
|
||||
("Audio Input", "Είσοδος ήχου"),
|
||||
("Enhancements", "Βελτιώσεις"),
|
||||
@@ -121,8 +123,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Show quality monitor", "Εμφάνιση παρακολούθησης ποιότητας σύνδεσης"),
|
||||
("Disable clipboard", "Απενεργοποίηση προχείρου"),
|
||||
("Lock after session end", "Κλείδωμα μετά το τέλος της συνεδρίας"),
|
||||
("Insert", "Εισάγετε"),
|
||||
("Insert Lock", "Εισαγωγή κλειδαριάς"),
|
||||
("Insert", ""),
|
||||
("Insert Lock", "Κλείδωμα απομακρυσμένου σταθμού"),
|
||||
("Refresh", "Ανανέωση"),
|
||||
("ID does not exist", "Το αναγνωριστικό ID δεν υπάρχει"),
|
||||
("Failed to connect to rendezvous server", "Αποτυχία σύνδεσης με διακομιστή"),
|
||||
@@ -179,7 +181,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Relayed and encrypted connection", "Κρυπτογραφημένη σύνδεση με αναμετάδοση"),
|
||||
("Direct and unencrypted connection", "Άμεση και μη κρυπτογραφημένη σύνδεση"),
|
||||
("Relayed and unencrypted connection", "Μη κρυπτογραφημένη σύνδεση με αναμετάδοση"),
|
||||
("Enter Remote ID", "Εισαγωγή απομακρυσμένου αναγνωριστικού ID"),
|
||||
("Enter Remote ID", "Εισαγωγή απομακρυσμένου ID"),
|
||||
("Enter your password", "Εισάγετε τον κωδικό σας"),
|
||||
("Logging in...", "Σύνδεση..."),
|
||||
("Enable RDP session sharing", "Ενεργοποίηση κοινής χρήσης RDP"),
|
||||
@@ -208,6 +210,11 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Always connect via relay", "Σύνδεση πάντα μέσω αναμετάδοσης"),
|
||||
("whitelist_tip", "Μόνο οι IP της λίστας επιτρεπόμενων έχουν πρόσβαση"),
|
||||
("Login", "Σύνδεση"),
|
||||
("Verify", ""),
|
||||
("Remember me", ""),
|
||||
("Trust this device", ""),
|
||||
("Verification code", ""),
|
||||
("verification_tip", ""),
|
||||
("Logout", "Αποσύνδεση"),
|
||||
("Tags", "Ετικέτες"),
|
||||
("Search ID", "Αναζήτηση ID"),
|
||||
@@ -332,7 +339,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Scale adaptive", "Προσαρμοστική κλίμακα"),
|
||||
("General", "Γενικά"),
|
||||
("Security", "Ασφάλεια"),
|
||||
("Account", "Λογαριασμός"),
|
||||
("Theme", "Θέμα"),
|
||||
("Dark Theme", "Σκούρο θέμα"),
|
||||
("Dark", "Σκούρο"),
|
||||
@@ -345,7 +351,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Server", "Διακομιστής"),
|
||||
("Direct IP Access", "Άμεση πρόσβαση IP"),
|
||||
("Proxy", "Διαμεσολαβητής"),
|
||||
("Port", "Θύρα"),
|
||||
("Apply", "Εφαρμογή"),
|
||||
("Disconnect all devices?", "Αποσύνδεση όλων των συσκευών;"),
|
||||
("Clear", "Καθαρισμός"),
|
||||
@@ -374,7 +379,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Other", "Άλλα"),
|
||||
("Confirm before closing multiple tabs", "Επιβεβαίωση πριν κλείσετε πολλές καρτέλες"),
|
||||
("Keyboard Settings", "Ρυθμίσεις πληκτρολογίου"),
|
||||
("Custom", "Προσαρμογή ποιότητας εικόνας"),
|
||||
("Full Access", "Πλήρης πρόσβαση"),
|
||||
("Screen Share", "Κοινή χρήση οθόνης"),
|
||||
("Wayland requires Ubuntu 21.04 or higher version.", "Το Wayland απαιτεί Ubuntu 21.04 ή νεότερη έκδοση."),
|
||||
@@ -399,6 +403,15 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("hide_cm_tip", "Να επιτρέπεται η απόκρυψη, μόνο εάν αποδέχεστε συνδέσεις μέσω κωδικού πρόσβασης και χρησιμοποιείτε μόνιμο κωδικό πρόσβασης"),
|
||||
("wayland_experiment_tip", "Η υποστήριξη Wayland βρίσκεται σε πειραματικό στάδιο, χρησιμοποιήστε το X11 εάν χρειάζεστε πρόσβαση χωρίς επίβλεψη."),
|
||||
("Right click to select tabs", "Κάντε δεξί κλικ για να επιλέξετε καρτέλες"),
|
||||
("Add to Address Book", ""),
|
||||
("Skipped", ""),
|
||||
("Add to Address Book", "Προσθήκη στο Βιβλίο Διευθύνσεων"),
|
||||
("Group", "Ομάδα"),
|
||||
("Search", "Αναζήτηση"),
|
||||
("Closed manually by the web console", ""),
|
||||
("Local keyboard type", ""),
|
||||
("Select local keyboard type", ""),
|
||||
("software_render_tip", ""),
|
||||
("Always use software rendering", ""),
|
||||
("config_input", ""),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
||||
@@ -39,6 +39,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Change ID", "Azonosító megváltoztatása"),
|
||||
("Website", "Weboldal"),
|
||||
("About", "Rólunk"),
|
||||
("Slogan_tip", ""),
|
||||
("Privacy Statement", ""),
|
||||
("Mute", "Némítás"),
|
||||
("Audio Input", "Hangátvitel"),
|
||||
("Enhancements", "Fejlesztések"),
|
||||
@@ -208,6 +210,11 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Always connect via relay", "Mindig közvetítőn keresztüli csatlakozás"),
|
||||
("whitelist_tip", "Csak az engedélyezési listán szereplő címek csatlakozhatnak"),
|
||||
("Login", "Belépés"),
|
||||
("Verify", ""),
|
||||
("Remember me", ""),
|
||||
("Trust this device", ""),
|
||||
("Verification code", ""),
|
||||
("verification_tip", ""),
|
||||
("Logout", "Kilépés"),
|
||||
("Tags", "Tagok"),
|
||||
("Search ID", "Azonosító keresése..."),
|
||||
@@ -332,7 +339,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Scale adaptive", "Adaptív méretarány"),
|
||||
("General", "Általános"),
|
||||
("Security", "Biztonság"),
|
||||
("Account", "Fiók"),
|
||||
("Theme", "Téma"),
|
||||
("Dark Theme", "Sötét téma"),
|
||||
("Dark", "Sötét"),
|
||||
@@ -345,7 +351,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Server", "Szerver"),
|
||||
("Direct IP Access", "Közvetlen IP hozzáférés"),
|
||||
("Proxy", "Proxy"),
|
||||
("Port", "Port"),
|
||||
("Apply", "Alkalmaz"),
|
||||
("Disconnect all devices?", "Leválasztja az összes eszközt?"),
|
||||
("Clear", "Tisztítás"),
|
||||
@@ -374,7 +379,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Other", "Egyéb"),
|
||||
("Confirm before closing multiple tabs", "Biztos, hogy bezárja az összes lapot?"),
|
||||
("Keyboard Settings", "Billentyűzet beállítások"),
|
||||
("Custom", "Egyedi"),
|
||||
("Full Access", "Teljes hozzáférés"),
|
||||
("Screen Share", "Képernyőmegosztás"),
|
||||
("Wayland requires Ubuntu 21.04 or higher version.", "A Waylandhoz Ubuntu 21.04 vagy újabb verzió szükséges."),
|
||||
@@ -399,6 +403,15 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("hide_cm_tip", ""),
|
||||
("wayland_experiment_tip", ""),
|
||||
("Right click to select tabs", ""),
|
||||
("Skipped", ""),
|
||||
("Add to Address Book", ""),
|
||||
("Group", ""),
|
||||
("Search", ""),
|
||||
("Closed manually by the web console", ""),
|
||||
("Local keyboard type", ""),
|
||||
("Select local keyboard type", ""),
|
||||
("software_render_tip", ""),
|
||||
("Always use software rendering", ""),
|
||||
("config_input", ""),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
||||
@@ -15,7 +15,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("not_ready_status", "Belum siap. Silakan periksa koneksi Anda"),
|
||||
("Control Remote Desktop", "Kontrol Remote Desktop"),
|
||||
("Transfer File", "File Transfer"),
|
||||
("Connect", "Menghubung"),
|
||||
("Connect", "Terhubung"),
|
||||
("Recent Sessions", "Sesi Terkini"),
|
||||
("Address Book", "Buku Alamat"),
|
||||
("Confirmation", "Konfirmasi"),
|
||||
@@ -30,15 +30,17 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("IP Whitelisting", "Daftar Putih IP"),
|
||||
("ID/Relay Server", "ID/Relay Server"),
|
||||
("Import Server Config", "Impor Konfigurasi Server"),
|
||||
("Export Server Config", ""),
|
||||
("Export Server Config", "Ekspor Konfigutasi Server"),
|
||||
("Import server configuration successfully", "Impor konfigurasi server berhasil"),
|
||||
("Export server configuration successfully", ""),
|
||||
("Export server configuration successfully", "Ekspor konfigurasi server berhasil"),
|
||||
("Invalid server configuration", "Konfigurasi server tidak valid"),
|
||||
("Clipboard is empty", "Papan klip kosong"),
|
||||
("Stop service", "Hentikan Layanan"),
|
||||
("Change ID", "Ubah ID"),
|
||||
("Website", "Website"),
|
||||
("About", "Tentang"),
|
||||
("Slogan_tip", ""),
|
||||
("Privacy Statement", "Pernyataan Privasi"),
|
||||
("Mute", "Bisukan"),
|
||||
("Audio Input", "Masukkan Audio"),
|
||||
("Enhancements", "Peningkatan"),
|
||||
@@ -58,16 +60,16 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Skip", "Lanjutkan"),
|
||||
("Close", "Tutup"),
|
||||
("Retry", "Ulangi"),
|
||||
("OK", "OK"),
|
||||
("Password Required", "Password dibutukan"),
|
||||
("Please enter your password", "Silahkan masukkan password anda"),
|
||||
("OK", "Oke"),
|
||||
("Password Required", "Kata sandi dibutuhkan"),
|
||||
("Please enter your password", "Silahkan masukkan kata sandi anda"),
|
||||
("Remember password", "Ingat Password"),
|
||||
("Wrong Password", "Password Salah"),
|
||||
("Wrong Password", "Kata sandi Salah"),
|
||||
("Do you want to enter again?", "Apakah anda ingin masuk lagi?"),
|
||||
("Connection Error", "Kesalahan koneksi"),
|
||||
("Error", "Kesalahan"),
|
||||
("Reset by the peer", "Setel ulang oleh rekan"),
|
||||
("Connecting...", "Hubungkan..."),
|
||||
("Connecting...", "Menghubungkan..."),
|
||||
("Connection in progress. Please wait.", "Koneksi sedang berlangsung. Mohon tunggu."),
|
||||
("Please try 1 minute later", "Silahkan coba 1 menit lagi"),
|
||||
("Login Error", "Kesalahan Login"),
|
||||
@@ -108,7 +110,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Block user input", "Blokir masukan pengguna"),
|
||||
("Unblock user input", "Jangan blokir masukan pengguna"),
|
||||
("Adjust Window", "Sesuaikan Jendela"),
|
||||
("Original", "Original"),
|
||||
("Original", "Asli"),
|
||||
("Shrink", "Susutkan"),
|
||||
("Stretch", "Regangkan"),
|
||||
("Scrollbar", "Scroll bar"),
|
||||
@@ -208,6 +210,11 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Always connect via relay", "Selalu terhubung melalui relai"),
|
||||
("whitelist_tip", "Hanya whitelisted IP yang dapat mengakses saya"),
|
||||
("Login", "Masuk"),
|
||||
("Verify", ""),
|
||||
("Remember me", ""),
|
||||
("Trust this device", ""),
|
||||
("Verification code", ""),
|
||||
("verification_tip", ""),
|
||||
("Logout", "Keluar"),
|
||||
("Tags", "Tag"),
|
||||
("Search ID", "Cari ID"),
|
||||
@@ -332,7 +339,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Scale adaptive", "Skala adaptif"),
|
||||
("General", "Umum"),
|
||||
("Security", "Keamanan"),
|
||||
("Account", "Akun"),
|
||||
("Theme", "Tema"),
|
||||
("Dark Theme", "Tema gelap"),
|
||||
("Dark", "Gelap"),
|
||||
@@ -345,7 +351,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Server", "Server"),
|
||||
("Direct IP Access", "Direct IP Access"),
|
||||
("Proxy", "Proxy"),
|
||||
("Port", "Port"),
|
||||
("Apply", "Terapkan"),
|
||||
("Disconnect all devices?", "Putuskan sambungan semua perangkat?"),
|
||||
("Clear", ""),
|
||||
@@ -374,31 +379,39 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Other", "Lainnya"),
|
||||
("Confirm before closing multiple tabs", "Konfirmasi sebelum menutup banyak tab"),
|
||||
("Keyboard Settings", "Pengaturan Papan Ketik"),
|
||||
("Custom", "Kustom"),
|
||||
("Full Access", "Akses penuh"),
|
||||
("Screen Share", "Berbagi Layar"),
|
||||
("Wayland requires Ubuntu 21.04 or higher version.", "Wayland membutuhkan Ubuntu 21.04 atau versi yang lebih tinggi."),
|
||||
("Wayland requires higher version of linux distro. Please try X11 desktop or change your OS.", "Wayland membutuhkan versi distro linux yang lebih tinggi. Silakan coba desktop X11 atau ubah OS Anda."),
|
||||
("JumpLink", "View"),
|
||||
("Please Select the screen to be shared(Operate on the peer side).", "Silakan Pilih layar yang akan dibagikan (Operasi di sisi rekan)."),
|
||||
("Show RustDesk", ""),
|
||||
("This PC", ""),
|
||||
("or", ""),
|
||||
("Continue with", ""),
|
||||
("Show RustDesk", "Tampilkan RustDesk"),
|
||||
("This PC", "PC ini"),
|
||||
("or", "atau"),
|
||||
("Continue with", "Lanjutkan dengan"),
|
||||
("Elevate", ""),
|
||||
("Zoom cursor", ""),
|
||||
("Accept sessions via password", ""),
|
||||
("Accept sessions via click", ""),
|
||||
("Accept sessions via both", ""),
|
||||
("Please wait for the remote side to accept your session request...", ""),
|
||||
("One-time Password", ""),
|
||||
("Use one-time password", ""),
|
||||
("Accept sessions via password", "Izinkan sesi dengan kata sandi"),
|
||||
("Accept sessions via click", "Izinkan sesi dengan klik"),
|
||||
("Accept sessions via both", "Izinkan sesi dengan keduanya"),
|
||||
("Please wait for the remote side to accept your session request...", "Harap tunggu sisi jarak jauh untuk menerima permintaan sesi Anda..."),
|
||||
("One-time Password", "Kata sandi satu kali"),
|
||||
("Use one-time password", "Gunakan kata sandi satu kali"),
|
||||
("One-time password length", ""),
|
||||
("Request access to your device", ""),
|
||||
("Hide connection management window", ""),
|
||||
("hide_cm_tip", ""),
|
||||
("wayland_experiment_tip", ""),
|
||||
("Right click to select tabs", ""),
|
||||
("Skipped", ""),
|
||||
("Add to Address Book", ""),
|
||||
("Group", ""),
|
||||
("Search", "Pencarian"),
|
||||
("Closed manually by the web console", ""),
|
||||
("Local keyboard type", ""),
|
||||
("Select local keyboard type", ""),
|
||||
("software_render_tip", ""),
|
||||
("Always use software rendering", ""),
|
||||
("config_input", ""),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
||||
@@ -39,6 +39,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Change ID", "Cambia ID"),
|
||||
("Website", "Sito web"),
|
||||
("About", "Informazioni"),
|
||||
("Slogan_tip", ""),
|
||||
("Privacy Statement", ""),
|
||||
("Mute", "Silenzia"),
|
||||
("Audio Input", "Input audio"),
|
||||
("Enhancements", "Miglioramenti"),
|
||||
@@ -208,6 +210,11 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Always connect via relay", "Connetti sempre tramite relay"),
|
||||
("whitelist_tip", "Solo gli indirizzi IP autorizzati possono connettersi a questo desktop"),
|
||||
("Login", "Accedi"),
|
||||
("Verify", ""),
|
||||
("Remember me", ""),
|
||||
("Trust this device", ""),
|
||||
("Verification code", ""),
|
||||
("verification_tip", ""),
|
||||
("Logout", "Esci"),
|
||||
("Tags", "Tag"),
|
||||
("Search ID", "Cerca ID"),
|
||||
@@ -332,7 +339,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Scale adaptive", "Scala adattiva"),
|
||||
("General", "Generale"),
|
||||
("Security", "Sicurezza"),
|
||||
("Account", "Account"),
|
||||
("Theme", "Tema"),
|
||||
("Dark Theme", "Tema Scuro"),
|
||||
("Dark", "Scuro"),
|
||||
@@ -345,7 +351,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Server", ""),
|
||||
("Direct IP Access", "Accesso IP diretto"),
|
||||
("Proxy", ""),
|
||||
("Port", "Porta"),
|
||||
("Apply", "Applica"),
|
||||
("Disconnect all devices?", "Disconnettere tutti i dispositivi?"),
|
||||
("Clear", "Ripulisci"),
|
||||
@@ -374,7 +379,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Other", "Altro"),
|
||||
("Confirm before closing multiple tabs", "Conferma prima di chiudere più schede"),
|
||||
("Keyboard Settings", "Impostazioni tastiera"),
|
||||
("Custom", "Personalizzato"),
|
||||
("Full Access", "Accesso completo"),
|
||||
("Screen Share", "Condivisione dello schermo"),
|
||||
("Wayland requires Ubuntu 21.04 or higher version.", "Wayland richiede Ubuntu 21.04 o successiva."),
|
||||
@@ -399,6 +403,15 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("hide_cm_tip", "Permetti di nascondere solo se si accettano sessioni con password permanente"),
|
||||
("wayland_experiment_tip", "Il supporto Wayland è in fase sperimentale, utilizza X11 se necessiti di un accesso stabile."),
|
||||
("Right click to select tabs", "Clic con il tasto destro per selezionare le schede"),
|
||||
("Skipped", "Saltato"),
|
||||
("Add to Address Book", "Aggiungi alla rubrica"),
|
||||
("Group", "Gruppo"),
|
||||
("Search", "Cerca"),
|
||||
("Closed manually by the web console", "Chiudi manualmente dalla console Web"),
|
||||
("Local keyboard type", "Tipo di tastiera locale"),
|
||||
("Select local keyboard type", "Seleziona il tipo di tastiera locale"),
|
||||
("software_render_tip", ""),
|
||||
("Always use software rendering", ""),
|
||||
("config_input", ""),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
||||
@@ -39,6 +39,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Change ID", "IDを変更"),
|
||||
("Website", "公式サイト"),
|
||||
("About", "情報"),
|
||||
("Slogan_tip", ""),
|
||||
("Privacy Statement", ""),
|
||||
("Mute", "ミュート"),
|
||||
("Audio Input", "音声入力デバイス"),
|
||||
("Enhancements", "追加機能"),
|
||||
@@ -208,6 +210,11 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Always connect via relay", "常に中継サーバー経由で接続"),
|
||||
("whitelist_tip", "ホワイトリストに登録されたIPからのみ接続を許可します"),
|
||||
("Login", "ログイン"),
|
||||
("Verify", ""),
|
||||
("Remember me", ""),
|
||||
("Trust this device", ""),
|
||||
("Verification code", ""),
|
||||
("verification_tip", ""),
|
||||
("Logout", "ログアウト"),
|
||||
("Tags", "タグ"),
|
||||
("Search ID", "IDを検索"),
|
||||
@@ -332,7 +339,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Scale adaptive", "フィットウィンドウ"),
|
||||
("General", ""),
|
||||
("Security", ""),
|
||||
("Account", ""),
|
||||
("Theme", ""),
|
||||
("Dark Theme", ""),
|
||||
("Dark", ""),
|
||||
@@ -345,7 +351,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Server", ""),
|
||||
("Direct IP Access", ""),
|
||||
("Proxy", ""),
|
||||
("Port", ""),
|
||||
("Apply", ""),
|
||||
("Disconnect all devices?", ""),
|
||||
("Clear", ""),
|
||||
@@ -374,7 +379,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Other", "他の"),
|
||||
("Confirm before closing multiple tabs", "同時に複数のタブを閉じる前に確認する"),
|
||||
("Keyboard Settings", ""),
|
||||
("Custom", ""),
|
||||
("Full Access", ""),
|
||||
("Screen Share", ""),
|
||||
("Wayland requires Ubuntu 21.04 or higher version.", "Wayland には、Ubuntu 21.04 以降のバージョンが必要です。"),
|
||||
@@ -399,6 +403,15 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("hide_cm_tip", ""),
|
||||
("wayland_experiment_tip", ""),
|
||||
("Right click to select tabs", ""),
|
||||
("Skipped", ""),
|
||||
("Add to Address Book", ""),
|
||||
("Group", ""),
|
||||
("Search", ""),
|
||||
("Closed manually by the web console", ""),
|
||||
("Local keyboard type", ""),
|
||||
("Select local keyboard type", ""),
|
||||
("software_render_tip", ""),
|
||||
("Always use software rendering", ""),
|
||||
("config_input", ""),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
||||
@@ -39,6 +39,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Change ID", "ID 변경"),
|
||||
("Website", "웹사이트"),
|
||||
("About", "정보"),
|
||||
("Slogan_tip", ""),
|
||||
("Privacy Statement", ""),
|
||||
("Mute", "음소거"),
|
||||
("Audio Input", "오디오 입력"),
|
||||
("Enhancements", ""),
|
||||
@@ -208,6 +210,11 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Always connect via relay", "항상 relay를 통해 접속하기"),
|
||||
("whitelist_tip", "화이트리스트에 있는 IP만 현 데스크탑에 접속 가능합니다"),
|
||||
("Login", "로그인"),
|
||||
("Verify", ""),
|
||||
("Remember me", ""),
|
||||
("Trust this device", ""),
|
||||
("Verification code", ""),
|
||||
("verification_tip", ""),
|
||||
("Logout", "로그아웃"),
|
||||
("Tags", "태그"),
|
||||
("Search ID", "ID 검색"),
|
||||
@@ -332,7 +339,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Scale adaptive", "맞는 창"),
|
||||
("General", ""),
|
||||
("Security", ""),
|
||||
("Account", ""),
|
||||
("Theme", ""),
|
||||
("Dark Theme", ""),
|
||||
("Dark", ""),
|
||||
@@ -345,7 +351,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Server", ""),
|
||||
("Direct IP Access", ""),
|
||||
("Proxy", ""),
|
||||
("Port", ""),
|
||||
("Apply", ""),
|
||||
("Disconnect all devices?", ""),
|
||||
("Clear", ""),
|
||||
@@ -374,7 +379,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Other", ""),
|
||||
("Confirm before closing multiple tabs", ""),
|
||||
("Keyboard Settings", ""),
|
||||
("Custom", ""),
|
||||
("Full Access", ""),
|
||||
("Screen Share", ""),
|
||||
("Wayland requires Ubuntu 21.04 or higher version.", "Wayland는 Ubuntu 21.04 이상 버전이 필요합니다."),
|
||||
@@ -399,6 +403,15 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("hide_cm_tip", ""),
|
||||
("wayland_experiment_tip", ""),
|
||||
("Right click to select tabs", ""),
|
||||
("Skipped", ""),
|
||||
("Add to Address Book", ""),
|
||||
("Group", ""),
|
||||
("Search", ""),
|
||||
("Closed manually by the web console", ""),
|
||||
("Local keyboard type", ""),
|
||||
("Select local keyboard type", ""),
|
||||
("software_render_tip", ""),
|
||||
("Always use software rendering", ""),
|
||||
("config_input", ""),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
||||
@@ -39,6 +39,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Change ID", "ID ауыстыру"),
|
||||
("Website", "Web-сайт"),
|
||||
("About", "Туралы"),
|
||||
("Slogan_tip", ""),
|
||||
("Privacy Statement", ""),
|
||||
("Mute", "Дыбыссыздандыру"),
|
||||
("Audio Input", "Аудио Еңгізу"),
|
||||
("Enhancements", "Жақсартулар"),
|
||||
@@ -208,6 +210,11 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Always connect via relay", "Әрқашан да релай сербері арқылы қосылу"),
|
||||
("whitelist_tip", "Маған тек ақ-тізімделген IP қол жеткізе алады"),
|
||||
("Login", "Кіру"),
|
||||
("Verify", ""),
|
||||
("Remember me", ""),
|
||||
("Trust this device", ""),
|
||||
("Verification code", ""),
|
||||
("verification_tip", ""),
|
||||
("Logout", "Шығу"),
|
||||
("Tags", "Тақтар"),
|
||||
("Search ID", "ID Іздеу"),
|
||||
@@ -332,7 +339,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Scale adaptive", "Scale adaptive"),
|
||||
("General", ""),
|
||||
("Security", ""),
|
||||
("Account", "Есепкі"),
|
||||
("Theme", ""),
|
||||
("Dark Theme", ""),
|
||||
("Dark", ""),
|
||||
@@ -345,7 +351,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Server", ""),
|
||||
("Direct IP Access", ""),
|
||||
("Proxy", ""),
|
||||
("Port", "Порт"),
|
||||
("Apply", ""),
|
||||
("Disconnect all devices?", ""),
|
||||
("Clear", ""),
|
||||
@@ -374,7 +379,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Other", ""),
|
||||
("Confirm before closing multiple tabs", ""),
|
||||
("Keyboard Settings", ""),
|
||||
("Custom", ""),
|
||||
("Full Access", ""),
|
||||
("Screen Share", ""),
|
||||
("Wayland requires Ubuntu 21.04 or higher version.", "Wayland Ubuntu 21.04 немесе одан жоғары нұсқасын қажет етеді."),
|
||||
@@ -399,6 +403,15 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("hide_cm_tip", ""),
|
||||
("wayland_experiment_tip", ""),
|
||||
("Right click to select tabs", ""),
|
||||
("Skipped", ""),
|
||||
("Add to Address Book", ""),
|
||||
("Group", ""),
|
||||
("Search", ""),
|
||||
("Closed manually by the web console", ""),
|
||||
("Local keyboard type", ""),
|
||||
("Select local keyboard type", ""),
|
||||
("software_render_tip", ""),
|
||||
("Always use software rendering", ""),
|
||||
("config_input", ""),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
[
|
||||
("Status", "Status"),
|
||||
("Your Desktop", "Twój pulpit"),
|
||||
("desk_tip", "Aby połaczyć się z tym urządzeniem należy użyć tego ID i hasła."),
|
||||
("desk_tip", "W celu zestawienia połączenia z tym urządzeniem należy poniższego ID i hasła."),
|
||||
("Password", "Hasło"),
|
||||
("Ready", "Gotowe"),
|
||||
("Established", "Nawiązano"),
|
||||
@@ -13,7 +13,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Service is running", "Usługa uruchomiona"),
|
||||
("Service is not running", "Usługa nie jest uruchomiona"),
|
||||
("not_ready_status", "Brak gotowości"),
|
||||
("Control Remote Desktop", "Kontroluj zdalny pulpit"),
|
||||
("Control Remote Desktop", "Połącz się z"),
|
||||
("Transfer File", "Transfer plików"),
|
||||
("Connect", "Połącz"),
|
||||
("Recent Sessions", "Ostatnie sesje"),
|
||||
@@ -39,6 +39,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Change ID", "Zmień ID"),
|
||||
("Website", "Strona internetowa"),
|
||||
("About", "O"),
|
||||
("Slogan_tip", ""),
|
||||
("Privacy Statement", ""),
|
||||
("Mute", "Wycisz"),
|
||||
("Audio Input", "Wejście audio"),
|
||||
("Enhancements", "Ulepszenia"),
|
||||
@@ -118,7 +120,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Optimize reaction time", "Zoptymalizuj czas reakcji"),
|
||||
("Custom", "Własne"),
|
||||
("Show remote cursor", "Pokazuj zdalny kursor"),
|
||||
("Show quality monitor", "Pokazuj jakość monitora"),
|
||||
("Show quality monitor", "Parametry połączenia"),
|
||||
("Disable clipboard", "Wyłącz schowek"),
|
||||
("Lock after session end", "Zablokuj po zakończeniu sesji"),
|
||||
("Insert", "Wyślij"),
|
||||
@@ -137,9 +139,9 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Set Password", "Ustaw hasło"),
|
||||
("OS Password", "Hasło systemu operacyjnego"),
|
||||
("install_tip", "RustDesk może nie działać poprawnie na maszynie zdalnej z przyczyn związanych z UAC. W celu uniknięcią problemów z UAC, kliknij poniższy przycisk by zainstalować RustDesk w swoim systemie."),
|
||||
("Click to upgrade", "Kliknij, aby zaktualizować (upgrade)"),
|
||||
("Click to download", "Kliknij, aby pobrać"),
|
||||
("Click to update", "Kliknij, aby zaktualizować (update)"),
|
||||
("Click to upgrade", "Zaktualizuj"),
|
||||
("Click to download", "Pobierz"),
|
||||
("Click to update", "Uaktualinij"),
|
||||
("Configure", "Konfiguruj"),
|
||||
("config_acc", "Konfiguracja konta"),
|
||||
("config_screen", "Konfiguracja ekranu"),
|
||||
@@ -208,6 +210,11 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Always connect via relay", "Zawsze łącz pośrednio"),
|
||||
("whitelist_tip", "Zezwlaj na łączenie z tym komputerem tylko z adresów IP znajdujących się na białej liście"),
|
||||
("Login", "Zaloguj"),
|
||||
("Verify", ""),
|
||||
("Remember me", ""),
|
||||
("Trust this device", ""),
|
||||
("Verification code", ""),
|
||||
("verification_tip", ""),
|
||||
("Logout", "Wyloguj"),
|
||||
("Tags", "Tagi"),
|
||||
("Search ID", "Szukaj ID"),
|
||||
@@ -314,25 +321,24 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("remote_restarting_tip", "Trwa ponownie uruchomienie zdalnego urządzenia, zamknij ten komunikat i ponownie nawiąż za chwilę połączenie używając hasła permanentnego"),
|
||||
("Copied", "Skopiowano"),
|
||||
("Exit Fullscreen", "Wyłączyć tryb pełnoekranowy"),
|
||||
("Fullscreen", "Pełny ekran"),
|
||||
("Mobile Actions", "Działania mobilne"),
|
||||
("Select Monitor", "Wybierz Monitor"),
|
||||
("Control Actions", "Działania kontrolne"),
|
||||
("Fullscreen", "Tryb pełnoekranowy"),
|
||||
("Mobile Actions", "Dostępne mobilne polecenia"),
|
||||
("Select Monitor", "Wybierz ekran"),
|
||||
("Control Actions", "Dostępne polecenia"),
|
||||
("Display Settings", "Ustawienia wyświetlania"),
|
||||
("Ratio", "Proporcje"),
|
||||
("Image Quality", "Jakość obrazu"),
|
||||
("Scroll Style", "Styl przewijania"),
|
||||
("Show Menubar", "Pokaż pasek menu"),
|
||||
("Hide Menubar", "Ukryj pasek menu"),
|
||||
("Direct Connection", "Połącznie Bezpośrednie"),
|
||||
("Relay Connection", "Połączenie Pośrednie"),
|
||||
("Secure Connection", "Połączenie Bezpieczne"),
|
||||
("Insecure Connection", "Połączenie Niebezpieczne"),
|
||||
("Direct Connection", "Połącznie bezpośrednie"),
|
||||
("Relay Connection", "Połączenie przez bramkę"),
|
||||
("Secure Connection", "Połączenie szyfrowane"),
|
||||
("Insecure Connection", "Połączenie nieszyfrowane"),
|
||||
("Scale original", "Skaluj oryginalnie"),
|
||||
("Scale adaptive", "Skaluj adaptacyjnie"),
|
||||
("General", "Ogólne"),
|
||||
("Security", "Zabezpieczenia"),
|
||||
("Account", "Konto"),
|
||||
("Theme", "Motyw"),
|
||||
("Dark Theme", "Ciemny motyw"),
|
||||
("Dark", "Ciemny"),
|
||||
@@ -345,7 +351,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Server", "Serwer"),
|
||||
("Direct IP Access", "Bezpośredni Adres IP"),
|
||||
("Proxy", "Proxy"),
|
||||
("Port", "Port"),
|
||||
("Apply", "Zastosuj"),
|
||||
("Disconnect all devices?", "Czy rozłączyć wszystkie urządzenia?"),
|
||||
("Clear", "Wyczyść"),
|
||||
@@ -364,17 +369,16 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Stop session recording", "Zatrzymaj nagrywanie sesji"),
|
||||
("Enable Recording Session", "Włącz Nagrywanie Sesji"),
|
||||
("Allow recording session", "Zezwól na nagrywanie sesji"),
|
||||
("Enable LAN Discovery", "Włącz Wykrywanie LAN"),
|
||||
("Deny LAN Discovery", "Zablokuj Wykrywanie LAN"),
|
||||
("Enable LAN Discovery", "Włącz wykrywanie urządzenia w sieci LAN"),
|
||||
("Deny LAN Discovery", "Zablokuj wykrywanie urządzenia w sieci LAN"),
|
||||
("Write a message", "Napisz wiadomość"),
|
||||
("Prompt", "Monit"),
|
||||
("Please wait for confirmation of UAC...", ""),
|
||||
("Please wait for confirmation of UAC...", "Oczekuje potwierdzenia ustawień UAC"),
|
||||
("elevated_foreground_window_tip", ""),
|
||||
("Disconnected", "Rozłączone"),
|
||||
("Other", "Inne"),
|
||||
("Confirm before closing multiple tabs", "Potwierdź przed zamknięciem wielu kart"),
|
||||
("Keyboard Settings", "Ustawienia klawiatury"),
|
||||
("Custom", "Własne"),
|
||||
("Full Access", "Pełny dostęp"),
|
||||
("Screen Share", "Udostępnianie ekranu"),
|
||||
("Wayland requires Ubuntu 21.04 or higher version.", "Wayland wymaga Ubuntu 21.04 lub nowszego."),
|
||||
@@ -385,20 +389,29 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("This PC", "Ten komputer"),
|
||||
("or", "albo"),
|
||||
("Continue with", "Kontynuuj z"),
|
||||
("Elevate", "Podwyższ"),
|
||||
("Elevate", "Uzyskaj uprawnienia"),
|
||||
("Zoom cursor", "Zoom kursora"),
|
||||
("Accept sessions via password", "Akceptuj sesje używając hasła"),
|
||||
("Accept sessions via click", "Akceptuj sesję klikając"),
|
||||
("Accept sessions via both", "Akceptuj sesjęna dwa sposoby"),
|
||||
("Please wait for the remote side to accept your session request...", "Proszę czekać aż zdalny host zaakceptuje Twoją prośbę..."),
|
||||
("Accept sessions via password", "Uwierzytelnij sesję używając hasła"),
|
||||
("Accept sessions via click", "Uwierzytelnij sesję poprzez kliknięcie"),
|
||||
("Accept sessions via both", "Uwierzytelnij sesję za pomocą obu sposobów"),
|
||||
("Please wait for the remote side to accept your session request...", "Oczekiwanie, na zatwierdzenie sesji przez host zdalny..."),
|
||||
("One-time Password", "Hasło jednorazowe"),
|
||||
("Use one-time password", "Użyj hasła jednorazowego"),
|
||||
("One-time password length", "Długość hasła jednorazowego"),
|
||||
("Request access to your device", "Żądanie dostępu do Twojego urządzenia"),
|
||||
("Hide connection management window", ""),
|
||||
("Hide connection management window", "Ukryj okno zarządzania połączeniem"),
|
||||
("hide_cm_tip", ""),
|
||||
("wayland_experiment_tip", ""),
|
||||
("Right click to select tabs", ""),
|
||||
("Add to Address Book", ""),
|
||||
("Skipped", ""),
|
||||
("Add to Address Book", "Dodaj do Książki Adresowej"),
|
||||
("Group", "Grypy"),
|
||||
("Search", "Szukaj"),
|
||||
("Closed manually by the web console", ""),
|
||||
("Local keyboard type", ""),
|
||||
("Select local keyboard type", ""),
|
||||
("software_render_tip", ""),
|
||||
("Always use software rendering", ""),
|
||||
("config_input", ""),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
||||
@@ -39,6 +39,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Change ID", "Alterar ID"),
|
||||
("Website", "Website"),
|
||||
("About", "Sobre"),
|
||||
("Slogan_tip", ""),
|
||||
("Privacy Statement", ""),
|
||||
("Mute", "Silenciar"),
|
||||
("Audio Input", "Entrada de Áudio"),
|
||||
("Enhancements", "Melhorias"),
|
||||
@@ -208,6 +210,11 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Always connect via relay", "Sempre conectar via relay"),
|
||||
("whitelist_tip", "Somente IPs na whitelist podem me acessar"),
|
||||
("Login", "Login"),
|
||||
("Verify", ""),
|
||||
("Remember me", ""),
|
||||
("Trust this device", ""),
|
||||
("Verification code", ""),
|
||||
("verification_tip", ""),
|
||||
("Logout", "Sair"),
|
||||
("Tags", "Tags"),
|
||||
("Search ID", "Procurar ID"),
|
||||
@@ -332,7 +339,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Scale adaptive", "Escala adaptável"),
|
||||
("General", ""),
|
||||
("Security", ""),
|
||||
("Account", ""),
|
||||
("Theme", ""),
|
||||
("Dark Theme", ""),
|
||||
("Dark", ""),
|
||||
@@ -345,7 +351,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Server", ""),
|
||||
("Direct IP Access", ""),
|
||||
("Proxy", ""),
|
||||
("Port", ""),
|
||||
("Apply", ""),
|
||||
("Disconnect all devices?", ""),
|
||||
("Clear", ""),
|
||||
@@ -374,7 +379,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Other", "Outro"),
|
||||
("Confirm before closing multiple tabs", "Confirme antes de fechar vários separadores"),
|
||||
("Keyboard Settings", "Configurações do teclado"),
|
||||
("Custom", ""),
|
||||
("Full Access", "Controlo total"),
|
||||
("Screen Share", ""),
|
||||
("Wayland requires Ubuntu 21.04 or higher version.", "Wayland requer Ubuntu 21.04 ou versão superior."),
|
||||
@@ -399,6 +403,15 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("hide_cm_tip", ""),
|
||||
("wayland_experiment_tip", ""),
|
||||
("Right click to select tabs", ""),
|
||||
("Skipped", ""),
|
||||
("Add to Address Book", ""),
|
||||
("Group", ""),
|
||||
("Search", ""),
|
||||
("Closed manually by the web console", ""),
|
||||
("Local keyboard type", ""),
|
||||
("Select local keyboard type", ""),
|
||||
("software_render_tip", ""),
|
||||
("Always use software rendering", ""),
|
||||
("config_input", ""),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
||||
@@ -39,6 +39,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Change ID", "Alterar ID"),
|
||||
("Website", "Website"),
|
||||
("About", "Sobre"),
|
||||
("Slogan_tip", ""),
|
||||
("Privacy Statement", ""),
|
||||
("Mute", "Desativar som"),
|
||||
("Audio Input", "Entrada de Áudio"),
|
||||
("Enhancements", "Melhorias"),
|
||||
@@ -208,6 +210,11 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Always connect via relay", "Sempre conectar via relay"),
|
||||
("whitelist_tip", "Somente IPs confiáveis podem me acessar"),
|
||||
("Login", "Login"),
|
||||
("Verify", ""),
|
||||
("Remember me", ""),
|
||||
("Trust this device", ""),
|
||||
("Verification code", ""),
|
||||
("verification_tip", ""),
|
||||
("Logout", "Sair"),
|
||||
("Tags", "Tags"),
|
||||
("Search ID", "Pesquisar ID"),
|
||||
@@ -332,7 +339,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Scale adaptive", "Escala adaptada"),
|
||||
("General", "Geral"),
|
||||
("Security", "Segurança"),
|
||||
("Account", "Conta"),
|
||||
("Theme", "Tema"),
|
||||
("Dark Theme", "Tema escuro"),
|
||||
("Dark", "Escuro"),
|
||||
@@ -345,7 +351,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Server", "Servidor"),
|
||||
("Direct IP Access", "Acesso direto por IP"),
|
||||
("Proxy", "Proxy"),
|
||||
("Port", "Porta"),
|
||||
("Apply", "Aplicar"),
|
||||
("Disconnect all devices?", "Desconectar todos os dispositivos?"),
|
||||
("Clear", "Limpar"),
|
||||
@@ -374,7 +379,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Other", "Outro"),
|
||||
("Confirm before closing multiple tabs", "Confirmar antes de fechar múltiplas abas"),
|
||||
("Keyboard Settings", "Configurações de teclado"),
|
||||
("Custom", "Personalizado"),
|
||||
("Full Access", "Acesso completo"),
|
||||
("Screen Share", "Compartilhamento de tela"),
|
||||
("Wayland requires Ubuntu 21.04 or higher version.", "Wayland requer Ubuntu 21.04 ou versão superior."),
|
||||
@@ -399,6 +403,15 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("hide_cm_tip", ""),
|
||||
("wayland_experiment_tip", ""),
|
||||
("Right click to select tabs", ""),
|
||||
("Skipped", ""),
|
||||
("Add to Address Book", ""),
|
||||
("Group", ""),
|
||||
("Search", ""),
|
||||
("Closed manually by the web console", ""),
|
||||
("Local keyboard type", ""),
|
||||
("Select local keyboard type", ""),
|
||||
("software_render_tip", ""),
|
||||
("Always use software rendering", ""),
|
||||
("config_input", ""),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
||||
@@ -39,6 +39,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Change ID", "Изменить ID"),
|
||||
("Website", "Сайт"),
|
||||
("About", "О программе"),
|
||||
("Slogan_tip", "Сделано с душой в этом безумном мире!"),
|
||||
("Privacy Statement", "Заявление о конфиденциальности"),
|
||||
("Mute", "Отключить звук"),
|
||||
("Audio Input", "Аудиовход"),
|
||||
("Enhancements", "Улучшения"),
|
||||
@@ -204,10 +206,15 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Closed manually by the peer", "Закрыто удалённым узлом вручную"),
|
||||
("Enable remote configuration modification", "Разрешить удалённое изменение конфигурации"),
|
||||
("Run without install", "Запустить без установки"),
|
||||
("Always connected via relay", "Всегда подключён через ретрансляционный сервер"),
|
||||
("Always connected via relay", "Всегда подключается через ретрансляционный сервер"),
|
||||
("Always connect via relay", "Всегда подключаться через ретрансляционный сервер"),
|
||||
("whitelist_tip", "Только IP-адреса из белого списка могут получить доступ ко мне"),
|
||||
("Login", "Войти"),
|
||||
("Verify", ""),
|
||||
("Remember me", ""),
|
||||
("Trust this device", ""),
|
||||
("Verification code", ""),
|
||||
("verification_tip", ""),
|
||||
("Logout", "Выйти"),
|
||||
("Tags", "Метки"),
|
||||
("Search ID", "Поиск по ID"),
|
||||
@@ -332,7 +339,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Scale adaptive", "Адаптивный масштаб"),
|
||||
("General", "Общие"),
|
||||
("Security", "Безопасность"),
|
||||
("Account", "Аккаунт"),
|
||||
("Theme", "Тема"),
|
||||
("Dark Theme", "Тёмная тема"),
|
||||
("Dark", "Тёмная"),
|
||||
@@ -345,7 +351,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Server", "Сервер"),
|
||||
("Direct IP Access", "Прямой IP-доступ"),
|
||||
("Proxy", "Прокси"),
|
||||
("Port", "Порт"),
|
||||
("Apply", "Применить"),
|
||||
("Disconnect all devices?", "Отключить все устройства?"),
|
||||
("Clear", "Очистить"),
|
||||
@@ -374,7 +379,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Other", "Другое"),
|
||||
("Confirm before closing multiple tabs", "Подтверждать закрытие несколько вкладок"),
|
||||
("Keyboard Settings", "Настройки клавиатуры"),
|
||||
("Custom", "Своё"),
|
||||
("Full Access", "Полный доступ"),
|
||||
("Screen Share", "Поделиться экраном"),
|
||||
("Wayland requires Ubuntu 21.04 or higher version.", "Wayland требует Ubuntu 21.04 или более позднюю версию."),
|
||||
@@ -399,6 +403,15 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("hide_cm_tip", "Разрешать скрытие случае, если принимаются сеансы по паролю или используется постоянный пароль"),
|
||||
("wayland_experiment_tip", "Поддержка Wayland находится на экспериментальной стадии, используйте X11, если вам требуется автоматический доступ."),
|
||||
("Right click to select tabs", "Выбор вкладок щелчком правой кнопки мыши"),
|
||||
("Skipped", "Пропущено"),
|
||||
("Add to Address Book", "Добавить в адресную книгу"),
|
||||
("Group", "Группа"),
|
||||
("Search", "Поиск"),
|
||||
("Closed manually by the web console", "Закрыто вручную через веб-консоль"),
|
||||
("Local keyboard type", "Тип локальной клавиатуры"),
|
||||
("Select local keyboard type", "Выберите тип локальной клавиатуры"),
|
||||
("software_render_tip", "Если у вас видеокарта Nvidia и удалённое окно закрывается сразу после подключения, может помочь установка драйвера Nouveau и выбор использования программной визуализации. Потребуется перезапуск."),
|
||||
("Always use software rendering", "Использовать программную визуализацию"),
|
||||
("config_input", "Чтобы управлять удалённым рабочим столом с помощью клавиатуры, необходимо предоставить RustDesk разрешения \"Мониторинг ввода\"."),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
||||
@@ -39,6 +39,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Change ID", "Zmeniť ID"),
|
||||
("Website", "Webová stránka"),
|
||||
("About", "O RustDesk"),
|
||||
("Slogan_tip", ""),
|
||||
("Privacy Statement", ""),
|
||||
("Mute", "Stíšiť"),
|
||||
("Audio Input", "Zvukový vstup"),
|
||||
("Enhancements", ""),
|
||||
@@ -208,6 +210,11 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Always connect via relay", "Vždy pripájať cez prepájací server"),
|
||||
("whitelist_tip", "Len vymenované IP adresy majú oprávnenie sa pripojiť k vzdialenej správe"),
|
||||
("Login", "Prihlásenie"),
|
||||
("Verify", ""),
|
||||
("Remember me", ""),
|
||||
("Trust this device", ""),
|
||||
("Verification code", ""),
|
||||
("verification_tip", ""),
|
||||
("Logout", "Odhlásenie"),
|
||||
("Tags", "Štítky"),
|
||||
("Search ID", "Hľadať ID"),
|
||||
@@ -332,7 +339,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Scale adaptive", "Prispôsobivá mierka"),
|
||||
("General", ""),
|
||||
("Security", ""),
|
||||
("Account", ""),
|
||||
("Theme", ""),
|
||||
("Dark Theme", ""),
|
||||
("Dark", ""),
|
||||
@@ -345,7 +351,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Server", ""),
|
||||
("Direct IP Access", ""),
|
||||
("Proxy", ""),
|
||||
("Port", ""),
|
||||
("Apply", ""),
|
||||
("Disconnect all devices?", ""),
|
||||
("Clear", ""),
|
||||
@@ -374,7 +379,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Other", ""),
|
||||
("Confirm before closing multiple tabs", ""),
|
||||
("Keyboard Settings", ""),
|
||||
("Custom", ""),
|
||||
("Full Access", ""),
|
||||
("Screen Share", ""),
|
||||
("Wayland requires Ubuntu 21.04 or higher version.", "Wayland vyžaduje Ubuntu 21.04 alebo vyššiu verziu."),
|
||||
@@ -399,6 +403,15 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("hide_cm_tip", ""),
|
||||
("wayland_experiment_tip", ""),
|
||||
("Right click to select tabs", ""),
|
||||
("Skipped", ""),
|
||||
("Add to Address Book", ""),
|
||||
("Group", ""),
|
||||
("Search", ""),
|
||||
("Closed manually by the web console", ""),
|
||||
("Local keyboard type", ""),
|
||||
("Select local keyboard type", ""),
|
||||
("software_render_tip", ""),
|
||||
("Always use software rendering", ""),
|
||||
("config_input", ""),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
||||
417
src/lang/sl.rs
Executable file
417
src/lang/sl.rs
Executable file
@@ -0,0 +1,417 @@
|
||||
lazy_static::lazy_static! {
|
||||
pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
[
|
||||
("Status", "Stanje"),
|
||||
("Your Desktop", "Vaše namizje"),
|
||||
("desk_tip", "Do vašega namizja lahko dostopate s spodnjim IDjem in geslom"),
|
||||
("Password", "Geslo"),
|
||||
("Ready", "Pripravljen"),
|
||||
("Established", "Povezava vzpostavljena"),
|
||||
("connecting_status", "Vzpostavljanje povezave z omrežjem RustDesk..."),
|
||||
("Enable Service", "Omogoči storitev"),
|
||||
("Start Service", "Zaženi storitev"),
|
||||
("Service is running", "Storitev se izvaja"),
|
||||
("Service is not running", "Storitev se ne izvaja"),
|
||||
("not_ready_status", "Ni pripravljeno, preverite vašo mrežno povezavo"),
|
||||
("Control Remote Desktop", "Nadzoruj oddaljeno namizje"),
|
||||
("Transfer File", "Prenos datotek"),
|
||||
("Connect", "Poveži"),
|
||||
("Recent Sessions", "Nedavne seje"),
|
||||
("Address Book", "Adresar"),
|
||||
("Confirmation", "Potrditev"),
|
||||
("TCP Tunneling", "TCP tuneliranje"),
|
||||
("Remove", "Odstrani"),
|
||||
("Refresh random password", "Osveži naključno geslo"),
|
||||
("Set your own password", "Nastavi lastno geslo"),
|
||||
("Enable Keyboard/Mouse", "Omogoči tipkovnico in miško"),
|
||||
("Enable Clipboard", "Omogoči odložišče"),
|
||||
("Enable File Transfer", "Omogoči prenos datotek"),
|
||||
("Enable TCP Tunneling", "Omogoči TCP tuneliranje"),
|
||||
("IP Whitelisting", "Omogoči seznam dovoljenih IPjev"),
|
||||
("ID/Relay Server", "Strežnik za ID/posredovanje"),
|
||||
("Import Server Config", "Uvozi nastavitve strežnika"),
|
||||
("Export Server Config", "Izvozi nastavitve strežnika"),
|
||||
("Import server configuration successfully", "Nastavitve strežnika uspešno uvožene"),
|
||||
("Export server configuration successfully", "Nastavitve strežnika uspešno izvožene"),
|
||||
("Invalid server configuration", "Neveljavne nastavitve strežnika"),
|
||||
("Clipboard is empty", "Odložišče je prazno"),
|
||||
("Stop service", "Ustavi storitev"),
|
||||
("Change ID", "Spremeni ID"),
|
||||
("Website", "Spletna stran"),
|
||||
("About", "O programu"),
|
||||
("Slogan_tip", ""),
|
||||
("Privacy Statement", ""),
|
||||
("Mute", "Izklopi zvok"),
|
||||
("Audio Input", "Avdio vhod"),
|
||||
("Enhancements", "Izboljšave"),
|
||||
("Hardware Codec", "Strojni kodek"),
|
||||
("Adaptive Bitrate", "Prilagodljiva bitna hitrost"),
|
||||
("ID Server", "ID strežnik"),
|
||||
("Relay Server", "Posredniški strežnik"),
|
||||
("API Server", "API strežnik"),
|
||||
("invalid_http", "mora se začeti s http:// ali https://"),
|
||||
("Invalid IP", "Neveljaven IP"),
|
||||
("id_change_tip", "Dovoljeni znaki so a-z, A-Z (brez šumnikov), 0-9 in _. Prvi znak mora biti črka, dolžina od 6 do 16 znakov."),
|
||||
("Invalid format", "Neveljavna oblika"),
|
||||
("server_not_support", "Strežnik še ne podpira"),
|
||||
("Not available", "Ni na voljo"),
|
||||
("Too frequent", "Prepogosto"),
|
||||
("Cancel", "Prekliči"),
|
||||
("Skip", "Izpusti"),
|
||||
("Close", "Zapri"),
|
||||
("Retry", "Ponovi"),
|
||||
("OK", "V redu"),
|
||||
("Password Required", "Potrebno je geslo"),
|
||||
("Please enter your password", "Vnesite vaše geslo"),
|
||||
("Remember password", "Zapomni si geslo"),
|
||||
("Wrong Password", "Napačno geslo"),
|
||||
("Do you want to enter again?", "Želite znova vnesti?"),
|
||||
("Connection Error", "Napaka pri povezavi"),
|
||||
("Error", "Napaka"),
|
||||
("Reset by the peer", "Povezava prekinjena"),
|
||||
("Connecting...", "Povezovanje..."),
|
||||
("Connection in progress. Please wait.", "Vzpostavljanje povezave, prosim počakajte."),
|
||||
("Please try 1 minute later", "Poizkusite čez 1 minuto"),
|
||||
("Login Error", "Napaka pri prijavi"),
|
||||
("Successful", "Uspešno"),
|
||||
("Connected, waiting for image...", "Povezava vzpostavljena, čakam na sliko..."),
|
||||
("Name", "Ime"),
|
||||
("Type", "Vrsta"),
|
||||
("Modified", "Čas spremembe"),
|
||||
("Size", "Velikost"),
|
||||
("Show Hidden Files", "Prikaži skrite datoteke"),
|
||||
("Receive", "Prejmi"),
|
||||
("Send", "Pošlji"),
|
||||
("Refresh File", "Osveži datoteko"),
|
||||
("Local", "Lokalno"),
|
||||
("Remote", "Oddaljeno"),
|
||||
("Remote Computer", "Oddaljeni računalnik"),
|
||||
("Local Computer", "Lokalni računalnik"),
|
||||
("Confirm Delete", "Potrdi izbris"),
|
||||
("Delete", "Izbriši"),
|
||||
("Properties", "Lastnosti"),
|
||||
("Multi Select", "Večkratna izbira"),
|
||||
("Select All", "Izberi vse"),
|
||||
("Unselect All", "Počisti vse"),
|
||||
("Empty Directory", "Prazen imenik"),
|
||||
("Not an empty directory", "Imenik ni prazen"),
|
||||
("Are you sure you want to delete this file?", "Ali res želite izbrisati to datoteko?"),
|
||||
("Are you sure you want to delete this empty directory?", "Ali res želite izbrisati to prazno mapo?"),
|
||||
("Are you sure you want to delete the file of this directory?", "Ali res želite datoteko iz mape?"),
|
||||
("Do this for all conflicts", "Naredi to za vse"),
|
||||
("This is irreversible!", "Tega dejanja ni mogoče razveljaviti!"),
|
||||
("Deleting", "Brisanje"),
|
||||
("files", "datoteke"),
|
||||
("Waiting", "Čakanje"),
|
||||
("Finished", "Opravljeno"),
|
||||
("Speed", "Hitrost"),
|
||||
("Custom Image Quality", "Kakovost slike po meri"),
|
||||
("Privacy mode", "Zasebni način"),
|
||||
("Block user input", "Onemogoči uporabnikov vnos"),
|
||||
("Unblock user input", "Omogoči uporabnikov vnos"),
|
||||
("Adjust Window", "Prilagodi okno"),
|
||||
("Original", "Originalno"),
|
||||
("Shrink", "Skrči"),
|
||||
("Stretch", "Raztegni"),
|
||||
("Scrollbar", "Drsenje z drsniki"),
|
||||
("ScrollAuto", "Samodejno drsenje"),
|
||||
("Good image quality", "Visoka kakovost slike"),
|
||||
("Balanced", "Uravnoteženo"),
|
||||
("Optimize reaction time", "Optimiraj odzivni čas"),
|
||||
("Custom", "Po meri"),
|
||||
("Show remote cursor", "Prikaži oddaljeni kazalec miške"),
|
||||
("Show quality monitor", "Prikaži nadzornik kakovosti"),
|
||||
("Disable clipboard", "Onemogoči odložišče"),
|
||||
("Lock after session end", "Zakleni ob koncu seje"),
|
||||
("Insert", "Vstavi"),
|
||||
("Insert Lock", "Zakleni oddaljeni računalnik"),
|
||||
("Refresh", "Osveži"),
|
||||
("ID does not exist", "ID ne obstaja"),
|
||||
("Failed to connect to rendezvous server", "Ni se bilo mogoče povezati na povezovalni strežnik"),
|
||||
("Please try later", "Poizkusite znova kasneje"),
|
||||
("Remote desktop is offline", "Oddaljeno namizje ni dosegljivo"),
|
||||
("Key mismatch", "Ključ ni ustrezen"),
|
||||
("Timeout", "Časovna omejitev"),
|
||||
("Failed to connect to relay server", "Ni se bilo mogoče povezati na posredniški strežnik"),
|
||||
("Failed to connect via rendezvous server", "Ni se bilo mogoče povezati preko povezovalnega strežnika"),
|
||||
("Failed to connect via relay server", "Ni se bilo mogoče povezati preko posredniškega strežnika"),
|
||||
("Failed to make direct connection to remote desktop", "Ni bilo mogoče vzpostaviti neposredne povezave z oddaljenim namizjem"),
|
||||
("Set Password", "Nastavi geslo"),
|
||||
("OS Password", "Geslo operacijskega sistema"),
|
||||
("install_tip", "Zaradi nadzora uporabniškega računa, RustDesk v nekaterih primerih na oddaljeni strani ne deluje pravilno. Temu se lahko izognete z namestitvijo."),
|
||||
("Click to upgrade", "Klikni za nadgradnjo"),
|
||||
("Click to download", "Klikni za prenos"),
|
||||
("Click to update", "Klikni za posodobitev"),
|
||||
("Configure", "Nastavi"),
|
||||
("config_acc", "Za oddaljeni nadzor namizja morate RustDesku dodeliti pravico za dostopnost"),
|
||||
("config_screen", "Za oddaljeni dostop do namizja morate RustDesku dodeliti pravico snemanje zaslona"),
|
||||
("Installing ...", "Nameščanje..."),
|
||||
("Install", "Namesti"),
|
||||
("Installation", "Namestitev"),
|
||||
("Installation Path", "Pot za namestitev"),
|
||||
("Create start menu shortcuts", "Ustvari bližnjice v meniju Začetek"),
|
||||
("Create desktop icon", "Ustvari ikono na namizju"),
|
||||
("agreement_tip", "Z namestitvijo se strinjate z licenčno pogodbo"),
|
||||
("Accept and Install", "Sprejmi in namesti"),
|
||||
("End-user license agreement", "Licenčna pogodba za končnega uporabnika"),
|
||||
("Generating ...", "Ustvarjanje ..."),
|
||||
("Your installation is lower version.", "Vaša namestitev je starejša"),
|
||||
("not_close_tcp_tip", "Med uporabo tunela ne zaprite tega okna"),
|
||||
("Listening ...", "Poslušam ..."),
|
||||
("Remote Host", "Oddaljeni gostitelj"),
|
||||
("Remote Port", "Oddaljena vrata"),
|
||||
("Action", "Dejanje"),
|
||||
("Add", "Dodaj"),
|
||||
("Local Port", "Lokalna vrata"),
|
||||
("Local Address", "Lokalni naslov"),
|
||||
("Change Local Port", "Spremeni lokalna vrata"),
|
||||
("setup_server_tip", "Za hitrejšo povezavo uporabite lasten strežnik"),
|
||||
("Too short, at least 6 characters.", "Prekratek, mora biti najmanj 6 znakov."),
|
||||
("The confirmation is not identical.", "Potrditev ni enaka."),
|
||||
("Permissions", "Dovoljenja"),
|
||||
("Accept", "Sprejmi"),
|
||||
("Dismiss", "Opusti"),
|
||||
("Disconnect", "Prekini povezavo"),
|
||||
("Allow using keyboard and mouse", "Dovoli uporabo tipkovnice in miške"),
|
||||
("Allow using clipboard", "Dovoli uporabo odložišča"),
|
||||
("Allow hearing sound", "Dovoli prenos zvoka"),
|
||||
("Allow file copy and paste", "Dovoli kopiranje in lepljenje datotek"),
|
||||
("Connected", "Povezan"),
|
||||
("Direct and encrypted connection", "Neposredna šifrirana povezava"),
|
||||
("Relayed and encrypted connection", "Posredovana šifrirana povezava"),
|
||||
("Direct and unencrypted connection", "Neposredna nešifrirana povezava"),
|
||||
("Relayed and unencrypted connection", "Posredovana šifrirana povezava"),
|
||||
("Enter Remote ID", "Vnesi oddaljeni ID"),
|
||||
("Enter your password", "Vnesi geslo"),
|
||||
("Logging in...", "Prijavljanje..."),
|
||||
("Enable RDP session sharing", "Omogoči deljenje RDP seje"),
|
||||
("Auto Login", "Samodejna prijava"),
|
||||
("Enable Direct IP Access", "Omogoči neposredni dostop preko IP"),
|
||||
("Rename", "Preimenuj"),
|
||||
("Space", "Prazno"),
|
||||
("Create Desktop Shortcut", "Ustvari bližnjico na namizju"),
|
||||
("Change Path", "Spremeni pot"),
|
||||
("Create Folder", "Ustvari mapo"),
|
||||
("Please enter the folder name", "Vnesite ime mape"),
|
||||
("Fix it", "Popravi"),
|
||||
("Warning", "Opozorilo"),
|
||||
("Login screen using Wayland is not supported", "Prijava z Waylandom ni podprta"),
|
||||
("Reboot required", "Potreben je ponovni zagon"),
|
||||
("Unsupported display server ", "Nepodprt zaslonski strežnik"),
|
||||
("x11 expected", "Pričakovan X11"),
|
||||
("Port", "Vrata"),
|
||||
("Settings", "Nastavitve"),
|
||||
("Username", "Uporabniško ime"),
|
||||
("Invalid port", "Neveljavno geslo"),
|
||||
("Closed manually by the peer", "Povezavo ročno prekinil odjemalec"),
|
||||
("Enable remote configuration modification", "Omogoči oddaljeno spreminjanje nastavitev"),
|
||||
("Run without install", "Zaženi brez namestitve"),
|
||||
("Always connected via relay", "Vedno povezan preko posrednika"),
|
||||
("Always connect via relay", "Vedno poveži preko posrednika"),
|
||||
("whitelist_tip", "Dostop je možen samo iz dovoljenih IPjev"),
|
||||
("Login", "Prijavi"),
|
||||
("Verify", ""),
|
||||
("Remember me", ""),
|
||||
("Trust this device", ""),
|
||||
("Verification code", ""),
|
||||
("verification_tip", ""),
|
||||
("Logout", "Odjavi"),
|
||||
("Tags", "Oznake"),
|
||||
("Search ID", "Išči ID"),
|
||||
("Current Wayland display server is not supported", "Trenutni Wayland zaslonski strežnik ni podprt"),
|
||||
("whitelist_sep", "Naslovi ločeni z vejico, podpičjem, presledkom ali novo vrstico"),
|
||||
("Add ID", "Dodaj ID"),
|
||||
("Add Tag", "Dodaj oznako"),
|
||||
("Unselect all tags", ""),
|
||||
("Network error", "Omrežna napaka"),
|
||||
("Username missed", "Up. ime izpuščeno"),
|
||||
("Password missed", "Geslo izpuščeno"),
|
||||
("Wrong credentials", "Napačne poverilnice"),
|
||||
("Edit Tag", "Uredi oznako"),
|
||||
("Unremember Password", "Pozabi geslo"),
|
||||
("Favorites", "Priljubljene"),
|
||||
("Add to Favorites", "Dodaj med priljubljene"),
|
||||
("Remove from Favorites", "Odstrani iz priljubljenih"),
|
||||
("Empty", "Prazno"),
|
||||
("Invalid folder name", "Napačno ime mape"),
|
||||
("Socks5 Proxy", "Socks5 posredniški strežnik"),
|
||||
("Hostname", "Ime gostitelja"),
|
||||
("Discovered", "Odkriti"),
|
||||
("install_daemon_tip", "Za samodejni zagon ob vklopu računalnika je potrebno dodati sistemsko storitev"),
|
||||
("Remote ID", "Oddaljeni ID"),
|
||||
("Paste", "Prilepi"),
|
||||
("Paste here?", "Prilepi tu?"),
|
||||
("Are you sure to close the connection?", "Ali želite prekiniti povezavo?"),
|
||||
("Download new version", "Prenesi novo različico"),
|
||||
("Touch mode", "Način dotika"),
|
||||
("Mouse mode", "Način mišle"),
|
||||
("One-Finger Tap", "Tap z enim prstom"),
|
||||
("Left Mouse", "Leva tipka miške"),
|
||||
("One-Long Tap", "Dolg tap z enim prstom"),
|
||||
("Two-Finger Tap", "Tap z dvema prstoma"),
|
||||
("Right Mouse", "Desna tipka miške"),
|
||||
("One-Finger Move", "Premik z enim prstom"),
|
||||
("Double Tap & Move", "Dvojni tap in premik"),
|
||||
("Mouse Drag", "Vlečenje z miško"),
|
||||
("Three-Finger vertically", "Triprstno navpično"),
|
||||
("Mouse Wheel", "Miškino kolesce"),
|
||||
("Two-Finger Move", "Premik z dvema prstoma"),
|
||||
("Canvas Move", "Premik platna"),
|
||||
("Pinch to Zoom", "Povečava s približevanjem prstov"),
|
||||
("Canvas Zoom", "Povečava platna"),
|
||||
("Reset canvas", "Ponastavi platno"),
|
||||
("No permission of file transfer", "Ni pravic za prenos datotek"),
|
||||
("Note", "Opomba"),
|
||||
("Connection", "Povezava"),
|
||||
("Share Screen", "Deli zaslon"),
|
||||
("CLOSE", "ZAPRI"),
|
||||
("OPEN", "ODPRI"),
|
||||
("Chat", "Pogovor"),
|
||||
("Total", "Skupaj"),
|
||||
("items", "elementi"),
|
||||
("Selected", "Izbrano"),
|
||||
("Screen Capture", "Zajem zaslona"),
|
||||
("Input Control", "Nadzor vnosa"),
|
||||
("Audio Capture", "Zajem zvoka"),
|
||||
("File Connection", "Datotečna povezava"),
|
||||
("Screen Connection", "Zaslonska povezava"),
|
||||
("Do you accept?", "Ali sprejmete?"),
|
||||
("Open System Setting", "Odpri sistemske nastavitve"),
|
||||
("How to get Android input permission?", "Kako pridobiti dovoljenje za vnos na Androidu?"),
|
||||
("android_input_permission_tip1", "Za oddaljeni nadzor vaše naprave Android, je potrebno RustDesku dodeliti pravico za dostopnost."),
|
||||
("android_input_permission_tip2", "Pojdite v sistemske nastavitve, poiščite »Nameščene storitve« in vklopite storitev »RustDesk Input«."),
|
||||
("android_new_connection_tip", "Prejeta je bila zahteva za oddaljeni nadzor vaše naprave."),
|
||||
("android_service_will_start_tip", "Z vklopom zajema zaslona se bo samodejno zagnala storitev, ki omogoča da oddaljene naprave pošljejo zahtevo za povezavo na vašo napravo."),
|
||||
("android_stop_service_tip", "Z zaustavitvijo storitve bodo samodejno prekinjene vse oddaljene povezave."),
|
||||
("android_version_audio_tip", "Trenutna različica Androida ne omogoča zajema zvoka. Za zajem zvoka nadgradite na Android 10 ali novejši."),
|
||||
("android_start_service_tip", "Tapnite »Zaženi storitev« ali »ODPRI« pri dovoljenju za zajem zaslona da zaženete storitev deljenja zaslona."),
|
||||
("Account", "Račun"),
|
||||
("Overwrite", "Prepiši"),
|
||||
("This file exists, skip or overwrite this file?", "Datoteka obstaja, izpusti ali prepiši?"),
|
||||
("Quit", "Izhod"),
|
||||
("doc_mac_permission", "https://rustdesk.com/docs/en/manual/mac/#enable-permissions"),
|
||||
("Help", "Pomoč"),
|
||||
("Failed", "Ni uspelo"),
|
||||
("Succeeded", "Uspelo"),
|
||||
("Someone turns on privacy mode, exit", "Vklopljen je zasebni način, izhod"),
|
||||
("Unsupported", "Ni podprto"),
|
||||
("Peer denied", "Odjemalec zavrnil"),
|
||||
("Please install plugins", "Namestite vključke"),
|
||||
("Peer exit", "Odjemalec se je zaprl"),
|
||||
("Failed to turn off", "Ni bilo mogoče izklopiti"),
|
||||
("Turned off", "Izklopljeno"),
|
||||
("In privacy mode", "V zasebnem načinu"),
|
||||
("Out privacy mode", "Iz zasebnega načina"),
|
||||
("Language", "Jezik"),
|
||||
("Keep RustDesk background service", "Ohrani RustDeskovo storitev v ozadju"),
|
||||
("Ignore Battery Optimizations", "Prezri optimizacije baterije"),
|
||||
("android_open_battery_optimizations_tip", "Če želite izklopiti to možnost, pojdite v nastavitve aplikacije RustDesk, poiščite »Baterija« in izklopite »Neomejeno«"),
|
||||
("Connection not allowed", "Povezava ni dovoljena"),
|
||||
("Legacy mode", "Stari način"),
|
||||
("Map mode", "Način preslikave"),
|
||||
("Translate mode", "Način prevajanja"),
|
||||
("Use permanent password", "Uporabi stalno geslo"),
|
||||
("Use both passwords", "Uporabi obe gesli"),
|
||||
("Set permanent password", "Nastavi stalno geslo"),
|
||||
("Enable Remote Restart", "Omogoči oddaljeni ponovni zagon"),
|
||||
("Allow remote restart", "Dovoli oddaljeni ponovni zagon"),
|
||||
("Restart Remote Device", "Znova zaženi oddaljeno napravo"),
|
||||
("Are you sure you want to restart", "Ali ste prepričani, da želite znova zagnati"),
|
||||
("Restarting Remote Device", "Ponovni zagon oddaljene naprave"),
|
||||
("remote_restarting_tip", "Oddaljena naprava se znova zaganja, prosim zaprite to sporočilo in se čez nekaj časa povežite s stalnim geslom."),
|
||||
("Copied", "Kopirano"),
|
||||
("Exit Fullscreen", "Izhod iz celozaslonskega načina"),
|
||||
("Fullscreen", "Celozaslonski način"),
|
||||
("Mobile Actions", "Dejanja za prenosne naprave"),
|
||||
("Select Monitor", "Izberite zaslon"),
|
||||
("Control Actions", "Dejanja za nadzor"),
|
||||
("Display Settings", "Nastavitve zaslona"),
|
||||
("Ratio", "Razmerje"),
|
||||
("Image Quality", "Kakovost slike"),
|
||||
("Scroll Style", "Način drsenja"),
|
||||
("Show Menubar", "Prikaži meni"),
|
||||
("Hide Menubar", "Skrij meni"),
|
||||
("Direct Connection", "Neposredna povezava"),
|
||||
("Relay Connection", "Posredovana povezava"),
|
||||
("Secure Connection", "Zavarovana povezava"),
|
||||
("Insecure Connection", "Nezavarovana povezava"),
|
||||
("Scale original", "Originalna velikost"),
|
||||
("Scale adaptive", "Prilagojena velikost"),
|
||||
("General", "Splošno"),
|
||||
("Security", "Varnost"),
|
||||
("Theme", "Tema"),
|
||||
("Dark Theme", "Temna tema"),
|
||||
("Dark", "Temna"),
|
||||
("Light", "Svetla"),
|
||||
("Follow System", "Sistemska"),
|
||||
("Enable hardware codec", "Omogoči strojno pospeševanje"),
|
||||
("Unlock Security Settings", "Odkleni varnostne nastavitve"),
|
||||
("Enable Audio", "Omogoči zvok"),
|
||||
("Unlock Network Settings", "Odkleni mrežne nastavitve"),
|
||||
("Server", "Strežnik"),
|
||||
("Direct IP Access", "Neposredni dostop preko IPja"),
|
||||
("Proxy", "Posredniški strežnik"),
|
||||
("Apply", "Uveljavi"),
|
||||
("Disconnect all devices?", "Odklopi vse naprave?"),
|
||||
("Clear", "Počisti"),
|
||||
("Audio Input Device", "Vhodna naprava za zvok"),
|
||||
("Deny remote access", "Onemogoči oddaljeni dostop"),
|
||||
("Use IP Whitelisting", "Omogoči seznam dovoljenih IP naslovov"),
|
||||
("Network", "Mreža"),
|
||||
("Enable RDP", "Omogoči RDP"),
|
||||
("Pin menubar", "Pripni menijsko vrstico"),
|
||||
("Unpin menubar", "Odpni menijsko vrstico"),
|
||||
("Recording", "Snemanje"),
|
||||
("Directory", "Imenik"),
|
||||
("Automatically record incoming sessions", "Samodejno snemaj vhodne seje"),
|
||||
("Change", "Spremeni"),
|
||||
("Start session recording", "Začni snemanje seje"),
|
||||
("Stop session recording", "Ustavi snemanje seje"),
|
||||
("Enable Recording Session", "Omogoči snemanje seje"),
|
||||
("Allow recording session", "Dovoli snemanje seje"),
|
||||
("Enable LAN Discovery", "Omogoči odkrivanje lokalnega omrežja"),
|
||||
("Deny LAN Discovery", "Onemogoči odkrivanje lokalnega omrežja"),
|
||||
("Write a message", "Napiši spoorčilo"),
|
||||
("Prompt", "Poziv"),
|
||||
("Please wait for confirmation of UAC...", "Počakajte za potrditev nadzora uporabniškega računa"),
|
||||
("elevated_foreground_window_tip", "Trenutno aktivno okno na oddaljenem računalniku zahteva višje pravice za upravljanje. Oddaljenega uporabnika lahko prosite, da okno minimizira, ali pa kliknite gumb za povzdig pravic v oknu za upravljanje povezave. Če se želite izogniti temu problemu, na oddaljenem računalniku RustDesk namestite."),
|
||||
("Disconnected", "Brez povezave"),
|
||||
("Other", "Drugo"),
|
||||
("Confirm before closing multiple tabs", "Zahtevajte potrditev pred zapiranjem večih zavihkov"),
|
||||
("Keyboard Settings", "Nastavitve tipkovnice"),
|
||||
("Full Access", "Poln dostop"),
|
||||
("Screen Share", "Deljenje zaslona"),
|
||||
("Wayland requires Ubuntu 21.04 or higher version.", "Wayland zahteva Ubuntu 21.04 ali novejši"),
|
||||
("Wayland requires higher version of linux distro. Please try X11 desktop or change your OS.", "Zahtevana je novejša različica Waylanda. Posodobite vašo distribucijo ali pa uporabite X11."),
|
||||
("JumpLink", "Pogled"),
|
||||
("Please Select the screen to be shared(Operate on the peer side).", "Izberite zaslon za delitev (na oddaljeni strani)."),
|
||||
("Show RustDesk", "Prikaži RustDesk"),
|
||||
("This PC", "Ta računalnik"),
|
||||
("or", "ali"),
|
||||
("Continue with", "Nadaljuj z"),
|
||||
("Elevate", "Povzdig pravic"),
|
||||
("Zoom cursor", "Prilagodi velikost miškinega kazalca"),
|
||||
("Accept sessions via password", "Sprejmi seje z geslom"),
|
||||
("Accept sessions via click", "Sprejmi seje s potrditvijo"),
|
||||
("Accept sessions via both", "Sprejmi seje z geslom ali potrditvijo"),
|
||||
("Please wait for the remote side to accept your session request...", "Počakajte, da oddaljeni računalnik sprejme povezavo..."),
|
||||
("One-time Password", "Enkratno geslo"),
|
||||
("Use one-time password", "Uporabi enkratno geslo"),
|
||||
("One-time password length", "Dolžina enkratnega gesla"),
|
||||
("Request access to your device", "Zahtevaj dostop do svoje naprave"),
|
||||
("Hide connection management window", "Skrij okno za upravljanje povezave"),
|
||||
("hide_cm_tip", "Dovoli skrivanje samo pri sprejemanju sej z geslom"),
|
||||
("wayland_experiment_tip", "Podpora za Wayland je v preizkusni fazi. Uporabite X11, če rabite nespremljan dostop."),
|
||||
("Right click to select tabs", "Desno-kliknite za izbiro zavihkov"),
|
||||
("Skipped", "Izpuščeno"),
|
||||
("Add to Address Book", "Dodaj v adresar"),
|
||||
("Group", "Skupina"),
|
||||
("Search", "Iskanje"),
|
||||
("Closed manually by the web console", "Ročno zaprto iz spletne konzole"),
|
||||
("Local keyboard type", "Lokalna vrsta tipkovnice"),
|
||||
("Select local keyboard type", "Izberite lokalno vrsto tipkovnice"),
|
||||
("software_render_tip", ""),
|
||||
("Always use software rendering", ""),
|
||||
("config_input", ""),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
@@ -39,6 +39,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Change ID", "Ndryshoni ID"),
|
||||
("Website", "Faqe ëebi"),
|
||||
("About", "Rreth"),
|
||||
("Slogan_tip", ""),
|
||||
("Privacy Statement", ""),
|
||||
("Mute", "Pa zë"),
|
||||
("Audio Input", "Inputi zërit"),
|
||||
("Enhancements", "Përmirësimet"),
|
||||
@@ -208,6 +210,11 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Always connect via relay", "Gjithmonë lidheni me transmetues"),
|
||||
("whitelist_tip", "Vetëm IP e listës së bardhë mund të më aksesoj."),
|
||||
("Login", "Hyrje"),
|
||||
("Verify", ""),
|
||||
("Remember me", ""),
|
||||
("Trust this device", ""),
|
||||
("Verification code", ""),
|
||||
("verification_tip", ""),
|
||||
("Logout", "Dalje"),
|
||||
("Tags", "Tage"),
|
||||
("Search ID", "Kerko ID"),
|
||||
@@ -332,7 +339,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Scale adaptive", " E përsjhtatshme në shkallë"),
|
||||
("General", "Gjeneral"),
|
||||
("Security", "Siguria"),
|
||||
("Account", "Llogaria"),
|
||||
("Theme", "Theme"),
|
||||
("Dark Theme", "Theme e errët"),
|
||||
("Dark", "E errët"),
|
||||
@@ -345,7 +351,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Server", "Server"),
|
||||
("Direct IP Access", "Qasje e drejtpërdrejtë IP"),
|
||||
("Proxy", "Proxy"),
|
||||
("Port", "Port"),
|
||||
("Apply", "Apliko"),
|
||||
("Disconnect all devices?", "Shkyç të gjitha pajisjet?"),
|
||||
("Clear", "Pastro"),
|
||||
@@ -374,7 +379,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Other", "Tjetër"),
|
||||
("Confirm before closing multiple tabs", "Konfirmo përpara se të mbyllësh shumë skeda"),
|
||||
("Keyboard Settings", "Cilësimet e tastierës"),
|
||||
("Custom", "Personalizuar"),
|
||||
("Full Access", "Qasje e plotë"),
|
||||
("Screen Share", "Ndarja e ekranit"),
|
||||
("Wayland requires Ubuntu 21.04 or higher version.", "Wayland kërkon Ubuntu 21.04 ose version më të lartë"),
|
||||
@@ -399,6 +403,15 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("hide_cm_tip", "Kjo është e mundur vetëm nëse aksesi bëhet nëpërmjet një fjalëkalimi të përhershëm"),
|
||||
("wayland_experiment_tip", ""),
|
||||
("Right click to select tabs", ""),
|
||||
("Skipped", ""),
|
||||
("Add to Address Book", ""),
|
||||
("Group", ""),
|
||||
("Search", ""),
|
||||
("Closed manually by the web console", ""),
|
||||
("Local keyboard type", ""),
|
||||
("Select local keyboard type", ""),
|
||||
("software_render_tip", ""),
|
||||
("Always use software rendering", ""),
|
||||
("config_input", ""),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
||||
417
src/lang/sr.rs
Normal file
417
src/lang/sr.rs
Normal file
@@ -0,0 +1,417 @@
|
||||
lazy_static::lazy_static! {
|
||||
pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
[
|
||||
("Status", "Status"),
|
||||
("Your Desktop", "Vaša radna površina"),
|
||||
("desk_tip", "Vašoj radnoj površini se može pristupiti ovim ID i lozinkom."),
|
||||
("Password", "Lozinka"),
|
||||
("Ready", "Spremno"),
|
||||
("Established", "Uspostavljeno"),
|
||||
("connecting_status", "Spajanje na RustDesk mrežu..."),
|
||||
("Enable Service", "Dozvoli servis"),
|
||||
("Start Service", "Pokreni servis"),
|
||||
("Service is running", "Servis je pokrenut"),
|
||||
("Service is not running", "Servis nije pokrenut"),
|
||||
("not_ready_status", "Nije spremno. Proverite konekciju."),
|
||||
("Control Remote Desktop", "Upravljanje udaljenom radnom površinom"),
|
||||
("Transfer File", "Prenos fajla"),
|
||||
("Connect", "Spajanje"),
|
||||
("Recent Sessions", "Poslednje sesije"),
|
||||
("Address Book", "Adresar"),
|
||||
("Confirmation", "Potvrda"),
|
||||
("TCP Tunneling", "TCP tunel"),
|
||||
("Remove", "Ukloni"),
|
||||
("Refresh random password", "Osveži slučajnu lozinku"),
|
||||
("Set your own password", "Postavi lozinku"),
|
||||
("Enable Keyboard/Mouse", "Dozvoli tastaturu/miša"),
|
||||
("Enable Clipboard", "Dozvoli clipboard"),
|
||||
("Enable File Transfer", "Dozvoli prenos fajlova"),
|
||||
("Enable TCP Tunneling", "Dozvoli TCP tunel"),
|
||||
("IP Whitelisting", "IP pouzdana lista"),
|
||||
("ID/Relay Server", "ID/Posredni server"),
|
||||
("Import Server Config", "Import server konfiguracije"),
|
||||
("Export Server Config", "Eksport server konfiguracije"),
|
||||
("Import server configuration successfully", "Import server konfiguracije uspešan"),
|
||||
("Export server configuration successfully", "Eksport server konfiguracije uspešan"),
|
||||
("Invalid server configuration", "Pogrešna konfiguracija servera"),
|
||||
("Clipboard is empty", "Clipboard je prazan"),
|
||||
("Stop service", "Stopiraj servis"),
|
||||
("Change ID", "Promeni ID"),
|
||||
("Website", "Web sajt"),
|
||||
("About", "O programu"),
|
||||
("Slogan_tip", ""),
|
||||
("Privacy Statement", ""),
|
||||
("Mute", "Utišaj"),
|
||||
("Audio Input", "Audio ulaz"),
|
||||
("Enhancements", "Proširenja"),
|
||||
("Hardware Codec", "Hardverski kodek"),
|
||||
("Adaptive Bitrate", "Prilagodljiva gustina podataka"),
|
||||
("ID Server", "ID server"),
|
||||
("Relay Server", "Posredni server"),
|
||||
("API Server", "API server"),
|
||||
("invalid_http", "mora početi sa http:// ili https://"),
|
||||
("Invalid IP", "Nevažeća IP"),
|
||||
("id_change_tip", "Dozvoljeni su samo a-z, A-Z, 0-9 i _ (donja crta) znakovi. Prvi znak mora biti slovo a-z, A-Z. Dužina je od 6 do 16."),
|
||||
("Invalid format", "Pogrešan format"),
|
||||
("server_not_support", "Server još uvek ne podržava"),
|
||||
("Not available", "Nije dostupno"),
|
||||
("Too frequent", "Previše često"),
|
||||
("Cancel", "Otkaži"),
|
||||
("Skip", "Preskoči"),
|
||||
("Close", "Zatvori"),
|
||||
("Retry", "Ponovi"),
|
||||
("OK", "Ok"),
|
||||
("Password Required", "Potrebna lozinka"),
|
||||
("Please enter your password", "Molimo unesite svoju lozinku"),
|
||||
("Remember password", "Zapamti lozinku"),
|
||||
("Wrong Password", "Pogrešna lozinka"),
|
||||
("Do you want to enter again?", "Želite li da unesete ponovo?"),
|
||||
("Connection Error", "Greška u konekciji"),
|
||||
("Error", "Greška"),
|
||||
("Reset by the peer", "Prekinuto sa druge strane"),
|
||||
("Connecting...", "Povezivanje..."),
|
||||
("Connection in progress. Please wait.", "Povezivanje u toku. Molimo sačekajte."),
|
||||
("Please try 1 minute later", "Pokušajte minut kasnije"),
|
||||
("Login Error", "Greška u prijavljivanju"),
|
||||
("Successful", "Uspešno"),
|
||||
("Connected, waiting for image...", "Spojeno, sačekajte sliku..."),
|
||||
("Name", "Ime"),
|
||||
("Type", "Tip"),
|
||||
("Modified", "Izmenjeno"),
|
||||
("Size", "Veličina"),
|
||||
("Show Hidden Files", "Prikaži skrivene datoteke"),
|
||||
("Receive", "Prijem"),
|
||||
("Send", "Slanje"),
|
||||
("Refresh File", "Osveži datoteku"),
|
||||
("Local", "Lokalno"),
|
||||
("Remote", "Udaljeno"),
|
||||
("Remote Computer", "Udaljeni računar"),
|
||||
("Local Computer", "Lokalni računar"),
|
||||
("Confirm Delete", "Potvrdite brisanje"),
|
||||
("Delete", "Brisanje"),
|
||||
("Properties", "Osobine"),
|
||||
("Multi Select", "Višestruko selektovanje"),
|
||||
("Select All", "Selektuj sve"),
|
||||
("Unselect All", "Deselektuj sve"),
|
||||
("Empty Directory", "Prazan direktorijum"),
|
||||
("Not an empty directory", "Nije prazan direktorijum"),
|
||||
("Are you sure you want to delete this file?", "Da li ste sigurni da želite da obrišete ovu datoteku?"),
|
||||
("Are you sure you want to delete this empty directory?", "Da li ste sigurni da želite da obrišete ovaj prazan direktorijum?"),
|
||||
("Are you sure you want to delete the file of this directory?", "Da li ste sigurni da želite da obrišete datoteku ovog direktorijuma?"),
|
||||
("Do this for all conflicts", "Uradi ovo za sve konflikte"),
|
||||
("This is irreversible!", "Ovo je nepovratno"),
|
||||
("Deleting", "Brisanje"),
|
||||
("files", "datoteke"),
|
||||
("Waiting", "Čekanje"),
|
||||
("Finished", "Završeno"),
|
||||
("Speed", "Brzina"),
|
||||
("Custom Image Quality", "Korisnički kvalitet slike"),
|
||||
("Privacy mode", "Mod privatnosti"),
|
||||
("Block user input", "Blokiraj korisnikov unos"),
|
||||
("Unblock user input", "Odblokiraj korisnikov unos"),
|
||||
("Adjust Window", "Podesi prozor"),
|
||||
("Original", "Original"),
|
||||
("Shrink", "Skupi"),
|
||||
("Stretch", "Raširi"),
|
||||
("Scrollbar", "Skrol linija"),
|
||||
("ScrollAuto", "Auto skrol"),
|
||||
("Good image quality", "Dobar kvalitet slike"),
|
||||
("Balanced", "Balansirano"),
|
||||
("Optimize reaction time", "Optimizuj vreme reakcije"),
|
||||
("Custom", "Korisnički"),
|
||||
("Show remote cursor", "Prikaži udaljeni kursor"),
|
||||
("Show quality monitor", "Prikaži monitor kvaliteta"),
|
||||
("Disable clipboard", "Zabrani clipboard"),
|
||||
("Lock after session end", "Zaključaj po završetku sesije"),
|
||||
("Insert", "Umetni"),
|
||||
("Insert Lock", "Zaključaj umetanje"),
|
||||
("Refresh", "Osveži"),
|
||||
("ID does not exist", "ID ne postoji"),
|
||||
("Failed to connect to rendezvous server", "Greška u spajanju na server za povezivanje"),
|
||||
("Please try later", "Molimo pokušajte kasnije"),
|
||||
("Remote desktop is offline", "Udaljeni ekran je isključen"),
|
||||
("Key mismatch", "Pogrešan ključ"),
|
||||
("Timeout", "Isteklo vreme"),
|
||||
("Failed to connect to relay server", "Greška u spajanju na posredni server"),
|
||||
("Failed to connect via rendezvous server", "Greška u spajanju preko servera za povezivanje"),
|
||||
("Failed to connect via relay server", "Greška u spajanju preko posrednog servera"),
|
||||
("Failed to make direct connection to remote desktop", "Greška u direktnom spajanju na udaljenu radnu površinu"),
|
||||
("Set Password", "Postavi lozinku"),
|
||||
("OS Password", "OS lozinka"),
|
||||
("install_tip", "Zbog UAC RustDesk ne može raditi pravilno u nekim slučajevima. Da biste prevazišli UAC, kliknite taster ispod da instalirate RustDesk na sistem."),
|
||||
("Click to upgrade", "Klik za nadogradnju"),
|
||||
("Click to download", "Klik za preuzimanje"),
|
||||
("Click to update", "Klik za ažuriranje"),
|
||||
("Configure", "Konfigurisanje"),
|
||||
("config_acc", "Da biste daljinski kontrolisali radnu površinu, RustDesk-u treba da dodelite \"Accessibility\" prava."),
|
||||
("config_screen", "Da biste daljinski pristupili radnoj površini, RustDesk-u treba da dodelite \"Screen Recording\" prava."),
|
||||
("Installing ...", "Instaliranje..."),
|
||||
("Install", "Instaliraj"),
|
||||
("Installation", "Instalacija"),
|
||||
("Installation Path", "Putanja za instalaciju"),
|
||||
("Create start menu shortcuts", "Kreiraj prečice u meniju"),
|
||||
("Create desktop icon", "Kreiraj ikonicu na radnoj površini"),
|
||||
("agreement_tip", "Pokretanjem instalacije prihvatate ugovor o licenciranju."),
|
||||
("Accept and Install", "Prihvati i instaliraj"),
|
||||
("End-user license agreement", "Ugovor sa krajnjim korisnikom"),
|
||||
("Generating ...", "Generisanje..."),
|
||||
("Your installation is lower version.", "Vaša instalacija je niže verzije"),
|
||||
("not_close_tcp_tip", "Ne zatvarajte ovaj prozor dok koristite tunel"),
|
||||
("Listening ...", "Na slušanju..."),
|
||||
("Remote Host", "Adresa udaljenog uređaja"),
|
||||
("Remote Port", "Udaljeni port"),
|
||||
("Action", "Akcija"),
|
||||
("Add", "Dodaj"),
|
||||
("Local Port", "Lokalni port"),
|
||||
("Local Address", "Lokalna adresa"),
|
||||
("Change Local Port", "Promeni lokalni port"),
|
||||
("setup_server_tip", "Za brže spajanje, molimo da koristite svoj server"),
|
||||
("Too short, at least 6 characters.", "Prekratko, najmanje 6 znakova."),
|
||||
("The confirmation is not identical.", "Potvrda nije identična"),
|
||||
("Permissions", "Dozvole"),
|
||||
("Accept", "Prihvati"),
|
||||
("Dismiss", "Odbaci"),
|
||||
("Disconnect", "Raskini konekciju"),
|
||||
("Allow using keyboard and mouse", "Dozvoli korišćenje tastature i miša"),
|
||||
("Allow using clipboard", "Dozvoli korišćenje clipboard-a"),
|
||||
("Allow hearing sound", "Dozvoli da se čuje zvuk"),
|
||||
("Allow file copy and paste", "Dozvoli kopiranje i lepljenje fajlova"),
|
||||
("Connected", "Spojeno"),
|
||||
("Direct and encrypted connection", "Direktna i kriptovana konekcija"),
|
||||
("Relayed and encrypted connection", "Posredna i kriptovana konekcija"),
|
||||
("Direct and unencrypted connection", "Direktna i nekriptovana konekcija"),
|
||||
("Relayed and unencrypted connection", "Posredna i nekriptovana konekcija"),
|
||||
("Enter Remote ID", "Unesite ID udaljenog uređaja"),
|
||||
("Enter your password", "Unesite svoju lozinku"),
|
||||
("Logging in...", "Prijava..."),
|
||||
("Enable RDP session sharing", "Dozvoli deljenje RDP sesije"),
|
||||
("Auto Login", "Auto prijavljivanje (Važeće samo ako ste postavili \"Lock after session end\")"),
|
||||
("Enable Direct IP Access", "Dozvoli direktan pristup preko IP"),
|
||||
("Rename", "Preimenuj"),
|
||||
("Space", "Prazno"),
|
||||
("Create Desktop Shortcut", "Kreiraj prečicu na radnoj površini"),
|
||||
("Change Path", "Promeni putanju"),
|
||||
("Create Folder", "Kreiraj direktorijum"),
|
||||
("Please enter the folder name", "Unesite ime direktorijuma"),
|
||||
("Fix it", "Popravi ga"),
|
||||
("Warning", "Upozorenje"),
|
||||
("Login screen using Wayland is not supported", "Ekran za prijavu koji koristi Wayland nije podržan"),
|
||||
("Reboot required", "Potreban je restart"),
|
||||
("Unsupported display server ", "Nepodržan server za prikaz"),
|
||||
("x11 expected", "x11 očekivan"),
|
||||
("Port", "Port"),
|
||||
("Settings", "Postavke"),
|
||||
("Username", "Korisničko ime"),
|
||||
("Invalid port", "Pogrešan port"),
|
||||
("Closed manually by the peer", "Klijent ručno raskinuo konekciju"),
|
||||
("Enable remote configuration modification", "Dozvoli modifikaciju udaljene konfiguracije"),
|
||||
("Run without install", "Pokreni bez instalacije"),
|
||||
("Always connected via relay", "Uvek spojne preko posrednika"),
|
||||
("Always connect via relay", "Uvek se spoj preko posrednika"),
|
||||
("whitelist_tip", "Samo dozvoljene IP mi mogu pristupiti"),
|
||||
("Login", "Prijava"),
|
||||
("Verify", ""),
|
||||
("Remember me", ""),
|
||||
("Trust this device", ""),
|
||||
("Verification code", ""),
|
||||
("verification_tip", ""),
|
||||
("Logout", "Odjava"),
|
||||
("Tags", "Oznake"),
|
||||
("Search ID", "Traži ID"),
|
||||
("Current Wayland display server is not supported", "Tekući Wazland server za prikaz nije podržan"),
|
||||
("whitelist_sep", "Odvojeno zarezima, tačka zarezima, praznim mestima ili novim redovima"),
|
||||
("Add ID", "Dodaj ID"),
|
||||
("Add Tag", "Dodaj oznaku"),
|
||||
("Unselect all tags", "Odselektuj sve oznake"),
|
||||
("Network error", "Greška na mreži"),
|
||||
("Username missed", "Korisničko ime promašeno"),
|
||||
("Password missed", "Lozinka promašena"),
|
||||
("Wrong credentials", "Pogrešno korisničko ime ili lozinka"),
|
||||
("Edit Tag", "Izmeni oznaku"),
|
||||
("Unremember Password", "Zaboravi lozinku"),
|
||||
("Favorites", "Favoriti"),
|
||||
("Add to Favorites", "Dodaj u favorite"),
|
||||
("Remove from Favorites", "Izbaci iz favorita"),
|
||||
("Empty", "Prazno"),
|
||||
("Invalid folder name", "Pogrešno ime direktorijuma"),
|
||||
("Socks5 Proxy", "Socks5 proksi"),
|
||||
("Hostname", "Ime uređaja"),
|
||||
("Discovered", "Otkriveno"),
|
||||
("install_daemon_tip", "Za pokretanje pri startu sistema, treba da instalirate sistemski servis."),
|
||||
("Remote ID", "Udaljeni ID"),
|
||||
("Paste", "Nalepi"),
|
||||
("Paste here?", "Nalepi ovde?"),
|
||||
("Are you sure to close the connection?", "Da li ste sigurni da želite da zatvorite konekciju?"),
|
||||
("Download new version", "Preuzmi novu verziju"),
|
||||
("Touch mode", "Mod na dodir"),
|
||||
("Mouse mode", "Miš mod"),
|
||||
("One-Finger Tap", "Pritisak jednim prstom"),
|
||||
("Left Mouse", "Levi miš"),
|
||||
("One-Long Tap", "Dugi pritisak"),
|
||||
("Two-Finger Tap", "Pritisak sa dva prsta"),
|
||||
("Right Mouse", "Desni miš"),
|
||||
("One-Finger Move", "Pomeranje jednim prstom"),
|
||||
("Double Tap & Move", "Dupli pritisak i pomeranje"),
|
||||
("Mouse Drag", "Prevlačenje mišem"),
|
||||
("Three-Finger vertically", "Sa tri prsta vertikalno"),
|
||||
("Mouse Wheel", "Točkić miša"),
|
||||
("Two-Finger Move", "Pomeranje sa dva prsta"),
|
||||
("Canvas Move", "Pomeranje pozadine"),
|
||||
("Pinch to Zoom", "Stisnite za zumiranje"),
|
||||
("Canvas Zoom", "Zumiranje pozadine"),
|
||||
("Reset canvas", "Resetuj pozadinu"),
|
||||
("No permission of file transfer", "Nemate pravo prenosa datoteka"),
|
||||
("Note", "Primedba"),
|
||||
("Connection", "Konekcija"),
|
||||
("Share Screen", "Podeli ekran"),
|
||||
("CLOSE", "ZATVORI"),
|
||||
("OPEN", "OTVORI"),
|
||||
("Chat", "Dopisivanje"),
|
||||
("Total", "Ukupno"),
|
||||
("items", "stavki"),
|
||||
("Selected", "Izabrano"),
|
||||
("Screen Capture", "Snimanje ekrana"),
|
||||
("Input Control", "Kontrola unosa"),
|
||||
("Audio Capture", "Snimanje zvuka"),
|
||||
("File Connection", "Spajanje preko datoteke"),
|
||||
("Screen Connection", "Podeli konekciju"),
|
||||
("Do you accept?", "Prihvatate?"),
|
||||
("Open System Setting", "Postavke otvorenog sistema"),
|
||||
("How to get Android input permission?", "Kako dobiti pristup za Android unos?"),
|
||||
("android_input_permission_tip1", "Da bi daljinski uređaj kontrolisao vaš Android uređaj preko miša ili na dodir, treba da dozvolite RustDesk-u da koristi \"Accessibility\" servis."),
|
||||
("android_input_permission_tip2", "Molimo pređite na sledeću stranicu sistemskih podešavanja, pronađite i unesite [Installed Services], uključite [RustDesk Input] servis."),
|
||||
("android_new_connection_tip", "Primljen je novi zahtev za upravljanje, koji želi da upravlja ovim vašim uređajem."),
|
||||
("android_service_will_start_tip", "Uključenje \"Screen Capture\" automatski će pokrenuti servis, dozvoljavajući drugim uređajima da zahtevaju spajanje na vaš uređaj."),
|
||||
("android_stop_service_tip", "Zatvaranje servisa automatski će zatvoriti sve uspostavljene konekcije."),
|
||||
("android_version_audio_tip", "Tekuća Android verzija ne podržava audio snimanje, molimo nadogradite na Android 10 ili veći."),
|
||||
("android_start_service_tip", "Kliknite [Start Service] ili OPEN [Screen Capture] dozvolu da pokrenete servis deljenja ekrana."),
|
||||
("Account", "Nalog"),
|
||||
("Overwrite", "Prepiši preko"),
|
||||
("This file exists, skip or overwrite this file?", "Ova datoteka postoji, preskoči ili prepiši preko?"),
|
||||
("Quit", "Izlaz"),
|
||||
("doc_mac_permission", "https://rustdesk.com/docs/en/manual/mac/#enable-permissions"),
|
||||
("Help", "Pomoć"),
|
||||
("Failed", "Greška"),
|
||||
("Succeeded", "Uspešno"),
|
||||
("Someone turns on privacy mode, exit", "Neko je uključio mod privatnosti, izlaz."),
|
||||
("Unsupported", "Nepodržano"),
|
||||
("Peer denied", "Klijent zabranjen"),
|
||||
("Please install plugins", "Molimo instalirajte dodatke"),
|
||||
("Peer exit", "Klijent izašao"),
|
||||
("Failed to turn off", "Greška kod isključenja"),
|
||||
("Turned off", "Isključeno"),
|
||||
("In privacy mode", "U modu privatnosti"),
|
||||
("Out privacy mode", "Van moda privatnosti"),
|
||||
("Language", "Jezik"),
|
||||
("Keep RustDesk background service", "Zadrži RustDesk kao pozadinski servis"),
|
||||
("Ignore Battery Optimizations", "Zanemari optimizacije baterije"),
|
||||
("android_open_battery_optimizations_tip", "Ako želite da onemogućite ovu funkciju, molimo idite na sledeću stranicu za podešavanje RustDesk aplikacije, pronađite i uđite u [Battery], isključite [Unrestricted]"),
|
||||
("Connection not allowed", "Konekcija nije dozvoljena"),
|
||||
("Legacy mode", "Zastareli mod"),
|
||||
("Map mode", "Mod mapiranja"),
|
||||
("Translate mode", "Mod prevođenja"),
|
||||
("Use permanent password", "Koristi trajnu lozinku"),
|
||||
("Use both passwords", "Koristi obe lozinke"),
|
||||
("Set permanent password", "Postavi trajnu lozinku"),
|
||||
("Enable Remote Restart", "Omogući daljinsko restartovanje"),
|
||||
("Allow remote restart", "Dozvoli daljinsko restartovanje"),
|
||||
("Restart Remote Device", "Restartuj daljinski uređaj"),
|
||||
("Are you sure you want to restart", "Da li ste sigurni da želite restart"),
|
||||
("Restarting Remote Device", "Restartovanje daljinskog uređaja"),
|
||||
("remote_restarting_tip", "Udaljeni uređaj se restartuje, molimo zatvorite ovu poruku i ponovo se kasnije povežite trajnom šifrom"),
|
||||
("Copied", "Kopirano"),
|
||||
("Exit Fullscreen", "Napusti mod celog ekrana"),
|
||||
("Fullscreen", "Mod celog ekrana"),
|
||||
("Mobile Actions", "Mobilne akcije"),
|
||||
("Select Monitor", "Izbor monitora"),
|
||||
("Control Actions", "Upravljačke akcije"),
|
||||
("Display Settings", "Postavke prikaza"),
|
||||
("Ratio", "Odnos"),
|
||||
("Image Quality", "Kvalitet slike"),
|
||||
("Scroll Style", "Stil skrolovanja"),
|
||||
("Show Menubar", "Prikaži meni"),
|
||||
("Hide Menubar", "Sakrij meni"),
|
||||
("Direct Connection", "Direktna konekcija"),
|
||||
("Relay Connection", "Posredna konekcija"),
|
||||
("Secure Connection", "Bezbedna konekcija"),
|
||||
("Insecure Connection", "Nebezbedna konekcija"),
|
||||
("Scale original", "Skaliraj original"),
|
||||
("Scale adaptive", "Adaptivno skaliranje"),
|
||||
("General", "Uopšteno"),
|
||||
("Security", "Bezbednost"),
|
||||
("Theme", "Tema"),
|
||||
("Dark Theme", "Tamna tema"),
|
||||
("Dark", "Tamno"),
|
||||
("Light", "Svetlo"),
|
||||
("Follow System", "Prema sistemu"),
|
||||
("Enable hardware codec", "Omogući hardverski kodek"),
|
||||
("Unlock Security Settings", "Otključaj postavke bezbednosti"),
|
||||
("Enable Audio", "Dozvoli zvuk"),
|
||||
("Unlock Network Settings", "Otključaj postavke mreže"),
|
||||
("Server", "Server"),
|
||||
("Direct IP Access", "Direktan IP pristup"),
|
||||
("Proxy", "Proksi"),
|
||||
("Apply", "Primeni"),
|
||||
("Disconnect all devices?", "Otkači sve uređaju?"),
|
||||
("Clear", "Obriši"),
|
||||
("Audio Input Device", "Uređaj za ulaz zvuka"),
|
||||
("Deny remote access", "Zabrani daljinski pristup"),
|
||||
("Use IP Whitelisting", "Koristi listu pouzdanih IP"),
|
||||
("Network", "Mreža"),
|
||||
("Enable RDP", "Dozvoli RDP"),
|
||||
("Pin menubar", "Zakači meni"),
|
||||
("Unpin menubar", "Otkači meni"),
|
||||
("Recording", "Snimanje"),
|
||||
("Directory", "Direktorijum"),
|
||||
("Automatically record incoming sessions", "Automatski snimaj dolazne sesije"),
|
||||
("Change", "Promeni"),
|
||||
("Start session recording", "Započni snimanje sesije"),
|
||||
("Stop session recording", "Zaustavi snimanje sesije"),
|
||||
("Enable Recording Session", "Omogući snimanje sesije"),
|
||||
("Allow recording session", "Dozvoli snimanje sesije"),
|
||||
("Enable LAN Discovery", "Omogući LAN otkrivanje"),
|
||||
("Deny LAN Discovery", "Zabrani LAN otkrivanje"),
|
||||
("Write a message", "Napiši poruku"),
|
||||
("Prompt", "Prompt"),
|
||||
("Please wait for confirmation of UAC...", "Molimo sačekajte UAC potvrdu..."),
|
||||
("elevated_foreground_window_tip", "Tekući prozor udaljene radne površine zahteva veću privilegiju za rad, tako da trenutno nije moguće koristiti miša i tastaturu. Možete zahtevati od udaljenog korisnika da minimizira aktivni prozor, ili kliknuti na taster za podizanje privilegija u prozoru za rad sa konekcijom. Da biste prevazišli ovaj problem, preporučljivo je da instalirate softver na udaljeni uređaj."),
|
||||
("Disconnected", "Odspojeno"),
|
||||
("Other", "Ostalo"),
|
||||
("Confirm before closing multiple tabs", "Potvrda pre zatvaranja više kartica"),
|
||||
("Keyboard Settings", "Postavke tastature"),
|
||||
("Full Access", "Pun pristup"),
|
||||
("Screen Share", "Deljenje ekrana"),
|
||||
("Wayland requires Ubuntu 21.04 or higher version.", "Wayland zahteva Ubuntu 21.04 ili veću verziju"),
|
||||
("Wayland requires higher version of linux distro. Please try X11 desktop or change your OS.", "Wayland zahteva veću verziju Linux distribucije. Molimo pokušajte X11 ili promenite OS."),
|
||||
("JumpLink", "Vidi"),
|
||||
("Please Select the screen to be shared(Operate on the peer side).", "Molimo izaberite ekran koji će biti podeljen (Za rad na klijent strani)"),
|
||||
("Show RustDesk", "Prikazi RustDesk"),
|
||||
("This PC", "Ovaj PC"),
|
||||
("or", "ili"),
|
||||
("Continue with", "Nastavi sa"),
|
||||
("Elevate", "Izdigni"),
|
||||
("Zoom cursor", "Zumiraj kursor"),
|
||||
("Accept sessions via password", "Prihvati sesije preko lozinke"),
|
||||
("Accept sessions via click", "Prihvati sesije preko klika"),
|
||||
("Accept sessions via both", "Prihvati sesije preko oboje"),
|
||||
("Please wait for the remote side to accept your session request...", "Molimo sačekajte da udaljena strana prihvati vaš zahtev za sesijom..."),
|
||||
("One-time Password", "Jednokratna lozinka"),
|
||||
("Use one-time password", "Koristi jednokratnu lozinku"),
|
||||
("One-time password length", "Dužina jednokratne lozinke"),
|
||||
("Request access to your device", "Zahtev za pristup vašem uređaju"),
|
||||
("Hide connection management window", "Sakrij prozor za uređivanje konekcije"),
|
||||
("hide_cm_tip", "Skrivanje dozvoljeno samo prihvatanjem sesije preko lozinke i korišćenjem trajne lozinke"),
|
||||
("wayland_experiment_tip", "Wayland eksperiment savet"),
|
||||
("Right click to select tabs", "Desni klik za izbor kartica"),
|
||||
("Skipped", ""),
|
||||
("Add to Address Book", "Dodaj u adresar"),
|
||||
("Group", "Grupa"),
|
||||
("Search", "Pretraga"),
|
||||
("Closed manually by the web console", ""),
|
||||
("Local keyboard type", ""),
|
||||
("Select local keyboard type", ""),
|
||||
("software_render_tip", ""),
|
||||
("Always use software rendering", ""),
|
||||
("config_input", ""),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
@@ -39,6 +39,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Change ID", "Byt ID"),
|
||||
("Website", "Hemsida"),
|
||||
("About", "Om"),
|
||||
("Slogan_tip", ""),
|
||||
("Privacy Statement", ""),
|
||||
("Mute", "Tyst"),
|
||||
("Audio Input", "Ljud input"),
|
||||
("Enhancements", "Förbättringar"),
|
||||
@@ -208,6 +210,11 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Always connect via relay", "Anslut alltid via relay"),
|
||||
("whitelist_tip", "Bara vitlistade IPs kan koppla upp till mig"),
|
||||
("Login", "Logga in"),
|
||||
("Verify", ""),
|
||||
("Remember me", ""),
|
||||
("Trust this device", ""),
|
||||
("Verification code", ""),
|
||||
("verification_tip", ""),
|
||||
("Logout", "Logga ut"),
|
||||
("Tags", "Taggar"),
|
||||
("Search ID", "Sök ID"),
|
||||
@@ -332,7 +339,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Scale adaptive", "Skala adaptivt"),
|
||||
("General", "Generellt"),
|
||||
("Security", "Säkerhet"),
|
||||
("Account", "Konto"),
|
||||
("Theme", "Tema"),
|
||||
("Dark Theme", "Mörkt tema"),
|
||||
("Dark", "Mörk"),
|
||||
@@ -345,7 +351,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Server", "Server"),
|
||||
("Direct IP Access", "Direkt IP åtkomst"),
|
||||
("Proxy", "Proxy"),
|
||||
("Port", "Port"),
|
||||
("Apply", "Tillämpa"),
|
||||
("Disconnect all devices?", "Koppla ifrån alla enheter?"),
|
||||
("Clear", "Töm"),
|
||||
@@ -374,7 +379,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Other", "Övrigt"),
|
||||
("Confirm before closing multiple tabs", "Bekräfta innan du stänger flera flikar"),
|
||||
("Keyboard Settings", "Tangentbordsinställningar"),
|
||||
("Custom", "Anpassat"),
|
||||
("Full Access", "Full tillgång"),
|
||||
("Screen Share", "Skärmdelning"),
|
||||
("Wayland requires Ubuntu 21.04 or higher version.", "Wayland kräver Ubuntu 21.04 eller högre."),
|
||||
@@ -399,6 +403,15 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("hide_cm_tip", "Tillåt att gömma endast om accepterande sessioner med lösenord och permanenta lösenord"),
|
||||
("wayland_experiment_tip", ""),
|
||||
("Right click to select tabs", ""),
|
||||
("Skipped", ""),
|
||||
("Add to Address Book", ""),
|
||||
("Group", ""),
|
||||
("Search", ""),
|
||||
("Closed manually by the web console", ""),
|
||||
("Local keyboard type", ""),
|
||||
("Select local keyboard type", ""),
|
||||
("software_render_tip", ""),
|
||||
("Always use software rendering", ""),
|
||||
("config_input", ""),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
||||
@@ -39,6 +39,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Change ID", ""),
|
||||
("Website", ""),
|
||||
("About", ""),
|
||||
("Slogan_tip", ""),
|
||||
("Privacy Statement", ""),
|
||||
("Mute", ""),
|
||||
("Audio Input", ""),
|
||||
("Enhancements", ""),
|
||||
@@ -208,6 +210,11 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Always connect via relay", ""),
|
||||
("whitelist_tip", ""),
|
||||
("Login", ""),
|
||||
("Verify", ""),
|
||||
("Remember me", ""),
|
||||
("Trust this device", ""),
|
||||
("Verification code", ""),
|
||||
("verification_tip", ""),
|
||||
("Logout", ""),
|
||||
("Tags", ""),
|
||||
("Search ID", ""),
|
||||
@@ -332,7 +339,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Scale adaptive", ""),
|
||||
("General", ""),
|
||||
("Security", ""),
|
||||
("Account", ""),
|
||||
("Theme", ""),
|
||||
("Dark Theme", ""),
|
||||
("Dark", ""),
|
||||
@@ -345,7 +351,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Server", ""),
|
||||
("Direct IP Access", ""),
|
||||
("Proxy", ""),
|
||||
("Port", ""),
|
||||
("Apply", ""),
|
||||
("Disconnect all devices?", ""),
|
||||
("Clear", ""),
|
||||
@@ -374,7 +379,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Other", ""),
|
||||
("Confirm before closing multiple tabs", ""),
|
||||
("Keyboard Settings", ""),
|
||||
("Custom", ""),
|
||||
("Full Access", ""),
|
||||
("Screen Share", ""),
|
||||
("Wayland requires Ubuntu 21.04 or higher version.", ""),
|
||||
@@ -399,6 +403,15 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("hide_cm_tip", ""),
|
||||
("wayland_experiment_tip", ""),
|
||||
("Right click to select tabs", ""),
|
||||
("Skipped", ""),
|
||||
("Add to Address Book", ""),
|
||||
("Group", ""),
|
||||
("Search", ""),
|
||||
("Closed manually by the web console", ""),
|
||||
("Local keyboard type", ""),
|
||||
("Select local keyboard type", ""),
|
||||
("software_render_tip", ""),
|
||||
("Always use software rendering", ""),
|
||||
("config_input", ""),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
||||
417
src/lang/th.rs
Normal file
417
src/lang/th.rs
Normal file
@@ -0,0 +1,417 @@
|
||||
lazy_static::lazy_static! {
|
||||
pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
[
|
||||
("Status", "สถานะ"),
|
||||
("Your Desktop", "หน้าจอของคุณ"),
|
||||
("desk_tip", "คุณสามารถเข้าถึงเดสก์ท็อปของคุณได้ด้วย ID และรหัสผ่านต่อไปนี้"),
|
||||
("Password", "รหัสผ่าน"),
|
||||
("Ready", "พร้อม"),
|
||||
("Established", "เชื่อมต่อแล้ว"),
|
||||
("connecting_status", "กำลังเชื่อมต่อไปยังเครือข่าย RustDesk..."),
|
||||
("Enable Service", "เปิดใช้การงานเซอร์วิส"),
|
||||
("Start Service", "เริ่มต้นใช้งานเซอร์วิส"),
|
||||
("Service is running", "เซอร์วิสกำลังทำงาน"),
|
||||
("Service is not running", "เซอร์วิสไม่ทำงาน"),
|
||||
("not_ready_status", "ไม่พร้อมใช้งาน กรุณาตรวจสอบการเชื่อมต่ออินเทอร์เน็ตของคุณ"),
|
||||
("Control Remote Desktop", "การควบคุมเดสก์ท็อปปลายทาง"),
|
||||
("Transfer File", "การถ่ายโอนไฟล์"),
|
||||
("Connect", "เชื่อมต่อ"),
|
||||
("Recent Sessions", "เซสชันล่าสุด"),
|
||||
("Address Book", "สมุดรายชื่อ"),
|
||||
("Confirmation", "การยืนยัน"),
|
||||
("TCP Tunneling", "อุโมงค์การเชื่อมต่อ TCP"),
|
||||
("Remove", "ลบ"),
|
||||
("Refresh random password", "รีเฟรชรหัสผ่านใหม่แบบสุ่ม"),
|
||||
("Set your own password", "ตั้งรหัสผ่านของคุณเอง"),
|
||||
("Enable Keyboard/Mouse", "เปิดการใช้งาน คีย์บอร์ด/เมาส์"),
|
||||
("Enable Clipboard", "เปิดการใช้งาน คลิปบอร์ด"),
|
||||
("Enable File Transfer", "เปิดการใช้งาน การถ่ายโอนไฟล์"),
|
||||
("Enable TCP Tunneling", "เปิดการใช้งาน อุโมงค์การเชื่อมต่อ TCP"),
|
||||
("IP Whitelisting", "IP ไวท์ลิสต์"),
|
||||
("ID/Relay Server", "เซิร์ฟเวอร์ ID/Relay"),
|
||||
("Import Server Config", "นำเข้าการตั้งค่าเซิร์ฟเวอร์"),
|
||||
("Export Server Config", "ส่งออกการตั้งค่าเซิร์ฟเวอร์"),
|
||||
("Import server configuration successfully", "นำเข้าการตั้งค่าเซิร์ฟเวอร์เสร็จสมบูรณ์"),
|
||||
("Export server configuration successfully", "ส่งออกการตั้งค่าเซิร์ฟเวอร์เสร็จสมบูรณ์"),
|
||||
("Invalid server configuration", "การตั้งค่าของเซิร์ฟเวอร์ไม่ถูกต้อง"),
|
||||
("Clipboard is empty", "คลิปบอร์ดว่างเปล่า"),
|
||||
("Stop service", "หยุดการใช้งานเซอร์วิส"),
|
||||
("Change ID", "เปลี่ยน ID"),
|
||||
("Website", "เว็บไซต์"),
|
||||
("About", "เกี่ยวกับ"),
|
||||
("Slogan_tip", "ทำด้วยใจ ในโลกใบนี้ที่ยุ่งเหยิง!"),
|
||||
("Privacy Statement", "คำแถลงเกี่ยวกับความเป็นส่วนตัว"),
|
||||
("Mute", "ปิดเสียง"),
|
||||
("Audio Input", "ออดิโออินพุท"),
|
||||
("Enhancements", "การปรับปรุง"),
|
||||
("Hardware Codec", "ฮาร์ดแวร์ codec"),
|
||||
("Adaptive Bitrate", "บิทเรทผันแปร"),
|
||||
("ID Server", "เซิร์ฟเวอร์ ID"),
|
||||
("Relay Server", "เซิร์ฟเวอร์ Relay"),
|
||||
("API Server", "เซิร์ฟเวอร์ API"),
|
||||
("invalid_http", "ต้องขึ้นต้นด้วย http:// หรือ https:// เท่านั้น"),
|
||||
("Invalid IP", "IP ไม่ถูกต้อง"),
|
||||
("id_change_tip", "อนุญาตเฉพาะตัวอักษร a-z A-Z 0-9 และ _ (ขีดล่าง) เท่านั้น โดยตัวอักษรขึ้นต้นจะต้องเป็น a-z หรือไม่ก็ A-Z และมีความยาวระหว่าง 6 ถึง 16 ตัวอักษร"),
|
||||
("Invalid format", "รูปแบบไม่ถูกต้อง"),
|
||||
("server_not_support", "ยังไม่รองรับโดยเซิร์ฟเวอร์"),
|
||||
("Not available", "ไม่พร้อมใช้งาน"),
|
||||
("Too frequent", "ดำเนินการถี่เกินไป"),
|
||||
("Cancel", "ยกเลิก"),
|
||||
("Skip", "ข้าม"),
|
||||
("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", "กรุณาลองใหม่อีกครั้งใน 1 นาที"),
|
||||
("Login Error", "การเข้าสู่ระบบผิดพลาด"),
|
||||
("Successful", "สำเร็จ"),
|
||||
("Connected, waiting for image...", "เชื่อมต่อสำเร็จ กำลังรับข้อมูลภาพ..."),
|
||||
("Name", "ชื่อ"),
|
||||
("Type", "ประเภท"),
|
||||
("Modified", "แก้ไขล่าสุด"),
|
||||
("Size", "ขนาด"),
|
||||
("Show Hidden Files", "แสดงไฟล์ที่ถูกซ่อน"),
|
||||
("Receive", "รับ"),
|
||||
("Send", "ส่ง"),
|
||||
("Refresh File", "รีเฟรชไฟล์"),
|
||||
("Local", "ต้นทาง"),
|
||||
("Remote", "ปลายทาง"),
|
||||
("Remote Computer", "คอมพิวเตอร์ปลายทาง"),
|
||||
("Local Computer", "คอมพิวเตอร์ต้นทาง"),
|
||||
("Confirm Delete", "ยืนยันการลบ"),
|
||||
("Delete", "ลบ"),
|
||||
("Properties", "ข้อมูล"),
|
||||
("Multi Select", "เลือกหลายรายการ"),
|
||||
("Select All", "เลือกทั้งหมด"),
|
||||
("Unselect All", "ยกเลิกการเลือกทั้งหมด"),
|
||||
("Empty Directory", "ไดเรกทอรีว่างเปล่า"),
|
||||
("Not an empty directory", "ไม่ใช่ไดเรกทอรีว่างเปล่า"),
|
||||
("Are you sure you want to delete this file?", "คุณแน่ใจหรือไม่ที่จะลบไฟล์นี้?"),
|
||||
("Are you sure you want to delete this empty directory?", "คุณแน่ใจหรือไม่ที่จะลบไดเรอทอรีว่างเปล่านี้?"),
|
||||
("Are you sure you want to delete the file of this directory?", "คุณแน่ใจหรือไม่ที่จะลบไฟล์ของไดเรกทอรีนี้?"),
|
||||
("Do this for all conflicts", "ดำเนินการแบบเดียวกันสำหรับรายการทั้งหมด"),
|
||||
("This is irreversible!", "การดำเนินการนี้ไม่สามารถย้อนกลับได้!"),
|
||||
("Deleting", "กำลังลบ"),
|
||||
("files", "ไฟล์"),
|
||||
("Waiting", "กำลังรอ"),
|
||||
("Finished", "เสร็จแล้ว"),
|
||||
("Speed", "ความเร็ว"),
|
||||
("Custom Image Quality", "คุณภาพของภาพแบบกำหนดเอง"),
|
||||
("Privacy mode", "โหมดความเป็นส่วนตัว"),
|
||||
("Block user input", "บล็อคอินพุทจากผู้ใช้งาน"),
|
||||
("Unblock user input", "ยกเลิกการบล็อคอินพุทจากผู้ใช้งาน"),
|
||||
("Adjust Window", "ปรับขนาดหน้าต่าง"),
|
||||
("Original", "ต้นฉบับ"),
|
||||
("Shrink", "ย่อ"),
|
||||
("Stretch", "ยืด"),
|
||||
("Scrollbar", "แถบเลื่อน"),
|
||||
("ScrollAuto", "เลื่อนอัตโนมัติ"),
|
||||
("Good image quality", "ภาพคุณภาพดี"),
|
||||
("Balanced", "สมดุล"),
|
||||
("Optimize reaction time", "เน้นการตอบสนอง"),
|
||||
("Custom", "กำหนดเอง"),
|
||||
("Show remote cursor", "แสดงเคอร์เซอร์ปลายทาง"),
|
||||
("Show quality monitor", "แสดงคุณภาพหน้าจอ"),
|
||||
("Disable clipboard", "ปิดการใช้งานคลิปบอร์ด"),
|
||||
("Lock after session end", "ล็อคหลังจากจบเซสชัน"),
|
||||
("Insert", "แทรก"),
|
||||
("Insert Lock", "แทรกล็อค"),
|
||||
("Refresh", "รีเฟรช"),
|
||||
("ID does not exist", "ไม่พอข้อมูล ID"),
|
||||
("Failed to connect to rendezvous server", "การเชื่อมต่อไปยังเซิร์ฟเวอร์นัดพบล้มเหลว"),
|
||||
("Please try later", "กรุณาลองใหม่ในภายหลัง"),
|
||||
("Remote desktop is offline", "เดสก์ท็อปปลายทางออฟไลน์"),
|
||||
("Key mismatch", "คีย์ไม่ถูกต้อง"),
|
||||
("Timeout", "หมดเวลา"),
|
||||
("Failed to connect to relay server", "การเชื่อมต่อไปยังเซิร์ฟเวอร์รีเลย์ล้มเหลว"),
|
||||
("Failed to connect via rendezvous server", "การเชื่อมต่อผ่านเซิร์ฟเวอร์นัดพบล้มเหลว"),
|
||||
("Failed to connect via relay server", "การเชื่อมต่อผ่านเซิร์ฟเวอร์รีเลย์ล้มเหลว"),
|
||||
("Failed to make direct connection to remote desktop", "การเชื่อมต่อตรงไปยังเดสก์ท็อปปลายทางล้มเหลว"),
|
||||
("Set Password", "ตั้งรหัสผ่าน"),
|
||||
("OS Password", "รหัสผ่านระบบปฏิบัติการ"),
|
||||
("install_tip", "เนื่องด้วยข้อจำกัดของการใช้งาน UAC ทำให้ RustDesk ไม่สามารถทำงานได้ปกติในฝั่งปลายทางในบางครั้ง เพื่อหลีกเลี่ยงข้อจำกัดของ UAC กรุณากดปุ่มด้านล่างเพื่อติดตั้ง RustDesk ไปยังระบบของคุณ"),
|
||||
("Click to upgrade", "คลิกเพื่ออัปเกรด"),
|
||||
("Click to download", "คลิกเพื่อดาวน์โหลด"),
|
||||
("Click to update", "คลิกเพื่ออัปเดต"),
|
||||
("Configure", "ปรับแต่งค่า"),
|
||||
("config_acc", "เพื่อที่จะควบคุมเดสก์ท็อปปลายทางของคุณ คุณจำเป็นจะต้องอนุญาตสิทธิ์ \"การเข้าถึง\" ให้แก่ RustDesk"),
|
||||
("config_screen", "เพื่อที่จะควบคุมเดสก์ท็อปปลายทางของคุณ คุณจำเป็นจะต้องอนุญาตสิทธิ์ \"การบันทึกภาพหน้าจอ\" ให้แก่ RustDesk"),
|
||||
("Installing ...", "กำลังติดตั้ง ..."),
|
||||
("Install", "ติดตั้ง"),
|
||||
("Installation", "การติดตั้ง"),
|
||||
("Installation Path", "ตำแหน่งที่ติดตั้ง"),
|
||||
("Create start menu shortcuts", "สร้างทางลัดไปยัง Start Menu"),
|
||||
("Create desktop icon", "สร้างไอคอนบนเดสก์ท็อป"),
|
||||
("agreement_tip", "ในการเริ่มต้นการติดตั้ง ถือว่าคุณได้ยอมรับข้อตกลงใบอนุญาตแล้ว"),
|
||||
("Accept and Install", "ยอมรับและติดตั้ง"),
|
||||
("End-user license agreement", "ข้อตกลงใบอนุญาตผู้ใช้งาน"),
|
||||
("Generating ...", "กำลังสร้าง ..."),
|
||||
("Your installation is lower version.", "การติดตั้งของคุณเป็นเวอร์ชั่นที่ต่ำกว่า"),
|
||||
("not_close_tcp_tip", "อย่าปิดหน้าต่างนี้ในขณะที่คุณกำลังใช้งานอุโมงค์การเชื่อมต่อ"),
|
||||
("Listening ...", "กำลังรอรับข้อมูล ..."),
|
||||
("Remote Host", "โฮสต์ปลายทาง"),
|
||||
("Remote Port", "พอร์ทปลายทาง"),
|
||||
("Action", "การดำเนินการ"),
|
||||
("Add", "เพิ่ม"),
|
||||
("Local Port", "พอร์ทต้นทาง"),
|
||||
("Local Address", "ที่อยู่ต้นทาง"),
|
||||
("Change Local Port", "เปลี่ยนพอร์ทต้นทาง"),
|
||||
("setup_server_tip", "เพื่อการเชื่อมต่อที่เร็วขึ้น กรุณาเซ็ตอัปเซิร์ฟเวอร์ของคุณเอง"),
|
||||
("Too short, at least 6 characters.", "สั้นเกินไป ต้องไม่ต่ำกว่า 6 ตัวอักษร"),
|
||||
("The confirmation is not identical.", "การยืนยันข้อมูลไม่ถูกต้อง"),
|
||||
("Permissions", "สิทธิ์การใช้งาน"),
|
||||
("Accept", "ยอมรับ"),
|
||||
("Dismiss", "ปิด"),
|
||||
("Disconnect", "ยกเลิกการเชื่อมต่อ"),
|
||||
("Allow using keyboard and mouse", "อนุญาตให้ใช้งานคีย์บอร์ดและเมาส์"),
|
||||
("Allow using clipboard", "อนุญาตให้ใช้คลิปบอร์ด"),
|
||||
("Allow hearing sound", "อนุญาตให้ได้ยินเสียง"),
|
||||
("Allow file copy and paste", "อนุญาตให้มีการคัดลอกและวางไฟล์"),
|
||||
("Connected", "เชื่อมต่อแล้ว"),
|
||||
("Direct and encrypted connection", "การเชื่อมต่อตรงที่มีการเข้ารหัส"),
|
||||
("Relayed and encrypted connection", "การเชื่อมต่อแบบรีเลย์ที่มีการเข้ารหัส"),
|
||||
("Direct and unencrypted connection", "การเชื่อมต่อตรงที่ไม่มีการเข้ารหัส"),
|
||||
("Relayed and unencrypted connection", "การเชื่อมต่อแบบรีเลย์ที่ไม่มีการเข้ารหัส"),
|
||||
("Enter Remote ID", "กรอก ID ปลายทาง"),
|
||||
("Enter your password", "กรอกรหัสผ่าน"),
|
||||
("Logging in...", "กำลังเข้าสู่ระบบ..."),
|
||||
("Enable RDP session sharing", "เปิดการใช้งานการแชร์เซสชัน RDP"),
|
||||
("Auto Login", "เข้าสู่ระบอัตโนมัติ"),
|
||||
("Enable Direct IP Access", "เปิดการใช้งาน IP ตรง"),
|
||||
("Rename", "ปลายทาง"),
|
||||
("Space", "พื้นที่ว่าง"),
|
||||
("Create Desktop Shortcut", "สร้างทางลัดบนเดสก์ท็อป"),
|
||||
("Change Path", "เปลี่ยนตำแหน่ง"),
|
||||
("Create Folder", "สร้างโฟลเดอร์"),
|
||||
("Please enter the folder name", "กรุณาใส่ชื่อโฟลเดอร์"),
|
||||
("Fix it", "แก้ไข"),
|
||||
("Warning", "คำเตือน"),
|
||||
("Login screen using Wayland is not supported", "หน้าจอการเข้าสู่ระบบโดยใช้ Wayland ยังไม่ถูกรองรับ"),
|
||||
("Reboot required", "จำเป็นต้องเริ่มต้นระบบใหม่"),
|
||||
("Unsupported display server ", "เซิร์ฟเวอร์การแสดงผลที่ไม่รองรับ"),
|
||||
("x11 expected", "ต้องใช้งาน x11"),
|
||||
("Port", "พอร์ท"),
|
||||
("Settings", "ตั้งค่า"),
|
||||
("Username", "ชื่อผู้ใช้งาน"),
|
||||
("Invalid port", "พอร์ทไม่ถูกต้อง"),
|
||||
("Closed manually by the peer", "ถูกปิดโดยอีกฝั่งการการเชื่อมต่อ"),
|
||||
("Enable remote configuration modification", "เปิดการใช้งานการแก้ไขการตั้งค่าปลายทาง"),
|
||||
("Run without install", "ใช้งานโดยไม่ต้องติดตั้ง"),
|
||||
("Always connected via relay", "เชื่อมต่อผ่านรีเลย์เสมอ"),
|
||||
("Always connect via relay", "เชื่อมต่อผ่านรีเลย์เสมอ"),
|
||||
("whitelist_tip", "อนุญาตเฉพาะการเชื่อมต่อจาก IP ที่ไวท์ลิสต์"),
|
||||
("Login", "เข้าสู่ระบบ"),
|
||||
("Verify", ""),
|
||||
("Remember me", ""),
|
||||
("Trust this device", ""),
|
||||
("Verification code", ""),
|
||||
("verification_tip", ""),
|
||||
("Logout", "ออกจากระบบ"),
|
||||
("Tags", "แท็ก"),
|
||||
("Search ID", "ค้นหา ID"),
|
||||
("Current Wayland display server is not supported", "เซิร์ฟเวอร์การแสดงผล Wayland ปัจจุบันไม่รองรับ"),
|
||||
("whitelist_sep", "คั่นโดยเครื่องหมาย comma semicolon เว้นวรรค หรือ ขึ้นบรรทัดใหม่"),
|
||||
("Add ID", "เพิ่ม ID"),
|
||||
("Add Tag", "เพิ่มแท็ก"),
|
||||
("Unselect all tags", "ยกเลิกการเลือกแท็กทั้งหมด"),
|
||||
("Network error", "ข้อผิดพลาดของเครือข่าย"),
|
||||
("Username missed", "ไม่พบข้อมูลผู้ใช้งาน"),
|
||||
("Password missed", "ไม่พบรหัสผ่าน"),
|
||||
("Wrong credentials", "ข้อมูลสำหรับเข้าสู่ระบบไม่ถูกต้อง"),
|
||||
("Edit Tag", "แก้ไขแท็ก"),
|
||||
("Unremember Password", "ยกเลิกการจดจำรหัสผ่าน"),
|
||||
("Favorites", "รายการโปรด"),
|
||||
("Add to Favorites", "เพิ่มไปยังรายการโปรด"),
|
||||
("Remove from Favorites", "ลบออกจากรายการโปรด"),
|
||||
("Empty", "ว่างเปล่า"),
|
||||
("Invalid folder name", "ชื่อโฟลเดอร์ไม่ถูกต้อง"),
|
||||
("Socks5 Proxy", "พรอกซี Socks5"),
|
||||
("Hostname", "ชื่อโฮสต์"),
|
||||
("Discovered", "ค้นพบ"),
|
||||
("install_daemon_tip", "หากต้องการใช้งานขณะระบบเริ่มต้น คุณจำเป็นจะต้องติดตั้งเซอร์วิส"),
|
||||
("Remote ID", "ID ปลายทาง"),
|
||||
("Paste", "วาง"),
|
||||
("Paste here?", "วางที่นี่หรือไม่?"),
|
||||
("Are you sure to close the connection?", "คุณแน่ใจหรือไม่ที่จะปิดการเชื่อมต่อ?"),
|
||||
("Download new version", "ดาวน์โหลดเวอร์ชั่นใหม่"),
|
||||
("Touch mode", "โหมดการสัมผัส"),
|
||||
("Mouse mode", "โหมดการใช้เมาส์"),
|
||||
("One-Finger Tap", "แตะนิ้วเดียว"),
|
||||
("Left Mouse", "เมาส์ซ้าย"),
|
||||
("One-Long Tap", "แตะยาวหนึ่งครั้ง"),
|
||||
("Two-Finger Tap", "แตะสองนิ้ว"),
|
||||
("Right Mouse", "เมาส์ขวา"),
|
||||
("One-Finger Move", "ลากนิ้วเดียว"),
|
||||
("Double Tap & Move", "แตะเบิ้ลและลาก"),
|
||||
("Mouse Drag", "ลากเมาส์"),
|
||||
("Three-Finger vertically", "สามนิ้วแนวตั้ง"),
|
||||
("Mouse Wheel", "ลูกลิ้งเมาส์"),
|
||||
("Two-Finger Move", "ลากสองนิ้ว"),
|
||||
("Canvas Move", "ลากแคนวาส"),
|
||||
("Pinch to Zoom", "ถ่างเพื่อขยาย"),
|
||||
("Canvas Zoom", "ขยายแคนวาส"),
|
||||
("Reset canvas", "รีเซ็ตแคนวาส"),
|
||||
("No permission of file transfer", "ไม่มีสิทธิ์ในการถ่ายโอนไฟล์"),
|
||||
("Note", "บันทึกข้อความ"),
|
||||
("Connection", "การเชื่อมต่อ"),
|
||||
("Share Screen", "แชร์หน้าจอ"),
|
||||
("CLOSE", "ปิด"),
|
||||
("OPEN", "เปิด"),
|
||||
("Chat", "แชท"),
|
||||
("Total", "รวม"),
|
||||
("items", "รายการ"),
|
||||
("Selected", "ถูกเลือก"),
|
||||
("Screen Capture", "แคปเจอร์หน้าจอ"),
|
||||
("Input Control", "ควบคุมอินพุท"),
|
||||
("Audio Capture", "แคปเจอร์เสียง"),
|
||||
("File Connection", "การเชื่อมต่อไฟล์"),
|
||||
("Screen Connection", "การเชื่อมต่อหน้าจอ"),
|
||||
("Do you accept?", "ยอมรับหรือไม่?"),
|
||||
("Open System Setting", "เปิดการตั้งค่าระบบ"),
|
||||
("How to get Android input permission?", "เปิดสิทธิ์การใช้งานอินพุทของแอนดรอยด์ได้อย่างไร?"),
|
||||
("android_input_permission_tip1", "ในการที่จะอนุญาตให้เครื่องปลายทางควบคุมอุปกรณ์แอนดรอยด์ของคุณโดยใช้เมาส์หรือการสัมผัส คุณจำเป็นจะต้องอนุญาตสิทธิ์ \"การเข้าถึง\" ให้แก่เซอร์วิสของ RustDesk"),
|
||||
("android_input_permission_tip2", "กรุณาไปยังหน้าตั้งค่าถัดไป ค้นหาและเข้าไปยัง [เซอร์วิสที่ถูกติดตั้ง] และเปิดการใช้งานเซอร์วิส [อินพุท RustDesk]"),
|
||||
("android_new_connection_tip", "ได้รับคำขอควบคุมใหม่ที่ต้องการควบคุมอุปกรณ์ของคุณ"),
|
||||
("android_service_will_start_tip", "การเปิดการใช้งาน \"การบันทึกหน้าจอ\" จะเป็นการเริ่มต้นการทำงานของเซอร์วิสโดยอัตโนมัติ ที่จะอนุญาตให้อุปกรณ์อื่นๆ ส่งคำขอเข้าถึงมายังอุปกรณ์ของคุณได้"),
|
||||
("android_stop_service_tip", "การปิดการใช้งานเซอร์วิสจะปิดการเชื่อมต่อทั้งหมดโดยอัตโนมัติ"),
|
||||
("android_version_audio_tip", "เวอร์ชั่นแอนดรอยด์ปัจจุบันของคุณไม่รองรับการบันทึกข้อมูลเสียง กรุณาอัปเกรดเป็นแอนดรอยด์เวอร์ชั่น 10 หรือสูงกว่า"),
|
||||
("android_start_service_tip", "แตะ [เริ่มต้นใช้งานเซอร์วิส] หรือเปิดสิทธิ์ [การบันทึกหน้าจอ] เพื่อเริ่มเซอร์วิสการแชร์หน้าจอ"),
|
||||
("Account", "บัญชี"),
|
||||
("Overwrite", "เขียนทับ"),
|
||||
("This file exists, skip or overwrite this file?", "พบไฟล์ที่มีอยู่แล้ว ต้องการเขียนทับหรือไม่?"),
|
||||
("Quit", "ออก"),
|
||||
("doc_mac_permission", "https://rustdesk.com/docs/en/manual/mac/#enable-permissions"),
|
||||
("Help", "ช่วยเหลือ"),
|
||||
("Failed", "ล้มเหลว"),
|
||||
("Succeeded", "สำเร็จ"),
|
||||
("Someone turns on privacy mode, exit", "มีใครบางคนเปิดใช้งานโหมดความเป็นส่วนตัว กำลังออก"),
|
||||
("Unsupported", "ไม่รองรับ"),
|
||||
("Peer denied", "ถูกปฏิเสธโดยอีกฝั่ง"),
|
||||
("Please install plugins", "กรุณาติดตั้งปลั๊กอิน"),
|
||||
("Peer exit", "อีกฝั่งออก"),
|
||||
("Failed to turn off", "การปิดล้มเหลว"),
|
||||
("Turned off", "ปิด"),
|
||||
("In privacy mode", "อยู่ในโหมดความเป็นส่วนตัว"),
|
||||
("Out privacy mode", "อยู่นอกโหมดความเป็นส่วนตัว"),
|
||||
("Language", "ภาษา"),
|
||||
("Keep RustDesk background service", "คงสถานะการทำงานเบื้องหลังของเซอร์วิส RustDesk"),
|
||||
("Ignore Battery Optimizations", "เพิกเฉยการตั้งค่าการใช้งาน Battery Optimization"),
|
||||
("android_open_battery_optimizations_tip", "หากคุณต้องการปิดการใช้งานฟีเจอร์นี้ กรุณาไปยังหน้าตั้งค่าในแอปพลิเคชัน RustDesk ค้นหาหัวข้อ [Battery] และยกเลิกการเลือกรายการ [Unrestricted]"),
|
||||
("Connection not allowed", "การเชื่อมต่อไม่อนุญาต"),
|
||||
("Legacy mode", ""),
|
||||
("Map mode", ""),
|
||||
("Translate mode", ""),
|
||||
("Use permanent password", "ใช้รหัสผ่านถาวร"),
|
||||
("Use both passwords", "ใช้รหัสผ่านทั้งสองแบบ"),
|
||||
("Set permanent password", "ตั้งค่ารหัสผ่านถาวร"),
|
||||
("Enable Remote Restart", "เปิดการใช้งานการรีสตาร์ทระบบทางไกล"),
|
||||
("Allow remote restart", "อนุญาตการรีสตาร์ทระบบทางไกล"),
|
||||
("Restart Remote Device", "รีสตาร์ทอุปกรณ์ปลายทาง"),
|
||||
("Are you sure you want to restart", "คุณแน่ใจหรือไม่ที่จะรีสตาร์ท"),
|
||||
("Restarting Remote Device", "กำลังรีสตาร์ทระบบปลายทาง"),
|
||||
("remote_restarting_tip", "ระบบปลายทางกำลังรีสตาร์ท กรุณาปิดกล่องข้อความนี้และดำเนินการเขื่อมต่อใหม่อีกครั้งด้วยรหัสผ่านถาวรหลังจากผ่านไปซักครู่"),
|
||||
("Copied", "คัดลอกแล้ว"),
|
||||
("Exit Fullscreen", "ออกจากเต็มหน้าจอ"),
|
||||
("Fullscreen", "เต็มหน้าจอ"),
|
||||
("Mobile Actions", "การดำเนินการบนมือถือ"),
|
||||
("Select Monitor", "เลือกหน้าจอ"),
|
||||
("Control Actions", "การดำเนินการควบคุม"),
|
||||
("Display Settings", "การตั้งค่าแสดงผล"),
|
||||
("Ratio", "อัตราส่วน"),
|
||||
("Image Quality", "คุณภาพภาพ"),
|
||||
("Scroll Style", "ลักษณะการเลื่อน"),
|
||||
("Show Menubar", "แสดงแถบเมนู"),
|
||||
("Hide Menubar", "ซ่อนแถบเมนู"),
|
||||
("Direct Connection", "การเชื่อมต่อตรง"),
|
||||
("Relay Connection", "การเชื่อมต่อแบบรีเลย์"),
|
||||
("Secure Connection", "การเชื่อมต่อที่ปลอดภัย"),
|
||||
("Insecure Connection", "การเชื่อมต่อที่ไม่ปลอดภัย"),
|
||||
("Scale original", "ขนาดเดิม"),
|
||||
("Scale adaptive", "ขนาดยืดหยุ่น"),
|
||||
("General", "ทั่วไป"),
|
||||
("Security", "ความปลอดภัย"),
|
||||
("Theme", "ธีม"),
|
||||
("Dark Theme", "ธีมมืด"),
|
||||
("Dark", "มืด"),
|
||||
("Light", "สว่าง"),
|
||||
("Follow System", "ตามระบบ"),
|
||||
("Enable hardware codec", "เปิดการใช้งานฮาร์ดแวร์ codec"),
|
||||
("Unlock Security Settings", "ปลดล็อคการตั้งค่าความปลอดภัย"),
|
||||
("Enable Audio", "เปิดการใช้งานเสียง"),
|
||||
("Unlock Network Settings", "ปลดล็อคการตั้งค่าเครือข่าย"),
|
||||
("Server", "เซิร์ฟเวอร์"),
|
||||
("Direct IP Access", "การเข้าถึง IP ตรง"),
|
||||
("Proxy", "พรอกซี"),
|
||||
("Apply", "นำไปใช้"),
|
||||
("Disconnect all devices?", "ยกเลิกการเชื่อมต่ออุปกรณ์ทั้งหมด?"),
|
||||
("Clear", "ล้างข้อมูล"),
|
||||
("Audio Input Device", "อุปกรณ์รับอินพุทข้อมูลเสียง"),
|
||||
("Deny remote access", "ปฏิเสธการเชื่อมต่อ"),
|
||||
("Use IP Whitelisting", "ใช้งาน IP ไวท์ลิสต์"),
|
||||
("Network", "เครือข่าย"),
|
||||
("Enable RDP", "เปิดการใช้งาน RDP"),
|
||||
("Pin menubar", "ปักหมุดแถบเมนู"),
|
||||
("Unpin menubar", "ยกเลิกการปักหมุดแถบเมนู"),
|
||||
("Recording", "การบันทึก"),
|
||||
("Directory", "ไดเรกทอรี่"),
|
||||
("Automatically record incoming sessions", "บันทึกเซสชันขาเข้าโดยอัตโนมัติ"),
|
||||
("Change", "เปลี่ยน"),
|
||||
("Start session recording", "เริ่มต้นการบันทึกเซสชัน"),
|
||||
("Stop session recording", "หยุดการบันทึกเซสซัน"),
|
||||
("Enable Recording Session", "เปิดใช้งานการบันทึกเซสชัน"),
|
||||
("Allow recording session", "อนุญาตการบันทึกเซสชัน"),
|
||||
("Enable LAN Discovery", "เปิดการใช้งานการค้นหาในวง LAN"),
|
||||
("Deny LAN Discovery", "ปฏิเสธการใช้งานการค้นหาในวง LAN"),
|
||||
("Write a message", "เขียนข้อความ"),
|
||||
("Prompt", ""),
|
||||
("Please wait for confirmation of UAC...", "กรุณารอการยืนยันจาก UAC..."),
|
||||
("elevated_foreground_window_tip", "หน้าต่างปัจจุบันของเครื่องปลายทางต้องการสิทธิ์การใช้งานที่สูงขึ้นสำหรับการทำงาน ดังนั้นเมาส์และคีย์บอร์ดจะไม่สามารถใช้งานได้ชั่วคราว คุณสามารถขอผู้ใช้งานปลายทางให้ย่อหน้าต่าง หรือคลิกปุ่มให้สิทธิ์การใช้งานในหน้าต่างการจัดการการเชื่อมต่อ เพื่อหลีกเลี่ยงปัญหานี้เราแนะนำให้ดำเนินการติดตั้งซอฟท์แวร์ในเครื่องปลายทาง"),
|
||||
("Disconnected", "ยกเลิกการเชื่อมต่อ"),
|
||||
("Other", "อื่นๆ"),
|
||||
("Confirm before closing multiple tabs", "ยืนยันการปิดหลายแท็บ"),
|
||||
("Keyboard Settings", "การตั้งค่าคีย์บอร์ด"),
|
||||
("Full Access", "การเข้าถึงทั้งหมด"),
|
||||
("Screen Share", "การแชร์จอ"),
|
||||
("Wayland requires Ubuntu 21.04 or higher version.", "Wayland ต้องการ Ubuntu เวอร์ชั่น 21.04 หรือสูงกว่า"),
|
||||
("Wayland requires higher version of linux distro. Please try X11 desktop or change your OS.", "Wayland ต้องการลินุกซ์เวอร์ชันที่สูงกว่านี้ กรุณาเปลี่ยนไปใช้เดสก์ท็อป X11 หรือเปลี่ยนระบบปฏิบัติการของคุณ"),
|
||||
("JumpLink", "View"),
|
||||
("Please Select the screen to be shared(Operate on the peer side).", "กรุณาเลือกหน้าจอที่ต้องการแชร์ (ใช้งานในอีกฝั่งของการเชื่อมต่อ)"),
|
||||
("Show RustDesk", "แสดง RustDesk"),
|
||||
("This PC", ""),
|
||||
("or", "หรือ"),
|
||||
("Continue with", "ทำต่อด้วย"),
|
||||
("Elevate", "ยกระดับ"),
|
||||
("Zoom cursor", "ขยายเคอร์เซอร์"),
|
||||
("Accept sessions via password", "ยอมรับการเชื่อมต่อด้วยรหัสผ่าน"),
|
||||
("Accept sessions via click", "ยอมรับการเชื่อมต่อด้วยการคลิก"),
|
||||
("Accept sessions via both", "ยอมรับการเชื่อมต่อด้วยทั้งสองวิธิ"),
|
||||
("Please wait for the remote side to accept your session request...", "กรุณารอให้อีกฝั่งยอมรับการเชื่อมต่อของคุณ..."),
|
||||
("One-time Password", "รหัสผ่านครั้งเดียว"),
|
||||
("Use one-time password", "ใช้รหัสผ่านครั้งเดียว"),
|
||||
("One-time password length", "ความยาวรหัสผ่านครั้งเดียว"),
|
||||
("Request access to your device", "คำขอการเข้าถึงอุปกรณ์ของคุณ"),
|
||||
("Hide connection management window", "ซ่อนหน้าต่างการจัดการการเชื่อมต่อ"),
|
||||
("hide_cm_tip", "อนุญาตการซ่อนก็ต่อเมื่อยอมรับการเชื่อมต่อด้วยรหัสผ่าน และต้องเป็นรหัสผ่านถาวรเท่านั้น"),
|
||||
("wayland_experiment_tip", "การสนับสนุน Wayland ยังอยู่ในขั้นตอนการทดลอง กรุณาใช้ X11 หากคุณต้องการใช้งานการเข้าถึงแบบไม่มีผู้ดูแล"),
|
||||
("Right click to select tabs", "คลิกขวาเพื่อเลือกแท็บ"),
|
||||
("Skipped", "ข้าม"),
|
||||
("Add to Address Book", "เพิ่มไปยังสมุดรายชื่อ"),
|
||||
("Group", "กลุ่ม"),
|
||||
("Search", "ค้นหา"),
|
||||
("Closed manually by the web console", "ถูกปิดโดยเว็บคอนโซล"),
|
||||
("Local keyboard type", "ประเภทคีย์บอร์ด"),
|
||||
("Select local keyboard type", "เลือกประเภทคีย์บอร์ด"),
|
||||
("software_render_tip", ""),
|
||||
("Always use software rendering", ""),
|
||||
("config_input", ""),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
@@ -39,6 +39,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Change ID", "ID Değiştir"),
|
||||
("Website", "Website"),
|
||||
("About", "Hakkında"),
|
||||
("Slogan_tip", ""),
|
||||
("Privacy Statement", ""),
|
||||
("Mute", "Sustur"),
|
||||
("Audio Input", "Ses Girişi"),
|
||||
("Enhancements", "Geliştirmeler"),
|
||||
@@ -208,6 +210,11 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Always connect via relay", "Always connect via relay"),
|
||||
("whitelist_tip", "Bu masaüstüne yalnızca yetkili IP adresleri bağlanabilir"),
|
||||
("Login", "Giriş yap"),
|
||||
("Verify", ""),
|
||||
("Remember me", ""),
|
||||
("Trust this device", ""),
|
||||
("Verification code", ""),
|
||||
("verification_tip", ""),
|
||||
("Logout", "Çıkış yap"),
|
||||
("Tags", "Etiketler"),
|
||||
("Search ID", "ID Arama"),
|
||||
@@ -332,7 +339,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Scale adaptive", "Ölçek uyarlanabilir"),
|
||||
("General", "Genel"),
|
||||
("Security", "Güvenlik"),
|
||||
("Account", "Hesap"),
|
||||
("Theme", "Tema"),
|
||||
("Dark Theme", "Koyu Tema"),
|
||||
("Dark", "Koyu"),
|
||||
@@ -345,7 +351,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Server", "Sunucu"),
|
||||
("Direct IP Access", "Direk IP Erişimi"),
|
||||
("Proxy", "Vekil"),
|
||||
("Port", "Port"),
|
||||
("Apply", "Uygula"),
|
||||
("Disconnect all devices?", "Tüm cihazların bağlantısını kes?"),
|
||||
("Clear", "Temizle"),
|
||||
@@ -374,7 +379,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Other", "Diğer"),
|
||||
("Confirm before closing multiple tabs", "Çoklu sekmeleri kapatmadan önce onayla"),
|
||||
("Keyboard Settings", "Klavye Ayarları"),
|
||||
("Custom", "Özel"),
|
||||
("Full Access", "Tam Erişim"),
|
||||
("Screen Share", "Ekran Paylaşımı"),
|
||||
("Wayland requires Ubuntu 21.04 or higher version.", "Wayland, Ubuntu 21.04 veya daha yüksek bir sürüm gerektirir."),
|
||||
@@ -399,6 +403,15 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("hide_cm_tip", ""),
|
||||
("wayland_experiment_tip", ""),
|
||||
("Right click to select tabs", ""),
|
||||
("Skipped", ""),
|
||||
("Add to Address Book", ""),
|
||||
("Group", ""),
|
||||
("Search", ""),
|
||||
("Closed manually by the web console", ""),
|
||||
("Local keyboard type", ""),
|
||||
("Select local keyboard type", ""),
|
||||
("software_render_tip", ""),
|
||||
("Always use software rendering", ""),
|
||||
("config_input", ""),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
||||
@@ -39,6 +39,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Change ID", "更改 ID"),
|
||||
("Website", "網站"),
|
||||
("About", "關於"),
|
||||
("Slogan_tip", ""),
|
||||
("Privacy Statement", ""),
|
||||
("Mute", "靜音"),
|
||||
("Audio Input", "音訊輸入"),
|
||||
("Enhancements", "增強功能"),
|
||||
@@ -208,6 +210,11 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Always connect via relay", "一律透過轉送連線"),
|
||||
("whitelist_tip", "只有白名單中的 IP 可以存取"),
|
||||
("Login", "登入"),
|
||||
("Verify", ""),
|
||||
("Remember me", ""),
|
||||
("Trust this device", ""),
|
||||
("Verification code", ""),
|
||||
("verification_tip", ""),
|
||||
("Logout", "登出"),
|
||||
("Tags", "標籤"),
|
||||
("Search ID", "搜尋 ID"),
|
||||
@@ -332,7 +339,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Scale adaptive", "適應窗口"),
|
||||
("General", "常規"),
|
||||
("Security", "安全"),
|
||||
("Account", "賬戶"),
|
||||
("Theme", "主題"),
|
||||
("Dark Theme", "暗黑主題"),
|
||||
("Dark", "黑暗"),
|
||||
@@ -345,7 +351,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Server", "服務器"),
|
||||
("Direct IP Access", "IP直接訪問"),
|
||||
("Proxy", "代理"),
|
||||
("Port", "端口"),
|
||||
("Apply", "應用"),
|
||||
("Disconnect all devices?", "斷開所有遠程連接?"),
|
||||
("Clear", "清空"),
|
||||
@@ -374,7 +379,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Other", "其他"),
|
||||
("Confirm before closing multiple tabs", "關閉多個分頁前跟我確認"),
|
||||
("Keyboard Settings", "鍵盤設置"),
|
||||
("Custom", "自定義"),
|
||||
("Full Access", "完全訪問"),
|
||||
("Screen Share", "僅共享屏幕"),
|
||||
("Wayland requires Ubuntu 21.04 or higher version.", "Wayland 需要 Ubuntu 21.04 或更高版本。"),
|
||||
@@ -399,6 +403,15 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("hide_cm_tip", "在只允許密碼連接並且只用固定密碼的情況下才允許隱藏"),
|
||||
("wayland_experiment_tip", ""),
|
||||
("Right click to select tabs", "右鍵選擇選項卡"),
|
||||
("Skipped", ""),
|
||||
("Add to Address Book", "添加到地址簿"),
|
||||
("Group", "小組"),
|
||||
("Search", "搜索"),
|
||||
("Closed manually by the web console", "被web控制台手動關閉"),
|
||||
("Local keyboard type", "本地鍵盤類型"),
|
||||
("Select local keyboard type", "請選擇本地鍵盤類型"),
|
||||
("software_render_tip", "如果你使用英偉達顯卡, 並且遠程窗口在會話建立後會立刻關閉, 那麼安裝nouveau驅動並且選擇使用軟件渲染可能會有幫助。重啟軟件後生效。"),
|
||||
("Always use software rendering", "使用軟件渲染"),
|
||||
("config_input", ""),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
||||
149
src/lang/ua.rs
149
src/lang/ua.rs
@@ -2,8 +2,8 @@ lazy_static::lazy_static! {
|
||||
pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
[
|
||||
("Status", "Статус"),
|
||||
("Your Desktop", "Ваш робочий стіл"),
|
||||
("desk_tip", "Ваш робочий стіл доступний з цим ідентифікатором і паролем"),
|
||||
("Your Desktop", "Ваша стільниця"),
|
||||
("desk_tip", "Ваша стільниця доступна з цим ідентифікатором і паролем"),
|
||||
("Password", "Пароль"),
|
||||
("Ready", "Готово"),
|
||||
("Established", "Встановлено"),
|
||||
@@ -13,7 +13,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Service is running", "Служба працює"),
|
||||
("Service is not running", "Служба не запущена"),
|
||||
("not_ready_status", "Не готово. Будь ласка, перевірте підключення"),
|
||||
("Control Remote Desktop", "Управління віддаленим робочим столом"),
|
||||
("Control Remote Desktop", "Керування віддаленою стільницею"),
|
||||
("Transfer File", "Передати файл"),
|
||||
("Connect", "Підключитися"),
|
||||
("Recent Sessions", "Останні сеанси"),
|
||||
@@ -30,7 +30,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("IP Whitelisting", "Список дозволених IP-адрес"),
|
||||
("ID/Relay Server", "ID/Сервер ретрансляції"),
|
||||
("Import Server Config", "Імпортувати конфігурацію сервера"),
|
||||
("Export Server Config", ""),
|
||||
("Export Server Config", "Експортувати конфігурацію сервера"),
|
||||
("Import server configuration successfully", "Конфігурацію сервера успішно імпортовано"),
|
||||
("Export server configuration successfully", ""),
|
||||
("Invalid server configuration", "Недійсна конфігурація сервера"),
|
||||
@@ -39,6 +39,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Change ID", "Змінити ID"),
|
||||
("Website", "Веб-сайт"),
|
||||
("About", "Про RustDesk"),
|
||||
("Slogan_tip", "Створено з душею в цьому хаотичному світі!"),
|
||||
("Privacy Statement", "Декларація про конфіденційність"),
|
||||
("Mute", "Вимкнути звук"),
|
||||
("Audio Input", "Аудіовхід"),
|
||||
("Enhancements", "Покращення"),
|
||||
@@ -89,8 +91,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Delete", "Видалити"),
|
||||
("Properties", "Властивості"),
|
||||
("Multi Select", "Багатоелементний вибір"),
|
||||
("Select All", ""),
|
||||
("Unselect All", ""),
|
||||
("Select All", "Вибрати все"),
|
||||
("Unselect All", "Скасувати вибір"),
|
||||
("Empty Directory", "Порожня папка"),
|
||||
("Not an empty directory", "Папка не порожня"),
|
||||
("Are you sure you want to delete this file?", "Ви впевнені, що хочете видалити цей файл?"),
|
||||
@@ -116,8 +118,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Good image quality", "Хороша якість зображення"),
|
||||
("Balanced", "Збалансований"),
|
||||
("Optimize reaction time", "Оптимізувати час реакції"),
|
||||
("Custom", ""),
|
||||
("Show remote cursor", "Показати віддалений курсор"),
|
||||
("Custom", "Користувацькі"),
|
||||
("Show remote cursor", "Показати віддалений вказівник"),
|
||||
("Show quality monitor", "Показати якість"),
|
||||
("Disable clipboard", "Відключити буфер обміну"),
|
||||
("Lock after session end", "Вихід з облікового запису після завершення сеансу"),
|
||||
@@ -127,13 +129,13 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("ID does not exist", "ID не існує"),
|
||||
("Failed to connect to rendezvous server", "Не вдалося підключитися до проміжного сервера"),
|
||||
("Please try later", "Будь ласка, спробуйте пізніше"),
|
||||
("Remote desktop is offline", "Віддалений робочий стіл не в мережі"),
|
||||
("Remote desktop is offline", "Віддалена стільниця не в мережі"),
|
||||
("Key mismatch", "Невідповідність ключів"),
|
||||
("Timeout", "Тайм-аут"),
|
||||
("Failed to connect to relay server", "Не вдалося підключитися до сервера ретрансляції"),
|
||||
("Failed to connect via rendezvous server", "Не вдалося підключитися через проміжний сервер"),
|
||||
("Failed to connect via relay server", "Не вдалося підключитися через сервер ретрансляції"),
|
||||
("Failed to make direct connection to remote desktop", "Не вдалося встановити пряме підключення до віддаленого робочого столу"),
|
||||
("Failed to make direct connection to remote desktop", "Не вдалося встановити пряме підключення до віддаленої стільниці"),
|
||||
("Set Password", "Встановити пароль"),
|
||||
("OS Password", "Пароль ОС"),
|
||||
("install_tip", "У деяких випадках через UAC RustDesk може працювати некоректно на віддаленому вузлі. Щоб уникнути UAC, натисніть кнопку нижче, щоб встановити RustDesk у системі"),
|
||||
@@ -141,16 +143,16 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Click to download", "Натисніть, щоб завантажити"),
|
||||
("Click to update", "Натисніть, щоб оновити"),
|
||||
("Configure", "Налаштувати"),
|
||||
("config_acc", "Щоб віддалено керувати своїм робочим столом, ви повинні надати RustDesk права \"доступу\""),
|
||||
("config_screen", "Для віддаленого доступу до робочого столу ви повинні надати RustDesk права \"знімок екрану\""),
|
||||
("config_acc", "Щоб віддалено керувати своєю стільницею, ви повинні надати RustDesk права \"доступності\""),
|
||||
("config_screen", "Для віддаленого доступу до стільниці ви повинні надати RustDesk права для \"запису екрану\""),
|
||||
("Installing ...", "Встановлюється..."),
|
||||
("Install", "Встановити"),
|
||||
("Installation", "Установка"),
|
||||
("Installation Path", "Шлях встановлення"),
|
||||
("Create start menu shortcuts", "Створити ярлики меню \"Пуск\""),
|
||||
("Create desktop icon", "Створити значок на робочому столі"),
|
||||
("Create desktop icon", "Створити значок на стільниці"),
|
||||
("agreement_tip", "Починаючи установку, ви приймаєте умови ліцензійної угоди"),
|
||||
("Accept and Install", "Прийняти і встановити"),
|
||||
("Accept and Install", "Прийняти та встановити"),
|
||||
("End-user license agreement", "Ліцензійна угода з кінцевим користувачем"),
|
||||
("Generating ...", "Генерація..."),
|
||||
("Your installation is lower version.", "Ваша установка більш ранньої версії"),
|
||||
@@ -161,8 +163,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Action", "Дія"),
|
||||
("Add", "Додати"),
|
||||
("Local Port", "Локальний порт"),
|
||||
("Local Address", ""),
|
||||
("Change Local Port", ""),
|
||||
("Local Address", "Локальна адреса"),
|
||||
("Change Local Port", "Змінити локальний порт"),
|
||||
("setup_server_tip", "Для більш швидкого підключення налаштуйте свій власний сервер підключення"),
|
||||
("Too short, at least 6 characters.", "Занадто коротко, мінімум 6 символів"),
|
||||
("The confirmation is not identical.", "Підтвердження не збігається"),
|
||||
@@ -170,15 +172,15 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Accept", "Прийняти"),
|
||||
("Dismiss", "Відхилити"),
|
||||
("Disconnect", "Відключити"),
|
||||
("Allow using keyboard and mouse", "Дозволити використання клавіатури і миші"),
|
||||
("Allow using keyboard and mouse", "Дозволити використання клавіатури та миші"),
|
||||
("Allow using clipboard", "Дозволити використання буфера обміну"),
|
||||
("Allow hearing sound", "Дозволити передачу звуку"),
|
||||
("Allow file copy and paste", "Дозволити копіювання і вставку файлів"),
|
||||
("Allow file copy and paste", "Дозволити копіювання та вставку файлів"),
|
||||
("Connected", "Підключено"),
|
||||
("Direct and encrypted connection", "Пряме і зашифроване з'єднання"),
|
||||
("Relayed and encrypted connection", "Ретрансльоване і зашифроване з'єднання"),
|
||||
("Direct and unencrypted connection", "Пряме і незашифроване з'єднання"),
|
||||
("Relayed and unencrypted connection", "Ретрансльоване і незашифроване з'єднання"),
|
||||
("Direct and encrypted connection", "Пряме та зашифроване з'єднання"),
|
||||
("Relayed and encrypted connection", "Ретрансльоване та зашифроване з'єднання"),
|
||||
("Direct and unencrypted connection", "Пряме та незашифроване з'єднання"),
|
||||
("Relayed and unencrypted connection", "Ретрансльоване та незашифроване з'єднання"),
|
||||
("Enter Remote ID", "Введіть віддалений ID"),
|
||||
("Enter your password", "Введіть пароль"),
|
||||
("Logging in...", "Вхід..."),
|
||||
@@ -187,7 +189,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Enable Direct IP Access", "Увімкнути прямий IP-доступ"),
|
||||
("Rename", "Перейменувати"),
|
||||
("Space", "Місце"),
|
||||
("Create Desktop Shortcut", "Створити ярлик на робочому столі"),
|
||||
("Create Desktop Shortcut", "Створити ярлик на стільниці"),
|
||||
("Change Path", "Змінити шлях"),
|
||||
("Create Folder", "Створити папку"),
|
||||
("Please enter the folder name", "Будь ласка, введіть ім'я папки"),
|
||||
@@ -195,7 +197,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Warning", "Попередження"),
|
||||
("Login screen using Wayland is not supported", "Вхід у систему з використанням Wayland не підтримується"),
|
||||
("Reboot required", "Потрібне перезавантаження"),
|
||||
("Unsupported display server ", ""),
|
||||
("Unsupported display server ", "Графічний сервер не підтримується"),
|
||||
("x11 expected", "Очікується X11"),
|
||||
("Port", "Порт"),
|
||||
("Settings", "Налаштування"),
|
||||
@@ -208,11 +210,16 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Always connect via relay", "Завжди підключатися через ретрансляційний сервер"),
|
||||
("whitelist_tip", "Тільки IP-адреси з білого списку можуть отримати доступ до мене"),
|
||||
("Login", "Увійти"),
|
||||
("Verify", ""),
|
||||
("Remember me", ""),
|
||||
("Trust this device", ""),
|
||||
("Verification code", ""),
|
||||
("verification_tip", ""),
|
||||
("Logout", "Вийти"),
|
||||
("Tags", "Ключові слова"),
|
||||
("Search ID", "Пошук за ID"),
|
||||
("Current Wayland display server is not supported", "Поточний сервер відображення Wayland не підтримується"),
|
||||
("whitelist_sep", "Окремо комою, крапкою з комою, пропуском або новим рядком"),
|
||||
("Current Wayland display server is not supported", "Поточний графічний сервер Wayland не підтримується"),
|
||||
("whitelist_sep", "Розділені комою, крапкою з комою, пробілом або новим рядком"),
|
||||
("Add ID", "Додати ID"),
|
||||
("Add Tag", "Додати ключове слово"),
|
||||
("Unselect all tags", "Скасувати вибір усіх тегів"),
|
||||
@@ -244,7 +251,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Two-Finger Tap", "Дотик двома пальцями"),
|
||||
("Right Mouse", "Права миша"),
|
||||
("One-Finger Move", "Рух одним пальцем"),
|
||||
("Double Tap & Move", "Подвійне натискання і переміщення"),
|
||||
("Double Tap & Move", "Подвійне натискання та переміщення"),
|
||||
("Mouse Drag", "Перетягування мишею"),
|
||||
("Three-Finger vertically", "Трьома пальцями по вертикалі"),
|
||||
("Mouse Wheel", "Коліщатко миші"),
|
||||
@@ -272,8 +279,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Open System Setting", "Відкрити налаштування системи"),
|
||||
("How to get Android input permission?", "Як отримати дозвіл на введення Android?"),
|
||||
("android_input_permission_tip1", "Щоб віддалений пристрій міг керувати вашим Android-пристроєм за допомогою миші або торкання, вам необхідно дозволити RustDesk використовувати службу \"Спеціальні можливості\"."),
|
||||
("android_input_permission_tip2", "Перейдіть на наступну сторінку системних налаштувань, знайдіть і увійдіть у [Встановлені служби], увімкніть службу [RustDesk Input]."),
|
||||
("android_new_connection_tip", "Отримано новий запит на управління вашим поточним пристроєм."),
|
||||
("android_input_permission_tip2", "Перейдіть на наступну сторінку системних налаштувань, знайдіть та увійдіть у [Встановлені служби], увімкніть службу [RustDesk Input]."),
|
||||
("android_new_connection_tip", "Отримано новий запит на керування вашим поточним пристроєм."),
|
||||
("android_service_will_start_tip", "Увімкнення захоплення екрана автоматично запускає службу, дозволяючи іншим пристроям запитувати з'єднання з цього пристрою."),
|
||||
("android_stop_service_tip", "Закриття служби автоматично закриє всі встановлені з'єднання."),
|
||||
("android_version_audio_tip", "Поточна версія Android не підтримує захоплення звуку, оновіть її до Android 10 або вище."),
|
||||
@@ -300,9 +307,9 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Ignore Battery Optimizations", "Ігнорувати оптимізацію батареї"),
|
||||
("android_open_battery_optimizations_tip", "Перейдіть на наступну сторінку налаштувань"),
|
||||
("Connection not allowed", "Підключення не дозволено"),
|
||||
("Legacy mode", ""),
|
||||
("Map mode", ""),
|
||||
("Translate mode", ""),
|
||||
("Legacy mode", "Застарілий режим"),
|
||||
("Map mode", "Режим карти"),
|
||||
("Translate mode", "Режим перекладу"),
|
||||
("Use permanent password", "Використовувати постійний пароль"),
|
||||
("Use both passwords", "Використовувати обидва паролі"),
|
||||
("Set permanent password", "Встановити постійний пароль"),
|
||||
@@ -311,13 +318,13 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Restart Remote Device", "Перезапустити віддалений пристрій"),
|
||||
("Are you sure you want to restart", "Ви впевнені, що хочете виконати перезапуск?"),
|
||||
("Restarting Remote Device", "Перезавантаження віддаленого пристрою"),
|
||||
("remote_restarting_tip", "Віддалений пристрій перезапускається. Будь ласка, закрийте це повідомлення і через деякий час перепідключіться, використовуючи постійний пароль."),
|
||||
("remote_restarting_tip", "Віддалений пристрій перезапускається. Будь ласка, закрийте це повідомлення та через деякий час перепідключіться, використовуючи постійний пароль."),
|
||||
("Copied", ""),
|
||||
("Exit Fullscreen", "Вийти з повноекранного режиму"),
|
||||
("Fullscreen", "Повноекранний"),
|
||||
("Mobile Actions", "Мобільні дії"),
|
||||
("Select Monitor", "Виберіть монітор"),
|
||||
("Control Actions", "Дії з управління"),
|
||||
("Control Actions", "Дії для керування"),
|
||||
("Display Settings", "Налаштування відображення"),
|
||||
("Ratio", "Співвідношення"),
|
||||
("Image Quality", "Якість зображення"),
|
||||
@@ -332,20 +339,18 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Scale adaptive", "Масштаб адаптивний"),
|
||||
("General", "Загальні"),
|
||||
("Security", "Безпека"),
|
||||
("Account", "Акаунт"),
|
||||
("Theme", "Тема"),
|
||||
("Dark Theme", "Темна тема"),
|
||||
("Dark", "Темна"),
|
||||
("Light", "Світла"),
|
||||
("Follow System", "Використовувати системну"),
|
||||
("Follow System", "Як у системі"),
|
||||
("Enable hardware codec", "Увімкнути апаратний кодек"),
|
||||
("Unlock Security Settings", "Розблокувати налаштування безпеки"),
|
||||
("Enable Audio", "Вімкнути аудіо"),
|
||||
("Enable Audio", "Увімкнути аудіо"),
|
||||
("Unlock Network Settings", "Розблокувати мережеві налаштування"),
|
||||
("Server", "Сервер"),
|
||||
("Direct IP Access", "Прямий IP доступ"),
|
||||
("Proxy", "Проксі"),
|
||||
("Port", "Порт"),
|
||||
("Apply", "Застосувати"),
|
||||
("Disconnect all devices?", "Відключити всі прилади?"),
|
||||
("Clear", "Очистити"),
|
||||
@@ -367,38 +372,46 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Enable LAN Discovery", "Увімкнути пошук локальної мережі"),
|
||||
("Deny LAN Discovery", "Заборонити виявлення локальної мережі"),
|
||||
("Write a message", "Написати повідомлення"),
|
||||
("Prompt", ""),
|
||||
("Please wait for confirmation of UAC...", ""),
|
||||
("elevated_foreground_window_tip", ""),
|
||||
("Disconnected", ""),
|
||||
("Other", ""),
|
||||
("Prompt", "Підказка"),
|
||||
("Please wait for confirmation of UAC...", "Будь ласка, зачекайте підтвердження UAC..."),
|
||||
("elevated_foreground_window_tip", "Поточне вікно віддаленої стільниці потребує розширених прав для роботи, тому наразі неможливо використати мишу та клавіатуру. Ви можете запропонувати віддаленому користувачу згорнути поточне вікно чи натиснути кнопку розширення прав у вікні керування з'єднаннями. Для уникнення цієї проблеми, рекомендується встановити програму на віддаленому пристрої"),
|
||||
("Disconnected", "Відключено"),
|
||||
("Other", "Інше"),
|
||||
("Confirm before closing multiple tabs", ""),
|
||||
("Keyboard Settings", ""),
|
||||
("Custom", ""),
|
||||
("Full Access", ""),
|
||||
("Screen Share", ""),
|
||||
("Keyboard Settings", "Налаштування клавіатури"),
|
||||
("Full Access", "Повний доступ"),
|
||||
("Screen Share", "Демонстрація екрану"),
|
||||
("Wayland requires Ubuntu 21.04 or higher version.", "Wayland потребує Ubuntu 21.04 або новішої версії."),
|
||||
("Wayland requires higher version of linux distro. Please try X11 desktop or change your OS.", "Для Wayland потрібна новіша версія дистрибутива Linux. Будь ласка, спробуйте робочий стіл X11 або змініть свою ОС."),
|
||||
("JumpLink", "View"),
|
||||
("Wayland requires higher version of linux distro. Please try X11 desktop or change your OS.", "Для Wayland потрібна новіша версія дистрибутива Linux. Будь ласка, спробуйте стільницю на X11 або змініть свою ОС."),
|
||||
("JumpLink", "Перегляд"),
|
||||
("Please Select the screen to be shared(Operate on the peer side).", "Будь ласка, виберіть екран, до якого потрібно надати доступ (працюйте на стороні однорангового пристрою)."),
|
||||
("Show RustDesk", ""),
|
||||
("This PC", ""),
|
||||
("or", ""),
|
||||
("Continue with", ""),
|
||||
("Elevate", ""),
|
||||
("Zoom cursor", ""),
|
||||
("Accept sessions via password", ""),
|
||||
("Accept sessions via click", ""),
|
||||
("Accept sessions via both", ""),
|
||||
("Please wait for the remote side to accept your session request...", ""),
|
||||
("One-time Password", ""),
|
||||
("Use one-time password", ""),
|
||||
("One-time password length", ""),
|
||||
("Request access to your device", ""),
|
||||
("Hide connection management window", ""),
|
||||
("hide_cm_tip", ""),
|
||||
("wayland_experiment_tip", ""),
|
||||
("Right click to select tabs", ""),
|
||||
("Add to Address Book", ""),
|
||||
("Show RustDesk", "Показати RustDesk"),
|
||||
("This PC", "Цей ПК"),
|
||||
("or", "чи"),
|
||||
("Continue with", "Продовжити з"),
|
||||
("Elevate", "Розширення прав"),
|
||||
("Zoom cursor", "Збільшити вказівник"),
|
||||
("Accept sessions via password", "Підтверджувати сеанси паролем"),
|
||||
("Accept sessions via click", "Підтверджувати сеанси натисканням"),
|
||||
("Accept sessions via both", "Підтверджувати сеанси обома способами"),
|
||||
("Please wait for the remote side to accept your session request...", "Буль ласка, зачекайте, поки віддалена сторона підтвердить запит на сеанс..."),
|
||||
("One-time Password", "Одноразовий пароль"),
|
||||
("Use one-time password", "Використати одноразовий пароль"),
|
||||
("One-time password length", "Довжина одноразового пароля"),
|
||||
("Request access to your device", "Дати запит щодо доступ до свого пристрою"),
|
||||
("Hide connection management window", "Приховати вікно керування з'єднаннями"),
|
||||
("hide_cm_tip", "Дозволено приховати лише якщо сеанс підтверджується постійним паролем"),
|
||||
("wayland_experiment_tip", "Підтримка Wayland на експериментальній стадії, будь ласка, використовуйте X11, якщо необхідний автоматичний доступ."),
|
||||
("Right click to select tabs", "Правий клік для вибору вкладки"),
|
||||
("Skipped", ""),
|
||||
("Add to Address Book", "Додати IP до Адресної книги"),
|
||||
("Group", "Група"),
|
||||
("Search", "Пошук"),
|
||||
("Closed manually by the web console", ""),
|
||||
("Local keyboard type", ""),
|
||||
("Select local keyboard type", ""),
|
||||
("software_render_tip", ""),
|
||||
("Always use software rendering", ""),
|
||||
("config_input", ""),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
||||
@@ -39,6 +39,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Change ID", "Thay đổi ID"),
|
||||
("Website", "Trang web"),
|
||||
("About", "About"),
|
||||
("Slogan_tip", ""),
|
||||
("Privacy Statement", ""),
|
||||
("Mute", "Tắt tiếng"),
|
||||
("Audio Input", "Đầu vào âm thanh"),
|
||||
("Enhancements", "Các tiện itchs"),
|
||||
@@ -208,6 +210,11 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Always connect via relay", "Luôn kết nối qua relay"),
|
||||
("whitelist_tip", "Chỉ có những IP đựoc cho phép mới có thể truy cập"),
|
||||
("Login", "Đăng nhập"),
|
||||
("Verify", ""),
|
||||
("Remember me", ""),
|
||||
("Trust this device", ""),
|
||||
("Verification code", ""),
|
||||
("verification_tip", ""),
|
||||
("Logout", "Đăng xuất"),
|
||||
("Tags", "Tags"),
|
||||
("Search ID", "Tìm ID"),
|
||||
@@ -332,7 +339,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Scale adaptive", "Quy mô thích ứng"),
|
||||
("General", ""),
|
||||
("Security", ""),
|
||||
("Account", ""),
|
||||
("Theme", ""),
|
||||
("Dark Theme", ""),
|
||||
("Dark", ""),
|
||||
@@ -345,7 +351,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Server", ""),
|
||||
("Direct IP Access", ""),
|
||||
("Proxy", ""),
|
||||
("Port", ""),
|
||||
("Apply", ""),
|
||||
("Disconnect all devices?", ""),
|
||||
("Clear", ""),
|
||||
@@ -374,7 +379,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Other", ""),
|
||||
("Confirm before closing multiple tabs", ""),
|
||||
("Keyboard Settings", ""),
|
||||
("Custom", ""),
|
||||
("Full Access", ""),
|
||||
("Screen Share", ""),
|
||||
("Wayland requires Ubuntu 21.04 or higher version.", "Wayland yêu cầu phiên bản Ubuntu 21.04 trở lên."),
|
||||
@@ -399,6 +403,15 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("hide_cm_tip", ""),
|
||||
("wayland_experiment_tip", ""),
|
||||
("Right click to select tabs", ""),
|
||||
("Skipped", ""),
|
||||
("Add to Address Book", ""),
|
||||
("Group", ""),
|
||||
("Search", ""),
|
||||
("Closed manually by the web console", ""),
|
||||
("Local keyboard type", ""),
|
||||
("Select local keyboard type", ""),
|
||||
("software_render_tip", ""),
|
||||
("Always use software rendering", ""),
|
||||
("config_input", ""),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#[cfg(not(any(target_os = "ios")))]
|
||||
/// cbindgen:ignore
|
||||
pub mod platform;
|
||||
mod keyboard;
|
||||
#[cfg(not(any(target_os = "android", target_os = "ios")))]
|
||||
pub use platform::{get_cursor, get_cursor_data, get_cursor_pos, start_os_service};
|
||||
#[cfg(not(any(target_os = "ios")))]
|
||||
|
||||
13
src/main.rs
13
src/main.rs
@@ -36,8 +36,9 @@ fn main() {
|
||||
use hbb_common::log;
|
||||
let args = format!(
|
||||
"-p, --port-forward=[PORT-FORWARD-OPTIONS] 'Format: remote-id:local-port:remote-port[:remote-host]'
|
||||
-c, --connect=[REMOTE_ID] 'test only'
|
||||
-k, --key=[KEY] ''
|
||||
-s, --server... 'Start server'",
|
||||
-s, --server=[] 'Start server'",
|
||||
);
|
||||
let matches = App::new("rustdesk")
|
||||
.version(crate::VERSION)
|
||||
@@ -71,6 +72,8 @@ fn main() {
|
||||
if options.len() > 3 {
|
||||
remote_host = options[3].clone();
|
||||
}
|
||||
common::test_rendezvous_server();
|
||||
common::test_nat_type();
|
||||
let key = matches.value_of("key").unwrap_or("").to_owned();
|
||||
let token = LocalConfig::get_option("access_token");
|
||||
cli::start_one_port_forward(
|
||||
@@ -81,6 +84,14 @@ fn main() {
|
||||
key,
|
||||
token,
|
||||
);
|
||||
} else if let Some(p) = matches.value_of("connect") {
|
||||
common::test_rendezvous_server();
|
||||
common::test_nat_type();
|
||||
let key = matches.value_of("key").unwrap_or("").to_owned();
|
||||
let token = LocalConfig::get_option("access_token");
|
||||
cli::connect_test(p, key, token);
|
||||
} else if let Some(p) = matches.value_of("server") {
|
||||
crate::start_server(true);
|
||||
}
|
||||
common::global_clean();
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ use hbb_common::{allow_err, bail, log};
|
||||
use libc::{c_char, c_int, c_void};
|
||||
use std::{
|
||||
cell::RefCell,
|
||||
collections::HashMap,
|
||||
path::PathBuf,
|
||||
sync::{
|
||||
atomic::{AtomicBool, Ordering},
|
||||
@@ -179,7 +180,8 @@ fn set_x11_env(uid: &str) {
|
||||
log::info!("uid of seat0: {}", uid);
|
||||
let gdm = format!("/run/user/{}/gdm/Xauthority", uid);
|
||||
let mut auth = get_env_tries("XAUTHORITY", uid, 10);
|
||||
if auth.is_empty() {
|
||||
// auth is another user's when uid = 0, https://github.com/rustdesk/rustdesk/issues/2468
|
||||
if auth.is_empty() || uid == "0" {
|
||||
auth = if std::path::Path::new(&gdm).exists() {
|
||||
gdm
|
||||
} else {
|
||||
@@ -715,3 +717,84 @@ pub fn get_double_click_time() -> u32 {
|
||||
double_click_time
|
||||
}
|
||||
}
|
||||
|
||||
/// forever: may not work
|
||||
pub fn system_message(title: &str, msg: &str, forever: bool) -> ResultType<()> {
|
||||
let cmds: HashMap<&str, Vec<&str>> = HashMap::from([
|
||||
("notify-send", [title, msg].to_vec()),
|
||||
(
|
||||
"zenity",
|
||||
[
|
||||
"--info",
|
||||
"--timeout",
|
||||
if forever { "0" } else { "3" },
|
||||
"--title",
|
||||
title,
|
||||
"--text",
|
||||
msg,
|
||||
]
|
||||
.to_vec(),
|
||||
),
|
||||
("kdialog", ["--title", title, "--msgbox", msg].to_vec()),
|
||||
(
|
||||
"xmessage",
|
||||
[
|
||||
"-center",
|
||||
"-timeout",
|
||||
if forever { "0" } else { "3" },
|
||||
title,
|
||||
msg,
|
||||
]
|
||||
.to_vec(),
|
||||
),
|
||||
]);
|
||||
for (k, v) in cmds {
|
||||
if std::process::Command::new(k).args(v).spawn().is_ok() {
|
||||
return Ok(());
|
||||
}
|
||||
}
|
||||
bail!("failed to post system message");
|
||||
}
|
||||
|
||||
extern "C" fn breakdown_signal_handler(sig: i32) {
|
||||
let mut stack = vec![];
|
||||
backtrace::trace(|frame| {
|
||||
backtrace::resolve_frame(frame, |symbol| {
|
||||
if let Some(name) = symbol.name() {
|
||||
stack.push(name.to_string());
|
||||
}
|
||||
});
|
||||
true // keep going to the next frame
|
||||
});
|
||||
let mut info = String::default();
|
||||
if stack.iter().any(|s| {
|
||||
s.contains(&"nouveau_pushbuf_kick")
|
||||
|| s.to_lowercase().contains("nvidia")
|
||||
|| s.contains("gdk_window_end_draw_frame")
|
||||
}) {
|
||||
hbb_common::config::Config::set_option(
|
||||
"allow-always-software-render".to_string(),
|
||||
"Y".to_string(),
|
||||
);
|
||||
info = "Always use software rendering will be set.".to_string();
|
||||
log::info!("{}", info);
|
||||
}
|
||||
log::error!(
|
||||
"Got signal {} and exit. stack:\n{}",
|
||||
sig,
|
||||
stack.join("\n").to_string()
|
||||
);
|
||||
system_message(
|
||||
"RustDesk",
|
||||
&format!("Got signal {} and exit.{}", sig, info),
|
||||
true,
|
||||
)
|
||||
.ok();
|
||||
std::process::exit(0);
|
||||
}
|
||||
|
||||
pub fn register_breakdown_handler() {
|
||||
unsafe {
|
||||
libc::signal(libc::SIGSEGV, breakdown_signal_handler as _);
|
||||
}
|
||||
}
|
||||
|
||||
36
src/platform/macos.mm
Normal file
36
src/platform/macos.mm
Normal file
@@ -0,0 +1,36 @@
|
||||
#import <AVFoundation/AVFoundation.h>
|
||||
#import <AppKit/AppKit.h>
|
||||
#import <IOKit/hidsystem/IOHIDLib.h>
|
||||
|
||||
// https://github.com/codebytere/node-mac-permissions/blob/main/permissions.mm
|
||||
|
||||
extern "C" bool InputMonitoringAuthStatus(bool prompt) {
|
||||
if (floor(NSAppKitVersionNumber) >= NSAppKitVersionNumber10_15) {
|
||||
IOHIDAccessType theType = IOHIDCheckAccess(kIOHIDRequestTypeListenEvent);
|
||||
NSLog(@"IOHIDCheckAccess = %d, kIOHIDAccessTypeGranted = %d", theType, kIOHIDAccessTypeGranted);
|
||||
switch (theType) {
|
||||
case kIOHIDAccessTypeGranted:
|
||||
return true;
|
||||
break;
|
||||
case kIOHIDAccessTypeDenied: {
|
||||
if (prompt) {
|
||||
NSString *urlString = @"x-apple.systempreferences:com.apple.preference.security?Privacy_ListenEvent";
|
||||
[[NSWorkspace sharedWorkspace] openURL:[NSURL URLWithString:urlString]];
|
||||
}
|
||||
break;
|
||||
}
|
||||
case kIOHIDAccessTypeUnknown: {
|
||||
if (prompt) {
|
||||
bool result = IOHIDRequestAccess(kIOHIDRequestTypeListenEvent);
|
||||
NSLog(@"IOHIDRequestAccess result = %d", result);
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@@ -4,6 +4,7 @@
|
||||
|
||||
use super::{CursorData, ResultType};
|
||||
use cocoa::{
|
||||
appkit::{NSApp, NSApplication, NSApplicationActivationPolicy::*},
|
||||
base::{id, nil, BOOL, NO, YES},
|
||||
foundation::{NSDictionary, NSPoint, NSSize, NSString},
|
||||
};
|
||||
@@ -32,6 +33,7 @@ extern "C" {
|
||||
fn CGEventGetLocation(e: *const c_void) -> CGPoint;
|
||||
static kAXTrustedCheckOptionPrompt: CFStringRef;
|
||||
fn AXIsProcessTrustedWithOptions(options: CFDictionaryRef) -> BOOL;
|
||||
fn InputMonitoringAuthStatus(_: BOOL) -> BOOL;
|
||||
}
|
||||
|
||||
pub fn is_process_trusted(prompt: bool) -> bool {
|
||||
@@ -47,6 +49,13 @@ pub fn is_process_trusted(prompt: bool) -> bool {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_can_input_monitoring(prompt: bool) -> bool {
|
||||
unsafe {
|
||||
let value = if prompt { YES } else { NO };
|
||||
InputMonitoringAuthStatus(value) == YES
|
||||
}
|
||||
}
|
||||
|
||||
// macOS >= 10.15
|
||||
// https://stackoverflow.com/questions/56597221/detecting-screen-recording-settings-on-macos-catalina/
|
||||
// remove just one app from all the permissions: tccutil reset All com.carriez.rustdesk
|
||||
@@ -500,7 +509,7 @@ pub fn start_os_service() {
|
||||
Err(err) => {
|
||||
log::error!("Failed to start server: {}", err);
|
||||
}
|
||||
_ => { /*no hapen*/ }
|
||||
_ => { /*no happen*/ }
|
||||
}
|
||||
}
|
||||
std::thread::sleep(std::time::Duration::from_millis(super::SERVICE_INTERVAL));
|
||||
@@ -542,3 +551,9 @@ pub fn get_double_click_time() -> u32 {
|
||||
// to-do: https://github.com/servo/core-foundation-rs/blob/786895643140fa0ee4f913d7b4aeb0c4626b2085/cocoa/src/appkit.rs#L2823
|
||||
500 as _
|
||||
}
|
||||
|
||||
pub fn hide_dock() {
|
||||
unsafe {
|
||||
NSApp().setActivationPolicy_(NSApplicationActivationPolicyAccessory);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -75,3 +75,4 @@ mod tests {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -95,7 +95,7 @@ extern "C"
|
||||
|
||||
CreateEnvironmentBlock(&lpEnvironment, // Environment block
|
||||
hToken, // New token
|
||||
TRUE); // Inheritence
|
||||
TRUE); // Inheritance
|
||||
}
|
||||
if (lpEnvironment)
|
||||
{
|
||||
@@ -588,4 +588,44 @@ extern "C"
|
||||
stop_system_key_propagate = v;
|
||||
}
|
||||
|
||||
// https://stackoverflow.com/questions/4023586/correct-way-to-find-out-if-a-service-is-running-as-the-system-user
|
||||
BOOL is_local_system()
|
||||
{
|
||||
HANDLE hToken;
|
||||
UCHAR bTokenUser[sizeof(TOKEN_USER) + 8 + 4 * SID_MAX_SUB_AUTHORITIES];
|
||||
PTOKEN_USER pTokenUser = (PTOKEN_USER)bTokenUser;
|
||||
ULONG cbTokenUser;
|
||||
SID_IDENTIFIER_AUTHORITY siaNT = SECURITY_NT_AUTHORITY;
|
||||
PSID pSystemSid;
|
||||
BOOL bSystem;
|
||||
|
||||
// open process token
|
||||
if (!OpenProcessToken(GetCurrentProcess(),
|
||||
TOKEN_QUERY,
|
||||
&hToken))
|
||||
return FALSE;
|
||||
|
||||
// retrieve user SID
|
||||
if (!GetTokenInformation(hToken, TokenUser, pTokenUser,
|
||||
sizeof(bTokenUser), &cbTokenUser))
|
||||
{
|
||||
CloseHandle(hToken);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
CloseHandle(hToken);
|
||||
|
||||
// allocate LocalSystem well-known SID
|
||||
if (!AllocateAndInitializeSid(&siaNT, 1, SECURITY_LOCAL_SYSTEM_RID,
|
||||
0, 0, 0, 0, 0, 0, 0, &pSystemSid))
|
||||
return FALSE;
|
||||
|
||||
// compare the user SID from the token with the LocalSystem SID
|
||||
bSystem = EqualSid(pTokenUser->User.Sid, pSystemSid);
|
||||
|
||||
FreeSid(pSystemSid);
|
||||
|
||||
return bSystem;
|
||||
}
|
||||
|
||||
} // end of extern "C"
|
||||
@@ -439,6 +439,7 @@ extern "C" {
|
||||
fn win32_disable_lowlevel_keyboard(hwnd: HWND);
|
||||
fn win_stop_system_key_propagate(v: BOOL);
|
||||
fn is_win_down() -> BOOL;
|
||||
fn is_local_system() -> BOOL;
|
||||
}
|
||||
|
||||
extern "system" {
|
||||
@@ -718,10 +719,10 @@ pub fn set_share_rdp(enable: bool) {
|
||||
}
|
||||
|
||||
pub fn get_active_username() -> String {
|
||||
let name = crate::username();
|
||||
if name != "SYSTEM" {
|
||||
return name;
|
||||
if !is_root() {
|
||||
return crate::username();
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
fn get_active_user(path: *mut u16, n: u32, rdp: BOOL) -> u32;
|
||||
}
|
||||
@@ -757,7 +758,8 @@ pub fn is_prelogin() -> bool {
|
||||
}
|
||||
|
||||
pub fn is_root() -> bool {
|
||||
crate::username() == "SYSTEM"
|
||||
// https://stackoverflow.com/questions/4023586/correct-way-to-find-out-if-a-service-is-running-as-the-system-user
|
||||
unsafe { is_local_system() == TRUE }
|
||||
}
|
||||
|
||||
pub fn lock_screen() {
|
||||
|
||||
@@ -18,13 +18,14 @@ use hbb_common::{
|
||||
log,
|
||||
protobuf::Message as _,
|
||||
rendezvous_proto::*,
|
||||
sleep, socket_client,
|
||||
sleep,
|
||||
socket_client::{self, is_ipv4},
|
||||
tokio::{
|
||||
self, select,
|
||||
time::{interval, Duration},
|
||||
},
|
||||
udp::FramedSocket,
|
||||
AddrMangle, IntoTargetAddr, ResultType, TargetAddr,
|
||||
AddrMangle, ResultType,
|
||||
};
|
||||
|
||||
use crate::server::{check_zombie, new as new_server, ServerPtr};
|
||||
@@ -38,7 +39,7 @@ static SHOULD_EXIT: AtomicBool = AtomicBool::new(false);
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct RendezvousMediator {
|
||||
addr: TargetAddr<'static>,
|
||||
addr: hbb_common::tokio_socks::TargetAddr<'static>,
|
||||
host: String,
|
||||
host_prefix: String,
|
||||
last_id_pk_registry: String,
|
||||
@@ -110,17 +111,15 @@ impl RendezvousMediator {
|
||||
}
|
||||
})
|
||||
.unwrap_or(host.to_owned());
|
||||
let host = crate::check_port(&host, RENDEZVOUS_PORT);
|
||||
let (mut socket, addr) = socket_client::new_udp_for(&host, RENDEZVOUS_TIMEOUT).await?;
|
||||
let mut rz = Self {
|
||||
addr: Config::get_any_listen_addr().into_target_addr()?,
|
||||
addr: addr,
|
||||
host: host.clone(),
|
||||
host_prefix,
|
||||
last_id_pk_registry: "".to_owned(),
|
||||
};
|
||||
|
||||
rz.addr = socket_client::get_target_addr(&crate::check_port(&host, RENDEZVOUS_PORT))?;
|
||||
let any_addr = Config::get_any_listen_addr();
|
||||
let mut socket = socket_client::new_udp(any_addr, RENDEZVOUS_TIMEOUT).await?;
|
||||
|
||||
const TIMER_OUT: Duration = Duration::from_secs(1);
|
||||
let mut timer = interval(TIMER_OUT);
|
||||
let mut last_timer: Option<Instant> = None;
|
||||
@@ -250,11 +249,11 @@ impl RendezvousMediator {
|
||||
Config::update_latency(&host, -1);
|
||||
old_latency = 0;
|
||||
if last_dns_check.elapsed().as_millis() as i64 > DNS_INTERVAL {
|
||||
rz.addr = socket_client::get_target_addr(&crate::check_port(&host, RENDEZVOUS_PORT))?;
|
||||
// in some case of network reconnect (dial IP network),
|
||||
// old UDP socket not work any more after network recover
|
||||
if let Some(s) = socket_client::rebind_udp(any_addr).await? {
|
||||
if let Some((s, addr)) = socket_client::rebind_udp_for(&rz.host).await? {
|
||||
socket = s;
|
||||
rz.addr = addr;
|
||||
}
|
||||
last_dns_check = Instant::now();
|
||||
}
|
||||
@@ -293,19 +292,14 @@ impl RendezvousMediator {
|
||||
) -> ResultType<()> {
|
||||
let peer_addr = AddrMangle::decode(&socket_addr);
|
||||
log::info!(
|
||||
"create_relay requested from from {:?}, relay_server: {}, uuid: {}, secure: {}",
|
||||
"create_relay requested from {:?}, relay_server: {}, uuid: {}, secure: {}",
|
||||
peer_addr,
|
||||
relay_server,
|
||||
uuid,
|
||||
secure,
|
||||
);
|
||||
|
||||
let mut socket = socket_client::connect_tcp(
|
||||
self.addr.to_owned(),
|
||||
Config::get_any_listen_addr(),
|
||||
RENDEZVOUS_TIMEOUT,
|
||||
)
|
||||
.await?;
|
||||
let mut socket = socket_client::connect_tcp(&*self.host, RENDEZVOUS_TIMEOUT).await?;
|
||||
|
||||
let mut msg_out = Message::new();
|
||||
let mut rr = RelayResponse {
|
||||
@@ -320,24 +314,41 @@ impl RendezvousMediator {
|
||||
}
|
||||
msg_out.set_relay_response(rr);
|
||||
socket.send(&msg_out).await?;
|
||||
crate::create_relay_connection(server, relay_server, uuid, peer_addr, secure).await;
|
||||
crate::create_relay_connection(
|
||||
server,
|
||||
relay_server,
|
||||
uuid,
|
||||
peer_addr,
|
||||
secure,
|
||||
is_ipv4(&self.addr),
|
||||
)
|
||||
.await;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn handle_intranet(&self, fla: FetchLocalAddr, server: ServerPtr) -> ResultType<()> {
|
||||
let relay_server = self.get_relay_server(fla.relay_server);
|
||||
if !is_ipv4(&self.addr) {
|
||||
// nat64, go relay directly, because current hbbs will crash if demangle ipv6 address
|
||||
let uuid = Uuid::new_v4().to_string();
|
||||
return self
|
||||
.create_relay(
|
||||
fla.socket_addr.into(),
|
||||
relay_server,
|
||||
uuid,
|
||||
server,
|
||||
true,
|
||||
true,
|
||||
)
|
||||
.await;
|
||||
}
|
||||
let peer_addr = AddrMangle::decode(&fla.socket_addr);
|
||||
log::debug!("Handle intranet from {:?}", peer_addr);
|
||||
let mut socket = socket_client::connect_tcp(
|
||||
self.addr.to_owned(),
|
||||
Config::get_any_listen_addr(),
|
||||
RENDEZVOUS_TIMEOUT,
|
||||
)
|
||||
.await?;
|
||||
let mut socket = socket_client::connect_tcp(&*self.host, RENDEZVOUS_TIMEOUT).await?;
|
||||
let local_addr = socket.local_addr();
|
||||
let local_addr: SocketAddr =
|
||||
format!("{}:{}", local_addr.ip(), local_addr.port()).parse()?;
|
||||
let mut msg_out = Message::new();
|
||||
let relay_server = self.get_relay_server(fla.relay_server);
|
||||
msg_out.set_local_addr(LocalAddr {
|
||||
id: Config::get_id(),
|
||||
socket_addr: AddrMangle::encode(peer_addr).into(),
|
||||
@@ -372,14 +383,11 @@ impl RendezvousMediator {
|
||||
let peer_addr = AddrMangle::decode(&ph.socket_addr);
|
||||
log::debug!("Punch hole to {:?}", peer_addr);
|
||||
let mut socket = {
|
||||
let socket = socket_client::connect_tcp(
|
||||
self.addr.to_owned(),
|
||||
Config::get_any_listen_addr(),
|
||||
RENDEZVOUS_TIMEOUT,
|
||||
)
|
||||
.await?;
|
||||
let socket = socket_client::connect_tcp(&*self.host, RENDEZVOUS_TIMEOUT).await?;
|
||||
let local_addr = socket.local_addr();
|
||||
allow_err!(socket_client::connect_tcp(peer_addr, local_addr, 300).await);
|
||||
// key important here for punch hole to tell my gateway incoming peer is safe.
|
||||
// it can not be async here, because local_addr can not be reused, we must close the connection before use it again.
|
||||
allow_err!(socket_client::connect_tcp_local(peer_addr, Some(local_addr), 30).await);
|
||||
socket
|
||||
};
|
||||
let mut msg_out = Message::new();
|
||||
@@ -467,15 +475,7 @@ impl RendezvousMediator {
|
||||
relay_server = provided_by_rendzvous_server;
|
||||
}
|
||||
if relay_server.is_empty() {
|
||||
if self.host.contains(":") {
|
||||
let tmp: Vec<&str> = self.host.split(":").collect();
|
||||
if tmp.len() == 2 {
|
||||
let port: u16 = tmp[1].parse().unwrap_or(0);
|
||||
relay_server = format!("{}:{}", tmp[0], port + 1);
|
||||
}
|
||||
} else {
|
||||
relay_server = self.host.clone();
|
||||
}
|
||||
relay_server = crate::increase_port(&self.host, 1);
|
||||
}
|
||||
relay_server
|
||||
}
|
||||
@@ -498,8 +498,7 @@ async fn direct_server(server: ServerPtr) {
|
||||
let disabled = Config::get_option("direct-server").is_empty();
|
||||
if !disabled && listener.is_none() {
|
||||
port = get_direct_port();
|
||||
let addr = format!("0.0.0.0:{}", port);
|
||||
match hbb_common::tcp::new_listener(&addr, false).await {
|
||||
match hbb_common::tcp::listen_any(port as _).await {
|
||||
Ok(l) => {
|
||||
listener = Some(l);
|
||||
log::info!(
|
||||
@@ -510,8 +509,8 @@ async fn direct_server(server: ServerPtr) {
|
||||
Err(err) => {
|
||||
// to-do: pass to ui
|
||||
log::error!(
|
||||
"Failed to start direct server on : {}, error: {}",
|
||||
addr,
|
||||
"Failed to start direct server on port: {}, error: {}",
|
||||
port,
|
||||
err
|
||||
);
|
||||
loop {
|
||||
@@ -532,7 +531,9 @@ async fn direct_server(server: ServerPtr) {
|
||||
if let Ok(Ok((stream, addr))) = hbb_common::timeout(1000, l.accept()).await {
|
||||
stream.set_nodelay(true).ok();
|
||||
log::info!("direct access from {}", addr);
|
||||
let local_addr = stream.local_addr().unwrap_or(Config::get_any_listen_addr());
|
||||
let local_addr = stream
|
||||
.local_addr()
|
||||
.unwrap_or(Config::get_any_listen_addr(true));
|
||||
let server = server.clone();
|
||||
tokio::spawn(async move {
|
||||
allow_err!(
|
||||
@@ -650,13 +651,7 @@ async fn create_online_stream() -> ResultType<FramedStream> {
|
||||
bail!("Invalid server address: {}", rendezvous_server);
|
||||
}
|
||||
let online_server = format!("{}:{}", tmp[0], port - 1);
|
||||
let server_addr = socket_client::get_target_addr(&online_server)?;
|
||||
socket_client::connect_tcp(
|
||||
server_addr,
|
||||
Config::get_any_listen_addr(),
|
||||
RENDEZVOUS_TIMEOUT,
|
||||
)
|
||||
.await
|
||||
socket_client::connect_tcp(online_server, RENDEZVOUS_TIMEOUT).await
|
||||
}
|
||||
|
||||
async fn query_online_states_(
|
||||
|
||||
@@ -85,7 +85,7 @@ pub fn new() -> ServerPtr {
|
||||
#[cfg(not(any(target_os = "android", target_os = "ios")))]
|
||||
{
|
||||
server.add_service(Box::new(clipboard_service::new()));
|
||||
if !video_service::capture_cursor_embeded() {
|
||||
if !video_service::capture_cursor_embedded() {
|
||||
server.add_service(Box::new(input_service::new_cursor()));
|
||||
server.add_service(Box::new(input_service::new_pos()));
|
||||
}
|
||||
@@ -194,6 +194,11 @@ pub async fn create_tcp_connection(
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(target_os = "macos")]{
|
||||
use std::process::Command;
|
||||
Command::new("/usr/bin/caffeinate").arg("-u").arg("-t 5").spawn().ok();
|
||||
log::info!("wake up macos");
|
||||
}
|
||||
Connection::start(addr, stream, id, Arc::downgrade(&server)).await;
|
||||
Ok(())
|
||||
}
|
||||
@@ -215,9 +220,10 @@ pub async fn create_relay_connection(
|
||||
uuid: String,
|
||||
peer_addr: SocketAddr,
|
||||
secure: bool,
|
||||
ipv4: bool,
|
||||
) {
|
||||
if let Err(err) =
|
||||
create_relay_connection_(server, relay_server, uuid.clone(), peer_addr, secure).await
|
||||
create_relay_connection_(server, relay_server, uuid.clone(), peer_addr, secure, ipv4).await
|
||||
{
|
||||
log::error!(
|
||||
"Failed to create relay connection for {} with uuid {}: {}",
|
||||
@@ -234,10 +240,10 @@ async fn create_relay_connection_(
|
||||
uuid: String,
|
||||
peer_addr: SocketAddr,
|
||||
secure: bool,
|
||||
ipv4: bool,
|
||||
) -> ResultType<()> {
|
||||
let mut stream = socket_client::connect_tcp(
|
||||
crate::check_port(relay_server, RELAY_PORT),
|
||||
Config::get_any_listen_addr(),
|
||||
socket_client::ipv4_to_ipv6(crate::check_port(relay_server, RELAY_PORT), ipv4),
|
||||
CONNECT_TIMEOUT,
|
||||
)
|
||||
.await?;
|
||||
|
||||
@@ -26,6 +26,7 @@ use hbb_common::{
|
||||
};
|
||||
#[cfg(any(target_os = "android", target_os = "ios"))]
|
||||
use scrap::android::call_main_service_mouse_input;
|
||||
use serde::Deserialize;
|
||||
use serde_json::{json, value::Value};
|
||||
use sha2::{Digest, Sha256};
|
||||
#[cfg(not(any(target_os = "android", target_os = "ios")))]
|
||||
@@ -72,6 +73,8 @@ pub struct Connection {
|
||||
hash: Hash,
|
||||
read_jobs: Vec<fs::TransferJob>,
|
||||
timer: Interval,
|
||||
file_timer: Interval,
|
||||
http_timer: Interval,
|
||||
file_transfer: Option<(String, bool)>,
|
||||
port_forward_socket: Option<Framed<TcpStream, BytesCodec>>,
|
||||
port_forward_address: String,
|
||||
@@ -93,7 +96,8 @@ pub struct Connection {
|
||||
tx_input: std_mpsc::Sender<MessageInput>, // handle input messages
|
||||
video_ack_required: bool,
|
||||
peer_info: (String, String),
|
||||
api_server: String,
|
||||
server_audit_conn: String,
|
||||
server_audit_file: String,
|
||||
lr: LoginRequest,
|
||||
last_recv_time: Arc<Mutex<Instant>>,
|
||||
chat_unanswered: bool,
|
||||
@@ -150,6 +154,7 @@ impl Connection {
|
||||
let (tx, mut rx) = mpsc::unbounded_channel::<(Instant, Arc<Message>)>();
|
||||
let (tx_video, mut rx_video) = mpsc::unbounded_channel::<(Instant, Arc<Message>)>();
|
||||
let (tx_input, rx_input) = std_mpsc::channel();
|
||||
let (tx_stop, mut rx_stop) = mpsc::unbounded_channel::<String>();
|
||||
|
||||
let tx_cloned = tx.clone();
|
||||
let mut conn = Self {
|
||||
@@ -163,6 +168,8 @@ impl Connection {
|
||||
hash,
|
||||
read_jobs: Vec::new(),
|
||||
timer: time::interval(SEC30),
|
||||
file_timer: time::interval(SEC30),
|
||||
http_timer: time::interval(Duration::from_secs(3)),
|
||||
file_transfer: None,
|
||||
port_forward_socket: None,
|
||||
port_forward_address: "".to_owned(),
|
||||
@@ -184,7 +191,8 @@ impl Connection {
|
||||
tx_input,
|
||||
video_ack_required: false,
|
||||
peer_info: Default::default(),
|
||||
api_server: "".to_owned(),
|
||||
server_audit_conn: "".to_owned(),
|
||||
server_audit_file: "".to_owned(),
|
||||
lr: Default::default(),
|
||||
last_recv_time: Arc::new(Mutex::new(Instant::now())),
|
||||
chat_unanswered: false,
|
||||
@@ -244,7 +252,7 @@ impl Connection {
|
||||
|
||||
loop {
|
||||
tokio::select! {
|
||||
// biased; // video has higher priority // causing test_delay_timer failed while transfering big file
|
||||
// biased; // video has higher priority // causing test_delay_timer failed while transferring big file
|
||||
|
||||
Some(data) = rx_from_cm.recv() => {
|
||||
match data {
|
||||
@@ -255,7 +263,7 @@ impl Connection {
|
||||
}
|
||||
}
|
||||
ipc::Data::Close => {
|
||||
conn.on_close_manually("connection manager").await;
|
||||
conn.on_close_manually("connection manager", "peer").await;
|
||||
break;
|
||||
}
|
||||
ipc::Data::ChatMessage{text} => {
|
||||
@@ -375,20 +383,26 @@ impl Connection {
|
||||
break;
|
||||
}
|
||||
},
|
||||
_ = conn.timer.tick() => {
|
||||
_ = conn.file_timer.tick() => {
|
||||
if !conn.read_jobs.is_empty() {
|
||||
if let Err(err) = fs::handle_read_jobs(&mut conn.read_jobs, &mut conn.stream).await {
|
||||
conn.on_close(&err.to_string(), false).await;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
conn.timer = time::interval_at(Instant::now() + SEC30, SEC30);
|
||||
conn.file_timer = time::interval_at(Instant::now() + SEC30, SEC30);
|
||||
}
|
||||
conn.post_audit(json!({})); // heartbeat
|
||||
}
|
||||
_ = conn.http_timer.tick() => {
|
||||
Connection::post_heartbeat(conn.server_audit_conn.clone(), conn.inner.id, tx_stop.clone());
|
||||
},
|
||||
Some(reason) = rx_stop.recv() => {
|
||||
conn.on_close_manually(&reason, &reason).await;
|
||||
|
||||
}
|
||||
Some((instant, value)) = rx_video.recv() => {
|
||||
if !conn.video_ack_required {
|
||||
video_service::notify_video_frame_feched(id, Some(instant.into()));
|
||||
video_service::notify_video_frame_fetched(id, Some(instant.into()));
|
||||
}
|
||||
if let Err(err) = conn.stream.send(&value as &Message).await {
|
||||
conn.on_close(&err.to_string(), false).await;
|
||||
@@ -412,7 +426,7 @@ impl Connection {
|
||||
Some(message::Union::Misc(m)) => {
|
||||
match &m.union {
|
||||
Some(misc::Union::StopService(_)) => {
|
||||
conn.on_close_manually("stop service").await;
|
||||
conn.on_close_manually("stop service", "peer").await;
|
||||
break;
|
||||
}
|
||||
_ => {},
|
||||
@@ -487,7 +501,7 @@ impl Connection {
|
||||
} else if video_privacy_conn_id == 0 {
|
||||
let _ = privacy_mode::turn_off_privacy(0);
|
||||
}
|
||||
video_service::notify_video_frame_feched(id, None);
|
||||
video_service::notify_video_frame_fetched(id, None);
|
||||
scrap::codec::Encoder::update_video_encoder(id, scrap::codec::EncoderUpdate::Remove);
|
||||
video_service::VIDEO_QOS.lock().unwrap().reset();
|
||||
if conn.authorized {
|
||||
@@ -497,7 +511,7 @@ impl Connection {
|
||||
conn.on_close(&err.to_string(), false).await;
|
||||
}
|
||||
|
||||
conn.post_audit(json!({
|
||||
conn.post_conn_audit(json!({
|
||||
"action": "close",
|
||||
}));
|
||||
log::info!("#{} connection loop exited", id);
|
||||
@@ -511,6 +525,8 @@ impl Connection {
|
||||
rdev::set_dw_mouse_extra_info(enigo::ENIGO_INPUT_EXTRA_VALUE);
|
||||
rdev::set_dw_keyboard_extra_info(enigo::ENIGO_INPUT_EXTRA_VALUE);
|
||||
}
|
||||
#[cfg(target_os = "macos")]
|
||||
reset_input_ondisconn();
|
||||
loop {
|
||||
match receiver.recv_timeout(std::time::Duration::from_millis(500)) {
|
||||
Ok(v) => match v {
|
||||
@@ -568,6 +584,7 @@ impl Connection {
|
||||
rx_from_cm: &mut mpsc::UnboundedReceiver<Data>,
|
||||
) -> ResultType<()> {
|
||||
let mut last_recv_time = Instant::now();
|
||||
let (tx_stop, mut rx_stop) = mpsc::unbounded_channel::<String>();
|
||||
if let Some(mut forward) = self.port_forward_socket.take() {
|
||||
log::info!("Running port forwarding loop");
|
||||
self.stream.set_raw();
|
||||
@@ -601,7 +618,10 @@ impl Connection {
|
||||
if last_recv_time.elapsed() >= H1 {
|
||||
bail!("Timeout");
|
||||
}
|
||||
self.post_audit(json!({})); // heartbeat
|
||||
Connection::post_heartbeat(self.server_audit_conn.clone(), self.inner.id, tx_stop.clone());
|
||||
}
|
||||
Some(reason) = rx_stop.recv() => {
|
||||
bail!(reason);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -642,6 +662,13 @@ impl Connection {
|
||||
{
|
||||
self.send_login_error("Your ip is blocked by the peer")
|
||||
.await;
|
||||
Self::post_alarm_audit(
|
||||
AlarmAuditType::IpWhiltelist, //"ip whiltelist",
|
||||
true,
|
||||
json!({
|
||||
"ip":addr.ip(),
|
||||
}),
|
||||
);
|
||||
sleep(1.).await;
|
||||
return false;
|
||||
}
|
||||
@@ -650,7 +677,7 @@ impl Connection {
|
||||
msg_out.set_hash(self.hash.clone());
|
||||
self.send(msg_out).await;
|
||||
self.get_api_server();
|
||||
self.post_audit(json!({
|
||||
self.post_conn_audit(json!({
|
||||
"ip": addr.ip(),
|
||||
"action": "new",
|
||||
}));
|
||||
@@ -658,30 +685,114 @@ impl Connection {
|
||||
}
|
||||
|
||||
fn get_api_server(&mut self) {
|
||||
self.api_server = crate::get_audit_server(
|
||||
self.server_audit_conn = crate::get_audit_server(
|
||||
Config::get_option("api-server"),
|
||||
Config::get_option("custom-rendezvous-server"),
|
||||
"conn".to_owned(),
|
||||
);
|
||||
self.server_audit_file = crate::get_audit_server(
|
||||
Config::get_option("api-server"),
|
||||
Config::get_option("custom-rendezvous-server"),
|
||||
"file".to_owned(),
|
||||
);
|
||||
}
|
||||
|
||||
fn post_audit(&self, v: Value) {
|
||||
if self.api_server.is_empty() {
|
||||
fn post_conn_audit(&self, v: Value) {
|
||||
if self.server_audit_conn.is_empty() {
|
||||
return;
|
||||
}
|
||||
let url = self.api_server.clone();
|
||||
let url = self.server_audit_conn.clone();
|
||||
let mut v = v;
|
||||
v["id"] = json!(Config::get_id());
|
||||
v["uuid"] = json!(base64::encode(hbb_common::get_uuid()));
|
||||
v["Id"] = json!(self.inner.id);
|
||||
v["conn_id"] = json!(self.inner.id);
|
||||
tokio::spawn(async move {
|
||||
allow_err!(Self::post_audit_async(url, v).await);
|
||||
});
|
||||
}
|
||||
|
||||
fn post_heartbeat(
|
||||
server_audit_conn: String,
|
||||
conn_id: i32,
|
||||
tx_stop: mpsc::UnboundedSender<String>,
|
||||
) {
|
||||
if server_audit_conn.is_empty() {
|
||||
return;
|
||||
}
|
||||
let url = server_audit_conn.clone();
|
||||
let mut v = Value::default();
|
||||
v["id"] = json!(Config::get_id());
|
||||
v["uuid"] = json!(base64::encode(hbb_common::get_uuid()));
|
||||
v["conn_id"] = json!(conn_id);
|
||||
tokio::spawn(async move {
|
||||
if let Ok(rsp) = Self::post_audit_async(url, v).await {
|
||||
if let Ok(rsp) = serde_json::from_str::<ConnAuditResponse>(&rsp) {
|
||||
if rsp.action == "disconnect" {
|
||||
tx_stop.send("web console".to_string()).ok();
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
fn post_file_audit(
|
||||
&self,
|
||||
r#type: FileAuditType,
|
||||
path: &str,
|
||||
files: Vec<(String, i64)>,
|
||||
info: Value,
|
||||
) {
|
||||
if self.server_audit_file.is_empty() {
|
||||
return;
|
||||
}
|
||||
let url = self.server_audit_file.clone();
|
||||
let file_num = files.len();
|
||||
let mut files = files;
|
||||
files.sort_by(|a, b| b.1.cmp(&a.1));
|
||||
files.truncate(10);
|
||||
let is_file = files.len() == 1 && files[0].0.is_empty();
|
||||
let mut info = info;
|
||||
info["ip"] = json!(self.ip.clone());
|
||||
info["name"] = json!(self.lr.my_name.clone());
|
||||
info["num"] = json!(file_num);
|
||||
info["files"] = json!(files);
|
||||
let v = json!({
|
||||
"id":json!(Config::get_id()),
|
||||
"uuid":json!(base64::encode(hbb_common::get_uuid())),
|
||||
"peer_id":json!(self.lr.my_id),
|
||||
"type": r#type as i8,
|
||||
"path":path,
|
||||
"is_file":is_file,
|
||||
"info":json!(info).to_string(),
|
||||
});
|
||||
tokio::spawn(async move {
|
||||
allow_err!(Self::post_audit_async(url, v).await);
|
||||
});
|
||||
}
|
||||
|
||||
pub fn post_alarm_audit(typ: AlarmAuditType, from_remote: bool, info: Value) {
|
||||
let url = crate::get_audit_server(
|
||||
Config::get_option("api-server"),
|
||||
Config::get_option("custom-rendezvous-server"),
|
||||
"alarm".to_owned(),
|
||||
);
|
||||
if url.is_empty() {
|
||||
return;
|
||||
}
|
||||
let mut v = Value::default();
|
||||
v["id"] = json!(Config::get_id());
|
||||
v["uuid"] = json!(base64::encode(hbb_common::get_uuid()));
|
||||
v["typ"] = json!(typ as i8);
|
||||
v["from_remote"] = json!(from_remote);
|
||||
v["info"] = serde_json::Value::String(info.to_string());
|
||||
tokio::spawn(async move {
|
||||
allow_err!(Self::post_audit_async(url, v).await);
|
||||
});
|
||||
}
|
||||
|
||||
#[inline]
|
||||
async fn post_audit_async(url: String, v: Value) -> ResultType<()> {
|
||||
crate::post_request(url, v.to_string(), "").await?;
|
||||
Ok(())
|
||||
async fn post_audit_async(url: String, v: Value) -> ResultType<String> {
|
||||
crate::post_request(url, v.to_string(), "").await
|
||||
}
|
||||
|
||||
async fn send_logon_response(&mut self) {
|
||||
@@ -695,7 +806,7 @@ impl Connection {
|
||||
} else {
|
||||
0
|
||||
};
|
||||
self.post_audit(json!({"peer": self.peer_info, "Type": conn_type}));
|
||||
self.post_conn_audit(json!({"peer": self.peer_info, "type": conn_type}));
|
||||
#[allow(unused_mut)]
|
||||
let mut username = crate::platform::get_active_username();
|
||||
let mut res = LoginResponse::new();
|
||||
@@ -1050,7 +1161,7 @@ impl Connection {
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
if !crate::is_ip(&lr.username) && lr.username != Config::get_id() {
|
||||
if !hbb_common::is_ipv4_str(&lr.username) && lr.username != Config::get_id() {
|
||||
self.send_login_error("Offline").await;
|
||||
} else if password::approve_mode() == ApproveMode::Click
|
||||
|| password::approve_mode() == ApproveMode::Both && !password::has_valid_password()
|
||||
@@ -1086,8 +1197,22 @@ impl Connection {
|
||||
if failure.2 > 30 {
|
||||
self.send_login_error("Too many wrong password attempts")
|
||||
.await;
|
||||
Self::post_alarm_audit(
|
||||
AlarmAuditType::ManyWrongPassword,
|
||||
true,
|
||||
json!({
|
||||
"ip":self.ip,
|
||||
}),
|
||||
);
|
||||
} else if time == failure.0 && failure.1 > 6 {
|
||||
self.send_login_error("Please try 1 minute later").await;
|
||||
Self::post_alarm_audit(
|
||||
AlarmAuditType::FrequentAttempt,
|
||||
true,
|
||||
json!({
|
||||
"ip":self.ip,
|
||||
}),
|
||||
);
|
||||
} else if !self.validate_password() {
|
||||
if failure.0 == time {
|
||||
failure.1 += 1;
|
||||
@@ -1225,8 +1350,18 @@ impl Connection {
|
||||
Ok(job) => {
|
||||
self.send(fs::new_dir(id, path, job.files().to_vec()))
|
||||
.await;
|
||||
let mut files = job.files().to_owned();
|
||||
self.read_jobs.push(job);
|
||||
self.timer = time::interval(MILLI1);
|
||||
self.file_timer = time::interval(MILLI1);
|
||||
self.post_file_audit(
|
||||
FileAuditType::RemoteSend,
|
||||
&s.path,
|
||||
files
|
||||
.drain(..)
|
||||
.map(|f| (f.name, f.size as _))
|
||||
.collect(),
|
||||
json!({}),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1237,7 +1372,7 @@ impl Connection {
|
||||
&self.lr.version,
|
||||
));
|
||||
self.send_fs(ipc::FS::NewWrite {
|
||||
path: r.path,
|
||||
path: r.path.clone(),
|
||||
id: r.id,
|
||||
file_num: r.file_num,
|
||||
files: r
|
||||
@@ -1248,6 +1383,16 @@ impl Connection {
|
||||
.collect(),
|
||||
overwrite_detection: od,
|
||||
});
|
||||
self.post_file_audit(
|
||||
FileAuditType::RemoteReceive,
|
||||
&r.path,
|
||||
r.files
|
||||
.to_vec()
|
||||
.drain(..)
|
||||
.map(|f| (f.name, f.size as _))
|
||||
.collect(),
|
||||
json!({}),
|
||||
);
|
||||
}
|
||||
Some(file_action::Union::RemoveDir(d)) => {
|
||||
self.send_fs(ipc::FS::RemoveDir {
|
||||
@@ -1330,7 +1475,7 @@ impl Connection {
|
||||
}
|
||||
}
|
||||
Some(misc::Union::VideoReceived(_)) => {
|
||||
video_service::notify_video_frame_feched(
|
||||
video_service::notify_video_frame_fetched(
|
||||
self.inner.id,
|
||||
Some(Instant::now().into()),
|
||||
);
|
||||
@@ -1541,10 +1686,10 @@ impl Connection {
|
||||
self.port_forward_socket.take();
|
||||
}
|
||||
|
||||
async fn on_close_manually(&mut self, close_from: &str) {
|
||||
async fn on_close_manually(&mut self, close_from: &str, close_by: &str) {
|
||||
self.close_manually = true;
|
||||
let mut misc = Misc::new();
|
||||
misc.set_close_reason("Closed manually by the peer".into());
|
||||
misc.set_close_reason(format!("Closed manually by the {}", close_by));
|
||||
let mut msg_out = Message::new();
|
||||
msg_out.set_misc(misc);
|
||||
self.send(msg_out).await;
|
||||
@@ -1721,3 +1866,21 @@ mod privacy_mode {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
struct ConnAuditResponse {
|
||||
#[allow(dead_code)]
|
||||
ret: bool,
|
||||
action: String,
|
||||
}
|
||||
|
||||
pub enum AlarmAuditType {
|
||||
IpWhiltelist = 0,
|
||||
ManyWrongPassword = 1,
|
||||
FrequentAttempt = 2,
|
||||
}
|
||||
|
||||
pub enum FileAuditType {
|
||||
RemoteSend = 0,
|
||||
RemoteReceive = 1,
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -4,7 +4,7 @@ use evdev::{
|
||||
uinput::{VirtualDevice, VirtualDeviceBuilder},
|
||||
AttributeSet, EventType, InputEvent,
|
||||
};
|
||||
use hbb_common::{allow_err, bail, log, tokio, ResultType};
|
||||
use hbb_common::{allow_err, bail, log, tokio::{self, runtime::Runtime}, ResultType};
|
||||
|
||||
static IPC_CONN_TIMEOUT: u64 = 1000;
|
||||
static IPC_REQUEST_TIMEOUT: u64 = 1000;
|
||||
@@ -17,24 +17,24 @@ pub mod client {
|
||||
|
||||
pub struct UInputKeyboard {
|
||||
conn: Connection,
|
||||
rt: Runtime,
|
||||
}
|
||||
|
||||
impl UInputKeyboard {
|
||||
pub async fn new() -> ResultType<Self> {
|
||||
let conn = ipc::connect(IPC_CONN_TIMEOUT, IPC_POSTFIX_KEYBOARD).await?;
|
||||
Ok(Self { conn })
|
||||
let rt = Runtime::new()?;
|
||||
Ok(Self { conn, rt })
|
||||
}
|
||||
|
||||
#[tokio::main(flavor = "current_thread")]
|
||||
async fn send(&mut self, data: Data) -> ResultType<()> {
|
||||
self.conn.send(&data).await
|
||||
fn send(&mut self, data: Data) -> ResultType<()> {
|
||||
self.rt.block_on(self.conn.send(&data))
|
||||
}
|
||||
|
||||
#[tokio::main(flavor = "current_thread")]
|
||||
async fn send_get_key_state(&mut self, data: Data) -> ResultType<bool> {
|
||||
self.conn.send(&data).await?;
|
||||
fn send_get_key_state(&mut self, data: Data) -> ResultType<bool> {
|
||||
self.rt.block_on(self.conn.send(&data))?;
|
||||
|
||||
match self.conn.next_timeout(IPC_REQUEST_TIMEOUT).await {
|
||||
match self.rt.block_on(self.conn.next_timeout(IPC_REQUEST_TIMEOUT)) {
|
||||
Ok(Some(Data::KeyboardResponse(ipc::DataKeyboardResponse::GetKeyState(state)))) => {
|
||||
Ok(state)
|
||||
}
|
||||
@@ -101,17 +101,18 @@ pub mod client {
|
||||
|
||||
pub struct UInputMouse {
|
||||
conn: Connection,
|
||||
rt: Runtime,
|
||||
}
|
||||
|
||||
impl UInputMouse {
|
||||
pub async fn new() -> ResultType<Self> {
|
||||
let conn = ipc::connect(IPC_CONN_TIMEOUT, IPC_POSTFIX_MOUSE).await?;
|
||||
Ok(Self { conn })
|
||||
let rt = Runtime::new()?;
|
||||
Ok(Self { conn, rt })
|
||||
}
|
||||
|
||||
#[tokio::main(flavor = "current_thread")]
|
||||
async fn send(&mut self, data: Data) -> ResultType<()> {
|
||||
self.conn.send(&data).await
|
||||
fn send(&mut self, data: Data) -> ResultType<()> {
|
||||
self.rt.block_on(self.conn.send(&data))
|
||||
}
|
||||
|
||||
pub fn send_refresh(&mut self) -> ResultType<()> {
|
||||
@@ -586,6 +587,16 @@ pub mod service {
|
||||
match data {
|
||||
Data::Mouse(data) => {
|
||||
if let DataMouse::Refresh = data {
|
||||
let resolution = RESOLUTION.lock().unwrap();
|
||||
let rng_x = resolution.0.clone();
|
||||
let rng_y = resolution.1.clone();
|
||||
log::info!(
|
||||
"Refresh uinput mouce with rng_x: ({}, {}), rng_y: ({}, {})",
|
||||
rng_x.0,
|
||||
rng_x.1,
|
||||
rng_y.0,
|
||||
rng_y.1
|
||||
);
|
||||
mouse = match mouce::Mouse::new_uinput(rng_x, rng_y) {
|
||||
Ok(mouse) => mouse,
|
||||
Err(e) => {
|
||||
|
||||
@@ -198,7 +198,7 @@ impl VideoQoS {
|
||||
|
||||
#[cfg(target_os = "android")]
|
||||
{
|
||||
// fix when andorid screen shrinks
|
||||
// fix when android screen shrinks
|
||||
let fix = scrap::Display::fix_quality() as u32;
|
||||
log::debug!("Android screen, fix quality:{}", fix);
|
||||
let base_bitrate = base_bitrate * fix;
|
||||
|
||||
@@ -78,11 +78,11 @@ fn is_capturer_mag_supported() -> bool {
|
||||
false
|
||||
}
|
||||
|
||||
pub fn capture_cursor_embeded() -> bool {
|
||||
scrap::is_cursor_embeded()
|
||||
pub fn capture_cursor_embedded() -> bool {
|
||||
scrap::is_cursor_embedded()
|
||||
}
|
||||
|
||||
pub fn notify_video_frame_feched(conn_id: i32, frame_tm: Option<Instant>) {
|
||||
pub fn notify_video_frame_fetched(conn_id: i32, frame_tm: Option<Instant>) {
|
||||
FRAME_FETCHED_NOTIFIER.0.send((conn_id, frame_tm)).unwrap()
|
||||
}
|
||||
|
||||
@@ -146,7 +146,7 @@ impl VideoFrameController {
|
||||
fetched_conn_ids.insert(id);
|
||||
}
|
||||
Ok(None) => {
|
||||
// this branch would nerver be reached
|
||||
// this branch would never be reached
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -162,7 +162,7 @@ fn check_display_changed(
|
||||
last_n: usize,
|
||||
last_current: usize,
|
||||
last_width: usize,
|
||||
last_hegiht: usize,
|
||||
last_height: usize,
|
||||
) -> bool {
|
||||
#[cfg(target_os = "linux")]
|
||||
{
|
||||
@@ -187,7 +187,7 @@ fn check_display_changed(
|
||||
if i != last_current {
|
||||
return true;
|
||||
};
|
||||
if d.width() != last_width || d.height() != last_hegiht {
|
||||
if d.width() != last_width || d.height() != last_height {
|
||||
return true;
|
||||
};
|
||||
}
|
||||
@@ -249,7 +249,7 @@ fn create_capturer(
|
||||
PRIVACY_WINDOW_NAME
|
||||
);
|
||||
}
|
||||
log::debug!("Create maginifier capture for {}", privacy_mode_id);
|
||||
log::debug!("Create magnifier capture for {}", privacy_mode_id);
|
||||
c = Some(Box::new(c1));
|
||||
}
|
||||
Err(e) => {
|
||||
@@ -385,10 +385,12 @@ fn get_capturer(use_yuv: bool, portable_service_running: bool) -> ResultType<Cap
|
||||
captuerer_privacy_mode_id,
|
||||
);
|
||||
|
||||
if privacy_mode_id != captuerer_privacy_mode_id {
|
||||
log::info!("In privacy mode, but show UAC prompt window for now");
|
||||
} else {
|
||||
log::info!("In privacy mode, the peer side cannot watch the screen");
|
||||
if privacy_mode_id != 0 {
|
||||
if privacy_mode_id != captuerer_privacy_mode_id {
|
||||
log::info!("In privacy mode, but show UAC prompt window for now");
|
||||
} else {
|
||||
log::info!("In privacy mode, the peer side cannot watch the screen");
|
||||
}
|
||||
}
|
||||
let capturer = create_capturer(
|
||||
captuerer_privacy_mode_id,
|
||||
@@ -413,7 +415,7 @@ fn run(sp: GenericService) -> ResultType<()> {
|
||||
#[cfg(windows)]
|
||||
ensure_close_virtual_device()?;
|
||||
|
||||
// ensure_inited() is needed because release_resouce() may be called.
|
||||
// ensure_inited() is needed because release_resource() may be called.
|
||||
#[cfg(target_os = "linux")]
|
||||
super::wayland::ensure_inited()?;
|
||||
#[cfg(windows)]
|
||||
@@ -464,7 +466,7 @@ fn run(sp: GenericService) -> ResultType<()> {
|
||||
y: c.origin.1 as _,
|
||||
width: c.width as _,
|
||||
height: c.height as _,
|
||||
cursor_embeded: capture_cursor_embeded(),
|
||||
cursor_embedded: capture_cursor_embedded(),
|
||||
..Default::default()
|
||||
});
|
||||
let mut msg_out = Message::new();
|
||||
@@ -599,7 +601,7 @@ fn run(sp: GenericService) -> ResultType<()> {
|
||||
would_block_count += 1;
|
||||
if !scrap::is_x11() {
|
||||
if would_block_count >= 100 {
|
||||
super::wayland::release_resouce();
|
||||
super::wayland::release_resource();
|
||||
bail!("Wayland capturer none 100 times, try restart captuere");
|
||||
}
|
||||
}
|
||||
@@ -653,7 +655,7 @@ fn run(sp: GenericService) -> ResultType<()> {
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
if !scrap::is_x11() {
|
||||
super::wayland::release_resouce();
|
||||
super::wayland::release_resource();
|
||||
}
|
||||
|
||||
Ok(())
|
||||
@@ -821,7 +823,7 @@ pub(super) fn get_displays_2(all: &Vec<Display>) -> (usize, Vec<DisplayInfo>) {
|
||||
height: d.height() as _,
|
||||
name: d.name(),
|
||||
online: d.is_online(),
|
||||
cursor_embeded: false,
|
||||
cursor_embedded: false,
|
||||
..Default::default()
|
||||
});
|
||||
}
|
||||
|
||||
@@ -129,7 +129,7 @@ pub(super) async fn check_init() -> ResultType<()> {
|
||||
let num = all.len();
|
||||
let (primary, mut displays) = super::video_service::get_displays_2(&all);
|
||||
for display in displays.iter_mut() {
|
||||
display.cursor_embeded = true;
|
||||
display.cursor_embedded = true;
|
||||
}
|
||||
|
||||
let mut rects: Vec<((i32, i32), usize, usize)> = Vec::new();
|
||||
@@ -244,7 +244,7 @@ pub(super) fn get_display_num() -> ResultType<usize> {
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub(super) fn release_resouce() {
|
||||
pub(super) fn release_resource() {
|
||||
if scrap::is_x11() {
|
||||
return;
|
||||
}
|
||||
|
||||
52
src/tray.rs
52
src/tray.rs
@@ -1,3 +1,4 @@
|
||||
#[cfg(any(target_os = "linux", target_os = "windows"))]
|
||||
use super::ui_interface::get_option_opt;
|
||||
#[cfg(target_os = "linux")]
|
||||
use hbb_common::log::{debug, error, info};
|
||||
@@ -44,7 +45,7 @@ pub fn start_tray() {
|
||||
} else {
|
||||
*control_flow = ControlFlow::Wait;
|
||||
}
|
||||
let stopped = is_service_stoped();
|
||||
let stopped = is_service_stopped();
|
||||
let state = if stopped { 2 } else { 1 };
|
||||
let old = *old_state.lock().unwrap();
|
||||
if state != old {
|
||||
@@ -88,6 +89,9 @@ pub fn start_tray() {
|
||||
/// This function will block current execution, show the tray icon and handle events.
|
||||
#[cfg(target_os = "linux")]
|
||||
pub fn start_tray() {
|
||||
use std::time::Duration;
|
||||
|
||||
use glib::{clone, Continue};
|
||||
use gtk::traits::{GtkMenuItemExt, MenuShellExt, WidgetExt};
|
||||
|
||||
info!("configuring tray");
|
||||
@@ -98,7 +102,7 @@ pub fn start_tray() {
|
||||
}
|
||||
if let Some(mut appindicator) = get_default_app_indicator() {
|
||||
let mut menu = gtk::Menu::new();
|
||||
let stoped = is_service_stoped();
|
||||
let stoped = is_service_stopped();
|
||||
// start/stop service
|
||||
let label = if stoped {
|
||||
crate::client::translate("Start Service".to_owned())
|
||||
@@ -106,9 +110,9 @@ pub fn start_tray() {
|
||||
crate::client::translate("Stop service".to_owned())
|
||||
};
|
||||
let menu_item_service = gtk::MenuItem::with_label(label.as_str());
|
||||
menu_item_service.connect_activate(move |item| {
|
||||
menu_item_service.connect_activate(move |_| {
|
||||
let _lock = crate::ui_interface::SENDER.lock().unwrap();
|
||||
update_tray_service_item(item);
|
||||
change_service_state();
|
||||
});
|
||||
menu.append(&menu_item_service);
|
||||
// show tray item
|
||||
@@ -116,6 +120,16 @@ pub fn start_tray() {
|
||||
appindicator.set_menu(&mut menu);
|
||||
// start event loop
|
||||
info!("Setting tray event loop");
|
||||
// check the connection status for every second
|
||||
glib::timeout_add_local(
|
||||
Duration::from_secs(1),
|
||||
clone!(@strong menu_item_service as item => move || {
|
||||
let _lock = crate::ui_interface::SENDER.lock().unwrap();
|
||||
update_tray_service_item(&item);
|
||||
// continue to trigger the next status check
|
||||
Continue(true)
|
||||
}),
|
||||
);
|
||||
gtk::main();
|
||||
} else {
|
||||
error!("Tray process exit now");
|
||||
@@ -123,20 +137,28 @@ pub fn start_tray() {
|
||||
}
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
fn update_tray_service_item(item: >k::MenuItem) {
|
||||
use gtk::traits::GtkMenuItemExt;
|
||||
|
||||
if is_service_stoped() {
|
||||
fn change_service_state() {
|
||||
if is_service_stopped() {
|
||||
debug!("Now try to start service");
|
||||
item.set_label(&crate::client::translate("Stop service".to_owned()));
|
||||
crate::ipc::set_option("stop-service", "");
|
||||
} else {
|
||||
debug!("Now try to stop service");
|
||||
item.set_label(&crate::client::translate("Start Service".to_owned()));
|
||||
crate::ipc::set_option("stop-service", "Y");
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
#[inline]
|
||||
fn update_tray_service_item(item: >k::MenuItem) {
|
||||
use gtk::traits::GtkMenuItemExt;
|
||||
|
||||
if is_service_stopped() {
|
||||
item.set_label(&crate::client::translate("Start Service".to_owned()));
|
||||
} else {
|
||||
item.set_label(&crate::client::translate("Stop service".to_owned()));
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
fn get_default_app_indicator() -> Option<AppIndicator> {
|
||||
use libappindicator::AppIndicatorStatus;
|
||||
@@ -173,7 +195,8 @@ fn get_default_app_indicator() -> Option<AppIndicator> {
|
||||
/// Check if service is stoped.
|
||||
/// Return [`true`] if service is stoped, [`false`] otherwise.
|
||||
#[inline]
|
||||
fn is_service_stoped() -> bool {
|
||||
#[cfg(any(target_os = "linux", target_os = "windows"))]
|
||||
fn is_service_stopped() -> bool {
|
||||
if let Some(v) = get_option_opt("stop-service") {
|
||||
v == "Y"
|
||||
} else {
|
||||
@@ -185,14 +208,14 @@ fn is_service_stoped() -> bool {
|
||||
pub fn make_tray() {
|
||||
use tray_item::TrayItem;
|
||||
let mode = dark_light::detect();
|
||||
let mut icon_path = "";
|
||||
let icon_path;
|
||||
match mode {
|
||||
dark_light::Mode::Dark => {
|
||||
icon_path = "mac-tray-light.png";
|
||||
},
|
||||
}
|
||||
dark_light::Mode::Light => {
|
||||
icon_path = "mac-tray-dark.png";
|
||||
},
|
||||
}
|
||||
}
|
||||
if let Ok(mut tray) = TrayItem::new(&crate::get_app_name(), icon_path) {
|
||||
tray.add_label(&format!(
|
||||
@@ -211,4 +234,3 @@ pub fn make_tray() {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
118
src/ui.rs
118
src/ui.rs
@@ -9,13 +9,8 @@ use sciter::Value;
|
||||
|
||||
use hbb_common::{
|
||||
allow_err,
|
||||
config::{self, Config, PeerConfig, RENDEZVOUS_PORT, RENDEZVOUS_TIMEOUT},
|
||||
futures::future::join_all,
|
||||
config::{self, PeerConfig},
|
||||
log,
|
||||
protobuf::Message as _,
|
||||
rendezvous_proto::*,
|
||||
tcp::FramedStream,
|
||||
tokio,
|
||||
};
|
||||
|
||||
use crate::common::get_app_name;
|
||||
@@ -31,8 +26,6 @@ pub mod remote;
|
||||
#[cfg(target_os = "windows")]
|
||||
pub mod win_privacy;
|
||||
|
||||
type Message = RendezvousMessage;
|
||||
|
||||
pub type Children = Arc<Mutex<(bool, HashMap<(String, String), Child>)>>;
|
||||
#[allow(dead_code)]
|
||||
type Status = (i32, bool, i64, String);
|
||||
@@ -124,12 +117,12 @@ pub fn start(args: &mut [String]) {
|
||||
let args: Vec<String> = iter.map(|x| x.clone()).collect();
|
||||
frame.set_title(&id);
|
||||
frame.register_behavior("native-remote", move || {
|
||||
Box::new(remote::SciterSession::new(
|
||||
cmd.clone(),
|
||||
id.clone(),
|
||||
pass.clone(),
|
||||
args.clone(),
|
||||
))
|
||||
let handler =
|
||||
remote::SciterSession::new(cmd.clone(), id.clone(), pass.clone(), args.clone());
|
||||
#[cfg(not(feature = "flutter"))]
|
||||
crate::keyboard::set_cur_session(handler.inner());
|
||||
|
||||
Box::new(handler)
|
||||
});
|
||||
page = "remote.html";
|
||||
} else {
|
||||
@@ -510,7 +503,7 @@ impl UI {
|
||||
|
||||
fn change_id(&self, id: String) {
|
||||
let old_id = self.get_id();
|
||||
change_id(id, old_id);
|
||||
change_id_shared(id, old_id);
|
||||
}
|
||||
|
||||
fn post_request(&self, url: String, body: String, header: String) {
|
||||
@@ -690,101 +683,6 @@ fn get_sound_inputs() -> Vec<String> {
|
||||
.collect()
|
||||
}
|
||||
|
||||
const INVALID_FORMAT: &'static str = "Invalid format";
|
||||
const UNKNOWN_ERROR: &'static str = "Unknown error";
|
||||
|
||||
#[tokio::main(flavor = "current_thread")]
|
||||
async fn change_id(id: String, old_id: String) -> &'static str {
|
||||
if !hbb_common::is_valid_custom_id(&id) {
|
||||
return INVALID_FORMAT;
|
||||
}
|
||||
let uuid = machine_uid::get().unwrap_or("".to_owned());
|
||||
if uuid.is_empty() {
|
||||
return UNKNOWN_ERROR;
|
||||
}
|
||||
let rendezvous_servers = crate::ipc::get_rendezvous_servers(1_000).await;
|
||||
let mut futs = Vec::new();
|
||||
let err: Arc<Mutex<&str>> = Default::default();
|
||||
for rendezvous_server in rendezvous_servers {
|
||||
let err = err.clone();
|
||||
let id = id.to_owned();
|
||||
let uuid = uuid.clone();
|
||||
let old_id = old_id.clone();
|
||||
futs.push(tokio::spawn(async move {
|
||||
let tmp = check_id(rendezvous_server, old_id, id, uuid).await;
|
||||
if !tmp.is_empty() {
|
||||
*err.lock().unwrap() = tmp;
|
||||
}
|
||||
}));
|
||||
}
|
||||
join_all(futs).await;
|
||||
let err = *err.lock().unwrap();
|
||||
if err.is_empty() {
|
||||
crate::ipc::set_config_async("id", id.to_owned()).await.ok();
|
||||
}
|
||||
err
|
||||
}
|
||||
|
||||
async fn check_id(
|
||||
rendezvous_server: String,
|
||||
old_id: String,
|
||||
id: String,
|
||||
uuid: String,
|
||||
) -> &'static str {
|
||||
let any_addr = Config::get_any_listen_addr();
|
||||
if let Ok(mut socket) = FramedStream::new(
|
||||
crate::check_port(rendezvous_server, RENDEZVOUS_PORT),
|
||||
any_addr,
|
||||
RENDEZVOUS_TIMEOUT,
|
||||
)
|
||||
.await
|
||||
{
|
||||
let mut msg_out = Message::new();
|
||||
msg_out.set_register_pk(RegisterPk {
|
||||
old_id,
|
||||
id,
|
||||
uuid: uuid.into(),
|
||||
..Default::default()
|
||||
});
|
||||
let mut ok = false;
|
||||
if socket.send(&msg_out).await.is_ok() {
|
||||
if let Some(Ok(bytes)) = socket.next_timeout(3_000).await {
|
||||
if let Ok(msg_in) = RendezvousMessage::parse_from_bytes(&bytes) {
|
||||
match msg_in.union {
|
||||
Some(rendezvous_message::Union::RegisterPkResponse(rpr)) => {
|
||||
match rpr.result.enum_value_or_default() {
|
||||
register_pk_response::Result::OK => {
|
||||
ok = true;
|
||||
}
|
||||
register_pk_response::Result::ID_EXISTS => {
|
||||
return "Not available";
|
||||
}
|
||||
register_pk_response::Result::TOO_FREQUENT => {
|
||||
return "Too frequent";
|
||||
}
|
||||
register_pk_response::Result::NOT_SUPPORT => {
|
||||
return "server_not_support";
|
||||
}
|
||||
register_pk_response::Result::INVALID_ID_FORMAT => {
|
||||
return INVALID_FORMAT;
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if !ok {
|
||||
return UNKNOWN_ERROR;
|
||||
}
|
||||
} else {
|
||||
return "Failed to connect to rendezvous server";
|
||||
}
|
||||
""
|
||||
}
|
||||
|
||||
// sacrifice some memory
|
||||
pub fn value_crash_workaround(values: &[Value]) -> Arc<Vec<Value>> {
|
||||
let persist = Arc::new(values.to_vec());
|
||||
|
||||
@@ -45,7 +45,7 @@ div.right-panel {
|
||||
|
||||
div.icon-and-id {
|
||||
flow: horizontal;
|
||||
border-spacing: 1em;
|
||||
border-spacing: 1em;
|
||||
}
|
||||
|
||||
div.icon {
|
||||
@@ -64,7 +64,7 @@ div.id {
|
||||
|
||||
div.permissions {
|
||||
flow: horizontal;
|
||||
border-spacing: 0.5em;
|
||||
border-spacing: 0.5em;
|
||||
}
|
||||
|
||||
div.permissions > div {
|
||||
@@ -141,7 +141,7 @@ button.elevate>span {
|
||||
}
|
||||
|
||||
button.elevate>span>span {
|
||||
margin-left:*;
|
||||
margin-left:*;
|
||||
margin-right:*;
|
||||
}
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
@import url(common.css);
|
||||
@import url(cm.css);
|
||||
</style>
|
||||
<script type="text/tiscript">
|
||||
<script type="text/tiscript">
|
||||
include "common.tis";
|
||||
include "cm.tis";
|
||||
</script>
|
||||
|
||||
@@ -31,7 +31,7 @@ class Body: Reactor.Component
|
||||
var disconnected = c.disconnected;
|
||||
var show_elevation_btn = handler.can_elevate() && show_elevation && !c.is_file_transfer && c.port_forward.length == 0;
|
||||
var show_accept_btn = handler.get_option('approve-mode') != 'password';
|
||||
// below size:* is work around for Linux, it alreayd set in css, but not work, shit sciter
|
||||
// below size:* is work around for Linux, it already set in css, but not work, shit sciter
|
||||
return <div .content style="size:*">
|
||||
<div .left-panel>
|
||||
<div .icon-and-id>
|
||||
|
||||
@@ -56,7 +56,7 @@ button[type=checkbox], button[type=checkbox]:active {
|
||||
|
||||
button.outline {
|
||||
border: color(border) solid 1px;
|
||||
background: transparent;
|
||||
background: transparent;
|
||||
color: color(text);
|
||||
}
|
||||
|
||||
@@ -115,7 +115,7 @@ textarea:empty {
|
||||
.base:disabled { background: transparent; }
|
||||
.slider:hover { background: grey; }
|
||||
.slider:active { background: grey; }
|
||||
.base { size: 16px; }
|
||||
.base { size: 16px; }
|
||||
.corner { background: white; }
|
||||
}
|
||||
|
||||
@@ -185,7 +185,7 @@ header div.window-icon icon {
|
||||
|
||||
header caption {
|
||||
size: *;
|
||||
}
|
||||
}
|
||||
|
||||
@media platform != "OSX" {
|
||||
button.window {
|
||||
|
||||
@@ -12,22 +12,22 @@ div#file-transfer {
|
||||
}
|
||||
|
||||
table
|
||||
{
|
||||
{
|
||||
font: system;
|
||||
border: 1px solid color(border);
|
||||
flow: table-fixed;
|
||||
prototype: Grid;
|
||||
size: *;
|
||||
padding:0;
|
||||
border-spacing: 0;
|
||||
border-spacing: 0;
|
||||
overflow-x: auto;
|
||||
overflow-y: hidden;
|
||||
}
|
||||
|
||||
table > thead {
|
||||
|
||||
table > thead {
|
||||
behavior: column-resizer;
|
||||
border-bottom: color(border) solid 1px;
|
||||
}
|
||||
}
|
||||
|
||||
table > tbody {
|
||||
behavior: select-multiple;
|
||||
@@ -41,20 +41,20 @@ table th {
|
||||
}
|
||||
|
||||
table th
|
||||
{
|
||||
{
|
||||
padding: 4px;
|
||||
foreground-repeat: no-repeat;
|
||||
foreground-position: 50% 3px auto auto;
|
||||
border-left: color(border) solid 1px;
|
||||
}
|
||||
}
|
||||
|
||||
table th.sortable[sort=asc]
|
||||
{
|
||||
table th.sortable[sort=asc]
|
||||
{
|
||||
foreground-image: url(stock:arrow-down);
|
||||
}
|
||||
}
|
||||
|
||||
table th.sortable[sort=desc]
|
||||
{
|
||||
{
|
||||
foreground-image: url(stock:arrow-up);
|
||||
}
|
||||
|
||||
@@ -81,10 +81,10 @@ table.has_current thead th:current {
|
||||
table tr:nth-child(odd) { background-color: white; } /* each odd row */
|
||||
table tr:nth-child(even) { background-color: #F4F5F6; } /* each even row */
|
||||
|
||||
table.has_current tr:current /* current row */
|
||||
{
|
||||
background-color: color(accent);
|
||||
}
|
||||
table.has_current tr:current /* current row */
|
||||
{
|
||||
background-color: color(accent);
|
||||
}
|
||||
|
||||
table.has_current tbody tr:checked
|
||||
{
|
||||
@@ -95,9 +95,9 @@ table.has_current tbody tr:checked td {
|
||||
color: highlighttext;
|
||||
}
|
||||
|
||||
table td
|
||||
{
|
||||
padding: 4px;
|
||||
table td
|
||||
{
|
||||
padding: 4px;
|
||||
text-align: left;
|
||||
font-size: 1em;
|
||||
height: 1.4em;
|
||||
@@ -124,11 +124,11 @@ table td:nth-child(4) {
|
||||
section {
|
||||
size: *;
|
||||
margin: 1em;
|
||||
border-spacing: 0.5em;
|
||||
border-spacing: 0.5em;
|
||||
}
|
||||
|
||||
table td:nth-child(1) {
|
||||
foreground-repeat: no-repeat;
|
||||
foreground-repeat: no-repeat;
|
||||
foreground-position: 50% 50%
|
||||
}
|
||||
|
||||
@@ -160,11 +160,11 @@ div.toolbar > div.button:hover {
|
||||
|
||||
div.toolbar > div.send {
|
||||
flow: horizontal;
|
||||
border-spacing: 0.5em;
|
||||
border-spacing: 0.5em;
|
||||
}
|
||||
|
||||
div.remote > div.send svg {
|
||||
transform: scale(-1, 1);
|
||||
transform: scale(-1, 1);
|
||||
}
|
||||
|
||||
div.navbar {
|
||||
@@ -207,7 +207,7 @@ table.job-table tr td {
|
||||
padding: 0.5em 1em;
|
||||
border-bottom: color(border) 1px solid;
|
||||
flow: horizontal;
|
||||
border-spacing: 1em;
|
||||
border-spacing: 1em;
|
||||
height: 3em;
|
||||
overflow-x: hidden;
|
||||
}
|
||||
@@ -217,11 +217,11 @@ table.job-table tr svg {
|
||||
}
|
||||
|
||||
table.job-table tr.is_remote svg {
|
||||
transform: scale(-1, 1);
|
||||
transform: scale(-1, 1);
|
||||
}
|
||||
|
||||
table.job-table tr.is_remote div.svg_continue svg {
|
||||
transform: scale(1, 1);
|
||||
transform: scale(1, 1);
|
||||
}
|
||||
|
||||
table.job-table tr td div.text {
|
||||
@@ -246,7 +246,7 @@ table#port-forward thead tr th {
|
||||
|
||||
table#port-forward tr td {
|
||||
height: 3em;
|
||||
text-align: left;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
table#port-forward input[type=text], table#port-forward input[type=number] {
|
||||
|
||||
@@ -8,7 +8,7 @@ header #screens {
|
||||
height: 22px;
|
||||
border-radius: 4px;
|
||||
flow: horizontal;
|
||||
border-spacing: 0.5em;
|
||||
border-spacing: 0.5em;
|
||||
padding-right: 1em;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
@@ -164,10 +164,10 @@ class Header: Reactor.Component {
|
||||
var codecs = handler.supported_hwcodec();
|
||||
var show_codec = handler.has_hwcodec() && (codecs[0] || codecs[1]);
|
||||
|
||||
var cursor_embeded = false;
|
||||
var cursor_embedded = false;
|
||||
if ((pi.displays || []).length > 0) {
|
||||
if (pi.displays.length > pi.current_display) {
|
||||
cursor_embeded = pi.displays[pi.current_display].cursor_embeded;
|
||||
cursor_embedded = pi.displays[pi.current_display].cursor_embedded;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -191,7 +191,7 @@ class Header: Reactor.Component {
|
||||
{codecs[1] ? <li #h265 type="codec-preference"><span>{svg_checkmark}</span>H265</li> : ""}
|
||||
</div> : ""}
|
||||
<div .separator />
|
||||
{!cursor_embeded && <li #show-remote-cursor .toggle-option><span>{svg_checkmark}</span>{translate('Show remote cursor')}</li>}
|
||||
{!cursor_embedded && <li #show-remote-cursor .toggle-option><span>{svg_checkmark}</span>{translate('Show remote cursor')}</li>}
|
||||
<li #show-quality-monitor .toggle-option><span>{svg_checkmark}</span>{translate('Show quality monitor')}</li>
|
||||
{audio_enabled ? <li #disable-audio .toggle-option><span>{svg_checkmark}</span>{translate('Mute')}</li> : ""}
|
||||
{is_win && pi.platform == 'Windows' && file_enabled ? <li #enable-file-transfer .toggle-option><span>{svg_checkmark}</span>{translate('Allow file copy and paste')}</li> : ""}
|
||||
@@ -208,7 +208,7 @@ class Header: Reactor.Component {
|
||||
{keyboard_enabled ? <li #os-password>{translate('OS Password')}<EditOsPassword /></li> : ""}
|
||||
<li #transfer-file>{translate('Transfer File')}</li>
|
||||
<li #tunnel>{translate('TCP Tunneling')}</li>
|
||||
{handler.get_audit_server() && <li #note>{translate('Note')}</li>}
|
||||
{handler.get_audit_server("conn") && <li #note>{translate('Note')}</li>}
|
||||
<div .separator />
|
||||
{keyboard_enabled && (pi.platform == "Linux" || pi.sas_enabled) ? <li #ctrl-alt-del>{translate('Insert')} Ctrl + Alt + Del</li> : ""}
|
||||
{restart_enabled && (pi.platform == "Linux" || pi.platform == "Windows" || pi.platform == "Mac OS") ? <li #restart_remote_device>{translate('Restart Remote Device')}</li> : ""}
|
||||
|
||||
@@ -361,7 +361,7 @@ class MyIdMenu: Reactor.Component {
|
||||
|
||||
function showAbout() {
|
||||
var name = handler.get_app_name();
|
||||
msgbox("custom-nocancel-nook-hasclose", "About " + name, "<div style='line-height: 2em'> \
|
||||
msgbox("custom-nocancel-nook-hasclose", translate("About") + " " + name, "<div style='line-height: 2em'> \
|
||||
<div>Version: " + handler.get_version() + " \
|
||||
<div .link .custom-event url='https://rustdesk.com/privacy'>Privacy Statement</div> \
|
||||
<div .link .custom-event url='https://rustdesk.com'>Website</div> \
|
||||
|
||||
@@ -13,7 +13,6 @@ use objc::{
|
||||
};
|
||||
use sciter::{make_args, Host};
|
||||
use std::{ffi::c_void, rc::Rc};
|
||||
use dark_light;
|
||||
|
||||
static APP_HANDLER_IVAR: &str = "GoDeskAppHandler";
|
||||
|
||||
|
||||
@@ -79,8 +79,8 @@ impl InvokeUiSession for SciterHandler {
|
||||
}
|
||||
}
|
||||
|
||||
fn set_display(&self, x: i32, y: i32, w: i32, h: i32, cursor_embeded: bool) {
|
||||
self.call("setDisplay", &make_args!(x, y, w, h, cursor_embeded));
|
||||
fn set_display(&self, x: i32, y: i32, w: i32, h: i32, cursor_embedded: bool) {
|
||||
self.call("setDisplay", &make_args!(x, y, w, h, cursor_embedded));
|
||||
// https://sciter.com/forums/topic/color_spaceiyuv-crash
|
||||
// Nothing spectacular in decoder – done on CPU side.
|
||||
// So if you can do BGRA translation on your side – the better.
|
||||
@@ -223,7 +223,7 @@ impl InvokeUiSession for SciterHandler {
|
||||
display.set_item("y", d.y);
|
||||
display.set_item("width", d.width);
|
||||
display.set_item("height", d.height);
|
||||
display.set_item("cursor_embeded", d.cursor_embeded);
|
||||
display.set_item("cursor_embedded", d.cursor_embedded);
|
||||
displays.push(display);
|
||||
}
|
||||
pi_sciter.set_item("displays", displays);
|
||||
@@ -231,6 +231,17 @@ impl InvokeUiSession for SciterHandler {
|
||||
self.call("updatePi", &make_args!(pi_sciter));
|
||||
}
|
||||
|
||||
fn on_connected(&self, conn_type: ConnType) {
|
||||
match conn_type {
|
||||
ConnType::RDP => {}
|
||||
ConnType::PORT_FORWARD => {}
|
||||
ConnType::FILE_TRANSFER => {}
|
||||
ConnType::DEFAULT_CONN => {
|
||||
crate::keyboard::client::start_grab_loop();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn msgbox(&self, msgtype: &str, title: &str, text: &str, link: &str, retry: bool) {
|
||||
self.call2(
|
||||
"msgbox_retry",
|
||||
@@ -337,7 +348,7 @@ impl sciter::EventHandler for SciterSession {
|
||||
}
|
||||
|
||||
sciter::dispatch_script_call! {
|
||||
fn get_audit_server();
|
||||
fn get_audit_server(String);
|
||||
fn send_note(String);
|
||||
fn is_xfce();
|
||||
fn get_id();
|
||||
@@ -434,6 +445,10 @@ impl SciterSession {
|
||||
Self(session)
|
||||
}
|
||||
|
||||
pub fn inner(&self) -> Session<SciterHandler> {
|
||||
self.0.clone()
|
||||
}
|
||||
|
||||
fn get_custom_image_quality(&mut self) -> Value {
|
||||
let mut v = Value::array(0);
|
||||
for x in self.lc.read().unwrap().custom_image_quality.iter() {
|
||||
|
||||
@@ -6,7 +6,7 @@ var display_width = 0;
|
||||
var display_height = 0;
|
||||
var display_origin_x = 0;
|
||||
var display_origin_y = 0;
|
||||
var display_cursor_embeded = false;
|
||||
var display_cursor_embedded = false;
|
||||
var display_scale = 1;
|
||||
var keyboard_enabled = true; // server side
|
||||
var clipboard_enabled = true; // server side
|
||||
@@ -16,17 +16,17 @@ var restart_enabled = true; // server side
|
||||
var recording_enabled = true; // server side
|
||||
var scroll_body = $(body);
|
||||
|
||||
handler.setDisplay = function(x, y, w, h, cursor_embeded) {
|
||||
handler.setDisplay = function(x, y, w, h, cursor_embedded) {
|
||||
display_width = w;
|
||||
display_height = h;
|
||||
display_origin_x = x;
|
||||
display_origin_y = y;
|
||||
display_cursor_embeded = cursor_embeded;
|
||||
display_cursor_embedded = cursor_embedded;
|
||||
adaptDisplay();
|
||||
if (recording) handler.record_screen(true, w, h);
|
||||
}
|
||||
|
||||
// in case toolbar not shown correclty
|
||||
// in case toolbar not shown correctly
|
||||
view.windowMinSize = (scaleIt(500), scaleIt(300));
|
||||
|
||||
function adaptDisplay() {
|
||||
@@ -197,7 +197,7 @@ function handler.onMouse(evt)
|
||||
dragging = false;
|
||||
break;
|
||||
case Event.MOUSE_MOVE:
|
||||
if (display_cursor_embeded) {
|
||||
if (display_cursor_embedded) {
|
||||
break;
|
||||
}
|
||||
if (cursor_img.style#display != "none" && keyboard_enabled) {
|
||||
@@ -365,7 +365,7 @@ function updateCursor(system=false) {
|
||||
}
|
||||
|
||||
function refreshCursor() {
|
||||
if (display_cursor_embeded) {
|
||||
if (display_cursor_embedded) {
|
||||
cursor_img.style#display = "none";
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -14,20 +14,17 @@ use hbb_common::{
|
||||
tokio::{self, sync::mpsc, time},
|
||||
};
|
||||
|
||||
#[cfg(any(target_os = "android", target_os = "ios", feature = "flutter"))]
|
||||
use hbb_common::{
|
||||
config::{RENDEZVOUS_PORT, RENDEZVOUS_TIMEOUT},
|
||||
futures::future::join_all,
|
||||
protobuf::Message as _,
|
||||
rendezvous_proto::*,
|
||||
tcp::FramedStream,
|
||||
};
|
||||
|
||||
#[cfg(feature = "flutter")]
|
||||
use crate::hbbs_http::account;
|
||||
use crate::{common::SOFTWARE_UPDATE_URL, ipc};
|
||||
|
||||
#[cfg(any(target_os = "android", target_os = "ios", feature = "flutter"))]
|
||||
type Message = RendezvousMessage;
|
||||
|
||||
pub type Children = Arc<Mutex<(bool, HashMap<(String, String), Child>)>>;
|
||||
@@ -161,6 +158,7 @@ pub fn get_license() -> String {
|
||||
}
|
||||
|
||||
#[inline]
|
||||
#[cfg(any(target_os = "linux", target_os = "windows"))]
|
||||
pub fn get_option_opt(key: &str) -> Option<String> {
|
||||
OPTIONS.lock().unwrap().get(key).map(|x| x.clone())
|
||||
}
|
||||
@@ -202,6 +200,18 @@ pub fn set_local_flutter_config(key: String, value: String) {
|
||||
LocalConfig::set_flutter_config(key, value);
|
||||
}
|
||||
|
||||
#[cfg(feature = "flutter")]
|
||||
#[inline]
|
||||
pub fn get_kb_layout_type() -> String {
|
||||
LocalConfig::get_kb_layout_type()
|
||||
}
|
||||
|
||||
#[cfg(feature = "flutter")]
|
||||
#[inline]
|
||||
pub fn set_kb_layout_type(kb_layout_type: String) {
|
||||
LocalConfig::set_kb_layout_type(kb_layout_type);
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn peer_has_password(id: String) -> bool {
|
||||
!PeerConfig::load(&id).password.is_empty()
|
||||
@@ -572,6 +582,14 @@ pub fn is_installed_daemon(_prompt: bool) -> bool {
|
||||
return true;
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn is_can_input_monitoring(_prompt: bool) -> bool {
|
||||
#[cfg(target_os = "macos")]
|
||||
return crate::platform::macos::is_can_input_monitoring(_prompt);
|
||||
#[cfg(not(target_os = "macos"))]
|
||||
return true;
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn get_error() -> String {
|
||||
#[cfg(not(any(feature = "cli")))]
|
||||
@@ -742,7 +760,7 @@ pub fn change_id(id: String) {
|
||||
*ASYNC_JOB_STATUS.lock().unwrap() = " ".to_owned();
|
||||
let old_id = get_id();
|
||||
std::thread::spawn(move || {
|
||||
*ASYNC_JOB_STATUS.lock().unwrap() = change_id_(id, old_id).to_owned();
|
||||
*ASYNC_JOB_STATUS.lock().unwrap() = change_id_shared(id, old_id).to_owned();
|
||||
});
|
||||
}
|
||||
|
||||
@@ -999,14 +1017,11 @@ pub(crate) async fn send_to_cm(data: &ipc::Data) {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(any(target_os = "android", target_os = "ios", feature = "flutter"))]
|
||||
const INVALID_FORMAT: &'static str = "Invalid format";
|
||||
#[cfg(any(target_os = "android", target_os = "ios", feature = "flutter"))]
|
||||
const UNKNOWN_ERROR: &'static str = "Unknown error";
|
||||
|
||||
#[cfg(any(target_os = "android", target_os = "ios", feature = "flutter"))]
|
||||
#[tokio::main(flavor = "current_thread")]
|
||||
async fn change_id_(id: String, old_id: String) -> &'static str {
|
||||
pub async fn change_id_shared(id: String, old_id: String) -> &'static str {
|
||||
if !hbb_common::is_valid_custom_id(&id) {
|
||||
return INVALID_FORMAT;
|
||||
}
|
||||
@@ -1054,17 +1069,14 @@ async fn change_id_(id: String, old_id: String) -> &'static str {
|
||||
err
|
||||
}
|
||||
|
||||
#[cfg(any(target_os = "android", target_os = "ios", feature = "flutter"))]
|
||||
async fn check_id(
|
||||
rendezvous_server: String,
|
||||
old_id: String,
|
||||
id: String,
|
||||
uuid: String,
|
||||
) -> &'static str {
|
||||
let any_addr = Config::get_any_listen_addr();
|
||||
if let Ok(mut socket) = FramedStream::new(
|
||||
if let Ok(mut socket) = hbb_common::socket_client::connect_tcp(
|
||||
crate::check_port(rendezvous_server, RENDEZVOUS_PORT),
|
||||
any_addr,
|
||||
RENDEZVOUS_TIMEOUT,
|
||||
)
|
||||
.await
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user