def cmd_status(argv, path_to_tx): """Print status of current project""" parser = status_parser() options = parser.parse_args(argv) resources = parse_csv_option(options.resources) prj = project.Project(path_to_tx) resources = prj.get_chosen_resources(resources) resources_num = len(resources) for idx, res in enumerate(resources): p, r = res.split('.') print("%s -> %s (%s of %s)" % (p, r, idx + 1, resources_num)) print("Translation Files:") slang = prj.get_resource_option(res, 'source_lang') sfile = prj.get_resource_option(res, 'source_file') or "N/A" lang_map = prj.get_resource_lang_mapping(res) print(" - %s: %s (%s)" % (utils.color_text(slang, "RED"), sfile, utils.color_text("source", "YELLOW"))) files = prj.get_resource_files(res) fkeys = list(files.keys()) fkeys.sort() for lang in fkeys: local_lang = lang if lang in list(lang_map.values()): local_lang = lang_map.flip[lang] print(" - %s: %s" % (utils.color_text(local_lang, "RED"), files[lang])) print("")
def cmd_status(argv, path_to_tx): "Print status of current project" parser = status_parser() (options, args) = parser.parse_args(argv) resources = parse_csv_option(options.resources) prj = project.Project(path_to_tx) resources = prj.get_chosen_resources(resources) resources_num = len(resources) for idx, res in enumerate(resources): p, r = res.split('.') logger.info("%s -> %s (%s of %s)" % (p, r, idx + 1, resources_num)) logger.info("Translation Files:") slang = prj.get_resource_option(res, 'source_lang') sfile = prj.get_resource_option(res, 'source_file') or "N/A" lang_map = prj.get_resource_lang_mapping(res) logger.info(" - %s: %s (%s)" % (utils.color_text(slang, "RED"), sfile, utils.color_text("source", "YELLOW"))) files = prj.get_resource_files(res) fkeys = files.keys() fkeys.sort() for lang in fkeys: local_lang = lang if lang in lang_map.values(): local_lang = lang_map.flip[lang] logger.info(" - %s: %s" % (utils.color_text(local_lang, "RED"), files[lang])) logger.info("")
def cmd_status(argv, path_to_tx): "Print status of current project" usage = "usage: %prog [tx_options] status [options]" description="Prints the status of the current project by reading the"\ " data in the configuration file." parser = OptionParser(usage=usage, description=description) parser.add_option("-r", "--resource", action="store", dest="resources", default=[], help="Specify resources") (options, args) = parser.parse_args(argv) if options.resources: resources = options.resources.split(',') else: resources = [] prj = project.Project(path_to_tx) resources = prj.get_chosen_resources(resources) resources_num = len(resources) for id, res in enumerate(resources): p, r = res.split('.') utils.MSG("%s -> %s (%s of %s)" % (p, r, id + 1, resources_num)) utils.MSG("Translation Files:") slang = prj.get_resource_option(res, 'source_lang') sfile = prj.get_resource_option(res, 'source_file') or "N/A" lang_map = prj.get_resource_lang_mapping(res) utils.MSG(" - %s: %s (%s)" % (utils.color_text( slang, "RED"), sfile, utils.color_text("source", "YELLOW"))) files = prj.get_resource_files(res) fkeys = files.keys() fkeys.sort() for lang in fkeys: local_lang = lang if lang in lang_map.values(): local_lang = lang_map.flip[lang] utils.MSG(" - %s: %s" % (utils.color_text(local_lang, "RED"), files[lang])) utils.MSG("")
def input_prompt(key, validation_method): user_input = '' first_time = True while not validation_method(user_input): if not first_time: print(messages.TEXTS[key]['error']) user_input = input( utils.color_text(messages.TEXTS[key]['message'], COLOR)) first_time = False return user_input
def cmd_status(argv, path_to_tx): "Print status of current project" usage="usage: %prog [tx_options] status [options]" description="Prints the status of the current project by reading the"\ " data in the configuration file." parser = OptionParser(usage=usage,description=description) parser.add_option("-r","--resource", action="store", dest="resources", default=[], help="Specify resources") (options, args) = parser.parse_args(argv) if options.resources: resources = options.resources.split(',') else: resources = [] prj = project.Project(path_to_tx) resources = prj.get_chosen_resources(resources) resources_num = len(resources) for id, res in enumerate(resources): p, r = res.split('.') utils.MSG("%s -> %s (%s of %s)" % (p, r, id+1, resources_num)) utils.MSG("Translation Files:") slang = prj.get_resource_option(res, 'source_lang') sfile = prj.get_resource_option(res, 'source_file') or "N/A" lang_map = prj.get_resource_lang_mapping(res) utils.MSG(" - %s: %s (%s)" % (utils.color_text(slang, "RED"), sfile, utils.color_text("source", "YELLOW"))) files = prj.get_resource_files(res) fkeys = files.keys() fkeys.sort() for lang in fkeys: local_lang = lang if lang in lang_map.values(): local_lang = lang_map.flip[lang] utils.MSG(" - %s: %s" % (utils.color_text(local_lang, "RED"), files[lang])) utils.MSG("")
def choice_prompt(l, key): """ l: A list of tuples (key, display_value) with the valid choices key: one of 'formats', 'organizations', 'projects' returns the key of the selected choice """ a = "\n".join([" {}. {}".format(i + 1, f[1]) for i, f in enumerate(l)]) a = a + "\n" print(a) choice = '' first_time = True r = '1' if len(l) == 1 else '1-{}'.format(len(l)) while not validate_int(choice, len(l)): if not first_time: print(messages.TEXTS[key]["error"]) choice = input( utils.color_text(messages.TEXTS[key]['message'].format(r=r), COLOR)) first_time = False return l[int(choice) - 1][0]
def choice_prompt(l, key): """ l: A list of tuples (key, display_value) with the valid choices key: one of 'formats', 'organizations', 'projects' returns the key of the selected choice """ a = "\n".join([" {}. {}".format(i+1, f[1]) for i, f in enumerate(l)]) a = a + "\n" print(a) choice = '' first_time = True r = '1' if len(l) == 1 else '1-{}'.format(len(l)) while not validate_int(choice, len(l)): if not first_time: print(messages.TEXTS[key]["error"]) choice = input(utils.color_text( messages.TEXTS[key]['message'].format(r=r), COLOR)) first_time = False return l[int(choice) - 1][0]
def single_pull(self, languages, resource, overwrite, fetchall, fetchsource, force, skip): logger.debug("Handling resource %s" % resource) project_slug, resource_slug = resource.split('.') files = self.get_resource_files(resource) slang = self.get_resource_option(resource, 'source_lang') sfile = self.get_resource_option(resource, 'source_file') lang_map = self.get_resource_lang_mapping(resource) host = self.get_resource_host(resource) logger.debug("Language mapping is: %s" % lang_map) url_info = { 'host': host, 'project': project_slug, 'resource': resource_slug } logger.debug("URL data are: %s" % url_info) stats = self._get_stats_for_resource(url_info) try: file_filter = self.config.get(resource, 'file_filter') except ConfigParser.NoOptionError: file_filter = None # Pull source file pull_languages = set([]) new_translations = set([]) if fetchall: new_translations = self._new_translations_to_add( files, slang, lang_map, resource, stats, force) if new_translations: MSG("New translations found for the following languages: %s" % ', '.join(new_translations)) existing, new = self._languages_to_pull(languages, files, lang_map, resource, stats, force) pull_languages |= existing new_translations |= new logger.debug("Adding to new translations: %s" % new) if fetchsource: if sfile and slang not in pull_languages: pull_languages.append(slang) elif slang not in new_translations: new_translations.append(slang) for lang in pull_languages: local_lang = lang if lang in lang_map.values(): remote_lang = lang_map.flip[lang] else: remote_lang = lang if languages and lang not in pull_languages: logger.debug("Skipping language %s" % lang) continue if lang != slang: local_file = files.get(lang, None) or files[lang_map[lang]] else: local_file = sfile logger.debug("Using file %s" % local_file) kwargs = { 'lang': remote_lang, 'stats': stats, 'local_file': local_file, 'force': force, 'resource': resource } if not self._should_update_translation(**kwargs): msg = "Skipping '%s' translation (file: %s)." MSG(msg % (color_text(remote_lang, "RED"), local_file)) continue if not overwrite: local_file = ("%s.new" % local_file) MSG(" -> %s: %s" % (color_text(remote_lang, "RED"), local_file)) try: r = self.do_url_request('pull_file', url_info, language=remote_lang) except Exception, e: if not skip: raise e else: ERRMSG(e) continue base_dir = os.path.split(local_file)[0] mkdir_p(base_dir) fd = open(local_file, 'wb') fd.write(r) fd.close()
def run(self): """ Runs the interactive wizard for `tx set` command and populates the parser's options with the customuser input. Options `local` and `execute` are by default True when interactive wizard is run. Returns: the options dictionary. """ TEXTS = messages.TEXTS print(TEXTS['source_file']['description']) source_file = input_prompt('source_file', validate_source_file) print( TEXTS['expression']['description'].format(source_file=source_file)) expression = input_prompt('expression', validate_expression) formats = self.get_formats(os.path.basename(source_file)) print(TEXTS['formats']['description']) i18n_type = choice_prompt(formats, 'formats') organizations = self.get_organizations() print(TEXTS['organization']['description']) org_slug = choice_prompt(organizations, 'organization') projects = [] first_time = True create_project = ("tx:new_project", "Create new project (show instructions)...") project = None while not project: if not first_time: retry_message = "Hit Enter to try selecting a project again: " input(utils.color_text(retry_message, COLOR)) projects = self.get_projects_for_org(org_slug) p_choices = [(p['slug'], p['name']) for p in projects] p_choices.append(create_project) if projects: print(TEXTS['projects']['description']) else: print("We found no projects in this organization!") first_time = False project_slug = choice_prompt(p_choices, 'projects') if project_slug == 'tx:new_project': print( messages.create_project_instructions.format(host=self.host, org=org_slug)) else: project = [p for p in projects if p['slug'] == project_slug][0] source_language = project['source_language']['code'] resource_slug = slugify(os.path.basename(source_file)) resource = '{}.{}'.format(project_slug, resource_slug) options = { 'source_file': source_file, 'expression': expression, 'i18n_type': i18n_type, 'source_language': source_language, 'resource': resource, } return options
def single_pull(self, languages, resource, overwrite, fetchall, fetchsource, force, skip): logger.debug("Handling resource %s" % resource) project_slug, resource_slug = resource.split('.') files = self.get_resource_files(resource) slang = self.get_resource_option(resource, 'source_lang') sfile = self.get_resource_option(resource, 'source_file') lang_map = self.get_resource_lang_mapping(resource) host = self.get_resource_host(resource) logger.debug("Language mapping is: %s" % lang_map) url_info = { 'host': host, 'project': project_slug, 'resource': resource_slug } logger.debug("URL data are: %s" % url_info) stats = self._get_stats_for_resource(url_info) try: file_filter = self.config.get(resource, 'file_filter') except ConfigParser.NoOptionError: file_filter = None # Pull source file pull_languages = set([]) new_translations = set([]) if fetchall: new_translations = self._new_translations_to_add( files, slang, lang_map, resource, stats, force ) if new_translations: MSG("New translations found for the following languages: %s" % ', '.join(new_translations)) existing, new = self._languages_to_pull( languages, files, lang_map, resource, stats, force ) pull_languages |= existing new_translations |= new logger.debug("Adding to new translations: %s" % new) if fetchsource: if sfile and slang not in pull_languages: pull_languages.append(slang) elif slang not in new_translations: new_translations.append(slang) for lang in pull_languages: local_lang = lang if lang in lang_map.values(): remote_lang = lang_map.flip[lang] else: remote_lang = lang if languages and lang not in pull_languages: logger.debug("Skipping language %s" % lang) continue if lang != slang: local_file = files.get(lang, None) or files[lang_map[lang]] else: local_file = sfile logger.debug("Using file %s" % local_file) kwargs = { 'lang': remote_lang, 'stats': stats, 'local_file': local_file, 'force': force, 'resource': resource } if not self._should_update_translation(**kwargs): msg = "Skipping '%s' translation (file: %s)." MSG(msg % (color_text(remote_lang, "RED"), local_file)) continue if not overwrite: local_file = ("%s.new" % local_file) MSG(" -> %s: %s" % (color_text(remote_lang,"RED"), local_file)) try: r = self.do_url_request('pull_file', url_info, language=remote_lang) except Exception,e: if not skip: raise e else: ERRMSG(e) continue base_dir = os.path.split(local_file)[0] mkdir_p(base_dir) fd = open(local_file, 'wb') fd.write(r) fd.close()
def run(self): """ Runs the interactive wizard for `tx set` command and populates the parser's options with the user input. Options `local` and `execute` are by default True when interactive wizard is run. Returns: the options dictionary. """ TEXTS = messages.TEXTS print(TEXTS['source_file']['description']) source_file = input_prompt('source_file', validate_source_file) print( TEXTS['expression']['description'].format(source_file=source_file) ) expression = input_prompt('expression', validate_expression) formats = self.get_formats(os.path.basename(source_file)) print(TEXTS['formats']['description']) i18n_type = choice_prompt(formats, 'formats') organizations = self.get_organizations() print(TEXTS['organization']['description']) org_slug = choice_prompt(organizations, 'organization') projects = [] first_time = True create_project = ("tx:new_project", "Create new project (show instructions)...") project = None while not project: if not first_time: retry_message = "Hit Enter to try selecting a project again: " input(utils.color_text(retry_message, COLOR)) projects = self.get_projects_for_org(org_slug) p_choices = [(p['slug'], p['name']) for p in projects] p_choices.append(create_project) if projects: print(TEXTS['projects']['description']) else: print("We found no projects in this organization!") first_time = False project_slug = choice_prompt(p_choices, 'projects') if project_slug == 'tx:new_project': print(messages.create_project_instructions.format( host=self.host, org=org_slug )) else: project = [p for p in projects if p['slug'] == project_slug][0] source_language = project['source_language']['code'] resource_slug = slugify(os.path.basename(source_file)) resource = '{}.{}'.format(project_slug, resource_slug) options = { 'source_file': source_file, 'expression': expression, 'i18n_type': i18n_type, 'source_language': source_language, 'resource': resource, } return options
def push(self, source=False, translations=False, force=False, resources=[], languages=[], skip=False, no_interactive=False): """Push all the resources""" resource_list = self.get_chosen_resources(resources) self.skip = skip self.force = force for resource in resource_list: push_languages = [] project_slug, resource_slug = resource.split('.', 1) files = self.get_resource_files(resource) slang = self.get_resource_option(resource, 'source_lang') sfile = self.get_source_file(resource) lang_map = self.get_resource_lang_mapping(resource) host = self.get_resource_host(resource) logger.debug("Language mapping is: %s" % lang_map) logger.debug("Using host %s" % host) self.url_info = { 'host': host, 'project': project_slug, 'resource': resource_slug } logger.info("Pushing translations for resource %s:" % resource) stats = self._get_stats_for_resource() if force and not no_interactive: answer = input("Warning: By using --force, the uploaded " "files will overwrite remote translations, " "even if they are newer than your uploaded " "files.\nAre you sure you want to continue? " "[y/N]") if answer not in ["", 'Y', 'y', "yes", 'YES']: return if source: if sfile is None: logger.error("You don't seem to have a proper source file " "mapping for resource %s. Try without the " "--source option or set a source file " "first and then try again." % resource) continue # Push source file try: logger.warning("Pushing source file (%s)" % sfile) if not self._resource_exists(stats): logger.info("Resource does not exist. Creating...") fileinfo = "%s;%s" % (resource_slug, slang) filename = self.get_full_path(sfile) self._create_resource( resource, project_slug, fileinfo, filename ) self.do_url_request( 'push_source', multipart=True, method="PUT", files=[("%s;%s" % (resource_slug, slang), self.get_full_path(sfile) )], ) except Exception as e: if isinstance(e, SSLError) or not skip: raise else: logger.error(e) else: try: self.do_url_request('resource_details') except Exception as e: if isinstance(e, SSLError): raise code = getattr(e, 'code', None) if code == 404: msg = "Resource %s doesn't exist on the server." logger.error(msg % resource) continue if translations: # Check if given language codes exist if not languages: push_languages = list(files.keys()) else: push_languages = [] f_langs = list(files.keys()) for l in languages: if l in list(lang_map.keys()): l = lang_map[l] push_languages.append(l) if l not in f_langs: msg = "Warning: No mapping found for " "language code '%s'." logger.error(msg % utils.color_text(l, "RED")) logger.debug("Languages to push are %s" % push_languages) # Push translation files one by one for lang in push_languages: local_lang = lang if lang in list(lang_map.values()): remote_lang = lang_map.flip[lang] else: remote_lang = lang local_file = files[local_lang] kwargs = { 'lang': remote_lang, 'stats': stats, 'local_file': local_file, 'force': force, } if not self._should_push_translation(**kwargs): msg = "Skipping '%s' translation (file: %s)." logger.info(msg % (utils.color_text(lang, "RED"), local_file) ) continue msg = "Pushing '%s' translations (file: %s)" logger.warning( msg % (utils.color_text(remote_lang, "RED"), local_file) ) try: self.do_url_request( 'push_translation', multipart=True, method='PUT', files=[("%s;%s" % (resource_slug, remote_lang), self.get_full_path(local_file) )], language=remote_lang ) logger.debug("Translation %s pushed." % remote_lang) except utils.HttpNotFound: if not source: logger.error("Resource hasn't been created. " "Try pushing source file.") except Exception as e: if isinstance(e, SSLError) or not skip: raise else: logger.error(e)
def pull(self, languages=[], resources=[], overwrite=True, fetchall=False, fetchsource=False, force=False, skip=False, minimum_perc=0, mode=None, pseudo=False): """Pull all translations file from transifex server.""" self.minimum_perc = minimum_perc resource_list = self.get_chosen_resources(resources) if mode == 'reviewed': url = 'pull_reviewed_file' elif mode == 'translator': url = 'pull_translator_file' elif mode == 'developer': url = 'pull_developer_file' elif mode == 'onlytranslated': url = 'pull_onlytranslated_file' elif mode == 'onlyreviewed': url = 'pull_onlyreviewed_file' else: url = 'pull_file' for resource in resource_list: logger.debug("Handling resource %s" % resource) self.resource = resource project_slug, resource_slug = resource.split('.', 1) files = self.get_resource_files(resource) slang = self.get_resource_option(resource, 'source_lang') sfile = self.get_source_file(resource) lang_map = self.get_resource_lang_mapping(resource) host = self.get_resource_host(resource) logger.debug("Language mapping is: %s" % lang_map) if mode is None: mode = self._get_option(resource, 'mode') self.url_info = { 'host': host, 'project': project_slug, 'resource': resource_slug } logger.debug("URL data are: %s" % self.url_info) stats = self._get_stats_for_resource() try: file_filter = self.config.get(resource, 'file_filter') except configparser.NoOptionError: file_filter = None # Pull source file pull_languages = set([]) new_translations = set([]) if pseudo: pseudo_file = self._get_pseudo_file( slang, resource, file_filter ) if self._should_download(slang, stats, local_file=pseudo_file): logger.info("Pulling pseudo file for resource %s (%s)." % ( resource, utils.color_text(pseudo_file, "RED") )) self._download_pseudo( project_slug, resource_slug, pseudo_file ) if not languages: continue if fetchall: new_translations = self._new_translations_to_add( files, slang, lang_map, stats, force ) if new_translations: msg = ("New translations found " "for the following languages:%s") logger.info(msg % ', '.join(new_translations)) existing, new = self._languages_to_pull( languages, files, lang_map, stats, force ) pull_languages |= existing new_translations |= new logger.debug("Adding to new translations: %s" % new) if fetchsource: if sfile and slang not in pull_languages: pull_languages.add(slang) elif slang not in new_translations: new_translations.add(slang) if pull_languages: logger.debug("Pulling languages for: %s" % pull_languages) msg = "Pulling translations for resource %s (source: %s)" logger.info(msg % (resource, sfile)) for lang in pull_languages: local_lang = lang if lang in list(lang_map.values()): remote_lang = lang_map.flip[lang] else: remote_lang = lang if languages and lang not in pull_languages: logger.debug("Skipping language %s" % lang) continue if lang != slang: local_file = files.get(lang, None) or files[lang_map[lang]] else: local_file = sfile logger.debug("Using file %s" % local_file) kwargs = { 'lang': remote_lang, 'stats': stats, 'local_file': local_file, 'force': force, 'mode': mode, } if not self._should_update_translation(**kwargs): msg = "Skipping '%s' translation (file: %s)." logger.info( msg % (utils.color_text(remote_lang, "RED"), local_file) ) continue if not overwrite: local_file = ("%s.new" % local_file) logger.warning( " -> %s: %s" % (utils.color_text(remote_lang, "RED"), local_file) ) try: r, charset = self.do_url_request(url, language=remote_lang) except Exception as e: if isinstance(e, SSLError) or not skip: raise else: logger.error(e) continue base_dir = os.path.split(local_file)[0] utils.mkdir_p(base_dir) fd = open(local_file, 'wb') fd.write(r.encode(charset)) fd.close() if new_translations: msg = "Pulling new translations for resource %s (source: %s)" logger.info(msg % (resource, sfile)) for lang in new_translations: if lang in list(lang_map.keys()): local_lang = lang_map[lang] else: local_lang = lang remote_lang = lang if file_filter: local_file = os.path.relpath( os.path.join( self.root, native_path( file_filter.replace('<lang>', local_lang) ) ), os.curdir ) else: trans_dir = os.path.join(self.root, ".tx", resource) if not os.path.exists(trans_dir): os.mkdir(trans_dir) local_file = os.path.relpath( os.path.join(trans_dir, '%s_translation' % local_lang, os.curdir)) if lang != slang: satisfies_min = self._satisfies_min_translated( stats[remote_lang], mode ) if not satisfies_min: msg = "Skipping language %s due to used options." logger.info(msg % lang) continue logger.warning( " -> %s: %s" % (utils.color_text(remote_lang, "RED"), local_file) ) r, charset = self.do_url_request(url, language=remote_lang) base_dir = os.path.split(local_file)[0] utils.mkdir_p(base_dir) fd = open(local_file, 'wb') fd.write(r.encode(charset)) fd.close()
if lang in lang_map.keys(): local_lang = lang_map[lang] else: local_lang = lang remote_lang = lang if file_filter: local_file = relpath(os.path.join(self.root, file_filter.replace('<lang>', local_lang)), os.curdir) else: trans_dir = os.path.join(self.root, ".tx", resource) if not os.path.exists(trans_dir): os.mkdir(trans_dir) local_file = relpath(os.path.join(trans_dir, '%s_translation' % local_lang, os.curdir)) MSG(" -> %s: %s" % (color_text(remote_lang, "RED"), local_file)) r = self.do_url_request('pull_file', url_info, language=remote_lang) base_dir = os.path.split(local_file)[0] mkdir_p(base_dir) fd = open(local_file, 'wb') fd.write(r) fd.close() def push(self, source=False, translations=False, force=False, resources=[], languages=[], skip=False, no_interactive=False): """ Push all the resources """ resource_list = self.get_chosen_resources(resources) for resource in resource_list:
if file_filter: local_file = relpath( os.path.join(self.root, file_filter.replace('<lang>', local_lang)), os.curdir) else: trans_dir = os.path.join(self.root, ".tx", resource) if not os.path.exists(trans_dir): os.mkdir(trans_dir) local_file = relpath( os.path.join(trans_dir, '%s_translation' % local_lang, os.curdir)) MSG(" -> %s: %s" % (color_text(remote_lang, "RED"), local_file)) r = self.do_url_request('pull_file', url_info, language=remote_lang) base_dir = os.path.split(local_file)[0] mkdir_p(base_dir) fd = open(local_file, 'wb') fd.write(r) fd.close() def push(self, source=False, translations=False, force=False, resources=[],
def push(self, source=False, translations=False, force=False, resources=[], languages=[], skip=False, no_interactive=False): """Push all the resources""" resource_list = self.get_chosen_resources(resources) self.skip = skip self.force = force for resource in resource_list: push_languages = [] project_slug, resource_slug = resource.split('.', 1) files = self.get_resource_files(resource) slang = self.get_resource_option(resource, 'source_lang') sfile = self.get_source_file(resource) lang_map = self.get_resource_lang_mapping(resource) host = self.get_resource_host(resource) logger.debug("Language mapping is: %s" % lang_map) logger.debug("Using host %s" % host) self.url_info = { 'host': host, 'project': project_slug, 'resource': resource_slug } logger.info("Pushing translations for resource %s:" % resource) stats = self._get_stats_for_resource() if force and not no_interactive: answer = input("Warning: By using --force, the uploaded " "files will overwrite remote translations, " "even if they are newer than your uploaded " "files.\nAre you sure you want to continue? " "[y/N]") if answer not in ["", 'Y', 'y', "yes", 'YES']: return if source: if sfile is None: logger.error("You don't seem to have a proper source file " "mapping for resource %s. Try without the " "--source option or set a source file " "first and then try again." % resource) continue # Push source file try: logger.warning("Pushing source file (%s)" % sfile) if not self._resource_exists(stats): logger.info("Resource does not exist. Creating...") fileinfo = "%s;%s" % (resource_slug, slang) filename = self.get_full_path(sfile) self._create_resource(resource, project_slug, fileinfo, filename) self.do_url_request( 'push_source', multipart=True, method="PUT", files=[("%s;%s" % (resource_slug, slang), self.get_full_path(sfile))], ) except Exception as e: if isinstance(e, SSLError) or not skip: raise else: logger.error(e) else: try: self.do_url_request('resource_details') except Exception as e: if isinstance(e, SSLError): raise code = getattr(e, 'code', None) if code == 404: msg = "Resource %s doesn't exist on the server." logger.error(msg % resource) continue if translations: # Check if given language codes exist if not languages: push_languages = list(files.keys()) else: push_languages = [] f_langs = list(files.keys()) for l in languages: if l in list(lang_map.keys()): l = lang_map[l] push_languages.append(l) if l not in f_langs: msg = "Warning: No mapping found for " "language code '%s'." logger.error(msg % utils.color_text(l, "RED")) logger.debug("Languages to push are %s" % push_languages) # Push translation files one by one for lang in push_languages: local_lang = lang if lang in list(lang_map.values()): remote_lang = lang_map.flip[lang] else: remote_lang = lang local_file = files[local_lang] kwargs = { 'lang': remote_lang, 'stats': stats, 'local_file': local_file, 'force': force, } if not self._should_push_translation(**kwargs): msg = "Skipping '%s' translation (file: %s)." logger.info( msg % (utils.color_text(lang, "RED"), local_file)) continue msg = "Pushing '%s' translations (file: %s)" logger.warning( msg % (utils.color_text(remote_lang, "RED"), local_file)) try: self.do_url_request( 'push_translation', multipart=True, method='PUT', files=[("%s;%s" % (resource_slug, remote_lang), self.get_full_path(local_file))], language=remote_lang) logger.debug("Translation %s pushed." % remote_lang) except utils.HttpNotFound: if not source: logger.error("Resource hasn't been created. " "Try pushing source file.") except Exception as e: if isinstance(e, SSLError) or not skip: raise else: logger.error(e)
def pull(self, languages=[], resources=[], overwrite=True, fetchall=False, fetchsource=False, force=False, skip=False, minimum_perc=0, mode=None, pseudo=False): """Pull all translations file from transifex server.""" self.minimum_perc = minimum_perc resource_list = self.get_chosen_resources(resources) skip_decode = False if mode == 'reviewed': url = 'pull_reviewed_file' elif mode == 'translator': url = 'pull_translator_file' elif mode == 'developer': url = 'pull_developer_file' elif mode == 'onlytranslated': url = 'pull_onlytranslated_file' elif mode == 'onlyreviewed': url = 'pull_onlyreviewed_file' else: url = 'pull_file' for resource in resource_list: logger.debug("Handling resource %s" % resource) self.resource = resource project_slug, resource_slug = resource.split('.', 1) files = self.get_resource_files(resource) slang = self.get_resource_option(resource, 'source_lang') sfile = self.get_source_file(resource) lang_map = self.get_resource_lang_mapping(resource) host = self.get_resource_host(resource) logger.debug("Language mapping is: %s" % lang_map) if mode is None: mode = self._get_option(resource, 'mode') self.url_info = { 'host': host, 'project': project_slug, 'resource': resource_slug } logger.debug("URL data are: %s" % self.url_info) stats = self._get_stats_for_resource() details_response, _ = self.do_url_request('resource_details') details = utils.parse_json(details_response) if details['i18n_type'] in self.SKIP_DECODE_I18N_TYPES: skip_decode = True try: file_filter = self.config.get(resource, 'file_filter') except configparser.NoOptionError: file_filter = None # Pull source file pull_languages = set([]) new_translations = set([]) if pseudo: pseudo_file = self._get_pseudo_file(slang, resource, file_filter) if self._should_download(slang, stats, local_file=pseudo_file): logger.info( "Pulling pseudo file for resource %s (%s)." % (resource, utils.color_text(pseudo_file, "RED"))) self._download_pseudo(project_slug, resource_slug, pseudo_file) if not languages: continue if fetchall: new_translations = self._new_translations_to_add( files, slang, lang_map, stats, force) if new_translations: msg = ("New translations found " "for the following languages:%s") logger.info(msg % ', '.join(new_translations)) existing, new = self._languages_to_pull(languages, files, lang_map, stats, force) pull_languages |= existing new_translations |= new logger.debug("Adding to new translations: %s" % new) if fetchsource: if sfile and slang not in pull_languages: pull_languages.add(slang) elif slang not in new_translations: new_translations.add(slang) if pull_languages: logger.debug("Pulling languages for: %s" % pull_languages) msg = "Pulling translations for resource %s (source: %s)" logger.info(msg % (resource, sfile)) for lang in pull_languages: local_lang = lang if lang in list(lang_map.values()): remote_lang = lang_map.flip[lang] else: remote_lang = lang if languages and lang not in pull_languages: logger.debug("Skipping language %s" % lang) continue if lang != slang: local_file = files.get(lang, None) or files[lang_map[lang]] else: local_file = sfile logger.debug("Using file %s" % local_file) kwargs = { 'lang': remote_lang, 'stats': stats, 'local_file': local_file, 'force': force, 'mode': mode, } if not self._should_update_translation(**kwargs): msg = "Skipping '%s' translation (file: %s)." logger.info( msg % (utils.color_text(remote_lang, "RED"), local_file)) continue if not overwrite: local_file = ("%s.new" % local_file) logger.warning( " -> %s: %s" % (utils.color_text(remote_lang, "RED"), local_file)) try: r, charset = self.do_url_request(url, language=remote_lang, skip_decode=skip_decode) except Exception as e: if isinstance(e, SSLError) or not skip: raise else: logger.error(e) continue self._save_file(local_file, charset, r) if new_translations: msg = "Pulling new translations for resource %s (source: %s)" logger.info(msg % (resource, sfile)) for lang in new_translations: if lang in list(lang_map.keys()): local_lang = lang_map[lang] else: local_lang = lang remote_lang = lang if file_filter: local_file = os.path.relpath( os.path.join( self.root, native_path( file_filter.replace('<lang>', local_lang))), os.curdir) else: trans_dir = os.path.join(self.root, ".tx", resource) if not os.path.exists(trans_dir): os.mkdir(trans_dir) local_file = os.path.relpath( os.path.join(trans_dir, '%s_translation' % local_lang, os.curdir)) if lang != slang: satisfies_min = self._satisfies_min_translated( stats[remote_lang], mode) if not satisfies_min: msg = "Skipping language %s due to used options." logger.info(msg % lang) continue logger.warning( " -> %s: %s" % (utils.color_text(remote_lang, "RED"), local_file)) r, charset = self.do_url_request(url, language=remote_lang, skip_decode=skip_decode) self._save_file(local_file, charset, r)