mirror of
https://github.com/Physton/sd-webui-prompt-all-in-one.git
synced 2026-05-01 03:31:41 +00:00
Enhance the translation function with TagComplete #17
Former-commit-id: e7083abfb2d325d602c0591bdf12b479cdbcbbe8
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -5,4 +5,5 @@
|
||||
/src/package-lock.json
|
||||
/storage
|
||||
/tests/tested.json
|
||||
/tags/*
|
||||
__pycache__
|
||||
|
||||
11
README.MD
11
README.MD
@@ -36,6 +36,11 @@ function supports the majority of countries worldwide.
|
||||
|
||||

|
||||
|
||||
|
||||
- Translation API settings / *翻译API设置*
|
||||
|
||||

|
||||
|
||||
- Show/Hide content / *显示/折叠内容*
|
||||
|
||||

|
||||
@@ -76,6 +81,12 @@ function supports the majority of countries worldwide.
|
||||
|
||||

|
||||
|
||||
- Use `danbooru.csv` in `a1111-sd-webui-tagcomplete` to enhance the translation function / *使用 `a1111-sd-webui-tagcomplete` 中的 `danbooru.csv` 增强翻译功能*
|
||||
|
||||

|
||||
|
||||

|
||||
|
||||
## Installation and Usage / *安装使用*
|
||||
|
||||
- ### Method 1 (Recommended) / *方式一(推荐)*:
|
||||
|
||||
@@ -1 +1 @@
|
||||
f76ac9bbd2793f2cbb0d397a7b452428baf29fb9
|
||||
8f0029951d020921489735c9e3a75e1def63be34
|
||||
@@ -1 +1 @@
|
||||
5aaff63664bfdc62ce3da89f118cd2d074a84047
|
||||
ef9405c47a3e0117023faf577104b90760329f07
|
||||
@@ -1 +1 @@
|
||||
378855a53fd50f1d67c879ade92600bdb9860b17
|
||||
1906c12aeeb784ba669515f453777d2e3056d2d9
|
||||
35
scripts/csv.py
Normal file
35
scripts/csv.py
Normal 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
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
})
|
||||
|
||||
|
||||
27
src/src/components/icons/iconRefresh.vue
Normal file
27
src/src/components/icons/iconRefresh.vue
Normal 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>
|
||||
@@ -1 +1 @@
|
||||
bc51050deef5bc2c3e6db50e6054aacd9c652da0
|
||||
14684a249601d8688b1ffb199227a759f7a77a0f
|
||||
@@ -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>
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
},
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user