日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

TextTranslatorOpenSource-文本翻译器开源版

發布時間:2023/12/8 编程问答 31 豆豆
生活随笔 收集整理的這篇文章主要介紹了 TextTranslatorOpenSource-文本翻译器开源版 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

TextTranslatorOpenSource-文本翻譯器開源版

僅用于學習研究之用,請勿商用

介紹

【文本翻譯器】是一款免費的簡潔實用的翻譯軟件。文本翻譯器應用程序完全免費,可以非常快速翻譯您的單詞,幫助您與外國人交流。文本翻譯器適用于旅行者、學生、商人和其他語言愛好者,使用文本翻譯器可以輕松了解其他語言。文本翻譯器支持多國語言,全新領先的翻譯引擎,讓各種變得更加可靠有保證。界面設計簡潔、優雅,體積小巧,但是功能很強大哦。趕快下載來試試吧~

功能特點:

*【詞典解析】除了基本的翻譯外,提供更詳細的詞典功能,詞性分類
*【多語言】目前支持主流語言:中文,中文繁體,英語,日語,法語,德語
*【單詞本】收藏喜歡的單詞
*【歷史記錄】記錄翻譯記錄
*【離線翻譯】如果已經翻譯過的即使沒有網絡也能翻譯
*【數據備份和恢復】備份歷史翻譯記錄和恢復記錄
*【自動朗讀】翻譯后為您朗讀
*【自動復制】將翻譯文本自動復制到剪貼板
*【全局復制查詞】在任何界面點復制就能查單詞
*【免費】使用功能過程中完全免費
*【界面簡潔】界面設計優雅、簡潔

展示

如果無法顯示圖片,請移步到這里

下載

Google Play

https://play.google.com/store/apps/details?id=com.allever.app.translation.text

Baidu

https://shouji.baidu.com/software/26838949.html

項目地址

https://github.com/devallever/TranslationTextOpenSource

項目架構

項目采用多組件 + MVP 架構

項目組件架構圖

  • common:通用模塊,包括基類和通用工具類,基本上所有模塊都依賴此模塊
  • commont:評分模塊
  • permission:申請權限模塊
  • recomend:推廣模塊
  • umeng:友盟統計
  • widget:通用UI組件模塊

項目包圖

  • app:基類和全局類
  • bean:實體類和EventBus事件類
  • function:功能類
  • ui:界面,包括mvp
  • util:工具類

其中主要代碼是在ui和function這兩個包

如何使用

  • 項目需要依賴AndroidDependencyLib中的一個或多個模塊,請預先配置

https://github.com/devallever/AndroidDependencyLib

  • 把AndroidDependencyLib項目和本項目放同一個目錄下

  • 項目需要依賴AndroidUIKit中的一個或多個模塊,請預先配置

https://github.com/devallever/AndroidUIKit

接口

https://translate.google.cn/

翻譯接口

https://translate.google.cn/translate_a/single?client=gtx&dt=t&dt=bd&dt=rm&dj=1&ie=UTF-8&oe=UTF-8&sl=auto&tl=zh-CN&hl=zh-CN&tk=&q=cat

可以參考以下默認值

@GET("translate_a/single")fun translate(@Query("q") q: String,@Query("client") content: String = "gtx",@Query("dt") dt: String = "t",@Query("dt") dt1: String = "bd",@Query("dt") dt2: String = "rm",@Query("dj") dj: String = "1",@Query("ie") ie: String = "UTF-8",@Query("oe") oe: String = "UTF-8",@Query("sl") sl: String = "auto",@Query("tl") tl: String = "en",@Query("hl") hl: String = "zh-CN",@Query("tk") tk: String = ""): Observable<TranslationBean>

主要用到sl、tl和q這幾個參數

  • sl:原語種
  • tl:翻譯語種
  • q:翻譯文本

關于語種可以參考項目中Languages這個類,包含了100多個語種代碼

  • Languages

返回json對應TranslationBean.kt這個實體類

