rahulrana0001 commited on
Commit
2cb8002
·
1 Parent(s): 4e04f3a

Fix Tamil translation: remove corrupted entries, add conversational idioms and Unicode-aware spoken Tamil grammar

Browse files
Files changed (3) hide show
  1. pipeline/custom_dictionary.json +59 -82
  2. pipeline/translation.py +212 -131
  3. test.py +4 -0
pipeline/custom_dictionary.json CHANGED
@@ -1,129 +1,106 @@
1
  {
2
  "spicy_map": {
3
- "முத்தம்": "உணர்ச்சிகரமான முத்தம்",
4
  "உடல்": "அழகிய மேனி",
5
- "காதல்": "தீவிர மோகம்",
6
  "படுக்கை": "அந்தரங்க படுக்கை",
7
- "தொடுதல்": "தீண்டல்",
8
- "அணைப்பு": "இறுக்கமான அணைப்பு"
 
 
 
 
 
 
 
 
9
  },
10
  "colloquial_map": {
11
  "செய்கிறேன்": "பண்றேன்",
12
  "செய்கிறாய்": "பண்ற",
13
  "செய்கிறான்": "பண்றான்",
14
- "செய்கிறாள்": "பண்றa",
15
  "செய்கிறார்கள்": "பண்றாங்க",
 
16
  "செய்வேன்": "பண்ணுவேன்",
17
- "செய்வோம்": "பண்ணuவோம்",
18
  "செய்தேன்": "பண்ணினேன்",
 
 
19
  "நன்றாக": "நல்லா",
20
  "இங்கே": "இங்க",
21
  "அங்கே": "அங்க",
22
  "எங்கே": "எங்க",
23
  "மிகவும்": "ரொம்ப",
24
- "மகிழ்ச்சி": "Happy",
 
 
25
  "பெரியது": "பெருசு",
26
  "சிறிய": "சின்ன",
27
  "சிறியது": "சின்னது",
28
  "வருகிறேன்": "வர்றேன்",
 
29
  "போகிறேன்": "போறேன்",
 
30
  "இருக்கிறேன்": "இருக்கேன்",
 
 
 
 
 
31
  "இருக்கிறது": "இருக்கு",
 
32
  "கொண்டிருக்கிறேன்": "இருக்கேன்",
33
  "உள்ளது": "இருக்கு",
34
  "இல்லை": "இல்ல",
35
  "யார்": "யாரு",
36
  "ஏன்": "எதுக்கு",
37
- "எப்படி": "எப்டி",
38
- "அப்படியா": "அப்டியா",
39
- "சரி": "ஓகே",
40
  "உணவு": "சாப்பாடு",
41
- "நீர்": "தண்ணi",
42
  "தாய்": "அம்மா",
43
  "தந்தை": "அப்பா",
44
- "sகோதரர்": "அண்ணன்",
45
- "sகோதரி": "அக்கா",
46
  "அவர்கள்": "அவங்க",
47
  "இவர்கள்": "இவங்க",
48
  "அவள்": "அவ",
49
  "இவள்": "இவ",
50
- "மகிழ்ச்சிய��க": "Happy-ஆ",
51
- "சந்தோஷமாக": "Happy-ஆ",
52
- "கதை": "Story",
53
- "முயற்சி": "Try",
54
- "உதவி": "Help",
55
- "நன்றி": "Thanks",
56
- "மன்னிக்கவும்": "Sorry",
57
- "தயவுசெய்து": "Please",
58
- "கோபமாக": "Angry-ஆ",
59
- "கோபம்": "Angry",
60
- "அறை": "Room",
61
- "வாழ்க்கை": "Life",
62
- "அழகாக": "Beautiful-ஆ",
63
- "அழகு": "Beautiful",
64
- "விருப்பம்": "Like",
65
- "பகிர்": "Share",
66
- "உணவகம்": "Hotel",
67
- "பேருந்து": "Bus",
68
- "மிதிவண்டி": "Cycle",
69
- "மின்னஞ்சல்": "Email",
70
- "கணினி": "System",
71
- "அலுவலகம்": "Office",
72
- "பள்ளி": "School",
73
- "கல்லூரி": "College",
74
- "மருத்துவமனை": "Hospital",
75
- "வங்கி": "Bank",
76
- "நேரம்": "Time",
77
- "நண்பன்": "Friend",
78
- "காதலி": "Girlfriend",
79
- "காதலன்": "Boyfriend",
80
- "வேலை": "Work",
81
- "பயணம்": "Trip",
82
- "பயிற்சி": "Practice",
83
- "சோதனை": "Test",
84
- "ஆசிரியர்": "Teacher",
85
- "செல்கிறேன்": "போறேன்",
86
- "செல்கிறாய்": "போற",
87
- "செல்கிறான்": "போறான்",
88
- "செல்கிறாள்": "போறa",
89
  "பார்த்தேன்": "பாத்தேன்",
90
  "பார்க்கிறேன்": "பாக்குறேன்",
 
91
  "பார்க்கலாம்": "பாக்கலாம்",
92
- "நண்பரே": "Friend",
93
- "நண்பர்களே": "Friends",
94
- "அலுவலகத்திற்கு": "Office-க்கு",
95
- "பள்ளிக்கு": "School-க்கு",
96
- "கல்லூரிக்கு": "College-க்கு",
97
- "மருத்துவமனைக்கு": "Hospital-க்கு",
98
- "வீட்டிற்கு": "வீட்டுக்கு",
99
  "இப்போது": "இப்ப",
100
- "பிறகு": "அப்றம்",
 
 
101
  "உடன்": "கூட",
102
  "மட்டும்": "மட்டும்",
103
  "ஆனால்": "ஆனா",
104
  "அல்லது": "இல்லனா",
105
  "ஏனென்றால்": "ஏன்னா",
106
- "ஒன்று": "1",
107
- "இரண்டு": "2",
108
- "மூன்று": "3",
109
- "நான்கு": "4",
110
- "ஐந்து": "5",
111
- "ஆறு": "6",
112
- "ஏழு": "7",
113
- "எட்டு": "8",
114
- "ஒன்பது": "9",
115
- "பத்து": "10",
116
- "பதினொன்று": "11",
117
- "பன்னிரண்டு": "12",
118
- "மணிக்கு": "மணிக்கு",
119
- "ரூபாய்": "ரூபா",
120
- "நூறு": "100",
121
- "ஆயிரம்": "1000",
122
- "லட்சம்": "லட்சம்",
123
- "கோடி": "கோடி",
124
- "என்னிடம்": "என்கிட்ட",
125
- "உன்னிடம்": "உன்கிட்ட",
126
- "அவனிடம்": "அவன்கிட்ட",
127
- "அவளிடம்": "அவகிட்ட"
128
  }
129
  }
 
