pengdaqian commited on
Commit
49226f5
1 Parent(s): 134c419
Files changed (8) hide show
  1. app.py +217 -105
  2. i18n.py +28 -0
  3. locales/zh-CN.json +3 -0
  4. model_test.py +20 -0
  5. requirements.txt +2 -1
  6. trans_constant.py +179 -0
  7. trans_google.py +251 -0
  8. trans_test.py +5 -0
app.py CHANGED
@@ -1,49 +1,122 @@
 
 
1
  import gradio as gr
2
  from datasets import load_dataset
3
  from PIL import Image
 
4
 
5
- import re
6
- import os
7
- import requests
8
-
9
- from share_btn import community_icon_html, loading_icon_html, share_js
10
 
11
  word_list_dataset = load_dataset("Gustavosta/Stable-Diffusion-Prompts")
12
  word_list = word_list_dataset["train"]['Prompt']
13
 
14
- from diffusers import StableDiffusionPipeline, EulerDiscreteScheduler
 
 
 
15
  import torch
 
 
16
 
 
17
  model_id = "stabilityai/stable-diffusion-2-1-base"
18
 
19
  scheduler = EulerDiscreteScheduler.from_pretrained(model_id, subfolder="scheduler")
20
  pipe = StableDiffusionPipeline.from_pretrained(
21
  model_id,
22
  scheduler=scheduler,
23
- safety_checker=None,
 
24
  torch_dtype=torch.float16)
25
 
 
 
26
  is_gpu_busy = False
27
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
28
 
29
- def infer(prompt, negative, scale):
 
30
  global is_gpu_busy
31
- for filter in word_list:
32
- if re.search(rf"\b{filter}\b", prompt):
33
- raise gr.Error("Unsafe content found. Please try again with different prompts.")
 
 
34
 
35
  images = []
36
- generator = torch.manual_seed(68781279)
37
- payload = {'prompt': prompt, 'negative_prompt': negative, 'guidance_scale': scale}
38
- image = pipe(prompt=prompt,
39
- negative_prompt=negative,
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
40
  guidance_scale=scale,
41
- num_inference_steps=15,
42
  generator=generator,
43
- height=512,
44
- width=768).images[0]
 
 
 
 
 
45
 
46
- images.append(image)
47
 
48
  return images
49
 
@@ -170,37 +243,76 @@ css = """
170
  #prompt-text-input, #negative-prompt-text-input{padding: .45rem 0.625rem}
171
  #component-16{border-top-width: 1px!important;margin-top: 1em}
172
  .image_duplication{position: absolute; width: 100px; left: 50px}
 
 
173
  """
174
 
175
  block = gr.Blocks(css=css)
176
 
177
- examples = [
178
- [
179
- 'A high tech solarpunk utopia in the Amazon rainforest',
180
- 'low quality',
181
- 9
182
- ],
183
- [
184
- 'A pikachu fine dining with a view to the Eiffel Tower',
185
- 'low quality',
186
- 9
187
- ],
188
- [
189
- 'A mecha robot in a favela in expressionist style',
190
- 'low quality, 3d, photorealistic',
191
- 9
192
- ],
193
- [
194
- 'an insect robot preparing a delicious meal',
195
- 'low quality, illustration',
196
- 9
197
- ],
198
- [
199
- "A small cabin on top of a snowy mountain in the style of Disney, artstation",
200
- 'low quality, ugly',
201
- 9
202
- ],
203
- ]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
204
 
205
  with block:
