1+ # -*- coding: utf-8 -*-
2+
3+ # This work is licensed under the GNU Public License (GPL).
4+ # To view a copy of this license, visit http://www.gnu.org/copyleft/gpl.html
5+
6+ # Written by Abd Allah Diab (mpcabd)
7+ # Email: mpcabd ^at^ gmail ^dot^ com
8+ # Website: http://mpcabd.igeex.biz
9+
10+ # Ported and tweaked from Java to Python, from Better Arabic Reshaper [https://github.com/agawish/Better-Arabic-Reshaper/]
11+
12+ import re
13+
14+ DEFINED_CHARACTERS_ORGINAL_ALF_UPPER_MDD = u'\u0622 '
15+ DEFINED_CHARACTERS_ORGINAL_ALF_UPPER_HAMAZA = u'\u0623 '
16+ DEFINED_CHARACTERS_ORGINAL_ALF_LOWER_HAMAZA = u'\u0625 '
17+ DEFINED_CHARACTERS_ORGINAL_ALF = u'\u0627 '
18+ DEFINED_CHARACTERS_ORGINAL_LAM = u'\u0644 '
19+
20+ LAM_ALEF_GLYPHS = [
21+ [u'\u3BA6 ' , u'\uFEF6 ' , u'\uFEF5 ' ],
22+ [u'\u3BA7 ' , u'\uFEF8 ' , u'\uFEF7 ' ],
23+ [u'\u0627 ' , u'\uFEFC ' , u'\uFEFB ' ],
24+ [u'\u0625 ' , u'\uFEFA ' , u'\uFEF9 ' ]
25+ ]
26+
27+ HARAKAT = [
28+ u'\u0600 ' , u'\u0601 ' , u'\u0602 ' , u'\u0603 ' , u'\u0606 ' , u'\u0607 ' , u'\u0608 ' , u'\u0609 ' ,
29+ u'\u060A ' , u'\u060B ' , u'\u060D ' , u'\u060E ' , u'\u0610 ' , u'\u0611 ' , u'\u0612 ' , u'\u0613 ' ,
30+ u'\u0614 ' , u'\u0615 ' , u'\u0616 ' , u'\u0617 ' , u'\u0618 ' , u'\u0619 ' , u'\u061A ' , u'\u061B ' ,
31+ u'\u061E ' , u'\u061F ' , u'\u0621 ' , u'\u063B ' , u'\u063C ' , u'\u063D ' , u'\u063E ' , u'\u063F ' ,
32+ u'\u0640 ' , u'\u064B ' , u'\u064C ' , u'\u064D ' , u'\u064E ' , u'\u064F ' , u'\u0650 ' , u'\u0651 ' ,
33+ u'\u0652 ' , u'\u0653 ' , u'\u0654 ' , u'\u0655 ' , u'\u0656 ' , u'\u0657 ' , u'\u0658 ' , u'\u0659 ' ,
34+ u'\u065A ' , u'\u065B ' , u'\u065C ' , u'\u065D ' , u'\u065E ' , u'\u0660 ' , u'\u066A ' , u'\u066B ' ,
35+ u'\u066C ' , u'\u066F ' , u'\u0670 ' , u'\u0672 ' , u'\u06D4 ' , u'\u06D5 ' , u'\u06D6 ' , u'\u06D7 ' ,
36+ u'\u06D8 ' , u'\u06D9 ' , u'\u06DA ' , u'\u06DB ' , u'\u06DC ' , u'\u06DF ' , u'\u06E0 ' , u'\u06E1 ' ,
37+ u'\u06E2 ' , u'\u06E3 ' , u'\u06E4 ' , u'\u06E5 ' , u'\u06E6 ' , u'\u06E7 ' , u'\u06E8 ' , u'\u06E9 ' ,
38+ u'\u06EA ' , u'\u06EB ' , u'\u06EC ' , u'\u06ED ' , u'\u06EE ' , u'\u06EF ' , u'\u06D6 ' , u'\u06D7 ' ,
39+ u'\u06D8 ' , u'\u06D9 ' , u'\u06DA ' , u'\u06DB ' , u'\u06DC ' , u'\u06DD ' , u'\u06DE ' , u'\u06DF ' ,
40+ u'\u06F0 ' , u'\u06FD ' , u'\uFE70 ' , u'\uFE71 ' , u'\uFE72 ' , u'\uFE73 ' , u'\uFE74 ' , u'\uFE75 ' ,
41+ u'\uFE76 ' , u'\uFE77 ' , u'\uFE78 ' , u'\uFE79 ' , u'\uFE7A ' , u'\uFE7B ' , u'\uFE7C ' , u'\uFE7D ' ,
42+ u'\uFE7E ' , u'\uFE7F ' , u'\uFC5E ' , u'\uFC5F ' , u'\uFC60 ' , u'\uFC61 ' , u'\uFC62 ' , u'\uFC63 '
43+ ]
44+
45+ ARABIC_GLYPHS = {
46+ u'\u0622 ' : [u'\u0622 ' , u'\uFE81 ' , u'\uFE81 ' , u'\uFE82 ' , u'\uFE82 ' , 2 ],
47+ u'\u0623 ' : [u'\u0623 ' , u'\uFE83 ' , u'\uFE83 ' , u'\uFE84 ' , u'\uFE84 ' , 2 ],
48+ u'\u0624 ' : [u'\u0624 ' , u'\uFE85 ' , u'\uFE85 ' , u'\uFE86 ' , u'\uFE86 ' , 2 ],
49+ u'\u0625 ' : [u'\u0625 ' , u'\uFE87 ' , u'\uFE87 ' , u'\uFE88 ' , u'\uFE88 ' , 2 ],
50+ u'\u0626 ' : [u'\u0626 ' , u'\uFE89 ' , u'\uFE8B ' , u'\uFE8C ' , u'\uFE8A ' , 4 ],
51+ u'\u0627 ' : [u'\u0627 ' , u'\u0627 ' , u'\u0627 ' , u'\uFE8E ' , u'\uFE8E ' , 2 ],
52+ u'\u0628 ' : [u'\u0628 ' , u'\uFE8F ' , u'\uFE91 ' , u'\uFE92 ' , u'\uFE90 ' , 4 ],
53+ u'\u0629 ' : [u'\u0629 ' , u'\uFE93 ' , u'\uFE93 ' , u'\uFE94 ' , u'\uFE94 ' , 2 ],
54+ u'\u062A ' : [u'\u062A ' , u'\uFE95 ' , u'\uFE97 ' , u'\uFE98 ' , u'\uFE96 ' , 4 ],
55+ u'\u062B ' : [u'\u062B ' , u'\uFE99 ' , u'\uFE9B ' , u'\uFE9C ' , u'\uFE9A ' , 4 ],
56+ u'\u062C ' : [u'\u062C ' , u'\uFE9D ' , u'\uFE9F ' , u'\uFEA0 ' , u'\uFE9E ' , 4 ],
57+ u'\u062D ' : [u'\u062D ' , u'\uFEA1 ' , u'\uFEA3 ' , u'\uFEA4 ' , u'\uFEA2 ' , 4 ],
58+ u'\u062E ' : [u'\u062E ' , u'\uFEA5 ' , u'\uFEA7 ' , u'\uFEA8 ' , u'\uFEA6 ' , 4 ],
59+ u'\u062F ' : [u'\u062F ' , u'\uFEA9 ' , u'\uFEA9 ' , u'\uFEAA ' , u'\uFEAA ' , 2 ],
60+ u'\u0630 ' : [u'\u0630 ' , u'\uFEAB ' , u'\uFEAB ' , u'\uFEAC ' , u'\uFEAC ' , 2 ],
61+ u'\u0631 ' : [u'\u0631 ' , u'\uFEAD ' , u'\uFEAD ' , u'\uFEAE ' , u'\uFEAE ' , 2 ],
62+ u'\u0632 ' : [u'\u0632 ' , u'\uFEAF ' , u'\uFEAF ' , u'\uFEB0 ' , u'\uFEB0 ' , 2 ],
63+ u'\u0633 ' : [u'\u0633 ' , u'\uFEB1 ' , u'\uFEB3 ' , u'\uFEB4 ' , u'\uFEB2 ' , 4 ],
64+ u'\u0634 ' : [u'\u0634 ' , u'\uFEB5 ' , u'\uFEB7 ' , u'\uFEB8 ' , u'\uFEB6 ' , 4 ],
65+ u'\u0635 ' : [u'\u0635 ' , u'\uFEB9 ' , u'\uFEBB ' , u'\uFEBC ' , u'\uFEBA ' , 4 ],
66+ u'\u0636 ' : [u'\u0636 ' , u'\uFEBD ' , u'\uFEBF ' , u'\uFEC0 ' , u'\uFEBE ' , 4 ],
67+ u'\u0637 ' : [u'\u0637 ' , u'\uFEC1 ' , u'\uFEC3 ' , u'\uFEC4 ' , u'\uFEC2 ' , 4 ],
68+ u'\u0638 ' : [u'\u0638 ' , u'\uFEC5 ' , u'\uFEC7 ' , u'\uFEC8 ' , u'\uFEC6 ' , 4 ],
69+ u'\u0639 ' : [u'\u0639 ' , u'\uFEC9 ' , u'\uFECB ' , u'\uFECC ' , u'\uFECA ' , 4 ],
70+ u'\u063A ' : [u'\u063A ' , u'\uFECD ' , u'\uFECF ' , u'\uFED0 ' , u'\uFECE ' , 4 ],
71+ u'\u0641 ' : [u'\u0641 ' , u'\uFED1 ' , u'\uFED3 ' , u'\uFED4 ' , u'\uFED2 ' , 4 ],
72+ u'\u0642 ' : [u'\u0642 ' , u'\uFED5 ' , u'\uFED7 ' , u'\uFED8 ' , u'\uFED6 ' , 4 ],
73+ u'\u0643 ' : [u'\u0643 ' , u'\uFED9 ' , u'\uFEDB ' , u'\uFEDC ' , u'\uFEDA ' , 4 ],
74+ u'\u0644 ' : [u'\u0644 ' , u'\uFEDD ' , u'\uFEDF ' , u'\uFEE0 ' , u'\uFEDE ' , 4 ],
75+ u'\u0645 ' : [u'\u0645 ' , u'\uFEE1 ' , u'\uFEE3 ' , u'\uFEE4 ' , u'\uFEE2 ' , 4 ],
76+ u'\u0646 ' : [u'\u0646 ' , u'\uFEE5 ' , u'\uFEE7 ' , u'\uFEE8 ' , u'\uFEE6 ' , 4 ],
77+ u'\u0647 ' : [u'\u0647 ' , u'\uFEE9 ' , u'\uFEEB ' , u'\uFEEC ' , u'\uFEEA ' , 4 ],
78+ u'\u0648 ' : [u'\u0648 ' , u'\uFEED ' , u'\uFEED ' , u'\uFEEE ' , u'\uFEEE ' , 2 ],
79+ u'\u0649 ' : [u'\u0649 ' , u'\uFEEF ' , u'\uFEEF ' , u'\uFEF0 ' , u'\uFEF0 ' , 2 ],
80+ u'\u0671 ' : [u'\u0671 ' , u'\u0671 ' , u'\u0671 ' , u'\uFB51 ' , u'\uFB51 ' , 2 ],
81+ u'\u064A ' : [u'\u064A ' , u'\uFEF1 ' , u'\uFEF3 ' , u'\uFEF4 ' , u'\uFEF2 ' , 4 ],
82+ u'\u066E ' : [u'\u066E ' , u'\uFBE4 ' , u'\uFBE8 ' , u'\uFBE9 ' , u'\uFBE5 ' , 4 ],
83+ u'\u06AA ' : [u'\u06AA ' , u'\uFB8E ' , u'\uFB90 ' , u'\uFB91 ' , u'\uFB8F ' , 4 ],
84+ u'\u06C1 ' : [u'\u06C1 ' , u'\uFBA6 ' , u'\uFBA8 ' , u'\uFBA9 ' , u'\uFBA7 ' , 4 ],
85+ u'\u06E4 ' : [u'\u06E4 ' , u'\u06E4 ' , u'\u06E4 ' , u'\u06E4 ' , u'\uFEEE ' , 2 ]
86+ }
87+
88+ ARABIC_GLYPHS_LIST = [
89+ [u'\u0622 ' , u'\uFE81 ' , u'\uFE81 ' , u'\uFE82 ' , u'\uFE82 ' , 2 ],
90+ [u'\u0623 ' , u'\uFE83 ' , u'\uFE83 ' , u'\uFE84 ' , u'\uFE84 ' , 2 ],
91+ [u'\u0624 ' , u'\uFE85 ' , u'\uFE85 ' , u'\uFE86 ' , u'\uFE86 ' , 2 ],
92+ [u'\u0625 ' , u'\uFE87 ' , u'\uFE87 ' , u'\uFE88 ' , u'\uFE88 ' , 2 ],
93+ [u'\u0626 ' , u'\uFE89 ' , u'\uFE8B ' , u'\uFE8C ' , u'\uFE8A ' , 4 ],
94+ [u'\u0627 ' , u'\u0627 ' , u'\u0627 ' , u'\uFE8E ' , u'\uFE8E ' , 2 ],
95+ [u'\u0628 ' , u'\uFE8F ' , u'\uFE91 ' , u'\uFE92 ' , u'\uFE90 ' , 4 ],
96+ [u'\u0629 ' , u'\uFE93 ' , u'\uFE93 ' , u'\uFE94 ' , u'\uFE94 ' , 2 ],
97+ [u'\u062A ' , u'\uFE95 ' , u'\uFE97 ' , u'\uFE98 ' , u'\uFE96 ' , 4 ],
98+ [u'\u062B ' , u'\uFE99 ' , u'\uFE9B ' , u'\uFE9C ' , u'\uFE9A ' , 4 ],
99+ [u'\u062C ' , u'\uFE9D ' , u'\uFE9F ' , u'\uFEA0 ' , u'\uFE9E ' , 4 ],
100+ [u'\u062D ' , u'\uFEA1 ' , u'\uFEA3 ' , u'\uFEA4 ' , u'\uFEA2 ' , 4 ],
101+ [u'\u062E ' , u'\uFEA5 ' , u'\uFEA7 ' , u'\uFEA8 ' , u'\uFEA6 ' , 4 ],
102+ [u'\u062F ' , u'\uFEA9 ' , u'\uFEA9 ' , u'\uFEAA ' , u'\uFEAA ' , 2 ],
103+ [u'\u0630 ' , u'\uFEAB ' , u'\uFEAB ' , u'\uFEAC ' , u'\uFEAC ' , 2 ],
104+ [u'\u0631 ' , u'\uFEAD ' , u'\uFEAD ' , u'\uFEAE ' , u'\uFEAE ' , 2 ],
105+ [u'\u0632 ' , u'\uFEAF ' , u'\uFEAF ' , u'\uFEB0 ' , u'\uFEB0 ' , 2 ],
106+ [u'\u0633 ' , u'\uFEB1 ' , u'\uFEB3 ' , u'\uFEB4 ' , u'\uFEB2 ' , 4 ],
107+ [u'\u0634 ' , u'\uFEB5 ' , u'\uFEB7 ' , u'\uFEB8 ' , u'\uFEB6 ' , 4 ],
108+ [u'\u0635 ' , u'\uFEB9 ' , u'\uFEBB ' , u'\uFEBC ' , u'\uFEBA ' , 4 ],
109+ [u'\u0636 ' , u'\uFEBD ' , u'\uFEBF ' , u'\uFEC0 ' , u'\uFEBE ' , 4 ],
110+ [u'\u0637 ' , u'\uFEC1 ' , u'\uFEC3 ' , u'\uFEC4 ' , u'\uFEC2 ' , 4 ],
111+ [u'\u0638 ' , u'\uFEC5 ' , u'\uFEC7 ' , u'\uFEC8 ' , u'\uFEC6 ' , 4 ],
112+ [u'\u0639 ' , u'\uFEC9 ' , u'\uFECB ' , u'\uFECC ' , u'\uFECA ' , 4 ],
113+ [u'\u063A ' , u'\uFECD ' , u'\uFECF ' , u'\uFED0 ' , u'\uFECE ' , 4 ],
114+ [u'\u0641 ' , u'\uFED1 ' , u'\uFED3 ' , u'\uFED4 ' , u'\uFED2 ' , 4 ],
115+ [u'\u0642 ' , u'\uFED5 ' , u'\uFED7 ' , u'\uFED8 ' , u'\uFED6 ' , 4 ],
116+ [u'\u0643 ' , u'\uFED9 ' , u'\uFEDB ' , u'\uFEDC ' , u'\uFEDA ' , 4 ],
117+ [u'\u0644 ' , u'\uFEDD ' , u'\uFEDF ' , u'\uFEE0 ' , u'\uFEDE ' , 4 ],
118+ [u'\u0645 ' , u'\uFEE1 ' , u'\uFEE3 ' , u'\uFEE4 ' , u'\uFEE2 ' , 4 ],
119+ [u'\u0646 ' , u'\uFEE5 ' , u'\uFEE7 ' , u'\uFEE8 ' , u'\uFEE6 ' , 4 ],
120+ [u'\u0647 ' , u'\uFEE9 ' , u'\uFEEB ' , u'\uFEEC ' , u'\uFEEA ' , 4 ],
121+ [u'\u0648 ' , u'\uFEED ' , u'\uFEED ' , u'\uFEEE ' , u'\uFEEE ' , 2 ],
122+ [u'\u0649 ' , u'\uFEEF ' , u'\uFEEF ' , u'\uFEF0 ' , u'\uFEF0 ' , 2 ],
123+ [u'\u0671 ' , u'\u0671 ' , u'\u0671 ' , u'\uFB51 ' , u'\uFB51 ' , 2 ],
124+ [u'\u064A ' , u'\uFEF1 ' , u'\uFEF3 ' , u'\uFEF4 ' , u'\uFEF2 ' , 4 ],
125+ [u'\u066E ' , u'\uFBE4 ' , u'\uFBE8 ' , u'\uFBE9 ' , u'\uFBE5 ' , 4 ],
126+ [u'\u06AA ' , u'\uFB8E ' , u'\uFB90 ' , u'\uFB91 ' , u'\uFB8F ' , 4 ],
127+ [u'\u06C1 ' , u'\uFBA6 ' , u'\uFBA8 ' , u'\uFBA9 ' , u'\uFBA7 ' , 4 ],
128+ [u'\u06E4 ' , u'\u06E4 ' , u'\u06E4 ' , u'\u06E4 ' , u'\uFEEE ' , 2 ]
129+ ]
130+
131+ def get_reshaped_glyph (target , location ):
132+ if ARABIC_GLYPHS .has_key (target ):
133+ return ARABIC_GLYPHS [target ][location ]
134+ else :
135+ return target
136+
137+ def get_glyph_type (target ):
138+ if ARABIC_GLYPHS .has_key (target ):
139+ return ARABIC_GLYPHS [target ][5 ]
140+ else :
141+ return 2
142+
143+ def is_haraka (target ):
144+ return target in HARAKAT
145+
146+ def replace_lam_alef (unshaped_word ):
147+ list_word = list (unshaped_word )
148+ letter_before = u''
149+ for i in range (len (unshaped_word )):
150+ if not is_haraka (unshaped_word [i ]) and unshaped_word [i ] != DEFINED_CHARACTERS_ORGINAL_LAM :
151+ letter_before = unshaped_word [i ]
152+
153+ if unshaped_word [i ] == DEFINED_CHARACTERS_ORGINAL_LAM :
154+ candidate_lam = unshaped_word [i ]
155+ lam_position = i
156+ haraka_position = i + 1
157+
158+ while haraka_position < len (unshaped_word ) and is_haraka (unshaped_word [haraka_position ]):
159+ haraka_position += 1
160+
161+ if haraka_position < len (unshaped_word ):
162+ if lam_position > 0 and get_glyph_type (letter_before ) > 2 :
163+ lam_alef = get_lam_alef (list_word [haraka_position ], candidate_lam , False )
164+ else :
165+ lam_alef = get_lam_alef (list_word [haraka_position ], candidate_lam , True )
166+ if lam_alef != '' :
167+ list_word [lam_position ] = lam_alef
168+ list_word [haraka_position ] = u' '
169+
170+ return u'' .join (list_word ).replace (u' ' , u'' )
171+
172+ def get_lam_alef (candidate_alef , candidate_lam , is_end_of_word ):
173+ shift_rate = 1
174+ reshaped_lam_alef = u''
175+ if is_end_of_word :
176+ shift_rate += 1
177+
178+ if DEFINED_CHARACTERS_ORGINAL_LAM == candidate_lam :
179+ if DEFINED_CHARACTERS_ORGINAL_ALF_UPPER_MDD == candidate_alef :
180+ reshaped_lam_alef = LAM_ALEF_GLYPHS [0 ][shift_rate ]
181+
182+ if DEFINED_CHARACTERS_ORGINAL_ALF_UPPER_HAMAZA == candidate_alef :
183+ reshaped_lam_alef = LAM_ALEF_GLYPHS [1 ][shift_rate ]
184+
185+ if DEFINED_CHARACTERS_ORGINAL_ALF == candidate_alef :
186+ reshaped_lam_alef = LAM_ALEF_GLYPHS [2 ][shift_rate ]
187+
188+ if DEFINED_CHARACTERS_ORGINAL_ALF_LOWER_HAMAZA == candidate_alef :
189+ reshaped_lam_alef = LAM_ALEF_GLYPHS [3 ][shift_rate ]
190+
191+ return reshaped_lam_alef
192+
193+ class DecomposedWord (object ):
194+ def __init__ (self , word ):
195+ self .stripped_harakat = []
196+ self .harakat_positions = []
197+ self .stripped_regular_letters = []
198+ self .letters_position = []
199+
200+ for i in range (len (word )):
201+ c = word [i ]
202+ if is_haraka (c ):
203+ self .harakat_positions .append (i )
204+ self .stripped_harakat .append (c )
205+ else :
206+ self .letters_position .append (i )
207+ self .stripped_regular_letters .append (c )
208+
209+ def reconstruct_word (self , reshaped_word ):
210+ l = list (u'\0 ' * (len (self .stripped_harakat ) + len (reshaped_word )))
211+ for i in range (len (self .letters_position )):
212+ l [self .letters_position [i ]] = reshaped_word [i ]
213+ for i in range (len (self .harakat_positions )):
214+ l [self .harakat_positions [i ]] = self .stripped_harakat [i ]
215+ return u'' .join (l )
216+
217+ def get_reshaped_word (unshaped_word ):
218+ unshaped_word = replace_lam_alef (unshaped_word )
219+ decomposed_word = DecomposedWord (unshaped_word )
220+ result = u''
221+ if decomposed_word .stripped_regular_letters :
222+ result = reshape_it (u'' .join (decomposed_word .stripped_regular_letters ))
223+ return decomposed_word .reconstruct_word (result )
224+
225+ def reshape_it (unshaped_word ):
226+ reshaped_word = [get_reshaped_glyph (unshaped_word [0 ], 2 )]
227+ for i in range (1 , len (unshaped_word ) - 1 ):
228+ if get_glyph_type (unshaped_word [i - 1 ]) == 2 :
229+ reshaped_word .append (get_reshaped_glyph (unshaped_word [i ], 2 ))
230+ else :
231+ reshaped_word .append (get_reshaped_glyph (unshaped_word [i ], 3 ))
232+
233+ if len (unshaped_word ) >= 2 :
234+ if get_glyph_type (unshaped_word [- 2 ]) == 2 :
235+ reshaped_word .append (get_reshaped_glyph (unshaped_word [- 1 ], 1 ))
236+ else :
237+ reshaped_word .append (get_reshaped_glyph (unshaped_word [- 1 ], 4 ))
238+
239+ return u'' .join (reshaped_word )
240+
241+
242+ def is_arabic_character (target ):
243+ return ARABIC_GLYPHS .has_key (target ) or target in HARAKAT
244+
245+ def get_words (sentence ):
246+ if sentence :
247+ return re .split ('\\ s' , sentence )
248+ return []
249+
250+ def has_arabic_letters (word ):
251+ for c in word :
252+ if is_arabic_character (c ):
253+ return True
254+ return False
255+
256+ def is_arabic_word (word ):
257+ for c in word :
258+ if not is_arabic_character (c ):
259+ return False
260+ return True
261+
262+ def get_words_from_mixed_word (word ):
263+ temp_word = u''
264+ words = []
265+ for c in word :
266+ if is_arabic_character (c ):
267+ if temp_word and not is_arabic_word (temp_word ):
268+ words .append (temp_word )
269+ temp_word = c
270+ else :
271+ temp_word += c
272+ else :
273+ if temp_word and is_arabic_word (temp_word ):
274+ words .append (temp_word )
275+ temp_word = c
276+ else :
277+ temp_word += c
278+ if temp_word :
279+ words .append (temp_word )
280+ return words
281+
282+ def reshape (text ):
283+ if text :
284+ lines = re .split ('\\ r?\\ n' , text )
285+ for i in range (len (lines )):
286+ lines [i ] = reshape_sentence (lines [i ])
287+ return u'\n ' .join (lines )
288+ return u''
289+
290+ def reshape_sentence (sentence ):
291+ words = get_words (sentence )
292+ for i in range (len (words )):
293+ word = words [i ]
294+ if has_arabic_letters (word ):
295+ if is_arabic_word (word ):
296+ words [i ] = get_reshaped_word (word )
297+ else :
298+ mixed_words = get_words_from_mixed_word (word )
299+ for j in range (len (mixed_words )):
300+ mixed_words [j ] = get_reshaped_word (mixed_words [j ])
301+ words [i ] = u'' .join (mixed_words )
302+ return u' ' .join (words )
0 commit comments