Subversion Repositories LCARS

Rev

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)