Skip to content

Commit

Permalink
Try to maintain the original format
Browse files Browse the repository at this point in the history
  • Loading branch information
Borber committed Feb 9, 2024
1 parent 6ff3550 commit 8b859f1
Show file tree
Hide file tree
Showing 8 changed files with 113 additions and 60 deletions.
6 changes: 5 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,12 @@

## [0.2.3]

### 新年快乐! Happy New Year!

- 调整翻译界面样式
- 安装 Fire Code 字体将使英语结果更加美观
- (可选) 安装 Fire Code 字体将使英语结果更加美观
- 尽量维持原格式, 对换行和空格进行特殊处理
- ![tran](https://fastly.jsdelivr.net/gh/Borber/PublicPic1/tran/v1/tran-new-line.png)

## [0.2.2]

Expand Down
3 changes: 2 additions & 1 deletion src-tauri/src/common.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,12 @@ use std::sync::{atomic::AtomicBool, Arc};
use once_cell::sync::Lazy;
use reqwest::Client;

use crate::manager;
use crate::{config, manager};

pub static CLIENT: Lazy<Client> = Lazy::new(Client::new);
pub static PIN: Lazy<Arc<AtomicBool>> = Lazy::new(|| Arc::new(AtomicBool::new(false)));

pub async fn init() {
config::load();
manager::mirror::init().await;
}
34 changes: 20 additions & 14 deletions src-tauri/src/config.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
use std::sync::Arc;
use std::sync::{
atomic::{AtomicBool, Ordering},
Arc,
};

use anyhow::Result;
use once_cell::sync::Lazy;
use parking_lot::Mutex;
use serde::{Deserialize, Serialize};

use crate::util;
Expand All @@ -12,49 +14,53 @@ use crate::util;
/// Config
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Config {
/// 模式, 0: 镜像模式, 1: 直连模式
/// 模式, true: 镜像模式, false: 直连模式
///
/// Mode, 0: mirror mode, 1: direct mode
pub mode: usize,
/// Mode, true: mirror mode, false: direct mode
pub mode: bool,
}

/// 全局配置
///
/// Global config
pub static CONFIG: Lazy<Arc<Mutex<Config>>> = Lazy::new(|| Arc::new(Mutex::new(load())));
pub static MODE: Lazy<Arc<AtomicBool>> = Lazy::new(|| Arc::new(AtomicBool::new(true)));

/// 读取配置
///
/// read config
pub fn load() -> Config {
pub fn load() {
let exe_dir = util::get_exe_dir();
let path = exe_dir.join("config.json");
// 检测文件是否存在
// Check if file exists
let exists = path.try_exists();
if exists.is_ok() && exists.expect("Failed to check if file exists") {
let config = std::fs::read_to_string(path).expect("Failed to read config");
serde_json::from_str(&config).expect("Failed to parse config")
let config = serde_json::from_str::<Config>(&config).expect("Failed to parse config");
MODE.store(config.mode, Ordering::SeqCst);
} else {
Config { mode: 0 }
MODE.store(true, Ordering::SeqCst);
}
}

/// 保存配置
///
/// save config
fn save(config: &Config) -> Result<()> {
fn save() -> Result<()> {
let config = Config {
mode: MODE.load(Ordering::SeqCst),
};
let exe_dir = util::get_exe_dir();
let path = exe_dir.join("config.json");
let config = serde_json::to_string_pretty(config).expect("Failed to serialize config");
let config = serde_json::to_string_pretty(&config).expect("Failed to serialize config");
std::fs::write(path, config).expect("Failed to write config");
Ok(())
}

/// 切换模式
///
/// switch mode
pub fn mode(mode: usize) {
CONFIG.lock().mode = mode;
save(&CONFIG.lock()).expect("Failed to save config after switch mode");
pub fn mode(mode: bool) {
MODE.store(mode, Ordering::SeqCst);
save().expect("Failed to save config after switch mode");
}
17 changes: 1 addition & 16 deletions src-tauri/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,14 +39,6 @@ fn copy(content: String) -> Resp<()> {
clip::set(content).into()
}

/// 切换模式
///
/// Switch mode
#[tauri::command]
fn switch_mode(mode: usize) {
config::mode(mode);
}

/// 打开指定链接
///
/// Open the specified link
Expand Down Expand Up @@ -104,14 +96,7 @@ async fn main() {
.plugin(tauri_plugin_process::init())
.plugin(tauri_plugin_single_instance::init(|_, _, _| {}))
.setup(setup::handler)
.invoke_handler(tauri::generate_handler![
copy,
open,
translate,
switch_mode,
pin,
update,
])
.invoke_handler(tauri::generate_handler![copy, open, translate, pin, update,])
.run(context)
.expect("error while running tauri application");
}
81 changes: 59 additions & 22 deletions src-tauri/src/manager/api.rs
Original file line number Diff line number Diff line change
@@ -1,17 +1,19 @@
use std::sync::atomic::Ordering;

use anyhow::Result;
use percent_encoding::{utf8_percent_encode, NON_ALPHANUMERIC};
use reqwest::Client;
use serde::Serialize;

use crate::{common::CLIENT, config::CONFIG, lang, manager::mirror};
use crate::{common::CLIENT, config::MODE, lang, manager::mirror};

/// 翻译结果
#[derive(Debug, Serialize)]
pub struct TransVO {
/// 是否为单词
pub word: bool,
/// 翻译结果
pub trans: Option<String>,
pub trans: Option<Vec<Tran>>,
/// 词典
pub dicts: Option<Vec<Dict>>,
}
Expand All @@ -22,24 +24,33 @@ pub struct Dict {
pub terms: Vec<String>,
}

#[derive(Debug, Serialize)]
pub struct Tran {
// 0: 文本
// 1: 换行
// 2: 空格
pub typ: u64,
pub data: Option<String>,
}

pub async fn translate(content: &str) -> Result<TransVO> {
// 翻译目标语言
let lang = lang::lang(content);

// 转换为 url 编码
let content = utf8_percent_encode(content, NON_ALPHANUMERIC).to_string();

let mode = CONFIG.lock().mode;
let host = match mode {
0 => mirror::one(),
_ => "https://translate.googleapis.com".to_string(),
let host = if MODE.load(Ordering::SeqCst) {
mirror::one()
} else {
"https://translate.googleapis.com".to_string()
};
send(&CLIENT, host, &lang, &content).await
}

async fn send(client: &Client, host: String, lang: &str, content: &str) -> Result<TransVO> {
let resp = client
.get(format!("{}/translate_a/single?client=gtx&sl=auto&tl={}&dj=1&dt=t&dt=bd&dt=qc&dt=rm&dt=ex&dt=at&dt=ss&dt=rw&dt=ld&q=%22{}%22", host, lang, content))
.get(format!("{}/translate_a/single?client=gtx&sl=auto&tl={}&dj=1&dt=t&dt=bd&dt=qc&dt=rm&dt=ex&dt=at&dt=ss&dt=rw&dt=ld&q={}", host, lang, content))
.header("Accept", "application/json, text/plain, */*")
.header("Accept-Encoding", "gzip")
.header("Accept-Language", "zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6")
Expand Down Expand Up @@ -83,24 +94,50 @@ async fn send(client: &Client, host: String, lang: &str, content: &str) -> Resul
vec![]
}
};
let trans = tran_list
.into_iter()
.map(|x| x["trans"].as_str().unwrap_or_default().to_string())
.collect::<Vec<String>>()
.join("");

let trans = trans
.trim()
.trim_matches('"')
.trim_matches('“')
.trim_matches('”')
.trim_matches('「')
.trim_matches('」')
.trim_matches('《')
.trim_matches('》');
let mut result = vec![];
for trans in tran_list {
let trans = trans["trans"].as_str().unwrap_or_default();
let mut tmp = String::new();

for c in trans.chars() {
match c {
'\r' => {
// Assuming '\r' is always followed by '\n' and they indicate a new 'Tran' type 1.
if !tmp.is_empty() {
result.push(Tran {
typ: 0,
data: Some(tmp.clone()),
});
tmp.clear();
}
result.push(Tran { typ: 1, data: None });
}
'\n' => {
// Do nothing assuming '\n' is always preceded by '\r', handled above.
}
' ' => {
result.push(Tran {
typ: 0,
data: Some(tmp.clone()),
});
tmp.clear();
result.push(Tran { typ: 2, data: None });
}
_ => tmp.push(c),
}
}
if !tmp.is_empty() {
result.push(Tran {
typ: 0,
data: Some(tmp),
});
}
}

let result = TransVO {
word: false,
trans: Some(trans.to_string()),
trans: Some(result),
dicts: None,
};
Ok(result)
Expand Down
4 changes: 2 additions & 2 deletions src-tauri/src/tray.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,8 @@ fn handler(app: &AppHandle, event: MenuEvent) {
"github" => {
let _ = open::that("https://github.com/Borber/Tran");
}
"mirror" => config::mode(0),
"google" => config::mode(1),
"mirror" => config::mode(true),
"google" => config::mode(false),
"exit" => {
let panel = app.get_webview_window("panel").unwrap();
let _ = panel.hide();
Expand Down
1 change: 1 addition & 0 deletions src/App.css
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@
background-color: #262a30;
overflow-x: hidden;
overflow-y: scroll;
word-wrap: break-word;
hyphens: auto;

line-height: 1.2;
Expand Down
27 changes: 23 additions & 4 deletions src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import { Resp } from "./model/resp"

interface TransVO {
word: boolean
trans: string
trans: Tran[]
dicts: Dict[]
}

Expand All @@ -22,6 +22,11 @@ interface Dict {
terms: string[]
}

interface Tran {
typ: number
data: string
}

const App = () => {
const panel = getCurrent()
const [result, Result] = createSignal<TransVO>()
Expand Down Expand Up @@ -90,13 +95,15 @@ const App = () => {
data-tauri-drag-region
class="result"
// 因为全局的可拖拽导致双击正好能触发点击事件
onClick={async () => {
onClick={async (e) => {
console.log("copy")
let content
if (result() == undefined) {
return
} else if (!result()?.word) {
content = result()!.trans
content = e.target.innerHTML
.replace(/<br>/g, "\r\n")
.replace(/&nbsp;/g, " ")
} else {
content = result()!.dicts[0].terms[0]
}
Expand Down Expand Up @@ -131,7 +138,19 @@ const App = () => {
)}
</For>
</Match>
<Match when={!result()?.word}>{result()?.trans}</Match>
<Match when={!result()?.word}>
<For each={result()!.trans}>
{(tran) => {
if (tran.typ == 0) {
return tran.data
} else if (tran.typ == 1) {
return <br />
} else {
return `\u00A0`
}
}}
</For>
</Match>
</Switch>
</div>
<Show when={update()}>
Expand Down

0 comments on commit 8b859f1

Please sign in to comment.