206
  gr.HTML(
@@ -252,14 +364,9 @@ with block:
252
  </h1>
253
  </div>
254
  <p style="margin-bottom: 10px; font-size: 94%; line-height: 23px;">
255
- Stable Diffusion 2.1 is the latest text-to-image model from StabilityAI. <a style="text-decoration: underline;" href="https://huggingface.co/spaces/stabilityai/stable-diffusion-1">Access Stable Diffusion 1 Space here</a><br>For faster generation and API
256
- access you can try
257
- <a
258
- href="http://beta.dreamstudio.ai/"
259
- style="text-decoration: underline;"
260
- target="_blank"
261
- >DreamStudio Beta</a
262
- >.</a>
263
  </p>
264
  </div>
265
  """
@@ -290,60 +397,65 @@ with block:
290
  rounded=(True, False, False, True),
291
  container=False,
292
  )
293
- btn = gr.Button("Generate image").style(
294
- margin=False,
295
- rounded=(False, True, True, False),
296
- full_width=False,
297
- )
298
 
299
- gallery = gr.Gallery(
300
- label="Generated images", show_label=False, elem_id="gallery"
301
- ).style(grid=[2], height="auto")
 
 
 
 
 
 
 
302
 
303
- with gr.Group(elem_id="container-advanced-btns"):
304
- # advanced_button = gr.Button("Advanced options", elem_id="advanced-btn")
305
- with gr.Group(elem_id="share-btn-container"):
306
- community_icon = gr.HTML(community_icon_html)
307
- loading_icon = gr.HTML(loading_icon_html)
308
- share_button = gr.Button("Share to community", elem_id="share-btn")
 
309
 
310
- with gr.Accordion("Advanced settings", open=False):
311
- # gr.Markdown("Advanced settings are temporarily unavailable")
312
- # samples = gr.Slider(label="Images", minimum=1, maximum=4, value=4, step=1)
313
- # steps = gr.Slider(label="Steps", minimum=1, maximum=50, value=45, step=1)
314
- guidance_scale = gr.Slider(
315
- label="Guidance Scale", minimum=0, maximum=50, value=9, step=0.1
316
- )
317
- # seed = gr.Slider(
318
- # label="Seed",
319
- # minimum=0,
320
- # maximum=2147483647,
321
- # step=1,
322
- # randomize=True,
323
- # )
324
 
325
- ex = gr.Examples(examples=examples, fn=infer, inputs=[text, negative, guidance_scale],
326
- outputs=[gallery, community_icon, loading_icon, share_button], cache_examples=False)
327
- ex.dataset.headers = [""]
328
- negative.submit(infer, inputs=[text, negative, guidance_scale], outputs=[gallery], postprocess=False)
329
- text.submit(infer, inputs=[text, negative, guidance_scale], outputs=[gallery], postprocess=False)
330
- btn.click(infer, inputs=[text, negative, guidance_scale], outputs=[gallery], postprocess=False)
 
 
 
 
331
 
332
- # advanced_button.click(
333
- # None,
334
- # [],
335
- # text,
336
- # _js="""
337
- # () => {
338
- # const options = document.querySelector("body > gradio-app").querySelector("#advanced-options");
339
- # options.style.display = ["none", ""].includes(options.style.display) ? "flex" : "none";
340
- # }""",
341
- # )
342
- share_button.click(
343
- None,
344
- [],
345
- [],
346
- _js=share_js,
347
- )
348
 
349
- block.queue(concurrency_count=80, max_size=100).launch(max_threads=150)
 
 
 
 
 
 
1
+ import random
2
+
3
  import gradio as gr
4
  from datasets import load_dataset
5
  from PIL import Image
6
+ from trans_google import google_translator
7
 
8
+ from i18n import i18nTranslator
 
 
 
 
9
 
10
  word_list_dataset = load_dataset("Gustavosta/Stable-Diffusion-Prompts")
11
  word_list = word_list_dataset["train"]['Prompt']
12
 
13
+ from diffusers import StableDiffusionPipeline, EulerDiscreteScheduler, DDIMScheduler, KDPM2AncestralDiscreteScheduler, \
14
+ UniPCMultistepScheduler, DPMSolverSinglestepScheduler, DEISMultistepScheduler, PNDMScheduler, \
15
+ DPMSolverMultistepScheduler, HeunDiscreteScheduler, EulerAncestralDiscreteScheduler, DDPMScheduler, \
16
+ LMSDiscreteScheduler, KDPM2DiscreteScheduler
17
  import torch
18
+ import base64
19
+ from io import BytesIO
20
 
21
+ #
22
  model_id = "stabilityai/stable-diffusion-2-1-base"
23
 
24
  scheduler = EulerDiscreteScheduler.from_pretrained(model_id, subfolder="scheduler")
25
  pipe = StableDiffusionPipeline.from_pretrained(
26
  model_id,
27
  scheduler=scheduler,
28
+ # safety_checker=None,
29
+ revision="fp16",
30
  torch_dtype=torch.float16)
31
 
32
+ if torch.cuda.is_available():
33
+ pipe = pipe.to('cuda')
34
  is_gpu_busy = False
35
 
36
+ translator = i18nTranslator()
37
+ translator.init(path='locales')
38
+ samplers = [
39
+ "EulerDiscrete",
40
+ "EulerAncestralDiscrete",
41
+ "UniPCMultistep",
42
+ "DPMSolverSinglestep",
43
+ "DPMSolverMultistep",
44
+ "KDPM2Discrete",
45
+ "KDPM2AncestralDiscrete",
46
+ "DEISMultistep",
47
+ "HeunDiscrete",
48
+ "PNDM",
49
+ "DDPM",
50
+ "DDIM",
51
+ "LMSDiscrete",
52
+ ]
53
+
54
+ rand = random.Random()
55
+ translator = google_translator()
56
 
57
+
58
+ def infer(prompt: str, negative: str, width: int, height: int, sampler: str, steps: int, seed: int, scale):
59
  global is_gpu_busy
60
+
61
+ if seed == 0:
62
+ seed = rand.randint(0, 10000)
63
+ else:
64
+ seed = int(seed)
65
 
66
  images = []
67
+ device = "cpu"
68
+ if torch.cuda.is_available():
69
+ device = "cuda"
70
+ generator = torch.Generator(device=device).manual_seed(seed)
71
+ if sampler == "EulerDiscrete":
72
+ pipe.scheduler = EulerDiscreteScheduler.from_config(pipe.scheduler.config)
73
+ elif sampler == "EulerAncestralDiscrete":
74
+ pipe.scheduler = EulerAncestralDiscreteScheduler.from_config(pipe.scheduler.config)
75
+ elif sampler == "KDPM2Discrete":
76
+ pipe.scheduler = KDPM2DiscreteScheduler.from_config(pipe.scheduler.config)
77
+ elif sampler == "KDPM2AncestralDiscrete":
78
+ pipe.scheduler = KDPM2AncestralDiscreteScheduler.from_config(pipe.scheduler.config)
79
+ elif sampler == "UniPCMultistep":
80
+ pipe.scheduler = UniPCMultistepScheduler.from_config(pipe.scheduler.config)
81
+ elif sampler == "DPMSolverSinglestep":
82
+ pipe.scheduler = DPMSolverSinglestepScheduler.from_config(pipe.scheduler.config)
83
+ elif sampler == "DPMSolverMultistep":
84
+ pipe.scheduler = DPMSolverMultistepScheduler.from_config(pipe.scheduler.config)
85
+ elif sampler == "HeunDiscrete":
86
+ pipe.scheduler = HeunDiscreteScheduler.from_config(pipe.scheduler.config)
87
+ elif sampler == "DEISMultistep":
88
+ pipe.scheduler = DEISMultistepScheduler.from_config(pipe.scheduler.config)
89
+ elif sampler == "PNDM":
90
+ pipe.scheduler = PNDMScheduler.from_config(pipe.scheduler.config)
91
+ elif sampler == "DDPM":
92
+ pipe.scheduler = DDPMScheduler.from_config(pipe.scheduler.config)
93
+ elif sampler == "DDIM":
94
+ pipe.scheduler = DDIMScheduler.from_config(pipe.scheduler.config)
95
+ elif sampler == "LMSDiscrete":
96
+ pipe.scheduler = LMSDiscreteScheduler.from_config(pipe.scheduler.config)
97
+
98
+ try:
99
+ translate_prompt = translator.translate(prompt, lang_tgt='en')
100
+ translate_negative = translator.translate(negative, lang_tgt='en')
101
+ except Exception as ex:
102
+ print(ex)
103
+ translate_prompt = prompt
104
+ translate_negative = negative
105
+
106
+ image = pipe(prompt=translate_prompt,
107
+ negative_prompt=translate_negative,
108
  guidance_scale=scale,
109
+ num_inference_steps=steps,
110
  generator=generator,
111
+ height=height,
112
+ width=width).images[0]
113
+
114
+ buffered = BytesIO()
115
+ image.save(buffered, format="JPEG")
116
+ img_str = base64.b64encode(buffered.getvalue())
117
+ img_base64 = bytes("data:image/jpeg;base64,", encoding='utf-8') + img_str
118
 
119
+ images.append(img_base64)
120
 
121
  return images
122
 
 
243
  #prompt-text-input, #negative-prompt-text-input{padding: .45rem 0.625rem}
244
  #component-16{border-top-width: 1px!important;margin-top: 1em}
245
  .image_duplication{position: absolute; width: 100px; left: 50px}
246
+ .generate-container {display: flex; justify-content: flex-end;}
247
+ #generate-btn {background: linear-gradient(to bottom right, #ffedd5, #fdba74)}
248
  """
249
 
250
  block = gr.Blocks(css=css)
251
 
252
+ # text, negative, width, height, sampler, steps, seed, guidance_scale
253
+ # examples = [
254
+ # [
255
+ # 'A high tech solarpunk utopia in the Amazon rainforest',
256
+ # 'low quality',
257
+ # 512,
258
+ # 512,
259
+ # 'ddim',
260
+ # 30,
261
+ # 0,
262
+ # 9
263
+ # ],
264
+ # [
265
+ # 'A pikachu fine dining with a view to the Eiffel Tower',
266
+ # 'low quality',
267
+ # 512,
268
+ # 512,
269
+ # 'ddim',
270
+ # 30,
271
+ # 0,
272
+ # 9
273
+ # ],
274
+ # [
275
+ # 'A mecha robot in a favela in expressionist style',
276
+ # 'low quality, 3d, photorealistic',
277
+ # 512,
278
+ # 512,
279
+ # 'ddim',
280
+ # 30,
281
+ # 0,
282
+ # 9
283
+ # ],
284
+ # [
285
+ # 'an insect robot preparing a delicious meal',
286
+ # 'low quality, illustration',
287
+ # 512,
288
+ # 512,
289
+ # 'ddim',
290
+ # 30,
291
+ # 0,
292
+ # 9
293
+ # ],
294
+ # [
295
+ # "A small cabin on top of a snowy mountain in the style of Disney, artstation",
296
+ # 'low quality, ugly',
297
+ # 512,
298
+ # 512,
299
+ # 'ddim',
300
+ # 30,
301
+ # 0,
302
+ # 9
303
+ # ],
304
+ # ]
305
+
306
+ examples = list(map(lambda x: [
307
+ x,
308
+ 'low quality',
309
+ 512,
310
+ 512,
311
+ 'ddim',
312
+ 30,
313
+ 0,
314
+ 9
315
+ ], word_list))[:500]
316
 
317
  with block:
318
  gr.HTML(
 
364
  </h1>
365
  </div>
366
  <p style="margin-bottom: 10px; font-size: 94%; line-height: 23px;">
367
+ Stable Diffusion 2.1 Demo App.
368
+ Click "Generate image" Button to generate image.
369
+ Also Change params to have a try
 
 
 
 
 
370
  </p>
371
  </div>
372
  """
 
397
  rounded=(True, False, False, True),
398
  container=False,
399
  )
