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'''The 'grit transl2tc' tool. 701b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org''' 801b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org 901b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org 1001b3bc768461bd303bff39f8cd1663682254e407joi@chromium.orgfrom grit import grd_reader 1101b3bc768461bd303bff39f8cd1663682254e407joi@chromium.orgfrom grit import util 12b9161407f737461b5db16a29782f8a31d19e602dbenrg@chromium.orgfrom grit.tool import interface 13b9161407f737461b5db16a29782f8a31d19e602dbenrg@chromium.orgfrom grit.tool import rc2grd 1401b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org 1501b3bc768461bd303bff39f8cd1663682254e407joi@chromium.orgfrom grit.extern import tclib 1601b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org 1701b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org 1801b3bc768461bd303bff39f8cd1663682254e407joi@chromium.orgclass TranslationToTc(interface.Tool): 1901b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org '''A tool for importing existing translations in RC format into the 2001b3bc768461bd303bff39f8cd1663682254e407joi@chromium.orgTranslation Console. 2101b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org 2201b3bc768461bd303bff39f8cd1663682254e407joi@chromium.orgUsage: 2301b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org 2401b3bc768461bd303bff39f8cd1663682254e407joi@chromium.orggrit -i GRD transl2tc [-l LIMITS] [RCOPTS] SOURCE_RC TRANSLATED_RC OUT_FILE 2501b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org 2601b3bc768461bd303bff39f8cd1663682254e407joi@chromium.orgThe tool needs a "source" RC file, i.e. in English, and an RC file that is a 2701b3bc768461bd303bff39f8cd1663682254e407joi@chromium.orgtranslation of precisely the source RC file (not of an older or newer version). 2801b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org 2901b3bc768461bd303bff39f8cd1663682254e407joi@chromium.orgThe tool also requires you to provide a .grd file (input file) e.g. using the 3001b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org-i global option or the GRIT_INPUT environment variable. The tool uses 3101b3bc768461bd303bff39f8cd1663682254e407joi@chromium.orginformation from your .grd file to correct placeholder names in the 3201b3bc768461bd303bff39f8cd1663682254e407joi@chromium.orgtranslations and ensure that only translatable items and translations still 3301b3bc768461bd303bff39f8cd1663682254e407joi@chromium.orgbeing used are output. 3401b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org 3501b3bc768461bd303bff39f8cd1663682254e407joi@chromium.orgThis tool will accept all the same RCOPTS as the 'grit rc2grd' tool. To get 3601b3bc768461bd303bff39f8cd1663682254e407joi@chromium.orga list of these options, run 'grit help rc2grd'. 3701b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org 3801b3bc768461bd303bff39f8cd1663682254e407joi@chromium.orgAdditionally, you can use the -l option (which must be the first option to the 3901b3bc768461bd303bff39f8cd1663682254e407joi@chromium.orgtool) to specify a file containing a list of message IDs to which output should 4001b3bc768461bd303bff39f8cd1663682254e407joi@chromium.orgbe limited. This is only useful if you are limiting the output to your XMB 4101b3bc768461bd303bff39f8cd1663682254e407joi@chromium.orgfiles using the 'grit xmb' tool's -l option. See 'grit help xmb' for how to 4201b3bc768461bd303bff39f8cd1663682254e407joi@chromium.orggenerate a file containing a list of the message IDs in an XMB file. 4301b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org 4401b3bc768461bd303bff39f8cd1663682254e407joi@chromium.orgThe tool will scan through both of the RC files as well as any HTML files they 4501b3bc768461bd303bff39f8cd1663682254e407joi@chromium.orgrefer to, and match together the source messages and translated messages. It 4601b3bc768461bd303bff39f8cd1663682254e407joi@chromium.orgwill output a file (OUTPUT_FILE) you can import directly into the TC using the 4701b3bc768461bd303bff39f8cd1663682254e407joi@chromium.orgBulk Translation Upload tool. 4801b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org''' 4901b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org 5001b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org def ShortDescription(self): 5101b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org return 'Import existing translations in RC format into the TC' 5201b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org 5301b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org def Setup(self, globopt, args): 5401b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org '''Sets the instance up for use. 5501b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org ''' 5601b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org self.SetOptions(globopt) 5701b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org self.rc2grd = rc2grd.Rc2Grd() 5801b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org self.rc2grd.SetOptions(globopt) 5901b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org self.limits = None 6001b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org if len(args) and args[0] == '-l': 61b9161407f737461b5db16a29782f8a31d19e602dbenrg@chromium.org self.limits = util.ReadFile(args[1], util.RAW_TEXT).split('\n') 6201b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org args = args[2:] 6301b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org return self.rc2grd.ParseOptions(args) 6401b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org 6501b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org def Run(self, globopt, args): 6601b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org args = self.Setup(globopt, args) 6701b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org 6801b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org if len(args) != 3: 6901b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org self.Out('This tool takes exactly three arguments:\n' 7001b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org ' 1. The path to the original RC file\n' 7101b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org ' 2. The path to the translated RC file\n' 7201b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org ' 3. The output file path.\n') 7301b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org return 2 7401b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org 7501b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org grd = grd_reader.Parse(self.o.input, debug=self.o.extra_verbose) 76ccda47032903a6550dac2921f88c51b4da55aa36benrg@chromium.org grd.RunGatherers() 7701b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org 78b9161407f737461b5db16a29782f8a31d19e602dbenrg@chromium.org source_rc = util.ReadFile(args[0], self.rc2grd.input_encoding) 79b9161407f737461b5db16a29782f8a31d19e602dbenrg@chromium.org transl_rc = util.ReadFile(args[1], self.rc2grd.input_encoding) 8001b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org translations = self.ExtractTranslations(grd, 81b9161407f737461b5db16a29782f8a31d19e602dbenrg@chromium.org source_rc, args[0], 82b9161407f737461b5db16a29782f8a31d19e602dbenrg@chromium.org transl_rc, args[1]) 8301b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org 84b9161407f737461b5db16a29782f8a31d19e602dbenrg@chromium.org with util.WrapOutputStream(open(args[2], 'w')) as output_file: 85b9161407f737461b5db16a29782f8a31d19e602dbenrg@chromium.org self.WriteTranslations(output_file, translations.items()) 8601b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org 8701b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org self.Out('Wrote output file %s' % args[2]) 8801b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org 89ccda47032903a6550dac2921f88c51b4da55aa36benrg@chromium.org def ExtractTranslations(self, current_grd, source_rc, source_path, 90ccda47032903a6550dac2921f88c51b4da55aa36benrg@chromium.org transl_rc, transl_path): 9101b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org '''Extracts translations from the translated RC file, matching them with 9201b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org translations in the source RC file to calculate their ID, and correcting 9301b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org placeholders, limiting output to translateables, etc. using the supplied 9401b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org .grd file which is the current .grd file for your project. 9501b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org 9601b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org If this object's 'limits' attribute is not None but a list, the output of 9701b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org this function will be further limited to include only messages that have 9801b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org message IDs in the 'limits' list. 9901b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org 10001b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org Args: 101ccda47032903a6550dac2921f88c51b4da55aa36benrg@chromium.org current_grd: grit.node.base.Node child, that has had RunGatherers() run 102ccda47032903a6550dac2921f88c51b4da55aa36benrg@chromium.org on it 10301b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org source_rc: Complete text of source RC file 10401b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org source_path: Path to the source RC file 10501b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org transl_rc: Complete text of translated RC file 10601b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org transl_path: Path to the translated RC file 10701b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org 10801b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org Return: 10901b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org { id1 : text1, '12345678' : 'Hello USERNAME, howzit?' } 11001b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org ''' 11101b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org source_grd = self.rc2grd.Process(source_rc, source_path) 11201b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org self.VerboseOut('Read %s into GRIT format, running gatherers.\n' % source_path) 113783385ad40d453977d8b9d537e204f851e21591abenrg@chromium.org source_grd.SetOutputLanguage(current_grd.output_language) 114783385ad40d453977d8b9d537e204f851e21591abenrg@chromium.org source_grd.SetDefines(current_grd.defines) 115ccda47032903a6550dac2921f88c51b4da55aa36benrg@chromium.org source_grd.RunGatherers(debug=self.o.extra_verbose) 11601b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org transl_grd = self.rc2grd.Process(transl_rc, transl_path) 117783385ad40d453977d8b9d537e204f851e21591abenrg@chromium.org transl_grd.SetOutputLanguage(current_grd.output_language) 118783385ad40d453977d8b9d537e204f851e21591abenrg@chromium.org transl_grd.SetDefines(current_grd.defines) 11901b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org self.VerboseOut('Read %s into GRIT format, running gatherers.\n' % transl_path) 120ccda47032903a6550dac2921f88c51b4da55aa36benrg@chromium.org transl_grd.RunGatherers(debug=self.o.extra_verbose) 12101b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org self.VerboseOut('Done running gatherers for %s.\n' % transl_path) 12201b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org 12301b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org # Proceed to create a map from ID to translation, getting the ID from the 12401b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org # source GRD and the translation from the translated GRD. 12501b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org id2transl = {} 12601b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org for source_node in source_grd: 12701b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org source_cliques = source_node.GetCliques() 12801b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org if not len(source_cliques): 12901b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org continue 13001b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org 13101b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org assert 'name' in source_node.attrs, 'All nodes with cliques should have an ID' 13201b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org node_id = source_node.attrs['name'] 13301b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org self.ExtraVerboseOut('Processing node %s\n' % node_id) 13401b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org transl_node = transl_grd.GetNodeById(node_id) 13501b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org 13601b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org if transl_node: 13701b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org transl_cliques = transl_node.GetCliques() 13801b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org if not len(transl_cliques) == len(source_cliques): 13901b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org self.Out( 14001b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org 'Warning: Translation for %s has wrong # of cliques, skipping.\n' % 14101b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org node_id) 14201b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org continue 14301b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org else: 14401b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org self.Out('Warning: No translation for %s, skipping.\n' % node_id) 14501b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org continue 14601b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org 14701b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org if source_node.name == 'message': 14801b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org # Fixup placeholders as well as possible based on information from 14901b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org # the current .grd file if they are 'TODO_XXXX' placeholders. We need 15001b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org # to fixup placeholders in the translated message so that it looks right 15101b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org # and we also need to fixup placeholders in the source message so that 15201b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org # its calculated ID will match the current message. 15301b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org current_node = current_grd.GetNodeById(node_id) 15401b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org if current_node: 155ccda47032903a6550dac2921f88c51b4da55aa36benrg@chromium.org assert len(source_cliques) == len(current_node.GetCliques()) == 1 15601b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org 15701b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org source_msg = source_cliques[0].GetMessage() 15801b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org current_msg = current_node.GetCliques()[0].GetMessage() 15901b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org 16001b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org # Only do this for messages whose source version has not changed. 16101b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org if (source_msg.GetRealContent() != current_msg.GetRealContent()): 16201b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org self.VerboseOut('Info: Message %s has changed; skipping\n' % node_id) 16301b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org else: 16401b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org transl_msg = transl_cliques[0].GetMessage() 16501b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org transl_content = transl_msg.GetContent() 16601b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org current_content = current_msg.GetContent() 16701b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org source_content = source_msg.GetContent() 16801b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org 16901b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org ok_to_fixup = True 17001b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org if (len(transl_content) != len(current_content)): 17101b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org # message structure of translation is different, don't try fixup 17201b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org ok_to_fixup = False 17301b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org if ok_to_fixup: 17401b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org for ix in range(len(transl_content)): 17501b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org if isinstance(transl_content[ix], tclib.Placeholder): 17601b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org if not isinstance(current_content[ix], tclib.Placeholder): 17701b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org ok_to_fixup = False # structure has changed 17801b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org break 17901b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org if (transl_content[ix].GetOriginal() != 18001b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org current_content[ix].GetOriginal()): 18101b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org ok_to_fixup = False # placeholders have likely been reordered 18201b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org break 18301b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org else: # translated part is not a placeholder but a string 18401b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org if isinstance(current_content[ix], tclib.Placeholder): 18501b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org ok_to_fixup = False # placeholders have likely been reordered 18601b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org break 18701b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org 18801b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org if not ok_to_fixup: 18901b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org self.VerboseOut( 19001b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org 'Info: Structure of message %s has changed; skipping.\n' % node_id) 19101b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org else: 19201b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org def Fixup(content, ix): 19301b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org if (isinstance(content[ix], tclib.Placeholder) and 19401b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org content[ix].GetPresentation().startswith('TODO_')): 19501b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org assert isinstance(current_content[ix], tclib.Placeholder) 19601b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org # Get the placeholder ID and example from the current message 19701b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org content[ix] = current_content[ix] 19801b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org for ix in range(len(transl_content)): 19901b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org Fixup(transl_content, ix) 20001b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org Fixup(source_content, ix) 20101b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org 20201b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org # Only put each translation once into the map. Warn if translations 20301b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org # for the same message are different. 20401b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org for ix in range(len(transl_cliques)): 20501b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org source_msg = source_cliques[ix].GetMessage() 20601b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org source_msg.GenerateId() # needed to refresh ID based on new placeholders 20701b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org message_id = source_msg.GetId() 20801b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org translated_content = transl_cliques[ix].GetMessage().GetPresentableContent() 20901b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org 21001b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org if message_id in id2transl: 21101b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org existing_translation = id2transl[message_id] 21201b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org if existing_translation != translated_content: 21301b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org original_text = source_cliques[ix].GetMessage().GetPresentableContent() 21401b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org self.Out('Warning: Two different translations for "%s":\n' 21501b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org ' Translation 1: "%s"\n' 21601b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org ' Translation 2: "%s"\n' % 21701b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org (original_text, existing_translation, translated_content)) 21801b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org else: 21901b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org id2transl[message_id] = translated_content 22001b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org 22101b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org # Remove translations for messages that do not occur in the current .grd 22201b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org # or have been marked as not translateable, or do not occur in the 'limits' 22301b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org # list (if it has been set). 22401b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org current_message_ids = current_grd.UberClique().AllMessageIds() 22501b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org for message_id in id2transl.keys(): 22601b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org if (message_id not in current_message_ids or 22701b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org not current_grd.UberClique().BestClique(message_id).IsTranslateable() or 22801b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org (self.limits and message_id not in self.limits)): 22901b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org del id2transl[message_id] 23001b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org 23101b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org return id2transl 23201b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org 233b9161407f737461b5db16a29782f8a31d19e602dbenrg@chromium.org @staticmethod 23401b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org def WriteTranslations(output_file, translations): 23501b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org '''Writes the provided list of translations to the provided output file 23601b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org in the format used by the TC's Bulk Translation Upload tool. The file 23701b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org must be UTF-8 encoded. 23801b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org 23901b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org Args: 240b9161407f737461b5db16a29782f8a31d19e602dbenrg@chromium.org output_file: util.WrapOutputStream(open('bingo.out', 'w')) 24101b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org translations: [ [id1, text1], ['12345678', 'Hello USERNAME, howzit?'] ] 24201b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org 24301b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org Return: 24401b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org None 24501b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org ''' 24601b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org for id, text in translations: 24701b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org text = text.replace('<', '<').replace('>', '>') 24801b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org output_file.write(id) 24901b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org output_file.write(' ') 25001b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org output_file.write(text) 25101b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org output_file.write('\n') 25201b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org 253