插件升级,添加百度翻译和本地翻译
This commit is contained in:
+2
-1
@@ -13,4 +13,5 @@ unpackage/dist/build/
|
||||
unpackage/dist/dev/
|
||||
|
||||
# python
|
||||
*.pyc
|
||||
*.pyc
|
||||
config/baidu.json
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
+121
-27
@@ -30,11 +30,24 @@ $el("style", {
|
||||
}
|
||||
.lam-model-tags-list {
|
||||
display: flex;
|
||||
align-content: flex-start;
|
||||
flex-wrap: wrap;
|
||||
list-style: none;
|
||||
gap: 10px;
|
||||
min-height: 100px;
|
||||
max-height: 200px;
|
||||
height: 60%;
|
||||
overflow: auto;
|
||||
margin: 10px 0;
|
||||
padding: 0;
|
||||
}
|
||||
.lam-model-tags-sel-list {
|
||||
display: flex;
|
||||
align-content: flex-start;
|
||||
flex-wrap: wrap;
|
||||
list-style: none;
|
||||
gap: 10px;
|
||||
min-height: 100px;
|
||||
height: 20%;
|
||||
overflow: auto;
|
||||
margin: 10px 0;
|
||||
padding: 0;
|
||||
@@ -128,7 +141,7 @@ async function getPrompt(name) {
|
||||
}
|
||||
|
||||
}
|
||||
function getTagList(tags) {
|
||||
function getTagList(tags,cat) {
|
||||
let rlist=[]
|
||||
Object.keys(tags).forEach((k) => {
|
||||
if (typeof tags[k] === "string") {
|
||||
@@ -138,6 +151,8 @@ function getTagList(tags) {
|
||||
{
|
||||
dataset: {
|
||||
tag: t[1],
|
||||
name: t[0],
|
||||
cat:cat
|
||||
},
|
||||
$: (el) => {
|
||||
el.onclick = () => {
|
||||
@@ -155,11 +170,40 @@ function getTagList(tags) {
|
||||
]
|
||||
))
|
||||
}else{
|
||||
rlist.push(...getTagList(tags[k]))
|
||||
rlist.push(...getTagList(tags[k],cat))
|
||||
}
|
||||
});
|
||||
return rlist
|
||||
}
|
||||
function getSelList(tags) {
|
||||
let rlist=[]
|
||||
Object.keys(tags).forEach((k) => {
|
||||
rlist.push($el(
|
||||
"li.lam-model-tag",
|
||||
{
|
||||
dataset: {
|
||||
name: tags[k]['name'],
|
||||
tag: tags[k]['tag'],
|
||||
cat: tags[k]['cat']
|
||||
},
|
||||
$: (el) => {
|
||||
el.onclick = () => {
|
||||
el.classList.add("lam-model-tag--del");
|
||||
};
|
||||
},
|
||||
},
|
||||
[
|
||||
$el("p", {
|
||||
textContent:tags[k]['name'],
|
||||
}),
|
||||
$el("span", {
|
||||
textContent: tags[k]['cat'],
|
||||
}),
|
||||
]
|
||||
))
|
||||
})
|
||||
return rlist;
|
||||
}
|
||||
// Displays input text on a node
|
||||
app.registerExtension({
|
||||
name: "EasyPromptSelecto",
|
||||
@@ -170,14 +214,31 @@ app.registerExtension({
|
||||
const onNodeCreated = nodeType.prototype.onNodeCreated;
|
||||
nodeType.prototype.onNodeCreated = function() {
|
||||
const r = onNodeCreated?.apply(this, arguments);
|
||||
this.setProperty("values", [])
|
||||
this.setProperty("selTags", {})
|
||||
ComfyWidgets["COMBO"](this, "category", ['a','b']).widget;
|
||||
const list = $el("ol.lam-model-tags-list",[]);
|
||||
let tags=this.addDOMWidget('tags',"list",list)
|
||||
const lists = $el("ol.lam-model-tags-sel-list",[]);
|
||||
let tags=this.addDOMWidget('tags',"list",$el('div.lam_style-preview',[$el('button',{
|
||||
textContent:'清除全部选择',
|
||||
style:{},
|
||||
onclick:()=>{
|
||||
tags.element.children[1].querySelectorAll(".lam-model-tag--selected").forEach(el => {
|
||||
el.classList.remove("lam-model-tag--selected");
|
||||
})
|
||||
this.properties["values"]=[]
|
||||
this.properties['selTags']={}
|
||||
tags.element.children[3].innerHTML=''
|
||||
|
||||
}}
|
||||
),list,$el('span',{textContent:"选择内容"}),lists]));
|
||||
let prompt_type = this.widgets[this.widgets.findIndex(obj => obj.name === 'prompt_type')];
|
||||
let textEl = this.widgets[this.widgets.findIndex(obj => obj.name === 'text')];
|
||||
let category = this.widgets[this.widgets.findIndex(obj => obj.name === 'category')];
|
||||
let cat_values=[]
|
||||
let cat_value=''
|
||||
let tagsValue=''
|
||||
|
||||
Object.defineProperty(category.options, "values", {
|
||||
set: (x) => {
|
||||
},
|
||||
@@ -193,7 +254,6 @@ app.registerExtension({
|
||||
return cat_values;
|
||||
}
|
||||
});
|
||||
let text_value=[]
|
||||
Object.defineProperty(category, "value", {
|
||||
set: (x) => {
|
||||
if(cat_value!=x){
|
||||
@@ -201,25 +261,32 @@ app.registerExtension({
|
||||
if(!cat_value){
|
||||
return
|
||||
}
|
||||
if(this.widgets.length!=4){
|
||||
const list = $el("ol.lam-model-tags-list", getTagList(pb_cache[prompt_type.value][cat_value]));
|
||||
this.addDOMWidget('tags',"list",list)
|
||||
}else{
|
||||
if(pb_cache[prompt_type.value]&&pb_cache[prompt_type.value][cat_value]){
|
||||
this.widgets[3].element.innerHTML=''
|
||||
let list =getTagList(pb_cache[prompt_type.value][cat_value]);
|
||||
this.widgets[3].element.append(...list)
|
||||
}
|
||||
if(pb_cache[prompt_type.value]&&pb_cache[prompt_type.value][cat_value]){
|
||||
tags.element.children[1].innerHTML=''
|
||||
let list =getTagList(pb_cache[prompt_type.value][cat_value],cat_value);
|
||||
tags.element.children[1].append(...list)
|
||||
}
|
||||
this.widgets[3].element.querySelectorAll(".lam-model-tag").forEach(el => {
|
||||
if(text_value.includes(el.dataset.tag)){
|
||||
tags.element.children[1].querySelectorAll(".lam-model-tag").forEach(el => {
|
||||
if(this.properties["values"].includes(el.dataset.tag)){
|
||||
el.classList.add("lam-model-tag--selected");
|
||||
}
|
||||
});
|
||||
this.setSize([500, 600]);
|
||||
|
||||
|
||||
}
|
||||
},
|
||||
get: () => {
|
||||
if(pb_cache[prompt_type.value]&&pb_cache[prompt_type.value][cat_value]&&tags.element.children[1].children.length==0){
|
||||
let list =getTagList(pb_cache[prompt_type.value][cat_value],cat_value);
|
||||
tags.element.children[1].append(...list)
|
||||
tags.element.children[1].querySelectorAll(".lam-model-tag").forEach(el => {
|
||||
if(this.properties["values"].includes(el.dataset.tag)){
|
||||
el.classList.add("lam-model-tag--selected");
|
||||
}
|
||||
this.setSize([500, 600]);
|
||||
});
|
||||
}
|
||||
return cat_value;
|
||||
}
|
||||
});
|
||||
@@ -228,24 +295,51 @@ app.registerExtension({
|
||||
|
||||
},
|
||||
get: () => {
|
||||
this.widgets[3].element.querySelectorAll(".lam-model-tag").forEach(el => {
|
||||
if(el.classList.value.indexOf("lam-model-tag--selected")>=0){
|
||||
if(!text_value.includes(el.dataset.tag)){
|
||||
text_value.push(el.dataset.tag);
|
||||
textEl.value=text_value.join(',');
|
||||
let namestr=Object.keys(this.properties['selTags']).join(',')
|
||||
let delList=[]
|
||||
tags.element.children[3].querySelectorAll(".lam-model-tag--del").forEach(el => {
|
||||
delList.push(el.dataset.tag)
|
||||
})
|
||||
tags.element.children[1].querySelectorAll(".lam-model-tag").forEach(el => {
|
||||
if(el.classList.value.indexOf("lam-model-tag--selected")>=0&&!delList.includes(el.dataset.tag)){
|
||||
if(!this.properties["values"].includes(el.dataset.tag)){
|
||||
this.properties["values"].push(el.dataset.tag);
|
||||
}
|
||||
if(!Object.keys(this.properties['selTags']).includes(el.dataset.name)){
|
||||
this.properties['selTags'][el.dataset.tag]={tag:el.dataset.tag,name:el.dataset.name,cat:el.dataset.cat}
|
||||
}
|
||||
}else{
|
||||
if(text_value.includes(el.dataset.tag)){
|
||||
text_value=text_value.filter(v=>v!=el.dataset.tag);
|
||||
textEl.value=text_value.join(',');
|
||||
if(delList.includes(el.dataset.tag)){
|
||||
el.classList.remove("lam-model-tag--selected");
|
||||
delList=delList.filter(v=>v!=el.dataset.tag)
|
||||
}
|
||||
if(this.properties["values"].includes(el.dataset.tag)){
|
||||
this.properties["values"]=this.properties["values"].filter(v=>v!=el.dataset.tag);
|
||||
delete this.properties['selTags'][el.dataset.tag];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
});
|
||||
return '';
|
||||
for(let i=0;i<delList.length;i++){
|
||||
if(this.properties["values"].includes(delList[i])){
|
||||
this.properties["values"]=this.properties["values"].filter(v=>v!=delList[i]);
|
||||
delete this.properties['selTags'][delList[i]];
|
||||
}
|
||||
}
|
||||
if(namestr!=Object.keys(this.properties['selTags']).join(',')||tags.element.children[3].innerHTML==''){
|
||||
if(Object.keys(this.properties['selTags']).length>0){
|
||||
let sellist=getSelList(this.properties['selTags'])
|
||||
tags.element.children[3].innerHTML=''
|
||||
tags.element.children[3].append(...sellist)
|
||||
}else{
|
||||
tags.element.children[3].innerHTML=''
|
||||
}
|
||||
}
|
||||
tagsValue = this.properties["values"].join(',');
|
||||
return tagsValue;
|
||||
}
|
||||
});
|
||||
this.setSize([400, 400]);
|
||||
this.setSize([500, 600]);
|
||||
return r;
|
||||
};
|
||||
|
||||
|
||||
+1
-1
@@ -7,7 +7,7 @@ app.registerExtension({
|
||||
name: "StatusInfo",
|
||||
async beforeRegisterNodeDef(nodeType, nodeData, app) {
|
||||
var names=["Image2Video",'Video2TalkingFace','VideoAddAudio','Image2TalkingFace','ForEnd','LoadVideo','VideoFaceFusion',
|
||||
'Text2AutioEdgeTts','VideoRoopFaceSwap']
|
||||
'Text2AutioEdgeTts','VideoRoopFaceSwap','PromptTranslator']
|
||||
if (names.indexOf(nodeData.name)>=0) {
|
||||
// When the node is created we want to add a readonly text widget to display the text
|
||||
const onNodeCreated = nodeType.prototype.onNodeCreated;
|
||||
|
||||
+3
-2
@@ -30,6 +30,7 @@ $el("style", {
|
||||
}
|
||||
.lam_style-model-tags-list {
|
||||
display: flex;
|
||||
align-content: flex-start;
|
||||
flex-wrap: wrap;
|
||||
list-style: none;
|
||||
gap: 10px;
|
||||
@@ -41,6 +42,7 @@ $el("style", {
|
||||
}
|
||||
.lam_style-model-tags-sel-list {
|
||||
display: flex;
|
||||
align-content: flex-start;
|
||||
flex-wrap: wrap;
|
||||
list-style: none;
|
||||
gap: 10px;
|
||||
@@ -59,7 +61,6 @@ $el("style", {
|
||||
border-radius: 5px;
|
||||
padding: 2px 5px;
|
||||
cursor: pointer;
|
||||
height: 26px;
|
||||
}
|
||||
.lam_style-model-tag--selected span::before {
|
||||
content: "✅";
|
||||
@@ -257,7 +258,7 @@ app.registerExtension({
|
||||
//stylesEl.inputEl.classList.add("lam-model-notes");
|
||||
const list = $el("ol.lam_style-model-tags-list",[]);
|
||||
const lists = $el("ol.lam_style-model-tags-sel-list",[]);
|
||||
let styles=this.addDOMWidget('button',"btn",$el('div.lam_style-preview',[$el('button',{
|
||||
let styles=this.addDOMWidget('styles',"list",$el('div.lam_style-preview',[$el('button',{
|
||||
textContent:'清除全部选择',
|
||||
style:{},
|
||||
onclick:()=>{
|
||||
|
||||
+11
-5
@@ -43,8 +43,8 @@ async def del_groupNode(request):
|
||||
if 'name' in list(json_data.keys()):
|
||||
if json_data['name'] in data:
|
||||
del data[json_data['name']]
|
||||
with open(file, 'w', encoding='utf-8') as f:
|
||||
json.dump(data, f, ensure_ascii=False, indent=4)
|
||||
with open(file, 'w', encoding='utf-8') as f:
|
||||
json.dump(data, f, ensure_ascii=False, indent=4)
|
||||
return web.Response(status=201)
|
||||
|
||||
#获取提示词
|
||||
@@ -87,9 +87,10 @@ class EasyPromptSelecto:
|
||||
|
||||
return {
|
||||
"required": {
|
||||
"text": ("STRING", {"multiline": True}),
|
||||
"text": ("STRING",{"default": ""}),
|
||||
"prompt_type":(files_name, ),
|
||||
},
|
||||
"hidden": {"unique_id": "UNIQUE_ID","wprompt":"PROMPT"},
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("STRING",)
|
||||
@@ -101,8 +102,13 @@ class EasyPromptSelecto:
|
||||
|
||||
CATEGORY = "lam"
|
||||
|
||||
def translate(self,text,**args):
|
||||
return (text,)
|
||||
def translate(self,prompt_type,unique_id,wprompt,text=''):
|
||||
values = ''
|
||||
if unique_id in wprompt:
|
||||
if wprompt[unique_id]["inputs"]['tags']:
|
||||
#分割字符串
|
||||
values = wprompt[unique_id]["inputs"]['tags']
|
||||
return (text+values,)
|
||||
|
||||
# A dictionary that contains all nodes you want to export with their names
|
||||
# NOTE: names should be globally unique
|
||||
|
||||
@@ -0,0 +1,94 @@
|
||||
from PIL import Image
|
||||
import numpy as np
|
||||
import os
|
||||
import time
|
||||
import requests
|
||||
import json
|
||||
|
||||
#获取组节点
|
||||
confdir = os.path.abspath(os.path.join(__file__, "../../config"))
|
||||
if not os.path.exists(confdir):
|
||||
os.mkdir(confdir)
|
||||
|
||||
class PromptTranslator:
|
||||
def __init__(self):
|
||||
self.data={"apiKey": "", "secretKey": "", "access_token": ""}
|
||||
self.baiduPath=os.path.join(confdir,'baidu.json')
|
||||
if os.path.exists(self.baiduPath):
|
||||
with open(self.baiduPath,'r') as f:
|
||||
self.data = json.load(f)
|
||||
|
||||
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls):
|
||||
baidu=os.path.join(confdir,'baidu.json')
|
||||
data={"apiKey": "", "secretKey": "", "access_token": "","changTime":""}
|
||||
if not os.path.exists(baidu):
|
||||
with open(baidu, 'w', encoding='utf-8') as f:
|
||||
json.dump(data, f, ensure_ascii=False, indent=4)
|
||||
else:
|
||||
with open(baidu,'r') as f:
|
||||
data = json.load(f)
|
||||
|
||||
return {
|
||||
"required": {
|
||||
"apiKey": ("STRING",{"default": data.get('apiKey','')}),
|
||||
"secretKey": ("STRING",{"default": data.get('secretKey','')}),
|
||||
"fromLang": (['auto','en','zh'], ),
|
||||
"toLang": (['en','zh'], ),
|
||||
"text": ("STRING", {"multiline": True,"default":""}),
|
||||
},
|
||||
}
|
||||
RETURN_TYPES = ("STRING",)
|
||||
RETURN_NAMES = ("翻译结果",)
|
||||
FUNCTION = "translator"
|
||||
OUTPUT_NODE = True
|
||||
|
||||
CATEGORY = "lam"
|
||||
|
||||
def translator(self,apiKey,secretKey,fromLang,toLang,text):
|
||||
if self.data and self.data['access_token'] and (time.time()-float(self.data['changTime']))/ (24 * 3600) <= 29:
|
||||
accessToken=self.data['access_token']
|
||||
else:
|
||||
accessToken=self.getAccessToken(apiKey,secretKey)
|
||||
if accessToken:
|
||||
self.data['apiKey']=apiKey
|
||||
self.data['secretKey']=secretKey
|
||||
self.data['access_token']=accessToken
|
||||
self.data['changTime']=time.time()
|
||||
with open(self.baiduPath,'w',encoding='utf-8') as f:
|
||||
json.dump(self.data, f, ensure_ascii=False, indent=4)
|
||||
|
||||
url = 'https://aip.baidubce.com/rpc/2.0/mt/texttrans/v1?access_token=' + accessToken
|
||||
headers = {'Content-Type': 'application/json'}
|
||||
payload = {'q': text, 'from': fromLang, 'to': toLang, 'termIds' : ''}
|
||||
# Send request
|
||||
r = requests.post(url, params=payload, headers=headers)
|
||||
result = r.json()
|
||||
if 'error_code' in result:
|
||||
return { "ui": { "text":"翻译失败:"+result['error_msg']},"result": (text) }
|
||||
else:
|
||||
return { "ui": { "text":"翻译结果:"+result['result']['trans_result'][0]['dst']},"result": (result['result']['trans_result'][0]['dst'],)}
|
||||
|
||||
def getAccessToken(self,apiKey,secretKey):
|
||||
url = f"https://aip.baidubce.com/oauth/2.0/token?grant_type=client_credentials&client_id={apiKey}&client_secret={secretKey}"
|
||||
payload = ""
|
||||
headers = {
|
||||
'Content-Type': 'application/json',
|
||||
'Accept': 'application/json'
|
||||
}
|
||||
|
||||
response = requests.request("POST", url, headers=headers, data=payload)
|
||||
data = response.json()
|
||||
if 'error' in data:
|
||||
return None
|
||||
else:
|
||||
return data['access_token']
|
||||
|
||||
NODE_CLASS_MAPPINGS = {
|
||||
"PromptTranslator": PromptTranslator
|
||||
}
|
||||
|
||||
NODE_DISPLAY_NAME_MAPPINGS = {
|
||||
"PromptTranslator": "百度翻译"
|
||||
}
|
||||
+13
-6
@@ -84,12 +84,13 @@ class StyleSelecto:
|
||||
},
|
||||
"optional": {
|
||||
"negative_prompt":("STRING",{"forceInput": True}),
|
||||
"i": ("INT",{"forceInput": True}),
|
||||
},
|
||||
"hidden": {"unique_id": "UNIQUE_ID","wprompt":"PROMPT"},
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("STRING","STRING",)
|
||||
RETURN_NAMES = ("正向提示词","反向提示词",)
|
||||
RETURN_TYPES = ("STRING","STRING","STRING",)
|
||||
RETURN_NAMES = ("正向提示词","反向提示词","i项风格名称",)
|
||||
|
||||
FUNCTION = "get_style"
|
||||
|
||||
@@ -97,19 +98,25 @@ class StyleSelecto:
|
||||
|
||||
CATEGORY = "lam"
|
||||
|
||||
def get_style(self,prompt,style_type,unique_id,wprompt,negative_prompt=""):
|
||||
def get_style(self,prompt,style_type,unique_id,wprompt,negative_prompt="",i=None):
|
||||
values = []
|
||||
if unique_id in wprompt:
|
||||
if wprompt[unique_id]["inputs"]['button']:
|
||||
if wprompt[unique_id]["inputs"]['styles']:
|
||||
#分割字符串
|
||||
values = wprompt[unique_id]["inputs"]['button'].split(',')
|
||||
values = wprompt[unique_id]["inputs"]['styles'].split(',')
|
||||
if i!=None:
|
||||
keysl=list(self.styleAll.keys())
|
||||
if 'prompt' in self.styleAll[keysl[i]]:
|
||||
prompt=self.styleAll[keysl[i]]['prompt'].format(prompt=prompt)
|
||||
if 'negative_prompt' in self.styleAll[keysl[i]]:
|
||||
negative_prompt+=','+self.styleAll[keysl[i]]['negative_prompt']
|
||||
for val in values:
|
||||
if 'prompt' in self.styleAll[val]:
|
||||
prompt=self.styleAll[val]['prompt'].format(prompt=prompt)
|
||||
if 'negative_prompt' in self.styleAll[val]:
|
||||
negative_prompt+=','+self.styleAll[val]['negative_prompt']
|
||||
|
||||
return (prompt,negative_prompt)
|
||||
return (prompt,negative_prompt,keysl[i] if i else '')
|
||||
|
||||
# A dictionary that contains all nodes you want to export with their names
|
||||
# NOTE: names should be globally unique
|
||||
|
||||
@@ -0,0 +1,152 @@
|
||||
import json
|
||||
import re
|
||||
import os
|
||||
import csv
|
||||
import string
|
||||
from collections import OrderedDict
|
||||
from transformers import MarianMTModel,MarianTokenizer
|
||||
|
||||
|
||||
|
||||
#获取组节点
|
||||
confdir = os.path.abspath(os.path.join(__file__, "../../config"))
|
||||
if not os.path.exists(confdir):
|
||||
os.mkdir(confdir)
|
||||
|
||||
my_translations = os.path.join(confdir,"translations.csv")
|
||||
model = MarianMTModel.from_pretrained('Helsinki-NLP/opus-mt-zh-en').cuda()
|
||||
tokenizer = MarianTokenizer.from_pretrained('Helsinki-NLP/opus-mt-zh-en')
|
||||
tokenizer.src_lang = "zh_CN"
|
||||
|
||||
|
||||
def translate(chinese_str: str) -> str:
|
||||
# 对中文句子进行分词
|
||||
input_ids = tokenizer.encode(chinese_str, return_tensors="pt").cuda()
|
||||
|
||||
# 进行翻译
|
||||
output_ids = model.generate(input_ids)
|
||||
|
||||
# 将翻译结果转换为字符串格式
|
||||
english_str = tokenizer.decode(output_ids[0], skip_special_tokens=True)
|
||||
#如果最后有一个.,则去掉
|
||||
if english_str[-1] == '.':
|
||||
english_str = english_str[:-1]
|
||||
return english_str
|
||||
|
||||
|
||||
|
||||
def sort_dict_by_key_length(d):
|
||||
sorted_keys = sorted(d.keys(), key=lambda x: len(x),reverse=True)
|
||||
sorted_dict = OrderedDict()
|
||||
for key in sorted_keys:
|
||||
sorted_dict[key] = d[key]
|
||||
return sorted_dict
|
||||
|
||||
|
||||
|
||||
|
||||
# 读取 csv 文件到内存中缓存起来
|
||||
def load_csv(csv_file):
|
||||
with open(csv_file, 'r', encoding='utf-8') as f:
|
||||
reader = csv.reader(f)
|
||||
cache = OrderedDict(reader)
|
||||
cache = sort_dict_by_key_length(cache)
|
||||
|
||||
return cache
|
||||
|
||||
|
||||
|
||||
|
||||
def contains_chinese(text):
|
||||
pattern = re.compile(r'[\u4e00-\u9fa5]')
|
||||
return bool(pattern.search(text))
|
||||
|
||||
|
||||
|
||||
|
||||
def remove_unnecessary_spaces(text):
|
||||
"""Removes unnecessary spaces between characters."""
|
||||
pattern = r"\)\s*\+\+|\)\+\+\s*"
|
||||
replacement = r")++"
|
||||
return re.sub(pattern, replacement, text)
|
||||
|
||||
|
||||
def process_text(text):
|
||||
# 将中文全角标点符号替换为半角标点符号
|
||||
text = text.translate(str.maketrans(',。!?;:‘’“”()【】', ',.!?;:\'\'\"\"()[]'))
|
||||
# 按逗号分割成数组
|
||||
text_array = text.split(',')
|
||||
# 对数组中每个字符串进行处理
|
||||
for i in range(len(text_array)):
|
||||
# 如果字符串以 < 开头 > 结尾,则是Lora,跳过不处理
|
||||
if text_array[i].startswith('<') and text_array[i].endswith('>'):
|
||||
continue
|
||||
# 判断是否只包含英文字符
|
||||
if all(char in string.printable + ' ' for char in text_array[i]):
|
||||
continue
|
||||
else:
|
||||
# 调用 transfer 函数进行翻译
|
||||
text_array[i] = translate(text_array[i])
|
||||
# 重新用逗号连接成字符串并返回
|
||||
return ','.join(text_array)
|
||||
|
||||
|
||||
|
||||
def replace_text(text, cache):
|
||||
for key, value in cache.items():
|
||||
if key in text:
|
||||
text = text.replace(key, value + ' ')
|
||||
return text
|
||||
|
||||
|
||||
|
||||
|
||||
class ZhPromptTranslator:
|
||||
@classmethod
|
||||
def INPUT_TYPES(s):
|
||||
return {
|
||||
"required": {
|
||||
"text_trans": ("STRING", {"multiline": True, "default": ""}),
|
||||
# "trans_switch": (["enabled", "disabled"],),
|
||||
},
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("STRING",)
|
||||
FUNCTION = "translation"
|
||||
CATEGORY = "lam"
|
||||
|
||||
def translation(self, text_trans, ):
|
||||
|
||||
if text_trans == "undefined":
|
||||
text_trans = ""
|
||||
|
||||
target_text = ""
|
||||
|
||||
print("prompt: ", text_trans)
|
||||
|
||||
cache = load_csv(my_translations)
|
||||
|
||||
if contains_chinese(text_trans):
|
||||
text_trans = remove_unnecessary_spaces(text_trans)
|
||||
modified_text = replace_text(text_trans, cache)
|
||||
print("modified_text: " + modified_text)
|
||||
|
||||
target_text = process_text(modified_text)
|
||||
target_text = re.sub('♪','', target_text)
|
||||
else:
|
||||
target_text = text_trans
|
||||
|
||||
print("target: " + target_text)
|
||||
|
||||
return (target_text,)
|
||||
|
||||
NODE_CLASS_MAPPINGS = {
|
||||
"ZhPromptTranslator": ZhPromptTranslator
|
||||
}
|
||||
|
||||
NODE_DISPLAY_NAME_MAPPINGS = {
|
||||
"ZhPromptTranslator": "中文翻译"
|
||||
}
|
||||
|
||||
|
||||
|
||||
+101
-4
@@ -7,7 +7,7 @@
|
||||
"Input Image": "图像输入",
|
||||
"Advanced": "高级设置",
|
||||
"Upscale or Variation": "放大或变化",
|
||||
"Image Prompt": "参考图",
|
||||
"Image Prompt": "图像提示词",
|
||||
"Inpaint or Outpaint": "内部重绘或外部扩图",
|
||||
"Drag above image to here": "将图像拖到这里",
|
||||
"Upscale or Variation:": "放大或变化:",
|
||||
@@ -50,7 +50,7 @@
|
||||
"Seed": "种子",
|
||||
"\ud83d\udcda History Log": "\ud83d\udcda 图片生成历史记录",
|
||||
"Image Style": "图像风格",
|
||||
"Fooocus V2": "Fooocus V2提示词智能扩图",
|
||||
"Fooocus V2": "Fooocus V2提示词智能扩展",
|
||||
"Default (Slightly Cinematic)": "默认(轻微的电影感)",
|
||||
"Fooocus Masterpiece": "Fooocus-杰作",
|
||||
"Fooocus Photograph": "Fooocus-照片",
|
||||
@@ -376,10 +376,12 @@
|
||||
"4Guofeng4XL_v1125D.safetensors": "国风动漫模型 4Guofeng4XL_v1125D",
|
||||
"SDXLRonghua_v30.safetensors": "国风容华 SDXLRonghua_v30",
|
||||
"juggernautXL_version6Rundiffusion.safetensors": "默认现实模型juggernautXL_version6Rundiffusion",
|
||||
"juggernautXL_v7Rundiffusion.safetensors": "默认现实模型juggernautXL_v7Rundiffusion",
|
||||
"Alt + wheel": "Alt + 滚轮",
|
||||
"Ctrl + wheel": "Ctrl + 滚轮",
|
||||
"- Zoom canvas": "= 缩放画布",
|
||||
"- Adjust brush size": "= 调整笔刷尺寸",
|
||||
"- Undo last action": "= 撤销上一步操作",
|
||||
"- Reset zoom": "= 画布复位",
|
||||
"- Fullscreen mode": "= 全屏模式",
|
||||
"- Move canvas": "= 移动画布",
|
||||
@@ -392,6 +394,7 @@
|
||||
"Downloading control models ...": "正在下载Control模型……",
|
||||
"Loading models ...": "正在装载模型……",
|
||||
"Loading control models ...": "正在装载Control模型……",
|
||||
"Downloading LCM components ...": "正在下载LCM组件……",
|
||||
"Processing prompts ...": "正在处理提示词……",
|
||||
"Image processing ...": "正在处理图像……",
|
||||
"Preparing Fooocus text #1 ...": "正在准备Fooocus文本 #1……",
|
||||
@@ -431,7 +434,7 @@
|
||||
"Inpaint Denoising Strength": "重绘去噪强度",
|
||||
"Same as the denoising strength in A1111 inpaint. Only used in inpaint, not used in outpaint. (Outpaint always use 1.0)": "与SD WebUI(A1111)重绘中的去噪强度相同。仅用于内部,不用于外部扩图。(外部扩图始终使用1.0)",
|
||||
"Inpaint Respective Field": "重绘遮罩区域",
|
||||
"The area to inpaint. Value 0 is same as \"Only Masked\" in A1111. Value 1 is same as \"Whole Image\" in A1111. Only used in inpaint, not used in outpaint. (Outpaint always use 1.0)": "重绘遮罩区域。值0与SD WebUI(A1111)中的“仅遮罩”相同。值1与SD WebUI(A1111)中的“整个图像”相同。中间值相当于PS中的羽化范围。只用于内部重绘,在外部扩图中不使用。(外部扩图总是使用1.0)",
|
||||
"The area to inpaint. Value 0 is same as \"Only Masked\" in A1111. Value 1 is same as \"Whole Image\" in A1111. Only used in inpaint, not used in outpaint. (Outpaint always use 1.0)": "仅用于手绘遮罩模式。值0与SD WebUI(A1111)中的“仅遮罩”相同。值1与SD WebUI(A1111)中的“整个图像”相同。中间值相当于PS中的羽化范围。根据扩散算法,值越高重绘区域融合度越好,显卡负担越重。(外部扩图不生效,默认1.0)",
|
||||
"Additional Prompt Quick List": "附加提示快速列表",
|
||||
"highly detailed face": "高细节的脸",
|
||||
"detailed girl face": "细节的女性脸",
|
||||
@@ -439,5 +442,99 @@
|
||||
"detailed hand": "细节的手",
|
||||
"beautiful eyes": "细节的眼",
|
||||
"Inpaint Additional Prompt": "重绘附加提示词",
|
||||
"Describe what you want to inpaint.": "描述你想要重绘的内容。"
|
||||
"Describe what you want to inpaint.": "描述你想要重绘的内容。",
|
||||
"Realtime Canvas": "实时画布",
|
||||
"Sketch": "草图",
|
||||
"Start drawing": "开始绘画",
|
||||
"Select brush color": "选择笔刷颜色",
|
||||
"Drag inapint mask image to here": "将重绘蒙版拖入这里",
|
||||
"Inpaint advanced": "内部重绘高级设置",
|
||||
"Enable upload mask": "启用蒙版上传",
|
||||
"Invert mask": "反选手绘遮罩",
|
||||
"Describe": "提示词反推",
|
||||
"Drag any image to here": "拖动任意图片到这里",
|
||||
"Content Type": "图像类型",
|
||||
"Photograph": "写实照片",
|
||||
"Art/Anime": "艺术/动漫",
|
||||
"Describe this Image into Prompt": "反推此图片的提示词",
|
||||
"Mk Chromolithography": "MK 彩色石版画",
|
||||
"Mk Cross Processing Print": "MK 交叉处理印刷",
|
||||
"Mk Dufaycolor Photograph": "MK 杜菲色彩照片",
|
||||
"Mk Herbarium": "MK 植物志",
|
||||
"Mk Punk Collage": "MK 朋克拼贴",
|
||||
"Mk Mosaic": "MK 马赛克",
|
||||
"Mk Van Gogh": "MK 梵高",
|
||||
"Mk Coloring Book": "MK 着色书",
|
||||
"Mk Singer Sargent": "MK 辛格·萨金特",
|
||||
"Mk Pollock": "MK 波洛克",
|
||||
"Mk Basquiat": "MK 巴斯奇亚特",
|
||||
"Mk Andy Warhol": "MK 安迪·沃霍尔",
|
||||
"Mk Halftone Print": "MK 半色调印刷",
|
||||
"Mk Gond Painting": "MK 贡德画",
|
||||
"Mk Albumen Print": "MK 相册印花",
|
||||
"Mk Aquatint Print": "MK 暗调印刷",
|
||||
"Mk Anthotype Print": "MK 蒙多类型印花",
|
||||
"Mk Inuit Carving": "MK 因纽特雕刻",
|
||||
"Mk Bromoil Print": "MK 溴油印画",
|
||||
"Mk Calotype Print": "MK 盐印画",
|
||||
"Mk Color Sketchnote": "MK 彩色速写笔记",
|
||||
"Mk Cibulak Porcelain": "MK 青花瓷雕塑",
|
||||
"Mk Alcohol Ink Art": "MK 酒精墨艺术",
|
||||
"Mk One Line Art": "MK 单线艺术",
|
||||
"Mk Blacklight Paint": "MK 紫外线荧光画",
|
||||
"Mk Carnival Glass": "MK 狂欢玻璃",
|
||||
"Mk Cyanotype Print": "MK 青印画",
|
||||
"Mk Cross Stitching": "MK 十字绣",
|
||||
"Mk Encaustic Paint": "MK 热蜡画",
|
||||
"Mk Embroidery": "MK 刺绣",
|
||||
"Mk Gyotaku": "MK 鱼拓",
|
||||
"Mk Luminogram": "MK 光影图",
|
||||
"Mk Lite Brite Art": "MK 亮彩艺术",
|
||||
"Mk Mokume Gane": "MK 木目金属",
|
||||
"Pebble Art": "MK 鹅卵石艺术",
|
||||
"Mk Pebble Art": "MK 鹅卵石艺术",
|
||||
"Mk Palekh": "MK 帕列赫艺术",
|
||||
"Mk Suminagashi": "MK 墨流画",
|
||||
"Mk Scrimshaw": "MK 浮雕雕刻",
|
||||
"Mk Shibori": "MK 染缬织物",
|
||||
"Mk Vitreous Enamel": "MK 琺琅雕塑",
|
||||
"Mk Ukiyo E": "MK 浮世绘",
|
||||
"Mk Vintage Airline Poster": "MK 航空复古海报",
|
||||
"Mk Vintage Travel Poster": "MK 旅行复古海报",
|
||||
"Mk Bauhaus Style": "MK 包豪斯风格",
|
||||
"Mk Afrofuturism": "MK 非洲未来主义插画",
|
||||
"Mk Atompunk": "MK 原子朋克插画",
|
||||
"Mk Constructivism": "MK 构成主义",
|
||||
"Mk Chicano Art": "MK 奇卡诺艺术",
|
||||
"Mk De Stijl": "MK 德斯泰尔艺术",
|
||||
"Mk Dayak Art": "MK 达雅克艺术雕塑",
|
||||
"Mk Fayum Portrait": "MK 法尤姆肖像",
|
||||
"Mk Illuminated Manuscript": "MK 象牙抄本",
|
||||
"Mk Kalighat Painting": "MK 卡利加特画",
|
||||
"Mk Madhubani Painting": "MK 马图哈尼画",
|
||||
"Mk Pictorialism": "MK 摄影画意主义插画",
|
||||
"Mk Pichwai Painting": "MK 皮查瓦伊画",
|
||||
"Mk Patachitra Painting": "MK 帕塔奇特拉画",
|
||||
"Mk Samoan Art Inspired": "MK 萨摩亚艺术风格木雕",
|
||||
"Mk Tlingit Art": "MK 特林吉特艺术",
|
||||
"Mk Adnate Style": "MK 阿德纳特风格画作",
|
||||
"Mk Ron English Style": "MK 罗恩·英格利斯风格画作",
|
||||
"Mk Shepard Fairey Style": "MK 谢帕德·费里风格画作",
|
||||
"Type prompt here or paste parameters.": "在此处输入提示语或粘贴参数。",
|
||||
"Load Parameters": "读取参数",
|
||||
"Prompt": "正向提示词",
|
||||
"Styles": "风格",
|
||||
"Resolution": "分辨率",
|
||||
"Sharpness": "采样锐度 Sharpness",
|
||||
"ADM Guidance": "ADM导向",
|
||||
"Base Model": "基础模型",
|
||||
"Refiner Model": "精炼模型",
|
||||
"Refiner Switch": "精炼开关",
|
||||
"Preset": "预设",
|
||||
"initial": "初始",
|
||||
"default": "默认",
|
||||
"anime": "动漫",
|
||||
"realistic": "现实",
|
||||
"lcm": "lcm极速",
|
||||
"turbo": "turbo极速"
|
||||
}
|
||||
+3
-3
@@ -1,7 +1,7 @@
|
||||
対象:
|
||||
1女孩: 1girl
|
||||
1男孩: 1boy
|
||||
1其他: 1other
|
||||
一个女孩: 1girl
|
||||
一个男孩: 1boy
|
||||
一个其他: 1other
|
||||
多个女孩: multiple girls
|
||||
|
||||
年龄:
|
||||
|
||||
Reference in New Issue
Block a user