Example #1
0
def normaliseAllPoFiles(filesGlob):
    if prefs['normalisePoFiles']:
        fileIndex = 0
        for fileName in sorted(filesGlob):
            fileIndex = fileIndex + 1
            poFile = polib.pofile(fileName)
            poFile.wrapwidth = 1024  # avoid re-wrapping
            poFile.check_for_duplicates = True
            print("\rNormalising translation files..." +
                  " {0:.0%}".format(float(fileIndex) /
                                    len(sorted(filesGlob)))),
            sys.stdout.flush()

            for cacheEntry in sorted(occurrencesCache, key=lambda r: r[0]):
                matchedEntries = [
                    e for e in poFile if e.msgid == polib.unescape(cacheEntry)
                ]
                if len(matchedEntries) == 0 and len(
                        occurrencesCache[cacheEntry]) > 0:
                    try:
                        newEntry = polib.POEntry(
                            msgid=polib.unescape(cacheEntry),
                            msgstr="",
                            occurrences=occurrencesCache[cacheEntry],
                            tcomment="normalised")
                        poFile.append(newEntry)
                    except:
                        pass
                elif len(matchedEntries) == 1 and matchedEntries[0].obsolete:
                    # matchedEntries[0].obsolete = False
                    pass
            poFile.save(fileName + prefs['newFileExt'])
Example #2
0
def dump_po(project, locale):
    """Update .po (gettext) files from database."""

    locale_paths = get_locale_paths(project, locale)

    for path in locale_paths:
        po = polib.pofile(path)
        date = datetime.datetime(1, 1, 1)
        newest = Translation()
        relative_path = get_relative_path(path, locale)
        resource = Resource.objects.filter(project=project, path=relative_path)
        entities = Entity.objects.filter(resource=resource, obsolete=False)

        for entity in entities:
            entry = po.find(polib.unescape(smart_text(entity.string)))
            if entry:
                if not entry.msgid_plural:
                    translation = get_translation(entity=entity, locale=locale)
                    if translation.string != '':
                        entry.msgstr = polib.unescape(translation.string)
                        if translation.date > date:
                            date = translation.date
                            newest = translation
                        if ('fuzzy' in entry.flags and not translation.fuzzy):
                            entry.flags.remove('fuzzy')

                else:
                    for i in range(0, 6):
                        if i < (locale.nplurals or 1):
                            translation = get_translation(
                                entity=entity, locale=locale, plural_form=i)
                            if translation.string != '':
                                entry.msgstr_plural[unicode(i)] = \
                                    polib.unescape(translation.string)
                                if translation.date > date:
                                    date = translation.date
                                    newest = translation
                                if ('fuzzy' in entry.flags and
                                   not translation.fuzzy):
                                    entry.flags.remove('fuzzy')
                        # Remove obsolete plural forms if exist
                        else:
                            if unicode(i) in entry.msgstr_plural:
                                del entry.msgstr_plural[unicode(i)]

        # Update PO metadata
        if newest.id:
            po.metadata['PO-Revision-Date'] = newest.date
            if newest.user:
                po.metadata['Last-Translator'] = '%s <%s>' \
                    % (newest.user.first_name, newest.user.email)
        po.metadata['Language'] = locale.code
        po.metadata['X-Generator'] = 'Pontoon'

        if locale.nplurals:
            po.metadata['Plural-Forms'] = 'nplurals=%s; plural=%s;' \
                % (str(locale.nplurals), locale.plural_rule)

        po.save()
        log.debug("File updated: " + path)
Example #3
0
 def validate(self, old, new):
     old = unescape(old)
     new = unescape(new)
     for c in self.bracket_chars:
         if new.count(c) != old.count(c):
             raise ValidationError(
                 _("Translation string doesn't contain the same "
                   "number of '%s' as the source string." % c))
Example #4
0
 def validate(self, old, new):
     old = unescape(old)
     new = unescape(new)
     for email in self.emails.findall(old):
         if email not in new:
             raise ValidationError(
                 _("The following email is either missing from the"
                   " translation or has been translated: '%s'." % email))
Example #5
0
 def validate(self, old, new):
     old = unescape(old)
     new = unescape(new)
     for email in self.emails.findall(old):
         if email not in new:
             raise ValidationError(
                 _("The following email is either missing from the"
                   " translation or has been translated: '%s'." % email)
             )
Example #6
0
 def validate(self, old, new):
     old = unescape(old)
     new = unescape(new)
     for c in self.bracket_chars:
         if new.count(c) != old.count(c):
             raise ValidationError(
                 _("Translation string doesn't contain the same "
                   "number of '%s' as the source string." % c)
             )
