def clean(self, init_locale, source_paths): print( colored(self.whoami, 'blue') + f': searching for resource snapshots by initialization locale "{init_locale}"...' ) resources = ResourceFileHandler.find_resources_in_source_paths( init_locale, source_paths) snapshots = [] for resource in resources: snapshot = resource + '.snapshot' if os.path.exists(snapshot): snapshots.append(snapshot) if len(snapshots) > 0: reply = Utilities.confirm( colored(self.whoami, 'green') + f': Found "{len(snapshots)}" ' + 'snapshots to clear; delete ' + colored('[a]', 'green') + 'll or ' + colored('[c]', 'green') + 'onfirm each?', ['a', 'c']) for snapshot in snapshots: if reply == 's': break if reply != 'a': reply = Utilities.confirm( colored(self.whoami, 'green') + ': Delete snapshot: "' + snapshot + '" ' + colored('[y]', 'green') + 'es, ' + colored('[n]', 'green') + 'o, ' + colored('[a]', 'green') + 'll, or ' + colored('[s]', 'green') + 'top?', ['y', 'n', 'a', 's']) if reply == 'y' or reply == 'a': os.remove(snapshot)
def process_response(self, manifest): import_manifest = {} new_messages = {} missing = manifest.data.get('missing') new = manifest.data.get('new') translations = XlsTranslationsProcessor.get_inbound_translations( self.package, self.default_locale, self.expected_locales) if self.options.dump: Utilities.write_to_json_file( Constants.DUMP_PATH + 'translations-raw', translations) if missing: for resource in missing: for path, messages in resource.items(): locale = Utilities.get_locale_from_path( path, self.supported_locales) inbound_locale = self.determine_inbound_locale(locale) locale_translations = translations.get(inbound_locale) if locale_translations is not None: for key, message in messages.items(): translation = locale_translations.get(message) if path not in import_manifest: import_manifest[path] = {} import_manifest[path][key] = translation if new: for resource in new: for source_path, messages in resource.items(): source_locale = Utilities.get_locale_from_path( source_path, [self.default_locale]) if source_locale: for locale in self.supported_locales: inbound_locale = self.determine_inbound_locale( locale) locale_translations = translations.get( inbound_locale) if locale_translations is not None: locale_resources_path = Utilities.replace_locale_in_path( source_path, source_locale, locale) for key, message in messages.items(): translation = locale_translations.get( message) # Update the import manifest with translations if locale_resources_path not in import_manifest: import_manifest[ locale_resources_path] = {} import_manifest[locale_resources_path][ key] = translation # Update new messages if source_path not in new_messages: new_messages[source_path] = {} new_messages[source_path][key] = message if self.options.dump: Utilities.write_to_json_file( Constants.DUMP_PATH + 'translations-manifest', import_manifest) Utilities.write_to_json_file( Constants.DUMP_PATH + 'translations-new-messages', new_messages) return import_manifest, new_messages
def get_inbound_translations(package, source_locale, locales): translations = {} try: with zipfile.ZipFile(package + '.zip', 'r') as zip_ref: zip_ref.extractall(IOConstants.IN_PATH) except: sys.exit(f'Translations ZIP package "{package}.zip" not found') files = glob.glob(IOConstants.IN_PATH + '**/*.xls', recursive=True) + \ glob.glob(IOConstants.IN_PATH + '**/*.xlsx', recursive=True) for file in files: locale = Utilities.get_locale_from_path(file, locales) if locale: print( colored(XlsTranslationsProcessor.__qualname__, 'blue') + f': Processing translations for {locale}, from {source_locale}, in file {file}' ) translations_data = pd.read_excel(file) # Validate if source_locale not in translations_data: print( f'Translations in "{file}" does not have a dedicated column for source locale "{source_locale}' ) if locale not in translations_data: print( f'Translations in "{file}" does not have a dedicated column for locale "{locale}' ) if locale not in translations: translations[locale] = {} for i in translations_data.index: message = translations_data[source_locale][i] translation = translations_data[locale][i] translations[locale][message] = translation else: print( colored(XlsTranslationsProcessor.__qualname__, 'red') + f': Could not determine locale for translation file: {file}' ) return translations
def __init__(self, config, options): if not options.package: sys.exit( colored(self.whoami, 'red') + ': Please provide the export package name by adding option "--package=<name>"' ) self.package = options.package self.default_locale = config.get_value(('locales', 'default')) self.supported_locales = config.get_value(('locales', 'supported')) self.export_mapping = config.get_value(('exporter', 'mapping')) self.options = options Utilities.init_dir(IOConstants.DEFAULT_TRANSL_XLS_PATH) Utilities.init_dir(IOConstants.OUT_PATH) Utilities.init_dir(IOConstants.IN_PATH)
def update(self, manifest, new_messages): new = manifest.get_new() if new: for resource in new: for source_path, messages in resource.items(): if source_path in new_messages.keys(): source_new_messages = new_messages[source_path] snapshot_path = source_path + '.snapshot' snapshot = ResourceFileHandler.read_snapshot( snapshot_path) for key, message in source_new_messages.items(): snapshot[key] = message ResourceFileHandler.write_snapshot( snapshot_path, snapshot) for copy_to_locale in self.copy_to_locales: print( colored(self.whoami, 'blue') + f': Copying snapshot "{snapshot_path}" content to locale {copy_to_locale}\'s resource.' ) ResourceFileHandler.write( Utilities.replace_locale_in_path( source_path, self.default_locale, copy_to_locale), snapshot)
def write(resource_path, messages): with open(resource_path, encoding='utf-8', mode='w') as outfile: for key in messages.keys(): line = key + '=' + Utilities.get_unicode_markup(messages[key]) outfile.write(line) outfile.write('\n')
def main(self, args=sys.argv[1:], prog=program): options = self.parse_args(args, prog) config = Config() if options.command == 'version': # ToDo: Improve sys.exit(colored(self.whoami, 'blue') + ': Version = 1.0.0') elif options.command == 'init': if not options.init_locale: sys.exit( f'{self.whoami}: cannot initialize if initialization locale is not provided' ) config.init(options.init_locale, options.source_paths) elif options.command == 'clean': if not options.init_locale: sys.exit( colored(self.whoami, 'red') + f': cannot clean resource snapshots if initialization locale is not provided' ) config.clean(options.init_locale, options.source_paths) else: config.load_config() config.validate() all_bundles = Bundler().gather(config) manifest = ManifestGenerator.generate(all_bundles, config, options) if options.command == 'view': print(colored(self.whoami, 'blue') + ': ' + str(manifest)) if options.dump: Utilities.write_to_json_file( Constants.DUMP_PATH + 'translations-manifest', manifest.data) elif options.command == 'export': exporter = self.instantiate_exporter(config, options) if exporter: exporter.generate_request(manifest) else: print( colored(self.whoami, 'red') + ': Failed to process exporter') elif options.command == 'import': importer = self.instantiate_importer(config, options) if importer: translation_updates, new_messages = importer.process_response( manifest) TranslationUpdater.update(translation_updates) SnapshotUpdater(config).update(manifest, new_messages) if self.options.dump: Utilities.write_to_json_file( Constants.DUMP_PATH + 'translations-manifest', manifest.data) Utilities.write_to_json_file( Constants.DUMP_PATH + 'translations-updates', translation_updates) else: print( colored(self.whoami, 'red') + ': Failed to process importer') elif options.command == 'reconcile': Reconciliator(options, all_bundles).reconcile() else: sys.exit( colored(self.whoami, 'red') + f': command "{options.command}" currently not supported.')
def __init__(self): Utilities.init_dir(Constants.WORKING_DIR) Utilities.init_dir(Constants.DUMP_PATH)
def generate_request(self, manifest): target_translations = {} for locale in self.supported_locales: locale_out_target = self.get_locale_out_target(locale) if locale_out_target: print( colored(self.whoami, 'blue') + f': Processing added messages for locale "{locale}" to be included on export "{locale_out_target}"' ) if locale_out_target in target_translations: translations = target_translations[locale_out_target] else: translations = [] for bundles in manifest.get_new(): for bundle_path in bundles: messages = bundles[bundle_path] for message in messages.values(): if message not in translations: translations.append(message) target_translations[locale_out_target] = translations else: print( colored(self.whoami, 'yellow') + f': Processing added messages for locale "{locale}" was ignored' ) for resources in manifest.get_missing(): for resource_path in resources: locale = Utilities.get_locale_from_path( resource_path, self.supported_locales) locale_out_target = self.get_locale_out_target(locale) if locale_out_target: print( colored(self.whoami, 'blue') + f': Processing missing messages in locale "{locale}" to be included on export "{locale_out_target}"' ) if locale_out_target in target_translations: translations = target_translations[locale_out_target] else: translations = [] messages = resources[resource_path] for message in messages.values(): if message not in translations: translations.append(message) target_translations[locale_out_target] = translations else: print( colored(self.whoami, 'yellow') + f': Processing missing messages for locale "{locale}" was ignored' ) for target in target_translations: print( colored(self.whoami, 'blue') + f': Writing locale "{target}" with "{len(target_translations[target])}" translations' ) self.write_xls(target, target_translations[target]) print( colored(self.whoami, 'blue') + f': Starting packaging: Using translations XLS in path "{IOConstants.DEFAULT_TRANSL_XLS_PATH}"' ) file_name = shutil.make_archive(IOConstants.OUT_PATH + self.package, 'zip', IOConstants.DEFAULT_TRANSL_XLS_PATH) print( colored(self.whoami, 'blue') + f': Package generated in "{file_name}"')