~cm-t/ubuntu-fr-tour/ubuntu-fr-tour

« back to all changes in this revision

Viewing changes to 12.04/translate-html/translate_html/StringMerger.py

  • Committer: cm-t arudy
  • Date: 2013-10-22 01:24:09 UTC
  • Revision ID: arudy@ubuntu-fr.org-20131022012409-3dmo4i9u4ufohe5f
First Fr push to 13.10
Fixed many icons (updated to new version or fixed graphic)
Added Cloud indicator
Added Keyboard uindicator
Fixed many layout to fit Fr string

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
#! /usr/bin/env python
2
 
# -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*-
3
 
### BEGIN LICENSE
4
 
# Copyright (C) 2011 David Planella <david.planella@ubuntu.com>
5
 
# This program is free software: you can redistribute it and/or modify it
6
 
# under the terms of the GNU General Public License version 3, as published
7
 
# by the Free Software Foundation.
8
 
#
9
 
# This program is distributed in the hope that it will be useful, but
10
 
# WITHOUT ANY WARRANTY; without even the implied warranties of
11
 
# MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
12
 
# PURPOSE.  See the GNU General Public License for more details.
13
 
#
14
 
# You should have received a copy of the GNU General Public License along
15
 
# with this program.  If not, see <http://www.gnu.org/licenses/>.
16
 
### END LICENSE
17
 
#
18
 
# This module implements a class to merge translations contained in Gettext
19
 
# PO files into different types of files. Right now only merging into HTML
20
 
# has been implemented.
21
 
 
22
 
import mimetypes
23
 
import codecs
24
 
import sys
25
 
import os
26
 
from translate_html import translate_htmlconfig
27
 
import re
28
 
 
29
 
try:
30
 
    import polib
31
 
except ImportError:
32
 
    sys.stderr.write('You need the Python Polib library to run this ' +
33
 
                     'script.\nYou can install it by running:\n\t' +
34
 
                     '$ sudo apt-get install python-polib')
35
 
 
36
 
# MIME type definitions (type, encoding)
37
 
HTML_FILE = ('text/html', None)
38
 
JS_FILE = ('application/javascript', None)
39
 
 
40
 
PO_FOLDER = translate_htmlconfig.PO_FOLDER
41
 
POTFILES = translate_htmlconfig.POTFILES
42
 
 
43
 
 
44
 
class StringMerger(object):
45
 
    """This class implements an object to load translations from Gettext
46
 
    PO files and merge them into different types of files.
47
 
 
48
 
    """
49
 
    def __init__(self, test_mode):
50
 
        self.translations = self._load_translations()
51
 
        self.files = self._load_files()
52
 
        self.test_mode = test_mode
53
 
 
54
 
    def _load_files(self):
55
 
        """Gets the list of files to merge translations for"""
56
 
        with open(translate_htmlconfig.get_source_file(PO_FOLDER,
57
 
                                                       POTFILES)) as fp:
58
 
            file_list = []
59
 
            for line in fp.readlines():
60
 
                if not line.startswith('#'):
61
 
                    line = os.path.join(
62
 
                        translate_htmlconfig.get_sources_path(), line)
63
 
                    file_list.append(line.strip())
64
 
            return file_list
65
 
 
66
 
    def _load_translations(self):
67
 
        """Loads the PO files to read translations from"""
68
 
        po_dir = os.path.join(translate_htmlconfig.get_sources_path(),
69
 
                              PO_FOLDER)
70
 
        translations = []
71
 
        for po_file in os.listdir(po_dir):
72
 
            fname, fext = os.path.splitext(po_file)
73
 
            if fext == '.po':
74
 
                translations.append(fname)
75
 
        return translations
76
 
 
77
 
    def merge(self):
78
 
        """Merge translations into the final translated files"""
79
 
        for translation in self.translations:
80
 
            for file_to_merge in self.files:
81
 
                merger = getMerger(self.test_mode, translation, file_to_merge)
82
 
                merger.merge()
83
 
 
84
 
 
85
 
class StringMergerHtml(object):
86
 
    """HTML string merger. Reads the given translations from PO files and
87
 
    merges them into an HTML file
88
 
 
89
 
    """
90
 
    def __init__(self, test_mode, langcode, htmlfile):
91
 
        self.langcode = langcode
92
 
        self.ietf_langcode = langcode_glib_to_ietf(langcode)
93
 
        self.pofile = os.path.join(translate_htmlconfig.get_sources_path(),
94
 
                              PO_FOLDER, self.langcode + '.po')
95
 
        self.htmlfile = htmlfile
96
 
        self.test_mode = test_mode
97
 
 
98
 
    def merge(self):
99
 
        """Does the actual merge operation and writes translated files to
100
 
        disk"""
101
 
        htmlfile_rel = self.htmlfile.replace(
102
 
                            translate_htmlconfig.get_sources_path(), '..')
103
 
        with codecs.open(self.htmlfile, 'r', 'utf-8') as f:
104
 
            html_file = f.read()
