示例#1
0
    def parse_store(cls, storefile):
        # try to load the given file via openpyxl
        # catch at least the BadZipFile exception if an unsupported
        # file has been given
        try:
            workbook = load_workbook(filename=storefile)
            worksheet = workbook.active
        except BadZipFile:
            return None, None

        output = StringIO()

        writer = csv.writer(output, dialect="unix")

        for row in worksheet.rows:
            writer.writerow([cell.value for cell in row])

        if isinstance(storefile, str):
            name = os.path.basename(storefile) + ".csv"
        else:
            name = os.path.basename(storefile.name) + ".csv"

        # return the new csv as bytes
        content = output.getvalue().encode()

        # Load the file as CSV
        return super().parse_store(BytesIOMode(name, content))
示例#2
0
    def handle_replace(self, request, fileobj):
        """Replace file content with uploaded one."""
        filecopy = fileobj.read()
        fileobj.close()
        fileobj = BytesIOMode(fileobj.name, filecopy)
        with self.component.repository.lock:
            if self.is_source:
                self.component.commit_pending("replace file", request.user)
            else:
                self.commit_pending("replace file", request.user)
            # This will throw an exception in case of error
            store2 = self.load_store(fileobj)
            store2.check_valid()

            # Actually replace file content
            self.store.save_atomic(
                self.store.storefile, lambda handle: handle.write(filecopy)
            )

            # Commit to VCS
            previous_revision = (self.component.repository.last_revision,)
            if self.git_commit(
                request.user, request.user.get_author_name(), store_hash=False
            ):

                # Drop store cache
                self.drop_store_cache()
                self.handle_store_change(
                    request,
                    request.user,
                    previous_revision,
                    change=Change.ACTION_REPLACE_UPLOAD,
                )

        return (0, 0, self.unit_set.count(), len(list(store2.content_units)))
示例#3
0
    def handle_replace(self, request, fileobj):
        """Replace file content with uploaded one."""
        filecopy = fileobj.read()
        fileobj.close()
        fileobj = BytesIOMode(fileobj.name, filecopy)
        with self.component.repository.lock, transaction.atomic():
            self.commit_pending('replace file', request.user)
            # This will throw an exception in case of error
            store2 = self.load_store(fileobj)
            store2.check_valid()

            # Actually replace file content
            self.store.save_atomic(self.store.storefile,
                                   lambda handle: handle.write(filecopy))

            # Commit to VCS
            if self.repo_needs_commit():
                self.__git_commit(request.user.get_author_name(),
                                  timezone.now())

                # Drop store cache
                self.drop_store_cache()

                # Parse the file again
                if self.is_template:
                    self.component.create_translations(request=request,
                                                       force=True)
                else:
                    self.check_sync(force=True,
                                    request=request,
                                    change=Change.ACTION_UPLOAD)
                    self.invalidate_cache()

        return (0, 0, self.unit_set.count(), len(list(store2.content_units)))
示例#4
0
    def test_changed(self):
        self.edit_unit("Hello, world!\n", "Hi, World!\n", "en")
        response = self.client.get(
            reverse("download_translation", kwargs=self.kw_translation),
            {"format": "csv"},
        )
        self.assertEqual(
            response.content.decode(), EXPECTED_CSV.replace("Hello, world", "Hi, World")
        )

        handle = BytesIOMode(
            "test.csv", UPLOAD_CSV.replace("Hello, world", "Hi, World").encode()
        )
        params = {
            "file": handle,
            "method": "translate",
            "author_name": self.user.full_name,
            "author_email": self.user.email,
        }
        response = self.client.post(
            reverse("upload_translation", kwargs=self.kw_translation),
            params,
            follow=True,
        )
        self.assertContains(response, "(skipped: 0, not found: 0, updated: 1)")
示例#5
0
 def check_unit(self, nplurals=3, template=None, source_info=None, **kwargs):
     if nplurals == 3:
         formula = "n==0 ? 0 : n==1 ? 1 : 2"
     else:
         formula = "0"
     lang = Language.objects.create(code="zz")
     plural = Plural.objects.create(language=lang, number=nplurals, formula=formula)
     project = Project(slug="test")
     component = Component(
         slug="comp",
         project=project,
         file_format="xliff",
         template=template,
         source_language=Language.objects.get(code="en"),
     )
     translation = Translation(language=lang, component=component, plural=plural)
     # Fake file format to avoid need for actual files
     translation.store = EmptyFormat(BytesIOMode("", b""))
     unit = Unit(translation=translation, id_hash=-1, **kwargs)
     if source_info:
         for key, value in source_info.items():
             setattr(unit, key, value)
         # The dashes need special handling in XML based formats
         unit.__dict__["unresolved_comments"] = [
             Comment(comment="Weblate translator comment ---- ")
         ]
         unit.__dict__["suggestions"] = [
             Suggestion(target="Weblate translator suggestion")
         ]
     else:
         unit.__dict__["unresolved_comments"] = []
     unit.source_unit = unit
     exporter = self.get_exporter(lang, translation=translation)
     exporter.add_unit(unit)
     return self.check_export(exporter)