/**** {"sentences":[{"trans":"串","orig":"string","backend":2},{"translit":"Chuàn","src_translit":"striNG"}],"dict":[{"pos":"名詞","terms":["串","弦","線","繩","繩子","細線","鞭","緄"],"entry":[{"word":"串","reverse_translation":["string"],"score":0.13323711},{"word":"弦","reverse_translation":["string","chord","bowstring","hypotenuse","subtense","string of musical instrument"],"score":0.016418032},{"word":"線","reverse_translation":["line","wire","thread","string","route","filament"],"score":0.0058540297},{"word":"繩","reverse_translation":["rope","cord","string"],"score":0.00477792},{"word":"繩子","reverse_translation":["rope","string","cord"],"score":0.0023652418},{"word":"細線","reverse_translation":["thread","string"],"score":2.2698537E-4},{"word":"鞭","reverse_translation":["whip","lash","string","firecracker","iron staff used as a weapon"],"score":8.139759E-6},{"word":"緄","reverse_translation":["cord","embroidered sash","string"],"score":2.4439987E-6}],"base_form":"string","pos_enum":1},{"pos":"動詞","terms":["紉"],"entry":[{"word":"紉","reverse_translation":["thread","string"],"score":4.860472E-6}],"base_form":"string","pos_enum":2}],"src":"en","confidence":0.9488189,"ld_result":{"srclangs":["en"],"srclangs_confidences":[0.9488189],"extended_srclangs":["en"]}}*/ @Keep class TranslationBean {/*** sentences : [{"trans":"串","orig":"string","backend":2},{"translit":"Chuàn","src_translit":"striNG"}]* dict : [{"pos":"名詞","terms":["串","弦","線","繩","繩子","細線","鞭","緄"],"entry":[{"word":"串","reverse_translation":["string"],"score":0.13323711},{"word":"弦","reverse_translation":["string","chord","bowstring","hypotenuse","subtense","string of musical instrument"],"score":0.016418032},{"word":"線","reverse_translation":["line","wire","thread","string","route","filament"],"score":0.0058540297},{"word":"繩","reverse_translation":["rope","cord","string"],"score":0.00477792},{"word":"繩子","reverse_translation":["rope","string","cord"],"score":0.0023652418},{"word":"細線","reverse_translation":["thread","string"],"score":2.2698537E-4},{"word":"鞭","reverse_translation":["whip","lash","string","firecracker","iron staff used as a weapon"],"score":8.139759E-6},{"word":"緄","reverse_translation":["cord","embroidered sash","string"],"score":2.4439987E-6}],"base_form":"string","pos_enum":1},{"pos":"動詞","terms":["紉"],"entry":[{"word":"紉","reverse_translation":["thread","string"],"score":4.860472E-6}],"base_form":"string","pos_enum":2}]* src : en* confidence : 0.9488189* ld_result : {"srclangs":["en"],"srclangs_confidences":[0.9488189],"extended_srclangs":["en"]}*/var src: String? = nullvar confidence: Double = 0.toDouble()var ld_result: LdResultBean? = nullvar sentences: List<SentencesBean>? = nullvar dict: List<DictBean>? = null@Keepclass LdResultBean {var srclangs: List<String>? = nullvar srclangs_confidences: List<Double>? = nullvar extended_srclangs: List<String>? = null}@Keepclass SentencesBean {/*** trans : 串* orig : string* backend : 2* translit : Chuàn* src_translit : striNG*/var trans: String? = nullvar orig: String? = nullvar backend: Int = 0var translit: String? = nullvar src_translit: String? = null}@Keepclass DictBean {/*** pos : 名詞* terms : ["串","弦","線","繩","繩子","細線","鞭","緄"]* entry : [{"word":"串","reverse_translation":["string"],"score":0.13323711},{"word":"弦","reverse_translation":["string","chord","bowstring","hypotenuse","subtense","string of musical instrument"],"score":0.016418032},{"word":"線","reverse_translation":["line","wire","thread","string","route","filament"],"score":0.0058540297},{"word":"繩","reverse_translation":["rope","cord","string"],"score":0.00477792},{"word":"繩子","reverse_translation":["rope","string","cord"],"score":0.0023652418},{"word":"細線","reverse_translation":["thread","string"],"score":2.2698537E-4},{"word":"鞭","reverse_translation":["whip","lash","string","firecracker","iron staff used as a weapon"],"score":8.139759E-6},{"word":"緄","reverse_translation":["cord","embroidered sash","string"],"score":2.4439987E-6}]* base_form : string* pos_enum : 1*/var pos: String? = nullvar base_form: String? = nullvar pos_enum: Int = 0var terms: List<String>? = nullvar entry: List<EntryBean>? = null@Keepclass EntryBean {/*** word : 串* reverse_translation : ["string"]* score : 0.13323711*/var word: String? = nullvar score: Double = 0.toDouble()var reverse_translation: List<String>? = null}} }
  • sentences 字段含原文本和翻譯文本
  • dict 字段包含詞典信息
  • 解析獲取對應字段的內容在 TranslationHelper 中

