195640e3a20adea634b4df4ccf8c93f411184c438joi@chromium.org#!/usr/bin/env python 295640e3a20adea634b4df4ccf8c93f411184c438joi@chromium.org# Copyright (c) 2012 The Chromium Authors. All rights reserved. 301b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org# Use of this source code is governed by a BSD-style license that can be 401b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org# found in the LICENSE file. 501b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org 601b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org'''Handling of the <message> element. 701b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org''' 801b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org 901b3bc768461bd303bff39f8cd1663682254e407joi@chromium.orgimport re 1001b3bc768461bd303bff39f8cd1663682254e407joi@chromium.orgimport types 1101b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org 1201b3bc768461bd303bff39f8cd1663682254e407joi@chromium.orgfrom grit.node import base 1301b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org 1401b3bc768461bd303bff39f8cd1663682254e407joi@chromium.orgimport grit.format.rc_header 1501b3bc768461bd303bff39f8cd1663682254e407joi@chromium.orgimport grit.format.rc 1601b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org 1701b3bc768461bd303bff39f8cd1663682254e407joi@chromium.orgfrom grit import clique 1801b3bc768461bd303bff39f8cd1663682254e407joi@chromium.orgfrom grit import exception 1901fadb72b6e94e6511eaffd1874a8cc095f098a7joi@chromium.orgfrom grit import lazy_re 2001b3bc768461bd303bff39f8cd1663682254e407joi@chromium.orgfrom grit import tclib 2101b3bc768461bd303bff39f8cd1663682254e407joi@chromium.orgfrom grit import util 2201b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org 2301b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org# Finds whitespace at the start and end of a string which can be multiline. 2401fadb72b6e94e6511eaffd1874a8cc095f098a7joi@chromium.org_WHITESPACE = lazy_re.compile('(?P<start>\s*)(?P<body>.+?)(?P<end>\s*)\Z', 2501fadb72b6e94e6511eaffd1874a8cc095f098a7joi@chromium.org re.DOTALL | re.MULTILINE) 2601b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org 2701b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org 2801b3bc768461bd303bff39f8cd1663682254e407joi@chromium.orgclass MessageNode(base.ContentNode): 2901b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org '''A <message> element.''' 3001b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org 3101b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org # For splitting a list of things that can be separated by commas or 3201b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org # whitespace 3301fadb72b6e94e6511eaffd1874a8cc095f098a7joi@chromium.org _SPLIT_RE = lazy_re.compile('\s*,\s*|\s+') 3401b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org 3501b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org def __init__(self): 36b9161407f737461b5db16a29782f8a31d19e602dbenrg@chromium.org super(MessageNode, self).__init__() 3701b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org # Valid after EndParsing, this is the MessageClique that contains the 3801b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org # source message and any translations of it that have been loaded. 3901b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org self.clique = None 4001b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org 4101b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org # We don't send leading and trailing whitespace into the translation 4201b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org # console, but rather tack it onto the source message and any 4301b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org # translations when formatting them into RC files or what have you. 4401b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org self.ws_at_start = '' # Any whitespace characters at the start of the text 4501b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org self.ws_at_end = '' # --"-- at the end of the text 4601b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org 4701b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org # A list of "shortcut groups" this message is in. We check to make sure 4801b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org # that shortcut keys (e.g. &J) within each shortcut group are unique. 4901b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org self.shortcut_groups_ = [] 5001b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org 51f221c01d847d97c0a487f4059ee33d4d7b6d7d5fnewt@chromium.org # Formatter-specific data used to control the output of individual strings. 52f221c01d847d97c0a487f4059ee33d4d7b6d7d5fnewt@chromium.org # formatter_data is a space separated list of C preprocessor-style 53f221c01d847d97c0a487f4059ee33d4d7b6d7d5fnewt@chromium.org # definitions. Names without values are given the empty string value. 54f221c01d847d97c0a487f4059ee33d4d7b6d7d5fnewt@chromium.org # Example: "foo=5 bar baz=100" 55f221c01d847d97c0a487f4059ee33d4d7b6d7d5fnewt@chromium.org self.formatter_data = {} 56f221c01d847d97c0a487f4059ee33d4d7b6d7d5fnewt@chromium.org 5701b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org def _IsValidChild(self, child): 5801b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org return isinstance(child, (PhNode)) 5901b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org 6001b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org def _IsValidAttribute(self, name, value): 6101b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org if name not in ['name', 'offset', 'translateable', 'desc', 'meaning', 6201b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org 'internal_comment', 'shortcut_groups', 'custom_type', 63f221c01d847d97c0a487f4059ee33d4d7b6d7d5fnewt@chromium.org 'validation_expr', 'use_name_for_id', 'sub_variable', 64f221c01d847d97c0a487f4059ee33d4d7b6d7d5fnewt@chromium.org 'formatter_data']: 6501b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org return False 6677cbaa8b1f1af05d8ba2c2a951c74e7909318830joi@chromium.org if (name in ('translateable', 'sub_variable') and 6777cbaa8b1f1af05d8ba2c2a951c74e7909318830joi@chromium.org value not in ['true', 'false']): 6801b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org return False 6901b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org return True 7001b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org 7101b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org def MandatoryAttributes(self): 7201b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org return ['name|offset'] 7301b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org 7401b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org def DefaultAttributes(self): 7501b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org return { 7677cbaa8b1f1af05d8ba2c2a951c74e7909318830joi@chromium.org 'custom_type' : '', 7701b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org 'desc' : '', 78f221c01d847d97c0a487f4059ee33d4d7b6d7d5fnewt@chromium.org 'formatter_data' : '', 7901b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org 'internal_comment' : '', 8077cbaa8b1f1af05d8ba2c2a951c74e7909318830joi@chromium.org 'meaning' : '', 8101b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org 'shortcut_groups' : '', 8277cbaa8b1f1af05d8ba2c2a951c74e7909318830joi@chromium.org 'sub_variable' : 'false', 8377cbaa8b1f1af05d8ba2c2a951c74e7909318830joi@chromium.org 'translateable' : 'true', 8401b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org 'use_name_for_id' : 'false', 8577cbaa8b1f1af05d8ba2c2a951c74e7909318830joi@chromium.org 'validation_expr' : '', 8601b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org } 8701b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org 88f221c01d847d97c0a487f4059ee33d4d7b6d7d5fnewt@chromium.org def HandleAttribute(self, attrib, value): 89f221c01d847d97c0a487f4059ee33d4d7b6d7d5fnewt@chromium.org base.ContentNode.HandleAttribute(self, attrib, value) 90f221c01d847d97c0a487f4059ee33d4d7b6d7d5fnewt@chromium.org if attrib == 'formatter_data': 91f221c01d847d97c0a487f4059ee33d4d7b6d7d5fnewt@chromium.org # Parse value, a space-separated list of defines, into a dict. 92f221c01d847d97c0a487f4059ee33d4d7b6d7d5fnewt@chromium.org # Example: "foo=5 bar" -> {'foo':'5', 'bar':''} 93f221c01d847d97c0a487f4059ee33d4d7b6d7d5fnewt@chromium.org for item in value.split(): 94f221c01d847d97c0a487f4059ee33d4d7b6d7d5fnewt@chromium.org name, sep, val = item.partition('=') 95f221c01d847d97c0a487f4059ee33d4d7b6d7d5fnewt@chromium.org self.formatter_data[name] = val 96f221c01d847d97c0a487f4059ee33d4d7b6d7d5fnewt@chromium.org 9701b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org def GetTextualIds(self): 9801b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org ''' 9901b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org Returns the concatenation of the parent's node first_id and 10001b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org this node's offset if it has one, otherwise just call the 10101b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org superclass' implementation 10201b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org ''' 10301b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org if 'offset' in self.attrs: 10401b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org # we search for the first grouping node in the parents' list 10501b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org # to take care of the case where the first parent is an <if> node 10601b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org grouping_parent = self.parent 10701b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org import grit.node.empty 10801b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org while grouping_parent and not isinstance(grouping_parent, 10901b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org grit.node.empty.GroupingNode): 11001b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org grouping_parent = grouping_parent.parent 11101b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org 11201b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org assert 'first_id' in grouping_parent.attrs 11301b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org return [grouping_parent.attrs['first_id'] + '_' + self.attrs['offset']] 11401b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org else: 115b9161407f737461b5db16a29782f8a31d19e602dbenrg@chromium.org return super(MessageNode, self).GetTextualIds() 11601b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org 11701b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org def IsTranslateable(self): 11801b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org return self.attrs['translateable'] == 'true' 11901b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org 12001b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org def EndParsing(self): 121b9161407f737461b5db16a29782f8a31d19e602dbenrg@chromium.org super(MessageNode, self).EndParsing() 12201b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org 12301b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org # Make the text (including placeholder references) and list of placeholders, 12401b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org # then strip and store leading and trailing whitespace and create the 12501b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org # tclib.Message() and a clique to contain it. 12601b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org 12701b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org text = '' 12801b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org placeholders = [] 12901b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org for item in self.mixed_content: 13001b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org if isinstance(item, types.StringTypes): 13101b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org text += item 13201b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org else: 13301b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org presentation = item.attrs['name'].upper() 13401b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org text += presentation 13501b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org ex = ' ' 13601b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org if len(item.children): 13701b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org ex = item.children[0].GetCdata() 13801b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org original = item.GetCdata() 13901b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org placeholders.append(tclib.Placeholder(presentation, original, ex)) 14001b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org 14101b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org m = _WHITESPACE.match(text) 14201b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org if m: 14301b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org self.ws_at_start = m.group('start') 14401b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org self.ws_at_end = m.group('end') 14501b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org text = m.group('body') 14601b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org 14701b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org self.shortcut_groups_ = self._SPLIT_RE.split(self.attrs['shortcut_groups']) 14801b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org self.shortcut_groups_ = [i for i in self.shortcut_groups_ if i != ''] 14901b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org 15001b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org description_or_id = self.attrs['desc'] 15101b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org if description_or_id == '' and 'name' in self.attrs: 15201b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org description_or_id = 'ID: %s' % self.attrs['name'] 15301b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org 15401b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org assigned_id = None 155ccda47032903a6550dac2921f88c51b4da55aa36benrg@chromium.org if self.attrs['use_name_for_id'] == 'true': 15601b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org assigned_id = self.attrs['name'] 15701b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org message = tclib.Message(text=text, placeholders=placeholders, 15801b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org description=description_or_id, 15901b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org meaning=self.attrs['meaning'], 16001b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org assigned_id=assigned_id) 16177cbaa8b1f1af05d8ba2c2a951c74e7909318830joi@chromium.org self.InstallMessage(message) 16277cbaa8b1f1af05d8ba2c2a951c74e7909318830joi@chromium.org 16377cbaa8b1f1af05d8ba2c2a951c74e7909318830joi@chromium.org def InstallMessage(self, message): 16477cbaa8b1f1af05d8ba2c2a951c74e7909318830joi@chromium.org '''Sets this node's clique from a tclib.Message instance. 16577cbaa8b1f1af05d8ba2c2a951c74e7909318830joi@chromium.org 16677cbaa8b1f1af05d8ba2c2a951c74e7909318830joi@chromium.org Args: 16777cbaa8b1f1af05d8ba2c2a951c74e7909318830joi@chromium.org message: A tclib.Message. 16877cbaa8b1f1af05d8ba2c2a951c74e7909318830joi@chromium.org ''' 16901b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org self.clique = self.UberClique().MakeClique(message, self.IsTranslateable()) 17001b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org for group in self.shortcut_groups_: 17101b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org self.clique.AddToShortcutGroup(group) 17201b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org if self.attrs['custom_type'] != '': 17301b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org self.clique.SetCustomType(util.NewClassInstance(self.attrs['custom_type'], 17401b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org clique.CustomType)) 17501b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org elif self.attrs['validation_expr'] != '': 17601b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org self.clique.SetCustomType( 17701b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org clique.OneOffCustomType(self.attrs['validation_expr'])) 17801b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org 17977cbaa8b1f1af05d8ba2c2a951c74e7909318830joi@chromium.org def SubstituteMessages(self, substituter): 18077cbaa8b1f1af05d8ba2c2a951c74e7909318830joi@chromium.org '''Applies substitution to this message. 18177cbaa8b1f1af05d8ba2c2a951c74e7909318830joi@chromium.org 18277cbaa8b1f1af05d8ba2c2a951c74e7909318830joi@chromium.org Args: 18377cbaa8b1f1af05d8ba2c2a951c74e7909318830joi@chromium.org substituter: a grit.util.Substituter object. 18477cbaa8b1f1af05d8ba2c2a951c74e7909318830joi@chromium.org ''' 18577cbaa8b1f1af05d8ba2c2a951c74e7909318830joi@chromium.org message = substituter.SubstituteMessage(self.clique.GetMessage()) 18677cbaa8b1f1af05d8ba2c2a951c74e7909318830joi@chromium.org if message is not self.clique.GetMessage(): 18777cbaa8b1f1af05d8ba2c2a951c74e7909318830joi@chromium.org self.InstallMessage(message) 18877cbaa8b1f1af05d8ba2c2a951c74e7909318830joi@chromium.org 18901b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org def GetCliques(self): 19001b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org if self.clique: 19101b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org return [self.clique] 19201b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org else: 19301b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org return [] 19401b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org 19501b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org def Translate(self, lang): 19601b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org '''Returns a translated version of this message. 19701b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org ''' 19801b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org assert self.clique 19901b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org msg = self.clique.MessageForLanguage(lang, 20001b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org self.PseudoIsAllowed(), 20101b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org self.ShouldFallbackToEnglish() 20201b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org ).GetRealContent() 20301b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org return msg.replace('[GRITLANGCODE]', lang) 20401b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org 20501b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org def NameOrOffset(self): 20601b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org if 'name' in self.attrs: 20701b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org return self.attrs['name'] 20801b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org else: 20901b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org return self.attrs['offset'] 21001b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org 21177cbaa8b1f1af05d8ba2c2a951c74e7909318830joi@chromium.org def ExpandVariables(self): 21277cbaa8b1f1af05d8ba2c2a951c74e7909318830joi@chromium.org '''We always expand variables on Messages.''' 21377cbaa8b1f1af05d8ba2c2a951c74e7909318830joi@chromium.org return True 21477cbaa8b1f1af05d8ba2c2a951c74e7909318830joi@chromium.org 21501b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org def GetDataPackPair(self, lang, encoding): 21601b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org '''Returns a (id, string) pair that represents the string id and the string 2174460b853d6df39e3b89ae1abb278e9241db72e02joaodasilva@chromium.org in the specified encoding, where |encoding| is one of the encoding values 2184460b853d6df39e3b89ae1abb278e9241db72e02joaodasilva@chromium.org accepted by util.Encode. This is used to generate the data pack data file. 21901b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org ''' 22001b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org from grit.format import rc_header 221ccda47032903a6550dac2921f88c51b4da55aa36benrg@chromium.org id_map = rc_header.GetIds(self.GetRoot()) 22201b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org id = id_map[self.GetTextualIds()[0]] 22301b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org 22401b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org message = self.ws_at_start + self.Translate(lang) + self.ws_at_end 2254460b853d6df39e3b89ae1abb278e9241db72e02joaodasilva@chromium.org return id, util.Encode(message, encoding) 22601b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org 227b9161407f737461b5db16a29782f8a31d19e602dbenrg@chromium.org @staticmethod 22801b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org def Construct(parent, message, name, desc='', meaning='', translateable=True): 22901b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org '''Constructs a new message node that is a child of 'parent', with the 23001b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org name, desc, meaning and translateable attributes set using the same-named 23101b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org parameters and the text of the message and any placeholders taken from 23201b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org 'message', which must be a tclib.Message() object.''' 23301b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org # Convert type to appropriate string 234b9161407f737461b5db16a29782f8a31d19e602dbenrg@chromium.org translateable = 'true' if translateable else 'false' 23501b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org 23601b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org node = MessageNode() 23701b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org node.StartParsing('message', parent) 23801b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org node.HandleAttribute('name', name) 23901b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org node.HandleAttribute('desc', desc) 24001b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org node.HandleAttribute('meaning', meaning) 24101b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org node.HandleAttribute('translateable', translateable) 24201b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org 24301b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org items = message.GetContent() 244b9161407f737461b5db16a29782f8a31d19e602dbenrg@chromium.org for ix, item in enumerate(items): 245b9161407f737461b5db16a29782f8a31d19e602dbenrg@chromium.org if isinstance(item, types.StringTypes): 24601b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org # Ensure whitespace at front and back of message is correctly handled. 24701b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org if ix == 0: 248b9161407f737461b5db16a29782f8a31d19e602dbenrg@chromium.org item = "'''" + item 24901b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org if ix == len(items) - 1: 250b9161407f737461b5db16a29782f8a31d19e602dbenrg@chromium.org item = item + "'''" 25101b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org 252b9161407f737461b5db16a29782f8a31d19e602dbenrg@chromium.org node.AppendContent(item) 25301b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org else: 25401b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org phnode = PhNode() 25501b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org phnode.StartParsing('ph', node) 256b9161407f737461b5db16a29782f8a31d19e602dbenrg@chromium.org phnode.HandleAttribute('name', item.GetPresentation()) 257b9161407f737461b5db16a29782f8a31d19e602dbenrg@chromium.org phnode.AppendContent(item.GetOriginal()) 25801b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org 259b9161407f737461b5db16a29782f8a31d19e602dbenrg@chromium.org if len(item.GetExample()) and item.GetExample() != ' ': 26001b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org exnode = ExNode() 26101b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org exnode.StartParsing('ex', phnode) 262b9161407f737461b5db16a29782f8a31d19e602dbenrg@chromium.org exnode.AppendContent(item.GetExample()) 26301b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org exnode.EndParsing() 26401b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org phnode.AddChild(exnode) 26501b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org 26601b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org phnode.EndParsing() 26701b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org node.AddChild(phnode) 26801b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org 26901b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org node.EndParsing() 27001b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org return node 27101b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org 27201b3bc768461bd303bff39f8cd1663682254e407joi@chromium.orgclass PhNode(base.ContentNode): 27301b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org '''A <ph> element.''' 27401b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org 27501b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org def _IsValidChild(self, child): 27601b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org return isinstance(child, ExNode) 27701b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org 27801b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org def MandatoryAttributes(self): 27901b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org return ['name'] 28001b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org 28101b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org def EndParsing(self): 282b9161407f737461b5db16a29782f8a31d19e602dbenrg@chromium.org super(PhNode, self).EndParsing() 28301b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org # We only allow a single example for each placeholder 28401b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org if len(self.children) > 1: 28501b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org raise exception.TooManyExamples() 28601b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org 287ccda47032903a6550dac2921f88c51b4da55aa36benrg@chromium.org def GetTextualIds(self): 288ccda47032903a6550dac2921f88c51b4da55aa36benrg@chromium.org # The 'name' attribute is not an ID. 289ccda47032903a6550dac2921f88c51b4da55aa36benrg@chromium.org return [] 290ccda47032903a6550dac2921f88c51b4da55aa36benrg@chromium.org 29101b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org 29201b3bc768461bd303bff39f8cd1663682254e407joi@chromium.orgclass ExNode(base.ContentNode): 29301b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org '''An <ex> element.''' 29401b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org pass 295