Example #7
0
 def validate(self, old, new):
     old = unescape(old)
     new = unescape(new)
     old_matches = list(self.printf_re.finditer(old))
     new_matches = list(self.printf_re.finditer(new))
     if len(old_matches) != len(new_matches):
         raise ValidationError("The number of arguments seems to differ "
                               "between the source string and the translation."
             )
Example #8
0
 def validate(self, old, new):
     old = unescape(old)
     new = unescape(new)
     old_matches = list(self.printf_re.finditer(old))
     new_matches = list(self.printf_re.finditer(new))
     if len(old_matches) != len(new_matches):
         raise ValidationError(
             "The number of arguments seems to differ "
             "between the source string and the translation.")
Example #9
0
 def validate(self, old, new):
     old = unescape(old)
     new = unescape(new)
     for num in self.numbers.findall(old):
         if num not in new:
             num = num.replace('.', ',', 1)
             if num not in new:
                 raise ValidationError(
                     _("Number %s is in the source string but not "
                       "in the translation." % num))
Example #10
0
    def validate(self, source_trans, target_trans):
        """Check, if all printf-format expressions in the source translation
        are in the target translation, too.

        We are interested in the conversion specifier and the positional
        key (if any). See ``printf(3)`` for details.

        So, we check, whether *every* conversion specifier found in
        the source translation exists in the target translation, too.
        Additionally, if there are positional keys, whether those
        found in the source translation exist in the target translation,
        as well.

        We raise a ``ValidationError``, whenever one of the
        conditions is not met.

        Args:
            source_trans: The source translation.
            target_trans: The target translation.
        Raises:
            ValidationError, in case the translation is not valid.
        """
        source_trans = unescape(source_trans)
        target_trans = unescape(target_trans)
        source_matches = list(self.printf_re.finditer(source_trans))
        target_matches = list(self.printf_re.finditer(target_trans))

        # We could use just one list comprehension:
        #
        # target_data = [
        #     (pattern.group('type'), pattern.group('key'))
        #     for pattern in target_matches
        # ]
        # target_specifiers, target_keys = map(
        #     list, zip(*target_data)
        # ) or [[], []]
        #
        # but that would probably be less efficient, since target_matches
        # should ususally have 0 - 5 elements, and much less readable.
        # So, we do it in two steps.
        target_specifiers = [pat.group('type') for pat in target_matches]
        target_keys = [pattern.group('key') for pattern in target_matches]

        for pattern in source_matches:
            key = pattern.group('key')
            if key not in target_keys:
                msg = "The expression '%s' is not present in the translation."
                raise ValidationError( _(msg  % pattern.group(0)))

            conversion_specifier = pattern.group('type')
            try:
                target_specifiers.remove(conversion_specifier)
            except ValueError:
                msg = "The expression '%s' is not present in the translation."
                raise ValidationError( _(msg  % pattern.group(0)))
Example #11
0
    def validate(self, source_trans, target_trans):
        """Check, if all printf-format expressions in the source translation
        are in the target translation, too.

        We are interested in the conversion specifier and the positional
        key (if any). See ``printf(3)`` for details.

        So, we check, whether *every* conversion specifier found in
        the source translation exists in the target translation, too.
        Additionally, if there are positional keys, whether those
        found in the source translation exist in the target translation,
        as well.

        We raise a ``ValidationError``, whenever one of the
        conditions is not met.

        Args:
            source_trans: The source translation.
            target_trans: The target translation.
        Raises:
            ValidationError, in case the translation is not valid.
        """
        source_trans = unescape(source_trans)
        target_trans = unescape(target_trans)
        source_matches = list(self.printf_re.finditer(source_trans))
        target_matches = list(self.printf_re.finditer(target_trans))

        # We could use just one list comprehension:
        #
        # target_data = [
        #     (pattern.group('type'), pattern.group('key'))
        #     for pattern in target_matches
        # ]
        # target_specifiers, target_keys = map(
        #     list, zip(*target_data)
        # ) or [[], []]
        #
        # but that would probably be less efficient, since target_matches
        # should ususally have 0 - 5 elements, and much less readable.
        # So, we do it in two steps.
        target_specifiers = [pat.group('type') for pat in target_matches]
        target_keys = [pattern.group('key') for pattern in target_matches]

        for pattern in source_matches:
            key = pattern.group('key')
            if key not in target_keys:
                msg = "The expression '%s' is not present in the translation."
                raise ValidationError(_(msg % pattern.group(0)))

            conversion_specifier = pattern.group('type')
            try:
                target_specifiers.remove(conversion_specifier)
            except ValueError:
                msg = "The expression '%s' is not present in the translation."
                raise ValidationError(_(msg % pattern.group(0)))
