Enhance the translation function with TagComplete #17

Former-commit-id: e7083abfb2d325d602c0591bdf12b479cdbcbbe8
This commit is contained in:
Physton
2023-05-18 13:26:13 +08:00
parent 42a2200bbc
commit 2b27e80455
15 changed files with 440 additions and 76 deletions

1
.gitignore vendored
View File

@@ -5,4 +5,5 @@
/src/package-lock.json
/storage
/tests/tested.json
/tags/*
__pycache__

View File

@@ -36,6 +36,11 @@ function supports the majority of countries worldwide.
![](https://raw.githubusercontent.com/Physton/sd-webui-prompt-all-in-one-assets/main/images/switch_language.png)
- Translation API settings / *翻译API设置*
![](https://raw.githubusercontent.com/Physton/sd-webui-prompt-all-in-one-assets/main/images/translate_setting.gif)
- Show/Hide content / *显示/折叠内容*
![](https://raw.githubusercontent.com/Physton/sd-webui-prompt-all-in-one-assets/main/images/fold.gif)
@@ -76,6 +81,12 @@ function supports the majority of countries worldwide.
![](https://raw.githubusercontent.com/Physton/sd-webui-prompt-all-in-one-assets/main/images/tagcomplete.gif)
- Use `danbooru.csv` in `a1111-sd-webui-tagcomplete` to enhance the translation function / *使用 `a1111-sd-webui-tagcomplete` 中的 `danbooru.csv` 增强翻译功能*
![](https://raw.githubusercontent.com/Physton/sd-webui-prompt-all-in-one-assets/main/images/tagcomplete_setting.png)
![](https://raw.githubusercontent.com/Physton/sd-webui-prompt-all-in-one-assets/main/images/tagcomplete_translate.gif)
## Installation and Usage / *安装使用*
- ### Method 1 (Recommended) / *方式一(推荐)*

View File

@@ -1 +1 @@
f76ac9bbd2793f2cbb0d397a7b452428baf29fb9
8f0029951d020921489735c9e3a75e1def63be34

View File

@@ -1 +1 @@
5aaff63664bfdc62ce3da89f118cd2d074a84047
ef9405c47a3e0117023faf577104b90760329f07

View File

@@ -1 +1 @@
378855a53fd50f1d67c879ade92600bdb9860b17
1906c12aeeb784ba669515f453777d2e3056d2d9

35
scripts/csv.py Normal file
View File

@@ -0,0 +1,35 @@
import os
from pathlib import Path
base_dir = str(Path().absolute())
dirs = [
os.path.join(base_dir, 'extensions', 'sd-webui-prompt-all-in-one', 'tags'),
os.path.join(base_dir, 'extensions', 'a1111-sd-webui-tagcomplete', 'tags'),
]
def get_csvs():
global base_dir
csvs = []
for dir in dirs:
if not os.path.exists(dir):
continue
for file in os.listdir(dir):
if file.endswith('.csv'):
path = os.path.join(dir, file)
name = os.path.basename(file)
size = os.path.getsize(path)
# 去除 base_dir 后的路径
key = path.replace(base_dir, '')
csvs.append({
'key': key,
'name': name,
'size': size,
'path': path
})
return csvs
def get_csv(key):
path = base_dir + key
if not os.path.exists(path):
return None
return path

View File

@@ -2,7 +2,8 @@ import gradio as gr
import os
from pathlib import Path
from modules import script_callbacks, extra_networks, prompt_parser
from fastapi import FastAPI, Body, Request
from fastapi import FastAPI, Body, Request, Response
from fastapi.responses import FileResponse
from scripts.storage import storage
from scripts.get_extensions import get_extensions
from scripts.get_token_counter import get_token_counter
@@ -10,6 +11,7 @@ from scripts.get_i18n import get_i18n
from scripts.get_translate_apis import get_translate_apis
from scripts.translate import translate
from scripts.history import history
from scripts.csv import get_csvs, get_csv
VERSION = '0.0.1'
@@ -182,6 +184,18 @@ def on_app_started(_: gr.Blocks, app: FastAPI):
@app.post("/physton_prompt/translate")
async def _translate(text: str = Body(...), from_lang: str = Body(...), to_lang: str = Body(...), api: str = Body(...), api_config: dict = Body(...)):
return translate(text, from_lang, to_lang, api, api_config)
return {"success": hi.remove_histories(data['type'])}
@app.get("/physton_prompt/get_csvs")
async def _get_csvs():
return {"csvs": get_csvs()}
@app.get("/physton_prompt/get_csv")
async def _get_csv(key: str):
file = get_csv(key)
if not file:
return Response(status_code=404)
return FileResponse(file, media_type='text/csv', filename=os.path.basename(file))
try:
script_callbacks.on_app_started(on_app_started)

View File

@@ -19,20 +19,25 @@
v-model:translate-api="translateApi"
:translate-api-config="translateApiConfig"
@click:translate-api="onTranslateApiClick"
v-model:tag-complete-file="tagCompleteFile"
@click:select-language="onSelectLanguageClick"></physton-prompt>
</template>
<translate-setting ref="translateSetting" v-model:language-code="languageCode"
:translate-apis="translateApis" :languages="languages"
@forceUpdate:translateApi="updateTranslateApiConfig"
v-model:tag-complete-file="tagCompleteFile"
v-model:translate-api="translateApi"></translate-setting>
<select-language ref="selectLanguage" v-model:language-code="languageCode"
:translate-apis="translateApis"
:languages="languages"
v-model:translate-api="translateApi"></select-language>
v-model:translate-api="translateApi"
v-model:tag-complete-file="tagCompleteFile"></select-language>
<history ref="history" v-model:language-code="languageCode"
:translate-apis="translateApis" :languages="languages" @use="onUseHistory"/>
:translate-apis="translateApis" :languages="languages"
v-model:tag-complete-file="tagCompleteFile" @use="onUseHistory"/>
<favorite ref="favorite" v-model:language-code="languageCode"
:translate-apis="translateApis" :languages="languages" @use="onUseFavorite"></favorite>
:translate-apis="translateApis" :languages="languages"
v-model:tag-complete-file="tagCompleteFile" @use="onUseFavorite"></favorite>
<div class="physton-paste-popup" v-if="showPastePopup" @click="closePastePopup">
<div class="paste-popup-main" @click.stop>
@@ -163,6 +168,7 @@ export default {
autoTranslateToLocal: false,
// hideDefaultInput: false,
enableTooltip: true,
tagCompleteFile: '',
startWatchSave: false,
@@ -242,6 +248,16 @@ export default {
},
immediate: false,
},
tagCompleteFile: {
handler: function (val, oldVal) {
if (!this.startWatchSave) return
console.log('onTagCompleteFileChange', val, oldVal)
this.gradioAPI.setData('tagCompleteFile', val).then(data => {
}).catch(err => {
})
},
immediate: false,
},
},
mounted() {
this.gradioAPI.getConfig().then(res => {
@@ -265,7 +281,7 @@ export default {
return common.getLang(key, this.languageCode, this.languages)
},
init() {
let dataListsKeys = ['languageCode', 'autoTranslateToEnglish', 'autoTranslateToLocal', /*'hideDefaultInput', */'translateApi', 'enableTooltip']
let dataListsKeys = ['languageCode', 'autoTranslateToEnglish', 'autoTranslateToLocal', /*'hideDefaultInput', */'translateApi', 'enableTooltip', 'tagCompleteFile']
this.prompts.forEach(item => {
dataListsKeys.push(item.hideDefaultInputKey)
dataListsKeys.push(item.hidePanelKey)
@@ -302,6 +318,21 @@ export default {
if (data.translateApi !== null) {
this.translateApi = data.translateApi
}
if (data.tagCompleteFile !== null) {
this.tagCompleteFile = data.tagCompleteFile
this.$nextTick(() => {
this.$refs.translateSetting.getCSV(this.tagCompleteFile)
})
} else {
if (typeof TAC_CFG === 'object' && typeof QUEUE_FILE_LOAD === 'object') {
QUEUE_FILE_LOAD.push(() => {
if (typeof TAC_CFG.translation !== 'object' || typeof TAC_CFG.translation.translationFile !== 'string') return
if (!TAC_CFG.translation.translationFile) return
this.tagCompleteFile = '\\extensions\\a1111-sd-webui-tagcomplete\\tags\\' + TAC_CFG.translation.translationFile
this.$refs.translateSetting.getCSV(this.tagCompleteFile)
})
}
}
this.updateTranslateApiConfig()
@@ -323,6 +354,7 @@ export default {
item.$prompt.parentElement.parentElement.style.display = item.hideDefaultInput ? 'none' : 'flex'
// item.$textarea.parentNode.appendChild($prompt)
})
this.startWatchSave = true
})