400
+ with gr.Row(elem_id="txt2img_size", scale=4):
401
+ width = gr.Slider(minimum=64, maximum=2048, step=8, label="Width", value=512,
402
+ elem_id="txt2img_width")
403
+ height = gr.Slider(minimum=64, maximum=2048, step=8, label="Height", value=512,
404
+ elem_id="txt2img_height")
405
 
406
+ with gr.Row(elem_id="txt2img_sampler", scale=4):
407
+ seed = gr.Number(value=0, label="Seed", elem_id="txt2img_seed")
408
+ sampler = gr.Dropdown(
409
+ samplers, value="",
410
+ multiselect=False,
411
+ label="Sampler",
412
+ info="sampler select"
413
+ )
414
+ steps = gr.Slider(minimum=1, maximum=80, step=1, elem_id=f"steps", label="Sampling steps",
415
+ value=20)
416
 
417
+ with gr.Accordion("Advanced settings", open=False):
418
+ # gr.Markdown("Advanced settings are temporarily unavailable")
419
+ # samples = gr.Slider(label="Images", minimum=1, maximum=4, value=4, step=1)
420
+ # steps = gr.Slider(label="Steps", minimum=1, maximum=50, value=45, step=1)
421
+ guidance_scale = gr.Slider(
422
+ label="Guidance Scale", minimum=0, maximum=50, value=9, step=0.1
423
+ )
424
 