1
  {
2
  "spicy_map": {
3
+ "முத்தம்": "இதழ் முத்தம்",
4
  "உடல்": "அழகிய மேனி",
5
+ "காதல்": "தீவிர காதல்",
6
  "படுக்கை": "அந்தரங்க படுக்கை",
7
+ "தொடுதல்": "மென்மையான தீண்டல்",
8
+ "அணைப்பு": "இறுக்கமான அணைப்பு",
9
+ "மூச்சு": "சூடான மூச்சுக்காற்று",
10
+ "இதயம்": "துடிக்கும் இதயம்",
11
+ "விரல்கள்": "மெல்லிய விரல்கள்",
12
+ "பார்வை": "மயக்கும் பார்வை",
13
+ "குரல்": "கிசுகிசுக்கும் குரல்",
14
+ "கண்கள்": "காதல் கண்கள்",
15
+ "உதடு": "மெல்லிய இதழ்கள்",
16
+ "நெருக்கம்": "அந்தரங்க நெருக்கம்"
17
  },
18
  "colloquial_map": {
19
  "செய்கிறேன்": "பண்றேன்",
20
  "செய்கிறாய்": "பண்ற",
21
  "செய்கிறான்": "பண்றான்",
22
+ "செய்கிறாள்": "பண்றா",
23
  "செய்கிறார்கள்": "பண்றாங்க",
24
+ "செய்கிறீர்கள்": "பண்றீங்க",
25
  "செய்வேன்": "பண்ணுவேன்",
26
+ "செய்வோம்": "பண்ணுவோம்",
27
  "செய்தேன்": "பண்ணினேன்",
28
+ "செய்தீர்கள்": "பண்ணீங்க",
29
+ "செய்தார்கள்": "பண்ணாங்க",
30
  "நன்றாக": "நல்லா",
31
  "இங்கே": "இங்க",
32
  "அங்கே": "அங்க",
33
  "எங்கே": "எங்க",
34
  "மிகவும்": "ரொம்ப",
35
+ "மகிழ்ச்சி": "சந்தோஷம்",
36
+ "மகிழ்ச்சியாக": "சந்தோஷமா",
37
+ "சந்தோஷமாக": "சந்தோஷமா",
38
  "பெரியது": "பெருசு",
39
  "சிறிய": "சின்ன",
40
  "சிறியது": "சின்னது",
41
  "வருகிறேன்": "வர்றேன்",
42
+ "வருகிறீர்கள்": "வர்றீங்க",
43
  "போகிறேன்": "போறேன்",
44
+ "போகிறீர்கள்": "போறீங்க",
45
  "இருக்கிறேன்": "இருக்கேன்",
46
+ "இருக்கிறீர்கள்": "இருக்கீங்க",
47
+ "இருக்கிறாய்": "இருக்க",
48
+ "இருக்கிறான்": "இருக்கான்",
49
+ "இருக்கிறாள்": "இருக்கா",
50
+ "இருக்கிறார்கள்": "இருக்காங்க",
51
  "இருக்கிறது": "இருக்கு",
52
+ "இருக்கின்றன": "இருக்கு",
53
  "கொண்டிருக்கிறேன்": "இருக்கேன்",
54
  "உள்ளது": "இருக்கு",
55
  "இல்லை": "இல்ல",
56
  "யார்": "யாரு",
57
  "ஏன்": "எதுக்கு",
58
+ "அப்படியா": "அப்படியா",
59
+ "சரி": "சரி",
 
60
  "உணவு": "சாப்பாடு",
61
+ "நீர்": "தண்ணீர்",
62
  "தாய்": "அம்மா",
63
  "தந்தை": "அப்பா",
64
+ "சகோதரர்": "அண்ணன்",
65
+ "சகோதரி": "அக்கா",
66
  "அவர்கள்": "அவங்க",
67
  "இவர்கள்": "இவங்க",
68
  "அவள்": "அவ",
69
  "இவள்": "இவ",
70
+ "அவன்": "அவன்",
71
+ "இவன்": "இவன்",
72
+ "நீங்கள்": "நீங்க",
73
+ "உங்கள்": "உங்க",
74
+ "உங்களுடைய": "உங்க",
75
+ "என்னிடம்": "என்கிட்ட",
76
+ "உன்னிடம்": "உன்கிட்ட",
77
+ "உங்களிடம்": "உங்ககிட்ட",
78
+ "அவனிடம்": "அவன்கிட்ட",
79
+ "அவளிடம்": "அவகிட்ட",
80
+ "அவர்களிடம்": "அவங்ககிட்ட",
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
81
  "பார்த்தேன்": "பாத்தேன்",
82
  "பார்க்கிறேன்": "பாக்குறேன்",
83
+ "பார்க்கிறீர்கள்": "பாக்குறீங்க",
84
  "பார்க்கலாம்": "பாக்கலாம்",
85
+ "செல்கிறேன்": "போறேன்",
86
+ "செல்கிறீர்கள்": "போறீங்க",
87
+ "சொல்கிறேன்": "சொல்றேன்",
88
+ "சொல்கிறீர்கள்": "சொல்றீங்க",
89
+ "கேட்கிறேன்": "கேக்குறேன்",
90
+ "கேட்கிறீர்கள்": "கேக்குறீங்க",
 
91
  "இப்போது": "இப்ப",
92
+ "பிறகு": "அப்புறம்",
93
+ "அப்போது": "அப்ப",
94
+ "எப்போது": "எப்ப",
95
  "உடன்": "கூட",
96
  "மட்டும்": "மட்டும்",
97
  "ஆனால்": "ஆனா",
98
  "அல்லது": "இல்லனா",
99
  "ஏனென்றால்": "ஏன்னா",
100
+ "ஏனெனில்": "ஏன்னா",
101
+ "அத���ால்": "அதனால",
102
+ "மெதுவாக": "மெதுவா",
103
+ "விரைவாக": "சீக்கிரம்",
104
+ "ஒன்றாக": "ஒண்ணா"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
105
  }
106
  }