View File

@@ -0,0 +1,27 @@
<template>
<div class="icon-svg" :style="{width: width + 'px', height: height + 'px'}">
<svg t="1684324200951" viewBox="0 0 1025 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"
p-id="5864" :width="width" :height="height" :style="{fill: color}">
<path d="M698.879266 777.973c-56.825 40.33-123.34 60.55-191.357 59.625-8.99-0.095-17.93-0.575-26.767-1.35-3.597-0.345-7.19-0.95-10.84-1.395-6.94-0.945-13.88-1.895-20.622-3.22-4.195-0.805-8.292-1.875-12.385-2.845-6.642-1.575-13.232-3.175-19.727-5.125-3.095-0.97-6.14-2.095-9.237-3.145-7.44-2.52-14.882-5.135-22.122-8.21-1.647-0.675-3.245-1.445-4.845-2.2-8.487-3.77-16.827-7.71-24.92-12.16-0.397-0.195-0.698-0.37-1.098-0.57-27.367-15.21-52.385-34.205-74.357-56.405-0.348-0.355-0.7-0.75-1.048-1.15-6.842-6.915-13.332-14.18-19.525-21.725-1.298-1.62-2.547-3.34-3.845-4.985-44.697-56.61-71.662-128.245-71.662-206.162l75.805 0c1.95 0 3.845-1.047 4.848-2.895 0.997-1.827 0.85-3.997-0.253-5.62l-127.39-193.477c-0.997-1.5-2.688-2.5-4.61-2.5-1.895 0-3.592 1-4.59 2.5L0.936266 498.409c-1.075 1.647-1.25 3.795-0.25 5.645 0.997 1.845 2.897 2.895 4.845 2.895l75.807 0c0 91.605 28.212 176.525 76.117 246.734 0.6 0.97 0.997 2.02 1.648 2.995 4.992 7.195 10.485 13.805 15.83 20.6 1.947 2.57 3.845 5.21 5.892 7.74 7.84 9.635 16.18 18.675 24.72 27.54 0.847 0.87 1.597 1.745 2.395 2.52 28.767 29.16 61.277 53.73 96.682 73.35 0.9 0.585 1.797 1.13 2.795 1.655 10.188 5.545 20.675 10.56 31.312 15.3 2.645 1.15 5.192 2.425 7.887 3.57 9.09 3.8 18.427 7.145 27.817 10.335 4.443 1.53 8.84 3.08 13.335 4.475 8.237 2.475 16.63 4.515 25.065 6.57 5.645 1.325 11.19 2.745 16.932 3.845 2.342 0.495 4.59 1.22 6.937 1.595 7.992 1.43 15.982 2.225 23.972 3.22 2.895 0.325 5.742 0.82 8.587 1.15 14.385 1.42 28.665 2.375 42.947 2.375 87.447 0 172.737-27.075 245.902-78.98 23.32-16.58 29.01-49.105 12.675-72.755C754.419266 767.113 722.199266 761.393 698.879266 777.973M941.484266 506.951c-0.045-91.335-28.065-176.075-75.755-246.137-0.705-1.2-1.195-2.422-1.95-3.52-5.945-8.565-12.39-16.555-18.825-24.57-0.75-0.975-1.45-1.997-2.245-2.945-43.65-53.605-98.435-95.027-160.555-122.095-1.7-0.75-3.4-1.597-5.1-2.347-9.935-4.117-20.065-7.762-30.255-11.235-3.695-1.223-7.345-2.572-11.09-3.695-8.885-2.722-17.92-4.942-27.015-7.065-5.04-1.175-10.04-2.472-15.125-3.472-2.555-0.5-4.895-1.247-7.395-1.695-6.79-1.202-13.635-1.728-20.425-2.6-4.7-0.597-9.345-1.347-14.09-1.847-11.43-1.072-22.77-1.522-34.105-1.722-2.045 0-4.095-0.325-6.142-0.325-0.348 0-0.7 0.1-1.095 0.125-87.292 0.075-172.437 26.765-245.499 78.6-23.37 16.527-29.062 49.11-12.73 72.755 16.327 23.645 48.587 29.39 71.91 12.81 56.43-40.025 122.297-60.275 189.812-59.672 9.74 0.072 19.28 0.548 28.715 1.445 2.95 0.348 5.795 0.775 8.69 1.15 7.795 0.95 15.485 2.072 23.07 3.595 3.35 0.647 6.69 1.525 9.935 2.272 7.445 1.695 14.895 3.52 22.185 5.742 2.29 0.747 4.54 1.572 6.83 2.345 8.34 2.75 16.485 5.717 24.52 9.09 0.81 0.348 1.655 0.772 2.45 1.097 48.09 20.95 90.29 53.207 123.205 93.53 0.19 0.253 0.395 0.575 0.59 0.8 46.345 57.102 74.26 130.107 74.26 209.579l-75.81 0c-1.94 0-3.845 1.048-4.84 2.895-1 1.845-0.855 3.997 0.255 5.645l127.43 193.454c0.96 1.495 2.66 2.465 4.6 2.465 1.895 0 3.595-0.97 4.595-2.465l127.345-193.454c1.095-1.648 1.245-3.8 0.25-5.645-1.005-1.847-2.895-2.895-4.85-2.895l-75.75 0L941.485266 506.951z" p-id="5865"></path>
</svg>
</div>
</template>
<script>
export default {
name: 'iconRefresh',
props: {
width: {
type: Number,
default: 16,
},
height: {
type: Number,
default: 16,
},
color: {
type: String,
default: '#02b7fd',
},
},
}
</script>