425
+ with gr.Row(elem_id="generate-container", elem_classes="generate-container"):
426
+ btn = gr.Button("Generate image", elem_id="generate-btn", elem_classes="generate-btn").style(
427
+ margin=False,
428
+ rounded=(False, True, True, False),
429
+ full_width=False,
430
+ )
 
 
 
 
 
 
 
 
431
 
432
+ gallery = gr.Gallery(
433
+ label="Generated images", show_label=False, elem_id="gallery"
434
+ ).style(grid=[2], height="auto")
435
+
436
+ # with gr.Group(elem_id="container-advanced-btns"):
437
+ # # advanced_button = gr.Button("Advanced options", elem_id="advanced-btn")
438
+ # with gr.Group(elem_id="share-btn-container"):
439
+ # community_icon = gr.HTML(community_icon_html)
440
+ # loading_icon = gr.HTML(loading_icon_html)
441
+ # share_button = gr.Button("Share to community", elem_id="share-btn")
442
 
443
+ ex = gr.Examples(examples=examples, fn=infer,
444
+ inputs=[text, negative, width, height, sampler, steps, seed, guidance_scale],
445
+ outputs=[gallery],
446
+ examples_per_page=10,
447
+ cache_examples=False)
448
+ ex.dataset.headers = [""]
449
+ negative.submit(infer, inputs=[text, negative, width, height, sampler, steps, seed, guidance_scale],
450
+ outputs=[gallery], postprocess=False)
451
+ text.submit(infer, inputs=[text, negative, width, height, sampler, steps, seed, guidance_scale],
452
+ outputs=[gallery], postprocess=False)
453
+ btn.click(infer, inputs=[text, negative, width, height, sampler, steps, seed, guidance_scale],
454
+ outputs=[gallery], postprocess=False)
 
 
 
 
455
 
456
+ block.queue(concurrency_count=80,
457
+ max_size=100).launch(
458
+ max_threads=150,
459
+ server_port=6006,
460
+ share=True,
461
+ )
i18n.py ADDED
@@ -0,0 +1,28 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import json
3
+
4
+ class i18nTranslator:
5
+ def __init__(self):
6
+ self.translations = {}
7
+
8
+ def init(self, path):
9
+ for filename in os.listdir(path):
10
+ if filename.endswith('.json'):
11
+ language = filename.split('.')[0]
12
+ with open(os.path.join(path, filename), 'r') as file:
13
+ self.translations[language] = json.load(file)
14
+
15
+ def trans(self, key, lng):
16
+ if lng in self.translations and key in self.translations[lng]:
17
+ return self.translations[lng][key]
18
+ elif 'en' in self.translations and key in self.translations['en']:
19
+ return self.translations['en'][key]
20
+ else:
21
+ return key
22
+
23
+ # Usage example
24
+
25
+ if __name__ == '__main__':
26
+ translator = i18nTranslator()
27
+ translator.init(path='locales')
28
+ print(translator.trans(key="Enter your prompt", lng="zh-CN")) # Output: "输入你的提示词(你希望生成的图片的描述)"
locales/zh-CN.json ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ {
2
+ "introduce": "Stable Diffusion 2.1 Demo App.\n Click \"Generate image\" Button to generate image.\n Also Change params to have a try",
3
+ }
model_test.py ADDED
@@ -0,0 +1,20 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ from diffusers import StableDiffusionPipeline, EulerDiscreteScheduler
3
+ import torch
4
+
5
+ model_id = "stabilityai/stable-diffusion-2-1-base"
6
+
7
+ scheduler = EulerDiscreteScheduler.from_pretrained(model_id, subfolder="scheduler")
8
+ pipe = StableDiffusionPipeline.from_pretrained(
9
+ model_id,
10
+ scheduler=scheduler,
11
+ # safety_checker=None,
12
+ revision="fp16",
13
+ torch_dtype=torch.float16)
14
+
15
+ pipe = pipe.to("cuda")
16
+
17
+ prompt = "a photo of an astronaut riding a horse on mars"
18
+ image = pipe(prompt).images[0]
19
+
20
+ image.save("astronaut_rides_horse.png")
requirements.txt CHANGED
@@ -3,4 +3,5 @@ diffusers
3
  transformers
4
  accelerate
5
  scipy
6
- safetensors
 
 
3
  transformers
4
  accelerate
5
  scipy
