OLD | NEW |
(Empty) | |
| 1 #!/usr/bin/python2.4 |
| 2 # Copyright (c) 2011 The Chromium Authors. All rights reserved. |
| 3 # Use of this source code is governed by a BSD-style license that can be |
| 4 # found in the LICENSE file. |
| 5 |
| 6 '''The <structure> element. |
| 7 ''' |
| 8 |
| 9 import os |
| 10 |
| 11 from grit.node import base |
| 12 from grit.node import variant |
| 13 |
| 14 from grit import constants |
| 15 from grit import exception |
| 16 from grit import util |
| 17 |
| 18 import grit.gather.rc |
| 19 import grit.gather.tr_html |
| 20 import grit.gather.admin_template |
| 21 import grit.gather.txt |
| 22 import grit.gather.muppet_strings |
| 23 import grit.gather.policy_json |
| 24 |
| 25 import grit.format.rc |
| 26 import grit.format.rc_header |
| 27 |
| 28 # RTL languages |
| 29 # TODO(jennyz): remove this fixed set of RTL language array |
| 30 # when generic expand_variable code is added by grit team. |
| 31 _RTL_LANGS = [ |
| 32 'ar', |
| 33 'iw', |
| 34 'ur', |
| 35 ] |
| 36 |
| 37 # Type of the gatherer to use for each type attribute |
| 38 _GATHERERS = { |
| 39 'accelerators' : grit.gather.rc.Accelerators, |
| 40 'admin_template' : grit.gather.admin_template.AdmGatherer, |
| 41 'dialog' : grit.gather.rc.Dialog, |
| 42 'menu' : grit.gather.rc.Menu, |
| 43 'muppet' : grit.gather.muppet_strings.MuppetStrings, |
| 44 'rcdata' : grit.gather.rc.RCData, |
| 45 'tr_html' : grit.gather.tr_html.TrHtml, |
| 46 'txt' : grit.gather.txt.TxtFile, |
| 47 'version' : grit.gather.rc.Version, |
| 48 'policy_template_metafile' : grit.gather.policy_json.PolicyJson, |
| 49 } |
| 50 |
| 51 |
| 52 # Formatter instance to use for each type attribute |
| 53 # when formatting .rc files. |
| 54 _RC_FORMATTERS = { |
| 55 'accelerators' : grit.format.rc.RcSection(), |
| 56 'admin_template' : grit.format.rc.RcInclude('ADM'), |
| 57 'dialog' : grit.format.rc.RcSection(), |
| 58 'menu' : grit.format.rc.RcSection(), |
| 59 'muppet' : grit.format.rc.RcInclude('XML'), |
| 60 'rcdata' : grit.format.rc.RcSection(), |
| 61 'tr_html' : grit.format.rc.RcInclude('HTML'), |
| 62 'txt' : grit.format.rc.RcInclude('TXT'), |
| 63 'version' : grit.format.rc.RcSection(), |
| 64 'policy_template_metafile': None, |
| 65 } |
| 66 |
| 67 |
| 68 # TODO(joi) Print a warning if the 'variant_of_revision' attribute indicates |
| 69 # that a skeleton variant is older than the original file. |
| 70 |
| 71 |
| 72 class StructureNode(base.Node): |
| 73 '''A <structure> element.''' |
| 74 |
| 75 def __init__(self): |
| 76 base.Node.__init__(self) |
| 77 self.gatherer = None |
| 78 self.skeletons = {} # expressions to skeleton gatherers |
| 79 |
| 80 def _IsValidChild(self, child): |
| 81 return isinstance(child, variant.SkeletonNode) |
| 82 |
| 83 def MandatoryAttributes(self): |
| 84 return ['type', 'name', 'file'] |
| 85 |
| 86 def DefaultAttributes(self): |
| 87 return { 'encoding' : 'cp1252', |
| 88 'exclude_from_rc' : 'false', |
| 89 'line_end' : 'unix', |
| 90 'output_encoding' : 'utf-8', |
| 91 'generateid': 'true', |
| 92 'expand_variables' : 'false', |
| 93 'output_filename' : '', |
| 94 # TODO(joi) this is a hack - should output all generated files |
| 95 # as SCons dependencies; however, for now there is a bug I can't |
| 96 # find where GRIT doesn't build the matching fileset, therefore |
| 97 # this hack so that only the files you really need are marked as |
| 98 # dependencies. |
| 99 'sconsdep' : 'false', |
| 100 } |
| 101 |
| 102 def IsExcludedFromRc(self): |
| 103 return self.attrs['exclude_from_rc'] == 'true' |
| 104 |
| 105 def GetLineEnd(self): |
| 106 '''Returns the end-of-line character or characters for files output because |
| 107 of this node ('\r\n', '\n', or '\r' depending on the 'line_end' attribute). |
| 108 ''' |
| 109 if self.attrs['line_end'] == 'unix': |
| 110 return '\n' |
| 111 elif self.attrs['line_end'] == 'windows': |
| 112 return '\r\n' |
| 113 elif self.attrs['line_end'] == 'mac': |
| 114 return '\r' |
| 115 else: |
| 116 raise exception.UnexpectedAttribute( |
| 117 "Attribute 'line_end' must be one of 'linux' (default), 'windows' or 'ma
c'") |
| 118 |
| 119 def GetCliques(self): |
| 120 if self.gatherer: |
| 121 return self.gatherer.GetCliques() |
| 122 else: |
| 123 return [] |
| 124 |
| 125 def GetTextualIds(self): |
| 126 if self.gatherer and self.attrs['type'] not in ['tr_html', 'admin_template',
'txt']: |
| 127 return self.gatherer.GetTextualIds() |
| 128 else: |
| 129 return [self.attrs['name']] |
| 130 |
| 131 def ItemFormatter(self, t): |
| 132 if t == 'rc_header': |
| 133 return grit.format.rc_header.Item() |
| 134 elif (t in ['rc_all', 'rc_translateable', 'rc_nontranslateable'] and |
| 135 self.SatisfiesOutputCondition()): |
| 136 return _RC_FORMATTERS[self.attrs['type']] |
| 137 else: |
| 138 return super(type(self), self).ItemFormatter(t) |
| 139 |
| 140 def RunGatherers(self, recursive=False, debug=False): |
| 141 if self.gatherer: |
| 142 return # idempotent |
| 143 |
| 144 gathertype = _GATHERERS[self.attrs['type']] |
| 145 |
| 146 if debug: |
| 147 print 'Running gatherer %s for file %s' % (str(gathertype), self.FilenameT
oOpen()) |
| 148 |
| 149 self.gatherer = gathertype.FromFile(self.FilenameToOpen(), |
| 150 self.attrs['name'], |
| 151 self.attrs['encoding']) |
| 152 self.gatherer.SetUberClique(self.UberClique()) |
| 153 self.gatherer.Parse() |
| 154 |
| 155 for child in self.children: |
| 156 assert isinstance(child, variant.SkeletonNode) |
| 157 skel = gathertype.FromFile(child.FilenameToOpen(), |
| 158 self.attrs['name'], |
| 159 child.GetEncodingToUse()) |
| 160 skel.SetUberClique(self.UberClique()) |
| 161 skel.SetSkeleton(True) |
| 162 skel.Parse() |
| 163 self.skeletons[child.attrs['expr']] = skel |
| 164 |
| 165 def GetSkeletonGatherer(self): |
| 166 '''Returns the gatherer for the alternate skeleton that should be used, |
| 167 based on the expressions for selecting skeletons, or None if the skeleton |
| 168 from the English version of the structure should be used. |
| 169 ''' |
| 170 for expr in self.skeletons: |
| 171 if self.EvaluateCondition(expr): |
| 172 return self.skeletons[expr] |
| 173 return None |
| 174 |
| 175 def GetFilePath(self): |
| 176 return self.ToRealPath(self.attrs['file']) |
| 177 |
| 178 def HasFileForLanguage(self): |
| 179 return self.attrs['type'] in ['tr_html', 'admin_template', 'txt', 'muppet'] |
| 180 |
| 181 def FileForLanguage(self, lang, output_dir, create_file=True, |
| 182 return_if_not_generated=True): |
| 183 '''Returns the filename of the file associated with this structure, |
| 184 for the specified language. |
| 185 |
| 186 Args: |
| 187 lang: 'fr' |
| 188 output_dir: 'c:\temp' |
| 189 create_file: True |
| 190 ''' |
| 191 assert self.HasFileForLanguage() |
| 192 if (lang == self.GetRoot().GetSourceLanguage() and |
| 193 self.attrs['expand_variables'] != 'true'): |
| 194 if return_if_not_generated: |
| 195 return self.GetFilePath() |
| 196 else: |
| 197 return None |
| 198 else: |
| 199 if self.attrs['output_filename'] != '': |
| 200 filename = self.attrs['output_filename'] |
| 201 else: |
| 202 filename = os.path.basename(self.attrs['file']) |
| 203 assert len(filename) |
| 204 filename = '%s_%s' % (lang, filename) |
| 205 filename = os.path.join(output_dir, filename) |
| 206 |
| 207 if create_file: |
| 208 text = self.gatherer.Translate( |
| 209 lang, |
| 210 pseudo_if_not_available=self.PseudoIsAllowed(), |
| 211 fallback_to_english=self.ShouldFallbackToEnglish(), |
| 212 skeleton_gatherer=self.GetSkeletonGatherer()) |
| 213 |
| 214 file_object = util.WrapOutputStream(file(filename, 'wb'), |
| 215 self._GetOutputEncoding()) |
| 216 file_contents = util.FixLineEnd(text, self.GetLineEnd()) |
| 217 if self.attrs['expand_variables'] == 'true': |
| 218 file_contents = file_contents.replace('[GRITLANGCODE]', lang) |
| 219 # TODO(jennyz): remove this hard coded logic for expanding |
| 220 # [GRITDIR] variable for RTL languages when the generic |
| 221 # expand_variable code is added by grit team. |
| 222 if lang in _RTL_LANGS : |
| 223 file_contents = file_contents.replace('[GRITDIR]', 'dir="RTL"') |
| 224 else : |
| 225 file_contents = file_contents.replace('[GRITDIR]', 'dir="LTR"') |
| 226 if self._ShouldAddBom(): |
| 227 file_object.write(constants.BOM) |
| 228 file_object.write(file_contents) |
| 229 file_object.close() |
| 230 |
| 231 return filename |
| 232 |
| 233 def _GetOutputEncoding(self): |
| 234 '''Python doesn't natively support UTF encodings with a BOM signature, |
| 235 so we add support by allowing you to append '-sig' to the encoding name. |
| 236 This function returns the specified output encoding minus that part. |
| 237 ''' |
| 238 enc = self.attrs['output_encoding'] |
| 239 if enc.endswith('-sig'): |
| 240 return enc[0:len(enc) - len('-sig')] |
| 241 else: |
| 242 return enc |
| 243 |
| 244 def _ShouldAddBom(self): |
| 245 '''Returns true if output files should have the Unicode BOM prepended. |
| 246 ''' |
| 247 return self.attrs['output_encoding'].endswith('-sig') |
| 248 |
| 249 # static method |
| 250 def Construct(parent, name, type, file, encoding='cp1252'): |
| 251 '''Creates a new node which is a child of 'parent', with attributes set |
| 252 by parameters of the same name. |
| 253 ''' |
| 254 node = StructureNode() |
| 255 node.StartParsing('structure', parent) |
| 256 node.HandleAttribute('name', name) |
| 257 node.HandleAttribute('type', type) |
| 258 node.HandleAttribute('file', file) |
| 259 node.HandleAttribute('encoding', encoding) |
| 260 node.EndParsing() |
| 261 return node |
| 262 Construct = staticmethod(Construct) |
| 263 |
OLD | NEW |