|
| 1 | +#!/usr/bin/python |
| 2 | + |
| 3 | +import argparse |
| 4 | +import datetime |
| 5 | +import os |
| 6 | +import subprocess |
| 7 | +import sys |
| 8 | +from ConfigParser import SafeConfigParser |
| 9 | + |
| 10 | +# Get absolute path of ../config from the current script location (not the |
| 11 | +# current folder) |
| 12 | +config_folder = os.path.abspath( |
| 13 | + os.path.join(os.path.dirname(__file__), os.pardir, 'config')) |
| 14 | + |
| 15 | +# Read Transvision's configuration file from ../config/config.ini |
| 16 | +# If not available use default a /storage folder to store data |
| 17 | +config_file = os.path.join(config_folder, 'config.ini') |
| 18 | +if not os.path.isfile(config_file): |
| 19 | + print 'Configuration file /app/config/config.ini is missing. Default folders will be used.' |
| 20 | + storage_path = os.path.abspath( |
| 21 | + os.path.join(os.path.dirname(__file__), os.pardir)) |
| 22 | + library_path = os.path.join(storage_path, 'libraries') |
| 23 | + storage_path = os.path.join(storage_path, 'tests', 'testfiles', 'output') |
| 24 | +else: |
| 25 | + config_parser = SafeConfigParser() |
| 26 | + config_parser.read(config_file) |
| 27 | + library_path = config_parser.get('config', 'libraries') |
| 28 | + storage_path = os.path.join(config_parser.get('config', 'root'), 'TMX') |
| 29 | + |
| 30 | +# Import Silme library (http://hg.mozilla.org/l10n/silme/) |
| 31 | +silme_path = os.path.join(library_path, 'silme') |
| 32 | + |
| 33 | +if not os.path.isdir(silme_path): |
| 34 | + try: |
| 35 | + print 'Cloning silme...' |
| 36 | + cmd_status = subprocess.check_output( |
| 37 | + ['hg', 'clone', 'https://hg.mozilla.org/l10n/silme', |
| 38 | + silme_path, '-u', 'silme-0.8.0'], |
| 39 | + stderr=subprocess.STDOUT, |
| 40 | + shell=False) |
| 41 | + print cmd_status |
| 42 | + except Exception as e: |
| 43 | + print e |
| 44 | + |
| 45 | +sys.path.append(os.path.join(silme_path, 'lib')) |
| 46 | +try: |
| 47 | + import silme.core |
| 48 | + import silme.io |
| 49 | + import silme.format |
| 50 | + silme.format.Manager.register('dtd', 'properties', 'ini', 'inc') |
| 51 | +except ImportError: |
| 52 | + print 'Error importing Silme library' |
| 53 | + sys.exit(1) |
| 54 | + |
| 55 | + |
| 56 | +def escape(translation): |
| 57 | + ''' |
| 58 | + Escape quotes and backslahes in translation. There are two issues: |
| 59 | + * Internal Python escaping: the string "this is a \", has an internal |
| 60 | + representation as "this is a \\". |
| 61 | + Also, "\\ test" is equivalent to r"\ test" (raw string). |
| 62 | + * We need to print these strings into a file, with the format of a |
| 63 | + PHP array delimited by single quotes ('id' => 'translation'). Hence |
| 64 | + we need to escape single quotes, but also escape backslashes. |
| 65 | + "this is a 'test'" => "this is a \'test\'" |
| 66 | + "this is a \'test\'" => "this is a \\\'test\\\'" |
| 67 | + ''' |
| 68 | + |
| 69 | + # Escape slashes |
| 70 | + escaped_translation = translation.replace('\\', '\\\\') |
| 71 | + # Escape single quotes |
| 72 | + escaped_translation = escaped_translation.replace('\'', '\\\'') |
| 73 | + |
| 74 | + return escaped_translation |
| 75 | + |
| 76 | + |
| 77 | +def get_strings(package, local_directory, strings_array): |
| 78 | + '''Store recursively translations from files in local_directory in a list of string''' |
| 79 | + for item in package: |
| 80 | + if (type(item[1]) is not silme.core.structure.Blob) and not(isinstance(item[1], silme.core.Package)): |
| 81 | + for entity in item[1]: |
| 82 | + # String ID is the format folder/filename:entity. Make |
| 83 | + # sure to remove a starting '/' from the folder's name |
| 84 | + string_id = u'{0}/{1}:{2}'.format( |
| 85 | + local_directory.lstrip('/'), item[0], entity) |
| 86 | + strings_array[string_id] = item[1][entity].get_value() |
| 87 | + elif (isinstance(item[1], silme.core.Package)): |
| 88 | + if (item[0] != 'en-US') and (item[0] != 'locales'): |
| 89 | + get_strings(item[1], local_directory + '/' + item[0], |
| 90 | + strings_array) |
| 91 | + else: |
| 92 | + get_strings(item[1], local_directory, strings_array) |
| 93 | + |
| 94 | + |
| 95 | +def create_directories_list(locale_repo, reference_repo, repository): |
| 96 | + ''' Create a list of folders to analyze ''' |
| 97 | + if repository.startswith('gaia') or repository == 'l20n_test': |
| 98 | + # Examine the entire folder |
| 99 | + dirs = [''] |
| 100 | + else: |
| 101 | + dirs_locale = os.listdir(locale_repo) |
| 102 | + dirs_reference = [ |
| 103 | + 'browser', 'calendar', 'chat', 'devtools', 'dom', 'editor', |
| 104 | + 'extensions', 'mail', 'mobile', 'netwerk', 'other-licenses', |
| 105 | + 'security', 'services', 'suite', 'toolkit', 'webapprt' |
| 106 | + ] |
| 107 | + dirs = filter(lambda x: x in dirs_locale, dirs_reference) |
| 108 | + |
| 109 | + return dirs |
| 110 | + |
| 111 | + |
| 112 | +def create_tmx_content(reference_repo, locale_repo, dirs): |
| 113 | + ''' Extract strings from repository, return them as a list of PHP array |
| 114 | + elements. ''' |
| 115 | + tmx_content = [] |
| 116 | + for directory in dirs: |
| 117 | + path_reference = os.path.join(reference_repo, directory) |
| 118 | + path_locale = os.path.join(locale_repo, directory) |
| 119 | + |
| 120 | + rcsClient = silme.io.Manager.get('file') |
| 121 | + try: |
| 122 | + l10nPackage_reference = rcsClient.get_package( |
| 123 | + path_reference, object_type='entitylist') |
| 124 | + except Exception as e: |
| 125 | + print 'Silme couldn\'t extract data for', path_reference |
| 126 | + print e |
| 127 | + continue |
| 128 | + |
| 129 | + if not os.path.isdir(path_locale): |
| 130 | + # Folder doesn't exist for this locale, don't log a warning, |
| 131 | + # just continue to the next folder. |
| 132 | + continue |
| 133 | + |
| 134 | + try: |
| 135 | + l10nPackage_locale = rcsClient.get_package( |
| 136 | + path_locale, object_type='entitylist') |
| 137 | + except Exception as e: |
| 138 | + print 'Silme couldn\'t extract data for', path_locale |
| 139 | + print e |
| 140 | + continue |
| 141 | + |
| 142 | + strings_reference = {} |
| 143 | + strings_locale = {} |
| 144 | + get_strings(l10nPackage_reference, directory, strings_reference) |
| 145 | + get_strings(l10nPackage_locale, directory, strings_locale) |
| 146 | + for entity in strings_reference: |
| 147 | + # Append string to tmx_content, using the format of a PHP array |
| 148 | + # element |
| 149 | + translation = escape( |
| 150 | + strings_locale.get(entity, '')).encode('utf-8') |
| 151 | + tmx_content.append("'{0}' => '{1}'".format( |
| 152 | + entity.encode('utf-8'), translation)) |
| 153 | + tmx_content.sort() |
| 154 | + |
| 155 | + return tmx_content |
| 156 | + |
| 157 | + |
| 158 | +def write_php_file(filename, tmx_content): |
| 159 | + ''' Write TMX content as a PHP array on file ''' |
| 160 | + target_locale_file = open(filename, 'w') |
| 161 | + target_locale_file.write('<?php\n$tmx = [\n') |
| 162 | + for line in tmx_content: |
| 163 | + target_locale_file.write(line + ',\n') |
| 164 | + target_locale_file.write('];\n') |
| 165 | + target_locale_file.close() |
| 166 | + |
| 167 | + |
| 168 | +def main(): |
| 169 | + # Read command line input parameters |
| 170 | + parser = argparse.ArgumentParser() |
| 171 | + parser.add_argument('locale_repo', help='Path to locale files') |
| 172 | + parser.add_argument('reference_repo', help='Path to reference files') |
| 173 | + parser.add_argument('locale_code', help='Locale language code') |
| 174 | + parser.add_argument('reference_code', help='Reference language code') |
| 175 | + parser.add_argument('repository', help='Repository name') |
| 176 | + args = parser.parse_args() |
| 177 | + |
| 178 | + dirs = create_directories_list( |
| 179 | + args.reference_repo, args.locale_repo, args.repository |
| 180 | + ) |
| 181 | + tmx_content = create_tmx_content( |
| 182 | + args.reference_repo, args.locale_repo, dirs |
| 183 | + ) |
| 184 | + |
| 185 | + # Store the actual file on disk |
| 186 | + filename_locale = os.path.join( |
| 187 | + os.path.join(storage_path, args.locale_code), |
| 188 | + 'cache_{0}_{1}.php'.format(args.locale_code, args.repository) |
| 189 | + ) |
| 190 | + write_php_file(filename_locale, tmx_content) |
| 191 | + |
| 192 | + |
| 193 | +if __name__ == '__main__': |
| 194 | + main() |
0 commit comments