pipeline/translation.py CHANGED
@@ -125,6 +125,32 @@ def _fetch_cloud_translation(text: str, target_lang: str = "Tamil") -> str:
125
 
126
  return text
127
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
128
  class Translator:
129
  def __init__(self):
130
  import json
@@ -134,45 +160,65 @@ class Translator:
134
 
135
  def get_default_maps(self):
136
  default_spicy = {
137
- "முத்தம்": "உணர்ச்சிகரமான முத்தம்",
138
  "உடல்": "அழகிய மேனி",
139
- "காதல்": "தீவிர மோகம்",
140
  "படுக்கை": "அந்தரங்க படுக்கை",
141
- "தொடுதல்": "தீண்டல்",
142
  "அணைப்பு": "இறுக்கமான அணைப்பு",
 
 
 
 
 
 
 
 
143
  }
144
  default_colloquial = {
145
  "செய்கிறேன்": "பண்றேன்",
146
  "செய்கிறாய்": "பண்ற",
147
  "செய்கிறான்": "பண்றான்",
148
- "செய்கிறாள்": "பண்றa",
149
  "செய்கிறார்கள்": "பண்றாங்க",
 
150
  "செய்வேன்": "பண்ணுவேன்",
151
- "செய்வோம்": "பண்ணuவோம்",
152
  "செய்தேன்": "பண்ணினேன்",
 
 
153
  "நன்றாக": "நல்லா",
154
  "இங்கே": "இங்க",
155
  "அங்கே": "அங்க",
156
  "எங்கே": "எங்க",
157
  "மிகவும்": "ரொம்ப",
158
  "மகிழ்ச்சி": "சந்தோஷம்",
 
 
159
  "பெரியது": "பெருசு",
160
  "சிறிய": "சின்ன",
161
  "சிறியது": "சின்னது",
162
  "வருகிறேன்": "வர்றேன்",
 
163
  "போகிறேன்": "போறேன்",
 
164
  "இருக்கிறேன்": "இருக்கேன்",
 
 
 
 
 
165
  "இருக்கிறது": "இருக்கு",
 
166
  "கொண்டிருக்கிறேன்": "இருக்கேன்",
167
  "உள்ளது": "இருக்கு",
168
  "இல்லை": "இல்ல",
169
  "யார்": "யாரு",
170
  "ஏன்": "எதுக்கு",
171
- "எப்படி": "எப்டி",
172
- "அப்படியா": "அப்டியா",
173
- "சரி": "ஓகே",
174
  "உணவு": "சாப்பாடு",
175
- "நீர்": "தண்ணi",
176
  "தாய்": "அம்மா",
177
  "தந்தை": "அப்பா",
178
  "சகோதரர்": "அண்ணன்",
@@ -181,85 +227,41 @@ class Translator:
181
  "இவர்கள்": "இவங்க",
182
  "அவள்": "அவ",
183
  "இவள்": "இவ",
184
- "மகிழ்ச்சியாக": "Happy-ஆ",
185
- "சந்தோஷமாக": "Happy-ஆ",
186
- "மகிழ்ச்சி": "Happy",
187
- "கதை": "Story",
188
- "முயற்சி": "Try",
189
- "உதவி": "Help",
190
- "நன்றி": "Thanks",
191
- "மன்னிக்கவும்": "Sorry",
192
- "தயவுசெய்து": "Please",
193
- "கோபமாக": "Angry-ஆ",
194
- "கோபம்": "Angry",
195
- "அறை": "Room",
196
- "வாழ்க்கை": "Life",
197
- "அழகாக": "Beautiful-ஆ",
198
- "அழகு": "Beautiful",
199
- "விருப்பம்": "Like",
200
- "பகிர்": "Share",
201
- "உணவகம்": "Hotel",
202
- "பேருந்து": "Bus",
203
- "மிதிவண்டி": "Cycle",
204
- "மின்னஞ்சல்": "Email",
205
- "கணினி": "System",
206
- "அலுவலகம்": "Office",
207
- "பள்ளி": "School",
208
- "கல்லூரி": "College",
209
- "மருத்துவமனை": "Hospital",
210
- "வங்கி": "Bank",
211
- "நேரம்": "Time",
212
- "நண்பன்": "Friend",
213
- "காதலி": "Girlfriend",
214
- "காதலன்": "Boyfriend",
215
- "வேலை": "Work",
216
- "பயணம்": "Trip",
217
- "பயிற்சி": "Practice",
218
- "சோதனை": "Test",
219
- "ஆசிரியர்": "Teacher",
220
- "செல்கிறேன்": "போறேன்",
221
- "செல்கிறாய்": "போற",
222
- "செல்கிறான்": "போறான்",
223
- "செல்கிறாள்": "போறa",
224
  "பார்த்தேன்": "பாத்தேன்",
225
  "பார்க்கிறேன்": "பாக்குறேன்",
 
226
  "பார்க்கலாம்": "பாக்கலாம்",
227
- "நண்பரே": "Friend",
228
- "நண்பர்களே": "Friends",
229
- "அலுவலகத்திற்கு": "Office-க்கு",
230
- "பள்ளிக்கு": "School-க்கு",
231
- "கல்லூரிக்கு": "College-க்கு",
232
- "மருத்துவமனைக்கு": "Hospital-க்கு",
233
- "வீட்டிற்கு": "வீட்டுக்கு",
234
  "இப்போது": "இப்ப",
235
- "பிறகு": "அப்றம்",
 
 
236
  "உடன்": "கூட",
237
  "மட்டும்": "மட்டும்",
238
  "ஆனால்": "ஆனா",
239
  "அல்லது": "இல்லனா",
240
  "ஏனென்றால்": "ஏன்னா",
241
- "ஒன்று": "1",
242
- "இரண்டு": "2",
243
- "மூன்று": "3",
244
- "நான்கு": "4",
245
- "ஐந்து": "5",
246
- "ஆறு": "6",
247
- "ஏழு": "7",
248
- "எட்டு": "8",
249
- "ஒன்பது": "9",
250
- "பத்து": "10",
251
- "பதினொன்று": "11",
252
- "பன்னிரண்டு": "12",
253
- "மணிக்கு": "மணிக்கு",
254
- "ரூபாய்": "ரூபா",
255
- "நூறு": "100",
256
- "ஆயிரம்": "1000",
257
- "லட்சம்": "லட்சம்",
258
- "கோடி": "கோடி",
259
- "என்னிடம்": "என்கிட்ட",
260
- "உன்னிடம்": "உன்கிட்ட",
261
- "அவனிடம்": "அவன்கிட்ட",
262
- "அவளிடம்": "அவகிட்ட",
263
  }
