def __call__(self, stream, directives, ctxt, **vars): ctxt.push({"_i18n.choose.params": self.params, "_i18n.choose.singular": None, "_i18n.choose.plural": None}) ngettext = ctxt.get("_i18n.ngettext") assert hasattr(ngettext, "__call__"), "No ngettext function available" dngettext = ctxt.get("_i18n.dngettext") if not dngettext: dngettext = lambda d, s, p, n: ngettext(s, p, n) new_stream = [] singular_stream = None singular_msgbuf = None plural_stream = None plural_msgbuf = None numeral = self.numeral.evaluate(ctxt) is_plural = self._is_plural(numeral, ngettext) for event in stream: if event[0] is SUB and any(isinstance(d, ChooseBranchDirective) for d in event[1][0]): subdirectives, substream = event[1] if isinstance(subdirectives[0], SingularDirective): singular_stream = list(_apply_directives(substream, subdirectives, ctxt, vars)) new_stream.append((MSGBUF, None, (None, -1, -1))) elif isinstance(subdirectives[0], PluralDirective): if is_plural: plural_stream = list(_apply_directives(substream, subdirectives, ctxt, vars)) else: new_stream.append(event) if ctxt.get("_i18n.domain"): ngettext = lambda s, p, n: dngettext(ctxt.get("_i18n.domain"), s, p, n) singular_msgbuf = ctxt.get("_i18n.choose.singular") if is_plural: plural_msgbuf = ctxt.get("_i18n.choose.plural") msgbuf, choice = plural_msgbuf, plural_stream else: msgbuf, choice = singular_msgbuf, singular_stream plural_msgbuf = MessageBuffer(self) for kind, data, pos in new_stream: if kind is MSGBUF: for event in choice: if event[0] is MSGBUF: translation = ngettext(singular_msgbuf.format(), plural_msgbuf.format(), numeral) for subevent in msgbuf.translate(translation): yield subevent else: yield event else: yield kind, data, pos ctxt.pop()
def __call__(self, stream): """Apply the filter to the given stream. :param stream: the markup event stream to filter """ in_form = in_select = in_option = in_textarea = False select_value = option_value = textarea_value = None option_start = None option_text = [] no_option_value = False for kind, data, pos in stream: if kind is START: tag, attrs = data tagname = tag.localname if tagname == 'form' and ( self.name and attrs.get('name') == self.name or self.id and attrs.get('id') == self.id or not (self.id or self.name)): in_form = True elif in_form: if tagname == 'input': type = attrs.get('type', '').lower() if type in ('checkbox', 'radio'): name = attrs.get('name') if name and name in self.data: value = self.data[name] declval = attrs.get('value') checked = False if isinstance(value, (list, tuple)): if declval is not None: checked = declval in [ str(v) for v in value ] else: checked = any(value) else: if declval is not None: checked = declval == str(value) elif type == 'checkbox': checked = bool(value) if checked: attrs |= [(QName('checked'), 'checked')] elif 'checked' in attrs: attrs -= 'checked' elif type in ('', 'hidden', 'text') \ or type == 'password' and self.passwords: name = attrs.get('name') if name and name in self.data: value = self.data[name] if isinstance(value, (list, tuple)): value = value[0] if value is not None: attrs |= [(QName('value'), str(value))] elif tagname == 'select': name = attrs.get('name') if name in self.data: select_value = self.data[name] in_select = True elif tagname == 'textarea': name = attrs.get('name') if name in self.data: textarea_value = self.data.get(name) if isinstance(textarea_value, (list, tuple)): textarea_value = textarea_value[0] in_textarea = True elif in_select and tagname == 'option': option_start = kind, data, pos option_value = attrs.get('value') if option_value is None: no_option_value = True option_value = '' in_option = True continue yield kind, (tag, attrs), pos elif in_form and kind is TEXT: if in_select and in_option: if no_option_value: option_value += data option_text.append((kind, data, pos)) continue elif in_textarea: continue yield kind, data, pos elif in_form and kind is END: tagname = data.localname if tagname == 'form': in_form = False elif tagname == 'select': in_select = False select_value = None elif in_select and tagname == 'option': if isinstance(select_value, (tuple, list)): selected = option_value in [ str(v) for v in select_value ] else: selected = option_value == str(select_value) okind, (tag, attrs), opos = option_start if selected: attrs |= [(QName('selected'), 'selected')] elif 'selected' in attrs: attrs -= 'selected' yield okind, (tag, attrs), opos if option_text: for event in option_text: yield event in_option = False no_option_value = False option_start = option_value = None option_text = [] elif in_textarea and tagname == 'textarea': if textarea_value: yield TEXT, str(textarea_value), pos textarea_value = None in_textarea = False yield kind, data, pos else: yield kind, data, pos
def __call__(self, stream, ctxt=None, translate_text=True, translate_attrs=True): """Translate any localizable strings in the given stream. This function shouldn't be called directly. Instead, an instance of the `Translator` class should be registered as a filter with the `Template` or the `TemplateLoader`, or applied as a regular stream filter. If used as a template filter, it should be inserted in front of all the default filters. :param stream: the markup event stream :param ctxt: the template context (not used) :param translate_text: whether text nodes should be translated (used internally) :param translate_attrs: whether attribute values should be translated (used internally) :return: the localized stream """ ignore_tags = self.ignore_tags include_attrs = self.include_attrs skip = 0 xml_lang = XML_NAMESPACE['lang'] if not self.extract_text: translate_text = False translate_attrs = False if type(self.translate) is FunctionType: gettext = self.translate if ctxt: ctxt['_i18n.gettext'] = gettext else: if IS_PYTHON2: gettext = self.translate.ugettext ngettext = self.translate.ungettext else: gettext = self.translate.gettext ngettext = self.translate.ngettext try: if IS_PYTHON2: dgettext = self.translate.dugettext dngettext = self.translate.dungettext else: dgettext = self.translate.dgettext dngettext = self.translate.dngettext except AttributeError: dgettext = lambda _, y: gettext(y) dngettext = lambda _, s, p, n: ngettext(s, p, n) if ctxt: ctxt['_i18n.gettext'] = gettext ctxt['_i18n.ngettext'] = ngettext ctxt['_i18n.dgettext'] = dgettext ctxt['_i18n.dngettext'] = dngettext if ctxt and ctxt.get('_i18n.domain'): # TODO: This can cause infinite recursion if dgettext is defined # via the AttributeError case above! gettext = lambda msg: dgettext(ctxt.get('_i18n.domain'), msg) for kind, data, pos in stream: # skip chunks that should not be localized if skip: if kind is START: skip += 1 elif kind is END: skip -= 1 yield kind, data, pos continue # handle different events that can be localized if kind is START: tag, attrs = data if tag in self.ignore_tags or \ isinstance(attrs.get(xml_lang), basestring): skip += 1 yield kind, data, pos continue new_attrs = [] changed = False for name, value in attrs: newval = value if isinstance(value, basestring): if translate_attrs and name in include_attrs: newval = gettext(value) else: newval = list( self(_ensure(value), ctxt, translate_text=False)) if newval != value: value = newval changed = True new_attrs.append((name, value)) if changed: attrs = Attrs(new_attrs) yield kind, (tag, attrs), pos elif translate_text and kind is TEXT: text = data.strip() if text: data = data.replace(text, unicode(gettext(text))) yield kind, data, pos elif kind is SUB: directives, substream = data current_domain = None for idx, directive in enumerate(directives): # Organize directives to make everything work # FIXME: There's got to be a better way to do this! if isinstance(directive, DomainDirective): # Grab current domain and update context current_domain = directive.domain ctxt.push({'_i18n.domain': current_domain}) # Put domain directive as the first one in order to # update context before any other directives evaluation directives.insert(0, directives.pop(idx)) # If this is an i18n directive, no need to translate text # nodes here is_i18n_directive = any([ isinstance(d, ExtractableI18NDirective) for d in directives ]) substream = list( self(substream, ctxt, translate_text=not is_i18n_directive, translate_attrs=translate_attrs)) yield kind, (directives, substream), pos if current_domain: ctxt.pop() else: yield kind, data, pos
def __call__(self, stream, directives, ctxt, **vars): ctxt.push({ '_i18n.choose.params': self.params, '_i18n.choose.singular': None, '_i18n.choose.plural': None }) ngettext = ctxt.get('_i18n.ngettext') assert hasattr(ngettext, '__call__'), 'No ngettext function available' dngettext = ctxt.get('_i18n.dngettext') if not dngettext: dngettext = lambda d, s, p, n: ngettext(s, p, n) new_stream = [] singular_stream = None singular_msgbuf = None plural_stream = None plural_msgbuf = None numeral = self.numeral.evaluate(ctxt) is_plural = self._is_plural(numeral, ngettext) for event in stream: if event[0] is SUB and any( isinstance(d, ChooseBranchDirective) for d in event[1][0]): subdirectives, substream = event[1] if isinstance(subdirectives[0], SingularDirective): singular_stream = list( _apply_directives(substream, subdirectives, ctxt, vars)) new_stream.append((MSGBUF, None, (None, -1, -1))) elif isinstance(subdirectives[0], PluralDirective): if is_plural: plural_stream = list( _apply_directives(substream, subdirectives, ctxt, vars)) else: new_stream.append(event) if ctxt.get('_i18n.domain'): ngettext = lambda s, p, n: dngettext(ctxt.get('_i18n.domain'), s, p, n) singular_msgbuf = ctxt.get('_i18n.choose.singular') if is_plural: plural_msgbuf = ctxt.get('_i18n.choose.plural') msgbuf, choice = plural_msgbuf, plural_stream else: msgbuf, choice = singular_msgbuf, singular_stream plural_msgbuf = MessageBuffer(self) for kind, data, pos in new_stream: if kind is MSGBUF: for event in choice: if event[0] is MSGBUF: translation = ngettext(singular_msgbuf.format(), plural_msgbuf.format(), numeral) for subevent in msgbuf.translate(translation): yield subevent else: yield event else: yield kind, data, pos ctxt.pop()
def __call__(self, stream): """Apply the filter to the given stream. :param stream: the markup event stream to filter """ in_form = in_select = in_option = in_textarea = False select_value = option_value = textarea_value = None option_start = None option_text = [] no_option_value = False for kind, data, pos in stream: if kind is START: tag, attrs = data tagname = tag.localname if tagname == 'form' and ( self.name and attrs.get('name') == self.name or self.id and attrs.get('id') == self.id or not (self.id or self.name)): in_form = True elif in_form: if tagname == 'input': type = attrs.get('type', '').lower() if type in ('checkbox', 'radio'): name = attrs.get('name') if name and name in self.data: value = self.data[name] declval = attrs.get('value') checked = False if isinstance(value, (list, tuple)): if declval is not None: checked = declval in [unicode(v) for v in value] else: checked = any(value) else: if declval is not None: checked = declval == unicode(value) elif type == 'checkbox': checked = bool(value) if checked: attrs |= [(QName('checked'), 'checked')] elif 'checked' in attrs: attrs -= 'checked' elif type in ('', 'hidden', 'text') \ or type == 'password' and self.passwords: name = attrs.get('name') if name and name in self.data: value = self.data[name] if isinstance(value, (list, tuple)): value = value[0] if value is not None: attrs |= [ (QName('value'), unicode(value)) ] elif tagname == 'select': name = attrs.get('name') if name in self.data: select_value = self.data[name] in_select = True elif tagname == 'textarea': name = attrs.get('name') if name in self.data: textarea_value = self.data.get(name) if isinstance(textarea_value, (list, tuple)): textarea_value = textarea_value[0] in_textarea = True elif in_select and tagname == 'option': option_start = kind, data, pos option_value = attrs.get('value') if option_value is None: no_option_value = True option_value = '' in_option = True continue yield kind, (tag, attrs), pos elif in_form and kind is TEXT: if in_select and in_option: if no_option_value: option_value += data option_text.append((kind, data, pos)) continue elif in_textarea: continue yield kind, data, pos elif in_form and kind is END: tagname = data.localname if tagname == 'form': in_form = False elif tagname == 'select': in_select = False select_value = None elif in_select and tagname == 'option': if isinstance(select_value, (tuple, list)): selected = option_value in [unicode(v) for v in select_value] else: selected = option_value == unicode(select_value) okind, (tag, attrs), opos = option_start if selected: attrs |= [(QName('selected'), 'selected')] elif 'selected' in attrs: attrs -= 'selected' yield okind, (tag, attrs), opos if option_text: for event in option_text: yield event in_option = False no_option_value = False option_start = option_value = None option_text = [] elif in_textarea and tagname == 'textarea': if textarea_value: yield TEXT, unicode(textarea_value), pos textarea_value = None in_textarea = False yield kind, data, pos else: yield kind, data, pos
def __call__(self, stream, ctxt=None, translate_text=True, translate_attrs=True): """Translate any localizable strings in the given stream. This function shouldn't be called directly. Instead, an instance of the `Translator` class should be registered as a filter with the `Template` or the `TemplateLoader`, or applied as a regular stream filter. If used as a template filter, it should be inserted in front of all the default filters. :param stream: the markup event stream :param ctxt: the template context (not used) :param translate_text: whether text nodes should be translated (used internally) :param translate_attrs: whether attribute values should be translated (used internally) :return: the localized stream """ ignore_tags = self.ignore_tags include_attrs = self.include_attrs skip = 0 xml_lang = XML_NAMESPACE['lang'] if not self.extract_text: translate_text = False translate_attrs = False if type(self.translate) is FunctionType: gettext = self.translate if ctxt: ctxt['_i18n.gettext'] = gettext else: if IS_PYTHON2: gettext = self.translate.ugettext ngettext = self.translate.ungettext else: gettext = self.translate.gettext ngettext = self.translate.ngettext try: if IS_PYTHON2: dgettext = self.translate.dugettext dngettext = self.translate.dungettext else: dgettext = self.translate.dgettext dngettext = self.translate.dngettext except AttributeError: dgettext = lambda _, y: gettext(y) dngettext = lambda _, s, p, n: ngettext(s, p, n) if ctxt: ctxt['_i18n.gettext'] = gettext ctxt['_i18n.ngettext'] = ngettext ctxt['_i18n.dgettext'] = dgettext ctxt['_i18n.dngettext'] = dngettext if ctxt and ctxt.get('_i18n.domain'): # TODO: This can cause infinite recursion if dgettext is defined # via the AttributeError case above! gettext = lambda msg: dgettext(ctxt.get('_i18n.domain'), msg) for kind, data, pos in stream: # skip chunks that should not be localized if skip: if kind is START: skip += 1 elif kind is END: skip -= 1 yield kind, data, pos continue # handle different events that can be localized if kind is START: tag, attrs = data if tag in self.ignore_tags or \ isinstance(attrs.get(xml_lang), basestring): skip += 1 yield kind, data, pos continue new_attrs = [] changed = False for name, value in attrs: newval = value if isinstance(value, basestring): if translate_attrs and name in include_attrs: newval = gettext(value) else: newval = list( self(_ensure(value), ctxt, translate_text=False) ) if newval != value: value = newval changed = True new_attrs.append((name, value)) if changed: attrs = Attrs(new_attrs) yield kind, (tag, attrs), pos elif translate_text and kind is TEXT: text = data.strip() if text: data = data.replace(text, unicode(gettext(text))) yield kind, data, pos elif kind is SUB: directives, substream = data current_domain = None for idx, directive in enumerate(directives): # Organize directives to make everything work # FIXME: There's got to be a better way to do this! if isinstance(directive, DomainDirective): # Grab current domain and update context current_domain = directive.domain ctxt.push({'_i18n.domain': current_domain}) # Put domain directive as the first one in order to # update context before any other directives evaluation directives.insert(0, directives.pop(idx)) # If this is an i18n directive, no need to translate text # nodes here is_i18n_directive = any([ isinstance(d, ExtractableI18NDirective) for d in directives ]) substream = list(self(substream, ctxt, translate_text=not is_i18n_directive, translate_attrs=translate_attrs)) yield kind, (directives, substream), pos if current_domain: ctxt.pop() else: yield kind, data, pos
def __call__(self, stream): """Apply the filter to the given stream. :param stream: the markup event stream to filter """ in_form = in_select = in_option = in_textarea = False select_value = option_value = textarea_value = None option_start = None option_text = [] no_option_value = False for kind, data, pos in stream: if kind is START: tag, attrs = data tagname = tag.localname if tagname == "form" and ( self.name and attrs.get("name") == self.name or self.id and attrs.get("id") == self.id or not (self.id or self.name) ): in_form = True elif in_form: if tagname == "input": type = attrs.get("type", "").lower() if type in ("checkbox", "radio"): name = attrs.get("name") if name and name in self.data: value = self.data[name] declval = attrs.get("value") checked = False if isinstance(value, (list, tuple)): if declval: checked = declval in [unicode(v) for v in value] else: checked = any(value) else: if declval: checked = declval == unicode(value) elif type == "checkbox": checked = bool(value) if checked: attrs |= [(QName("checked"), "checked")] elif "checked" in attrs: attrs -= "checked" elif type in ("", "hidden", "text") or type == "password" and self.passwords: name = attrs.get("name") if name and name in self.data: value = self.data[name] if isinstance(value, (list, tuple)): value = value[0] if value is not None: attrs |= [(QName("value"), unicode(value))] elif tagname == "select": name = attrs.get("name") if name in self.data: select_value = self.data[name] in_select = True elif tagname == "textarea": name = attrs.get("name") if name in self.data: textarea_value = self.data.get(name) if isinstance(textarea_value, (list, tuple)): textarea_value = textarea_value[0] in_textarea = True elif in_select and tagname == "option": option_start = kind, data, pos option_value = attrs.get("value") if option_value is None: no_option_value = True option_value = "" in_option = True continue yield kind, (tag, attrs), pos elif in_form and kind is TEXT: if in_select and in_option: if no_option_value: option_value += data option_text.append((kind, data, pos)) continue elif in_textarea: continue yield kind, data, pos elif in_form and kind is END: tagname = data.localname if tagname == "form": in_form = False elif tagname == "select": in_select = False select_value = None elif in_select and tagname == "option": if isinstance(select_value, (tuple, list)): selected = option_value in [unicode(v) for v in select_value] else: selected = option_value == unicode(select_value) okind, (tag, attrs), opos = option_start if selected: attrs |= [(QName("selected"), "selected")] elif "selected" in attrs: attrs -= "selected" yield okind, (tag, attrs), opos if option_text: for event in option_text: yield event in_option = False no_option_value = False option_start = option_value = None option_text = [] elif tagname == "textarea": if textarea_value: yield TEXT, unicode(textarea_value), pos in_textarea = False yield kind, data, pos else: yield kind, data, pos