def compilePO(self, po): #compile into Lua code output = io.StringIO() output.write('{\n') idSet = {} for entry in po: if entry.msgid_plural: #TODO: plural support msgid = polib.escape(entry.msgid_plural) output.write('\t["%s"] = { \n' % msgid) for k, s in entry.msgstr_plural.items(): msgstr = polib.escape(s) if msgstr: msgstr = msgstr.replace('\\r', '') output.write('\t\t["%s"] = "%s",\n' % (k, msgstr)) output.write('\t};\n') else: msgid = polib.escape(entry.msgid) msgstr = polib.escape(entry.msgstr) if msgstr: msgstr = msgstr.replace('\\r', '') output.write('\t["%s"] = "%s";\n' % (msgid, msgstr)) if idSet.get(msgid, None): logging.warning('entry Id duplicated: %s, %s' % (msgid, self.packPath)) idSet[msgid] = True output.write('\t};\n') return output.getvalue()
def makeLocaleOverview(outputPath, packPath, pofiles, basePofiles): # output = cStringIO.StringIO() output = open(outputPath, mode='w', encoding='utf-8') output.writelines([ OVERVIEW_HEAD, '<body>' '<title>PACK NAME: %s</title>' % packPath, '<title>DATE: %s</title>' % time.strftime('%H:%M:%S %Z %A %Y-%m-%d '), ]) for name, po in pofiles.items(): fileOutput = io.StringIO() count = 0 basePO = None if basePofiles: basePO = basePofiles.get(name, None) for entry in po: count += 1 if entry.msgid_plural: #TODO: plural support pass else: msgid = polib.escape(entry.msgid) msgstr = polib.escape(entry.msgstr) msgctxt = polib.escape(entry.msgctxt) if (not msgstr) and basePO: baseEntry = basePO.find(msgid) if baseEntry: msgstr2 = polib.escape(baseEntry.msgstr) if msgstr2: msgstr = msgstr2 fileOutput.write('<entry>\n') fileOutput.write('<id>id:%s</id>\n' % msgid) if msgctxt: fileOutput.write('<ctx>ctx:%s</ctx>\n' % msgctxt) if msgstr: fileOutput.write('<text><pre>') msgstr = msgstr.replace('\\n', '\n') msgstr = msgstr.replace('\\t', '\t') fileOutput.write('%s\n' % msgstr) fileOutput.write('</pre></text>') fileOutput.write('</entry>\n') output.writelines([ '\n', '<file>\n', '<info>FILE: %s</info>\n' % name, '<info>count: %d</info>\n' % count, '<entries/>\n' ]) output.write(fileOutput.getvalue()) output.write('\n') output.write('</entries></file>\n') output.write('</body>\n') output.write(OVERVIEW_FOOT) output.close()
def validate(self, old, new): old = escape(old) new = escape(new) old_matches = list(self.printf_re.finditer(old)) new_matches = list(self.printf_re.finditer(new)) for pattern in new_matches: if pattern.group(0) not in old: raise ValidationError( _('The expression \'%s\' is not present ' 'in the source string.' % pattern.group(0)) )
def process_po(path, output): po = polib.pofile(path) output.write(u'(function(){{\nvar a={0}["{1}"]={0}["{1}"]||{{}};a=a["{2}"]=a["{2}"]||{{}};\n'.format(CATALOG_VAR, polib.escape(u'messages'), polib.escape(po.metadata[u'Language']))) pl = get_plural_form(po.metadata[u'Plural-Forms']) output.write(u'var b=a.messages=a.messages||{{}};a.nplurals={0};a.plural=function(n){{return {1}}};\n'.format(pl[0], pl[1])) for e in po: output.write(u'b["{0}"]={{'.format(polib.escape(e.msgid))) output.write(u'msgstr:"{0}",msgstr_plural:{{'.format(polib.escape(e.msgstr))) for k in e.msgstr_plural: output.write(u'{0}:"{1}",'.format(k, polib.escape(e.msgstr_plural[k]))) output.write(u'}};\n') output.write(u'})();\n')
def write(glos, filename): fp = open(filename, 'wb') fp.write('#\nmsgid ""\nmsgstr ""\n') for inf in glos.infoKeys(): fp.write('"%s: %s\\n"\n' % (inf, glos.getInfo(inf))) for entry in glos: word = entry.getWord() defi = entry.getDefi() fp.write('msgid %s\nmsgstr %s\n\n' % ( escape(word), escape(defi), )) fp.close()
def traducir(cadea): """ Traduce unha cadea do inglés ao galego, empregando apertium Parámetros: cadea -- Cadea a traducir """ cadea = polib.escape(cadea.encode('utf-8')) cmd = 'echo -n "%s" | apertium en-es -u | apertium es-gl -u ' % cadea f = os.popen(cmd) traducion = f.read() traducion = polib.escape(unicode(traducion, "utf-8")) return traducion
def test_escape(self): """ Tests the escape function. """ self.assertEqual( polib.escape('\\t and \\n and \\r and " and \\ and \\\\'), '\\\\t and \\\\n and \\\\r and \\" and \\\\ and \\\\\\\\')
def isFoundInFile(msgid, data): isFound = False regex_msgid = r'["\'](' + re.escape(msgid) + '|' + re.escape( polib.escape(msgid)) + ')["\']' if re.search(regex_msgid, data): isFound = True return isFound
def searchCodebaseForOccurrences(poFile): if prefs['searchCodebaseForOccurrences']: unCachedEntries = getUncachedEntries(poFile) if len(unCachedEntries) > 0: print("Searching for %d occurrences..." % len(unCachedEntries)) for root, dirs, files in os.walk(codeBasePath, topdown=True, onerror=None): for fPath in getIncludedExcludedPaths(root, dirs, files): fPath = os.path.abspath(fPath) if fPath in nonTranslatableFiles: continue indicateProgress() sys.stdout.flush() try: size = os.stat(fPath).st_size f2 = open(fPath) data = mmap.mmap(f2.fileno(), size, access=mmap.ACCESS_READ) if not isFileTranslatable(fPath, data): continue entryIndex = 0 for poEntry in unCachedEntries: entryIndex = entryIndex + 1 if prefs['processMaxEntries'] > 0: if entryIndex > prefs['processMaxEntries']: break encodedMsgid = polib.escape(poEntry.msgid) try: poEntry.occurrences = occurrencesCache[ encodedMsgid] except KeyError: occurrencesCache[encodedMsgid] = [] if isFoundInFile(poEntry.msgid, data): fPathSplit = fPath.split('/') fPathLastPart = fPathSplit[len(fPathSplit) - 1] if fPathLastPart.lower() in [ "plugin.py", "__init__.py" ]: fPathLastPart = fPathSplit[len( fPathSplit) - 2] + "/" + fPathLastPart occurrencesCache[ encodedMsgid] = occurrencesCache[ encodedMsgid] + [(fPathLastPart, None)] poEntry.occurrences = occurrencesCache[ encodedMsgid] else: tcomment = "not found in source code" except UnicodeDecodeError: # found non-text data pass except ValueError: # possibly an empty file pass finally: data = None
def spellcheck(request, project_slug, lang_code, resource_slug=None): """ Shows mispelled words along with suggestions """ data = simplejson.loads(request.raw_post_data) lang_code = lang_code.encode('utf-8') string = escape(data["text"]) string_ = string string = string.encode('utf-8') lang_codes = SPELLCHECK_SUPPORTED_LANGS if lang_code in lang_codes: xmlData = '''<?xml version="1.0" encoding="UTF-8" ?> <spellrequest textalreadyclipped="0" ignoredups="1" ignoredigits="1" ignoreallcaps="1" suggestedlang="%s"> <text>%s</text> </spellrequest>'''%(lang_code, string) headers = {"Content-type": "text/xml; charset=utf-8", "Request-number":"1", "Document-type":"Request", "Connection":"close"} con = httplib.HTTPSConnection('www.google.com') con.request('POST', '/tbproxy/spell?lang=%s'%(lang_code), xmlData, headers) response = con.getresponse().read().decode('utf-8') pattern = re.compile(r'<c o="(?P<o>\d*)" l="(?P<l>\d*)" s="\d*">(?P<suggestions>[^<]*)<\/c>', re.UNICODE) matches = pattern.findall(response) d = [] for i in matches: o = int(i[0]) l = int(i[1]) suggestions = i[2].split('\t') word = string_[o:o+l].strip() d.append([word, suggestions]) else: d = [] json_dict = simplejson.dumps(d, 'utf-8') return HttpResponse(json_dict, mimetype='application/json')
def __add_entry(self, msg: str, lineno: Optional[int] = None, is_docstring: bool = False) -> None: if lineno is None: lineno: int = self.__lineno entry = next( (entry for entry in self.__cur_potfile if entry.msgid == msg), None) occurrence = (str(self.__cur_infile), lineno) if is_docstring: flags = ["docstring"] else: flags = [] if entry is None: self.__cur_potfile.append( polib.POEntry( msgid=polib.escape(msg), occurrences=[occurrence], flags=flags, )) else: entry.occurrences.append(occurrence) entry.occurrences.sort()
def test_escape(self): """ Tests the escape function. """ self.assertEqual( polib.escape('\\t and \\n and \\r and " and \\ and \\\\'), '\\\\t and \\\\n and \\\\r and \\" and \\\\ and \\\\\\\\' )
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)
def getUncachedEntries(poFile): entryIndex = 0 unCachedEntries = [] for entry in poFile: entryIndex = entryIndex + 1 if prefs['processMaxEntries'] > 0: if entryIndex > prefs['processMaxEntries']: break if entry.msgid == " ": entry.tcomment = "DO NOT TRANSLATE!" elif (re.match("^#[a-fA-F0-9]{6,8}", entry.msgid)): entry.tcomment = "Remove from translation (hex colour value)" entry.obsolete = True else: if (polib.escape(entry.msgid) in [o for o in occurrencesCache]): entry.occurrences = occurrencesCache[polib.escape(entry.msgid)] else: unCachedEntries.append(entry) return unCachedEntries
def process_po(path, output): po = polib.pofile(path) output.write( u'(function(){{\nvar a={0}["{1}"]={0}["{1}"]||{{}};a=a["{2}"]=a["{2}"]||{{}};\n' .format(CATALOG_VAR, polib.escape(u'messages'), polib.escape(po.metadata[u'Language']))) pl = get_plural_form(po.metadata[u'Plural-Forms']) output.write( u'var b=a.messages=a.messages||{{}};a.nplurals={0};a.plural=function(n){{return {1}}};\n' .format(pl[0], pl[1])) for e in po: output.write(u'b["{0}"]={{'.format(polib.escape(e.msgid))) output.write(u'msgstr:"{0}",msgstr_plural:{{'.format( polib.escape(e.msgstr))) for k in e.msgstr_plural: output.write(u'{0}:"{1}",'.format(k, polib.escape( e.msgstr_plural[k]))) output.write(u'}};\n') output.write(u'})();\n')
def generate_lua_dict(project, podir, lang): print("Generate lua dict for %s" % project['name']) pofile = os.path.join(podir, "%s.po" % lang) if not os.path.isfile(pofile): print("Could not read po file at %s" % pofile) exit() po = polib.pofile(pofile) f = open(os.path.join(podir, "lang.lua"), "w") f.write("return {\n") for entry in po: for occurrence in entry.occurrences: value = entry.msgstr if entry.translated() else entry.msgid f.write(" {} = \"{}\",\n".format(occurrence[0], polib.escape(value))) f.write("}") f.close
def spellcheck(request, project_slug, lang_code, resource_slug=None): """ Shows mispelled words along with suggestions """ data = simplejson.loads(request.raw_post_data) lang_code = lang_code.encode('utf-8') string = escape(data["text"]) string_ = string string = string.encode('utf-8') lang_codes = SPELLCHECK_SUPPORTED_LANGS if lang_code in lang_codes: xmlData = '''<?xml version="1.0" encoding="UTF-8" ?> <spellrequest textalreadyclipped="0" ignoredups="1" ignoredigits="1" ignoreallcaps="1" suggestedlang="%s"> <text>%s</text> </spellrequest>''' % (lang_code, string) headers = { "Content-type": "text/xml; charset=utf-8", "Request-number": "1", "Document-type": "Request", "Connection": "close" } con = httplib.HTTPSConnection('www.google.com') con.request('POST', '/tbproxy/spell?lang=%s' % (lang_code), xmlData, headers) response = con.getresponse().read().decode('utf-8') pattern = re.compile( r'<c o="(?P<o>\d*)" l="(?P<l>\d*)" s="\d*">(?P<suggestions>[^<]*)<\/c>', re.UNICODE) matches = pattern.findall(response) d = [] for i in matches: o = int(i[0]) l = int(i[1]) suggestions = i[2].split('\t') word_with_ws = string_[o:o + l] word = word_with_ws.strip() if len(word) < len(word_with_ws): start, end = re.search(re.escape(word), word_with_ws).span() l = end - start + 1 o = o + start d.append([(o, l), word, suggestions]) else: d = [] d.sort() json_dict = simplejson.dumps(d, 'utf-8') return HttpResponse(json_dict, mimetype='application/json')
def searchCodebaseForOccurrences(poFile): if prefs['searchCodebaseForOccurrences']: unCachedEntries = getUncachedEntries(poFile) if len(unCachedEntries) > 0: print("Searching for %d occurrences..." % len(unCachedEntries)) for root, dirs, files in os.walk(codeBasePath, topdown=True, onerror=None): for fName in getIncludedExcludedPaths(root, dirs, files): indicateProgress() sys.stdout.flush() try: baseDirectory = fName.replace(codeBasePath, "") size = os.stat(fName).st_size f2 = open(fName) data = mmap.mmap(f2.fileno(), size, access=mmap.ACCESS_READ) entryIndex = 0 for poEntry in unCachedEntries: entryIndex = entryIndex + 1 if prefs['processMaxEntries'] > 0: if entryIndex > prefs['processMaxEntries']: break encodedMsgid = polib.escape(poEntry.msgid) try: poEntry.occurrences = occurrencesCache[ encodedMsgid] except KeyError: occurrencesCache[encodedMsgid] = [] if isFoundInFile(poEntry.msgid, data): occurrencesCache[ encodedMsgid] = occurrencesCache[ encodedMsgid] + [(baseDirectory, '0')] poEntry.occurrences = occurrencesCache[ encodedMsgid] except UnicodeDecodeError: # found non-text data pass except ValueError: # possibly an empty file pass finally: data = None
def translate(msgid, flags, msgstr_lines, po2, options): msgstr = parse_msg(msgstr_lines) if options.overwrite: other = po2.find(msgid) if not other: return 0 if not other.translated(): return 0 if msgstr == other.msgstr: return 0 else: if msgstr != '' and not u'fuzzy' in flags: return 0 other = po2.find(msgid) if not other: return 0 if not other.translated(): return 0 if options.nonnull and other.msgstr == other.msgid: return 0 msgstr = other.msgstr if 'fuzzy' in other.flags: if not u'fuzzy' in flags: flags.append(u'fuzzy') else: if u'fuzzy' in flags: flags.remove(u'fuzzy') obsolete = (msgstr_lines[0].find('#~') == 0) j = msgstr_lines[0].find('"') # must not assign to msgstr_lines, because that would not be seen by our caller new_lines = polib.wrap(msgstr_lines[0][0:j + 1] + polib.escape(msgstr), 76, drop_whitespace=False) del msgstr_lines[:] for i in range(0, len(new_lines)): if i == 0: msgstr_lines.append(new_lines[i] + '"') elif obsolete: msgstr_lines.append('#~ "' + new_lines[i] + '"') else: msgstr_lines.append('"' + new_lines[i] + '"') return 1
def process_entry(entry, wrapper): """ Process one entry entry: entry for processing wrapper: constructed textwrap object used for wrapping (width property maye be changed here) Returns: True, if entry was changed :return: bool """ max_width = max([len(x) for x in entry.msgid.splitlines()]) max_trans_width = max([len(x) for x in entry.msgstr.splitlines()]) changed = False # if split already OK, don't do anything if max_trans_width <= max_width + _WARN_DELTA: return changed wrapper.width = max_width new_line = entry.msgstr if _NL_STR in entry.msgstr: _LOGGER.debug( "Skipped. Newline in translation.\n" "\tmsgid: '%s'\n\tmsgstr: '%s'.\n", polib.escape(entry.msgid), polib.escape(entry.msgstr)) return changed new_line = wrapper.fill(entry.msgstr) if new_line != entry.msgstr: entry.msgstr = new_line _LOGGER.info("Splitted.\n" "\tmsgid: '%s'\n\tmsgstr: '%s'.\n", polib.escape(entry.msgid), polib.escape(entry.msgstr)) changed = True else: changed = False max_trans_width = max([len(x) for x in entry.msgstr.splitlines()]) if max_trans_width > max_width + _WARN_DELTA: _LOGGER.warning( "Fuzzy. Translation's line length more that original.\n" "\tmsgid: '%s'\n\tmsgstr: '%s'.\n", polib.escape(entry.msgid), polib.escape(entry.msgstr)) # set fuzzy only if string was changed if changed and _FUZZY_FLAG not in entry.flags: entry.flags.append(_FUZZY_FLAG) return changed
def translate(msgid, flags, msgstr_lines, po2, options): msgstr = parse_msg(msgstr_lines) if options.overwrite: other = po2.find(msgid) if not other: return 0 if not other.translated(): return 0 if msgstr == other.msgstr: return 0 else: if msgstr != '' and not u'fuzzy' in flags: return 0 other = po2.find(msgid) if not other: return 0 if not other.translated(): return 0 if options.nonnull and other.msgstr == other.msgid: return 0 msgstr = other.msgstr if 'fuzzy' in other.flags: if not u'fuzzy' in flags: flags.append(u'fuzzy') else: if u'fuzzy' in flags: flags.remove(u'fuzzy') obsolete = (msgstr_lines[0].find('#~') == 0) j = msgstr_lines[0].find('"') # must not assign to msgstr_lines, because that would not be seen by our caller new_lines = polib.wrap(msgstr_lines[0][0:j+1] + polib.escape(msgstr), 76, drop_whitespace = False) del msgstr_lines[:] for i in range(0, len(new_lines)): if i == 0: msgstr_lines.append(new_lines[i] + '"') elif obsolete: msgstr_lines.append('#~ "' + new_lines[i] + '"') else: msgstr_lines.append('"' + new_lines[i] + '"') return 1
def _untranslated(self): """ Builds a list of translation strings without any translation Returns: None """ for model_class in self.models_and_fields.keys(): class_path = ".".join( [model_class.__module__, model_class.__name__]) for instance in model_class._default_manager.all().order_by('pk'): for field_name in self.models_and_fields[model_class]: try: field_value = polib.escape( getattr(instance, field_name)) except AttributeError: continue if not field_value: continue self.strings[field_value]['occurrences'].append( (".".join([class_path, field_name]), instance.pk))
def process_entry(entry, wrapper): """ Process one entry entry: entry for processing wrapper: constructed textwrap object used for wrapping (width property maye be changed here) Returns: True, if entry was changed :return: bool """ max_width = max([len(x) for x in entry.msgid.splitlines()]) max_trans_width = max([len(x) for x in entry.msgstr.splitlines()]) changed = False # if split already OK, don't do anything if max_trans_width <= max_width + _WARN_DELTA: return changed wrapper.width = max_width new_line = entry.msgstr if _NL_STR in entry.msgstr: _LOGGER.debug("Skipped. Newline in translation.\n" "\tmsgid: '%s'\n\tmsgstr: '%s'.\n", polib.escape(entry.msgid), polib.escape(entry.msgstr)) return changed new_line = wrapper.fill(entry.msgstr) if new_line != entry.msgstr: entry.msgstr = new_line _LOGGER.info("Splitted.\n" "\tmsgid: '%s'\n\tmsgstr: '%s'.\n", polib.escape(entry.msgid), polib.escape(entry.msgstr)) changed = True else: changed = False max_trans_width = max([len(x) for x in entry.msgstr.splitlines()]) if max_trans_width > max_width + _WARN_DELTA: _LOGGER.warning("Fuzzy. Translation's line length more that original.\n" "\tmsgid: '%s'\n\tmsgstr: '%s'.\n", polib.escape(entry.msgid), polib.escape(entry.msgstr)) # set fuzzy only if string was changed if changed and _FUZZY_FLAG not in entry.flags: entry.flags.append(_FUZZY_FLAG) return changed
# similar langs, all in a dictionary (see also below) _get_source_strings(s, source_language, language.code, more_languages), # 4. Get all the Translation strings mapped with plural rules # in a single dictionary (see docstring of function) _get_strings(translated_strings, language, s.source_entity), # 5. A number which indicates the number of Suggestion objects # attached to this row of the table. Suggestion.objects.filter(source_entity=s.source_entity, language__code=language.code).count(), # 6. save buttons and hidden context (ready to inject snippet) # It includes the following content, wrapped in span tags: # * SourceEntity object's "context" value # * SourceEntity object's "id" value ('<span class="save edit-panel inactive" id="save_' + str(counter) + '" style="border:0" title="' + _("Save the specific change") + '"></span>' '<span class="spellcheck edit-panel inactive" id="spellcheck_' + str(counter) + '" style="border:0" title="' + _("Check spelling") + '"></span>' '<span class="undo edit-panel inactive" id="undo_' + str(counter) + '" style="border:0" title="' + _("Undo to initial text") + '"></span>' '<span class="context" id="context_' + str(counter) + '" style="display:none;">' + escape(str(s.source_entity.context_string.encode('UTF-8'))) + '</span>' '<span class="source_id" id="sourceid_' + str(counter) + '"style="display:none;">' + str(s.source_entity.id) + '</span>'), ] for counter,s in enumerate(source_strings[dstart:dstart+dlength]) ], } if review: for counter, s in enumerate(source_strings[dstart:dstart+dlength]): try: translation = Translation.objects.get( source_entity__id=s.source_entity.id, language__code=language.code, rule=5 ) review_snippet = '<span><input class="review-check" id="review_source_' + str(s.source_entity.id) + '" type="checkbox" name="review" ' + ('checked="checked"' if translation.reviewed else '') + ' value="Review"/></span>', except Translation.DoesNotExist: review_snippet = '<span><input class="review-check" id="review_source_' + str(s.source_entity.id) + '" type="checkbox" name="review" disabled="disabled" value="Review"/></span>',
# 6. save buttons and hidden context (ready to inject snippet) # It includes the following content, wrapped in span tags: # * SourceEntity object's "context" value # * SourceEntity object's "id" value ('<span class="save edit-panel inactive" id="save_' + str(counter) + '" style="border:0" title="' + _("Save the specific change") + '"></span>' '<span class="spellcheck edit-panel inactive" id="spellcheck_' + str(counter) + '" style="border:0" title="' + _("Check spelling") + '"></span>' '<span class="undo edit-panel inactive" id="undo_' + str(counter) + '" style="border:0" title="' + _("Undo to initial text") + '"></span>' '<span class="context" id="context_' + str(counter) + '" style="display:none;">' + escape(str(s.source_entity.context_string.encode('UTF-8'))) + '</span>' '<span class="source_id" id="sourceid_' + str(counter) + '"style="display:none;">' + str(s.source_entity.id) + '</span>'), ] for counter, s in enumerate(source_strings[dstart:dstart + dlength]) ], } if review: for counter, s in enumerate(source_strings[dstart:dstart + dlength]): try: translation = Translation.objects.get( source_entity__id=s.source_entity.id, language__code=language.code,