View File

@@ -1 +1 @@
bc51050deef5bc2c3e6db50e6054aacd9c652da0
14684a249601d8688b1ffb199227a759f7a77a0f

View File

@@ -1,62 +1,88 @@
<template>
<div class="physton-prompt-translate-setting" v-if="isOpen">
<div class="translate-setting-main">
<div class="setting-line">
<div class="line-title">{{ getLang('translate_api') }}</div>
<div class="line-content">
<select v-model="apiKey">
<optgroup v-for="typeGroup in supportApi" :key="typeGroup.type"
:label="getLang(typeGroup.type)">
<option v-for="item in typeGroup.children" :key="item.key" :value="item.key">
{{ item.name }}
</option>
</optgroup>
</select>
</div>
</div>
<div class="setting-line" v-if="apiItem && apiItem.type == 'translators'">
<div class="line-title"></div>
<div class="line-content">
<span style="color: var(--red5)">*{{ getLang('not_api_key_desc') }}</span>
</div>
</div>
<div class="setting-line" v-if="apiItem.help">
<div class="line-title"></div>
<div class="line-content">
<div v-for="item in apiItem.help" class="help-list">
<div class="help-item">[?] <a :href="item.url" target="_blank">{{ item.title }}</a></div>
<div class="translate-setting-content">
<div class="setting-line">
<div class="line-title">{{ getLang('translate_api') }}</div>
<div class="line-content">
<select v-model="apiKey">
<optgroup v-for="typeGroup in supportApi" :key="typeGroup.type"
:label="getLang(typeGroup.type)">
<option v-for="item in typeGroup.children" :key="item.key" :value="item.key">
{{ item.name }}
</option>
</optgroup>
</select>
</div>
</div>
</div>
<div class="setting-line" v-for="config in configs">
<div class="line-title">{{ config.title }}</div>
<div class="line-content">
<input v-if="config.type == 'input'" v-model="config.value">
<select v-if="config.type == 'select'" v-model="config.value">
<option v-for="option in config.options" :value="option">{{ option }}</option>
</select>
</div>
</div>
<div class="setting-line">
<div class="line-title">{{ getLang('translate_test') }}</div>
<div class="line-content">
<textarea class="test-input" v-model="testText"></textarea>
</div>
</div>
<div class="setting-line">
<div class="line-title"></div>
<div class="line-content">
<div class="hover-scale-120 test-btn" @click="onTestClick">
<icon-loading v-if="loading" width="40" height="40" aria-required="true"/>
<block v-else>Test!</block>
<div class="setting-line" v-if="apiItem && apiItem.type == 'translators'">
<div class="line-title"></div>
<div class="line-content">
<span style="color: var(--red5)">*{{ getLang('not_api_key_desc') }}</span>
</div>
</div>
</div>
<div class="setting-line">
<div class="line-title"></div>
<div class="line-content">
<div class="translate-error" v-if="!translateSuccess && errorMessage">{{ errorMessage }}</div>
<textarea class="test-input" v-if="translatedText" v-model="translatedText"></textarea>
<div class="setting-line" v-if="apiItem.help">
<div class="line-title"></div>
<div class="line-content">
<div v-for="item in apiItem.help" class="help-list">
<div class="help-item">[?] <a :href="item.url" target="_blank">{{ item.title }}</a></div>
</div>
</div>
</div>
<div class="setting-line" v-for="config in configs">
<div class="line-title">{{ config.title }}</div>
<div class="line-content">
<input v-if="config.type == 'input'" v-model="config.value">
<select v-if="config.type == 'select'" v-model="config.value">
<option v-for="option in config.options" :value="option">{{ option }}</option>
</select>
</div>
</div>
<div class="setting-line">
<div class="line-title">{{ getLang('translate_test') }}</div>
<div class="line-content">
<textarea class="test-input" v-model="testText"></textarea>
</div>
</div>
<div class="setting-line">
<div class="line-title"></div>
<div class="line-content">
<div class="hover-scale-120 test-btn" @click="onTestClick">
<icon-loading v-if="loading" width="40" height="40" aria-required="true"/>
<template v-else>{{getLang('test')}}</template>
</div>
</div>
</div>
<div class="setting-line">
<div class="line-title"></div>
<div class="line-content">
<div class="translate-error" v-if="!translateSuccess && errorMessage">{{ errorMessage }}</div>
<textarea class="test-input" v-if="translatedText" v-model="translatedText"></textarea>
</div>
</div>
<div class="setting-line">
<div class="line-title">TagComplete</div>
<div class="line-content">
<div v-html="getLang('tagcomplete_translate_desc')"></div>
<div class="line-row">
<select v-model="tagCompleteFileKey" @change="tagCompleteResults = []">
<option v-for="item in tagCompleteFiles" :value="item.key">{{ item.name }}</option>
</select>
<div class="refresh-btn hover-scale-120" v-tooltip="getLang('refresh')" @click="refreshCSVs">
<icon-loading v-if="tagCompleteFilesLoading" width="20" height="20" aria-required="true"/>
<icon-refresh v-else width="20" height="20" />
</div>
</div>
</div>
</div>
<div class="setting-line" v-show="tagCompleteFileKey">
<div class="line-title"></div>
<div class="line-content">
<div class="hover-scale-120 test-btn" @click="onTagCompleteTestClick">{{ getLang('test') }}</div>
<div v-show="tagCompleteResults.length > 0">
<p v-for="text in tagCompleteResults" :key="text">{{ text }}</p>
</div>
</div>
</div>
</div>
<div class="setting-btns">
@@ -71,10 +97,11 @@ import LanguageMixin from "@/mixins/languageMixin";
import IconCopy from "@/components/icons/iconCopy.vue";
import IconLoading from "@/components/icons/iconLoading.vue";
import common from "@/utils/common";
import IconRefresh from "@/components/icons/iconRefresh.vue";
export default {
name: 'TranslateSetting',
components: {IconLoading, IconCopy},
components: {IconRefresh, IconLoading, IconCopy},
mixins: [LanguageMixin],
props: {},
data() {
@@ -92,6 +119,10 @@ Github: Physton/sd-webui-prompt-all-in-one`,
isOpen: false,
configs: [],
apiKey: '',
tagCompleteFiles: [],
tagCompleteFilesLoading: false,
tagCompleteFileKey: '',
tagCompleteResults: [],
}
},
computed: {
@@ -113,7 +144,7 @@ Github: Physton/sd-webui-prompt-all-in-one`,
this.translatedText = ''
this.loading = false
},
emits: ['update:translateApi', 'forceUpdate:translateApi'],
emits: ['update:translateApi', 'forceUpdate:translateApi', 'update:tagCompleteFile'],
watch: {
apiKey: {
handler: function (val, oldVal) {
@@ -147,6 +178,29 @@ Github: Physton/sd-webui-prompt-all-in-one`,
this.errorMessage = ''
this.translatedText = ''
this.loading = false
this.tagCompleteFileKey = this.tagCompleteFile
this.refreshCSVs()
},
refreshCSVs() {
if (this.tagCompleteFilesLoading) return
this.tagCompleteFilesLoading = true
this.tagCompleteFiles = []
this.gradioAPI.getCSVs().then(res => {
this.tagCompleteFilesLoading = false
if (!res || res.length <= 0) return
this.tagCompleteFiles.push({
key: '',
name: this.getLang('not_enable'),
})
for (const item of res) {
this.tagCompleteFiles.push({
key: item.key,
name: item.key,
})
}
}).catch(err => {
this.tagCompleteFilesLoading = false
})
},
onTestClick() {
if (this.loading) return
@@ -178,13 +232,26 @@ Github: Physton/sd-webui-prompt-all-in-one`,
configs[item.key] = item.value
}
this.$emit('update:translateApi', this.apiKey)
this.$emit('update:tagCompleteFile', this.tagCompleteFileKey)
this.gradioAPI.setData('translate_api.' + this.apiKey, configs).then(res => {
if (this.apiKey === this.translateApi) this.$emit('forceUpdate:translateApi')
})
},
onCloseClick() {
this.isOpen = false
}
},
onTagCompleteTestClick() {
this.tagCompleteResults = []
const texts = ['1girl', 'Robot dog']
texts.forEach(text => {
let lang = this.getLang('translate_result')
this.translateToLocalByCSV(text, this.tagCompleteFileKey, true).then(res => {
this.tagCompleteResults.push(lang.replace('{0}', text).replace('{1}', res))
}).catch(err => {
this.$toastr.error(err)
})
})
},
},
}
</script>