6
+ safetensors
7
+ python-i18n
trans_constant.py ADDED
@@ -0,0 +1,179 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ LANGUAGES = {
2
+ 'af': 'afrikaans',
3
+ 'sq': 'albanian',
4
+ 'am': 'amharic',
5
+ 'ar': 'arabic',
6
+ 'hy': 'armenian',
7
+ 'az': 'azerbaijani',
8
+ 'eu': 'basque',
9
+ 'be': 'belarusian',
10
+ 'bn': 'bengali',
11
+ 'bs': 'bosnian',
12
+ 'bg': 'bulgarian',
13
+ 'ca': 'catalan',
14
+ 'ceb': 'cebuano',
15
+ 'ny': 'chichewa',
16
+ 'zh-cn': 'chinese (simplified)',
17
+ 'zh-tw': 'chinese (traditional)',
18
+ 'co': 'corsican',
19
+ 'hr': 'croatian',
20
+ 'cs': 'czech',
21
+ 'da': 'danish',
22
+ 'nl': 'dutch',
23
+ 'en': 'english',
24
+ 'eo': 'esperanto',
25
+ 'et': 'estonian',
26
+ 'tl': 'filipino',
27
+ 'fi': 'finnish',
28
+ 'fr': 'french',
29
+ 'fy': 'frisian',
30
+ 'gl': 'galician',
31
+ 'ka': 'georgian',
32
+ 'de': 'german',
33
+ 'el': 'greek',
34
+ 'gu': 'gujarati',
35
+ 'ht': 'haitian creole',
36
+ 'ha': 'hausa',
37
+ 'haw': 'hawaiian',
38
+ 'iw': 'hebrew',
39
+ 'he': 'hebrew',
40
+ 'hi': 'hindi',
41
+ 'hmn': 'hmong',
42
+ 'hu': 'hungarian',
43
+ 'is': 'icelandic',
44
+ 'ig': 'igbo',
45
+ 'id': 'indonesian',
46
+ 'ga': 'irish',
47
+ 'it': 'italian',
48
+ 'ja': 'japanese',
49
+ 'jw': 'javanese',
50
+ 'kn': 'kannada',
51
+ 'kk': 'kazakh',
52
+ 'km': 'khmer',
53
+ 'ko': 'korean',
54
+ 'ku': 'kurdish (kurmanji)',
55
+ 'ky': 'kyrgyz',
56
+ 'lo': 'lao',
57
+ 'la': 'latin',
58
+ 'lv': 'latvian',
59
+ 'lt': 'lithuanian',
60
+ 'lb': 'luxembourgish',
61
+ 'mk': 'macedonian',
62
+ 'mg': 'malagasy',
63
+ 'ms': 'malay',
64
+ 'ml': 'malayalam',
65
+ 'mt': 'maltese',
66
+ 'mi': 'maori',
67
+ 'mr': 'marathi',
68
+ 'mn': 'mongolian',
69
+ 'my': 'myanmar (burmese)',
70
+ 'ne': 'nepali',
71
+ 'no': 'norwegian',
72
+ 'or': 'odia',
73
+ 'ps': 'pashto',
74
+ 'fa': 'persian',
75
+ 'pl': 'polish',
76
+ 'pt': 'portuguese',
77
+ 'pa': 'punjabi',
78
+ 'ro': 'romanian',
79
+ 'ru': 'russian',
80
+ 'sm': 'samoan',
81
+ 'gd': 'scots gaelic',
82
+ 'sr': 'serbian',
83
+ 'st': 'sesotho',
84
+ 'sn': 'shona',
85
+ 'sd': 'sindhi',
86
+ 'si': 'sinhala',
87
+ 'sk': 'slovak',
88
+ 'sl': 'slovenian',
89
+ 'so': 'somali',
90
+ 'es': 'spanish',
91
+ 'su': 'sundanese',
92
+ 'sw': 'swahili',
93
+ 'sv': 'swedish',
94
+ 'tg': 'tajik',
95
+ 'ta': 'tamil',
96
+ 'tt': 'tatar',
97
+ 'te': 'telugu',
98
+ 'th': 'thai',
99
+ 'tr': 'turkish',
100
+ 'tk': 'turkmen',
101
+ 'uk': 'ukrainian',
102
+ 'ur': 'urdu',
103
+ 'ug': 'uyghur',
104
+ 'uz': 'uzbek',
105
+ 'vi': 'vietnamese',
106
+ 'cy': 'welsh',
107
+ 'xh': 'xhosa',
108
+ 'yi': 'yiddish',
109
+ 'yo': 'yoruba',
110
+ 'zu': 'zulu',
111
+ }
112
+
113
+ DEFAULT_SERVICE_URLS = ('translate.google.ac','translate.google.ad','translate.google.ae',
114
+ 'translate.google.al','translate.google.am','translate.google.as',
115
+ 'translate.google.at','translate.google.az','translate.google.ba',
116
+ 'translate.google.be','translate.google.bf','translate.google.bg',
117
+ 'translate.google.bi','translate.google.bj','translate.google.bs',
118
+ 'translate.google.bt','translate.google.by','translate.google.ca',
119
+ 'translate.google.cat','translate.google.cc','translate.google.cd',
120
+ 'translate.google.cf','translate.google.cg','translate.google.ch',
121
+ 'translate.google.ci','translate.google.cl','translate.google.cm',
122
+ 'translate.google.cn','translate.google.co.ao','translate.google.co.bw',
123
+ 'translate.google.co.ck','translate.google.co.cr','translate.google.co.id',
124
+ 'translate.google.co.il','translate.google.co.in','translate.google.co.jp',
125
+ 'translate.google.co.ke','translate.google.co.kr','translate.google.co.ls',
126
+ 'translate.google.co.ma','translate.google.co.mz','translate.google.co.nz',
127
+ 'translate.google.co.th','translate.google.co.tz','translate.google.co.ug',
128
+ 'translate.google.co.uk','translate.google.co.uz','translate.google.co.ve',
129
+ 'translate.google.co.vi','translate.google.co.za','translate.google.co.zm',
130
+ 'translate.google.co.zw','translate.google.co','translate.google.com.af',
131
+ 'translate.google.com.ag','translate.google.com.ai','translate.google.com.ar',
132
+ 'translate.google.com.au','translate.google.com.bd','translate.google.com.bh',
133
+ 'translate.google.com.bn','translate.google.com.bo','translate.google.com.br',
134
+ 'translate.google.com.bz','translate.google.com.co','translate.google.com.cu',
135
+ 'translate.google.com.cy','translate.google.com.do','translate.google.com.ec',
136
+ 'translate.google.com.eg','translate.google.com.et','translate.google.com.fj',
137
+ 'translate.google.com.gh','translate.google.com.gi','translate.google.com.gt',
138
+ 'translate.google.com.hk','translate.google.com.jm','translate.google.com.kh',
139
+ 'translate.google.com.kw','translate.google.com.lb','translate.google.com.lc',
140
+ 'translate.google.com.ly','translate.google.com.mm','translate.google.com.mt',
141
+ 'translate.google.com.mx','translate.google.com.my','translate.google.com.na',
142
+ 'translate.google.com.ng','translate.google.com.ni','translate.google.com.np',
143
+ 'translate.google.com.om','translate.google.com.pa','translate.google.com.pe',
144
+ 'translate.google.com.pg','translate.google.com.ph','translate.google.com.pk',
145
+ 'translate.google.com.pr','translate.google.com.py','translate.google.com.qa',
146
+ 'translate.google.com.sa','translate.google.com.sb','translate.google.com.sg',
147
+ 'translate.google.com.sl','translate.google.com.sv','translate.google.com.tj',
148
+ 'translate.google.com.tr','translate.google.com.tw','translate.google.com.ua',
149
+ 'translate.google.com.uy','translate.google.com.vc','translate.google.com.vn',
150
+ 'translate.google.com','translate.google.cv','translate.google.cx',
151
+ 'translate.google.cz','translate.google.de','translate.google.dj',
152
+ 'translate.google.dk','translate.google.dm','translate.google.dz',
153
+ 'translate.google.ee','translate.google.es','translate.google.eu',
154
+ 'translate.google.fi','translate.google.fm','translate.google.fr',
155
+ 'translate.google.ga','translate.google.ge','translate.google.gf',
156
+ 'translate.google.gg','translate.google.gl','translate.google.gm',
157
+ 'translate.google.gp','translate.google.gr','translate.google.gy',
158
+ 'translate.google.hn','translate.google.hr','translate.google.ht',
159
+ 'translate.google.hu','translate.google.ie','translate.google.im',
160
+ 'translate.google.io','translate.google.iq','translate.google.is',
161
+ 'translate.google.it','translate.google.je','translate.google.jo',
162
+ 'translate.google.kg','translate.google.ki','translate.google.kz',
163
+ 'translate.google.la','translate.google.li','translate.google.lk',
164
+ 'translate.google.lt','translate.google.lu','translate.google.lv',
165
+ 'translate.google.md','translate.google.me','translate.google.mg',
166
+ 'translate.google.mk','translate.google.ml','translate.google.mn',
167
+ 'translate.google.ms','translate.google.mu','translate.google.mv',
168
+ 'translate.google.mw','translate.google.ne','translate.google.nf',
169
+ 'translate.google.nl','translate.google.no','translate.google.nr',
170
+ 'translate.google.nu','translate.google.pl','translate.google.pn',
171
+ 'translate.google.ps','translate.google.pt','translate.google.ro',
172
+ 'translate.google.rs','translate.google.ru','translate.google.rw',
173
+ 'translate.google.sc','translate.google.se','translate.google.sh',
174
+ 'translate.google.si','translate.google.sk','translate.google.sm',
175
+ 'translate.google.sn','translate.google.so','translate.google.sr',
176
+ 'translate.google.st','translate.google.td','translate.google.tg',
177
+ 'translate.google.tk','translate.google.tl','translate.google.tm',
178
+ 'translate.google.tn','translate.google.to','translate.google.tt',
179
+ 'translate.google.us','translate.google.vg','translate.google.vu','translate.google.ws')
trans_google.py ADDED
@@ -0,0 +1,251 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # coding:utf-8
2
+ # author LuShan
3
+ # version : 1.1.9
4
+ import json, requests, random, re
5
+ from urllib.parse import quote
6
+ import urllib3
7
+ import logging
8
+ from trans_constant import LANGUAGES, DEFAULT_SERVICE_URLS
9
+
10
+ log = logging.getLogger(__name__)
11
+ log.addHandler(logging.NullHandler())
12
+
13
+ urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
14
+
15
+ URLS_SUFFIX = [re.search('translate.google.(.*)', url.strip()).group(1) for url in DEFAULT_SERVICE_URLS]
16
+ URL_SUFFIX_DEFAULT = 'com'
17
+
18
+
19
+ class google_new_transError(Exception):
20
+ """Exception that uses context to present a meaningful error message"""
21
+
22
+ def __init__(self, msg=None, **kwargs):
23
+ self.tts = kwargs.pop('tts', None)
24
+ self.rsp = kwargs.pop('response', None)
25
+ if msg:
26
+ self.msg = msg
27
+ elif self.tts is not None:
28
+ self.msg = self.infer_msg(self.tts, self.rsp)
29
+ else:
30
+ self.msg = None
31
+ super(google_new_transError, self).__init__(self.msg)
32
+
33
+ def infer_msg(self, tts, rsp=None):
34
+ cause = "Unknown"
35
+
36
+ if rsp is None:
37
+ premise = "Failed to connect"
38
+
39
+ return "{}. Probable cause: {}".format(premise, "timeout")
40
+ # if tts.tld != 'com':
41
+ # host = _translate_url(tld=tts.tld)
42
+ # cause = "Host '{}' is not reachable".format(host)
43
+
44
+ else:
45
+ status = rsp.status_code
46
+ reason = rsp.reason
47
+
48
+ premise = "{:d} ({}) from TTS API".format(status, reason)
49
+
50
+ if status == 403:
51
+ cause = "Bad token or upstream API changes"
52
+ elif status == 200 and not tts.lang_check:
53
+ cause = "No audio stream in response. Unsupported language '%s'" % self.tts.lang
54
+ elif status >= 500:
55
+ cause = "Uptream API error. Try again later."
56
+
57
+ return "{}. Probable cause: {}".format(premise, cause)
58
+
59
+
60
+ class google_translator:
61
+ '''
62
+ You can use 108 language in target and source,details view LANGUAGES.
63
+ Target language: like 'en'、'zh'、'th'...
64
+
65
+ :param url_suffix: The source text(s) to be translated. Batch translation is supported via sequence input.
66
+ The value should be one of the url_suffix listed in : `DEFAULT_SERVICE_URLS`
67
+ :type url_suffix: UTF-8 :class:`str`; :class:`unicode`; string sequence (list, tuple, iterator, generator)
68
+
69
+ :param text: The source text(s) to be translated.
70
+ :type text: UTF-8 :class:`str`; :class:`unicode`;
71
+
72
+ :param lang_tgt: The language to translate the source text into.
73
+ The value should be one of the language codes listed in : `LANGUAGES`
74
+ :type lang_tgt: :class:`str`; :class:`unicode`
75
+
76
+ :param lang_src: The language of the source text.
77
+ The value should be one of the language codes listed in :const:`googletrans.LANGUAGES`
78
+ If a language is not specified,
79
+ the system will attempt to identify the source language automatically.
80
+ :type lang_src: :class:`str`; :class:`unicode`
81
+
82
+ :param timeout: Timeout Will be used for every request.
83
+ :type timeout: number or a double of numbers
84
+
85
+ :param proxies: proxies Will be used for every request.
86
+ :type proxies: class : dict; like: {'http': 'http:171.112.169.47:19934/', 'https': 'https:171.112.169.47:19934/'}
87
+
88
+ '''
89
+
90
+ def __init__(self, url_suffix="com", timeout=5, proxies=None):
91
+ self.proxies = proxies
92
+ if url_suffix not in URLS_SUFFIX:
93
+ self.url_suffix = URL_SUFFIX_DEFAULT
94
+ else:
95
+ self.url_suffix = url_suffix
96
+ url_base = "https://translate.google.{}".format(self.url_suffix)
97
+ self.url = url_base + "/_/TranslateWebserverUi/data/batchexecute"
98
+ self.timeout = timeout
99
+
100
+ def _package_rpc(self, text, lang_src='auto', lang_tgt='auto'):
101
+ GOOGLE_TTS_RPC = ["MkEWBc"]
102
+ parameter = [[text.strip(), lang_src, lang_tgt, True], [1]]
103
+ escaped_parameter = json.dumps(parameter, separators=(',', ':'))
104
+ rpc = [[[random.choice(GOOGLE_TTS_RPC), escaped_parameter, None, "generic"]]]
105
+ espaced_rpc = json.dumps(rpc, separators=(',', ':'))
106
+ # text_urldecode = quote(text.strip())
107
+ freq_initial = "f.req={}&".format(quote(espaced_rpc))
108
+ freq = freq_initial
109
+ return freq
110
+
111
+ def translate(self, text, lang_tgt='auto', lang_src='auto', pronounce=False):
112
+ try:
113
+ lang = LANGUAGES[lang_src]
114
+ except:
115
+ lang_src = 'auto'
116
+ try:
117
+ lang = LANGUAGES[lang_tgt]
118
+ except:
119
+ lang_src = 'auto'
120
+ text = str(text)
121
+ if len(text) >= 5000:
122
+ return "Warning: Can only detect less than 5000 characters"
123
+ if len(text) == 0:
124
+ return ""
125
+ headers = {
126
+ "Referer": "http://translate.google.{}/".format(self.url_suffix),
127
+ "User-Agent":
128
+ "Mozilla/5.0 (Windows NT 10.0; WOW64) "
129
+ "AppleWebKit/537.36 (KHTML, like Gecko) "
130
+ "Chrome/47.0.2526.106 Safari/537.36",
131
+ "Content-Type": "application/x-www-form-urlencoded;charset=utf-8"
132
+ }
133
+ freq = self._package_rpc(text, lang_src, lang_tgt)
134
+ response = requests.Request(method='POST',
135
+ url=self.url,
136
+ data=freq,
137
+ headers=headers,
138
+ )
139
+ try:
140
+ if self.proxies == None or type(self.proxies) != dict:
141
+ self.proxies = {}
142
+ with requests.Session() as s:
143
+ s.proxies = self.proxies
144
+ r = s.send(request=response.prepare(),
145
+ verify=False,
146
+ timeout=self.timeout)
147
+ for line in r.iter_lines(chunk_size=1024):
148
+ decoded_line = line.decode('utf-8')
149
+ if "MkEWBc" in decoded_line:
150
+ try:
151
+ response = decoded_line
152
+ response = json.loads(response)
153
+ response = list(response)
154
+ response = json.loads(response[0][2])
155
+ response_ = list(response)
156
+ response = response_[1][0]
157
+ if len(response) == 1:
158
+ if len(response[0]) > 5:
159
+ sentences = response[0][5]
160
+ else: ## only url
161
+ sentences = response[0][0]
162
+ if pronounce == False:
163
+ return sentences
164
+ elif pronounce == True:
165
+ return [sentences,None,None]
166
+ translate_text = ""
167
+ for sentence in sentences:
168
+ sentence = sentence[0]
169
+ translate_text += sentence.strip() + ' '
170
+ translate_text = translate_text
171
+ if pronounce == False:
172
+ return translate_text
173
+ elif pronounce == True:
174
+ pronounce_src = (response_[0][0])
175
+ pronounce_tgt = (response_[1][0][0][1])
176
+ return [translate_text, pronounce_src, pronounce_tgt]
177
+ elif len(response) == 2:
178
+ sentences = []
179
+ for i in response:
180
+ sentences.append(i[0])
181
+ if pronounce == False:
182
+ return sentences
183
+ elif pronounce == True:
184
+ pronounce_src = (response_[0][0])
185
+ pronounce_tgt = (response_[1][0][0][1])
186
+ return [sentences, pronounce_src, pronounce_tgt]
187
+ except Exception as e:
188
+ raise e
189
+ r.raise_for_status()
190
+ except requests.exceptions.ConnectTimeout as e:
191
+ raise e
192
+ except requests.exceptions.HTTPError as e:
193
+ # Request successful, bad response
194
+ raise google_new_transError(tts=self, response=r)
195
+ except requests.exceptions.RequestException as e:
196
+ # Request failed
197
+ raise google_new_transError(tts=self)
198
+
199
+ def detect(self, text):
200
+ text = str(text)
201
+ if len(text) >= 5000:
202
+ return log.debug("Warning: Can only detect less than 5000 characters")
203
+ if len(text) == 0:
204
+ return ""
205
+ headers = {
206
+ "Referer": "http://translate.google.{}/".format(self.url_suffix),
207
+ "User-Agent":
208
+ "Mozilla/5.0 (Windows NT 10.0; WOW64) "
209
+ "AppleWebKit/537.36 (KHTML, like Gecko) "
210
+ "Chrome/47.0.2526.106 Safari/537.36",
211
+ "Content-Type": "application/x-www-form-urlencoded;charset=utf-8"
212
+ }
213
+ freq = self._package_rpc(text)
214
+ response = requests.Request(method='POST',
215
+ url=self.url,
216
+ data=freq,
217
+ headers=headers)
218
+ try:
219
+ if self.proxies == None or type(self.proxies) != dict:
220
+ self.proxies = {}
221
+ with requests.Session() as s:
222
+ s.proxies = self.proxies
223
+ r = s.send(request=response.prepare(),
224
+ verify=False,
225
+ timeout=self.timeout)
226
+
227
+ for line in r.iter_lines(chunk_size=1024):
228
+ decoded_line = line.decode('utf-8')
229
+ if "MkEWBc" in decoded_line:
230
+ # regex_str = r"\[\[\"wrb.fr\",\"MkEWBc\",\"\[\[(.*).*?,\[\[\["
231
+ try:
232
+ # data_got = re.search(regex_str,decoded_line).group(1)
233
+ response = (decoded_line + ']')
234
+ response = json.loads(response)
235
+ response = list(response)
236
+ response = json.loads(response[0][2])
237
+ response = list(response)
238
+ detect_lang = response[0][2]
239
+ except Exception:
240
+ raise Exception
241
+ # data_got = data_got.split('\\\"]')[0]
242
+ return [detect_lang, LANGUAGES[detect_lang.lower()]]
243
+ r.raise_for_status()
244
+ except requests.exceptions.HTTPError as e:
245
+ # Request successful, bad response
246
+ log.debug(str(e))
247
+ raise google_new_transError(tts=self, response=r)
248
+ except requests.exceptions.RequestException as e:
249
+ # Request failed
250
+ log.debug(str(e))
251
+ raise google_new_transError(tts=self)
trans_test.py ADDED
@@ -0,0 +1,5 @@
 
 
 
 
 
 
1
+ from trans_google import google_translator
2
+
3
+ translator = google_translator()
4
+ translate_text = translator.translate('Hello World', lang_tgt='zh')
5
+ print(translate_text)