示例#6
0
 def check_unit(self, nplurals=3, template=None, **kwargs):
     if nplurals == 3:
         equation = 'n==0 ? 0 : n==1 ? 1 : 2'
     else:
         equation = '0'
     lang = Language.objects.create(
         code='zz',
     )
     plural = Plural.objects.create(
         language=lang,
         number=nplurals,
         equation=equation
     )
     project = Project(
         slug='test',
         source_language=Language.objects.get(code='en'),
     )
     component = Component(
         slug='comp',
         project=project,
         file_format='xliff',
         template=template
     )
     translation = Translation(
         language=lang,
         component=component,
         plural=plural,
     )
     # Fake file format to avoid need for actual files
     translation.store = EmptyFormat(BytesIOMode('', b''))
     unit = Unit(translation=translation, id_hash=-1, **kwargs)
     exporter = self.get_exporter(lang, translation=translation)
     exporter.add_unit(unit)
     return self.check_export(exporter)
示例#7
0
    def parse_store(cls, storefile):
        # try to load the given file via openpyxl
        # catch at least the BadZipFile exception if an unsupported
        # file has been given
        try:
            workbook = load_workbook(filename=storefile)
            worksheet = workbook.active
        except BadZipFile:
            return None, None

        if six.PY3:
            output = six.StringIO()
        else:
            output = six.BytesIO()

        writer = csv.writer(output)

        for row in worksheet.rows:
            writer.writerow([cls.encode(cell.value) for cell in row])

        if isinstance(storefile, six.string_types):
            name = os.path.basename(storefile) + ".csv"
        else:
            name = os.path.basename(storefile.name) + ".csv"

        # return the new csv as bytes
        content = output.getvalue()

        if six.PY3:
            content = content.encode("utf-8")

        # Load the file as CSV
        return super(XlsxFormat, cls).parse_store(BytesIOMode(name, content))
示例#8
0
文件: auto.py 项目: renatofb/weblate
def try_load(
    filename, content, original_format, template_store, as_template: bool = False
):
    """Try to load file by guessing type."""
    # Start with original format and translate-toolkit based autodetection
    formats = [original_format, AutodetectFormat]
    detected_format = detect_filename(filename)
    if detected_format is not None and detected_format != original_format:
        # Insert detected filename into most probable location. In case the extension
        # matches original, insert it after that as it is more likely that the upload
        # is in the original format (for example if component is monolingual PO file,
        # the uploaded PO file is more likely to be monolingual as well).
        formats.insert(
            1 if detected_format.extension() == original_format.extension() else 0,
            detected_format,
        )
    # Provide fallback to bilingual class in case using monolingual
    if (
        original_format.bilingual_class
        and original_format.bilingual_class != detected_format
    ):
        formats.insert(1, original_format.bilingual_class)
    failure = Exception("Bug!")
    for file_format in formats:
        if file_format.monolingual in (True, None) and (template_store or as_template):
            try:
                result = file_format.parse(
                    BytesIOMode(filename, content), template_store
                )
                result.check_valid()
                # Skip if there is untranslated unit
                # this can easily happen when importing bilingual
                # storage which can be monolingual as well
                if list(result.iterate_merge("")):
                    return result
            except Exception as error:
                failure = error
        if file_format.monolingual in (False, None):
            try:
                result = file_format.parse(BytesIOMode(filename, content))
                result.check_valid()
                return result
            except Exception as error:
                failure = error

    raise failure
示例#9
0
 def convertfile(storefile):
     store = pofile()
     # Fake input file with a blank filename
     htmlparser = htmlfile(includeuntaggeddata=False,
                           inputfile=BytesIOMode("", storefile.read()))
     for htmlunit in htmlparser.units:
         thepo = store.addsourceunit(htmlunit.source)
         thepo.addlocations(htmlunit.getlocations())
         thepo.addnote(htmlunit.getnotes(), "developer")
     store.removeduplicates("msgctxt")
     return store
