def __init__(self, params): self.total = None self.select = None try: for spec in params.alt.split(","): if spec.endswith("t"): self.total = int(spec[:-1]) else: self.select = int(spec) except: raise SieveError( _("@info", "Malformed specification for " "resolution of alternatives '%(spec)s'.", spec=params.alt)) if self.total is None: raise SieveError( _("@info", "Number of alternatives per directive not given.")) if self.select is None: raise SieveError( _("@info", "Index of selected alternative not given.")) if self.total < 1: raise SieveError( _("@info", "Number of alternatives specified as %(num)d, " "but must be greater than 1.", num=self.total)) if self.select < 1 or self.select > self.total: raise SieveError( _("@info", "Selected alternative no. %(ord)d is out of range.", ord=self.select)) self.nresolved = 0
def _construct_aspell(lang, envs, encoding, variety, extopts, suponly): # Get Pology's internal personal dictonary for this language. dictpath, temporary = _compose_personal_dict(lang, envs) if not suponly: # Prepare Aspell options. aopts = {} aopts["lang"] = lang aopts["encoding"] = encoding if variety: aopts["variety"] = variety if dictpath: aopts["personal-path"] = dictpath if extopts: aopts.update(extopts) aopts = dict([(x, y.encode(encoding)) for x, y in aopts.items()]) # Create Aspell object. import pology.external.pyaspell as A try: checker = A.Aspell(aopts.items()) except A.AspellConfigError, e: raise PologyError( _("@info", "Aspell configuration error:\n%(msg)s", msg=e)) except A.AspellError, e: raise PologyError( _("@info", "Cannot initialize Aspell:\n%(msg)s", msg=e))
def setup_sieve(p): p.set_desc( _("@info sieve discription", "Initialize or update the PO header with own translator data.")) p.add_param( "proj", unicode, mandatory=True, metavar=_("@info sieve parameter value placeholder", "ID"), desc=_( "@info sieve parameter discription", "Project ID in Pology configuration file, " "which contains the necessary project data to update the header.")) p.add_param( "init", bool, defval=False, desc=_( "@info sieve parameter discription", "Consider header as uninitialized, removing any existing information " "before adding own and project data.")) p.add_param("onmod", bool, defval=False, desc=_( "@info sieve parameter discription", "Update header only if the catalog was otherwise modified " "(in sieve chains)."))
def __init__ (self, params): self.caller_sync = False self.caller_monitored = False self.propcons = None if params.propcons: self.propcons = self._read_propcons(params.propcons) self.p = params if not params.pmhead: raise SieveError(_("@info", "Prefix which starts property map entries " "in comments cannot be empty.")) if not params.sdhead: raise SieveError(_("@info", "Prefix which starts syntagma derivator entries " "in comments cannot be empty.")) # Collected entries. # Each element is a tuple of the form: # (ekeys, props, psep, kvsep, msg, cat) self.entries = [] # Syntagma derivator, for synder entries. self.synder = Synder() self.sdord = 0
def spell_error(msg, cat, faultyWord, suggestions): """Print formated rule error message on screen @param msg: pology.message.Message object @param cat: pology.catalog.Catalog object @param faultyWord: badly spelled word @param suggestions : list of correct words to suggest""" report("-" * 40) report( ColorString("<bold>%s:%d(%d)</bold>") % (cat.filename, msg.refline, msg.refentry)) if msg.msgctxt: report( _("@info", "<bold>Context:</bold> %(snippet)s", snippet=msg.msgctxt)) #TODO: color in red part of context that make the mistake report( _("@info", "<bold>Faulty word:</bold> <red>%(word)s</red>", word=faultyWord)) if suggestions: report( _("@info", "<bold>Suggestions:</bold> %(wordlist)s", wordlist=format_item_list(suggestions)))
def __unicode__(self): if self.expr is not None and self.start is not None: start = self.start if self.end is not None: end = self.end else: end = self.start + 10 subexpr = self.expr[start:end] if start > 0: subexpr = "..." + subexpr if end < len(self.expr): subexpr = subexpr + "..." else: subexpr = None if self.msg is not None and subexpr is not None: repstr = _("@info", "Invalid expression at %(col)d [%(snippet)s]: " "%(reason)s.", col=self.start, snippet=subexpr, reason=self.msg) elif self.msg is not None: repstr = _("@info", "Invalid expression: %(reason)s.", reason=self.msg) elif subexpr is not None: repstr = _("@info", "Invalid expression at %(col)d [%(snippet)s].", col=self.start, snippet=subexpr) else: repstr = _("@info", "Invalid expression.") return unicode(repstr)
def match_for_index (index, interps_orig, n_can_miss=0): nproblems = 0 interps_trans = _collect_interps(msg.msgstr[index]) if interps_orig != interps_trans: interps_missing = interps_orig.difference(interps_trans) # Eliminate from check interpolations explicitly ignored. for cmnt in [x.strip() for x in msg.manual_comment]: if cmnt.startswith("ignore-interpolations:"): interps = cmnt[cmnt.find(":") + 1:].split() for interp in interps: interp = interp.strip() if not interp.startswith("$"): interp = "$%s" % interp if interp in interps_missing: interps_missing.remove(interp) interps_unknown = interps_trans.difference(interps_orig) if interps_missing and len(interps_missing) > n_can_miss: vfmt = format_item_list(interps_missing) hl.append(("msgstr", index, [(None, None, _("@info", "Missing interpolations: %(interplist)s.", interplist=vfmt))])) nproblems += 1 elif interps_unknown: vfmt = format_item_list(interps_unknown) hl.append(("msgstr", index, [(None, None, _("@info", "Unknown interpolations: %(interplist)s.", interplist=vfmt))])) nproblems += 1 return nproblems
def add_cmdopt_wrapping (opars): """ Options for wrapping in catalogs when writing them out. """ opars.add_option( "--wrap", action="store_true", dest="do_wrap", default=None, help=_("@info command line option description", "Basic wrapping: on colum count.")) opars.add_option( "--no-wrap", action="store_false", dest="do_wrap", default=None, help=_("@info command line option description", "No basic wrapping.")) opars.add_option( "--fine-wrap", action="store_true", dest="do_fine_wrap", default=None, help=_("@info command line option description", "Fine wrapping: on logical breaks (e.g. some markup tags).")) opars.add_option( "--no-fine-wrap", action="store_false", dest="do_fine_wrap", default=None, help=_("@info command line option description", "No fine wrapping."))
def setup_sieve(p): p.set_desc( _("@info sieve discription", "Resolve aggregate messages produced by '%(cmd)s'.", cmd="msgcat")) p.add_param( "first", bool, defval=False, desc=_( "@info sieve parameter discription", "Always pick the first variant (by default, aggregate messages " "are resolved by taking the most frequent variant).")) p.add_param( "unfuzzy", bool, defval=False, desc=_( "@info sieve parameter discription", "Unfuzzy resolved messages. " "DANGEROUS: Use only if all messages in aggregation can be guaranteed " "not to be fuzzy.")) p.add_param( "keepsrc", bool, defval=False, desc=_( "@info sieve parameter discription", "Keep source reference on resolved messages instead of removing them." ))
def pairs_update_effort (pspecs, quiet=False): update_progress = None if len(pspecs) > 1 and not quiet: update_progress = init_file_progress([vp[1] for fp, vp in pspecs], addfmt=t_("@info:progress", "Diffing: %(file)s")) nntw_total = 0.0 for fpaths, vpaths in pspecs: upprogf = None if update_progress: upprogf = lambda: update_progress(vpaths[1]) upprogf() # Quick check if files are binary equal. if fpaths[0] and fpaths[1] and filecmp.cmp(*fpaths): continue cats = [] for fpath in fpaths: try: cats.append(Catalog(fpath, create=True, monitored=False)) except: error_wcl(_("@info", "Cannot parse catalog '%(file)s'.", file=fpath), norem=[fpath]) nntw = cats_update_effort(cats[0], cats[1], upprogf) nntw_total += nntw if update_progress: update_progress() updeff = [ ("nntw", _("@item", "nominal newly translated words"), nntw_total, "%.0f" % nntw_total), ] return updeff
def setup_sieve (p): p.set_desc(_("@info sieve discription", "Check validity of messages in catalogs within KDE Translation Project." )) p.add_param("strict", bool, defval=False, desc=_("@info sieve parameter discription", "Check translations strictly: report problems in translation regardless " "of whether original itself is valid (default is to check translation " "only if original passes checks)." )) chnames = _known_checks.keys() chnames.sort() p.add_param("check", unicode, seplist=True, metavar=_("@info sieve parameter value placeholder", "KEYWORD,..."), desc=_("@info sieve parameter discription", "Run only this check instead of all (currently available: %(chklist)s). " "Several checks can be specified as a comma-separated list.", chklist=format_item_list(chnames) )) p.add_param("showmsg", bool, defval=False, desc=_("@info sieve parameter discription", "Also show the full message that had some problems." )) add_param_poeditors(p)
def _value(self, typ, name, default=None, typename=None): if not _config.has_option(self.name, name): return default value = _config.get(self.name, name) if typ is not bool: try: cvalue = typ(value) except: cvalue = None else: cvalue = strbool(value) if cvalue is None: if typename: error( _("@info", "User configuration: value '%(val)s' " "of field '%(field)s' in section '%(sec)s' " "cannot be converted into '%(type)s' type.", val=value, field=name, sec=self.name, type=typename)) else: error( _("@info", "User configuration: value '%(val)s' " "of field '%(field)s' in section '%(sec)s' " "cannot be converted into requested type.", val=value, field=name, sec=self.name)) return cvalue
def add_param_filter (p, intro=None): """ Add C{filter} parameter to sieve parameters. @param intro: first paragraph for the parameter description @type intro: string """ desc = _("@info sieve parameter description", "For a module pology.FOO which defines FOO() function, " "the hook specification is simply FOO. " "If the hook function is named BAR() instead of FOO(), then " "the hook specification is FOO/BAR. " "Language specific hooks (pology.lang.LANG.FOO) are aditionally " "preceded by the language code with colon, as LANG:FOO or LANG:FOO/BAR. " "\n\n" "If the function is actually a hook factory, the arguments for " "the factory are passed separated by tilde: LANG:FOO/BAR~ARGS " "(where LANG: and /BAR may be omitted under previous conditions). " "The ARGS string is a list of arguments as it would appear " "in the function call in Python code, omitting parenthesis. " "\n\n" "Several hooks can be given by repeating the parameter, " "when they are applied in the given order." ) if intro: desc = "%s\n\n%s" % (intro, desc) p.add_param("filter", unicode, multival=True, metavar=_("@info sieve parameter value placeholder", "HOOKSPEC"), desc=desc)
def _check_keyword_list_text (text, msg, cat): spans = [] ctxt = msg.msgctxt or "" if ctxt == "Keywords" or ctxt.startswith("Keywords|"): pos = text.find(",") if pos >= 0: spans.append((pos, pos + 1, _("@info", "Keyword list with context '%(ident)s' " "must not contain commas.", ident="Keywords"))) if not text.endswith(";"): spans.append((len(text), len(text), _("@info", "Keyword list with context '%(ident)s' " "must end with semicolon.", ident="Keywords"))) elif ctxt == "X-KDE-Keywords" or ctxt.startswith("X-KDE-Keywords|"): pos = text.find(";") if pos >= 0: spans.append((pos, pos + 1, _("@info", "Keyword list with context '%(ident)s' " "must not contain semicolons.", ident="X-KDE-Keywords"))) return spans
def get_hook(modpath, lang=None, proj=None, func=None, args=None, abort=False): """ Fetch a hook function. Loads a hook function from a module obtained by applying L{get_module} to C{modpath}, C{lang}, and C{proj} parameters. If C{func} is C{None}, the function name defaults to module name; if C{func} is not C{None}, but function of that name is not found, then the function named C{<modname>_<func>} is additionally tried (where C{<modname>} is the last element in C{modpath}). If C{args} is not C{None}, then the loaded function is considered a hook factory, and the hook is created by calling it with C{args} string as argument list (it should have no surrounding parenthesis). @param modpath: hook module @type modpath: string @param lang: language code @type lang: string @param proj: project code @type proj: string @param func: function name of hook or hook factory @type func: string @param args: argument string to hook factory @type args: string @param abort: whether to abort execution or raise exception if the hook cannot be loaded @type abort: bool @returns: the hook """ lmod, modpath = get_module(modpath, lang, proj, abort, wpath=True) modname = modpath.rsplit(".", 1)[-1] if func is None: func = modname func2 = "\0" else: func2 = "%s_%s" % (modname, func) call = getattr(lmod, func, None) or getattr(lmod, func2, None) if call is None: _raise_or_abort( _("@info", "Module '%(mod)s' does not define " "'%(func)s' function.", mod=modpath, func=func), abort) if args is not None: try: call = eval("call(%s)" % args) except Exception, e: fspec = "%s/%s" % (modpath, func) _raise_or_abort( _("@info", "Cannot create hook by applying function " "'%(func)s' to argument list %(args)s; " "reported error:\n%(msg)s", func=fspec, args=repr(args), msg=e), abort)
def translate(self, texts): # Serialize texts to send to Apertium in one go. # Separate texts with an inplace tag followed by dot, # to have each text interpreted as standalone sentence. # FIXME: Any way to really translate each text in turn, # without it being horribly slow? sep0 = "<br class='..." sep1 = "..." sep2 = "'/>." sep = None nsep = 0 while not sep: # determine shortest acceptable separator sep = sep0 + sep1 * nsep + sep2 for text in texts: if sep in text: sep = None nsep += 1 break stext = sep.join(texts) # Translate empty string to test language pair. # Otherwise, if a lot of text is sent and language pair not good, # Apertium may just signal broken pipe. res = collect_system(self.cmdline, instr="") if res[2] != 0: warning( _("@info", "Executing Apertium failed:\n%(output)s", output=res[0])) # ...really res[0], error is output to stdout. Tsk. return None res = collect_system(self.cmdline, instr=stext) if res[2] != 0: warning( _("@info", "Executing Apertium failed:\n%(output)s", output=res[0])) # ...really res[0], error is output to stdout. Tsk. return None texts_tr = res[0].split(sep) if len(texts_tr) != len(texts): warning( _("@info", "Apertium reported wrong number of translations, " "%(num1)d instead of %(num2)d.", num1=len(texts_tr), num2=len(texts))) return None texts_tr = [ resolve_entities_simple(x, self.htmlents) for x in texts_tr ] return texts_tr
def setup_sieve(p): p.set_desc( _("@info sieve discription", "Transform ASCII single and double quotes into fancy counterparts.")) p.add_param("single", unicode, metavar=_("@info sieve parameter value placeholder", "QUOTES"), desc=_("@info sieve parameter discription", "Opening and closing single quote (two characters).")) p.add_param("double", unicode, metavar=_("@info sieve parameter value placeholder", "QUOTES"), desc=_("@info sieve parameter discription", "Opening and closing double quote (two characters).")) p.add_param( "longsingle", unicode, metavar=_("@info sieve parameter value placeholder", "OPEN,CLOSED"), desc=_( "@info sieve parameter discription", "Opening and closing single quote longer than single character.")) p.add_param( "longdouble", unicode, metavar=_("@info sieve parameter value placeholder", "OPEN,CLOSED"), desc=_( "@info sieve parameter discription", "Opening and closing double quote longer than single character."))
def strdlist(self, name, default=None): """ Get a configuration field as a list of delimited strings. Delimiter is taken to be the non-alphanumeric character with which the field value starts. In this example:: afield = /foo/bar/baz/ the delimiter is C{/}. If the field value does not start with a non-alphanumeric, or it does not end with the delimiter, error is signalled. @rtype: unicode or as C{default} """ value = self._value(unicode, name, None, "string") if value is None: return default value = value.strip() if len(value) < 2: error( _("@info", "User configuration: value '%(val)s' of field '%(field)s' " "in section '%(sec)s' is too short for a delimited list.", val=value, field=name, sec=self.name)) if value[0].isalnum(): error( _("@info", "User configuration: value '%(val)s' of field '%(field)s' " "in section '%(sec)s' does not start with " "a non-alphanumeric delimiter character.", val=value, field=name, sec=self.name)) delim = value[0] if value[-1] != delim: error( _("@info", "User configuration: value '%(val)s' of field '%(field)s' " "in section '%(sec)s' does not end with " "the delimiter character with which it starts.", val=value, field=name, sec=self.name)) lst = value[1:-1].split(delim) return lst
def setup_sieve (p): p.set_desc(_("@info sieve discription", "Remove previous fields (#| ...) from messages." )) p.add_param("all", bool, desc=_("@info sieve parameter discription", "Remove previous fields from all messages " "(by default previous fields are not removed from fuzzy messages)." ))
def setup_sieve (p): p.set_desc(_("@info sieve discription", "Check catalogs covering Docbook 4.x documents for various problems." )) p.add_param("showmsg", bool, defval=False, desc=_("@info sieve parameter discription", "Also show the full message which has a problem." )) add_param_poeditors(p)
def _check_space (msg, cat, strict, hl): # Check only for explicitly listed languages. if (cat.language() or cat.name) not in _langs_w_outspc: return 0 # Check if explicitly stated in extracted comment # that outer space in original is significant. kw_outspcsig = "outer-space-significant" outspcsig = reduce(lambda s, x: s or kw_outspcsig in x.lower(), msg.auto_comment, False) nproblems = 0 haslead_o = msg.msgid.startswith(" ") hastail_o = msg.msgid.endswith(" ") tailnspc_o = msg.msgid.strip()[-1:] for i in range(len(msg.msgstr)): haslead_t = msg.msgstr[i].startswith(" ") hastail_t = msg.msgstr[i].endswith(" ") # Consider trailing space in original significant # if explicitly stated so, if it is preceded by colon, # or there was a leading space. if ( hastail_o and not hastail_t and (outspcsig or haslead_o or tailnspc_o in ":") ): hl.append(("msgstr", i, [(-1, -1, _("@info", "Missing trailing space."))])) nproblems += 1 # Consider leading space always significant. if haslead_o and not haslead_t: hl.append(("msgstr", i, [(0, 0, _("@info", "Missing leading space."))])) nproblems += 1 """ Nah, usually invisible and yet frequent. # If original has no trailing space, # translation should also have none. if not hastail_o and hastail_t: hl.append(("msgstr", i, [(-1, -1, "extra trailing space")])) nproblems += 1 """ # If original has no leading space, # translation should also have none. if not haslead_o and haslead_t: hl.append(("msgstr", i, [(0, 0, _("@info", "Extra leading space."))])) nproblems += 1 return nproblems
def setup_sieve(p): p.set_desc( _( "@info sieve discription", "Apply hooks to header." "\n\n" "Catalog header is passed through one or more of " "F4B, V4B, S4B hooks. ")) add_param_filter( p, _("@info sieve parameter discription", "Specification of the hook through which headers are passed."))
def setup_sieve(p): p.set_desc( _("@info sieve discription", "Resolve XML entities in translation.")) add_param_entdef(p) p.add_param("ignore", unicode, seplist=True, metavar=_("@info sieve parameter value placeholder", "ENTITY1,..."), desc=_("@info sieve parameter discription", "Comma-separated list of entity names to ignore."))
def setup_sieve(p): p.set_desc( _("@info sieve discription", "Convert separator-embedded context to Gettext context.")) p.add_param( "sep", unicode, mandatory=True, metavar=_("@info sieve parameter value placeholder", "STRING"), desc=_("@info sieve parameter discription", "Separator between the context and the text in msgid field."))
def setup_sieve(p): p.set_desc( _("@info sieve discription", "Spell-check translation using Aspell.")) add_param_spellcheck(p) p.add_param("enc", unicode, metavar=_("@info sieve parameter value placeholder", "ENCODING"), desc=_("@info sieve parameter discription", "Encoding for text sent to Aspell.")) p.add_param("var", unicode, metavar=_("@info sieve parameter value placeholder", "VARIETY"), desc=_("@info sieve parameter discription", "Variety of the Aspell dictionary.")) p.add_param("xml", unicode, metavar=_("@info sieve parameter value placeholder", "FILE"), desc=_("@info sieve parameter discription", "Build XML report file at given path.")) p.add_param("simsp", bool, defval=False, desc=_( "@info sieve parameter discription", "Split text into words in a simpler way (deprecated,)."))
def setup_sieve(p): p.set_desc( _("@info sieve discription", "Remove selected manual comments from fuzzy messages.")) p.add_param("all", bool, defval=False, desc=_("@info sieve parameter discription", "Remove all manual comments.")) p.add_param("nopipe", bool, defval=False, desc=_( "@info sieve parameter discription", "Remove embedded lists of no-pipe flags (# |, foo, ...).")) p.add_param("pattern", unicode, metavar=_("@info sieve parameter value placeholder", "REGEX"), desc=_("@info sieve parameter discription", "Remove comments matching the regular expression.")) p.add_param("exclude", unicode, metavar=_("@info sieve parameter value placeholder", "REGEX"), desc=_("@info sieve parameter discription", "Remove comments not matching the regular expression.")) p.add_param("case", bool, defval=False, desc=_("@info sieve parameter discription", "Case-sensitive pattern matching."))
def listcmd (self, subcmds=None, wcol=None, stream=sys.stdout): """ Formatted listing of subcommands with short descriptions. @param subcmds: subcommand names (all subcommands if C{None}) @type subcmds: list of strings @param wcol: column to wrap text at (<= 0 for no wrapping, C{None} for automatic according to output stream) @type wcol: int @param stream: intended output stream for the text @type stream: file @return: formatted listing @rtype: string """ if subcmds is None: subcmds = self._scviews.keys() subcmds.sort() maxsclen = max([len(x) for x in subcmds]) ndsep = _("@item:intext splitter between a subcommand name " "and its description", " - ") flead = " " * 2 lead = flead + " " * (maxsclen + 3) if wcol is None: wcol = (term_width(stream=stream) or 80) - 1 fmts = [] for subcmd in subcmds: scview = self._scviews.get(subcmd, None) if scview is None: raise SubcmdError( _("@info", "Trying to include an unknown subcommand '%(cmd)s' " "into listing.", cmd=subcmd)) desc = scview.shdesc() if desc: name = cinterp("%%-%ds" % maxsclen, subcmd) s = name + ndsep + desc else: s = name lines = wrap_text(s, wcol=wcol, flead=flead, lead=lead, endl="") fmts.extend(lines) return cjoin(fmts, "\n")
def _construct_enchant(provider, lang, envs, encoding, variety, suponly): # Get Pology's internal personal dictonary for this language. dictpath, temporary = _compose_personal_dict(lang, envs) if not suponly: try: import enchant except ImportError: pkgs = ["python-enchant"] raise PologyError( _("@info", "Python wrapper for Enchant not found, " "please install it (possible package names: " "%(pkglist)s).", pkglist=format_item_list(pkgs))) # Create Enchant broker. try: broker = enchant.Broker() except Exception, e: raise PologyError( _("@info", "Cannot initialize Enchant:\n%(msg)s", msg=e)) # Find Enchant language. e_langs = filter(broker.dict_exists, [variety, lang]) if e_langs: e_lang = e_langs[0] else: if variety is not None: raise PologyError( _("@info", "Language '%(lang)s' and variety '%(var)s' " "not known to Enchant.", lang=lang, var=variety)) else: raise PologyError( _("@info", "Language '%(lang)s' not known to Enchant.", lang=lang)) # Choose the provider for the selected language. try: broker.set_ordering((e_lang or "*"), provider) except Exception, e: raise PologyError( _("@info", "Cannot configure Enchant for provider '%(pvd)s':\n%(msg)s", pvd=provider, msg=e))
def setup_sieve(p): p.set_desc( _("@info sieve discription", "Spell-check translation using Enchant.")) p.add_param("provider", unicode, seplist=True, metavar=_("@info sieve parameter value placeholder", "NAME"), desc=_( "@info sieve parameter discription", "The spell-checking provider to use. " "Several provider can be given as comma-separated list.")) add_param_spellcheck(p)
def setup_sieve(p): p.set_desc( _("@info sieve discription", "Check native KDE4 PO files for various problems.")) p.add_param( "strict", bool, defval=False, desc=_( "@info sieve parameter discription", "Check for problems in translation regardless of whether the original " "itself is free of problems (default is to check translation only if " "the original has no problems).")) add_param_poeditors(p)