def create_locale_directory(self, locale, path): if not self.db_project.has_multi_locale_repositories: source_directory = self.source_directory_path() parent_directory = os.path.abspath(os.path.join(source_directory, os.pardir)) locale_directory = os.path.join(parent_directory, locale.code.replace('-', '_')) # For asymmetric formats, create empty folder if is_asymmetric_resource(path): os.makedirs(locale_directory) # For other formats, copy resources from source directory else: shutil.copytree(source_directory, locale_directory) for root, dirnames, filenames in os.walk(locale_directory): for filename in filenames: path = os.path.join(root, filename) if is_resource(filename): os.rename(path, source_to_locale_path(path)) else: os.remove(path) return locale_directory else: raise MissingLocaleDirectoryError( 'Directory for locale `{0}` not found'.format(locale.code) )
def locale_directory_paths(self): """ A map of locale codes and their absolute directory paths. Create locale directory, if not in repository yet. """ locale_directory_paths = {} parent_directories = set() for locale in self.locales: try: if self.configuration: locale_directory_paths[locale.code] = self.configuration.l10n_base else: locale_directory_paths[locale.code] = locale_directory_path( self.checkout_path, locale.code, parent_directories, ) parent_directory = get_parent_directory( locale_directory_paths[locale.code] ) except IOError: if not self.db_project.has_multi_locale_repositories: source_directory = self.source_directory_path parent_directory = get_parent_directory(source_directory) locale_code = locale.code if uses_undercore_as_separator(parent_directory): locale_code = locale_code.replace("-", "_") locale_directory = os.path.join(parent_directory, locale_code) # For asymmetric formats, create empty folder if is_asymmetric_resource(next(self.relative_resource_paths())): os.makedirs(locale_directory) # For other formats, copy resources from source directory else: shutil.copytree(source_directory, locale_directory) for root, dirnames, filenames in scandir.walk(locale_directory): for filename in filenames: path = os.path.join(root, filename) if is_resource(filename): os.rename(path, source_to_locale_path(path)) else: os.remove(path) locale_directory_paths[locale.code] = locale_directory else: raise MissingLocaleDirectoryError( "Directory for locale `{0}` not found".format(locale.code) ) parent_directories.add(parent_directory) return locale_directory_paths
def locale_directory_paths(self): """ A map of locale codes and their absolute directory paths. Create locale directory, if not in repository yet. """ locale_directory_paths = {} parent_directories = set() for locale in self.locales: try: if self.configuration: locale_directory_paths[locale.code] = self.configuration.l10n_base else: locale_directory_paths[locale.code] = locale_directory_path( self.checkout_path, locale.code, parent_directories, ) parent_directory = get_parent_directory(locale_directory_paths[locale.code]) except IOError: if not self.db_project.has_multi_locale_repositories: source_directory = self.source_directory_path parent_directory = get_parent_directory(source_directory) locale_code = locale.code if uses_undercore_as_separator(parent_directory): locale_code = locale_code.replace('-', '_') locale_directory = os.path.join(parent_directory, locale_code) # For asymmetric formats, create empty folder if is_asymmetric_resource(next(self.relative_resource_paths())): os.makedirs(locale_directory) # For other formats, copy resources from source directory else: shutil.copytree(source_directory, locale_directory) for root, dirnames, filenames in scandir.walk(locale_directory): for filename in filenames: path = os.path.join(root, filename) if is_resource(filename): os.rename(path, source_to_locale_path(path)) else: os.remove(path) locale_directory_paths[locale.code] = locale_directory else: raise MissingLocaleDirectoryError( 'Directory for locale `{0}` not found'.format(locale.code) ) parent_directories.add(parent_directory) return locale_directory_paths
def relative_resource_paths(self): """ List of paths relative to the locale directories returned by self.source_directory_path for each resource in this project. """ path = self.source_directory_path for absolute_path in self.resources_for_path(path): absolute_path = source_to_locale_path(absolute_path) yield os.path.relpath(absolute_path, path)
def relative_resource_paths(self): """ List of all source resource paths, relative to source_directory_path. """ if self.configuration: paths = self.resource_paths_with_config() else: paths = self.resource_paths_without_config() for path in paths: path = source_to_locale_path(path) yield os.path.relpath(path, self.source_directory_path)
def get_download_content(slug, code, part): """ Get content of the file to be downloaded. :arg str slug: Project slug. :arg str code: Locale code. :arg str part: Resource path or Subpage name. """ # Avoid circular import; someday we should refactor to avoid. from pontoon.sync import formats from pontoon.sync.utils import source_to_locale_path from pontoon.sync.vcs.models import VCSProject from pontoon.base.models import Entity, Locale, Project, Resource project = get_object_or_404(Project, slug=slug) locale = get_object_or_404(Locale, code=code) vcs_project = VCSProject(project, locales=[locale]) # Download a ZIP of all files if project has > 1 and < 10 resources resources = Resource.objects.filter(project=project, translatedresources__locale=locale) isZipable = 1 < len(resources) < 10 if isZipable: s = io.BytesIO() zf = zipfile.ZipFile(s, "w") # Download a single file if project has 1 or >= 10 resources else: relative_path = _get_relative_path_from_part(slug, part) resources = [ get_object_or_404(Resource, project__slug=slug, path=relative_path) ] locale_prefixes = project.repositories if not project.configuration_file: locale_prefixes = locale_prefixes.filter( permalink_prefix__contains="{locale_code}") locale_prefixes = locale_prefixes.values_list("permalink_prefix", flat=True).distinct() source_prefixes = project.repositories.values_list("permalink_prefix", flat=True).distinct() for resource in resources: # Get locale file dirnames = set([locale.code, locale.code.replace("-", "_")]) locale_path = _download_file(locale_prefixes, dirnames, vcs_project, resource.path) if not locale_path and not resource.is_asymmetric: return None, None # Get source file if needed source_path = None if resource.is_asymmetric: dirnames = VCSProject.SOURCE_DIR_NAMES source_path = _download_file(source_prefixes, dirnames, vcs_project, resource.path) if not source_path: return None, None # If locale file doesn't exist, create it if not locale_path: extension = os.path.splitext(resource.path)[1] with tempfile.NamedTemporaryFile( prefix="strings" if extension == ".xml" else "", suffix=extension, delete=False, ) as temp: temp.flush() locale_path = temp.name # Update file from database resource_file = formats.parse(locale_path, source_path) entities_dict = {} entities_qs = Entity.objects.filter( changedentitylocale__locale=locale, resource__project=project, resource__path=resource.path, obsolete=False, ) for e in entities_qs: entities_dict[e.key] = e.translation_set.filter(approved=True, locale=locale) for vcs_translation in resource_file.translations: key = vcs_translation.key if key in entities_dict: entity = entities_dict[key] vcs_translation.update_from_db(entity) resource_file.save(locale) if not locale_path: return None, None if isZipable: zf.write(locale_path, source_to_locale_path(resource.path)) else: with codecs.open(locale_path, "r", "utf-8") as f: content = f.read() filename = os.path.basename(source_to_locale_path(resource.path)) # Remove temporary files os.remove(locale_path) if source_path: os.remove(source_path) if isZipable: zf.close() content = s.getvalue() filename = project.slug + ".zip" return content, filename