Hide keyboard shortcuts

Hot-keys on this page

r m x p   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

1############################################################################## 

2# 

3# Copyright (c) 2001, 2002 Zope Foundation and Contributors. 

4# All Rights Reserved. 

5# 

6# This software is subject to the provisions of the Zope Public License, 

7# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution. 

8# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED 

9# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 

10# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS 

11# FOR A PARTICULAR PURPOSE. 

12# 

13############################################################################## 

14 

15import re 

16 

17from .exc import CompilationError 

18from .utils import unicode_string 

19 

20NAME_RE = r"[a-zA-Z][-a-zA-Z0-9_]*" 

21 

22WHITELIST = frozenset([ 

23 "translate", 

24 "domain", 

25 "context", 

26 "target", 

27 "source", 

28 "attributes", 

29 "data", 

30 "name", 

31 "mode", 

32 "xmlns", 

33 "xml", 

34 "comment", 

35 "ignore", 

36 "ignore-attributes", 

37 ]) 

38 

39_interp_regex = re.compile(r'(?<!\$)(\$(?:(%(n)s)|{(%(n)s)}))' 

40 % ({'n': NAME_RE})) 

41 

42 

43try: # pragma: no cover 

44 str = unicode 

45except NameError: 

46 pass 

47 

48# BBB: The ``fast_translate`` function here is kept for backwards 

49# compatibility reasons. Do not use! 

50 

51try: # pragma: no cover 

52 from zope.i18n import interpolate 

53 from zope.i18n import translate 

54 from zope.i18nmessageid import Message 

55except ImportError: # pragma: no cover 

56 pass 

57else: # pragma: no cover 

58 def fast_translate(msgid, domain=None, mapping=None, context=None, 

59 target_language=None, default=None): 

60 if msgid is None: 

61 return 

62 

63 if target_language is not None or context is not None: 

64 result = translate( 

65 msgid, domain=domain, mapping=mapping, context=context, 

66 target_language=target_language, default=default) 

67 if result != msgid: 

68 return result 

69 

70 if isinstance(msgid, Message): 

71 default = msgid.default 

72 mapping = msgid.mapping 

73 

74 if default is None: 

75 default = str(msgid) 

76 

77 if not isinstance(default, basestring): 

78 return default 

79 

80 return interpolate(default, mapping) 

81 

82 

83def simple_translate(msgid, domain=None, mapping=None, context=None, 

84 target_language=None, default=None): 

85 if default is None: 

86 default = getattr(msgid, "default", msgid) 

87 

88 if mapping is None: 

89 mapping = getattr(msgid, "mapping", None) 

90 

91 if mapping: 

92 def replace(match): 

93 whole, param1, param2 = match.groups() 

94 return unicode_string(mapping.get(param1 or param2, whole)) 

95 return _interp_regex.sub(replace, default) 

96 

97 return default 

98 

99 

100def parse_attributes(attrs, xml=True): 

101 d = {} 

102 

103 # filter out empty items, eg: 

104 # i18n:attributes="value msgid; name msgid2;" 

105 # would result in 3 items where the last one is empty 

106 attrs = [spec for spec in attrs.split(";") if spec] 

107 

108 for spec in attrs: 

109 if ',' in spec: 

110 raise CompilationError( 

111 "Attribute must not contain comma. Use semicolon to " 

112 "list multiple attributes", spec 

113 ) 

114 parts = spec.split() 

115 if len(parts) == 2: 

116 attr, msgid = parts 

117 elif len(parts) == 1: 

118 attr = parts[0] 

119 msgid = None 

120 else: 

121 raise CompilationError( 

122 "Illegal i18n:attributes specification.", spec) 

123 if not xml: 

124 attr = attr.lower() 

125 attr = attr.strip() 

126 if attr in d: 

127 raise CompilationError( 

128 "Attribute may only be specified once in i18n:attributes", attr) 

129 d[attr] = msgid 

130 

131 return d