語音接口

https://translate.google.cn/translate_tts?client=gtx&ie=UTF-8&tl=zh-CN&total=1&idx=0&textlen=2&tk=&q=setting

其中主要用到 tl 和 q 參數,同上

可以參考以下默認值

@GET("translate_tts")fun requestTTS(@Query("q") q: String,@Query("client") content: String = "gtx",@Query("ie") ie: String = "UTF-8",@Query("tl") tl: String = "en",@Query("hl") hl: String = "zh-CN",@Query("total") total: String = "1",@Query("idx") idx: String = "0",@Query("textlen") textlen: String = "0",@Query("tk") tk: String = ""): Call<ResponseBody>

翻譯基本流程

項目采用MVP架構

  • TranslationFragment:調用presenter接口進行請求翻譯
mPresenter.translate(content, sl, tl)
  • TranslationPresenter:調用RetrofitUtil進行網絡請求,并回調TranslationView的接口刷新界面
  • DBHelper:負責存取翻譯記錄
fun translate(content: String, sl: String = Lang.AUTO.CODE, translateLanguage: String) {if (content.isEmpty()) {toast(R.string.please_input_content)return}val history = DBHelper.getHistory(content, sl, translateLanguage)val translationBean =JsonHelper.json2Object(history?.result ?: "", TranslationBean::class.java)if (translationBean != null) {parse(translationBean)mViewRef?.get()?.refreshLiked(history?.liked == 1)val translateText = TranslationHelper.getTranslateText(translationBean)if (translateText.isNotEmpty()) {play(translateText, translateLanguage)copyToClipBoard(translateText)}log("獲取到數據庫翻譯內容")DBHelper.updateHistoryTime(history)EventBus.getDefault().post(UpdateRecordEvent())return}RetrofitUtil.translate(object : Subscriber<TranslationBean>() {override fun onCompleted() {}override fun onError(e: Throwable) {e.printStackTrace()log("失敗")}override fun onNext(bean: TranslationBean) {parse(bean)val translateText = TranslationHelper.getTranslateText(bean)mViewRef?.get()?.refreshLiked(false)play(translateText, translateLanguage)copyToClipBoard(translateText)DBHelper.addHistory(content, sl, translateLanguage, bean)EventBus.getDefault().post(UpdateRecordEvent())}}, content, sl, translateLanguage)}
  • TranslationHelper:負責解析數據
  • TranslationView:刷新界面
