|
|
|
|
@ -1,332 +1,344 @@
|
|
|
|
|
package com.smartlibrary.android.service;
|
|
|
|
|
|
|
|
|
|
import android.content.Context;
|
|
|
|
|
import android.util.Log;
|
|
|
|
|
|
|
|
|
|
import com.smartlibrary.android.ai.AIConfig;
|
|
|
|
|
|
|
|
|
|
import org.json.JSONArray;
|
|
|
|
|
import org.json.JSONObject;
|
|
|
|
|
|
|
|
|
|
import java.io.BufferedReader;
|
|
|
|
|
import java.io.InputStreamReader;
|
|
|
|
|
import java.io.OutputStream;
|
|
|
|
|
import java.net.HttpURLConnection;
|
|
|
|
|
import java.net.URL;
|
|
|
|
|
import java.util.HashMap;
|
|
|
|
|
import java.util.Map;
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* AI跨语种实时翻译服务 - 基于DeepSeek API
|
|
|
|
|
*
|
|
|
|
|
* 功能:
|
|
|
|
|
* 1. OCR文字识别
|
|
|
|
|
* 2. 多语种翻译(DeepSeek API)
|
|
|
|
|
* 3. 难度适配(儿童版/成人版)
|
|
|
|
|
* 4. 语音朗读翻译结果
|
|
|
|
|
*/
|
|
|
|
|
public class TranslationService {
|
|
|
|
|
|
|
|
|
|
private static final String TAG = "TranslationService";
|
|
|
|
|
|
|
|
|
|
private static TranslationService instance;
|
|
|
|
|
private Context context;
|
|
|
|
|
private boolean useDeepSeekAPI = true; // 是否使用DeepSeek API
|
|
|
|
|
|
|
|
|
|
// 支持的语言
|
|
|
|
|
public static final String LANG_ZH = "zh"; // 中文
|
|
|
|
|
public static final String LANG_EN = "en"; // 英文
|
|
|
|
|
public static final String LANG_JA = "ja"; // 日文
|
|
|
|
|
public static final String LANG_KO = "ko"; // 韩文
|
|
|
|
|
public static final String LANG_FR = "fr"; // 法文
|
|
|
|
|
public static final String LANG_DE = "de"; // 德文
|
|
|
|
|
public static final String LANG_ES = "es"; // 西班牙文
|
|
|
|
|
|
|
|
|
|
// 翻译难度
|
|
|
|
|
public static final int LEVEL_CHILD = 1; // 儿童版(简化)
|
|
|
|
|
public static final int LEVEL_NORMAL = 2; // 普通版
|
|
|
|
|
public static final int LEVEL_PROFESSIONAL = 3; // 专业版(精准)
|
|
|
|
|
|
|
|
|
|
private TranslationService(Context context) {
|
|
|
|
|
this.context = context.getApplicationContext();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static synchronized TranslationService getInstance(Context context) {
|
|
|
|
|
if (instance == null) {
|
|
|
|
|
instance = new TranslationService(context);
|
|
|
|
|
}
|
|
|
|
|
return instance;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 翻译结果
|
|
|
|
|
*/
|
|
|
|
|
public static class TranslationResult {
|
|
|
|
|
public String originalText;
|
|
|
|
|
public String translatedText;
|
|
|
|
|
public String sourceLanguage;
|
|
|
|
|
public String targetLanguage;
|
|
|
|
|
public int difficultyLevel;
|
|
|
|
|
public double confidence;
|
|
|
|
|
public String pronunciation; // 发音(拼音/音标)
|
|
|
|
|
public String[] keywords; // 关键词
|
|
|
|
|
public String notes; // 注释说明
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 翻译文本
|
|
|
|
|
*/
|
|
|
|
|
public TranslationResult translate(String text, String sourceLang, String targetLang, int level) {
|
|
|
|
|
TranslationResult result = new TranslationResult();
|
|
|
|
|
result.originalText = text;
|
|
|
|
|
result.sourceLanguage = sourceLang;
|
|
|
|
|
result.targetLanguage = targetLang;
|
|
|
|
|
result.difficultyLevel = level;
|
|
|
|
|
|
|
|
|
|
// 使用DeepSeek API或本地模拟翻译
|
|
|
|
|
if (useDeepSeekAPI) {
|
|
|
|
|
result.translatedText = translateWithDeepSeek(text, sourceLang, targetLang, level);
|
|
|
|
|
result.confidence = 0.95;
|
|
|
|
|
} else {
|
|
|
|
|
result.translatedText = simulateTranslation(text, sourceLang, targetLang, level);
|
|
|
|
|
result.confidence = 0.7;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
result.pronunciation = generatePronunciation(result.translatedText, targetLang);
|
|
|
|
|
result.keywords = extractKeywords(text);
|
|
|
|
|
result.notes = generateNotes(text, level);
|
|
|
|
|
|
|
|
|
|
Log.d(TAG, "翻译完成: " + sourceLang + " -> " + targetLang + " (DeepSeek: " + useDeepSeekAPI + ")");
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 自动检测语言并翻译
|
|
|
|
|
*/
|
|
|
|
|
public TranslationResult autoTranslate(String text, String targetLang, int level) {
|
|
|
|
|
String detectedLang = detectLanguage(text);
|
|
|
|
|
return translate(text, detectedLang, targetLang, level);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 检测文本语言
|
|
|
|
|
* 使用字符遍历代替正则表达式,避免ReDoS攻击
|
|
|
|
|
*/
|
|
|
|
|
public String detectLanguage(String text) {
|
|
|
|
|
if (text == null || text.isEmpty()) return LANG_EN;
|
|
|
|
|
|
|
|
|
|
// 使用字符遍历检测语言,避免正则表达式回溯攻击
|
|
|
|
|
for (int i = 0; i < text.length(); i++) {
|
|
|
|
|
char c = text.charAt(i);
|
|
|
|
|
// 检测中文字符 (CJK统一汉字)
|
|
|
|
|
if (c >= '\u4e00' && c <= '\u9fa5') {
|
|
|
|
|
return LANG_ZH;
|
|
|
|
|
}
|
|
|
|
|
// 检测日文字符 (平假名和片假名)
|
|
|
|
|
if ((c >= '\u3040' && c <= '\u309f') || (c >= '\u30a0' && c <= '\u30ff')) {
|
|
|
|
|
return LANG_JA;
|
|
|
|
|
}
|
|
|
|
|
// 检测韩文字符 (韩文音节)
|
|
|
|
|
if (c >= '\uac00' && c <= '\ud7af') {
|
|
|
|
|
return LANG_KO;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return LANG_EN;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 使用DeepSeek API进行翻译
|
|
|
|
|
*/
|
|
|
|
|
private String translateWithDeepSeek(String text, String sourceLang, String targetLang, int level) {
|
|
|
|
|
try {
|
|
|
|
|
String sourceName = getLanguageName(sourceLang);
|
|
|
|
|
String targetName = getLanguageName(targetLang);
|
|
|
|
|
|
|
|
|
|
// 构建翻译提示词
|
|
|
|
|
String levelHint = "";
|
|
|
|
|
if (level == LEVEL_CHILD) {
|
|
|
|
|
levelHint = "请使用简单易懂的词汇,适合儿童阅读理解。";
|
|
|
|
|
} else if (level == LEVEL_PROFESSIONAL) {
|
|
|
|
|
levelHint = "请保持专业术语的准确性,提供精准翻译。";
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
String prompt = String.format(
|
|
|
|
|
"请将以下%s文本翻译成%s。%s只返回翻译结果,不要添加任何解释。\n\n原文:%s",
|
|
|
|
|
sourceName, targetName, levelHint, text
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
// 调用DeepSeek API
|
|
|
|
|
URL url = new URL(AIConfig.DEEPSEEK_API_URL);
|
|
|
|
|
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
|
|
|
|
|
conn.setRequestMethod("POST");
|
|
|
|
|
conn.setRequestProperty("Content-Type", "application/json");
|
|
|
|
|
conn.setRequestProperty("Authorization", "Bearer " + AIConfig.DEEPSEEK_API_KEY);
|
|
|
|
|
conn.setConnectTimeout(AIConfig.CONNECTION_TIMEOUT);
|
|
|
|
|
conn.setReadTimeout(AIConfig.READ_TIMEOUT);
|
|
|
|
|
conn.setDoOutput(true);
|
|
|
|
|
|
|
|
|
|
// 构建请求体
|
|
|
|
|
JSONObject requestBody = new JSONObject();
|
|
|
|
|
requestBody.put("model", AIConfig.DEEPSEEK_MODEL);
|
|
|
|
|
|
|
|
|
|
JSONArray messages = new JSONArray();
|
|
|
|
|
JSONObject systemMsg = new JSONObject();
|
|
|
|
|
systemMsg.put("role", "system");
|
|
|
|
|
systemMsg.put("content", "你是一个专业的多语种翻译助手,擅长准确、流畅地翻译各种语言的文本。");
|
|
|
|
|
messages.put(systemMsg);
|
|
|
|
|
|
|
|
|
|
JSONObject userMsg = new JSONObject();
|
|
|
|
|
userMsg.put("role", "user");
|
|
|
|
|
userMsg.put("content", prompt);
|
|
|
|
|
messages.put(userMsg);
|
|
|
|
|
|
|
|
|
|
requestBody.put("messages", messages);
|
|
|
|
|
requestBody.put("temperature", 0.3);
|
|
|
|
|
requestBody.put("max_tokens", 2000);
|
|
|
|
|
|
|
|
|
|
// 发送请求
|
|
|
|
|
try (OutputStream os = conn.getOutputStream()) {
|
|
|
|
|
byte[] input = requestBody.toString().getBytes("utf-8");
|
|
|
|
|
os.write(input, 0, input.length);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 读取响应
|
|
|
|
|
int responseCode = conn.getResponseCode();
|
|
|
|
|
if (responseCode == HttpURLConnection.HTTP_OK) {
|
|
|
|
|
BufferedReader br = new BufferedReader(new InputStreamReader(conn.getInputStream(), "utf-8"));
|
|
|
|
|
StringBuilder response = new StringBuilder();
|
|
|
|
|
String line;
|
|
|
|
|
while ((line = br.readLine()) != null) {
|
|
|
|
|
response.append(line);
|
|
|
|
|
}
|
|
|
|
|
br.close();
|
|
|
|
|
|
|
|
|
|
// 解析响应
|
|
|
|
|
JSONObject jsonResponse = new JSONObject(response.toString());
|
|
|
|
|
JSONArray choices = jsonResponse.getJSONArray("choices");
|
|
|
|
|
if (choices.length() > 0) {
|
|
|
|
|
JSONObject choice = choices.getJSONObject(0);
|
|
|
|
|
JSONObject message = choice.getJSONObject("message");
|
|
|
|
|
return message.getString("content").trim();
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
Log.e(TAG, "DeepSeek API错误: " + responseCode);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
conn.disconnect();
|
|
|
|
|
} catch (Exception e) {
|
|
|
|
|
Log.e(TAG, "DeepSeek翻译失败", e);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 失败时使用本地模拟翻译
|
|
|
|
|
return simulateTranslation(text, sourceLang, targetLang, level);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 本地模拟翻译(备用方案)
|
|
|
|
|
*/
|
|
|
|
|
private String simulateTranslation(String text, String sourceLang, String targetLang, int level) {
|
|
|
|
|
// 简单的模拟翻译词典
|
|
|
|
|
Map<String, String> enToZh = new HashMap<>();
|
|
|
|
|
enToZh.put("hello", "你好");
|
|
|
|
|
enToZh.put("world", "世界");
|
|
|
|
|
enToZh.put("book", "书籍");
|
|
|
|
|
enToZh.put("library", "图书馆");
|
|
|
|
|
enToZh.put("read", "阅读");
|
|
|
|
|
enToZh.put("welcome", "欢迎");
|
|
|
|
|
enToZh.put("smart", "智能");
|
|
|
|
|
|
|
|
|
|
if (LANG_EN.equals(sourceLang) && LANG_ZH.equals(targetLang)) {
|
|
|
|
|
String result = text.toLowerCase();
|
|
|
|
|
for (Map.Entry<String, String> entry : enToZh.entrySet()) {
|
|
|
|
|
result = result.replace(entry.getKey(), entry.getValue());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (level == LEVEL_CHILD) {
|
|
|
|
|
return "【简化版】" + result;
|
|
|
|
|
}
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return "[翻译] " + text;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 设置是否使用DeepSeek API
|
|
|
|
|
*/
|
|
|
|
|
public void setUseDeepSeekAPI(boolean use) {
|
|
|
|
|
this.useDeepSeekAPI = use;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 生成发音
|
|
|
|
|
*/
|
|
|
|
|
private String generatePronunciation(String text, String lang) {
|
|
|
|
|
if (LANG_ZH.equals(lang)) {
|
|
|
|
|
return "[拼音] " + text; // 实际应用中生成拼音
|
|
|
|
|
} else if (LANG_EN.equals(lang)) {
|
|
|
|
|
return "[音标] /" + text.toLowerCase() + "/";
|
|
|
|
|
}
|
|
|
|
|
return "";
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 提取关键词
|
|
|
|
|
*/
|
|
|
|
|
private String[] extractKeywords(String text) {
|
|
|
|
|
// 简单的关键词提取
|
|
|
|
|
String[] words = text.split("\\s+");
|
|
|
|
|
if (words.length <= 5) return words;
|
|
|
|
|
|
|
|
|
|
String[] keywords = new String[5];
|
|
|
|
|
System.arraycopy(words, 0, keywords, 0, 5);
|
|
|
|
|
return keywords;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 生成注释说明
|
|
|
|
|
*/
|
|
|
|
|
private String generateNotes(String text, int level) {
|
|
|
|
|
if (level == LEVEL_CHILD) {
|
|
|
|
|
return "💡 这段文字已简化为适合儿童阅读的版本";
|
|
|
|
|
} else if (level == LEVEL_PROFESSIONAL) {
|
|
|
|
|
return "📚 这是专业精准翻译,保留了原文的专业术语";
|
|
|
|
|
}
|
|
|
|
|
return "";
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 获取支持的语言列表
|
|
|
|
|
*/
|
|
|
|
|
public Map<String, String> getSupportedLanguages() {
|
|
|
|
|
Map<String, String> languages = new HashMap<>();
|
|
|
|
|
languages.put(LANG_ZH, "中文");
|
|
|
|
|
languages.put(LANG_EN, "English");
|
|
|
|
|
languages.put(LANG_JA, "日本語");
|
|
|
|
|
languages.put(LANG_KO, "한국어");
|
|
|
|
|
languages.put(LANG_FR, "Français");
|
|
|
|
|
languages.put(LANG_DE, "Deutsch");
|
|
|
|
|
languages.put(LANG_ES, "Español");
|
|
|
|
|
return languages;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 获取语言显示名称
|
|
|
|
|
*/
|
|
|
|
|
public String getLanguageName(String langCode) {
|
|
|
|
|
Map<String, String> languages = getSupportedLanguages();
|
|
|
|
|
return languages.getOrDefault(langCode, langCode);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 批量翻译
|
|
|
|
|
*/
|
|
|
|
|
public TranslationResult[] batchTranslate(String[] texts, String sourceLang, String targetLang, int level) {
|
|
|
|
|
TranslationResult[] results = new TranslationResult[texts.length];
|
|
|
|
|
for (int i = 0; i < texts.length; i++) {
|
|
|
|
|
results[i] = translate(texts[i], sourceLang, targetLang, level);
|
|
|
|
|
}
|
|
|
|
|
return results;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
package com.smartlibrary.android.service;
|
|
|
|
|
|
|
|
|
|
import android.content.Context;
|
|
|
|
|
import android.util.Log;
|
|
|
|
|
|
|
|
|
|
import com.smartlibrary.android.ai.AIConfig;
|
|
|
|
|
|
|
|
|
|
import org.json.JSONArray;
|
|
|
|
|
import org.json.JSONObject;
|
|
|
|
|
|
|
|
|
|
import java.io.BufferedReader;
|
|
|
|
|
import java.io.InputStreamReader;
|
|
|
|
|
import java.io.OutputStream;
|
|
|
|
|
import java.net.HttpURLConnection;
|
|
|
|
|
import java.net.URL;
|
|
|
|
|
import java.util.HashMap;
|
|
|
|
|
import java.util.Map;
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* AI跨语种实时翻译服务 - 基于DeepSeek API
|
|
|
|
|
*
|
|
|
|
|
* 功能:
|
|
|
|
|
* 1. OCR文字识别
|
|
|
|
|
* 2. 多语种翻译(DeepSeek API)
|
|
|
|
|
* 3. 难度适配(儿童版/成人版)
|
|
|
|
|
* 4. 语音朗读翻译结果
|
|
|
|
|
*/
|
|
|
|
|
public class TranslationService {
|
|
|
|
|
|
|
|
|
|
private static final String TAG = "TranslationService";
|
|
|
|
|
|
|
|
|
|
private static TranslationService instance;
|
|
|
|
|
private Context context;
|
|
|
|
|
private boolean useDeepSeekAPI = true; // 是否使用DeepSeek API
|
|
|
|
|
|
|
|
|
|
// 支持的语言
|
|
|
|
|
public static final String LANG_ZH = "zh"; // 中文
|
|
|
|
|
public static final String LANG_EN = "en"; // 英文
|
|
|
|
|
public static final String LANG_JA = "ja"; // 日文
|
|
|
|
|
public static final String LANG_KO = "ko"; // 韩文
|
|
|
|
|
public static final String LANG_FR = "fr"; // 法文
|
|
|
|
|
public static final String LANG_DE = "de"; // 德文
|
|
|
|
|
public static final String LANG_ES = "es"; // 西班牙文
|
|
|
|
|
|
|
|
|
|
// 翻译难度
|
|
|
|
|
public static final int LEVEL_CHILD = 1; // 儿童版(简化)
|
|
|
|
|
public static final int LEVEL_NORMAL = 2; // 普通版
|
|
|
|
|
public static final int LEVEL_PROFESSIONAL = 3; // 专业版(精准)
|
|
|
|
|
|
|
|
|
|
private TranslationService(Context context) {
|
|
|
|
|
this.context = context.getApplicationContext();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static synchronized TranslationService getInstance(Context context) {
|
|
|
|
|
if (instance == null) {
|
|
|
|
|
instance = new TranslationService(context);
|
|
|
|
|
}
|
|
|
|
|
return instance;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 翻译结果
|
|
|
|
|
*/
|
|
|
|
|
public static class TranslationResult {
|
|
|
|
|
public String originalText;
|
|
|
|
|
public String translatedText;
|
|
|
|
|
public String sourceLanguage;
|
|
|
|
|
public String targetLanguage;
|
|
|
|
|
public int difficultyLevel;
|
|
|
|
|
public double confidence;
|
|
|
|
|
public String pronunciation; // 发音(拼音/音标)
|
|
|
|
|
public String[] keywords; // 关键词
|
|
|
|
|
public String notes; // 注释说明
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 翻译文本
|
|
|
|
|
*/
|
|
|
|
|
public TranslationResult translate(String text, String sourceLang, String targetLang, int level) {
|
|
|
|
|
TranslationResult result = new TranslationResult();
|
|
|
|
|
result.originalText = text;
|
|
|
|
|
result.sourceLanguage = sourceLang;
|
|
|
|
|
result.targetLanguage = targetLang;
|
|
|
|
|
result.difficultyLevel = level;
|
|
|
|
|
|
|
|
|
|
// 使用DeepSeek API或本地模拟翻译
|
|
|
|
|
if (useDeepSeekAPI) {
|
|
|
|
|
result.translatedText = translateWithDeepSeek(text, sourceLang, targetLang, level);
|
|
|
|
|
result.confidence = 0.95;
|
|
|
|
|
} else {
|
|
|
|
|
result.translatedText = simulateTranslation(text, sourceLang, targetLang, level);
|
|
|
|
|
result.confidence = 0.7;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
result.pronunciation = generatePronunciation(result.translatedText, targetLang);
|
|
|
|
|
result.keywords = extractKeywords(text);
|
|
|
|
|
result.notes = generateNotes(text, level);
|
|
|
|
|
|
|
|
|
|
Log.d(TAG, "翻译完成: " + sourceLang + " -> " + targetLang + " (DeepSeek: " + useDeepSeekAPI + ")");
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 自动检测语言并翻译
|
|
|
|
|
*/
|
|
|
|
|
public TranslationResult autoTranslate(String text, String targetLang, int level) {
|
|
|
|
|
String detectedLang = detectLanguage(text);
|
|
|
|
|
return translate(text, detectedLang, targetLang, level);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 检测文本语言
|
|
|
|
|
* 使用字符遍历代替正则表达式,避免ReDoS攻击
|
|
|
|
|
*/
|
|
|
|
|
public String detectLanguage(String text) {
|
|
|
|
|
if (text == null || text.isEmpty()) return LANG_EN;
|
|
|
|
|
|
|
|
|
|
// 使用字符遍历检测语言,避免正则表达式回溯攻击
|
|
|
|
|
for (int i = 0; i < text.length(); i++) {
|
|
|
|
|
char c = text.charAt(i);
|
|
|
|
|
// 检测中文字符 (CJK统一汉字)
|
|
|
|
|
if (c >= '\u4e00' && c <= '\u9fa5') {
|
|
|
|
|
return LANG_ZH;
|
|
|
|
|
}
|
|
|
|
|
// 检测日文字符 (平假名和片假名)
|
|
|
|
|
if ((c >= '\u3040' && c <= '\u309f') || (c >= '\u30a0' && c <= '\u30ff')) {
|
|
|
|
|
return LANG_JA;
|
|
|
|
|
}
|
|
|
|
|
// 检测韩文字符 (韩文音节)
|
|
|
|
|
if (c >= '\uac00' && c <= '\ud7af') {
|
|
|
|
|
return LANG_KO;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return LANG_EN;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 使用DeepSeek API进行翻译
|
|
|
|
|
*/
|
|
|
|
|
private String translateWithDeepSeek(String text, String sourceLang, String targetLang, int level) {
|
|
|
|
|
try {
|
|
|
|
|
String sourceName = getLanguageName(sourceLang);
|
|
|
|
|
String targetName = getLanguageName(targetLang);
|
|
|
|
|
|
|
|
|
|
// 构建翻译提示词
|
|
|
|
|
String levelHint = "";
|
|
|
|
|
if (level == LEVEL_CHILD) {
|
|
|
|
|
levelHint = "请使用简单易懂的词汇,适合儿童阅读理解。";
|
|
|
|
|
} else if (level == LEVEL_PROFESSIONAL) {
|
|
|
|
|
levelHint = "请保持专业术语的准确性,提供精准翻译。";
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
String prompt = String.format(
|
|
|
|
|
"请将以下%s文本翻译成%s。%s只返回翻译结果,不要添加任何解释。\n\n原文:%s",
|
|
|
|
|
sourceName, targetName, levelHint, text
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
// 调用DeepSeek API
|
|
|
|
|
URL url = new URL(AIConfig.DEEPSEEK_API_URL);
|
|
|
|
|
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
|
|
|
|
|
conn.setRequestMethod("POST");
|
|
|
|
|
conn.setRequestProperty("Content-Type", "application/json");
|
|
|
|
|
conn.setRequestProperty("Authorization", "Bearer " + AIConfig.DEEPSEEK_API_KEY);
|
|
|
|
|
conn.setConnectTimeout(AIConfig.CONNECTION_TIMEOUT);
|
|
|
|
|
conn.setReadTimeout(AIConfig.READ_TIMEOUT);
|
|
|
|
|
conn.setDoOutput(true);
|
|
|
|
|
|
|
|
|
|
// 构建请求体
|
|
|
|
|
JSONObject requestBody = new JSONObject();
|
|
|
|
|
requestBody.put("model", AIConfig.DEEPSEEK_MODEL);
|
|
|
|
|
|
|
|
|
|
JSONArray messages = new JSONArray();
|
|
|
|
|
JSONObject systemMsg = new JSONObject();
|
|
|
|
|
systemMsg.put("role", "system");
|
|
|
|
|
systemMsg.put("content", "你是一个专业的多语种翻译助手,擅长准确、流畅地翻译各种语言的文本。");
|
|
|
|
|
messages.put(systemMsg);
|
|
|
|
|
|
|
|
|
|
JSONObject userMsg = new JSONObject();
|
|
|
|
|
userMsg.put("role", "user");
|
|
|
|
|
userMsg.put("content", prompt);
|
|
|
|
|
messages.put(userMsg);
|
|
|
|
|
|
|
|
|
|
requestBody.put("messages", messages);
|
|
|
|
|
requestBody.put("temperature", 0.3);
|
|
|
|
|
requestBody.put("max_tokens", 2000);
|
|
|
|
|
|
|
|
|
|
// 发送请求
|
|
|
|
|
try (OutputStream os = conn.getOutputStream()) {
|
|
|
|
|
byte[] input = requestBody.toString().getBytes("utf-8");
|
|
|
|
|
os.write(input, 0, input.length);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 读取响应
|
|
|
|
|
int responseCode = conn.getResponseCode();
|
|
|
|
|
if (responseCode == HttpURLConnection.HTTP_OK) {
|
|
|
|
|
BufferedReader br = new BufferedReader(new InputStreamReader(conn.getInputStream(), "utf-8"));
|
|
|
|
|
StringBuilder response = new StringBuilder();
|
|
|
|
|
String line;
|
|
|
|
|
while ((line = br.readLine()) != null) {
|
|
|
|
|
response.append(line);
|
|
|
|
|
}
|
|
|
|
|
br.close();
|
|
|
|
|
|
|
|
|
|
// 解析响应 - 添加JSON解析异常处理
|
|
|
|
|
try {
|
|
|
|
|
JSONObject jsonResponse = new JSONObject(response.toString());
|
|
|
|
|
if (jsonResponse.has("choices")) {
|
|
|
|
|
JSONArray choices = jsonResponse.getJSONArray("choices");
|
|
|
|
|
if (choices.length() > 0) {
|
|
|
|
|
JSONObject choice = choices.getJSONObject(0);
|
|
|
|
|
if (choice.has("message")) {
|
|
|
|
|
JSONObject message = choice.getJSONObject("message");
|
|
|
|
|
if (message.has("content")) {
|
|
|
|
|
return message.getString("content").trim();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
Log.w(TAG, "DeepSeek API响应格式异常: 缺少必要字段");
|
|
|
|
|
} catch (JSONException e) {
|
|
|
|
|
Log.e(TAG, "DeepSeek API响应JSON解析失败: " + e.getMessage());
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
Log.e(TAG, "DeepSeek API错误: " + responseCode);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
conn.disconnect();
|
|
|
|
|
} catch (Exception e) {
|
|
|
|
|
Log.e(TAG, "DeepSeek翻译失败", e);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 失败时使用本地模拟翻译
|
|
|
|
|
return simulateTranslation(text, sourceLang, targetLang, level);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 本地模拟翻译(备用方案)
|
|
|
|
|
*/
|
|
|
|
|
private String simulateTranslation(String text, String sourceLang, String targetLang, int level) {
|
|
|
|
|
// 简单的模拟翻译词典
|
|
|
|
|
Map<String, String> enToZh = new HashMap<>();
|
|
|
|
|
enToZh.put("hello", "你好");
|
|
|
|
|
enToZh.put("world", "世界");
|
|
|
|
|
enToZh.put("book", "书籍");
|
|
|
|
|
enToZh.put("library", "图书馆");
|
|
|
|
|
enToZh.put("read", "阅读");
|
|
|
|
|
enToZh.put("welcome", "欢迎");
|
|
|
|
|
enToZh.put("smart", "智能");
|
|
|
|
|
|
|
|
|
|
if (LANG_EN.equals(sourceLang) && LANG_ZH.equals(targetLang)) {
|
|
|
|
|
String result = text.toLowerCase();
|
|
|
|
|
for (Map.Entry<String, String> entry : enToZh.entrySet()) {
|
|
|
|
|
result = result.replace(entry.getKey(), entry.getValue());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (level == LEVEL_CHILD) {
|
|
|
|
|
return "【简化版】" + result;
|
|
|
|
|
}
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return "[翻译] " + text;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 设置是否使用DeepSeek API
|
|
|
|
|
*/
|
|
|
|
|
public void setUseDeepSeekAPI(boolean use) {
|
|
|
|
|
this.useDeepSeekAPI = use;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 生成发音
|
|
|
|
|
*/
|
|
|
|
|
private String generatePronunciation(String text, String lang) {
|
|
|
|
|
if (LANG_ZH.equals(lang)) {
|
|
|
|
|
return "[拼音] " + text; // 实际应用中生成拼音
|
|
|
|
|
} else if (LANG_EN.equals(lang)) {
|
|
|
|
|
return "[音标] /" + text.toLowerCase() + "/";
|
|
|
|
|
}
|
|
|
|
|
return "";
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 提取关键词
|
|
|
|
|
*/
|
|
|
|
|
private String[] extractKeywords(String text) {
|
|
|
|
|
// 简单的关键词提取
|
|
|
|
|
String[] words = text.split("\\s+");
|
|
|
|
|
if (words.length <= 5) return words;
|
|
|
|
|
|
|
|
|
|
String[] keywords = new String[5];
|
|
|
|
|
System.arraycopy(words, 0, keywords, 0, 5);
|
|
|
|
|
return keywords;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 生成注释说明
|
|
|
|
|
*/
|
|
|
|
|
private String generateNotes(String text, int level) {
|
|
|
|
|
if (level == LEVEL_CHILD) {
|
|
|
|
|
return "💡 这段文字已简化为适合儿童阅读的版本";
|
|
|
|
|
} else if (level == LEVEL_PROFESSIONAL) {
|
|
|
|
|
return "📚 这是专业精准翻译,保留了原文的专业术语";
|
|
|
|
|
}
|
|
|
|
|
return "";
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 获取支持的语言列表
|
|
|
|
|
*/
|
|
|
|
|
public Map<String, String> getSupportedLanguages() {
|
|
|
|
|
Map<String, String> languages = new HashMap<>();
|
|
|
|
|
languages.put(LANG_ZH, "中文");
|
|
|
|
|
languages.put(LANG_EN, "English");
|
|
|
|
|
languages.put(LANG_JA, "日本語");
|
|
|
|
|
languages.put(LANG_KO, "한국어");
|
|
|
|
|
languages.put(LANG_FR, "Français");
|
|
|
|
|
languages.put(LANG_DE, "Deutsch");
|
|
|
|
|
languages.put(LANG_ES, "Español");
|
|
|
|
|
return languages;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 获取语言显示名称
|
|
|
|
|
*/
|
|
|
|
|
public String getLanguageName(String langCode) {
|
|
|
|
|
Map<String, String> languages = getSupportedLanguages();
|
|
|
|
|
return languages.getOrDefault(langCode, langCode);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 批量翻译
|
|
|
|
|
*/
|
|
|
|
|
public TranslationResult[] batchTranslate(String[] texts, String sourceLang, String targetLang, int level) {
|
|
|
|
|
TranslationResult[] results = new TranslationResult[texts.length];
|
|
|
|
|
for (int i = 0; i < texts.length; i++) {
|
|
|
|
|
results[i] = translate(texts[i], sourceLang, targetLang, level);
|
|
|
|
|
}
|
|
|
|
|
return results;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|