264
  return default_spicy, default_colloquial
265
 
@@ -270,8 +272,17 @@ class Translator:
270
  try:
271
  with open(self.dict_path, "r", encoding="utf-8") as f:
272
  data = json.load(f)
273
- self.spicy_map = data.get("spicy_map", default_spicy)
274
- self.colloquial_map = data.get("colloquial_map", default_colloquial)
 
 
 
 
 
 
 
 
 
275
  except Exception as e:
276
  print(f"Error loading custom dictionary: {e}")
277
  self.spicy_map = default_spicy
@@ -322,64 +333,126 @@ class Translator:
322
 
323
  def _apply_colloquial_style(self, text: str) -> str:
324
  """
325
- Converts formal Tamil to Spoken/Common Tamil.
326
  """
327
- # 1. Direct Word Mapping
328
- for formal, spoken in self.colloquial_map.items():
329
- text = text.replace(formal, spoken)
330
-
331
- # 2. Suffix Rules
332
  import re
333
 
334
- text = re.sub(r'ஒன்று மணி', '1 மணி', text)
335
- text = re.sub(r'இரண்டு மணி', '2 மணி', text)
336
- text = re.sub(r'மூன்று மணி', '3 மணி', text)
337
- text = re.sub(r'நான்கு மணி', '4 மணி', text)
338
- text = re.sub(r'ஐந்து மணி', '5 மணி', text)
339
- text = re.sub(r'ஆறு மணி', '6 மணி', text)
340
- text = re.sub(r'ஏழு மணி', '7 மணி', text)
341
- text = re.sub(r'எட்டு மணி', '8 மணி', text)
342
- text = re.sub(r'ஒன்பது மணி', '9 மணி', text)
343
- text = re.sub(r'பத்து மணி', '10 மணி', text)
344
 
345
- # Verb Tense & Agreement Endings
346
- text = re.sub(r'கிறேன்(?=[^\u0b80-\u0bff]|$)', 'றேன்', text)
347
- text = re.sub(r'கிறாய்(?=[^\u0b80-\u0bff]|$)', 'ற', text)
348
- text = re.sub(r'கிறான்(?=[^\u0b80-\u0bff]|$)', 'றான்', text)
349
- text = re.sub(r'கிறாள்(?=[^\u0b80-\u0bff]|$)', 'றா', text)
350
- text = re.sub(r'கிறார்(?=[^\u0b80-\u0bff]|$)', 'றார்', text)
351
- text = re.sub(r'கிறார்கள்(?=[^\u0b80-\u0bff]|$)', 'றாங்க', text)
352
- text = re.sub(r'க்கிறது(?=[^\u0b80-\u0bff]|$)', 'து', text)
353
- text = re.sub(r'கிறது(?=[^\u0b80-\u0bff]|$)', 'து', text)
354
- text = re.sub(r'கின்றது(?=[^\u0b80-\u0bff]|$)', 'து', text)
355
- text = re.sub(r'விட்டது(?=[^\u0b80-\u0bff]|$)', 'டுச்சு', text)
356
 
357
- # Modern Case Suffixes & Spoken Conversational Grammar
358
- text = re.sub(r'உடைய(?=[^\u0b80-\u0bff]|$)', 'ோட', text)
359
- text = re.sub(r'இல்(?=[^\u0b80-\u0bff]|$)', 'ல', text)
360
- text = re.sub(r'ஆல்(?=[^\u0b80-\u0bff]|$)', 'ால', text)
 
 
 
 
 
361
  text = re.sub(r'திற்கு(?=[^\u0b80-\u0bff]|$)', 'துக்கு', text)
362
  text = re.sub(r'இற்கு(?=[^\u0b80-\u0bff]|$)', 'ுக்கு', text)
363
- text = re.sub(r'வில்லை(?=[^\u0b80-\u0bff]|$)', 'ல', text)
364
- text = re.sub(r'ார்(?=[^\u0b80-\u0bff]|$)', 'ாரு', text)
365
- text = re.sub(r'தனர்(?=[^\u0b80-\u0bff]|$)', 'தாங்க', text)
366
- text = re.sub(r'இனர்(?=[^\u0b80-\u0bff]|$)', 'ினாங்க', text)
367
- text = re.sub(r'தார்கள்(?=[^\u0b80-\u0bff]|$)', 'தாங்க', text)
368
- text = re.sub(r'னார்கள்(?=[^\u0b80-\u0bff]|$)', 'னாங்க', text)
369
- text = re.sub(r'கொண்டனர்(?=[^\u0b80-\u0bff]|$)', 'கிட்டாங்க', text)
370
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
371
  return text
372
 
373
  def translate(self, text: str, target_lang: str = "Tamil", spicy: bool = False, colloquial: bool = True, mode: str = "Cloud APIs (Fast & Lightweight ⚡)") -> str:
374
- """
375
- Executes the 5-Step Hybrid Translation Architecture:
376
- Step 1 — Input Reception: Receives English, Tanglish, Hinglish, Manglish, etc.
377
- Step 2 — Language Detection: Uses Lingua & pattern detection to categorize input.
378
- Step 3 & 4 — Dynamic Hybrid Routing Strategy:
379
- Path A (Straightforward English) -> IndicTrans2 (Fast NMT).
380
- Path B (Code-switched / Tanglish / Hinglish / Manglish) -> Qwen3 Semantic Understanding.
381
- Step 5 — Natural Localization: Conversational, context-aware native output keeping common loanwords (site, helmet, etc.).
382
- """
383
  if not text or not text.strip():
