├── .gitignore ├── .vscode └── settings.json ├── LICENSE ├── README.md └── scripts └── main.py /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | *$py.class 5 | 6 | # C extensions 7 | *.so 8 | 9 | # Distribution / packaging 10 | .Python 11 | build/ 12 | develop-eggs/ 13 | dist/ 14 | downloads/ 15 | eggs/ 16 | .eggs/ 17 | lib/ 18 | lib64/ 19 | parts/ 20 | sdist/ 21 | var/ 22 | wheels/ 23 | pip-wheel-metadata/ 24 | share/python-wheels/ 25 | *.egg-info/ 26 | .installed.cfg 27 | *.egg 28 | MANIFEST 29 | 30 | # PyInstaller 31 | # Usually these files are written by a python script from a template 32 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 33 | *.manifest 34 | *.spec 35 | 36 | # Installer logs 37 | pip-log.txt 38 | pip-delete-this-directory.txt 39 | 40 | # Unit test / coverage reports 41 | htmlcov/ 42 | .tox/ 43 | .nox/ 44 | .coverage 45 | .coverage.* 46 | .cache 47 | nosetests.xml 48 | coverage.xml 49 | *.cover 50 | *.py,cover 51 | .hypothesis/ 52 | .pytest_cache/ 53 | 54 | # Translations 55 | *.mo 56 | *.pot 57 | 58 | # Django stuff: 59 | *.log 60 | local_settings.py 61 | db.sqlite3 62 | db.sqlite3-journal 63 | 64 | # Flask stuff: 65 | instance/ 66 | .webassets-cache 67 | 68 | # Scrapy stuff: 69 | .scrapy 70 | 71 | # Sphinx documentation 72 | docs/_build/ 73 | 74 | # PyBuilder 75 | target/ 76 | 77 | # Jupyter Notebook 78 | .ipynb_checkpoints 79 | 80 | # IPython 81 | profile_default/ 82 | ipython_config.py 83 | 84 | # pyenv 85 | .python-version 86 | 87 | # pipenv 88 | # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. 89 | # However, in case of collaboration, if having platform-specific dependencies or dependencies 90 | # having no cross-platform support, pipenv may install dependencies that don't work, or not 91 | # install all needed dependencies. 92 | #Pipfile.lock 93 | 94 | # PEP 582; used by e.g. github.com/David-OConnor/pyflow 95 | __pypackages__/ 96 | 97 | # Celery stuff 98 | celerybeat-schedule 99 | celerybeat.pid 100 | 101 | # SageMath parsed files 102 | *.sage.py 103 | 104 | # Environments 105 | .env 106 | .venv 107 | env/ 108 | venv/ 109 | ENV/ 110 | env.bak/ 111 | venv.bak/ 112 | 113 | # Spyder project settings 114 | .spyderproject 115 | .spyproject 116 | 117 | # Rope project settings 118 | .ropeproject 119 | 120 | # mkdocs documentation 121 | /site 122 | 123 | # mypy 124 | .mypy_cache/ 125 | .dmypy.json 126 | dmypy.json 127 | 128 | # Pyre type checker 129 | .pyre/ 130 | 131 | # remove models 132 | models -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "ros.distro": "noetic" 3 | } -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 Saifeddine ALOUI 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Prompt Translator for Stable Diffusion 2 | [![Follow me on Twitter](https://img.shields.io/twitter/follow/SpaceNerduino?style=social)](https://twitter.com/SpaceNerduino) 3 | [![Follow Me on YouTube](https://img.shields.io/badge/Follow%20Me%20on-YouTube-red?style=flat&logo=youtube)](https://www.youtube.com/user/Parisneo) 4 | 5 | Stable diffusion is a text to image generation model. The `prompt_translator` extension allows people to translate their prompt from any language to English before executing the generation, making it accessible to a wider audience. 6 | 7 | ## Utility 8 | 9 | Here is an example of how useful prompt_translator can be: 10 | 11 | Let's say that you are a French speaker and want to use Stable Diffusion to generate an image of a beautiful mountain. However, the model requires the prompt to be in English. Without prompt_translator, you would need to either write your prompt in English (if you're comfortable with the language) or use an external translation tool to manually translate your prompt to English. 12 | 13 | With prompt_translator, you can simply select "French" as your source language and write your prompt in French. The extension will automatically translate your prompt to English before sending it to the model. This way, you can use Stable Diffusion without having to worry about the language barrier. 14 | 15 | Using prompt_translator makes Stable Diffusion more accessible to people who are not comfortable with English or have limited proficiency in the language. It opens up new possibilities for text-to-image generation by allowing users to use their native language to write prompts. 16 | 17 | We hope that prompt_translator will make Stable Diffusion more accessible and easier to use for people around the world. Please feel free to contribute to the project or report any issues on our GitHub page. 18 | 19 | ## Installation 20 | 21 | To install `prompt_translator`, clone the repository or extract the zip file to the extensions folder of the sd_webui mother application. 22 | 23 | ## Usage 24 | 25 | After installing `prompt_translator`, a new entry will be added to the Gradio UI. To use the automatic translation tool, click the "Load Translation Model" button to load the translation model. The translation model used in this tool is the `mbart-large-50-many-to-one-mmt` model developed by Meta (formerly Facebook). You can find more information about the model on its [Hugging Face model card](https://huggingface.co/facebook/mbart-large-50-many-to-one-mmt). 26 | 27 | Once the model is loaded, a dropdown UI will be displayed, where the user can select the source language of their prompt. The user can then write their prompt in the desired language and press the "Generate" button to generate the image. The prompt will automatically be translated to English, and the resulting image will look as described in the text. 28 | 29 | Here are some screenshots of the extension in work: 30 | 31 | ![image](https://user-images.githubusercontent.com/827993/228090321-2554472d-6fd0-4449-a6d4-190a62ddcce9.png) 32 | ![image](https://user-images.githubusercontent.com/827993/228090380-9f2f8928-4698-403e-8ed5-94043ed25480.png) 33 | 34 | Using the X/Y/Z script, we can test changing words in another language. Here is French: 35 | ![image](https://user-images.githubusercontent.com/827993/229276434-6e024886-13d8-4aa5-b143-6622e544f192.png) 36 | 37 | ## Supported Languages 38 | 39 | The list of supported languages is: Arabic (ar_AR), Czech (cs_CZ), German (de_DE), English (en_XX), Spanish (es_XX), Estonian (et_EE), Finnish (fi_FI), French (fr_XX), Gujarati (gu_IN), Hindi (hi_IN), Italian (it_IT), Japanese (ja_XX), Kazakh (kk_KZ), Korean (ko_KR), Lithuanian (lt_LT), Latvian (lv_LV), Burmese (my_MM), Nepali (ne_NP), Dutch (nl_XX), Romanian (ro_RO), Russian (ru_RU), Sinhala (si_LK), Turkish (tr_TR), Vietnamese (vi_VN), Chinese (zh_CN), Afrikaans (af_ZA), Azerbaijani (az_AZ), Bengali (bn_IN), Persian (fa_IR), Hebrew (he_IL), Croatian (hr_HR), Indonesian (id_ID), Georgian (ka_GE), Khmer (km_KH), Macedonian (mk_MK), Malayalam (ml_IN), Mongolian (mn_MN), Marathi (mr_IN), Polish (pl_PL), Pashto (ps_AF), Portuguese (pt_XX), Swedish (sv_SE), Swahili (sw_KE), Tamil (ta_IN), Telugu (te_IN), Thai (th_TH), Tagalog (tl_XX), Ukrainian (uk_UA), Urdu (ur_PK), Xhosa (xh_ZA), Galician (gl_ES), Slovene (sl_SI). 40 | 41 | ## License 42 | 43 | This project is licensed under the MIT license. 44 | 45 | ## Contributing 46 | Contributions to prompt_translator are welcome! If you find a bug or have an idea for a new feature, please create an issue on the project's GitHub page. If you'd like to contribute code, please fork the repository, make your changes, and submit a pull request. 47 | -------------------------------------------------------------------------------- /scripts/main.py: -------------------------------------------------------------------------------- 1 | # MBartTranslator : 2 | # Author : ParisNeo 3 | # Description : This script translates Stable diffusion prompt from one of the 50 languages supported by MBART 4 | # It uses MBartTranslator class that provides a simple interface for translating text using the MBart language model. 5 | 6 | import os 7 | import re 8 | 9 | import gradio as gr 10 | from transformers import MBart50TokenizerFast, MBartForConditionalGeneration 11 | 12 | import modules.scripts as scripts 13 | 14 | # The directory to store the models 15 | cache_dir = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'models') 16 | 17 | 18 | class MBartTranslator: 19 | """MBartTranslator class provides a simple interface for translating text using the MBart language model. 20 | 21 | The class can translate between 50 languages and is based on the "facebook/mbart-large-50-many-to-many-mmt" 22 | pre-trained MBart model. However, it is possible to use a different MBart model by specifying its name. 23 | 24 | Attributes: 25 | model (MBartForConditionalGeneration): The MBart language model. 26 | tokenizer (MBart50TokenizerFast): The MBart tokenizer. 27 | """ 28 | 29 | def __init__(self, model_name="facebook/mbart-large-50-many-to-many-mmt", src_lang=None, tgt_lang=None): 30 | 31 | print("Building translator") 32 | print("Loading generator (this may take few minutes the first time as I need to download the model)") 33 | self.model = MBartForConditionalGeneration.from_pretrained(model_name, cache_dir=cache_dir) 34 | print("Loading tokenizer") 35 | self.tokenizer = MBart50TokenizerFast.from_pretrained(model_name, src_lang=src_lang, tgt_lang=tgt_lang, 36 | cache_dir=cache_dir) 37 | print("Translator is ready") 38 | 39 | def translate(self, text: str, input_language: str, output_language: str) -> str: 40 | """Translate the given text from the input language to the output language. 41 | 42 | Args: 43 | text (str): The text to translate. 44 | input_language (str): The input language code (e.g. "hi_IN" for Hindi). 45 | output_language (str): The output language code (e.g. "en_US" for English). 46 | 47 | Returns: 48 | str: The translated text. 49 | """ 50 | if input_language not in self.tokenizer.lang_code_to_id: 51 | raise ValueError( 52 | f"Input language not supported. Supported languages: {self.tokenizer.lang_code_to_id}") 53 | if output_language not in self.tokenizer.lang_code_to_id: 54 | raise ValueError( 55 | f"Output language not supported. Supported languages: {self.tokenizer.lang_code_to_id}") 56 | 57 | self.tokenizer.src_lang = input_language 58 | encoded_input = self.tokenizer(text, return_tensors="pt") 59 | generated_tokens = self.model.generate( 60 | **encoded_input, forced_bos_token_id=self.tokenizer.lang_code_to_id[output_language] 61 | ) 62 | translated_text = self.tokenizer.batch_decode(generated_tokens, skip_special_tokens=True) 63 | 64 | return translated_text[0] 65 | 66 | 67 | # This is a list of LanguageOption objects that represent the various language options available. 68 | # Each LanguageOption object contains a label that represents the display name of the language and 69 | # a language code that represents the code for the language that will be used by the translation model. 70 | # The language codes follow a format of "xx_YY" where "xx" represents the language code and "YY" represents the 71 | # country or region code. If the language code is not specific to a country or region, then "XX" is used instead. 72 | # For example, "en_XX" represents English language and "fr_FR" represents French language specific to France. 73 | # These LanguageOption objects will be used to display the language options to the user and to retrieve the 74 | # corresponding language code when the user selects a language. 75 | language_options = { 76 | 'Afrikaans': 'af_ZA', 77 | 'Arabic': 'ar_AR', 78 | 'Azerbaijani (Azerbaijan)': 'az_AZ', 79 | 'Bengali (India)': 'bn_IN', 80 | 'Burmese (Myanmar)': 'my_MM', 81 | 'Chinese': 'zh_CN', 82 | 'Croatian': 'hr_HR', 83 | 'Czech': 'cs_CZ', 84 | 'Deutsch': 'de_DE', 85 | "Dutch": "nl_XX", 86 | 'English': 'en_XX', 87 | 'Estonian': 'et_EE', 88 | 'Finnish': 'fi_FI', 89 | 'French': 'fr_XX', 90 | 'Galician (Spain)': 'gl_ES', 91 | 'Georgian': 'ka_GE', 92 | 'Gujarati': 'gu_IN', 93 | 'Hebrew': 'he_IL', 94 | 'Hindi': 'hi_IN', 95 | 'Indonesian': 'id_ID', 96 | 'Italian': 'it_IT', 97 | 'Japanese': 'ja_XX', 98 | 'Kazakh (Kazakhstan)': 'kk_KZ', 99 | 'Khmer': 'km_KH', 100 | 'Korean': 'ko_KR', 101 | 'Latvian': 'lv_LV', 102 | 'Lithuanian': 'lt_LT', 103 | 'Macedonian': 'mk_MK', 104 | 'Malayalam': 'ml_IN', 105 | 'Marathi': 'mr_IN', 106 | 'Mongolian (Mongolia)': 'mn_MN', 107 | 'Nepali': 'ne_NP', 108 | 'Pashto (Afghanistan)': 'ps_AF', 109 | 'Persian': 'fa_IR', 110 | 'Polish (Poland)': 'pl_PL', 111 | 'Portuguese': 'pt_XX', 112 | 'Romanian': 'ro_RO', 113 | 'Russian': 'ru_RU', 114 | 'Sinhala': 'si_LK', 115 | 'Slovenian': 'sl_SI', 116 | 'Spanish': 'es_XX', 117 | 'Swahili (Kenya)': 'sw_KE', 118 | 'Swedish (Sweden)': 'sv_SE', 119 | 'Tamil': 'ta_IN', 120 | 'Telugu': 'te_IN', 121 | "Tagalog": "tl_XX", 122 | 'Thai': 'th_TH', 123 | 'Turkish': 'tr_TR', 124 | 'Ukrainian': 'uk_UA', 125 | 'Urdu': 'ur_PK', 126 | 'Vietnamese': 'vi_VN', 127 | 'Xhosa (South Africa)': 'xh_ZA' 128 | } 129 | 130 | 131 | def remove_unnecessary_spaces(text): 132 | """Removes unnecessary spaces between characters.""" 133 | pattern = r"\)\s*\+\+|\)\+\+\s*" 134 | replacement = r")++" 135 | return re.sub(pattern, replacement, text) 136 | 137 | 138 | def correct_translation_format(original_text, translated_text): 139 | original_parts = original_text.split('++') 140 | translated_parts = translated_text.split('++') 141 | 142 | corrected_parts = [] 143 | for i, original_part in enumerate(original_parts): 144 | translated_part = translated_parts[i] 145 | 146 | original_plus_count = original_part.count('+') 147 | translated_plus_count = translated_part.count('+') 148 | plus_difference = translated_plus_count - original_plus_count 149 | 150 | if plus_difference > 0: 151 | translated_part = translated_part.replace('+' * plus_difference, '', 1) 152 | elif plus_difference < 0: 153 | translated_part += '+' * abs(plus_difference) 154 | 155 | corrected_parts.append(translated_part) 156 | 157 | corrected_text = '++'.join(corrected_parts) 158 | return corrected_text 159 | 160 | 161 | def extract_plus_positions(text): 162 | """ 163 | Given a string of text, extracts the positions of all sequences of one or more '+' characters. 164 | 165 | Args: 166 | - text (str): the input text 167 | 168 | Returns: 169 | - positions (list of lists): a list of [start, end, count] for each match, where start is the index of the 170 | first '+' character, end is the index of the last '+' character + 1, and count is the number of '+' characters 171 | in the match. 172 | """ 173 | # Match any sequence of one or more '+' characters 174 | pattern = re.compile(r'\++') 175 | 176 | # Find all matches of the pattern in the text 177 | matches = pattern.finditer(text) 178 | 179 | # Loop through the matches and add their positions to the output list 180 | positions = [] 181 | last_match_end = None 182 | for match in matches: 183 | if last_match_end is not None and match.start() != last_match_end: 184 | # If there is a gap between the current match and the previous one, add a new position 185 | j = last_match_end - 1 186 | while text[j] == "+": 187 | j -= 1 188 | j += 1 189 | positions.append([j, last_match_end, last_match_end - j]) 190 | 191 | last_match_end = match.end() 192 | 193 | # If the final match extends to the end of the string, add its position to the output list 194 | if last_match_end is not None and last_match_end == len(text): 195 | j = last_match_end - 1 196 | while text[j] == "+": 197 | j -= 1 198 | j += 1 199 | positions.append([j, last_match_end, last_match_end - j]) 200 | 201 | return positions 202 | 203 | 204 | def match_pluses(original_text, translated_text): 205 | """ 206 | Given two strings of text, replaces sequences of '+' characters in the second string with the corresponding 207 | sequences of '+' characters in the first string. 208 | 209 | Args: 210 | - original_text (str): the original text 211 | - translated_text (str): the translated text with '+' characters 212 | 213 | Returns: 214 | - output (str): the translated text with '+' characters replaced by those in the original text 215 | """ 216 | in_positions = extract_plus_positions(original_text) 217 | out_positions = extract_plus_positions(translated_text) 218 | 219 | out_vals = [] 220 | out_current_pos = 0 221 | 222 | if len(in_positions) == len(out_positions): 223 | # Iterate through the positions and replace the sequences of '+' characters in the translated text 224 | # with those in the original text 225 | for in_, out_ in zip(in_positions, out_positions): 226 | out_vals.append(translated_text[out_current_pos:out_[0]]) 227 | out_vals.append(original_text[in_[0]:in_[1]]) 228 | out_current_pos = out_[1] 229 | 230 | # Check that the number of '+' characters in the original and translated sequences is the same 231 | if in_[2] != out_[2]: 232 | print("detected different + count") 233 | 234 | # Add any remaining text from the translated string to the output 235 | out_vals.append(translated_text[out_current_pos:]) 236 | 237 | # Join the output values into a single string 238 | output = "".join(out_vals) 239 | return output 240 | 241 | 242 | def post_process_prompt(original, translated): 243 | """Applies post-processing to the translated prompt such as removing unnecessary spaces and extra plus signs.""" 244 | clean_prompt = remove_unnecessary_spaces(translated) 245 | clean_prompt = match_pluses(original, clean_prompt) 246 | # clean_prompt = remove_extra_plus(clean_prompt) 247 | return clean_prompt 248 | 249 | 250 | class Script(scripts.Script): 251 | def __init__(self) -> None: 252 | """Initializes the Script class and sets the default value for enable_translation attribute.""" 253 | super().__init__() 254 | self.enable_translation = False 255 | self.is_negative_translate_active = False 256 | 257 | def title(self): 258 | """Returns the title of the script.""" 259 | return "Translate prompt to english" 260 | 261 | def show(self, is_img2img): 262 | """Returns the visibility status of the script in the interface.""" 263 | return scripts.AlwaysVisible 264 | 265 | def set_active(self, active): 266 | """Sets the is_active attribute and initializes the translator object if not already created. 267 | Also, sets the visibility of the language dropdown to True.""" 268 | self.is_active = active 269 | if not hasattr(self, "translator"): 270 | self.translator = MBartTranslator() 271 | if self.is_active: 272 | return "# I am ready", self.options.update(visible=True) 273 | else: 274 | return "After enabling translation, please Wait until I am ready", self.options.update(visible=False) 275 | 276 | def set_negative_translate_active(self, negative_translate_active): 277 | """Sets the is_active attribute and initializes the translator object if not already created. 278 | Also, sets the visibility of the language dropdown to True.""" 279 | self.is_negative_translate_active = negative_translate_active 280 | 281 | def ui(self, is_img2img): 282 | """Sets up the user interface of the script.""" 283 | self.is_active = False 284 | 285 | with gr.Row(): 286 | with gr.Column(scale=19): 287 | with gr.Accordion("Prompt Translator", open=False): 288 | with gr.Accordion("Help", open=False): 289 | gr.Markdown(""" 290 | # Description 291 | This script translates your prompt from another language to english before generating the image allowing you to write prompts in your native language. 292 | # How to use 293 | Select Enable translation and wait until you the label shows ready. 294 | Once the label has Ready on it, select the prompt language, write the prompt in the prompt field then press generate. The script will translate the prompt and generate the text. 295 | # Note 296 | First time you enable the script, it may take a long time (around a minute), but once loaded, it will be faster. 297 | """) 298 | with gr.Column(): 299 | self.enable_translation = gr.Checkbox(label="Enable translation") 300 | with gr.Column() as options: 301 | self.options = options 302 | self.translate_negative_prompt = gr.Checkbox(label="Translate negative prompt") 303 | self.enable_translation.value = False 304 | self.language = gr.Dropdown( 305 | label="Source language", 306 | choices=sorted(language_options.keys()), 307 | value="Chinese", 308 | type="value", 309 | elem_id=self.elem_id("x_type") 310 | ) 311 | self.output = gr.Markdown(value="After enabling translation, please Wait until I am ready", 312 | visible=True) 313 | self.enable_translation.change( 314 | self.set_active, 315 | [self.enable_translation], 316 | [self.output, self.options], 317 | show_progress=True 318 | ) 319 | self.translate_negative_prompt.change( 320 | self.set_negative_translate_active, 321 | [self.translate_negative_prompt], 322 | ) 323 | 324 | self.options.visible = False 325 | return [self.language] 326 | 327 | def get_prompts(self, p): 328 | """Returns the original prompts and negative prompts associated with a Prompt object.""" 329 | original_prompts = p.all_prompts if len(p.all_prompts) > 0 else [p.prompt] 330 | original_negative_prompts = ( 331 | p.all_negative_prompts 332 | if len(p.all_negative_prompts) > 0 333 | else [p.negative_prompt] 334 | ) 335 | 336 | return original_prompts, original_negative_prompts 337 | 338 | def process(self, p, language, **kwargs): 339 | """Translates the prompts from a non-English language to English using the MBartTranslator object.""" 340 | 341 | if hasattr(self, "translator") and self.is_active: 342 | original_prompts, original_negative_prompts = self.get_prompts(p) 343 | translated_prompts = [] 344 | previous_prompt = "" 345 | previous_translated_prompt = "" 346 | 347 | for original_prompt in original_prompts: 348 | if previous_prompt != original_prompt: 349 | print(f"Translating prompt to English from {language}") 350 | print(f"Initial prompt:{original_prompt}") 351 | ln_code = language_options[language] 352 | translated_prompt = self.translator.translate(original_prompt, ln_code, "en_XX") 353 | translated_prompt = post_process_prompt(original_prompt, translated_prompt) 354 | print(f"Translated prompt:{translated_prompt}") 355 | translated_prompts.append(translated_prompt) 356 | 357 | previous_prompt = original_prompt 358 | previous_translated_prompt = translated_prompt 359 | else: 360 | translated_prompts.append(previous_translated_prompt) 361 | 362 | if p.negative_prompt != '' and self.is_negative_translate_active: 363 | previous_negative_prompt = "" 364 | previous_translated_negative_prompt = "" 365 | translated_negative_prompts = [] 366 | for negative_prompt in original_negative_prompts: 367 | if previous_negative_prompt != negative_prompt: 368 | print(f"Translating negative prompt to English from {language}") 369 | print(f"Initial negative prompt:{negative_prompt}") 370 | ln_code = language_options[language] 371 | translated_negative_prompt = self.translator.translate(negative_prompt, ln_code, "en_XX") 372 | translated_negative_prompt = post_process_prompt(negative_prompt, translated_negative_prompt) 373 | print(f"Translated negative prompt:{translated_negative_prompt}") 374 | translated_negative_prompts.append(translated_negative_prompt) 375 | 376 | previous_negative_prompt = negative_prompt 377 | previous_translated_negative_prompt = translated_negative_prompt 378 | else: 379 | translated_negative_prompts.append(previous_translated_negative_prompt) 380 | 381 | p.negative_prompt = translated_negative_prompts[0] 382 | p.all_negative_prompts = translated_negative_prompts 383 | p.prompt = translated_prompts[0] 384 | p.prompt_for_display = translated_prompts[0] 385 | p.all_prompts = translated_prompts 386 | --------------------------------------------------------------------------------