import gradio as gr import requests import json import os import time from collections import defaultdict from PIL import Image import io BASE_URL = "https://api.jigsawstack.com/v1" headers = { "x-api-key": os.getenv("JIGSAWSTACK_API_KEY") } # Rate limiting configuration request_times = defaultdict(list) MAX_REQUESTS = 20 # Maximum requests per time window TIME_WINDOW = 3600 # Time window in seconds (1 hour) def get_real_ip(request: gr.Request): """Extract real IP address using x-forwarded-for header or fallback""" if not request: return "unknown" forwarded = request.headers.get("x-forwarded-for") if forwarded: ip = forwarded.split(",")[0].strip() # First IP in the list is the client's else: ip = request.client.host # fallback return ip def check_rate_limit(request: gr.Request): """Check if the current request exceeds rate limits""" if not request: return True, "Rate limit check failed - no request info" ip = get_real_ip(request) now = time.time() # Clean up old timestamps outside the time window request_times[ip] = [t for t in request_times[ip] if now - t < TIME_WINDOW] # Check if rate limit exceeded if len(request_times[ip]) >= MAX_REQUESTS: time_remaining = int(TIME_WINDOW - (now - request_times[ip][0])) time_remaining_minutes = round(time_remaining / 60, 1) time_window_minutes = round(TIME_WINDOW / 60, 1) return False, f"Rate limit exceeded. You can make {MAX_REQUESTS} requests per {time_window_minutes} minutes. Try again in {time_remaining_minutes} minutes." # Add current request timestamp request_times[ip].append(now) return True, "" # ----------------- JigsawStack API Wrappers ------------------ def translate_text(text_input, target_lang, request: gr.Request): # Check rate limit first rate_limit_ok, rate_limit_msg = check_rate_limit(request) if not rate_limit_ok: return {"error": "Rate limit exceeded", "message": rate_limit_msg} # Validate required inputs if not text_input or not text_input.strip(): return {"error": "Text input is required"} if not target_lang or not target_lang.strip(): return {"error": "Target language code is required"} # Handle both single string and comma-separated multiple phrases if "," in text_input and not text_input.strip().startswith("["): text_payload = [t.strip() for t in text_input.split(",") if t.strip()] else: text_payload = text_input.strip() payload = { "text": text_payload, "target_language": target_lang.strip() } try: r = requests.post(f"{BASE_URL}/ai/translate", headers=headers, json=payload) r.raise_for_status() data = r.json() if not data.get("success"): return {"error": "Translation failed", "response": data} # Return a more comprehensive result matching the API response result = { "success": True, "translated_text": data.get("translated_text") } return result except requests.exceptions.RequestException as req_err: return {"error": "Request failed", "message": str(req_err)} except Exception as e: return {"error": "Unexpected error", "message": str(e)} # ----------------- Gradio UI ------------------ with gr.Blocks() as demo: gr.Markdown("""

🧩 Text Translation

Translate text from one language to another with support for multiple text formats.

For more details and API usage, see the documentation.

""") with gr.Row(): # Left Column: Inputs and Examples with gr.Column(scale=2): gr.Markdown("#### Input") text_input = gr.Textbox( label="Text to Translate", lines=4, placeholder="Enter text to translate (use commas to separate multiple phrases for batch translation)" ) gr.Markdown("#### Translation Options") target_lang = gr.Textbox( label="Target Language Code", placeholder="es (Spanish), fr (French), de (German), etc.", info="Common codes: es, fr, de, hi, ja, ko, zh, ar, ru, pt" ) gr.Markdown("#### Quick Examples") gr.Markdown("Click any example below to auto-fill the fields:") with gr.Row(): example_btn1 = gr.Button("🇪🇸 Hello World → Spanish", size="sm") example_btn2 = gr.Button("🇫🇷 Good morning → French", size="sm") example_btn3 = gr.Button("🇩🇪 Thank you → German", size="sm") with gr.Row(): example_btn4 = gr.Button("🇯🇵 How are you? → Japanese", size="sm") example_btn5 = gr.Button("🇨🇳 Welcome → Chinese", size="sm") example_btn6 = gr.Button("🇰🇷 Goodbye → Korean", size="sm") with gr.Row(): example_btn7 = gr.Button("🇮🇳 Batch: Hello, Goodbye, Thank you → Hindi", size="sm") example_btn8 = gr.Button("🇷🇺 Business: Meeting, Project, Deadline → Russian", size="sm") gr.Markdown("") # Spacer translate_btn = gr.Button("Translate", variant="primary") # Middle Column: Supported Languages with gr.Column(scale=1): gr.Markdown("#### Supported Languages") gr.Markdown(""" **Common Language Codes:** - `es` - Spanish - `fr` - French - `de` - German - `hi` - Hindi - `ja` - Japanese - `ko` - Korean - `zh` - Chinese - `ar` - Arabic - `ru` - Russian - `pt` - Portuguese - `tr` - Turkish - `bn` - Bengali - `fi` - Finnish - `sw` - Swahili *For a complete list of 162+ supported languages, visit the [Language Codes Reference](https://jigsawstack.com/docs/additional-resources/languages)* """) # Example functions to auto-fill fields def fill_example_1(): return "Hello World", "es" def fill_example_2(): return "Good morning", "fr" def fill_example_3(): return "Thank you", "de" def fill_example_4(): return "How are you?", "ja" def fill_example_5(): return "Welcome", "zh" def fill_example_6(): return "Goodbye", "ko" def fill_example_7(): return "Hello, Goodbye, Thank you", "hi" def fill_example_8(): return "Meeting, Project, Deadline", "ru" # Connect example buttons to auto-fill functions example_btn1.click(fill_example_1, outputs=[text_input, target_lang]) example_btn2.click(fill_example_2, outputs=[text_input, target_lang]) example_btn3.click(fill_example_3, outputs=[text_input, target_lang]) example_btn4.click(fill_example_4, outputs=[text_input, target_lang]) example_btn5.click(fill_example_5, outputs=[text_input, target_lang]) example_btn6.click(fill_example_6, outputs=[text_input, target_lang]) example_btn7.click(fill_example_7, outputs=[text_input, target_lang]) example_btn8.click(fill_example_8, outputs=[text_input, target_lang]) gr.Markdown("#### Translation Result") translate_result = gr.JSON() translate_btn.click( translate_text, inputs=[text_input, target_lang], outputs=translate_result, ) demo.launch()