384
  return ""
385
 
@@ -406,16 +479,24 @@ class Translator:
406
  return self.cache[cache_key]
407
 
408
  try:
409
- # 100% Free Cloud Translation (zero cost, zero tokens, sub-second response)
 
 
 
 
 
 
 
410
  translated = _fetch_cloud_translation(clean_text, target_lang)
411
 
412
- # Step 5: Post-processing (Colloquial & Spicy styles for Tamil)
413
  if target_lang == "Tamil":
414
  if colloquial:
415
  translated = self._apply_colloquial_style(translated)
416
  if spicy:
417
  for eng, tam in self.spicy_map.items():
418
- translated = translated.replace(eng, tam)
 
419
 
420
  # Save in Cache
421
  self.cache[cache_key] = translated
 
125
 
126
  return text
127
 
128
+ def tamil_boundary(word: str) -> str:
129
+ return r'(?<![\u0b80-\u0bff])' + re.escape(word) + r'(?![\u0b80-\u0bff])'
130
+
131
+ # Clean English Conversational Idioms Mapping for instant natural spoken Tamil
132
+ CONVERSATIONAL_IDIOMS = [
133
+ (r'(?i)^\s*how\s+are\s+you\s+(?:all\s+)?girls[\s\?\.\!]*$', 'பொண்ணுங்களா, எப்படி இருக்கீங்க?'),
134
+ (r'(?i)^\s*how\s+are\s+you\s+(?:all\s+)?(?:guys|boys)[\s\?\.\!]*$', 'பசங்களா, எப்படி இருக்கீங்க?'),
135
+ (r'(?i)^\s*how\s+are\s+you\s+all[\s\?\.\!]*$', 'எல்லாரும் எப்படி இருக்கீங்க?'),
136
+ (r'(?i)^\s*how\s+are\s+you\s+doing[\s\?\.\!]*$', 'எப்படி இருக்கீங்க?'),
137
+ (r'(?i)^\s*how\s+are\s+you[\s\?\.\!]*$', 'எப்படி இருக்கீங்க?'),
138
+ (r'(?i)^\s*what(?:\s+are|\'re)\s+you\s+doing[\s\?\.\!]*$', 'என்ன பண்றீங்க?'),
139
+ (r'(?i)^\s*where\s+are\s+you\s+going[\s\?\.\!]*$', 'எங்க போறீங்க?'),
140
+ (r'(?i)^\s*where\s+are\s+you[\s\?\.\!]*$', 'எங்க இருக்கீங்க?'),
141
+ (r'(?i)^\s*what\s+happened[\s\?\.\!]*$', 'என்ன ஆச்சு?'),
142
+ (r'(?i)^\s*what(?:\s+is|\'s)\s+up[\s\?\.\!]*$', 'என்ன சமாச்சாரம்?'),
143
+ (r'(?i)^\s*i\s+love\s+you\s+so\s+much[\s\?\.\!]*$', 'நான் உன்னை ரொம்ப காதலிக்கிறேன்'),
144
+ (r'(?i)^\s*i\s+love\s+you[\s\?\.\!]*$', 'நான் உன்னை காதலிக்கிறேன்'),
145
+ (r'(?i)^\s*i\s+miss\s+you\s+so\s+much[\s\?\.\!]*$', 'உன்னை ரொம்ப மிஸ் பண்றேன்'),
146
+ (r'(?i)^\s*i\s+miss\s+you[\s\?\.\!]*$', 'உன்னை மிஸ் பண்றேன்'),
147
+ (r'(?i)^\s*don\'?t\s+worry[\s\?\.\!]*$', 'கவலைப்படாதீங்க'),
148
+ (r'(?i)^\s*take\s+care[\s\?\.\!]*$', 'உடம்ப பாத்துக்கோங்க'),
149
+ (r'(?i)^\s*see\s+you\s+(?:later|soon)[\s\?\.\!]*$', 'அப்புறம் பாக்கலாம்'),
150
+ (r'(?i)^\s*good\s+morning[\s\?\.\!]*$', 'காலை வணக்கம்'),
151
+ (r'(?i)^\s*good\s+night[\s\?\.\!]*$', 'இனிய இரவு வணக்கம்'),
152
+ ]
153
+
154
  class Translator:
155
  def __init__(self):
156
  import json
 
160
 
161
  def get_default_maps(self):
162
  default_spicy = {
163
+ "முத்தம்": "இதழ் முத்தம்",
164
  "உடல்": "அழகிய மேனி",
165
+ "காதல்": "தீவிர காதல்",
166
  "படுக்கை": "அந்தரங்க படுக்கை",
167
+ "தொடுதல்": "மென்மையான தீண்டல்",
168
  "அணைப்பு": "இறுக்கமான அணைப்பு",
169
+ "மூச்சு": "சூடான மூச்சுக்காற்று",
170
+ "இதயம்": "துடிக்கும் இதயம்",
171
+ "விரல்கள்": "மெல்லிய விரல்கள்",
172
+ "பார்வை": "மயக்கும் பார்வை",
173
+ "குரல்": "கிசுகிசுக்கும் குரல்",
174
+ "கண்கள்": "காதல் கண்கள்",
175
+ "உதடு": "மெல்லிய இதழ்கள்",
176
+ "நெருக்கம்": "அந்தரங்க நெருக்கம்"
177
  }