示例#10
0
 def check_unit(self,
                nplurals=3,
                template=None,
                source_info=None,
                **kwargs):
     if nplurals == 3:
         equation = 'n==0 ? 0 : n==1 ? 1 : 2'
     else:
         equation = '0'
     lang = Language.objects.create(code='zz', )
     plural = Plural.objects.create(language=lang,
                                    number=nplurals,
                                    equation=equation)
     project = Project(
         slug='test',
         source_language=Language.objects.get(code='en'),
     )
     component = Component(slug='comp',
                           project=project,
                           file_format='xliff',
                           template=template)
     translation = Translation(
         language=lang,
         component=component,
         plural=plural,
     )
     # Fake file format to avoid need for actual files
     translation.store = EmptyFormat(BytesIOMode('', b''))
     unit = Unit(translation=translation, id_hash=-1, **kwargs)
     if source_info:
         for key, value in source_info.items():
             setattr(unit, key, value)
         unit.get_comments = fake_get_comments
         unit.__dict__['suggestions'] = [
             Suggestion(target='Weblate translator suggestion')
         ]
     else:
         unit.get_comments = empty_get_comments
     exporter = self.get_exporter(lang, translation=translation)
     exporter.add_unit(unit)
     return self.check_export(exporter)
示例#11
0
 def convertfile(storefile, template_store):
     store = pofile()
     # Fake input file with a blank filename
     htmlparser = htmlfile(inputfile=BytesIOMode("", storefile.read()))
     for htmlunit in htmlparser.units:
         locations = htmlunit.getlocations()
         if template_store:
             # Transalation
             template = template_store.find_unit_mono("".join(locations))
             if template is None:
                 # Skip locations not present in the source HTML file
                 continue
             # Create unit with matching source
             thepo = store.addsourceunit(template.source)
             thepo.target = htmlunit.source
         else:
             # Source file
             thepo = store.addsourceunit(htmlunit.source)
             thepo.target = htmlunit.source
         thepo.addlocations(htmlunit.getlocations())
         thepo.addnote(htmlunit.getnotes(), "developer")
     store.removeduplicates("msgctxt")
     return store
示例#12
0
 def validate_new_unit_data(  # noqa: C901
     self,
     context: str,
     source: Union[str, List[str]],
     target: Optional[Union[str, List[str]]] = None,
     auto_context: bool = False,
     extra_flags: Optional[str] = None,
 ):
     extra = {}
     if isinstance(source, str):
         source = [source]
     if isinstance(target, str):
         target = [target]
     if not self.component.has_template():
         extra["source"] = join_plural(source)
     if not auto_context and self.unit_set.filter(context=context, **extra).exists():
         raise ValidationError(_("This string seems to already exist."))
     # Avoid using source translations without a filename
     if not self.filename:
         try:
             translation = self.component.translation_set.exclude(pk=self.pk)[0]
         except IndexError:
             raise ValidationError(
                 _("Failed adding string: %s") % _("No translation found.")
             )
         translation.validate_new_unit_data(
             context,
             source,
             target,
             auto_context=auto_context,
             extra_flags=extra_flags,
         )
         return
     # Always load a new copy of store
     store = self.load_store()
     old_units = len(store.all_units)
     # Add new unit
     store.new_unit(context, source, target, skip_build=True)
     # Serialize the content
     handle = BytesIOMode("", b"")
     # Catch serialization error
     try:
         store.save_content(handle)
     except Exception as error:
         raise ValidationError(_("Failed adding string: %s") % error)
     handle.seek(0)
     # Parse new file (check that it is valid)
     try:
         newstore = self.load_store(handle)
     except Exception as error:
         raise ValidationError(_("Failed adding string: %s") % error)
     # Verify there is a single unit added
     if len(newstore.all_units) != old_units + 1:
         raise ValidationError(
             _("Failed adding string: %s") % _("Failed to parse new string")
         )
     # Find newly added unit (it can be on any position), but we assume
     # the storage has consistent ordering
     unit = None
     for pos, current in enumerate(newstore.all_units):
         if pos >= old_units or (
             current.source != store.all_units[pos].source
             and current.context != store.all_units[pos].context
         ):
             unit = current
             break
     # Verify unit matches data
     if unit is None:
         raise ValidationError(
             _("Failed adding string: %s") % _("Failed to parse new string")
         )
     created_source = split_plural(unit.source)
     if unit.context != context and (
         self.component.has_template()
         or self.component.file_format_cls.set_context_bilingual
     ):
         raise ValidationError(
             {"context": _('Context would be created as "%s"') % unit.context}
         )
     if created_source != source:
         raise ValidationError(
             {"source": _("Source would be created as %s") % created_source}
         )
示例#13
0
 def extract_document(content):
     return bytes(
         OpenDocumentFormat.convertfile(BytesIOMode("test.odt", content))
     ).decode()
示例#14
0
 def extract_document(content):
     return bytes(IDMLFormat.convertfile(BytesIOMode("test.idml", content))).decode()