杂谈 #Java脚本
因本人英语不好在使用Obsidian时,一些插件的设置英文多令人头痛。故有写一个的翻译插件介绍和设置脚本的想法。看到有些前人写的一下翻译方法,简直惨目忍睹。竟然要手动。这个应该写好到只需要一键就可以汉化的地步吗?
好吧。我承认这有些难度。翻译引擎就用有道的吧。我觉得它对专业名词的翻译准确度还是很高的。
- 提取main.js中需要的词句
- 使用有道API来翻译并生成对应的文件
- 使用Quicker的插件一键替换
这里不想详细写过程了,直接贴代码吧。以后有空再整合。
main.js处理代码:(用了FastJson里面的工具,需要导入)
import com.alibaba.fastjson.JSON;
import java.io.*;
import java.util.LinkedList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* @author ShuangLian
* @date 2022/7/4 1:07
*/
public class test {
public static void main(String[] args) throws IOException {
// 需要翻译的插件对应的main.js文件
File file = new File(\"C:\\\\Users\\\\91324\\\\Documents\\\\Projects\\\\IdeaProjects\\\\Test-demo\\\\src\\\\test\\\\java\\\\cn\\\\lian\\\\main.js\");
System.out.println(file.getAbsolutePath());
FileInputStream stream = new FileInputStream(file);
InputStreamReader reader = new InputStreamReader(stream);
BufferedReader bufferedReader = new BufferedReader(reader);
LinkedList<String> list = new LinkedList<>();
String line;
while ((line = bufferedReader.readLine()) != null) {
// 匹配要翻译的部分
String s_setName = \"setName\\\\([^\\\\)]+\\\\)\";
String s_addOption = \"addOption\\\\([^\\\\)]+\\\\)\";
String s_setDesc = \"setDesc\\\\([^\\\\)]+\\\\)*\\\"\\\\)\";
String s_name = \"name: \\\".*\\\",\";
// 使用正则查找匹配
List<String> linkedList;
if ((linkedList = find(s_setName, line)).size() != 0) {
for (String s : linkedList) {
list.add(s.substring(9, s.length() - 2));
}
}
if ((linkedList = find(s_setDesc, line)).size() != 0) {
for (String s : linkedList) {
list.add(s.substring(9, s.length() - 2));
}
}
if ((linkedList = find(s_addOption, line)).size() != 0) {
for (String ss : linkedList) {
String substring = ss.substring(10, ss.length() - 1);
String[] split = substring.split(\",\");
for (String s : split) {
s = s.strip();
list.add(s.substring(1, s.length() - 1));
}
}
}
if ((linkedList = find(s_name, line)).size() != 0) {
for (String s : linkedList) {
list.add(s.substring(7, s.length() - 2));
}
}
}
System.out.println(list);
bufferedReader.close();
// 输出汉英对照.txt
File file1 = new File(\".\\\\test2.txt\");
FileOutputStream fileOutputStream = new FileOutputStream(file1);
// 指定输出文件编码为gbk,不知道为啥做替换插件的那个2b不使用UTF-8
OutputStreamWriter outputStreamWriter = new OutputStreamWriter(fileOutputStream, \"gbk\");
// OutputStreamWriter outputStreamWriter = new OutputStreamWriter(fileOutputStream);
BufferedWriter writer = new BufferedWriter(outputStreamWriter);
for (String s : list) {
writer.append(s).append(\"\\n\");
String query = FanyiV3Demo.query(s);
String translation = JSON.parseObject(query).getJSONArray(\"translation\").get(0).toString();
writer.append(translation).append(\"\\n\");
}
writer.flush();
}
public static List<String> find(String regex, String str) {
List<String> strings = new LinkedList<>();
Pattern p = Pattern.compile(regex);
Matcher matcher = p.matcher(str);
while (matcher.find()) {
String fundStr = str.substring(matcher.start(), matcher.end());
System.out.println(fundStr);
strings.add(fundStr);
}
return strings;
}
}
有道翻译Java SDK改装
/**
* @author ShuangLian
* @date 2022/7/4 3:49
*/
import org.apache.http.Header;
import org.apache.http.HttpEntity;
import org.apache.http.NameValuePair;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.*;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.*;
/**
* 由有道提供,直接调用query方法即可
* 返回示例:
* {
* \"tSpeakUrl\": \"https://openapi.youdao.com/ttsapi?\",
* \"requestId\": \"afc14ed2-e6ca-49fe-8f8f-b36e6ff5bbaa\",
* \"query\": \"Preview on Hover for File Links\",
* \"translation\": [
* \"预览悬停文件链接\"
* ],
* \"errorCode\": \"0\",
* \"dict\": {
* \"url\": \"yddict://m.youdao.com/dict?le=eng&q=Preview+on+Hover+for+File+Links\"
* },
* \"webdict\": {
* \"url\": \"http://mobile.youdao.com/dict?le=eng&q=Preview+on+Hover+for+File+Links\"
* },
* \"l\": \"en2zh-CHS\",
* \"isWord\": false,
* \"speakUrl\": \"https://openapi.youdao.com/ttsapi?\"
* }
*/
public class FanyiV3Demo {
private static Logger logger = LoggerFactory.getLogger(FanyiV3Demo.class);
private static final String YOUDAO_URL = \"https://openapi.youdao.com/api\";
// 去有道查看,这里不能直接用
private static final String APP_KEY = \"1fcc4\";
//
private static final String APP_SECRET = \"LgA5Wxpm60KP7nyuGp\";
public static void main(String[] args) throws IOException {
Map<String, String> params = new HashMap<String, String>();
String q = \"Decrease body font size\";
String salt = String.valueOf(System.currentTimeMillis());
params.put(\"from\", \"en\");
params.put(\"to\", \"zh-CHS\");
params.put(\"signType\", \"v3\");
String curtime = String.valueOf(System.currentTimeMillis() / 1000);
params.put(\"curtime\", curtime);
String signStr = APP_KEY + truncate(q) + salt + curtime + APP_SECRET;
String sign = getDigest(signStr);
params.put(\"appKey\", APP_KEY);
params.put(\"q\", q);
params.put(\"salt\", salt);
params.put(\"sign\", sign);
params.put(\"vocabId\", \"您的用户词表ID\");
/** 处理结果 */
requestForHttp(YOUDAO_URL, params);
}
public static String query(String Str) throws IOException {
Map<String, String> params = new HashMap<String, String>();
String q = Str;
String salt = String.valueOf(System.currentTimeMillis());
params.put(\"from\", \"en\");
params.put(\"to\", \"zh-CHS\");
params.put(\"signType\", \"v3\");
String curtime = String.valueOf(System.currentTimeMillis() / 1000);
params.put(\"curtime\", curtime);
String signStr = APP_KEY + truncate(q) + salt + curtime + APP_SECRET;
String sign = getDigest(signStr);
params.put(\"appKey\", APP_KEY);
params.put(\"q\", q);
params.put(\"salt\", salt);
params.put(\"sign\", sign);
params.put(\"vocabId\", \"您的用户词表ID\");
/** 处理结果 */
return requestForHttp(YOUDAO_URL, params);
}
public static String requestForHttp(String url, Map<String, String> params) throws IOException {
String json = null;
/** 创建HttpClient */
CloseableHttpClient httpClient = HttpClients.createDefault();
/** httpPost */
HttpPost httpPost = new HttpPost(url);
List<NameValuePair> paramsList = new ArrayList<NameValuePair>();
Iterator<Map.Entry<String, String>> it = params.entrySet().iterator();
while (it.hasNext()) {
Map.Entry<String, String> en = it.next();
String key = en.getKey();
String value = en.getValue();
paramsList.add(new BasicNameValuePair(key, value));
}
httpPost.setEntity(new UrlEncodedFormEntity(paramsList, \"UTF-8\"));
CloseableHttpResponse httpResponse = httpClient.execute(httpPost);
try {
Header[] contentType = httpResponse.getHeaders(\"Content-Type\");
logger.info(\"Content-Type:\" + contentType[0].getValue());
if (\"audio/mp3\".equals(contentType[0].getValue())) {
//如果响应是wav
HttpEntity httpEntity = httpResponse.getEntity();
ByteArrayOutputStream baos = new ByteArrayOutputStream();
httpResponse.getEntity().writeTo(baos);
byte[] result = baos.toByteArray();
EntityUtils.consume(httpEntity);
if (result != null) {//合成成功
String file = \"合成的音频存储路径\" + System.currentTimeMillis() + \".mp3\";
byte2File(result, file);
}
} else {
/** 响应不是音频流,直接显示结果 */
HttpEntity httpEntity = httpResponse.getEntity();
json = EntityUtils.toString(httpEntity, \"UTF-8\");
EntityUtils.consume(httpEntity);
logger.info(json);
System.out.println(json);
}
} finally {
try {
if (httpResponse != null) {
httpResponse.close();
}
} catch (IOException e) {
logger.info(\"## release resouce error ##\" + e);
}
}
return json;
}
/**
* 生成加密字段
*/
public static String getDigest(String string) {
if (string == null) {
return null;
}
char hexDigits[] = {\'0\', \'1\', \'2\', \'3\', \'4\', \'5\', \'6\', \'7\', \'8\', \'9\', \'A\', \'B\', \'C\', \'D\', \'E\', \'F\'};
byte[] btInput = string.getBytes(StandardCharsets.UTF_8);
try {
MessageDigest mdInst = MessageDigest.getInstance(\"SHA-256\");
mdInst.update(btInput);
byte[] md = mdInst.digest();
int j = md.length;
char str[] = new char[j * 2];
int k = 0;
for (byte byte0 : md) {
str[k++] = hexDigits[byte0 >>> 4 & 0xf];
str[k++] = hexDigits[byte0 & 0xf];
}
return new String(str);
} catch (NoSuchAlgorithmException e) {
return null;
}
}
/**
* @param result 音频字节流
* @param file 存储路径
*/
private static void byte2File(byte[] result, String file) {
File audioFile = new File(file);
FileOutputStream fos = null;
try {
fos = new FileOutputStream(audioFile);
fos.write(result);
} catch (Exception e) {
logger.info(e.toString());
} finally {
if (fos != null) {
try {
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
public static String truncate(String q) {
if (q == null) {
return null;
}
int len = q.length();
String result;
return len <= 20 ? q : (q.substring(0, 10) + len + q.substring(len - 10, len));
}
}
还有一个问题:
Quicker插件只是替换功能,有可能会替换到正文的单词。这里应该是需要再使用正则匹配一遍。干脆改成只用java来处理吧。
来源:https://www.cnblogs.com/lians/p/16444103.html
本站部分图文来源于网络,如有侵权请联系删除。