private fun parse(bean: TranslationBean) {val srcSymbol = TranslationHelper.getSrcSymbol(bean)val translateSymbol = TranslationHelper.getTranslateSymbol(bean)//音標顯示邏輯if (srcSymbol.isNotEmpty()) {mViewRef?.get()?.showOrHideSoundSrcSymbol(true)} else {mViewRef?.get()?.showOrHideSoundSrcSymbol(false)}if (translateSymbol.isNotEmpty()) {mViewRef?.get()?.showOrHideSoundTranslateSymbol(true)} else {mViewRef?.get()?.showOrHideSoundTranslateSymbol(false)}if (TranslationHelper.getDictText(bean).isNotEmpty()) {mViewRef?.get()?.showOrHideDictInfo(true)} else {mViewRef?.get()?.showOrHideDictInfo(false)}mViewRef?.get()?.updateResult(bean,TranslationHelper.getSrcLang(bean),TranslationHelper.getSrcText(bean),TranslationHelper.getSrcSymbol(bean),TranslationHelper.getTranslateText(bean),TranslationHelper.getTranslateSymbol(bean),TranslationHelper.getDictText(bean))}

以上就是翻譯的基本流程

復制查詞功能實現

  • 監聽粘貼板變化并彈出Dialog風格的Activity,當在應用內復制時候,不彈出。
val clipBoardManager = getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManagerclipBoardManager.addPrimaryClipChangedListener {log("剪貼板變化")if (ActivityCollector.size() == 0 && SettingHelper.getAutoTranslate()) {val srcText = clipBoardManager.primaryClip?.getItemAt(0)?.text.toString()DialogTranslateActivity.start(this, srcText)}}

通知欄常駐

  • 啟動一個前臺服務 TranslationService 保活
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {log("啟動服務")val paddingFlag = 1val pendingIntent = PendingIntent.getActivity(this,0,Intent(this, MainDrawerActivity::class.java),PendingIntent.FLAG_UPDATE_CURRENT,null)val notificationBuilder = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {val channelId = "translation"val channelName = "翻譯"val importance = NotificationManager.IMPORTANCE_HIGHcreateNotificationChannel(channelId, channelName, importance)NotificationCompat.Builder(this, channelId).setNumber(paddingFlag)} else {NotificationCompat.Builder(this)}notificationBuilder.setContentTitle(getString(R.string.app_name)).setContentText(getString(R.string.notification_msg, getString(R.string.app_name))).setSmallIcon(R.drawable.ic_logo).setLargeIcon(BitmapFactory.decodeResource(resources, R.drawable.ic_logo)).setContentIntent(pendingIntent)startForeground(1, notificationBuilder.build())return super.onStartCommand(intent, flags, startId)}

離線翻譯功能

將翻譯過的記錄保存下來,即每次請求網絡翻譯時候就保存記錄

//sl:原語種代碼 //translateLanguage:翻譯語種代碼 //bean:TranslationBean請求翻譯的實體類 DBHelper.addHistory(content, sl, translateLanguage, bean)

通過History這個實體類保存翻譯記錄

fun addHistory(content: String, sl: String, tl: String, bean: TranslationBean) {run {try {val history = History()history.srcText = contenthistory.sl = slhistory.tl = tlhistory.time = System.currentTimeMillis()history.liked = 0history.result = Gson().toJson(bean)history.ttsPath = MD5.getMD5StrToLowerCase("$content$tl.mp3")val saveResult = history.save()if (saveResult) {log("保存翻譯成功")} else {loge("保存翻譯失敗")}} catch (e: Exception) {e.printStackTrace()loge("保存翻譯失敗")}}}

History實體類

@Keep class History : LitePalSupport() {var srcText: String = ""var sl: String = "en"var tl: String = "en"var time: Long = 0var liked: Int = 0//全路徑var ttsPath: String = ""var result: String = "" }

每次請求就先獲取本地記錄

val history = DBHelper.getHistory(content, sl, translateLanguage)val translationBean =JsonHelper.json2Object(history?.result ?: "", TranslationBean::class.java)if (translationBean != null) {parse(translationBean)mViewRef?.get()?.refreshLiked(history?.liked == 1)val translateText = TranslationHelper.getTranslateText(translationBean)if (translateText.isNotEmpty()) {play(translateText, translateLanguage)copyToClipBoard(translateText)}log("獲取到數據庫翻譯內容")DBHelper.updateHistoryTime(history)EventBus.getDefault().post(UpdateRecordEvent())return}

歷史記錄和單詞本

  • 單詞本從數據庫中按條件查找like = 1 的記錄,,四種情況就是選中所要查找的語言
fun getLikedHistory(sl: String, tl: String) {run {try {//四種情況var historyList = mutableListOf<History>()if (sl.isEmpty() && tl.isEmpty()) {//查所有historyList =LitePal.where("liked = ?", "1").order("time desc").find(History::class.java)}if (sl.isNotEmpty() && tl.isNotEmpty()) {historyList = LitePal.where("sl = ? and tl = ? and liked = ?", sl, tl, "1").order("time desc").find(History::class.java)}if (sl.isEmpty() && tl.isNotEmpty()) {historyList = LitePal.where("tl = ? and liked = ?", tl, "1").order("time desc").find(History::class.java)}if (sl.isNotEmpty() && tl.isEmpty()) {historyList = LitePal.where("sl = ? and liked = ?", sl, "1").order("time desc").find(History::class.java)}val wordItemList = mutableListOf<WordItem>()historyList.map {val wordItem = WordItem()wordItem.history = itwordItem.checked = falsewordItemList.add(wordItem)}mViewRef?.get()?.updateWordList(wordItemList)} catch (e: Exception) {e.printStackTrace()}}}
  • 歷史記錄就是全部記錄,四種情況就是選中所要查找的語言
fun getHistory(sl: String, tl: String) {run {try {//四種情況var historyList = mutableListOf<History>()if (sl.isEmpty() && tl.isEmpty()) {//查所有historyList = (LitePal.order("time desc").find(History::class.java))}if (sl.isNotEmpty() && tl.isNotEmpty()) {historyList = LitePal.where("sl = ? and tl = ?", sl, tl).order("time desc").find(History::class.java)}if (sl.isEmpty() && tl.isNotEmpty()) {historyList = LitePal.where("tl = ?", tl).order("time desc").find(History::class.java)}if (sl.isNotEmpty() && tl.isEmpty()) {historyList = LitePal.where("sl = ?", sl).order("time desc").find(History::class.java)}val wordItemList = mutableListOf<WordItem>()historyList.map {val wordItem = WordItem()wordItem.history = itwordItem.checked = falsewordItemList.add(wordItem)}mViewRef?.get()?.updateWordList(wordItemList)} catch (e: Exception) {e.printStackTrace()}}}

數據備份和恢復功能

將所有History記錄取出來,封裝成BackupBean,再轉成json保存到文件中

val historyList = DBHelper.getAllHistory() if (historyList.isEmpty()) {toast(R.string.no_backup_data)task.run()return } val backupBean = BackupBean() backupBean.data = historyList val result = Gson().toJson(backupBean) log("backupResult = $result") val success = FileUtil.saveStringToFile(result, BACKUP_FILE_PATH) if (success) {toast(R.string.backup_success) } else {toast(R.string.backup_fail) } ...

最后一個是百度的語音識別功能

項目中集成了百度語音識別,但控件被隱藏,邏輯還是有的,通過一個ImageView觸發。
識別功能封裝在baiduvoice模塊中的BaiduVoiceHelper

object BaiduVoiceHelper : EventListener {private var mEventManager: EventManager? = nullprivate var mRecognizedListenerList = mutableListOf<RecognizedListener>()private var mRecognizedType: RecognizedType = RecognizedType.CHINESE // private var mListener: RecognizedListener? = null//重新識別private var mNeedReRecognized = truefun init() {mEventManager = EventManagerFactory.create(App.context, "asr")mEventManager?.registerListener(this)}fun setRecognizedListener(recognizedListener: RecognizedListener) {mRecognizedListenerList.add(recognizedListener)}fun removeRecognised(recognizedListener: RecognizedListener) {mRecognizedListenerList.remove(recognizedListener)}fun startRecognize(type: RecognizedType = mRecognizedType) {mNeedReRecognized = truemRecognizedType = typeval params = LinkedHashMap<String, Any>()var event: String? = nullevent = SpeechConstant.ASR_START // 替換成測試的event// 基于SDK集成2.1 設置識別參數params[SpeechConstant.ACCEPT_AUDIO_VOLUME] = false// params.put(SpeechConstant.NLU, "enable");// params.put(SpeechConstant.VAD_ENDPOINT_TIMEOUT, 0); // 長語音// params.put(SpeechConstant.IN_FILE, "res:///com/baidu/android/voicedemo/16k_test.pcm");// params.put(SpeechConstant.VAD, SpeechConstant.VAD_DNN);if (mRecognizedType == RecognizedType.ENGLISH) {params[SpeechConstant.PID] = 1737 //英語} else {params[SpeechConstant.PID] = 15362 //普通話搜索模型, 默認}/* 語音自訓練平臺特有參數 */// params.put(SpeechConstant.PID, 8002);// 語音自訓練平臺特殊pid,8002:搜索模型類似開放平臺 1537 具體是8001還是8002,看自訓練平臺頁面上的顯示// params.put(SpeechConstant.LMID,1068); // 語音自訓練平臺已上線的模型ID,https://ai.baidu.com/smartasr/model// 注意模型ID必須在你的appId所在的百度賬號下/* 語音自訓練平臺特有參數 */// 請先使用如‘在線識別’界面測試和生成識別參數。 params同ActivityRecog類中myRecognizer.start(params);// 復制此段可以自動檢測錯誤AutoCheck(App.context, @SuppressLint("HandlerLeak")object : Handler() {override fun handleMessage(msg: Message) {if (msg.what == 100) {val autoCheck = msg.obj as AutoChecksynchronized(autoCheck) {val message =autoCheck.obtainErrorMessage() // autoCheck.obtainAllMessage(); // txtLog.append(message + "\n")log(message)// Log.w("AutoCheckMessage", message);}// 可以用下面一行替代,在logcat中查看代碼}}}, false).checkAsr(params)var json: String? = null // 可以替換成自己的jsonjson = JSONObject(params as Map<*, *>).toString() // 這里可以替換成你需要測試的jsonmEventManager?.send(event, json, null, 0, 0)log("開始識別: 輸入參數:$json")}fun stopRecognize() {mNeedReRecognized = falselog("停止識別:ASR_STOP")mEventManager?.send(SpeechConstant.ASR_STOP, null, null, 0, 0) //}fun destroy() {stopRecognize()mEventManager?.unregisterListener(this)}// 基于sdk集成1.2 自定義輸出事件類 EventListener 回調方法// 基于SDK集成3.1 開始回調事件override fun onEvent(name: String,params: String?,data: ByteArray?,offset: Int,length: Int) {var logTxt = "name: $name"if (params != null && !params.isEmpty()) {logTxt += " ;params :$params"}if (data != null) {logTxt += " ;data length=" + data.size}log(logTxt)if (params?.contains("final_result") == true) {loge("最后識別結果: $logTxt")try {val jsonObject = JSONObject(params)val result = jsonObject.getString("best_result")?:""mRecognizedListenerList.map {it.onResult(params, result)}} catch (e: Exception) {e.printStackTrace()}}if (name == "asr.exit" && mNeedReRecognized) {startRecognize()//重新識別}} }

用到的開源項目

  • Eventbus
  • LitePal: 數據庫
  • RxJava/RxAndroid
  • Retrofit/Okhttp
  • Glide

更多項目

VirtualCallOpenSource-虛擬來電開源版

LoseWeight-減肥健身App開源版

最后

如果喜歡,請star
最重要一點,請勿商用。
如非必要,請更改包名,類名,包結構。
謝謝。

我的Github

https://github.com/devallever

總結

以上是生活随笔為你收集整理的TextTranslatorOpenSource-文本翻译器开源版的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。