| # 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 = ( |
| # <include> tags mostly point to resource files that don't contain UI |
| # strings. |
| 'include', |
| # <structure> tags point to image files. |
| 'structure', |
| # <part> 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 <part> files because grdp files are |
| # handled separately in GetGrdpMessagesFromString. Grdp files are also |
| # expected to not contain any <part> 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 |
| <part> tag. Currently, none of the grdp files in the repository does that. |
| """ |
| replaced_string = grdp_string.replace( |
| '<grit-part>', |
| """<grit base_dir="." latest_public_release="1" current_release="1"> |
| <release seq="1" allow_pseudo="false"> |
| <messages fallback_to_english="true"> |
| """) |
| replaced_string = replaced_string.replace( |
| '</grit-part>', """</messages> |
| </release> |
| </grit>""") |
| 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 |