अनुवाद प्रणाली: तीन-तंत्रज्ञान हायब्रीड दृष्टिकोण
हा लेख आमची अनुवाद प्रणाली स्पष्ट करतो जी तीन तंत्रज्ञानांना एकत्र करते—टेम्पलेट्ससाठी Flask-Babel, फ्रेझ टेबल्ससाठी TranslationManager आणि सामग्री अनुवादासाठी DeepSeek AI—व्यापक बहुभाषिक समर्थन प्रदान करण्यासाठी.
समस्या: एक जटिल वेबसाइटचे अनुवाद करणे
आमच्या वेबसाइटवर अनेक प्रकारची सामग्री आहे ज्याचे अनुवाद करणे आवश्यक आहे:
-
स्थिर टेम्पलेट्स: नेव्हिगेशन, बटणे, लेबले (५००+ स्ट्रिंग्ज)
-
डायनॅमिक सामग्री: उत्पादन नावे, वर्णने, वैशिष्ट्ये (१०,०००+ स्ट्रिंग्ज)
-
वापरकर्ता-निर्मित सामग्री: पुनरावलोकने, टिप्पण्या, समर्थन तिकिटे
-
तांत्रिक संज्ञा: ब्रँड नावे, SKU, URL (अनुवादित करू नये)
एकच अनुवाद दृष्टिकोन कार्य करत नाही:
-
यंत्र अनुवाद: जलद पण तांत्रिक संज्ञांसाठी अचूक नाही
-
मॅन्युअल अनुवाद: अचूक पण मंद आणि महाग
-
केवळ टेम्पलेट: डायनॅमिक सामग्री हाताळत नाही
आम्हाला एक हायब्रीड दृष्टिकोन आवश्यक आहे जो तिन्हीचे सर्वोत्तम एकत्र करतो.
अनुवाद आर्किटेक्चर
graph TD
Request[वापरकर्ता विनंती
lang=hi]
subgraph Templates
Babel[Flask-Babel
.po फाइल्स]
Static[स्थिर स्ट्रिंग्ज
बटणे, लेबले]
end
subgraph Dynamic
TM[TranslationManager
फ्रेझ टेबल्स]
Phrases[उत्पादन नावे
वैशिष्ट्ये, संज्ञा]
end
subgraph AI
DS[DeepSeek API
AI अनुवाद]
Content[वर्णने
लेख, लांब मजकूर]
end
Request --> Babel
Request --> TM
Request --> DS
Babel --> Static
TM --> Phrases
DS --> Content
Static --> Response[अनुवादित पृष्ठ]
Phrases --> Response
Content --> Responseतीन तंत्रज्ञाने
१. Flask-Babel: टेम्पलेट अनुवाद
Flask-Babel gettext .po फाइल्स वापरून स्थिर टेम्पलेट स्ट्रिंग्ज हाताळते.
-
वापर प्रकरण: नेव्हिगेशन, बटणे, लेबले, त्रुटी संदेश
-
उदाहरण:
# टेम्पलेट
{{ _('Add to Cart') }}
# .po फाइल (हिंदी)
msgid "Add to Cart"
msgstr "कार्ट में जोड़ें"
फायदे:
-
✅ मानक i18n दृष्टिकोन
-
✅ अनुवाद साधन समर्थन (Poedit, Weblate)
-
✅ संकलन-वेळ पडताळणी
-
✅ जलद शोध (संकलित .mo फाइल्स)
मर्यादा:
-
❌ केवळ स्थिर स्ट्रिंग्जसाठी कार्य करते
-
❌ नवीन स्ट्रिंग्ज जोडण्यासाठी कोड बदल आवश्यक
-
❌ डायनॅमिक सामग्री समर्थन नाही
२. TranslationManager: फ्रेझ टेबल्स
आमची सानुकूल TranslationManager वर्ग JSON फ्रेझ टेबल्स वापरून डायनॅमिक सामग्री हाताळते.
-
वापर प्रकरण: उत्पादन नावे, वैशिष्ट्ये, तपशील, वर्णने
-
उदाहरण:
{
"Mini PC": "मिनी पीसी",
"Intel N100": "Intel N100",
"8GB RAM": "8GB RAM",
"256GB SSD": "256GB SSD"
}
फायदे:
-
✅ डायनॅमिक सामग्री समर्थन
-
✅ रनटाइम अद्यतने (पुन्हा सुरू करण्याची गरज नाही)
-
✅ संरक्षण नियम (ब्रँड नावे, SKU)
-
✅ प्रादेशिक स्वरूपण (दशांश विभाजक)
-
✅ अनुवाद रांग (गहाळ स्ट्रिंग्ज)
मर्यादा:
-
❌ मॅन्युअल फ्रेझ व्यवस्थापन
-
❌ अनुवादकांसाठी संदर्भ नाही
-
❌ प्रारंभिक अनुवाद आवश्यक
३. DeepSeek AI: सामग्री अनुवाद
DeepSeek AI मॉडेल लांब-स्वरूपातील सामग्री अनुवाद हाताळते.
-
वापर प्रकरण: ब्लॉग लेख, उत्पादन वर्णने, विपणन कॉपी
-
उदाहरण:
prompt = f"Translate to {lang}: {text}"
response = deepseek.generate(prompt)
फायदे:
-
✅ लांब सामग्री हाताळते (१०००+ शब्द)
-
✅ संदर्भ-जाणीव अनुवाद
-
✅ नैसर्गिक भाषा आउटपुट
-
✅ बॅच प्रक्रिया
मर्यादा:
-
❌ प्रति अनुवाद API खर्च
-
❌ इंटरनेट कनेक्शन आवश्यक
-
❌ तांत्रिक संज्ञा चुकीच्या पद्धतीने अनुवादित करू शकते
TranslationManager आर्किटेक्चर
फ्रेझ टेबल रचना
फ्रेझ टेबल्स प्रति भाषा JSON फाइल्स म्हणून संग्रहित केल्या जातात:
app/shared/translation/phrase_tables/
प्रत्येक फाइल इंग्रजी फ्रेझेस अनुवादांशी मॅप करते:
{
"Mini PC": "मिनी पीसी",
"Thin Client": "थिन क्लाइंट",
"Industrial PC": "औद्योगिक पीसी",
"All-in-One": "ऑल-इन-वन"
}
अनुवाद शोध
get() पद्धत बहु-स्तरीय शोध करते:
१. संरक्षण तपासणी:
if self._should_skip_translation(text, lang):
return text # ब्रँड नावे, SKU, URL अनुवादित करू नका
२. स्वल्पविराम विभाजन (लांब स्ट्रिंग्जसाठी):
if len(text) > 150 and "," in text:
parts = text.split(",")
return ", ".join(self.get(p, lang) for p in parts)
३. फ्रेझ टेबल शोध:
if text in self.phrase_tables[lang]:
return self.phrase_tables[lang][text]
४. लीगेसी कॅश प्रमोशन:
if text_hash in self.legacy_caches[lang]:
translation = self.legacy_caches[lang][text_hash]
self.set(text, lang, translation) # फ्रेझ टेबलमध्ये प्रमोट करा
return translation
५. गहाळ असल्यास रांगेत ठेवा:
if queue_if_missing:
self.add_to_queue(text, lang)
return None # अनुवाद सापडला नाही
संरक्षण नियम
आम्ही विशिष्ट सामग्री प्रकार जतन करतो:
ब्रँड नावे:
BRAND_NAMES_PRESERVE = [
"Thinvent", "Intel", "AMD", "Microsoft", "Ubuntu",
"Windows", "Linux", "WiFi", "Bluetooth"
]
तांत्रिक संज्ञा:
TECHNICAL_TERMS_PRESERVE = [
"HDMI", "DisplayPort", "VGA", "USB", "Ethernet",
"DDR4", "SSD", "NVMe", "PCIe", "SATA"
]
SKU (पॅटर्न-आधारित):
if not " " in text and text.count("-") >= 2:
return True # "Treo-N100-8-256-2H-W6-11P" जतन करा
URL:
if text.startswith(("/", "http://", "https://")):
return True
प्रादेशिक स्वरूपण
युरोपियन स्थानिकांसाठी (जर्मन, फ्रेंच, स्पॅनिश), आम्ही प्रादेशिक स्वरूपण लागू करतो:
दशांश विभाजक:
# इंग्रजी: 34.00
# जर्मन: 34,00
text = text.replace(".", ",")
व्होल्टेज/अँपरेज:
# इंग्रजी: 12.5V
# जर्मन: 12,5V
text = re.sub(r"(\d+)\.(\d+)V", r"\1,\2V", text)
हे खात्री करते की संख्या प्रत्येक स्थानिकासाठी योग्यरित्या प्रदर्शित होतात.
अनुवाद रांग
गहाळ अनुवाद बॅच प्रक्रियेसाठी रांगेत ठेवले जातात:
[
{
"text": "Compact Desktop",
"lang": "hi",
"hash": "a1b2c3d4e5f6"
},
{
"text": "Fanless Design",
"lang": "hi",
"hash": "f6e5d4c3b2a1"
}
]
एक पार्श्वभूमी स्क्रिप्ट DeepSeek AI वापरून रांग प्रक्रिया करते:
for item in queue:
translation = deepseek.translate(item["text"], item["lang"])
translation_manager.set(item["text"], item["lang"], translation)
फाइल लॉकिंग
आम्ही एकाचवेळी लेखन टाळण्यासाठी fcntl फाइल लॉकिंग वापरतो:
with open(lock_path, "w") as lock_file:
fcntl.flock(lock_file, fcntl.LOCK_EX)
try:
# फ्रेझ टेबल वाचा, सुधारा, लिहा
with open(table_path, "r+") as f:
data = json.load(f)
data.update(new_translations)
f.seek(0)
json.dump(data, f)
f.truncate()
finally:
fcntl.flock(lock_file, fcntl.LOCK_UN)
हे खात्री करते की एकाधिक प्रक्रिया फ्रेझ टेबल्स बिघडवत नाहीत.
भाषा शोधणे
आम्ही युनिकोड रेंज आणि स्टॉपवर्ड्स वापरून क्वेरी भाषा शोधतो:
युनिकोड रेंज शोधणे
देवनागरी (हिंदी, मराठी):
if 0x0900 <= ord(char) <= 0x097F:
return "hi"
बंगाली:
if 0x0980 <= ord(char) <= 0x09FF:
return "bn"
अरबी:
if 0x0600 <= ord(char) <= 0x06FF:
return "ar"
सिरिलिक (रशियन):
if 0x0400 <= ord(char) <= 0x04FF:
return "ru"
CJK (चायनीज, जपानी, कोरियन):
if 0x4E00 <= ord(char) <= 0x9FFF: # कांजी/हँझी
has_cjk = True
if 0x3040 <= ord(char) <= 0x30FF: # हिरागाना/कटाकाना
return "ja"
if 0xAC00 <= ord(char) <= 0xD7AF: # हंगुल
return "ko"
स्टॉपवर्ड शोधणे
लॅटिन-आधारित भाषांसाठी, आम्ही स्टॉपवर्ड्स वापरतो:
स्पॅनिश:
SPANISH_STOPWORDS = {
"el", "la", "los", "las", "un", "una", "para", "con",
"en", "por", "que", "es", "su", "y", "del", "al"
}
फ्रेंच:
FRENCH_STOPWORDS = {
"le", "la", "les", "des", "du", "un", "une", "pour",
"avec", "en", "est", "sur", "et", "au", "dans"
}
जर्मन:
GERMAN_STOPWORDS = {
"der", "die", "das", "ein", "eine", "für", "mit",
"ist", "und", "auf", "den", "dem", "bei", "von"
}
कोणतेही स्टॉपवर्ड जुळल्यास, आम्ही ती भाषा परत करतो.
डायनॅमिक भाषा शोधणे
वापरकर्ते खालील मार्गांनी भाषा निर्दिष्ट करू शकतात:
१. URL पॅरामीटर
/p/Treo-N100-8-256-2H-W6-11P?lang=hi
२. कुकी
response.set_cookie("lang", "hi", max_age=31536000)
३. ब्राउझर स्वीकार-भाषा हेडर
lang = request.accept_languages.best_match(["en", "hi", "es", "fr", "de"])
प्राधान्य: URL पॅराम > कुकी > स्वीकार-भाषा > ड