178
  default_colloquial = {
179
  "செய்கிறேன்": "பண்றேன்",
180
  "செய்கிறாய்": "பண்ற",
181
  "செய்கிறான்": "பண்றான்",
182
+ "செய்கிறாள்": "பண்றா",
183
  "செய்கிறார்கள்": "பண்றாங்க",
184
+ "செய்கிறீர்கள்": "பண்றீங்க",
185
  "செய்வேன்": "பண்ணுவேன்",
186
+ "செய்வோம்": "பண்ணுவோம்",
187
  "செய்தேன்": "பண்ணினேன்",
188
+ "செய்தீர்கள்": "பண்ணீங்க",
189
+ "செய்தார்கள்": "பண்ணாங்க",
190
  "நன்றாக": "நல்லா",
191
  "இங்கே": "இங்க",
192
  "அங்கே": "அங்க",
193
  "எங்கே": "எங்க",
194
  "மிகவும்": "ரொம்ப",
195
  "மகிழ்ச்சி": "சந்தோஷம்",
196
+ "மகிழ்ச்சியாக": "சந்தோஷமா",
197
+ "சந்தோஷமாக": "சந்தோஷமா",
198
  "பெரியது": "பெருசு",
199
  "சிறிய": "சின்ன",
200
  "சிறியது": "சின்னது",
201
  "வருகிறேன்": "வர்றேன்",
202
+ "வருகிறீர்கள்": "வர்றீங்க",
203
  "போகிறேன்": "போறேன்",
204
+ "போகிறீர்கள்": "போறீங்க",
205
  "இருக்கிறேன்": "இருக்கேன்",
206
+ "இருக்கிறீர்கள்": "இருக்கீங்க",
207
+ "இருக்கிறாய்": "இருக்க",
208
+ "இருக்கிறான்": "இருக்கான்",
209
+ "இருக்கிறாள்": "இருக்கா",
210
+ "இருக்கிறார்கள்": "இருக்காங்க",
211
  "இருக்கிறது": "இருக்கு",
212
+ "இருக்கின்றன": "இருக்கு",
213
  "கொண்டிருக்கிறேன்": "இருக்கேன்",
214
  "உள்ளது": "இருக்கு",
215
  "இல்லை": "இல்ல",
216
  "யார்": "யாரு",
217
  "ஏன்": "எதுக்கு",
218
+ "அப்படியா": "அப்படியா",
219
+ "சரி": "சரி",
 
220
  "உணவு": "சாப்பாடு",
221
+ "நீர்": "தண்ணீர்",
222
  "தாய்": "அம்மா",
223
  "தந்தை": "அப்பா",
224
  "சகோதரர்": "அண்ணன்",
 
227
  "இவர்கள்": "இவங்க",
228
  "அவள்": "அவ",
229
  "இவள்": "இவ",
230
+ "அவன்": "அவன்",
231
+ "இவன்": "இவன்",
232
+ "நீங்கள்": "நீங்க",
233
+ "உங்கள்": "உங்க",
234
+ "உங்களுடைய": "உங்க",
235
+ "என்னிடம்": "என்கிட்ட",
236
+ "உன்னிடம்": "உன்கிட்ட",
237
+ "உங்களிடம்": "உங்ககிட்ட",
238
+ "அவனிடம்": "அவன்கிட்ட",
239
+ "அவளிடம்": "அவகிட்ட",
240
+ "அவர்களிடம்": "அவங்ககிட்ட",
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
241
  "பார்த்தேன்": "பாத்தேன்",
242
  "பார்க்கிறேன்": "பாக்குறேன்",
243
+ "பார்க்கிறீர்கள்": "பாக்குறீங்க",
244
  "பார்க்கலாம்": "பாக்கலாம்",
245
+ "செல்கிறேன்": "போறேன்",
246
+ "செல்கிறீர்கள்": "போறீங்க",
247
+ "சொல்கிறேன்": "சொல்றேன்",
248
+ "சொல்கிறீர்கள்": "சொல்றீங்க",
249
+ "கேட்கிறேன்": "கேக்குறேன்",
250
+ "கேட்கிறீர்கள்": "கேக்குறீங்க",
 
251
  "இப்போது": "இப்ப",
252
+ "பிறகு": "அப்புறம்",
253
+ "அப்போது": "அப்ப",
254
+ "எப்போது": "எப்ப",
255
  "உடன்": "கூட",
256
  "மட்டும்": "மட்டும்",
257
  "ஆனால்": "ஆனா",
258
  "அல்லது": "இல்லனா",
259
  "ஏனென்றால்": "ஏன்னா",
260
+ "ஏனெனில்": "ஏன்னா",
261
+ "அதனால்": "அதனால",
262
+ "மெதுவாக": "மெதுவா",
263
+ "விரைவாக": "சீக்கிரம்",
264
+ "ஒன்றாக": "ஒண்ணா"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
265
  }
266
  return default_spicy, default_colloquial
267
 
 
272
  try:
273
  with open(self.dict_path, "r", encoding="utf-8") as f:
274
  data = json.load(f)
275
+ spicy = data.get("spicy_map", default_spicy)
276
+ colloquial = data.get("colloquial_map", default_colloquial)
277
+
278
+ # Sanitize any legacy corrupted dictionary entries
279
+ if colloquial.get("எப்படி") == "எப்டி" or "Happy" in colloquial.values() or "பண்றa" in colloquial.values() or "Story" in colloquial.values():
280
+ self.spicy_map = default_spicy
281
+ self.colloquial_map = default_colloquial
282
+ self.save_dictionary()
283
+ else:
284
+ self.spicy_map = spicy
285
+ self.colloquial_map = colloquial
286
  except Exception as e:
287
  print(f"Error loading custom dictionary: {e}")
288
  self.spicy_map = default_spicy
 
333
 
334
  def _apply_colloquial_style(self, text: str) -> str:
335
  """
336
+ Converts formal/bookish Google Translate Tamil into natural, fluent Spoken Tamil (பேச்சுத் தமிழ்).
337
  """
 
 
 
 
 
338
  import re
339
 
340
+ # 1. Vocatives & Addressing (e.g., "பெண்கள் எப்படி இருக்கிறீர்கள்" -> "பொண்ணுங்களா, எப்படி இருக்கீங்க?")
341
+ text = re.sub(r'([\"\'“‘\s]|^)(?:ஹேய்\s+)?பெண்கள்\s+(?=எப்படி|என்ன|எங்க)', r'\1பொண்ணுங்களா, ', text)
342
+ text = re.sub(tamil_boundary('பெண்களே'), 'பொண்ணுங்களா', text)
343
+ text = re.sub(r'([\"\'“‘\s]|^)(?:ஹேய்\s+)?ஆண்கள்\s+(?=எப்படி|என்ன|எங்க)', r'\1பசங்களா, ', text)
344
+ text = re.sub(tamil_boundary('ஆண்களே'), 'பசங்களா', text)
 
 
 
 
 
