# Copyright 2019 The Chromium Authors. All rights reserved. # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. import os import sys import tempfile here = os.path.dirname(os.path.realpath(__file__)) repo_root = os.path.normpath(os.path.join(here, '..', '..', '..')) try: old_sys_path = sys.path sys.path = sys.path + [os.path.join(repo_root, 'tools', 'grit')] import grit.grd_reader import grit.node.message import grit.util finally: sys.path = old_sys_path TAGS_TO_IGNORE = ( # tags mostly point to resource files that don't contain UI # strings. 'include', # tags point to image files. 'structure', # tags point to .grdp files. Don't load included part files when # loading a .grd or .grdp file. A grd file's contents can refer to deleted # grdp files (e.g. if a grdp file was renamed). Trying to load it would # fail. It's also unnecessary to load files because grdp files are # handled separately in GetGrdpMessagesFromString. Grdp files are also # expected to not contain any tags. 'part') def GetGrdMessages(grd_path_or_string, dir_path): """Load the grd file and return a dict of message ids to messages. Ignores non-translateable messages.""" doc = grit.grd_reader.Parse( grd_path_or_string, dir_path, stop_after=None, first_ids_file=None, debug=False, defines={'_chromium': 1}, tags_to_ignore=set(TAGS_TO_IGNORE)) return { msg.attrs['name']: msg for msg in doc.GetChildrenOfType(grit.node.message.MessageNode) if msg.IsTranslateable() and not msg.IsAccessibilityWithNoUI() } def GetGrdpMessagesFromString(grdp_string): """Parses the contents of the grdp file given in grdp_string. grd_reader can't parse grdp files directly. Instead, this replaces grd specific tags in the input string with grdp specific tags, writes the output string in a temporary file and loads the grd from the temporary file. This code previously created a temporary directory (using grit.util), wrote a temporary grd file pointing to another temporary grdp file that contained the input string. This was not testable since os.path.exists is overridden in tests and grit.util uses mkdirs which in turn calls os.path.exists. This new code works because it doesn't need to check the existence of a path. It's expected that a grdp file will not refer to another grdp file via a tag. Currently, none of the grdp files in the repository does that. """ replaced_string = grdp_string.replace( '', """ """) replaced_string = replaced_string.replace( '', """ """) with tempfile.NamedTemporaryFile(delete=False) as f: f.write(replaced_string.encode('utf-8')) f.close() messages = GetGrdMessages(f.name, os.path.dirname(f.name)) os.remove(f.name) return messages