- Timestamp:
- Apr 21, 2010, 10:00:37 PM (13 years ago)
- File:
-
- 1 edited
-
trunk/genshi/filters/i18n.py (modified) (19 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/genshi/filters/i18n.py
r1115 r1118 28 28 from types import FunctionType 29 29 30 from genshi.core import Attrs, Namespace, QName, START, END, TEXT, START_NS,\31 END_NS,XML_NAMESPACE, _ensure, StreamEventKind30 from genshi.core import Attrs, Namespace, QName, START, END, TEXT, \ 31 XML_NAMESPACE, _ensure, StreamEventKind 32 32 from genshi.template.eval import _ast 33 33 from genshi.template.base import DirectiveFactory, EXPR, SUB, _apply_directives … … 216 216 self.params = ctxt.get('_i18n.choose.params', [])[:] 217 217 msgbuf = MessageBuffer(self) 218 219 stream = iter(_apply_directives(stream, directives, ctxt, vars)) 220 218 stream = _apply_directives(stream, directives, ctxt, vars) 219 221 220 previous = stream.next() 222 221 if previous[0] is START: … … 224 223 else: 225 224 msgbuf.append(*previous) 226 225 227 226 try: 228 227 previous = stream.next() … … 230 229 # For example <i18n:singular> or <i18n:plural> directives 231 230 yield MSGBUF, (), -1 # the place holder for msgbuf output 232 ctxt['_i18n.choose.%s' % type(self).__name__] = msgbuf231 ctxt['_i18n.choose.%s' % self.tagname] = msgbuf 233 232 return 234 235 for kind, data, posin stream:233 234 for event in stream: 236 235 msgbuf.append(*previous) 237 previous = kind, data, pos236 previous = event 238 237 yield MSGBUF, (), -1 # the place holder for msgbuf output 239 238 … … 242 241 else: 243 242 msgbuf.append(*previous) 244 ctxt['_i18n.choose.%s' % type(self).__name__] = msgbuf 245 243 ctxt['_i18n.choose.%s' % self.tagname] = msgbuf 246 244 247 245 def extract(self, translator, stream, gettext_functions=GETTEXT_FUNCTIONS, … … 362 360 def __call__(self, stream, directives, ctxt, **vars): 363 361 ctxt.push({'_i18n.choose.params': self.params, 364 '_i18n.choose.SingularDirective': None, 365 '_i18n.choose.PluralDirective': None}) 362 '_i18n.choose.singular': None, 363 '_i18n.choose.plural': None}) 364 365 ngettext = ctxt.get('_i18n.ngettext') 366 assert hasattr(ngettext, '__call__'), 'No ngettext function available' 367 dngettext = ctxt.get('_i18n.dngettext') 368 if not dngettext: 369 dngettext = lambda d, s, p, n: ngettext(s, p, n) 366 370 367 371 new_stream = [] … … 371 375 plural_msgbuf = None 372 376 373 ngettext = ctxt.get('_i18n.ungettext') 374 assert hasattr(ngettext, '__call__'), 'No ngettext function available' 375 dngettext = ctxt.get('_i18n.dngettext') 376 if not dngettext: 377 dngettext = lambda d, s, p, n: ngettext(s, p, n) 378 379 for kind, event, pos in stream: 380 if kind is SUB: 381 subdirectives, substream = event 382 if isinstance(subdirectives[0], 383 SingularDirective) and not singular_stream: 384 strip_directive_present = [] 385 for idx, subdirective in enumerate(subdirectives): 386 if isinstance(subdirective, StripDirective): 387 # Any strip directive should be applied AFTER 388 # the event's have been translated. 389 strip_directive_present.append( 390 subdirectives.pop(idx) 391 ) 392 # Apply directives to update context 377 numeral = self.numeral.evaluate(ctxt) 378 is_plural = self._is_plural(numeral, ngettext) 379 380 for event in stream: 381 if event[0] is SUB and any(isinstance(d, ChooseBranchDirective) 382 for d in event[1][0]): 383 subdirectives, substream = event[1] 384 385 if isinstance(subdirectives[0], SingularDirective): 393 386 singular_stream = list(_apply_directives(substream, 394 387 subdirectives, 395 388 ctxt, vars)) 396 if strip_directive_present: 397 singular_stream = list( 398 _apply_directives(singular_stream, 399 strip_directive_present, 400 ctxt, vars) 401 ) 402 del strip_directive_present 403 new_stream.append((MSGBUF, (), ('', -1))) # msgbuf place holder 404 singular_msgbuf = ctxt.get('_i18n.choose.SingularDirective') 405 elif isinstance(subdirectives[0], 406 PluralDirective) and not plural_stream: 407 strip_directive_present = [] 408 for idx, subdirective in enumerate(subdirectives): 409 if isinstance(subdirective, StripDirective): 410 # Any strip directive should be applied AFTER 411 # the event's have been translated. 412 strip_directive_present.append( 413 subdirectives.pop(idx) 414 ) 415 # Apply directives to update context 416 plural_stream = list(_apply_directives(substream, 417 subdirectives, 418 ctxt, vars)) 419 if strip_directive_present: 420 plural_stream = list( 421 _apply_directives(plural_stream, 422 strip_directive_present, 423 ctxt, vars) 424 ) 425 del strip_directive_present 426 plural_msgbuf = ctxt.get('_i18n.choose.PluralDirective') 427 else: 428 new_stream.append((kind, event, pos)) 389 new_stream.append((MSGBUF, None, (None, -1, -1))) 390 391 elif isinstance(subdirectives[0], PluralDirective): 392 if is_plural: 393 plural_stream = list(_apply_directives(substream, 394 subdirectives, 395 ctxt, vars)) 396 429 397 else: 430 new_stream.append( (kind, event, pos))398 new_stream.append(event) 431 399 432 400 if ctxt.get('_i18n.domain'): … … 434 402 s, p, n) 435 403 436 # XXX: should we test which form was chosen like this!?!?!? 437 # There should be no match in any catalogue for these singular and 438 # plural test strings 439 singular_test = u'O\x85\xbe\xa9\xa8az\xc3?\xe6\xa1\x02n\x84\x93' 440 plural_test = u'\xcc\xfb+\xd3Pn\x9d\tT\xec\x1d\xda\x1a\x88\x00' 441 translation = ngettext(singular_test, plural_test, 442 self.numeral.evaluate(ctxt)) 443 if translation == singular_test: 444 chosen_msgbuf = singular_msgbuf 445 chosen_stream = singular_stream 404 singular_msgbuf = ctxt.get('_i18n.choose.singular') 405 if is_plural: 406 plural_msgbuf = ctxt.get('_i18n.choose.plural') 407 msgbuf, choice = plural_msgbuf, plural_stream 446 408 else: 447 chosen_msgbuf = plural_msgbuf 448 chosen_stream = plural_stream 449 del singular_test, plural_test, translation 409 msgbuf, choice = singular_msgbuf, singular_stream 410 plural_msgbuf = MessageBuffer(self) 450 411 451 412 for kind, data, pos in new_stream: 452 413 if kind is MSGBUF: 453 for skind, sdata, spos in chosen_stream:454 if skindis MSGBUF:414 for event in choice: 415 if event[0] is MSGBUF: 455 416 translation = ngettext(singular_msgbuf.format(), 456 417 plural_msgbuf.format(), 457 self.numeral.evaluate(ctxt))458 for event in chosen_msgbuf.translate(translation):459 yield event418 numeral) 419 for subevent in msgbuf.translate(translation): 420 yield subevent 460 421 else: 461 yield skind, sdata, spos422 yield event 462 423 else: 463 424 yield kind, data, pos … … 518 479 comment_stack[-1:] 519 480 481 def _is_plural(self, numeral, ngettext): 482 # XXX: should we test which form was chosen like this!?!?!? 483 # There should be no match in any catalogue for these singular and 484 # plural test strings 485 singular = u'O\x85\xbe\xa9\xa8az\xc3?\xe6\xa1\x02n\x84\x93' 486 plural = u'\xcc\xfb+\xd3Pn\x9d\tT\xec\x1d\xda\x1a\x88\x00' 487 return ngettext(singular, plural, numeral) == plural 488 520 489 521 490 class DomainDirective(I18NDirective): … … 559 528 offset=-1): 560 529 Directive.__init__(self, None, template, namespaces, lineno, offset) 561 self.domain = value and value.strip() or '__DEFAULT__' 530 self.domain = value and value.strip() or '__DEFAULT__' 562 531 563 532 @classmethod … … 664 633 self.extract_text = extract_text 665 634 666 def __call__(self, stream, ctxt=None, search_text=True): 635 def __call__(self, stream, ctxt=None, translate_text=True, 636 translate_attrs=True): 667 637 """Translate any localizable strings in the given stream. 668 638 … … 675 645 :param stream: the markup event stream 676 646 :param ctxt: the template context (not used) 677 :param search_text: whether text nodes should be translated (used 678 internally) 647 :param translate_text: whether text nodes should be translated (used 648 internally) 649 :param translate_attrs: whether attribute values should be translated 650 (used internally) 679 651 :return: the localized stream 680 652 """ … … 683 655 skip = 0 684 656 xml_lang = XML_NAMESPACE['lang'] 657 if not self.extract_text: 658 translate_text = False 659 translate_attrs = False 685 660 686 661 if type(self.translate) is FunctionType: … … 690 665 else: 691 666 gettext = self.translate.ugettext 667 ngettext = self.translate.ungettext 692 668 try: 693 669 dgettext = self.translate.dugettext 694 except AttributeError:695 dgettext = lambda x, y: gettext(y)696 ngettext = self.translate.ungettext697 try:698 670 dngettext = self.translate.dungettext 699 671 except AttributeError: 700 d ngettext = lambda d, s, p, n: ngettext(s, p, n)701 672 dgettext = lambda _, y: gettext(y) 673 dngettext = lambda _, s, p, n: ngettext(s, p, n) 702 674 if ctxt: 703 675 ctxt['_i18n.gettext'] = gettext 704 ctxt['_i18n. ugettext'] =gettext676 ctxt['_i18n.ngettext'] = ngettext 705 677 ctxt['_i18n.dgettext'] = dgettext 706 ctxt['_i18n.ngettext'] = ngettext707 ctxt['_i18n.ungettext'] = ngettext708 678 ctxt['_i18n.dngettext'] = dngettext 709 679 710 extract_text = self.extract_text711 if not extract_text:712 search_text = False713 714 680 if ctxt and ctxt.get('_i18n.domain'): 715 old_gettext = gettext716 681 gettext = lambda msg: dgettext(ctxt.get('_i18n.domain'), msg) 717 682 … … 741 706 for name, value in attrs: 742 707 newval = value 743 if extract_text andisinstance(value, basestring):744 if name in include_attrs:708 if isinstance(value, basestring): 709 if translate_attrs and name in include_attrs: 745 710 newval = gettext(value) 746 711 else: 747 712 newval = list( 748 self(_ensure(value), ctxt, search_text=False)713 self(_ensure(value), ctxt, translate_text=False) 749 714 ) 750 715 if newval != value: … … 757 722 yield kind, (tag, attrs), pos 758 723 759 elif search_text and kind is TEXT:724 elif translate_text and kind is TEXT: 760 725 text = data.strip() 761 726 if text: … … 768 733 for idx, directive in enumerate(directives): 769 734 # Organize directives to make everything work 735 # FIXME: There's got to be a better way to do this! 770 736 if isinstance(directive, DomainDirective): 771 737 # Grab current domain and update context … … 783 749 ]) 784 750 substream = list(self(substream, ctxt, 785 search_text=not is_i18n_directive)) 751 translate_text=not is_i18n_directive, 752 translate_attrs=translate_attrs)) 786 753 yield kind, (directives, substream), pos 787 754 … … 1049 1016 """ 1050 1017 substream = None 1051 1018 1052 1019 def yield_parts(string): 1053 1020 for idx, part in enumerate(regex.split(string)):
Note: See TracChangeset
for help on using the changeset viewer.