345
 
346
+ # 2. Pronouns (Natural Spoken)
347
+ text = re.sub(tamil_boundary('நீங்கள்'), 'நீங்க', text)
348
+ text = re.sub(tamil_boundary('உங்கள்'), 'உங்க', text)
349
+ text = re.sub(tamil_boundary('உங்களுடைய'), 'உங்க', text)
350
+ text = re.sub(tamil_boundary('அவர்கள்'), 'அவங்க', text)
351
+ text = re.sub(tamil_boundary('இவர்கள்'), 'இவங்க', text)
352
+ text = re.sub(tamil_boundary('அவள்'), 'அவ', text)
353
+ text = re.sub(tamil_boundary('இவள்'), 'இவ', text)
354
+ text = re.sub(tamil_boundary('அவன்'), 'அவன்', text)
 
 
355
 
356
+ # 3. Postpositions & Cases
357
+ text = re.sub(tamil_boundary('என்னிடம்'), 'என்கிட்ட', text)
358
+ text = re.sub(tamil_boundary('உன்னிடம்'), 'உன்கிட்ட', text)
359
+ text = re.sub(tamil_boundary('உங்களிடம்'), 'உங்ககிட்ட', text)
360
+ text = re.sub(tamil_boundary('அவனிடம்'), 'அவன்கிட்ட', text)
361
+ text = re.sub(tamil_boundary('அவளிடம்'), 'அவகிட்ட', text)
362
+ text = re.sub(tamil_boundary('அவர்களிடம்'), 'அவங்ககிட்ட', text)
363
+ text = re.sub(r'யுடன்(?=[^\u0b80-\u0bff]|$)', 'யோட', text)
364
+ text = re.sub(r'உடன்(?=[^\u0b80-\u0bff]|$)', 'ோட', text)
365
  text = re.sub(r'திற்கு(?=[^\u0b80-\u0bff]|$)', 'துக்கு', text)
366
  text = re.sub(r'இற்கு(?=[^\u0b80-\u0bff]|$)', 'ுக்கு', text)
 
 
 
 
 
 
 
367
 
