Rev 296 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed
| Rev | Author | Line No. | Line |
|---|---|---|---|
| 292 | PointedEar | 1 | #!/usr/bin/env python3 |
| 2 | |||
| 291 | PointedEar | 3 | ''' |
| 4 | Created on 2014-10-20 |
||
| 5 | |||
| 6 | @author: Thomas 'PointedEars' Lahn <mail@PointedEars.de> |
||
| 7 | ''' |
||
| 8 | from sys import argv, stderr |
||
| 293 | PointedEar | 9 | from re import findall, DOTALL, match, sub, compile, \ |
| 10 | escape, search |
||
| 11 | from os.path import basename |
||
| 291 | PointedEar | 12 | from functools import cmp_to_key |
| 293 | PointedEar | 13 | from Dictionary import Dictionary, dmsg, \ |
| 14 | sort_dict_alnum_english_key |
||
| 291 | PointedEar | 15 | |
| 16 | dictionary = {} |
||
| 17 | |||
| 18 | prepositions = { |
||
| 19 | "fi'": 'on', |
||
| 20 | "na'": 'at|to', |
||
| 21 | "t'": 'of' |
||
| 22 | } |
||
| 23 | |||
| 292 | PointedEar | 24 | def cli_help(): |
| 25 | print('Usage: {0} TEXT...'.format(basename(argv[0]))) |
||
| 26 | |||
| 296 | PointedEar | 27 | def get_sort_dict_alnum_vulcan_key (): |
| 291 | PointedEar | 28 | letters = list(map(str.lower, [ |
| 29 | " ", 'S', 'T', 'P', 'K', 'R', 'L', 'A', 'Sh', 'O', 'U', 'D', |
||
| 30 | 'V', 'Kh', 'E', 'H', 'G', 'Ch', 'I', 'N', 'Zh', 'M', 'Y', 'F', 'Z', |
||
| 31 | 'Th', 'W', 'B', "'", '-'])) |
||
| 32 | letter_values = dict(map(lambda x: (x[1], x[0]), enumerate(letters))) |
||
| 33 | letters_re = compile(r'(?:{0})'.format('|'.join(sorted(letters, key=lambda char:-len(char))))) |
||
| 34 | |||
| 35 | def sort_dict_alnum_vulcan (a, b): |
||
| 36 | # split into Vulcan letters |
||
| 37 | a = findall(letters_re, sort_dict_alnum_english_key(a)) |
||
| 38 | b = findall(letters_re, sort_dict_alnum_english_key(b)) |
||
| 39 | |||
| 40 | if len(a) < len(b): |
||
| 41 | for index, char in enumerate(a): |
||
| 42 | diff = letter_values[char] - letter_values[b[index]] |
||
| 43 | if diff != 0: |
||
| 44 | return diff |
||
| 45 | return -1 |
||
| 46 | |||
| 47 | # len(b) <= len(a) |
||
| 48 | for index, char in enumerate(b): |
||
| 49 | diff = letter_values[a[index]] - letter_values[char] |
||
| 50 | if diff != 0: |
||
| 51 | return diff |
||
| 52 | |||
| 53 | return 1 if len(b) < len(a) else 0 |
||
| 54 | |||
| 55 | return cmp_to_key(sort_dict_alnum_vulcan) |
||
| 56 | |||
| 296 | PointedEar | 57 | class VulcanDictionary (Dictionary): |
| 297 | PointedEar | 58 | """ |
| 59 | |||
| 60 | """ |
||
| 293 | PointedEar | 61 | def translate (self, phrase, search_prefix=True, search_plural=True): |
| 297 | PointedEar | 62 | """ |
| 63 | |||
| 64 | :param phrase: |
||
| 65 | :type phrase: |
||
| 66 | :param search_prefix: |
||
| 67 | :type search_prefix: |
||
| 68 | :param search_plural: |
||
| 69 | :type search_plural: |
||
| 70 | """ |
||
| 296 | PointedEar | 71 | translation = super().translate(phrase) |
| 293 | PointedEar | 72 | if translation is not None: |
| 73 | return translation |
||
| 74 | else: |
||
| 297 | PointedEar | 75 | expr_translation = self.translate_expression(phrase) |
| 296 | PointedEar | 76 | if expr_translation is not None: |
| 77 | return expr_translation |
||
| 78 | |||
| 293 | PointedEar | 79 | if search_prefix: |
| 80 | # find prefix |
||
| 81 | for preposition in prepositions: |
||
| 82 | prefix = match(escape(preposition), phrase) |
||
| 83 | if prefix is not None: |
||
| 84 | prefix_translation = self.translate(prefix.group(0)) |
||
| 85 | if prefix_translation is not None: |
||
| 86 | tail = sub(preposition, '', phrase) |
||
| 87 | tail_translation = self.translate(tail, search_prefix=False) |
||
| 88 | if tail_translation is not None: |
||
| 89 | return [prefix_translation, tail_translation] |
||
| 90 | elif search_plural: |
||
| 91 | # find plural |
||
| 92 | suffix = search(r'lar$', phrase) |
||
| 93 | if suffix is not None: |
||
| 94 | head = sub(r'lar$', '', phrase) |
||
| 95 | head_translation = self.translate(head, search_prefix=False, search_plural=False) |
||
| 96 | if head_translation is not None: |
||
| 97 | head_translation = dict(head_translation) |
||
| 98 | head_translation['en'] += ' (pl.)' |
||
| 99 | return head_translation |
||
| 291 | PointedEar | 100 | |
| 293 | PointedEar | 101 | return None |
| 102 | |||
| 297 | PointedEar | 103 | def clean_entry(self, phrase): |
| 104 | """ |
||
| 105 | Replace GV Media Script parens with FSE parens |
||
| 106 | :param phrase: |
||
| 107 | :type phrase: |
||
| 108 | """ |
||
| 109 | return sub( |
||
| 110 | r'(\([^)]*\))|\|([^|)]+)\|', |
||
| 111 | lambda m: '({0})'.format(m.group(2)) if m.group(2) else m.group(1), |
||
| 112 | phrase) |
||
| 113 | |||
| 292 | PointedEar | 114 | if __name__ == '__main__': |
| 115 | if len(argv) < 2: |
||
| 116 | print('Nothing to translate.', end='\n\n', file=stderr) |
||
| 117 | cli_help() |
||
| 118 | exit(1) |
||
| 291 | PointedEar | 119 | |
| 296 | PointedEar | 120 | text = ' '.join(argv[1:]) |
| 292 | PointedEar | 121 | |
| 293 | PointedEar | 122 | dictionary = VulcanDictionary(dictionary) |
| 294 | PointedEar | 123 | dictionary.load('vuh-gol-en.dict.zdb.txt', 'vuh') |
| 293 | PointedEar | 124 | dictionary.clean() |
| 291 | PointedEar | 125 | |
| 126 | # try: |
||
| 127 | # for phrase, data in OrderedDict(sorted( |
||
| 128 | # dictionary.items(), |
||
| 129 | # key=get_sort_dict_alnum_vulcan_key() |
||
| 130 | # )).items(): |
||
| 131 | # print(phrase, "=", data) |
||
| 132 | # except BrokenPipeError: |
||
| 133 | # pass |
||
| 134 | |||
| 293 | PointedEar | 135 | dmsg("text:", text, min_level=2) |
| 291 | PointedEar | 136 | sentences = findall(r'(?!\s+)(?:.+?\.{1,3}|.+$)', text, DOTALL) |
| 292 | PointedEar | 137 | dmsg("sentences:", sentences, min_level=2) |
| 291 | PointedEar | 138 | for sentence in sentences: |
| 292 | PointedEar | 139 | dmsg("sentence:", sentence, min_level=2) |
| 291 | PointedEar | 140 | |
| 293 | PointedEar | 141 | clauses = findall(r'(?!\s+)(?:.+?(?:\s+-\s*|\s*[–—]\s*|\.{1,3}|.+$))', sentence, DOTALL) |
| 292 | PointedEar | 142 | dmsg("clauses:", clauses, min_level=2) |
| 143 | for clause in clauses: |
||
| 144 | dmsg("clause:", clause, min_level=2) |
||
| 291 | PointedEar | 145 | |
| 292 | PointedEar | 146 | words = findall(r'[^\s.]+', clause) |
| 147 | dmsg("words:", words, min_level=2) |
||
| 291 | PointedEar | 148 | |
| 292 | PointedEar | 149 | offset = 0 |
| 150 | while offset < len(words): |
||
| 151 | translation = None |
||
| 291 | PointedEar | 152 | |
| 293 | PointedEar | 153 | for i in range(len(words), offset, -1): |
| 154 | dmsg("words[{0}:{1}] = {2}".format(offset, i, words[offset:i]), min_level=2) |
||
| 292 | PointedEar | 155 | phrase = ' '.join(words[offset:i]) |
| 291 | PointedEar | 156 | |
| 292 | PointedEar | 157 | dmsg("phrase:", phrase, min_level=2) |
| 158 | |||
| 293 | PointedEar | 159 | translation = dictionary.translate(phrase) |
| 292 | PointedEar | 160 | |
| 161 | if translation is not None: |
||
| 162 | dmsg("phrase-translation:", translation, min_level=2) |
||
| 163 | dmsg("words[{0}:{1}] = [\"{2}\"]".format(offset, i, translation), min_level=2) |
||
| 164 | words[offset:i] = [translation] |
||
| 293 | PointedEar | 165 | offset += i - offset |
| 292 | PointedEar | 166 | break |
| 167 | |||
| 168 | if translation is None: |
||
| 169 | dmsg("phrase-translation:", translation, min_level=2) |
||
| 170 | offset += 1 |
||
| 171 | |||
| 172 | dmsg("words-translation:", words, min_level=2) |
||
| 296 | PointedEar | 173 | dmsg("words-translation-reduced:", |
| 174 | list(map( |
||
| 175 | lambda word: |
||
| 176 | word['en'] |
||
| 177 | if (hasattr(word, "get") and word.get('en', None) is not None) |
||
| 178 | else word, |
||
| 179 | words)), |
||
| 180 | min_level=2) |
||
| 297 | PointedEar | 181 | # for key, value in dictionary._expressions.items(): |
| 182 | # dmsg(key, value, min_level=3) |