def _get_time_of_local_file(self, path): """Get the modified time of the path_. Args: path: The path we want the mtime for. Returns: The time as a timestamp or None, if the file does not exist """ time_format = "%Y-%m-%d %H:%M:%S %Z" if not os.path.exists(path): return None try: rtype, git_dir, fname = self._get_git_dir(path) assert rtype == 'git', rtype # FIXME: requires python 2.7! out = subprocess.check_output(['git', 'rev-list', '-n', '1', '--pretty=format:%at', 'HEAD', '--', fname], cwd=git_dir) if out: lines = out.split('\n') return float(lines[1]) except KeyError: # It's not a git dir! pass except Exception, e: logger.warning("Cannot check with git:", exc_info=True)
def delete(self, resources=[], languages=[], skip=False): """Delete translations.""" resource_list = self.get_chosen_resources(resources) for resource in resources: delete_languages = [] files = self.get_resource_files(resource) project_slug, resource_slug = resource.split('.') lang_map = self.get_resource_lang_mapping(resource) host = self.get_resource_host(resource) url_info = { 'host': host, 'project': project_slug, 'resource': resource_slug } logger.debug("URL data are: %s" % url_info) MSG("Deleting translations for resource %s:" % resource) if not languages: logger.warning("No languages specified.") return for language in languages: try: self.do_url_request('delete_translation', url_info, language=language, method="DELETE") msg = "Deleted language %s from resource %s in project %s." MSG(msg % (language, resource_slug, project_slug)) except Exception, e: msg = "ERROR: Unable to delete translation %s.%s.%s" MSG(msg % (project_slug, resource_slug, language)) if not skip: raise
def delete(self, resources=[], languages=[], skip=False): """Delete translations.""" resource_list = self.get_chosen_resources(resources) for resource in resources: delete_languages = [] files = self.get_resource_files(resource) project_slug, resource_slug = resource.split('.') lang_map = self.get_resource_lang_mapping(resource) host = self.get_resource_host(resource) url_info = { 'host': host, 'project': project_slug, 'resource': resource_slug } logger.debug("URL data are: %s" % url_info) MSG("Deleting translations for resource %s:" % resource) if not languages: logger.warning("No languages specified.") return for language in languages: try: self.do_url_request( 'delete_translation', url_info, language=language, method="DELETE" ) msg = "Deleted language %s from resource %s in project %s." MSG(msg % (language, resource_slug, project_slug)) except Exception, e: msg = "ERROR: Unable to delete translation %s.%s.%s" MSG(msg % (project_slug, resource_slug, language)) if not skip: raise
def _delete_translation(self, project_details, resource, stats, language): """Delete a specific translation from the specified resource.""" project_slug, resource_slug = resource.split('.') if language not in stats: if not self.skip: msg = "Skipping %s: Translation does not exist." logger.warning(msg % (language)) return if not self.force: teams = project_details['teams'] if language in teams: msg = ( "Skipping %s: Unable to delete translation because it is " "associated with a team.\nPlease use -f or --force option " "to delete this translation.") logger.warning(msg % language) return if int(stats[language]['translated_entities']) > 0: msg = ( "Skipping %s: Unable to delete translation because it " "is not empty.\nPlease use -f or --force option to delete " "this translation.") logger.warning(msg % language) return try: self.do_url_request('delete_translation', language=language, method="DELETE") msg = "Deleted language %s from resource %s of project %s." logger.info(msg % (language, resource_slug, project_slug)) except Exception, e: msg = "Unable to delete translation %s" logger.error(msg % language) if not self.skip: raise
def rename(): """Rename a resource.""" prj = project.Project(path_to_tx) res_old = request.form['elementid'] res_new = request.form['value'] # Raise error with invalid resource ID if res_new.count('.') != 1: error_msg = u"New resource ID should have one dot in it." flash(error_msg, 'error') logger.warning(error_msg) return(res_old) # Avoid deleting the same resource if unchanged: if res_new == res_old: return(res_old) logger.info("Renaming %s to %s" % (res_old, res_new)) prj.config._sections[res_new] = prj.config._sections[res_old] prj.config._sections.pop(res_old) prj.save() return res_new
def rename(): """Rename a resource.""" prj = project.Project(path_to_tx) res_old = request.form['elementid'] res_new = request.form['value'] # Raise error with invalid resource ID if res_new.count('.') != 1: error_msg = u"New resource ID should have one dot in it." flash(error_msg, 'error') logger.warning(error_msg) return (res_old) # Avoid deleting the same resource if unchanged: if res_new == res_old: return (res_old) logger.info("Renaming %s to %s" % (res_old, res_new)) prj.config._sections[res_new] = prj.config._sections[res_old] prj.config._sections.pop(res_old) prj.save() return res_new
def _delete_translation(self, project_details, resource, stats, language): """Delete a specific translation from the specified resource.""" project_slug, resource_slug = resource.split('.', 1) if language not in stats: if not self.skip: msg = "Skipping %s: Translation does not exist." logger.warning(msg % (language)) return if not self.force: teams = project_details['teams'] if language in teams: msg = ( "Skipping %s: Unable to delete translation because it is " "associated with a team.\nPlease use -f or --force option " "to delete this translation." ) logger.warning(msg % language) return if int(stats[language]['translated_entities']) > 0: msg = ( "Skipping %s: Unable to delete translation because it " "is not empty.\nPlease use -f or --force option to delete " "this translation." ) logger.warning(msg % language) return try: self.do_url_request( 'delete_translation', language=language, method="DELETE" ) msg = "Deleted language %s from resource %s of project %s." logger.info(msg % (language, resource_slug, project_slug)) except Exception as e: msg = "Unable to delete translation %s" logger.error(msg % language) if isinstance(e, SSLError) or not self.skip: raise
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 not answer 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 % 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 % (color_text(lang, "RED"), local_file)) continue msg = "Pushing '%s' translations (file: %s)" logger.warning( msg % (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 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' 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, 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 % (color_text(remote_lang, "RED"), local_file) ) continue if not overwrite: local_file = ("%s.new" % local_file) logger.warning( " -> %s: %s" % (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] 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" % (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] mkdir_p(base_dir) fd = open(local_file, 'wb') fd.write(r.encode(charset)) 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) self.skip = skip self.force = force for resource in resource_list: push_languages = [] 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) 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 = raw_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 not answer in ["", 'Y', 'y', "yes", 'YES']: return if source: if sfile == 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, e: if not skip: raise e else: logger.error(e) else: try: self.do_url_request('resource_details') except Exception, e: code = getattr(e, 'code', None) if code == 404: msg = "Resource %s doesn't exist on the server." logger.error(msg % resource) continue
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 % (color_text(lang, "RED"), local_file)) continue msg = "Pushing '%s' translations (file: %s)" logger.warning( msg % (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 Exception, e: if not skip: raise e else: logger.error(e)
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('.') 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) verify_ssl(host) 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 = raw_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 not answer 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, e: if not skip: raise else: logger.error(e) else: try: self.do_url_request('resource_details') except Exception, e: code = getattr(e, 'code', None) if code == 404: msg = "Resource %s doesn't exist on the server." logger.error(msg % resource) continue
def pull(self, languages=[], resources=[], overwrite=True, fetchall=False, fetchsource=False, force=False, skip=False, minimum_perc=0, mode=None): """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' else: url = 'pull_file' for resource in resource_list: logger.debug("Handling resource %s" % resource) self.resource = resource project_slug, resource_slug = resource.split('.') 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) verify_ssl(host) 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 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 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 % (color_text(remote_lang, "RED"), local_file)) continue if not overwrite: local_file = ("%s.new" % local_file) logger.warning(" -> %s: %s" % (color_text(remote_lang, "RED"), local_file)) try: r = self.do_url_request(url, language=remote_lang) except Exception, e: if not skip: raise e else: logger.error(e) continue base_dir = os.path.split(local_file)[0] mkdir_p(base_dir) fd = open(local_file, 'wb') fd.write(r) 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 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.decode('utf-8')) 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" % (color_text(remote_lang, "RED"), local_file)) r = self.do_url_request(url, 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()
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 % (color_text(lang, "RED"), local_file)) continue msg = "Pushing '%s' translations (file: %s)" logger.warning( msg % (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 Exception, e: if not skip: raise e else: logger.error(e)
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 not answer 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 % 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 % (color_text(lang, "RED"), local_file)) continue msg = "Pushing '%s' translations (file: %s)" logger.warning( msg % (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 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)