368
+ # 4. Adverbs & Conjunctions
369
+ text = re.sub(tamil_boundary('மிகவும்'), 'ரொம்ப', text)
370
+ text = re.sub(tamil_boundary('நன்றாக'), 'நல்லா', text)
371
+ text = re.sub(tamil_boundary('ஒன்றாக'), 'ஒண்ணா', text)
372
+ text = re.sub(tamil_boundary('மெதுவாக'), 'மெதுவா', text)
373
+ text = re.sub(tamil_boundary('விரைவாக'), 'சீக்கிரம்', text)
374
+ text = re.sub(tamil_boundary('இப்போது'), 'இப்ப', text)
375
+ text = re.sub(tamil_boundary('அப்போது'), 'அப்ப', text)
376
+ text = re.sub(tamil_boundary('எப்போது'), 'எப்ப', text)
377
+ text = re.sub(tamil_boundary('இங்கே'), 'இங்க', text)
378
+ text = re.sub(tamil_boundary('அங்கே'), 'அங்க', text)
379
+ text = re.sub(tamil_boundary('எங்கே'), 'எங்க', text)
380
+ text = re.sub(tamil_boundary('ஆனால்'), 'ஆனா', text)
381
+ text = re.sub(tamil_boundary('ஏனெனில்'), 'ஏன்னா', text)
382
+ text = re.sub(tamil_boundary('ஏனென்றால்'), 'ஏன்னா', text)
383
+ text = re.sub(tamil_boundary('அதனால்'), 'அதனால', text)
384
+ text = re.sub(tamil_boundary('மட்டுமே'), 'மட்டும்', text)
385
+
386
+ # 5. Question & Auxiliary Verb Forms
387
+ text = re.sub(tamil_boundary('இருக்கிறீர்கள்'), 'இருக்கீங்க', text)
388
+ text = re.sub(tamil_boundary('செய்கிறீர்கள்'), 'பண்றீங்க', text)
389
+ text = re.sub(tamil_boundary('வருகிறீர்கள்'), 'வர்றீங்க', text)
390
+ text = re.sub(tamil_boundary('போகிறீர்கள்'), 'போறீங்க', text)
391
+ text = re.sub(tamil_boundary('பார்க்கிறீர்கள்'), 'பாக்குறீங்க', text)
392
+ text = re.sub(tamil_boundary('பேசுகிறீர்கள்'), 'பேசுறீங்க', text)
393
+ text = re.sub(tamil_boundary('சொல்கிறீர்கள்'), 'சொல்றீங்க', text)
394
+ text = re.sub(tamil_boundary('கேட்கிறீர்கள்'), 'கேக்குறீங்க', text)
395
+
396
+ text = re.sub(tamil_boundary('செய்கிறேன்'), 'பண்றேன்', text)
397
+ text = re.sub(tamil_boundary('செய்கிறாய்'), 'பண்ற', text)
398
+ text = re.sub(tamil_boundary('செய்கிறான்'), 'பண்றான்', text)
399
+ text = re.sub(tamil_boundary('செய்கிறாள்'), 'பண்றா', text)
400
+ text = re.sub(tamil_boundary('செய்கிறார்கள்'), 'பண்றாங்க', text)
401
+
402
+ text = re.sub(tamil_boundary('இருக்கிறேன்'), 'இருக்கேன்', text)
403
+ text = re.sub(tamil_boundary('இருக்கிறாய்'), 'இருக்க', text)
404
+ text = re.sub(tamil_boundary('இருக்கிறான்'), 'இருக்கான்', text)
405
+ text = re.sub(tamil_boundary('இருக்கிறாள்'), 'இருக்கா', text)
406
+ text = re.sub(tamil_boundary('இருக்கிறார்கள்'), 'இருக்காங்க', text)
407
+ text = re.sub(tamil_boundary('இருக்கிறது'), 'இருக்கு', text)
408
+ text = re.sub(tamil_boundary('இருக்கின்றன'), 'இருக்கு', text)
409
+ text = re.sub(tamil_boundary('உள்ளது'), 'இருக்கு', text)
410
+ text = re.sub(tamil_boundary('இல்லை'), 'இல்ல', text)
411
+
412
+ # 6. Polite Imperatives
413
+ text = re.sub(tamil_boundary('வாருங்கள்'), 'வாங்க', text)
414
+ text = re.sub(tamil_boundary('போங்கள்'), 'போங்க', text)
415
+ text = re.sub(tamil_boundary('சொல்லுங்கள்'), 'சொல்லுங்க', text)
416
+ text = re.sub(tamil_boundary('பாருங்கள்'), 'பாருங்க', text)
417
+ text = re.sub(tamil_boundary('கேளுங்கள்'), 'கேளுங்க', text)
418
+ text = re.sub(tamil_boundary('செய்யுங்கள்'), 'பண்ணுங்க', text)
419
+ text = re.sub(tamil_boundary('உட்காருங்கள்'), 'உட்காருங்க', text)
420
+ text = re.sub(tamil_boundary('நில்லுங்கள்'), 'நில்லுங்க', text)
421
+
422
+ # 7. Common Negatives
423
+ text = re.sub(tamil_boundary('தெரியவில்லை'), 'தெரியல', text)
424
+ text = re.sub(tamil_boundary('புரியவில்லை'), 'புரியல', text)
425
+ text = re.sub(tamil_boundary('வரவில்லை'), 'வரல', text)
426
+ text = re.sub(tamil_boundary('போகவில்லை'), 'போகல', text)
427
+ text = re.sub(tamil_boundary('செய்யவில்லை'), 'பண்ணல', text)
428
+ text = re.sub(tamil_boundary('பார்க்கவில்லை'), 'பாக்கல', text)
429
+ text = re.sub(tamil_boundary('பிடிக்கவில்லை'), 'புடிக்கல', text)
430
+
431
+ # 8. Past Completed / Narrative Suffixes
432
+ text = re.sub(tamil_boundary('பார்த்தாள்'), 'பாத்தா', text)
433
+ text = re.sub(tamil_boundary('பார்த்தான்'), 'பாத்தான்', text)
434
+ text = re.sub(tamil_boundary('பார்த்தேன்'), 'பாத்தேன்', text)
435
+ text = re.sub(tamil_boundary('பார்த்தார்கள்'), 'பாத்தாங்க', text)
436
+ text = re.sub(tamil_boundary('சிரித்தாள்'), 'சிரிச்சா', text)
437
+ text = re.sub(tamil_boundary('சிரித்தான்'), 'சிரிச்சான்', text)
438
+ text = re.sub(tamil_boundary('சிரித்து'), 'சிரிச்சுட்டு', text)
439
+ text = re.sub(tamil_boundary('சொன்னாள்'), 'சொன்னா', text)
440
+ text = re.sub(tamil_boundary('சொன்னான்'), 'சொன்னான்', text)
441
+ text = re.sub(tamil_boundary('கேட்டாள்'), 'கேட்டா', text)
442
+ text = re.sub(tamil_boundary('கேட்டான்'), 'கேட்டான்', text)
443
+ text = re.sub(tamil_boundary('ஆகிவிட்டது'), 'ஆயிடுச்சு', text)
444
+ text = re.sub(tamil_boundary('போய்விட்டது'), 'போயிடுச்சு', text)
445
+ text = re.sub(tamil_boundary('வந்துவிட்டது'), 'வந்துடுச்சு', text)
446
+ text = re.sub(tamil_boundary('முடிந்துவிட்டது'), 'முடிஞ்சுடுச்சு', text)
447
+
448
+ # 9. Custom Dictionary Words
449
+ for formal, spoken in self.colloquial_map.items():
450
+ if formal in text:
451
+ text = re.sub(tamil_boundary(formal), spoken, text)
452
+
453
  return text
454
 
455
  def translate(self, text: str, target_lang: str = "Tamil", spicy: bool = False, colloquial: bool = True, mode: str = "Cloud APIs (Fast & Lightweight ⚡)") -> str:
 
 
 
 
 
 
 
 
 
456
  if not text or not text.strip():
457
  return ""
458
 
 
479
  return self.cache[cache_key]
480
 
481
  try:
482
+ # 1. Check English conversational idioms first for instant 100% natural spoken Tamil
483
+ if target_lang == "Tamil":
484
+ for pat, rep in CONVERSATIONAL_IDIOMS:
485
+ if re.match(pat, clean_text):
486
+ self.cache[cache_key] = rep
487
+ return rep
488
+
489
+ # 2. Cloud Translation
490
  translated = _fetch_cloud_translation(clean_text, target_lang)
491
 
492
+ # 3. Post-processing (Colloquial & Spicy styles for Tamil)
493
  if target_lang == "Tamil":
494
  if colloquial:
495
  translated = self._apply_colloquial_style(translated)
496
  if spicy:
497
  for eng, tam in self.spicy_map.items():
498
+ if eng in translated:
499
+ translated = re.sub(tamil_boundary(eng), tam, translated)
500
 
501
  # Save in Cache
502
  self.cache[cache_key] = translated
test.py CHANGED
@@ -2,9 +2,13 @@ from pipeline.translation import translate_to_tamil
2
  from pipeline.tts import generate_tamil_speech
3
  from app import save_audio_to_mp3
4
  import os
 
5
  import time
6
  import gc
7
 
 
 
 
8
  def run_test():
9
  print("Testing translation...")
10
  english_text = "Hello, how are you? I am very happy to meet you."
 
2
  from pipeline.tts import generate_tamil_speech
3
  from app import save_audio_to_mp3
4
  import os
5
+ import sys
6
  import time
7
  import gc
8
 
9
+ if sys.stdout and hasattr(sys.stdout, "reconfigure"):
10
+ sys.stdout.reconfigure(encoding='utf-8')
11
+
12
  def run_test():
13
  print("Testing translation...")
14
  english_text = "Hello, how are you? I am very happy to meet you."