Example #12
0
 def validate(self, old, new):
     old = unescape(old)
     new = unescape(new)
     old_has_newline = old[-1] == '\n'
     new_has_newline = new[-1] == '\n'
     if old_has_newline != new_has_newline:
         if old_has_newline:
             msg = _("Translation must end with a newline (\\n)")
         else:
             msg = _("Translation should not end with a newline (\\n)")
         raise ValidationError(msg)
Example #13
0
 def validate(self, old, new):
     old = unescape(old)
     new = unescape(new)
     old_has_newline = old[-1] == '\n'
     new_has_newline = new[-1] == '\n'
     if old_has_newline != new_has_newline:
         if old_has_newline:
             msg = _("Translation must end with a newline (\\n)")
         else:
             msg = _("Translation should not end with a newline (\\n)")
         raise ValidationError(msg)
Example #14
0
 def validate(self, old, new):
     old = unescape(old)
     new = unescape(new)
     for num in self.numbers.findall(old):
         if num not in new:
             num = num.replace('.', ',', 1)
             if num not in new:
                 raise ValidationError(
                     _("Number %s is in the source string but not "
                       "in the translation." % num)
                 )
Example #15
0
def _save_translation(source_string, translations, target_language, user):
    """Save a translation string to the database.

    This functions handle a signle source entity translation
    (could be pluralized).

    Currently, the function only returns warning strings.
    There is no message for success.

    Args:
        source_string: A Translation object of the string in the source
            language.
        translations: A (rule, string) tuple.
        target_language: The language the string is translated to.
        user: The translator.
    Returns:
        A list if strings to display to the user.
    Raises:
        An LotteBadRequestError exception in case of errors.
    """
    source_id = source_string.pk
    resource = source_string.source_entity.resource
    source_language = resource.source_language
    warnings = []

    for rule, target_string in translations.items():
        rule = target_language.get_rule_num_from_name(rule)
        if rule != 5:
            # fetch correct source string for plural rule
            try:
                source_string = Translation.objects.get(
                    source_entity=source_string.source_entity,
                    language=source_language, rule=rule
                )
            except Translation.DoesNotExist:
                # target language has extra plural forms
                pass
        ss = unescape(source_string.string)
        tr = unescape(target_string)

        # check for errors
        try:
            for ErrorValidator in create_error_validators(resource.i18n_type):
                v = ErrorValidator(source_language, target_language, rule)
                v(ss, tr)
        except ValidationError, e:
            raise LotteBadRequestError(e.message)
        # check for warnings
        for WarningValidator in create_warning_validators(resource.i18n_type):
            v = WarningValidator(source_language, target_language, rule)
            try:
                v(ss, tr)
            except ValidationError, e:
                warnings.append(e.message)
Example #16
0
File: tests.py Project: H0bby/polib
 def test_unescape(self):
     """
     Tests the unescape function.
     """
     self.assertEqual(
         polib.unescape('\\\\t and \\\\n and \\\\r and \\\\" and \\\\\\\\'),
         '\\t and \\n and \\r and \\" and \\\\')
Example #17
0
def solve(new_file: str, old_file: str, arguments):
    """ Translates single file. """
    lines = read_lines(old_file)
    for line in lines:
        line.msgstr = polib.unescape(
            translate(polib.escape(line.msgid), arguments))
        print(f"Translated {lines.percent_translated()}% of the lines.")
    save_lines(new_file, lines)
Example #18
0
 def test_unescape(self):
     """
     Tests the unescape function.
     """
     self.assertEqual(
         polib.unescape('\\\\t and \\\\n and \\\\r and \\\\" and \\\\\\\\'),
         '\\t and \\n and \\r and \\" and \\\\'
     )
Example #19
0
def parse_msg(lines):
    " Extracts msgid or msgstr from lines."
    if len(lines) < 1:
        return ''
    i = lines[0].find('"')
    if i < 0:
        return ''
    msg = lines[0][i:].strip('"')
    for i in range(1, len(lines)):
        j = lines[i].find('"')
        if j < 0:
            return ''
        msg = msg + lines[i][j:].strip('"')
    return polib.unescape(msg)
Example #20
0
def parse_msg(lines):
    " Extracts msgid or msgstr from lines."
    if len(lines) < 1:
        return ''
    i = lines[0].find('"')
    if i < 0:
        return ''
    msg = lines[0][i:].strip('"')
    for i in range(1, len(lines)):
        j = lines[i].find('"')
        if j < 0:
            return ''
        msg = msg + lines[i][j:].strip('"')
    return polib.unescape(msg)