View File

@@ -1035,6 +1035,21 @@
.translate-setting-main {
.common-popup-main();
.translate-setting-content {
max-height: 600px;
overflow: hidden;
overflow-y: auto;
padding: 6px;
border: 1px solid #464646;
border-radius: 6px;
// 始终显示滚动条
&::-webkit-scrollbar {
width: 6px;
height: 6px;
}
}
.setting-line {
display: flex;
justify-content: flex-start;
@@ -1054,11 +1069,21 @@
font-size: 14px;
color: #fff;
span {
span, p {
font-size: 14px;
color: #fff;
}
p {
margin: 5px 0;
}
a {
font-size: 14px;
color: #108bb5;
text-decoration: underline;
}
.api-name {
display: inline-block;
.common-colourful-background();
@@ -1082,16 +1107,40 @@
}
}
.line-row {
display: flex;
justify-content: flex-start;
> * {
margin-left: 4px;
&:first-child {
margin-left: 0;
}
}
}
.refresh-btn {
cursor: pointer;
width: 28px;
height: 28px;
background: #000;
display: flex;
justify-content: center;
align-items: center;
border-radius: 4px;
}
.test-input {
height: 150px;
height: 70px;
}
.test-btn {
cursor: pointer;
display: inline-block;
padding: 0 40px;
height: 40px;
line-height: 40px;
height: 32px;
line-height: 32px;
color: #fff;
background: #108bb5;
border-radius: 4px;

View File

@@ -22,9 +22,14 @@ export default {
translateApiConfig: {
type: Object
},
tagCompleteFile: {
type: String,
default: ''
}
},
data() {
return {}
return {
}
},
computed: {
langName() {
@@ -54,12 +59,20 @@ export default {
}
},
translate(text, from_lang, to_lang, translateApi = null, translateApiConfig = null) {
return new Promise((resolve, reject) => {
return new Promise(async (resolve, reject) => {
translateApi = translateApi || this.translateApi
translateApiConfig = translateApiConfig || this.translateApiConfig || {}
if (!common.canTranslate(text)) {
resolve(this._translateRes(true, '', text, text, from_lang, to_lang, translateApi, translateApiConfig))
return
}
let translateText = await this.translateByCSV(text, from_lang, to_lang)
if (translateText) {
resolve(this._translateRes(true, '', text, translateText, from_lang, to_lang, translateApi, translateApiConfig))
return
}
if (translateApi === 'openai') {
text = JSON.stringify({text})
}
@@ -100,10 +113,15 @@ export default {
for (const index in texts) {
const text = texts[index]
if (common.canTranslate(text)) {
needTranslateTexts.push({
"text": text,
"index": index
})
let translateText = this.translateByCSV(text, from_lang, to_lang)
if (translateText) {
callback(this._translateRes(true, '', text, translateText, from_lang, to_lang, translateApi, translateApiConfig), index)
} else {
needTranslateTexts.push({
"text": text,
"index": index
})
}
} else {
callback(this._translateRes(true, '', text, text, from_lang, to_lang, translateApi, translateApiConfig), index)
}
@@ -173,6 +191,108 @@ export default {
}
if (complete) complete()
}
}
},
getCSV(tagCompleteFile = null, reload = false) {
window.tagCompleteFileCache = window.tagCompleteFileCache || {}
return new Promise((resolve, reject) => {
tagCompleteFile = tagCompleteFile || this.tagCompleteFile
if (!reload && window.tagCompleteFileCache[tagCompleteFile]) {
resolve(window.tagCompleteFileCache[tagCompleteFile])
return
}
let data = {toEn: new Map(), toLocal: new Map()}
let setData = (en, local) => {
const texts = [
en,
en.replace(/\_/g, ' '),
en.replace(/\-/g, ' '),
]
texts.forEach(t => data.toLocal.set(t, local))
data.toEn.set(local, en)
}
if (!tagCompleteFile) {
if (typeof translations === 'object' && translations instanceof Map) {
translations.forEach((local, en) => {
setData(en, local)
})
window.tagCompleteFileCache[tagCompleteFile] = data
resolve(data)
return
}
}
if (!tagCompleteFile) {
reject(this.getLang('not_found_csv_file'))
return
}
this.gradioAPI.getCSV(tagCompleteFile).then(res => {
// 解析csv
res = res.replace(/\r/g, '\n')
let lines = res.split('\n')
lines.forEach(line => {
if (line === '') return
if (line.trim() === '') return
let items = line.split(',')
if (items.length < 2) return
let en = items[0].trim()
let local = items[1].trim()
if (en === '' || local === '') return
setData(en, local)
})
window.tagCompleteFileCache[tagCompleteFile] = data
resolve(data)
}).catch(error => {
if (error.response && error.response.status === 404) {
reject(this.getLang('not_found_csv_file'))
} else {
reject(error.message)
}
})
})
},
translateToLocalByCSV(text, tagCompleteFile = null, reload = false) {
return new Promise((resolve, reject) => {
this.getCSV(tagCompleteFile, reload).then(res => {
text = text.trim().toLowerCase()
if (res.toLocal.has(text)) {
resolve(res.toLocal.get(text))
}
resolve('')
}).catch(err => {
reject(err)
})
});
},
translateToEnByCSV(text, tagCompleteFile = null, reload = false) {
return new Promise((resolve, reject) => {
this.getCSV(tagCompleteFile, reload).then(res => {
text = text.trim().toLowerCase()
if (res.toEn.has(text)) {
resolve(res.toEn.get(text))
}
resolve('')
}).catch(err => {
reject(err)
})
});
},
async translateByCSV(text, from_lang, to_lang, tagCompleteFile = null, reload = false) {
let translateText = ''
try {
if (from_lang === this.languageCode && to_lang === 'en_US') {
translateText = await this.translateToEnByCSV(text, tagCompleteFile, reload)
} else if (from_lang === 'en_US' && to_lang === this.languageCode) {
translateText = await this.translateToLocalByCSV(text, tagCompleteFile, reload)
}
} catch (e) {
console.log(e)
}
if (!translateText) return ''
return translateText
},
}
}

View File

@@ -133,4 +133,12 @@ export default class GradioAPI {
}
return data
}
async getCSVs() {
return (await this.api.get("/get_csvs")).data.csvs
}
async getCSV(key) {
return (await this.api.get("/get_csv", {params: {key}})).data
}
}

File diff suppressed because one or more lines are too long