105
 
 
106
 
            fname = os.path.basename(self.htmlfile)
107
 
            dirname = os.path.join(translate_htmlconfig.get_sources_path(),
108
 
                                                   self.ietf_langcode)
109
 
            if not os.path.exists(dirname):
110
 
                os.makedirs(dirname)
111
 
 
112
 
            html_file_translated = os.path.join(dirname, fname)
113
 
            print >> sys.stderr, 'Translation written at:', \
114
 
                                 html_file_translated
115
 
            with codecs.open(html_file_translated,
116
 
                             'w+', 'utf-8') as fd:
117
 
                po = polib.pofile(self.pofile)
118
 
 
119
 
                html_file_translated = html_file
120
 
 
121
 
                if self.test_mode:
122
 
                    entry_list = po
123
 
                else:
124
 
                    entry_list = po.translated_entries()
125
 
 
126
 
                for entry in entry_list:
127
 
                    #FIXME: is this check too strict? (We're limiting merging
128
 
                    # translations only if the original file listed in the
129
 
                    # PO files source file comments exists)
130
 
                    if (htmlfile_rel, '') in entry.occurrences:
131
 
                        # Note that we preserve the leading and trailing space
132
 
                        # to cater for words or sentences that have been split
133
 
                        # and are part of a larger sentence.
134
 
                        regex = re.compile(r'>(\s*)' +
135
 
                                           re.escape(entry.msgid) + r'(\s*)<')
136
 
                        msgstr = self._mangle_po_entry(entry)
137
 
                        replacement = r'>\g<1>' + msgstr + '\g<2><'
138
 
 
139
 
                        html_file_translated = re.sub(regex, replacement,
140
 
                                                      html_file_translated)
141
 
 
142
 
                html_file_translated = self.add_html_language(
143
 
                                                        self.ietf_langcode,
144
 
                                                        html_file_translated)
145
 
                fd.write(html_file_translated)
146
 
 
147
 
    def _mangle_po_entry(self, po_entry):
148
 
        """If the test mode is set, inverts the original English text in the
149
 
        msgid. We do this to spot untranslatable strings."""
150
 
        if self.test_mode and self._is_po_entry_untranslated(po_entry):
151
 
                po_entry = po_entry.msgid[::-1]
152
 
        else:
153
 
            po_entry = po_entry.msgstr
154
 
 
155
 
        return po_entry
156
 
 
157
 
    def _is_po_entry_untranslated(self, po_entry):
158
 
        #FIXME: polib has a bug whereby the fuzzy flag is not set when reading
159
 
        # a PO file
160
 
        is_untranslated = False
161
 
        if not po_entry.translated() and not po_entry.obsolete and \
162
 
            not 'fuzzy' in po_entry.flags:
163
 
            is_untranslated = True
164
 
        return is_untranslated
165
 
 
166
 
    def add_html_language(self, ietf_langcode, html_str):
167
 
        """Adds the 'lang' and 'dir' attributes to the final translated file's
168
 
        <html> tag"""
169
 
        rtl_langs = ['he', 'ps', 'ar', 'ur']
170
 
        lang_dir = 'ltr'
171
 
 
172
 
        if ietf_langcode.split('-')[0] in rtl_langs:
173
 
            lang_dir = 'rtl'
174
 
 
175
 
        regex = re.compile('(<html)(.*?)(>)')
176
 
        repl = r'\1 lang="{0}" dir="{1}"\3'.format(ietf_langcode, lang_dir)
177
 
 
178
 
        html_str = re.sub(regex, repl, html_str)
179
 
 
180
 
        return html_str
181
 
 
182
 
 
183
 
class StringMergerJs(object):
184
 
    """JavaScript string merger. Currently not implemented.
185
 
 
186
 
    """
187
 
    def __init__(self):
188
 
        pass
189
 
 
190
 
    def merge(self):
191
 
        pass
192
 
 
193
 
 
194
 
class StringMergerNone(object):
195
 
    """Dummy string merger
196
 
 
197
 
    """
198
 
    def __init__(self):
199
 
        pass
200
 
 
201
 
    def merge(self):
202
 
        pass
203
 
 
204
 
 
205
 
def getMerger(test_mode, pofile, path):
206
 
    """Factory-like function to guess the type of file to merge translations
207
 
    into by its MIME type, and return the appropriate merger class to
208
 
    handle it.
209
 
 
210
 
    """
211
 
    # Guess the type of the given file
212
 
    filetype, encoding = mimetypes.guess_type(path)
213
 
 
214
 
    # Return the appropriate merger class to handle the type
215
 
    if (filetype, encoding) == HTML_FILE:
216
 
        return StringMergerHtml(test_mode, pofile, path)
217
 
    elif (filetype, encoding) == JS_FILE:
218
 
        return StringMergerJs(test_mode, pofile, path)
219
 
    else:
220
 
        return StringMergerNone(test_mode, pofile, path)
221
 
 
222
 
 
223
 
def langcode_glib_to_ietf(glib_langcode):
224
 
    return re.sub('[_@]', '-', glib_langcode)