Example #21
0
def read(glos, filename):
    fp = open(filename, 'rb')
    word = ''
    defi = ''
    msgstr = False
    for line in fp:
        if not line:
            if word:
                glos.addEntry(word, defi)
                word = ''
                defi = ''
            break
        line = line.strip()
        if not line:
            continue
        if line.startswith('#'):
            continue
        if line.startswith('msgid '):
            if word:
                glos.addEntry(word, defi)
                word = ''
                defi = ''
            word = unescape(line[6:])
            msgstr = False
        elif line.startswith('msgstr '):
            if msgstr:
                log.error('msgid omitted!')
            defi = unescape(line[7:])
            msgstr = True
        else:
            if msgstr:
                defi += unescape(line)
            else:
                word += unescape(line)
    if word:
        glos.addEntry(word, defi)
Example #22
0
def create_terminal_quest_assets(podir, lang):
    print("Creating terminal quest assets")
    pofile = os.path.join(podir, lang, "assets.po")
    po = polib.pofile(pofile)
    with tempfile.TemporaryDirectory() as tmpdirname:
        for entry in po:
            for filename in entry.occurrences:
                f = open(os.path.join(tmpdirname, filename[0]), "w")
                value = entry.msgstr if entry.translated() else entry.msgid
                f.write(polib.unescape(value))
                f.close
        # SCP directory
        copy_terminal_quest_assets(tmpdirname, lang)

    # We don't need the assets.po file anymore
    os.remove(pofile)
                    line = NSIWorkingFile.readline()
                    lineNo += 1
                    while line != '':
                        line = removeEscapedNewLine(line)
                        end = line.find('"')
                        if end != -1:  #If we found the closing character, append
                            value += line[:end].lstrip()
                            break
                        else:  #If not, append and continue
                            value += line.lstrip()
                        line = NSIWorkingFile.readline()
                        lineNo += 1

            # Remove whitespace and new lines
            value = value.strip("\t\n")
            value = polib.unescape(value)
            if not value in LangStringCache:
                LangStringCache[value] = []
            # Note down our file and line number
            LangStringCache[value].append([options.input, lineNo])

            if not value in LangStringLabels:
                LangStringLabels[value] = []
            # Note down our label
            LangStringLabels[value].append(label)

    line = NSIWorkingFile.readline()
    lineNo += 1

# Now, we loop through our cache and build PO entries for each
# We use PO comment field to store our NSIS labels, so we can decode it back later
Example #24
0
 def validate(self, old, new):
     new = unescape(new)
     if len(new.strip()) == 0:
         raise ValidationError(
             _("Translation string only contains whitespaces."))
                    line = NSIWorkingFile.readline()
                    lineNo += 1
                    while line != '':
                        line = removeEscapedNewLine(line)
                        end = line.find('"')
                        if end != -1: #If we found the closing character, append
                            value += line[:end].lstrip()
                            break
                        else: #If not, append and continue
                            value += line.lstrip()
                        line=NSIWorkingFile.readline()
                        lineNo += 1

            # Remove whitespace and new lines
            value = value.strip("\t\n")
            value = polib.unescape ( value )
            if not value in LangStringCache:
                LangStringCache[value] = []
            # Note down our file and line number
            LangStringCache[value].append([options.input,lineNo])

            if not value in LangStringLabels:
                LangStringLabels[value] = []
            # Note down our label
            LangStringLabels[value].append(label)
            
    line=NSIWorkingFile.readline()
    lineNo += 1

# Now, we loop through our cache and build PO entries for each
# We use PO comment field to store our NSIS labels, so we can decode it back later
Example #26
0
    if os.path.isfile(filename):
        print(filename + " already exists, we skip it")
        continue

    context = entry.comment

    currentNews = {}
    if news.get(filename):
        currentNews = news.get(filename)

    if "title" in context:
        currentNews['title'] = entry.msgstr
        currentNews['originalFilename'] = originalFilename
    else:
        currentNews[polib.unescape(entry.msgid)] = polib.unescape(entry.msgstr)

    news[filename] = currentNews
# for all news we have in the pot file, we create the corresponding html 
# translated file
for currentNews in news:
    if not 'title' in news[currentNews] or news[currentNews]['title'] == "":
        print("Skip news", currentNews)
        continue

    print("Creating", currentNews)

    # Read in the file
    with open(news[currentNews]['originalFilename'], "r", encoding="utf-8") as originalFile:
        fileData = originalFile.read()
Example #27
0
 def validate(self, old, new):
     new = unescape(new)
     if len(new.strip()) == 0:
         raise ValidationError(
             _("Translation string only contains whitespaces.")
         )