import gradio as gr import os from transformers import pipeline from pypinyin import pinyin, Style from janome.tokenizer import Tokenizer import re from pytube import Search import requests from chinese_english_lookup import Dictionary as CEDict from jamdict import Jamdict import jieba import json # Hugging Face pipelines translation_pipeline = pipeline("translation", model="Helsinki-NLP/opus-mt-mul-en") lang_detection_pipeline = pipeline("text-classification", model="papluca/xlm-roberta-base-language-detection") # Initialize the dictionary libraries cedict = CEDict() jam = Jamdict() # Pinyin Romanization for Chinese def get_pinyin_from_chinese(lyrics): pinyin_result = pinyin(lyrics, style=Style.TONE) return " ".join(["".join(word) for word in pinyin_result]) # Romanization for Japanese (Romaji) def get_romaji_from_japanese(lyrics): t = Tokenizer() romaji_lyrics = [] for token in t.tokenize(lyrics): romaji_lyrics.append(token.reading.lower().replace("*", "")) return " ".join(romaji_lyrics) # Function to search YouTube and generate embed code def search_and_embed_video(song_name, artist_name): query = f"{song_name} {artist_name} official lyrics" try: s = Search(query) video_id = s.results[0].video_id youtube_url = f"https://www.youtube.com/embed/{video_id}" return f'' except Exception as e: return "
Could not find a YouTube video for this song.
" # Lookup functions for each language def lookup_english_word(word): api_url = f"https://api.dictionaryapi.dev/api/v2/entries/en/{word}" try: response = requests.get(api_url) response.raise_for_status() data = response.json() html_output = f"• {def_text}
" if 'example' in definition: example_text = definition['example'] html_output += f"Example: {example_text}
" return html_output except requests.exceptions.HTTPError as e: return f"Could not find a definition for '{word}'.
" except Exception as e: return f"An error occurred: {e}
" def lookup_chinese_word(word): try: result = cedict.lookup(word) if not result: return f"Could not find a definition for '{word}'.
" html_output = "" for entry in result: html_output += f"• {definitions}
" return html_output except Exception as e: return f"An error occurred during Chinese lookup: {e}
" def lookup_japanese_word(word): try: result = jam.lookup(word) if not result.entries and not result.kanji: return f"Could not find a definition for '{word}'.
" html_output = "" for entry in result.entries: html_output += f"• {', '.join(gloss.glosses)}
" for k in result.kanji: html_output += f"• Meaning: {', '.join(k.meanings)}
" if k.readings: html_output += f"• Readings: {', '.join(k.readings)}
" return html_output except Exception as e: return f"An error occurred during Japanese lookup: {e}
" # The main dictionary lookup function, which acts as a dispatcher def get_dictionary_output(json_data: str): if not json_data: return "Click on a word to get its definition." try: data = json.loads(json_data) word = data.get('word', '') language = data.get('lang', '') if language == 'en': return lookup_english_word(word) elif language == 'zh': return lookup_chinese_word(word) elif language == 'ja': return lookup_japanese_word(word) else: return f"Dictionary lookup for language '{language}' is not yet supported.
" except json.JSONDecodeError: return "Error: Invalid data received for dictionary lookup." # Helper function to generate the HTML for display def create_html_display(original_lyrics, translated_lyrics, romanized_lyrics=None, language="en"): # This is the most important part of the fix. We are embedding the JS `onclick` # handler directly and ensuring it's a simple, reliable call. original_lines = original_lyrics.strip().split('\n') translated_lines = translated_lyrics.strip().split('\n') num_lines = max(len(original_lines), len(translated_lines)) original_lines.extend([""] * (num_lines - len(original_lines))) translated_lines.extend([""] * (num_lines - len(translated_lines))) romanized_lines = [] if romanized_lyrics: romanized_lines = romanized_lyrics.strip().split('\n') romanized_lines.extend([""] * (num_lines - len(romanized_lines))) html_content = "" for i in range(num_lines): if language == 'zh': words_in_line = jieba.cut(original_lines[i]) elif language == 'ja': words_in_line = [char for char in original_lines[i] if char] else: words_in_line = original_lines[i].split() # # The onclick handler now directly sets the hidden textbox's value. # original_line_html = " ".join([ # f"{word}" # for word in words_in_line # ]) # We no longer need the onclick handler here. original_line_html = " ".join([ f"{word}" for word in words_in_line ]) # original_line_html = " ".join([ # f"{word}" # for word in words_in_line # ]) orig_line = f"{original_line_html}
" if romanized_lines: rom_line = f"{romanized_lines[i]}
" trans_line = f"{translated_lines[i]}
" html_content += f"""{translated_lines[i]}
" html_content += f"""