Log In
New Account
  
Home My Page Project Cloud Code Snippets Project Openings Hermes
Summary Lists News SCM
1 # coding: utf-8
3 ur"""
5 The **trans** module
6 ====================
8 This module translates national characters into similar sounding
9 latin characters (transliteration).
10 At the moment, Greek, Turkish, Russian, Ukrainian, Czech, Polish,
11 Latvian alphabets are supported (it covers 99% of needs).
13 .. contents::
15 Simple usage
16 ------------
17 It's very easy to use
18 ~~~~~~~~~~~~~~~~~~~~~
19   >>> # coding: utf-8
20   >>> import trans
21   >>> u'Hello World!'.encode('trans')
22   u'Hello World!'
23   >>> u'Привет, Мир!'.encode('trans')
24   u'Privet, Mir!'
27 Work only with unicode strings
28 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
29   >>> 'Hello World!'.encode('trans')
30   Traceback (most recent call last):
31       ...
32   TypeError: trans codec support only unicode string, <type 'str'> given.
34 This is readability
35 ~~~~~~~~~~~~~~~~~~~
36   >>> s = u'''\
37   ...    -- Раскудрить твою через коромысло в бога душу мать
38   ...             триста тысяч раз едрену вошь тебе в крыло
39   ...             и кактус в глотку! -- взревел разъяренный Никодим.
40   ...    -- Аминь, -- робко добавил из склепа папа Пий.
41   ...                 (c) Г. Л. Олди, "Сказки дедушки вампира".'''
42   >>> 
43   >>> print s.encode('trans')
44      -- Raskudrit tvoyu cherez koromyslo v boga dushu mat
45               trista tysyach raz edrenu vosh tebe v krylo
46               i kaktus v glotku! -- vzrevel razyarennyy Nikodim.
47      -- Amin, -- robko dobavil iz sklepa papa Piy.
48                   (c) G. L. Oldi, "Skazki dedushki vampira".
50 Table "**id**"
51 ~~~~~~~~~~~~~~
52 Use the table "id", leaving only the Latin characters, digits and underscores:
54   >>> print u'1 2 3 4 5 \n6 7 8 9 0'.encode('trans')
55   1 2 3 4 5 
56   6 7 8 9 0
57   >>> print u'1 2 3 4 5 \n6 7 8 9 0'.encode('trans/id')
58   1_2_3_4_5__6_7_8_9_0
59   >>> s.encode('trans/id')[-42:-1]
60   u'_c__G__L__Oldi___Skazki_dedushki_vampira_'
63 Define user tables
64 ------------------
65 Simple variant
66 ~~~~~~~~~~~~~~
67   >>> u'1 2 3 4 5 6 7 8 9 0'.encode('trans/my')
68   Traceback (most recent call last):
69       ...
70   ValueError: Table "my" not found in tables!
71   >>> trans.tables['my'] = {u'1': u'A', u'2': u'B'}; 
72   >>> u'1 2 3 4 5 6 7 8 9 0'.encode('trans/my')
73   u'A_B________________'
74   >>> 
76 A little harder
77 ~~~~~~~~~~~~~~~
78 Table can consist of two parts - the map of diphthongs and map of characters.
79 First are processed diphthongs, by simple replacement on the substring.
80 Then according to the map of characters, replacing each character of string
81 by it's mapping. If character is absent in characters map, checked key None,
82 if not, then is used the default character u'_'.
84   >>> diphthongs = {u'11': u'AA', u'22': u'BB'}
85   >>> characters = {u'a': u'z', u'b': u'y', u'c': u'x',
86   ...               u'A': u'A', u'B': u'B', None: u'-'}
87   >>> trans.tables['test'] = (diphthongs, characters)
88   >>> u'11abc22cbaCC'.encode('trans/test')
89   u'AAzyxBBxyz--'
91 **The characters created by processing of diphthongs are also processed
92 by the map of the symbols:**
94   >>> diphthongs = {u'11': u'AA', u'22': u'BB'}
95   >>> characters = {u'a': u'z', u'b': u'y', u'c': u'x', None: u'-'}
96   >>> trans.tables['test'] = (diphthongs, characters)
97   >>> u'11abc22cbaCC'.encode('trans/test')
98   u'--zyx--xyz--'
100 Without the diphthongs
101 ~~~~~~~~~~~~~~~~~~~~~~
102 These two tables are equivalent:
104   >>> characters = {u'a': u'z', u'b': u'y', u'c': u'x', None: u'-'}
105   >>> trans.tables['t1'] = characters
106   >>> trans.tables['t2'] = ({}, characters)
107   >>> u'11abc22cbaCC'.encode('trans/t1') == u'11abc22cbaCC'.encode('trans/t2')
108   True
111 Finally
112 -------
113 + *Special thanks to Yuri Yurevich aka j2a for the kick in the right direction.*
114     - http://www.python.su/forum/viewtopic.php?pid=28965
115     - http://code.djangoproject.com/browser/django/trunk/django/contrib/admin/media/js/urlify.js
116 + *I please forgiveness for my bad English. I promise to be corrected.*
118 """
120 __version__ = '1.1a7'
121 __author__ = 'Zelenyak Aleksandr aka ZZZ <zzz.sochi@gmail.com>'
123 latin = {
124     u'à': u'a',  u'á': u'a',  u'â': u'a', u'ã': u'a', u'ä': u'a', u'å': u'a',
125     u'æ': u'ae', u'ç': u'c',  u'è': u'e', u'é': u'e', u'ê': u'e', u'ë': u'e',
126     u'ì': u'i',  u'í': u'i',  u'î': u'i', u'ï': u'i', u'ð': u'd', u'ñ': u'n',
127     u'ò': u'o',  u'ó': u'o',  u'ô': u'o', u'õ': u'o', u'ö': u'o', u'ő': u'o',
128     u'ø': u'o',  u'ù': u'u',  u'ú': u'u', u'û': u'u', u'ü': u'u', u'ű': u'u',
129     u'ý': u'y',  u'þ': u'th', u'ÿ': u'y',
131     u'À': u'A',  u'Á': u'A',  u'Â': u'A', u'Ã': u'A', u'Ä': u'A', u'Å': u'A',
132     u'Æ': u'AE', u'Ç': u'C',  u'È': u'E', u'É': u'E', u'Ê': u'E', u'Ë': u'E',
133     u'Ì': u'I',  u'Í': u'I',  u'Î': u'I', u'Ï': u'I', u'Ð': u'D', u'Ñ': u'N',
134     u'Ò': u'O',  u'Ó': u'O',  u'Ô': u'O', u'Õ': u'O', u'Ö': u'O', u'Ő': u'O',
135     u'Ø': u'O',  u'Ù': u'U',  u'Ú': u'U', u'Û': u'U', u'Ü': u'U', u'Ű': u'U',
136     u'Ý': u'Y',  u'Þ': u'TH', u'ß': u'ss'
139 greek = {
140     u'α': u'a', u'β': u'b', u'γ': u'g', u'δ': u'd', u'ε': u'e',  u'ζ': u'z',
141     u'η': u'h', u'θ': u'8', u'ι': u'i', u'κ': u'k', u'λ': u'l',  u'μ': u'm',
142     u'ν': u'n', u'ξ': u'3', u'ο': u'o', u'π': u'p', u'ρ': u'r',  u'σ': u's',
143     u'τ': u't', u'υ': u'y', u'φ': u'f', u'χ': u'x', u'ψ': u'ps', u'ω': u'w',
144     u'ά': u'a', u'έ': u'e', u'ί': u'i', u'ό': u'o', u'ύ': u'y',  u'ή': u'h',
145     u'ώ': u'w', u'ς': u's', u'ϊ': u'i', u'ΰ': u'y', u'ϋ': u'y',  u'ΐ': u'i',
147     u'Α': u'A', u'Β': u'B', u'Γ': u'G', u'Δ': u'D', u'Ε': u'E',  u'Ζ': u'Z',
148     u'Η': u'H', u'Θ': u'8', u'Ι': u'I', u'Κ': u'K', u'Λ': u'L',  u'Μ': u'M',
149     u'Ν': u'N', u'Ξ': u'3', u'Ο': u'O', u'Π': u'P', u'Ρ': u'R',  u'Σ': u'S',
150     u'Τ': u'T', u'Υ': u'Y', u'Φ': u'F', u'Χ': u'X', u'Ψ': u'PS', u'Ω': u'W',
151     u'Ά': u'A', u'Έ': u'E', u'Ί': u'I', u'Ό': u'O', u'Ύ': u'Y',  u'Ή': u'H',
152     u'Ώ': u'W', u'Ϊ': u'I', u'Ϋ': u'Y'
155 turkish = {
156     u'ş': u's', u'Ş': u'S', u'ı': u'i', u'İ': u'I', u'ç': u'c', u'Ç': u'C',
157     u'ü': u'u', u'Ü': u'U', u'ö': u'o', u'Ö': u'O', u'ğ': u'g', u'Ğ': u'G'
160 russian = (
161     {u'юй': u'yuy', u'ей': u'yay',
162      u'Юй': u'Yuy', u'Ей': u'Yay'},
163     {
164     u'а': u'a',  u'б': u'b',  u'в': u'v',  u'г': u'g', u'д': u'd', u'е': u'e',
165     u'ё': u'yo', u'ж': u'zh', u'з': u'z',  u'и': u'i', u'й': u'y', u'к': u'k',
166     u'л': u'l',  u'м': u'm',  u'н': u'n',  u'о': u'o', u'п': u'p', u'р': u'r',
167     u'с': u's',  u'т': u't',  u'у': u'u',  u'ф': u'f', u'х': u'h', u'ц': u'c',
168     u'ч': u'ch', u'ш': u'sh', u'щ': u'sh', u'ъ': u'',  u'ы': u'y', u'ь': u'',
169     u'э': u'e',  u'ю': u'yu', u'я': u'ya',
171     u'А': u'A',  u'Б': u'B',  u'В': u'V',  u'Г': u'G', u'Д': u'D', u'Е': u'E',
172     u'Ё': u'Yo', u'Ж': u'Zh', u'З': u'Z',  u'И': u'I', u'Й': u'Y', u'К': u'K',
173     u'Л': u'L',  u'М': u'M',  u'Н': u'N',  u'О': u'O', u'П': u'P', u'Р': u'R',
174     u'С': u'S',  u'Т': u'T',  u'У': u'U',  u'Ф': u'F', u'Х': u'H', u'Ц': u'C',
175     u'Ч': u'Ch', u'Ш': u'Sh', u'Щ': u'Sh', u'Ъ': u'',  u'Ы': u'Y', u'Ь': u'',
176     u'Э': u'E',  u'Ю': u'Yu', u'Я': u'Ya'
177 })
179 ukrainian = (russian[0].copy(), {
180     u'Є': u'Ye', u'І': u'I', u'Ї': u'Yi', u'Ґ': u'G',
181     u'є': u'ye', u'і': u'i', u'ї': u'yi', u'ґ': u'g'
182 })
183 ukrainian[1].update(russian[1])
185 czech = {
186     u'č': u'c', u'ď': u'd', u'ě': u'e', u'ň': u'n', u'ř': u'r', u'š': u's',
187     u'ť': u't', u'ů': u'u', u'ž': u'z',
188     u'Č': u'C', u'Ď': u'D', u'Ě': u'E', u'Ň': u'N', u'Ř': u'R', u'Š': u'S',
189     u'Ť': u'T', u'Ů': u'U', u'Ž': u'Z'
192 polish = {
193     u'ą': u'a', u'ć': u'c', u'ę': u'e', u'ł': u'l', u'ń': u'n', u'ó': u'o',
194     u'ś': u's', u'ź': u'z', u'ż': u'z',
195     u'Ą': u'A', u'Ć': u'C', u'Ę': u'e', u'Ł': u'L', u'Ń': u'N', u'Ó': u'o',
196     u'Ś': u'S', u'Ź': u'Z', u'Ż': u'Z'
199 latvian = {
200     u'ā': u'a', u'č': u'c', u'ē': u'e', u'ģ': u'g', u'ī': u'i', u'ķ': u'k',
201     u'ļ': u'l', u'ņ': u'n', u'š': u's', u'ū': u'u', u'ž': u'z',
202     u'Ā': u'A', u'Č': u'C', u'Ē': u'E', u'Ģ': u'G', u'Ī': u'i', u'Ķ': u'k',
203     u'Ļ': u'L', u'Ņ': u'N', u'Š': u'S', u'Ū': u'u', u'Ž': u'Z'
208 ascii_str = u'''_0123456789
209 abcdefghijklmnopqrstuvwxyz
210 ABCDEFGHIJKLMNOPQRSTUVWXYZ
211 !"#$%&'()*+,_-./:;<=>?@[\\]^`{|}~ \t\n\r\x0b\x0c'''
213 ascii = ({}, dict(zip(ascii_str, ascii_str)))
214 for t in [latin, greek, turkish, russian, ukrainian, czech, polish, latvian]:
215     if isinstance(t, dict):
216         t = ({}, t)
217     ascii[0].update(t[0])
218     ascii[1].update(t[1])
219 ascii[1][None] = u'_'
220 del t
223 id = (ascii[0].copy(), ascii[1].copy())
224 for c in '''!"#$%&'()*+,_-./:;<=>?@[\\]^`{|}~ \t\n\r\x0b\x0c''':
225     del id[1][c]
228 def trans(input, table=ascii):
229     '''Translate unicode string, using 'table'.
230        Table may be tuple (diphthongs, other) or dict (other).'''
231     if not isinstance(input, unicode):
232         raise TypeError, 'trans codec support only unicode string, %r given.' \
233                                                         % type(input)
234     if isinstance(table, dict):
235         table = ({}, table)
237     first = input
238     for diphthong, value in table[0].items():
239         first = first.replace(diphthong, value)
241     second = u''
242     for char in first:
243         second += table[1].get(char, table[1].get(None, u'_'))
245     return second, len(second)
247 tables = {'ascii': ascii, 'text': ascii, 'id': id}
249 import codecs
251 def encode(input, errors='strict', table_name='ascii'):
252     try:
253         table = tables[table_name]
254     except KeyError:
255         raise ValueError, 'Table "%s" not found in tables!' % table_name
256     else:
257         return trans(input, table)
259 def no_decode(input, errors='strict'):
260     raise TypeError("trans codec does not support decode.")
262 def trans_codec(enc):
263     if enc == 'trans':
264         return codecs.CodecInfo(encode, no_decode)
265 #    else:
266     try:
267         enc_name, table_name = enc.split('/', 1)
268     except ValueError:
269         return None
270     if enc_name != 'trans':
271         return None
272     if table_name not in tables:
273         raise ValueError, 'Table "%s" not found in tables!' % table_name
275     return codecs.CodecInfo(lambda i, e='strict': encode(i, e, table_name),
276                             no_decode)
278 codecs.register(trans_codec)

Terms of Use    Privacy Policy    Contribution Guidelines    Feedback

Powered By GForge Collaborative Development Environment