summaryrefslogtreecommitdiffstats
path: root/tools/grit
diff options
context:
space:
mode:
authorjoi@chromium.org <joi@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-09-23 12:23:48 +0000
committerjoi@chromium.org <joi@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-09-23 12:23:48 +0000
commite1633ca0d36fdc49bcf547de5d9c2a30919d331f (patch)
tree2f1afa2b6b86a8b111b53a440bdbecbc1faab4ce /tools/grit
parent3adc005112670c2c1c25e5e2525e2451c4ed5075 (diff)
downloadchromium_src-e1633ca0d36fdc49bcf547de5d9c2a30919d331f.zip
chromium_src-e1633ca0d36fdc49bcf547de5d9c2a30919d331f.tar.gz
chromium_src-e1633ca0d36fdc49bcf547de5d9c2a30919d331f.tar.bz2
Removing grit from Chrome repo, and bringing it back in from its
now-separate open source project via DEPS. BUG=97420 TEST=existing Review URL: http://codereview.chromium.org/7994005 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@102483 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'tools/grit')
-rw-r--r--tools/grit/PRESUBMIT.py21
-rw-r--r--tools/grit/README2
-rwxr-xr-xtools/grit/grit.py16
-rw-r--r--tools/grit/grit/__init__.py10
-rw-r--r--tools/grit/grit/clique.py447
-rw-r--r--tools/grit/grit/clique_unittest.py203
-rw-r--r--tools/grit/grit/constants.py22
-rw-r--r--tools/grit/grit/exception.py153
-rw-r--r--tools/grit/grit/extern/FP.py34
-rw-r--r--tools/grit/grit/extern/__init__.py0
-rw-r--r--tools/grit/grit/extern/tclib.py503
-rw-r--r--tools/grit/grit/format/__init__.py10
-rwxr-xr-xtools/grit/grit/format/data_pack.py168
-rw-r--r--tools/grit/grit/format/data_pack_unittest.py34
-rwxr-xr-xtools/grit/grit/format/html_inline.py330
-rw-r--r--tools/grit/grit/format/interface.py32
-rw-r--r--tools/grit/grit/format/js_map_format.py66
-rw-r--r--tools/grit/grit/format/js_map_format_unittest.py98
-rw-r--r--tools/grit/grit/format/policy_templates/PRESUBMIT.py27
-rw-r--r--tools/grit/grit/format/policy_templates/__init__.py9
-rw-r--r--tools/grit/grit/format/policy_templates/policy_template_generator.py152
-rw-r--r--tools/grit/grit/format/policy_templates/policy_template_generator_unittest.py371
-rw-r--r--tools/grit/grit/format/policy_templates/template_formatter.py103
-rw-r--r--tools/grit/grit/format/policy_templates/writer_configuration.py50
-rw-r--r--tools/grit/grit/format/policy_templates/writers/__init__.py9
-rw-r--r--tools/grit/grit/format/policy_templates/writers/adm_writer.py219
-rw-r--r--tools/grit/grit/format/policy_templates/writers/adm_writer_unittest.py525
-rw-r--r--tools/grit/grit/format/policy_templates/writers/adml_writer.py167
-rw-r--r--tools/grit/grit/format/policy_templates/writers/adml_writer_unittest.py336
-rw-r--r--tools/grit/grit/format/policy_templates/writers/admx_writer.py327
-rw-r--r--tools/grit/grit/format/policy_templates/writers/admx_writer_unittest.py343
-rw-r--r--tools/grit/grit/format/policy_templates/writers/doc_writer.py538
-rw-r--r--tools/grit/grit/format/policy_templates/writers/doc_writer_unittest.py475
-rw-r--r--tools/grit/grit/format/policy_templates/writers/json_writer.py72
-rw-r--r--tools/grit/grit/format/policy_templates/writers/json_writer_unittest.py264
-rw-r--r--tools/grit/grit/format/policy_templates/writers/mock_writer.py29
-rw-r--r--tools/grit/grit/format/policy_templates/writers/plist_helper.py14
-rw-r--r--tools/grit/grit/format/policy_templates/writers/plist_strings_writer.py72
-rw-r--r--tools/grit/grit/format/policy_templates/writers/plist_strings_writer_unittest.py284
-rw-r--r--tools/grit/grit/format/policy_templates/writers/plist_writer.py126
-rw-r--r--tools/grit/grit/format/policy_templates/writers/plist_writer_unittest.py369
-rw-r--r--tools/grit/grit/format/policy_templates/writers/reg_writer.py92
-rw-r--r--tools/grit/grit/format/policy_templates/writers/reg_writer_unittest.py278
-rw-r--r--tools/grit/grit/format/policy_templates/writers/template_writer.py249
-rw-r--r--tools/grit/grit/format/policy_templates/writers/template_writer_unittest.py83
-rw-r--r--tools/grit/grit/format/policy_templates/writers/writer_unittest_common.py85
-rw-r--r--tools/grit/grit/format/policy_templates/writers/xml_formatted_writer.py88
-rw-r--r--tools/grit/grit/format/policy_templates/writers/xml_writer_base_unittest.py38
-rw-r--r--tools/grit/grit/format/rc.py445
-rw-r--r--tools/grit/grit/format/rc_header.py180
-rw-r--r--tools/grit/grit/format/rc_header_unittest.py104
-rw-r--r--tools/grit/grit/format/rc_unittest.py302
-rw-r--r--tools/grit/grit/format/repack.py24
-rw-r--r--tools/grit/grit/format/resource_map.py127
-rw-r--r--tools/grit/grit/gather/__init__.py9
-rw-r--r--tools/grit/grit/gather/admin_template.py79
-rw-r--r--tools/grit/grit/gather/admin_template_unittest.py116
-rw-r--r--tools/grit/grit/gather/interface.py108
-rw-r--r--tools/grit/grit/gather/json_loader.py53
-rw-r--r--tools/grit/grit/gather/muppet_strings.py142
-rw-r--r--tools/grit/grit/gather/muppet_strings_unittest.py66
-rw-r--r--tools/grit/grit/gather/policy_json.py258
-rw-r--r--tools/grit/grit/gather/policy_json_unittest.py190
-rw-r--r--tools/grit/grit/gather/rc.py403
-rw-r--r--tools/grit/grit/gather/rc_unittest.py368
-rw-r--r--tools/grit/grit/gather/regexp.py97
-rw-r--r--tools/grit/grit/gather/skeleton_gatherer.py127
-rw-r--r--tools/grit/grit/gather/tr_html.py679
-rw-r--r--tools/grit/grit/gather/tr_html_unittest.py412
-rw-r--r--tools/grit/grit/gather/txt.py52
-rw-r--r--tools/grit/grit/gather/txt_unittest.py34
-rw-r--r--tools/grit/grit/grd_reader.py176
-rw-r--r--tools/grit/grit/grd_reader_unittest.py184
-rw-r--r--tools/grit/grit/grit-todo.xml62
-rw-r--r--tools/grit/grit/grit_runner.py212
-rw-r--r--tools/grit/grit/grit_runner_unittest.py40
-rw-r--r--tools/grit/grit/node/__init__.py9
-rw-r--r--tools/grit/grit/node/base.py549
-rw-r--r--tools/grit/grit/node/base_unittest.py169
-rw-r--r--tools/grit/grit/node/custom/__init__.py9
-rw-r--r--tools/grit/grit/node/custom/filename.py29
-rw-r--r--tools/grit/grit/node/custom/filename_unittest.py34
-rw-r--r--tools/grit/grit/node/empty.py72
-rw-r--r--tools/grit/grit/node/include.py140
-rw-r--r--tools/grit/grit/node/io.py115
-rw-r--r--tools/grit/grit/node/io_unittest.py84
-rw-r--r--tools/grit/grit/node/mapping.py58
-rw-r--r--tools/grit/grit/node/message.py282
-rw-r--r--tools/grit/grit/node/message_unittest.py62
-rw-r--r--tools/grit/grit/node/misc.py403
-rw-r--r--tools/grit/grit/node/misc_unittest.py208
-rw-r--r--tools/grit/grit/node/structure.py263
-rw-r--r--tools/grit/grit/node/structure_unittest.py62
-rw-r--r--tools/grit/grit/node/variant.py42
-rw-r--r--tools/grit/grit/pseudo.py130
-rw-r--r--tools/grit/grit/pseudo_rtl.py102
-rw-r--r--tools/grit/grit/pseudo_unittest.py53
-rw-r--r--tools/grit/grit/shortcuts.py95
-rw-r--r--tools/grit/grit/shortcuts_unittests.py79
-rw-r--r--tools/grit/grit/tclib.py216
-rw-r--r--tools/grit/grit/tclib_unittest.py166
-rw-r--r--tools/grit/grit/test_suite_all.py89
-rw-r--r--tools/grit/grit/testdata/GoogleDesktop.adm945
-rw-r--r--tools/grit/grit/testdata/README.txt87
-rw-r--r--tools/grit/grit/testdata/about.html45
-rw-r--r--tools/grit/grit/testdata/bad_browser.html16
-rw-r--r--tools/grit/grit/testdata/browser.html42
-rw-r--r--tools/grit/grit/testdata/cache_prefix.html24
-rw-r--r--tools/grit/grit/testdata/cache_prefix_file.html25
-rw-r--r--tools/grit/grit/testdata/chat_result.html24
-rw-r--r--tools/grit/grit/testdata/chrome/app/generated_resources.grd199
-rw-r--r--tools/grit/grit/testdata/del_footer.html8
-rw-r--r--tools/grit/grit/testdata/del_header.html60
-rw-r--r--tools/grit/grit/testdata/deleted.html21
-rw-r--r--tools/grit/grit/testdata/details.html10
-rw-r--r--tools/grit/grit/testdata/duplicate-name-input.xml26
-rw-r--r--tools/grit/grit/testdata/email_result.html34
-rw-r--r--tools/grit/grit/testdata/email_thread.html10
-rw-r--r--tools/grit/grit/testdata/error.html8
-rw-r--r--tools/grit/grit/testdata/explicit_web.html11
-rw-r--r--tools/grit/grit/testdata/footer.html14
-rw-r--r--tools/grit/grit/testdata/generated_resources_fr.xtb3090
-rw-r--r--tools/grit/grit/testdata/header.html39
-rw-r--r--tools/grit/grit/testdata/homepage.html37
-rw-r--r--tools/grit/grit/testdata/hover.html177
-rw-r--r--tools/grit/grit/testdata/include_test.html31
-rw-r--r--tools/grit/grit/testdata/included_sample.html1
-rw-r--r--tools/grit/grit/testdata/indexing_speed.html58
-rw-r--r--tools/grit/grit/testdata/install_prefs.html92
-rw-r--r--tools/grit/grit/testdata/install_prefs2.html52
-rw-r--r--tools/grit/grit/testdata/klonk-alternate-skeleton.rcbin1088 -> 0 bytes
-rw-r--r--tools/grit/grit/testdata/klonk.icobin766 -> 0 bytes
-rw-r--r--tools/grit/grit/testdata/klonk.rcbin9428 -> 0 bytes
-rw-r--r--tools/grit/grit/testdata/ko_oem_enable_bug.html1
-rw-r--r--tools/grit/grit/testdata/ko_oem_non_admin_bug.html1
-rw-r--r--tools/grit/grit/testdata/mini.html36
-rw-r--r--tools/grit/grit/testdata/oem_enable.html106
-rw-r--r--tools/grit/grit/testdata/oem_non_admin.html39
-rw-r--r--tools/grit/grit/testdata/onebox.html21
-rw-r--r--tools/grit/grit/testdata/oneclick.html34
-rw-r--r--tools/grit/grit/testdata/password.html37
-rw-r--r--tools/grit/grit/testdata/preferences.html234
-rw-r--r--tools/grit/grit/testdata/privacy.html35
-rw-r--r--tools/grit/grit/testdata/quit_apps.html49
-rw-r--r--tools/grit/grit/testdata/recrawl.html30
-rw-r--r--tools/grit/grit/testdata/resource_ids10
-rw-r--r--tools/grit/grit/testdata/script.html38
-rw-r--r--tools/grit/grit/testdata/searchbox.html22
-rw-r--r--tools/grit/grit/testdata/sidebar_h.html82
-rw-r--r--tools/grit/grit/testdata/sidebar_v.html267
-rw-r--r--tools/grit/grit/testdata/simple-input.xml52
-rw-r--r--tools/grit/grit/testdata/simple.html3
-rw-r--r--tools/grit/grit/testdata/source.rc57
-rw-r--r--tools/grit/grit/testdata/status.html44
-rw-r--r--tools/grit/grit/testdata/time_related.html11
-rw-r--r--tools/grit/grit/testdata/toolbar_about.html138
-rw-r--r--tools/grit/grit/testdata/tools/grit/resource_ids175
-rw-r--r--tools/grit/grit/testdata/transl.rc56
-rw-r--r--tools/grit/grit/testdata/versions.html7
-rw-r--r--tools/grit/grit/tool/__init__.py10
-rw-r--r--tools/grit/grit/tool/build.py300
-rw-r--r--tools/grit/grit/tool/count.py44
-rw-r--r--tools/grit/grit/tool/diff_structures.py114
-rw-r--r--tools/grit/grit/tool/interface.py59
-rw-r--r--tools/grit/grit/tool/menu_from_parts.py84
-rw-r--r--tools/grit/grit/tool/newgrd.py71
-rw-r--r--tools/grit/grit/tool/postprocess_interface.py33
-rw-r--r--tools/grit/grit/tool/postprocess_unittest.py63
-rw-r--r--tools/grit/grit/tool/preprocess_interface.py29
-rw-r--r--tools/grit/grit/tool/preprocess_unittest.py49
-rw-r--r--tools/grit/grit/tool/rc2grd.py403
-rw-r--r--tools/grit/grit/tool/rc2grd_unittest.py138
-rw-r--r--tools/grit/grit/tool/resize.py303
-rw-r--r--tools/grit/grit/tool/test.py24
-rw-r--r--tools/grit/grit/tool/toolbar_postprocess.py126
-rw-r--r--tools/grit/grit/tool/toolbar_preprocess.py62
-rw-r--r--tools/grit/grit/tool/transl2tc.py254
-rw-r--r--tools/grit/grit/tool/transl2tc_unittest.py130
-rw-r--r--tools/grit/grit/tool/unit.py26
-rw-r--r--tools/grit/grit/util.py310
-rw-r--r--tools/grit/grit/util_unittest.py70
-rw-r--r--tools/grit/grit/xtb_reader.py132
-rw-r--r--tools/grit/grit/xtb_reader_unittest.py83
-rwxr-xr-xtools/grit/grit_info.py240
184 files changed, 0 insertions, 26440 deletions
diff --git a/tools/grit/PRESUBMIT.py b/tools/grit/PRESUBMIT.py
deleted file mode 100644
index f1d58aa..0000000
--- a/tools/grit/PRESUBMIT.py
+++ /dev/null
@@ -1,21 +0,0 @@
-# Copyright (c) 2011 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.
-
-"""grit unittests presubmit script.
-
-See http://dev.chromium.org/developers/how-tos/depottools/presubmit-scripts for
-details on the presubmit API built into gcl.
-"""
-
-
-def RunUnittests(input_api, output_api):
- return input_api.canned_checks.RunPythonUnitTests(input_api, output_api,
- ['grit.test_suite_all'])
-
-
-def CheckChangeOnUpload(input_api, output_api):
- return RunUnittests(input_api, output_api)
-
-def CheckChangeOnCommit(input_api, output_api):
- return RunUnittests(input_api, output_api)
diff --git a/tools/grit/README b/tools/grit/README
deleted file mode 100644
index 8fcdafe..0000000
--- a/tools/grit/README
+++ /dev/null
@@ -1,2 +0,0 @@
-GRIT (Google Resource and Internationalization Tool) is a tool for Windows
-projects to manage resources and simplify the localization workflow.
diff --git a/tools/grit/grit.py b/tools/grit/grit.py
deleted file mode 100755
index 772d8c2..0000000
--- a/tools/grit/grit.py
+++ /dev/null
@@ -1,16 +0,0 @@
-#!/usr/bin/python
-# Copyright (c) 2011 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.
-
-'''Bootstrapping for GRIT.
-'''
-
-import sys
-
-import grit.grit_runner
-
-
-if __name__ == '__main__':
- grit.grit_runner.Main(sys.argv[1:])
-
diff --git a/tools/grit/grit/__init__.py b/tools/grit/grit/__init__.py
deleted file mode 100644
index a6fd45c..0000000
--- a/tools/grit/grit/__init__.py
+++ /dev/null
@@ -1,10 +0,0 @@
-#!/usr/bin/python2.4
-# Copyright (c) 2006-2008 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.
-
-'''Package 'grit'
-'''
-
-pass
-
diff --git a/tools/grit/grit/clique.py b/tools/grit/grit/clique.py
deleted file mode 100644
index 6b0fda6..0000000
--- a/tools/grit/grit/clique.py
+++ /dev/null
@@ -1,447 +0,0 @@
-#!/usr/bin/python2.4
-# Copyright (c) 2011 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.
-
-'''Collections of messages and their translations, called cliques. Also
-collections of cliques (uber-cliques).
-'''
-
-import types
-
-from grit import constants
-from grit import exception
-from grit import pseudo
-from grit import pseudo_rtl
-from grit import tclib
-
-
-class UberClique(object):
- '''A factory (NOT a singleton factory) for making cliques. It has several
- methods for working with the cliques created using the factory.
- '''
-
- def __init__(self):
- # A map from message ID to list of cliques whose source messages have
- # that ID. This will contain all cliques created using this factory.
- # Different messages can have the same ID because they have the
- # same translateable portion and placeholder names, but occur in different
- # places in the resource tree.
- self.cliques_ = {}
-
- # A map of clique IDs to list of languages to indicate translations where we
- # fell back to English.
- self.fallback_translations_ = {}
-
- # A map of clique IDs to list of languages to indicate missing translations.
- self.missing_translations_ = {}
-
- def _AddMissingTranslation(self, lang, clique, is_error):
- tl = self.fallback_translations_
- if is_error:
- tl = self.missing_translations_
- id = clique.GetId()
- if id not in tl:
- tl[id] = {}
- if lang not in tl[id]:
- tl[id][lang] = 1
-
- def HasMissingTranslations(self):
- return len(self.missing_translations_) > 0
-
- def MissingTranslationsReport(self):
- '''Returns a string suitable for printing to report missing
- and fallback translations to the user.
- '''
- def ReportTranslation(clique, langs):
- text = clique.GetMessage().GetPresentableContent()
- extract = text[0:40]
- ellipsis = ''
- if len(text) > 40:
- ellipsis = '...'
- langs_extract = langs[0:6]
- describe_langs = ','.join(langs_extract)
- if len(langs) > 6:
- describe_langs += " and %d more" % (len(langs) - 6)
- return " %s \"%s%s\" %s" % (clique.GetId(), extract, ellipsis,
- describe_langs)
- lines = []
- if len(self.fallback_translations_):
- lines.append(
- "WARNING: Fell back to English for the following translations:")
- for (id, langs) in self.fallback_translations_.items():
- lines.append(ReportTranslation(self.cliques_[id][0], langs.keys()))
- if len(self.missing_translations_):
- lines.append("ERROR: The following translations are MISSING:")
- for (id, langs) in self.missing_translations_.items():
- lines.append(ReportTranslation(self.cliques_[id][0], langs.keys()))
- return '\n'.join(lines)
-
- def MakeClique(self, message, translateable=True):
- '''Create a new clique initialized with a message.
-
- Args:
- message: tclib.Message()
- translateable: True | False
- '''
- clique = MessageClique(self, message, translateable)
-
- # Enable others to find this clique by its message ID
- if message.GetId() in self.cliques_:
- presentable_text = clique.GetMessage().GetPresentableContent()
- for c in self.cliques_[message.GetId()]:
- assert c.GetMessage().GetPresentableContent() == presentable_text
- self.cliques_[message.GetId()].append(clique)
- else:
- self.cliques_[message.GetId()] = [clique]
-
- return clique
-
- def FindCliqueAndAddTranslation(self, translation, language):
- '''Adds the specified translation to the clique with the source message
- it is a translation of.
-
- Args:
- translation: tclib.Translation()
- language: 'en' | 'fr' ...
-
- Return:
- True if the source message was found, otherwise false.
- '''
- if translation.GetId() in self.cliques_:
- for clique in self.cliques_[translation.GetId()]:
- clique.AddTranslation(translation, language)
- return True
- else:
- return False
-
- def BestClique(self, id):
- '''Returns the "best" clique from a list of cliques. All the cliques
- must have the same ID. The "best" clique is chosen in the following
- order of preference:
- - The first clique that has a non-ID-based description
- - If no such clique found, one of the cliques with an ID-based description
- - Otherwise an arbitrary clique
- '''
- clique_list = self.cliques_[id]
- clique_to_ret = None
- for clique in clique_list:
- if not clique_to_ret:
- clique_to_ret = clique
-
- description = clique.GetMessage().GetDescription()
- if description and len(description) > 0:
- clique_to_ret = clique
- if not description.startswith('ID:'):
- break # this is the preferred case so we exit right away
- return clique_to_ret
-
- def BestCliquePerId(self):
- '''Iterates over the list of all cliques and returns the best clique for
- each ID. This will be the first clique with a source message that has a
- non-empty description, or an arbitrary clique if none of them has a
- description.
- '''
- for id in self.cliques_:
- yield self.BestClique(id)
-
- def BestCliqueByOriginalText(self, text, meaning):
- '''Finds the "best" (as in BestClique()) clique that has original text
- 'text' and meaning 'meaning'. Returns None if there is no such clique.
- '''
- # If needed, this can be optimized by maintaining a map of
- # fingerprints of original text+meaning to cliques.
- for c in self.BestCliquePerId():
- msg = c.GetMessage()
- if msg.GetRealContent() == text and msg.GetMeaning() == meaning:
- return msg
- return None
-
- def AllMessageIds(self):
- '''Returns a list of all defined message IDs.
- '''
- return self.cliques_.keys()
-
- def AllCliques(self):
- '''Iterates over all cliques. Note that this can return multiple cliques
- with the same ID.
- '''
- for cliques in self.cliques_.values():
- for c in cliques:
- yield c
-
- def GenerateXtbParserCallback(self, lang, debug=False):
- '''Creates a callback function as required by grit.xtb_reader.Parse().
- This callback will create Translation objects for each message from
- the XTB that exists in this uberclique, and add them as translations for
- the relevant cliques. The callback will add translations to the language
- specified by 'lang'
-
- Args:
- lang: 'fr'
- debug: True | False
- '''
- def Callback(id, structure):
- if id not in self.cliques_:
- if debug: print "Ignoring translation #%s" % id
- return
-
- if debug: print "Adding translation #%s" % id
-
- # We fetch placeholder information from the original message (the XTB file
- # only contains placeholder names).
- original_msg = self.BestClique(id).GetMessage()
-
- translation = tclib.Translation(id=id)
- for is_ph,text in structure:
- if not is_ph:
- translation.AppendText(text)
- else:
- found_placeholder = False
- for ph in original_msg.GetPlaceholders():
- if ph.GetPresentation() == text:
- translation.AppendPlaceholder(tclib.Placeholder(
- ph.GetPresentation(), ph.GetOriginal(), ph.GetExample()))
- found_placeholder = True
- break
- if not found_placeholder:
- raise exception.MismatchingPlaceholders(
- 'Translation for message ID %s had <ph name="%s%/>, no match\n'
- 'in original message' % (id, text))
- self.FindCliqueAndAddTranslation(translation, lang)
- return Callback
-
-
-class CustomType(object):
- '''A base class you should implement if you wish to specify a custom type
- for a message clique (i.e. custom validation and optional modification of
- translations).'''
-
- def Validate(self, message):
- '''Returns true if the message (a tclib.Message object) is valid,
- otherwise false.
- '''
- raise NotImplementedError()
-
- def ValidateAndModify(self, lang, translation):
- '''Returns true if the translation (a tclib.Translation object) is valid,
- otherwise false. The language is also passed in. This method may modify
- the translation that is passed in, if it so wishes.
- '''
- raise NotImplementedError()
-
- def ModifyTextPart(self, lang, text):
- '''If you call ModifyEachTextPart, it will turn around and call this method
- for each text part of the translation. You should return the modified
- version of the text, or just the original text to not change anything.
- '''
- raise NotImplementedError()
-
- def ModifyEachTextPart(self, lang, translation):
- '''Call this to easily modify one or more of the textual parts of a
- translation. It will call ModifyTextPart for each part of the
- translation.
- '''
- contents = translation.GetContent()
- for ix in range(len(contents)):
- if (isinstance(contents[ix], types.StringTypes)):
- contents[ix] = self.ModifyTextPart(lang, contents[ix])
-
-
-class OneOffCustomType(CustomType):
- '''A very simple custom type that performs the validation expressed by
- the input expression on all languages including the source language.
- The expression can access the variables 'lang', 'msg' and 'text()' where 'lang'
- is the language of 'msg', 'msg' is the message or translation being
- validated and 'text()' returns the real contents of 'msg' (for shorthand).
- '''
- def __init__(self, expression):
- self.expr = expression
- def Validate(self, message):
- return self.ValidateAndModify(MessageClique.source_language, message)
- def ValidateAndModify(self, lang, msg):
- def text():
- return msg.GetRealContent()
- return eval(self.expr, {},
- {'lang' : lang,
- 'text' : text,
- 'msg' : msg,
- })
-
-
-class MessageClique(object):
- '''A message along with all of its translations. Also code to bring
- translations together with their original message.'''
-
- # change this to the language code of Messages you add to cliques_.
- # TODO(joi) Actually change this based on the <grit> node's source language
- source_language = 'en'
-
- # A constant translation we use when asked for a translation into the
- # special language constants.CONSTANT_LANGUAGE.
- CONSTANT_TRANSLATION = tclib.Translation(text='TTTTTT')
-
- def __init__(self, uber_clique, message, translateable=True, custom_type=None):
- '''Create a new clique initialized with just a message.
-
- Args:
- uber_clique: Our uber-clique (collection of cliques)
- message: tclib.Message()
- translateable: True | False
- custom_type: instance of clique.CustomType interface
- '''
- # Our parent
- self.uber_clique = uber_clique
- # If not translateable, we only store the original message.
- self.translateable = translateable
- # A mapping of language identifiers to tclib.BaseMessage and its
- # subclasses (i.e. tclib.Message and tclib.Translation).
- self.clique = { MessageClique.source_language : message }
- # A list of the "shortcut groups" this clique is
- # part of. Within any given shortcut group, no shortcut key (e.g. &J)
- # must appear more than once in each language for all cliques that
- # belong to the group.
- self.shortcut_groups = []
- # An instance of the CustomType interface, or None. If this is set, it will
- # be used to validate the original message and translations thereof, and
- # will also get a chance to modify translations of the message.
- self.SetCustomType(custom_type)
-
- def GetMessage(self):
- '''Retrieves the tclib.Message that is the source for this clique.'''
- return self.clique[MessageClique.source_language]
-
- def GetId(self):
- '''Retrieves the message ID of the messages in this clique.'''
- return self.GetMessage().GetId()
-
- def IsTranslateable(self):
- return self.translateable
-
- def AddToShortcutGroup(self, group):
- self.shortcut_groups.append(group)
-
- def SetCustomType(self, custom_type):
- '''Makes this clique use custom_type for validating messages and
- translations, and optionally modifying translations.
- '''
- self.custom_type = custom_type
- if custom_type and not custom_type.Validate(self.GetMessage()):
- raise exception.InvalidMessage(self.GetMessage().GetRealContent())
-
- def MessageForLanguage(self, lang, pseudo_if_no_match=True, fallback_to_english=False):
- '''Returns the message/translation for the specified language, providing
- a pseudotranslation if there is no available translation and a pseudo-
- translation is requested.
-
- The translation of any message whatsoever in the special language
- 'x_constant' is the message "TTTTTT".
-
- Args:
- lang: 'en'
- pseudo_if_no_match: True
- fallback_to_english: False
-
- Return:
- tclib.BaseMessage
- '''
- if not self.translateable:
- return self.GetMessage()
-
- if lang == constants.CONSTANT_LANGUAGE:
- return self.CONSTANT_TRANSLATION
-
- for msglang in self.clique.keys():
- if lang == msglang:
- return self.clique[msglang]
-
- if lang == constants.FAKE_BIDI:
- return pseudo_rtl.PseudoRTLMessage(self.GetMessage())
-
- if fallback_to_english:
- self.uber_clique._AddMissingTranslation(lang, self, is_error=False)
- return self.GetMessage()
-
- # If we're not supposed to generate pseudotranslations, we add an error
- # report to a list of errors, then fail at a higher level, so that we
- # get a list of all messages that are missing translations.
- if not pseudo_if_no_match:
- self.uber_clique._AddMissingTranslation(lang, self, is_error=True)
-
- return pseudo.PseudoMessage(self.GetMessage())
-
- def AllMessagesThatMatch(self, lang_re, include_pseudo = True):
- '''Returns a map of all messages that match 'lang', including the pseudo
- translation if requested.
-
- Args:
- lang_re: re.compile('fr|en')
- include_pseudo: True
-
- Return:
- { 'en' : tclib.Message,
- 'fr' : tclib.Translation,
- pseudo.PSEUDO_LANG : tclib.Translation }
- '''
- if not self.translateable:
- return [self.GetMessage()]
-
- matches = {}
- for msglang in self.clique:
- if lang_re.match(msglang):
- matches[msglang] = self.clique[msglang]
-
- if include_pseudo:
- matches[pseudo.PSEUDO_LANG] = pseudo.PseudoMessage(self.GetMessage())
-
- return matches
-
- def AddTranslation(self, translation, language):
- '''Add a translation to this clique. The translation must have the same
- ID as the message that is the source for this clique.
-
- If this clique is not translateable, the function just returns.
-
- Args:
- translation: tclib.Translation()
- language: 'en'
-
- Throws:
- grit.exception.InvalidTranslation if the translation you're trying to add
- doesn't have the same message ID as the source message of this clique.
- '''
- if not self.translateable:
- return
- if translation.GetId() != self.GetId():
- raise exception.InvalidTranslation(
- 'Msg ID %s, transl ID %s' % (self.GetId(), translation.GetId()))
-
- assert not language in self.clique
-
- # Because two messages can differ in the original content of their
- # placeholders yet share the same ID (because they are otherwise the
- # same), the translation we are getting may have different original
- # content for placeholders than our message, yet it is still the right
- # translation for our message (because it is for the same ID). We must
- # therefore fetch the original content of placeholders from our original
- # English message.
- #
- # See grit.clique_unittest.MessageCliqueUnittest.testSemiIdenticalCliques
- # for a concrete explanation of why this is necessary.
-
- original = self.MessageForLanguage(self.source_language, False)
- if len(original.GetPlaceholders()) != len(translation.GetPlaceholders()):
- print ("ERROR: '%s' translation of message id %s does not match" %
- (language, translation.GetId()))
- assert False
-
- transl_msg = tclib.Translation(id=self.GetId(),
- text=translation.GetPresentableContent(),
- placeholders=original.GetPlaceholders())
-
- if self.custom_type and not self.custom_type.ValidateAndModify(language, transl_msg):
- print "WARNING: %s translation failed validation: %s" % (
- language, transl_msg.GetId())
-
- self.clique[language] = transl_msg
-
diff --git a/tools/grit/grit/clique_unittest.py b/tools/grit/grit/clique_unittest.py
deleted file mode 100644
index 99b3c99..0000000
--- a/tools/grit/grit/clique_unittest.py
+++ /dev/null
@@ -1,203 +0,0 @@
-#!/usr/bin/python2.4
-# Copyright (c) 2011 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.
-
-'''Unit tests for grit.clique'''
-
-import os
-import sys
-if __name__ == '__main__':
- sys.path.append(os.path.join(os.path.dirname(sys.argv[0]), '..'))
-
-import re
-import StringIO
-import unittest
-
-from grit import clique
-from grit import exception
-from grit import pseudo
-from grit import tclib
-from grit import grd_reader
-from grit import util
-
-class MessageCliqueUnittest(unittest.TestCase):
- def testClique(self):
- factory = clique.UberClique()
- msg = tclib.Message(text='Hello USERNAME, how are you?',
- placeholders=[
- tclib.Placeholder('USERNAME', '%s', 'Joi')])
- c = factory.MakeClique(msg)
-
- self.failUnless(c.GetMessage() == msg)
- self.failUnless(c.GetId() == msg.GetId())
-
- msg_fr = tclib.Translation(text='Bonjour USERNAME, comment ca va?',
- id=msg.GetId(), placeholders=[
- tclib.Placeholder('USERNAME', '%s', 'Joi')])
- msg_de = tclib.Translation(text='Guten tag USERNAME, wie geht es dir?',
- id=msg.GetId(), placeholders=[
- tclib.Placeholder('USERNAME', '%s', 'Joi')])
-
- c.AddTranslation(msg_fr, 'fr')
- factory.FindCliqueAndAddTranslation(msg_de, 'de')
-
- # sort() sorts lists in-place and does not return them
- for lang in ('en', 'fr', 'de'):
- self.failUnless(lang in c.clique)
-
- self.failUnless(c.MessageForLanguage('fr').GetRealContent() ==
- msg_fr.GetRealContent())
-
- try:
- c.MessageForLanguage('zh-CN', False)
- self.fail('Should have gotten exception')
- except:
- pass
-
- self.failUnless(c.MessageForLanguage('zh-CN', True) != None)
-
- rex = re.compile('fr|de|bingo')
- self.failUnless(len(c.AllMessagesThatMatch(rex, False)) == 2)
- self.failUnless(c.AllMessagesThatMatch(rex, True)[pseudo.PSEUDO_LANG] != None)
-
- def testBestClique(self):
- factory = clique.UberClique()
- factory.MakeClique(tclib.Message(text='Alfur', description='alfaholl'))
- factory.MakeClique(tclib.Message(text='Alfur', description=''))
- factory.MakeClique(tclib.Message(text='Vaettur', description=''))
- factory.MakeClique(tclib.Message(text='Vaettur', description=''))
- factory.MakeClique(tclib.Message(text='Troll', description=''))
- factory.MakeClique(tclib.Message(text='Gryla', description='ID: IDS_GRYLA'))
- factory.MakeClique(tclib.Message(text='Gryla', description='vondakerling'))
- factory.MakeClique(tclib.Message(text='Leppaludi', description='ID: IDS_LL'))
- factory.MakeClique(tclib.Message(text='Leppaludi', description=''))
-
- count_best_cliques = 0
- for c in factory.BestCliquePerId():
- count_best_cliques += 1
- msg = c.GetMessage()
- text = msg.GetRealContent()
- description = msg.GetDescription()
- if text == 'Alfur':
- self.failUnless(description == 'alfaholl')
- elif text == 'Gryla':
- self.failUnless(description == 'vondakerling')
- elif text == 'Leppaludi':
- self.failUnless(description == 'ID: IDS_LL')
- self.failUnless(count_best_cliques == 5)
-
- def testAllInUberClique(self):
- resources = grd_reader.Parse(util.WrapInputStream(
- StringIO.StringIO('''<?xml version="1.0" encoding="UTF-8"?>
-<grit latest_public_release="2" source_lang_id="en-US" current_release="3" base_dir=".">
- <release seq="3">
- <messages>
- <message name="IDS_GREETING" desc="Printed to greet the currently logged in user">
- Hello <ph name="USERNAME">%s<ex>Joi</ex></ph>, how are you doing today?
- </message>
- </messages>
- <structures>
- <structure type="dialog" name="IDD_ABOUTBOX" encoding="utf-16" file="grit/testdata/klonk.rc" />
- <structure type="tr_html" name="ID_HTML" file="grit/testdata/simple.html" />
- </structures>
- </release>
-</grit>''')), util.PathFromRoot('.'))
- resources.RunGatherers(True)
- content_list = []
- for clique_list in resources.UberClique().cliques_.values():
- for clique in clique_list:
- content_list.append(clique.GetMessage().GetRealContent())
- self.failUnless('Hello %s, how are you doing today?' in content_list)
- self.failUnless('Jack "Black" Daniels' in content_list)
- self.failUnless('Hello!' in content_list)
-
- def testCorrectExceptionIfWrongEncodingOnResourceFile(self):
- '''This doesn't really belong in this unittest file, but what the heck.'''
- resources = grd_reader.Parse(util.WrapInputStream(
- StringIO.StringIO('''<?xml version="1.0" encoding="UTF-8"?>
-<grit latest_public_release="2" source_lang_id="en-US" current_release="3" base_dir=".">
- <release seq="3">
- <structures>
- <structure type="dialog" name="IDD_ABOUTBOX" file="grit/testdata/klonk.rc" />
- </structures>
- </release>
-</grit>''')), util.PathFromRoot('.'))
- self.assertRaises(exception.SectionNotFound, resources.RunGatherers, True)
-
- def testSemiIdenticalCliques(self):
- messages = [
- tclib.Message(text='Hello USERNAME',
- placeholders=[tclib.Placeholder('USERNAME', '$1', 'Joi')]),
- tclib.Message(text='Hello USERNAME',
- placeholders=[tclib.Placeholder('USERNAME', '%s', 'Joi')]),
- ]
- self.failUnless(messages[0].GetId() == messages[1].GetId())
-
- # Both of the above would share a translation.
- translation = tclib.Translation(id=messages[0].GetId(),
- text='Bonjour USERNAME',
- placeholders=[tclib.Placeholder(
- 'USERNAME', '$1', 'Joi')])
-
- factory = clique.UberClique()
- cliques = [factory.MakeClique(msg) for msg in messages]
-
- for clq in cliques:
- clq.AddTranslation(translation, 'fr')
-
- self.failUnless(cliques[0].MessageForLanguage('fr').GetRealContent() ==
- 'Bonjour $1')
- self.failUnless(cliques[1].MessageForLanguage('fr').GetRealContent() ==
- 'Bonjour %s')
-
- def testMissingTranslations(self):
- messages = [ tclib.Message(text='Hello'), tclib.Message(text='Goodbye') ]
- factory = clique.UberClique()
- cliques = [factory.MakeClique(msg) for msg in messages]
-
- cliques[1].MessageForLanguage('fr', False, True)
-
- self.failUnless(not factory.HasMissingTranslations())
-
- cliques[0].MessageForLanguage('de', False, False)
-
- self.failUnless(factory.HasMissingTranslations())
-
- report = factory.MissingTranslationsReport()
- self.failUnless(report.count('WARNING') == 1)
- self.failUnless(report.count('8053599568341804890 "Goodbye" fr') == 1)
- self.failUnless(report.count('ERROR') == 1)
- self.failUnless(report.count('800120468867715734 "Hello" de') == 1)
-
- def testCustomTypes(self):
- factory = clique.UberClique()
- message = tclib.Message(text='Bingo bongo')
- c = factory.MakeClique(message)
- try:
- c.SetCustomType(DummyCustomType())
- self.fail()
- except:
- pass # expected case - 'Bingo bongo' does not start with 'jjj'
-
- message = tclib.Message(text='jjjBingo bongo')
- c = factory.MakeClique(message)
- c.SetCustomType(util.NewClassInstance(
- 'grit.clique_unittest.DummyCustomType', clique.CustomType))
- translation = tclib.Translation(id=message.GetId(), text='Bilingo bolongo')
- c.AddTranslation(translation, 'fr')
- self.failUnless(c.MessageForLanguage('fr').GetRealContent().startswith('jjj'))
-
-
-class DummyCustomType(clique.CustomType):
- def Validate(self, message):
- return message.GetRealContent().startswith('jjj')
- def ValidateAndModify(self, lang, translation):
- is_ok = self.Validate(translation)
- self.ModifyEachTextPart(lang, translation)
- def ModifyTextPart(self, lang, text):
- return 'jjj%s' % text
-
-
-if __name__ == '__main__':
- unittest.main()
diff --git a/tools/grit/grit/constants.py b/tools/grit/grit/constants.py
deleted file mode 100644
index e0de4d2..0000000
--- a/tools/grit/grit/constants.py
+++ /dev/null
@@ -1,22 +0,0 @@
-#!/usr/bin/python2.4
-# Copyright (c) 2011 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.
-
-'''Constant definitions for GRIT.
-'''
-
-
-# This is the Icelandic noun meaning "grit" and is used to check that our
-# input files are in the correct encoding. The middle character gets encoded
-# as two bytes in UTF-8, so this is sufficient to detect incorrect encoding.
-ENCODING_CHECK = u'm\u00f6l'
-
-# A special language, translations into which are always "TTTTTT".
-CONSTANT_LANGUAGE = 'x_constant'
-
-# The Unicode byte-order-marker character (this is the Unicode code point,
-# not the encoding of that character into any particular Unicode encoding).
-BOM = u"\ufeff"
-
-FAKE_BIDI = 'fake-bidi' \ No newline at end of file
diff --git a/tools/grit/grit/exception.py b/tools/grit/grit/exception.py
deleted file mode 100644
index fee77f7..0000000
--- a/tools/grit/grit/exception.py
+++ /dev/null
@@ -1,153 +0,0 @@
-#!/usr/bin/python2.4
-# Copyright (c) 2006-2008 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.
-
-'''Exception types for GRIT.
-'''
-
-class Base(Exception):
- '''A base exception that uses the class's docstring in addition to any
- user-provided message as the body of the Base.
- '''
- def __init__(self, msg=''):
- if len(msg):
- if self.__doc__:
- msg = self.__doc__ + ': ' + msg
- else:
- msg = self.__doc__
- Exception.__init__(self, msg)
-
-
-class Parsing(Base):
- '''An error occurred parsing a GRD or XTB file.'''
- def __init__(self, msg=''):
- Base.__init__(self, msg)
-
-
-class UnknownElement(Parsing):
- '''An unknown node type was encountered.'''
- def __init__(self, msg=''):
- Parsing.__init__(self, msg)
-
-
-class MissingElement(Parsing):
- '''An expected element was missing.'''
- def __init__(self, msg=''):
- Parsing.__init__(self, msg)
-
-
-class UnexpectedChild(Parsing):
- '''An unexpected child element was encountered (on a leaf node).'''
- def __init__(self, msg=''):
- Parsing.__init__(self, msg)
-
-
-class UnexpectedAttribute(Parsing):
- '''The attribute was not expected'''
- def __init__(self, msg=''):
- Parsing.__init__(self, msg)
-
-
-class UnexpectedContent(Parsing):
- '''This element should not have content'''
- def __init__(self, msg=''):
- Parsing.__init__(self, msg)
-
-
-class MissingMandatoryAttribute(Parsing):
- '''This element is missing a mandatory attribute'''
- def __init__(self, msg=''):
- Parsing.__init__(self, msg)
-
-
-class MutuallyExclusiveMandatoryAttribute(Parsing):
- '''This element has 2 mutually exclusive mandatory attributes'''
- def __init__(self, msg=''):
- Parsing.__init__(self, msg)
-
-
-class DuplicateKey(Parsing):
- '''A duplicate key attribute was found.'''
- def __init__(self, msg=''):
- Parsing.__init__(self, msg)
-
-
-class TooManyExamples(Parsing):
- '''Only one <ex> element is allowed for each <ph> element.'''
- def __init__(self, msg=''):
- Parsing.__init__(self, msg)
-
-
-class GotPathExpectedFilenameOnly(Parsing):
- '''The 'filename' attribute of an <output> node must not be a path, only
- a filename.
- '''
- def __init__(self, msg=''):
- Parsing.__init__(self, msg)
-
-
-class InvalidMessage(Base):
- '''The specified message failed validation.'''
- def __init__(self, msg=''):
- Base.__init__(self, msg)
-
-
-class InvalidTranslation(Base):
- '''Attempt to add an invalid translation to a clique.'''
- def __init__(self, msg=''):
- Base.__init__(self, msg)
-
-
-class NoSuchTranslation(Base):
- '''Requested translation not available'''
- def __init__(self, msg=''):
- Base.__init__(self, msg)
-
-
-class NotReady(Base):
- '''Attempt to use an object before it is ready, or attempt to translate
- an empty document.'''
- def __init__(self, msg=''):
- Base.__init__(self, msg)
-
-
-class TooManyPlaceholders(Base):
- '''Too many placeholders for elements of the same type.'''
- def __init__(self, msg=''):
- Base.__init__(self, msg)
-
-
-class MismatchingPlaceholders(Base):
- '''Placeholders do not match.'''
- def __init__(self, msg=''):
- Base.__init__(self, msg)
-
-
-class InvalidPlaceholderName(Base):
- '''Placeholder name can only contain A-Z, a-z, 0-9 and underscore.'''
- def __init__(self, msg=''):
- Base.__init__(self, msg)
-
-
-class BlockTagInTranslateableChunk(Base):
- '''A block tag was encountered where it wasn't expected.'''
- def __init__(self, msg=''):
- Base.__init__(self, msg)
-
-
-class SectionNotFound(Base):
- '''The section you requested was not found in the RC file. Make
-sure the section ID is correct (matches the section's ID in the RC file).
-Also note that you may need to specify the RC file's encoding (using the
-encoding="" attribute) if it is not in the default Windows-1252 encoding.
- '''
- def __init__(self, msg=''):
- Base.__init__(self, msg)
-
-
-class IdRangeOverlap(Base):
- '''ID range overlap.'''
- def __init__(self, msg=''):
- Base.__init__(self, msg)
-
diff --git a/tools/grit/grit/extern/FP.py b/tools/grit/grit/extern/FP.py
deleted file mode 100644
index 77b1adc..0000000
--- a/tools/grit/grit/extern/FP.py
+++ /dev/null
@@ -1,34 +0,0 @@
-#!/usr/bin/python
-# Copyright (c) 2006-2008 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.
-
-try:
- import hashlib
- _new_md5 = hashlib.md5
-except ImportError:
- import md5
- _new_md5 = md5.new
-
-"""64-bit fingerprint support for strings.
-
-Usage:
- from extern import FP
- print 'Fingerprint is %ld' % FP.FingerPrint('Hello world!')
-"""
-
-
-def UnsignedFingerPrint(str, encoding='utf-8'):
- """Generate a 64-bit fingerprint by taking the first half of the md5
- of the string."""
- hex128 = _new_md5(str).hexdigest()
- int64 = long(hex128[:16], 16)
- return int64
-
-def FingerPrint(str, encoding='utf-8'):
- fp = UnsignedFingerPrint(str, encoding=encoding)
- # interpret fingerprint as signed longs
- if fp & 0x8000000000000000L:
- fp = - ((~fp & 0xFFFFFFFFFFFFFFFFL) + 1)
- return fp
-
diff --git a/tools/grit/grit/extern/__init__.py b/tools/grit/grit/extern/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/tools/grit/grit/extern/__init__.py
+++ /dev/null
diff --git a/tools/grit/grit/extern/tclib.py b/tools/grit/grit/extern/tclib.py
deleted file mode 100644
index c9dba2b..0000000
--- a/tools/grit/grit/extern/tclib.py
+++ /dev/null
@@ -1,503 +0,0 @@
-#!/usr/bin/python2.4
-# Copyright (c) 2006-2008 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.
-
-# The tclib module contains tools for aggregating, verifying, and storing
-# messages destined for the Translation Console, as well as for reading
-# translations back and outputting them in some desired format.
-#
-# This has been stripped down to include only the functionality needed by grit
-# for creating Windows .rc and .h files. These are the only parts needed by
-# the Chrome build process.
-
-import exceptions
-
-from grit.extern import FP
-
-# This module assumes that within a bundle no two messages can have the
-# same id unless they're identical.
-
-# The basic classes defined here for external use are Message and Translation,
-# where the former is used for English messages and the latter for
-# translations. These classes have a lot of common functionality, as expressed
-# by the common parent class BaseMessage. Perhaps the most important
-# distinction is that translated text is stored in UTF-8, whereas original text
-# is stored in whatever encoding the client uses (presumably Latin-1).
-
-# --------------------
-# The public interface
-# --------------------
-
-# Generate message id from message text and meaning string (optional),
-# both in utf-8 encoding
-#
-def GenerateMessageId(message, meaning=''):
- fp = FP.FingerPrint(message)
- if meaning:
- # combine the fingerprints of message and meaning
- fp2 = FP.FingerPrint(meaning)
- if fp < 0:
- fp = fp2 + (fp << 1) + 1
- else:
- fp = fp2 + (fp << 1)
- # To avoid negative ids we strip the high-order bit
- return str(fp & 0x7fffffffffffffffL)
-
-# -------------------------------------------------------------------------
-# The MessageTranslationError class is used to signal tclib-specific errors.
-
-class MessageTranslationError(exceptions.Exception):
- def __init__(self, args = ''):
- self.args = args
-
-
-# -----------------------------------------------------------
-# The Placeholder class represents a placeholder in a message.
-
-class Placeholder(object):
- # String representation
- def __str__(self):
- return '%s, "%s", "%s"' % \
- (self.__presentation, self.__original, self.__example)
-
- # Getters
- def GetOriginal(self):
- return self.__original
-
- def GetPresentation(self):
- return self.__presentation
-
- def GetExample(self):
- return self.__example
-
- def __eq__(self, other):
- return self.EqualTo(other, strict=1, ignore_trailing_spaces=0)
-
- # Equality test
- #
- # ignore_trailing_spaces: TC is using varchar to store the
- # phrwr fields, as a result of that, the trailing spaces
- # are removed by MySQL when the strings are stored into TC:-(
- # ignore_trailing_spaces parameter is used to ignore
- # trailing spaces during equivalence comparison.
- #
- def EqualTo(self, other, strict = 1, ignore_trailing_spaces = 1):
- if type(other) is not Placeholder:
- return 0
- if StringEquals(self.__presentation, other.__presentation,
- ignore_trailing_spaces):
- if not strict or (StringEquals(self.__original, other.__original,
- ignore_trailing_spaces) and
- StringEquals(self.__example, other.__example,
- ignore_trailing_spaces)):
- return 1
- return 0
-
-
-# -----------------------------------------------------------------
-# BaseMessage is the common parent class of Message and Translation.
-# It is not meant for direct use.
-
-class BaseMessage(object):
- # Three types of message construction is supported. If the message text is a
- # simple string with no dynamic content, you can pass it to the constructor
- # as the "text" parameter. Otherwise, you can omit "text" and assemble the
- # message step by step using AppendText() and AppendPlaceholder(). Or, as an
- # alternative, you can give the constructor the "presentable" version of the
- # message and a list of placeholders; it will then parse the presentation and
- # build the message accordingly. For example:
- # Message(text = "There are NUM_BUGS bugs in your code",
- # placeholders = [Placeholder("NUM_BUGS", "%d", "33")],
- # description = "Bla bla bla")
- def __eq__(self, other):
- # "source encoding" is nonsense, so ignore it
- return _ObjectEquals(self, other, ['_BaseMessage__source_encoding'])
-
- def GetName(self):
- return self.__name
-
- def GetSourceEncoding(self):
- return self.__source_encoding
-
- # Append a placeholder to the message
- def AppendPlaceholder(self, placeholder):
- if not isinstance(placeholder, Placeholder):
- raise MessageTranslationError, ("Invalid message placeholder %s in "
- "message %s" % (placeholder, self.GetId()))
- # Are there other placeholders with the same presentation?
- # If so, they need to be the same.
- for other in self.GetPlaceholders():
- if placeholder.GetPresentation() == other.GetPresentation():
- if not placeholder.EqualTo(other):
- raise MessageTranslationError, \
- "Conflicting declarations of %s within message" % \
- placeholder.GetPresentation()
- # update placeholder list
- dup = 0
- for item in self.__content:
- if isinstance(item, Placeholder) and placeholder.EqualTo(item):
- dup = 1
- break
- if not dup:
- self.__placeholders.append(placeholder)
-
- # update content
- self.__content.append(placeholder)
-
- # Strips leading and trailing whitespace, and returns a tuple
- # containing the leading and trailing space that was removed.
- def Strip(self):
- leading = trailing = ''
- if len(self.__content) > 0:
- s0 = self.__content[0]
- if not isinstance(s0, Placeholder):
- s = s0.lstrip()
- leading = s0[:-len(s)]
- self.__content[0] = s
-
- s0 = self.__content[-1]
- if not isinstance(s0, Placeholder):
- s = s0.rstrip()
- trailing = s0[len(s):]
- self.__content[-1] = s
- return leading, trailing
-
- # Return the id of this message
- def GetId(self):
- if self.__id is None:
- return self.GenerateId()
- return self.__id
-
- # Set the id of this message
- def SetId(self, id):
- if id is None:
- self.__id = None
- else:
- self.__id = str(id) # Treat numerical ids as strings
-
- # Return content of this message as a list (internal use only)
- def GetContent(self):
- return self.__content
-
- # Return a human-readable version of this message
- def GetPresentableContent(self):
- presentable_content = ""
- for item in self.__content:
- if isinstance(item, Placeholder):
- presentable_content += item.GetPresentation()
- else:
- presentable_content += item
-
- return presentable_content
-
- # Return a fragment of a message in escaped format
- def EscapeFragment(self, fragment):
- return fragment.replace('%', '%%')
-
- # Return the "original" version of this message, doing %-escaping
- # properly. If source_msg is specified, the placeholder original
- # information inside source_msg will be used instead.
- def GetOriginalContent(self, source_msg = None):
- original_content = ""
- for item in self.__content:
- if isinstance(item, Placeholder):
- if source_msg:
- ph = source_msg.GetPlaceholder(item.GetPresentation())
- if not ph:
- raise MessageTranslationError, \
- "Placeholder %s doesn't exist in message: %s" % \
- (item.GetPresentation(), source_msg);
- original_content += ph.GetOriginal()
- else:
- original_content += item.GetOriginal()
- else:
- original_content += self.EscapeFragment(item)
- return original_content
-
- # Return the example of this message
- def GetExampleContent(self):
- example_content = ""
- for item in self.__content:
- if isinstance(item, Placeholder):
- example_content += item.GetExample()
- else:
- example_content += item
- return example_content
-
- # Return a list of all unique placeholders in this message
- def GetPlaceholders(self):
- return self.__placeholders
-
- # Return a placeholder in this message
- def GetPlaceholder(self, presentation):
- for item in self.__content:
- if (isinstance(item, Placeholder) and
- item.GetPresentation() == presentation):
- return item
- return None
-
- # Return this message's description
- def GetDescription(self):
- return self.__description
-
- # Add a message source
- def AddSource(self, source):
- self.__sources.append(source)
-
- # Return this message's sources as a list
- def GetSources(self):
- return self.__sources
-
- # Return this message's sources as a string
- def GetSourcesAsText(self, delimiter = "; "):
- return delimiter.join(self.__sources)
-
- # Set the obsolete flag for a message (internal use only)
- def SetObsolete(self):
- self.__obsolete = 1
-
- # Get the obsolete flag for a message (internal use only)
- def IsObsolete(self):
- return self.__obsolete
-
- # Get the sequence number (0 by default)
- def GetSequenceNumber(self):
- return self.__sequence_number
-
- # Set the sequence number
- def SetSequenceNumber(self, number):
- self.__sequence_number = number
-
- # Increment instance counter
- def AddInstance(self):
- self.__num_instances += 1
-
- # Return instance count
- def GetNumInstances(self):
- return self.__num_instances
-
- def GetErrors(self, from_tc=0):
- """
- Returns a description of the problem if the message is not
- syntactically valid, or None if everything is fine.
-
- Args:
- from_tc: indicates whether this message came from the TC. We let
- the TC get away with some things we normally wouldn't allow for
- historical reasons.
- """
- # check that placeholders are unambiguous
- pos = 0
- phs = {}
- for item in self.__content:
- if isinstance(item, Placeholder):
- phs[pos] = item
- pos += len(item.GetPresentation())
- else:
- pos += len(item)
- presentation = self.GetPresentableContent()
- for ph in self.GetPlaceholders():
- for pos in FindOverlapping(presentation, ph.GetPresentation()):
- # message contains the same text as a placeholder presentation
- other_ph = phs.get(pos)
- if ((not other_ph
- and not IsSubstringInPlaceholder(pos, len(ph.GetPresentation()), phs))
- or
- (other_ph and len(other_ph.GetPresentation()) < len(ph.GetPresentation()))):
- return "message contains placeholder name '%s':\n%s" % (
- ph.GetPresentation(), presentation)
- return None
-
-
- def __CopyTo(self, other):
- """
- Returns a copy of this BaseMessage.
- """
- assert isinstance(other, self.__class__) or isinstance(self, other.__class__)
- other.__source_encoding = self.__source_encoding
- other.__content = self.__content[:]
- other.__description = self.__description
- other.__id = self.__id
- other.__num_instances = self.__num_instances
- other.__obsolete = self.__obsolete
- other.__name = self.__name
- other.__placeholders = self.__placeholders[:]
- other.__sequence_number = self.__sequence_number
- other.__sources = self.__sources[:]
-
- return other
-
- def HasText(self):
- """Returns true iff this message has anything other than placeholders."""
- for item in self.__content:
- if not isinstance(item, Placeholder):
- return True
- return False
-
-# --------------------------------------------------------
-# The Message class represents original (English) messages
-
-class Message(BaseMessage):
- # See BaseMessage constructor
- def __init__(self, source_encoding, text=None, id=None,
- description=None, meaning="", placeholders=None,
- source=None, sequence_number=0, clone_from=None,
- time_created=0, name=None, is_hidden = 0):
-
- if clone_from is not None:
- BaseMessage.__init__(self, None, clone_from=clone_from)
- self.__meaning = clone_from.__meaning
- self.__time_created = clone_from.__time_created
- self.__is_hidden = clone_from.__is_hidden
- return
-
- BaseMessage.__init__(self, source_encoding, text, id, description,
- placeholders, source, sequence_number,
- name=name)
- self.__meaning = meaning
- self.__time_created = time_created
- self.SetIsHidden(is_hidden)
-
- # String representation
- def __str__(self):
- s = 'source: %s, id: %s, content: "%s", meaning: "%s", ' \
- 'description: "%s"' % \
- (self.GetSourcesAsText(), self.GetId(), self.GetPresentableContent(),
- self.__meaning, self.GetDescription())
- if self.GetName() is not None:
- s += ', name: "%s"' % self.GetName()
- placeholders = self.GetPlaceholders()
- for i in range(len(placeholders)):
- s += ", placeholder[%d]: %s" % (i, placeholders[i])
- return s
-
- # Strips leading and trailing whitespace, and returns a tuple
- # containing the leading and trailing space that was removed.
- def Strip(self):
- leading = trailing = ''
- content = self.GetContent()
- if len(content) > 0:
- s0 = content[0]
- if not isinstance(s0, Placeholder):
- s = s0.lstrip()
- leading = s0[:-len(s)]
- content[0] = s
-
- s0 = content[-1]
- if not isinstance(s0, Placeholder):
- s = s0.rstrip()
- trailing = s0[len(s):]
- content[-1] = s
- return leading, trailing
-
- # Generate an id by hashing message content
- def GenerateId(self):
- self.SetId(GenerateMessageId(self.GetPresentableContent(),
- self.__meaning))
- return self.GetId()
-
- def GetMeaning(self):
- return self.__meaning
-
- def GetTimeCreated(self):
- return self.__time_created
-
- # Equality operator
- def EqualTo(self, other, strict = 1):
- # Check id, meaning, content
- if self.GetId() != other.GetId():
- return 0
- if self.__meaning != other.__meaning:
- return 0
- if self.GetPresentableContent() != other.GetPresentableContent():
- return 0
- # Check descriptions if comparison is strict
- if (strict and
- self.GetDescription() is not None and
- other.GetDescription() is not None and
- self.GetDescription() != other.GetDescription()):
- return 0
- # Check placeholders
- ph1 = self.GetPlaceholders()
- ph2 = other.GetPlaceholders()
- if len(ph1) != len(ph2):
- return 0
- for i in range(len(ph1)):
- if not ph1[i].EqualTo(ph2[i], strict):
- return 0
-
- return 1
-
- def Copy(self):
- """
- Returns a copy of this Message.
- """
- assert isinstance(self, Message)
- return Message(None, clone_from=self)
-
- def SetIsHidden(self, is_hidden):
- """Sets whether this message should be hidden.
-
- Args:
- is_hidden : 0 or 1 - if the message should be hidden, 0 otherwise
- """
- if is_hidden not in [0, 1]:
- raise MessageTranslationError, "is_hidden must be 0 or 1, got %s"
- self.__is_hidden = is_hidden
-
- def IsHidden(self):
- """Returns 1 if this message is hidden, and 0 otherwise."""
- return self.__is_hidden
-
-# ----------------------------------------------------
-# The Translation class represents translated messages
-
-class Translation(BaseMessage):
- # See BaseMessage constructor
- def __init__(self, source_encoding, text=None, id=None,
- description=None, placeholders=None, source=None,
- sequence_number=0, clone_from=None, ignore_ph_errors=0,
- name=None):
- if clone_from is not None:
- BaseMessage.__init__(self, None, clone_from=clone_from)
- return
-
- BaseMessage.__init__(self, source_encoding, text, id, description,
- placeholders, source, sequence_number,
- ignore_ph_errors=ignore_ph_errors, name=name)
-
- # String representation
- def __str__(self):
- s = 'source: %s, id: %s, content: "%s", description: "%s"' % \
- (self.GetSourcesAsText(), self.GetId(), self.GetPresentableContent(),
- self.GetDescription());
- placeholders = self.GetPlaceholders()
- for i in range(len(placeholders)):
- s += ", placeholder[%d]: %s" % (i, placeholders[i])
- return s
-
- # Equality operator
- def EqualTo(self, other, strict=1):
- # Check id and content
- if self.GetId() != other.GetId():
- return 0
- if self.GetPresentableContent() != other.GetPresentableContent():
- return 0
- # Check placeholders
- ph1 = self.GetPlaceholders()
- ph2 = other.GetPlaceholders()
- if len(ph1) != len(ph2):
- return 0
- for i in range(len(ph1)):
- if not ph1[i].EqualTo(ph2[i], strict):
- return 0
-
- return 1
-
- def Copy(self):
- """
- Returns a copy of this Translation.
- """
- return Translation(None, clone_from=self)
-
diff --git a/tools/grit/grit/format/__init__.py b/tools/grit/grit/format/__init__.py
deleted file mode 100644
index 7444912..0000000
--- a/tools/grit/grit/format/__init__.py
+++ /dev/null
@@ -1,10 +0,0 @@
-#!/usr/bin/python2.4
-# Copyright (c) 2006-2008 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.
-
-'''Module grit.format
-'''
-
-pass
-
diff --git a/tools/grit/grit/format/data_pack.py b/tools/grit/grit/format/data_pack.py
deleted file mode 100755
index 87db064..0000000
--- a/tools/grit/grit/format/data_pack.py
+++ /dev/null
@@ -1,168 +0,0 @@
-#!/usr/bin/python2.4
-# Copyright (c) 2011 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.
-
-'''Support for formatting a data pack file used for platform agnostic resource
-files.
-'''
-
-import exceptions
-import os
-import struct
-import sys
-
-sys.path.append(os.path.join(os.path.dirname(__file__), '..', '..'))
-from grit.format import interface
-from grit.node import include
-from grit.node import message
-from grit.node import misc
-
-
-PACK_FILE_VERSION = 4
-HEADER_LENGTH = 2 * 4 + 1 # Two uint32s. (file version, number of entries) and
- # one uint8 (encoding of text resources)
-BINARY, UTF8, UTF16 = range(3)
-
-class WrongFileVersion(Exception):
- pass
-
-class DataPackContents:
- def __init__(self, resources, encoding):
- self.resources = resources
- self.encoding = encoding
-
-class DataPack(interface.ItemFormatter):
- '''Writes out the data pack file format (platform agnostic resource file).'''
- def Format(self, item, lang='en', begin_item=True, output_dir='.'):
- if not begin_item:
- return ''
-
- assert isinstance(item, misc.ReleaseNode)
-
- nodes = DataPack.GetDataNodes(item)
- data = {}
- for node in nodes:
- id, value = node.GetDataPackPair(lang, UTF8)
- data[id] = value
- return DataPack.WriteDataPackToString(data, UTF8)
-
- @staticmethod
- def GetDataNodes(item):
- '''Returns a list of nodes that can be packed into the data pack file.'''
- nodes = []
- if (isinstance(item, misc.IfNode) and not item.IsConditionSatisfied()):
- return nodes
- if (isinstance(item, include.IncludeNode) or
- isinstance(item, message.MessageNode)):
- # Include this node if it wasn't marked as skipped by a whitelist.
- if not item.WhitelistMarkedAsSkip():
- return [item]
- return nodes
- for child in item.children:
- nodes.extend(DataPack.GetDataNodes(child))
- return nodes
-
- @staticmethod
- def ReadDataPack(input_file):
- """Reads a data pack file and returns a dictionary."""
- data = open(input_file, "rb").read()
- original_data = data
-
- # Read the header.
- version, num_entries, encoding = struct.unpack("<IIB",
- data[:HEADER_LENGTH])
- if version != PACK_FILE_VERSION:
- print "Wrong file version in ", input_file
- raise WrongFileVersion
-
- resources = {}
- if num_entries == 0:
- return DataPackContents(resources, encoding)
-
- # Read the index and data.
- data = data[HEADER_LENGTH:]
- kIndexEntrySize = 2 + 4 # Each entry is a uint16 and a uint32.
- for _ in range(num_entries):
- id, offset = struct.unpack("<HI", data[:kIndexEntrySize])
- data = data[kIndexEntrySize:]
- next_id, next_offset = struct.unpack("<HI", data[:kIndexEntrySize])
- resources[id] = original_data[offset:next_offset]
-
- return DataPackContents(resources, encoding)
-
- @staticmethod
- def WriteDataPackToString(resources, encoding):
- """Write a map of id=>data into a string in the data pack format and return
- it."""
- ids = sorted(resources.keys())
- ret = []
-
- # Write file header.
- ret.append(struct.pack("<IIB", PACK_FILE_VERSION, len(ids), encoding))
- HEADER_LENGTH = 2 * 4 + 1 # Two uint32s and one uint8.
-
- # Each entry is a uint16 + a uint32s. We have one extra entry for the last
- # item.
- index_length = (len(ids) + 1) * (2 + 4)
-
- # Write index.
- data_offset = HEADER_LENGTH + index_length
- for id in ids:
- ret.append(struct.pack("<HI", id, data_offset))
- data_offset += len(resources[id])
-
- ret.append(struct.pack("<HI", 0, data_offset))
-
- # Write data.
- for id in ids:
- ret.append(resources[id])
- return ''.join(ret)
-
- @staticmethod
- def WriteDataPack(resources, output_file, encoding):
- """Write a map of id=>data into output_file as a data pack."""
- file = open(output_file, "wb")
- content = DataPack.WriteDataPackToString(resources, encoding)
- file.write(content)
-
- @staticmethod
- def RePack(output_file, input_files):
- """Write a new data pack to |output_file| based on a list of filenames
- (|input_files|)"""
- resources = {}
- encoding = None
- for filename in input_files:
- new_content = DataPack.ReadDataPack(filename)
-
- # Make sure we have no dups.
- duplicate_keys = set(new_content.resources.keys()) & set(resources.keys())
- if len(duplicate_keys) != 0:
- raise exceptions.KeyError("Duplicate keys: " +
- str(list(duplicate_keys)))
-
- # Make sure encoding is consistent.
- if encoding in (None, BINARY):
- encoding = new_content.encoding
- elif new_content.encoding not in (BINARY, encoding):
- raise exceptions.KeyError("Inconsistent encodings: " +
- str(encoding) + " vs " +
- str(new_content.encoding))
-
- resources.update(new_content.resources)
-
- # Encoding is 0 for BINARY, 1 for UTF8 and 2 for UTF16
- if encoding is None:
- encoding = BINARY
- DataPack.WriteDataPack(resources, output_file, encoding)
-
-def main():
- # Just write a simple file.
- data = { 1: "", 4: "this is id 4", 6: "this is id 6", 10: "" }
- DataPack.WriteDataPack(data, "datapack1.pak", UTF8)
- data2 = { 1000: "test", 5: "five" }
- DataPack.WriteDataPack(data2, "datapack2.pak", UTF8)
- print "wrote datapack1 and datapack2 to current directory."
-
-if __name__ == '__main__':
- main()
diff --git a/tools/grit/grit/format/data_pack_unittest.py b/tools/grit/grit/format/data_pack_unittest.py
deleted file mode 100644
index 8de54ef..0000000
--- a/tools/grit/grit/format/data_pack_unittest.py
+++ /dev/null
@@ -1,34 +0,0 @@
-#!/usr/bin/python2.4
-# Copyright (c) 2011 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.
-
-'''Unit tests for grit.format.data_pack'''
-
-import os
-import sys
-if __name__ == '__main__':
- sys.path.append(os.path.join(os.path.dirname(sys.argv[0]), '../..'))
-import unittest
-
-from grit.format import data_pack
-
-class FormatDataPackUnittest(unittest.TestCase):
- def testWriteDataPack(self):
- expected = (
- '\x04\x00\x00\x00' # header(version
- '\x04\x00\x00\x00' # no. entries,
- '\x01' # encoding)
- '\x01\x00\x27\x00\x00\x00' # index entry 1
- '\x04\x00\x27\x00\x00\x00' # index entry 4
- '\x06\x00\x33\x00\x00\x00' # index entry 6
- '\x0a\x00\x3f\x00\x00\x00' # index entry 10
- '\x00\x00\x3f\x00\x00\x00' # extra entry for the size of last
- 'this is id 4this is id 6') # data
- input = { 1: "", 4: "this is id 4", 6: "this is id 6", 10: "" }
- output = data_pack.DataPack.WriteDataPackToString(input, data_pack.UTF8)
- self.failUnless(output == expected)
-
-
-if __name__ == '__main__':
- unittest.main()
diff --git a/tools/grit/grit/format/html_inline.py b/tools/grit/grit/format/html_inline.py
deleted file mode 100755
index a886dda..0000000
--- a/tools/grit/grit/format/html_inline.py
+++ /dev/null
@@ -1,330 +0,0 @@
-#!/usr/bin/python
-# Copyright (c) 2011 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.
-
-"""Flattens a HTML file by inlining its external resources.
-
-This is a small script that takes a HTML file, looks for src attributes
-and inlines the specified file, producing one HTML file with no external
-dependencies.
-
-This does not inline anything referenced from an inlined file.
-"""
-
-import os
-import re
-import sys
-import base64
-import mimetypes
-
-from grit.node import base
-
-DIST_DEFAULT = 'chromium'
-DIST_ENV_VAR = 'CHROMIUM_BUILD'
-DIST_SUBSTR = '%DISTRIBUTION%'
-
-# Matches beginning of an "if" block with trailing spaces.
-_BEGIN_IF_BLOCK = re.compile('<if [^>]*?expr="(?P<expression>[^"]*)"[^>]*?>\s*')
-
-# Matches ending of an "if" block with preceding spaces.
-_END_IF_BLOCK = re.compile('\s*</if>')
-
-def ReadFile(input_filename):
- """Helper function that returns input_filename as a string.
-
- Args:
- input_filename: name of file to be read
-
- Returns:
- string
- """
- f = open(input_filename, 'rb')
- file_contents = f.read()
- f.close()
- return file_contents
-
-def SrcInlineAsDataURL(
- src_match, base_path, distribution, inlined_files, names_only=False):
- """regex replace function.
-
- Takes a regex match for src="filename", attempts to read the file
- at 'filename' and returns the src attribute with the file inlined
- as a data URI. If it finds DIST_SUBSTR string in file name, replaces
- it with distribution.
-
- Args:
- src_match: regex match object with 'filename' named capturing group
- base_path: path that to look for files in
- distribution: string that should replace DIST_SUBSTR
- inlined_files: The name of the opened file is appended to this list.
- names_only: If true, the function will not read the file but just return "".
- It will still add the filename to |inlined_files|.
-
- Returns:
- string
- """
- filename = src_match.group('filename')
-
- if filename.find(':') != -1:
- # filename is probably a URL, which we don't want to bother inlining
- return src_match.group(0)
-
- filename = filename.replace('%DISTRIBUTION%', distribution)
- filepath = os.path.join(base_path, filename)
- inlined_files.add(filepath)
-
- if names_only:
- return ""
-
- mimetype = mimetypes.guess_type(filename)[0] or 'text/plain'
- inline_data = base64.standard_b64encode(ReadFile(filepath))
-
- prefix = src_match.string[src_match.start():src_match.start('filename')-1]
- return "%s\"data:%s;base64,%s\"" % (prefix, mimetype, inline_data)
-
-
-class InlinedData:
- """Helper class holding the results from DoInline().
-
- Holds the inlined data and the set of filenames of all the inlined
- files.
- """
- def __init__(self, inlined_data, inlined_files):
- self.inlined_data = inlined_data
- self.inlined_files = inlined_files
-
-def DoInline(
- input_filename, grd_node, allow_external_script=False, names_only=False):
- """Helper function that inlines the resources in a specified file.
-
- Reads input_filename, finds all the src attributes and attempts to
- inline the files they are referring to, then returns the result and
- the set of inlined files.
-
- Args:
- input_filename: name of file to read in
- grd_node: html node from the grd file for this include tag
- names_only: |nil| will be returned for the inlined contents (faster).
- Returns:
- a tuple of the inlined data as a string and the set of filenames
- of all the inlined files
- """
- input_filepath = os.path.dirname(input_filename)
-
- distribution = DIST_DEFAULT
- if DIST_ENV_VAR in os.environ.keys():
- distribution = os.environ[DIST_ENV_VAR]
- if len(distribution) > 1 and distribution[0] == '_':
- distribution = distribution[1:].lower()
-
- # Keep track of all the files we inline.
- inlined_files = set()
-
- def SrcReplace(src_match, filepath=input_filepath,
- inlined_files=inlined_files):
- """Helper function to provide SrcInlineAsDataURL with the base file path"""
- return SrcInlineAsDataURL(
- src_match, filepath, distribution, inlined_files, names_only=names_only)
-
- def GetFilepath(src_match):
- filename = src_match.group('filename')
-
- if filename.find(':') != -1:
- # filename is probably a URL, which we don't want to bother inlining
- return None
-
- filename = filename.replace('%DISTRIBUTION%', distribution)
- return os.path.join(input_filepath, filename)
-
- def IsConditionSatisfied(src_match):
- expression = src_match.group('expression')
- return grd_node is None or grd_node.EvaluateCondition(expression)
-
- def CheckConditionalElements(str):
- """Helper function to conditionally inline inner elements"""
- while True:
- begin_if = _BEGIN_IF_BLOCK.search(str)
- if begin_if is None:
- return str
-
- condition_satisfied = IsConditionSatisfied(begin_if)
- leading = str[0:begin_if.start()]
- content_start = begin_if.end()
-
- # Find matching "if" block end.
- count = 1
- pos = begin_if.end()
- while True:
- end_if = _END_IF_BLOCK.search(str, pos)
- if end_if is None:
- raise Exception('Unmatched <if>')
-
- next_if = _BEGIN_IF_BLOCK.search(str, pos)
- if next_if is None or next_if.start() >= end_if.end():
- count = count - 1
- if count == 0:
- break
- pos = end_if.end()
- else:
- count = count + 1
- pos = next_if.end()
-
- content = str[content_start:end_if.start()]
- trailing = str[end_if.end():]
-
- if condition_satisfied:
- str = leading + CheckConditionalElements(content) + trailing
- else:
- str = leading + trailing
-
- def InlineFileContents(src_match, pattern, inlined_files=inlined_files):
- """Helper function to inline external script and css files"""
- filepath = GetFilepath(src_match)
- if filepath is None:
- return src_match.group(0)
- inlined_files.add(filepath)
-
- # Even if names_only is set, html files needs to be opened, because it
- # can link to images that need to be added to the file set.
- if names_only and not filepath.endswith('.html'):
- return ""
-
- return pattern % ReadFile(filepath)
-
- def InlineIncludeFiles(src_match):
- """Helper function to inline external script files"""
- return InlineFileContents(src_match, '%s')
-
- def InlineScript(src_match):
- """Helper function to inline external script files"""
- return InlineFileContents(src_match, '<script>%s</script>')
-
- def InlineCSSText(text, css_filepath):
- """Helper function that inlines external resources in CSS text"""
- filepath = os.path.dirname(css_filepath)
- return InlineCSSImages(text, filepath)
-
- def InlineCSSFile(src_match, inlined_files=inlined_files):
- """Helper function to inline external css files.
-
- Args:
- src_match: A regular expression match with a named group named "filename".
-
- Returns:
- The text that should replace the reference to the CSS file.
- """
- filepath = GetFilepath(src_match)
- if filepath is None:
- return src_match.group(0)
-
- # Even if names_only is set, the CSS file needs to be opened, because it
- # can link to images that need to be added to the file set.
- inlined_files.add(filepath)
- # When resolving CSS files we need to pass in the path so that relative URLs
- # can be resolved.
- return '<style>%s</style>' % InlineCSSText(ReadFile(filepath), filepath)
-
- def InlineCSSImages(text, filepath=input_filepath):
- """Helper function that inlines external images in CSS backgrounds."""
- # Replace contents of url() for css attributes: content, background,
- # or *-image.
- return re.sub('(?:content|background|[\w-]*-image):[ ]*' +
- 'url\((?:\'|\")(?P<filename>[^"\'\)\(]*)(?:\'|\")',
- lambda m: SrcReplace(m, filepath),
- text)
-
- flat_text = ReadFile(input_filename)
-
- if not allow_external_script:
- # We need to inline css and js before we inline images so that image
- # references gets inlined in the css and js
- flat_text = re.sub('<script .*?src="(?P<filename>[^"\']*)".*?></script>',
- InlineScript,
- flat_text)
-
- flat_text = re.sub(
- '<link rel="stylesheet".+?href="(?P<filename>[^"]*)".*?>',
- InlineCSSFile,
- flat_text)
-
- flat_text = re.sub(
- '<include\s+src="(?P<filename>[^"\']*)".*>',
- InlineIncludeFiles,
- flat_text)
-
- # Check conditional elements, remove unsatisfied ones from the file.
- flat_text = CheckConditionalElements(flat_text)
-
- flat_text = re.sub('<(?!script)[^>]+?src="(?P<filename>[^"\']*)"',
- SrcReplace,
- flat_text)
-
- # TODO(arv): Only do this inside <style> tags.
- flat_text = InlineCSSImages(flat_text)
-
- flat_text = re.sub('<link rel="icon".+?href="(?P<filename>[^"\']*)"',
- SrcReplace,
- flat_text)
-
- if names_only:
- flat_text = None # Will contains garbage if the flag is set anyway.
- return InlinedData(flat_text, inlined_files)
-
-
-def InlineToString(input_filename, grd_node, allow_external_script=False):
- """Inlines the resources in a specified file and returns it as a string.
-
- Args:
- input_filename: name of file to read in
- grd_node: html node from the grd file for this include tag
- Returns:
- the inlined data as a string
- """
- try:
- return DoInline(input_filename,
- grd_node,
- allow_external_script=allow_external_script).inlined_data
- except IOError, e:
- raise Exception("Failed to open %s while trying to flatten %s. (%s)" %
- (e.filename, input_filename, e.strerror))
-
-
-def InlineToFile(input_filename, output_filename, grd_node):
- """Inlines the resources in a specified file and writes it.
-
- Reads input_filename, finds all the src attributes and attempts to
- inline the files they are referring to, then writes the result
- to output_filename.
-
- Args:
- input_filename: name of file to read in
- output_filename: name of file to be written to
- grd_node: html node from the grd file for this include tag
- Returns:
- a set of filenames of all the inlined files
- """
- inlined_data = InlineToString(input_filename, grd_node)
- out_file = open(output_filename, 'wb')
- out_file.writelines(inlined_data)
- out_file.close()
-
-
-def GetResourceFilenames(filename):
- """For a grd file, returns a set of all the files that would be inline."""
- try:
- return DoInline(filename, None, names_only=True).inlined_files
- except IOError, e:
- raise Exception("Failed to open %s while trying to flatten %s. (%s)" %
- (e.filename, filename, e.strerror))
-
-
-def main():
- if len(sys.argv) <= 2:
- print "Flattens a HTML file by inlining its external resources.\n"
- print "html_inline.py inputfile outputfile"
- else:
- InlineToFile(sys.argv[1], sys.argv[2], None)
-
-if __name__ == '__main__':
- main()
diff --git a/tools/grit/grit/format/interface.py b/tools/grit/grit/format/interface.py
deleted file mode 100644
index 3f91ab2..0000000
--- a/tools/grit/grit/format/interface.py
+++ /dev/null
@@ -1,32 +0,0 @@
-#!/usr/bin/python2.4
-# Copyright (c) 2006-2008 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.
-
-'''Base classes for item formatters and file formatters.
-'''
-
-
-import re
-
-
-class ItemFormatter(object):
- '''Base class for a formatter that knows how to format a single item.'''
-
- def Format(self, item, lang='', begin_item=True, output_dir='.'):
- '''Returns a Unicode string representing 'item' in the format known by this
- item formatter, for the language 'lang'. May be called once at the
- start of the item (begin_item == True) and again at the end
- (begin_item == False), or only at the start of the item (begin_item == True)
-
- Args:
- item: anything
- lang: 'en'
- begin_item: True | False
- output_dir: '.'
-
- Return:
- u'hello'
- '''
- raise NotImplementedError()
-
diff --git a/tools/grit/grit/format/js_map_format.py b/tools/grit/grit/format/js_map_format.py
deleted file mode 100644
index 94efb6b..0000000
--- a/tools/grit/grit/format/js_map_format.py
+++ /dev/null
@@ -1,66 +0,0 @@
-#!/usr/bin/python2.4
-#
-# Copyright (c) 2009 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.
-
-"""Formats as a .js file using a map: <english text> -> <localized text>.
-"""
-
-import os
-import re
-import types
-
-from grit import util
-from grit.format import interface
-from grit.node import io
-
-
-class TopLevel(interface.ItemFormatter):
- """Writes out the required preamble for JS files."""
-
- def Format(self, item, lang='en', begin_item=True, output_dir='.'):
- """Format the JS file header."""
- assert isinstance(lang, types.StringTypes)
- if not begin_item:
- return ''
- else:
- return '''// Copyright %d Google Inc. All Rights Reserved.
-// This file is automatically generated by GRIT. Do not edit.
-''' % (util.GetCurrentYear())
-
-
-class StringTable(interface.ItemFormatter):
- """Writes out the string table."""
-
- def Format(self, item, lang='en', begin_item=True, output_dir='.'):
- if begin_item:
- return ''
- else:
- return '\n'
-
-
-class Message(interface.ItemFormatter):
- """Writes out a single message."""
-
- def Format(self, item, lang='en', begin_item=True, output_dir='.'):
- """Format a single message."""
- if not begin_item:
- return ''
-
- from grit.node import message
-
- assert isinstance(lang, types.StringTypes)
- assert isinstance(item, message.MessageNode)
-
- en_message = item.ws_at_start + item.Translate('en') + item.ws_at_end
- # Remove position numbers from placeholders.
- en_message = re.sub(r'%\d\$([a-z])', r'%\1', en_message)
- # Escape double quotes.
- en_message = re.sub(r'"', r'\"', en_message)
-
- loc_message = item.ws_at_start + item.Translate(lang) + item.ws_at_end
- # Escape double quotes.
- loc_message = re.sub(r'"', r'\"', loc_message)
-
- return '\nlocalizedStrings["%s"] = "%s";' % (en_message, loc_message)
diff --git a/tools/grit/grit/format/js_map_format_unittest.py b/tools/grit/grit/format/js_map_format_unittest.py
deleted file mode 100644
index fcd812b..0000000
--- a/tools/grit/grit/format/js_map_format_unittest.py
+++ /dev/null
@@ -1,98 +0,0 @@
-#!/usr/bin/python2.4
-#
-# Copyright (c) 2009 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.
-
-"""Unittest for js_map_format.py.
-"""
-
-import os
-import re
-import sys
-if __name__ == '__main__':
- sys.path.append(os.path.join(os.path.dirname(sys.argv[0]), '../..'))
-
-import unittest
-import StringIO
-
-from grit import grd_reader
-from grit import util
-from grit.tool import build
-
-
-class JsMapFormatUnittest(unittest.TestCase):
-
- def testMessages(self):
- grd_text = u"""
- <messages>
- <message name="IDS_SIMPLE_MESSAGE">
- Simple message.
- </message>
- <message name="IDS_QUOTES">
- element\u2019s \u201c<ph name="NAME">%s<ex>name</ex></ph>\u201d attribute
- </message>
- <message name="IDS_PLACEHOLDERS">
- <ph name="ERROR_COUNT">%1$d<ex>1</ex></ph> error, <ph name="WARNING_COUNT">%2$d<ex>1</ex></ph> warning
- </message>
- <message name="IDS_STARTS_WITH_SPACE">
- ''' (<ph name="COUNT">%d<ex>2</ex></ph>)
- </message>
- <message name="IDS_DOUBLE_QUOTES">
- A "double quoted" message.
- </message>
- </messages>
- """
- root = grd_reader.Parse(StringIO.StringIO(grd_text.encode('utf-8')),
- flexible_root=True)
- util.FixRootForUnittest(root)
-
- buf = StringIO.StringIO()
- build.RcBuilder.ProcessNode(root, DummyOutput('js_map_format', 'en'), buf)
- output = buf.getvalue()
- test = u"""
-localizedStrings["Simple message."] = "Simple message.";
-localizedStrings["element\u2019s \u201c%s\u201d attribute"] = "element\u2019s \u201c%s\u201d attribute";
-localizedStrings["%d error, %d warning"] = "%1$d error, %2$d warning";
-localizedStrings[" (%d)"] = " (%d)";
-localizedStrings["A \\\"double quoted\\\" message."] = "A \\\"double quoted\\\" message.";
-"""
- self.failUnless(output.strip() == test.strip())
-
- def testTranslations(self):
- root = grd_reader.Parse(StringIO.StringIO("""
- <messages>
- <message name="ID_HELLO">Hello!</message>
- <message name="ID_HELLO_USER">Hello <ph name="USERNAME">%s<ex>
- Joi</ex></ph></message>
- </messages>
- """), flexible_root=True)
- util.FixRootForUnittest(root)
-
- buf = StringIO.StringIO()
- build.RcBuilder.ProcessNode(root, DummyOutput('js_map_format', 'fr'), buf)
- output = buf.getvalue()
- test = u"""
-localizedStrings["Hello!"] = "H\xe9P\xe9ll\xf4P\xf4!";
-localizedStrings["Hello %s"] = "H\xe9P\xe9ll\xf4P\xf4 %s";
-"""
- self.failUnless(output.strip() == test.strip())
-
-
-class DummyOutput(object):
-
- def __init__(self, type, language):
- self.type = type
- self.language = language
-
- def GetType(self):
- return self.type
-
- def GetLanguage(self):
- return self.language
-
- def GetOutputFilename(self):
- return 'hello.gif'
-
-if __name__ == '__main__':
- unittest.main()
diff --git a/tools/grit/grit/format/policy_templates/PRESUBMIT.py b/tools/grit/grit/format/policy_templates/PRESUBMIT.py
deleted file mode 100644
index 2822968..0000000
--- a/tools/grit/grit/format/policy_templates/PRESUBMIT.py
+++ /dev/null
@@ -1,27 +0,0 @@
-# Copyright (c) 2011 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.
-
-UNIT_TESTS = [
- 'policy_template_generator_unittest',
- 'writers.adm_writer_unittest',
- 'writers.adml_writer_unittest',
- 'writers.admx_writer_unittest',
- 'writers.doc_writer_unittest',
- 'writers.json_writer_unittest',
- 'writers.plist_strings_writer_unittest',
- 'writers.plist_writer_unittest',
- 'writers.reg_writer_unittest',
- 'writers.template_writer_unittest'
-]
-
-def CheckChangeOnUpload(input_api, output_api):
- return input_api.canned_checks.RunPythonUnitTests(input_api,
- output_api,
- UNIT_TESTS)
-
-
-def CheckChangeOnCommit(input_api, output_api):
- return input_api.canned_checks.RunPythonUnitTests(input_api,
- output_api,
- UNIT_TESTS)
diff --git a/tools/grit/grit/format/policy_templates/__init__.py b/tools/grit/grit/format/policy_templates/__init__.py
deleted file mode 100644
index 1f159c0..0000000
--- a/tools/grit/grit/format/policy_templates/__init__.py
+++ /dev/null
@@ -1,9 +0,0 @@
-# Copyright (c) 2010 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.
-
-'''Module grit.format.policy_templates
-'''
-
-pass
-
diff --git a/tools/grit/grit/format/policy_templates/policy_template_generator.py b/tools/grit/grit/format/policy_templates/policy_template_generator.py
deleted file mode 100644
index e2f61e6..0000000
--- a/tools/grit/grit/format/policy_templates/policy_template_generator.py
+++ /dev/null
@@ -1,152 +0,0 @@
-# Copyright (c) 2011 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 copy
-
-
-class PolicyTemplateGenerator:
- '''Generates template text for a particular platform.
-
- This class is used to traverse a JSON structure from a .json template
- definition metafile and merge GUI message string definitions that come
- from a .grd resource tree onto it. After this, it can be used to output
- this data to policy template files using TemplateWriter objects.
- '''
-
- def _ImportMessage(self, msg_txt):
- msg_txt = msg_txt.decode('utf-8')
- # Replace the placeholder of app name.
- msg_txt = msg_txt.replace('$1', self._config['app_name'])
- msg_txt = msg_txt.replace('$2', self._config['os_name'])
- msg_txt = msg_txt.replace('$3', self._config['frame_name'])
- # Strip spaces and escape newlines.
- lines = msg_txt.split('\n')
- lines = [line.strip() for line in lines]
- return "\n".join(lines)
-
- def __init__(self, config, policy_data):
- '''Initializes this object with all the data necessary to output a
- policy template.
-
- Args:
- messages: An identifier to string dictionary of all the localized
- messages that might appear in the policy template.
- policy_definitions: The list of defined policies and groups, as
- parsed from the policy metafile. Note that this list is passed by
- reference and its contents are modified.
- See chrome/app/policy.policy_templates.json for description and
- content.
- '''
- # List of all the policies:
- self._policy_data = copy.deepcopy(policy_data)
- # Localized messages to be inserted to the policy_definitions structure:
- self._messages = self._policy_data['messages']
- self._config = config
- for key in self._messages.keys():
- self._messages[key]['text'] = self._ImportMessage(
- self._messages[key]['text'])
- self._policy_definitions = self._policy_data['policy_definitions']
- self._ProcessPolicyList(self._policy_definitions)
-
- def _ProcessSupportedOn(self, supported_on):
- '''Parses and converts the string items of the list of supported platforms
- into dictionaries.
-
- Args:
- supported_on: The list of supported platforms. E.g.:
- ['chrome.win:8-10', 'chrome_frame:10-']
-
- Returns:
- supported_on: The list with its items converted to dictionaries. E.g.:
- [{
- 'product': 'chrome',
- 'platform': 'win',
- 'since_version': '8',
- 'until_version': '10'
- }, {
- 'product': 'chrome_frame',
- 'platform': 'win',
- 'since_version': '10',
- 'until_version': ''
- }]
- '''
- result = []
- for supported_on_item in supported_on:
- product_platform_part, version_part = supported_on_item.split(':')
- if '.' in product_platform_part:
- product, platform = product_platform_part.split('.')
- if platform == '*':
- # e.g.: 'chrome.*:8-10'
- platforms = ['linux', 'mac', 'win']
- else:
- # e.g.: 'chrome.win:-10'
- platforms = [platform]
- else:
- # e.g.: 'chrome_frame:7-'
- product = product_platform_part
- platform = {
- 'chrome_os': 'chrome_os',
- 'chrome_frame': 'win'
- }[product]
- platforms = [platform]
- since_version, until_version = version_part.split('-')
- result.append({
- 'product': product,
- 'platforms': platforms,
- 'since_version': since_version,
- 'until_version': until_version
- })
- return result
-
- def _ProcessPolicy(self, policy):
- '''Processes localized message strings in a policy or a group.
- Also breaks up the content of 'supported_on' attribute into a list.
-
- Args:
- policy: The data structure of the policy or group, that will get message
- strings here.
- '''
- policy['desc'] = self._ImportMessage(policy['desc'])
- policy['caption'] = self._ImportMessage(policy['caption'])
- if 'label' in policy:
- policy['label'] = self._ImportMessage(policy['label'])
-
- if policy['type'] == 'group':
- self._ProcessPolicyList(policy['policies'])
- elif policy['type'] in ('string-enum', 'int-enum'):
- # Iterate through all the items of an enum-type policy, and add captions.
- for item in policy['items']:
- item['caption'] = self._ImportMessage(item['caption'])
- if policy['type'] != 'group':
- if not 'label' in policy:
- # If 'label' is not specified, then it defaults to 'caption':
- policy['label'] = policy['caption']
- policy['supported_on'] = self._ProcessSupportedOn(
- policy['supported_on'])
-
- def _ProcessPolicyList(self, policy_list):
- '''Adds localized message strings to each item in a list of policies and
- groups. Also breaks up the content of 'supported_on' attributes into lists
- of dictionaries.
-
- Args:
- policy_list: A list of policies and groups. Message strings will be added
- for each item and to their child items, recursively.
- '''
- for policy in policy_list:
- self._ProcessPolicy(policy)
-
- def GetTemplateText(self, template_writer):
- '''Generates the text of the template from the arguments given
- to the constructor, using a given TemplateWriter.
-
- Args:
- template_writer: An object implementing TemplateWriter. Its methods
- are called here for each item of self._policy_groups.
-
- Returns:
- The text of the generated template.
- '''
- return template_writer.WriteTemplate(self._policy_data)
diff --git a/tools/grit/grit/format/policy_templates/policy_template_generator_unittest.py b/tools/grit/grit/format/policy_templates/policy_template_generator_unittest.py
deleted file mode 100644
index 7d9a8bf..0000000
--- a/tools/grit/grit/format/policy_templates/policy_template_generator_unittest.py
+++ /dev/null
@@ -1,371 +0,0 @@
-# Copyright (c) 2011 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
-if __name__ == '__main__':
- sys.path.append(os.path.join(os.path.dirname(sys.argv[0]), '../../..'))
-
-import unittest
-
-from grit.format.policy_templates import policy_template_generator
-from grit.format.policy_templates.writers import mock_writer
-from grit.format.policy_templates.writers import template_writer
-
-
-class PolicyTemplateGeneratorUnittest(unittest.TestCase):
- '''Unit tests for policy_template_generator.py.'''
-
- def do_test(self, policy_data, writer):
- '''Executes a test case.
-
- Creates and invokes an instance of PolicyTemplateGenerator with
- the given arguments.
-
- Notice: Plain comments are used in test methods instead of docstrings,
- so that method names do not get overridden by the docstrings in the
- test output.
-
- Args:
- policy_data: The list of policies and groups as it would be
- loaded from policy_templates.json.
- writer: A writer used for this test. It is usually derived from
- mock_writer.MockWriter.
- '''
- writer.tester = self
- config = {
- 'app_name': '_app_name',
- 'frame_name': '_frame_name',
- 'os_name': '_os_name',
- }
- if not 'messages' in policy_data:
- policy_data['messages'] = {}
- if not 'placeholders' in policy_data:
- policy_data['placeholders'] = []
- if not 'policy_definitions' in policy_data:
- policy_data['policy_definitions'] = []
- policy_generator = policy_template_generator.PolicyTemplateGenerator(
- config,
- policy_data)
- res = policy_generator.GetTemplateText(writer)
- writer.Test()
- return res
-
- def testSequence(self):
- # Test the sequence of invoking the basic PolicyWriter operations,
- # in case of empty input data structures.
- class LocalMockWriter(mock_writer.MockWriter):
- def __init__(self):
- self.log = 'init;'
- def Init(self):
- self.log += 'prepare;'
- def BeginTemplate(self):
- self.log += 'begin;'
- def EndTemplate(self):
- self.log += 'end;'
- def GetTemplateText(self):
- self.log += 'get_text;'
- return 'writer_result_string'
- def Test(self):
- self.tester.assertEquals(self.log,
- 'init;prepare;begin;end;get_text;')
- result = self.do_test({}, LocalMockWriter())
- self.assertEquals(result, 'writer_result_string')
-
- def testEmptyGroups(self):
- # Test that empty policy groups are not passed to the writer.
- policies_mock = {
- 'policy_definitions': [
- {'name': 'Group1', 'type': 'group', 'policies': [],
- 'desc': '', 'caption': ''},
- {'name': 'Group2', 'type': 'group', 'policies': [],
- 'desc': '', 'caption': ''},
- {'name': 'Group3', 'type': 'group', 'policies': [],
- 'desc': '', 'caption': ''},
- ]
- }
- class LocalMockWriter(mock_writer.MockWriter):
- def __init__(self):
- self.log = ''
- def BeginPolicyGroup(self, group):
- self.log += '['
- def EndPolicyGroup(self):
- self.log += ']'
- def Test(self):
- self.tester.assertEquals(self.log, '')
- self.do_test(policies_mock, LocalMockWriter())
-
- def testGroups(self):
- # Test that policy groups are passed to the writer in the correct order.
- policies_mock = {
- 'policy_definitions': [
- {
- 'name': 'Group1', 'type': 'group',
- 'caption': '', 'desc': '',
- 'policies': [{'name': 'TAG1', 'type': 'mock', 'supported_on': [],
- 'caption': '', 'desc': ''}]
- },
- {
- 'name': 'Group2', 'type': 'group',
- 'caption': '', 'desc': '',
- 'policies': [{'name': 'TAG2', 'type': 'mock', 'supported_on': [],
- 'caption': '', 'desc': ''}]
- },
- {
- 'name': 'Group3', 'type': 'group',
- 'caption': '', 'desc': '',
- 'policies': [{'name': 'TAG3', 'type': 'mock', 'supported_on': [],
- 'caption': '', 'desc': ''}]
- },
- ]
- }
- class LocalMockWriter(mock_writer.MockWriter):
- def __init__(self):
- self.log = ''
- def BeginPolicyGroup(self, group):
- self.log += '[' + group['policies'][0]['name']
- def EndPolicyGroup(self):
- self.log += ']'
- def Test(self):
- self.tester.assertEquals(self.log, '[TAG1][TAG2][TAG3]')
- self.do_test(policies_mock, LocalMockWriter())
-
- def testPolicies(self):
- # Test that policies are passed to the writer in the correct order.
- policy_defs_mock = {
- 'policy_definitions': [
- {
- 'name': 'Group1',
- 'type': 'group',
- 'caption': '',
- 'desc': '',
- 'policies': [
- {'name': 'Group1Policy1', 'type': 'string', 'supported_on': [],
- 'caption': '', 'desc': ''},
- {'name': 'Group1Policy2', 'type': 'string', 'supported_on': [],
- 'caption': '', 'desc': ''},
- ]
- },
- {
- 'name': 'Group2',
- 'type': 'group',
- 'caption': '',
- 'desc': '',
- 'policies': [
- {'name': 'Group2Policy3', 'type': 'string', 'supported_on': [],
- 'caption': '', 'desc': ''},
- ]
- }
- ]
- }
- class LocalMockWriter(mock_writer.MockWriter):
- def __init__(self):
- self.policy_name = None
- self.policy_list = []
- def BeginPolicyGroup(self, group):
- self.group = group;
- def EndPolicyGroup(self):
- self.group = None
- def WritePolicy(self, policy):
- self.tester.assertEquals(policy['name'][0:6], self.group['name'])
- self.policy_list.append(policy['name'])
- def Test(self):
- self.tester.assertEquals(
- self.policy_list,
- ['Group1Policy1', 'Group1Policy2', 'Group2Policy3'])
- self.do_test( policy_defs_mock, LocalMockWriter())
-
- def testPolicyTexts(self):
- # Test that GUI messages of policies all get placeholders replaced.
- policy_data_mock = {
- 'policy_definitions': [
- {
- 'name': 'Group1',
- 'type': 'group',
- 'desc': '',
- 'caption': '',
- 'policies': [
- {
- 'name': 'Policy1',
- 'caption': '1. app_name -- $1',
- 'label': '2. os_name -- $2',
- 'desc': '3. frame_name -- $3',
- 'type': 'string',
- 'supported_on': []
- },
- ]
- }
- ]
- }
- class LocalMockWriter(mock_writer.MockWriter):
- def WritePolicy(self, policy):
- if policy['name'] == 'Policy1':
- self.tester.assertEquals(policy['caption'],
- '1. app_name -- _app_name')
- self.tester.assertEquals(policy['label'],
- '2. os_name -- _os_name')
- self.tester.assertEquals(policy['desc'],
- '3. frame_name -- _frame_name')
- elif policy['name'] == 'Group1':
- pass
- else:
- self.tester.fail()
- self.do_test(policy_data_mock, LocalMockWriter())
-
- def testIntEnumTexts(self):
- # Test that GUI messages are assigned correctly to int-enums
- # (aka dropdown menus).
- policy_defs_mock = {
- 'policy_definitions': [{
- 'name': 'Policy1',
- 'type': 'int-enum',
- 'caption': '', 'desc': '',
- 'supported_on': [],
- 'items': [
- {'name': 'item1', 'value': 0, 'caption': 'string1', 'desc': ''},
- {'name': 'item2', 'value': 1, 'caption': 'string2', 'desc': ''},
- {'name': 'item3', 'value': 3, 'caption': 'string3', 'desc': ''},
- ]
- }]
- }
-
- class LocalMockWriter(mock_writer.MockWriter):
- def WritePolicy(self, policy):
- self.tester.assertEquals(policy['items'][0]['caption'], 'string1')
- self.tester.assertEquals(policy['items'][1]['caption'], 'string2')
- self.tester.assertEquals(policy['items'][2]['caption'], 'string3')
- self.do_test(policy_defs_mock, LocalMockWriter())
-
- def testStringEnumTexts(self):
- # Test that GUI messages are assigned correctly to string-enums
- # (aka dropdown menus).
- policy_data_mock = {
- 'policy_definitions': [{
- 'name': 'Policy1',
- 'type': 'string-enum',
- 'caption': '', 'desc': '',
- 'supported_on': [],
- 'items': [
- {'name': 'item1', 'value': 'one', 'caption': 'string1', 'desc': ''},
- {'name': 'item2', 'value': 'two', 'caption': 'string2', 'desc': ''},
- {'name': 'item3', 'value': 'three', 'caption': 'string3', 'desc': ''},
- ]
- }]
- }
- class LocalMockWriter(mock_writer.MockWriter):
- def WritePolicy(self, policy):
- self.tester.assertEquals(policy['items'][0]['caption'], 'string1')
- self.tester.assertEquals(policy['items'][1]['caption'], 'string2')
- self.tester.assertEquals(policy['items'][2]['caption'], 'string3')
- self.do_test(policy_data_mock, LocalMockWriter())
-
- def testPolicyFiltering(self):
- # Test that policies are filtered correctly based on their annotations.
- policy_data_mock = {
- 'policy_definitions': [
- {
- 'name': 'Group1',
- 'type': 'group',
- 'caption': '',
- 'desc': '',
- 'policies': [
- {
- 'name': 'Group1Policy1',
- 'type': 'string',
- 'caption': '',
- 'desc': '',
- 'supported_on': [
- 'chrome.aaa:8-', 'chrome.bbb:8-', 'chrome.ccc:8-'
- ]
- },
- {
- 'name': 'Group1Policy2',
- 'type': 'string',
- 'caption': '',
- 'desc': '',
- 'supported_on': ['chrome.ddd:8-']
- },
- ]
- }, {
- 'name': 'Group2',
- 'type': 'group',
- 'caption': '',
- 'desc': '',
- 'policies': [
- {
- 'name': 'Group2Policy3',
- 'type': 'string',
- 'caption': '',
- 'desc': '',
- 'supported_on': ['chrome.eee:8-']
- },
- ]
- }, {
- 'name': 'SinglePolicy',
- 'type': 'int',
- 'caption': '',
- 'desc': '',
- 'supported_on': ['chrome.eee:8-']
- }
- ]
- }
- # This writer accumulates the list of policies it is asked to write.
- # This list is stored in the result_list member variable and can
- # be used later for assertions.
- class LocalMockWriter(mock_writer.MockWriter):
- def __init__(self, platforms):
- self.platforms = platforms
- self.policy_name = None
- self.result_list = []
- def BeginPolicyGroup(self, group):
- self.group = group;
- self.result_list.append('begin_' + group['name'])
- def EndPolicyGroup(self):
- self.result_list.append('end_group')
- self.group = None
- def WritePolicy(self, policy):
- self.result_list.append(policy['name'])
- def IsPolicySupported(self, policy):
- # Call the original (non-mock) implementation of this method.
- return template_writer.TemplateWriter.IsPolicySupported(self, policy)
-
- local_mock_writer = LocalMockWriter(['eee'])
- self.do_test(policy_data_mock, local_mock_writer)
- # Test that only policies of platform 'eee' were written:
- self.assertEquals(
- local_mock_writer.result_list,
- ['begin_Group2', 'Group2Policy3', 'end_group', 'SinglePolicy'])
-
- local_mock_writer = LocalMockWriter(['ddd', 'bbb'])
- self.do_test(policy_data_mock, local_mock_writer)
- # Test that only policies of platforms 'ddd' and 'bbb' were written:
- self.assertEquals(
- local_mock_writer.result_list,
- ['begin_Group1', 'Group1Policy1', 'Group1Policy2', 'end_group'])
-
- def testSortingInvoked(self):
- # Tests that policy-sorting happens before passing policies to the writer.
- policy_data = {
- 'policy_definitions': [
- {'name': 'zp', 'type': 'string', 'supported_on': [],
- 'caption': '', 'desc': ''},
- {'name': 'ap', 'type': 'string', 'supported_on': [],
- 'caption': '', 'desc': ''},
- ]
- }
- class LocalMockWriter(mock_writer.MockWriter):
- def __init__(self):
- self.result_list = []
- def WritePolicy(self, policy):
- self.result_list.append(policy['name'])
- def Test(self):
- self.tester.assertEquals(
- self.result_list,
- ['ap', 'zp'])
- self.do_test(policy_data, LocalMockWriter())
-
-
-if __name__ == '__main__':
- unittest.main()
diff --git a/tools/grit/grit/format/policy_templates/template_formatter.py b/tools/grit/grit/format/policy_templates/template_formatter.py
deleted file mode 100644
index fdd5dd9..0000000
--- a/tools/grit/grit/format/policy_templates/template_formatter.py
+++ /dev/null
@@ -1,103 +0,0 @@
-# Copyright (c) 2011 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 types
-
-from grit.format import interface
-from grit.format.policy_templates import policy_template_generator
-from grit.format.policy_templates import writer_configuration
-from grit.node import structure
-from grit.node import message
-from grit.node import misc
-
-
-class TemplateFormatter(interface.ItemFormatter):
- '''Creates a template file corresponding to an <output> node of the grit
- tree.
-
- More precisely, processes the whole grit tree for a given <output> node whose
- type is 'adm'. TODO(gfeher) add new types here
- The result of processing is a policy template file with the
- given type and language of the <output> node. A new instance of this class
- is created by grit.misc.GritNode for each <output> node. This class does
- the interfacing with grit, but the actual template-generating work is done in
- policy_template_generator.PolicyTemplateGenerator.
- '''
-
- def __init__(self, writer_name):
- '''Initializes this formatter to output messages with a given writer.
-
- Args:
- writer_name: A string identifying the TemplateWriter subclass used
- for generating the output. If writer name is 'adm', then the class
- from module 'writers.adm_writer' will be used.
- '''
- super(type(self), self).__init__()
- writer_module_name = \
- 'grit.format.policy_templates.writers.' + writer_name + '_writer'
- __import__(writer_module_name)
- # The module that contains the writer class:
- self._writer_module = sys.modules[writer_module_name]
-
- def Format(self, item, lang='en', begin_item=True, output_dir='.'):
- '''Generates a template corresponding to an <output> node in the grd file.
-
- Args:
- item: the <grit> root node of the grit tree.
- lang: the language of outputted text, e.g.: 'en'
- begin_item: True or False, depending on if this function was called at
- the beginning or at the end of the item.
- output_dir: The output directory, currently unused here.
-
- Returns:
- The text of the template file.
- '''
- if not begin_item:
- return ''
-
- self._lang = lang
- self._config = writer_configuration.GetConfigurationForBuild(item.defines)
- self._policy_data = None
- self._messages = {}
- self._ParseGritNodes(item)
- return self._GetOutput()
-
- def _GetOutput(self):
- '''Generates a template file using the instance variables initialized
- in Format() using the writer specified in __init__().
-
- Returns:
- The text of the policy template based on the parameters passed
- to __init__() and Format().
- '''
- policy_generator = policy_template_generator.PolicyTemplateGenerator(
- self._config,
- self._policy_data)
- writer = self._writer_module.GetWriter(self._config)
- str = policy_generator.GetTemplateText(writer)
- return str
-
- def _ParseGritNodes(self, item):
- '''Collects the necessary information from the grit tree:
- the message strings and the policy definitions.
-
- Args:
- item: The grit node parsed currently.
- '''
- nodes = []
- if (isinstance(item, misc.IfNode) and not item.IsConditionSatisfied()):
- return
- if (isinstance(item, structure.StructureNode) and
- item.attrs['type'] == 'policy_template_metafile'):
- assert self._policy_data == None
- json_text = item.gatherer.Translate(
- self._lang,
- pseudo_if_not_available=item.PseudoIsAllowed(),
- fallback_to_english=item.ShouldFallbackToEnglish())
- self._policy_data = eval(json_text)
- for child in item.children:
- self._ParseGritNodes(child)
diff --git a/tools/grit/grit/format/policy_templates/writer_configuration.py b/tools/grit/grit/format/policy_templates/writer_configuration.py
deleted file mode 100644
index 1d4cdf4..0000000
--- a/tools/grit/grit/format/policy_templates/writer_configuration.py
+++ /dev/null
@@ -1,50 +0,0 @@
-# Copyright (c) 2011 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.
-
-
-def GetConfigurationForBuild(defines):
- '''Returns a configuration dictionary for the given build that contains
- build-specific settings and information.
-
- Args:
- defines: Definitions coming from the build system.
-
- Raises:
- Exception: If 'defines' contains an unknown build-type.
- '''
- # The prefix of key names in config determines which writer will use their
- # corresponding values:
- # win: Both ADM and ADMX.
- # mac: Only plist.
- # admx: Only ADMX.
- # none/other: Used by all the writers.
- if '_chromium' in defines:
- config = {
- 'build': 'chromium',
- 'app_name': 'Chromium',
- 'frame_name': 'Chromium Frame',
- 'os_name': 'Chromium OS',
- 'win_reg_key_name': 'Software\\Policies\\Chromium',
- 'win_category_path': ['chromium'],
- 'admx_namespace': 'Chromium.Policies.Chromium',
- 'admx_prefix': 'chromium',
- }
- elif '_google_chrome' in defines:
- config = {
- 'build': 'chrome',
- 'app_name': 'Google Chrome',
- 'frame_name': 'Google Chrome Frame',
- 'os_name': 'Google Chrome OS',
- 'win_reg_key_name': 'Software\\Policies\\Google\\Chrome',
- 'win_category_path': ['google', 'googlechrome'],
- 'admx_namespace': 'Google.Policies.Chrome',
- 'admx_prefix': 'chrome',
- }
- else:
- raise Exception('Unknown build')
- config['win_group_policy_class'] = 'Both'
- config['win_supported_os'] = 'SUPPORTED_WINXPSP2'
- if 'mac_bundle_id' in defines:
- config['mac_bundle_id'] = defines['mac_bundle_id']
- return config
diff --git a/tools/grit/grit/format/policy_templates/writers/__init__.py b/tools/grit/grit/format/policy_templates/writers/__init__.py
deleted file mode 100644
index 68aab64..0000000
--- a/tools/grit/grit/format/policy_templates/writers/__init__.py
+++ /dev/null
@@ -1,9 +0,0 @@
-# Copyright (c) 2010 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.
-
-'''Module grit.format.policy_templates.writers
-'''
-
-pass
-
diff --git a/tools/grit/grit/format/policy_templates/writers/adm_writer.py b/tools/grit/grit/format/policy_templates/writers/adm_writer.py
deleted file mode 100644
index 5b071fa..0000000
--- a/tools/grit/grit/format/policy_templates/writers/adm_writer.py
+++ /dev/null
@@ -1,219 +0,0 @@
-# Copyright (c) 2011 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.
-
-
-from grit.format.policy_templates.writers import template_writer
-
-
-NEWLINE = '\r\n'
-
-
-def GetWriter(config):
- '''Factory method for creating AdmWriter objects.
- See the constructor of TemplateWriter for description of
- arguments.
- '''
- return AdmWriter(['win'], config)
-
-
-class IndentedStringBuilder:
- '''Utility class for building text with indented lines.'''
-
- def __init__(self):
- self.lines = []
- self.indent = ''
-
- def AddLine(self, string='', indent_diff=0):
- '''Appends a string with indentation and a linebreak to |self.lines|.
-
- Args:
- string: The string to print.
- indent_diff: the difference of indentation of the printed line,
- compared to the next/previous printed line. Increment occurs
- after printing the line, while decrement occurs before that.
- '''
- indent_diff *= 2
- if indent_diff < 0:
- self.indent = self.indent[(-indent_diff):]
- if string != '':
- self.lines.append(self.indent + string)
- else:
- self.lines.append('')
- if indent_diff > 0:
- self.indent += ''.ljust(indent_diff)
-
- def AddLines(self, other):
- '''Appends the content of another |IndentedStringBuilder| to |self.lines|.
- Indentation of the added lines will be the sum of |self.indent| and
- their original indentation.
-
- Args:
- other: The buffer from which lines are copied.
- '''
- for line in other.lines:
- self.AddLine(line)
-
- def ToString(self):
- '''Returns |self.lines| as text string.'''
- return NEWLINE.join(self.lines)
-
-
-class AdmWriter(template_writer.TemplateWriter):
- '''Class for generating policy templates in Windows ADM format.
- It is used by PolicyTemplateGenerator to write ADM files.
- '''
-
- TYPE_TO_INPUT = {
- 'string': 'EDITTEXT',
- 'int': 'NUMERIC',
- 'string-enum': 'DROPDOWNLIST',
- 'int-enum': 'DROPDOWNLIST',
- 'list': 'LISTBOX'
- }
-
- def _AddGuiString(self, name, value):
- # Escape newlines in the value.
- value = value.replace('\n', '\\n')
- line = '%s="%s"' % (name, value)
- self.strings.AddLine(line)
-
- def _WriteSupported(self):
- self.policies.AddLine('#if version >= 4', 1)
- self.policies.AddLine('SUPPORTED !!SUPPORTED_WINXPSP2')
- self.policies.AddLine('#endif', -1)
-
- def _WritePart(self, policy):
- '''Writes the PART ... END PART section of a policy.
-
- Args:
- policy: The policy to write to the output.
- '''
- policy_part_name = policy['name'] + '_Part'
- self._AddGuiString(policy_part_name, policy['label'])
-
- # Print the PART ... END PART section:
- self.policies.AddLine()
- adm_type = self.TYPE_TO_INPUT[policy['type']]
- self.policies.AddLine('PART !!%s %s' % (policy_part_name, adm_type), 1)
- if policy['type'] == 'list':
- # Note that the following line causes FullArmor ADMX Migrator to create
- # corrupt ADMX files. Please use admx_writer to get ADMX files.
- self.policies.AddLine('KEYNAME "%s\\%s"' %
- (self.config['win_reg_key_name'], policy['name']))
- self.policies.AddLine('VALUEPREFIX ""')
- else:
- self.policies.AddLine('VALUENAME "%s"' % policy['name'])
- if policy['type'] in ('int-enum', 'string-enum'):
- self.policies.AddLine('ITEMLIST', 1)
- for item in policy['items']:
- if policy['type'] == 'int-enum':
- value_text = 'NUMERIC ' + str(item['value'])
- else:
- value_text = '"' + item['value'] + '"'
- self.policies.AddLine('NAME !!%s_DropDown VALUE %s' %
- (item['name'], value_text))
- self._AddGuiString(item['name'] + '_DropDown', item['caption'])
- self.policies.AddLine('END ITEMLIST', -1)
- self.policies.AddLine('END PART', -1)
-
- def WritePolicy(self, policy):
- self._AddGuiString(policy['name'] + '_Policy', policy['caption'])
- self.policies.AddLine('POLICY !!%s_Policy' % policy['name'], 1)
- self._WriteSupported()
- policy_explain_name = policy['name'] + '_Explain'
- self._AddGuiString(policy_explain_name, policy['desc'])
- self.policies.AddLine('EXPLAIN !!' + policy_explain_name)
-
- if policy['type'] == 'main':
- self.policies.AddLine('VALUENAME "%s"' % policy['name'])
- self.policies.AddLine('VALUEON NUMERIC 1')
- self.policies.AddLine('VALUEOFF NUMERIC 0')
- else:
- self._WritePart(policy)
-
- self.policies.AddLine('END POLICY', -1)
- self.policies.AddLine()
-
- def BeginPolicyGroup(self, group):
- self._open_category = len(group['policies']) > 1
- # Open a category for the policies if there is more than one in the
- # group.
- if self._open_category:
- category_name = group['name'] + '_Category'
- self._AddGuiString(category_name, group['caption'])
- self.policies.AddLine('CATEGORY !!' + category_name, 1)
-
- def EndPolicyGroup(self):
- if self._open_category:
- self.policies.AddLine('END CATEGORY', -1)
- self.policies.AddLine('')
-
- def _CreateTemplateForClass(self, policy_class, policies):
- '''Creates the whole ADM template except for the [Strings] section, and
- returns it as an |IndentedStringBuilder|.
-
- Args:
- policy_class: USER or MACHINE
- policies: ADM code for all the policies in an |IndentedStringBuilder|.
- '''
- lines = IndentedStringBuilder()
- category_path = self.config['win_category_path']
-
- lines.AddLine('CLASS ' + policy_class, 1)
- if self.config['build'] == 'chrome':
- lines.AddLine('CATEGORY !!' + category_path[0], 1)
- lines.AddLine('CATEGORY !!' + category_path[1], 1)
- elif self.config['build'] == 'chromium':
- lines.AddLine('CATEGORY !!' + category_path[0], 1)
- lines.AddLine('KEYNAME "%s"' % self.config['win_reg_key_name'])
- lines.AddLine()
-
- lines.AddLines(policies)
-
- if self.config['build'] == 'chrome':
- lines.AddLine('END CATEGORY', -1)
- lines.AddLine('END CATEGORY', -1)
- lines.AddLine('', -1)
- elif self.config['build'] == 'chromium':
- lines.AddLine('END CATEGORY', -1)
- lines.AddLine('', -1)
-
- return lines
-
- def BeginTemplate(self):
- category_path = self.config['win_category_path']
- self._AddGuiString(self.config['win_supported_os'],
- self.messages['win_supported_winxpsp2']['text'])
- if self.config['build'] == 'chrome':
- self._AddGuiString(category_path[0], 'Google')
- self._AddGuiString(category_path[1], self.config['app_name'])
- elif self.config['build'] == 'chromium':
- self._AddGuiString(category_path[0], self.config['app_name'])
- # All the policies will be written into self.policies.
- # The final template text will be assembled into self.lines by
- # self.EndTemplate().
-
- def EndTemplate(self):
- # Copy policies into self.lines.
- policy_class = self.config['win_group_policy_class'].upper()
- if policy_class in ('BOTH', 'MACHINE'):
- self.lines.AddLines(self._CreateTemplateForClass('MACHINE',
- self.policies))
- if policy_class in ('BOTH', 'USER'):
- self.lines.AddLines(self._CreateTemplateForClass('USER',
- self.policies))
- # Copy user strings into self.lines.
- self.lines.AddLine('[Strings]')
- self.lines.AddLines(self.strings)
-
- def Init(self):
- # String buffer for building the whole ADM file.
- self.lines = IndentedStringBuilder()
- # String buffer for building the strings section of the ADM file.
- self.strings = IndentedStringBuilder()
- # String buffer for building the policies of the ADM file.
- self.policies = IndentedStringBuilder()
-
- def GetTemplateText(self):
- return self.lines.ToString()
diff --git a/tools/grit/grit/format/policy_templates/writers/adm_writer_unittest.py b/tools/grit/grit/format/policy_templates/writers/adm_writer_unittest.py
deleted file mode 100644
index ee5dc25..0000000
--- a/tools/grit/grit/format/policy_templates/writers/adm_writer_unittest.py
+++ /dev/null
@@ -1,525 +0,0 @@
-#!/usr/bin/python2.4
-# Copyright (c) 2011 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.
-
-'''Unit tests for grit.format.policy_templates.writers.adm_writer'''
-
-
-import os
-import sys
-if __name__ == '__main__':
- sys.path.append(os.path.join(os.path.dirname(sys.argv[0]), '../../../..'))
-
-import tempfile
-import unittest
-import StringIO
-
-from grit.format.policy_templates.writers import writer_unittest_common
-from grit import grd_reader
-from grit import util
-from grit.tool import build
-
-
-class AdmWriterUnittest(writer_unittest_common.WriterUnittestCommon):
- '''Unit tests for AdmWriter.'''
-
- def ConstructOutput(self, classes, body, strings):
- result = []
- for clazz in classes:
- result.append('CLASS ' + clazz)
- result.append(body)
- result.append(strings)
- return ''.join(result)
-
- def CompareOutputs(self, output, expected_output):
- '''Compares the output of the adm_writer with its expected output.
-
- Args:
- output: The output of the adm writer as returned by grit.
- expected_output: The expected output.
-
- Raises:
- AssertionError: if the two strings are not equivalent.
- '''
- self.assertEquals(
- output.strip(),
- expected_output.strip().replace('\n', '\r\n'))
-
- def testEmpty(self):
- # Test PListWriter in case of empty polices.
- grd = self.PrepareTest('''
- {
- 'policy_definitions': [],
- 'placeholders': [],
- 'messages': {
- 'win_supported_winxpsp2': {
- 'text': 'At least "Windows 3.11', 'desc': 'blah'
- }
- }
- }''')
- output = self.GetOutput(grd, 'fr', {'_chromium': '1',}, 'adm', 'en')
- expected_output = self.ConstructOutput(
- ['MACHINE', 'USER'], '''
- CATEGORY !!chromium
- KEYNAME "Software\\Policies\\Chromium"
-
- END CATEGORY
-
-''', '''[Strings]
-SUPPORTED_WINXPSP2="At least "Windows 3.11"
-chromium="Chromium"''')
- self.CompareOutputs(output, expected_output)
-
- def testMainPolicy(self):
- # Tests a policy group with a single policy of type 'main'.
- grd = self.PrepareTest('''
- {
- 'policy_definitions': [
- {
- 'name': 'MainPolicy',
- 'type': 'main',
- 'supported_on': ['chrome.win:8-'],
- 'caption': 'Caption of main.',
- 'desc': 'Description of main.',
- },
- ],
- 'placeholders': [],
- 'messages': {
- 'win_supported_winxpsp2': {
- 'text': 'At least Windows 3.12', 'desc': 'blah'
- }
- }
- }''')
- output = self.GetOutput(grd, 'fr', {'_google_chrome' : '1'}, 'adm', 'en')
- expected_output = self.ConstructOutput(
- ['MACHINE', 'USER'], '''
- CATEGORY !!google
- CATEGORY !!googlechrome
- KEYNAME "Software\\Policies\\Google\\Chrome"
-
- POLICY !!MainPolicy_Policy
- #if version >= 4
- SUPPORTED !!SUPPORTED_WINXPSP2
- #endif
- EXPLAIN !!MainPolicy_Explain
- VALUENAME "MainPolicy"
- VALUEON NUMERIC 1
- VALUEOFF NUMERIC 0
- END POLICY
-
- END CATEGORY
- END CATEGORY
-
-''', '''[Strings]
-SUPPORTED_WINXPSP2="At least Windows 3.12"
-google="Google"
-googlechrome="Google Chrome"
-MainPolicy_Policy="Caption of main."
-MainPolicy_Explain="Description of main."''')
- self.CompareOutputs(output, expected_output)
-
- def testStringPolicy(self):
- # Tests a policy group with a single policy of type 'string'.
- grd = self.PrepareTest('''
- {
- 'policy_definitions': [
- {
- 'name': 'StringPolicy',
- 'type': 'string',
- 'supported_on': ['chrome.win:8-'],
- 'desc': """Description of group.
-With a newline.""",
- 'caption': 'Caption of policy.',
- },
- ],
- 'placeholders': [],
- 'messages': {
- 'win_supported_winxpsp2': {
- 'text': 'At least Windows 3.13', 'desc': 'blah'
- }
- }
- }''')
- output = self.GetOutput(grd, 'fr', {'_chromium' : '1'}, 'adm', 'en')
- expected_output = self.ConstructOutput(
- ['MACHINE', 'USER'], '''
- CATEGORY !!chromium
- KEYNAME "Software\\Policies\\Chromium"
-
- POLICY !!StringPolicy_Policy
- #if version >= 4
- SUPPORTED !!SUPPORTED_WINXPSP2
- #endif
- EXPLAIN !!StringPolicy_Explain
-
- PART !!StringPolicy_Part EDITTEXT
- VALUENAME "StringPolicy"
- END PART
- END POLICY
-
- END CATEGORY
-
-''', '''[Strings]
-SUPPORTED_WINXPSP2="At least Windows 3.13"
-chromium="Chromium"
-StringPolicy_Policy="Caption of policy."
-StringPolicy_Explain="Description of group.\\nWith a newline."
-StringPolicy_Part="Caption of policy."
-''')
- self.CompareOutputs(output, expected_output)
-
- def testIntPolicy(self):
- # Tests a policy group with a single policy of type 'string'.
- grd = self.PrepareTest('''
- {
- 'policy_definitions': [
- {
- 'name': 'IntPolicy',
- 'type': 'int',
- 'caption': 'Caption of policy.',
- 'desc': 'Description of policy.',
- 'supported_on': ['chrome.win:8-']
- },
- ],
- 'placeholders': [],
- 'messages': {
- 'win_supported_winxpsp2': {
- 'text': 'At least Windows 3.13', 'desc': 'blah'
- }
- }
- }''')
- output = self.GetOutput(grd, 'fr', {'_chromium' : '1'}, 'adm', 'en')
- expected_output = self.ConstructOutput(
- ['MACHINE', 'USER'], '''
- CATEGORY !!chromium
- KEYNAME "Software\\Policies\\Chromium"
-
- POLICY !!IntPolicy_Policy
- #if version >= 4
- SUPPORTED !!SUPPORTED_WINXPSP2
- #endif
- EXPLAIN !!IntPolicy_Explain
-
- PART !!IntPolicy_Part NUMERIC
- VALUENAME "IntPolicy"
- END PART
- END POLICY
-
- END CATEGORY
-
-''', '''[Strings]
-SUPPORTED_WINXPSP2="At least Windows 3.13"
-chromium="Chromium"
-IntPolicy_Policy="Caption of policy."
-IntPolicy_Explain="Description of policy."
-IntPolicy_Part="Caption of policy."
-''')
- self.CompareOutputs(output, expected_output)
-
- def testIntEnumPolicy(self):
- # Tests a policy group with a single policy of type 'int-enum'.
- grd = self.PrepareTest('''
- {
- 'policy_definitions': [
- {
- 'name': 'EnumPolicy',
- 'type': 'int-enum',
- 'items': [
- {
- 'name': 'ProxyServerDisabled',
- 'value': 0,
- 'caption': 'Option1',
- },
- {
- 'name': 'ProxyServerAutoDetect',
- 'value': 1,
- 'caption': 'Option2',
- },
- ],
- 'desc': 'Description of policy.',
- 'caption': 'Caption of policy.',
- 'supported_on': ['chrome.win:8-']
- },
- ],
- 'placeholders': [],
- 'messages': {
- 'win_supported_winxpsp2': {
- 'text': 'At least Windows 3.14', 'desc': 'blah'
- }
- }
- }''')
- output = self.GetOutput(grd, 'fr', {'_google_chrome': '1'}, 'adm', 'en')
- expected_output = self.ConstructOutput(
- ['MACHINE', 'USER'], '''
- CATEGORY !!google
- CATEGORY !!googlechrome
- KEYNAME "Software\\Policies\\Google\\Chrome"
-
- POLICY !!EnumPolicy_Policy
- #if version >= 4
- SUPPORTED !!SUPPORTED_WINXPSP2
- #endif
- EXPLAIN !!EnumPolicy_Explain
-
- PART !!EnumPolicy_Part DROPDOWNLIST
- VALUENAME "EnumPolicy"
- ITEMLIST
- NAME !!ProxyServerDisabled_DropDown VALUE NUMERIC 0
- NAME !!ProxyServerAutoDetect_DropDown VALUE NUMERIC 1
- END ITEMLIST
- END PART
- END POLICY
-
- END CATEGORY
- END CATEGORY
-
-''', '''[Strings]
-SUPPORTED_WINXPSP2="At least Windows 3.14"
-google="Google"
-googlechrome="Google Chrome"
-EnumPolicy_Policy="Caption of policy."
-EnumPolicy_Explain="Description of policy."
-EnumPolicy_Part="Caption of policy."
-ProxyServerDisabled_DropDown="Option1"
-ProxyServerAutoDetect_DropDown="Option2"
-''')
- self.CompareOutputs(output, expected_output)
-
- def testStringEnumPolicy(self):
- # Tests a policy group with a single policy of type 'int-enum'.
- grd = self.PrepareTest('''
- {
- 'policy_definitions': [
- {
- 'name': 'EnumPolicy',
- 'type': 'string-enum',
- 'caption': 'Caption of policy.',
- 'desc': 'Description of policy.',
- 'items': [
- {'name': 'ProxyServerDisabled', 'value': 'one',
- 'caption': 'Option1'},
- {'name': 'ProxyServerAutoDetect', 'value': 'two',
- 'caption': 'Option2'},
- ],
- 'supported_on': ['chrome.win:8-']
- },
- ],
- 'placeholders': [],
- 'messages': {
- 'win_supported_winxpsp2': {
- 'text': 'At least Windows 3.14', 'desc': 'blah'
- }
- }
- }''')
- output = self.GetOutput(grd, 'fr', {'_google_chrome': '1'}, 'adm', 'en')
- expected_output = self.ConstructOutput(
- ['MACHINE', 'USER'], '''
- CATEGORY !!google
- CATEGORY !!googlechrome
- KEYNAME "Software\\Policies\\Google\\Chrome"
-
- POLICY !!EnumPolicy_Policy
- #if version >= 4
- SUPPORTED !!SUPPORTED_WINXPSP2
- #endif
- EXPLAIN !!EnumPolicy_Explain
-
- PART !!EnumPolicy_Part DROPDOWNLIST
- VALUENAME "EnumPolicy"
- ITEMLIST
- NAME !!ProxyServerDisabled_DropDown VALUE "one"
- NAME !!ProxyServerAutoDetect_DropDown VALUE "two"
- END ITEMLIST
- END PART
- END POLICY
-
- END CATEGORY
- END CATEGORY
-
-''', '''[Strings]
-SUPPORTED_WINXPSP2="At least Windows 3.14"
-google="Google"
-googlechrome="Google Chrome"
-EnumPolicy_Policy="Caption of policy."
-EnumPolicy_Explain="Description of policy."
-EnumPolicy_Part="Caption of policy."
-ProxyServerDisabled_DropDown="Option1"
-ProxyServerAutoDetect_DropDown="Option2"
-''')
- self.CompareOutputs(output, expected_output)
-
- def testListPolicy(self):
- # Tests a policy group with a single policy of type 'list'.
- grd = self.PrepareTest('''
- {
- 'policy_definitions': [
- {
- 'name': 'ListPolicy',
- 'type': 'list',
- 'supported_on': ['chrome.win:8-'],
- 'desc': """Description of list policy.
-With a newline.""",
- 'caption': 'Caption of list policy.',
- 'label': 'Label of list policy.'
- },
- ],
- 'placeholders': [],
- 'messages': {
- 'win_supported_winxpsp2': {
- 'text': 'At least Windows 3.15', 'desc': 'blah'
- }
- },
- }''')
- output = self.GetOutput(grd, 'fr', {'_chromium' : '1'}, 'adm', 'en')
- expected_output = self.ConstructOutput(
- ['MACHINE', 'USER'], '''
- CATEGORY !!chromium
- KEYNAME "Software\\Policies\\Chromium"
-
- POLICY !!ListPolicy_Policy
- #if version >= 4
- SUPPORTED !!SUPPORTED_WINXPSP2
- #endif
- EXPLAIN !!ListPolicy_Explain
-
- PART !!ListPolicy_Part LISTBOX
- KEYNAME "Software\\Policies\\Chromium\\ListPolicy"
- VALUEPREFIX ""
- END PART
- END POLICY
-
- END CATEGORY
-
-''', '''[Strings]
-SUPPORTED_WINXPSP2="At least Windows 3.15"
-chromium="Chromium"
-ListPolicy_Policy="Caption of list policy."
-ListPolicy_Explain="Description of list policy.\\nWith a newline."
-ListPolicy_Part="Label of list policy."
-''')
- self.CompareOutputs(output, expected_output)
-
- def testNonSupportedPolicy(self):
- # Tests a policy that is not supported on Windows, so it shouldn't
- # be included in the ADM file.
- grd = self.PrepareTest('''
- {
- 'policy_definitions': [
- {
- 'name': 'NonWinGroup',
- 'type': 'group',
- 'policies': [{
- 'name': 'NonWinPolicy',
- 'type': 'list',
- 'supported_on': ['chrome.linux:8-', 'chrome.mac:8-'],
- 'caption': 'Caption of list policy.',
- 'desc': 'Desc of list policy.',
- }],
- 'caption': 'Group caption.',
- 'desc': 'Group description.',
- },
- ],
- 'placeholders': [],
- 'messages': {
- 'win_supported_winxpsp2': {
- 'text': 'At least Windows 3.16', 'desc': 'blah'
- }
- }
- }''')
- output = self.GetOutput(grd, 'fr', {'_chromium' : '1'}, 'adm', 'en')
- expected_output = self.ConstructOutput(
- ['MACHINE', 'USER'], '''
- CATEGORY !!chromium
- KEYNAME "Software\\Policies\\Chromium"
-
- END CATEGORY
-
-''', '''[Strings]
-SUPPORTED_WINXPSP2="At least Windows 3.16"
-chromium="Chromium"
-''')
- self.CompareOutputs(output, expected_output)
-
- def testPolicyGroup(self):
- # Tests a policy group that has more than one policies.
- grd = self.PrepareTest('''
- {
- 'policy_definitions': [
- {
- 'name': 'Group1',
- 'type': 'group',
- 'desc': 'Description of group.',
- 'caption': 'Caption of group.',
- 'policies': [{
- 'name': 'Policy1',
- 'type': 'list',
- 'supported_on': ['chrome.win:8-'],
- 'caption': 'Caption of policy1.',
- 'desc': """Description of policy1.
-With a newline."""
- },{
- 'name': 'Policy2',
- 'type': 'string',
- 'supported_on': ['chrome.win:8-'],
- 'caption': 'Caption of policy2.',
- 'desc': """Description of policy2.
-With a newline."""
- }],
- },
- ],
- 'placeholders': [],
- 'messages': {
- 'win_supported_winxpsp2': {
- 'text': 'At least Windows 3.16', 'desc': 'blah'
- }
- }
- }''')
- output = self.GetOutput(grd, 'fr', {'_chromium' : '1'}, 'adm', 'en')
- expected_output = self.ConstructOutput(
- ['MACHINE', 'USER'], '''
- CATEGORY !!chromium
- KEYNAME "Software\\Policies\\Chromium"
-
- CATEGORY !!Group1_Category
- POLICY !!Policy1_Policy
- #if version >= 4
- SUPPORTED !!SUPPORTED_WINXPSP2
- #endif
- EXPLAIN !!Policy1_Explain
-
- PART !!Policy1_Part LISTBOX
- KEYNAME "Software\\Policies\\Chromium\\Policy1"
- VALUEPREFIX ""
- END PART
- END POLICY
-
- POLICY !!Policy2_Policy
- #if version >= 4
- SUPPORTED !!SUPPORTED_WINXPSP2
- #endif
- EXPLAIN !!Policy2_Explain
-
- PART !!Policy2_Part EDITTEXT
- VALUENAME "Policy2"
- END PART
- END POLICY
-
- END CATEGORY
-
- END CATEGORY
-
-''', '''[Strings]
-SUPPORTED_WINXPSP2="At least Windows 3.16"
-chromium="Chromium"
-Group1_Category="Caption of group."
-Policy1_Policy="Caption of policy1."
-Policy1_Explain="Description of policy1.\\nWith a newline."
-Policy1_Part="Caption of policy1."
-Policy2_Policy="Caption of policy2."
-Policy2_Explain="Description of policy2.\\nWith a newline."
-Policy2_Part="Caption of policy2."
-''')
- self.CompareOutputs(output, expected_output)
-
-if __name__ == '__main__':
- unittest.main()
diff --git a/tools/grit/grit/format/policy_templates/writers/adml_writer.py b/tools/grit/grit/format/policy_templates/writers/adml_writer.py
deleted file mode 100644
index 46e299d..0000000
--- a/tools/grit/grit/format/policy_templates/writers/adml_writer.py
+++ /dev/null
@@ -1,167 +0,0 @@
-# Copyright (c) 2011 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.
-
-from xml.dom import minidom
-from grit.format.policy_templates.writers import xml_formatted_writer
-
-
-def GetWriter(config):
- '''Factory method for instanciating the ADMLWriter. Every Writer needs a
- GetWriter method because the TemplateFormatter uses this method to
- instantiate a Writer.
- '''
- return ADMLWriter(['win'], config)
-
-
-class ADMLWriter(xml_formatted_writer.XMLFormattedWriter):
- ''' Class for generating an ADML policy template. It is used by the
- PolicyTemplateGenerator to write the ADML file.
- '''
-
- # DOM root node of the generated ADML document.
- _doc = None
-
- # The string-table contains all ADML "string" elements.
- _string_table_elem = None
-
- # The presentation-table is the container for presentation elements, that
- # describe the presentation of Policy-Groups and Policies.
- _presentation_table_elem = None
-
- def _AddString(self, parent, id, text):
- ''' Adds an ADML "string" element to the passed parent. The following
- ADML snippet contains an example:
-
- <string id="$(id)">$(text)</string>
-
- Args:
- parent: Parent element to which the new "string" element is added.
- id: ID of the newly created "string" element.
- text: Value of the newly created "string" element.
- '''
- string_elem = self.AddElement(parent, 'string', {'id': id})
- string_elem.appendChild(self._doc.createTextNode(text))
-
- def WritePolicy(self, policy):
- '''Generates the ADML elements for a Policy.
- <stringTable>
- ...
- <string id="$(policy_group_name)">$(caption)</string>
- <string id="$(policy_group_name)_Explain">$(description)</string>
- </stringTable>
-
- <presentationTables>
- ...
- <presentation id=$(policy_group_name)/>
- </presentationTables>
-
- Args:
- policy: The Policy to generate ADML elements for.
- '''
- policy_type = policy['type']
- policy_name = policy['name']
- if 'caption' in policy:
- policy_caption = policy['caption']
- else:
- policy_caption = policy_name
- if 'desc' in policy:
- policy_description = policy['desc']
- else:
- policy_description = policy_name
- if 'label' in policy:
- policy_label = policy['label']
- else:
- policy_label = policy_name
-
- self._AddString(self._string_table_elem, policy_name, policy_caption)
- self._AddString(self._string_table_elem, policy_name + '_Explain',
- policy_description)
- presentation_elem = self.AddElement(
- self._presentation_table_elem, 'presentation', {'id': policy_name})
-
- if policy_type == 'main':
- pass
- elif policy_type == 'string':
- textbox_elem = self.AddElement(presentation_elem, 'textBox',
- {'refId': policy_name})
- label_elem = self.AddElement(textbox_elem, 'label')
- label_elem.appendChild(self._doc.createTextNode(policy_label))
- elif policy_type == 'int':
- textbox_elem = self.AddElement(presentation_elem, 'decimalTextBox',
- {'refId': policy_name})
- textbox_elem.appendChild(self._doc.createTextNode(policy_label + ':'))
- elif policy_type in ('int-enum', 'string-enum'):
- for item in policy['items']:
- self._AddString(self._string_table_elem, item['name'], item['caption'])
- dropdownlist_elem = self.AddElement(presentation_elem, 'dropdownList',
- {'refId': policy_name})
- dropdownlist_elem.appendChild(self._doc.createTextNode(policy_label))
- elif policy_type == 'list':
- self._AddString(self._string_table_elem,
- policy_name + 'Desc',
- policy_caption)
- listbox_elem = self.AddElement(presentation_elem, 'listBox',
- {'refId': policy_name + 'Desc'})
- listbox_elem.appendChild(self._doc.createTextNode(policy_label))
- elif policy_type == 'group':
- pass
- else:
- raise Exception('Unknown policy type %s.' % policy_type)
-
- def BeginPolicyGroup(self, group):
- '''Generates ADML elements for a Policy-Group. For each Policy-Group two
- ADML "string" elements are added to the string-table. One contains the
- caption of the Policy-Group and the other a description. A Policy-Group also
- requires an ADML "presentation" element that must be added to the
- presentation-table. The "presentation" element is the container for the
- elements that define the visual presentation of the Policy-Goup's Policies.
- The following ADML snippet shows an example:
-
- Args:
- group: The Policy-Group to generate ADML elements for.
- '''
- # Add ADML "string" elements to the string-table that are required by a
- # Policy-Group.
- self._AddString(self._string_table_elem, group['name'] + '_group',
- group['caption'])
-
- def _AddBaseStrings(self, string_table_elem, build):
- ''' Adds ADML "string" elements to the string-table that are referenced by
- the ADMX file but not related to any specific Policy-Group or Policy.
- '''
- self._AddString(string_table_elem, self.config['win_supported_os'],
- self.messages['win_supported_winxpsp2']['text'])
- if build == 'chrome':
- self._AddString(string_table_elem, self.config['win_category_path'][0],
- 'Google')
- self._AddString(string_table_elem, self.config['win_category_path'][1],
- self.config['app_name'])
- elif build == 'chromium':
- self._AddString(string_table_elem, self.config['win_category_path'][0],
- self.config['app_name'])
-
- def BeginTemplate(self):
- dom_impl = minidom.getDOMImplementation('')
- self._doc = dom_impl.createDocument(None, 'policyDefinitionResources',
- None)
- policy_definitions_resources_elem = self._doc.documentElement
- policy_definitions_resources_elem.attributes['revision'] = '1.0'
- policy_definitions_resources_elem.attributes['schemaVersion'] = '1.0'
-
- self.AddElement(policy_definitions_resources_elem, 'displayName')
- self.AddElement(policy_definitions_resources_elem, 'description')
- resources_elem = self.AddElement(policy_definitions_resources_elem,
- 'resources')
- self._string_table_elem = self.AddElement(resources_elem, 'stringTable')
- self._AddBaseStrings(self._string_table_elem, self.config['build'])
- self._presentation_table_elem = self.AddElement(resources_elem,
- 'presentationTable')
-
- def GetTemplateText(self):
- # Using "toprettyxml()" confuses the Windows Group Policy Editor
- # (gpedit.msc) because it interprets whitespace characters in text between
- # the "string" tags. This prevents gpedit.msc from displaying the category
- # names correctly.
- # TODO(markusheintz): Find a better formatting that works with gpedit.
- return self._doc.toxml()
diff --git a/tools/grit/grit/format/policy_templates/writers/adml_writer_unittest.py b/tools/grit/grit/format/policy_templates/writers/adml_writer_unittest.py
deleted file mode 100644
index 41e9e8d..0000000
--- a/tools/grit/grit/format/policy_templates/writers/adml_writer_unittest.py
+++ /dev/null
@@ -1,336 +0,0 @@
-#!/usr/bin/python2.4
-# Copyright (c) 2011 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.
-
-
-"""Unittests for grit.format.policy_templates.writers.adml_writer."""
-
-
-import os
-import sys
-import unittest
-if __name__ == '__main__':
- sys.path.append(os.path.join(os.path.dirname(sys.argv[0]), '../../../..'))
-
-
-from grit.format.policy_templates.writers import adml_writer
-from grit.format.policy_templates.writers import xml_writer_base_unittest
-from xml.dom import minidom
-
-
-class AdmlWriterTest(xml_writer_base_unittest.XmlWriterBaseTest):
-
- def setUp(self):
- config = {
- 'build': 'test',
- 'win_supported_os': 'SUPPORTED_TESTOS',
- }
- self.writer = adml_writer.GetWriter(config)
- self.writer.messages = {
- 'win_supported_winxpsp2': {
- 'text': 'Supported on Test OS or higher',
- 'desc': 'blah'
- }
- }
- self.writer.Init()
-
- def _InitWriterForAddingPolicyGroups(self, writer):
- '''Initialize the writer for adding policy groups. This method must be
- called before the method "BeginPolicyGroup" can be called. It initializes
- attributes of the writer.
- '''
- writer.BeginTemplate()
-
- def _InitWriterForAddingPolicies(self, writer, policy):
- '''Initialize the writer for adding policies. This method must be
- called before the method "WritePolicy" can be called. It initializes
- attributes of the writer.
- '''
- self._InitWriterForAddingPolicyGroups(writer)
- policy_group = {
- 'name': 'PolicyGroup',
- 'caption': 'Test Caption',
- 'desc': 'This is the test description of the test policy group.',
- 'policies': policy,
- }
- writer.BeginPolicyGroup(policy_group)
-
- string_elements = \
- self.writer._string_table_elem.getElementsByTagName('string')
- for elem in string_elements:
- self.writer._string_table_elem.removeChild(elem)
-
- def testEmpty(self):
- self.writer.BeginTemplate()
- self.writer.EndTemplate()
- output = self.writer.GetTemplateText()
- expected_output = (
- '<?xml version="1.0" ?><policyDefinitionResources'
- ' revision="1.0" schemaVersion="1.0"><displayName/><description/>'
- '<resources><stringTable><string id="SUPPORTED_TESTOS">Supported on'
- ' Test OS or higher</string></stringTable><presentationTable/>'
- '</resources></policyDefinitionResources>')
- self.AssertXMLEquals(output, expected_output)
-
- def testPolicyGroup(self):
- empty_policy_group = {
- 'name': 'PolicyGroup',
- 'caption': 'Test Group Caption',
- 'desc': 'This is the test description of the test policy group.',
- 'policies': [
- {'name': 'PolicyStub2',
- 'type': 'main'},
- {'name': 'PolicyStub1',
- 'type': 'main'},
- ],
- }
- self._InitWriterForAddingPolicyGroups(self.writer)
- self.writer.BeginPolicyGroup(empty_policy_group)
- self.writer.EndPolicyGroup
- # Assert generated string elements.
- output = self.GetXMLOfChildren(self.writer._string_table_elem)
- expected_output = (
- '<string id="SUPPORTED_TESTOS">\n'
- ' Supported on Test OS or higher\n'
- '</string>\n'
- '<string id="PolicyGroup_group">\n'
- ' Test Group Caption\n'
- '</string>')
- self.AssertXMLEquals(output, expected_output)
- # Assert generated presentation elements.
- output = self.GetXMLOfChildren(self.writer._presentation_table_elem)
- expected_output = ''
- self.AssertXMLEquals(output, expected_output)
-
- def testMainPolicy(self):
- main_policy = {
- 'name': 'DummyMainPolicy',
- 'type': 'main',
- 'caption': 'Main policy caption',
- 'desc': 'Main policy test description.'
- }
- self. _InitWriterForAddingPolicies(self.writer, main_policy)
- self.writer.WritePolicy(main_policy)
- # Assert generated string elements.
- output = self.GetXMLOfChildren(self.writer._string_table_elem)
- expected_output = (
- '<string id="DummyMainPolicy">\n'
- ' Main policy caption\n'
- '</string>\n'
- '<string id="DummyMainPolicy_Explain">\n'
- ' Main policy test description.\n'
- '</string>')
- self.AssertXMLEquals(output, expected_output)
- # Assert generated presentation elements.
- output = self.GetXMLOfChildren(self.writer._presentation_table_elem)
- expected_output = '<presentation id="DummyMainPolicy"/>'
- self.AssertXMLEquals(output, expected_output)
-
- def testStringPolicy(self):
- string_policy = {
- 'name': 'StringPolicyStub',
- 'type': 'string',
- 'caption': 'String policy caption',
- 'label': 'String policy label',
- 'desc': 'This is a test description.',
- }
- self. _InitWriterForAddingPolicies(self.writer, string_policy)
- self.writer.WritePolicy(string_policy)
- # Assert generated string elements.
- output = self.GetXMLOfChildren(self.writer._string_table_elem)
- expected_output = (
- '<string id="StringPolicyStub">\n'
- ' String policy caption\n'
- '</string>\n'
- '<string id="StringPolicyStub_Explain">\n'
- ' This is a test description.\n'
- '</string>')
- self.AssertXMLEquals(output, expected_output)
- # Assert generated presentation elements.
- output = self.GetXMLOfChildren(self.writer._presentation_table_elem)
- expected_output = (
- '<presentation id="StringPolicyStub">\n'
- ' <textBox refId="StringPolicyStub">\n'
- ' <label>\n'
- ' String policy label\n'
- ' </label>\n'
- ' </textBox>\n'
- '</presentation>')
- self.AssertXMLEquals(output, expected_output)
-
- def testIntPolicy(self):
- int_policy = {
- 'name': 'IntPolicyStub',
- 'type': 'int',
- 'caption': 'Int policy caption',
- 'label': 'Int policy label',
- 'desc': 'This is a test description.',
- }
- self. _InitWriterForAddingPolicies(self.writer, int_policy)
- self.writer.WritePolicy(int_policy)
- # Assert generated string elements.
- output = self.GetXMLOfChildren(self.writer._string_table_elem)
- expected_output = (
- '<string id="IntPolicyStub">\n'
- ' Int policy caption\n'
- '</string>\n'
- '<string id="IntPolicyStub_Explain">\n'
- ' This is a test description.\n'
- '</string>')
- self.AssertXMLEquals(output, expected_output)
- # Assert generated presentation elements.
- output = self.GetXMLOfChildren(self.writer._presentation_table_elem)
- expected_output = (
- '<presentation id="IntPolicyStub">\n'
- ' <decimalTextBox refId="IntPolicyStub">\n'
- ' Int policy label:\n'
- ' </decimalTextBox>\n'
- '</presentation>')
- self.AssertXMLEquals(output, expected_output)
-
- def testIntEnumPolicy(self):
- enum_policy = {
- 'name': 'EnumPolicyStub',
- 'type': 'int-enum',
- 'caption': 'Enum policy caption',
- 'label': 'Enum policy label',
- 'desc': 'This is a test description.',
- 'items': [
- {
- 'name': 'item 1',
- 'value': 1,
- 'caption': 'Caption Item 1',
- },
- {
- 'name': 'item 2',
- 'value': 2,
- 'caption': 'Caption Item 2',
- },
- ],
- }
- self. _InitWriterForAddingPolicies(self.writer, enum_policy)
- self.writer.WritePolicy(enum_policy)
- # Assert generated string elements.
- output = self.GetXMLOfChildren(self.writer._string_table_elem)
- expected_output = (
- '<string id="EnumPolicyStub">\n'
- ' Enum policy caption\n'
- '</string>\n'
- '<string id="EnumPolicyStub_Explain">\n'
- ' This is a test description.\n'
- '</string>\n'
- '<string id="item 1">\n'
- ' Caption Item 1\n'
- '</string>\n'
- '<string id="item 2">\n'
- ' Caption Item 2\n'
- '</string>')
- self.AssertXMLEquals(output, expected_output)
- # Assert generated presentation elements.
- output = self.GetXMLOfChildren(self.writer._presentation_table_elem)
- expected_output = (
- '<presentation id="EnumPolicyStub">\n'
- ' <dropdownList refId="EnumPolicyStub">\n'
- ' Enum policy label\n'
- ' </dropdownList>\n'
- '</presentation>')
- self.AssertXMLEquals(output, expected_output)
-
- def testStringEnumPolicy(self):
- enum_policy = {
- 'name': 'EnumPolicyStub',
- 'type': 'string-enum',
- 'caption': 'Enum policy caption',
- 'label': 'Enum policy label',
- 'desc': 'This is a test description.',
- 'items': [
- {
- 'name': 'item 1',
- 'value': 'value 1',
- 'caption': 'Caption Item 1',
- },
- {
- 'name': 'item 2',
- 'value': 'value 2',
- 'caption': 'Caption Item 2',
- },
- ],
- }
- self. _InitWriterForAddingPolicies(self.writer, enum_policy)
- self.writer.WritePolicy(enum_policy)
- # Assert generated string elements.
- output = self.GetXMLOfChildren(self.writer._string_table_elem)
- expected_output = (
- '<string id="EnumPolicyStub">\n'
- ' Enum policy caption\n'
- '</string>\n'
- '<string id="EnumPolicyStub_Explain">\n'
- ' This is a test description.\n'
- '</string>\n'
- '<string id="item 1">\n'
- ' Caption Item 1\n'
- '</string>\n'
- '<string id="item 2">\n'
- ' Caption Item 2\n'
- '</string>')
- self.AssertXMLEquals(output, expected_output)
- # Assert generated presentation elements.
- output = self.GetXMLOfChildren(self.writer._presentation_table_elem)
- expected_output = (
- '<presentation id="EnumPolicyStub">\n'
- ' <dropdownList refId="EnumPolicyStub">\n'
- ' Enum policy label\n'
- ' </dropdownList>\n'
- '</presentation>')
- self.AssertXMLEquals(output, expected_output)
-
- def testListPolicy(self):
- list_policy = {
- 'name': 'ListPolicyStub',
- 'type': 'list',
- 'caption': 'List policy caption',
- 'label': 'List policy label',
- 'desc': 'This is a test description.',
- }
- self. _InitWriterForAddingPolicies(self.writer, list_policy)
- self.writer.WritePolicy(list_policy)
- # Assert generated string elements.
- output = self.GetXMLOfChildren(self.writer._string_table_elem)
- expected_output = (
- '<string id="ListPolicyStub">\n'
- ' List policy caption\n'
- '</string>\n'
- '<string id="ListPolicyStub_Explain">\n'
- ' This is a test description.\n'
- '</string>\n'
- '<string id="ListPolicyStubDesc">\n'
- ' List policy caption\n'
- '</string>')
- self.AssertXMLEquals(output, expected_output)
- # Assert generated presentation elements.
- output = self.GetXMLOfChildren(self.writer._presentation_table_elem)
- expected_output = (
- '<presentation id="ListPolicyStub">\n'
- ' <listBox refId="ListPolicyStubDesc">\n'
- ' List policy label\n'
- ' </listBox>\n'
- '</presentation>')
- self.AssertXMLEquals(output, expected_output)
-
- def testPlatform(self):
- # Test that the writer correctly chooses policies of platform Windows.
- self.assertTrue(self.writer.IsPolicySupported({
- 'supported_on': [
- {'platforms': ['win', 'zzz']}, {'platforms': ['aaa']}
- ]
- }))
- self.assertFalse(self.writer.IsPolicySupported({
- 'supported_on': [
- {'platforms': ['mac', 'linux']}, {'platforms': ['aaa']}
- ]
- }))
-
-
-if __name__ == '__main__':
- unittest.main()
diff --git a/tools/grit/grit/format/policy_templates/writers/admx_writer.py b/tools/grit/grit/format/policy_templates/writers/admx_writer.py
deleted file mode 100644
index da4aa64..0000000
--- a/tools/grit/grit/format/policy_templates/writers/admx_writer.py
+++ /dev/null
@@ -1,327 +0,0 @@
-# Copyright (c) 2011 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.
-
-from xml.dom import minidom
-from grit.format.policy_templates.writers import xml_formatted_writer
-
-
-def GetWriter(config):
- '''Factory method for instanciating the ADMXWriter. Every Writer needs a
- GetWriter method because the TemplateFormatter uses this method to
- instantiate a Writer.
- '''
- return ADMXWriter(['win'], config)
-
-
-class ADMXWriter(xml_formatted_writer.XMLFormattedWriter):
- '''Class for generating an ADMX policy template. It is used by the
- PolicyTemplateGenerator to write the admx file.
- '''
-
- # DOM root node of the generated ADMX document.
- _doc = None
-
- # The ADMX "policies" element that contains the ADMX "policy" elements that
- # are generated.
- _active_policies_elem = None
-
- def _AdmlString(self, name):
- '''Creates a reference to the named string in an ADML file.
- Args:
- name: Name of the referenced ADML string.
- '''
- return '$(string.' + name + ')'
-
- def _AdmlStringExplain(self, name):
- '''Creates a reference to the named explanation string in an ADML file.
- Args:
- name: Name of the referenced ADML explanation.
- '''
- return '$(string.' + name + '_Explain)'
-
- def _AdmlPresentation(self, name):
- '''Creates a reference to the named presentation element in an ADML file.
- Args:
- name: Name of the referenced ADML presentation element.
- '''
- return '$(presentation.' + name + ')'
-
- def _AddPolicyNamespaces(self, parent, prefix, namespace):
- '''Generates the ADMX "policyNamespace" element and adds the elements to the
- passed parent element. The namespace of the generated ADMX document is
- define via the ADMX "target" element. Used namespaces are declared with an
- ADMX "using" element. ADMX "target" and "using" elements are children of the
- ADMX "policyNamespace" element.
-
- Args:
- parent: The parent node to which all generated elements are added.
- prefix: A logical name that can be used in the generated ADMX document to
- refere to this namespace.
- namespace: Namespace of the generated ADMX document.
- '''
- policy_namespaces_elem = self.AddElement(parent, 'policyNamespaces')
- attributes = {
- 'prefix': prefix,
- 'namespace': namespace,
- }
- self.AddElement(policy_namespaces_elem, 'target', attributes)
- attributes = {
- 'prefix': 'windows',
- 'namespace': 'Microsoft.Policies.Windows',
- }
- self.AddElement(policy_namespaces_elem, 'using', attributes)
-
- def _AddCategory(self, parent, name, display_name,
- parent_category_name=None):
- '''Adds an ADMX category element to the passed parent node. The following
- snippet shows an example of a category element where "chromium" is the value
- of the parameter name:
-
- <category displayName="$(string.chromium)" name="chromium"/>
-
- Args:
- parent: The parent node to which all generated elements are added.
- name: Name of the category.
- display_name: Display name of the category.
- parent_category_name: Name of the parent category. Defaults to None.
- '''
- attributes = {
- 'name': name,
- 'displayName': display_name,
- }
- category_elem = self.AddElement(parent, 'category', attributes)
- if parent_category_name:
- attributes = {'ref': parent_category_name}
- self.AddElement(category_elem, 'parentCategory', attributes)
-
- def _AddCategories(self, parent, categories):
- '''Generates the ADMX "categories" element and adds it to the passed parent
- node. The "categories" element defines the category for the policies defined
- in this ADMX document. Here is an example of an ADMX "categories" element:
-
- <categories>
- <category displayName="$(string.google)" name="google"/>
- <category displayName="$(string.googlechrome)" name="googlechrome">
- <parentCategory ref="google"/>
- </category>
- </categories>
-
- Args:
- parent: The parent node to which all generated elements are added.
- categories_path: The categories path e.g. ['google', 'googlechrome']. For
- each level in the path a "category" element will be generated. Except
- for the root level, each level refers to its parent. Since the root
- level category has no parent it does not require a parent reference.
- '''
- self._categories_elem = self.AddElement(parent, 'categories')
- category_name = None
- for category in categories:
- parent_category_name = category_name
- category_name = category
- self._AddCategory(self._categories_elem, category_name,
- self._AdmlString(category_name), parent_category_name)
-
- def _AddSupportedOn(self, parent, supported_os):
- '''Generates the "supportedOn" ADMX element and adds it to the passed
- parent node. The "supportedOn" element contains information about supported
- Windows OS versions. The following code snippet contains an example of a
- "supportedOn" element:
-
- <supportedOn>
- <definitions>
- <definition name="SUPPORTED_WINXPSP2"
- displayName="$(string.SUPPORTED_WINXPSP2)"/>
- </definitions>
- ...
- </supportedOn>
-
- Args:
- parent: The parent element to which all generated elements are added.
- supported_os: List with all supported Win OSes.
- '''
- supported_on_elem = self.AddElement(parent, 'supportedOn')
- definitions_elem = self.AddElement(supported_on_elem, 'definitions')
- attributes = {
- 'name': supported_os,
- 'displayName': self._AdmlString(supported_os)
- }
- self.AddElement(definitions_elem, 'definition', attributes)
-
- def _AddStringPolicy(self, parent, name):
- '''Generates ADMX elements for a String-Policy and adds them to the
- passed parent node.
- '''
- attributes = {
- 'id': name,
- 'valueName': name,
- }
- self.AddElement(parent, 'text', attributes)
-
- def _AddIntPolicy(self, parent, name):
- '''Generates ADMX elements for an Int-Policy and adds them to the passed
- parent node.
- '''
- attributes = {
- 'id': name,
- 'valueName': name,
- }
- self.AddElement(parent, 'decimal', attributes)
-
- def _AddEnumPolicy(self, parent, policy):
- '''Generates ADMX elements for an Enum-Policy and adds them to the
- passed parent element.
- '''
- name = policy['name']
- items = policy['items']
- attributes = {
- 'id': name,
- 'valueName': name,
- }
- enum_elem = self.AddElement(parent, 'enum', attributes)
- for item in items:
- attributes = {'displayName': self._AdmlString(item['name'])}
- item_elem = self.AddElement(enum_elem, 'item', attributes)
- value_elem = self.AddElement(item_elem, 'value')
- value_string = str(item['value'])
- if policy['type'] == 'int-enum':
- self.AddElement(value_elem, 'decimal', {'value': value_string})
- else:
- self.AddElement(value_elem, 'string', {}, value_string)
-
- def _AddListPolicy(self, parent, name):
- '''Generates ADMX XML elements for a List-Policy and adds them to the
- passed parent element.
- '''
- attributes = {
- # The ID must be in sync with ID of the corresponding element in the ADML
- # file.
- 'id': name + 'Desc',
- 'valuePrefix': '',
- 'key': self.config['win_reg_key_name'] + '\\' + name,
- }
- self.AddElement(parent, 'list', attributes)
-
- def _AddMainPolicy(self, parent):
- '''Generates ADMX elements for a Main-Policy amd adds them to the
- passed parent element.
- '''
- enabled_value_elem = self.AddElement(parent, 'enabledValue');
- self.AddElement(enabled_value_elem, 'decimal', {'value': '1'})
- disabled_value_elem = self.AddElement(parent, 'disabledValue');
- self.AddElement(disabled_value_elem, 'decimal', {'value': '0'})
-
- def _GetElements(self, policy_group_elem):
- '''Returns the ADMX "elements" child from an ADMX "policy" element. If the
- "policy" element has no "elements" child yet, a new child is created.
-
- Args:
- policy_group_elem: The ADMX "policy" element from which the child element
- "elements" is returned.
-
- Raises:
- Exception: The policy_group_elem does not contain a ADMX "policy" element.
- '''
- if policy_group_elem.tagName != 'policy':
- raise Exception('Expected a "policy" element but got a "%s" element'
- % policy_group_elem.tagName)
- elements_list = policy_group_elem.getElementsByTagName('elements');
- if len(elements_list) == 0:
- return self.AddElement(policy_group_elem, 'elements')
- elif len(elements_list) == 1:
- return elements_list[0]
- else:
- raise Exception('There is supposed to be only one "elements" node but'
- ' there are %s.' % str(len(elements_list)))
-
- def WritePolicy(self, policy):
- '''Generates AMDX elements for a Policy. There are four different policy
- types: Main-Policy, String-Policy, Enum-Policy and List-Policy.
- '''
- policies_elem = self._active_policies_elem
- policy_type = policy['type']
- policy_name = policy['name']
-
- attributes = {
- 'name': policy_name,
- 'class': self.config['win_group_policy_class'],
- 'displayName': self._AdmlString(policy_name),
- 'explainText': self._AdmlStringExplain(policy_name),
- 'presentation': self._AdmlPresentation(policy_name),
- 'key': self.config['win_reg_key_name'],
- }
- # Store the current "policy" AMDX element in self for later use by the
- # WritePolicy method.
- policy_elem = self.AddElement(policies_elem, 'policy',
- attributes)
- self.AddElement(policy_elem, 'parentCategory',
- {'ref': self._active_policy_group_name})
- self.AddElement(policy_elem, 'supportedOn',
- {'ref': self.config['win_supported_os']})
- if policy_type == 'main':
- self.AddAttribute(policy_elem, 'valueName', policy_name)
- self._AddMainPolicy(policy_elem)
- elif policy_type == 'string':
- parent = self._GetElements(policy_elem)
- self._AddStringPolicy(parent, policy_name)
- elif policy_type == 'int':
- parent = self._GetElements(policy_elem)
- self._AddIntPolicy(parent, policy_name)
- elif policy_type in ('int-enum', 'string-enum'):
- parent = self._GetElements(policy_elem)
- self._AddEnumPolicy(parent, policy)
- elif policy_type == 'list':
- parent = self._GetElements(policy_elem)
- self._AddListPolicy(parent, policy_name)
- elif policy_type == 'group':
- pass
- else:
- raise Exception('Unknown policy type %s.' % policy_type)
-
- def BeginPolicyGroup(self, group):
- '''Generates ADMX elements for a Policy-Group.
- '''
- policy_group_name = group['name']
- attributes = {
- 'name': policy_group_name,
- 'displayName': self._AdmlString(policy_group_name + '_group'),
- }
- category_elem = self.AddElement(self._categories_elem,
- 'category',
- attributes)
- attributes = {
- 'ref': self.config['win_category_path'][-1],
- }
- self.AddElement(category_elem, 'parentCategory', attributes)
- self._active_policy_group_name = policy_group_name
-
- def EndPolicyGroup(self):
- self._active_policy_group_name = self.config['win_category_path'][-1]
-
- def BeginTemplate(self):
- '''Generates the skeleton of the ADMX template. An ADMX template contains
- an ADMX "PolicyDefinitions" element with four child nodes: "policies"
- "policyNamspaces", "resources", "supportedOn" and "categories"
- '''
- dom_impl = minidom.getDOMImplementation('')
- self._doc = dom_impl.createDocument(None, 'policyDefinitions', None)
- policy_definitions_elem = self._doc.documentElement
-
- policy_definitions_elem.attributes['revision'] = '1.0'
- policy_definitions_elem.attributes['schemaVersion'] = '1.0'
-
- self._AddPolicyNamespaces(policy_definitions_elem,
- self.config['admx_prefix'],
- self.config['admx_namespace'])
- self.AddElement(policy_definitions_elem, 'resources',
- {'minRequiredRevision' : '1.0'})
- self._AddSupportedOn(policy_definitions_elem,
- self.config['win_supported_os'])
- self._AddCategories(policy_definitions_elem,
- self.config['win_category_path'])
- self._active_policies_elem = self.AddElement(policy_definitions_elem,
- 'policies')
- self._active_policy_group_name = self.config['win_category_path'][-1]
-
- def GetTemplateText(self):
- return self.ToPrettyXml(self._doc)
diff --git a/tools/grit/grit/format/policy_templates/writers/admx_writer_unittest.py b/tools/grit/grit/format/policy_templates/writers/admx_writer_unittest.py
deleted file mode 100644
index 0a7f226..0000000
--- a/tools/grit/grit/format/policy_templates/writers/admx_writer_unittest.py
+++ /dev/null
@@ -1,343 +0,0 @@
-#!/usr/bin/python2.4
-# Copyright (c) 2011 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.
-
-
-"""Unittests for grit.format.policy_templates.writers.admx_writer."""
-
-
-import os
-import sys
-import unittest
-if __name__ == '__main__':
- sys.path.append(os.path.join(os.path.dirname(sys.argv[0]), '../../../..'))
-
-
-from grit.format.policy_templates.writers import admx_writer
-from grit.format.policy_templates.writers import xml_writer_base_unittest
-from xml.dom import minidom
-
-
-class AdmxWriterTest(xml_writer_base_unittest.XmlWriterBaseTest):
-
- def _CreateDocumentElement(self):
- dom_impl = minidom.getDOMImplementation('')
- doc = dom_impl.createDocument(None, 'root', None)
- return doc.documentElement
-
- def setUp(self):
- # Writer configuration. This dictionary contains parameter used by the ADMX
- # Writer
- config = {
- 'win_group_policy_class': 'TestClass',
- 'win_supported_os': 'SUPPORTED_TESTOS',
- 'win_reg_key_name': 'Software\\Policies\\Test',
- 'win_category_path': ['test_category'],
- 'admx_namespace': 'ADMXWriter.Test.Namespace',
- 'admx_prefix': 'test_prefix'
- }
- self.writer = admx_writer.GetWriter(config)
- self.writer.Init()
-
- def _GetPoliciesElement(self, doc):
- node_list = doc.getElementsByTagName('policies')
- self.assertTrue(node_list.length == 1)
- return node_list.item(0)
-
- def _GetCategoriesElement(self, doc):
- node_list = doc.getElementsByTagName('categories')
- self.assertTrue(node_list.length == 1)
- return node_list.item(0)
-
- def testEmpty(self):
- self.writer.BeginTemplate()
- self.writer.EndTemplate()
-
- output = self.writer.GetTemplateText()
- expected_output = (
- '<?xml version="1.0" ?>\n'
- '<policyDefinitions revision="1.0" schemaVersion="1.0">\n'
- ' <policyNamespaces>\n'
- ' <target namespace="ADMXWriter.Test.Namespace"'
- ' prefix="test_prefix"/>\n'
- ' <using namespace="Microsoft.Policies.Windows" prefix="windows"/>\n'
- ' </policyNamespaces>\n'
- ' <resources minRequiredRevision="1.0"/>\n'
- ' <supportedOn>\n'
- ' <definitions>\n'
- ' <definition displayName="'
- '$(string.SUPPORTED_TESTOS)" name="SUPPORTED_TESTOS"/>\n'
- ' </definitions>\n'
- ' </supportedOn>\n'
- ' <categories>\n'
- ' <category displayName="$(string.test_category)"'
- ' name="test_category"/>\n'
- ' </categories>\n'
- ' <policies/>\n'
- '</policyDefinitions>')
- self.AssertXMLEquals(output, expected_output)
-
- def testEmptyPolicyGroup(self):
- empty_policy_group = {
- 'name': 'PolicyGroup',
- 'policies': []
- }
- # Initialize writer to write a policy group.
- self.writer.BeginTemplate()
- # Write policy group
- self.writer.BeginPolicyGroup(empty_policy_group)
- self.writer.EndPolicyGroup()
-
- output = self.GetXMLOfChildren(self._GetPoliciesElement(self.writer._doc))
- expected_output = ''
- self.AssertXMLEquals(output, expected_output)
-
- output = self.GetXMLOfChildren(
- self._GetCategoriesElement(self.writer._doc))
- expected_output = (
- '<category displayName="$(string.test_category)"'
- ' name="test_category"/>\n'
- '<category displayName="$(string.PolicyGroup_group)"'
- ' name="PolicyGroup">\n'
- ' <parentCategory ref="test_category"/>\n'
- '</category>')
-
- self.AssertXMLEquals(output, expected_output)
-
- def testPolicyGroup(self):
- empty_policy_group = {
- 'name': 'PolicyGroup',
- 'policies': [
- {'name': 'PolicyStub2',
- 'type': 'main'},
- {'name': 'PolicyStub1',
- 'type': 'main'},
- ]
- }
- # Initialize writer to write a policy group.
- self.writer.BeginTemplate()
- # Write policy group
- self.writer.BeginPolicyGroup(empty_policy_group)
- self.writer.EndPolicyGroup()
-
- output = self.GetXMLOfChildren(self._GetPoliciesElement(self.writer._doc))
- expected_output = ''
- self.AssertXMLEquals(output, expected_output)
-
- output = self.GetXMLOfChildren(
- self._GetCategoriesElement(self.writer._doc))
- expected_output = (
- '<category displayName="$(string.test_category)"'
- ' name="test_category"/>\n'
- '<category displayName="$(string.PolicyGroup_group)"'
- ' name="PolicyGroup">\n'
- ' <parentCategory ref="test_category"/>\n'
- '</category>')
- self.AssertXMLEquals(output, expected_output)
-
-
- def _initWriterForPolicy(self, writer, policy):
- '''Initializes the writer to write the given policy next.
- '''
- policy_group = {
- 'name': 'PolicyGroup',
- 'policies': [policy]
- }
- writer.BeginTemplate()
- writer.BeginPolicyGroup(policy_group)
-
- def testMainPolicy(self):
- main_policy = {
- 'name': 'DummyMainPolicy',
- 'type': 'main',
- }
-
- self._initWriterForPolicy(self.writer, main_policy)
-
- self.writer.WritePolicy(main_policy)
-
- output = self.GetXMLOfChildren(self._GetPoliciesElement(self.writer._doc))
- expected_output = (
- '<policy class="TestClass" displayName="$(string.DummyMainPolicy)"'
- ' explainText="$(string.DummyMainPolicy_Explain)"'
- ' key="Software\\Policies\\Test" name="DummyMainPolicy"'
- ' presentation="$(presentation.DummyMainPolicy)"'
- ' valueName="DummyMainPolicy">\n'
- ' <parentCategory ref="PolicyGroup"/>\n'
- ' <supportedOn ref="SUPPORTED_TESTOS"/>\n'
- ' <enabledValue>\n'
- ' <decimal value="1"/>\n'
- ' </enabledValue>\n'
- ' <disabledValue>\n'
- ' <decimal value="0"/>\n'
- ' </disabledValue>\n'
- '</policy>')
-
- self.AssertXMLEquals(output, expected_output)
-
- def testStringPolicy(self):
- string_policy = {
- 'name': 'SampleStringPolicy',
- 'type': 'string',
- }
- self._initWriterForPolicy(self.writer, string_policy)
-
- self.writer.WritePolicy(string_policy)
- output = self.GetXMLOfChildren(self._GetPoliciesElement(self.writer._doc))
- expected_output = (
- '<policy class="TestClass" displayName="$(string.SampleStringPolicy)"'
- ' explainText="$(string.SampleStringPolicy_Explain)"'
- ' key="Software\\Policies\\Test" name="SampleStringPolicy"'
- ' presentation="$(presentation.SampleStringPolicy)">\n'
- ' <parentCategory ref="PolicyGroup"/>\n'
- ' <supportedOn ref="SUPPORTED_TESTOS"/>\n'
- ' <elements>\n'
- ' <text id="SampleStringPolicy" valueName="SampleStringPolicy"/>\n'
- ' </elements>\n'
- '</policy>')
- self.AssertXMLEquals(output, expected_output)
-
- def testIntPolicy(self):
- int_policy = {
- 'name': 'SampleIntPolicy',
- 'type': 'int',
- }
- self._initWriterForPolicy(self.writer, int_policy)
-
- self.writer.WritePolicy(int_policy)
- output = self.GetXMLOfChildren(self._GetPoliciesElement(self.writer._doc))
- expected_output = (
- '<policy class="TestClass" displayName="$(string.SampleIntPolicy)"'
- ' explainText="$(string.SampleIntPolicy_Explain)"'
- ' key="Software\\Policies\\Test" name="SampleIntPolicy"'
- ' presentation="$(presentation.SampleIntPolicy)">\n'
- ' <parentCategory ref="PolicyGroup"/>\n'
- ' <supportedOn ref="SUPPORTED_TESTOS"/>\n'
- ' <elements>\n'
- ' <decimal id="SampleIntPolicy" valueName="SampleIntPolicy"/>\n'
- ' </elements>\n'
- '</policy>')
- self.AssertXMLEquals(output, expected_output)
-
- def testIntEnumPolicy(self):
- enum_policy = {
- 'name': 'SampleEnumPolicy',
- 'type': 'int-enum',
- 'items': [
- {'name': 'item_1', 'value': 0},
- {'name': 'item_2', 'value': 1},
- ]
- }
-
- self._initWriterForPolicy(self.writer, enum_policy)
- self.writer.WritePolicy(enum_policy)
- output = self.GetXMLOfChildren(self._GetPoliciesElement(self.writer._doc))
- expected_output = (
- '<policy class="TestClass" displayName="$(string.SampleEnumPolicy)"'
- ' explainText="$(string.SampleEnumPolicy_Explain)"'
- ' key="Software\\Policies\\Test" name="SampleEnumPolicy"'
- ' presentation="$(presentation.SampleEnumPolicy)">\n'
- ' <parentCategory ref="PolicyGroup"/>\n'
- ' <supportedOn ref="SUPPORTED_TESTOS"/>\n'
- ' <elements>\n'
- ' <enum id="SampleEnumPolicy" valueName="SampleEnumPolicy">\n'
- ' <item displayName="$(string.item_1)">\n'
- ' <value>\n'
- ' <decimal value="0"/>\n'
- ' </value>\n'
- ' </item>\n'
- ' <item displayName="$(string.item_2)">\n'
- ' <value>\n'
- ' <decimal value="1"/>\n'
- ' </value>\n'
- ' </item>\n'
- ' </enum>\n'
- ' </elements>\n'
- '</policy>')
- self.AssertXMLEquals(output, expected_output)
-
- def testStringEnumPolicy(self):
- enum_policy = {
- 'name': 'SampleEnumPolicy',
- 'type': 'string-enum',
- 'items': [
- {'name': 'item_1', 'value': 'one'},
- {'name': 'item_2', 'value': 'two'},
- ]
- }
-
- # This test is different than the others because it also tests that space
- # usage inside <string> nodes is correct.
- dom_impl = minidom.getDOMImplementation('')
- self.writer._doc = dom_impl.createDocument(None, 'policyDefinitions', None)
- self.writer._active_policies_elem = self.writer._doc.documentElement
- self.writer._active_policy_group_name = 'PolicyGroup'
- self.writer.WritePolicy(enum_policy)
- output = self.writer.GetTemplateText()
- expected_output = (
- '<?xml version="1.0" ?>\n'
- '<policyDefinitions>\n'
- ' <policy class="TestClass" displayName="$(string.SampleEnumPolicy)"'
- ' explainText="$(string.SampleEnumPolicy_Explain)"'
- ' key="Software\\Policies\\Test" name="SampleEnumPolicy"'
- ' presentation="$(presentation.SampleEnumPolicy)">\n'
- ' <parentCategory ref="PolicyGroup"/>\n'
- ' <supportedOn ref="SUPPORTED_TESTOS"/>\n'
- ' <elements>\n'
- ' <enum id="SampleEnumPolicy" valueName="SampleEnumPolicy">\n'
- ' <item displayName="$(string.item_1)">\n'
- ' <value>\n'
- ' <string>one</string>\n'
- ' </value>\n'
- ' </item>\n'
- ' <item displayName="$(string.item_2)">\n'
- ' <value>\n'
- ' <string>two</string>\n'
- ' </value>\n'
- ' </item>\n'
- ' </enum>\n'
- ' </elements>\n'
- ' </policy>\n'
- '</policyDefinitions>')
- self.AssertXMLEquals(output, expected_output)
-
- def testListPolicy(self):
- list_policy = {
- 'name': 'SampleListPolicy',
- 'type': 'list',
- }
- self._initWriterForPolicy(self.writer, list_policy)
- self.writer.WritePolicy(list_policy)
- output = self.GetXMLOfChildren(self._GetPoliciesElement(self.writer._doc))
- expected_output = (
- '<policy class="TestClass" displayName="$(string.SampleListPolicy)"'
- ' explainText="$(string.SampleListPolicy_Explain)"'
- ' key="Software\\Policies\\Test" name="SampleListPolicy"'
- ' presentation="$(presentation.SampleListPolicy)">\n'
- ' <parentCategory ref="PolicyGroup"/>\n'
- ' <supportedOn ref="SUPPORTED_TESTOS"/>\n'
- ' <elements>\n'
- ' <list id="SampleListPolicyDesc"'
- ' key="Software\Policies\Test\SampleListPolicy" valuePrefix=""/>\n'
- ' </elements>\n'
- '</policy>')
-
- self.AssertXMLEquals(output, expected_output)
-
- def testPlatform(self):
- # Test that the writer correctly chooses policies of platform Windows.
- self.assertTrue(self.writer.IsPolicySupported({
- 'supported_on': [
- {'platforms': ['win', 'zzz']}, {'platforms': ['aaa']}
- ]
- }))
- self.assertFalse(self.writer.IsPolicySupported({
- 'supported_on': [
- {'platforms': ['mac', 'linux']}, {'platforms': ['aaa']}
- ]
- }))
-
-
-if __name__ == '__main__':
- unittest.main()
diff --git a/tools/grit/grit/format/policy_templates/writers/doc_writer.py b/tools/grit/grit/format/policy_templates/writers/doc_writer.py
deleted file mode 100644
index 34f111e..0000000
--- a/tools/grit/grit/format/policy_templates/writers/doc_writer.py
+++ /dev/null
@@ -1,538 +0,0 @@
-# Copyright (c) 2011 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 re
-
-from xml.dom import minidom
-from grit.format.policy_templates.writers import xml_formatted_writer
-
-
-def GetWriter(config):
- '''Factory method for creating DocWriter objects.
- See the constructor of TemplateWriter for description of
- arguments.
- '''
- return DocWriter(['*'], config)
-
-
-class DocWriter(xml_formatted_writer.XMLFormattedWriter):
- '''Class for generating policy templates in HTML format.
- The intended use of the generated file is to upload it on
- http://dev.chromium.org, therefore its format has some limitations:
- - No HTML and body tags.
- - Restricted set of element attributes: for example no 'class'.
- Because of the latter the output is styled using the 'style'
- attributes of HTML elements. This is supported by the dictionary
- self._STYLES[] and the method self._AddStyledElement(), they try
- to mimic the functionality of CSS classes. (But without inheritance.)
-
- This class is invoked by PolicyTemplateGenerator to create the HTML
- files.
- '''
-
- def _GetLocalizedMessage(self, msg_id):
- '''Returns a localized message for this writer.
-
- Args:
- msg_id: The identifier of the message.
-
- Returns:
- The localized message.
- '''
- return self.messages['doc_' + msg_id]['text']
-
- def _MapListToString(self, item_map, items):
- '''Creates a comma-separated list.
-
- Args:
- item_map: A dictionary containing all the elements of 'items' as
- keys.
- items: A list of arbitrary items.
-
- Returns:
- Looks up each item of 'items' in 'item_maps' and concatenates the
- resulting items into a comma-separated list.
- '''
- return ', '.join([item_map[x] for x in items])
-
- def _AddTextWithLinks(self, parent, text):
- '''Parse a string for URLs and add it to a DOM node with the URLs replaced
- with <a> HTML links.
-
- Args:
- parent: The DOM node to which the text will be added.
- text: The string to be added.
- '''
- # Iterate through all the URLs and replace them with links.
- out = []
- while True:
- # Look for the first URL.
- res = self._url_matcher.search(text)
- if not res:
- break
- # Calculate positions of the substring of the URL.
- url = res.group(0)
- start = res.start(0)
- end = res.end(0)
- # Add the text prior to the URL.
- self.AddText(parent, text[:start])
- # Add a link for the URL.
- self.AddElement(parent, 'a', {'href': url}, url)
- # Drop the part of text that is added.
- text = text[end:]
- self.AddText(parent, text)
-
-
- def _AddStyledElement(self, parent, name, style_ids, attrs=None, text=None):
- '''Adds an XML element to a parent, with CSS style-sheets included.
-
- Args:
- parent: The parent DOM node.
- name: Name of the element to add.
- style_ids: A list of CSS style strings from self._STYLE[].
- attrs: Dictionary of attributes for the element.
- text: Text content for the element.
- '''
- if attrs == None:
- attrs = {}
-
- style = ''.join([self._STYLE[x] for x in style_ids])
- if style != '':
- # Apply the style specified by style_ids.
- attrs['style'] = style + attrs.get('style', '')
- return self.AddElement(parent, name, attrs, text)
-
- def _AddDescription(self, parent, policy):
- '''Adds a string containing the description of the policy. URLs are
- replaced with links and the possible choices are enumerated in case
- of 'string-enum' and 'int-enum' type policies.
-
- Args:
- parent: The DOM node for which the feature list will be added.
- policy: The data structure of a policy.
- '''
- # Replace URLs with links in the description.
- self._AddTextWithLinks(parent, policy['desc'])
- # Add list of enum items.
- if policy['type'] in ('string-enum', 'int-enum'):
- ul = self.AddElement(parent, 'ul')
- for item in policy['items']:
- if policy['type'] == 'int-enum':
- value_string = str(item['value'])
- else:
- value_string = '"%s"' % item['value']
- self.AddElement(
- ul, 'li', {}, '%s = %s' % (value_string, item['caption']))
-
- def _AddFeatures(self, parent, policy):
- '''Adds a string containing the list of supported features of a policy
- to a DOM node. The text will look like as:
- Feature_X: Yes, Feature_Y: No
-
- Args:
- parent: The DOM node for which the feature list will be added.
- policy: The data structure of a policy.
- '''
- features = []
- for key, value in policy['features'].iteritems():
- key_name = self._FEATURE_MAP[key]
- if value == 0:
- value_name = self._GetLocalizedMessage('not_supported')
- else:
- value_name = self._GetLocalizedMessage('supported')
- features.append('%s: %s' % (key_name, value_name))
- self.AddText(parent, ', '.join(features))
-
- def _AddListExampleMac(self, parent, policy):
- '''Adds an example value for Mac of a 'list' policy to a DOM node.
-
- Args:
- parent: The DOM node for which the example will be added.
- policy: A policy of type 'list', for which the Mac example value
- is generated.
- '''
- example_value = policy['example_value']
- self.AddElement(parent, 'dt', {}, 'Mac:')
- mac = self._AddStyledElement(parent, 'dd', ['.monospace', '.pre'])
-
- mac_text = ['<array>']
- for item in example_value:
- mac_text.append(' <string>%s</string>' % item)
- mac_text.append('</array>')
- self.AddText(mac, '\n'.join(mac_text))
-
- def _AddListExampleWindows(self, parent, policy):
- '''Adds an example value for Windows of a 'list' policy to a DOM node.
-
- Args:
- parent: The DOM node for which the example will be added.
- policy: A policy of type 'list', for which the Windows example value
- is generated.
- '''
- example_value = policy['example_value']
- self.AddElement(parent, 'dt', {}, 'Windows:')
- win = self._AddStyledElement(parent, 'dd', ['.monospace', '.pre'])
- win_text = []
- cnt = 1
- for item in example_value:
- win_text.append(
- '%s\\%s\\%d = "%s"' %
- (self.config['win_reg_key_name'], policy['name'], cnt, item))
- cnt = cnt + 1
- self.AddText(win, '\n'.join(win_text))
-
- def _AddListExampleLinux(self, parent, policy):
- '''Adds an example value for Linux of a 'list' policy to a DOM node.
-
- Args:
- parent: The DOM node for which the example will be added.
- policy: A policy of type 'list', for which the Linux example value
- is generated.
- '''
- example_value = policy['example_value']
- self.AddElement(parent, 'dt', {}, 'Linux:')
- linux = self._AddStyledElement(parent, 'dd', ['.monospace'])
- linux_text = []
- for item in example_value:
- linux_text.append('"%s"' % item)
- self.AddText(linux, '[%s]' % ', '.join(linux_text))
-
-
- def _AddListExample(self, parent, policy):
- '''Adds the example value of a 'list' policy to a DOM node. Example output:
- <dl>
- <dt>Windows:</dt>
- <dd>
- Software\Policies\Chromium\DisabledPlugins\0 = "Java"
- Software\Policies\Chromium\DisabledPlugins\1 = "Shockwave Flash"
- </dd>
- <dt>Linux:</dt>
- <dd>["Java", "Shockwave Flash"]</dd>
- <dt>Mac:</dt>
- <dd>
- <array>
- <string>Java</string>
- <string>Shockwave Flash</string>
- </array>
- </dd>
- </dl>
-
- Args:
- parent: The DOM node for which the example will be added.
- policy: The data structure of a policy.
- '''
- example_value = policy['example_value']
- examples = self._AddStyledElement(parent, 'dl', ['dd dl'])
- self._AddListExampleWindows(examples, policy)
- self._AddListExampleLinux(examples, policy)
- self._AddListExampleMac(examples, policy)
-
- def _AddExample(self, parent, policy):
- '''Adds the HTML DOM representation of the example value of a policy to
- a DOM node. It is simple text for boolean policies, like
- '0x00000001 (Windows), true (Linux), <true /> (Mac)' in case of boolean
- policies, but it may also contain other HTML elements. (See method
- _AddListExample.)
-
- Args:
- parent: The DOM node for which the example will be added.
- policy: The data structure of a policy.
-
- Raises:
- Exception: If the type of the policy is unknown or the example value
- of the policy is out of its expected range.
- '''
- example_value = policy['example_value']
- policy_type = policy['type']
- if policy_type == 'main':
- if example_value == True:
- self.AddText(
- parent, '0x00000001 (Windows), true (Linux), <true /> (Mac)')
- elif example_value == False:
- self.AddText(
- parent, '0x00000000 (Windows), false (Linux), <false /> (Mac)')
- else:
- raise Exception('Expected boolean value.')
- elif policy_type == 'string':
- self.AddText(parent, '"%s"' % example_value)
- elif policy_type in ('int', 'int-enum'):
- self.AddText(
- parent,
- '0x%08x (Windows), %d (Linux/Mac)' % (example_value, example_value))
- elif policy_type == 'string-enum':
- self.AddText(parent, '"%s"' % (example_value))
- elif policy_type == 'list':
- self._AddListExample(parent, policy)
- else:
- raise Exception('Unknown policy type: ' + policy_type)
-
- def _AddPolicyAttribute(self, dl, term_id,
- definition=None, definition_style=None):
- '''Adds a term-definition pair to a HTML DOM <dl> node. This method is
- used by _AddPolicyDetails. Its result will have the form of:
- <dt style="...">...</dt>
- <dd style="...">...</dd>
-
- Args:
- dl: The DOM node of the <dl> list.
- term_id: A key to self._STRINGS[] which specifies the term of the pair.
- definition: The text of the definition. (Optional.)
- definition_style: List of references to values self._STYLE[] that specify
- the CSS stylesheet of the <dd> (definition) element.
-
- Returns:
- The DOM node representing the definition <dd> element.
- '''
- # Avoid modifying the default value of definition_style.
- if definition_style == None:
- definition_style = []
- term = self._GetLocalizedMessage(term_id)
- self._AddStyledElement(dl, 'dt', ['dt'], {}, term)
- return self._AddStyledElement(dl, 'dd', definition_style, {}, definition)
-
- def _AddSupportedOnList(self, parent, supported_on_list):
- '''Creates a HTML list containing the platforms, products and versions
- that are specified in the list of supported_on.
-
- Args:
- parent: The DOM node for which the list will be added.
- supported_on_list: The list of supported products, as a list of
- dictionaries.
- '''
- ul = self._AddStyledElement(parent, 'ul', ['ul'])
- for supported_on in supported_on_list:
- text = []
- product = supported_on['product']
- platforms = supported_on['platforms']
- text.append(self._PRODUCT_MAP[product])
- text.append('(%s)' %
- self._MapListToString(self._PLATFORM_MAP, platforms))
- if supported_on['since_version']:
- since_version = self._GetLocalizedMessage('since_version')
- text.append(since_version.replace('$6', supported_on['since_version']))
- if supported_on['until_version']:
- until_version = self._GetLocalizedMessage('until_version')
- text.append(until_version.replace('$6', supported_on['until_version']))
- # Add the list element:
- self.AddElement(ul, 'li', {}, ' '.join(text))
-
- def _AddPolicyDetails(self, parent, policy):
- '''Adds the list of attributes of a policy to the HTML DOM node parent.
- It will have the form:
- <dl>
- <dt>Attribute:</dt><dd>Description</dd>
- ...
- </dl>
-
- Args:
- parent: A DOM element for which the list will be added.
- policy: The data structure of the policy.
- '''
-
- dl = self.AddElement(parent, 'dl')
- self._AddPolicyAttribute(
- dl,
- 'data_type',
- self._TYPE_MAP[policy['type']])
- self._AddPolicyAttribute(
- dl,
- 'win_reg_loc',
- self.config['win_reg_key_name'] + '\\' + policy['name'],
- ['.monospace'])
- self._AddPolicyAttribute(
- dl,
- 'mac_linux_pref_name',
- policy['name'],
- ['.monospace'])
- dd = self._AddPolicyAttribute(dl, 'supported_on')
- self._AddSupportedOnList(dd, policy['supported_on'])
- dd = self._AddPolicyAttribute(dl, 'supported_features')
- self._AddFeatures(dd, policy)
- dd = self._AddPolicyAttribute(dl, 'description')
- self._AddDescription(dd, policy)
- dd = self._AddPolicyAttribute(dl, 'example_value')
- self._AddExample(dd, policy)
-
- def _AddPolicyNote(self, parent, policy):
- '''If a policy has an additional web page assigned with it, then add
- a link for that page.
-
- Args:
- policy: The data structure of the policy.
- '''
- if 'problem_href' not in policy:
- return
- problem_href = policy['problem_href']
- div = self._AddStyledElement(parent, 'div', ['div.note'])
- note = self._GetLocalizedMessage('note').replace('$6', problem_href)
- self._AddTextWithLinks(div, note)
-
- def _AddPolicyRow(self, parent, policy):
- '''Adds a row for the policy in the summary table.
-
- Args:
- parent: The DOM node of the summary table.
- policy: The data structure of the policy.
- '''
- tr = self._AddStyledElement(parent, 'tr', ['tr'])
- indent = 'padding-left: %dpx;' % (7 + self._indent_level * 14)
- if policy['type'] != 'group':
- # Normal policies get two columns with name and caption.
- name_td = self._AddStyledElement(tr, 'td', ['td', 'td.left'],
- {'style': indent})
- self.AddElement(name_td, 'a',
- {'href': '#' + policy['name']}, policy['name'])
- self._AddStyledElement(tr, 'td', ['td', 'td.right'], {},
- policy['caption'])
- else:
- # Groups get one column with caption.
- name_td = self._AddStyledElement(tr, 'td', ['td', 'td.left'],
- {'style': indent, 'colspan': '2'})
- self.AddElement(name_td, 'a', {'href': '#' + policy['name']},
- policy['caption'])
-
- def _AddPolicySection(self, parent, policy):
- '''Adds a section about the policy in the detailed policy listing.
-
- Args:
- parent: The DOM node of the <div> of the detailed policy list.
- policy: The data structure of the policy.
- '''
- # Set style according to group nesting level.
- indent = 'margin-left: %dpx' % (self._indent_level * 28)
- if policy['type'] == 'group':
- heading = 'h2'
- else:
- heading = 'h3'
- parent2 = self.AddElement(parent, 'div', {'style': indent})
-
- h2 = self.AddElement(parent2, heading)
- self.AddElement(h2, 'a', {'name': policy['name']})
- if policy['type'] != 'group':
- # Normal policies get a full description.
- policy_name_text = policy['name']
- if 'deprecated' in policy and policy['deprecated'] == True:
- policy_name_text += " ("
- policy_name_text += self._GetLocalizedMessage('deprecated') + ")"
- self.AddText(h2, policy_name_text)
- self.AddElement(parent2, 'span', {}, policy['caption'])
- self._AddPolicyNote(parent2, policy)
- self._AddPolicyDetails(parent2, policy)
- else:
- # Groups get a more compact description.
- self.AddText(h2, policy['caption'])
- self._AddStyledElement(parent2, 'div', ['div.group_desc'],
- {}, policy['desc'])
- self.AddElement(
- parent2, 'a', {'href': '#top'},
- self._GetLocalizedMessage('back_to_top'))
-
- #
- # Implementation of abstract methods of TemplateWriter:
- #
-
- def IsDeprecatedPolicySupported(self, policy):
- return True
-
- def WritePolicy(self, policy):
- self._AddPolicyRow(self._summary_tbody, policy)
- self._AddPolicySection(self._details_div, policy)
-
- def BeginPolicyGroup(self, group):
- self.WritePolicy(group)
- self._indent_level += 1
-
- def EndPolicyGroup(self):
- self._indent_level -= 1
-
- def BeginTemplate(self):
- # Add a <div> for the summary section.
- summary_div = self.AddElement(self._main_div, 'div')
- self.AddElement(summary_div, 'a', {'name': 'top'})
- self.AddElement(summary_div, 'br')
- self._AddTextWithLinks(
- summary_div,
- self._GetLocalizedMessage('intro'))
- self.AddElement(summary_div, 'br')
- self.AddElement(summary_div, 'br')
- self.AddElement(summary_div, 'br')
- # Add the summary table of policies.
- summary_table = self._AddStyledElement(summary_div, 'table', ['table'])
- # Add the first row.
- thead = self.AddElement(summary_table, 'thead')
- tr = self._AddStyledElement(thead, 'tr', ['tr'])
- self._AddStyledElement(
- tr, 'td', ['td', 'td.left', 'thead td'], {},
- self._GetLocalizedMessage('name_column_title'))
- self._AddStyledElement(
- tr, 'td', ['td', 'td.right', 'thead td'], {},
- self._GetLocalizedMessage('description_column_title'))
- self._summary_tbody = self.AddElement(summary_table, 'tbody')
-
- # Add a <div> for the detailed policy listing.
- self._details_div = self.AddElement(self._main_div, 'div')
-
- def Init(self):
- dom_impl = minidom.getDOMImplementation('')
- self._doc = dom_impl.createDocument(None, 'html', None)
- body = self.AddElement(self._doc.documentElement, 'body')
- self._main_div = self.AddElement(body, 'div')
- self._indent_level = 0
-
- # Human-readable names of supported platforms.
- self._PLATFORM_MAP = {
- 'win': 'Windows',
- 'mac': 'Mac',
- 'linux': 'Linux',
- 'chrome_os': self.config['os_name'],
- }
- # Human-readable names of supported products.
- self._PRODUCT_MAP = {
- 'chrome': self.config['app_name'],
- 'chrome_frame': self.config['frame_name'],
- 'chrome_os': self.config['os_name'],
- }
- # Human-readable names of supported features.
- self._FEATURE_MAP = {
- 'dynamic_refresh': self._GetLocalizedMessage('feature_dynamic_refresh')
- }
- # Human-readable names of types.
- self._TYPE_MAP = {
- 'string': 'String (REG_SZ)',
- 'int': 'Integer (REG_DWORD)',
- 'main': 'Boolean (REG_DWORD)',
- 'int-enum': 'Integer (REG_DWORD)',
- 'string-enum': 'String (REG_SZ)',
- 'list': 'List of strings',
- }
- # The CSS style-sheet used for the document. It will be used in Google
- # Sites, which strips class attributes from HTML tags. To work around this,
- # the style-sheet is a dictionary and the style attributes will be added
- # "by hand" for each element.
- self._STYLE = {
- 'table': 'border-style: none; border-collapse: collapse;',
- 'tr': 'height: 0px;',
- 'td': 'border: 1px dotted rgb(170, 170, 170); padding: 7px; '
- 'vertical-align: top; width: 236px; height: 15px;',
- 'thead td': 'font-weight: bold;',
- 'td.left': 'width: 200px;',
- 'td.right': 'width: 100%;',
- 'dt': 'font-weight: bold;',
- 'dd dl': 'margin-top: 0px; margin-bottom: 0px;',
- '.monospace': 'font-family: monospace;',
- '.pre': 'white-space: pre;',
- 'div.note': 'border: 2px solid black; padding: 5px; margin: 5px;',
- 'div.group_desc': 'margin-top: 20px; margin-bottom: 20px;',
- 'ul': 'padding-left: 0px; margin-left: 0px;'
- }
-
- # A simple regexp to search for URLs. It is enough for now.
- self._url_matcher = re.compile('(http://[^\\s]*[^\\s\\.])')
-
- def GetTemplateText(self):
- # Return the text representation of the main <div> tag.
- return self._main_div.toxml()
- # To get a complete HTML file, use the following.
- # return self._doc.toxml()
diff --git a/tools/grit/grit/format/policy_templates/writers/doc_writer_unittest.py b/tools/grit/grit/format/policy_templates/writers/doc_writer_unittest.py
deleted file mode 100644
index 6186500..0000000
--- a/tools/grit/grit/format/policy_templates/writers/doc_writer_unittest.py
+++ /dev/null
@@ -1,475 +0,0 @@
-# Copyright (c) 2011 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.
-
-'''Unit tests for grit.format.policy_templates.writers.doc_writer'''
-
-
-import os
-import re
-import sys
-if __name__ == '__main__':
- sys.path.append(os.path.join(os.path.dirname(sys.argv[0]), '../../../..'))
-
-import tempfile
-import unittest
-import StringIO
-from xml.dom import minidom
-
-from grit.format import rc
-from grit.format.policy_templates.writers import writer_unittest_common
-from grit.format.policy_templates.writers import doc_writer
-from grit import grd_reader
-from grit import util
-from grit.tool import build
-
-class MockMessageDictionary:
- '''A mock dictionary passed to a writer as the dictionary of
- localized messages.
- '''
-
- # Dictionary of messages.
- msg_dict = {}
-
-class DocWriterUnittest(writer_unittest_common.WriterUnittestCommon):
- '''Unit tests for DocWriter.'''
-
- def setUp(self):
- # Create a writer for the tests.
- self.writer = doc_writer.GetWriter(
- config={
- 'app_name': 'Chrome',
- 'frame_name': 'Chrome Frame',
- 'os_name': 'Chrome OS',
- 'win_reg_key_name': 'MockKey',
- })
- self.writer.messages = {
- 'doc_back_to_top': {'text': '_test_back_to_top'},
- 'doc_data_type': {'text': '_test_data_type'},
- 'doc_description': {'text': '_test_description'},
- 'doc_description_column_title': {
- 'text': '_test_description_column_title'
- },
- 'doc_example_value': {'text': '_test_example_value'},
- 'doc_feature_dynamic_refresh': {'text': '_test_feature_dynamic_refresh'},
- 'doc_intro': {'text': '_test_intro'},
- 'doc_mac_linux_pref_name': {'text': '_test_mac_linux_pref_name'},
- 'doc_note': {'text': '_test_note'},
- 'doc_name_column_title': {'text': '_test_name_column_title'},
- 'doc_not_supported': {'text': '_test_not_supported'},
- 'doc_since_version': {'text': '_test_since_version'},
- 'doc_supported': {'text': '_test_supported'},
- 'doc_supported_features': {'text': '_test_supported_features'},
- 'doc_supported_on': {'text': '_test_supported_on'},
- 'doc_win_reg_loc': {'text': '_test_win_reg_loc'},
-
- 'doc_bla': {'text': '_test_bla'},
- }
- self.writer.Init()
-
- # It is not worth testing the exact content of style attributes.
- # Therefore we override them here with shorter texts.
- for key in self.writer._STYLE.keys():
- self.writer._STYLE[key] = 'style_%s;' % key
- # Add some more style attributes for additional testing.
- self.writer._STYLE['key1'] = 'style1;'
- self.writer._STYLE['key2'] = 'style2;'
-
- # Create a DOM document for the tests.
- dom_impl = minidom.getDOMImplementation('')
- self.doc = dom_impl.createDocument(None, 'root', None)
- self.doc_root = self.doc.documentElement
-
- def testSkeleton(self):
- # Test if DocWriter creates the skeleton of the document correctly.
- self.writer.BeginTemplate()
- self.assertEquals(
- self.writer._main_div.toxml(),
- '<div>'
- '<div>'
- '<a name="top"/><br/>_test_intro<br/><br/><br/>'
- '<table style="style_table;">'
- '<thead><tr style="style_tr;">'
- '<td style="style_td;style_td.left;style_thead td;">'
- '_test_name_column_title'
- '</td>'
- '<td style="style_td;style_td.right;style_thead td;">'
- '_test_description_column_title'
- '</td>'
- '</tr></thead>'
- '<tbody/>'
- '</table>'
- '</div>'
- '<div/>'
- '</div>')
-
- def testGetLocalizedMessage(self):
- # Test if localized messages are retrieved correctly.
- self.writer.messages = {
- 'doc_hello_world': {'text': 'hello, vilag!'}
- }
- self.assertEquals(
- self.writer._GetLocalizedMessage('hello_world'),
- 'hello, vilag!')
-
- def testMapListToString(self):
- # Test function DocWriter.MapListToString()
- self.assertEquals(
- self.writer._MapListToString({'a1': 'a2', 'b1': 'b2'}, ['a1', 'b1']),
- 'a2, b2')
- self.assertEquals(
- self.writer._MapListToString({'a1': 'a2', 'b1': 'b2'}, []),
- '')
- result = self.writer._MapListToString(
- {'a': '1', 'b': '2', 'c': '3', 'd': '4'}, ['b', 'd'])
- expected_result = '2, 4'
- self.assertEquals(
- result,
- expected_result)
-
- def testAddStyledElement(self):
- # Test function DocWriter.AddStyledElement()
-
- # Test the case of zero style.
- e1 = self.writer._AddStyledElement(
- self.doc_root, 'z', [], {'a': 'b'}, 'text')
- self.assertEquals(
- e1.toxml(),
- '<z a="b">text</z>')
-
- # Test the case of one style.
- e2 = self.writer._AddStyledElement(
- self.doc_root, 'z', ['key1'], {'a': 'b'}, 'text')
- self.assertEquals(
- e2.toxml(),
- '<z a="b" style="style1;">text</z>')
-
- # Test the case of two styles.
- e3 = self.writer._AddStyledElement(
- self.doc_root, 'z', ['key1', 'key2'], {'a': 'b'}, 'text')
- self.assertEquals(
- e3.toxml(),
- '<z a="b" style="style1;style2;">text</z>')
-
- def testAddDescriptionIntEnum(self):
- # Test if URLs are replaced and choices of 'int-enum' policies are listed
- # correctly.
- policy = {
- 'type': 'int-enum',
- 'items': [
- {'value': 0, 'caption': 'Disable foo'},
- {'value': 2, 'caption': 'Solve your problem'},
- {'value': 5, 'caption': 'Enable bar'},
- ],
- 'desc': '''This policy disables foo, except in case of bar.
-See http://policy-explanation.example.com for more details.
-'''
- }
- self.writer._AddDescription(self.doc_root, policy)
- self.assertEquals(
- self.doc_root.toxml(),
- '''<root>This policy disables foo, except in case of bar.
-See <a href="http://policy-explanation.example.com">http://policy-explanation.example.com</a> for more details.
-<ul><li>0 = Disable foo</li><li>2 = Solve your problem</li><li>5 = Enable bar</li></ul></root>''')
-
- def testAddDescriptionStringEnum(self):
- # Test if URLs are replaced and choices of 'int-enum' policies are listed
- # correctly.
- policy = {
- 'type': 'string-enum',
- 'items': [
- {'value': "one", 'caption': 'Disable foo'},
- {'value': "two", 'caption': 'Solve your problem'},
- {'value': "three", 'caption': 'Enable bar'},
- ],
- 'desc': '''This policy disables foo, except in case of bar.
-See http://policy-explanation.example.com for more details.
-'''
- }
- self.writer._AddDescription(self.doc_root, policy)
- self.assertEquals(
- self.doc_root.toxml(),
- '''<root>This policy disables foo, except in case of bar.
-See <a href="http://policy-explanation.example.com">http://policy-explanation.example.com</a> for more details.
-<ul><li>&quot;one&quot; = Disable foo</li><li>&quot;two&quot; = Solve your problem</li><li>&quot;three&quot; = Enable bar</li></ul></root>''')
-
- def testAddFeatures(self):
- # Test if the list of features of a policy is handled correctly.
- policy = {
- 'features': {'spaceship_docking': 0, 'dynamic_refresh': 1}
- }
- self.writer._FEATURE_MAP = {
- 'spaceship_docking': 'Spaceship Docking',
- 'dynamic_refresh': 'Dynamic Refresh'
- }
- self.writer._AddFeatures(self.doc_root, policy)
- self.assertEquals(
- self.doc_root.toxml(),
- '<root>'
- 'Dynamic Refresh: _test_supported, '
- 'Spaceship Docking: _test_not_supported'
- '</root>')
-
- def testAddListExample(self):
- policy = {
- 'name': 'PolicyName',
- 'example_value': ['Foo', 'Bar']
- }
- self.writer._AddListExample(self.doc_root, policy)
- self.assertEquals(
- self.doc_root.toxml(),
- '<root>'
- '<dl style="style_dd dl;">'
- '<dt>Windows:</dt>'
- '<dd style="style_.monospace;style_.pre;">'
- 'MockKey\\PolicyName\\1 = &quot;Foo&quot;\n'
- 'MockKey\\PolicyName\\2 = &quot;Bar&quot;'
- '</dd>'
- '<dt>Linux:</dt>'
- '<dd style="style_.monospace;">'
- '[&quot;Foo&quot;, &quot;Bar&quot;]'
- '</dd>'
- '<dt>Mac:</dt>'
- '<dd style="style_.monospace;style_.pre;">'
- '&lt;array&gt;\n'
- ' &lt;string&gt;Foo&lt;/string&gt;\n'
- ' &lt;string&gt;Bar&lt;/string&gt;\n'
- '&lt;/array&gt;'
- '</dd>'
- '</dl>'
- '</root>')
-
- def testBoolExample(self):
- # Test representation of boolean example values.
- policy = {
- 'name': 'PolicyName',
- 'type': 'main',
- 'example_value': True
- }
- e1 = self.writer.AddElement(self.doc_root, 'e1')
- self.writer._AddExample(e1, policy)
- self.assertEquals(
- e1.toxml(),
- '<e1>0x00000001 (Windows), true (Linux), &lt;true /&gt; (Mac)</e1>')
-
- policy = {
- 'name': 'PolicyName',
- 'type': 'main',
- 'example_value': False
- }
- e2 = self.writer.AddElement(self.doc_root, 'e2')
- self.writer._AddExample(e2, policy)
- self.assertEquals(
- e2.toxml(),
- '<e2>0x00000000 (Windows), false (Linux), &lt;false /&gt; (Mac)</e2>')
-
- def testIntEnumExample(self):
- # Test representation of 'int-enum' example values.
- policy = {
- 'name': 'PolicyName',
- 'type': 'int-enum',
- 'example_value': 16
- }
- self.writer._AddExample(self.doc_root, policy)
- self.assertEquals(
- self.doc_root.toxml(),
- '<root>0x00000010 (Windows), 16 (Linux/Mac)</root>')
-
- def testStringEnumExample(self):
- # Test representation of 'int-enum' example values.
- policy = {
- 'name': 'PolicyName',
- 'type': 'string-enum',
- 'example_value': "wacky"
- }
- self.writer._AddExample(self.doc_root, policy)
- self.assertEquals(
- self.doc_root.toxml(),
- '<root>&quot;wacky&quot;</root>')
-
- def testStringExample(self):
- # Test representation of 'string' example values.
- policy = {
- 'name': 'PolicyName',
- 'type': 'string',
- 'example_value': 'awesome-example'
- }
- self.writer._AddExample(self.doc_root, policy)
- self.assertEquals(
- self.doc_root.toxml(),
- '<root>&quot;awesome-example&quot;</root>')
-
- def testIntExample(self):
- # Test representation of 'int' example values.
- policy = {
- 'name': 'PolicyName',
- 'type': 'int',
- 'example_value': 26
- }
- self.writer._AddExample(self.doc_root, policy)
- self.assertEquals(
- self.doc_root.toxml(),
- '<root>0x0000001a (Windows), 26 (Linux/Mac)</root>')
-
- def testAddPolicyAttribute(self):
- # Test creating a policy attribute term-definition pair.
- self.writer._AddPolicyAttribute(
- self.doc_root, 'bla', 'hello, world', ['key1'])
- self.assertEquals(
- self.doc_root.toxml(),
- '<root>'
- '<dt style="style_dt;">_test_bla</dt>'
- '<dd style="style1;">hello, world</dd>'
- '</root>')
-
- def testAddPolicyDetails(self):
- # Test if the definition list (<dl>) of policy details is created correctly.
- policy = {
- 'type': 'main',
- 'name': 'TestPolicyName',
- 'caption': 'TestPolicyCaption',
- 'desc': 'TestPolicyDesc',
- 'supported_on': [{
- 'product': 'chrome',
- 'platforms': ['win'],
- 'since_version': '8',
- 'until_version': '',
- }],
- 'features': {'dynamic_refresh': 0},
- 'example_value': False
- }
- self.writer.messages['doc_since_version'] = {'text': '...$6...'}
- self.writer._AddPolicyDetails(self.doc_root, policy)
- self.assertEquals(
- self.doc_root.toxml(),
- '<root><dl>'
- '<dt style="style_dt;">_test_data_type</dt><dd>Boolean (REG_DWORD)</dd>'
- '<dt style="style_dt;">_test_win_reg_loc</dt>'
- '<dd style="style_.monospace;">MockKey\TestPolicyName</dd>'
- '<dt style="style_dt;">_test_mac_linux_pref_name</dt>'
- '<dd style="style_.monospace;">TestPolicyName</dd>'
- '<dt style="style_dt;">_test_supported_on</dt>'
- '<dd>'
- '<ul style="style_ul;">'
- '<li>Chrome (Windows) ...8...</li>'
- '</ul>'
- '</dd>'
- '<dt style="style_dt;">_test_supported_features</dt>'
- '<dd>_test_feature_dynamic_refresh: _test_not_supported</dd>'
- '<dt style="style_dt;">_test_description</dt><dd>TestPolicyDesc</dd>'
- '<dt style="style_dt;">_test_example_value</dt>'
- '<dd>0x00000000 (Windows), false (Linux), &lt;false /&gt; (Mac)</dd>'
- '</dl></root>')
-
- def testAddPolicyNote(self):
- # TODO(jkummerow): The functionality tested by this test is currently not
- # used for anything and will probably soon be removed.
- # Test if nodes are correctly added to policies.
- policy = {
- 'problem_href': 'http://www.example.com/5'
- }
- self.writer.messages['doc_note'] = {'text': '...$6...'}
- self.writer._AddPolicyNote(self.doc_root, policy)
- self.assertEquals(
- self.doc_root.toxml(),
- '<root><div style="style_div.note;">...'
- '<a href="http://www.example.com/5">http://www.example.com/5</a>'
- '...</div></root>')
-
- def testAddPolicyRow(self):
- # Test if policies are correctly added to the summary table.
- policy = {
- 'name': 'PolicyName',
- 'caption': 'PolicyCaption',
- 'type': 'string',
- }
- self.writer._indent_level = 3
- self.writer._AddPolicyRow(self.doc_root, policy)
- self.assertEquals(
- self.doc_root.toxml(),
- '<root><tr style="style_tr;">'
- '<td style="style_td;style_td.left;padding-left: 49px;">'
- '<a href="#PolicyName">PolicyName</a>'
- '</td>'
- '<td style="style_td;style_td.right;">PolicyCaption</td>'
- '</tr></root>')
- self.setUp()
- policy = {
- 'name': 'PolicyName',
- 'caption': 'PolicyCaption',
- 'type': 'group',
- }
- self.writer._indent_level = 2
- self.writer._AddPolicyRow(self.doc_root, policy)
- self.assertEquals(
- self.doc_root.toxml(),
- '<root><tr style="style_tr;">'
- '<td colspan="2" style="style_td;style_td.left;padding-left: 35px;">'
- '<a href="#PolicyName">PolicyCaption</a>'
- '</td>'
- '</tr></root>')
-
- def testAddPolicySection(self):
- # Test if policy details are correctly added to the document.
- policy = {
- 'name': 'PolicyName',
- 'caption': 'PolicyCaption',
- 'desc': 'PolicyDesc',
- 'type': 'string',
- 'supported_on': [{
- 'product': 'chrome',
- 'platforms': ['win'],
- 'since_version': '7',
- 'until_version': '',
- }],
- 'features': {'dynamic_refresh': 0},
- 'example_value': False
- }
- self.writer.messages['doc_since_version'] = {'text': '..$6..'}
- self.writer._AddPolicySection(self.doc_root, policy)
- self.assertEquals(
- self.doc_root.toxml(),
- '<root>'
- '<div style="margin-left: 0px">'
- '<h3><a name="PolicyName"/>PolicyName</h3>'
- '<span>PolicyCaption</span>'
- '<dl>'
- '<dt style="style_dt;">_test_data_type</dt>'
- '<dd>String (REG_SZ)</dd>'
- '<dt style="style_dt;">_test_win_reg_loc</dt>'
- '<dd style="style_.monospace;">MockKey\\PolicyName</dd>'
- '<dt style="style_dt;">_test_mac_linux_pref_name</dt>'
- '<dd style="style_.monospace;">PolicyName</dd>'
- '<dt style="style_dt;">_test_supported_on</dt>'
- '<dd>'
- '<ul style="style_ul;">'
- '<li>Chrome (Windows) ..7..</li>'
- '</ul>'
- '</dd>'
- '<dt style="style_dt;">_test_supported_features</dt>'
- '<dd>_test_feature_dynamic_refresh: _test_not_supported</dd>'
- '<dt style="style_dt;">_test_description</dt>'
- '<dd>PolicyDesc</dd>'
- '<dt style="style_dt;">_test_example_value</dt>'
- '<dd>&quot;False&quot;</dd>'
- '</dl>'
- '<a href="#top">_test_back_to_top</a>'
- '</div>'
- '</root>')
- # Test for groups.
- self.setUp()
- policy['type'] = 'group'
- self.writer._AddPolicySection(self.doc_root, policy)
- self.assertEquals(
- self.doc_root.toxml(),
- '<root>'
- '<div style="margin-left: 0px">'
- '<h2><a name="PolicyName"/>PolicyCaption</h2>'
- '<div style="style_div.group_desc;">PolicyDesc</div>'
- '<a href="#top">_test_back_to_top</a>'
- '</div>'
- '</root>')
-
-
-if __name__ == '__main__':
- unittest.main()
diff --git a/tools/grit/grit/format/policy_templates/writers/json_writer.py b/tools/grit/grit/format/policy_templates/writers/json_writer.py
deleted file mode 100644
index de7ec27..0000000
--- a/tools/grit/grit/format/policy_templates/writers/json_writer.py
+++ /dev/null
@@ -1,72 +0,0 @@
-# Copyright (c) 2011 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.
-
-
-from xml.dom import minidom
-from grit.format.policy_templates.writers import template_writer
-
-
-def GetWriter(config):
- '''Factory method for creating JsonWriter objects.
- See the constructor of TemplateWriter for description of
- arguments.
- '''
- return JsonWriter(['linux'], config)
-
-
-class JsonWriter(template_writer.TemplateWriter):
- '''Class for generating policy files in JSON format (for Linux). The
- generated files will define all the supported policies with example values
- set for them. This class is used by PolicyTemplateGenerator to write .json
- files.
- '''
-
- def PreprocessPolicies(self, policy_list):
- return self.FlattenGroupsAndSortPolicies(policy_list)
-
- def WritePolicy(self, policy):
- example_value = policy['example_value']
- if policy['type'] == 'string':
- example_value_str = '"' + example_value + '"'
- elif policy['type'] == 'int':
- example_value_str = str(example_value)
- elif policy['type'] == 'list':
- if example_value == []:
- example_value_str = '[]'
- else:
- example_value_str = '["%s"]' % '", "'.join(example_value)
- elif policy['type'] == 'main':
- if example_value == True:
- example_value_str = 'true'
- else:
- example_value_str = 'false'
- elif policy['type'] == 'string-enum':
- example_value_str = '"%s"' % example_value;
- elif policy['type'] == 'int-enum':
- example_value_str = str(example_value)
- else:
- raise Exception('unknown policy type %s:' % policy['type'])
-
- # Add comme to the end of the previous line.
- if not self._first_written:
- self._out[-1] += ','
-
- line = ' "%s": %s' % (policy['name'], example_value_str)
- self._out.append(line)
-
- self._first_written = False
-
- def BeginTemplate(self):
- self._out.append('{')
-
- def EndTemplate(self):
- self._out.append('}')
-
- def Init(self):
- self._out = []
- # The following boolean member is true until the first policy is written.
- self._first_written = True
-
- def GetTemplateText(self):
- return '\n'.join(self._out)
diff --git a/tools/grit/grit/format/policy_templates/writers/json_writer_unittest.py b/tools/grit/grit/format/policy_templates/writers/json_writer_unittest.py
deleted file mode 100644
index a3fc3a2..0000000
--- a/tools/grit/grit/format/policy_templates/writers/json_writer_unittest.py
+++ /dev/null
@@ -1,264 +0,0 @@
-#!/usr/bin/python2.4
-# Copyright (c) 2011 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.
-
-'''Unit tests for grit.format.policy_templates.writers.json_writer'''
-
-
-import os
-import sys
-if __name__ == '__main__':
- sys.path.append(os.path.join(os.path.dirname(sys.argv[0]), '../../../..'))
-
-import unittest
-
-from grit.format.policy_templates.writers import writer_unittest_common
-
-
-class JsonWriterUnittest(writer_unittest_common.WriterUnittestCommon):
- '''Unit tests for JsonWriter.'''
-
- def CompareOutputs(self, output, expected_output):
- '''Compares the output of the json_writer with its expected output.
-
- Args:
- output: The output of the json writer as returned by grit.
- expected_output: The expected output.
-
- Raises:
- AssertionError: if the two strings are not equivalent.
- '''
- self.assertEquals(
- output.strip(),
- expected_output.strip())
-
- def testEmpty(self):
- # Test the handling of an empty policy list.
- grd = self.PrepareTest(
- '{'
- ' "policy_definitions": [],'
- ' "placeholders": [],'
- ' "messages": {},'
- '}')
- output = self.GetOutput(grd, 'fr', {'_chromium': '1',}, 'json', 'en')
- expected_output = '{\n}'
- self.CompareOutputs(output, expected_output)
-
- def testMainPolicy(self):
- # Tests a policy group with a single policy of type 'main'.
- grd = self.PrepareTest(
- '{'
- ' "policy_definitions": ['
- ' {'
- ' "name": "MainPolicy",'
- ' "type": "main",'
- ' "caption": "",'
- ' "desc": "",'
- ' "supported_on": ["chrome.linux:8-"],'
- ' "example_value": True'
- ' },'
- ' ],'
- ' "placeholders": [],'
- ' "messages": {},'
- '}')
- output = self.GetOutput(grd, 'fr', {'_google_chrome' : '1'}, 'json', 'en')
- expected_output = (
- '{\n'
- ' "MainPolicy": true\n'
- '}')
- self.CompareOutputs(output, expected_output)
-
- def testStringPolicy(self):
- # Tests a policy group with a single policy of type 'string'.
- grd = self.PrepareTest(
- '{'
- ' "policy_definitions": ['
- ' {'
- ' "name": "StringPolicy",'
- ' "type": "string",'
- ' "caption": "",'
- ' "desc": "",'
- ' "supported_on": ["chrome.linux:8-"],'
- ' "example_value": "hello, world!"'
- ' },'
- ' ],'
- ' "placeholders": [],'
- ' "messages": {},'
- '}')
- output = self.GetOutput(grd, 'fr', {'_chromium' : '1'}, 'json', 'en')
- expected_output = (
- '{\n'
- ' "StringPolicy": "hello, world!"\n'
- '}')
- self.CompareOutputs(output, expected_output)
-
- def testIntPolicy(self):
- # Tests a policy group with a single policy of type 'string'.
- grd = self.PrepareTest(
- '{'
- ' "policy_definitions": ['
- ' {'
- ' "name": "IntPolicy",'
- ' "type": "int",'
- ' "caption": "",'
- ' "desc": "",'
- ' "supported_on": ["chrome.linux:8-"],'
- ' "example_value": 15'
- ' },'
- ' ],'
- ' "placeholders": [],'
- ' "messages": {},'
- '}')
- output = self.GetOutput(grd, 'fr', {'_chromium' : '1'}, 'json', 'en')
- expected_output = (
- '{\n'
- ' "IntPolicy": 15\n'
- '}')
- self.CompareOutputs(output, expected_output)
-
- def testIntEnumPolicy(self):
- # Tests a policy group with a single policy of type 'int-enum'.
- grd = self.PrepareTest(
- '{'
- ' "policy_definitions": ['
- ' {'
- ' "name": "EnumPolicy",'
- ' "type": "int-enum",'
- ' "caption": "",'
- ' "desc": "",'
- ' "items": ['
- ' {"name": "ProxyServerDisabled", "value": 0, "caption": ""},'
- ' {"name": "ProxyServerAutoDetect", "value": 1, "caption": ""},'
- ' ],'
- ' "supported_on": ["chrome.linux:8-"],'
- ' "example_value": 1'
- ' },'
- ' ],'
- ' "placeholders": [],'
- ' "messages": {},'
- '}')
- output = self.GetOutput(grd, 'fr', {'_google_chrome': '1'}, 'json', 'en')
- expected_output = (
- '{\n'
- ' "EnumPolicy": 1\n'
- '}')
- self.CompareOutputs(output, expected_output)
-
- def testStringEnumPolicy(self):
- # Tests a policy group with a single policy of type 'string-enum'.
- grd = self.PrepareTest(
- '{'
- ' "policy_definitions": ['
- ' {'
- ' "name": "EnumPolicy",'
- ' "type": "string-enum",'
- ' "caption": "",'
- ' "desc": "",'
- ' "items": ['
- ' {"name": "ProxyServerDisabled", "value": "one",'
- ' "caption": ""},'
- ' {"name": "ProxyServerAutoDetect", "value": "two",'
- ' "caption": ""},'
- ' ],'
- ' "supported_on": ["chrome.linux:8-"],'
- ' "example_value": "one"'
- ' },'
- ' ],'
- ' "placeholders": [],'
- ' "messages": {},'
- '}')
- output = self.GetOutput(grd, 'fr', {'_google_chrome': '1'}, 'json', 'en')
- expected_output = (
- '{\n'
- ' "EnumPolicy": "one"\n'
- '}')
- self.CompareOutputs(output, expected_output)
-
- def testListPolicy(self):
- # Tests a policy group with a single policy of type 'list'.
- grd = self.PrepareTest(
- '{'
- ' "policy_definitions": ['
- ' {'
- ' "name": "ListPolicy",'
- ' "type": "list",'
- ' "caption": "",'
- ' "desc": "",'
- ' "supported_on": ["chrome.linux:8-"],'
- ' "example_value": ["foo", "bar"]'
- ' },'
- ' ],'
- ' "placeholders": [],'
- ' "messages": {},'
- '}')
- output = self.GetOutput(grd, 'fr', {'_chromium' : '1'}, 'json', 'en')
- expected_output = (
- '{\n'
- ' "ListPolicy": ["foo", "bar"]\n'
- '}')
- self.CompareOutputs(output, expected_output)
-
- def testNonSupportedPolicy(self):
- # Tests a policy that is not supported on Linux, so it shouldn't
- # be included in the JSON file.
- grd = self.PrepareTest(
- '{'
- ' "policy_definitions": ['
- ' {'
- ' "name": "NonLinuxPolicy",'
- ' "type": "list",'
- ' "caption": "",'
- ' "desc": "",'
- ' "supported_on": ["chrome.mac:8-"],'
- ' "example_value": ["a"]'
- ' },'
- ' ],'
- ' "placeholders": [],'
- ' "messages": {},'
- '}')
- output = self.GetOutput(grd, 'fr', {'_chromium' : '1'}, 'json', 'en')
- expected_output = '{\n}'
- self.CompareOutputs(output, expected_output)
-
- def testPolicyGroup(self):
- # Tests a policy group that has more than one policies.
- grd = self.PrepareTest(
- '{'
- ' "policy_definitions": ['
- ' {'
- ' "name": "Group1",'
- ' "type": "group",'
- ' "caption": "",'
- ' "desc": "",'
- ' "policies": [{'
- ' "name": "Policy1",'
- ' "type": "list",'
- ' "caption": "",'
- ' "desc": "",'
- ' "supported_on": ["chrome.linux:8-"],'
- ' "example_value": ["a", "b"]'
- ' },{'
- ' "name": "Policy2",'
- ' "type": "string",'
- ' "caption": "",'
- ' "desc": "",'
- ' "supported_on": ["chrome.linux:8-"],'
- ' "example_value": "c"'
- ' }],'
- ' },'
- ' ],'
- ' "placeholders": [],'
- ' "messages": {},'
- '}')
- output = self.GetOutput(grd, 'fr', {'_chromium' : '1'}, 'json', 'en')
- expected_output = (
- '{\n'
- ' "Policy1": ["a", "b"],\n'
- ' "Policy2": "c"\n'
- '}')
- self.CompareOutputs(output, expected_output)
-
-
-if __name__ == '__main__':
- unittest.main()
diff --git a/tools/grit/grit/format/policy_templates/writers/mock_writer.py b/tools/grit/grit/format/policy_templates/writers/mock_writer.py
deleted file mode 100644
index f402d68..0000000
--- a/tools/grit/grit/format/policy_templates/writers/mock_writer.py
+++ /dev/null
@@ -1,29 +0,0 @@
-# Copyright (c) 2010 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.
-
-
-from template_writer import TemplateWriter
-
-
-class MockWriter(TemplateWriter):
- '''Helper class for unit tests in policy_template_generator_unittest.py
- '''
-
- def __init__(self):
- pass
-
- def WritePolicy(self, policy):
- pass
-
- def BeginTemplate(self):
- pass
-
- def GetTemplateText(self):
- pass
-
- def IsPolicySupported(self, policy):
- return True
-
- def Test(self):
- pass
diff --git a/tools/grit/grit/format/policy_templates/writers/plist_helper.py b/tools/grit/grit/format/policy_templates/writers/plist_helper.py
deleted file mode 100644
index 16a5803..0000000
--- a/tools/grit/grit/format/policy_templates/writers/plist_helper.py
+++ /dev/null
@@ -1,14 +0,0 @@
-# Copyright (c) 2010 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.
-
-
-'''Common functions for plist_writer and plist_strings_writer.
-'''
-
-
-def GetPlistFriendlyName(name):
- '''Transforms a string so that it will be suitable for use as
- a pfm_name in the plist manifest file.
- '''
- return name.replace(' ', '_') \ No newline at end of file
diff --git a/tools/grit/grit/format/policy_templates/writers/plist_strings_writer.py b/tools/grit/grit/format/policy_templates/writers/plist_strings_writer.py
deleted file mode 100644
index 082e9f8..0000000
--- a/tools/grit/grit/format/policy_templates/writers/plist_strings_writer.py
+++ /dev/null
@@ -1,72 +0,0 @@
-# Copyright (c) 2011 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.
-
-
-from grit.format.policy_templates.writers import plist_helper
-from grit.format.policy_templates.writers import template_writer
-
-
-def GetWriter(config):
- '''Factory method for creating PListStringsWriter objects.
- See the constructor of TemplateWriter for description of
- arguments.
- '''
- return PListStringsWriter(['mac'], config)
-
-
-class PListStringsWriter(template_writer.TemplateWriter):
- '''Outputs localized string table files for the Mac policy file.
- These files are named Localizable.strings and they are in the
- [lang].lproj subdirectories of the manifest bundle.
- '''
-
- def _AddToStringTable(self, item_name, caption, desc):
- '''Add a title and a description of an item to the string table.
-
- Args:
- item_name: The name of the item that will get the title and the
- description.
- title: The text of the title to add.
- desc: The text of the description to add.
- '''
- caption = caption.replace('"', '\\"')
- caption = caption.replace('\n', '\\n')
- desc = desc.replace('"', '\\"')
- desc = desc.replace('\n', '\\n')
- self._out.append('%s.pfm_title = \"%s\";' % (item_name, caption))
- self._out.append('%s.pfm_description = \"%s\";' % (item_name, desc))
-
- def PreprocessPolicies(self, policy_list):
- return self.FlattenGroupsAndSortPolicies(policy_list)
-
- def WritePolicy(self, policy):
- '''Add strings to the stringtable corresponding a given policy.
-
- Args:
- policy: The policy for which the strings will be added to the
- string table.
- '''
- desc = policy['desc']
- if policy['type'] in ('int-enum','string-enum'):
- # Append the captions of enum items to the description string.
- item_descs = []
- for item in policy['items']:
- item_descs.append(str(item['value']) + ' - ' + item['caption'])
- desc = '\n'.join(item_descs) + '\n' + desc
-
- self._AddToStringTable(policy['name'], policy['label'], desc)
-
- def BeginTemplate(self):
- app_name = plist_helper.GetPlistFriendlyName(self.config['app_name'])
- self._AddToStringTable(
- app_name,
- self.config['app_name'],
- self.messages['mac_chrome_preferences']['text'])
-
- def Init(self):
- # A buffer for the lines of the string table being generated.
- self._out = []
-
- def GetTemplateText(self):
- return '\n'.join(self._out)
diff --git a/tools/grit/grit/format/policy_templates/writers/plist_strings_writer_unittest.py b/tools/grit/grit/format/policy_templates/writers/plist_strings_writer_unittest.py
deleted file mode 100644
index 15db925..0000000
--- a/tools/grit/grit/format/policy_templates/writers/plist_strings_writer_unittest.py
+++ /dev/null
@@ -1,284 +0,0 @@
-#!/usr/bin/python2.4
-# Copyright (c) 2011 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.
-
-'''Unit tests for grit.format.policy_templates.writers.plist_strings_writer'''
-
-
-import os
-import sys
-if __name__ == '__main__':
- sys.path.append(os.path.join(os.path.dirname(sys.argv[0]), '../../../..'))
-
-import tempfile
-import unittest
-import StringIO
-
-from grit.format.policy_templates.writers import writer_unittest_common
-from grit import grd_reader
-from grit import util
-from grit.tool import build
-
-
-class PListStringsWriterUnittest(writer_unittest_common.WriterUnittestCommon):
- '''Unit tests for PListStringsWriter.'''
-
- def testEmpty(self):
- # Test PListStringsWriter in case of empty polices.
- grd = self.PrepareTest('''
- {
- 'policy_definitions': [],
- 'placeholders': [],
- 'messages': {
- 'mac_chrome_preferences': {
- 'text': '$1 preferen"ces',
- 'desc': 'blah'
- }
- }
- }''')
- output = self.GetOutput(
- grd,
- 'fr',
- {'_chromium': '1', 'mac_bundle_id': 'com.example.Test'},
- 'plist_strings',
- 'en')
- expected_output = (
- 'Chromium.pfm_title = "Chromium";\n'
- 'Chromium.pfm_description = "Chromium preferen\\"ces";')
- self.assertEquals(output.strip(), expected_output.strip())
-
- def testMainPolicy(self):
- # Tests a policy group with a single policy of type 'main'.
- grd = self.PrepareTest('''
- {
- 'policy_definitions': [
- {
- 'name': 'MainGroup',
- 'type': 'group',
- 'caption': 'Caption of main.',
- 'desc': 'Description of main.',
- 'policies': [{
- 'name': 'MainPolicy',
- 'type': 'main',
- 'supported_on': ['chrome.mac:8-'],
- 'caption': 'Caption of main policy.',
- 'desc': 'Description of main policy.',
- }],
- },
- ],
- 'placeholders': [],
- 'messages': {
- 'mac_chrome_preferences': {
- 'text': 'Preferences of $1',
- 'desc': 'blah'
- }
- }
- }''')
- output = self.GetOutput(
- grd,
- 'fr',
- {'_google_chrome' : '1', 'mac_bundle_id': 'com.example.Test'},
- 'plist_strings',
- 'en')
- expected_output = (
- 'Google_Chrome.pfm_title = "Google Chrome";\n'
- 'Google_Chrome.pfm_description = "Preferences of Google Chrome";\n'
- 'MainPolicy.pfm_title = "Caption of main policy.";\n'
- 'MainPolicy.pfm_description = "Description of main policy.";')
- self.assertEquals(output.strip(), expected_output.strip())
-
- def testStringPolicy(self):
- # Tests a policy group with a single policy of type 'string'. Also test
- # inheriting group description to policy description.
- grd = self.PrepareTest('''
- {
- 'policy_definitions': [
- {
- 'name': 'StringGroup',
- 'type': 'group',
- 'caption': 'Caption of group.',
- 'desc': """Description of group.
-With a newline.""",
- 'policies': [{
- 'name': 'StringPolicy',
- 'type': 'string',
- 'caption': 'Caption of policy.',
- 'desc': """Description of policy.
-With a newline.""",
- 'supported_on': ['chrome.mac:8-'],
- }],
- },
- ],
- 'placeholders': [],
- 'messages': {
- 'mac_chrome_preferences': {
- 'text': 'Preferences of $1',
- 'desc': 'blah'
- }
- }
- }''')
- output = self.GetOutput(
- grd,
- 'fr',
- {'_chromium' : '1', 'mac_bundle_id': 'com.example.Test'},
- 'plist_strings',
- 'en')
- expected_output = (
- 'Chromium.pfm_title = "Chromium";\n'
- 'Chromium.pfm_description = "Preferences of Chromium";\n'
- 'StringPolicy.pfm_title = "Caption of policy.";\n'
- 'StringPolicy.pfm_description = '
- '"Description of policy.\\nWith a newline.";')
- self.assertEquals(output.strip(), expected_output.strip())
-
- def testIntEnumPolicy(self):
- # Tests a policy group with a single policy of type 'int-enum'.
- grd = self.PrepareTest('''
- {
- 'policy_definitions': [
- {
- 'name': 'EnumGroup',
- 'type': 'group',
- 'desc': '',
- 'caption': '',
- 'policies': [{
- 'name': 'EnumPolicy',
- 'type': 'int-enum',
- 'desc': 'Description of policy.',
- 'caption': 'Caption of policy.',
- 'items': [
- {
- 'name': 'ProxyServerDisabled',
- 'value': 0,
- 'caption': 'Option1'
- },
- {
- 'name': 'ProxyServerAutoDetect',
- 'value': 1,
- 'caption': 'Option2'
- },
- ],
- 'supported_on': ['chrome.mac:8-'],
- }],
- },
- ],
- 'placeholders': [],
- 'messages': {
- 'mac_chrome_preferences': {
- 'text': '$1 preferences',
- 'desc': 'blah'
- }
- }
- }''')
- output = self.GetOutput(
- grd,
- 'fr',
- {'_google_chrome': '1', 'mac_bundle_id': 'com.example.Test2'},
- 'plist_strings',
- 'en')
- expected_output = (
- 'Google_Chrome.pfm_title = "Google Chrome";\n'
- 'Google_Chrome.pfm_description = "Google Chrome preferences";\n'
- 'EnumPolicy.pfm_title = "Caption of policy.";\n'
- 'EnumPolicy.pfm_description = '
- '"0 - Option1\\n1 - Option2\\nDescription of policy.";\n')
-
- self.assertEquals(output.strip(), expected_output.strip())
-
- def testStringEnumPolicy(self):
- # Tests a policy group with a single policy of type 'string-enum'.
- grd = self.PrepareTest('''
- {
- 'policy_definitions': [
- {
- 'name': 'EnumGroup',
- 'type': 'group',
- 'desc': '',
- 'caption': '',
- 'policies': [{
- 'name': 'EnumPolicy',
- 'type': 'string-enum',
- 'desc': 'Description of policy.',
- 'caption': 'Caption of policy.',
- 'items': [
- {
- 'name': 'ProxyServerDisabled',
- 'value': 'one',
- 'caption': 'Option1'
- },
- {
- 'name': 'ProxyServerAutoDetect',
- 'value': 'two',
- 'caption': 'Option2'
- },
- ],
- 'supported_on': ['chrome.mac:8-'],
- }],
- },
- ],
- 'placeholders': [],
- 'messages': {
- 'mac_chrome_preferences': {
- 'text': '$1 preferences',
- 'desc': 'blah'
- }
- }
- }''')
- output = self.GetOutput(
- grd,
- 'fr',
- {'_google_chrome': '1', 'mac_bundle_id': 'com.example.Test2'},
- 'plist_strings',
- 'en')
- expected_output = (
- 'Google_Chrome.pfm_title = "Google Chrome";\n'
- 'Google_Chrome.pfm_description = "Google Chrome preferences";\n'
- 'EnumPolicy.pfm_title = "Caption of policy.";\n'
- 'EnumPolicy.pfm_description = '
- '"one - Option1\\ntwo - Option2\\nDescription of policy.";\n')
-
- self.assertEquals(output.strip(), expected_output.strip())
-
- def testNonSupportedPolicy(self):
- # Tests a policy that is not supported on Mac, so its strings shouldn't
- # be included in the plist string table.
- grd = self.PrepareTest('''
- {
- 'policy_definitions': [
- {
- 'name': 'NonMacGroup',
- 'type': 'group',
- 'caption': '',
- 'desc': '',
- 'policies': [{
- 'name': 'NonMacPolicy',
- 'type': 'string',
- 'caption': '',
- 'desc': '',
- 'supported_on': ['chrome_os:8-'],
- }],
- },
- ],
- 'placeholders': [],
- 'messages': {
- 'mac_chrome_preferences': {
- 'text': '$1 preferences',
- 'desc': 'blah'
- }
- }
- }''')
- output = self.GetOutput(
- grd,
- 'fr',
- {'_google_chrome': '1', 'mac_bundle_id': 'com.example.Test2'},
- 'plist_strings',
- 'en')
- expected_output = (
- 'Google_Chrome.pfm_title = "Google Chrome";\n'
- 'Google_Chrome.pfm_description = "Google Chrome preferences";')
- self.assertEquals(output.strip(), expected_output.strip())
-
-
-if __name__ == '__main__':
- unittest.main()
diff --git a/tools/grit/grit/format/policy_templates/writers/plist_writer.py b/tools/grit/grit/format/policy_templates/writers/plist_writer.py
deleted file mode 100644
index 46ff0a4..0000000
--- a/tools/grit/grit/format/policy_templates/writers/plist_writer.py
+++ /dev/null
@@ -1,126 +0,0 @@
-# Copyright (c) 2011 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.
-
-
-from xml.dom import minidom
-from grit.format.policy_templates.writers import plist_helper
-from grit.format.policy_templates.writers import xml_formatted_writer
-
-
-def GetWriter(config):
- '''Factory method for creating PListWriter objects.
- See the constructor of TemplateWriter for description of
- arguments.
- '''
- return PListWriter(['mac'], config)
-
-
-class PListWriter(xml_formatted_writer.XMLFormattedWriter):
- '''Class for generating policy templates in Mac plist format.
- It is used by PolicyTemplateGenerator to write plist files.
- '''
-
- STRING_TABLE = 'Localizable.strings'
- TYPE_TO_INPUT = {
- 'string': 'string',
- 'int': 'integer',
- 'int-enum': 'integer',
- 'string-enum': 'string',
- 'main': 'boolean',
- 'list': 'array',
- }
-
- def _AddKeyValuePair(self, parent, key_string, value_tag):
- '''Adds a plist key-value pair to a parent XML element.
-
- A key-value pair in plist consists of two XML elements next two each other:
- <key>key_string</key>
- <value_tag>...</value_tag>
-
- Args:
- key_string: The content of the key tag.
- value_tag: The name of the value element.
-
- Returns:
- The XML element of the value tag.
- '''
- self.AddElement(parent, 'key', {}, key_string)
- return self.AddElement(parent, value_tag)
-
- def _AddStringKeyValuePair(self, parent, key_string, value_string):
- '''Adds a plist key-value pair to a parent XML element, where the
- value element contains a string. The name of the value element will be
- <string>.
-
- Args:
- key_string: The content of the key tag.
- value_string: The content of the value tag.
- '''
- self.AddElement(parent, 'key', {}, key_string)
- self.AddElement(parent, 'string', {}, value_string)
-
- def _AddTargets(self, parent):
- '''Adds the following XML snippet to an XML element:
- <key>pfm_targets</key>
- <array>
- <string>user-managed</string>
- </array>
-
- Args:
- parent: The parent XML element where the snippet will be added.
- '''
- array = self._AddKeyValuePair(parent, 'pfm_targets', 'array')
- self.AddElement(array, 'string', {}, 'user-managed')
-
- def PreprocessPolicies(self, policy_list):
- return self.FlattenGroupsAndSortPolicies(policy_list)
-
- def WritePolicy(self, policy):
- policy_name = policy['name']
- policy_type = policy['type']
-
- dict = self.AddElement(self._array, 'dict')
- self._AddStringKeyValuePair(dict, 'pfm_name', policy_name)
- # Set empty strings for title and description. They will be taken by the
- # OSX Workgroup Manager from the string table in a Localizable.strings file.
- # Those files are generated by plist_strings_writer.
- self._AddStringKeyValuePair(dict, 'pfm_description', '')
- self._AddStringKeyValuePair(dict, 'pfm_title', '')
- self._AddTargets(dict)
- self._AddStringKeyValuePair(dict, 'pfm_type',
- self.TYPE_TO_INPUT[policy_type])
- if policy_type in ('int-enum', 'string-enum'):
- range_list = self._AddKeyValuePair(dict, 'pfm_range_list', 'array')
- for item in policy['items']:
- if policy_type == 'int-enum':
- element_type = 'integer'
- else:
- element_type = 'string'
- self.AddElement(range_list, element_type, {}, str(item['value']))
-
- def BeginTemplate(self):
- self._plist.attributes['version'] = '1'
- dict = self.AddElement(self._plist, 'dict')
-
- app_name = plist_helper.GetPlistFriendlyName(self.config['app_name'])
- self._AddStringKeyValuePair(dict, 'pfm_name', app_name)
- self._AddStringKeyValuePair(dict, 'pfm_description', '')
- self._AddStringKeyValuePair(dict, 'pfm_title', '')
- self._AddStringKeyValuePair(dict, 'pfm_version', '1')
- self._AddStringKeyValuePair(dict, 'pfm_domain',
- self.config['mac_bundle_id'])
-
- self._array = self._AddKeyValuePair(dict, 'pfm_subkeys', 'array')
-
- def Init(self):
- dom_impl = minidom.getDOMImplementation('')
- doctype = dom_impl.createDocumentType(
- 'plist',
- '-//Apple//DTD PLIST 1.0//EN',
- 'http://www.apple.com/DTDs/PropertyList-1.0.dtd')
- self._doc = dom_impl.createDocument(None, 'plist', doctype)
- self._plist = self._doc.documentElement
-
- def GetTemplateText(self):
- return self.ToPrettyXml(self._doc)
diff --git a/tools/grit/grit/format/policy_templates/writers/plist_writer_unittest.py b/tools/grit/grit/format/policy_templates/writers/plist_writer_unittest.py
deleted file mode 100644
index 4f51f3c..0000000
--- a/tools/grit/grit/format/policy_templates/writers/plist_writer_unittest.py
+++ /dev/null
@@ -1,369 +0,0 @@
-# Copyright (c) 2011 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.
-
-'''Unit tests for grit.format.policy_templates.writers.plist_writer'''
-
-
-import os
-import re
-import sys
-if __name__ == '__main__':
- sys.path.append(os.path.join(os.path.dirname(sys.argv[0]), '../../../..'))
-
-import tempfile
-import unittest
-import StringIO
-from xml.dom import minidom
-
-from grit.format import rc
-from grit.format.policy_templates.writers import writer_unittest_common
-from grit import grd_reader
-from grit import util
-from grit.tool import build
-
-
-class PListWriterUnittest(writer_unittest_common.WriterUnittestCommon):
- '''Unit tests for PListWriter.'''
-
- def _GetExpectedOutputs(self, product_name, bundle_id, policies):
- '''Substitutes the variable parts into a plist template. The result
- of this function can be used as an expected result to test the output
- of PListWriter.
-
- Args:
- product_name: The name of the product, normally Chromium or Google Chrome.
- bundle_id: The mac bundle id of the product.
- policies: The list of policies.
-
- Returns:
- The text of a plist template with the variable parts substituted.
- '''
- return '''
-<?xml version="1.0" ?>
-<!DOCTYPE plist PUBLIC '-//Apple//DTD PLIST 1.0//EN' 'http://www.apple.com/DTDs/PropertyList-1.0.dtd'>
-<plist version="1">
- <dict>
- <key>pfm_name</key>
- <string>%s</string>
- <key>pfm_description</key>
- <string/>
- <key>pfm_title</key>
- <string/>
- <key>pfm_version</key>
- <string>1</string>
- <key>pfm_domain</key>
- <string>%s</string>
- <key>pfm_subkeys</key>
- %s
- </dict>
-</plist>''' % (product_name, bundle_id, policies)
-
- def testEmpty(self):
- # Test PListWriter in case of empty polices.
- grd = self.PrepareTest('''
- {
- 'policy_definitions': [],
- 'placeholders': [],
- 'messages': {},
- }''')
-
- output = self.GetOutput(
- grd,
- 'fr',
- {'_chromium': '1', 'mac_bundle_id': 'com.example.Test'},
- 'plist',
- 'en')
- expected_output = self._GetExpectedOutputs(
- 'Chromium', 'com.example.Test', '<array/>')
- self.assertEquals(output.strip(), expected_output.strip())
-
- def testMainPolicy(self):
- # Tests a policy group with a single policy of type 'main'.
- grd = self.PrepareTest('''
- {
- 'policy_definitions': [
- {
- 'name': 'MainGroup',
- 'type': 'group',
- 'policies': [{
- 'name': 'MainPolicy',
- 'type': 'main',
- 'desc': '',
- 'caption': '',
- 'supported_on': ['chrome.mac:8-'],
- }],
- 'desc': '',
- 'caption': '',
- },
- ],
- 'placeholders': [],
- 'messages': {}
- }''')
- output = self.GetOutput(
- grd,
- 'fr',
- {'_chromium' : '1', 'mac_bundle_id': 'com.example.Test'},
- 'plist',
- 'en')
- expected_output = self._GetExpectedOutputs(
- 'Chromium', 'com.example.Test', '''<array>
- <dict>
- <key>pfm_name</key>
- <string>MainPolicy</string>
- <key>pfm_description</key>
- <string/>
- <key>pfm_title</key>
- <string/>
- <key>pfm_targets</key>
- <array>
- <string>user-managed</string>
- </array>
- <key>pfm_type</key>
- <string>boolean</string>
- </dict>
- </array>''')
- self.assertEquals(output.strip(), expected_output.strip())
-
- def testStringPolicy(self):
- # Tests a policy group with a single policy of type 'string'.
- grd = self.PrepareTest('''
- {
- 'policy_definitions': [
- {
- 'name': 'StringGroup',
- 'type': 'group',
- 'desc': '',
- 'caption': '',
- 'policies': [{
- 'name': 'StringPolicy',
- 'type': 'string',
- 'supported_on': ['chrome.mac:8-'],
- 'desc': '',
- 'caption': '',
- }],
- },
- ],
- 'placeholders': [],
- 'messages': {},
- }''')
- output = self.GetOutput(
- grd,
- 'fr',
- {'_chromium' : '1', 'mac_bundle_id': 'com.example.Test'},
- 'plist',
- 'en')
- expected_output = self._GetExpectedOutputs(
- 'Chromium', 'com.example.Test', '''<array>
- <dict>
- <key>pfm_name</key>
- <string>StringPolicy</string>
- <key>pfm_description</key>
- <string/>
- <key>pfm_title</key>
- <string/>
- <key>pfm_targets</key>
- <array>
- <string>user-managed</string>
- </array>
- <key>pfm_type</key>
- <string>string</string>
- </dict>
- </array>''')
- self.assertEquals(output.strip(), expected_output.strip())
-
- def testIntPolicy(self):
- # Tests a policy group with a single policy of type 'int'.
- grd = self.PrepareTest('''
- {
- 'policy_definitions': [
- {
- 'name': 'IntGroup',
- 'type': 'group',
- 'caption': '',
- 'desc': '',
- 'policies': [{
- 'name': 'IntPolicy',
- 'type': 'int',
- 'caption': '',
- 'desc': '',
- 'supported_on': ['chrome.mac:8-'],
- }],
- },
- ],
- 'placeholders': [],
- 'messages': {},
- }''')
- output = self.GetOutput(
- grd,
- 'fr',
- {'_chromium' : '1', 'mac_bundle_id': 'com.example.Test'},
- 'plist',
- 'en')
- expected_output = self._GetExpectedOutputs(
- 'Chromium', 'com.example.Test', '''<array>
- <dict>
- <key>pfm_name</key>
- <string>IntPolicy</string>
- <key>pfm_description</key>
- <string/>
- <key>pfm_title</key>
- <string/>
- <key>pfm_targets</key>
- <array>
- <string>user-managed</string>
- </array>
- <key>pfm_type</key>
- <string>integer</string>
- </dict>
- </array>''')
- self.assertEquals(output.strip(), expected_output.strip())
-
- def testIntEnumPolicy(self):
- # Tests a policy group with a single policy of type 'int-enum'.
- grd = self.PrepareTest('''
- {
- 'policy_definitions': [
- {
- 'name': 'EnumGroup',
- 'type': 'group',
- 'caption': '',
- 'desc': '',
- 'policies': [{
- 'name': 'EnumPolicy',
- 'type': 'int-enum',
- 'desc': '',
- 'caption': '',
- 'items': [
- {'name': 'ProxyServerDisabled', 'value': 0, 'caption': ''},
- {'name': 'ProxyServerAutoDetect', 'value': 1, 'caption': ''},
- ],
- 'supported_on': ['chrome.mac:8-'],
- }],
- },
- ],
- 'placeholders': [],
- 'messages': {},
- }''')
- output = self.GetOutput(
- grd,
- 'fr',
- {'_google_chrome': '1', 'mac_bundle_id': 'com.example.Test2'},
- 'plist',
- 'en')
- expected_output = self._GetExpectedOutputs(
- 'Google_Chrome', 'com.example.Test2', '''<array>
- <dict>
- <key>pfm_name</key>
- <string>EnumPolicy</string>
- <key>pfm_description</key>
- <string/>
- <key>pfm_title</key>
- <string/>
- <key>pfm_targets</key>
- <array>
- <string>user-managed</string>
- </array>
- <key>pfm_type</key>
- <string>integer</string>
- <key>pfm_range_list</key>
- <array>
- <integer>0</integer>
- <integer>1</integer>
- </array>
- </dict>
- </array>''')
- self.assertEquals(output.strip(), expected_output.strip())
-
- def testStringEnumPolicy(self):
- # Tests a policy group with a single policy of type 'string-enum'.
- grd = self.PrepareTest('''
- {
- 'policy_definitions': [
- {
- 'name': 'EnumGroup',
- 'type': 'group',
- 'caption': '',
- 'desc': '',
- 'policies': [{
- 'name': 'EnumPolicy',
- 'type': 'string-enum',
- 'desc': '',
- 'caption': '',
- 'items': [
- {'name': 'ProxyServerDisabled', 'value': 'one', 'caption': ''},
- {'name': 'ProxyServerAutoDetect', 'value': 'two', 'caption': ''},
- ],
- 'supported_on': ['chrome.mac:8-'],
- }],
- },
- ],
- 'placeholders': [],
- 'messages': {},
- }''')
- output = self.GetOutput(
- grd,
- 'fr',
- {'_google_chrome': '1', 'mac_bundle_id': 'com.example.Test2'},
- 'plist',
- 'en')
- expected_output = self._GetExpectedOutputs(
- 'Google_Chrome', 'com.example.Test2', '''<array>
- <dict>
- <key>pfm_name</key>
- <string>EnumPolicy</string>
- <key>pfm_description</key>
- <string/>
- <key>pfm_title</key>
- <string/>
- <key>pfm_targets</key>
- <array>
- <string>user-managed</string>
- </array>
- <key>pfm_type</key>
- <string>string</string>
- <key>pfm_range_list</key>
- <array>
- <string>one</string>
- <string>two</string>
- </array>
- </dict>
- </array>''')
- self.assertEquals(output.strip(), expected_output.strip())
-
- def testNonSupportedPolicy(self):
- # Tests a policy that is not supported on Mac, so it shouldn't
- # be included in the plist file.
- grd = self.PrepareTest('''
- {
- 'policy_definitions': [
- {
- 'name': 'NonMacGroup',
- 'type': 'group',
- 'caption': '',
- 'desc': '',
- 'policies': [{
- 'name': 'NonMacPolicy',
- 'type': 'string',
- 'supported_on': ['chrome.linux:8-', 'chrome.win:7-'],
- 'caption': '',
- 'desc': '',
- }],
- },
- ],
- 'placeholders': [],
- 'messages': {},
- }''')
- output = self.GetOutput(
- grd,
- 'fr',
- {'_google_chrome': '1', 'mac_bundle_id': 'com.example.Test2'},
- 'plist',
- 'en')
- expected_output = self._GetExpectedOutputs(
- 'Google_Chrome', 'com.example.Test2', '''<array/>''')
- self.assertEquals(output.strip(), expected_output.strip())
-
-
-if __name__ == '__main__':
- unittest.main()
diff --git a/tools/grit/grit/format/policy_templates/writers/reg_writer.py b/tools/grit/grit/format/policy_templates/writers/reg_writer.py
deleted file mode 100644
index dc6a08d..0000000
--- a/tools/grit/grit/format/policy_templates/writers/reg_writer.py
+++ /dev/null
@@ -1,92 +0,0 @@
-# Copyright (c) 2011 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.
-
-
-from xml.dom import minidom
-from grit.format.policy_templates.writers import template_writer
-
-
-def GetWriter(config):
- '''Factory method for creating RegWriter objects.
- See the constructor of TemplateWriter for description of
- arguments.
- '''
- return RegWriter(['win'], config)
-
-
-class RegWriter(template_writer.TemplateWriter):
- '''Class for generating policy example files in .reg format (for Windows).
- The generated files will define all the supported policies with example
- values set for them. This class is used by PolicyTemplateGenerator to
- write .reg files.
- '''
-
- NEWLINE = '\r\n'
-
- def _EscapeRegString(self, string):
- return string.replace('\\', '\\\\').replace('\"', '\\\"')
-
- def _StartBlock(self, suffix):
- key = 'HKEY_LOCAL_MACHINE\\' + self.config['win_reg_key_name']
- if suffix:
- key = key + '\\' + suffix
- if key != self._last_key:
- self._out.append('')
- self._out.append('[%s]' % key)
- self._last_key = key
-
- def PreprocessPolicies(self, policy_list):
- return self.FlattenGroupsAndSortPolicies(policy_list,
- self.GetPolicySortingKey)
-
- def GetPolicySortingKey(self, policy):
- '''Extracts a sorting key from a policy. These keys can be used for
- list.sort() methods to sort policies.
- See TemplateWriter.SortPoliciesGroupsFirst for usage.
- '''
- is_list = policy['type'] == 'list'
- # Lists come after regular policies.
- return (is_list, policy['name'])
-
- def WritePolicy(self, policy):
- example_value = policy['example_value']
-
- if policy['type'] == 'list':
- self._StartBlock(policy['name'])
- i = 1
- for item in example_value:
- escaped_str = self._EscapeRegString(item)
- self._out.append('"%d"="%s"' % (i, escaped_str))
- i = i + 1
- else:
- self._StartBlock(None)
- if policy['type'] == 'string':
- escaped_str = self._EscapeRegString(example_value)
- example_value_str = '"' + escaped_str + '"'
- elif policy['type'] == 'main':
- if example_value == True:
- example_value_str = 'dword:00000001'
- else:
- example_value_str = 'dword:00000000'
- elif policy['type'] in ('int', 'int-enum'):
- example_value_str = 'dword:%08x' % example_value
- elif policy['type'] == 'string-enum':
- example_value_str = '"%s"' % example_value
- else:
- raise Exception('unknown policy type %s:' % policy['type'])
-
- self._out.append('"%s"=%s' % (policy['name'], example_value_str))
-
- def BeginTemplate(self):
- pass
-
- def EndTemplate(self):
- pass
-
- def Init(self):
- self._out = ['Windows Registry Editor Version 5.00']
- self._last_key = None
-
- def GetTemplateText(self):
- return self.NEWLINE.join(self._out)
diff --git a/tools/grit/grit/format/policy_templates/writers/reg_writer_unittest.py b/tools/grit/grit/format/policy_templates/writers/reg_writer_unittest.py
deleted file mode 100644
index 58e8226..0000000
--- a/tools/grit/grit/format/policy_templates/writers/reg_writer_unittest.py
+++ /dev/null
@@ -1,278 +0,0 @@
-#!/usr/bin/python2.6
-# Copyright (c) 2011 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.
-
-
-'''Unit tests for grit.format.policy_templates.writers.reg_writer'''
-
-
-import os
-import sys
-if __name__ == '__main__':
- sys.path.append(os.path.join(os.path.dirname(sys.argv[0]), '../../../..'))
-
-import unittest
-
-from grit.format.policy_templates.writers import writer_unittest_common
-
-
-class RegWriterUnittest(writer_unittest_common.WriterUnittestCommon):
- '''Unit tests for RegWriter.'''
-
- NEWLINE = '\r\n'
-
- def CompareOutputs(self, output, expected_output):
- '''Compares the output of the reg_writer with its expected output.
-
- Args:
- output: The output of the reg writer as returned by grit.
- expected_output: The expected output.
-
- Raises:
- AssertionError: if the two strings are not equivalent.
- '''
- self.assertEquals(
- output.strip(),
- expected_output.strip())
-
- def testEmpty(self):
- # Test the handling of an empty policy list.
- grd = self.PrepareTest(
- '{'
- ' "policy_definitions": [],'
- ' "placeholders": [],'
- ' "messages": {}'
- '}')
- output = self.GetOutput(grd, 'fr', {'_chromium': '1', }, 'reg', 'en')
- expected_output = 'Windows Registry Editor Version 5.00'
- self.CompareOutputs(output, expected_output)
-
- def testMainPolicy(self):
- # Tests a policy group with a single policy of type 'main'.
- grd = self.PrepareTest(
- '{'
- ' "policy_definitions": ['
- ' {'
- ' "name": "MainPolicy",'
- ' "type": "main",'
- ' "caption": "",'
- ' "desc": "",'
- ' "supported_on": ["chrome.win:8-"],'
- ' "example_value": True'
- ' },'
- ' ],'
- ' "placeholders": [],'
- ' "messages": {},'
- '}')
- output = self.GetOutput(grd, 'fr', {'_google_chrome' : '1'}, 'reg', 'en')
- expected_output = self.NEWLINE.join([
- 'Windows Registry Editor Version 5.00',
- '',
- '[HKEY_LOCAL_MACHINE\\Software\\Policies\\Google\\Chrome]',
- '"MainPolicy"=dword:00000001'])
- self.CompareOutputs(output, expected_output)
-
- def testStringPolicy(self):
- # Tests a policy group with a single policy of type 'string'.
- grd = self.PrepareTest(
- '{'
- ' "policy_definitions": ['
- ' {'
- ' "name": "StringPolicy",'
- ' "type": "string",'
- ' "caption": "",'
- ' "desc": "",'
- ' "supported_on": ["chrome.win:8-"],'
- ' "example_value": "hello, world! \\\" \\\\"'
- ' },'
- ' ],'
- ' "placeholders": [],'
- ' "messages": {},'
- '}')
- output = self.GetOutput(grd, 'fr', {'_chromium' : '1'}, 'reg', 'en')
- expected_output = self.NEWLINE.join([
- 'Windows Registry Editor Version 5.00',
- '',
- '[HKEY_LOCAL_MACHINE\\Software\\Policies\\Chromium]',
- '"StringPolicy"="hello, world! \\\" \\\\"'])
- self.CompareOutputs(output, expected_output)
-
- def testIntPolicy(self):
- # Tests a policy group with a single policy of type 'int'.
- grd = self.PrepareTest(
- '{'
- ' "policy_definitions": ['
- ' {'
- ' "name": "IntPolicy",'
- ' "type": "int",'
- ' "caption": "",'
- ' "desc": "",'
- ' "supported_on": ["chrome.win:8-"],'
- ' "example_value": 26'
- ' },'
- ' ],'
- ' "placeholders": [],'
- ' "messages": {},'
- '}')
- output = self.GetOutput(grd, 'fr', {'_chromium' : '1'}, 'reg', 'en')
- expected_output = self.NEWLINE.join([
- 'Windows Registry Editor Version 5.00',
- '',
- '[HKEY_LOCAL_MACHINE\\Software\\Policies\\Chromium]',
- '"IntPolicy"=dword:0000001a'])
- self.CompareOutputs(output, expected_output)
-
- def testIntEnumPolicy(self):
- # Tests a policy group with a single policy of type 'int-enum'.
- grd = self.PrepareTest(
- '{'
- ' "policy_definitions": ['
- ' {'
- ' "name": "EnumPolicy",'
- ' "type": "int-enum",'
- ' "caption": "",'
- ' "desc": "",'
- ' "items": ['
- ' {"name": "ProxyServerDisabled", "value": 0, "caption": ""},'
- ' {"name": "ProxyServerAutoDetect", "value": 1, "caption": ""},'
- ' ],'
- ' "supported_on": ["chrome.win:8-"],'
- ' "example_value": 1'
- ' },'
- ' ],'
- ' "placeholders": [],'
- ' "messages": {},'
- '}')
- output = self.GetOutput(grd, 'fr', {'_google_chrome': '1'}, 'reg', 'en')
- expected_output = self.NEWLINE.join([
- 'Windows Registry Editor Version 5.00',
- '',
- '[HKEY_LOCAL_MACHINE\\Software\\Policies\\Google\\Chrome]',
- '"EnumPolicy"=dword:00000001'])
- self.CompareOutputs(output, expected_output)
-
- def testStringEnumPolicy(self):
- # Tests a policy group with a single policy of type 'string-enum'.
- grd = self.PrepareTest(
- '{'
- ' "policy_definitions": ['
- ' {'
- ' "name": "EnumPolicy",'
- ' "type": "string-enum",'
- ' "caption": "",'
- ' "desc": "",'
- ' "items": ['
- ' {"name": "ProxyServerDisabled", "value": "one",'
- ' "caption": ""},'
- ' {"name": "ProxyServerAutoDetect", "value": "two",'
- ' "caption": ""},'
- ' ],'
- ' "supported_on": ["chrome.win:8-"],'
- ' "example_value": "two"'
- ' },'
- ' ],'
- ' "placeholders": [],'
- ' "messages": {},'
- '}')
- output = self.GetOutput(grd, 'fr', {'_google_chrome': '1'}, 'reg', 'en')
- expected_output = self.NEWLINE.join([
- 'Windows Registry Editor Version 5.00',
- '',
- '[HKEY_LOCAL_MACHINE\\Software\\Policies\\Google\\Chrome]',
- '"EnumPolicy"="two"'])
- self.CompareOutputs(output, expected_output)
-
- def testListPolicy(self):
- # Tests a policy group with a single policy of type 'list'.
- grd = self.PrepareTest(
- '{'
- ' "policy_definitions": ['
- ' {'
- ' "name": "ListPolicy",'
- ' "type": "list",'
- ' "caption": "",'
- ' "desc": "",'
- ' "supported_on": ["chrome.linux:8-"],'
- ' "example_value": ["foo", "bar"]'
- ' },'
- ' ],'
- ' "placeholders": [],'
- ' "messages": {},'
- '}')
- output = self.GetOutput(grd, 'fr', {'_chromium' : '1'}, 'reg', 'en')
- expected_output = self.NEWLINE.join([
- 'Windows Registry Editor Version 5.00',
- '',
- '[HKEY_LOCAL_MACHINE\\Software\\Policies\\Chromium\\ListPolicy]',
- '"1"="foo"',
- '"2"="bar"'])
-
- def testNonSupportedPolicy(self):
- # Tests a policy that is not supported on Windows, so it shouldn't
- # be included in the .REG file.
- grd = self.PrepareTest(
- '{'
- ' "policy_definitions": ['
- ' {'
- ' "name": "NonWindowsPolicy",'
- ' "type": "list",'
- ' "caption": "",'
- ' "desc": "",'
- ' "supported_on": ["chrome.mac:8-"],'
- ' "example_value": ["a"]'
- ' },'
- ' ],'
- ' "placeholders": [],'
- ' "messages": {},'
- '}')
- output = self.GetOutput(grd, 'fr', {'_chromium' : '1'}, 'reg', 'en')
- expected_output = self.NEWLINE.join([
- 'Windows Registry Editor Version 5.00'])
- self.CompareOutputs(output, expected_output)
-
- def testPolicyGroup(self):
- # Tests a policy group that has more than one policies.
- grd = self.PrepareTest(
- '{'
- ' "policy_definitions": ['
- ' {'
- ' "name": "Group1",'
- ' "type": "group",'
- ' "caption": "",'
- ' "desc": "",'
- ' "policies": [{'
- ' "name": "Policy1",'
- ' "type": "list",'
- ' "caption": "",'
- ' "desc": "",'
- ' "supported_on": ["chrome.win:8-"],'
- ' "example_value": ["a", "b"]'
- ' },{'
- ' "name": "Policy2",'
- ' "type": "string",'
- ' "caption": "",'
- ' "desc": "",'
- ' "supported_on": ["chrome.win:8-"],'
- ' "example_value": "c"'
- ' }],'
- ' },'
- ' ],'
- ' "placeholders": [],'
- ' "messages": {},'
- '}')
- output = self.GetOutput(grd, 'fr', {'_chromium' : '1'}, 'reg', 'en')
- expected_output = self.NEWLINE.join([
- 'Windows Registry Editor Version 5.00',
- '',
- '[HKEY_LOCAL_MACHINE\\Software\\Policies\\Chromium]',
- '"Policy2"="c"',
- '',
- '[HKEY_LOCAL_MACHINE\\Software\\Policies\\Chromium\\Policy1]',
- '"1"="a"',
- '"2"="b"'])
- self.CompareOutputs(output, expected_output)
-
-
-if __name__ == '__main__':
- unittest.main()
diff --git a/tools/grit/grit/format/policy_templates/writers/template_writer.py b/tools/grit/grit/format/policy_templates/writers/template_writer.py
deleted file mode 100644
index 7311990..0000000
--- a/tools/grit/grit/format/policy_templates/writers/template_writer.py
+++ /dev/null
@@ -1,249 +0,0 @@
-# Copyright (c) 2011 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 itertools
-
-
-class TemplateWriter(object):
- '''Abstract base class for writing policy templates in various formats.
- The methods of this class will be called by PolicyTemplateGenerator.
- '''
-
- def __init__(self, platforms, config):
- '''Initializes a TemplateWriter object.
-
- Args:
- platforms: List of platforms for which this writer can write policies.
- config: A dictionary of information required to generate the template.
- It contains some key-value pairs, including the following examples:
- 'build': 'chrome' or 'chromium'
- 'branding': 'Google Chrome' or 'Chromium'
- 'mac_bundle_id': The Mac bundle id of Chrome. (Only set when building
- for Mac.)
- messages: List of all the message strings from the grd file. Most of them
- are also present in the policy data structures that are passed to
- methods. That is the preferred way of accessing them, this should only
- be used in exceptional cases. An example for its use is the
- IDS_POLICY_WIN_SUPPORTED_WINXPSP2 message in ADM files, because that
- cannot be associated with any policy or group.
- '''
- self.platforms = platforms
- self.config = config
-
- def IsDeprecatedPolicySupported(self, policy):
- '''Checks if the given deprecated policy is supported by the writer.
-
- Args:
- policy: The dictionary of the policy.
-
- Returns:
- True if the writer chooses to include the deprecated 'policy' in its
- output.
- '''
- return False
-
- def IsFuturePolicySupported(self, policy):
- '''Checks if the given future policy is supported by the writer.
-
- Args:
- policy: The dictionary of the policy.
-
- Returns:
- True if the writer chooses to include the deprecated 'policy' in its
- output.
- '''
- return False
-
- def IsPolicySupported(self, policy):
- '''Checks if the given policy is supported by the writer.
- In other words, the set of platforms supported by the writer
- has a common subset with the set of platforms that support
- the policy.
-
- Args:
- policy: The dictionary of the policy.
-
- Returns:
- True if the writer chooses to include 'policy' in its output.
- '''
- if ('deprecated' in policy and policy['deprecated'] is True and
- not self.IsDeprecatedPolicySupported(policy)):
- return False
-
- if ('future' in policy and policy['future'] is True and
- not self.IsFuturePolicySupported(policy)):
- return False
-
- if '*' in self.platforms:
- # Currently chrome_os is only catched here.
- return True
- for supported_on in policy['supported_on']:
- for supported_on_platform in supported_on['platforms']:
- if supported_on_platform in self.platforms:
- return True
- return False
-
- def _GetPoliciesForWriter(self, group):
- '''Filters the list of policies in the passed group that are supported by
- the writer.
-
- Args:
- group: The dictionary of the policy group.
-
- Returns: The list of policies of the policy group that are compatible
- with the writer.
- '''
- if not 'policies' in group:
- return []
- result = []
- for policy in group['policies']:
- if self.IsPolicySupported(policy):
- result.append(policy)
- return result
-
- def Init(self):
- '''Initializes the writer. If the WriteTemplate method is overridden, then
- this method must be called as first step of each template generation
- process.
- '''
- pass
-
- def WriteTemplate(self, template):
- '''Writes the given template definition.
-
- Args:
- template: Template definition to write.
-
- Returns:
- Generated output for the passed template definition.
- '''
- self.messages = template['messages']
- self.Init()
- template['policy_definitions'] = \
- self.PreprocessPolicies(template['policy_definitions'])
- self.BeginTemplate()
- for policy in template['policy_definitions']:
- if policy['type'] == 'group':
- child_policies = self._GetPoliciesForWriter(policy)
- if child_policies:
- # Only write nonempty groups.
- self.BeginPolicyGroup(policy)
- for child_policy in child_policies:
- # Nesting of groups is currently not supported.
- self.WritePolicy(child_policy)
- self.EndPolicyGroup()
- elif self.IsPolicySupported(policy):
- self.WritePolicy(policy)
- self.EndTemplate()
- return self.GetTemplateText()
-
- def PreprocessPolicies(self, policy_list):
- '''Preprocesses a list of policies according to a given writer's needs.
- Preprocessing steps include sorting policies and stripping unneeded
- information such as groups (for writers that ignore them).
- Subclasses are encouraged to override this method, overriding
- implementations may call one of the provided specialized implementations.
- The default behaviour is to use SortPoliciesGroupsFirst().
-
- Args:
- policy_list: A list containing the policies to sort.
-
- Returns:
- The sorted policy list.
- '''
- return self.SortPoliciesGroupsFirst(policy_list)
-
- def WritePolicy(self, policy):
- '''Appends the template text corresponding to a policy into the
- internal buffer.
-
- Args:
- policy: The policy as it is found in the JSON file.
- '''
- raise NotImplementedError()
-
- def BeginPolicyGroup(self, group):
- '''Appends the template text corresponding to the beginning of a
- policy group into the internal buffer.
-
- Args:
- group: The policy group as it is found in the JSON file.
- '''
- pass
-
- def EndPolicyGroup(self):
- '''Appends the template text corresponding to the end of a
- policy group into the internal buffer.
- '''
- pass
-
- def BeginTemplate(self):
- '''Appends the text corresponding to the beginning of the whole
- template into the internal buffer.
- '''
- raise NotImplementedError()
-
- def EndTemplate(self):
- '''Appends the text corresponding to the end of the whole
- template into the internal buffer.
- '''
- pass
-
- def GetTemplateText(self):
- '''Gets the content of the internal template buffer.
-
- Returns:
- The generated template from the the internal buffer as a string.
- '''
- raise NotImplementedError()
-
- def SortPoliciesGroupsFirst(self, policy_list):
- '''Sorts a list of policies alphabetically. The order is the
- following: first groups alphabetically by caption, then other policies
- alphabetically by name. The order of policies inside groups is unchanged.
-
- Args:
- policy_list: The list of policies to sort. Sub-lists in groups will not
- be sorted.
- '''
- policy_list.sort(key=self.GetPolicySortingKeyGroupsFirst)
- return policy_list
-
- def FlattenGroupsAndSortPolicies(self, policy_list, sorting_key=None):
- '''Sorts a list of policies according to |sorting_key|, defaulting
- to alphabetical sorting if no key is given. If |policy_list| contains
- policies with type="group", it is flattened first, i.e. any groups' contents
- are inserted into the list as first-class elements and the groups are then
- removed.
- '''
- new_list = []
- for policy in policy_list:
- if policy['type'] == 'group':
- for grouped_policy in policy['policies']:
- new_list.append(grouped_policy)
- else:
- new_list.append(policy)
- if sorting_key == None:
- sorting_key = self.GetPolicySortingKeyName
- new_list.sort(key=sorting_key)
- return new_list
-
- def GetPolicySortingKeyName(self, policy):
- return policy['name']
-
- def GetPolicySortingKeyGroupsFirst(self, policy):
- '''Extracts a sorting key from a policy. These keys can be used for
- list.sort() methods to sort policies.
- See TemplateWriter.SortPolicies for usage.
- '''
- is_group = policy['type'] == 'group'
- if is_group:
- # Groups are sorted by caption.
- str_key = policy['caption']
- else:
- # Regular policies are sorted by name.
- str_key = policy['name']
- # Groups come before regular policies.
- return (not is_group, str_key)
diff --git a/tools/grit/grit/format/policy_templates/writers/template_writer_unittest.py b/tools/grit/grit/format/policy_templates/writers/template_writer_unittest.py
deleted file mode 100644
index 02d24a5..0000000
--- a/tools/grit/grit/format/policy_templates/writers/template_writer_unittest.py
+++ /dev/null
@@ -1,83 +0,0 @@
-# Copyright (c) 2011 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.
-
-'''Unit tests for grit.format.policy_templates.writers.template_writer'''
-
-import os
-import sys
-if __name__ == '__main__':
- sys.path.append(os.path.join(os.path.dirname(sys.argv[0]), '../../../..'))
-
-import unittest
-
-from grit.format.policy_templates.writers import template_writer
-
-
-POLICY_DEFS = [
- {'name': 'zp', 'type': 'string', 'caption': 'a1', 'supported_on': []},
- {
- 'type': 'group',
- 'caption': 'z_group1_caption',
- 'name': 'group1',
- 'policies': [
- {'name': 'z0', 'type': 'string', 'supported_on': []},
- {'name': 'a0', 'type': 'string', 'supported_on': []}
- ]
- },
- {
- 'type': 'group',
- 'caption': 'b_group2_caption',
- 'name': 'group2',
- 'policies': [{'name': 'q', 'type': 'string', 'supported_on': []}],
- },
- {'name': 'ap', 'type': 'string', 'caption': 'a2', 'supported_on': []}
-]
-
-
-GROUP_FIRST_SORTED_POLICY_DEFS = [
- {
- 'type': 'group',
- 'caption': 'b_group2_caption',
- 'name': 'group2',
- 'policies': [{'name': 'q', 'type': 'string', 'supported_on': []}],
- },
- {
- 'type': 'group',
- 'caption': 'z_group1_caption',
- 'name': 'group1',
- 'policies': [
- {'name': 'z0', 'type': 'string', 'supported_on': []},
- {'name': 'a0', 'type': 'string', 'supported_on': []}
- ]
- },
- {'name': 'ap', 'type': 'string', 'caption': 'a2', 'supported_on': []},
- {'name': 'zp', 'type': 'string', 'caption': 'a1', 'supported_on': []},
-]
-
-
-IGNORE_GROUPS_SORTED_POLICY_DEFS = [
- {'name': 'a0', 'type': 'string', 'supported_on': []},
- {'name': 'ap', 'type': 'string', 'caption': 'a2', 'supported_on': []},
- {'name': 'q', 'type': 'string', 'supported_on': []},
- {'name': 'z0', 'type': 'string', 'supported_on': []},
- {'name': 'zp', 'type': 'string', 'caption': 'a1', 'supported_on': []},
-]
-
-
-class TemplateWriterUnittests(unittest.TestCase):
- '''Unit tests for templater_writer.py.'''
-
- def testSortingGroupsFirst(self):
- tw = template_writer.TemplateWriter(None, None)
- sorted_list = tw.SortPoliciesGroupsFirst(POLICY_DEFS)
- self.assertEqual(sorted_list, GROUP_FIRST_SORTED_POLICY_DEFS)
-
- def testSortingIgnoreGroups(self):
- tw = template_writer.TemplateWriter(None, None)
- sorted_list = tw.FlattenGroupsAndSortPolicies(POLICY_DEFS)
- self.assertEqual(sorted_list, IGNORE_GROUPS_SORTED_POLICY_DEFS)
-
-
-if __name__ == '__main__':
- unittest.main()
diff --git a/tools/grit/grit/format/policy_templates/writers/writer_unittest_common.py b/tools/grit/grit/format/policy_templates/writers/writer_unittest_common.py
deleted file mode 100644
index 9a10d12..0000000
--- a/tools/grit/grit/format/policy_templates/writers/writer_unittest_common.py
+++ /dev/null
@@ -1,85 +0,0 @@
-# Copyright (c) 2011 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.
-
-'''Common tools for unit-testing writers.'''
-
-
-import os
-import sys
-if __name__ == '__main__':
- sys.path.append(os.path.join(os.path.dirname(sys.argv[0]), '../../../..'))
-
-import tempfile
-import unittest
-import StringIO
-
-from grit import grd_reader
-from grit import util
-from grit.tool import build
-
-
-class DummyOutput(object):
- def __init__(self, type, language, file = 'hello.gif'):
- self.type = type
- self.language = language
- self.file = file
- def GetType(self):
- return self.type
- def GetLanguage(self):
- return self.language
- def GetOutputFilename(self):
- return self.file
-
-
-class WriterUnittestCommon(unittest.TestCase):
- '''Common class for unittesting writers.'''
-
- def PrepareTest(self, policy_json):
- '''Prepares and parses a grit tree along with a data structure of policies.
-
- Args:
- policy_json: The policy data structure in JSON format.
- '''
- # First create a temporary file that contains the JSON policy list.
- tmp_file_name = 'test.json'
- tmp_dir_name = tempfile.gettempdir()
- json_file_path = tmp_dir_name + '/' + tmp_file_name
- f = open(json_file_path, 'w')
- f.write(policy_json.strip())
- f.close()
- # Then assemble the grit tree.
- grd_text = '''
- <grit base_dir="." latest_public_release="0" current_release="1" source_lang_id="en">
- <release seq="1">
- <structures>
- <structure name="IDD_POLICY_SOURCE_FILE" file="%s" type="policy_template_metafile" />
- </structures>
- </release>
- </grit>''' % json_file_path
- grd_string_io = StringIO.StringIO(grd_text)
- # Parse the grit tree and load the policies' JSON with a gatherer.
- grd = grd_reader.Parse(grd_string_io, dir=tmp_dir_name)
- grd.RunGatherers(recursive=True)
- # Remove the policies' JSON.
- os.unlink(json_file_path)
- return grd
-
- def GetOutput(self, grd, env_lang, env_defs, out_type, out_lang):
- '''Generates an output of a writer.
-
- Args:
- grd: The root of the grit tree.
- env_lang: The environment language.
- env_defs: Environment definitions.
- out_type: Type of the output node for which output will be generated.
- This selects the writer.
- out_lang: Language of the output node for which output will be generated.
-
- Returns:
- The string of the tamplete created by the writer.
- '''
- grd.SetOutputContext(env_lang, env_defs)
- buf = StringIO.StringIO()
- build.RcBuilder.ProcessNode(grd, DummyOutput(out_type, out_lang), buf)
- return buf.getvalue()
diff --git a/tools/grit/grit/format/policy_templates/writers/xml_formatted_writer.py b/tools/grit/grit/format/policy_templates/writers/xml_formatted_writer.py
deleted file mode 100644
index 8323c2e..0000000
--- a/tools/grit/grit/format/policy_templates/writers/xml_formatted_writer.py
+++ /dev/null
@@ -1,88 +0,0 @@
-# Copyright (c) 2011 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.
-
-
-from xml.dom import minidom
-from grit.format.policy_templates.writers import template_writer
-
-
-class XMLFormattedWriter(template_writer.TemplateWriter):
- '''Helper class for generating XML-based templates.
- '''
-
- def AddElement(self, parent, name, attrs=None, text=None):
- '''
- Adds a new XML Element as a child to an existing element or the Document.
-
- Args:
- parent: An XML element or the document, where the new element will be
- added.
- name: The name of the new element.
- attrs: A dictionary of the attributes' names and values for the new
- element.
- text: Text content for the new element.
-
- Returns:
- The created new element.
- '''
- if attrs == None:
- attrs = {}
-
- doc = parent.ownerDocument
- element = doc.createElement(name)
- for key, value in attrs.iteritems():
- element.setAttribute(key, value)
- if text:
- element.appendChild(doc.createTextNode(text))
- parent.appendChild(element)
- return element
-
- def AddText(self, parent, text):
- '''Adds text to a parent node.
- '''
- doc = parent.ownerDocument
- parent.appendChild(doc.createTextNode(text))
-
- def AddAttribute(self, parent, name, value):
- '''Adds a new attribute to the parent Element. If an attribute with the
- given name already exists then it will be replaced.
- '''
- doc = parent.ownerDocument
- attribute = doc.createAttribute(name)
- attribute.value = value
- parent.setAttributeNode(attribute)
-
- def ToPrettyXml(self, doc):
- # return doc.toprettyxml(indent=' ')
- # The above pretty-printer does not print the doctype and adds spaces
- # around texts, e.g.:
- # <string>
- # value of the string
- # </string>
- # This is problematic both for the OSX Workgroup Manager (plist files) and
- # the Windows Group Policy Editor (admx files). What they need instead:
- # <string>value of string</string>
- # So we use the poor man's pretty printer here. It assumes that there are
- # no mixed-content nodes.
- # Get all the XML content in a one-line string.
- xml = doc.toxml()
- # Determine where the line breaks will be. (They will only be between tags.)
- lines = xml[1:len(xml) - 1].split('><')
- indent = ''
- res = ''
- # Determine indent for each line.
- for i in range(len(lines)):
- line = lines[i]
- if line[0] == '/':
- # If the current line starts with a closing tag, decrease indent before
- # printing.
- indent = indent[2:]
- lines[i] = indent + '<' + line + '>'
- if (line[0] not in ['/', '?', '!'] and '</' not in line and
- line[len(line) - 1] != '/'):
- # If the current line starts with an opening tag and does not conatin a
- # closing tag, increase indent after the line is printed.
- indent += ' '
- # Reconstruct XML text from the lines.
- return '\n'.join(lines)
diff --git a/tools/grit/grit/format/policy_templates/writers/xml_writer_base_unittest.py b/tools/grit/grit/format/policy_templates/writers/xml_writer_base_unittest.py
deleted file mode 100644
index 91ff6ed..0000000
--- a/tools/grit/grit/format/policy_templates/writers/xml_writer_base_unittest.py
+++ /dev/null
@@ -1,38 +0,0 @@
-#!/usr/bin/python2.4
-# Copyright (c) 2011 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.
-
-
-"""Unittests for grit.format.policy_templates.writers.admx_writer."""
-
-
-import os
-import sys
-import unittest
-
-
-from xml.dom import minidom
-
-
-class XmlWriterBaseTest(unittest.TestCase):
- '''Base class for XML writer unit-tests.
- '''
-
- def GetXMLOfChildren(self, parent):
- '''Returns the XML of all child nodes of the given parent node.
- Args:
- parent: The XML of the children of this node will be returned.
-
- Return: XML of the chrildren of the parent node.
- '''
- return ''.join(
- child.toprettyxml(indent=' ') for child in parent.childNodes)
-
- def AssertXMLEquals(self, output, expected_output):
- '''Asserts if the passed XML arguements are equal.
- Args:
- output: Actual XML text.
- expected_output: Expected XML text.
- '''
- self.assertEquals(output.strip(), expected_output.strip())
diff --git a/tools/grit/grit/format/rc.py b/tools/grit/grit/format/rc.py
deleted file mode 100644
index 3878ba8..0000000
--- a/tools/grit/grit/format/rc.py
+++ /dev/null
@@ -1,445 +0,0 @@
-#!/usr/bin/python2.4
-# Copyright (c) 2011 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.
-
-'''Support for formatting an RC file for compilation.
-'''
-
-import os
-import types
-import re
-
-from grit import util
-from grit.format import interface
-
-# Matches all different types of linebreaks.
-_LINEBREAKS = re.compile('\r\n|\n|\r')
-
-'''
-This dictionary defines the langauge charset pair lookup table, which is used
-for replacing the GRIT expand variables for language info in Product Version
-resource. The key is the language ISO country code, and the value
-is the language and character-set pair, which is a hexadecimal string
-consisting of the concatenation of the language and character-set identifiers.
-The first 4 digit of the value is the hex value of LCID, the remaining
-4 digits is the hex value of character-set id(code page)of the language.
-
-We have defined three GRIT expand_variables to be used in the version resource
-file to set the language info. Here is an example how they should be used in
-the VS_VERSION_INFO section of the resource file to allow GRIT to localize
-the language info correctly according to product locale.
-
-VS_VERSION_INFO VERSIONINFO
-...
-BEGIN
- BLOCK "StringFileInfo"
- BEGIN
- BLOCK "[GRITVERLANGCHARSETHEX]"
- BEGIN
- ...
- END
- END
- BLOCK "VarFileInfo"
- BEGIN
- VALUE "Translation", [GRITVERLANGID], [GRITVERCHARSETID]
- END
-END
-
-'''
-
-_LANGUAGE_CHARSET_PAIR = {
- 'ar' : '040104e8',
- 'fi' : '040b04e4',
- 'ko' : '041203b5',
- 'es' : '040a04e4',
- 'bg' : '040204e3',
- 'fr' : '040c04e4',
- 'lv' : '042604e9',
- 'sv' : '041d04e4',
- 'ca' : '040304e4',
- 'de' : '040704e4',
- 'lt' : '042704e9',
- # no lcid for tl(Tagalog), use default custom locale
- 'tl' : '0c0004b0',
- 'zh-CN' : '080403a8',
- 'el' : '040804e5',
- 'no' : '041404e4',
- 'th' : '041e036a',
- 'zh-TW' : '040403b6',
- 'iw' : '040d04e7',
- 'pl' : '041504e2',
- 'tr' : '041f04e6',
- 'hr' : '041a04e4',
- # no codepage for hindi, use unicode(1200)
- 'hi' : '043904b0',
- 'pt-BR' : '041604e4',
- 'uk' : '042204e3',
- 'cs' : '040504e2',
- 'hu' : '040e04e2',
- 'ro' : '041804e2',
- # no codepage for urdu, use unicode(1200)
- 'ur' : '042004b0',
- 'da' : '040604e4',
- 'is' : '040f04e4',
- 'ru' : '041904e3',
- 'vi' : '042a04ea',
- 'nl' : '041304e4',
- 'id' : '042104e4',
- 'sr' : '081a04e2',
- 'en-GB' : '0809040e',
- 'it' : '041004e4',
- 'sk' : '041b04e2',
- 'et' : '042504e9',
- 'ja' : '041103a4',
- 'sl' : '042404e2',
- 'en' : '040904b0',
- 'fake_bidi' : '040d04e7',
-}
-
-_LANGUAGE_DIRECTIVE_PAIR = {
- 'ar' : 'LANG_ARABIC, SUBLANG_DEFAULT',
- 'fi' : 'LANG_FINNISH, SUBLANG_DEFAULT',
- 'ko' : 'LANG_KOREAN, SUBLANG_KOREAN',
- 'es' : 'LANG_SPANISH, SUBLANG_SPANISH_MODERN',
- 'bg' : 'LANG_BULGARIAN, SUBLANG_DEFAULT',
- 'fr' : 'LANG_FRENCH, SUBLANG_FRENCH',
- 'lv' : 'LANG_LATVIAN, SUBLANG_DEFAULT',
- 'sv' : 'LANG_SWEDISH, SUBLANG_SWEDISH',
- 'ca' : 'LANG_CATALAN, SUBLANG_DEFAULT',
- 'de' : 'LANG_GERMAN, SUBLANG_GERMAN',
- 'lt' : 'LANG_LITHUANIAN, SUBLANG_LITHUANIAN',
- 'tl' : 'LANG_NEUTRAL, SUBLANG_DEFAULT',
- 'zh-CN' : 'LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED',
- 'el' : 'LANG_GREEK, SUBLANG_DEFAULT',
- 'no' : 'LANG_NORWEGIAN, SUBLANG_DEFAULT',
- 'th' : 'LANG_THAI, SUBLANG_DEFAULT',
- 'zh-TW' : 'LANG_CHINESE, SUBLANG_CHINESE_TRADITIONAL',
- 'iw' : 'LANG_HEBREW, SUBLANG_DEFAULT',
- 'pl' : 'LANG_POLISH, SUBLANG_DEFAULT',
- 'tr' : 'LANG_TURKISH, SUBLANG_DEFAULT',
- 'hr' : 'LANG_CROATIAN, SUBLANG_DEFAULT',
- 'hi' : 'LANG_HINDI, SUBLANG_DEFAULT',
- 'pt-BR' : 'LANG_PORTUGUESE, SUBLANG_DEFAULT',
- 'uk' : 'LANG_UKRAINIAN, SUBLANG_DEFAULT',
- 'cs' : 'LANG_CZECH, SUBLANG_DEFAULT',
- 'hu' : 'LANG_HUNGARIAN, SUBLANG_DEFAULT',
- 'ro' : 'LANG_ROMANIAN, SUBLANG_DEFAULT',
- 'ur' : 'LANG_URDU, SUBLANG_DEFAULT',
- 'da' : 'LANG_DANISH, SUBLANG_DEFAULT',
- 'is' : 'LANG_ICELANDIC, SUBLANG_DEFAULT',
- 'ru' : 'LANG_RUSSIAN, SUBLANG_DEFAULT',
- 'vi' : 'LANG_VIETNAMESE, SUBLANG_DEFAULT',
- 'nl' : 'LANG_DUTCH, SUBLANG_DEFAULT',
- 'id' : 'LANG_INDONESIAN, SUBLANG_DEFAULT',
- 'sr' : 'LANG_SERBIAN, SUBLANG_SERBIAN_CYRILLIC',
- 'en-GB' : 'LANG_ENGLISH, SUBLANG_ENGLISH_UK',
- 'it' : 'LANG_ITALIAN, SUBLANG_DEFAULT',
- 'sk' : 'LANG_SLOVAK, SUBLANG_DEFAULT',
- 'et' : 'LANG_ESTONIAN, SUBLANG_DEFAULT',
- 'ja' : 'LANG_JAPANESE, SUBLANG_DEFAULT',
- 'sl' : 'LANG_SLOVENIAN, SUBLANG_DEFAULT',
- 'en' : 'LANG_ENGLISH, SUBLANG_ENGLISH_US',
- 'fake_bidi' : 'LANG_HEBREW, SUBLANG_DEFAULT',
-}
-
-def GetLangCharsetPair(language) :
- if _LANGUAGE_CHARSET_PAIR.has_key(language) :
- return _LANGUAGE_CHARSET_PAIR[language]
- else :
- print 'Warning:GetLangCharsetPair() found undefined language %s' %(language)
- return ''
-
-def GetLangDirectivePair(language) :
- if _LANGUAGE_DIRECTIVE_PAIR.has_key(language) :
- return _LANGUAGE_DIRECTIVE_PAIR[language]
- else :
- print 'Warning:GetLangDirectivePair() found undefined language %s' % (language)
- return 'unknown language: see tools/grit/format/rc.py'
-
-def GetLangIdHex(language) :
- if _LANGUAGE_CHARSET_PAIR.has_key(language) :
- langcharset = _LANGUAGE_CHARSET_PAIR[language]
- lang_id = '0x' + langcharset[0:4]
- return lang_id
- else :
- print 'Warning:GetLangIdHex() found undefined language %s' %(language)
- return ''
-
-
-def GetCharsetIdDecimal(language) :
- if _LANGUAGE_CHARSET_PAIR.has_key(language) :
- langcharset = _LANGUAGE_CHARSET_PAIR[language]
- charset_decimal = int(langcharset[4:], 16)
- return str(charset_decimal)
- else :
- print 'Warning:GetCharsetIdDecimal() found undefined language %s' %(language)
- return ''
-
-
-def GetUnifiedLangCode(language) :
- r = re.compile('([a-z]{1,2})_([a-z]{1,2})')
- if r.match(language) :
- underscore = language.find('_')
- return language[0:underscore] + '-' + language[underscore + 1:].upper()
- else :
- return language
-
-
-def _MakeRelativePath(base_path, path_to_make_relative):
- '''Returns a relative path such from the base_path to
- the path_to_make_relative.
-
- In other words, os.join(base_path,
- MakeRelativePath(base_path, path_to_make_relative))
- is the same location as path_to_make_relative.
-
- Args:
- base_path: the root path
- path_to_make_relative: an absolute path that is on the same drive
- as base_path
- '''
-
- def _GetPathAfterPrefix(prefix_path, path_with_prefix):
- '''Gets the subpath within in prefix_path for the path_with_prefix
- with no beginning or trailing path separators.
-
- Args:
- prefix_path: the base path
- path_with_prefix: a path that starts with prefix_path
- '''
- assert path_with_prefix.startswith(prefix_path)
- path_without_prefix = path_with_prefix[len(prefix_path):]
- normalized_path = os.path.normpath(path_without_prefix.strip(os.path.sep))
- if normalized_path == '.':
- normalized_path = ''
- return normalized_path
-
- def _GetCommonBaseDirectory(*args):
- '''Returns the common prefix directory for the given paths
-
- Args:
- The list of paths (at least one of which should be a directory)
- '''
- prefix = os.path.commonprefix(args)
- # prefix is a character-by-character prefix (i.e. it does not end
- # on a directory bound, so this code fixes that)
-
- # if the prefix ends with the separator, then it is prefect.
- if len(prefix) > 0 and prefix[-1] == os.path.sep:
- return prefix
-
- # We need to loop through all paths or else we can get
- # tripped up by "c:\a" and "c:\abc". The common prefix
- # is "c:\a" which is a directory and looks good with
- # respect to the first directory but it is clear that
- # isn't a common directory when the second path is
- # examined.
- for path in args:
- assert len(path) >= len(prefix)
- # If the prefix the same length as the path,
- # then the prefix must be a directory (since one
- # of the arguements should be a directory).
- if path == prefix:
- continue
- # if the character after the prefix in the path
- # is the separator, then the prefix appears to be a
- # valid a directory as well for the given path
- if path[len(prefix)] == os.path.sep:
- continue
- # Otherwise, the prefix is not a directory, so it needs
- # to be shortened to be one
- index_sep = prefix.rfind(os.path.sep)
- # The use "index_sep + 1" because it includes the final sep
- # and it handles the case when the index_sep is -1 as well
- prefix = prefix[:index_sep + 1]
- # At this point we backed up to a directory bound which is
- # common to all paths, so we can quit going through all of
- # the paths.
- break
- return prefix
-
- prefix = _GetCommonBaseDirectory(base_path, path_to_make_relative)
- # If the paths had no commonality at all, then return the absolute path
- # because it is the best that can be done. If the path had to be relative
- # then eventually this absolute path will be discovered (when a build breaks)
- # and an appropriate fix can be made, but having this allows for the best
- # backward compatibility with the absolute path behavior in the past.
- if len(prefix) <= 0:
- return path_to_make_relative
- # Build a path from the base dir to the common prefix
- remaining_base_path = _GetPathAfterPrefix(prefix, base_path)
-
- # The follow handles two case: "" and "foo\\bar"
- path_pieces = remaining_base_path.split(os.path.sep)
- base_depth_from_prefix = len([d for d in path_pieces if len(d)])
- base_to_prefix = (".." + os.path.sep) * base_depth_from_prefix
-
- # Put add in the path from the prefix to the path_to_make_relative
- remaining_other_path = _GetPathAfterPrefix(prefix, path_to_make_relative)
- return base_to_prefix + remaining_other_path
-
-
-class TopLevel(interface.ItemFormatter):
- '''Writes out the required preamble for RC files.'''
- def Format(self, item, lang='en', begin_item=True, output_dir='.'):
- assert isinstance(lang, types.StringTypes)
- if not begin_item:
- return ''
- else:
- # Find the location of the resource header file, so that we can include
- # it.
- resource_header = 'resource.h' # fall back to this
- language_directive = ''
- for output in item.GetRoot().GetOutputFiles():
- if output.attrs['type'] == 'rc_header':
- resource_header = os.path.abspath(output.GetOutputFilename())
- resource_header = _MakeRelativePath(output_dir, resource_header)
- if output.attrs['lang'] != lang:
- continue
- if output.attrs['language_section'] == '':
- # If no language_section is requested, no directive is added
- # (Used when the generated rc will be included from another rc
- # file that will have the appropriate language directive)
- language_directive = ''
- elif output.attrs['language_section'] == 'neutral':
- # If a neutral language section is requested (default), add a
- # neutral language directive
- language_directive = 'LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL'
- elif output.attrs['language_section'] == 'lang':
- language_directive = 'LANGUAGE %s' % GetLangDirectivePair(lang)
- resource_header = resource_header.replace('\\', '\\\\')
- return '''// Copyright (c) Google Inc. %d
-// All rights reserved.
-// This file is automatically generated by GRIT. Do not edit.
-
-#include "%s"
-#include <winresrc.h>
-#ifdef IDC_STATIC
-#undef IDC_STATIC
-#endif
-#define IDC_STATIC (-1)
-
-%s
-
-
-''' % (util.GetCurrentYear(), resource_header, language_directive)
-# end Format() function
-
-
-
-class StringTable(interface.ItemFormatter):
- '''Surrounds a collection of string messages with the required begin and
- end blocks to declare a string table.'''
-
- def Format(self, item, lang='en', begin_item=True, output_dir='.'):
- assert isinstance(lang, types.StringTypes)
- if begin_item:
- return 'STRINGTABLE\nBEGIN\n'
- else:
- return 'END\n\n'
-
-
-class Message(interface.ItemFormatter):
- '''Writes out a single message to a string table.'''
-
- def Format(self, item, lang='en', begin_item=True, output_dir='.'):
- from grit.node import message
- if not begin_item:
- return ''
-
- assert isinstance(lang, types.StringTypes)
- assert isinstance(item, message.MessageNode)
-
- message = item.ws_at_start + item.Translate(lang) + item.ws_at_end
- # Escape quotation marks (RC format uses doubling-up
- message = message.replace('"', '""')
- # Replace linebreaks with a \n escape
- message = _LINEBREAKS.sub(r'\\n', message)
-
- name_attr = item.GetTextualIds()[0]
-
- return ' %-15s "%s"\n' % (name_attr, message)
-
-
-class RcSection(interface.ItemFormatter):
- '''Writes out an .rc file section.'''
-
- def Format(self, item, lang='en', begin_item=True, output_dir='.'):
- if not begin_item:
- return ''
-
- assert isinstance(lang, types.StringTypes)
- from grit.node import structure
- assert isinstance(item, structure.StructureNode)
-
- if item.IsExcludedFromRc():
- return ''
- else:
- text = item.gatherer.Translate(
- lang, skeleton_gatherer=item.GetSkeletonGatherer(),
- pseudo_if_not_available=item.PseudoIsAllowed(),
- fallback_to_english=item.ShouldFallbackToEnglish()) + '\n\n'
-
- # Replace the language expand_variables in version rc info.
- unified_lang_code = GetUnifiedLangCode(lang)
- if text.find('[GRITVERLANGCHARSETHEX]') != -1:
- text = text.replace('[GRITVERLANGCHARSETHEX]',
- GetLangCharsetPair(unified_lang_code))
- if text.find('[GRITVERLANGID]') != -1:
- text = text.replace('[GRITVERLANGID]', GetLangIdHex(unified_lang_code))
- if text.find('[GRITVERCHARSETID]') != -1:
- text = text.replace('[GRITVERCHARSETID]',
- GetCharsetIdDecimal(unified_lang_code))
-
- return text
-
-
-class RcInclude(interface.ItemFormatter):
- '''Writes out an item that is included in an .rc file (e.g. an ICON)'''
-
- def __init__(self, type, filenameWithoutPath = 0, relative_path = 0,
- flatten_html = 0):
- '''Indicates to the instance what the type of the resource include is,
- e.g. 'ICON' or 'HTML'. Case must be correct, i.e. if the type is all-caps
- the parameter should be all-caps.
-
- Args:
- type: 'ICON'
- '''
- self.type_ = type
- self.filenameWithoutPath = filenameWithoutPath
- self.relative_path_ = relative_path
- self.flatten_html = flatten_html
-
- def Format(self, item, lang='en', begin_item=True, output_dir='.'):
- if not begin_item:
- return ''
-
- assert isinstance(lang, types.StringTypes)
- from grit.node import structure
- from grit.node import include
- assert isinstance(item, (structure.StructureNode, include.IncludeNode))
- assert (isinstance(item, include.IncludeNode) or
- item.attrs['type'] in ['tr_html', 'admin_template', 'txt', 'muppet'])
-
- # By default, we use relative pathnames to included resources so that
- # sharing the resulting .rc files is possible.
- #
- # The FileForLanguage() Function has the side effect of generating the file
- # if needed (e.g. if it is an HTML file include).
- filename = os.path.abspath(item.FileForLanguage(lang, output_dir))
- if self.flatten_html:
- filename = item.Flatten(output_dir)
- elif self.filenameWithoutPath:
- filename = os.path.basename(filename)
- elif self.relative_path_:
- filename = _MakeRelativePath(output_dir, filename)
-
- filename = filename.replace('\\', '\\\\') # escape for the RC format
-
- if isinstance(item, structure.StructureNode) and item.IsExcludedFromRc():
- return ''
- else:
- return '%-18s %-18s "%s"\n' % (item.attrs['name'], self.type_, filename)
-
diff --git a/tools/grit/grit/format/rc_header.py b/tools/grit/grit/format/rc_header.py
deleted file mode 100644
index 849bf14..0000000
--- a/tools/grit/grit/format/rc_header.py
+++ /dev/null
@@ -1,180 +0,0 @@
-#!/usr/bin/python2.4
-# Copyright (c) 2006-2008 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.
-
-'''Item formatters for RC headers.
-'''
-
-import re
-
-from grit.format import interface
-from grit import exception
-from grit import util
-
-from grit.extern import FP
-
-
-class TopLevel(interface.ItemFormatter):
- '''Writes the necessary preamble for a resource.h file.'''
-
- def Format(self, item, lang='', begin_item=True, output_dir='.'):
- if not begin_item:
- return ''
- else:
- header_string = '''// Copyright (c) Google Inc. %d
-// All rights reserved.
-// This file is automatically generated by GRIT. Do not edit.
-
-#pragma once
-''' % (util.GetCurrentYear())
- # Check for emit nodes under the rc_header. If any emit node
- # is present, we assume it means the GRD file wants to override
- # the default header, with no includes.
- for output_node in item.GetOutputFiles():
- if output_node.GetType() == 'rc_header':
- for child in output_node.children:
- if child.name == 'emit':
- if child.attrs['emit_type'] == 'prepend':
- return header_string
- # else print out the default header with include
- return header_string + '''
-#include <atlres.h>
-
-'''
-
-
-class EmitAppender(interface.ItemFormatter):
- '''Adds the content of the <emit> nodes to the RC header file.'''
-
- def Format(self, item, lang='', begin_item=True, output_dir='.'):
- if not begin_item:
- return ''
- else:
- return '%s\n' % (item.GetCdata())
-
-class Item(interface.ItemFormatter):
- '''Writes the #define line(s) for a single item in a resource.h file. If
- your node has multiple IDs that need to be defined (as is the case e.g. for
- dialog resources) it should define a function GetTextIds(self) that returns
- a list of textual IDs (strings). Otherwise the formatter will use the
- 'name' attribute of the node.'''
-
- # All IDs allocated so far, mapped to the textual ID they represent.
- # Used to detect and resolve collisions.
- ids_ = {}
-
- # All textual IDs allocated so far, mapped to the numerical ID they
- # represent. Used when literal IDs are being defined in the 'identifiers'
- # section of the GRD file to define other message IDs.
- tids_ = {}
-
- def _VerifyId(self, id, tid, msg_if_error):
- if id in self.ids_ and self.ids_[id] != tid:
- raise exception.IdRangeOverlap(msg_if_error +
- '\nUse the first_id attribute on grouping nodes (<structures>,\n'
- '<includes>, <messages> and <ids>) to fix this problem.')
- if id < 101:
- print ('WARNING: Numeric resource IDs should be greater than 100 to avoid\n'
- 'conflicts with system-defined resource IDs.')
-
- def Format(self, item, lang='', begin_item=True, output_dir='.'):
- if not begin_item:
- return ''
-
- # Resources that use the RES protocol don't need
- # any numerical ids generated, so we skip them altogether.
- # This is accomplished by setting the flag 'generateid' to false
- # in the GRD file.
- if 'generateid' in item.attrs:
- if item.attrs['generateid'] == 'false':
- return ''
-
- text_ids = item.GetTextualIds()
-
- # We consider the "parent" of the item to be the GroupingNode containing
- # the item, as its immediate parent may be an <if> node.
- item_parent = item.parent
- import grit.node.empty
- while item_parent and not isinstance(item_parent,
- grit.node.empty.GroupingNode):
- item_parent = item_parent.parent
-
- lines = []
- for tid in text_ids:
- if util.SYSTEM_IDENTIFIERS.match(tid):
- # Don't emit a new ID for predefined IDs
- continue
-
- # Some identifier nodes can provide their own id,
- # and we use that id in the generated header in that case.
- if hasattr(item, 'GetId') and item.GetId():
- id = long(item.GetId())
-
- elif ('offset' in item.attrs and item_parent and
- 'first_id' in item_parent.attrs and item_parent.attrs['first_id'] != ''):
- offset_text = item.attrs['offset']
- parent_text = item_parent.attrs['first_id']
-
- try:
- offset_id = long(offset_text)
- except ValueError:
- offset_id = self.tids_[offset_text]
-
- try:
- parent_id = long(parent_text)
- except ValueError:
- parent_id = self.tids_[parent_text]
-
- id = parent_id + offset_id
-
- # We try to allocate IDs sequentially for blocks of items that might
- # be related, for instance strings in a stringtable (as their IDs might be
- # used e.g. as IDs for some radio buttons, in which case the IDs must
- # be sequential).
- #
- # We do this by having the first item in a section store its computed ID
- # (computed from a fingerprint) in its parent object. Subsequent children
- # of the same parent will then try to get IDs that sequentially follow
- # the currently stored ID (on the parent) and increment it.
- elif not item_parent or not hasattr(item_parent, '_last_id_'):
- # First check if the starting ID is explicitly specified by the parent.
- if (item_parent and 'first_id' in item_parent.attrs and
- item_parent.attrs['first_id'] != ''):
- id = long(item_parent.attrs['first_id'])
- self._VerifyId(id, tid,
- 'Explicitly specified numeric first_id %d conflicts with one of the\n'
- 'ID ranges already used.' % id)
- else:
- # Automatically generate the ID based on the first clique from the
- # first child of the first child node of our parent (i.e. when we
- # first get to this location in the code).
-
- # According to
- # http://msdn.microsoft.com/en-us/library/t2zechd4(VS.71).aspx
- # the safe usable range for resource IDs in Windows is from decimal
- # 101 to 0x7FFF.
-
- id = FP.UnsignedFingerPrint(tid)
- id = id % (0x7FFF - 101)
- id += 101
-
- self._VerifyId(id, tid,
- 'Automatic (fingerprint-based) numeric ID for %s (%d) overlapped\n'
- 'with a previously allocated range.' % (tid, id))
-
- if item_parent:
- item_parent._last_id_ = id
- else:
- assert hasattr(item_parent, '_last_id_')
- id = item_parent._last_id_ = item_parent._last_id_ + 1
- self._VerifyId(id, tid,
- 'Wanted to make numeric value for ID %s (%d) follow the numeric value of\n'
- 'the previous ID in the .grd file, but it was already used.' % (tid, id))
-
- if tid not in self.ids_.values():
- self.ids_[id] = tid
- self.tids_[tid] = id
- lines.append('#define %s %d\n' % (tid, id))
- return ''.join(lines)
-
diff --git a/tools/grit/grit/format/rc_header_unittest.py b/tools/grit/grit/format/rc_header_unittest.py
deleted file mode 100644
index 3f2a228..0000000
--- a/tools/grit/grit/format/rc_header_unittest.py
+++ /dev/null
@@ -1,104 +0,0 @@
-#!/usr/bin/python2.4
-# Copyright (c) 2006-2008 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.
-
-'''Unit tests for the rc_header formatter'''
-
-import os
-import sys
-if __name__ == '__main__':
- sys.path.append(os.path.join(os.path.dirname(sys.argv[0]), '../..'))
-
-import StringIO
-import unittest
-
-from grit.format import rc_header
-from grit.node import message
-from grit.node import structure
-from grit.node import include
-from grit.node import misc
-from grit import grd_reader
-from grit import exception
-
-
-class RcHeaderFormatterUnittest(unittest.TestCase):
- def setUp(self):
- self.formatter = rc_header.Item()
- self.formatter.ids_ = {} # need to reset this between tests
-
- def FormatAll(self, grd):
- output = []
- for node in grd:
- if isinstance(node, (message.MessageNode, structure.StructureNode,
- include.IncludeNode, misc.IdentifierNode)):
- output.append(self.formatter.Format(node))
- output = ''.join(output)
- return output.replace(' ', '')
-
- def testFormatter(self):
- grd = grd_reader.Parse(StringIO.StringIO('''<?xml version="1.0" encoding="UTF-8"?>
- <grit latest_public_release="2" source_lang_id="en" current_release="3" base_dir=".">
- <release seq="3">
- <includes first_id="300" comment="bingo">
- <include type="gif" name="ID_LOGO" file="images/logo.gif" />
- </includes>
- <messages first_id="10000">
- <message name="IDS_GREETING" desc="Printed to greet the currently logged in user">
- Hello <ph name="USERNAME">%s<ex>Joi</ex></ph>, how are you doing today?
- </message>
- <message name="IDS_BONGO">
- Bongo!
- </message>
- </messages>
- <structures>
- <structure type="dialog" name="IDD_NARROW_DIALOG" file="rc_files/dialogs.rc" />
- <structure type="version" name="VS_VERSION_INFO" file="rc_files/version.rc" />
- </structures>
- </release>
- </grit>'''), '.')
- output = self.FormatAll(grd)
- self.failUnless(output.count('IDS_GREETING10000'))
- self.failUnless(output.count('ID_LOGO300'))
-
- def testExplicitFirstIdOverlaps(self):
- # second first_id will overlap preexisting range
- grd = grd_reader.Parse(StringIO.StringIO('''<?xml version="1.0" encoding="UTF-8"?>
- <grit latest_public_release="2" source_lang_id="en" current_release="3" base_dir=".">
- <release seq="3">
- <includes first_id="300" comment="bingo">
- <include type="gif" name="ID_LOGO" file="images/logo.gif" />
- <include type="gif" name="ID_LOGO2" file="images/logo2.gif" />
- </includes>
- <messages first_id="301">
- <message name="IDS_GREETING" desc="Printed to greet the currently logged in user">
- Hello <ph name="USERNAME">%s<ex>Joi</ex></ph>, how are you doing today?
- </message>
- <message name="IDS_SMURFGEBURF">Frubegfrums</message>
- </messages>
- </release>
- </grit>'''), '.')
- self.assertRaises(exception.IdRangeOverlap, self.FormatAll, grd)
-
- def testImplicitOverlapsPreexisting(self):
- # second message in <messages> will overlap preexisting range
- grd = grd_reader.Parse(StringIO.StringIO('''<?xml version="1.0" encoding="UTF-8"?>
- <grit latest_public_release="2" source_lang_id="en" current_release="3" base_dir=".">
- <release seq="3">
- <includes first_id="301" comment="bingo">
- <include type="gif" name="ID_LOGO" file="images/logo.gif" />
- <include type="gif" name="ID_LOGO2" file="images/logo2.gif" />
- </includes>
- <messages first_id="300">
- <message name="IDS_GREETING" desc="Printed to greet the currently logged in user">
- Hello <ph name="USERNAME">%s<ex>Joi</ex></ph>, how are you doing today?
- </message>
- <message name="IDS_SMURFGEBURF">Frubegfrums</message>
- </messages>
- </release>
- </grit>'''), '.')
- self.assertRaises(exception.IdRangeOverlap, self.FormatAll, grd)
-
-
-if __name__ == '__main__':
- unittest.main()
diff --git a/tools/grit/grit/format/rc_unittest.py b/tools/grit/grit/format/rc_unittest.py
deleted file mode 100644
index d8094aa..0000000
--- a/tools/grit/grit/format/rc_unittest.py
+++ /dev/null
@@ -1,302 +0,0 @@
-#!/usr/bin/env python
-# Copyright (c) 2011 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.
-
-'''Unit tests for grit.format.rc'''
-
-import os
-import re
-import sys
-if __name__ == '__main__':
- sys.path.append(os.path.join(os.path.dirname(sys.argv[0]), '../..'))
-
-import tempfile
-import unittest
-import StringIO
-
-from grit.format import rc
-from grit import grd_reader
-from grit import util
-from grit.tool import build
-
-class DummyOutput(object):
- def __init__(self, type, language, file = 'hello.gif'):
- self.type = type
- self.language = language
- self.file = file
- def GetType(self):
- return self.type
- def GetLanguage(self):
- return self.language
- def GetOutputFilename(self):
- return self.file
-
-class FormatRcUnittest(unittest.TestCase):
- def testMessages(self):
- root = grd_reader.Parse(StringIO.StringIO('''
- <messages>
- <message name="IDS_BTN_GO" desc="Button text" meaning="verb">Go!</message>
- <message name="IDS_GREETING" desc="Printed to greet the currently logged in user">
- Hello <ph name="USERNAME">%s<ex>Joi</ex></ph>, how are you doing today?
- </message>
- <message name="BONGO" desc="Flippo nippo">
- Howdie "Mr. Elephant", how are you doing? \'\'\'
- </message>
- <message name="IDS_WITH_LINEBREAKS">
-Good day sir,
-I am a bee
-Sting sting
- </message>
- </messages>
- '''), flexible_root = True)
- util.FixRootForUnittest(root)
-
- buf = StringIO.StringIO()
- build.RcBuilder.ProcessNode(root, DummyOutput('rc_all', 'en'), buf)
- output = buf.getvalue()
- self.failUnless(output.strip() == u'''
-STRINGTABLE
-BEGIN
- IDS_BTN_GO "Go!"
- IDS_GREETING "Hello %s, how are you doing today?"
- BONGO "Howdie ""Mr. Elephant"", how are you doing? "
- IDS_WITH_LINEBREAKS "Good day sir,\\nI am a bee\\nSting sting"
-END'''.strip())
-
-
- def testRcSection(self):
- root = grd_reader.Parse(StringIO.StringIO('''
- <structures>
- <structure type="menu" name="IDC_KLONKMENU" file="grit\\testdata\klonk.rc" encoding="utf-16" />
- <structure type="dialog" name="IDD_ABOUTBOX" file="grit\\testdata\klonk.rc" encoding="utf-16" />
- <structure type="version" name="VS_VERSION_INFO" file="grit\\testdata\klonk.rc" encoding="utf-16" />
- </structures>'''), flexible_root = True)
- util.FixRootForUnittest(root)
- root.RunGatherers(recursive = True)
-
- buf = StringIO.StringIO()
- build.RcBuilder.ProcessNode(root, DummyOutput('rc_all', 'en'), buf)
- output = buf.getvalue().strip()
- expected = u'''
-IDC_KLONKMENU MENU
-BEGIN
- POPUP "&File"
- BEGIN
- MENUITEM "E&xit", IDM_EXIT
- MENUITEM "This be ""Klonk"" me like", ID_FILE_THISBE
- POPUP "gonk"
- BEGIN
- MENUITEM "Klonk && is ""good""", ID_GONK_KLONKIS
- END
- END
- POPUP "&Help"
- BEGIN
- MENUITEM "&About ...", IDM_ABOUT
- END
-END
-
-IDD_ABOUTBOX DIALOGEX 22, 17, 230, 75
-STYLE DS_SETFONT | DS_MODALFRAME | WS_CAPTION | WS_SYSMENU
-CAPTION "About"
-FONT 8, "System", 0, 0, 0x0
-BEGIN
- ICON IDI_KLONK,IDC_MYICON,14,9,20,20
- LTEXT "klonk Version ""yibbee"" 1.0",IDC_STATIC,49,10,119,8,
- SS_NOPREFIX
- LTEXT "Copyright (C) 2005",IDC_STATIC,49,20,119,8
- DEFPUSHBUTTON "OK",IDOK,195,6,30,11,WS_GROUP
- CONTROL "Jack ""Black"" Daniels",IDC_RADIO1,"Button",
- BS_AUTORADIOBUTTON,46,51,84,10
-END
-
-VS_VERSION_INFO VERSIONINFO
- FILEVERSION 1,0,0,1
- PRODUCTVERSION 1,0,0,1
- FILEFLAGSMASK 0x17L
-#ifdef _DEBUG
- FILEFLAGS 0x1L
-#else
- FILEFLAGS 0x0L
-#endif
- FILEOS 0x4L
- FILETYPE 0x1L
- FILESUBTYPE 0x0L
-BEGIN
- BLOCK "StringFileInfo"
- BEGIN
- BLOCK "040904b0"
- BEGIN
- VALUE "FileDescription", "klonk Application"
- VALUE "FileVersion", "1, 0, 0, 1"
- VALUE "InternalName", "klonk"
- VALUE "LegalCopyright", "Copyright (C) 2005"
- VALUE "OriginalFilename", "klonk.exe"
- VALUE "ProductName", " klonk Application"
- VALUE "ProductVersion", "1, 0, 0, 1"
- END
- END
- BLOCK "VarFileInfo"
- BEGIN
- VALUE "Translation", 0x409, 1200
- END
-END'''.strip()
- for expected_line, output_line in zip(expected.split(), output.split()):
- self.assertEqual(expected_line, output_line)
-
- def testRcIncludeStructure(self):
- root = grd_reader.Parse(StringIO.StringIO('''
- <structures>
- <structure type="tr_html" name="IDR_HTML" file="bingo.html"/>
- <structure type="tr_html" name="IDR_HTML2" file="bingo2.html"/>
- </structures>'''), flexible_root = True)
- util.FixRootForUnittest(root, '/temp')
- # We do not run gatherers as it is not needed and wouldn't find the file
-
- buf = StringIO.StringIO()
- build.RcBuilder.ProcessNode(root, DummyOutput('rc_all', 'en'), buf)
- output = buf.getvalue()
- expected = (u'IDR_HTML HTML "%s"\n'
- u'IDR_HTML2 HTML "%s"'
- % (util.normpath('/temp/bingo.html').replace('\\', '\\\\'),
- util.normpath('/temp/bingo2.html').replace('\\', '\\\\')))
- # hackety hack to work on win32&lin
- output = re.sub('"[c-zC-Z]:', '"', output)
- self.failUnless(output.strip() == expected)
-
- def testRcIncludeFile(self):
- root = grd_reader.Parse(StringIO.StringIO('''
- <includes>
- <include type="TXT" name="TEXT_ONE" file="bingo.txt"/>
- <include type="TXT" name="TEXT_TWO" file="bingo2.txt" filenameonly="true" />
- </includes>'''), flexible_root = True)
- util.FixRootForUnittest(root, '/temp')
-
- buf = StringIO.StringIO()
- build.RcBuilder.ProcessNode(root, DummyOutput('rc_all', 'en'), buf)
- output = buf.getvalue()
- expected = (u'TEXT_ONE TXT "%s"\n'
- u'TEXT_TWO TXT "%s"'
- % (util.normpath('/temp/bingo.txt').replace('\\', '\\\\'),
- 'bingo2.txt'))
- # hackety hack to work on win32&lin
- output = re.sub('"[c-zC-Z]:', '"', output)
- self.failUnless(output.strip() == expected)
-
- def testRcIncludeFlattenedHtmlFile(self):
- input_file = util.PathFromRoot('grit/testdata/include_test.html')
- output_file = '%s/HTML_FILE1_include_test.html' % tempfile.gettempdir()
- root = grd_reader.Parse(StringIO.StringIO('''
- <includes>
- <include name="HTML_FILE1" flattenhtml="true" file="%s" type="BINDATA" />
- </includes>''' % input_file), flexible_root = True)
- util.FixRootForUnittest(root, '.')
-
- buf = StringIO.StringIO()
- build.RcBuilder.ProcessNode(root, DummyOutput('rc_all', 'en', output_file),
- buf)
- output = buf.getvalue()
-
- expected = u'HTML_FILE1 BINDATA "HTML_FILE1_include_test.html"'
- # hackety hack to work on win32&lin
- output = re.sub('"[c-zC-Z]:', '"', output)
- self.failUnless(output.strip() == expected)
-
- fo = file(output_file)
- file_contents = fo.read()
- fo.close()
-
- # Check for the content added by the <include> tag.
- self.failUnless(file_contents.find('Hello Include!') != -1)
- # Check for the content that was removed by if tag.
- self.failUnless(file_contents.find('should be removed') == -1)
- # Check for the content that was kept in place by if.
- self.failUnless(file_contents.find('should be kept') != -1)
- self.failUnless(file_contents.find('in the middle...') != -1)
- self.failUnless(file_contents.find('at the end...') != -1)
- # Check for nested content that was kept
- self.failUnless(file_contents.find('nested true should be kept') != -1)
- self.failUnless(file_contents.find('silbing true should be kept') != -1)
- # Check for removed "<if>" and "</if>" tags.
- self.failUnless(file_contents.find('<if expr=') == -1)
- self.failUnless(file_contents.find('</if>') == -1)
-
-
- def testStructureNodeOutputfile(self):
- input_file = util.PathFromRoot('grit/testdata/simple.html')
- root = grd_reader.Parse(StringIO.StringIO(
- '<structure type="tr_html" name="IDR_HTML" file="%s" />' %input_file),
- flexible_root = True)
- util.FixRootForUnittest(root, '.')
- # We must run the gatherers since we'll be wanting the translation of the
- # file. The file exists in the location pointed to.
- root.RunGatherers(recursive=True)
-
- output_dir = tempfile.gettempdir()
- en_file = root.FileForLanguage('en', output_dir)
- self.failUnless(en_file == input_file)
- fr_file = root.FileForLanguage('fr', output_dir)
- self.failUnless(fr_file == os.path.join(output_dir, 'fr_simple.html'))
-
- fo = file(fr_file)
- contents = fo.read()
- fo.close()
-
- self.failUnless(contents.find('<p>') != -1) # should contain the markup
- self.failUnless(contents.find('Hello!') == -1) # should be translated
-
-
- def testFallbackToEnglish(self):
- root = grd_reader.Parse(StringIO.StringIO('''<?xml version="1.0" encoding="UTF-8"?>
- <grit latest_public_release="2" source_lang_id="en-US" current_release="3" base_dir=".">
- <release seq="1" allow_pseudo="False">
- <structures fallback_to_english="True">
- <structure type="dialog" name="IDD_ABOUTBOX" file="grit\\testdata\klonk.rc" encoding="utf-16" />
- </structures>
- </release>
- </grit>'''), util.PathFromRoot('.'))
- util.FixRootForUnittest(root)
- root.RunGatherers(recursive = True)
-
- node = root.GetNodeById("IDD_ABOUTBOX")
- formatter = node.ItemFormatter('rc_all')
- output = formatter.Format(node, 'bingobongo')
- self.failUnless(output.strip() == '''IDD_ABOUTBOX DIALOGEX 22, 17, 230, 75
-STYLE DS_SETFONT | DS_MODALFRAME | WS_CAPTION | WS_SYSMENU
-CAPTION "About"
-FONT 8, "System", 0, 0, 0x0
-BEGIN
- ICON IDI_KLONK,IDC_MYICON,14,9,20,20
- LTEXT "klonk Version ""yibbee"" 1.0",IDC_STATIC,49,10,119,8,
- SS_NOPREFIX
- LTEXT "Copyright (C) 2005",IDC_STATIC,49,20,119,8
- DEFPUSHBUTTON "OK",IDOK,195,6,30,11,WS_GROUP
- CONTROL "Jack ""Black"" Daniels",IDC_RADIO1,"Button",
- BS_AUTORADIOBUTTON,46,51,84,10
-END''')
-
-
- def testRelativePath(self):
- ''' Verify that _MakeRelativePath works in some tricky cases.'''
- def TestRelativePathCombinations(base_path, other_path, expected_result):
- ''' Verify that the relative path function works for
- the given paths regardless of whether or not they end with
- a trailing slash.'''
- for path1 in [base_path, base_path + os.path.sep]:
- for path2 in [other_path, other_path + os.path.sep]:
- result = rc._MakeRelativePath(path1, path2)
- self.failUnless(result == expected_result)
-
- # set-up variables
- root_dir = 'c:%sa' % os.path.sep
- result1 = '..%sabc' % os.path.sep
- path1 = root_dir + 'bc'
- result2 = 'bc'
- path2 = '%s%s%s' % (root_dir, os.path.sep, result2)
- # run the tests
- TestRelativePathCombinations(root_dir, path1, result1)
- TestRelativePathCombinations(root_dir, path2, result2)
-
-
-if __name__ == '__main__':
- unittest.main()
diff --git a/tools/grit/grit/format/repack.py b/tools/grit/grit/format/repack.py
deleted file mode 100644
index 3f312a4..0000000
--- a/tools/grit/grit/format/repack.py
+++ /dev/null
@@ -1,24 +0,0 @@
-#!/usr/bin/python
-# Copyright (c) 2011 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.
-
-"""
-A simple utility function to merge data pack files into a single data pack. See
-http://dev.chromium.org/developers/design-documents/linuxresourcesandlocalizedstrings
-for details about the file format.
-"""
-
-import sys
-
-import data_pack
-
-def main(argv):
- if len(argv) < 3:
- print ("Usage:\n %s <output_filename> <input_file1> [input_file2] ... " %
- argv[0])
- sys.exit(-1)
- data_pack.DataPack.RePack(argv[1], argv[2:])
-
-if '__main__' == __name__:
- main(sys.argv)
diff --git a/tools/grit/grit/format/resource_map.py b/tools/grit/grit/format/resource_map.py
deleted file mode 100644
index 4527af8..0000000
--- a/tools/grit/grit/format/resource_map.py
+++ /dev/null
@@ -1,127 +0,0 @@
-#!/usr/bin/python2.4
-# Copyright (c) 2010 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.
-
-'''This file contains item formatters for resource_map_header and
-resource_map_source files. A resource map is a mapping between resource names
-(string) and the internal resource ID.'''
-
-import os
-
-from grit import util
-from grit.format import interface
-
-def GetMapName(root):
- '''Get the name of the resource map based on the header file name. E.g.,
- if our header filename is theme_resources.h, we name our resource map
- kThemeResourcesMap.
-
- |root| is the grd file root.'''
- outputs = root.GetOutputFiles()
- rc_header_file = None
- for output in outputs:
- if 'rc_header' == output.GetType():
- rc_header_file = output.GetFilename()
- if not rc_header_file:
- raise Exception('unable to find resource header filename')
- filename = os.path.splitext(os.path.split(rc_header_file)[1])[0]
- filename = filename[0].upper() + filename[1:]
- while filename.find('_') != -1:
- pos = filename.find('_')
- if pos >= len(filename):
- break
- filename = filename[:pos] + filename[pos + 1].upper() + filename[pos + 2:]
- return 'k' + filename
-
-
-class HeaderTopLevel(interface.ItemFormatter):
- '''Create the header file for the resource mapping. This file just declares
- an array of name/value pairs.'''
- def Format(self, item, lang='en', begin_item=True, output_dir='.'):
- if not begin_item:
- return ''
- return '''\
-// Copyright (c) %(year)d 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.
-// This file is automatically generated by GRIT. Do not edit.
-
-#include <stddef.h>
-
-#ifndef GRIT_RESOURCE_MAP_STRUCT_
-#define GRIT_RESOURCE_MAP_STRUCT_
-struct GritResourceMap {
- const char* const name;
- int value;
-};
-#endif // GRIT_RESOURCE_MAP_STRUCT_
-
-extern const GritResourceMap %(map_name)s[];
-extern const size_t %(map_name)sSize;
-''' % { 'year': util.GetCurrentYear(),
- 'map_name': GetMapName(item.GetRoot()),
- }
-
-
-class SourceTopLevel(interface.ItemFormatter):
- '''Create the C++ source file for the resource mapping. This class handles
- the header/footer of the file.'''
- def Format(self, item, lang='en', begin_item=True, output_dir='.'):
- if begin_item:
- grit_root = item.GetRoot()
- outputs = grit_root.GetOutputFiles()
- rc_header_file = None
- map_header_file = None
- for output in outputs:
- if 'rc_header' == output.GetType():
- rc_header_file = output.GetFilename()
- elif 'resource_map_header' == output.GetType():
- map_header_file = output.GetFilename()
- if not rc_header_file or not map_header_file:
- raise Exception('resource_map_source output type requires '
- 'resource_map_header and rc_header outputs')
-
- return '''\
-// Copyright (c) %(year)d 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.
-// This file is automatically generated by GRIT. Do not edit.
-
-#include "%(map_header_file)s"
-
-#include "base/basictypes.h"
-#include "%(rc_header_file)s"
-
-const GritResourceMap %(map_name)s[] = {
-''' % { 'year': util.GetCurrentYear(),
- 'map_header_file': map_header_file,
- 'rc_header_file': rc_header_file,
- 'map_name': GetMapName(item.GetRoot()),
- }
- else:
- # Return the footer text.
- return '''\
-};
-
-const size_t %(map_name)sSize = arraysize(%(map_name)s);
-''' % { 'map_name': GetMapName(item.GetRoot()) }
-
-
-class SourceInclude(interface.ItemFormatter):
- '''Populate the resource mapping. For each include, we map a string to
- the resource ID.'''
- def Format(self, item, lang='en', begin_item=True, output_dir='.'):
- if not begin_item:
- return ''
- return ' {"%s", %s},\n' % (item.attrs['name'], item.attrs['name'])
-
-
-class SourceFileInclude(interface.ItemFormatter):
- '''Populate the resource mapping. For each include, we map a filename to
- the resource ID.'''
- def Format(self, item, lang='en', begin_item=True, output_dir='.'):
- if not begin_item:
- return ''
- filename = item.attrs['file'].replace("\\", "/")
- return ' {"%s", %s},\n' % (filename, item.attrs['name'])
diff --git a/tools/grit/grit/gather/__init__.py b/tools/grit/grit/gather/__init__.py
deleted file mode 100644
index 2e90181..0000000
--- a/tools/grit/grit/gather/__init__.py
+++ /dev/null
@@ -1,9 +0,0 @@
-#!/usr/bin/python2.4
-# Copyright (c) 2006-2008 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.
-
-'''Module grit.gather
-'''
-
-pass
diff --git a/tools/grit/grit/gather/admin_template.py b/tools/grit/grit/gather/admin_template.py
deleted file mode 100644
index fc07ed8..0000000
--- a/tools/grit/grit/gather/admin_template.py
+++ /dev/null
@@ -1,79 +0,0 @@
-#!/usr/bin/python2.4
-# Copyright (c) 2006-2008 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.
-
-'''Gatherer for administrative template files.
-'''
-
-import re
-import types
-
-from grit.gather import regexp
-from grit import exception
-from grit import tclib
-from grit import util
-
-
-class MalformedAdminTemplateException(exception.Base):
- '''This file doesn't look like a .adm file to me.'''
- def __init__(self, msg=''):
- exception.Base.__init__(self, msg)
-
-
-class AdmGatherer(regexp.RegexpGatherer):
- '''Gatherer for the translateable portions of an admin template.
-
- This gatherer currently makes the following assumptions:
- - there is only one [strings] section and it is always the last section
- of the file
- - translateable strings do not need to be escaped.
- '''
-
- # Finds the strings section as the group named 'strings'
- _STRINGS_SECTION = re.compile('(?P<first_part>.+^\[strings\])(?P<strings>.+)\Z',
- re.MULTILINE | re.DOTALL)
-
- # Finds the translateable sections from within the [strings] section.
- _TRANSLATEABLES = re.compile('^\s*[A-Za-z0-9_]+\s*=\s*"(?P<text>.+)"\s*$',
- re.MULTILINE)
-
- def __init__(self, text):
- regexp.RegexpGatherer.__init__(self, text)
-
- def Escape(self, text):
- return text.replace('\n', '\\n')
-
- def UnEscape(self, text):
- return text.replace('\\n', '\n')
-
- def Parse(self):
- if self.have_parsed_:
- return
- m = self._STRINGS_SECTION.match(self.text_)
- if not m:
- raise MalformedAdminTemplateException()
- # Add the first part, which is all nontranslateable, to the skeleton
- self._AddNontranslateableChunk(m.group('first_part'))
- # Then parse the rest using the _TRANSLATEABLES regexp.
- self._RegExpParse(self._TRANSLATEABLES, m.group('strings'))
-
- # static method
- def FromFile(adm_file, ext_key=None, encoding='cp1252'):
- '''Loads the contents of 'adm_file' in encoding 'encoding' and creates
- an AdmGatherer instance that gathers from those contents.
-
- The 'ext_key' parameter is ignored.
-
- Args:
- adm_file: file('bingo.rc') | 'filename.rc'
- encoding: 'utf-8'
-
- Return:
- AdmGatherer(contents_of_file)
- '''
- if isinstance(adm_file, types.StringTypes):
- adm_file = util.WrapInputStream(file(adm_file, 'r'), encoding)
- return AdmGatherer(adm_file.read())
- FromFile = staticmethod(FromFile)
-
diff --git a/tools/grit/grit/gather/admin_template_unittest.py b/tools/grit/grit/gather/admin_template_unittest.py
deleted file mode 100644
index e93588d..0000000
--- a/tools/grit/grit/gather/admin_template_unittest.py
+++ /dev/null
@@ -1,116 +0,0 @@
-#!/usr/bin/python2.4
-# Copyright (c) 2011 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.
-
-'''Unit tests for the admin template gatherer.'''
-
-import os
-import sys
-if __name__ == '__main__':
- sys.path.append(os.path.join(os.path.dirname(sys.argv[0]), '../..'))
-
-import StringIO
-import tempfile
-import unittest
-
-from grit.gather import admin_template
-from grit import util
-from grit import grd_reader
-from grit import grit_runner
-from grit.tool import build
-
-
-class AdmGathererUnittest(unittest.TestCase):
- def testParsingAndTranslating(self):
- pseudofile = StringIO.StringIO(
- 'bingo bongo\n'
- 'ding dong\n'
- '[strings] \n'
- 'whatcha="bingo bongo"\n'
- 'gotcha = "bingolabongola "the wise" fingulafongula" \n')
- gatherer = admin_template.AdmGatherer.FromFile(pseudofile)
- gatherer.Parse()
- self.failUnless(len(gatherer.GetCliques()) == 2)
- self.failUnless(gatherer.GetCliques()[1].GetMessage().GetRealContent() ==
- 'bingolabongola "the wise" fingulafongula')
-
- translation = gatherer.Translate('en')
- self.failUnless(translation == gatherer.GetText().strip())
-
- def testErrorHandling(self):
- pseudofile = StringIO.StringIO(
- 'bingo bongo\n'
- 'ding dong\n'
- 'whatcha="bingo bongo"\n'
- 'gotcha = "bingolabongola "the wise" fingulafongula" \n')
- gatherer = admin_template.AdmGatherer.FromFile(pseudofile)
- self.assertRaises(admin_template.MalformedAdminTemplateException,
- gatherer.Parse)
-
- _TRANSLATABLES_FROM_FILE = (
- 'Google', 'Google Desktop', 'Preferences',
- 'Controls Google Desktop preferences',
- 'Indexing and Capture Control',
- 'Controls what files, web pages, and other content will be indexed by Google Desktop.',
- 'Prevent indexing of email',
- # there are lots more but we don't check any further
- )
-
- def VerifyCliquesFromAdmFile(self, cliques):
- self.failUnless(len(cliques) > 20)
- for ix in range(len(self._TRANSLATABLES_FROM_FILE)):
- text = cliques[ix].GetMessage().GetRealContent()
- self.failUnless(text == self._TRANSLATABLES_FROM_FILE[ix])
-
- def testFromFile(self):
- fname = util.PathFromRoot('grit/testdata/GoogleDesktop.adm')
- gatherer = admin_template.AdmGatherer.FromFile(fname)
- gatherer.Parse()
- cliques = gatherer.GetCliques()
- self.VerifyCliquesFromAdmFile(cliques)
-
- def MakeGrd(self):
- grd = grd_reader.Parse(StringIO.StringIO('''<?xml version="1.0" encoding="UTF-8"?>
- <grit latest_public_release="2" source_lang_id="en-US" current_release="3">
- <release seq="3">
- <structures>
- <structure type="admin_template" name="IDAT_GOOGLE_DESKTOP_SEARCH"
- file="GoogleDesktop.adm" exclude_from_rc="true" />
- <structure type="txt" name="BINGOBONGO"
- file="README.txt" exclude_from_rc="true" />
- </structures>
- </release>
- <outputs>
- <output filename="de_res.rc" type="rc_all" lang="de" />
- </outputs>
- </grit>'''), util.PathFromRoot('grit/testdata'))
- grd.RunGatherers(recursive=True)
- return grd
-
- def testInGrd(self):
- grd = self.MakeGrd()
- cliques = grd.children[0].children[0].children[0].GetCliques()
- self.VerifyCliquesFromAdmFile(cliques)
-
- def testFileIsOutput(self):
- grd = self.MakeGrd()
- dirname = tempfile.mkdtemp()
- try:
- tool = build.RcBuilder()
- tool.o = grit_runner.Options()
- tool.output_directory = dirname
- tool.res = grd
- tool.Process()
-
- self.failUnless(os.path.isfile(
- os.path.join(dirname, 'de_GoogleDesktop.adm')))
- self.failUnless(os.path.isfile(
- os.path.join(dirname, 'de_README.txt')))
- finally:
- for f in os.listdir(dirname):
- os.unlink(os.path.join(dirname, f))
- os.rmdir(dirname)
-
-if __name__ == '__main__':
- unittest.main()
diff --git a/tools/grit/grit/gather/interface.py b/tools/grit/grit/gather/interface.py
deleted file mode 100644
index 8a6532e..0000000
--- a/tools/grit/grit/gather/interface.py
+++ /dev/null
@@ -1,108 +0,0 @@
-#!/usr/bin/python2.4
-# Copyright (c) 2006-2008 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.
-
-'''Interface for all gatherers.
-'''
-
-
-from grit import clique
-
-
-class GathererBase(object):
- '''Interface for all gatherer implementations. Subclasses must implement
- all methods that raise NotImplemented.'''
-
- def __init__(self):
- # A default uberclique that is local to this object. Users can override
- # this with the uberclique they are using.
- self.uberclique = clique.UberClique()
- # Indicates whether this gatherer is a skeleton gatherer, in which case
- # we should not do some types of processing on the translateable bits.
- self.is_skeleton = False
-
- def SetUberClique(self, uberclique):
- '''Overrides the default uberclique so that cliques created by this object
- become part of the uberclique supplied by the user.
- '''
- self.uberclique = uberclique
-
- def SetSkeleton(self, is_skeleton):
- self.is_skeleton = is_skeleton
-
- def IsSkeleton(self):
- return self.is_skeleton
-
- def Parse(self):
- '''Parses the contents of what is being gathered.'''
- raise NotImplementedError()
-
- def GetText(self):
- '''Returns the text of what is being gathered.'''
- raise NotImplementedError()
-
- def GetTextualIds(self):
- '''Returns the mnemonic IDs that need to be defined for the resource
- being gathered to compile correctly.'''
- return []
-
- def GetCliques(self):
- '''Returns the MessageClique objects for all translateable portions.'''
- return []
-
- def Translate(self, lang, pseudo_if_not_available=True,
- skeleton_gatherer=None, fallback_to_english=False):
- '''Returns the resource being gathered, with translateable portions filled
- with the translation for language 'lang'.
-
- If pseudo_if_not_available is true, a pseudotranslation will be used for any
- message that doesn't have a real translation available.
-
- If no translation is available and pseudo_if_not_available is false,
- fallback_to_english controls the behavior. If it is false, throw an error.
- If it is true, use the English version of the message as its own
- "translation".
-
- If skeleton_gatherer is specified, the translation will use the nontranslateable
- parts from the gatherer 'skeleton_gatherer', which must be of the same type
- as 'self'.
-
- If fallback_to_english
-
- Args:
- lang: 'en'
- pseudo_if_not_available: True | False
- skeleton_gatherer: other_gatherer
- fallback_to_english: True | False
-
- Return:
- e.g. 'ID_THIS_SECTION TYPE\n...BEGIN\n "Translated message"\n......\nEND'
-
- Raises:
- grit.exception.NotReady() if used before Parse() has been successfully
- called.
- grit.exception.NoSuchTranslation() if 'pseudo_if_not_available' and
- fallback_to_english are both false and there is no translation for the
- requested language.
- '''
- raise NotImplementedError()
-
- def FromFile(rc_file, extkey=None, encoding = 'cp1252'):
- '''Loads the resource from the file 'rc_file'. Optionally an external key
- (which gets passed to the gatherer's constructor) can be specified.
-
- If 'rc_file' is a filename, it will be opened for reading using 'encoding'.
- Otherwise the 'encoding' parameter is ignored.
-
- Args:
- rc_file: file('') | 'filename.rc'
- extkey: e.g. 'ID_MY_DIALOG'
- encoding: 'utf-8'
-
- Return:
- grit.gather.interface.GathererBase subclass
- '''
- raise NotImplementedError()
- FromFile = staticmethod(FromFile)
-
diff --git a/tools/grit/grit/gather/json_loader.py b/tools/grit/grit/gather/json_loader.py
deleted file mode 100644
index e2518e4..0000000
--- a/tools/grit/grit/gather/json_loader.py
+++ /dev/null
@@ -1,53 +0,0 @@
-# Copyright (c) 2010 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 types
-
-from grit.gather import interface
-from grit import util
-
-
-class JsonLoader(interface.GathererBase):
- '''A simple gatherer that loads and parses a JSON file.'''
-
- def __init__(self, json_text):
- '''Initializes a gatherer object with JSON input.
-
- Args:
- json_text: A string containing a JSON expression.
- '''
- super(type(self), self).__init__()
- self._json_text = json_text
- self._data = None
-
- def Parse(self):
- '''Parses the text of self._json_text into the data structure in
- self._data.
- '''
- globs = {}
- exec('data = ' + self._json_text, globs)
- self._data = globs['data']
-
- def GetData(self):
- '''Returns the parsed JSON data.'''
- return self._data
-
- def FromFile(filename_or_stream, extkey, encoding):
- '''Creates a JSONLoader instance from a file or stream.
-
- Args:
- filename_or_stream: The source of JSON data.
- extkey: Unused, see interface.py.
- encoding: The encoding used in the JSON file. (Note that it should
- not contain localized strings.)
-
- Returns:
- The JSONLoader instance holding the JSON data unparsed.
- '''
- if isinstance(filename_or_stream, types.StringTypes):
- filename_or_stream = \
- util.WrapInputStream(file(filename_or_stream, 'rU'), encoding)
- return JsonLoader(filename_or_stream.read())
- FromFile = staticmethod(FromFile)
diff --git a/tools/grit/grit/gather/muppet_strings.py b/tools/grit/grit/gather/muppet_strings.py
deleted file mode 100644
index 119f851..0000000
--- a/tools/grit/grit/gather/muppet_strings.py
+++ /dev/null
@@ -1,142 +0,0 @@
-#!/usr/bin/python2.4
-# Copyright (c) 2006-2008 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.
-
-'''Support for "strings.xml" format used by Muppet plug-ins in Google Desktop.'''
-
-import StringIO
-import types
-import re
-import xml.sax
-import xml.sax.handler
-import xml.sax.saxutils
-
-from grit.gather import regexp
-from grit import util
-from grit import tclib
-
-# Placeholders can be defined in strings.xml files by putting the name of the
-# placeholder between [![ and ]!] e.g. <MSG>Hello [![USER]!] how are you<MSG>
-PLACEHOLDER_RE = re.compile('(\[!\[|\]!\])')
-
-
-class MuppetStringsContentHandler(xml.sax.handler.ContentHandler):
- '''A very dumb parser for splitting the strings.xml file into translateable
- and nontranslateable chunks.'''
-
- def __init__(self, parent):
- self.curr_elem = ''
- self.curr_text = ''
- self.parent = parent
- self.description = ''
- self.meaning = ''
- self.translateable = True
-
- def startElement(self, name, attrs):
- if (name != 'strings'):
- self.curr_elem = name
-
- attr_names = attrs.getQNames()
- if 'desc' in attr_names:
- self.description = attrs.getValueByQName('desc')
- if 'meaning' in attr_names:
- self.meaning = attrs.getValueByQName('meaning')
- if 'translateable' in attr_names:
- value = attrs.getValueByQName('translateable')
- if value.lower() not in ['true', 'yes']:
- self.translateable = False
-
- att_text = []
- for attr_name in attr_names:
- att_text.append(' ')
- att_text.append(attr_name)
- att_text.append('=')
- att_text.append(
- xml.sax.saxutils.quoteattr(attrs.getValueByQName(attr_name)))
-
- self.parent._AddNontranslateableChunk("<%s%s>" %
- (name, ''.join(att_text)))
-
- def characters(self, content):
- if self.curr_elem != '':
- self.curr_text += content
-
- def endElement(self, name):
- if name != 'strings':
- self.parent.AddMessage(self.curr_text, self.description,
- self.meaning, self.translateable)
- self.parent._AddNontranslateableChunk("</%s>\n" % name)
- self.curr_elem = ''
- self.curr_text = ''
- self.description = ''
- self.meaning = ''
- self.translateable = True
-
- def ignorableWhitespace(self, whitespace):
- pass
-
-class MuppetStrings(regexp.RegexpGatherer):
- '''Supports the strings.xml format used by Muppet gadgets.'''
-
- def __init__(self, text):
- if util.IsExtraVerbose():
- print text
- regexp.RegexpGatherer.__init__(self, text)
-
- def AddMessage(self, msgtext, description, meaning, translateable):
- if msgtext == '':
- return
-
- msg = tclib.Message(description=description, meaning=meaning)
-
- unescaped_text = self.UnEscape(msgtext)
- parts = PLACEHOLDER_RE.split(unescaped_text)
- in_placeholder = False
- for part in parts:
- if part == '':
- continue
- elif part == '[![':
- in_placeholder = True
- elif part == ']!]':
- in_placeholder = False
- else:
- if in_placeholder:
- msg.AppendPlaceholder(tclib.Placeholder(part, '[![%s]!]' % part,
- '(placeholder)'))
- else:
- msg.AppendText(part)
-
- self.skeleton_.append(
- self.uberclique.MakeClique(msg, translateable=translateable))
-
- # if statement needed because this is supposed to be idempotent (so never
- # set back to false)
- if translateable:
- self.translatable_chunk_ = True
-
- # Although we use the RegexpGatherer base class, we do not use the
- # _RegExpParse method of that class to implement Parse(). Instead, we
- # parse using a SAX parser.
- def Parse(self):
- if (self.have_parsed_):
- return
- self.have_parsed_ = True
- self._AddNontranslateableChunk(u'<strings>\n')
- stream = StringIO.StringIO(self.text_)
- handler = MuppetStringsContentHandler(self)
- xml.sax.parse(stream, handler)
- self._AddNontranslateableChunk(u'</strings>\n')
-
- def Escape(self, text):
- return util.EncodeCdata(text)
-
- def FromFile(filename_or_stream, extkey=None, encoding='cp1252'):
- if isinstance(filename_or_stream, types.StringTypes):
- if util.IsVerbose():
- print "MuppetStrings reading file %s, encoding %s" % (
- filename_or_stream, encoding)
- filename_or_stream = util.WrapInputStream(file(filename_or_stream, 'r'), encoding)
- return MuppetStrings(filename_or_stream.read())
- FromFile = staticmethod(FromFile)
-
diff --git a/tools/grit/grit/gather/muppet_strings_unittest.py b/tools/grit/grit/gather/muppet_strings_unittest.py
deleted file mode 100644
index 434d9f8..0000000
--- a/tools/grit/grit/gather/muppet_strings_unittest.py
+++ /dev/null
@@ -1,66 +0,0 @@
-#!/usr/bin/python2.4
-# Copyright (c) 2006-2008 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.
-
-'''Unit tests for grit.gather.muppet_strings'''
-
-import os
-import sys
-if __name__ == '__main__':
- sys.path.append(os.path.join(os.path.dirname(sys.argv[0]), '../..'))
-
-import unittest
-
-from grit.gather import muppet_strings
-
-class MuppetStringsUnittest(unittest.TestCase):
- def testParsing(self):
- original = '''<strings><BLA desc="Says hello">hello!</BLA><BINGO>YEEEESSS!!!</BINGO></strings>'''
- gatherer = muppet_strings.MuppetStrings(original)
- gatherer.Parse()
- self.failUnless(len(gatherer.GetCliques()) == 2)
- self.failUnless(gatherer.Translate('en').replace('\n', '') == original)
-
- def testEscapingAndLinebreaks(self):
- original = ('''\
-<strings>
-<LINEBREAK desc="Howdie">Hello
-there
-how
-are
-you?</LINEBREAK> <ESCAPED meaning="bingo">4 &lt; 6</ESCAPED>
-</strings>''')
- gatherer = muppet_strings.MuppetStrings(original)
- gatherer.Parse()
- self.failUnless(gatherer.GetCliques()[0].translateable)
- self.failUnless(len(gatherer.GetCliques()) == 2)
- self.failUnless(gatherer.GetCliques()[0].GetMessage().GetRealContent() ==
- 'Hello\nthere\nhow\nare\nyou?')
- self.failUnless(gatherer.GetCliques()[0].GetMessage().GetDescription() == 'Howdie')
- self.failUnless(gatherer.GetCliques()[1].GetMessage().GetRealContent() ==
- '4 < 6')
- self.failUnless(gatherer.GetCliques()[1].GetMessage().GetMeaning() == 'bingo')
-
- def testPlaceholders(self):
- original = "<strings><MESSAGE translateable='True'>Hello [![USER]!] how are you? [![HOUR]!]:[![MINUTE]!]</MESSAGE></strings>"
- gatherer = muppet_strings.MuppetStrings(original)
- gatherer.Parse()
- self.failUnless(gatherer.GetCliques()[0].translateable)
- msg = gatherer.GetCliques()[0].GetMessage()
- self.failUnless(len(msg.GetPlaceholders()) == 3)
- ph = msg.GetPlaceholders()[0]
- self.failUnless(ph.GetOriginal() == '[![USER]!]')
- self.failUnless(ph.GetPresentation() == 'USER')
-
- def testTranslateable(self):
- original = "<strings><BINGO translateable='false'>Yo yo hi there</BINGO></strings>"
- gatherer = muppet_strings.MuppetStrings(original)
- gatherer.Parse()
- msg = gatherer.GetCliques()[0].GetMessage()
- self.failUnless(msg.GetRealContent() == "Yo yo hi there")
- self.failUnless(not gatherer.GetCliques()[0].translateable)
-
-if __name__ == '__main__':
- unittest.main()
-
diff --git a/tools/grit/grit/gather/policy_json.py b/tools/grit/grit/gather/policy_json.py
deleted file mode 100644
index 378c696..0000000
--- a/tools/grit/grit/gather/policy_json.py
+++ /dev/null
@@ -1,258 +0,0 @@
-#!/usr/bin/python2.4
-# Copyright (c) 2011 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.
-
-'''Support for "policy_templates.json" format used by the policy template
-generator as a source for generating ADM,ADMX,etc files.'''
-
-import types
-import pprint
-import re
-
-from grit.gather import skeleton_gatherer
-from grit import util
-from grit import tclib
-from xml.dom import minidom
-
-
-class PolicyJson(skeleton_gatherer.SkeletonGatherer):
- '''Collects and translates the following strings from policy_templates.json:
- - captions,descriptions and labels of policies
- - captions of enumeration items
- - misc strings from the 'messages' section
- Translatable strings may have untranslateable placeholders with the same
- format that is used in .grd files.
- '''
-
- def __init__(self, text):
- if util.IsExtraVerbose():
- print text
- skeleton_gatherer.SkeletonGatherer.__init__(self)
- self.text_ = text
-
- def _ParsePlaceholder(self, placeholder, msg):
- '''Extracts a placeholder from a DOM node and adds it to a tclib Message.
-
- Args:
- placeholder: A DOM node of the form:
- <ph name="PLACEHOLDER_NAME">Placeholder text<ex>Example value</ex></ph>
- msg: The placeholder is added to this message.
- '''
- text = []
- example_text = []
- for node1 in placeholder.childNodes:
- if (node1.nodeType == minidom.Node.TEXT_NODE):
- text.append(node1.data)
- elif (node1.nodeType == minidom.Node.ELEMENT_NODE and
- node1.tagName == 'ex'):
- for node2 in node1.childNodes:
- example_text.append(node2.toxml())
- else:
- raise Exception('Unexpected element inside a placeholder: ' +
- node2.toxml())
- if example_text == []:
- # In such cases the original text is okay for an example.
- example_text = text
- msg.AppendPlaceholder(tclib.Placeholder(
- placeholder.attributes['name'].value,
- ''.join(text).strip(),
- ''.join(example_text).strip()))
-
- def _ParseMessage(self, string, desc):
- '''Parses a given string and adds it to the output as a translatable chunk
- with a given description.
-
- Args:
- string: The message string to parse.
- desc: The description of the message (for the translators).
- '''
- msg = tclib.Message(description=desc)
- xml = '<msg>' + string + '</msg>'
- node = minidom.parseString(xml).childNodes[0]
- for child in node.childNodes:
- if child.nodeType == minidom.Node.TEXT_NODE:
- msg.AppendText(child.data)
- elif child.nodeType == minidom.Node.ELEMENT_NODE:
- if child.tagName == 'ph':
- self._ParsePlaceholder(child, msg)
- else:
- raise Exception("Not implemented.")
- else:
- raise Exception("Not implemented.")
- self.skeleton_.append(self.uberclique.MakeClique(msg))
-
- def _ParseNode(self, node):
- '''Traverses the subtree of a DOM node, and register a tclib message for
- all the <message> nodes.
- '''
- att_text = []
- if node.attributes:
- items = node.attributes.items()
- items.sort()
- for key, value in items:
- att_text.append(' %s=\"%s\"' % (key, value))
- self._AddNontranslateableChunk("<%s%s>" %
- (node.tagName, ''.join(att_text)))
- if node.tagName == 'message':
- msg = tclib.Message(description=node.attributes['desc'])
- for child in node.childNodes:
- if child.nodeType == minidom.Node.TEXT_NODE:
- if msg == None:
- self._AddNontranslateableChunk(child.data)
- else:
- msg.AppendText(child.data)
- elif child.nodeType == minidom.Node.ELEMENT_NODE:
- if child.tagName == 'ph':
- self._ParsePlaceholder(child, msg)
- else:
- assert False
- self.skeleton_.append(self.uberclique.MakeClique(msg))
- else:
- for child in node.childNodes:
- if child.nodeType == minidom.Node.TEXT_NODE:
- self._AddNontranslateableChunk(child.data)
- elif node.nodeType == minidom.Node.ELEMENT_NODE:
- self._ParseNode(child)
-
- self._AddNontranslateableChunk("</%s>" % node.tagName)
-
- def _AddIndentedNontranslateableChunk(self, depth, string):
- '''Adds a nontranslateable chunk of text to the internally stored output.
-
- Args:
- depth: The number of double spaces to prepend to the next argument string.
- string: The chunk of text to add.
- '''
- result = []
- while depth > 0:
- result.append(' ')
- depth = depth - 1
- result.append(string)
- self._AddNontranslateableChunk(''.join(result))
-
- def _GetDescription(self, item, item_type, parent_item, key):
- '''Creates a description for a translatable message. The description gives
- some context for the person who will translate this message.
-
- Args:
- item: A policy or an enumeration item.
- item_type: 'enum_item' | 'policy'
- parent_item: The owner of item. (A policy of type group or enum.)
- key: The name of the key to parse.
- depth: The level of indentation.
- '''
- key_map = {
- 'desc': 'Description',
- 'caption': 'Caption',
- 'label': 'Label',
- }
- if item_type == 'policy':
- return '%s of the policy named %s' % (key_map[key], item['name'])
- elif item_type == 'enum_item':
- return ('%s of the option named %s in policy %s' %
- (key_map[key], item['name'], parent_item['name']))
- else:
- raise Exception('Unexpected type %s' % item_type)
-
- def _AddPolicyKey(self, item, item_type, parent_item, key, depth):
- '''Given a policy/enumeration item and a key, adds that key and its value
- into the output.
- E.g.:
- 'example_value': 123
- If key indicates that the value is a translatable string, then it is parsed
- as a translatable string.
-
- Args:
- item: A policy or an enumeration item.
- item_type: 'enum_item' | 'policy'
- parent_item: The owner of item. (A policy of type group or enum.)
- key: The name of the key to parse.
- depth: The level of indentation.
- '''
- self._AddIndentedNontranslateableChunk(depth, "'%s': " % key)
- if key in ('desc', 'caption', 'label'):
- self._AddNontranslateableChunk("'''")
- self._ParseMessage(
- item[key],
- self._GetDescription(item, item_type, parent_item, key))
- self._AddNontranslateableChunk("''',\n")
- else:
- str_val = item[key]
- if type(str_val) == types.StringType:
- str_val = "'%s'" % self.Escape(str_val)
- else:
- str_val = str(str_val)
- self._AddNontranslateableChunk(str_val + ',\n')
-
- def _AddItems(self, items, item_type, parent_item, depth):
- '''Parses and adds a list of items from the JSON file. Items can be policies
- or parts of an enum policy.
-
- Args:
- items: Either a list of policies or a list of dictionaries.
- item_type: 'enum_item' | 'policy'
- parent_item: If items contains a list of policies, then this is the policy
- group that owns them. If items contains a list of enumeration items,
- then this is the enum policy that holds them.
- depth: Indicates the depth of our position in the JSON hierarchy. Used to
- add nice line-indent to the output.
- '''
- for item1 in items:
- self._AddIndentedNontranslateableChunk(depth, "{\n")
- for key in item1.keys():
- if key == 'items':
- self._AddIndentedNontranslateableChunk(depth + 1, "'items': [\n")
- self._AddItems(item1['items'], 'enum_item', item1, depth + 2)
- self._AddIndentedNontranslateableChunk(depth + 1, "],\n")
- elif key == 'policies':
- self._AddIndentedNontranslateableChunk(depth + 1, "'policies': [\n")
- self._AddItems(item1['policies'], 'policy', item1, depth + 2)
- self._AddIndentedNontranslateableChunk(depth + 1, "],\n")
- else:
- self._AddPolicyKey(item1, item_type, parent_item, key, depth + 1)
- self._AddIndentedNontranslateableChunk(depth, "},\n")
-
- def _AddMessages(self):
- '''Processed and adds the 'messages' section to the output.'''
- self._AddNontranslateableChunk(" 'messages': {\n")
- for name, message in self.data['messages'].iteritems():
- self._AddNontranslateableChunk(" '%s': {\n" % name)
- self._AddNontranslateableChunk(" 'text': '''")
- self._ParseMessage(message['text'], message['desc'])
- self._AddNontranslateableChunk("'''\n")
- self._AddNontranslateableChunk(" },\n")
- self._AddNontranslateableChunk(" },\n")
-
- # Although we use the RegexpGatherer base class, we do not use the
- # _RegExpParse method of that class to implement Parse(). Instead, we
- # parse using a DOM parser.
- def Parse(self):
- if (self.have_parsed_):
- return
- self.have_parsed_ = True
-
- self.data = eval(self.text_)
-
- self._AddNontranslateableChunk('{\n')
- self._AddNontranslateableChunk(" 'policy_definitions': [\n")
- self._AddItems(self.data['policy_definitions'], 'policy', None, 2)
- self._AddNontranslateableChunk(" ],\n")
- self._AddMessages()
- self._AddNontranslateableChunk('\n}')
-
- def Escape(self, text):
- # \ -> \\
- # ' -> \'
- # " -> \"
- return text.replace('\\', '\\\\').replace('"', '\\"').replace("'", "\\'")
-
- def FromFile(filename_or_stream, extkey=None, encoding='cp1252'):
- if isinstance(filename_or_stream, types.StringTypes):
- if util.IsVerbose():
- print "PolicyJson reading file %s, encoding %s" % (
- filename_or_stream, encoding)
- filename_or_stream = \
- util.WrapInputStream(file(filename_or_stream, 'r'), encoding)
- return PolicyJson(filename_or_stream.read())
- FromFile = staticmethod(FromFile)
diff --git a/tools/grit/grit/gather/policy_json_unittest.py b/tools/grit/grit/gather/policy_json_unittest.py
deleted file mode 100644
index 9ebddb8..0000000
--- a/tools/grit/grit/gather/policy_json_unittest.py
+++ /dev/null
@@ -1,190 +0,0 @@
-#!/usr/bin/env python
-# Copyright (c) 2011 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.
-
-'''Unit tests for grit.gather.policy_json'''
-
-import os
-import re
-import sys
-if __name__ == '__main__':
- sys.path.append(os.path.join(os.path.dirname(sys.argv[0]), '../..'))
-
-import unittest
-
-from grit.gather import muppet_strings
-from grit.gather import policy_json
-
-class PolicyJsonUnittest(unittest.TestCase):
-
- def GetExpectedOutput(self, original):
- expected = eval(original)
- for key, message in expected['messages'].iteritems():
- del message['desc']
- return expected
-
- def testEmpty(self):
- original = "{'policy_definitions': [], 'messages': {}}"
- gatherer = policy_json.PolicyJson(original)
- gatherer.Parse()
- self.failUnless(len(gatherer.GetCliques()) == 0)
- self.failUnless(eval(original) == eval(gatherer.Translate('en')))
-
- def testGeneralPolicy(self):
- original = (
- "{"
- " 'policy_definitions': ["
- " {"
- " 'name': 'HomepageLocation',"
- " 'type': 'string',"
- " 'supported_on': ['chrome.*:8-'],"
- " 'features': {'dynamic_refresh': 1},"
- " 'example_value': 'http://chromium.org',"
- " 'caption': 'nothing special 1',"
- " 'desc': 'nothing special 2',"
- " 'label': 'nothing special 3',"
- " },"
- " ],"
- " 'messages': {"
- " 'msg_identifier': {"
- " 'text': 'nothing special 3',"
- " 'desc': 'nothing special descr 3',"
- " }"
- " }"
- "}")
- gatherer = policy_json.PolicyJson(original)
- gatherer.Parse()
- self.failUnless(len(gatherer.GetCliques()) == 4)
- expected = self.GetExpectedOutput(original)
- self.failUnless(expected == eval(gatherer.Translate('en')))
-
- def testEnum(self):
- original = (
- "{"
- " 'policy_definitions': ["
- " {"
- " 'name': 'Policy1',"
- " 'items': ["
- " {"
- " 'name': 'Item1',"
- " 'caption': 'nothing special',"
- " }"
- " ]"
- " },"
- " ],"
- " 'messages': {}"
- "}")
- gatherer = policy_json.PolicyJson(original)
- gatherer.Parse()
- self.failUnless(len(gatherer.GetCliques()) == 1)
- expected = self.GetExpectedOutput(original)
- self.failUnless(expected == eval(gatherer.Translate('en')))
-
- def testSubPolicy(self):
- original = (
- "{"
- " 'policy_definitions': ["
- " {"
- " 'policies': ["
- " {"
- " 'name': 'Policy1',"
- " 'caption': 'nothing special',"
- " }"
- " ]"
- " },"
- " ],"
- " 'messages': {}"
- "}")
- gatherer = policy_json.PolicyJson(original)
- gatherer.Parse()
- self.failUnless(len(gatherer.GetCliques()) == 1)
- expected = self.GetExpectedOutput(original)
- self.failUnless(expected == eval(gatherer.Translate('en')))
-
- def testEscapingAndLineBreaks(self):
- original = """{
- 'policy_definitions': [],
- 'messages': {
- 'msg1': {
- # The following line will contain two backslash characters when it
- # ends up in eval().
- 'text': '''backslashes, Sir? \\\\''',
- 'desc': '',
- },
- 'msg2': {
- 'text': '''quotes, Madam? "''',
- 'desc': '',
- },
- 'msg3': {
- # The following line will contain two backslash characters when it
- # ends up in eval().
- 'text': 'backslashes, Sir? \\\\',
- 'desc': '',
- },
- 'msg4': {
- 'text': "quotes, Madam? '",
- 'desc': '',
- },
- 'msg5': {
- 'text': '''what happens
-with a newline?''',
- 'desc': ''
- },
- 'msg6': {
- # The following line will contain a backslash+n when it ends up in
- # eval().
- 'text': 'what happens\\nwith a newline? (Episode 1)',
- 'desc': ''
- }
- }
-}"""
- gatherer = policy_json.PolicyJson(original)
- gatherer.Parse()
- self.failUnless(len(gatherer.GetCliques()) == 6)
- expected = self.GetExpectedOutput(original)
- self.failUnless(expected == eval(gatherer.Translate('en')))
-
- def testPlaceholders(self):
- original = """{
- 'policy_definitions': [
- {
- 'name': 'Policy1',
- 'caption': '''Please install
- <ph name="PRODUCT_NAME">$1<ex>Google Chrome</ex></ph>.''',
- },
- ],
- 'messages': {}
-}"""
- gatherer = policy_json.PolicyJson(original)
- gatherer.Parse()
- self.failUnless(len(gatherer.GetCliques()) == 1)
- expected = eval(re.sub('<ph.*ph>', '$1', original))
- self.failUnless(expected == eval(gatherer.Translate('en')))
- self.failUnless(gatherer.GetCliques()[0].translateable)
- msg = gatherer.GetCliques()[0].GetMessage()
- self.failUnless(len(msg.GetPlaceholders()) == 1)
- ph = msg.GetPlaceholders()[0]
- self.failUnless(ph.GetOriginal() == '$1')
- self.failUnless(ph.GetPresentation() == 'PRODUCT_NAME')
- self.failUnless(ph.GetExample() == 'Google Chrome')
-
- def testGetDescription(self):
- gatherer = policy_json.PolicyJson({})
- self.assertEquals(
- gatherer._GetDescription({'name': 'Policy1'}, 'policy', None, 'desc'),
- 'Description of the policy named Policy1')
- self.assertEquals(
- gatherer._GetDescription({'name': 'Plcy2'}, 'policy', None, 'caption'),
- 'Caption of the policy named Plcy2')
- self.assertEquals(
- gatherer._GetDescription({'name': 'Plcy3'}, 'policy', None, 'label'),
- 'Label of the policy named Plcy3')
- self.assertEquals(
- gatherer._GetDescription({'name': 'Item'}, 'enum_item',
- {'name': 'Policy'}, 'caption'),
- 'Caption of the option named Item in policy Policy')
-
-
-if __name__ == '__main__':
- unittest.main()
diff --git a/tools/grit/grit/gather/rc.py b/tools/grit/grit/gather/rc.py
deleted file mode 100644
index f0af109..0000000
--- a/tools/grit/grit/gather/rc.py
+++ /dev/null
@@ -1,403 +0,0 @@
-#!/usr/bin/python2.4
-# Copyright (c) 2006-2008 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.
-
-'''Support for gathering resources from RC files.
-'''
-
-
-import re
-import types
-
-from grit import clique
-from grit import exception
-from grit import util
-from grit import tclib
-
-from grit.gather import regexp
-
-
-# Find portions that need unescaping in resource strings. We need to be
-# careful that a \\n is matched _first_ as a \\ rather than matching as
-# a \ followed by a \n.
-# TODO(joi) Handle ampersands if we decide to change them into <ph>
-# TODO(joi) May need to handle other control characters than \n
-_NEED_UNESCAPE = re.compile(r'""|\\\\|\\n|\\t')
-
-# Find portions that need escaping to encode string as a resource string.
-_NEED_ESCAPE = re.compile(r'"|\n|\t|\\|\&nbsp\;')
-
-# How to escape certain characters
-_ESCAPE_CHARS = {
- '"' : '""',
- '\n' : '\\n',
- '\t' : '\\t',
- '\\' : '\\\\',
- '&nbsp;' : ' '
-}
-
-# How to unescape certain strings
-_UNESCAPE_CHARS = dict([[value, key] for key, value in _ESCAPE_CHARS.items()])
-
-
-
-class Section(regexp.RegexpGatherer):
- '''A section from a resource file.'''
-
- def __init__(self, section_text):
- '''Creates a new object.
-
- Args:
- section_text: 'ID_SECTION_ID SECTIONTYPE\n.....\nBEGIN\n.....\nEND'
- '''
- regexp.RegexpGatherer.__init__(self, section_text)
-
- # static method
- def Escape(text):
- '''Returns a version of 'text' with characters escaped that need to be
- for inclusion in a resource section.'''
- def Replace(match):
- return _ESCAPE_CHARS[match.group()]
- return _NEED_ESCAPE.sub(Replace, text)
- Escape = staticmethod(Escape)
-
- # static method
- def UnEscape(text):
- '''Returns a version of 'text' with escaped characters unescaped.'''
- def Replace(match):
- return _UNESCAPE_CHARS[match.group()]
- return _NEED_UNESCAPE.sub(Replace, text)
- UnEscape = staticmethod(UnEscape)
-
- def _RegExpParse(self, rexp, text_to_parse):
- '''Overrides _RegExpParse to add shortcut group handling. Otherwise
- the same.
- '''
- regexp.RegexpGatherer._RegExpParse(self, rexp, text_to_parse)
-
- if not self.IsSkeleton() and len(self.GetTextualIds()) > 0:
- group_name = self.GetTextualIds()[0]
- for c in self.GetCliques():
- c.AddToShortcutGroup(group_name)
-
- # Static method
- def FromFileImpl(rc_file, extkey, encoding, type):
- '''Implementation of FromFile. Need to keep separate so we can have
- a FromFile in this class that has its type set to Section by default.
- '''
- if isinstance(rc_file, types.StringTypes):
- rc_file = util.WrapInputStream(file(rc_file, 'r'), encoding)
-
- out = ''
- begin_count = 0
- for line in rc_file.readlines():
- if len(out) > 0 or (line.strip().startswith(extkey) and
- line.strip().split()[0] == extkey):
- out += line
-
- # we stop once we reach the END for the outermost block.
- begin_count_was = begin_count
- if len(out) > 0 and line.strip() == 'BEGIN':
- begin_count += 1
- elif len(out) > 0 and line.strip() == 'END':
- begin_count -= 1
- if begin_count_was == 1 and begin_count == 0:
- break
-
- if len(out) == 0:
- raise exception.SectionNotFound('%s in file %s' % (extkey, rc_file))
-
- return type(out)
- FromFileImpl = staticmethod(FromFileImpl)
-
- # static method
- def FromFile(rc_file, extkey, encoding='cp1252'):
- '''Retrieves the section of 'rc_file' that has the key 'extkey'. This is
- matched against the start of a line, and that line and the rest of that
- section in the RC file is returned.
-
- If 'rc_file' is a filename, it will be opened for reading using 'encoding'.
- Otherwise the 'encoding' parameter is ignored.
-
- This method instantiates an object of type 'type' with the text from the
- file.
-
- Args:
- rc_file: file('') | 'filename.rc'
- extkey: 'ID_MY_DIALOG'
- encoding: 'utf-8'
- type: class to instantiate with text of section
-
- Return:
- type(text_of_section)
- '''
- return Section.FromFileImpl(rc_file, extkey, encoding, Section)
- FromFile = staticmethod(FromFile)
-
-
-class Dialog(Section):
- '''A resource section that contains a dialog resource.'''
-
- # A typical dialog resource section looks like this:
- #
- # IDD_ABOUTBOX DIALOGEX 22, 17, 230, 75
- # STYLE DS_SETFONT | DS_MODALFRAME | WS_CAPTION | WS_SYSMENU
- # CAPTION "About"
- # FONT 8, "System", 0, 0, 0x0
- # BEGIN
- # ICON IDI_KLONK,IDC_MYICON,14,9,20,20
- # LTEXT "klonk Version ""yibbee"" 1.0",IDC_STATIC,49,10,119,8,
- # SS_NOPREFIX
- # LTEXT "Copyright (C) 2005",IDC_STATIC,49,20,119,8
- # DEFPUSHBUTTON "OK",IDOK,195,6,30,11,WS_GROUP
- # CONTROL "Jack ""Black"" Daniels",IDC_RADIO1,"Button",
- # BS_AUTORADIOBUTTON,46,51,84,10
- # END
-
- # We are using a sorted set of keys, and we assume that the
- # group name used for descriptions (type) will come after the "text"
- # group in alphabetical order. We also assume that there cannot be
- # more than one description per regular expression match.
- # If that's not the case some descriptions will be clobbered.
- dialog_re_ = re.compile('''
- # The dialog's ID in the first line
- (?P<id1>[A-Z0-9_]+)\s+DIALOG(EX)?
- |
- # The caption of the dialog
- (?P<type1>CAPTION)\s+"(?P<text1>.*?([^"]|""))"\s
- |
- # Lines for controls that have text and an ID
- \s+(?P<type2>[A-Z]+)\s+"(?P<text2>.*?([^"]|"")?)"\s*,\s*(?P<id2>[A-Z0-9_]+)\s*,
- |
- # Lines for controls that have text only
- \s+(?P<type3>[A-Z]+)\s+"(?P<text3>.*?([^"]|"")?)"\s*,
- |
- # Lines for controls that reference other resources
- \s+[A-Z]+\s+[A-Z0-9_]+\s*,\s*(?P<id3>[A-Z0-9_]*[A-Z][A-Z0-9_]*)
- |
- # This matches "NOT SOME_STYLE" so that it gets consumed and doesn't get
- # matched by the next option (controls that have only an ID and then just
- # numbers)
- \s+NOT\s+[A-Z][A-Z0-9_]+
- |
- # Lines for controls that have only an ID and then just numbers
- \s+[A-Z]+\s+(?P<id4>[A-Z0-9_]*[A-Z][A-Z0-9_]*)\s*,
- ''', re.MULTILINE | re.VERBOSE)
-
- def Parse(self):
- '''Knows how to parse dialog resource sections.'''
- self._RegExpParse(self.dialog_re_, self.text_)
-
- # static method
- def FromFile(rc_file, extkey, encoding = 'cp1252'):
- return Section.FromFileImpl(rc_file, extkey, encoding, Dialog)
- FromFile = staticmethod(FromFile)
-
-
-class Menu(Section):
- '''A resource section that contains a menu resource.'''
-
- # A typical menu resource section looks something like this:
- #
- # IDC_KLONK MENU
- # BEGIN
- # POPUP "&File"
- # BEGIN
- # MENUITEM "E&xit", IDM_EXIT
- # MENUITEM "This be ""Klonk"" me like", ID_FILE_THISBE
- # POPUP "gonk"
- # BEGIN
- # MENUITEM "Klonk && is ""good""", ID_GONK_KLONKIS
- # END
- # END
- # POPUP "&Help"
- # BEGIN
- # MENUITEM "&About ...", IDM_ABOUT
- # END
- # END
-
- # Description used for the messages generated for menus, to explain to
- # the translators how to handle them.
- MENU_MESSAGE_DESCRIPTION = (
- 'This message represents a menu. Each of the items appears in sequence '
- '(some possibly within sub-menus) in the menu. The XX01XX placeholders '
- 'serve to separate items. Each item contains an & (ampersand) character '
- 'in front of the keystroke that should be used as a shortcut for that item '
- 'in the menu. Please make sure that no two items in the same menu share '
- 'the same shortcut.'
- )
-
- # A dandy regexp to suck all the IDs and translateables out of a menu
- # resource
- menu_re_ = re.compile('''
- # Match the MENU ID on the first line
- ^(?P<id1>[A-Z0-9_]+)\s+MENU
- |
- # Match the translateable caption for a popup menu
- POPUP\s+"(?P<text1>.*?([^"]|""))"\s
- |
- # Match the caption & ID of a MENUITEM
- MENUITEM\s+"(?P<text2>.*?([^"]|""))"\s*,\s*(?P<id2>[A-Z0-9_]+)
- ''', re.MULTILINE | re.VERBOSE)
-
- def Parse(self):
- '''Knows how to parse menu resource sections. Because it is important that
- menu shortcuts are unique within the menu, we return each menu as a single
- message with placeholders to break up the different menu items, rather than
- return a single message per menu item. we also add an automatic description
- with instructions for the translators.'''
- self.single_message_ = tclib.Message(description=self.MENU_MESSAGE_DESCRIPTION)
- self._RegExpParse(self.menu_re_, self.text_)
-
- # static method
- def FromFile(rc_file, extkey, encoding = 'cp1252'):
- return Section.FromFileImpl(rc_file, extkey, encoding, Menu)
- FromFile = staticmethod(FromFile)
-
-
-class Version(Section):
- '''A resource section that contains a VERSIONINFO resource.'''
-
- # A typical version info resource can look like this:
- #
- # VS_VERSION_INFO VERSIONINFO
- # FILEVERSION 1,0,0,1
- # PRODUCTVERSION 1,0,0,1
- # FILEFLAGSMASK 0x3fL
- # #ifdef _DEBUG
- # FILEFLAGS 0x1L
- # #else
- # FILEFLAGS 0x0L
- # #endif
- # FILEOS 0x4L
- # FILETYPE 0x2L
- # FILESUBTYPE 0x0L
- # BEGIN
- # BLOCK "StringFileInfo"
- # BEGIN
- # BLOCK "040904e4"
- # BEGIN
- # VALUE "CompanyName", "TODO: <Company name>"
- # VALUE "FileDescription", "TODO: <File description>"
- # VALUE "FileVersion", "1.0.0.1"
- # VALUE "LegalCopyright", "TODO: (c) <Company name>. All rights reserved."
- # VALUE "InternalName", "res_format_test.dll"
- # VALUE "OriginalFilename", "res_format_test.dll"
- # VALUE "ProductName", "TODO: <Product name>"
- # VALUE "ProductVersion", "1.0.0.1"
- # END
- # END
- # BLOCK "VarFileInfo"
- # BEGIN
- # VALUE "Translation", 0x409, 1252
- # END
- # END
- #
- #
- # In addition to the above fields, VALUE fields named "Comments" and
- # "LegalTrademarks" may also be translateable.
-
- version_re_ = re.compile('''
- # Match the ID on the first line
- ^(?P<id1>[A-Z0-9_]+)\s+VERSIONINFO
- |
- # Match all potentially translateable VALUE sections
- \s+VALUE\s+"
- (
- CompanyName|FileDescription|LegalCopyright|
- ProductName|Comments|LegalTrademarks
- )",\s+"(?P<text1>.*?([^"]|""))"\s
- ''', re.MULTILINE | re.VERBOSE)
-
- def Parse(self):
- '''Knows how to parse VERSIONINFO resource sections.'''
- self._RegExpParse(self.version_re_, self.text_)
-
- # TODO(joi) May need to override the Translate() method to change the
- # "Translation" VALUE block to indicate the correct language code.
-
- # static method
- def FromFile(rc_file, extkey, encoding = 'cp1252'):
- return Section.FromFileImpl(rc_file, extkey, encoding, Version)
- FromFile = staticmethod(FromFile)
-
-class RCData(Section):
- '''A resource section that contains some data .'''
-
- # A typical rcdataresource section looks like this:
- #
- # IDR_BLAH RCDATA { 1, 2, 3, 4 }
-
- dialog_re_ = re.compile('''
- ^(?P<id1>[A-Z0-9_]+)\s+RCDATA\s+(DISCARDABLE)?\s+\{.*?\}
- ''', re.MULTILINE | re.VERBOSE | re.DOTALL)
-
- def Parse(self):
- '''Knows how to parse RCDATA resource sections.'''
- self._RegExpParse(self.dialog_re_, self.text_)
-
- # static method
- def FromFile(rc_file, extkey, encoding = 'cp1252'):
- '''Implementation of FromFile for resource types w/braces (not BEGIN/END)
- '''
- if isinstance(rc_file, types.StringTypes):
- rc_file = util.WrapInputStream(file(rc_file, 'r'), encoding)
-
- out = ''
- begin_count = 0
- openbrace_count = 0
- for line in rc_file.readlines():
- if len(out) > 0 or line.strip().startswith(extkey):
- out += line
-
- # we stop once balance the braces (could happen on one line)
- begin_count_was = begin_count
- if len(out) > 0:
- openbrace_count += line.count('{')
- begin_count += line.count('{')
- begin_count -= line.count('}')
- if ((begin_count_was == 1 and begin_count == 0) or
- (openbrace_count > 0 and begin_count == 0)):
- break
-
- if len(out) == 0:
- raise exception.SectionNotFound('%s in file %s' % (extkey, rc_file))
-
- return RCData(out)
- FromFile = staticmethod(FromFile)
-
-
-class Accelerators(Section):
- '''An ACCELERATORS table.
- '''
-
- # A typical ACCELERATORS section looks like this:
- #
- # IDR_ACCELERATOR1 ACCELERATORS
- # BEGIN
- # "^C", ID_ACCELERATOR32770, ASCII, NOINVERT
- # "^V", ID_ACCELERATOR32771, ASCII, NOINVERT
- # VK_INSERT, ID_ACCELERATOR32772, VIRTKEY, CONTROL, NOINVERT
- # END
-
- accelerators_re_ = re.compile('''
- # Match the ID on the first line
- ^(?P<id1>[A-Z0-9_]+)\s+ACCELERATORS\s+
- |
- # Match accelerators specified as VK_XXX
- \s+VK_[A-Z0-9_]+,\s*(?P<id2>[A-Z0-9_]+)\s*,
- |
- # Match accelerators specified as e.g. "^C"
- \s+"[^"]*",\s+(?P<id3>[A-Z0-9_]+)\s*,
- ''', re.MULTILINE | re.VERBOSE)
-
- def Parse(self):
- '''Knows how to parse ACCELERATORS resource sections.'''
- self._RegExpParse(self.accelerators_re_, self.text_)
-
- # static method
- def FromFile(rc_file, extkey, encoding = 'cp1252'):
- return Section.FromFileImpl(rc_file, extkey, encoding, Accelerators)
- FromFile = staticmethod(FromFile)
-
diff --git a/tools/grit/grit/gather/rc_unittest.py b/tools/grit/grit/gather/rc_unittest.py
deleted file mode 100644
index 2374017..0000000
--- a/tools/grit/grit/gather/rc_unittest.py
+++ /dev/null
@@ -1,368 +0,0 @@
-#!/usr/bin/python2.4
-# Copyright (c) 2011 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.
-
-'''Unit tests for grit.gather.rc'''
-
-
-import os
-import sys
-if __name__ == '__main__':
- sys.path.append(os.path.join(os.path.dirname(sys.argv[0]), '../..'))
-
-import unittest
-import StringIO
-
-from grit.gather import rc
-from grit import util
-
-
-class RcUnittest(unittest.TestCase):
-
- part_we_want = '''IDC_KLONKACC ACCELERATORS
-BEGIN
- "?", IDM_ABOUT, ASCII, ALT
- "/", IDM_ABOUT, ASCII, ALT
-END'''
-
- def testSectionFromFile(self):
- buf = '''IDC_SOMETHINGELSE BINGO
-BEGIN
- BLA BLA
- BLA BLA
-END
-%s
-
-IDC_KLONK BINGOBONGO
-BEGIN
- HONGO KONGO
-END
-''' % self.part_we_want
-
- f = StringIO.StringIO(buf)
-
- out = rc.Section.FromFile(f, 'IDC_KLONKACC')
- self.failUnless(out.GetText() == self.part_we_want)
-
- out = rc.Section.FromFile(util.PathFromRoot(r'grit/testdata/klonk.rc'),
- 'IDC_KLONKACC',
- encoding='utf-16')
- out_text = out.GetText().replace('\t', '')
- out_text = out_text.replace(' ', '')
- self.part_we_want = self.part_we_want.replace(' ', '')
- self.failUnless(out_text.strip() == self.part_we_want.strip())
-
-
- def testDialog(self):
- dlg = rc.Dialog('''IDD_ABOUTBOX DIALOGEX 22, 17, 230, 75
-STYLE DS_SETFONT | DS_MODALFRAME | WS_CAPTION | WS_SYSMENU
-CAPTION "About"
-FONT 8, "System", 0, 0, 0x0
-BEGIN
- ICON IDI_KLONK,IDC_MYICON,14,9,20,20
- LTEXT "klonk Version ""yibbee"" 1.0",IDC_STATIC,49,10,119,8,
- SS_NOPREFIX
- LTEXT "Copyright (C) 2005",IDC_STATIC,49,20,119,8
- DEFPUSHBUTTON "OK",IDOK,195,6,30,11,WS_GROUP
- CONTROL "Jack ""Black"" Daniels",IDC_RADIO1,"Button",
- BS_AUTORADIOBUTTON,46,51,84,10
- // try a line where the ID is on the continuation line
- LTEXT "blablablabla blablabla blablablablablablablabla blablabla",
- ID_SMURF, whatever...
-END
-''')
- dlg.Parse()
- self.failUnless(len(dlg.GetTextualIds()) == 7)
- self.failUnless(len(dlg.GetCliques()) == 6)
- self.failUnless(dlg.GetCliques()[1].GetMessage().GetRealContent() ==
- 'klonk Version "yibbee" 1.0')
-
- transl = dlg.Translate('en')
- self.failUnless(transl.strip() == dlg.GetText().strip())
-
- def testAlternateSkeleton(self):
- dlg = rc.Dialog('''IDD_ABOUTBOX DIALOGEX 22, 17, 230, 75
-STYLE DS_SETFONT | DS_MODALFRAME | WS_CAPTION | WS_SYSMENU
-CAPTION "About"
-FONT 8, "System", 0, 0, 0x0
-BEGIN
- LTEXT "Yipee skippy",IDC_STATIC,49,10,119,8,
- SS_NOPREFIX
-END
-''')
- dlg.Parse()
-
- alt_dlg = rc.Dialog('''IDD_ABOUTBOX DIALOGEX 040704, 17, 230, 75
-STYLE DS_SETFONT | DS_MODALFRAME | WS_CAPTION | WS_SYSMENU
-CAPTION "XXXXXXXXX"
-FONT 8, "System", 0, 0, 0x0
-BEGIN
- LTEXT "XXXXXXXXXXXXXXXXX",IDC_STATIC,110978,10,119,8,
- SS_NOPREFIX
-END
-''')
- alt_dlg.Parse()
-
- transl = dlg.Translate('en', skeleton_gatherer=alt_dlg)
- self.failUnless(transl.count('040704') and
- transl.count('110978'))
- self.failUnless(transl.count('Yipee skippy'))
-
- def testMenu(self):
- menu = rc.Menu('''IDC_KLONK MENU
-BEGIN
- POPUP "&File """
- BEGIN
- MENUITEM "E&xit", IDM_EXIT
- MENUITEM "This be ""Klonk"" me like", ID_FILE_THISBE
- POPUP "gonk"
- BEGIN
- MENUITEM "Klonk && is ""good""", ID_GONK_KLONKIS
- END
- MENUITEM "This is a very long menu caption to try to see if we can make the ID go to a continuation line, blablabla blablabla bla blabla blablabla blablabla blablabla blablabla...",
- ID_FILE_THISISAVERYLONGMENUCAPTIONTOTRYTOSEEIFWECANMAKETHEIDGOTOACONTINUATIONLINE
- END
- POPUP "&Help"
- BEGIN
- MENUITEM "&About ...", IDM_ABOUT
- END
-END''')
-
- menu.Parse()
- self.failUnless(len(menu.GetTextualIds()) == 6)
- self.failUnless(len(menu.GetCliques()) == 1)
- self.failUnless(len(menu.GetCliques()[0].GetMessage().GetPlaceholders()) ==
- 9)
-
- transl = menu.Translate('en')
- self.failUnless(transl.strip() == menu.GetText().strip())
-
- def testVersion(self):
- version = rc.Version('''
-VS_VERSION_INFO VERSIONINFO
- FILEVERSION 1,0,0,1
- PRODUCTVERSION 1,0,0,1
- FILEFLAGSMASK 0x3fL
-#ifdef _DEBUG
- FILEFLAGS 0x1L
-#else
- FILEFLAGS 0x0L
-#endif
- FILEOS 0x4L
- FILETYPE 0x2L
- FILESUBTYPE 0x0L
-BEGIN
- BLOCK "StringFileInfo"
- BEGIN
- BLOCK "040904e4"
- BEGIN
- VALUE "CompanyName", "TODO: <Company name>"
- VALUE "FileDescription", "TODO: <File description>"
- VALUE "FileVersion", "1.0.0.1"
- VALUE "LegalCopyright", "TODO: (c) <Company name>. All rights reserved."
- VALUE "InternalName", "res_format_test.dll"
- VALUE "OriginalFilename", "res_format_test.dll"
- VALUE "ProductName", "TODO: <Product name>"
- VALUE "ProductVersion", "1.0.0.1"
- END
- END
- BLOCK "VarFileInfo"
- BEGIN
- VALUE "Translation", 0x409, 1252
- END
-END
-'''.strip())
- version.Parse()
- self.failUnless(len(version.GetTextualIds()) == 1)
- self.failUnless(len(version.GetCliques()) == 4)
-
- transl = version.Translate('en')
- self.failUnless(transl.strip() == version.GetText().strip())
-
-
- def testRegressionDialogBox(self):
- dialog = rc.Dialog('''
-IDD_SIDEBAR_WEATHER_PANEL_PROPPAGE DIALOGEX 0, 0, 205, 157
-STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD
-FONT 8, "MS Shell Dlg", 400, 0, 0x1
-BEGIN
- EDITTEXT IDC_SIDEBAR_WEATHER_NEW_CITY,3,27,112,14,ES_AUTOHSCROLL
- DEFPUSHBUTTON "Add Location",IDC_SIDEBAR_WEATHER_ADD,119,27,50,14
- LISTBOX IDC_SIDEBAR_WEATHER_CURR_CITIES,3,48,127,89,
- LBS_NOINTEGRALHEIGHT | WS_VSCROLL | WS_TABSTOP
- PUSHBUTTON "Move Up",IDC_SIDEBAR_WEATHER_MOVE_UP,134,104,50,14
- PUSHBUTTON "Move Down",IDC_SIDEBAR_WEATHER_MOVE_DOWN,134,121,50,14
- PUSHBUTTON "Remove",IDC_SIDEBAR_WEATHER_DELETE,134,48,50,14
- LTEXT "To see current weather conditions and forecasts in the USA, enter the zip code (example: 94043) or city and state (example: Mountain View, CA).",
- IDC_STATIC,3,0,199,25
- CONTROL "Fahrenheit",IDC_SIDEBAR_WEATHER_FAHRENHEIT,"Button",
- BS_AUTORADIOBUTTON | WS_GROUP | WS_TABSTOP,3,144,51,10
- CONTROL "Celsius",IDC_SIDEBAR_WEATHER_CELSIUS,"Button",
- BS_AUTORADIOBUTTON,57,144,38,10
-END'''.strip())
- dialog.Parse()
- self.failUnless(len(dialog.GetTextualIds()) == 10)
-
-
- def testRegressionDialogBox2(self):
- dialog = rc.Dialog('''
-IDD_SIDEBAR_EMAIL_PANEL_PROPPAGE DIALOG DISCARDABLE 0, 0, 264, 220
-STYLE WS_CHILD
-FONT 8, "MS Shell Dlg"
-BEGIN
- GROUPBOX "Email Filters",IDC_STATIC,7,3,250,190
- LTEXT "Click Add Filter to create the email filter.",IDC_STATIC,16,41,130,9
- PUSHBUTTON "Add Filter...",IDC_SIDEBAR_EMAIL_ADD_FILTER,196,38,50,14
- PUSHBUTTON "Remove",IDC_SIDEBAR_EMAIL_REMOVE,196,174,50,14
- PUSHBUTTON "", IDC_SIDEBAR_EMAIL_HIDDEN, 200, 178, 5, 5, NOT WS_VISIBLE
- LISTBOX IDC_SIDEBAR_EMAIL_LIST,16,60,230,108,
- LBS_NOINTEGRALHEIGHT | WS_VSCROLL | WS_TABSTOP
- LTEXT "You can prevent certain emails from showing up in the sidebar with a filter.",
- IDC_STATIC,16,18,234,18
-END'''.strip())
- dialog.Parse()
- self.failUnless('IDC_SIDEBAR_EMAIL_HIDDEN' in dialog.GetTextualIds())
-
-
- def testRegressionMenuId(self):
- menu = rc.Menu('''
-IDR_HYPERMENU_FOLDER MENU
-BEGIN
- POPUP "HyperFolder"
- BEGIN
- MENUITEM "Open Containing Folder", IDM_OPENFOLDER
- END
-END'''.strip())
- menu.Parse()
- self.failUnless(len(menu.GetTextualIds()) == 2)
-
- def testRegressionNewlines(self):
- menu = rc.Menu('''
-IDR_HYPERMENU_FOLDER MENU
-BEGIN
- POPUP "Hyper\\nFolder"
- BEGIN
- MENUITEM "Open Containing Folder", IDM_OPENFOLDER
- END
-END'''.strip())
- menu.Parse()
- transl = menu.Translate('en')
- # Shouldn't find \\n (the \n shouldn't be changed to \\n)
- self.failUnless(transl.find('\\\\n') == -1)
-
- def testRegressionTabs(self):
- menu = rc.Menu('''
-IDR_HYPERMENU_FOLDER MENU
-BEGIN
- POPUP "Hyper\\tFolder"
- BEGIN
- MENUITEM "Open Containing Folder", IDM_OPENFOLDER
- END
-END'''.strip())
- menu.Parse()
- transl = menu.Translate('en')
- # Shouldn't find \\t (the \t shouldn't be changed to \\t)
- self.failUnless(transl.find('\\\\t') == -1)
-
- def testEscapeUnescape(self):
- original = 'Hello "bingo"\n How\\are\\you\\n?'
- escaped = rc.Section.Escape(original)
- self.failUnless(escaped == 'Hello ""bingo""\\n How\\\\are\\\\you\\\\n?')
- unescaped = rc.Section.UnEscape(escaped)
- self.failUnless(unescaped == original)
-
- def testRegressionPathsWithSlashN(self):
- original = '..\\\\..\\\\trs\\\\res\\\\nav_first.gif'
- unescaped = rc.Section.UnEscape(original)
- self.failUnless(unescaped == '..\\..\\trs\\res\\nav_first.gif')
-
- def testRegressionDialogItemsTextOnly(self):
- dialog = rc.Dialog('''IDD_OPTIONS_SEARCH DIALOGEX 0, 0, 280, 292
-STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | DS_CENTER | WS_POPUP |
- WS_DISABLED | WS_CAPTION | WS_SYSMENU
-CAPTION "Search"
-FONT 8, "MS Shell Dlg", 400, 0, 0x1
-BEGIN
- GROUPBOX "Select search buttons and options",-1,7,5,266,262
- CONTROL "",IDC_OPTIONS,"SysTreeView32",TVS_DISABLEDRAGDROP |
- WS_BORDER | WS_TABSTOP | 0x800,16,19,248,218
- LTEXT "Use Google site:",-1,26,248,52,8
- COMBOBOX IDC_GOOGLE_HOME,87,245,177,256,CBS_DROPDOWNLIST |
- WS_VSCROLL | WS_TABSTOP
- PUSHBUTTON "Restore Defaults...",IDC_RESET,187,272,86,14
-END''')
- dialog.Parse()
- translateables = [c.GetMessage().GetRealContent()
- for c in dialog.GetCliques()]
- self.failUnless('Select search buttons and options' in translateables)
- self.failUnless('Use Google site:' in translateables)
-
- def testAccelerators(self):
- acc = rc.Accelerators('''\
-IDR_ACCELERATOR1 ACCELERATORS
-BEGIN
- "^C", ID_ACCELERATOR32770, ASCII, NOINVERT
- "^V", ID_ACCELERATOR32771, ASCII, NOINVERT
- VK_INSERT, ID_ACCELERATOR32772, VIRTKEY, CONTROL, NOINVERT
-END
-''')
- acc.Parse()
- self.failUnless(len(acc.GetTextualIds()) == 4)
- self.failUnless(len(acc.GetCliques()) == 0)
-
- transl = acc.Translate('en')
- self.failUnless(transl.strip() == acc.GetText().strip())
-
-
- def testRegressionEmptyString(self):
- dlg = rc.Dialog('''\
-IDD_CONFIRM_QUIT_GD_DLG DIALOGEX 0, 0, 267, 108
-STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | DS_CENTER | WS_POPUP |
- WS_CAPTION
-EXSTYLE WS_EX_TOPMOST
-CAPTION "Google Desktop"
-FONT 8, "MS Shell Dlg", 400, 0, 0x1
-BEGIN
- DEFPUSHBUTTON "&Yes",IDYES,82,87,50,14
- PUSHBUTTON "&No",IDNO,136,87,50,14
- ICON 32514,IDC_STATIC,7,9,21,20
- EDITTEXT IDC_TEXTBOX,34,7,231,60,ES_MULTILINE | ES_READONLY | NOT WS_BORDER
- CONTROL "",
- IDC_ENABLE_GD_AUTOSTART,"Button",BS_AUTOCHECKBOX |
- WS_TABSTOP,33,70,231,10
-END''')
- dlg.Parse()
-
- def Check():
- self.failUnless(transl.count('IDC_ENABLE_GD_AUTOSTART'))
- self.failUnless(transl.count('END'))
-
- transl = dlg.Translate('de', pseudo_if_not_available=True,
- fallback_to_english=True)
- Check()
- transl = dlg.Translate('de', pseudo_if_not_available=True,
- fallback_to_english=False)
- Check()
- transl = dlg.Translate('de', pseudo_if_not_available=False,
- fallback_to_english=True)
- Check()
- transl = dlg.Translate('de', pseudo_if_not_available=False,
- fallback_to_english=False)
- Check()
- transl = dlg.Translate('en', pseudo_if_not_available=True,
- fallback_to_english=True)
- Check()
- transl = dlg.Translate('en', pseudo_if_not_available=True,
- fallback_to_english=False)
- Check()
- transl = dlg.Translate('en', pseudo_if_not_available=False,
- fallback_to_english=True)
- Check()
- transl = dlg.Translate('en', pseudo_if_not_available=False,
- fallback_to_english=False)
- Check()
-
-
-if __name__ == '__main__':
- unittest.main()
diff --git a/tools/grit/grit/gather/regexp.py b/tools/grit/grit/gather/regexp.py
deleted file mode 100644
index 150a777..0000000
--- a/tools/grit/grit/gather/regexp.py
+++ /dev/null
@@ -1,97 +0,0 @@
-#!/usr/bin/python2.4
-# Copyright (c) 2006-2008 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.
-
-'''A baseclass for simple gatherers based on regular expressions.
-'''
-
-import re
-import types
-
-from grit.gather import skeleton_gatherer
-from grit import clique
-from grit import tclib
-
-
-class RegexpGatherer(skeleton_gatherer.SkeletonGatherer):
- '''Common functionality of gatherers based on parsing using a single
- regular expression.
- '''
-
- DescriptionMapping_ = {
- 'CAPTION' : 'This is a caption for a dialog',
- 'CHECKBOX' : 'This is a label for a checkbox',
- 'CONTROL': 'This is the text on a control',
- 'CTEXT': 'This is a label for a control',
- 'DEFPUSHBUTTON': 'This is a button definition',
- 'GROUPBOX': 'This is a label for a grouping',
- 'ICON': 'This is a label for an icon',
- 'LTEXT': 'This is the text for a label',
- 'PUSHBUTTON': 'This is the text for a button',
- }
-
- def __init__(self, text):
- skeleton_gatherer.SkeletonGatherer.__init__(self)
- # Original text of what we're parsing
- self.text_ = text.strip()
-
- # Contextualization elements. Used for adding additional information
- # to the message bundle description string from RC files.
- def AddDescriptionElement(self, string):
- if self.DescriptionMapping_.has_key(string):
- description = self.DescriptionMapping_[string]
- else:
- description = string
- if self.single_message_:
- self.single_message_.SetDescription(description)
- else:
- if (self.translatable_chunk_):
- message = self.skeleton_[len(self.skeleton_) - 1].GetMessage()
- message.SetDescription(description)
-
- def _RegExpParse(self, regexp, text_to_parse):
- '''An implementation of Parse() that can be used for resource sections that
- can be parsed using a single multi-line regular expression.
-
- All translateables must be in named groups that have names starting with
- 'text'. All textual IDs must be in named groups that have names starting
- with 'id'. All type definitions that can be included in the description
- field for contextualization purposes should have a name that starts with
- 'type'.
-
- Args:
- regexp: re.compile('...', re.MULTILINE)
- text_to_parse:
- '''
- if self.have_parsed_:
- return
- self.have_parsed_ = True
-
- chunk_start = 0
- for match in regexp.finditer(text_to_parse):
- groups = match.groupdict()
- keys = groups.keys()
- keys.sort()
- self.translatable_chunk_ = False
- for group in keys:
- if group.startswith('id') and groups[group]:
- self._AddTextualId(groups[group])
- elif group.startswith('text') and groups[group]:
- self._AddNontranslateableChunk(
- text_to_parse[chunk_start : match.start(group)])
- chunk_start = match.end(group) # Next chunk will start after the match
- self._AddTranslateableChunk(groups[group])
- elif group.startswith('type') and groups[group]:
- # Add the description to the skeleton_ list. This works because
- # we are using a sort set of keys, and because we assume that the
- # group name used for descriptions (type) will come after the "text"
- # group in alphabetical order. We also assume that there cannot be
- # more than one description per regular expression match.
- self.AddDescriptionElement(groups[group])
-
- self._AddNontranslateableChunk(text_to_parse[chunk_start:])
-
- if self.single_message_:
- self.skeleton_.append(self.uberclique.MakeClique(self.single_message_))
-
diff --git a/tools/grit/grit/gather/skeleton_gatherer.py b/tools/grit/grit/gather/skeleton_gatherer.py
deleted file mode 100644
index 15cb3f3..0000000
--- a/tools/grit/grit/gather/skeleton_gatherer.py
+++ /dev/null
@@ -1,127 +0,0 @@
-#!/usr/bin/python2.4
-# Copyright (c) 2011 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.
-
-'''A baseclass for simple gatherers that store their gathered resource in a
-list.
-'''
-
-import re
-import types
-
-from grit.gather import interface
-from grit import clique
-from grit import tclib
-
-
-class SkeletonGatherer(interface.GathererBase):
- '''Common functionality of gatherers that parse their input as a skeleton of
- translatable and nontranslatable chunks.
- '''
-
- def __init__(self):
- interface.GathererBase.__init__(self)
- # List of parts of the document. Translateable parts are
- # clique.MessageClique objects, nontranslateable parts are plain strings.
- # Translated messages are inserted back into the skeleton using the quoting
- # rules defined by self.Escape()
- self.skeleton_ = []
- # A list of the names of IDs that need to be defined for this resource
- # section to compile correctly.
- self.ids_ = []
- # True if Parse() has already been called.
- self.have_parsed_ = False
- # True if a translatable chunk has been added
- self.translatable_chunk_ = False
- # If not None, all parts of the document will be put into this single
- # message; otherwise the normal skeleton approach is used.
- self.single_message_ = None
- # Number to use for the next placeholder name. Used only if single_message
- # is not None
- self.ph_counter_ = 1
-
- def GetText(self):
- '''Returns the original text of the section'''
- return self.text_
-
- def Escape(self, text):
- '''Subclasses can override. Base impl is identity.
- '''
- return text
-
- def UnEscape(self, text):
- '''Subclasses can override. Base impl is identity.
- '''
- return text
-
- def GetTextualIds(self):
- '''Returns the list of textual IDs that need to be defined for this
- resource section to compile correctly.'''
- return self.ids_
-
- def _AddTextualId(self, id):
- self.ids_.append(id)
-
- def GetCliques(self):
- '''Returns the message cliques for each translateable message in the
- resource section.'''
- return filter(lambda x: isinstance(x, clique.MessageClique), self.skeleton_)
-
- def Translate(self, lang, pseudo_if_not_available=True,
- skeleton_gatherer=None, fallback_to_english=False):
- if len(self.skeleton_) == 0:
- raise exception.NotReady()
- if skeleton_gatherer:
- assert len(skeleton_gatherer.skeleton_) == len(self.skeleton_)
-
- out = []
- for ix in range(len(self.skeleton_)):
- if isinstance(self.skeleton_[ix], types.StringTypes):
- if skeleton_gatherer:
- # Make sure the skeleton is like the original
- assert(isinstance(skeleton_gatherer.skeleton_[ix], types.StringTypes))
- out.append(skeleton_gatherer.skeleton_[ix])
- else:
- out.append(self.skeleton_[ix])
- else:
- if skeleton_gatherer: # Make sure the skeleton is like the original
- assert(not isinstance(skeleton_gatherer.skeleton_[ix],
- types.StringTypes))
- msg = self.skeleton_[ix].MessageForLanguage(lang,
- pseudo_if_not_available,
- fallback_to_english)
-
- def MyEscape(text):
- return self.Escape(text)
- text = msg.GetRealContent(escaping_function=MyEscape)
- out.append(text)
- return ''.join(out)
-
- def Parse(self):
- '''Parses the section. Implemented by subclasses. Idempotent.'''
- raise NotImplementedError()
-
- def _AddNontranslateableChunk(self, chunk):
- '''Adds a nontranslateable chunk.'''
- if self.single_message_:
- ph = tclib.Placeholder('XX%02dXX' % self.ph_counter_, chunk, chunk)
- self.ph_counter_ += 1
- self.single_message_.AppendPlaceholder(ph)
- else:
- self.skeleton_.append(chunk)
-
- def _AddTranslateableChunk(self, chunk):
- '''Adds a translateable chunk. It will be unescaped before being added.'''
- # We don't want empty messages since they are redundant and the TC
- # doesn't allow them.
- if chunk == '':
- return
-
- unescaped_text = self.UnEscape(chunk)
- if self.single_message_:
- self.single_message_.AppendText(unescaped_text)
- else:
- self.skeleton_.append(self.uberclique.MakeClique(
- tclib.Message(text=unescaped_text)))
- self.translatable_chunk_ = True
diff --git a/tools/grit/grit/gather/tr_html.py b/tools/grit/grit/gather/tr_html.py
deleted file mode 100644
index 269e6f2..0000000
--- a/tools/grit/grit/gather/tr_html.py
+++ /dev/null
@@ -1,679 +0,0 @@
-#!/usr/bin/python2.4
-# Copyright (c) 2006-2008 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.
-
-'''A gatherer for the TotalRecall brand of HTML templates with replaceable
-portions. We wanted to reuse extern.tclib.api.handlers.html.TCHTMLParser
-but this proved impossible due to the fact that the TotalRecall HTML templates
-are in general quite far from parseable HTML and the TCHTMLParser derives
-from HTMLParser.HTMLParser which requires relatively well-formed HTML. Some
-examples of "HTML" from the TotalRecall HTML templates that wouldn't be
-parseable include things like:
-
- <a [PARAMS]>blabla</a> (not parseable because attributes are invalid)
-
- <table><tr><td>[LOTSOFSTUFF]</tr></table> (not parseable because closing
- </td> is in the HTML [LOTSOFSTUFF]
- is replaced by)
-
-The other problem with using general parsers (such as TCHTMLParser) is that
-we want to make sure we output the TotalRecall template with as little changes
-as possible in terms of whitespace characters, layout etc. With any parser
-that generates a parse tree, and generates output by dumping the parse tree,
-we would always have little inconsistencies which could cause bugs (the
-TotalRecall template stuff is quite brittle and can break if e.g. a tab
-character is replaced with spaces).
-
-The solution, which may be applicable to some other HTML-like template
-languages floating around Google, is to create a parser with a simple state
-machine that keeps track of what kind of tag it's inside, and whether it's in
-a translateable section or not. Translateable sections are:
-
-a) text (including [BINGO] replaceables) inside of tags that
- can contain translateable text (which is all tags except
- for a few)
-
-b) text inside of an 'alt' attribute in an <image> element, or
- the 'value' attribute of a <submit>, <button> or <text>
- element.
-
-The parser does not build up a parse tree but rather a "skeleton" which
-is a list of nontranslateable strings intermingled with grit.clique.MessageClique
-objects. This simplifies the parser considerably compared to a regular HTML
-parser. To output a translated document, each item in the skeleton is
-printed out, with the relevant Translation from each MessageCliques being used
-for the requested language.
-
-This implementation borrows some code, constants and ideas from
-extern.tclib.api.handlers.html.TCHTMLParser.
-'''
-
-
-import re
-import types
-
-from grit import clique
-from grit import exception
-from grit import util
-from grit import tclib
-
-from grit.gather import interface
-
-
-# HTML tags which break (separate) chunks.
-_BLOCK_TAGS = ['script', 'p', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'hr', 'br',
- 'body', 'style', 'head', 'title', 'table', 'tr', 'td', 'th',
- 'ul', 'ol', 'dl', 'nl', 'li', 'div', 'object', 'center',
- 'html', 'link', 'form', 'select', 'textarea',
- 'button', 'option', 'map', 'area', 'blockquote', 'pre',
- 'meta', 'xmp', 'noscript', 'label', 'tbody', 'thead',
- 'script', 'style', 'pre', 'iframe', 'img', 'input', 'nowrap']
-
-# HTML tags which may appear within a chunk.
-_INLINE_TAGS = ['b', 'i', 'u', 'tt', 'code', 'font', 'a', 'span', 'small',
- 'key', 'nobr', 'url', 'em', 's', 'sup', 'strike',
- 'strong']
-
-# HTML tags within which linebreaks are significant.
-_PREFORMATTED_TAGS = ['textarea', 'xmp', 'pre']
-
-# An array mapping some of the inline HTML tags to more meaningful
-# names for those tags. This will be used when generating placeholders
-# representing these tags.
-_HTML_PLACEHOLDER_NAMES = { 'a' : 'link', 'br' : 'break', 'b' : 'bold',
- 'i' : 'italic', 'li' : 'item', 'ol' : 'ordered_list', 'p' : 'paragraph',
- 'ul' : 'unordered_list', 'img' : 'image', 'em' : 'emphasis' }
-
-# We append each of these characters in sequence to distinguish between
-# different placeholders with basically the same name (e.g. BOLD1, BOLD2).
-# Keep in mind that a placeholder name must not be a substring of any other
-# placeholder name in the same message, so we can't simply count (BOLD_1
-# would be a substring of BOLD_10).
-_SUFFIXES = '123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ'
-
-# Matches whitespace in an HTML document. Also matches HTML comments, which are
-# treated as whitespace.
-_WHITESPACE = re.compile(r'(\s|&nbsp;|\\n|\\r|<!--\s*desc\s*=.*?-->)+',
- re.DOTALL)
-
-# Finds a non-whitespace character
-_NON_WHITESPACE = re.compile(r'\S')
-
-# Matches two or more &nbsp; in a row (a single &nbsp is not changed into
-# placeholders because different languages require different numbers of spaces
-# and placeholders must match exactly; more than one is probably a "special"
-# whitespace sequence and should be turned into a placeholder).
-_NBSP = re.compile(r'&nbsp;(&nbsp;)+')
-
-# Matches nontranslateable chunks of the document
-_NONTRANSLATEABLES = re.compile(r'''
- <\s*script.+?<\s*/\s*script\s*>
- |
- <\s*style.+?<\s*/\s*style\s*>
- |
- <!--.+?-->
- |
- <\?IMPORT\s.+?> # import tag
- |
- <\s*[a-zA-Z_]+:.+?> # custom tag (open)
- |
- <\s*/\s*[a-zA-Z_]+:.+?> # custom tag (close)
- |
- <!\s*[A-Z]+\s*([^>]+|"[^"]+"|'[^']+')*?>
- ''', re.MULTILINE | re.DOTALL | re.VERBOSE | re.IGNORECASE)
-
-# Matches a tag and its attributes
-_ELEMENT = re.compile(r'''
- # Optional closing /, element name
- <\s*(?P<closing>/)?\s*(?P<element>[a-zA-Z0-9]+)\s*
- # Attributes and/or replaceables inside the tag, if any
- (?P<atts>(
- \s*([a-zA-Z_][-:.a-zA-Z_0-9]*) # Attribute name
- (\s*=\s*(\'[^\']*\'|"[^"]*"|[-a-zA-Z0-9./,:;+*%?!&$\(\)_#=~\'"@]*))?
- |
- \s*\[(\$?\~)?([A-Z0-9-_]+?)(\~\$?)?\]
- )*)
- \s*(?P<empty>/)?\s*> # Optional empty-tag closing /, and tag close
- ''',
- re.MULTILINE | re.DOTALL | re.VERBOSE)
-
-# Matches elements that may have translateable attributes. The value of these
-# special attributes is given by group 'value1' or 'value2'. Note that this
-# regexp demands that the attribute value be quoted; this is necessary because
-# the non-tree-building nature of the parser means we don't know when we're
-# writing out attributes, so we wouldn't know to escape spaces.
-_SPECIAL_ELEMENT = re.compile(r'''
- <\s*(
- input[^>]+?value\s*=\s*(\'(?P<value3>[^\']*)\'|"(?P<value4>[^"]*)")
- [^>]+type\s*=\s*"?'?(button|reset|text|submit)'?"?
- |
- (
- table[^>]+?title\s*=
- |
- img[^>]+?alt\s*=
- |
- input[^>]+?type\s*=\s*"?'?(button|reset|text|submit)'?"?[^>]+?value\s*=
- )
- \s*(\'(?P<value1>[^\']*)\'|"(?P<value2>[^"]*)")
- )[^>]*?>
- ''', re.MULTILINE | re.DOTALL | re.VERBOSE | re.IGNORECASE)
-
-# Matches stuff that is translateable if it occurs in the right context
-# (between tags). This includes all characters and character entities.
-# Note that this also matches &nbsp; which needs to be handled as whitespace
-# before this regexp is applied.
-_CHARACTERS = re.compile(r'''
- (
- \w
- |
- [\!\@\#\$\%\^\*\(\)\-\=\_\+\[\]\{\}\\\|\;\:\'\"\,\.\/\?\`\~]
- |
- &(\#[0-9]+|\#x[0-9a-fA-F]+|[A-Za-z0-9]+);
- )+
- ''', re.MULTILINE | re.DOTALL | re.VERBOSE)
-
-# Matches Total Recall's "replaceable" tags, which are just any text
-# in capitals enclosed by delimiters like [] or [~~] or [$~~$] (e.g. [HELLO],
-# [~HELLO~] and [$~HELLO~$]).
-_REPLACEABLE = re.compile(r'\[(\$?\~)?(?P<name>[A-Z0-9-_]+?)(\~\$?)?\]',
- re.MULTILINE)
-
-
-# Matches the silly [!]-prefixed "header" that is used in some TotalRecall
-# templates.
-_SILLY_HEADER = re.compile(r'\[!\]\ntitle\t(?P<title>[^\n]+?)\n.+?\n\n',
- re.MULTILINE | re.DOTALL)
-
-
-# Matches a comment that provides a description for the message it occurs in.
-_DESCRIPTION_COMMENT = re.compile(
- r'<!--\s*desc\s*=\s*(?P<description>.+?)\s*-->', re.DOTALL)
-
-
-_DEBUG = 0
-def _DebugPrint(text):
- if _DEBUG:
- print text.encode('utf-8')
-
-
-class HtmlChunks(object):
- '''A parser that knows how to break an HTML-like document into a list of
- chunks, where each chunk is either translateable or non-translateable.
- The chunks are unmodified sections of the original document, so concatenating
- the text of all chunks would result in the original document.'''
-
- def InTranslateable(self):
- return self.last_translateable != -1
-
- def Rest(self):
- return self.text_[self.current:]
-
- def StartTranslateable(self):
- assert not self.InTranslateable()
- if self.current != 0:
- # Append a nontranslateable chunk
- chunk_text = self.text_[self.chunk_start : self.last_nontranslateable + 1]
- # Needed in the case where document starts with a translateable.
- if len(chunk_text) > 0:
- self.AddChunk(False, chunk_text)
- self.chunk_start = self.last_nontranslateable + 1
- self.last_translateable = self.current
- self.last_nontranslateable = -1
-
- def EndTranslateable(self):
- assert self.InTranslateable()
- # Append a translateable chunk
- self.AddChunk(True,
- self.text_[self.chunk_start : self.last_translateable + 1])
- self.chunk_start = self.last_translateable + 1
- self.last_translateable = -1
- self.last_nontranslateable = self.current
-
- def AdvancePast(self, match):
- self.current += match.end()
-
- def AddChunk(self, translateable, text):
- '''Adds a chunk to self, removing linebreaks and duplicate whitespace
- if appropriate.
- '''
- if translateable and not self.last_element_ in _PREFORMATTED_TAGS:
- text = text.replace('\n', ' ')
- text = text.replace('\r', ' ')
- text = text.replace(' ', ' ')
- text = text.replace(' ', ' ')
-
- m = _DESCRIPTION_COMMENT.search(text)
- if m:
- self.last_description = m.group('description')
- # remove the description from the output text
- text = _DESCRIPTION_COMMENT.sub('', text)
-
- if translateable:
- description = self.last_description
- self.last_description = ''
- else:
- description = ''
-
- if text != '':
- self.chunks_.append((translateable, text, description))
-
- def Parse(self, text):
- '''Parses self.text_ into an intermediate format stored in self.chunks_
- which is translateable and nontranslateable chunks. Also returns
- self.chunks_
-
- Return:
- [chunk1, chunk2, chunk3, ...] (instances of class Chunk)
- '''
- #
- # Chunker state
- #
-
- self.text_ = text
-
- # A list of tuples (is_translateable, text) which represents the document
- # after chunking.
- self.chunks_ = []
-
- # Start index of the last chunk, whether translateable or not
- self.chunk_start = 0
-
- # Index of the last for-sure translateable character if we are parsing
- # a translateable chunk, -1 to indicate we are not in a translateable chunk.
- # This is needed so that we don't include trailing whitespace in the
- # translateable chunk (whitespace is neutral).
- self.last_translateable = -1
-
- # Index of the last for-sure nontranslateable character if we are parsing
- # a nontranslateable chunk, -1 if we are not in a nontranslateable chunk.
- # This is needed to make sure we can group e.g. "<b>Hello</b> there"
- # together instead of just "Hello</b> there" which would be much worse
- # for translation.
- self.last_nontranslateable = -1
-
- # Index of the character we're currently looking at.
- self.current = 0
-
- # The name of the last block element parsed.
- self.last_element_ = ''
-
- # The last explicit description we found.
- self.last_description = ''
-
- while self.current < len(self.text_):
- _DebugPrint('REST: %s' % self.text_[self.current:self.current+60])
-
- # First try to match whitespace
- m = _WHITESPACE.match(self.Rest())
- if m:
- # Whitespace is neutral, it just advances 'current' and does not switch
- # between translateable/nontranslateable. If we are in a
- # nontranslateable section that extends to the current point, we extend
- # it to include the whitespace. If we are in a translateable section,
- # we do not extend it until we find
- # more translateable parts, because we never want a translateable chunk
- # to end with whitespace.
- if (not self.InTranslateable() and
- self.last_nontranslateable == self.current - 1):
- self.last_nontranslateable = self.current + m.end() - 1
- self.AdvancePast(m)
- continue
-
- # Then we try to match nontranslateables
- m = _NONTRANSLATEABLES.match(self.Rest())
- if m:
- if self.InTranslateable():
- self.EndTranslateable()
- self.last_nontranslateable = self.current + m.end() - 1
- self.AdvancePast(m)
- continue
-
- # Now match all other HTML element tags (opening, closing, or empty, we
- # don't care).
- m = _ELEMENT.match(self.Rest())
- if m:
- element_name = m.group('element').lower()
- if element_name in _BLOCK_TAGS:
- self.last_element_ = element_name
- if self.InTranslateable():
- self.EndTranslateable()
-
- # Check for "special" elements, i.e. ones that have a translateable
- # attribute, and handle them correctly. Note that all of the
- # "special" elements are block tags, so no need to check for this
- # if the tag is not a block tag.
- sm = _SPECIAL_ELEMENT.match(self.Rest())
- if sm:
- # Get the appropriate group name
- for group in sm.groupdict().keys():
- if sm.groupdict()[group]:
- break
-
- # First make a nontranslateable chunk up to and including the
- # quote before the translateable attribute value
- self.AddChunk(False, self.text_[
- self.chunk_start : self.current + sm.start(group)])
- # Then a translateable for the translateable bit
- self.AddChunk(True, self.Rest()[sm.start(group) : sm.end(group)])
- # Finally correct the data invariant for the parser
- self.chunk_start = self.current + sm.end(group)
-
- self.last_nontranslateable = self.current + m.end() - 1
- elif self.InTranslateable():
- # We're in a translateable and the tag is an inline tag, so we
- # need to include it in the translateable.
- self.last_translateable = self.current + m.end() - 1
- self.AdvancePast(m)
- continue
-
- # Anything else we find must be translateable, so we advance one character
- # at a time until one of the above matches.
- if not self.InTranslateable():
- self.StartTranslateable()
- else:
- self.last_translateable = self.current
- self.current += 1
-
- # Close the final chunk
- if self.InTranslateable():
- self.AddChunk(True, self.text_[self.chunk_start : ])
- else:
- self.AddChunk(False, self.text_[self.chunk_start : ])
-
- return self.chunks_
-
-
-def HtmlToMessage(html, include_block_tags=False, description=''):
- '''Takes a bit of HTML, which must contain only "inline" HTML elements,
- and changes it into a tclib.Message. This involves escaping any entities and
- replacing any HTML code with placeholders.
-
- If include_block_tags is true, no error will be given if block tags (e.g.
- <p> or <br>) are included in the HTML.
-
- Args:
- html: 'Hello <b>[USERNAME]</b>, how&nbsp;<i>are</i> you?'
- include_block_tags: False
-
- Return:
- tclib.Message('Hello START_BOLD1USERNAMEEND_BOLD, '
- 'howNBSPSTART_ITALICareEND_ITALIC you?',
- [ Placeholder('START_BOLD', '<b>', ''),
- Placeholder('USERNAME', '[USERNAME]', ''),
- Placeholder('END_BOLD', '</b>', ''),
- Placeholder('START_ITALIC', '<i>', ''),
- Placeholder('END_ITALIC', '</i>', ''), ])
- '''
- # Approach is:
- # - first placeholderize, finding <elements>, [REPLACEABLES] and &nbsp;
- # - then escape all character entities in text in-between placeholders
-
- parts = [] # List of strings (for text chunks) and tuples (ID, original)
- # for placeholders
-
- count_names = {} # Map of base names to number of times used
- end_names = {} # Map of base names to stack of end tags (for correct nesting)
-
- def MakeNameClosure(base, type = ''):
- '''Returns a closure that can be called once all names have been allocated
- to return the final name of the placeholder. This allows us to minimally
- number placeholders for non-overlap.
-
- Also ensures that END_XXX_Y placeholders have the same Y as the
- corresponding BEGIN_XXX_Y placeholder when we have nested tags of the same
- type.
-
- Args:
- base: 'phname'
- type: '' | 'begin' | 'end'
-
- Return:
- Closure()
- '''
- name = base
- if type != '':
- name = ('%s_%s' % (type, base)).upper()
-
- if name in count_names.keys():
- count_names[name] += 1
- else:
- count_names[name] = 1
-
- def MakeFinalName(name_ = name, index = count_names[name] - 1):
- if (type.lower() == 'end' and
- base in end_names.keys() and len(end_names[base])):
- return end_names[base].pop(-1) # For correct nesting
- if count_names[name_] != 1:
- name_ = '%s_%s' % (name_, _SUFFIXES[index])
- # We need to use a stack to ensure that the end-tag suffixes match
- # the begin-tag suffixes. Only needed when more than one tag of the
- # same type.
- if type == 'begin':
- end_name = ('END_%s_%s' % (base, _SUFFIXES[index])).upper()
- if base in end_names.keys():
- end_names[base].append(end_name)
- else:
- end_names[base] = [end_name]
-
- return name_
-
- return MakeFinalName
-
- current = 0
-
- while current < len(html):
- m = _NBSP.match(html[current:])
- if m:
- parts.append((MakeNameClosure('SPACE'), m.group()))
- current += m.end()
- continue
-
- m = _REPLACEABLE.match(html[current:])
- if m:
- # Replaceables allow - but placeholders don't, so replace - with _
- ph_name = MakeNameClosure('X_%s_X' % m.group('name').replace('-', '_'))
- parts.append((ph_name, m.group()))
- current += m.end()
- continue
-
- m = _SPECIAL_ELEMENT.match(html[current:])
- if m:
- if not include_block_tags:
- raise exception.BlockTagInTranslateableChunk(html)
- element_name = 'block' # for simplification
- # Get the appropriate group name
- for group in m.groupdict().keys():
- if m.groupdict()[group]:
- break
- parts.append((MakeNameClosure(element_name, 'begin'),
- html[current : current + m.start(group)]))
- parts.append(m.group(group))
- parts.append((MakeNameClosure(element_name, 'end'),
- html[current + m.end(group) : current + m.end()]))
- current += m.end()
- continue
-
- m = _ELEMENT.match(html[current:])
- if m:
- element_name = m.group('element').lower()
- if not include_block_tags and not element_name in _INLINE_TAGS:
- raise exception.BlockTagInTranslateableChunk(html[current:])
- if element_name in _HTML_PLACEHOLDER_NAMES: # use meaningful names
- element_name = _HTML_PLACEHOLDER_NAMES[element_name]
-
- # Make a name for the placeholder
- type = ''
- if not m.group('empty'):
- if m.group('closing'):
- type = 'end'
- else:
- type = 'begin'
- parts.append((MakeNameClosure(element_name, type), m.group()))
- current += m.end()
- continue
-
- if len(parts) and isinstance(parts[-1], types.StringTypes):
- parts[-1] += html[current]
- else:
- parts.append(html[current])
- current += 1
-
- msg_text = ''
- placeholders = []
- for part in parts:
- if isinstance(part, types.TupleType):
- final_name = part[0]()
- original = part[1]
- msg_text += final_name
- placeholders.append(tclib.Placeholder(final_name, original, '(HTML code)'))
- else:
- msg_text += part
-
- msg = tclib.Message(text=msg_text, placeholders=placeholders,
- description=description)
- content = msg.GetContent()
- for ix in range(len(content)):
- if isinstance(content[ix], types.StringTypes):
- content[ix] = util.UnescapeHtml(content[ix], replace_nbsp=False)
-
- return msg
-
-
-class TrHtml(interface.GathererBase):
- '''Represents a document or message in the template format used by
- Total Recall for HTML documents.'''
-
- def __init__(self, text):
- '''Creates a new object that represents 'text'.
- Args:
- text: '<html>...</html>'
- '''
- super(type(self), self).__init__()
-
- self.text_ = text
- self.have_parsed_ = False
- self.skeleton_ = [] # list of strings and MessageClique objects
-
- def GetText(self):
- '''Returns the original text of the HTML document'''
- return self.text_
-
- def GetCliques(self):
- '''Returns the message cliques for each translateable message in the
- document.'''
- return filter(lambda x: isinstance(x, clique.MessageClique), self.skeleton_)
-
- def Translate(self, lang, pseudo_if_not_available=True,
- skeleton_gatherer=None, fallback_to_english=False):
- '''Returns this document with translateable messages filled with
- the translation for language 'lang'.
-
- Args:
- lang: 'en'
- pseudo_if_not_available: True
-
- Return:
- 'ID_THIS_SECTION TYPE\n...BEGIN\n "Translated message"\n......\nEND
-
- Raises:
- grit.exception.NotReady() if used before Parse() has been successfully
- called.
- grit.exception.NoSuchTranslation() if 'pseudo_if_not_available' is false
- and there is no translation for the requested language.
- '''
- if len(self.skeleton_) == 0:
- raise exception.NotReady()
-
- # TODO(joi) Implement support for skeleton gatherers here.
-
- out = []
- for item in self.skeleton_:
- if isinstance(item, types.StringTypes):
- out.append(item)
- else:
- msg = item.MessageForLanguage(lang,
- pseudo_if_not_available,
- fallback_to_english)
- for content in msg.GetContent():
- if isinstance(content, tclib.Placeholder):
- out.append(content.GetOriginal())
- else:
- # We escape " characters to increase the chance that attributes
- # will be properly escaped.
- out.append(util.EscapeHtml(content, True))
-
- return ''.join(out)
-
-
- # Parsing is done in two phases: First, we break the document into
- # translateable and nontranslateable chunks. Second, we run through each
- # translateable chunk and insert placeholders for any HTML elements, unescape
- # escaped characters, etc.
- def Parse(self):
- if self.have_parsed_:
- return
- self.have_parsed_ = True
-
- text = self.text_
-
- # First handle the silly little [!]-prefixed header because it's not
- # handled by our HTML parsers.
- m = _SILLY_HEADER.match(text)
- if m:
- self.skeleton_.append(text[:m.start('title')])
- self.skeleton_.append(self.uberclique.MakeClique(
- tclib.Message(text=text[m.start('title'):m.end('title')])))
- self.skeleton_.append(text[m.end('title') : m.end()])
- text = text[m.end():]
-
- chunks = HtmlChunks().Parse(text)
-
- for chunk in chunks:
- if chunk[0]: # Chunk is translateable
- self.skeleton_.append(self.uberclique.MakeClique(
- HtmlToMessage(chunk[1], description=chunk[2])))
- else:
- self.skeleton_.append(chunk[1])
-
- # Go through the skeleton and change any messages that consist solely of
- # placeholders and whitespace into nontranslateable strings.
- for ix in range(len(self.skeleton_)):
- got_text = False
- if isinstance(self.skeleton_[ix], clique.MessageClique):
- msg = self.skeleton_[ix].GetMessage()
- for item in msg.GetContent():
- if (isinstance(item, types.StringTypes) and _NON_WHITESPACE.search(item)
- and item != '&nbsp;'):
- got_text = True
- break
- if not got_text:
- self.skeleton_[ix] = msg.GetRealContent()
-
-
- # Static method
- def FromFile(html, extkey=None, encoding = 'utf-8'):
- '''Creates a TrHtml object from the contents of 'html' which are decoded
- using 'encoding'. Returns a new TrHtml object, upon which Parse() has not
- been called.
-
- Args:
- html: file('') | 'filename.html'
- extkey: ignored
- encoding: 'utf-8' (note that encoding is ignored if 'html' is not a file
- name but instead an open file or file-like object)
-
- Return:
- TrHtml(text_of_file)
- '''
- if isinstance(html, types.StringTypes):
- html = util.WrapInputStream(file(html, 'r'), encoding)
- doc = html.read()
-
- # Ignore the BOM character if the document starts with one.
- if len(doc) and doc[0] == u'\ufeff':
- doc = doc[1:]
-
- return TrHtml(doc)
- FromFile = staticmethod(FromFile)
-
diff --git a/tools/grit/grit/gather/tr_html_unittest.py b/tools/grit/grit/gather/tr_html_unittest.py
deleted file mode 100644
index 2a59c3a..0000000
--- a/tools/grit/grit/gather/tr_html_unittest.py
+++ /dev/null
@@ -1,412 +0,0 @@
-#!/usr/bin/python2.4
-# Copyright (c) 2011 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.
-
-'''Unit tests for grit.gather.tr_html'''
-
-
-import os
-import sys
-if __name__ == '__main__':
- sys.path.append(os.path.join(os.path.dirname(sys.argv[0]), '../..'))
-
-import types
-import unittest
-
-from grit.gather import tr_html
-from grit import clique
-from grit import util
-
-
-class ParserUnittest(unittest.TestCase):
- def testChunking(self):
- p = tr_html.HtmlChunks()
- chunks = p.Parse('<p>Hello <b>dear</b> how <i>are</i>you?<p>Fine!')
- self.failUnless(chunks == [
- (False, '<p>', ''), (True, 'Hello <b>dear</b> how <i>are</i>you?', ''),
- (False, '<p>', ''), (True, 'Fine!', '')])
-
- chunks = p.Parse('<p> Hello <b>dear</b> how <i>are</i>you? <p>Fine!')
- self.failUnless(chunks == [
- (False, '<p> ', ''), (True, 'Hello <b>dear</b> how <i>are</i>you?', ''),
- (False, ' <p>', ''), (True, 'Fine!', '')])
-
- chunks = p.Parse('<p> Hello <b>dear how <i>are you? <p> Fine!')
- self.failUnless(chunks == [
- (False, '<p> ', ''), (True, 'Hello <b>dear how <i>are you?', ''),
- (False, ' <p> ', ''), (True, 'Fine!', '')])
-
- # Ensure translateable sections that start with inline tags contain
- # the starting inline tag.
- chunks = p.Parse('<b>Hello!</b> how are you?<p><i>I am fine.</i>')
- self.failUnless(chunks == [
- (True, '<b>Hello!</b> how are you?', ''), (False, '<p>', ''),
- (True, '<i>I am fine.</i>', '')])
-
- # Ensure translateable sections that end with inline tags contain
- # the ending inline tag.
- chunks = p.Parse("Hello! How are <b>you?</b><p><i>I'm fine!</i>")
- self.failUnless(chunks == [
- (True, 'Hello! How are <b>you?</b>', ''), (False, '<p>', ''),
- (True, "<i>I'm fine!</i>", '')])
-
- # Check capitals and explicit descriptions
- chunks = p.Parse('<!-- desc=bingo! --><B>Hello!</B> how are you?<P><I>I am fine.</I>')
- self.failUnless(chunks == [
- (True, '<B>Hello!</B> how are you?', 'bingo!'), (False, '<P>', ''),
- (True, '<I>I am fine.</I>', '')])
- chunks = p.Parse('<B><!-- desc=bingo! -->Hello!</B> how are you?<P><I>I am fine.</I>')
- self.failUnless(chunks == [
- (True, '<B>Hello!</B> how are you?', 'bingo!'), (False, '<P>', ''),
- (True, '<I>I am fine.</I>', '')])
- # Linebreaks get changed to spaces just like any other HTML content
- chunks = p.Parse('<B>Hello!</B> <!-- desc=bi\nngo\n! -->how are you?<P><I>I am fine.</I>')
- self.failUnless(chunks == [
- (True, '<B>Hello!</B> how are you?', 'bi ngo !'), (False, '<P>', ''),
- (True, '<I>I am fine.</I>', '')])
-
- # In this case, because the explicit description appears after the first
- # translateable, it will actually apply to the second translateable.
- chunks = p.Parse('<B>Hello!</B> how are you?<!-- desc=bingo! --><P><I>I am fine.</I>')
- self.failUnless(chunks == [
- (True, '<B>Hello!</B> how are you?', ''), (False, '<P>', ''),
- (True, '<I>I am fine.</I>', 'bingo!')])
-
- # Check that replaceables within block tags (where attributes would go) are
- # handled correctly.
- chunks = p.Parse('<b>Hello!</b> how are you?<p [BINGO] [$~BONGO~$]>'
- '<i>I am fine.</i>')
- self.failUnless(chunks == [
- (True, '<b>Hello!</b> how are you?', ''),
- (False, '<p [BINGO] [$~BONGO~$]>', ''),
- (True, '<i>I am fine.</i>', '')])
-
- # Check that the contents of preformatted tags preserve line breaks.
- chunks = p.Parse('<textarea>Hello\nthere\nhow\nare\nyou?</textarea>')
- self.failUnless(chunks == [(False, '<textarea>', ''),
- (True, 'Hello\nthere\nhow\nare\nyou?', ''), (False, '</textarea>', '')])
-
- # ...and that other tags' line breaks are converted to spaces
- chunks = p.Parse('<p>Hello\nthere\nhow\nare\nyou?</p>')
- self.failUnless(chunks == [(False, '<p>', ''),
- (True, 'Hello there how are you?', ''), (False, '</p>', '')])
-
- def testTranslateableAttributes(self):
- p = tr_html.HtmlChunks()
-
- # Check that the translateable attributes in <img>, <submit>, <button> and
- # <text> elements buttons are handled correctly.
- chunks = p.Parse('<img src=bingo.jpg alt="hello there">'
- '<input type=submit value="hello">'
- '<input type="button" value="hello">'
- '<input type=\'text\' value=\'Howdie\'>')
- self.failUnless(chunks == [
- (False, '<img src=bingo.jpg alt="', ''), (True, 'hello there', ''),
- (False, '"><input type=submit value="', ''), (True, 'hello', ''),
- (False, '"><input type="button" value="', ''), (True, 'hello', ''),
- (False, '"><input type=\'text\' value=\'', ''), (True, 'Howdie', ''),
- (False, '\'>', '')])
-
-
- def testTranslateableHtmlToMessage(self):
- msg = tr_html.HtmlToMessage(
- 'Hello <b>[USERNAME]</b>, &lt;how&gt;&nbsp;<i>are</i> you?')
- pres = msg.GetPresentableContent()
- self.failUnless(pres ==
- 'Hello BEGIN_BOLDX_USERNAME_XEND_BOLD, '
- '<how>&nbsp;BEGIN_ITALICareEND_ITALIC you?')
-
- msg = tr_html.HtmlToMessage('<b>Hello</b><I>Hello</I><b>Hello</b>')
- pres = msg.GetPresentableContent()
- self.failUnless(pres ==
- 'BEGIN_BOLD_1HelloEND_BOLD_1BEGIN_ITALICHelloEND_ITALIC'
- 'BEGIN_BOLD_2HelloEND_BOLD_2')
-
- # Check that nesting (of the <font> tags) is handled correctly - i.e. that
- # the closing placeholder numbers match the opening placeholders.
- msg = tr_html.HtmlToMessage(
- '''<font size=-1><font color=#FF0000>Update!</font> '''
- '''<a href='http://desktop.google.com/whatsnew.html?hl=[$~LANG~$]'>'''
- '''New Features</a>: Now search PDFs, MP3s, Firefox web history, and '''
- '''more</font>''')
- pres = msg.GetPresentableContent()
- self.failUnless(pres ==
- 'BEGIN_FONT_1BEGIN_FONT_2Update!END_FONT_2 BEGIN_LINK'
- 'New FeaturesEND_LINK: Now search PDFs, MP3s, Firefox '
- 'web history, and moreEND_FONT_1')
-
- msg = tr_html.HtmlToMessage('''<a href='[$~URL~$]'><b>[NUM][CAT]</b></a>''')
- pres = msg.GetPresentableContent()
- self.failUnless(pres == 'BEGIN_LINKBEGIN_BOLDX_NUM_XX_CAT_XEND_BOLDEND_LINK')
-
- msg = tr_html.HtmlToMessage(
- '''<font size=-1><a class=q onClick='return window.qs?qs(this):1' '''
- '''href='http://[WEBSERVER][SEARCH_URI]'>Desktop</a></font>&nbsp;&nbsp;'''
- '''&nbsp;&nbsp;''')
- pres = msg.GetPresentableContent()
- self.failUnless(pres ==
- '''BEGIN_FONTBEGIN_LINKDesktopEND_LINKEND_FONTSPACE''')
-
- msg = tr_html.HtmlToMessage(
- '''<br><br><center><font size=-2>&copy;2005 Google </font></center>''', 1)
- pres = msg.GetPresentableContent()
- self.failUnless(pres ==
- u'BEGIN_BREAK_1BEGIN_BREAK_2BEGIN_CENTERBEGIN_FONT\xa92005'
- u' Google END_FONTEND_CENTER')
-
- msg = tr_html.HtmlToMessage(
- '''&nbsp;-&nbsp;<a class=c href=[$~CACHE~$]>Cached</a>''')
- pres = msg.GetPresentableContent()
- self.failUnless(pres ==
- '&nbsp;-&nbsp;BEGIN_LINKCachedEND_LINK')
-
- # Check that upper-case tags are handled correctly.
- msg = tr_html.HtmlToMessage(
- '''You can read the <A HREF='http://desktop.google.com/privacypolicy.'''
- '''html?hl=[LANG_CODE]'>Privacy Policy</A> and <A HREF='http://desktop'''
- '''.google.com/privacyfaq.html?hl=[LANG_CODE]'>Privacy FAQ</A> online.''')
- pres = msg.GetPresentableContent()
- self.failUnless(pres ==
- 'You can read the BEGIN_LINK_1Privacy PolicyEND_LINK_1 and '
- 'BEGIN_LINK_2Privacy FAQEND_LINK_2 online.')
-
- # Check that tags with linebreaks immediately preceding them are handled
- # correctly.
- msg = tr_html.HtmlToMessage(
- '''You can read the
-<A HREF='http://desktop.google.com/privacypolicy.html?hl=[LANG_CODE]'>Privacy Policy</A>
-and <A HREF='http://desktop.google.com/privacyfaq.html?hl=[LANG_CODE]'>Privacy FAQ</A> online.''')
- pres = msg.GetPresentableContent()
- self.failUnless(pres == '''You can read the
-BEGIN_LINK_1Privacy PolicyEND_LINK_1
-and BEGIN_LINK_2Privacy FAQEND_LINK_2 online.''')
-
-
-
-class TrHtmlUnittest(unittest.TestCase):
- def testTable(self):
- html = tr_html.TrHtml('''<table class="shaded-header"><tr>
-<td class="header-element b expand">Preferences</td>
-<td class="header-element s">
-<a href="http://desktop.google.com/preferences.html">Preferences&nbsp;Help</a>
-</td>
-</tr></table>''')
- html.Parse()
- self.failUnless(html.skeleton_[3].GetMessage().GetPresentableContent() ==
- 'BEGIN_LINKPreferences&nbsp;HelpEND_LINK')
-
- def testSubmitAttribute(self):
- html = tr_html.TrHtml('''</td>
-<td class="header-element"><input type=submit value="Save Preferences"
-name=submit2></td>
-</tr></table>''')
- html.Parse()
- self.failUnless(html.skeleton_[1].GetMessage().GetPresentableContent() ==
- 'Save Preferences')
-
- def testWhitespaceAfterInlineTag(self):
- '''Test that even if there is whitespace after an inline tag at the start
- of a translateable section the inline tag will be included.
- '''
- html = tr_html.TrHtml('''<label for=DISPLAYNONE><font size=-1> Hello</font>''')
- html.Parse()
- self.failUnless(html.skeleton_[1].GetMessage().GetRealContent() ==
- '<font size=-1> Hello</font>')
-
- def testSillyHeader(self):
- html = tr_html.TrHtml('''[!]
-title\tHello
-bingo
-bongo
-bla
-
-<p>Other stuff</p>''')
- html.Parse()
- content = html.skeleton_[1].GetMessage().GetRealContent()
- self.failUnless(content == 'Hello')
- self.failUnless(html.skeleton_[-1] == '</p>')
- # Right after the translateable the nontranslateable should start with
- # a linebreak (this catches a bug we had).
- self.failUnless(html.skeleton_[2][0] == '\n')
-
-
- def testExplicitDescriptions(self):
- html = tr_html.TrHtml('Hello [USER]<br/><!-- desc=explicit --><input type="button">Go!</input>')
- html.Parse()
- msg = html.GetCliques()[1].GetMessage()
- self.failUnless(msg.GetDescription() == 'explicit')
- self.failUnless(msg.GetRealContent() == 'Go!')
-
-
- def testRegressionInToolbarAbout(self):
- html = tr_html.TrHtml.FromFile(
- util.PathFromRoot(r'grit/testdata/toolbar_about.html'))
- html.Parse()
- cliques = html.GetCliques()
- for cl in cliques:
- content = cl.GetMessage().GetRealContent()
- if content.count('De parvis grandis acervus erit'):
- self.failIf(content.count('$/translate'))
-
-
- def HtmlFromFileWithManualCheck(self, f):
- html = tr_html.TrHtml.FromFile(f)
- html.Parse()
-
- # For manual results inspection only...
- list = []
- for item in html.skeleton_:
- if isinstance(item, types.StringTypes):
- list.append(item)
- else:
- list.append(item.GetMessage().GetPresentableContent())
-
- return html
-
-
- def testPrivacyHtml(self):
- html = self.HtmlFromFileWithManualCheck(
- util.PathFromRoot(r'grit/testdata/privacy.html'))
-
- self.failUnless(html.skeleton_[1].GetMessage().GetRealContent() ==
- 'Privacy and Google Desktop Search')
- self.failUnless(html.skeleton_[3].startswith('<'))
- self.failUnless(len(html.skeleton_) > 10)
-
-
- def testPreferencesHtml(self):
- html = self.HtmlFromFileWithManualCheck(
- util.PathFromRoot(r'grit/testdata/preferences.html'))
-
- # Verify that we don't get '[STATUS-MESSAGE]' as the original content of
- # one of the MessageClique objects (it would be a placeholder-only message
- # and we're supposed to have stripped those).
-
- for item in filter(lambda x: isinstance(x, clique.MessageClique),
- html.skeleton_):
- if (item.GetMessage().GetRealContent() == '[STATUS-MESSAGE]' or
- item.GetMessage().GetRealContent() == '[ADDIN-DO] [ADDIN-OPTIONS]'):
- self.fail()
-
- self.failUnless(len(html.skeleton_) > 100)
-
- def AssertNumberOfTranslateables(self, files, num):
- '''Fails if any of the files in files don't have exactly
- num translateable sections.
-
- Args:
- files: ['file1', 'file2']
- num: 3
- '''
- for f in files:
- f = util.PathFromRoot(r'grit/testdata/%s' % f)
- html = self.HtmlFromFileWithManualCheck(f)
- self.failUnless(len(html.GetCliques()) == num)
-
- def testFewTranslateables(self):
- self.AssertNumberOfTranslateables(['browser.html', 'email_thread.html',
- 'header.html', 'mini.html',
- 'oneclick.html', 'script.html',
- 'time_related.html', 'versions.html'], 0)
- self.AssertNumberOfTranslateables(['footer.html', 'hover.html'], 1)
-
- def testOtherHtmlFilesForManualInspection(self):
- files = [
- 'about.html', 'bad_browser.html', 'cache_prefix.html',
- 'cache_prefix_file.html', 'chat_result.html', 'del_footer.html',
- 'del_header.html', 'deleted.html', 'details.html', 'email_result.html',
- 'error.html', 'explicit_web.html', 'footer.html',
- 'homepage.html', 'indexing_speed.html',
- 'install_prefs.html', 'install_prefs2.html',
- 'oem_enable.html', 'oem_non_admin.html', 'onebox.html',
- 'password.html', 'quit_apps.html', 'recrawl.html',
- 'searchbox.html', 'sidebar_h.html', 'sidebar_v.html', 'status.html',
- ]
- for f in files:
- self.HtmlFromFileWithManualCheck(
- util.PathFromRoot(r'grit/testdata/%s' % f))
-
- def testTranslate(self):
- # Note that the English translation of documents that use character
- # literals (e.g. &copy;) will not be the same as the original document
- # because the character literal will be transformed into the Unicode
- # character itself. So for this test we choose some relatively complex
- # HTML without character entities (but with &nbsp; because that's handled
- # specially).
- html = tr_html.TrHtml(''' <script>
- <!--
- function checkOffice() { var w = document.getElementById("h7");
- var e = document.getElementById("h8"); var o = document.getElementById("h10");
- if (!(w.checked || e.checked)) { o.checked=0;o.disabled=1;} else {o.disabled=0;} }
- // -->
- </script>
- <input type=checkbox [CHECK-DOC] name=DOC id=h7 onclick='checkOffice()'>
- <label for=h7> Word</label><br>
- <input type=checkbox [CHECK-XLS] name=XLS id=h8 onclick='checkOffice()'>
- <label for=h8> Excel</label><br>
- <input type=checkbox [CHECK-PPT] name=PPT id=h9>
- <label for=h9> PowerPoint</label><br>
- </span></td><td nowrap valign=top><span class="s">
- <input type=checkbox [CHECK-PDF] name=PDF id=hpdf>
- <label for=hpdf> PDF</label><br>
- <input type=checkbox [CHECK-TXT] name=TXT id=h6>
- <label for=h6> Text, media, and other files</label><br>
- </tr>&nbsp;&nbsp;
- <tr><td nowrap valign=top colspan=3><span class="s"><br />
- <input type=checkbox [CHECK-SECUREOFFICE] name=SECUREOFFICE id=h10>
- <label for=h10> Password-protected Office documents (Word, Excel)</label><br />
- <input type=checkbox [DISABLED-HTTPS] [CHECK-HTTPS] name=HTTPS id=h12><label
- for=h12> Secure pages (HTTPS) in web history</label></span></td></tr>
- </table>''')
- html.Parse()
- trans = html.Translate('en')
- if (html.GetText() != trans):
- self.fail()
-
-
- def testHtmlToMessageWithBlockTags(self):
- msg = tr_html.HtmlToMessage(
- 'Hello<p>Howdie<img alt="bingo" src="image.gif">', True)
- result = msg.GetPresentableContent()
- self.failUnless(
- result == 'HelloBEGIN_PARAGRAPHHowdieBEGIN_BLOCKbingoEND_BLOCK')
-
- msg = tr_html.HtmlToMessage(
- 'Hello<p>Howdie<input type="button" value="bingo">', True)
- result = msg.GetPresentableContent()
- self.failUnless(
- result == 'HelloBEGIN_PARAGRAPHHowdieBEGIN_BLOCKbingoEND_BLOCK')
-
-
- def testHtmlToMessageRegressions(self):
- msg = tr_html.HtmlToMessage(' - ', True)
- result = msg.GetPresentableContent()
- self.failUnless(result == ' - ')
-
-
- def testEscapeUnescaped(self):
- text = '&copy;&nbsp; & &quot;&lt;hello&gt;&quot;'
- unescaped = util.UnescapeHtml(text)
- self.failUnless(unescaped == u'\u00a9\u00a0 & "<hello>"')
- escaped_unescaped = util.EscapeHtml(unescaped, True)
- self.failUnless(escaped_unescaped ==
- u'\u00a9\u00a0 &amp; &quot;&lt;hello&gt;&quot;')
-
- def testRegressionCjkHtmlFile(self):
- # TODO(joi) Fix this problem where unquoted attributes that
- # have a value that is CJK characters causes the regular expression
- # match never to return. (culprit is the _ELEMENT regexp(
- if False:
- html = self.HtmlFromFileWithManualCheck(util.PathFromRoot(
- r'grit/testdata/ko_oem_enable_bug.html'))
- self.failUnless(True)
-
- def testRegressionCpuHang(self):
- # If this regression occurs, the unit test will never return
- html = tr_html.TrHtml(
- '''<input type=text size=12 id=advFileTypeEntry [~SHOW-FILETYPE-BOX~] value="[EXT]" name=ext>''')
- html.Parse()
-
-if __name__ == '__main__':
- unittest.main()
diff --git a/tools/grit/grit/gather/txt.py b/tools/grit/grit/gather/txt.py
deleted file mode 100644
index 428c202..0000000
--- a/tools/grit/grit/gather/txt.py
+++ /dev/null
@@ -1,52 +0,0 @@
-#!/usr/bin/python2.4
-# Copyright (c) 2006-2008 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.
-
-'''Supports making amessage from a text file.
-'''
-
-import types
-
-from grit.gather import interface
-from grit import tclib
-from grit import util
-
-
-class TxtFile(interface.GathererBase):
- '''A text file gatherer. Very simple, all text from the file becomes a
- single clique.
- '''
-
- def __init__(self, contents):
- super(type(self), self).__init__()
- self.text_ = contents
- self.clique_ = None
-
- def Parse(self):
- self.clique_ = self.uberclique.MakeClique(tclib.Message(text=self.text_))
- pass
-
- def GetText(self):
- '''Returns the text of what is being gathered.'''
- return self.text_
-
- def GetTextualIds(self):
- return []
-
- def GetCliques(self):
- '''Returns the MessageClique objects for all translateable portions.'''
- return [self.clique_]
-
- def Translate(self, lang, pseudo_if_not_available=True,
- skeleton_gatherer=None, fallback_to_english=False):
- return self.clique_.MessageForLanguage(lang,
- pseudo_if_not_available,
- fallback_to_english).GetRealContent()
-
- def FromFile(filename_or_stream, extkey=None, encoding = 'cp1252'):
- if isinstance(filename_or_stream, types.StringTypes):
- filename_or_stream = util.WrapInputStream(file(filename_or_stream, 'rb'), encoding)
- return TxtFile(filename_or_stream.read())
- FromFile = staticmethod(FromFile)
-
diff --git a/tools/grit/grit/gather/txt_unittest.py b/tools/grit/grit/gather/txt_unittest.py
deleted file mode 100644
index 532534e..0000000
--- a/tools/grit/grit/gather/txt_unittest.py
+++ /dev/null
@@ -1,34 +0,0 @@
-#!/usr/bin/python2.4
-# Copyright (c) 2006-2008 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.
-
-'''Unit tests for TxtFile gatherer'''
-
-
-import os
-import sys
-if __name__ == '__main__':
- sys.path.append(os.path.join(os.path.dirname(sys.argv[0]), '../..'))
-
-
-import StringIO
-import unittest
-
-from grit.gather import txt
-
-
-class TxtUnittest(unittest.TestCase):
- def testGather(self):
- input = StringIO.StringIO('Hello there\nHow are you?')
- gatherer = txt.TxtFile.FromFile(input)
- gatherer.Parse()
- self.failUnless(gatherer.GetText() == input.getvalue())
- self.failUnless(len(gatherer.GetCliques()) == 1)
- self.failUnless(gatherer.GetCliques()[0].GetMessage().GetRealContent() ==
- input.getvalue())
-
-
-if __name__ == '__main__':
- unittest.main()
-
diff --git a/tools/grit/grit/grd_reader.py b/tools/grit/grit/grd_reader.py
deleted file mode 100644
index 9e72e38..0000000
--- a/tools/grit/grit/grd_reader.py
+++ /dev/null
@@ -1,176 +0,0 @@
-#!/usr/bin/python2.4
-# Copyright (c) 2011 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.
-
-'''Class for reading GRD files into memory, without processing them.
-'''
-
-import os.path
-import types
-import xml.sax
-import xml.sax.handler
-
-from grit import exception
-from grit.node import base
-from grit.node import mapping
-from grit.node import misc
-from grit import util
-
-
-class StopParsingException(Exception):
- '''An exception used to stop parsing.'''
- pass
-
-
-class GrdContentHandler(xml.sax.handler.ContentHandler):
- def __init__(self,
- stop_after=None, debug=False, defines=None, tags_to_ignore=None):
- # Invariant of data:
- # 'root' is the root of the parse tree being created, or None if we haven't
- # parsed out any elements.
- # 'stack' is the a stack of elements that we push new nodes onto and
- # pop from when they finish parsing, or [] if we are not currently parsing.
- # 'stack[-1]' is the top of the stack.
- self.root = None
- self.stack = []
- self.stop_after = stop_after
- self.debug = debug
- self.defines = defines
- self.tags_to_ignore = tags_to_ignore or set()
- self.ignore_depth = 0
-
- def startElement(self, name, attrs):
- assert not self.root or len(self.stack) > 0
-
- if name in self.tags_to_ignore:
- self.ignore_depth += 1
- if self.debug:
- print "Ignoring element %s and its children" % name
-
- if self.ignore_depth != 0:
- return
-
- if self.debug:
- attr_list = []
- for attr in attrs.getNames():
- attr_list.append('%s="%s"' % (attr, attrs.getValue(attr)))
- if len(attr_list) == 0: attr_list = ['(none)']
- attr_list = ' '.join(attr_list)
- print ("Starting parsing of element %s with attributes %r" %
- (name, attr_list))
-
- typeattr = None
- if 'type' in attrs.getNames():
- typeattr = attrs.getValue('type')
-
- node = mapping.ElementToClass(name, typeattr)()
-
- if not self.root:
- self.root = node
- if self.defines:
- self.root.SetDefines(self.defines)
-
- if len(self.stack) > 0:
- self.stack[-1].AddChild(node)
- node.StartParsing(name, self.stack[-1])
- else:
- node.StartParsing(name, None)
-
- # Push
- self.stack.append(node)
-
- for attr in attrs.getNames():
- node.HandleAttribute(attr, attrs.getValue(attr))
-
- def endElement(self, name):
- if self.ignore_depth == 0:
- if self.debug:
- print "End parsing of element %s" % name
- # Pop
- self.stack[-1].EndParsing()
- assert len(self.stack) > 0
- self.stack = self.stack[:-1]
- if self.stop_after and name == self.stop_after:
- raise StopParsingException()
-
- if name in self.tags_to_ignore:
- self.ignore_depth -= 1
-
- def characters(self, content):
- if self.ignore_depth == 0:
- if self.stack[-1]:
- self.stack[-1].AppendContent(content)
-
- def ignorableWhitespace(self, whitespace):
- # TODO(joi) This is not supported by expat. Should use a different XML parser?
- pass
-
-
-def Parse(filename_or_stream, dir=None, flexible_root=False,
- stop_after=None, debug=False, first_id_filename=None,
- defines=None, tags_to_ignore=None):
- '''Parses a GRD file into a tree of nodes (from grit.node).
-
- If flexible_root is False, the root node must be a <grit> element. Otherwise
- it can be any element. The "own" directory of the file will only be fixed up
- if the root node is a <grit> element.
-
- 'dir' should point to the directory of the input file, or be the full path
- to the input file (the filename will be stripped).
-
- If 'stop_after' is provided, the parsing will stop once the first node
- with this name has been fully parsed (including all its contents).
-
- If 'debug' is true, lots of information about the parsing events will be
- printed out during parsing of the file.
-
- If first_id_filename is provided, then we use the provided path instead of
- resources_id to gather the first id values for resources.
-
- Args:
- filename_or_stream: './bla.xml' (must be filename if dir is None)
- dir: '.' or None (only if filename_or_stream is a filename)
- flexible_root: True | False
- stop_after: 'inputs'
- debug: False
- first_id_filename: None
- defines: dictionary of defines, like {'chromeos': '1'}
-
- Return:
- Subclass of grit.node.base.Node
-
- Throws:
- grit.exception.Parsing
- '''
- handler = GrdContentHandler(stop_after=stop_after, debug=debug,
- defines=defines, tags_to_ignore=tags_to_ignore)
- try:
- xml.sax.parse(filename_or_stream, handler)
- except StopParsingException:
- assert stop_after
- pass
- except:
- if not debug:
- print "parse exception: run GRIT with the -x flag to debug .grd problems"
- raise
-
- if not flexible_root or hasattr(handler.root, 'SetOwnDir'):
- assert isinstance(filename_or_stream, types.StringType) or dir != None
- if not dir:
- dir = util.dirname(filename_or_stream)
- if len(dir) == 0:
- dir = '.'
- # Fix up the base_dir so it is relative to the input file.
- handler.root.SetOwnDir(dir)
-
- # Assign first ids to the nodes that don't have them.
- if isinstance(handler.root, misc.GritNode) and first_id_filename != '':
- handler.root.AssignFirstIds(filename_or_stream, first_id_filename, defines)
-
- return handler.root
-
-
-if __name__ == '__main__':
- util.ChangeStdoutEncoding()
- print unicode(Parse(sys.argv[1]))
diff --git a/tools/grit/grit/grd_reader_unittest.py b/tools/grit/grit/grd_reader_unittest.py
deleted file mode 100644
index f922a97..0000000
--- a/tools/grit/grit/grd_reader_unittest.py
+++ /dev/null
@@ -1,184 +0,0 @@
-#!/usr/bin/python2.4
-# Copyright (c) 2011 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.
-
-'''Unit tests for grd_reader package'''
-
-import os
-import sys
-if __name__ == '__main__':
- sys.path.append(os.path.join(os.path.dirname(sys.argv[0]), '..'))
-
-import unittest
-import StringIO
-
-from grit import grd_reader
-from grit import constants
-from grit import util
-from grit.node import empty
-
-
-class GrdReaderUnittest(unittest.TestCase):
- def testParsingAndXmlOutput(self):
- input = u'''<?xml version="1.0" encoding="UTF-8"?>
-<grit latest_public_release="2" source_lang_id="en-US" current_release="3" base_dir=".">
- <release seq="3">
- <includes>
- <include name="ID_LOGO" file="images/logo.gif" type="gif" />
- </includes>
- <messages>
- <if expr="True">
- <message name="IDS_GREETING" desc="Printed to greet the currently logged in user">
- Hello <ph name="USERNAME">%s<ex>Joi</ex></ph>, how are you doing today?
- </message>
- </if>
- </messages>
- <structures>
- <structure name="IDD_NARROW_DIALOG" file="rc_files/dialogs.rc" type="dialog">
- <skeleton variant_of_revision="3" expr="lang == 'fr-FR'" file="bla.rc" />
- </structure>
- <structure name="VS_VERSION_INFO" file="rc_files/version.rc" type="version" />
- </structures>
- </release>
- <translations>
- <file lang="nl" path="nl_translations.xtb" />
- </translations>
- <outputs>
- <output type="rc_header" filename="resource.h" />
- <output lang="en-US" type="rc_all" filename="resource.rc" />
- </outputs>
-</grit>'''
- pseudo_file = StringIO.StringIO(input)
- tree = grd_reader.Parse(pseudo_file, '.')
- output = unicode(tree)
- # All but first two lines are the same (sans enc_check)
- self.failUnless('\n'.join(input.split('\n')[2:]) ==
- '\n'.join(output.split('\n')[2:]))
- self.failUnless(tree.GetNodeById('IDS_GREETING'))
-
-
- def testStopAfter(self):
- input = u'''<?xml version="1.0" encoding="UTF-8"?>
-<grit latest_public_release="2" source_lang_id="en-US" current_release="3" base_dir=".">
- <outputs>
- <output filename="resource.h" type="rc_header" />
- <output filename="resource.rc" lang="en-US" type="rc_all" />
- </outputs>
- <release seq="3">
- <includes>
- <include type="gif" name="ID_LOGO" file="images/logo.gif"/>
- </includes>
- </release>
-</grit>'''
- pseudo_file = util.WrapInputStream(StringIO.StringIO(input))
- tree = grd_reader.Parse(pseudo_file, '.', stop_after='outputs')
- # only an <outputs> child
- self.failUnless(len(tree.children) == 1)
- self.failUnless(tree.children[0].name == 'outputs')
-
- def testLongLinesWithComments(self):
- input = u'''<?xml version="1.0" encoding="UTF-8"?>
-<grit latest_public_release="2" source_lang_id="en-US" current_release="3" base_dir=".">
- <release seq="3">
- <messages>
- <message name="IDS_GREETING" desc="Printed to greet the currently logged in user">
- This is a very long line with no linebreaks yes yes it stretches on <!--
- -->and on <!--
- -->and on!
- </message>
- </messages>
- </release>
-</grit>'''
- pseudo_file = StringIO.StringIO(input)
- tree = grd_reader.Parse(pseudo_file, '.')
-
- greeting = tree.GetNodeById('IDS_GREETING')
- self.failUnless(greeting.GetCliques()[0].GetMessage().GetRealContent() ==
- 'This is a very long line with no linebreaks yes yes it '
- 'stretches on and on and on!')
-
- def testAssignFirstIds(self):
- input = u'''<?xml version="1.0" encoding="UTF-8"?>
-<grit latest_public_release="2" source_lang_id="en-US" current_release="3" base_dir=".">
- <release seq="3">
- <messages>
- <message name="IDS_TEST" desc="test">
- test
- </message>
- </messages>
- </release>
-</grit>'''
- pseudo_file = StringIO.StringIO(input)
- root = grd_reader.Parse(pseudo_file, '.')
- grit_root_dir = os.path.join(os.path.abspath(os.path.dirname(__file__)),
- '..')
- root.AssignFirstIds(
- os.path.join(grit_root_dir,
- "grit/testdata/chrome/app/generated_resources.grd"),
- os.path.join(grit_root_dir, "grit/testdata/tools/grit/resource_ids"),
- {})
- messages_node = root.children[0].children[0]
- self.failUnless(isinstance(messages_node, empty.MessagesNode))
- self.failUnless(messages_node.attrs["first_id"] !=
- empty.MessagesNode().DefaultAttributes()["first_id"])
-
- def testAssignFirstIdsMultipleMessages(self):
- """If there are multiple messages sections, the resource_ids file
- needs to list multiple first_id values."""
- input = u'''<?xml version="1.0" encoding="UTF-8"?>
-<grit latest_public_release="2" source_lang_id="en-US" current_release="3" base_dir=".">
- <release seq="3">
- <messages>
- <message name="IDS_TEST" desc="test">
- test
- </message>
- </messages>
- <messages>
- <message name="IDS_TEST2" desc="test">
- test2
- </message>
- </messages>
- </release>
-</grit>'''
- pseudo_file = StringIO.StringIO(input)
- root = grd_reader.Parse(pseudo_file, '.')
- grit_root_dir = os.path.join(os.path.abspath(os.path.dirname(__file__)),
- '..')
- root.AssignFirstIds(
- # This file does not actually exist, but must use absolute
- # path as resource_ids has '' for SRCDIR (see special handling
- # in grit.node.misc).
- os.path.join(grit_root_dir, "/test.grd"),
- os.path.join(grit_root_dir, "grit/testdata/resource_ids"),
- {})
- messages_node = root.children[0].children[0]
- self.assertTrue(isinstance(messages_node, empty.MessagesNode))
- self.assertEqual('100', messages_node.attrs["first_id"])
- messages_node = root.children[0].children[1]
- self.assertTrue(isinstance(messages_node, empty.MessagesNode))
- self.assertEqual('10000', messages_node.attrs["first_id"])
-
- def testUseNameForIdAndPpIfdef(self):
- input = u'''<?xml version="1.0" encoding="UTF-8"?>
-<grit latest_public_release="2" source_lang_id="en-US" current_release="3" base_dir=".">
- <release seq="3">
- <messages>
- <if expr="pp_ifdef('hello')">
- <message name="IDS_HELLO" use_name_for_id="true">
- Hello!
- </message>
- </if>
- </messages>
- </release>
-</grit>'''
- pseudo_file = StringIO.StringIO(input)
- root = grd_reader.Parse(pseudo_file, '.', defines={'hello': '1'})
-
- # Check if the ID is set to the name. In the past, there was a bug
- # that caused the ID to be a generated number.
- hello = root.GetNodeById('IDS_HELLO')
- self.failUnless(hello.GetCliques()[0].GetId() == 'IDS_HELLO')
-
-if __name__ == '__main__':
- unittest.main()
diff --git a/tools/grit/grit/grit-todo.xml b/tools/grit/grit/grit-todo.xml
deleted file mode 100644
index b8c20fd..0000000
--- a/tools/grit/grit/grit-todo.xml
+++ /dev/null
@@ -1,62 +0,0 @@
-<?xml version="1.0" encoding="windows-1252"?>
-<TODOLIST FILEFORMAT="6" PROJECTNAME="GRIT" NEXTUNIQUEID="56" FILEVERSION="69" LASTMODIFIED="2005-08-19">
- <TASK STARTDATESTRING="2005-04-08" PRIORITY="5" TIMEESPENTUNITS="H" LASTMOD="38453.49975694" TITLE="check 'name' attribute is unique" TIMEESTUNITS="H" ID="2" PERCENTDONE="100" STARTDATE="38450.00000000" DONEDATESTRING="2005-04-11" POS="22" DONEDATE="38453.00000000"/>
- <TASK STARTDATESTRING="2005-04-08" PRIORITY="5" TIMEESPENTUNITS="H" LASTMOD="38488.48189815" TITLE="import id-calculating code" TIMEESTUNITS="H" ID="3" PERCENTDONE="100" STARTDATE="38450.00000000" DONEDATESTRING="2005-05-16" POS="13" DONEDATE="38488.00000000"/>
- <TASK STARTDATESTRING="2005-05-16" PRIORITY="5" TIMEESPENTUNITS="H" LASTMOD="38488.48209491" TITLE="Import tool for existing translations" TIMEESTUNITS="H" ID="6" PERCENTDONE="100" STARTDATE="38488.00000000" DONEDATESTRING="2005-06-16" POS="12" DONEDATE="38519.00000000"/>
- <TASK STARTDATESTRING="2005-05-16" PRIORITY="5" TIMEESPENTUNITS="H" LASTMOD="38511.00805556" TITLE="Export XMBs" TIMEESTUNITS="H" ID="8" PERCENTDONE="100" STARTDATE="38488.00000000" DONEDATESTRING="2005-06-08" POS="20" DONEDATE="38511.00000000"/>
- <TASK STARTDATESTRING="2005-05-16" PRIORITY="5" TIMEESPENTUNITS="H" LASTMOD="38511.00924769" TITLE="Initial Integration" TIMEESTUNITS="H" ID="10" PERCENTDONE="100" STARTDATE="38488.00000000" DONEDATESTRING="2005-06-08" POS="10" DONEDATE="38511.00000000">
- <TASK STARTDATESTRING="2005-05-16" PRIORITY="5" TIMEESPENTUNITS="H" LASTMOD="38496.54048611" TITLE="parser for %s strings" TIMEESTUNITS="H" ID="4" PERCENTDONE="100" STARTDATE="38488.00000000" DONEDATESTRING="2005-05-24" POS="2" DONEDATE="38496.00000000"/>
- <TASK STARTDATESTRING="2005-05-16" PRIORITY="5" TIMEESPENTUNITS="H" LASTMOD="38497.00261574" TITLE="import tool for existing RC files" TIMEESTUNITS="H" ID="5" PERCENTDONE="100" STARTDATE="38488.00000000" DONEDATESTRING="2005-05-25" POS="4" DONEDATE="38497.00000000">
- <TASK STARTDATESTRING="2005-05-24" PRIORITY="5" TIMEESPENTUNITS="H" LASTMOD="38496.92990741" TITLE="handle button value= and img alt= in message HTML text" TIMEESTUNITS="H" ID="22" PERCENTDONE="100" STARTDATE="38496.00000000" DONEDATESTRING="2005-05-24" POS="1" DONEDATE="38496.00000000"/>
- <TASK STARTDATESTRING="2005-05-24" PRIORITY="5" TIMEESPENTUNITS="H" LASTMOD="38497.00258102" TITLE="&amp;nbsp; bug" TIMEESTUNITS="H" ID="23" PERCENTDONE="100" STARTDATE="38496.00000000" DONEDATESTRING="2005-05-25" POS="2" DONEDATE="38497.00000000"/>
- </TASK>
- <TASK STARTDATESTRING="2005-05-16" PRIORITY="5" TIMEESPENTUNITS="H" LASTMOD="38490.61171296" TITLE="grit build" TIMEESTUNITS="H" ID="7" PERCENTDONE="100" STARTDATE="38488.00000000" DONEDATESTRING="2005-05-18" POS="6" DONEDATE="38490.00000000">
- <TASK STARTDATESTRING="2005-05-16" PRIORITY="5" TIMEESPENTUNITS="H" LASTMOD="38490.61168981" TITLE="use IDs gathered from gatherers for .h file" TIMEESTUNITS="H" ID="20" PERCENTDONE="100" STARTDATE="38488.00000000" DONEDATESTRING="2005-05-18" POS="1" DONEDATE="38490.00000000"/>
- </TASK>
- <TASK STARTDATESTRING="2005-05-16" PRIORITY="5" TIMEESPENTUNITS="H" LASTMOD="38504.55199074" TITLE="SCons Integration" TIMEESTUNITS="H" ID="9" PERCENTDONE="100" STARTDATE="38488.00000000" DONEDATESTRING="2005-06-01" POS="1" DONEDATE="38504.00000000"/>
- <TASK STARTDATESTRING="2005-05-16" PRIORITY="5" TIMEESPENTUNITS="H" LASTMOD="38490.61181713" TITLE="handle includes" TIMEESTUNITS="H" ID="12" PERCENTDONE="100" STARTDATE="38488.00000000" DONEDATESTRING="2005-05-18" POS="5" DONEDATE="38490.00000000"/>
- <TASK STARTDATESTRING="2005-05-24" PRIORITY="5" TIMEESPENTUNITS="H" LASTMOD="38507.98567130" TITLE="output translated HTML templates" TIMEESTUNITS="H" ID="25" PERCENTDONE="100" STARTDATE="38496.00000000" DONEDATESTRING="2005-06-04" POS="3" DONEDATE="38507.00000000"/>
- <TASK STARTDATESTRING="2005-05-31" PRIORITY="5" TIMEESPENTUNITS="H" LASTMOD="38507.99394676" TITLE="bug: re-escape too much in RC dialogs etc." TIMEESTUNITS="H" ID="38" PERCENTDONE="100" STARTDATE="38503.00000000" DONEDATESTRING="2005-06-04" POS="7" DONEDATE="38507.00000000"/>
- </TASK>
- <TASK STARTDATESTRING="2005-05-16" PRIORITY="5" TIMEESPENTUNITS="H" LASTMOD="38489.46444444" TITLE="handle structure variants" TIMEESTUNITS="H" ID="11" PERCENTDONE="100" STARTDATE="38488.00000000" DONEDATESTRING="2005-06-16" POS="15" DONEDATE="38519.00000000"/>
- <TASK STARTDATESTRING="2005-05-16" PRIORITY="5" TIMEESPENTUNITS="H" LASTMOD="38489.46456019" TITLE="handle include variants" TIMEESTUNITS="H" ID="13" PERCENTDONE="100" STARTDATE="38488.00000000" DONEDATESTRING="2005-06-16" POS="17" DONEDATE="38519.00000000"/>
- <TASK STARTDATESTRING="2005-05-16" PRIORITY="5" TIMEESPENTUNITS="H" LASTMOD="38489.46537037" TITLE="handle translateable text for includes (e.g. image text)" TIMEESTUNITS="H" ID="14" PERCENTDONE="100" STARTDATE="38488.00000000" DONEDATESTRING="2005-06-16" POS="14" DONEDATE="38519.00000000"/>
- <TASK STARTDATESTRING="2005-05-16" PRIORITY="5" TIMEESPENTUNITS="H" LASTMOD="38489.46712963" TITLE="ddoc" TIMEESTUNITS="H" ID="15" STARTDATE="38488.00000000" POS="4">
- <TASK STARTDATESTRING="2005-05-16" PRIORITY="5" TIMEESPENTUNITS="H" LASTMOD="38489.46718750" TITLE="review comments miket" TIMEESTUNITS="H" ID="16" STARTDATE="38488.00000000" POS="2"/>
- <TASK STARTDATESTRING="2005-05-16" PRIORITY="5" TIMEESPENTUNITS="H" LASTMOD="38489.46722222" TITLE="review comments pdoyle" TIMEESTUNITS="H" ID="17" STARTDATE="38488.00000000" POS="1"/>
- <TASK STARTDATESTRING="2005-05-16" PRIORITY="5" TIMEESPENTUNITS="H" LASTMOD="38489.46732639" TITLE="remove 'extkey' from structure" TIMEESTUNITS="H" ID="18" STARTDATE="38488.00000000" POS="3"/>
- <TASK STARTDATESTRING="2005-05-16" PRIORITY="5" TIMEESPENTUNITS="H" LASTMOD="38489.53537037" TITLE="add 'encoding' to structure" TIMEESTUNITS="H" ID="19" STARTDATE="38488.00000000" POS="6"/>
- <TASK STARTDATESTRING="2005-05-31" PRIORITY="5" TIMEESPENTUNITS="H" LASTMOD="38503.55304398" TITLE="document limitation: emitter doesn't emit the translated HTML templates" TIMEESTUNITS="H" ID="30" STARTDATE="38503.00000000" POS="4"/>
- <TASK STARTDATESTRING="2005-05-31" PRIORITY="5" TIMEESPENTUNITS="H" LASTMOD="38504.58541667" TITLE="add 'internal_comment' to &lt;message&gt;" TIMEESTUNITS="H" ID="32" STARTDATE="38503.00000000" POS="5"/>
- <TASK STARTDATESTRING="2005-05-31" PRIORITY="5" TIMEESPENTUNITS="H" LASTMOD="38505.73391204" TITLE="&lt;outputs&gt; can not have paths (because of SCons integration - goes to build dir)" TIMEESTUNITS="H" ID="36" STARTDATE="38503.00000000" POS="9"/>
- <TASK STARTDATESTRING="2005-05-31" PRIORITY="5" TIMEESPENTUNITS="H" LASTMOD="38506.64265046" TITLE="&lt;identifers&gt; and &lt;identifier&gt; nodes" TIMEESTUNITS="H" ID="37" STARTDATE="38503.00000000" POS="10"/>
- <TASK STARTDATESTRING="2005-06-23" PRIORITY="5" TIMEESPENTUNITS="H" LASTMOD="38526.62344907" TITLE="&lt;structure&gt; can have 'exclude_from_rc' attribute (default false)" TIMEESTUNITS="H" ID="47" STARTDATE="38526.00000000" POS="8"/>
- <TASK STARTDATESTRING="2005-06-23" PRIORITY="5" TIMEESPENTUNITS="H" LASTMOD="38531.94135417" TITLE="add 'enc_check' to &lt;grit&gt;" TIMEESTUNITS="H" ID="48" STARTDATE="38526.00000000" POS="7"/>
- </TASK>
- <TASK STARTDATESTRING="2005-05-18" PRIORITY="5" TIMEESPENTUNITS="H" LASTMOD="38492.51549769" TITLE="handle nontranslateable messages (in MessageClique?)" TIMEESTUNITS="H" ID="21" PERCENTDONE="100" STARTDATE="38490.00000000" DONEDATESTRING="2005-06-16" POS="16" DONEDATE="38519.00000000"/>
- <TASK STARTDATESTRING="2005-05-24" PRIORITY="5" TIMEESPENTUNITS="H" LASTMOD="38505.70454861" TITLE="ask cprince about SCons builder in new mk system" TIMEESTUNITS="H" ID="24" PERCENTDONE="100" STARTDATE="38496.00000000" DONEDATESTRING="2005-06-02" POS="25" DONEDATE="38505.00000000"/>
- <TASK STARTDATESTRING="2005-05-24" PRIORITY="5" TIMEESPENTUNITS="H" LASTMOD="38504.57436343" TITLE="fix AOL resource in trunk (&quot;???????&quot;)" TIMEESTUNITS="H" ID="26" PERCENTDONE="100" STARTDATE="38496.00000000" DONEDATESTRING="2005-06-01" POS="19" DONEDATE="38504.00000000"/>
- <TASK STARTDATESTRING="2005-05-24" PRIORITY="5" TIMEESPENTUNITS="H" LASTMOD="38498.53893519" TITLE="rc_all vs. rc_translateable vs. rc_nontranslateable" TIMEESTUNITS="H" ID="27" PERCENTDONE="100" STARTDATE="38496.00000000" DONEDATESTRING="2005-06-16" POS="6" DONEDATE="38519.00000000"/>
- <TASK STARTDATESTRING="2005-05-31" PRIORITY="5" TIMEESPENTUNITS="H" LASTMOD="38509.45532407" TITLE="make separate .grb &quot;outputs&quot; file (and change SCons integ) (??)" TIMEESTUNITS="H" ID="28" PERCENTDONE="100" STARTDATE="38503.00000000" DONEDATESTRING="2005-06-06" POS="8" DONEDATE="38509.00000000"/>
- <TASK STARTDATESTRING="2005-05-31" PRIORITY="5" TIMEESPENTUNITS="H" LASTMOD="38511.00939815" TITLE="fix unit tests so they run from any directory" TIMEESTUNITS="H" ID="33" PERCENTDONE="100" STARTDATE="38503.00000000" DONEDATESTRING="2005-06-08" POS="18" DONEDATE="38511.00000000"/>
- <TASK STARTDATESTRING="2005-05-31" PRIORITY="5" TIMEESPENTUNITS="H" LASTMOD="38508.96640046" TITLE="Change R4 tool to CC correct team(s) on GRIT changes" TIMEESTUNITS="H" ID="39" PERCENTDONE="100" STARTDATE="38503.00000000" DONEDATESTRING="2005-06-05" POS="23" DONEDATE="38508.00000000"/>
- <TASK STARTDATESTRING="2005-06-07" PRIORITY="5" TIMEESPENTUNITS="H" LASTMOD="38511.00881944" TITLE="Document why wrapper.rc" TIMEESTUNITS="H" ID="40" PERCENTDONE="100" STARTDATE="38510.00000000" DONEDATESTRING="2005-06-08" POS="21" DONEDATE="38511.00000000"/>
- <TASK STARTDATESTRING="2005-06-08" PRIORITY="5" TIMEESPENTUNITS="H" LASTMOD="38511.00804398" TITLE="import XTBs" TIMEESTUNITS="H" ID="41" PERCENTDONE="100" STARTDATE="38511.00000000" DONEDATESTRING="2005-06-16" POS="11" DONEDATE="38519.00000000"/>
- <TASK STARTDATESTRING="2005-06-08" PRIORITY="5" TIMEESPENTUNITS="H" LASTMOD="38511.00875000" TITLE="Nightly build integration" TIMEESTUNITS="H" ID="42" STARTDATE="38511.00000000" POS="3"/>
- <TASK STARTDATESTRING="2005-06-08" PRIORITY="5" TIMEESPENTUNITS="H" LASTMOD="38511.00891204" TITLE="BUGS" TIMEESTUNITS="H" ID="43" STARTDATE="38511.00000000" POS="24">
- <TASK STARTDATESTRING="2005-06-08" PRIORITY="5" TIMEESPENTUNITS="H" LASTMOD="38513.03375000" TITLE="Should report error if RC-section structure refers to does not exist" TIMEESTUNITS="H" ID="44" PERCENTDONE="100" STARTDATE="38511.00000000" DONEDATESTRING="2005-06-10" POS="1" DONEDATE="38513.00000000"/>
- </TASK>
- <TASK STARTDATESTRING="2005-06-08" PRIORITY="5" TIMEESPENTUNITS="H" LASTMOD="38511.00981481" TITLE="NEW FEATURES" TIMEESTUNITS="H" ID="45" PERCENTDONE="100" STARTDATE="38511.00000000" DONEDATESTRING="2005-06-16" POS="7" DONEDATE="38519.00000000">
- <TASK STARTDATESTRING="2005-05-31" PRIORITY="5" TIMEESPENTUNITS="H" LASTMOD="38505.70077546" TITLE="Implement line-continuation feature (\ at end of line?)" TIMEESTUNITS="H" ID="34" PERCENTDONE="100" STARTDATE="38503.00000000" DONEDATESTRING="2005-06-16" POS="1" DONEDATE="38519.00000000"/>
- <TASK STARTDATESTRING="2005-05-31" PRIORITY="5" TIMEESPENTUNITS="H" LASTMOD="38505.70262731" TITLE="Implement conditional inclusion &amp; reflect the conditionals from R3 RC file" TIMEESTUNITS="H" ID="35" PERCENTDONE="100" STARTDATE="38503.00000000" DONEDATESTRING="2005-06-16" POS="2" DONEDATE="38519.00000000"/>
- </TASK>
- <TASK STARTDATESTRING="2005-06-08" PRIORITY="5" TIMEESPENTUNITS="H" LASTMOD="38511.01046296" TITLE="TC integration (one-way TO the TC)" TIMEESTUNITS="H" ID="46" PERCENTDONE="100" STARTDATE="38511.00000000" DONEDATESTRING="2005-06-16" POS="5" DONEDATE="38519.00000000"/>
- <TASK STARTDATESTRING="2005-06-30" PRIORITY="5" TIMEESPENTUNITS="H" LASTMOD="38533.59072917" TITLE="bazaar20 ad for GRIT help" TIMEESTUNITS="H" ID="49" STARTDATE="38533.00000000" POS="2">
- <TASK STARTDATESTRING="2005-08-19" PRIORITY="5" TIMEESPENTUNITS="H" LASTMOD="38583.72346065" TITLE="bazaar20 ideas" TIMEESTUNITS="H" ID="51" STARTDATE="38583.00000000" POS="1">
- <TASK STARTDATESTRING="2005-08-19" PRIORITY="5" TIMEESPENTUNITS="H" LASTMOD="38583.72354167" TITLE="GUI for adding/editing messages" TIMEESTUNITS="H" ID="52" STARTDATE="38583.00000000" POS="2"/>
- <TASK STARTDATESTRING="2005-08-19" PRIORITY="5" TIMEESPENTUNITS="H" LASTMOD="38583.72365741" TITLE="XLIFF import/export" TIMEESTUNITS="H" ID="54" STARTDATE="38583.00000000" POS="1"/>
- </TASK>
- </TASK>
- <TASK STARTDATESTRING="2005-06-30" PRIORITY="5" TIMEESPENTUNITS="H" LASTMOD="38583.73721065" TITLE="internal_comment for all resource nodes (not just &lt;message&gt;)" TIMEESTUNITS="H" ID="50" PERCENTDONE="100" STARTDATE="38533.00000000" DONEDATESTRING="2005-08-19" POS="9" DONEDATE="38583.73721065"/>
- <TASK STARTDATESTRING="2005-08-19" PRIORITY="5" TIMEESPENTUNITS="H" LASTMOD="38583.73743056" TITLE="Preserve XML comments - this gives us line continuation and more" TIMEESTUNITS="H" ID="55" STARTDATE="38583.72326389" POS="1"/>
-</TODOLIST>
diff --git a/tools/grit/grit/grit_runner.py b/tools/grit/grit/grit_runner.py
deleted file mode 100644
index b42bfce..0000000
--- a/tools/grit/grit/grit_runner.py
+++ /dev/null
@@ -1,212 +0,0 @@
-#!/usr/bin/python2.4
-# Copyright (c) 2011 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.
-
-'''Command processor for GRIT. This is the script you invoke to run the various
-GRIT tools.
-'''
-
-import os
-import sys
-if __name__ == '__main__':
- sys.path.append(os.path.join(os.path.dirname(sys.argv[0]), '..'))
-
-import getopt
-
-from grit import util
-
-import grit.exception
-
-import grit.tool.build
-import grit.tool.count
-import grit.tool.diff_structures
-import grit.tool.menu_from_parts
-import grit.tool.newgrd
-import grit.tool.resize
-import grit.tool.rc2grd
-import grit.tool.test
-import grit.tool.transl2tc
-import grit.tool.unit
-
-
-# Copyright notice
-_COPYRIGHT = '''\
-GRIT - the Google Resource and Internationalization Tool
-Copyright (c) Google Inc. %d
-''' % util.GetCurrentYear()
-
-# Keys for the following map
-_CLASS = 1
-_REQUIRES_INPUT = 2
-_HIDDEN = 3 # optional key - presence indicates tool is hidden
-
-
-# Maps tool names to the tool's module. Done as a list of (key, value) tuples
-# instead of a map to preserve ordering.
-_TOOLS = [
- ['build', { _CLASS : grit.tool.build.RcBuilder, _REQUIRES_INPUT : True }],
- ['newgrd', { _CLASS : grit.tool.newgrd.NewGrd, _REQUIRES_INPUT : False }],
- ['rc2grd', { _CLASS : grit.tool.rc2grd.Rc2Grd, _REQUIRES_INPUT : False }],
- ['transl2tc', { _CLASS : grit.tool.transl2tc.TranslationToTc,
- _REQUIRES_INPUT : False }],
- ['sdiff', { _CLASS : grit.tool.diff_structures.DiffStructures,
- _REQUIRES_INPUT : False }],
- ['resize', {
- _CLASS : grit.tool.resize.ResizeDialog, _REQUIRES_INPUT : True }],
- ['unit', { _CLASS : grit.tool.unit.UnitTestTool, _REQUIRES_INPUT : False }],
- ['count', { _CLASS : grit.tool.count.CountMessage, _REQUIRES_INPUT : True }],
- ['test', {
- _CLASS: grit.tool.test.TestTool, _REQUIRES_INPUT : True,
- _HIDDEN : True }],
- ['menufromparts', {
- _CLASS: grit.tool.menu_from_parts.MenuTranslationsFromParts,
- _REQUIRES_INPUT : True, _HIDDEN : True }],
-]
-
-
-def PrintUsage():
- print _COPYRIGHT
-
- tool_list = ''
- for (tool, info) in _TOOLS:
- if not _HIDDEN in info.keys():
- tool_list += ' %-12s %s\n' % (tool, info[_CLASS]().ShortDescription())
-
- # TODO(joi) Put these back into the usage when appropriate:
- #
- # -d Work disconnected. This causes GRIT not to attempt connections with
- # e.g. Perforce.
- #
- # -c Use the specified Perforce CLIENT when talking to Perforce.
- print '''Usage: grit [GLOBALOPTIONS] TOOL [args to tool]
-
-Global options:
-
- -i INPUT Specifies the INPUT file to use (a .grd file). If this is not
- specified, GRIT will look for the environment variable GRIT_INPUT.
- If it is not present either, GRIT will try to find an input file
- named 'resource.grd' in the current working directory.
-
- -v Print more verbose runtime information.
-
- -x Print extremely verbose runtime information. Implies -v
-
- -p FNAME Specifies that GRIT should profile its execution and output the
- results to the file FNAME.
-
-Tools:
-
- TOOL can be one of the following:
-%s
- For more information on how to use a particular tool, and the specific
- arguments you can send to that tool, execute 'grit help TOOL'
-''' % (tool_list)
-
-
-class Options(object):
- '''Option storage and parsing.'''
-
- def __init__(self):
- self.disconnected = False
- self.client = ''
- self.input = None
- self.verbose = False
- self.extra_verbose = False
- self.output_stream = sys.stdout
- self.profile_dest = None
-
- def ReadOptions(self, args):
- '''Reads options from the start of args and returns the remainder.'''
- (opts, args) = getopt.getopt(args, 'g:dvxc:i:p:')
- for (key, val) in opts:
- if key == '-d': self.disconnected = True
- elif key == '-c': self.client = val
- elif key == '-i': self.input = val
- elif key == '-v':
- self.verbose = True
- util.verbose = True
- elif key == '-x':
- self.verbose = True
- util.verbose = True
- self.extra_verbose = True
- util.extra_verbose = True
- elif key == '-p': self.profile_dest = val
-
- if not self.input:
- if 'GRIT_INPUT' in os.environ:
- self.input = os.environ['GRIT_INPUT']
- else:
- self.input = 'resource.grd'
-
- return args
-
- def __repr__(self):
- return '(disconnected: %d, verbose: %d, client: %s, input: %s)' % (
- self.disconnected, self.verbose, self.client, self.input)
-
-
-def _GetToolInfo(tool):
- '''Returns the info map for the tool named 'tool' or None if there is no
- such tool.'''
- matches = filter(lambda t: t[0] == tool, _TOOLS)
- if not len(matches):
- return None
- else:
- return matches[0][1]
-
-
-def Main(args):
- '''Parses arguments and does the appropriate thing.'''
- util.ChangeStdoutEncoding()
-
- if not len(args) or len(args) == 1 and args[0] == 'help':
- PrintUsage()
- return 0
- elif len(args) == 2 and args[0] == 'help':
- tool = args[1].lower()
- if not _GetToolInfo(tool):
- print "No such tool. Try running 'grit help' for a list of tools."
- return 2
-
- print ("Help for 'grit %s' (for general help, run 'grit help'):\n"
- % (tool))
- print _GetToolInfo(tool)[_CLASS].__doc__
- return 0
- else:
- options = Options()
- args = options.ReadOptions(args) # args may be shorter after this
- if not args:
- print "No tool provided. Try running 'grit help' for a list of tools."
- return 2
- tool = args[0]
- if not _GetToolInfo(tool):
- print "No such tool. Try running 'grit help' for a list of tools."
- return 2
-
- try:
- if _GetToolInfo(tool)[_REQUIRES_INPUT]:
- os.stat(options.input)
- except OSError:
- print ('Input file %s not found.\n'
- 'To specify a different input file:\n'
- ' 1. Use the GRIT_INPUT environment variable.\n'
- ' 2. Use the -i command-line option. This overrides '
- 'GRIT_INPUT.\n'
- ' 3. Specify neither GRIT_INPUT or -i and GRIT will try to load '
- "'resource.grd'\n"
- ' from the current directory.' % options.input)
- return 2
-
- toolobject = _GetToolInfo(tool)[_CLASS]()
- if options.profile_dest:
- import hotshot
- prof = hotshot.Profile(options.profile_dest)
- prof.runcall(toolobject.Run, options, args[1:])
- else:
- toolobject.Run(options, args[1:])
-
-
-if __name__ == '__main__':
- sys.exit(Main(sys.argv[1:]))
-
diff --git a/tools/grit/grit/grit_runner_unittest.py b/tools/grit/grit/grit_runner_unittest.py
deleted file mode 100644
index 2d5f0c3..0000000
--- a/tools/grit/grit/grit_runner_unittest.py
+++ /dev/null
@@ -1,40 +0,0 @@
-#!/usr/bin/python2.4
-# Copyright (c) 2011 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.
-
-'''Unit tests for grit.py'''
-
-import os
-import sys
-if __name__ == '__main__':
- sys.path.append(os.path.join(os.path.dirname(sys.argv[0]), '..'))
-
-import unittest
-import StringIO
-
-from grit import util
-import grit.grit_runner
-
-class OptionArgsUnittest(unittest.TestCase):
- def setUp(self):
- self.buf = StringIO.StringIO()
- self.old_stdout = sys.stdout
- sys.stdout = self.buf
-
- def tearDown(self):
- sys.stdout = self.old_stdout
-
- def testSimple(self):
- grit.grit_runner.Main(['-i',
- util.PathFromRoot('grit/testdata/simple-input.xml'),
- '-d', 'test', 'bla', 'voff', 'ga'])
- output = self.buf.getvalue()
- self.failUnless(output.count('disconnected'))
- self.failUnless(output.count("'test'") == 0) # tool name doesn't occur
- self.failUnless(output.count('bla'))
- self.failUnless(output.count('simple-input.xml'))
-
-
-if __name__ == '__main__':
- unittest.main()
diff --git a/tools/grit/grit/node/__init__.py b/tools/grit/grit/node/__init__.py
deleted file mode 100644
index 139d3d3..0000000
--- a/tools/grit/grit/node/__init__.py
+++ /dev/null
@@ -1,9 +0,0 @@
-#!/usr/bin/python2.4
-# Copyright (c) 2006-2008 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.
-
-'''Package 'grit.node'
-'''
-
-pass
diff --git a/tools/grit/grit/node/base.py b/tools/grit/grit/node/base.py
deleted file mode 100644
index ec4ae6e..0000000
--- a/tools/grit/grit/node/base.py
+++ /dev/null
@@ -1,549 +0,0 @@
-#!/usr/bin/python2.4
-# Copyright (c) 2011 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.
-
-'''Base types for nodes in a GRIT resource tree.
-'''
-
-import os
-import sys
-import types
-from xml.sax import saxutils
-
-from grit import exception
-from grit import util
-from grit import clique
-import grit.format.interface
-
-
-class Node(grit.format.interface.ItemFormatter):
- '''An item in the tree that has children. Also implements the
- ItemFormatter interface to allow formatting a node as a GRD document.'''
-
- # Valid content types that can be returned by _ContentType()
- _CONTENT_TYPE_NONE = 0 # No CDATA content but may have children
- _CONTENT_TYPE_CDATA = 1 # Only CDATA, no children.
- _CONTENT_TYPE_MIXED = 2 # CDATA and children, possibly intermingled
-
- # Default nodes to not whitelist skipped
- _whitelist_marked_as_skip = False
-
- def __init__(self):
- self.children = [] # A list of child elements
- self.mixed_content = [] # A list of u'' and/or child elements (this
- # duplicates 'children' but
- # is needed to preserve markup-type content).
- self.name = u'' # The name of this element
- self.attrs = {} # The set of attributes (keys to values)
- self.parent = None # Our parent unless we are the root element.
- self.uberclique = None # Allows overriding uberclique for parts of tree
-
- def __iter__(self):
- '''An in-order iteration through the tree that this node is the
- root of.'''
- return self.inorder()
-
- def inorder(self):
- '''Generator that generates first this node, then the same generator for
- any child nodes.'''
- yield self
- for child in self.children:
- for iterchild in child.inorder():
- yield iterchild
-
- def GetRoot(self):
- '''Returns the root Node in the tree this Node belongs to.'''
- curr = self
- while curr.parent:
- curr = curr.parent
- return curr
-
- # TODO(joi) Use this (currently untested) optimization?:
- #if hasattr(self, '_root'):
- # return self._root
- #curr = self
- #while curr.parent and not hasattr(curr, '_root'):
- # curr = curr.parent
- #if curr.parent:
- # self._root = curr._root
- #else:
- # self._root = curr
- #return self._root
-
- def StartParsing(self, name, parent):
- '''Called at the start of parsing.
-
- Args:
- name: u'elementname'
- parent: grit.node.base.Node or subclass or None
- '''
- assert isinstance(name, types.StringTypes)
- assert not parent or isinstance(parent, Node)
- self.name = name
- self.parent = parent
-
- def AddChild(self, child):
- '''Adds a child to the list of children of this node, if it is a valid
- child for the node.'''
- assert isinstance(child, Node)
- if (not self._IsValidChild(child) or
- self._ContentType() == self._CONTENT_TYPE_CDATA):
- if child.parent:
- explanation = 'child %s of parent %s' % (child.name, child.parent.name)
- else:
- explanation = 'node %s with no parent' % child.name
- raise exception.UnexpectedChild(explanation)
- self.children.append(child)
- self.mixed_content.append(child)
-
- def RemoveChild(self, child_id):
- '''Removes the first node that has a "name" attribute which
- matches "child_id" in the list of immediate children of
- this node.
-
- Args:
- child_id: String identifying the child to be removed
- '''
- index = 0
- # Safe not to copy since we only remove the first element found
- for child in self.children:
- name_attr = child.attrs['name']
- if name_attr == child_id:
- self.children.pop(index)
- self.mixed_content.pop(index)
- break
- index += 1
-
- def AppendContent(self, content):
- '''Appends a chunk of text as content of this node.
-
- Args:
- content: u'hello'
-
- Return:
- None
- '''
- assert isinstance(content, types.StringTypes)
- if self._ContentType() != self._CONTENT_TYPE_NONE:
- self.mixed_content.append(content)
- elif content.strip() != '':
- raise exception.UnexpectedContent()
-
- def HandleAttribute(self, attrib, value):
- '''Informs the node of an attribute that was parsed out of the GRD file
- for it.
-
- Args:
- attrib: 'name'
- value: 'fooblat'
-
- Return:
- None
- '''
- assert isinstance(attrib, types.StringTypes)
- assert isinstance(value, types.StringTypes)
- if self._IsValidAttribute(attrib, value):
- self.attrs[attrib] = value
- else:
- raise exception.UnexpectedAttribute(attrib)
-
- def EndParsing(self):
- '''Called at the end of parsing.'''
-
- # TODO(joi) Rewrite this, it's extremely ugly!
- if len(self.mixed_content):
- if isinstance(self.mixed_content[0], types.StringTypes):
- # Remove leading and trailing chunks of pure whitespace.
- while (len(self.mixed_content) and
- isinstance(self.mixed_content[0], types.StringTypes) and
- self.mixed_content[0].strip() == ''):
- self.mixed_content = self.mixed_content[1:]
- # Strip leading and trailing whitespace from mixed content chunks
- # at front and back.
- if (len(self.mixed_content) and
- isinstance(self.mixed_content[0], types.StringTypes)):
- self.mixed_content[0] = self.mixed_content[0].lstrip()
- # Remove leading and trailing ''' (used to demarcate whitespace)
- if (len(self.mixed_content) and
- isinstance(self.mixed_content[0], types.StringTypes)):
- if self.mixed_content[0].startswith("'''"):
- self.mixed_content[0] = self.mixed_content[0][3:]
- if len(self.mixed_content):
- if isinstance(self.mixed_content[-1], types.StringTypes):
- # Same stuff all over again for the tail end.
- while (len(self.mixed_content) and
- isinstance(self.mixed_content[-1], types.StringTypes) and
- self.mixed_content[-1].strip() == ''):
- self.mixed_content = self.mixed_content[:-1]
- if (len(self.mixed_content) and
- isinstance(self.mixed_content[-1], types.StringTypes)):
- self.mixed_content[-1] = self.mixed_content[-1].rstrip()
- if (len(self.mixed_content) and
- isinstance(self.mixed_content[-1], types.StringTypes)):
- if self.mixed_content[-1].endswith("'''"):
- self.mixed_content[-1] = self.mixed_content[-1][:-3]
-
- # Check that all mandatory attributes are there.
- for node_mandatt in self.MandatoryAttributes():
- mandatt_list = []
- if node_mandatt.find('|') >= 0:
- mandatt_list = node_mandatt.split('|')
- else:
- mandatt_list.append(node_mandatt)
-
- mandatt_option_found = False
- for mandatt in mandatt_list:
- assert mandatt not in self.DefaultAttributes().keys()
- if mandatt in self.attrs:
- if not mandatt_option_found:
- mandatt_option_found = True
- else:
- raise exception.MutuallyExclusiveMandatoryAttribute(mandatt)
-
- if not mandatt_option_found:
- raise exception.MissingMandatoryAttribute(mandatt)
-
- # Add default attributes if not specified in input file.
- for defattr in self.DefaultAttributes():
- if not defattr in self.attrs:
- self.attrs[defattr] = self.DefaultAttributes()[defattr]
-
- def GetCdata(self):
- '''Returns all CDATA of this element, concatenated into a single
- string. Note that this ignores any elements embedded in CDATA.'''
- return ''.join(filter(lambda c: isinstance(c, types.StringTypes),
- self.mixed_content))
-
- def __unicode__(self):
- '''Returns this node and all nodes below it as an XML document in a Unicode
- string.'''
- header = u'<?xml version="1.0" encoding="UTF-8"?>\n'
- return header + self.FormatXml()
-
- # Compliance with ItemFormatter interface.
- def Format(self, item, lang_re = None, begin_item=True):
- if not begin_item:
- return ''
- else:
- return item.FormatXml()
-
- def FormatXml(self, indent = u'', one_line = False):
- '''Returns this node and all nodes below it as an XML
- element in a Unicode string. This differs from __unicode__ in that it does
- not include the <?xml> stuff at the top of the string. If one_line is true,
- children and CDATA are layed out in a way that preserves internal
- whitespace.
- '''
- assert isinstance(indent, types.StringTypes)
-
- content_one_line = (one_line or
- self._ContentType() == self._CONTENT_TYPE_MIXED)
- inside_content = self.ContentsAsXml(indent, content_one_line)
-
- # Then the attributes for this node.
- attribs = u' '
- for (attrib, value) in self.attrs.iteritems():
- # Only print an attribute if it is other than the default value.
- if (not self.DefaultAttributes().has_key(attrib) or
- value != self.DefaultAttributes()[attrib]):
- attribs += u'%s=%s ' % (attrib, saxutils.quoteattr(value))
- attribs = attribs.rstrip() # if no attribs, we end up with '', otherwise
- # we end up with a space-prefixed string
-
- # Finally build the XML for our node and return it
- if len(inside_content) > 0:
- if one_line:
- return u'<%s%s>%s</%s>' % (self.name, attribs, inside_content, self.name)
- elif content_one_line:
- return u'%s<%s%s>\n%s %s\n%s</%s>' % (
- indent, self.name, attribs,
- indent, inside_content,
- indent, self.name)
- else:
- return u'%s<%s%s>\n%s\n%s</%s>' % (
- indent, self.name, attribs,
- inside_content,
- indent, self.name)
- else:
- return u'%s<%s%s />' % (indent, self.name, attribs)
-
- def ContentsAsXml(self, indent, one_line):
- '''Returns the contents of this node (CDATA and child elements) in XML
- format. If 'one_line' is true, the content will be laid out on one line.'''
- assert isinstance(indent, types.StringTypes)
-
- # Build the contents of the element.
- inside_parts = []
- last_item = None
- for mixed_item in self.mixed_content:
- if isinstance(mixed_item, Node):
- inside_parts.append(mixed_item.FormatXml(indent + u' ', one_line))
- if not one_line:
- inside_parts.append(u'\n')
- else:
- message = mixed_item
- # If this is the first item and it starts with whitespace, we add
- # the ''' delimiter.
- if not last_item and message.lstrip() != message:
- message = u"'''" + message
- inside_parts.append(util.EncodeCdata(message))
- last_item = mixed_item
-
- # If there are only child nodes and no cdata, there will be a spurious
- # trailing \n
- if len(inside_parts) and inside_parts[-1] == '\n':
- inside_parts = inside_parts[:-1]
-
- # If the last item is a string (not a node) and ends with whitespace,
- # we need to add the ''' delimiter.
- if (isinstance(last_item, types.StringTypes) and
- last_item.rstrip() != last_item):
- inside_parts[-1] = inside_parts[-1] + u"'''"
-
- return u''.join(inside_parts)
-
- def RunGatherers(self, recursive=0, debug=False):
- '''Runs all gatherers on this object, which may add to the data stored
- by the object. If 'recursive' is true, will call RunGatherers() recursively
- on all child nodes first. If 'debug' is True, will print out information
- as it is running each nodes' gatherers.
-
- Gatherers for <translations> child nodes will always be run after all other
- child nodes have been gathered.
- '''
- if recursive:
- process_last = []
- for child in self.children:
- if child.name == 'translations':
- process_last.append(child)
- else:
- child.RunGatherers(recursive=recursive, debug=debug)
- for child in process_last:
- child.RunGatherers(recursive=recursive, debug=debug)
-
- def ItemFormatter(self, type):
- '''Returns an instance of the item formatter for this object of the
- specified type, or None if not supported.
-
- Args:
- type: 'rc-header'
-
- Return:
- (object RcHeaderItemFormatter)
- '''
- if type == 'xml':
- return self
- else:
- return None
-
- def SatisfiesOutputCondition(self):
- '''Returns true if this node is either not a child of an <if> element
- or if it is a child of an <if> element and the conditions for it being
- output are satisfied.
-
- Used to determine whether to return item formatters for formats that
- obey conditional output of resources (e.g. the RC formatters).
- '''
- from grit.node import misc
- if not self.parent or not isinstance(self.parent, misc.IfNode):
- return True
- else:
- return self.parent.IsConditionSatisfied()
-
- def _IsValidChild(self, child):
- '''Returns true if 'child' is a valid child of this node.
- Overridden by subclasses.'''
- return False
-
- def _IsValidAttribute(self, name, value):
- '''Returns true if 'name' is the name of a valid attribute of this element
- and 'value' is a valid value for that attribute. Overriden by
- subclasses unless they have only mandatory attributes.'''
- return (name in self.MandatoryAttributes() or
- name in self.DefaultAttributes())
-
- def _ContentType(self):
- '''Returns the type of content this element can have. Overridden by
- subclasses. The content type can be one of the _CONTENT_TYPE_XXX constants
- above.'''
- return self._CONTENT_TYPE_NONE
-
- def MandatoryAttributes(self):
- '''Returns a list of attribute names that are mandatory (non-optional)
- on the current element. One can specify a list of
- "mutually exclusive mandatory" attributes by specifying them as one
- element in the list, separated by a "|" character.
- '''
- return []
-
- def DefaultAttributes(self):
- '''Returns a dictionary of attribute names that have defaults, mapped to
- the default value. Overridden by subclasses.'''
- return {}
-
- def GetCliques(self):
- '''Returns all MessageClique objects belonging to this node. Overridden
- by subclasses.
-
- Return:
- [clique1, clique2] or []
- '''
- return []
-
- def ToRealPath(self, path_from_basedir):
- '''Returns a real path (which can be absolute or relative to the current
- working directory), given a path that is relative to the base directory
- set for the GRIT input file.
-
- Args:
- path_from_basedir: '..'
-
- Return:
- 'resource'
- '''
- return util.normpath(os.path.join(self.GetRoot().GetBaseDir(),
- path_from_basedir))
-
- def FilenameToOpen(self):
- '''Returns a path, either absolute or relative to the current working
- directory, that points to the file the node refers to. This is only valid
- for nodes that have a 'file' or 'path' attribute. Note that the attribute
- is a path to the file relative to the 'base-dir' of the .grd file, whereas
- this function returns a path that can be used to open the file.'''
- file_attribute = 'file'
- if not file_attribute in self.attrs:
- file_attribute = 'path'
- return self.ToRealPath(self.attrs[file_attribute])
-
- def UberClique(self):
- '''Returns the uberclique that should be used for messages originating in
- a given node. If the node itself has its uberclique set, that is what we
- use, otherwise we search upwards until we find one. If we do not find one
- even at the root node, we set the root node's uberclique to a new
- uberclique instance.
- '''
- node = self
- while not node.uberclique and node.parent:
- node = node.parent
- if not node.uberclique:
- node.uberclique = clique.UberClique()
- return node.uberclique
-
- def IsTranslateable(self):
- '''Returns false if the node has contents that should not be translated,
- otherwise returns false (even if the node has no contents).
- '''
- if not 'translateable' in self.attrs:
- return True
- else:
- return self.attrs['translateable'] == 'true'
-
- def GetNodeById(self, id):
- '''Returns the node in the subtree parented by this node that has a 'name'
- attribute matching 'id'. Returns None if no such node is found.
- '''
- for node in self:
- if 'name' in node.attrs and node.attrs['name'] == id:
- return node
- return None
-
- def GetTextualIds(self):
- '''Returns the textual ids of this node, if it has some.
- Otherwise it just returns None.
- '''
- if 'name' in self.attrs:
- return [self.attrs['name']]
- return None
-
- def EvaluateCondition(self, expr):
- '''Returns true if and only if the Python expression 'expr' evaluates
- to true.
-
- The expression is given a few local variables:
- - 'lang' is the language currently being output
- - 'defs' is a map of C preprocessor-style define names to their values
- - 'os' is the current platform (likely 'linux2', 'win32' or 'darwin').
- - 'pp_ifdef(define)' which behaves just like the C preprocessors #ifdef,
- i.e. it is shorthand for "define in defs"
- - 'pp_if(define)' which behaves just like the C preprocessor's #if, i.e.
- it is shorthand for "define in defs and defs[define]".
- '''
- root = self.GetRoot()
- lang = ''
- defs = {}
- def pp_ifdef(define):
- return define in defs
- def pp_if(define):
- return define in defs and defs[define]
- if hasattr(root, 'output_language'):
- lang = root.output_language
- if hasattr(root, 'defines'):
- defs = root.defines
- variable_map = {
- 'lang' : lang,
- 'defs' : defs,
- 'os': sys.platform,
- 'is_linux': sys.platform.startswith('linux'),
- 'is_macosx': sys.platform == 'darwin',
- 'is_win': sys.platform in ('cygwin', 'win32'),
- 'is_posix': (sys.platform in ('darwin', 'linux2', 'linux3', 'sunos5')
- or sys.platform.find('bsd') != -1),
- 'pp_ifdef' : pp_ifdef,
- 'pp_if' : pp_if,
- }
- return eval(expr, {}, variable_map)
-
- def OnlyTheseTranslations(self, languages):
- '''Turns off loading of translations for languages not in the provided list.
-
- Attrs:
- languages: ['fr', 'zh_cn']
- '''
- for node in self:
- if (hasattr(node, 'IsTranslation') and
- node.IsTranslation() and
- node.GetLang() not in languages):
- node.DisableLoading()
-
- def PseudoIsAllowed(self):
- '''Returns true if this node is allowed to use pseudo-translations. This
- is true by default, unless this node is within a <release> node that has
- the allow_pseudo attribute set to false.
- '''
- p = self.parent
- while p:
- if 'allow_pseudo' in p.attrs:
- return (p.attrs['allow_pseudo'].lower() == 'true')
- p = p.parent
- return True
-
- def ShouldFallbackToEnglish(self):
- '''Returns true iff this node should fall back to English when
- pseudotranslations are disabled and no translation is available for a
- given message.
- '''
- p = self.parent
- while p:
- if 'fallback_to_english' in p.attrs:
- return (p.attrs['fallback_to_english'].lower() == 'true')
- p = p.parent
- return False
-
- def WhitelistMarkedAsSkip(self):
- '''Returns true if the node is marked to be skipped in the output by a
- whitelist.
- '''
- return self._whitelist_marked_as_skip
-
- def SetWhitelistMarkedAsSkip(self, mark_skipped):
- '''Sets WhitelistMarkedAsSkip.
- '''
- self._whitelist_marked_as_skip = mark_skipped
-
-
-class ContentNode(Node):
- '''Convenience baseclass for nodes that can have content.'''
- def _ContentType(self):
- return self._CONTENT_TYPE_MIXED
-
diff --git a/tools/grit/grit/node/base_unittest.py b/tools/grit/grit/node/base_unittest.py
deleted file mode 100644
index 958e715..0000000
--- a/tools/grit/grit/node/base_unittest.py
+++ /dev/null
@@ -1,169 +0,0 @@
-#!/usr/bin/python2.4
-# Copyright (c) 2006-2008 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.
-
-'''Unit tests for base.Node functionality (as used in various subclasses)'''
-
-
-import os
-import sys
-if __name__ == '__main__':
- sys.path.append(os.path.join(os.path.dirname(sys.argv[0]), '../..'))
-
-import unittest
-
-from grit.node import base
-from grit.node import message
-from grit.node import structure
-from grit.node import variant
-
-def MakePlaceholder(phname='BINGO'):
- ph = message.PhNode()
- ph.StartParsing(u'ph', None)
- ph.HandleAttribute(u'name', phname)
- ph.AppendContent(u'bongo')
- ph.EndParsing()
- return ph
-
-
-class NodeUnittest(unittest.TestCase):
- def testWhitespaceHandling(self):
- # We test using the Message node type.
- node = message.MessageNode()
- node.StartParsing(u'hello', None)
- node.HandleAttribute(u'name', u'bla')
- node.AppendContent(u" ''' two spaces ")
- node.EndParsing()
- self.failUnless(node.GetCdata() == u' two spaces')
-
- node = message.MessageNode()
- node.StartParsing(u'message', None)
- node.HandleAttribute(u'name', u'bla')
- node.AppendContent(u" two spaces ''' ")
- node.EndParsing()
- self.failUnless(node.GetCdata() == u'two spaces ')
-
- def testWhitespaceHandlingWithChildren(self):
- # We test using the Message node type.
- node = message.MessageNode()
- node.StartParsing(u'message', None)
- node.HandleAttribute(u'name', u'bla')
- node.AppendContent(u" ''' two spaces ")
- node.AddChild(MakePlaceholder())
- node.AppendContent(u' space before and after ')
- node.AddChild(MakePlaceholder('BONGO'))
- node.AppendContent(u" space before two after '''")
- node.EndParsing()
- self.failUnless(node.mixed_content[0] == u' two spaces ')
- self.failUnless(node.mixed_content[2] == u' space before and after ')
- self.failUnless(node.mixed_content[-1] == u' space before two after ')
-
- def testXmlFormatMixedContent(self):
- # Again test using the Message node type, because it is the only mixed
- # content node.
- node = message.MessageNode()
- node.StartParsing(u'message', None)
- node.HandleAttribute(u'name', u'name')
- node.AppendContent(u'Hello <young> ')
-
- ph = message.PhNode()
- ph.StartParsing(u'ph', None)
- ph.HandleAttribute(u'name', u'USERNAME')
- ph.AppendContent(u'$1')
- ex = message.ExNode()
- ex.StartParsing(u'ex', None)
- ex.AppendContent(u'Joi')
- ex.EndParsing()
- ph.AddChild(ex)
- ph.EndParsing()
-
- node.AddChild(ph)
- node.EndParsing()
-
- non_indented_xml = node.Format(node)
- self.failUnless(non_indented_xml == u'<message name="name">\n Hello '
- u'&lt;young&gt; <ph name="USERNAME">$1<ex>Joi</ex></ph>'
- u'\n</message>')
-
- indented_xml = node.FormatXml(u' ')
- self.failUnless(indented_xml == u' <message name="name">\n Hello '
- u'&lt;young&gt; <ph name="USERNAME">$1<ex>Joi</ex></ph>'
- u'\n </message>')
-
- def testXmlFormatMixedContentWithLeadingWhitespace(self):
- # Again test using the Message node type, because it is the only mixed
- # content node.
- node = message.MessageNode()
- node.StartParsing(u'message', None)
- node.HandleAttribute(u'name', u'name')
- node.AppendContent(u"''' Hello <young> ")
-
- ph = message.PhNode()
- ph.StartParsing(u'ph', None)
- ph.HandleAttribute(u'name', u'USERNAME')
- ph.AppendContent(u'$1')
- ex = message.ExNode()
- ex.StartParsing(u'ex', None)
- ex.AppendContent(u'Joi')
- ex.EndParsing()
- ph.AddChild(ex)
- ph.EndParsing()
-
- node.AddChild(ph)
- node.AppendContent(u" yessiree '''")
- node.EndParsing()
-
- non_indented_xml = node.Format(node)
- self.failUnless(non_indented_xml ==
- u"<message name=\"name\">\n ''' Hello"
- u' &lt;young&gt; <ph name="USERNAME">$1<ex>Joi</ex></ph>'
- u" yessiree '''\n</message>")
-
- indented_xml = node.FormatXml(u' ')
- self.failUnless(indented_xml ==
- u" <message name=\"name\">\n ''' Hello"
- u' &lt;young&gt; <ph name="USERNAME">$1<ex>Joi</ex></ph>'
- u" yessiree '''\n </message>")
-
- self.failUnless(node.GetNodeById('name'))
-
- def testXmlFormatContentWithEntities(self):
- '''Tests a bug where &nbsp; would not be escaped correctly.'''
- from grit import tclib
- msg_node = message.MessageNode.Construct(None, tclib.Message(
- text = 'BEGIN_BOLDHelloWHITESPACEthere!END_BOLD Bingo!',
- placeholders = [
- tclib.Placeholder('BEGIN_BOLD', '<b>', 'bla'),
- tclib.Placeholder('WHITESPACE', '&nbsp;', 'bla'),
- tclib.Placeholder('END_BOLD', '</b>', 'bla')]),
- 'BINGOBONGO')
- xml = msg_node.FormatXml()
- self.failUnless(xml.find('&nbsp;') == -1, 'should have no entities')
-
- def testIter(self):
- # First build a little tree of message and ph nodes.
- node = message.MessageNode()
- node.StartParsing(u'message', None)
- node.HandleAttribute(u'name', u'bla')
- node.AppendContent(u" ''' two spaces ")
- node.AppendContent(u' space before and after ')
- ph = message.PhNode()
- ph.StartParsing(u'ph', None)
- ph.AddChild(message.ExNode())
- ph.HandleAttribute(u'name', u'BINGO')
- ph.AppendContent(u'bongo')
- node.AddChild(ph)
- node.AddChild(message.PhNode())
- node.AppendContent(u" space before two after '''")
-
- order = [message.MessageNode, message.PhNode, message.ExNode, message.PhNode]
- for n in node:
- self.failUnless(type(n) == order[0])
- order = order[1:]
- self.failUnless(len(order) == 0)
-
-
-if __name__ == '__main__':
- unittest.main()
-
diff --git a/tools/grit/grit/node/custom/__init__.py b/tools/grit/grit/node/custom/__init__.py
deleted file mode 100644
index f8479b9..0000000
--- a/tools/grit/grit/node/custom/__init__.py
+++ /dev/null
@@ -1,9 +0,0 @@
-#!/usr/bin/python2.4
-# Copyright 2004 Google Inc.
-# All Rights Reserved.
-# Author: Joi Sigurdsson <joi@google.com>
-
-'''Package 'grit.node.custom'
-'''
-
-pass
diff --git a/tools/grit/grit/node/custom/filename.py b/tools/grit/grit/node/custom/filename.py
deleted file mode 100644
index d6de1d0..0000000
--- a/tools/grit/grit/node/custom/filename.py
+++ /dev/null
@@ -1,29 +0,0 @@
-#!/usr/bin/python2.4
-# Copyright (c) 2006-2008 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.
-
-'''A CustomType for filenames.'''
-
-import re
-
-from grit import clique
-
-
-class WindowsFilename(clique.CustomType):
- '''Validates that messages can be used as Windows filenames, and strips
- illegal characters out of translations.
- '''
-
- BANNED = re.compile('\+|:|\/|\\\\|\*|\?|\"|\<|\>|\|')
-
- def Validate(self, message):
- return not self.BANNED.search(message.GetPresentableContent())
-
- def ValidateAndModify(self, lang, translation):
- is_ok = self.Validate(translation)
- self.ModifyEachTextPart(lang, translation)
- return is_ok
-
- def ModifyTextPart(self, lang, text):
- return self.BANNED.sub(' ', text)
diff --git a/tools/grit/grit/node/custom/filename_unittest.py b/tools/grit/grit/node/custom/filename_unittest.py
deleted file mode 100644
index 69ac0bd..0000000
--- a/tools/grit/grit/node/custom/filename_unittest.py
+++ /dev/null
@@ -1,34 +0,0 @@
-#!/usr/bin/python2.4
-# Copyright (c) 2006-2008 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.
-
-'''Unit tests for grit.node.custom.filename'''
-
-
-import os
-import sys
-if __name__ == '__main__':
- sys.path.append(os.path.join(os.path.dirname(sys.argv[0]), '../../..'))
-
-import unittest
-from grit.node.custom import filename
-from grit import clique
-from grit import tclib
-
-
-class WindowsFilenameUnittest(unittest.TestCase):
-
- def testValidate(self):
- factory = clique.UberClique()
- msg = tclib.Message(text='Bingo bongo')
- c = factory.MakeClique(msg)
- c.SetCustomType(filename.WindowsFilename())
- translation = tclib.Translation(id=msg.GetId(), text='Bilingo bolongo:')
- c.AddTranslation(translation, 'fr')
- self.failUnless(c.MessageForLanguage('fr').GetRealContent() == 'Bilingo bolongo ')
-
-
-if __name__ == '__main__':
- unittest.main()
-
diff --git a/tools/grit/grit/node/empty.py b/tools/grit/grit/node/empty.py
deleted file mode 100644
index 2964cda..0000000
--- a/tools/grit/grit/node/empty.py
+++ /dev/null
@@ -1,72 +0,0 @@
-#!/usr/bin/python2.4
-# Copyright (c) 2006-2008 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.
-
-'''Container nodes that don't have any logic.
-'''
-
-
-from grit.node import base
-from grit.node import include
-from grit.node import structure
-from grit.node import message
-from grit.node import io
-from grit.node import misc
-
-
-class GroupingNode(base.Node):
- '''Base class for all the grouping elements (<structures>, <includes>,
- <messages> and <identifiers>).'''
- def DefaultAttributes(self):
- return {
- 'first_id' : '',
- 'comment' : '',
- 'fallback_to_english' : 'false',
- }
-
-
-class IncludesNode(GroupingNode):
- '''The <includes> element.'''
- def _IsValidChild(self, child):
- return isinstance(child, (include.IncludeNode, misc.IfNode))
-
-
-class MessagesNode(GroupingNode):
- '''The <messages> element.'''
- def _IsValidChild(self, child):
- return isinstance(child, (message.MessageNode, misc.IfNode))
-
- def ItemFormatter(self, t):
- '''Return the stringtable itemformatter if an RC is being formatted.'''
- if t in ['rc_all', 'rc_translateable', 'rc_nontranslateable']:
- from grit.format import rc # avoid circular dep by importing here
- return rc.StringTable()
- elif t == 'js_map_format':
- from grit.format import js_map_format
- return js_map_format.StringTable()
-
-
-class StructuresNode(GroupingNode):
- '''The <structures> element.'''
- def _IsValidChild(self, child):
- return isinstance(child, (structure.StructureNode, misc.IfNode))
-
-
-class TranslationsNode(base.Node):
- '''The <translations> element.'''
- def _IsValidChild(self, child):
- return isinstance(child, (io.FileNode, misc.IfNode))
-
-
-class OutputsNode(base.Node):
- '''The <outputs> element.'''
- def _IsValidChild(self, child):
- return isinstance(child, (io.OutputNode, misc.IfNode))
-
-
-class IdentifiersNode(GroupingNode):
- '''The <identifiers> element.'''
- def _IsValidChild(self, child):
- from grit.node import misc
- return isinstance(child, misc.IdentifierNode)
diff --git a/tools/grit/grit/node/include.py b/tools/grit/grit/node/include.py
deleted file mode 100644
index dc29315..0000000
--- a/tools/grit/grit/node/include.py
+++ /dev/null
@@ -1,140 +0,0 @@
-#!/usr/bin/python2.4
-# Copyright (c) 2011 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.
-
-'''Handling of the <include> element.
-'''
-
-import os
-
-import grit.format.html_inline
-import grit.format.rc_header
-import grit.format.rc
-
-from grit.node import base
-from grit import util
-
-class IncludeNode(base.Node):
- '''An <include> element.'''
- def __init__(self):
- base.Node.__init__(self)
-
- # Cache flattened data so that we don't flatten the same file
- # multiple times.
- self._flattened_data = None
- # Also keep track of the last filename we flattened to, so we can
- # avoid doing it more than once.
- self._last_flat_filename = None
-
- def _IsValidChild(self, child):
- return False
-
- def _GetFlattenedData(self, allow_external_script=False):
- if not self._flattened_data:
- filename = self.FilenameToOpen()
- self._flattened_data = (
- grit.format.html_inline.InlineToString(filename, self,
- allow_external_script=allow_external_script))
- return self._flattened_data
-
- def MandatoryAttributes(self):
- return ['name', 'type', 'file']
-
- def DefaultAttributes(self):
- return {'translateable' : 'true',
- 'generateid': 'true',
- 'filenameonly': 'false',
- 'flattenhtml': 'false',
- 'allowexternalscript': 'false',
- 'relativepath': 'false',
- }
-
- def ItemFormatter(self, t):
- if t == 'rc_header':
- return grit.format.rc_header.Item()
- elif (t in ['rc_all', 'rc_translateable', 'rc_nontranslateable'] and
- self.SatisfiesOutputCondition()):
- return grit.format.rc.RcInclude(self.attrs['type'].upper(),
- self.attrs['filenameonly'] == 'true',
- self.attrs['relativepath'] == 'true',
- self.attrs['flattenhtml'] == 'true')
- elif t == 'resource_map_source':
- from grit.format import resource_map
- return resource_map.SourceInclude()
- elif t == 'resource_file_map_source':
- from grit.format import resource_map
- return resource_map.SourceFileInclude()
- else:
- return super(type(self), self).ItemFormatter(t)
-
- def FileForLanguage(self, lang, output_dir):
- '''Returns the file for the specified language. This allows us to return
- different files for different language variants of the include file.
- '''
- return self.FilenameToOpen()
-
- def GetDataPackPair(self, lang, encoding):
- '''Returns a (id, string) pair that represents the resource id and raw
- bytes of the data. This is used to generate the data pack data file.
- '''
- from grit.format import rc_header
- id_map = rc_header.Item.tids_
- id = id_map[self.GetTextualIds()[0]]
- if self.attrs['flattenhtml'] == 'true':
- allow_external_script = self.attrs['allowexternalscript'] == 'true'
- data = self._GetFlattenedData(allow_external_script=allow_external_script)
- else:
- filename = self.FilenameToOpen()
- infile = open(filename, 'rb')
- data = infile.read()
- infile.close()
-
- # Include does not care about the encoding, because it only returns binary
- # data.
- return id, data
-
- def Flatten(self, output_dir):
- '''Rewrite file references to be base64 encoded data URLs. The new file
- will be written to output_dir and the name of the new file is returned.'''
- filename = self.FilenameToOpen()
- flat_filename = os.path.join(output_dir,
- self.attrs['name'] + '_' + os.path.basename(filename))
-
- if self._last_flat_filename == flat_filename:
- return
-
- outfile = open(flat_filename, 'wb')
- outfile.write(self._GetFlattenedData())
- outfile.close()
-
- self._last_flat_filename = flat_filename
- return os.path.basename(flat_filename)
-
-
- def GetHtmlResourceFilenames(self):
- """Returns a set of all filenames inlined by this file."""
- return grit.format.html_inline.GetResourceFilenames(self.FilenameToOpen())
-
- # static method
- def Construct(parent, name, type, file, translateable=True,
- filenameonly=False, relativepath=False):
- '''Creates a new node which is a child of 'parent', with attributes set
- by parameters of the same name.
- '''
- # Convert types to appropriate strings
- translateable = util.BoolToString(translateable)
- filenameonly = util.BoolToString(filenameonly)
- relativepath = util.BoolToString(relativepath)
-
- node = IncludeNode()
- node.StartParsing('include', parent)
- node.HandleAttribute('name', name)
- node.HandleAttribute('type', type)
- node.HandleAttribute('file', file)
- node.HandleAttribute('translateable', translateable)
- node.HandleAttribute('filenameonly', filenameonly)
- node.HandleAttribute('relativepath', relativepath)
- node.EndParsing()
- return node
- Construct = staticmethod(Construct)
diff --git a/tools/grit/grit/node/io.py b/tools/grit/grit/node/io.py
deleted file mode 100644
index 047d9dc..0000000
--- a/tools/grit/grit/node/io.py
+++ /dev/null
@@ -1,115 +0,0 @@
-#!/usr/bin/python2.4
-# Copyright (c) 2006-2008 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.
-
-'''The <output> and <file> elements.
-'''
-
-import os
-import re
-import grit.format.rc_header
-
-from grit.node import base
-from grit import exception
-from grit import util
-from grit import xtb_reader
-
-
-class FileNode(base.Node):
- '''A <file> element.'''
-
- def __init__(self):
- super(type(self), self).__init__()
- self.re = None
- self.should_load_ = True
-
- def IsTranslation(self):
- return True
-
- def GetLang(self):
- return self.attrs['lang']
-
- def DisableLoading(self):
- self.should_load_ = False
-
- def MandatoryAttributes(self):
- return ['path', 'lang']
-
- def RunGatherers(self, recursive=False, debug=False):
- if not self.should_load_ or not self.SatisfiesOutputCondition():
- return
-
- root = self.GetRoot()
- defs = {}
- if hasattr(root, 'defines'):
- defs = root.defines
-
- xtb_file = file(self.GetFilePath())
- try:
- lang = xtb_reader.Parse(xtb_file,
- self.UberClique().GenerateXtbParserCallback(
- self.attrs['lang'], debug=debug),
- defs=defs)
- except:
- print "Exception during parsing of %s" % self.GetFilePath()
- raise
- # We special case 'he' and 'iw' because the translation console uses 'iw'
- # and we use 'he'.
- assert (lang == self.attrs['lang'] or
- (lang == 'iw' and self.attrs['lang'] == 'he')), ('The XTB file you '
- 'reference must contain messages in the language specified\n'
- 'by the \'lang\' attribute.')
-
- def GetFilePath(self):
- return self.ToRealPath(os.path.expandvars(self.attrs['path']))
-
-
-class OutputNode(base.Node):
- '''An <output> element.'''
-
- def MandatoryAttributes(self):
- return ['filename', 'type']
-
- def DefaultAttributes(self):
- return { 'lang' : '', # empty lang indicates all languages
- 'language_section' : 'neutral' # defines a language neutral section
- }
-
- def GetType(self):
- return self.attrs['type']
-
- def GetLanguage(self):
- '''Returns the language ID, default 'en'.'''
- return self.attrs['lang']
-
- def GetFilename(self):
- return self.attrs['filename']
-
- def GetOutputFilename(self):
- if hasattr(self, 'output_filename'):
- return self.output_filename
- else:
- return self.attrs['filename']
-
- def _IsValidChild(self, child):
- return isinstance(child, EmitNode)
-
-class EmitNode(base.ContentNode):
- ''' An <emit> element.'''
-
- def DefaultAttributes(self):
- return { 'emit_type' : 'prepend'}
-
- def GetEmitType(self):
- '''Returns the emit_type for this node. Default is 'append'.'''
- return self.attrs['emit_type']
-
- def ItemFormatter(self, t):
- if t == 'rc_header':
- return grit.format.rc_header.EmitAppender()
- else:
- return super(type(self), self).ItemFormatter(t)
-
-
-
diff --git a/tools/grit/grit/node/io_unittest.py b/tools/grit/grit/node/io_unittest.py
deleted file mode 100644
index c4eadf0..0000000
--- a/tools/grit/grit/node/io_unittest.py
+++ /dev/null
@@ -1,84 +0,0 @@
-#!/usr/bin/python2.4
-# Copyright (c) 2011 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.
-
-'''Unit tests for io.FileNode'''
-
-import os
-import sys
-if __name__ == '__main__':
- sys.path.append(os.path.join(os.path.dirname(sys.argv[0]), '../..'))
-
-import os
-import StringIO
-import unittest
-
-from grit.node import misc
-from grit.node import io
-from grit.node import empty
-from grit import grd_reader
-from grit import util
-
-
-class FileNodeUnittest(unittest.TestCase):
- def testGetPath(self):
- root = misc.GritNode()
- root.StartParsing(u'grit', None)
- root.HandleAttribute(u'latest_public_release', u'0')
- root.HandleAttribute(u'current_release', u'1')
- root.HandleAttribute(u'base_dir', ur'..\resource')
- translations = empty.TranslationsNode()
- translations.StartParsing(u'translations', root)
- root.AddChild(translations)
- file_node = io.FileNode()
- file_node.StartParsing(u'file', translations)
- file_node.HandleAttribute(u'path', ur'flugel\kugel.pdf')
- translations.AddChild(file_node)
- root.EndParsing()
-
- self.failUnless(file_node.GetFilePath() ==
- util.normpath(
- os.path.join(ur'../resource', ur'flugel/kugel.pdf')))
-
- def testLoadTranslations(self):
- grd = grd_reader.Parse(StringIO.StringIO('''<?xml version="1.0" encoding="UTF-8"?>
- <grit latest_public_release="2" source_lang_id="en-US" current_release="3" base_dir=".">
- <translations>
- <file path="generated_resources_fr.xtb" lang="fr" />
- </translations>
- <release seq="3">
- <messages>
- <message name="ID_HELLO">Hello!</message>
- <message name="ID_HELLO_USER">Hello <ph name="USERNAME">%s<ex>Joi</ex></ph></message>
- </messages>
- </release>
- </grit>'''), util.PathFromRoot('grit/testdata'))
- grd.RunGatherers(recursive=True)
- self.failUnless(True)
-
- def testIffyness(self):
- grd = grd_reader.Parse(StringIO.StringIO('''<?xml version="1.0" encoding="UTF-8"?>
- <grit latest_public_release="2" source_lang_id="en-US" current_release="3" base_dir=".">
- <translations>
- <if expr="lang == 'fr'">
- <file path="generated_resources_fr.xtb" lang="fr" />
- </if>
- </translations>
- <release seq="3">
- <messages>
- <message name="ID_HELLO">Hello!</message>
- <message name="ID_HELLO_USER">Hello <ph name="USERNAME">%s<ex>Joi</ex></ph></message>
- </messages>
- </release>
- </grit>'''), util.PathFromRoot('grit/testdata'))
- grd.SetOutputContext('en', {})
- grd.RunGatherers(recursive=True)
-
- grd.SetOutputContext('fr', {})
- grd.RunGatherers(recursive=True)
-
-
-
-if __name__ == '__main__':
- unittest.main()
diff --git a/tools/grit/grit/node/mapping.py b/tools/grit/grit/node/mapping.py
deleted file mode 100644
index 6e6be93..0000000
--- a/tools/grit/grit/node/mapping.py
+++ /dev/null
@@ -1,58 +0,0 @@
-#!/usr/bin/python2.4
-# Copyright (c) 2006-2008 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.
-
-'''Maps each node type to an implementation class.
-When adding a new node type, you add to this mapping.
-'''
-
-
-from grit import exception
-
-from grit.node import empty
-from grit.node import message
-from grit.node import misc
-from grit.node import variant
-from grit.node import structure
-from grit.node import include
-from grit.node import io
-
-
-_ELEMENT_TO_CLASS = {
- 'includes' : empty.IncludesNode,
- 'messages' : empty.MessagesNode,
- 'structures' : empty.StructuresNode,
- 'translations' : empty.TranslationsNode,
- 'outputs' : empty.OutputsNode,
- 'message' : message.MessageNode,
- 'ph' : message.PhNode,
- 'ex' : message.ExNode,
- 'grit' : misc.GritNode,
- 'include' : include.IncludeNode,
- 'structure' : structure.StructureNode,
- 'skeleton' : variant.SkeletonNode,
- 'release' : misc.ReleaseNode,
- 'file' : io.FileNode,
- 'output' : io.OutputNode,
- 'emit' : io.EmitNode,
- 'identifiers' : empty.IdentifiersNode,
- 'identifier' : misc.IdentifierNode,
- 'if' : misc.IfNode,
-}
-
-
-def ElementToClass(name, typeattr):
- '''Maps an element to a class that handles the element.
-
- Args:
- name: 'element' (the name of the element)
- typeattr: 'type' (the value of the type attribute, if present, else None)
-
- Return:
- type
- '''
- if not _ELEMENT_TO_CLASS.has_key(name):
- raise exception.UnknownElement()
- return _ELEMENT_TO_CLASS[name]
-
diff --git a/tools/grit/grit/node/message.py b/tools/grit/grit/node/message.py
deleted file mode 100644
index 3c5ac64..0000000
--- a/tools/grit/grit/node/message.py
+++ /dev/null
@@ -1,282 +0,0 @@
-#!/usr/bin/python2.4
-# Copyright (c) 2011 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.
-
-'''Handling of the <message> element.
-'''
-
-import re
-import types
-
-from grit.node import base
-
-import grit.format.rc_header
-import grit.format.rc
-
-from grit import clique
-from grit import exception
-from grit import tclib
-from grit import util
-
-BINARY, UTF8, UTF16 = range(3)
-
-# Finds whitespace at the start and end of a string which can be multiline.
-_WHITESPACE = re.compile('(?P<start>\s*)(?P<body>.+?)(?P<end>\s*)\Z',
- re.DOTALL | re.MULTILINE)
-
-
-class MessageNode(base.ContentNode):
- '''A <message> element.'''
-
- # For splitting a list of things that can be separated by commas or
- # whitespace
- _SPLIT_RE = re.compile('\s*,\s*|\s+')
-
- def __init__(self):
- super(type(self), self).__init__()
- # Valid after EndParsing, this is the MessageClique that contains the
- # source message and any translations of it that have been loaded.
- self.clique = None
-
- # We don't send leading and trailing whitespace into the translation
- # console, but rather tack it onto the source message and any
- # translations when formatting them into RC files or what have you.
- self.ws_at_start = '' # Any whitespace characters at the start of the text
- self.ws_at_end = '' # --"-- at the end of the text
-
- # A list of "shortcut groups" this message is in. We check to make sure
- # that shortcut keys (e.g. &J) within each shortcut group are unique.
- self.shortcut_groups_ = []
-
- def _IsValidChild(self, child):
- return isinstance(child, (PhNode))
-
- def _IsValidAttribute(self, name, value):
- if name not in ['name', 'offset', 'translateable', 'desc', 'meaning',
- 'internal_comment', 'shortcut_groups', 'custom_type',
- 'validation_expr', 'use_name_for_id']:
- return False
- if name == 'translateable' and value not in ['true', 'false']:
- return False
- return True
-
- def MandatoryAttributes(self):
- return ['name|offset']
-
- def DefaultAttributes(self):
- return {
- 'translateable' : 'true',
- 'desc' : '',
- 'meaning' : '',
- 'internal_comment' : '',
- 'shortcut_groups' : '',
- 'custom_type' : '',
- 'validation_expr' : '',
- 'use_name_for_id' : 'false',
- }
-
- def GetTextualIds(self):
- '''
- Returns the concatenation of the parent's node first_id and
- this node's offset if it has one, otherwise just call the
- superclass' implementation
- '''
- if 'offset' in self.attrs:
- # we search for the first grouping node in the parents' list
- # to take care of the case where the first parent is an <if> node
- grouping_parent = self.parent
- import grit.node.empty
- while grouping_parent and not isinstance(grouping_parent,
- grit.node.empty.GroupingNode):
- grouping_parent = grouping_parent.parent
-
- assert 'first_id' in grouping_parent.attrs
- return [grouping_parent.attrs['first_id'] + '_' + self.attrs['offset']]
- else:
- return super(type(self), self).GetTextualIds()
-
- def IsTranslateable(self):
- return self.attrs['translateable'] == 'true'
-
- def ItemFormatter(self, t):
- # Only generate an output if the if condition is satisfied.
- if not self.SatisfiesOutputCondition():
- return super(type(self), self).ItemFormatter(t)
-
- if t == 'rc_header':
- return grit.format.rc_header.Item()
- elif t in ('rc_all', 'rc_translateable', 'rc_nontranslateable'):
- return grit.format.rc.Message()
- elif t == 'js_map_format':
- return grit.format.js_map_format.Message()
- else:
- return super(type(self), self).ItemFormatter(t)
-
- def EndParsing(self):
- super(type(self), self).EndParsing()
-
- # Make the text (including placeholder references) and list of placeholders,
- # then strip and store leading and trailing whitespace and create the
- # tclib.Message() and a clique to contain it.
-
- text = ''
- placeholders = []
- for item in self.mixed_content:
- if isinstance(item, types.StringTypes):
- text += item
- else:
- presentation = item.attrs['name'].upper()
- text += presentation
- ex = ' '
- if len(item.children):
- ex = item.children[0].GetCdata()
- original = item.GetCdata()
- placeholders.append(tclib.Placeholder(presentation, original, ex))
-
- m = _WHITESPACE.match(text)
- if m:
- self.ws_at_start = m.group('start')
- self.ws_at_end = m.group('end')
- text = m.group('body')
-
- self.shortcut_groups_ = self._SPLIT_RE.split(self.attrs['shortcut_groups'])
- self.shortcut_groups_ = [i for i in self.shortcut_groups_ if i != '']
-
- description_or_id = self.attrs['desc']
- if description_or_id == '' and 'name' in self.attrs:
- description_or_id = 'ID: %s' % self.attrs['name']
-
- assigned_id = None
- if (self.attrs['use_name_for_id'] == 'true' and
- self.SatisfiesOutputCondition()):
- assigned_id = self.attrs['name']
- message = tclib.Message(text=text, placeholders=placeholders,
- description=description_or_id,
- meaning=self.attrs['meaning'],
- assigned_id=assigned_id)
- self.clique = self.UberClique().MakeClique(message, self.IsTranslateable())
- for group in self.shortcut_groups_:
- self.clique.AddToShortcutGroup(group)
- if self.attrs['custom_type'] != '':
- self.clique.SetCustomType(util.NewClassInstance(self.attrs['custom_type'],
- clique.CustomType))
- elif self.attrs['validation_expr'] != '':
- self.clique.SetCustomType(
- clique.OneOffCustomType(self.attrs['validation_expr']))
-
- def GetCliques(self):
- if self.clique:
- return [self.clique]
- else:
- return []
-
- def Translate(self, lang):
- '''Returns a translated version of this message.
- '''
- assert self.clique
- msg = self.clique.MessageForLanguage(lang,
- self.PseudoIsAllowed(),
- self.ShouldFallbackToEnglish()
- ).GetRealContent()
- return msg.replace('[GRITLANGCODE]', lang)
-
- def NameOrOffset(self):
- if 'name' in self.attrs:
- return self.attrs['name']
- else:
- return self.attrs['offset']
-
- def GetDataPackPair(self, lang, encoding):
- '''Returns a (id, string) pair that represents the string id and the string
- in utf8. This is used to generate the data pack data file.
- '''
- from grit.format import rc_header
- id_map = rc_header.Item.tids_
- id = id_map[self.GetTextualIds()[0]]
-
- message = self.ws_at_start + self.Translate(lang) + self.ws_at_end
- if "\\n" in message:
- # Windows automatically translates \n to a new line, but GTK+ doesn't.
- # Manually do the conversion here rather than at run time.
- message = message.replace("\\n", "\n")
- # |message| is a python unicode string, so convert to a byte stream that
- # has the correct encoding requested for the datapacks. We skip the first
- # 2 bytes of text resources because it is the BOM.
- if encoding == UTF8:
- return id, message.encode('utf8')
- if encoding == UTF16:
- return id, message.encode('utf16')[2:]
- # Default is BINARY
- return id, message
-
- # static method
- def Construct(parent, message, name, desc='', meaning='', translateable=True):
- '''Constructs a new message node that is a child of 'parent', with the
- name, desc, meaning and translateable attributes set using the same-named
- parameters and the text of the message and any placeholders taken from
- 'message', which must be a tclib.Message() object.'''
- # Convert type to appropriate string
- if translateable:
- translateable = 'true'
- else:
- translateable = 'false'
-
- node = MessageNode()
- node.StartParsing('message', parent)
- node.HandleAttribute('name', name)
- node.HandleAttribute('desc', desc)
- node.HandleAttribute('meaning', meaning)
- node.HandleAttribute('translateable', translateable)
-
- items = message.GetContent()
- for ix in range(len(items)):
- if isinstance(items[ix], types.StringTypes):
- text = items[ix]
-
- # Ensure whitespace at front and back of message is correctly handled.
- if ix == 0:
- text = "'''" + text
- if ix == len(items) - 1:
- text = text + "'''"
-
- node.AppendContent(text)
- else:
- phnode = PhNode()
- phnode.StartParsing('ph', node)
- phnode.HandleAttribute('name', items[ix].GetPresentation())
- phnode.AppendContent(items[ix].GetOriginal())
-
- if len(items[ix].GetExample()) and items[ix].GetExample() != ' ':
- exnode = ExNode()
- exnode.StartParsing('ex', phnode)
- exnode.AppendContent(items[ix].GetExample())
- exnode.EndParsing()
- phnode.AddChild(exnode)
-
- phnode.EndParsing()
- node.AddChild(phnode)
-
- node.EndParsing()
- return node
- Construct = staticmethod(Construct)
-
-class PhNode(base.ContentNode):
- '''A <ph> element.'''
-
- def _IsValidChild(self, child):
- return isinstance(child, ExNode)
-
- def MandatoryAttributes(self):
- return ['name']
-
- def EndParsing(self):
- super(type(self), self).EndParsing()
- # We only allow a single example for each placeholder
- if len(self.children) > 1:
- raise exception.TooManyExamples()
-
-
-class ExNode(base.ContentNode):
- '''An <ex> element.'''
- pass
diff --git a/tools/grit/grit/node/message_unittest.py b/tools/grit/grit/node/message_unittest.py
deleted file mode 100644
index 4255dcb..0000000
--- a/tools/grit/grit/node/message_unittest.py
+++ /dev/null
@@ -1,62 +0,0 @@
-#!/usr/bin/python2.4
-# Copyright (c) 2006-2008 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.
-
-'''Unit tests for grit.node.message'''
-
-
-import os
-import sys
-if __name__ == '__main__':
- sys.path.append(os.path.join(os.path.dirname(sys.argv[0]), '../..'))
-
-import unittest
-import StringIO
-
-from grit.node import message
-from grit import grd_reader
-from grit import tclib
-
-class MessageUnittest(unittest.TestCase):
- def testMessage(self):
- buf = StringIO.StringIO('''<message name="IDS_GREETING"
- desc="Printed to greet the currently logged in user">
- Hello <ph name="USERNAME">%s<ex>Joi</ex></ph>, how are you doing today?
- </message>''')
- res = grd_reader.Parse(buf, flexible_root = True)
- cliques = res.GetCliques()
- content = cliques[0].GetMessage().GetPresentableContent()
- self.failUnless(content == 'Hello USERNAME, how are you doing today?')
-
- def testMessageWithWhitespace(self):
- buf = StringIO.StringIO('<message name="IDS_BLA" desc="">'
- '\'\'\' Hello there <ph name="USERNAME">%s</ph> \'\'\''
- '</message>')
- res = grd_reader.Parse(buf, flexible_root = True)
- content = res.GetCliques()[0].GetMessage().GetPresentableContent()
- self.failUnless(content == 'Hello there USERNAME')
- self.failUnless(res.ws_at_start == ' ')
- self.failUnless(res.ws_at_end == ' ')
-
- def testConstruct(self):
- msg = tclib.Message(text=" Hello USERNAME, how are you? BINGO\t\t",
- placeholders=[tclib.Placeholder('USERNAME', '%s', 'Joi'),
- tclib.Placeholder('BINGO', '%d', '11')])
- msg_node = message.MessageNode.Construct(None, msg, 'BINGOBONGO')
- self.failUnless(msg_node.children[0].name == 'ph')
- self.failUnless(msg_node.children[0].children[0].name == 'ex')
- self.failUnless(msg_node.children[0].children[0].GetCdata() == 'Joi')
- self.failUnless(msg_node.children[1].children[0].GetCdata() == '11')
- self.failUnless(msg_node.ws_at_start == ' ')
- self.failUnless(msg_node.ws_at_end == '\t\t')
-
- def testUnicodeConstruct(self):
- text = u'Howdie \u00fe'
- msg = tclib.Message(text=text)
- msg_node = message.MessageNode.Construct(None, msg, 'BINGOBONGO')
- msg_from_node = msg_node.GetCdata()
- self.failUnless(msg_from_node == text)
-
-if __name__ == '__main__':
- unittest.main()
diff --git a/tools/grit/grit/node/misc.py b/tools/grit/grit/node/misc.py
deleted file mode 100644
index 5bc34b4..0000000
--- a/tools/grit/grit/node/misc.py
+++ /dev/null
@@ -1,403 +0,0 @@
-#!/usr/bin/python2.4
-# Copyright (c) 2011 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.
-
-'''Miscellaneous node types.
-'''
-
-import os.path
-import re
-import sys
-
-from grit.node import base
-from grit.node import message
-
-from grit import exception
-from grit import constants
-from grit import util
-
-import grit.format.rc_header
-
-
-def _ReadFirstIdsFromFile(filename, defines):
- '''Read the starting resource id values from |filename|. We also
- expand variables of the form <(FOO) based on defines passed in on
- the command line.
-
- Returns a tuple, the absolute path of SRCDIR followed by the
- first_ids dictionary.
- '''
- first_ids_dict = eval(open(filename).read())
-
- # TODO(joi@chromium.org): It might make sense to make this a
- # parameter of the .grd file rather than of the resource_ids file.
- src_root_dir = os.path.abspath(os.path.join(os.path.dirname(filename),
- first_ids_dict['SRCDIR']))
- # Special case for testing.
- if first_ids_dict['SRCDIR'] == '':
- src_root_dir = ''
-
- def ReplaceVariable(matchobj):
- for key, value in defines.iteritems():
- if matchobj.group(1) == key:
- value = os.path.abspath(value)[len(src_root_dir) + 1:]
- return value
- return ''
-
- renames = []
- for grd_filename in first_ids_dict:
- new_grd_filename = re.sub(r'<\(([A-Za-z_]+)\)', ReplaceVariable,
- grd_filename)
- if new_grd_filename != grd_filename:
- new_grd_filename = new_grd_filename.replace('\\', '/')
- renames.append((grd_filename, new_grd_filename))
-
- for grd_filename, new_grd_filename in renames:
- first_ids_dict[new_grd_filename] = first_ids_dict[grd_filename]
- del(first_ids_dict[grd_filename])
-
- return (src_root_dir, first_ids_dict)
-
-
-class IfNode(base.Node):
- '''A node for conditional inclusion of resources.
- '''
-
- def _IsValidChild(self, child):
- from grit.node import empty
- assert self.parent, '<if> node should never be root.'
- if isinstance(self.parent, empty.IncludesNode):
- from grit.node import include
- return isinstance(child, include.IncludeNode)
- elif isinstance(self.parent, empty.MessagesNode):
- from grit.node import message
- return isinstance(child, message.MessageNode)
- elif isinstance(self.parent, empty.StructuresNode):
- from grit.node import structure
- return isinstance(child, structure.StructureNode)
- elif isinstance(self.parent, empty.OutputsNode):
- from grit.node import io
- return isinstance(child, io.OutputNode)
- elif isinstance(self.parent, empty.TranslationsNode):
- from grit.node import io
- return isinstance(child, io.FileNode)
- else:
- return False
-
- def MandatoryAttributes(self):
- return ['expr']
-
- def IsConditionSatisfied(self):
- '''Returns true if and only if the Python expression stored in attribute
- 'expr' evaluates to true.
- '''
- return self.EvaluateCondition(self.attrs['expr'])
-
-
-class ReleaseNode(base.Node):
- '''The <release> element.'''
-
- def _IsValidChild(self, child):
- from grit.node import empty
- return isinstance(child, (empty.IncludesNode, empty.MessagesNode,
- empty.StructuresNode, empty.IdentifiersNode))
-
- def _IsValidAttribute(self, name, value):
- return (
- (name == 'seq' and int(value) <= self.GetRoot().GetCurrentRelease()) or
- name == 'allow_pseudo'
- )
-
- def MandatoryAttributes(self):
- return ['seq']
-
- def DefaultAttributes(self):
- return { 'allow_pseudo' : 'true' }
-
- def GetReleaseNumber():
- '''Returns the sequence number of this release.'''
- return self.attribs['seq']
-
- def ItemFormatter(self, t):
- if t == 'data_package':
- from grit.format import data_pack
- return data_pack.DataPack()
- else:
- return super(type(self), self).ItemFormatter(t)
-
-class GritNode(base.Node):
- '''The <grit> root element.'''
-
- def __init__(self):
- base.Node.__init__(self)
- self.output_language = ''
- self.defines = {}
-
- def _IsValidChild(self, child):
- from grit.node import empty
- return isinstance(child, (ReleaseNode, empty.TranslationsNode,
- empty.OutputsNode))
-
- def _IsValidAttribute(self, name, value):
- if name not in ['base_dir', 'source_lang_id',
- 'latest_public_release', 'current_release',
- 'enc_check', 'tc_project']:
- return False
- if name in ['latest_public_release', 'current_release'] and value.strip(
- '0123456789') != '':
- return False
- return True
-
- def MandatoryAttributes(self):
- return ['latest_public_release', 'current_release']
-
- def DefaultAttributes(self):
- return {
- 'base_dir' : '.',
- 'source_lang_id' : 'en',
- 'enc_check' : constants.ENCODING_CHECK,
- 'tc_project' : 'NEED_TO_SET_tc_project_ATTRIBUTE',
- }
-
- def EndParsing(self):
- base.Node.EndParsing(self)
- if (int(self.attrs['latest_public_release'])
- > int(self.attrs['current_release'])):
- raise exception.Parsing('latest_public_release cannot have a greater '
- 'value than current_release')
-
- self.ValidateUniqueIds()
-
- # Add the encoding check if it's not present (should ensure that it's always
- # present in all .grd files generated by GRIT). If it's present, assert if
- # it's not correct.
- if 'enc_check' not in self.attrs or self.attrs['enc_check'] == '':
- self.attrs['enc_check'] = constants.ENCODING_CHECK
- else:
- assert self.attrs['enc_check'] == constants.ENCODING_CHECK, (
- 'Are you sure your .grd file is in the correct encoding (UTF-8)?')
-
- def ValidateUniqueIds(self):
- '''Validate that 'name' attribute is unique in all nodes in this tree
- except for nodes that are children of <if> nodes.
- '''
- unique_names = {}
- duplicate_names = []
- for node in self:
- if isinstance(node, message.PhNode):
- continue # PhNode objects have a 'name' attribute which is not an ID
-
- node_ids = node.GetTextualIds()
- if node_ids:
- for node_id in node_ids:
- if util.SYSTEM_IDENTIFIERS.match(node_id):
- continue # predefined IDs are sometimes used more than once
-
- # Don't complain about duplicate IDs if they occur in a node that is
- # inside an <if> node.
- if (node_id in unique_names and node_id not in duplicate_names and
- (not node.parent or not isinstance(node.parent, IfNode))):
- duplicate_names.append(node_id)
- unique_names[node_id] = 1
-
- if len(duplicate_names):
- raise exception.DuplicateKey(', '.join(duplicate_names))
-
-
- def GetCurrentRelease(self):
- '''Returns the current release number.'''
- return int(self.attrs['current_release'])
-
- def GetLatestPublicRelease(self):
- '''Returns the latest public release number.'''
- return int(self.attrs['latest_public_release'])
-
- def GetSourceLanguage(self):
- '''Returns the language code of the source language.'''
- return self.attrs['source_lang_id']
-
- def GetTcProject(self):
- '''Returns the name of this project in the TranslationConsole, or
- 'NEED_TO_SET_tc_project_ATTRIBUTE' if it is not defined.'''
- return self.attrs['tc_project']
-
- def SetOwnDir(self, dir):
- '''Informs the 'grit' element of the directory the file it is in resides.
- This allows it to calculate relative paths from the input file, which is
- what we desire (rather than from the current path).
-
- Args:
- dir: r'c:\bla'
-
- Return:
- None
- '''
- assert dir
- self.base_dir = os.path.normpath(os.path.join(dir, self.attrs['base_dir']))
-
- def GetBaseDir(self):
- '''Returns the base directory, relative to the working directory. To get
- the base directory as set in the .grd file, use GetOriginalBaseDir()
- '''
- if hasattr(self, 'base_dir'):
- return self.base_dir
- else:
- return self.GetOriginalBaseDir()
-
- def GetOriginalBaseDir(self):
- '''Returns the base directory, as set in the .grd file.
- '''
- return self.attrs['base_dir']
-
- def _CollectOutputFiles(self, nodes, output_files):
- '''Recursively filters the list of nodes that may contain other lists
- in <if> nodes, and collects all the nodes that are not enclosed by
- unsatisfied <if> conditionals and not <if> nodes themselves.
-
- Args:
- nodes: The list of nodes to filter.
- output_files: The list of satisfying nodes.
- '''
- for node in nodes:
- if node.name == 'if':
- if node.IsConditionSatisfied():
- self._CollectOutputFiles(node.children, output_files)
- else:
- output_files.append(node)
-
- def GetOutputFiles(self):
- '''Returns the list of <output> nodes that are descendants of this node's
- <outputs> child and are not enclosed by unsatisfied <if> conditionals.
- '''
- for child in self.children:
- if child.name == 'outputs':
- output_files = []
- self._CollectOutputFiles(child.children, output_files)
- return output_files
- raise exception.MissingElement()
-
- def ItemFormatter(self, t):
- if t == 'rc_header':
- from grit.format import rc_header # import here to avoid circular dep
- return rc_header.TopLevel()
- elif t in ['rc_all', 'rc_translateable', 'rc_nontranslateable']:
- from grit.format import rc # avoid circular dep
- return rc.TopLevel()
- elif t == 'resource_map_header':
- from grit.format import resource_map
- return resource_map.HeaderTopLevel()
- elif t in ('resource_map_source', 'resource_file_map_source'):
- from grit.format import resource_map
- return resource_map.SourceTopLevel()
- elif t == 'js_map_format':
- from grit.format import js_map_format
- return js_map_format.TopLevel()
- elif t in ('adm', 'plist', 'plist_strings', 'admx', 'adml', 'doc', 'json',
- 'reg'):
- from grit.format.policy_templates import template_formatter
- return template_formatter.TemplateFormatter(t)
- else:
- return super(type(self), self).ItemFormatter(t)
-
- def SetOutputContext(self, output_language, defines):
- self.output_language = output_language
- self.defines = defines
-
- def SetDefines(self, defines):
- self.defines = defines
-
- def AssignFirstIds(self, filename_or_stream, first_id_filename, defines):
- '''Assign first ids to each grouping node based on values from
- tools/grit/resource_ids.'''
- # If the input is a stream, then we're probably in a unit test and
- # should skip this step.
- if type(filename_or_stream) not in (str, unicode):
- return
-
- # TODO(joi@chromium.org): Get rid of this hack by making it
- # possible to specify the resource_ids file to use as an attribute
- # of the <grit> node in the .grd file, and doing so in all Chrome
- # .grd files.
- #
- # For now, by default, we use the the file
- # ../gritsettings/resource_ids relative to grit.py.
- if not first_id_filename:
- first_id_filename = os.path.join(
- os.path.dirname(__file__),
- '..', '..', '..',
- 'gritsettings', 'resource_ids')
-
- first_ids = None
- from grit.node import empty
- for node in self.inorder():
- if isinstance(node, empty.GroupingNode):
- if not first_ids:
- src_root_dir, first_ids = _ReadFirstIdsFromFile(first_id_filename,
- defines)
- filename = os.path.abspath(filename_or_stream)[
- len(src_root_dir) + 1:]
- filename = filename.replace('\\', '/')
-
- # TODO(joi@chromium.org): Generalize this; users other than
- # Chrome might want to use the first_id attribute; could check
- # for first_ids == None to indicate not loaded, first_ids ==
- # {} to indicate tried to load but found no resource_ids file.
- if node.attrs['first_id'] != '':
- raise Exception("Don't set the first_id attribute, update "
- "%s instead." % first_id_filename)
-
- try:
- id_list = first_ids[filename][node.name]
- except KeyError, e:
- print '-' * 78
- print 'Resource id not set for %s (%s)!' % (filename, node.name)
- print ('Please update %s to include an entry for %s. See the '
- 'comments in resource_ids for information on why you need to '
- 'update that file.' % (first_id_filename, filename))
- print '-' * 78
- raise e
-
- try:
- node.attrs['first_id'] = str(id_list.pop(0))
- except IndexError, e:
- raise Exception('Please update %s and add a first id for %s (%s).'
- % (first_id_filename, filename, node.name))
-
-
-class IdentifierNode(base.Node):
- '''A node for specifying identifiers that should appear in the resource
- header file, and be unique amongst all other resource identifiers, but don't
- have any other attributes or reference any resources.
- '''
-
- def MandatoryAttributes(self):
- return ['name']
-
- def DefaultAttributes(self):
- return { 'comment' : '', 'id' : '' }
-
- def ItemFormatter(self, t):
- if t == 'rc_header':
- return grit.format.rc_header.Item()
-
- def GetId(self):
- '''Returns the id of this identifier if it has one, None otherwise
- '''
- if 'id' in self.attrs:
- return self.attrs['id']
- return None
-
- # static method
- def Construct(parent, name, id, comment):
- '''Creates a new node which is a child of 'parent', with attributes set
- by parameters of the same name.
- '''
- node = IdentifierNode()
- node.StartParsing('identifier', parent)
- node.HandleAttribute('name', name)
- node.HandleAttribute('id', id)
- node.HandleAttribute('comment', comment)
- node.EndParsing()
- return node
- Construct = staticmethod(Construct)
diff --git a/tools/grit/grit/node/misc_unittest.py b/tools/grit/grit/node/misc_unittest.py
deleted file mode 100644
index 855ff5b..0000000
--- a/tools/grit/grit/node/misc_unittest.py
+++ /dev/null
@@ -1,208 +0,0 @@
-#!/usr/bin/python2.4
-# Copyright (c) 2011 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.
-
-'''Unit tests for misc.GritNode'''
-
-
-import os
-import sys
-if __name__ == '__main__':
- sys.path.append(os.path.join(os.path.dirname(sys.argv[0]), '../..'))
-
-import unittest
-import StringIO
-
-from grit import grd_reader
-import grit.exception
-from grit import util
-from grit.node import misc
-
-
-class GritNodeUnittest(unittest.TestCase):
- def testUniqueNameAttribute(self):
- try:
- restree = grd_reader.Parse(
- util.PathFromRoot('grit/testdata/duplicate-name-input.xml'))
- self.fail('Expected parsing exception because of duplicate names.')
- except grit.exception.Parsing:
- pass # Expected case
-
- def testReadFirstIdsFromFile(self):
- test_resource_ids = os.path.join(os.path.dirname(__file__), '..',
- 'testdata', 'resource_ids')
- src_dir, id_dict = misc._ReadFirstIdsFromFile(
- test_resource_ids,
- {
- 'FOO': '/bar',
- 'SHARED_INTERMEDIATE_DIR': '/out/Release/obj/gen',
- })
- self.assertEqual({}, id_dict.get('bar/file.grd', None))
- self.assertEqual({},
- id_dict.get('out/Release/obj/gen/devtools/devtools.grd', None))
-
-
-class IfNodeUnittest(unittest.TestCase):
- def testIffyness(self):
- grd = grd_reader.Parse(StringIO.StringIO('''
- <grit latest_public_release="2" source_lang_id="en-US" current_release="3" base_dir=".">
- <release seq="3">
- <messages>
- <if expr="'bingo' in defs">
- <message name="IDS_BINGO">
- Bingo!
- </message>
- </if>
- <if expr="'hello' in defs">
- <message name="IDS_HELLO">
- Hello!
- </message>
- </if>
- <if expr="lang == 'fr' or 'FORCE_FRENCH' in defs">
- <message name="IDS_HELLO" internal_comment="French version">
- Good morning
- </message>
- </if>
- </messages>
- </release>
- </grit>'''), dir='.')
-
- messages_node = grd.children[0].children[0]
- bingo_message = messages_node.children[0].children[0]
- hello_message = messages_node.children[1].children[0]
- french_message = messages_node.children[2].children[0]
- self.assertTrue(bingo_message.name == 'message')
- self.assertTrue(hello_message.name == 'message')
- self.assertTrue(french_message.name == 'message')
-
- grd.SetOutputContext('fr', {'hello' : '1'})
- self.failUnless(not bingo_message.SatisfiesOutputCondition())
- self.failUnless(hello_message.SatisfiesOutputCondition())
- self.failUnless(french_message.SatisfiesOutputCondition())
-
- grd.SetOutputContext('en', {'bingo' : 1})
- self.failUnless(bingo_message.SatisfiesOutputCondition())
- self.failUnless(not hello_message.SatisfiesOutputCondition())
- self.failUnless(not french_message.SatisfiesOutputCondition())
-
- grd.SetOutputContext('en', {'FORCE_FRENCH' : '1', 'bingo' : '1'})
- self.failUnless(bingo_message.SatisfiesOutputCondition())
- self.failUnless(not hello_message.SatisfiesOutputCondition())
- self.failUnless(french_message.SatisfiesOutputCondition())
-
- def testIffynessWithOutputNodes(self):
- grd = grd_reader.Parse(StringIO.StringIO('''
- <grit latest_public_release="2" source_lang_id="en-US" current_release="3" base_dir=".">
- <outputs>
- <output filename="uncond1.rc" type="rc_data" />
- <if expr="lang == 'fr' or 'hello' in defs">
- <output filename="only_fr.adm" type="adm" />
- <output filename="only_fr.plist" type="plist" />
- </if>
- <if expr="lang == 'ru'">
- <output filename="doc.html" type="document" />
- </if>
- <output filename="uncond2.adm" type="adm" />
- <output filename="iftest.h" type="rc_header">
- <emit emit_type='prepend'></emit>
- </output>
- </outputs>
- </grit>'''), dir='.')
-
- outputs_node = grd.children[0]
- uncond1_output = outputs_node.children[0]
- only_fr_adm_output = outputs_node.children[1].children[0]
- only_fr_plist_output = outputs_node.children[1].children[1]
- doc_output = outputs_node.children[2].children[0]
- uncond2_output = outputs_node.children[0]
- self.assertTrue(uncond1_output.name == 'output')
- self.assertTrue(only_fr_adm_output.name == 'output')
- self.assertTrue(only_fr_plist_output.name == 'output')
- self.assertTrue(doc_output.name == 'output')
- self.assertTrue(uncond2_output.name == 'output')
-
- grd.SetOutputContext('ru', {'hello' : '1'})
- outputs = [output.GetFilename() for output in grd.GetOutputFiles()]
- self.assertEquals(
- outputs,
- ['uncond1.rc', 'only_fr.adm', 'only_fr.plist', 'doc.html',
- 'uncond2.adm', 'iftest.h'])
-
- grd.SetOutputContext('ru', {'bingo': '2'})
- outputs = [output.GetFilename() for output in grd.GetOutputFiles()]
- self.assertEquals(
- outputs,
- ['uncond1.rc', 'doc.html', 'uncond2.adm', 'iftest.h'])
-
- grd.SetOutputContext('fr', {'hello': '1'})
- outputs = [output.GetFilename() for output in grd.GetOutputFiles()]
- self.assertEquals(
- outputs,
- ['uncond1.rc', 'only_fr.adm', 'only_fr.plist', 'uncond2.adm',
- 'iftest.h'])
-
- grd.SetOutputContext('en', {'bingo': '1'})
- outputs = [output.GetFilename() for output in grd.GetOutputFiles()]
- self.assertEquals(outputs, ['uncond1.rc', 'uncond2.adm', 'iftest.h'])
-
- grd.SetOutputContext('fr', {'bingo': '1'})
- outputs = [output.GetFilename() for output in grd.GetOutputFiles()]
- self.assertNotEquals(outputs, ['uncond1.rc', 'uncond2.adm', 'iftest.h'])
-
-class ReleaseNodeUnittest(unittest.TestCase):
- def testPseudoControl(self):
- grd = grd_reader.Parse(StringIO.StringIO('''<?xml version="1.0" encoding="UTF-8"?>
- <grit latest_public_release="1" source_lang_id="en-US" current_release="2" base_dir=".">
- <release seq="1" allow_pseudo="false">
- <messages>
- <message name="IDS_HELLO">
- Hello
- </message>
- </messages>
- <structures>
- <structure type="dialog" name="IDD_ABOUTBOX" encoding="utf-16" file="klonk.rc" />
- </structures>
- </release>
- <release seq="2">
- <messages>
- <message name="IDS_BINGO">
- Bingo
- </message>
- </messages>
- <structures>
- <structure type="menu" name="IDC_KLONKMENU" encoding="utf-16" file="klonk.rc" />
- </structures>
- </release>
- </grit>'''), util.PathFromRoot('grit/testdata'))
- grd.RunGatherers(recursive=True)
-
- hello = grd.GetNodeById('IDS_HELLO')
- aboutbox = grd.GetNodeById('IDD_ABOUTBOX')
- bingo = grd.GetNodeById('IDS_BINGO')
- menu = grd.GetNodeById('IDC_KLONKMENU')
-
- for node in [hello, aboutbox]:
- self.failUnless(not node.PseudoIsAllowed())
-
- for node in [bingo, menu]:
- self.failUnless(node.PseudoIsAllowed())
-
- for node in [hello, aboutbox]:
- try:
- formatter = node.ItemFormatter('rc_all')
- formatter.Format(node, 'xyz-pseudo')
- self.fail('Should have failed during Format since pseudo is not allowed')
- except:
- pass # expected case
-
- for node in [bingo, menu]:
- try:
- formatter = node.ItemFormatter('rc_all')
- formatter.Format(node, 'xyz-pseudo')
- except:
- self.fail('Should not have gotten exception since pseudo is allowed')
-
-
-if __name__ == '__main__':
- unittest.main()
diff --git a/tools/grit/grit/node/structure.py b/tools/grit/grit/node/structure.py
deleted file mode 100644
index 8d5e381..0000000
--- a/tools/grit/grit/node/structure.py
+++ /dev/null
@@ -1,263 +0,0 @@
-#!/usr/bin/python2.4
-# Copyright (c) 2011 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.
-
-'''The <structure> element.
-'''
-
-import os
-
-from grit.node import base
-from grit.node import variant
-
-from grit import constants
-from grit import exception
-from grit import util
-
-import grit.gather.rc
-import grit.gather.tr_html
-import grit.gather.admin_template
-import grit.gather.txt
-import grit.gather.muppet_strings
-import grit.gather.policy_json
-
-import grit.format.rc
-import grit.format.rc_header
-
-# RTL languages
-# TODO(jennyz): remove this fixed set of RTL language array
-# when generic expand_variable code is added by grit team.
-_RTL_LANGS = [
- 'ar',
- 'iw',
- 'ur',
-]
-
-# Type of the gatherer to use for each type attribute
-_GATHERERS = {
- 'accelerators' : grit.gather.rc.Accelerators,
- 'admin_template' : grit.gather.admin_template.AdmGatherer,
- 'dialog' : grit.gather.rc.Dialog,
- 'menu' : grit.gather.rc.Menu,
- 'muppet' : grit.gather.muppet_strings.MuppetStrings,
- 'rcdata' : grit.gather.rc.RCData,
- 'tr_html' : grit.gather.tr_html.TrHtml,
- 'txt' : grit.gather.txt.TxtFile,
- 'version' : grit.gather.rc.Version,
- 'policy_template_metafile' : grit.gather.policy_json.PolicyJson,
-}
-
-
-# Formatter instance to use for each type attribute
-# when formatting .rc files.
-_RC_FORMATTERS = {
- 'accelerators' : grit.format.rc.RcSection(),
- 'admin_template' : grit.format.rc.RcInclude('ADM'),
- 'dialog' : grit.format.rc.RcSection(),
- 'menu' : grit.format.rc.RcSection(),
- 'muppet' : grit.format.rc.RcInclude('XML'),
- 'rcdata' : grit.format.rc.RcSection(),
- 'tr_html' : grit.format.rc.RcInclude('HTML'),
- 'txt' : grit.format.rc.RcInclude('TXT'),
- 'version' : grit.format.rc.RcSection(),
- 'policy_template_metafile': None,
-}
-
-
-# TODO(joi) Print a warning if the 'variant_of_revision' attribute indicates
-# that a skeleton variant is older than the original file.
-
-
-class StructureNode(base.Node):
- '''A <structure> element.'''
-
- def __init__(self):
- base.Node.__init__(self)
- self.gatherer = None
- self.skeletons = {} # expressions to skeleton gatherers
-
- def _IsValidChild(self, child):
- return isinstance(child, variant.SkeletonNode)
-
- def MandatoryAttributes(self):
- return ['type', 'name', 'file']
-
- def DefaultAttributes(self):
- return { 'encoding' : 'cp1252',
- 'exclude_from_rc' : 'false',
- 'line_end' : 'unix',
- 'output_encoding' : 'utf-8',
- 'generateid': 'true',
- 'expand_variables' : 'false',
- 'output_filename' : '',
- # TODO(joi) this is a hack - should output all generated files
- # as SCons dependencies; however, for now there is a bug I can't
- # find where GRIT doesn't build the matching fileset, therefore
- # this hack so that only the files you really need are marked as
- # dependencies.
- 'sconsdep' : 'false',
- }
-
- def IsExcludedFromRc(self):
- return self.attrs['exclude_from_rc'] == 'true'
-
- def GetLineEnd(self):
- '''Returns the end-of-line character or characters for files output because
- of this node ('\r\n', '\n', or '\r' depending on the 'line_end' attribute).
- '''
- if self.attrs['line_end'] == 'unix':
- return '\n'
- elif self.attrs['line_end'] == 'windows':
- return '\r\n'
- elif self.attrs['line_end'] == 'mac':
- return '\r'
- else:
- raise exception.UnexpectedAttribute(
- "Attribute 'line_end' must be one of 'linux' (default), 'windows' or 'mac'")
-
- def GetCliques(self):
- if self.gatherer:
- return self.gatherer.GetCliques()
- else:
- return []
-
- def GetTextualIds(self):
- if self.gatherer and self.attrs['type'] not in ['tr_html', 'admin_template', 'txt']:
- return self.gatherer.GetTextualIds()
- else:
- return [self.attrs['name']]
-
- def ItemFormatter(self, t):
- if t == 'rc_header':
- return grit.format.rc_header.Item()
- elif (t in ['rc_all', 'rc_translateable', 'rc_nontranslateable'] and
- self.SatisfiesOutputCondition()):
- return _RC_FORMATTERS[self.attrs['type']]
- else:
- return super(type(self), self).ItemFormatter(t)
-
- def RunGatherers(self, recursive=False, debug=False):
- if self.gatherer:
- return # idempotent
-
- gathertype = _GATHERERS[self.attrs['type']]
-
- if debug:
- print 'Running gatherer %s for file %s' % (str(gathertype), self.FilenameToOpen())
-
- self.gatherer = gathertype.FromFile(self.FilenameToOpen(),
- self.attrs['name'],
- self.attrs['encoding'])
- self.gatherer.SetUberClique(self.UberClique())
- self.gatherer.Parse()
-
- for child in self.children:
- assert isinstance(child, variant.SkeletonNode)
- skel = gathertype.FromFile(child.FilenameToOpen(),
- self.attrs['name'],
- child.GetEncodingToUse())
- skel.SetUberClique(self.UberClique())
- skel.SetSkeleton(True)
- skel.Parse()
- self.skeletons[child.attrs['expr']] = skel
-
- def GetSkeletonGatherer(self):
- '''Returns the gatherer for the alternate skeleton that should be used,
- based on the expressions for selecting skeletons, or None if the skeleton
- from the English version of the structure should be used.
- '''
- for expr in self.skeletons:
- if self.EvaluateCondition(expr):
- return self.skeletons[expr]
- return None
-
- def GetFilePath(self):
- return self.ToRealPath(self.attrs['file'])
-
- def HasFileForLanguage(self):
- return self.attrs['type'] in ['tr_html', 'admin_template', 'txt', 'muppet']
-
- def FileForLanguage(self, lang, output_dir, create_file=True,
- return_if_not_generated=True):
- '''Returns the filename of the file associated with this structure,
- for the specified language.
-
- Args:
- lang: 'fr'
- output_dir: 'c:\temp'
- create_file: True
- '''
- assert self.HasFileForLanguage()
- if (lang == self.GetRoot().GetSourceLanguage() and
- self.attrs['expand_variables'] != 'true'):
- if return_if_not_generated:
- return self.GetFilePath()
- else:
- return None
- else:
- if self.attrs['output_filename'] != '':
- filename = self.attrs['output_filename']
- else:
- filename = os.path.basename(self.attrs['file'])
- assert len(filename)
- filename = '%s_%s' % (lang, filename)
- filename = os.path.join(output_dir, filename)
-
- if create_file:
- text = self.gatherer.Translate(
- lang,
- pseudo_if_not_available=self.PseudoIsAllowed(),
- fallback_to_english=self.ShouldFallbackToEnglish(),
- skeleton_gatherer=self.GetSkeletonGatherer())
-
- file_object = util.WrapOutputStream(file(filename, 'wb'),
- self._GetOutputEncoding())
- file_contents = util.FixLineEnd(text, self.GetLineEnd())
- if self.attrs['expand_variables'] == 'true':
- file_contents = file_contents.replace('[GRITLANGCODE]', lang)
- # TODO(jennyz): remove this hard coded logic for expanding
- # [GRITDIR] variable for RTL languages when the generic
- # expand_variable code is added by grit team.
- if lang in _RTL_LANGS :
- file_contents = file_contents.replace('[GRITDIR]', 'dir="RTL"')
- else :
- file_contents = file_contents.replace('[GRITDIR]', 'dir="LTR"')
- if self._ShouldAddBom():
- file_object.write(constants.BOM)
- file_object.write(file_contents)
- file_object.close()
-
- return filename
-
- def _GetOutputEncoding(self):
- '''Python doesn't natively support UTF encodings with a BOM signature,
- so we add support by allowing you to append '-sig' to the encoding name.
- This function returns the specified output encoding minus that part.
- '''
- enc = self.attrs['output_encoding']
- if enc.endswith('-sig'):
- return enc[0:len(enc) - len('-sig')]
- else:
- return enc
-
- def _ShouldAddBom(self):
- '''Returns true if output files should have the Unicode BOM prepended.
- '''
- return self.attrs['output_encoding'].endswith('-sig')
-
- # static method
- def Construct(parent, name, type, file, encoding='cp1252'):
- '''Creates a new node which is a child of 'parent', with attributes set
- by parameters of the same name.
- '''
- node = StructureNode()
- node.StartParsing('structure', parent)
- node.HandleAttribute('name', name)
- node.HandleAttribute('type', type)
- node.HandleAttribute('file', file)
- node.HandleAttribute('encoding', encoding)
- node.EndParsing()
- return node
- Construct = staticmethod(Construct)
-
diff --git a/tools/grit/grit/node/structure_unittest.py b/tools/grit/grit/node/structure_unittest.py
deleted file mode 100644
index 0bb9757..0000000
--- a/tools/grit/grit/node/structure_unittest.py
+++ /dev/null
@@ -1,62 +0,0 @@
-#!/usr/bin/python2.4
-# Copyright (c) 2006-2008 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.
-
-'''Unit tests for <structure> nodes.
-'''
-
-import os
-import sys
-if __name__ == '__main__':
- sys.path.append(os.path.join(os.path.dirname(sys.argv[0]), '../..'))
-
-import unittest
-import StringIO
-
-from grit.node import structure
-from grit import grd_reader
-from grit import util
-
-
-class StructureUnittest(unittest.TestCase):
- def testSkeleton(self):
- grd = grd_reader.Parse(StringIO.StringIO(
- '''<?xml version="1.0" encoding="UTF-8"?>
- <grit latest_public_release="2" source_lang_id="en-US" current_release="3" base_dir=".">
- <release seq="3">
- <structures>
- <structure type="dialog" name="IDD_ABOUTBOX" file="klonk.rc" encoding="utf-16-le">
- <skeleton expr="lang == 'fr'" variant_of_revision="1" file="klonk-alternate-skeleton.rc" />
- </structure>
- </structures>
- </release>
- </grit>'''), dir=util.PathFromRoot('grit\\test\\data'))
- grd.RunGatherers(recursive=True)
- grd.output_language = 'fr'
-
- node = grd.GetNodeById('IDD_ABOUTBOX')
- formatter = node.ItemFormatter('rc_all')
- self.failUnless(formatter)
- transl = formatter.Format(node, 'fr')
-
- self.failUnless(transl.count('040704') and transl.count('110978'))
- self.failUnless(transl.count('2005",IDC_STATIC'))
-
- def testOutputEncoding(self):
- grd = grd_reader.Parse(StringIO.StringIO(
- '''<?xml version="1.0" encoding="UTF-8"?>
- <grit latest_public_release="2" source_lang_id="en-US" current_release="3" base_dir=".">
- <release seq="3">
- <structures>
- <structure type="dialog" name="IDD_ABOUTBOX" file="klonk.rc" encoding="utf-16-le" output_encoding="utf-8-sig" />
- </structures>
- </release>
- </grit>'''), dir=util.PathFromRoot('grit\\test\\data'))
- node = grd.GetNodeById('IDD_ABOUTBOX')
- self.failUnless(node._GetOutputEncoding() == 'utf-8')
- self.failUnless(node._ShouldAddBom())
-
-if __name__ == '__main__':
- unittest.main()
-
diff --git a/tools/grit/grit/node/variant.py b/tools/grit/grit/node/variant.py
deleted file mode 100644
index 0249d17..0000000
--- a/tools/grit/grit/node/variant.py
+++ /dev/null
@@ -1,42 +0,0 @@
-#!/usr/bin/python2.4
-# Copyright (c) 2006-2008 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.
-
-'''The <skeleton> element.
-'''
-
-
-from grit.node import base
-
-
-class SkeletonNode(base.Node):
- '''A <skeleton> element.'''
-
- # TODO(joi) Support inline skeleton variants as CDATA instead of requiring
- # a 'file' attribute.
-
- def MandatoryAttributes(self):
- return ['expr', 'variant_of_revision', 'file']
-
- def DefaultAttributes(self):
- '''If not specified, 'encoding' will actually default to the parent node's
- encoding.
- '''
- return {'encoding' : ''}
-
- def _ContentType(self):
- if self.attrs.has_key('file'):
- return self._CONTENT_TYPE_NONE
- else:
- return self._CONTENT_TYPE_CDATA
-
- def GetEncodingToUse(self):
- if self.attrs['encoding'] == '':
- return self.parent.attrs['encoding']
- else:
- return self.attrs['encoding']
-
- def GetFilePath(self):
- return self.ToRealPath(self.attrs['file'])
-
diff --git a/tools/grit/grit/pseudo.py b/tools/grit/grit/pseudo.py
deleted file mode 100644
index 4c3db07..0000000
--- a/tools/grit/grit/pseudo.py
+++ /dev/null
@@ -1,130 +0,0 @@
-#!/usr/bin/python2.4
-# Copyright (c) 2006-2008 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.
-
-'''Pseudotranslation support. Our pseudotranslations are based on the
-P-language, which is a simple vowel-extending language. Examples of P:
- - "hello" becomes "hepellopo"
- - "howdie" becomes "hopowdiepie"
- - "because" becomes "bepecaupause" (but in our implementation we don't
- handle the silent e at the end so it actually would return "bepecaupausepe"
-
-The P-language has the excellent quality of increasing the length of text
-by around 30-50% which is great for pseudotranslations, to stress test any
-GUI layouts etc.
-
-To make the pseudotranslations more obviously "not a translation" and to make
-them exercise any code that deals with encodings, we also transform all English
-vowels into equivalent vowels with diacriticals on them (rings, acutes,
-diaresis, and circumflex), and we write the "p" in the P-language as a Hebrew
-character Qof. It looks sort of like a latin character "p" but it is outside
-the latin-1 character set which will stress character encoding bugs.
-'''
-
-import re
-import types
-
-from grit import tclib
-
-
-# An RFC language code for the P pseudolanguage.
-PSEUDO_LANG = 'x-P-pseudo'
-
-# Hebrew character Qof. It looks kind of like a 'p' but is outside
-# the latin-1 character set which is good for our purposes.
-# TODO(joi) For now using P instead of Qof, because of some bugs it used. Find
-# a better solution, i.e. one that introduces a non-latin1 character into the
-# pseudotranslation.
-#_QOF = u'\u05e7'
-_QOF = u'P'
-
-# How we map each vowel.
-_VOWELS = {
- u'a' : u'\u00e5', # a with ring
- u'e' : u'\u00e9', # e acute
- u'i' : u'\u00ef', # i diaresis
- u'o' : u'\u00f4', # o circumflex
- u'u' : u'\u00fc', # u diaresis
- u'y' : u'\u00fd', # y acute
- u'A' : u'\u00c5', # A with ring
- u'E' : u'\u00c9', # E acute
- u'I' : u'\u00cf', # I diaresis
- u'O' : u'\u00d4', # O circumflex
- u'U' : u'\u00dc', # U diaresis
- u'Y' : u'\u00dd', # Y acute
-}
-
-# Matches vowels and P
-_PSUB_RE = re.compile("(%s)" % '|'.join(_VOWELS.keys() + ['P']))
-
-
-# Pseudotranslations previously created. This is important for performance
-# reasons, especially since we routinely pseudotranslate the whole project
-# several or many different times for each build.
-_existing_translations = {}
-
-
-def MapVowels(str, also_p = False):
- '''Returns a copy of 'str' where characters that exist as keys in _VOWELS
- have been replaced with the corresponding value. If also_p is true, this
- function will also change capital P characters into a Hebrew character Qof.
- '''
- def Repl(match):
- if match.group() == 'p':
- if also_p:
- return _QOF
- else:
- return 'p'
- else:
- return _VOWELS[match.group()]
- return _PSUB_RE.sub(Repl, str)
-
-
-def PseudoString(str):
- '''Returns a pseudotranslation of the provided string, in our enhanced
- P-language.'''
- if str in _existing_translations:
- return _existing_translations[str]
-
- outstr = u''
- ix = 0
- while ix < len(str):
- if str[ix] not in _VOWELS.keys():
- outstr += str[ix]
- ix += 1
- else:
- # We want to treat consecutive vowels as one composite vowel. This is not
- # always accurate e.g. in composite words but good enough.
- consecutive_vowels = u''
- while ix < len(str) and str[ix] in _VOWELS.keys():
- consecutive_vowels += str[ix]
- ix += 1
- changed_vowels = MapVowels(consecutive_vowels)
- outstr += changed_vowels
- outstr += _QOF
- outstr += changed_vowels
-
- _existing_translations[str] = outstr
- return outstr
-
-
-def PseudoMessage(message):
- '''Returns a pseudotranslation of the provided message.
-
- Args:
- message: tclib.Message()
-
- Return:
- tclib.Translation()
- '''
- transl = tclib.Translation()
-
- for part in message.GetContent():
- if isinstance(part, tclib.Placeholder):
- transl.AppendPlaceholder(part)
- else:
- transl.AppendText(PseudoString(part))
-
- return transl
-
diff --git a/tools/grit/grit/pseudo_rtl.py b/tools/grit/grit/pseudo_rtl.py
deleted file mode 100644
index 4dcc4b2..0000000
--- a/tools/grit/grit/pseudo_rtl.py
+++ /dev/null
@@ -1,102 +0,0 @@
-#!/usr/bin/python
-# Copyright (c) 2011 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.
-
-'''Pseudo RTL, (aka Fake Bidi) support. It simply wraps each word with
-Unicode RTL overrides.
-More info at https://sites.google.com/a/chromium.org/dev/Home/fake-bidi
-'''
-
-import re
-import types
-
-from grit import tclib
-
-ACCENTED_STRINGS = {
- 'a': u"\u00e5", 'e': u"\u00e9", 'i': u"\u00ee", 'o': u"\u00f6",
- 'u': u"\u00fb", 'A': u"\u00c5", 'E': u"\u00c9", 'I': u"\u00ce",
- 'O': u"\u00d6", 'U': u"\u00db", 'c': u"\u00e7", 'd': u"\u00f0",
- 'n': u"\u00f1", 'p': u"\u00fe", 'y': u"\u00fd", 'C': u"\u00c7",
- 'D': u"\u00d0", 'N': u"\u00d1", 'P': u"\u00de", 'Y': u"\u00dd",
- 'f': u"\u0192", 's': u"\u0161", 'S': u"\u0160", 'z': u"\u017e",
- 'Z': u"\u017d", 'g': u"\u011d", 'G': u"\u011c", 'h': u"\u0125",
- 'H': u"\u0124", 'j': u"\u0135", 'J': u"\u0134", 'k': u"\u0137",
- 'K': u"\u0136", 'l': u"\u013c", 'L': u"\u013b", 't': u"\u0163",
- 'T': u"\u0162", 'w': u"\u0175", 'W': u"\u0174",
- '$': u"\u20ac", '?': u"\u00bf", 'R': u"\u00ae", r'!': u"\u00a1",
-}
-
-# a character set containing the keys in ACCENTED_STRINGS
-# We should not accent characters in an escape sequence such as "\n".
-# To be safe, we assume every character following a backslash is an escaped
-# character. We also need to consider the case like "\\n", which means
-# a blackslash and a character "n", we will accent the character "n".
-TO_ACCENT = re.compile(r'[%s]|\\[a-z\\]' % ''.join(ACCENTED_STRINGS.keys()))
-
-# Lex text so that we don't interfere with html tokens and entities.
-# This lexing scheme will handle all well formed tags and entities, html or
-# xhtml. It will not handle comments, CDATA sections, or the unescaping tags:
-# script, style, xmp or listing. If any of those appear in messages,
-# something is wrong.
-TOKENS = [ re.compile(
- '^%s' % pattern, # match at the beginning of input
- re.I | re.S # html tokens are case-insensitive
- )
- for pattern in
- (
- # a run of non html special characters
- r'[^<&]+',
- # a tag
- (r'</?[a-z]\w*' # beginning of tag
- r'(?:\s+\w+(?:\s*=\s*' # attribute start
- r'(?:[^\s"\'>]+|"[^\"]*"|\'[^\']*\'))?' # attribute value
- r')*\s*/?>'),
- # an entity
- r'&(?:[a-z]\w+|#\d+|#x[\da-f]+);',
- # an html special character not part of a special sequence
- r'.'
- ) ]
-
-ALPHABETIC_RUN = re.compile(r'([^\W0-9_]+)')
-
-RLO = u'\u202e'
-PDF = u'\u202c'
-
-def PseudoRTLString(text):
- '''Returns a fake bidirectional version of the source string. This code is
- based on accentString above, in turn copied from Frank Tang.
- '''
- parts = []
- while text:
- m = None
- for token in TOKENS:
- m = token.search(text)
- if m:
- part = m.group(0)
- text = text[len(part):]
- if part[0] not in ('<', '&'):
- # not a tag or entity, so accent
- part = ALPHABETIC_RUN.sub(lambda run: RLO + run.group() + PDF, part)
- parts.append(part)
- break
- return ''.join(parts)
-
-
-def PseudoRTLMessage(message):
- '''Returns a pseudo-RTL (aka Fake-Bidi) translation of the provided message.
-
- Args:
- message: tclib.Message()
-
- Return:
- tclib.Translation()
- '''
- transl = tclib.Translation()
- for part in message.GetContent():
- if isinstance(part, tclib.Placeholder):
- transl.AppendPlaceholder(part)
- else:
- transl.AppendText(PseudoRTLString(part))
-
- return transl
diff --git a/tools/grit/grit/pseudo_unittest.py b/tools/grit/grit/pseudo_unittest.py
deleted file mode 100644
index 6191b20..0000000
--- a/tools/grit/grit/pseudo_unittest.py
+++ /dev/null
@@ -1,53 +0,0 @@
-#!/usr/bin/python2.4
-# Copyright (c) 2006-2008 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.
-
-'''Unit tests for grit.pseudo'''
-
-import os
-import sys
-if __name__ == '__main__':
- sys.path.append(os.path.join(os.path.dirname(sys.argv[0]), '..'))
-
-import unittest
-
-from grit import pseudo
-from grit import tclib
-
-
-class PseudoUnittest(unittest.TestCase):
- def testVowelMapping(self):
- self.failUnless(pseudo.MapVowels('abebibobuby') ==
- u'\u00e5b\u00e9b\u00efb\u00f4b\u00fcb\u00fd')
- self.failUnless(pseudo.MapVowels('ABEBIBOBUBY') ==
- u'\u00c5B\u00c9B\u00cfB\u00d4B\u00dcB\u00dd')
-
- def testPseudoString(self):
- out = pseudo.PseudoString('hello')
- self.failUnless(out == pseudo.MapVowels(u'hePelloPo', True))
-
- def testConsecutiveVowels(self):
- out = pseudo.PseudoString("beautiful weather, ain't it?")
- self.failUnless(out == pseudo.MapVowels(
- u"beauPeautiPifuPul weaPeathePer, aiPain't iPit?", 1))
-
- def testCapitals(self):
- out = pseudo.PseudoString("HOWDIE DOODIE, DR. JONES")
- self.failUnless(out == pseudo.MapVowels(
- u"HOPOWDIEPIE DOOPOODIEPIE, DR. JOPONEPES", 1))
-
- def testPseudoMessage(self):
- msg = tclib.Message(text='Hello USERNAME, how are you?',
- placeholders=[
- tclib.Placeholder('USERNAME', '%s', 'Joi')])
- trans = pseudo.PseudoMessage(msg)
- # TODO(joi) It would be nicer if 'you' -> 'youPou' instead of
- # 'you' -> 'youPyou' and if we handled the silent e in 'are'
- self.failUnless(trans.GetPresentableContent() ==
- pseudo.MapVowels(
- u'HePelloPo USERNAME, hoPow aParePe youPyou?', 1))
-
-
-if __name__ == '__main__':
- unittest.main()
diff --git a/tools/grit/grit/shortcuts.py b/tools/grit/grit/shortcuts.py
deleted file mode 100644
index c1f7fb1..0000000
--- a/tools/grit/grit/shortcuts.py
+++ /dev/null
@@ -1,95 +0,0 @@
-#!/usr/bin/python2.4
-# Copyright (c) 2006-2008 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.
-
-'''Stuff to prevent conflicting shortcuts.
-'''
-
-import re
-
-from grit import util
-
-
-class ShortcutGroup(object):
- '''Manages a list of cliques that belong together in a single shortcut
- group. Knows how to detect conflicting shortcut keys.
- '''
-
- # Matches shortcut keys, e.g. &J
- SHORTCUT_RE = re.compile('([^&]|^)(&[A-Za-z])')
-
- def __init__(self, name):
- self.name = name
- # Map of language codes to shortcut keys used (which is a map of
- # shortcut keys to counts).
- self.keys_by_lang = {}
- # List of cliques in this group
- self.cliques = []
-
- def AddClique(self, c):
- for existing_clique in self.cliques:
- if existing_clique.GetId() == c.GetId():
- # This happens e.g. when we have e.g.
- # <if expr1><structure 1></if> <if expr2><structure 2></if>
- # where only one will really be included in the output.
- return
-
- self.cliques.append(c)
- for (lang, msg) in c.clique.items():
- if lang not in self.keys_by_lang:
- self.keys_by_lang[lang] = {}
- keymap = self.keys_by_lang[lang]
-
- content = msg.GetRealContent()
- keys = [groups[1] for groups in self.SHORTCUT_RE.findall(content)]
- for key in keys:
- key = key.upper()
- if key in keymap:
- keymap[key] += 1
- else:
- keymap[key] = 1
-
- def GenerateWarnings(self, tc_project):
- # For any language that has more than one occurrence of any shortcut,
- # make a list of the conflicting shortcuts.
- problem_langs = {}
- for (lang, keys) in self.keys_by_lang.items():
- for (key, count) in keys.items():
- if count > 1:
- if lang not in problem_langs:
- problem_langs[lang] = []
- problem_langs[lang].append(key)
-
- warnings = []
- if len(problem_langs):
- warnings.append("WARNING - duplicate keys exist in shortcut group %s" %
- self.name)
- for (lang,keys) in problem_langs.items():
- warnings.append(" %6s duplicates: %s" % (lang, ', '.join(keys)))
- return warnings
-
-
-def GenerateDuplicateShortcutsWarnings(uberclique, tc_project):
- '''Given an UberClique and a project name, will print out helpful warnings
- if there are conflicting shortcuts within shortcut groups in the provided
- UberClique.
-
- Args:
- uberclique: clique.UberClique()
- tc_project: 'MyProjectNameInTheTranslationConsole'
-
- Returns:
- ['warning line 1', 'warning line 2', ...]
- '''
- warnings = []
- groups = {}
- for c in uberclique.AllCliques():
- for group in c.shortcut_groups:
- if group not in groups:
- groups[group] = ShortcutGroup(group)
- groups[group].AddClique(c)
- for group in groups.values():
- warnings += group.GenerateWarnings(tc_project)
- return warnings
-
diff --git a/tools/grit/grit/shortcuts_unittests.py b/tools/grit/grit/shortcuts_unittests.py
deleted file mode 100644
index 9517346..0000000
--- a/tools/grit/grit/shortcuts_unittests.py
+++ /dev/null
@@ -1,79 +0,0 @@
-#!/usr/bin/python2.4
-# Copyright (c) 2006-2008 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.
-
-'''Unit tests for grit.shortcuts
-'''
-
-import os
-import sys
-if __name__ == '__main__':
- sys.path.append(os.path.join(os.path.dirname(sys.argv[0]), '..'))
-
-import unittest
-
-from grit import shortcuts
-from grit import clique
-from grit import tclib
-from grit.gather import rc
-
-class ShortcutsUnittest(unittest.TestCase):
-
- def setUp(self):
- self.uq = clique.UberClique()
-
- def testFunctionality(self):
- c = self.uq.MakeClique(tclib.Message(text="Hello &there"))
- c.AddToShortcutGroup('group_name')
- c = self.uq.MakeClique(tclib.Message(text="Howdie &there partner"))
- c.AddToShortcutGroup('group_name')
-
- warnings = shortcuts.GenerateDuplicateShortcutsWarnings(self.uq, 'PROJECT')
- self.failUnless(warnings)
-
- def testAmpersandEscaping(self):
- c = self.uq.MakeClique(tclib.Message(text="Hello &there"))
- c.AddToShortcutGroup('group_name')
- c = self.uq.MakeClique(tclib.Message(text="S&&T are the &letters S and T"))
- c.AddToShortcutGroup('group_name')
-
- warnings = shortcuts.GenerateDuplicateShortcutsWarnings(self.uq, 'PROJECT')
- self.failUnless(len(warnings) == 0)
-
- def testDialog(self):
- dlg = rc.Dialog('''\
-IDD_SIDEBAR_RSS_PANEL_PROPPAGE DIALOGEX 0, 0, 239, 221
-STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD
-FONT 8, "MS Shell Dlg", 400, 0, 0x1
-BEGIN
- PUSHBUTTON "Add &URL",IDC_SIDEBAR_RSS_ADD_URL,182,53,57,14
- EDITTEXT IDC_SIDEBAR_RSS_NEW_URL,0,53,178,15,ES_AUTOHSCROLL
- PUSHBUTTON "&Remove",IDC_SIDEBAR_RSS_REMOVE,183,200,56,14
- PUSHBUTTON "&Edit",IDC_SIDEBAR_RSS_EDIT,123,200,56,14
- CONTROL "&Automatically add commonly viewed clips",
- IDC_SIDEBAR_RSS_AUTO_ADD,"Button",BS_AUTOCHECKBOX |
- BS_MULTILINE | WS_TABSTOP,0,200,120,17
- PUSHBUTTON "",IDC_SIDEBAR_RSS_HIDDEN,179,208,6,6,NOT WS_VISIBLE
- LTEXT "You can display clips from blogs, news sites, and other online sources.",
- IDC_STATIC,0,0,239,10
- LISTBOX IDC_SIDEBAR_DISPLAYED_FEED_LIST,0,69,239,127,LBS_SORT |
- LBS_OWNERDRAWFIXED | LBS_HASSTRINGS |
- LBS_NOINTEGRALHEIGHT | WS_VSCROLL | WS_HSCROLL |
- WS_TABSTOP
- LTEXT "Add a clip from a recently viewed website by clicking Add Recent Clips.",
- IDC_STATIC,0,13,141,19
- LTEXT "Or, if you know a site supports RSS or Atom, you can enter the RSS or Atom URL below and add it to your list of Web Clips.",
- IDC_STATIC,0,33,239,18
- PUSHBUTTON "Add Recent &Clips (10)...",
- IDC_SIDEBAR_RSS_ADD_RECENT_CLIPS,146,14,93,14
-END''')
- dlg.SetUberClique(self.uq)
- dlg.Parse()
-
- warnings = shortcuts.GenerateDuplicateShortcutsWarnings(self.uq, 'PROJECT')
- self.failUnless(len(warnings) == 0)
-
-if __name__ == '__main__':
- unittest.main()
-
diff --git a/tools/grit/grit/tclib.py b/tools/grit/grit/tclib.py
deleted file mode 100644
index fbe10d8..0000000
--- a/tools/grit/grit/tclib.py
+++ /dev/null
@@ -1,216 +0,0 @@
-#!/usr/bin/python2.4
-# Copyright (c) 2006-2008 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.
-
-'''Adaptation of the extern.tclib classes for our needs.
-'''
-
-
-import re
-import types
-
-from grit import exception
-import grit.extern.tclib
-
-def Identity(i):
- return i
-
-
-class BaseMessage(object):
- '''Base class with methods shared by Message and Translation.
- '''
-
- def __init__(self, text='', placeholders=[], description='', meaning=''):
- self.parts = []
- self.placeholders = []
- self.description = description
- self.meaning = meaning
- self.dirty = True # True if self.id is (or might be) wrong
- self.id = 0
-
- if text != '':
- if not placeholders or placeholders == []:
- self.AppendText(text)
- else:
- tag_map = {}
- for placeholder in placeholders:
- tag_map[placeholder.GetPresentation()] = [placeholder, 0]
- tag_re = '(' + '|'.join(tag_map.keys()) + ')'
- # This creates a regexp like '(TAG1|TAG2|TAG3)'
- chunked_text = re.split(tag_re, text)
- for chunk in chunked_text:
- if chunk: # ignore empty chunk
- if tag_map.has_key(chunk):
- self.AppendPlaceholder(tag_map[chunk][0])
- tag_map[chunk][1] += 1 # increase placeholder use count
- else:
- self.AppendText(chunk)
- for key in tag_map.keys():
- assert tag_map[key][1] != 0
-
- def GetRealContent(self, escaping_function=Identity):
- '''Returns the original content, i.e. what your application and users
- will see.
-
- Specify a function to escape each translateable bit, if you like.
- '''
- bits = []
- for item in self.parts:
- if isinstance(item, types.StringTypes):
- bits.append(escaping_function(item))
- else:
- bits.append(item.GetOriginal())
- return ''.join(bits)
-
- def GetPresentableContent(self):
- presentable_content = []
- for part in self.parts:
- if isinstance(part, Placeholder):
- presentable_content.append(part.GetPresentation())
- else:
- presentable_content.append(part)
- return ''.join(presentable_content)
-
- def AppendPlaceholder(self, placeholder):
- assert isinstance(placeholder, Placeholder)
- dup = False
- for other in self.GetPlaceholders():
- if other.presentation == placeholder.presentation:
- assert other.original == placeholder.original
- dup = True
-
- if not dup:
- self.placeholders.append(placeholder)
- self.parts.append(placeholder)
- self.dirty = True
-
- def AppendText(self, text):
- assert isinstance(text, types.StringTypes)
- assert text != ''
-
- self.parts.append(text)
- self.dirty = True
-
- def GetContent(self):
- '''Returns the parts of the message. You may modify parts if you wish.
- Note that you must not call GetId() on this object until you have finished
- modifying the contents.
- '''
- self.dirty = True # user might modify content
- return self.parts
-
- def GetDescription(self):
- return self.description
-
- def SetDescription(self, description):
- self.description = description
-
- def GetMeaning(self):
- return self.meaning
-
- def GetId(self):
- if self.dirty:
- self.id = self.GenerateId()
- self.dirty = False
- return self.id
-
- def GenerateId(self):
- # Must use a UTF-8 encoded version of the presentable content, along with
- # the meaning attribute, to match the TC.
- return grit.extern.tclib.GenerateMessageId(
- self.GetPresentableContent().encode('utf-8'), self.meaning)
-
- def GetPlaceholders(self):
- return self.placeholders
-
- def FillTclibBaseMessage(self, msg):
- msg.SetDescription(self.description.encode('utf-8'))
-
- for part in self.parts:
- if isinstance(part, Placeholder):
- ph = grit.extern.tclib.Placeholder(
- part.presentation.encode('utf-8'),
- part.original.encode('utf-8'),
- part.example.encode('utf-8'))
- msg.AppendPlaceholder(ph)
- else:
- msg.AppendText(part.encode('utf-8'))
-
-
-class Message(BaseMessage):
- '''A message.'''
-
- def __init__(self, text='', placeholders=[], description='', meaning='',
- assigned_id=None):
- BaseMessage.__init__(self, text, placeholders, description, meaning)
- self.assigned_id = assigned_id
-
- def ToTclibMessage(self):
- msg = grit.extern.tclib.Message('utf-8', meaning=self.meaning)
- self.FillTclibBaseMessage(msg)
- return msg
-
- def GetId(self):
- '''Use the assigned id if we have one.'''
- if self.assigned_id:
- return self.assigned_id
-
- return BaseMessage.GetId(self)
-
-
-class Translation(BaseMessage):
- '''A translation.'''
-
- def __init__(self, text='', id='', placeholders=[], description='', meaning=''):
- BaseMessage.__init__(self, text, placeholders, description, meaning)
- self.id = id
-
- def GetId(self):
- assert id != '', "ID has not been set."
- return self.id
-
- def SetId(self, id):
- self.id = id
-
- def ToTclibMessage(self):
- msg = grit.extern.tclib.Message(
- 'utf-8', id=self.id, meaning=self.meaning)
- self.FillTclibBaseMessage(msg)
- return msg
-
-
-class Placeholder(grit.extern.tclib.Placeholder):
- '''Modifies constructor to accept a Unicode string
- '''
-
- # Must match placeholder presentation names
- _NAME_RE = re.compile('^[A-Za-z0-9_]+$')
-
- def __init__(self, presentation, original, example):
- '''Creates a new placeholder.
-
- Args:
- presentation: 'USERNAME'
- original: '%s'
- example: 'Joi'
- '''
- assert presentation != ''
- assert original != ''
- assert example != ''
- if not self._NAME_RE.match(presentation):
- raise exception.InvalidPlaceholderName(presentation)
- self.presentation = presentation
- self.original = original
- self.example = example
-
- def GetPresentation(self):
- return self.presentation
-
- def GetOriginal(self):
- return self.original
-
- def GetExample(self):
- return self.example
-
-
diff --git a/tools/grit/grit/tclib_unittest.py b/tools/grit/grit/tclib_unittest.py
deleted file mode 100644
index 92c12f7..0000000
--- a/tools/grit/grit/tclib_unittest.py
+++ /dev/null
@@ -1,166 +0,0 @@
-#!/usr/bin/python2.4
-# Copyright (c) 2006-2008 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.
-
-'''Unit tests for grit.tclib'''
-
-
-import sys
-import os.path
-if __name__ == '__main__':
- sys.path.append(os.path.join(os.path.dirname(sys.argv[0]), '..'))
-
-import types
-import unittest
-
-from grit import tclib
-
-from grit import exception
-import grit.extern.tclib
-
-
-class TclibUnittest(unittest.TestCase):
- def testInit(self):
- msg = tclib.Message(text=u'Hello Earthlings')
- self.failUnless(msg.GetPresentableContent() == 'Hello Earthlings')
- self.failUnless(isinstance(msg.GetPresentableContent(), types.StringTypes))
-
- def testGetAttr(self):
- msg = tclib.Message()
- msg.AppendText(u'Hello') # Tests __getattr__
- self.failUnless(msg.GetPresentableContent() == 'Hello')
- self.failUnless(isinstance(msg.GetPresentableContent(), types.StringTypes))
-
- def testAll(self):
- text = u'Howdie USERNAME'
- phs = [tclib.Placeholder(u'USERNAME', u'%s', 'Joi')]
- msg = tclib.Message(text=text, placeholders=phs)
- self.failUnless(msg.GetPresentableContent() == 'Howdie USERNAME')
-
- trans = tclib.Translation(text=text, placeholders=phs)
- self.failUnless(trans.GetPresentableContent() == 'Howdie USERNAME')
- self.failUnless(isinstance(trans.GetPresentableContent(), types.StringTypes))
-
- def testUnicodeReturn(self):
- text = u'\u00fe'
- msg = tclib.Message(text=text)
- self.failUnless(msg.GetPresentableContent() == text)
- from_list = msg.GetContent()[0]
- self.failUnless(from_list == text)
-
- def testRegressionTranslationInherited(self):
- '''Regression tests a bug that was caused by grit.tclib.Translation
- inheriting from the translation console's Translation object
- instead of only owning an instance of it.
- '''
- msg = tclib.Message(text=u"BLA1\r\nFrom: BLA2 \u00fe BLA3",
- placeholders=[
- tclib.Placeholder('BLA1', '%s', '%s'),
- tclib.Placeholder('BLA2', '%s', '%s'),
- tclib.Placeholder('BLA3', '%s', '%s')])
- transl = tclib.Translation(text=msg.GetPresentableContent(),
- placeholders=msg.GetPlaceholders())
- content = transl.GetContent()
- self.failUnless(isinstance(content[3], types.UnicodeType))
-
- def testFingerprint(self):
- # This has Windows line endings. That is on purpose.
- id = grit.extern.tclib.GenerateMessageId(
- 'Google Desktop for Enterprise\r\n'
- 'Copyright (C) 2006 Google Inc.\r\n'
- 'All Rights Reserved\r\n'
- '\r\n'
- '---------\r\n'
- 'Contents\r\n'
- '---------\r\n'
- 'This distribution contains the following files:\r\n'
- '\r\n'
- 'GoogleDesktopSetup.msi - Installation and setup program\r\n'
- 'GoogleDesktop.adm - Group Policy administrative template file\r\n'
- 'AdminGuide.pdf - Google Desktop for Enterprise administrative guide\r\n'
- '\r\n'
- '\r\n'
- '--------------\r\n'
- 'Documentation\r\n'
- '--------------\r\n'
- 'Full documentation and installation instructions are in the \r\n'
- 'administrative guide, and also online at \r\n'
- 'http://desktop.google.com/enterprise/adminguide.html.\r\n'
- '\r\n'
- '\r\n'
- '------------------------\r\n'
- 'IBM Lotus Notes Plug-In\r\n'
- '------------------------\r\n'
- 'The Lotus Notes plug-in is included in the release of Google \r\n'
- 'Desktop for Enterprise. The IBM Lotus Notes Plug-in for Google \r\n'
- 'Desktop indexes mail, calendar, task, contact and journal \r\n'
- 'documents from Notes. Discussion documents including those from \r\n'
- 'the discussion and team room templates can also be indexed by \r\n'
- 'selecting an option from the preferences. Once indexed, this data\r\n'
- 'will be returned in Google Desktop searches. The corresponding\r\n'
- 'document can be opened in Lotus Notes from the Google Desktop \r\n'
- 'results page.\r\n'
- '\r\n'
- 'Install: The plug-in will install automatically during the Google \r\n'
- 'Desktop setup process if Lotus Notes is already installed. Lotus \r\n'
- 'Notes must not be running in order for the install to occur. \r\n'
- '\r\n'
- 'Preferences: Preferences and selection of databases to index are\r\n'
- 'set in the \'Google Desktop for Notes\' dialog reached through the \r\n'
- '\'Actions\' menu.\r\n'
- '\r\n'
- 'Reindexing: Selecting \'Reindex all databases\' will index all the \r\n'
- 'documents in each database again.\r\n'
- '\r\n'
- '\r\n'
- 'Notes Plug-in Known Issues\r\n'
- '---------------------------\r\n'
- '\r\n'
- 'If the \'Google Desktop for Notes\' item is not available from the \r\n'
- 'Lotus Notes Actions menu, then installation was not successful. \r\n'
- 'Installation consists of writing one file, notesgdsplugin.dll, to \r\n'
- 'the Notes application directory and a setting to the notes.ini \r\n'
- 'configuration file. The most likely cause of an unsuccessful \r\n'
- 'installation is that the installer was not able to locate the \r\n'
- 'notes.ini file. Installation will complete if the user closes Notes\r\n'
- 'and manually adds the following setting to this file on a new line:\r\n'
- 'AddinMenus=notegdsplugin.dll\r\n'
- '\r\n'
- 'If the notesgdsplugin.dll file is not in the application directory\r\n'
- '(e.g., C:\Program Files\Lotus\Notes) after Google Desktop \r\n'
- 'installation, it is likely that Notes was not installed correctly. \r\n'
- '\r\n'
- 'Only local databases can be indexed. If they can be determined, \r\n'
- 'the user\'s local mail file and address book will be included in the\r\n'
- 'list automatically. Mail archives and other databases must be \r\n'
- 'added with the \'Add\' button.\r\n'
- '\r\n'
- 'Some users may experience performance issues during the initial \r\n'
- 'indexing of a database. The \'Perform the initial index of a \r\n'
- 'database only when I\'m idle\' option will limit the indexing process\r\n'
- 'to times when the user is not using the machine. If this does not \r\n'
- 'alleviate the problem or the user would like to continually index \r\n'
- 'but just do so more slowly or quickly, the GoogleWaitTime notes.ini\r\n'
- 'value can be set. Increasing the GoogleWaitTime value will slow \r\n'
- 'down the indexing process, and lowering the value will speed it up.\r\n'
- 'A value of zero causes the fastest possible indexing. Removing the\r\n'
- 'ini parameter altogether returns it to the default (20).\r\n'
- '\r\n'
- 'Crashes have been known to occur with certain types of history \r\n'
- 'bookmarks. If the Notes client seems to crash randomly, try \r\n'
- 'disabling the \'Index note history\' option. If it crashes before,\r\n'
- 'you can get to the preferences, add the following line to your \r\n'
- 'notes.ini file:\r\n'
- 'GDSNoIndexHistory=1\r\n')
- self.failUnless(id == '8961534701379422820')
-
- def testPlaceholderNameChecking(self):
- try:
- ph = tclib.Placeholder('BINGO BONGO', 'bla', 'bla')
- raise Exception("We shouldn't get here")
- except exception.InvalidPlaceholderName:
- pass # Expect exception to be thrown because presentation contained space
-
-if __name__ == '__main__':
- unittest.main()
diff --git a/tools/grit/grit/test_suite_all.py b/tools/grit/grit/test_suite_all.py
deleted file mode 100644
index e0f9b77..0000000
--- a/tools/grit/grit/test_suite_all.py
+++ /dev/null
@@ -1,89 +0,0 @@
-#!/usr/bin/env python
-# Copyright (c) 2011 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.
-
-'''Unit test suite that collects all test cases for GRIT.'''
-
-import os
-import sys
-if __name__ == '__main__':
- sys.path.append(os.path.join(os.path.dirname(sys.argv[0]), '..'))
-
-import unittest
-
-
-# TODO(joi) Use unittest.defaultTestLoader to automatically load tests
-# from modules. Iterating over the directory and importing could then
-# automate this all the way, if desired.
-
-
-class TestSuiteAll(unittest.TestSuite):
- def __init__(self):
- super(type(self), self).__init__()
- # Imports placed here to prevent circular imports.
- from grit import grd_reader_unittest
- from grit import grit_runner_unittest
- from grit.node import base_unittest
- from grit.node import io_unittest
- from grit import clique_unittest
- from grit.node import misc_unittest
- from grit.gather import rc_unittest
- from grit.gather import tr_html_unittest
- from grit.node import message_unittest
- from grit import tclib_unittest
- import grit.format.rc_unittest
- import grit.format.data_pack_unittest
- from grit.tool import rc2grd_unittest
- from grit.tool import transl2tc_unittest
- from grit.gather import txt_unittest
- from grit.gather import admin_template_unittest
- from grit import xtb_reader_unittest
- from grit import util_unittest
- from grit.tool import preprocess_unittest
- from grit.tool import postprocess_unittest
- from grit import shortcuts_unittests
- from grit.gather import muppet_strings_unittest
- from grit.gather import policy_json_unittest
- from grit.node.custom import filename_unittest
- import grit.format.js_map_format_unittest
-
- test_classes = [
- base_unittest.NodeUnittest,
- io_unittest.FileNodeUnittest,
- grit_runner_unittest.OptionArgsUnittest,
- grd_reader_unittest.GrdReaderUnittest,
- clique_unittest.MessageCliqueUnittest,
- misc_unittest.GritNodeUnittest,
- rc_unittest.RcUnittest,
- tr_html_unittest.ParserUnittest,
- tr_html_unittest.TrHtmlUnittest,
- message_unittest.MessageUnittest,
- tclib_unittest.TclibUnittest,
- grit.format.rc_unittest.FormatRcUnittest,
- grit.format.data_pack_unittest.FormatDataPackUnittest,
- rc2grd_unittest.Rc2GrdUnittest,
- transl2tc_unittest.TranslationToTcUnittest,
- txt_unittest.TxtUnittest,
- admin_template_unittest.AdmGathererUnittest,
- xtb_reader_unittest.XtbReaderUnittest,
- misc_unittest.IfNodeUnittest,
- util_unittest.UtilUnittest,
- preprocess_unittest.PreProcessingUnittest,
- postprocess_unittest.PostProcessingUnittest,
- misc_unittest.ReleaseNodeUnittest,
- shortcuts_unittests.ShortcutsUnittest,
- muppet_strings_unittest.MuppetStringsUnittest,
- filename_unittest.WindowsFilenameUnittest,
- grit.format.js_map_format_unittest.JsMapFormatUnittest,
- policy_json_unittest.PolicyJsonUnittest,
- # add test classes here...
- ]
-
- for test_class in test_classes:
- self.addTest(unittest.makeSuite(test_class))
-
-
-if __name__ == '__main__':
- test_result = unittest.TextTestRunner(verbosity=2).run(TestSuiteAll())
- sys.exit(len(test_result.errors) + len(test_result.failures))
diff --git a/tools/grit/grit/testdata/GoogleDesktop.adm b/tools/grit/grit/testdata/GoogleDesktop.adm
deleted file mode 100644
index 758fb8e..0000000
--- a/tools/grit/grit/testdata/GoogleDesktop.adm
+++ /dev/null
@@ -1,945 +0,0 @@
-CLASS MACHINE
- CATEGORY !!Cat_Google
- CATEGORY !!Cat_GoogleDesktopSearch
- KEYNAME "Software\Policies\Google\Google Desktop"
-
- CATEGORY !!Cat_Preferences
- KEYNAME "Software\Policies\Google\Google Desktop\Preferences"
-
- CATEGORY !!Cat_IndexAndCaptureControl
- POLICY !!Blacklist_Email
- EXPLAIN !!Explain_Blacklist_Email
- KEYNAME "Software\Policies\Google\Google Desktop\Preferences\blacklist-1"
- VALUENAME "1"
- END POLICY
-
- POLICY !!Blacklist_Gmail
- EXPLAIN !!Explain_Blacklist_Gmail
- KEYNAME "Software\Policies\Google\Google Desktop\Preferences\blacklist-pop"
- VALUENAME "gmail"
- END POLICY
-
- POLICY !!Blacklist_WebHistory
- EXPLAIN !!Explain_Blacklist_WebHistory
- KEYNAME "Software\Policies\Google\Google Desktop\Preferences\blacklist-1"
- VALUENAME "2"
- END POLICY
-
- POLICY !!Blacklist_Chat
- EXPLAIN !!Explain_Blacklist_Chat
- KEYNAME "Software\Policies\Google\Google Desktop\Preferences\blacklist-1"
- ACTIONLISTON
- VALUENAME "3" VALUE NUMERIC 1
- END ACTIONLISTON
- END POLICY
-
- POLICY !!Blacklist_Text
- EXPLAIN !!Explain_Blacklist_Text
- KEYNAME "Software\Policies\Google\Google Desktop\Preferences\blacklist-1"
- ACTIONLISTON
- VALUENAME "4" VALUE NUMERIC 1
- END ACTIONLISTON
- END POLICY
-
- POLICY !!Blacklist_Media
- EXPLAIN !!Explain_Blacklist_Media
- KEYNAME "Software\Policies\Google\Google Desktop\Preferences\blacklist-1"
- ACTIONLISTON
- VALUENAME "5" VALUE NUMERIC 1
- END ACTIONLISTON
- END POLICY
-
- POLICY !!Blacklist_Contact
- EXPLAIN !!Explain_Blacklist_Contact
- KEYNAME "Software\Policies\Google\Google Desktop\Preferences\blacklist-1"
- ACTIONLISTON
- VALUENAME "9" VALUE NUMERIC 1
- END ACTIONLISTON
- END POLICY
-
- POLICY !!Blacklist_Calendar
- EXPLAIN !!Explain_Blacklist_Calendar
- KEYNAME "Software\Policies\Google\Google Desktop\Preferences\blacklist-1"
- ACTIONLISTON
- VALUENAME "10" VALUE NUMERIC 1
- END ACTIONLISTON
- END POLICY
-
- POLICY !!Blacklist_Task
- EXPLAIN !!Explain_Blacklist_Task
- KEYNAME "Software\Policies\Google\Google Desktop\Preferences\blacklist-1"
- ACTIONLISTON
- VALUENAME "11" VALUE NUMERIC 1
- END ACTIONLISTON
- END POLICY
-
- POLICY !!Blacklist_Note
- EXPLAIN !!Explain_Blacklist_Note
- KEYNAME "Software\Policies\Google\Google Desktop\Preferences\blacklist-1"
- ACTIONLISTON
- VALUENAME "12" VALUE NUMERIC 1
- END ACTIONLISTON
- END POLICY
-
- POLICY !!Blacklist_Journal
- EXPLAIN !!Explain_Blacklist_Journal
- KEYNAME "Software\Policies\Google\Google Desktop\Preferences\blacklist-1"
- ACTIONLISTON
- VALUENAME "13" VALUE NUMERIC 1
- END ACTIONLISTON
- END POLICY
-
- POLICY !!Blacklist_Word
- EXPLAIN !!Explain_Blacklist_Word
- KEYNAME "Software\Policies\Google\Google Desktop\Preferences\blacklist-2"
- VALUENAME "DOC"
- END POLICY
-
- POLICY !!Blacklist_Excel
- EXPLAIN !!Explain_Blacklist_Excel
- KEYNAME "Software\Policies\Google\Google Desktop\Preferences\blacklist-2"
- VALUENAME "XLS"
- END POLICY
-
- POLICY !!Blacklist_Powerpoint
- EXPLAIN !!Explain_Blacklist_Powerpoint
- KEYNAME "Software\Policies\Google\Google Desktop\Preferences\blacklist-2"
- VALUENAME "PPT"
- END POLICY
-
- POLICY !!Blacklist_PDF
- EXPLAIN !!Explain_Blacklist_PDF
- KEYNAME "Software\Policies\Google\Google Desktop\Preferences\blacklist-2"
- VALUENAME "PDF"
- END POLICY
-
- POLICY !!Blacklist_ZIP
- EXPLAIN !!Explain_Blacklist_ZIP
- KEYNAME "Software\Policies\Google\Google Desktop\Preferences\blacklist-2"
- VALUENAME "ZIP"
- END POLICY
-
- POLICY !!Blacklist_HTTPS
- EXPLAIN !!Explain_Blacklist_HTTPS
- KEYNAME "Software\Policies\Google\Google Desktop\Preferences\blacklist-3"
- VALUENAME "HTTPS"
- END POLICY
-
- POLICY !!Blacklist_PasswordProtectedOffice
- EXPLAIN !!Explain_Blacklist_PasswordProtectedOffice
- KEYNAME "Software\Policies\Google\Google Desktop\Preferences\blacklist-13"
- VALUENAME "SECUREOFFICE"
- END POLICY
-
- POLICY !!Blacklist_URI_Contains
- EXPLAIN !!Explain_Blacklist_URI_Contains
- KEYNAME "Software\Policies\Google\Google Desktop\Preferences\blacklist-6"
- PART !!Blacklist_URI_Contains LISTBOX
- END PART
- END POLICY
-
- POLICY !!Blacklist_Extensions
- EXPLAIN !!Explain_Blacklist_Extensions
- PART !!Blacklist_Extensions EDITTEXT
- VALUENAME "file_extensions_to_skip"
- END PART
- END POLICY
-
- POLICY !!Pol_Disallow_UserSearchLocations
- EXPLAIN !!Explain_Disallow_UserSearchLocations
- VALUENAME user_search_locations
- VALUEON NUMERIC 1
- END POLICY
-
- POLICY !!Pol_Search_Location_Whitelist
- EXPLAIN !!Explain_Search_Location_Whitelist
- KEYNAME "Software\Policies\Google\Google Desktop\Preferences\policy_search_location_whitelist"
- PART !!Search_Locations_Whitelist LISTBOX
- END PART
- END POLICY
-
- POLICY !!Email_Retention
- EXPLAIN !!Explain_Email_Retention
- PART !!Email_Retention_Edit NUMERIC
- VALUENAME "email_days_to_retain"
- MIN 1 MAX 65535 DEFAULT 30 SPIN 1
- END PART
- END POLICY
-
- POLICY !!Webpage_Retention
- EXPLAIN !!Explain_Webpage_Retention
- PART !!Webpage_Retention_Edit NUMERIC
- VALUENAME "webpage_days_to_retain"
- MIN 1 MAX 65535 DEFAULT 30 SPIN 1
- END PART
- END POLICY
-
- POLICY !!File_Retention
- EXPLAIN !!Explain_File_Retention
- PART !!File_Retention_Edit NUMERIC
- VALUENAME "file_days_to_retain"
- MIN 1 MAX 65535 DEFAULT 30 SPIN 1
- END PART
- END POLICY
-
- POLICY !!IM_Retention
- EXPLAIN !!Explain_IM_Retention
- PART !!IM_Retention_Edit NUMERIC
- VALUENAME "im_days_to_retain"
- MIN 1 MAX 65535 DEFAULT 30 SPIN 1
- END PART
- END POLICY
-
- POLICY !!Pol_Remove_Deleted_Items
- EXPLAIN !!Explain_Remove_Deleted_Items
- VALUENAME remove_deleted_items
- VALUEON NUMERIC 1
- END POLICY
-
- POLICY !!Pol_Allow_Simultaneous_Indexing
- EXPLAIN !!Explain_Allow_Simultaneous_Indexing
- VALUENAME simultaneous_indexing
- VALUEON NUMERIC 1
- END POLICY
-
- END CATEGORY
-
- POLICY !!Pol_TurnOffAdvancedFeatures
- EXPLAIN !!Explain_TurnOffAdvancedFeatures
- VALUENAME error_report_on
- VALUEON NUMERIC 0
- END POLICY
-
- POLICY !!Pol_TurnOffImproveGd
- EXPLAIN !!Explain_TurnOffImproveGd
- VALUENAME improve_gd
- VALUEON NUMERIC 0
- VALUEOFF NUMERIC 1
- END POLICY
-
- POLICY !!Pol_NoPersonalizationInfo
- EXPLAIN !!Explain_NoPersonalizationInfo
- VALUENAME send_personalization_info
- VALUEON NUMERIC 0
- VALUEOFF NUMERIC 1
- END POLICY
-
- POLICY !!Pol_OneBoxMode
- EXPLAIN !!Explain_OneBoxMode
- VALUENAME onebox_mode
- VALUEON NUMERIC 0
- END POLICY
-
- POLICY !!Pol_EncryptIndex
- EXPLAIN !!Explain_EncryptIndex
- VALUENAME encrypt_index
- VALUEON NUMERIC 1
- END POLICY
-
- POLICY !!Pol_Hyper
- EXPLAIN !!Explain_Hyper
- VALUENAME hyper_off
- VALUEON NUMERIC 1
- END POLICY
-
- POLICY !!Pol_Display_Mode
- EXPLAIN !!Explain_Display_Mode
- PART !!Pol_Display_Mode DROPDOWNLIST
- VALUENAME display_mode
- ITEMLIST
- NAME !!Sidebar VALUE NUMERIC 1
- NAME !!Deskbar VALUE NUMERIC 8
- NAME !!FloatingDeskbar VALUE NUMERIC 4
- NAME !!None VALUE NUMERIC 0
- END ITEMLIST
- END PART
- END POLICY
-
- END CATEGORY ; Preferences
-
- CATEGORY !!Cat_Enterprise
- KEYNAME "Software\Policies\Google\Google Desktop\Enterprise"
-
- POLICY !!Pol_Autoupdate
- EXPLAIN !!Explain_Autoupdate
- VALUENAME autoupdate_host
- VALUEON ""
- END POLICY
-
- POLICY !!Pol_AutoupdateAsSystem
- EXPLAIN !!Explain_AutoupdateAsSystem
- VALUENAME autoupdate_impersonate_user
- VALUEON NUMERIC 0
- VALUEOFF NUMERIC 1
- END POLICY
-
- POLICY !!Pol_EnterpriseTab
- EXPLAIN !!Explain_EnterpriseTab
- PART !!EnterpriseTabText EDITTEXT
- VALUENAME enterprise_tab_text
- END PART
- PART !!EnterpriseTabHomepage EDITTEXT
- VALUENAME enterprise_tab_homepage
- END PART
- PART !!EnterpriseTabHomepageQuery CHECKBOX
- VALUENAME enterprise_tab_homepage_query
- END PART
- PART !!EnterpriseTabResults EDITTEXT
- VALUENAME enterprise_tab_results
- END PART
- PART !!EnterpriseTabResultsQuery CHECKBOX
- VALUENAME enterprise_tab_results_query
- END PART
- END POLICY
-
- POLICY !!Pol_GSAHosts
- EXPLAIN !!Explain_GSAHosts
- KEYNAME "Software\Policies\Google\Google Desktop\Enterprise\GSAHosts"
- PART !!Pol_GSAHosts LISTBOX
- END PART
- END POLICY
-
- POLICY !!Pol_PolicyUnawareClientProhibitedFlag
- EXPLAIN !!Explain_PolicyUnawareClientProhibitedFlag
- KEYNAME "Software\Policies\Google\Google Desktop"
- VALUENAME PolicyUnawareClientProhibitedFlag
- END POLICY
-
- POLICY !!Pol_MinimumAllowedVersion
- EXPLAIN !!Explain_MinimumAllowedVersion
- PART !!Pol_MinimumAllowedVersion EDITTEXT
- VALUENAME minimum_allowed_version
- END PART
- END POLICY
-
- POLICY !!Pol_MaximumAllowedVersion
- EXPLAIN !!Explain_MaximumAllowedVersion
- PART !!Pol_MaximumAllowedVersion EDITTEXT
- VALUENAME maximum_allowed_version
- END PART
- END POLICY
-
- POLICY !!Pol_Disallow_Gadgets
- EXPLAIN !!Explain_Disallow_Gadgets
- VALUENAME disallow_gadgets
- VALUEON NUMERIC 1
- PART !!Disallow_Only_Non_Builtin_Gadgets CHECKBOX DEFCHECKED
- VALUENAME disallow_only_non_builtin_gadgets
- VALUEON NUMERIC 1
- VALUEOFF NUMERIC 0
- END PART
- END POLICY
-
- POLICY !!Pol_Gadget_Whitelist
- EXPLAIN !!Explain_Gadget_Whitelist
- KEYNAME "Software\Policies\Google\Google Desktop\Enterprise\gadget_whitelist"
- PART !!Pol_Gadget_Whitelist LISTBOX
- END PART
- END POLICY
-
- POLICY !!Pol_Gadget_Install_Confirmation_Whitelist
- EXPLAIN !!Explain_Gadget_Install_Confirmation_Whitelist
- KEYNAME "Software\Policies\Google\Google Desktop\Enterprise\install_confirmation_whitelist"
- PART !!Pol_Gadget_Install_Confirmation_Whitelist LISTBOX
- END PART
- END POLICY
-
- POLICY !!Pol_Alternate_User_Data_Dir
- EXPLAIN !!Explain_Alternate_User_Data_Dir
- PART !!Pol_Alternate_User_Data_Dir EDITTEXT
- VALUENAME alternate_user_data_dir
- END PART
- END POLICY
-
- POLICY !!Pol_MaxAllowedOutlookConnections
- EXPLAIN !!Explain_MaxAllowedOutlookConnections
- PART !!Pol_MaxAllowedOutlookConnections NUMERIC
- VALUENAME max_allowed_outlook_connections
- MIN 1 MAX 65535 DEFAULT 400 SPIN 1
- END PART
- END POLICY
-
- POLICY !!Pol_DisallowSsdService
- EXPLAIN !!Explain_DisallowSsdService
- VALUENAME disallow_ssd_service
- VALUEON NUMERIC 1
- END POLICY
-
- POLICY !!Pol_DisallowSsdOutbound
- EXPLAIN !!Explain_DisallowSsdOutbound
- VALUENAME disallow_ssd_outbound
- VALUEON NUMERIC 1
- END POLICY
-
- POLICY !!Pol_Disallow_Store_Gadget_Service
- EXPLAIN !!Explain_Disallow_Store_Gadget_Service
- VALUENAME disallow_store_gadget_service
- VALUEON NUMERIC 1
- END POLICY
-
- POLICY !!Pol_MaxExchangeIndexingRate
- EXPLAIN !!Explain_MaxExchangeIndexingRate
- PART !!Pol_MaxExchangeIndexingRate NUMERIC
- VALUENAME max_exchange_indexing_rate
- MIN 1 MAX 1000 DEFAULT 60 SPIN 1
- END PART
- END POLICY
-
- POLICY !!Pol_EnableSafeweb
- EXPLAIN !!Explain_Safeweb
- VALUENAME safe_browsing
- VALUEON NUMERIC 1
- VALUEOFF NUMERIC 0
- END POLICY
-
- END CATEGORY ; Enterprise
-
- END CATEGORY ; GoogleDesktopSearch
- END CATEGORY ; Google
-
-
-CLASS USER
- CATEGORY !!Cat_Google
- CATEGORY !!Cat_GoogleDesktopSearch
- KEYNAME "Software\Policies\Google\Google Desktop"
-
- CATEGORY !!Cat_Preferences
- KEYNAME "Software\Policies\Google\Google Desktop\Preferences"
-
- CATEGORY !!Cat_IndexAndCaptureControl
- POLICY !!Blacklist_Email
- EXPLAIN !!Explain_Blacklist_Email
- KEYNAME "Software\Policies\Google\Google Desktop\Preferences\blacklist-1"
- VALUENAME "1"
- END POLICY
-
- POLICY !!Blacklist_Gmail
- EXPLAIN !!Explain_Blacklist_Gmail
- KEYNAME "Software\Policies\Google\Google Desktop\Preferences\blacklist-pop"
- VALUENAME "gmail"
- END POLICY
-
- POLICY !!Blacklist_WebHistory
- EXPLAIN !!Explain_Blacklist_WebHistory
- KEYNAME "Software\Policies\Google\Google Desktop\Preferences\blacklist-1"
- VALUENAME "2"
- END POLICY
-
- POLICY !!Blacklist_Chat
- EXPLAIN !!Explain_Blacklist_Chat
- KEYNAME "Software\Policies\Google\Google Desktop\Preferences\blacklist-1"
- ACTIONLISTON
- VALUENAME "3" VALUE NUMERIC 1
- END ACTIONLISTON
- END POLICY
-
- POLICY !!Blacklist_Text
- EXPLAIN !!Explain_Blacklist_Text
- KEYNAME "Software\Policies\Google\Google Desktop\Preferences\blacklist-1"
- ACTIONLISTON
- VALUENAME "4" VALUE NUMERIC 1
- END ACTIONLISTON
- END POLICY
-
- POLICY !!Blacklist_Media
- EXPLAIN !!Explain_Blacklist_Media
- KEYNAME "Software\Policies\Google\Google Desktop\Preferences\blacklist-1"
- ACTIONLISTON
- VALUENAME "5" VALUE NUMERIC 1
- END ACTIONLISTON
- END POLICY
-
- POLICY !!Blacklist_Contact
- EXPLAIN !!Explain_Blacklist_Contact
- KEYNAME "Software\Policies\Google\Google Desktop\Preferences\blacklist-1"
- ACTIONLISTON
- VALUENAME "9" VALUE NUMERIC 1
- END ACTIONLISTON
- END POLICY
-
- POLICY !!Blacklist_Calendar
- EXPLAIN !!Explain_Blacklist_Calendar
- KEYNAME "Software\Policies\Google\Google Desktop\Preferences\blacklist-1"
- ACTIONLISTON
- VALUENAME "10" VALUE NUMERIC 1
- END ACTIONLISTON
- END POLICY
-
- POLICY !!Blacklist_Task
- EXPLAIN !!Explain_Blacklist_Task
- KEYNAME "Software\Policies\Google\Google Desktop\Preferences\blacklist-1"
- ACTIONLISTON
- VALUENAME "11" VALUE NUMERIC 1
- END ACTIONLISTON
- END POLICY
-
- POLICY !!Blacklist_Note
- EXPLAIN !!Explain_Blacklist_Note
- KEYNAME "Software\Policies\Google\Google Desktop\Preferences\blacklist-1"
- ACTIONLISTON
- VALUENAME "12" VALUE NUMERIC 1
- END ACTIONLISTON
- END POLICY
-
- POLICY !!Blacklist_Journal
- EXPLAIN !!Explain_Blacklist_Journal
- KEYNAME "Software\Policies\Google\Google Desktop\Preferences\blacklist-1"
- ACTIONLISTON
- VALUENAME "13" VALUE NUMERIC 1
- END ACTIONLISTON
- END POLICY
-
- POLICY !!Blacklist_Word
- EXPLAIN !!Explain_Blacklist_Word
- KEYNAME "Software\Policies\Google\Google Desktop\Preferences\blacklist-2"
- VALUENAME "DOC"
- END POLICY
-
- POLICY !!Blacklist_Excel
- EXPLAIN !!Explain_Blacklist_Excel
- KEYNAME "Software\Policies\Google\Google Desktop\Preferences\blacklist-2"
- VALUENAME "XLS"
- END POLICY
-
- POLICY !!Blacklist_Powerpoint
- EXPLAIN !!Explain_Blacklist_Powerpoint
- KEYNAME "Software\Policies\Google\Google Desktop\Preferences\blacklist-2"
- VALUENAME "PPT"
- END POLICY
-
- POLICY !!Blacklist_PDF
- EXPLAIN !!Explain_Blacklist_PDF
- KEYNAME "Software\Policies\Google\Google Desktop\Preferences\blacklist-2"
- VALUENAME "PDF"
- END POLICY
-
- POLICY !!Blacklist_ZIP
- EXPLAIN !!Explain_Blacklist_ZIP
- KEYNAME "Software\Policies\Google\Google Desktop\Preferences\blacklist-2"
- VALUENAME "ZIP"
- END POLICY
-
- POLICY !!Blacklist_HTTPS
- EXPLAIN !!Explain_Blacklist_HTTPS
- KEYNAME "Software\Policies\Google\Google Desktop\Preferences\blacklist-3"
- VALUENAME "HTTPS"
- END POLICY
-
- POLICY !!Blacklist_PasswordProtectedOffice
- EXPLAIN !!Explain_Blacklist_PasswordProtectedOffice
- KEYNAME "Software\Policies\Google\Google Desktop\Preferences\blacklist-13"
- VALUENAME "SECUREOFFICE"
- END POLICY
-
- POLICY !!Blacklist_URI_Contains
- EXPLAIN !!Explain_Blacklist_URI_Contains
- KEYNAME "Software\Policies\Google\Google Desktop\Preferences\blacklist-6"
- PART !!Blacklist_URI_Contains LISTBOX
- END PART
- END POLICY
-
- POLICY !!Blacklist_Extensions
- EXPLAIN !!Explain_Blacklist_Extensions
- PART !!Blacklist_Extensions EDITTEXT
- VALUENAME "file_extensions_to_skip"
- END PART
- END POLICY
-
- POLICY !!Pol_Disallow_UserSearchLocations
- EXPLAIN !!Explain_Disallow_UserSearchLocations
- VALUENAME user_search_locations
- VALUEON NUMERIC 1
- END POLICY
-
- POLICY !!Pol_Search_Location_Whitelist
- EXPLAIN !!Explain_Search_Location_Whitelist
- KEYNAME "Software\Policies\Google\Google Desktop\Preferences\policy_search_location_whitelist"
- PART !!Search_Locations_Whitelist LISTBOX
- END PART
- END POLICY
-
- POLICY !!Email_Retention
- EXPLAIN !!Explain_Email_Retention
- PART !!Email_Retention_Edit NUMERIC
- VALUENAME "email_days_to_retain"
- MIN 1 MAX 65535 DEFAULT 30 SPIN 1
- END PART
- END POLICY
-
- POLICY !!Webpage_Retention
- EXPLAIN !!Explain_Webpage_Retention
- PART !!Webpage_Retention_Edit NUMERIC
- VALUENAME "webpage_days_to_retain"
- MIN 1 MAX 65535 DEFAULT 30 SPIN 1
- END PART
- END POLICY
-
- POLICY !!File_Retention
- EXPLAIN !!Explain_File_Retention
- PART !!File_Retention_Edit NUMERIC
- VALUENAME "file_days_to_retain"
- MIN 1 MAX 65535 DEFAULT 30 SPIN 1
- END PART
- END POLICY
-
- POLICY !!IM_Retention
- EXPLAIN !!Explain_IM_Retention
- PART !!IM_Retention_Edit NUMERIC
- VALUENAME "im_days_to_retain"
- MIN 1 MAX 65535 DEFAULT 30 SPIN 1
- END PART
- END POLICY
-
- POLICY !!Pol_Remove_Deleted_Items
- EXPLAIN !!Explain_Remove_Deleted_Items
- VALUENAME remove_deleted_items
- VALUEON NUMERIC 1
- END POLICY
-
- POLICY !!Pol_Allow_Simultaneous_Indexing
- EXPLAIN !!Explain_Allow_Simultaneous_Indexing
- VALUENAME simultaneous_indexing
- VALUEON NUMERIC 1
- END POLICY
-
- END CATEGORY
-
- POLICY !!Pol_TurnOffAdvancedFeatures
- EXPLAIN !!Explain_TurnOffAdvancedFeatures
- VALUENAME error_report_on
- VALUEON NUMERIC 0
- END POLICY
-
- POLICY !!Pol_TurnOffImproveGd
- EXPLAIN !!Explain_TurnOffImproveGd
- VALUENAME improve_gd
- VALUEON NUMERIC 0
- VALUEOFF NUMERIC 1
- END POLICY
-
- POLICY !!Pol_NoPersonalizationInfo
- EXPLAIN !!Explain_NoPersonalizationInfo
- VALUENAME send_personalization_info
- VALUEON NUMERIC 0
- VALUEOFF NUMERIC 1
- END POLICY
-
- POLICY !!Pol_OneBoxMode
- EXPLAIN !!Explain_OneBoxMode
- VALUENAME onebox_mode
- VALUEON NUMERIC 0
- END POLICY
-
- POLICY !!Pol_EncryptIndex
- EXPLAIN !!Explain_EncryptIndex
- VALUENAME encrypt_index
- VALUEON NUMERIC 1
- END POLICY
-
- POLICY !!Pol_Hyper
- EXPLAIN !!Explain_Hyper
- VALUENAME hyper_off
- VALUEON NUMERIC 1
- END POLICY
-
- POLICY !!Pol_Display_Mode
- EXPLAIN !!Explain_Display_Mode
- PART !!Pol_Display_Mode DROPDOWNLIST
- VALUENAME display_mode
- ITEMLIST
- NAME !!Sidebar VALUE NUMERIC 1
- NAME !!Deskbar VALUE NUMERIC 8
- NAME !!FloatingDeskbar VALUE NUMERIC 4
- NAME !!None VALUE NUMERIC 0
- END ITEMLIST
- END PART
- END POLICY
-
- END CATEGORY ; Preferences
-
- CATEGORY !!Cat_Enterprise
- KEYNAME "Software\Policies\Google\Google Desktop\Enterprise"
-
- POLICY !!Pol_Autoupdate
- EXPLAIN !!Explain_Autoupdate
- VALUENAME autoupdate_host
- VALUEON ""
- END POLICY
-
- POLICY !!Pol_AutoupdateAsSystem
- EXPLAIN !!Explain_AutoupdateAsSystem
- VALUENAME autoupdate_impersonate_user
- VALUEON NUMERIC 0
- VALUEOFF NUMERIC 1
- END POLICY
-
- POLICY !!Pol_EnterpriseTab
- EXPLAIN !!Explain_EnterpriseTab
- PART !!EnterpriseTabText EDITTEXT
- VALUENAME enterprise_tab_text
- END PART
- PART !!EnterpriseTabHomepage EDITTEXT
- VALUENAME enterprise_tab_homepage
- END PART
- PART !!EnterpriseTabHomepageQuery CHECKBOX
- VALUENAME enterprise_tab_homepage_query
- END PART
- PART !!EnterpriseTabResults EDITTEXT
- VALUENAME enterprise_tab_results
- END PART
- PART !!EnterpriseTabResultsQuery CHECKBOX
- VALUENAME enterprise_tab_results_query
- END PART
- END POLICY
-
- POLICY !!Pol_GSAHosts
- EXPLAIN !!Explain_GSAHosts
- KEYNAME "Software\Policies\Google\Google Desktop\Enterprise\GSAHosts"
- PART !!Pol_GSAHosts LISTBOX
- END PART
- END POLICY
-
- POLICY !!Pol_Disallow_Gadgets
- EXPLAIN !!Explain_Disallow_Gadgets
- VALUENAME disallow_gadgets
- VALUEON NUMERIC 1
- PART !!Disallow_Only_Non_Builtin_Gadgets CHECKBOX DEFCHECKED
- VALUENAME disallow_only_non_builtin_gadgets
- VALUEON NUMERIC 1
- VALUEOFF NUMERIC 0
- END PART
- END POLICY
-
- POLICY !!Pol_Gadget_Whitelist
- EXPLAIN !!Explain_Gadget_Whitelist
- KEYNAME "Software\Policies\Google\Google Desktop\Enterprise\gadget_whitelist"
- PART !!Pol_Gadget_Whitelist LISTBOX
- END PART
- END POLICY
-
- POLICY !!Pol_Gadget_Install_Confirmation_Whitelist
- EXPLAIN !!Explain_Gadget_Install_Confirmation_Whitelist
- KEYNAME "Software\Policies\Google\Google Desktop\Enterprise\install_confirmation_whitelist"
- PART !!Pol_Gadget_Install_Confirmation_Whitelist LISTBOX
- END PART
- END POLICY
-
- POLICY !!Pol_Alternate_User_Data_Dir
- EXPLAIN !!Explain_Alternate_User_Data_Dir
- PART !!Pol_Alternate_User_Data_Dir EDITTEXT
- VALUENAME alternate_user_data_dir
- END PART
- END POLICY
-
- POLICY !!Pol_MaxAllowedOutlookConnections
- EXPLAIN !!Explain_MaxAllowedOutlookConnections
- PART !!Pol_MaxAllowedOutlookConnections NUMERIC
- VALUENAME max_allowed_outlook_connections
- MIN 1 MAX 65535 DEFAULT 400 SPIN 1
- END PART
- END POLICY
-
- POLICY !!Pol_DisallowSsdService
- EXPLAIN !!Explain_DisallowSsdService
- VALUENAME disallow_ssd_service
- VALUEON NUMERIC 1
- END POLICY
-
- POLICY !!Pol_DisallowSsdOutbound
- EXPLAIN !!Explain_DisallowSsdOutbound
- VALUENAME disallow_ssd_outbound
- VALUEON NUMERIC 1
- END POLICY
-
- POLICY !!Pol_Disallow_Store_Gadget_Service
- EXPLAIN !!Explain_Disallow_Store_Gadget_Service
- VALUENAME disallow_store_gadget_service
- VALUEON NUMERIC 1
- END POLICY
-
- POLICY !!Pol_MaxExchangeIndexingRate
- EXPLAIN !!Explain_MaxExchangeIndexingRate
- PART !!Pol_MaxExchangeIndexingRate NUMERIC
- VALUENAME max_exchange_indexing_rate
- MIN 1 MAX 1000 DEFAULT 60 SPIN 1
- END PART
- END POLICY
-
- POLICY !!Pol_EnableSafeweb
- EXPLAIN !!Explain_Safeweb
- VALUENAME safe_browsing
- VALUEON NUMERIC 1
- VALUEOFF NUMERIC 0
- END POLICY
-
- END CATEGORY ; Enterprise
-
- END CATEGORY ; GoogleDesktopSearch
- END CATEGORY ; Google
-
-;------------------------------------------------------------------------------
-
-[strings]
-Cat_Google="Google"
-Cat_GoogleDesktopSearch="Google Desktop"
-
-;------------------------------------------------------------------------------
-; Preferences
-;------------------------------------------------------------------------------
-Cat_Preferences="Preferences"
-Explain_Preferences="Controls Google Desktop preferences"
-
-Cat_IndexAndCaptureControl="Indexing and Capture Control"
-Explain_IndexAndCaptureControl="Controls what files, web pages, and other content will be indexed by Google Desktop."
-
-Blacklist_Email="Prevent indexing of email"
-Explain_Blacklist_Email="Enabling this policy will prevent Google Desktop from indexing emails.\n\nIf this policy is not configured, the user can choose whether or not to index emails."
-Blacklist_Gmail="Prevent indexing of Gmail"
-Explain_Blacklist_Gmail="Enabling this policy prevents Google Desktop from indexing Gmail messages.\n\nThis policy is in effect only when the policy "Prevent indexing of email" is disabled. When that policy is enabled, all email indexing is disabled, including Gmail indexing.\n\nIf both this policy and "Prevent indexing of email" are disabled or not configured, a user can choose whether or not to index Gmail messages."
-Blacklist_WebHistory="Prevent indexing of web pages"
-Explain_Blacklist_WebHistory="Enabling this policy will prevent Google Desktop from indexing web pages.\n\nIf this policy is disabled or not configured, the user can choose whether or not to index web pages."
-Blacklist_Text="Prevent indexing of text files"
-Explain_Blacklist_Text="Enabling this policy will prevent Google Desktop from indexing text files.\n\nIf this policy is disabled or not configured, the user can choose whether or not to index text files."
-Blacklist_Media="Prevent indexing of media files"
-Explain_Blacklist_Media="Enabling this policy will prevent Google Desktop from indexing media files.\n\nIf this policy is disabled or not configured, the user can choose whether or not to index media files."
-Blacklist_Contact="Prevent indexing of contacts"
-Explain_Blacklist_Contact="Enabling this policy will prevent Google Desktop from indexing contacts.\n\nIf this policy is disabled or not configured, the user can choose whether or not to index contacts."
-Blacklist_Calendar="Prevent indexing of calendar entries"
-Explain_Blacklist_Calendar="Enabling this policy will prevent Google Desktop from indexing calendar entries.\n\nIf this policy is disabled or not configured, the user can choose whether or not to index calendar entries."
-Blacklist_Task="Prevent indexing of tasks"
-Explain_Blacklist_Task="Enabling this policy will prevent Google Desktop from indexing tasks.\n\nIf this policy is disabled or not configured, the user can choose whether or not to index tasks."
-Blacklist_Note="Prevent indexing of notes"
-Explain_Blacklist_Note="Enabling this policy will prevent Google Desktop from indexing notes.\n\nIf this policy is disabled or not configured, the user can choose whether or not to index notes."
-Blacklist_Journal="Prevent indexing of journal entries"
-Explain_Blacklist_Journal="Enabling this policy will prevent Google Desktop from indexing journal entries.\n\nIf this policy is disabled or not configured, the user can choose whether or not to index journal entries."
-Blacklist_Word="Prevent indexing of Word documents"
-Explain_Blacklist_Word="Enabling this policy will prevent Google Desktop from indexing Word documents.\n\nIf this policy is disabled or not configured, the user can choose whether or not to index Word documents."
-Blacklist_Excel="Prevent indexing of Excel documents"
-Explain_Blacklist_Excel="Enabling this policy will prevent Google Desktop from indexing Excel documents.\n\nIf this policy is disabled or not configured, the user can choose whether or not to index Excel documents."
-Blacklist_Powerpoint="Prevent indexing of PowerPoint documents"
-Explain_Blacklist_Powerpoint="Enabling this policy will prevent Google Desktop from indexing PowerPoint documents.\n\nIf this policy is disabled or not configured, the user can choose whether or not to index PowerPoint documents."
-Blacklist_PDF="Prevent indexing of PDF documents"
-Explain_Blacklist_PDF="Enabling this policy will prevent Google Desktop from indexing PDF documents.\n\nIf this policy is disabled or not configured, the user can choose whether or not to index PDF documents."
-Blacklist_ZIP="Prevent indexing of ZIP files"
-Explain_Blacklist_ZIP="Enabling this policy will prevent Google Desktop from indexing ZIP files.\n\nIf this policy is disabled or not configured, the user can choose whether or not to index ZIP files."
-Blacklist_HTTPS="Prevent indexing of secure web pages"
-Explain_Blacklist_HTTPS="Enabling this policy will prevent Google Desktop from indexing secure web pages (pages with HTTPS in the URL).\n\nIf this policy is disabled or not configured, the user can choose whether or not to index secure web pages."
-Blacklist_URI_Contains="Prevent indexing of specific web sites and folders"
-Explain_Blacklist_URI_Contains="This policy allows you to prevent Google Desktop from indexing specific websites or folders. If an item's URL or path name contains any of these specified strings, it will not be indexed. These restrictions will be applied in addition to any websites or folders that the user has specified.\n\nThis policy has no effect when disabled or not configured."
-Blacklist_Chat="Prevent indexing of IM chats"
-Explain_Blacklist_Chat="Enabling this policy will prevent Google Desktop from indexing IM chat conversations.\n\nIf this policy is disabled or not configured, the user can choose whether or not to index IM chat conversations."
-Blacklist_PasswordProtectedOffice="Prevent indexing of password-protected Office documents (Word, Excel)"
-Explain_Blacklist_PasswordProtectedOffice="Enabling this policy will prevent Google Desktop from indexing password-protected office documents.\n\nIf this policy is disabled or not configured, the user can choose whether or not to index password-protected office documents."
-Blacklist_Extensions="Prevent indexing of specific file extensions"
-Explain_Blacklist_Extensions="This policy allows you to prevent Google Desktop from indexing files with specific extensions. Enter a list of file extensions, separated by commas, that you wish to exclude from indexing.\n\nThis policy has no effect when disabled or not configured."
-Pol_Disallow_UserSearchLocations="Disallow adding search locations for indexing"
-Explain_Disallow_UserSearchLocations="Enabling this policy will prevent the user from specifying additional drives or networked folders to be indexed by Google Desktop.\n\nIf this policy is disabled or not configured, users may specify additional drives and networked folders to be indexed."
-Pol_Search_Location_Whitelist="Allow indexing of specific folders"
-Explain_Search_Location_Whitelist="This policy allows you to add additional drives and networked folders to index."
-Search_Locations_Whitelist="Search these locations"
-Email_Retention="Only retain emails that are less than x days old"
-Explain_Email_Retention="This policy allows you to configure Google Desktop to only retain emails that are less than the specified number of days old in the index. Enter the number of days to retain emails for\n\nThis policy has no effect when disabled or not configured."
-Email_Retention_Edit="Number of days to retain emails"
-Webpage_Retention="Only retain webpages that are less than x days old"
-Explain_Webpage_Retention="This policy allows you to configure Google Desktop to only retain webpages that are less than the specified number of days old in the index. Enter the number of days to retain webpages for\n\nThis policy has no effect when disabled or not configured."
-Webpage_Retention_Edit="Number of days to retain webpages"
-File_Retention="Only retain files that are less than x days old"
-Explain_File_Retention="This policy allows you to configure Google Desktop to only retain files that are less than the specified number of days old in the index. Enter the number of days to retain files for\n\nThis policy has no effect when disabled or not configured."
-File_Retention_Edit="Number of days to retain files"
-IM_Retention="Only retain IM that are less than x days old"
-Explain_IM_Retention="This policy allows you to configure Google Desktop to only retain IM that are less than the specified number of days old in the index. Enter the number of days to retain IM for\n\nThis policy has no effect when disabled or not configured."
-IM_Retention_Edit="Number of days to retain IM"
-
-Pol_Remove_Deleted_Items="Remove deleted items from the index."
-Explain_Remove_Deleted_Items="Enabling this policy will remove all deleted items from the index and cache. Any items that are deleted will no longer be searchable."
-
-Pol_Allow_Simultaneous_Indexing="Allow historical indexing for multiple users simultaneously."
-Explain_Allow_Simultaneous_Indexing="Enabling this policy will allow a computer to generate first-time indexes for multiple users simultaneously. \n\nIf this policy is disabled or not configured, historical indexing will happen only for the logged-in user that was connected last; historical indexing for any other logged-in user will happen the next time that other user connects."
-
-Pol_TurnOffAdvancedFeatures="Turn off Advanced Features options"
-Explain_TurnOffAdvancedFeatures="Enabling this policy will prevent Google Desktop from sending Advanced Features data to Google (for either improvements or personalization), and users won't be able to change these options. Enabling this policy also prevents older versions of Google Desktop from sending data.\n\nIf this policy is disabled or not configured and the user has a pre-5.5 version of Google Desktop, the user can choose whether or not to enable sending data to Google. If the user has version 5.5 or later, the 'Turn off Improve Google Desktop option' and 'Do not send personalization info' policies will be used instead."
-
-Pol_TurnOffImproveGd="Turn off Improve Google Desktop option"
-Explain_TurnOffImproveGd="Enabling this policy will prevent Google Desktop from sending improvement data, including crash reports and anonymous usage data, to Google.\n\nIf this policy is disabled, improvement data will be sent to Google and the user won't be able to change the option.\n\nIf this policy is not configured, the user can choose whether or not to enable the Improve Google Desktop option.\n\nNote that this policy applies only to version 5.5 or later and doesn't affect previous versions of Google Desktop.\n\nAlso note that this policy can be overridden by the 'Turn off Advanced Features options' policy."
-
-Pol_NoPersonalizationInfo="Do not send personalization info"
-Explain_NoPersonalizationInfo="Enabling this policy will prevent Google Desktop from displaying personalized content, such as news that reflects the user's past interest in articles. Personalized content is derived from anonymous usage data sent to Google.\n\nIf this policy is disabled, personalized content will be displayed for all users, and users won't be able to disable this feature.\n\nIf this policy is not configured, users can choose whether or not to enable personalization in each gadget that supports this feature.\n\nNote that this policy applies only to version 5.5 or later and doesn't affect previous versions of Google Desktop.\n\nAlso note that this policy can be overridden by the 'Turn off Advanced Features options' policy."
-
-Pol_OneBoxMode="Turn off Google Web Search Integration"
-Explain_OneBoxMode="Enabling this policy will prevent Google Desktop from displaying Desktop Search results in queries to google.com.\n\nIf this policy is disabled or not configured, the user can choose whether or not to include Desktop Search results in queries to google.com."
-
-Pol_EncryptIndex="Encrypt index data"
-Explain_EncryptIndex="Enabling this policy will cause Google Desktop to turn on Windows file encryption for the folder containing the Google Desktop index and related user data the next time it is run.\n\nNote that Windows EFS is only available on NTFS volumes. If the user's data is stored on a FAT volume, this policy will have no effect.\n\nThis policy has no effect when disabled or not configured."
-
-Pol_Hyper="Turn off Quick Find"
-Explain_Hyper="Enabling this policy will cause Google Desktop to turn off Quick Find feature. Quick Find allows you to see results as you type.\n\nIf this policy is disabled or not configured, the user can choose whether or not to enable it."
-
-Pol_Display_Mode="Choose display option"
-Explain_Display_Mode="This policy sets the Google Desktop display option: Sidebar, Deskbar, Floating Deskbar or none.\n\nNote that on 64-bit systems, a setting of Deskbar will be interpreted as Floating Deskbar.\n\nIf this policy is disabled or not configured, the user can choose a display option."
-Sidebar="Sidebar"
-Deskbar="Deskbar"
-FloatingDeskbar="Floating Deskbar"
-None="None"
-
-;------------------------------------------------------------------------------
-; Enterprise
-;------------------------------------------------------------------------------
-Cat_Enterprise="Enterprise Integration"
-Explain_Enterprise="Controls features specific to Enterprise installations of Google Desktop"
-
-Pol_Autoupdate="Block Auto-update"
-Explain_Autoupdate="Enabling this policy prevents Google Desktop from automatically checking for and installing updates from google.com.\n\nIf you enable this policy, you must distribute updates to Google Desktop using Group Policy, SMS, or a similar enterprise software distribution mechanism. You should check http://desktop.google.com/enterprise/ for updates.\n\nIf this policy is disabled or not configured, Google Desktop will periodically check for updates from desktop.google.com."
-
-Pol_AutoupdateAsSystem="Use system proxy settings when auto-updating"
-Explain_AutoupdateAsSystem="Enabling this policy makes Google Desktop use the machine-wide proxy settings (as specified using e.g. proxycfg.exe) when performing autoupdates (if enabled).\n\nIf this policy is disabled or not configured, Google Desktop will use the logged-on user's Internet Explorer proxy settings when checking for auto-updates (if enabled)."
-
-Pol_EnterpriseTab="Enterprise search tab"
-Explain_EnterpriseTab="This policy allows you to add a search tab for your Google Search Appliance to Google Desktop and google.com web pages.\n\nYou must provide the name of the tab, such as "Intranet", as well as URLs for the search homepage and for retrieving search results. Use [DISP_QUERY] in place of the query term for the search results URL.\n\nSee the administrator's guide for more details."
-EnterpriseTabText="Tab name"
-EnterpriseTabHomepage="Search homepage URL"
-EnterpriseTabHomepageQuery="Check if search homepage supports '&&q=<query>'"
-EnterpriseTabResults="Search results URL"
-EnterpriseTabResultsQuery="Check if search results page supports '&&q=<query>'"
-
-Pol_GSAHosts="Google Search Appliances"
-Explain_GSAHosts="This policy allows you to list any Google Search Appliances in your intranet. When properly configured, Google Desktop will insert Google Desktop results into the results of queries on the Google Search Appliance"
-
-Pol_PolicyUnawareClientProhibitedFlag="Prohibit Policy-Unaware versions"
-Explain_PolicyUnawareClientProhibitedFlag="Prohibits installation and execution of versions of Google Desktop that are unaware of group policy.\n\nEnabling this policy will prevent users from installing or running version 1.0 of Google Desktop.\n\nThis policy has no effect when disabled or not configured."
-
-Pol_MinimumAllowedVersion="Minimum allowed version"
-Explain_MinimumAllowedVersion="This policy allows you to prevent installation and/or execution of older versions of Google Desktop by specifying the minimum version you wish to allow. When enabling this policy, you should also enable the "Prohibit Policy-Unaware versions" policy to block versions of Google Desktop that did not support group policy.\n\nThis policy has no effect when disabled or not configured."
-
-Pol_MaximumAllowedVersion="Maximum allowed version"
-Explain_MaximumAllowedVersion="This policy allows you to prevent installation and/or execution of newer versions of Google Desktop by specifying the maximum version you wish to allow.\n\nThis policy has no effect when disabled or not configured."
-
-Pol_Disallow_Gadgets="Disallow gadgets and indexing plug-ins"
-Explain_Disallow_Gadgets="This policy prevents the use of all Google Desktop gadgets and indexing plug-ins. The policy applies to gadgets that are included in the Google Desktop installation package (built-in gadgets), built-in indexing plug-ins (currently only the Lotus Notes plug-in), and to gadgets or indexing plug-ins that a user might want to add later (non-built-in gadgets and indexing plug-ins).\n\nYou can prohibit use of all non-built-in gadgets and indexing plug-ins, but allow use of built-in gadgets and indexing plug-ins. To do so, enable this policy and then select the option "Disallow only non-built-in gadgets and indexing plug-ins.\n\nYou can supersede this policy to allow specified built-in and non-built-in gadgets and indexing plug-ins. To do so, enable this policy and then specify the gadgets and/or indexing plug-ins you want to allow under "Gadget and Plug-in Whitelist.""
-Disallow_Only_Non_Builtin_Gadgets="Disallow only non-built-in gadgets and indexing plug-ins"
-
-Pol_Gadget_Whitelist="Gadget and plug-in whitelist"
-Explain_Gadget_Whitelist="This policy specifies a list of Google Desktop gadgets and indexing plug-ins that you want to allow, as exceptions to the "Disallow gadgets and indexing plug-ins" policy. This policy is valid only when the "Disallow gadgets and indexing plug-ins" policy is enabled.\n\nFor each gadget or indexing plug-in you wish to allow, add the CLSID or PROGID of the gadget or indexing plug-in (see the administrator's guide for more details).\n\nThis policy has no effect when disabled or not configured."
-
-Pol_Gadget_Install_Confirmation_Whitelist="Allow silent installation of gadgets"
-Explain_Gadget_Install_Confirmation_Whitelist="Enabling this policy lets you specify a list of Google Desktop gadgets or indexing plug-ins that can be installed without confirmation from the user.\n\nAdd a gadget or indexing plug-in by placing its class ID (CLSID) or program identifier (PROGID) in the list, surrounded with curly braces ({ }).\n\nThis policy has no effect when disabled or not configured."
-
-Pol_Alternate_User_Data_Dir="Alternate user data directory"
-Explain_Alternate_User_Data_Dir="This policy allows you to specify a directory to be used to store user data for Google Desktop (such as index data and cached documents).\n\nYou may use [USER_NAME] or [DOMAIN_NAME] in the path to specify the current user's name or domain. If [USER_NAME] is not specified, the user name will be appended at the end of the path.\n\nThis policy has no effect when disabled or not configured."
-
-Pol_MaxAllowedOutlookConnections="Maximum allowed Outlook connections"
-Explain_MaxAllowedOutlookConnections="This policy specifies the maximum number of open connections that Google Desktop maintains with the Exchange server. Google Desktop opens a connection for each email folder that it indexes. If insufficient connections are allowed, Google Desktop cannot index all the user email folders.\n\nThe default value is 400. Because users rarely have as many as 400 email folders, Google Desktop rarely reaches the limit.\n\nIf you set this policy's value above 400, you must also configure the number of open connections between Outlook and the Exchange server. By default, approximately 400 connections are allowed. If Google Desktop uses too many of these connections, Outlook might be unable to access email.\n\nThis policy has no effect when disabled or not configured."
-
-Pol_DisallowSsdService="Disallow sharing and receiving of web history and documents across computers"
-Explain_DisallowSsdService="Enabling this policy will prevent Google Desktop from sharing the user's web history and document contents across the user's different Google Desktop installations, and will also prevent it from receiving such shared items from the user's other machines. To allow reception but disallow sharing, use DisallowSsdOutbound.\nThis policy has no effect when disabled or not configured."
-
-Pol_DisallowSsdOutbound="Disallow sharing of web history and documents to user's other computers."
-Explain_DisallowSsdOutbound="Enabling this policy will prevent Google Desktop from sending the user's web history and document contents from this machine to the user's other machines. It does not prevent reception of items from the user's other machines; to disallow both, use DisallowSsdService.\nThis policy has no effect when disabled or not configured."
-
-Pol_Disallow_Store_Gadget_Service="Disallow storage of gadget content and settings."
-Explain_Disallow_Store_Gadget_Service="Enabling this policy will prevent users from storing their gadget content and settings with Google. Users will be unable to access their gadget content and settings from other computers and all content and settings will be lost if Google Desktop is uninstalled."
-
-Pol_MaxExchangeIndexingRate="Maximum allowed Exchange indexing rate"
-Explain_MaxExchangeIndexingRate="This policy allows you to specify the maximum number of emails that are indexed per minute. \n\nThis policy has no effect when disabled or not configured."
-
-Pol_EnableSafeweb="Enable or disable safe browsing"
-Explain_Safeweb="Google Desktop safe browsing informs the user whenever they visit any site which is a suspected forgery site or may harm their computer. Enabling this policy turns on safe browsing; disabling the policy turns it off. \n\nIf this policy is not configured, the user can select whether to turn on safe browsing." \ No newline at end of file
diff --git a/tools/grit/grit/testdata/README.txt b/tools/grit/grit/testdata/README.txt
deleted file mode 100644
index 60f3e58..0000000
--- a/tools/grit/grit/testdata/README.txt
+++ /dev/null
@@ -1,87 +0,0 @@
-Google Desktop for Enterprise
-Copyright (C) 2007 Google Inc.
-All Rights Reserved
-
----------
-Contents
----------
-This distribution contains the following files:
-
-GoogleDesktopSetup.msi - Installation and setup program
-GoogleDesktop.adm - Group Policy administrative template file
-AdminGuide.pdf - Google Desktop for Enterprise administrative guide
-
-
---------------
-Documentation
---------------
-Full documentation and installation instructions are in the
-administrative guide, and also online at
-http://desktop.google.com/enterprise/adminguide.html.
-
-
-------------------------
-IBM Lotus Notes Plug-In
-------------------------
-The Lotus Notes plug-in is included in the release of Google
-Desktop for Enterprise. The IBM Lotus Notes Plug-in for Google
-Desktop indexes mail, calendar, task, contact and journal
-documents from Notes. Discussion documents including those from
-the discussion and team room templates can also be indexed by
-selecting an option from the preferences. Once indexed, this data
-will be returned in Google Desktop searches. The corresponding
-document can be opened in Lotus Notes from the Google Desktop
-results page.
-
-Install: The plug-in will install automatically during the Google
-Desktop setup process if Lotus Notes is already installed. Lotus
-Notes must not be running in order for the install to occur. The
-Class ID for this plug-in is {8F42BDFB-33E8-427B-AFDC-A04E046D3F07}.
-
-Preferences: Preferences and selection of databases to index are
-set in the 'Google Desktop for Notes' dialog reached through the
-'Actions' menu.
-
-Reindexing: Selecting 'Reindex all databases' will index all the
-documents in each database again.
-
-
-Notes Plug-in Known Issues
----------------------------
-
-If the 'Google Desktop for Notes' item is not available from the
-Lotus Notes Actions menu, then installation was not successful.
-Installation consists of writing one file, notesgdsplugin.dll, to
-the Notes application directory and a setting to the notes.ini
-configuration file. The most likely cause of an unsuccessful
-installation is that the installer was not able to locate the
-notes.ini file. Installation will complete if the user closes Notes
-and manually adds the following setting to this file on a new line:
-AddinMenus=notesgdsplugin.dll
-
-If the notesgdsplugin.dll file is not in the application directory
-(e.g., C:\Program Files\Lotus\Notes) after Google Desktop
-installation, it is likely that Notes was not installed correctly.
-
-Only local databases can be indexed. If they can be determined,
-the user's local mail file and address book will be included in the
-list automatically. Mail archives and other databases must be
-added with the 'Add' button.
-
-Some users may experience performance issues during the initial
-indexing of a database. The 'Perform the initial index of a
-database only when I'm idle' option will limit the indexing process
-to times when the user is not using the machine. If this does not
-alleviate the problem or the user would like to continually index
-but just do so more slowly or quickly, the GoogleWaitTime notes.ini
-value can be set. Increasing the GoogleWaitTime value will slow
-down the indexing process, and lowering the value will speed it up.
-A value of zero causes the fastest possible indexing. Removing the
-ini parameter altogether returns it to the default (20).
-
-Crashes have been known to occur with certain types of history
-bookmarks. If the Notes client seems to crash randomly, try
-disabling the 'Index note history' option. If it crashes before,
-you can get to the preferences, add the following line to your
-notes.ini file:
-GDSNoIndexHistory=1
diff --git a/tools/grit/grit/testdata/about.html b/tools/grit/grit/testdata/about.html
deleted file mode 100644
index 8e5fad7..0000000
--- a/tools/grit/grit/testdata/about.html
+++ /dev/null
@@ -1,45 +0,0 @@
-[HEADER]
-<table cellspacing=0 cellPadding=0 width="100%" border=0><tr bgcolor=#3399cc><td align=middle height=1><img height=1 width=1></td></tr></table>
-<table cellspacing=0 cellPadding=1 width="100%" bgcolor=#e8f4f7 border=0><tr><td height=20><font size=+1 color=#000000>&nbsp;<b>[TITLE]</b></font></td></tr></table>
-<br><center><span style="line-height:16pt"><font color=#335cec><B>Google Desktop Search: Search your own computer.</B></font></span></center><br>
-
-<table cellspacing=1 cellpadding=0 width=300 align=center border=0>
-<tr><td nowrap><font size=-1><img style="vertical-align:middle" height=16 src="outlook.gif" width=16>&nbsp;&nbsp;Outlook Email</font></td>
-<td nowrap>&nbsp;</td>
-<td nowrap><font size=-1><img style="vertical-align:middle" height=16 src="netscape.gif" width=16>&nbsp;&nbsp;Netscape Mail / Thunderbird</font></td></tr>
-
-<tr><td nowrap><font size=-1><img style="vertical-align:middle" height=16 src="oe.gif" width=16>&nbsp;&nbsp;Outlook Express</font></td>
-<td nowrap>&nbsp;</td>
-<td nowrap><font size=-1><img style="vertical-align:middle" height=16 src="ff.gif" width=16>&nbsp;&nbsp;Netscape / Firefox / Mozilla</font></td></tr>
-
-<tr><td nowrap><font size=-1><img style="vertical-align:middle" height=16 src="doc.gif" width=16>&nbsp;&nbsp;Word</font></td>
-<td nowrap>&nbsp;</td>
-<td nowrap><font size=-1><img style="vertical-align:middle" height=16 src="pdf.gif" width=16>&nbsp;&nbsp;PDF</font></td></tr>
-
-<tr><td nowrap><font size=-1><img style="vertical-align:middle" height=16 src="xls.gif" width=16>&nbsp;&nbsp;Excel</font></td>
-<td nowrap>&nbsp;</td>
-<td nowrap><font size=-1><img style="vertical-align:middle" height=16 src="mus.gif" width=16>&nbsp;&nbsp;Music</font></td></tr>
-
-<tr><td nowrap><font size=-1><img style="vertical-align:middle" height=16 src="ppt.gif" width=16>&nbsp;&nbsp;PowerPoint</font></td>
-<td nowrap>&nbsp;</td>
-<td nowrap><font size=-1><img style="vertical-align:middle" height=16 src="jpg.gif" width=16>&nbsp;&nbsp;Images</font></td></tr>
-
-<tr><td nowrap><font size=-1><img style="vertical-align:middle" height=16 src="ie.gif" width=16>&nbsp;&nbsp;Internet Explorer</font></td>
-<td nowrap>&nbsp;</td>
-<td nowrap><font size=-1><img style="vertical-align:middle" height=16 src="mov.gif" width=16>&nbsp;&nbsp;Video</font></td></tr>
-
-<tr><td nowrap><font size=-1><img style="vertical-align:middle" height=16 src="aim.gif" width=16>&nbsp;&nbsp;AOL Instant Messenger</font></td>
-<td nowrap>&nbsp;</td>
-<td nowrap><font size=-1><img style="vertical-align:middle" height=16 src="other.gif" width=16>&nbsp;&nbsp;Even more with <a href="http://desktop.google.com/plugins.html">these plug-ins</A></font></td></tr>
-
-<tr><td nowrap><font size=-1><img style="vertical-align:middle" height=16 src="txt.gif" width=16>&nbsp;&nbsp;Text and others</font></td></tr>
-</table>
-<center>
-<p><table cellpadding=1>
-<tr><td><a href="http://desktop.google.com/gettingstarted.html?hl=[LANG_CODE]"><B>Getting Started</B></A> - Learn more about using Google Desktop Search</td></tr>
-<tr><td><a href="http://desktop.google.com/help.html?hl=[LANG_CODE]"><B>Online Help</B></A> - Up-to-date answers to your questions</td></tr>
-<tr><td><a href="[$~PRIVACY~$]"><B>Privacy</B></A> - A few words about privacy and Google Desktop Search</td></tr>
-<tr><td><a href="http://desktop.google.com/uninstall.html?hl=[LANG_CODE]"><B>Uninstall</B></A> - How to uninstall Google Desktop Search</td></tr>
-<tr><td><a href="http://desktop.google.com/feedback.html?hl=[LANG_CODE]"><B>Submit Feedback</B></A> - Send us your comments and ideas</td></tr>
-</table><br><font size=-2>Google Desktop Search [$~BUILDNUMBER~$]</font><br><br>
-[FOOTER] \ No newline at end of file
diff --git a/tools/grit/grit/testdata/bad_browser.html b/tools/grit/grit/testdata/bad_browser.html
deleted file mode 100644
index e8cf346..0000000
--- a/tools/grit/grit/testdata/bad_browser.html
+++ /dev/null
@@ -1,16 +0,0 @@
-<p><b>We're sorry, but we don't seem to be compatible.</b></p>
-<p><font size="-1">Our software suggests that you're using a browser incompatible with Google Desktop Search.
- Google Desktop Search currently supports the following:</font></p>
-<ul><font size="-1">
- <li>Microsoft IE 5 and newer (<a href="http://www.microsoft.com/windows/ie/downloads/default.asp">Download</a>)</li>
- <li>Mozilla (<a href="http://www.mozilla.org/products/mozilla1.x/">Download</a>)</li>
- <li>Mozilla Firefox (<a href="http://www.mozilla.org/products/firefox/">Download</a>)</li>
- <li>Netscape 7 and newer (<a href="http://channels.netscape.com/ns/browsers/download.jsp">Download</a>)</li>
-</font></ul>
-
-<p><font size="-1">You may <a href="[REDIR]">click here</a> to use your
- unsupported browser, though you likely will encounter some areas that don't
- work as expected. You need to have Javascript enabled, regardless of the
- browser you use.</font>
-<p><font size="-1">We hope to expand this list in the near future and announce new
- browsers as they become available.
diff --git a/tools/grit/grit/testdata/browser.html b/tools/grit/grit/testdata/browser.html
deleted file mode 100644
index 45d364d..0000000
--- a/tools/grit/grit/testdata/browser.html
+++ /dev/null
@@ -1,42 +0,0 @@
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
-<html><head><title>[$~TITLE~$]</title>
-<style>
-BODY { MARGIN-LEFT: 1em; MARGIN-RIGHT: 1em }
-BODY, TD, DIV, A { FONT-FAMILY: arial,sans-serif}
-DIV, TD { COLOR: #000}
-A:link { COLOR: #00c}
-A:visited { COLOR: #551a8b}
-A:active { COLOR: #f00 }
-</style>
-</head>
-
-<body bgcolor="#ffffff" text="#000000" link="#0000cc" vlink="#800080" alink="#ff0000" topmargin=2>
-
-<table cellspacing=2 cellpadding=0 width="99%" border=0>
-<tr>
- <td width="1%" rowspan=2>[$~IMAGE~$]
- <td>&nbsp;</td>
- <td rowspan=2>
- <table cellspacing=0 cellpadding=0 width="100%" border=0>
- <tr>
- <td bgcolor=#3399cc><img height=1 width=1></td>
- </tr>
- </table>
- <table cellspacing=0 cellpadding=0 width="100%" border=0 bgcolor=#efefef>
- <tr>
- <td nowrap bgcolor=#E8F4F7><font face=arial,sans-serif color=#000000 size=+1><b>&nbsp;[$~CHROME_TITLE~$]</b></font></td>
- </tr>
- </table>
- </td>
-</tr>
-</table>
-
-<table cellpadding=3 width="94%" align="center" cellspacing=0 border=0>
-<tr valign="middle">
- <td valign="top">
- [$~BODY~$]
- </td>
- </tr>
-</table>
-[$~FOOTER~$]
-</body></html> \ No newline at end of file
diff --git a/tools/grit/grit/testdata/cache_prefix.html b/tools/grit/grit/testdata/cache_prefix.html
deleted file mode 100644
index b1f91dd..0000000
--- a/tools/grit/grit/testdata/cache_prefix.html
+++ /dev/null
@@ -1,24 +0,0 @@
-<head>
-<meta http-equiv="cache-control" content="no-cache">
-<meta http-equiv="pragma" content="no-cache">
-<meta http-equiv="expires" content="-1">
-</head>
-<body onload="[ONLOAD]">
-<table width="100%" border=1><tr><td>
-<table cellspacing=0 cellpadding=10 width="100%" bgcolor=#ffffff border=1 color="#ffffff">
-<tr><td><font face="arial,sans-serif" color=black size=-1>This is one version of <a href="[$~URL~$]">
-<font color="blue">[URL-DISP]</font></a> from your personal <a href="http://desktop.google.com/webcache.html"><font color=blue>cache</font></a>.<br>
-The page may have changed since that time. Click here for the <a href="[$~URL~$]"><font color="blue">current page</font></a>.<br>
-Since this page is stored on your computer, publicly linking to this page will not work.[$~EXTRA~$]<br><br>
-<font size="-2"><i>Google may not be affiliated with the authors of this page nor responsible for its content. This page may be protected by copyright.</i></font>
-</td>
-</tr></table></td></tr></table>
-<style>
-.hl { color:black; background-color:#ffff88}
-</style>
-<script>
-[$~HIGHLIGHT_SCRIPT~$]
-window.onerror=new Function(';');
-</script>
-<hr id=gg_1>
-</body> \ No newline at end of file
diff --git a/tools/grit/grit/testdata/cache_prefix_file.html b/tools/grit/grit/testdata/cache_prefix_file.html
deleted file mode 100644
index f3eb8e0..0000000
--- a/tools/grit/grit/testdata/cache_prefix_file.html
+++ /dev/null
@@ -1,25 +0,0 @@
-<head>
-<meta http-equiv="cache-control" content="no-cache">
-<meta http-equiv="pragma" content="no-cache">
-<meta http-equiv="expires" content="-1"></head>
-<body onload="[ONLOAD]">
-<table width="100%" border=1>
-<tr><td>
-<table cellspacing=0 cellpadding=10 width="100%" bgcolor=#ffffff border=1 color="#ffffff">
-<tr><td><font face=arial,sans-serif color=black size=-1>This is one version of <a href="[$~URL~$]"><font color=blue>[URL-DISP]</font></a>
-from your personal <a href="http://desktop.google.com/filecache.html"><font color=blue>cache</font></a>.<br>
-The file may have changed since that time. Click here for the <a href="[$~URL~$]"><font color=blue>current file</font></a>.<br>
-Since this file is stored on your computer, publicly linking to it will not work.[$~EXTRA~$]<br><br>
-<font size="-2"><i>Google may not be affiliated with the authors of this page nor responsible for its content. This page may be protected by copyright.</i></font>
-</td></tr>
-</table>
-</td></tr></table>
-<style>
-.hl { color:black; background-color:#ffff88}
-</style>
-<script>
-[$~HIGHLIGHT_SCRIPT~$]
-window.onerror=new Function(';');
-</script>
-<hr id=gg_1>
-</body> \ No newline at end of file
diff --git a/tools/grit/grit/testdata/chat_result.html b/tools/grit/grit/testdata/chat_result.html
deleted file mode 100644
index 318078b..0000000
--- a/tools/grit/grit/testdata/chat_result.html
+++ /dev/null
@@ -1,24 +0,0 @@
-[HEADER]
-[CHROME]
-<table border=0 cellpadding=2 cellspacing=2>
-<tr><td>[$~STARTCHAT~$]</td></tr>
-</table>
-<blockquote id=gg_1>
-<table bgcolor=#f0f8ff width=80% cellpadding=5><tr><td>
-<img style="vertical-align:middle;" height=16 src="16x16_chat.gif" width=16> &nbsp; <b>[$~TITLE~$]</b>
-<font size=-1><br><br>Participants: [USERNAME], [BUDDYNAME]<br>
-Date: [TIME]</font></td></tr></table>
-<br id=contents>
-<label>[CONTENTS]</label>
-</blockquote>
-<table border=0 cellpadding=2 cellspacing=2>
-<tr><td>[$~STARTCHAT~$]</td></tr>
-</table>
-<style>
-.hl { color:black; background-color:#ffff88}
-</style>
-<script>
-[$~HIGHLIGHT_SCRIPT~$]
-[ONLOAD]
-</script>
-[FOOTER]
diff --git a/tools/grit/grit/testdata/chrome/app/generated_resources.grd b/tools/grit/grit/testdata/chrome/app/generated_resources.grd
deleted file mode 100644
index c2efb77..0000000
--- a/tools/grit/grit/testdata/chrome/app/generated_resources.grd
+++ /dev/null
@@ -1,199 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-
-<!--
-This file contains definitions of resources that will be translated for each
-locale. The variables is_win, is_macosx, is_linux, and is_posix are available
-for making strings OS specific. Other platform defines such as use_titlecase
-are declared in build/common.gypi.
--->
-
-<grit base_dir="." latest_public_release="0" current_release="1"
- source_lang_id="en" enc_check="möl">
- <outputs>
- <output filename="grit/generated_resources.h" type="rc_header">
- <emit emit_type='prepend'></emit>
- </output>
- <output filename="generated_resources_am.pak" type="data_package" lang="am" />
- <output filename="generated_resources_ar.pak" type="data_package" lang="ar" />
- <if expr="pp_ifdef('use_third_party_translations')">
- <output filename="generated_resources_ast.pak" type="data_package" lang="ast" />
- </if>
- <output filename="generated_resources_bg.pak" type="data_package" lang="bg" />
- <output filename="generated_resources_bn.pak" type="data_package" lang="bn" />
- <if expr="pp_ifdef('use_third_party_translations')">
- <output filename="generated_resources_bs.pak" type="data_package" lang="bs" />
- </if>
- <output filename="generated_resources_ca.pak" type="data_package" lang="ca" />
- <if expr="pp_ifdef('use_third_party_translations')">
- <output filename="generated_resources_ca@valencia.pak" type="data_package" lang="ca@valencia" />
- </if>
- <output filename="generated_resources_cs.pak" type="data_package" lang="cs" />
- <output filename="generated_resources_da.pak" type="data_package" lang="da" />
- <output filename="generated_resources_de.pak" type="data_package" lang="de" />
- <output filename="generated_resources_el.pak" type="data_package" lang="el" />
- <if expr="pp_ifdef('use_third_party_translations')">
- <output filename="generated_resources_en-AU.pak" type="data_package" lang="en-AU" />
- </if>
- <output filename="generated_resources_en-GB.pak" type="data_package" lang="en-GB" />
- <output filename="generated_resources_en-US.pak" type="data_package" lang="en" />
- <if expr="pp_ifdef('use_third_party_translations')">
- <output filename="generated_resources_eo.pak" type="data_package" lang="eo" />
- </if>
- <output filename="generated_resources_es.pak" type="data_package" lang="es" />
- <output filename="generated_resources_es-419.pak" type="data_package" lang="es-419" />
- <output filename="generated_resources_et.pak" type="data_package" lang="et" />
- <if expr="pp_ifdef('use_third_party_translations')">
- <output filename="generated_resources_eu.pak" type="data_package" lang="eu" />
- </if>
- <output filename="generated_resources_fa.pak" type="data_package" lang="fa" />
- <output filename="generated_resources_fake-bidi.pak" type="data_package" lang="fake-bidi" />
- <output filename="generated_resources_fi.pak" type="data_package" lang="fi" />
- <output filename="generated_resources_fil.pak" type="data_package" lang="fil" />
- <output filename="generated_resources_fr.pak" type="data_package" lang="fr" />
- <if expr="pp_ifdef('use_third_party_translations')">
- <output filename="generated_resources_gl.pak" type="data_package" lang="gl" />
- </if>
- <output filename="generated_resources_gu.pak" type="data_package" lang="gu" />
- <output filename="generated_resources_he.pak" type="data_package" lang="he" />
- <output filename="generated_resources_hi.pak" type="data_package" lang="hi" />
- <output filename="generated_resources_hr.pak" type="data_package" lang="hr" />
- <output filename="generated_resources_hu.pak" type="data_package" lang="hu" />
- <if expr="pp_ifdef('use_third_party_translations')">
- <output filename="generated_resources_hy.pak" type="data_package" lang="hy" />
- <output filename="generated_resources_ia.pak" type="data_package" lang="ia" />
- </if>
- <output filename="generated_resources_id.pak" type="data_package" lang="id" />
- <output filename="generated_resources_it.pak" type="data_package" lang="it" />
- <output filename="generated_resources_ja.pak" type="data_package" lang="ja" />
- <if expr="pp_ifdef('use_third_party_translations')">
- <output filename="generated_resources_ka.pak" type="data_package" lang="ka" />
- </if>
- <output filename="generated_resources_kn.pak" type="data_package" lang="kn" />
- <output filename="generated_resources_ko.pak" type="data_package" lang="ko" />
- <if expr="pp_ifdef('use_third_party_translations')">
- <output filename="generated_resources_ku.pak" type="data_package" lang="ku" />
- <output filename="generated_resources_kw.pak" type="data_package" lang="kw" />
- </if>
- <output filename="generated_resources_lt.pak" type="data_package" lang="lt" />
- <output filename="generated_resources_lv.pak" type="data_package" lang="lv" />
- <output filename="generated_resources_ml.pak" type="data_package" lang="ml" />
- <output filename="generated_resources_mr.pak" type="data_package" lang="mr" />
- <if expr="pp_ifdef('use_third_party_translations')">
- <output filename="generated_resources_ms.pak" type="data_package" lang="ms" />
- </if>
- <output filename="generated_resources_nl.pak" type="data_package" lang="nl" />
- <!-- The translation console uses 'no' for Norwegian Bokmål. It should
- be 'nb'. -->
- <output filename="generated_resources_nb.pak" type="data_package" lang="no" />
- <output filename="generated_resources_pl.pak" type="data_package" lang="pl" />
- <output filename="generated_resources_pt-BR.pak" type="data_package" lang="pt-BR" />
- <output filename="generated_resources_pt-PT.pak" type="data_package" lang="pt-PT" />
- <output filename="generated_resources_ro.pak" type="data_package" lang="ro" />
- <output filename="generated_resources_ru.pak" type="data_package" lang="ru" />
- <output filename="generated_resources_sk.pak" type="data_package" lang="sk" />
- <output filename="generated_resources_sl.pak" type="data_package" lang="sl" />
- <output filename="generated_resources_sr.pak" type="data_package" lang="sr" />
- <output filename="generated_resources_sv.pak" type="data_package" lang="sv" />
- <output filename="generated_resources_sw.pak" type="data_package" lang="sw" />
- <output filename="generated_resources_ta.pak" type="data_package" lang="ta" />
- <output filename="generated_resources_te.pak" type="data_package" lang="te" />
- <output filename="generated_resources_th.pak" type="data_package" lang="th" />
- <output filename="generated_resources_tr.pak" type="data_package" lang="tr" />
- <if expr="pp_ifdef('use_third_party_translations')">
- <output filename="generated_resources_ug.pak" type="data_package" lang="ug" />
- </if>
- <output filename="generated_resources_uk.pak" type="data_package" lang="uk" />
- <output filename="generated_resources_vi.pak" type="data_package" lang="vi" />
- <output filename="generated_resources_zh-CN.pak" type="data_package" lang="zh-CN" />
- <output filename="generated_resources_zh-TW.pak" type="data_package" lang="zh-TW" />
- </outputs>
- <translations>
- <file path="resources/generated_resources_am.xtb" lang="am" />
- <file path="resources/generated_resources_ar.xtb" lang="ar" />
- <file path="../../third_party/launchpad_translations/generated_resources_ast.xtb" lang="ast" />
- <file path="resources/generated_resources_bg.xtb" lang="bg" />
- <file path="resources/generated_resources_bn.xtb" lang="bn" />
- <file path="../../third_party/launchpad_translations/generated_resources_bs.xtb" lang="bs" />
- <file path="resources/generated_resources_ca.xtb" lang="ca" />
- <file path="../../third_party/launchpad_translations/generated_resources_ca-valencia.xtb" lang="ca@valencia" />
- <file path="resources/generated_resources_cs.xtb" lang="cs" />
- <file path="resources/generated_resources_da.xtb" lang="da" />
- <file path="resources/generated_resources_de.xtb" lang="de" />
- <file path="resources/generated_resources_el.xtb" lang="el" />
- <file path="../../third_party/launchpad_translations/generated_resources_en-AU.xtb" lang="en-AU" />
- <file path="resources/generated_resources_en-GB.xtb" lang="en-GB" />
- <file path="../../third_party/launchpad_translations/generated_resources_eo.xtb" lang="eo" />
- <file path="resources/generated_resources_es.xtb" lang="es" />
- <file path="resources/generated_resources_es-419.xtb" lang="es-419" />
- <file path="resources/generated_resources_et.xtb" lang="et" />
- <file path="../../third_party/launchpad_translations/generated_resources_eu.xtb" lang="eu" />
- <file path="resources/generated_resources_fa.xtb" lang="fa" />
- <file path="resources/generated_resources_fi.xtb" lang="fi" />
- <file path="resources/generated_resources_fil.xtb" lang="fil" />
- <file path="resources/generated_resources_fr.xtb" lang="fr" />
- <file path="../../third_party/launchpad_translations/generated_resources_gl.xtb" lang="gl" />
- <file path="resources/generated_resources_gu.xtb" lang="gu" />
- <file path="resources/generated_resources_hi.xtb" lang="hi" />
- <file path="resources/generated_resources_hr.xtb" lang="hr" />
- <file path="resources/generated_resources_hu.xtb" lang="hu" />
- <file path="../../third_party/launchpad_translations/generated_resources_hy.xtb" lang="hy" />
- <file path="../../third_party/launchpad_translations/generated_resources_ia.xtb" lang="ia" />
- <file path="resources/generated_resources_id.xtb" lang="id" />
- <file path="resources/generated_resources_it.xtb" lang="it" />
- <!-- The translation console uses 'iw' for Hebrew, but we use 'he'. -->
- <file path="resources/generated_resources_iw.xtb" lang="he" />
- <file path="resources/generated_resources_ja.xtb" lang="ja" />
- <file path="../../third_party/launchpad_translations/generated_resources_ka.xtb" lang="ka" />
- <file path="resources/generated_resources_kn.xtb" lang="kn" />
- <file path="resources/generated_resources_ko.xtb" lang="ko" />
- <file path="../../third_party/launchpad_translations/generated_resources_ku.xtb" lang="ku" />
- <file path="../../third_party/launchpad_translations/generated_resources_kw.xtb" lang="kw" />
- <file path="resources/generated_resources_lt.xtb" lang="lt" />
- <file path="resources/generated_resources_lv.xtb" lang="lv" />
- <file path="resources/generated_resources_ml.xtb" lang="ml" />
- <file path="resources/generated_resources_mr.xtb" lang="mr" />
- <file path="../../third_party/launchpad_translations/generated_resources_ms.xtb" lang="ms" />
- <file path="resources/generated_resources_nl.xtb" lang="nl" />
- <file path="resources/generated_resources_no.xtb" lang="no" />
- <file path="resources/generated_resources_pl.xtb" lang="pl" />
- <file path="resources/generated_resources_pt-BR.xtb" lang="pt-BR" />
- <file path="resources/generated_resources_pt-PT.xtb" lang="pt-PT" />
- <file path="resources/generated_resources_ro.xtb" lang="ro" />
- <file path="resources/generated_resources_ru.xtb" lang="ru" />
- <file path="resources/generated_resources_sk.xtb" lang="sk" />
- <file path="resources/generated_resources_sl.xtb" lang="sl" />
- <file path="resources/generated_resources_sr.xtb" lang="sr" />
- <file path="resources/generated_resources_sv.xtb" lang="sv" />
- <file path="resources/generated_resources_sw.xtb" lang="sw" />
- <file path="resources/generated_resources_ta.xtb" lang="ta" />
- <file path="resources/generated_resources_te.xtb" lang="te" />
- <file path="resources/generated_resources_th.xtb" lang="th" />
- <file path="resources/generated_resources_tr.xtb" lang="tr" />
- <file path="../../third_party/launchpad_translations/generated_resources_ug.xtb" lang="ug" />
- <file path="resources/generated_resources_uk.xtb" lang="uk" />
- <file path="resources/generated_resources_vi.xtb" lang="vi" />
- <file path="resources/generated_resources_zh-CN.xtb" lang="zh-CN" />
- <file path="resources/generated_resources_zh-TW.xtb" lang="zh-TW" />
- </translations>
- <release seq="1" allow_pseudo="false">
- <messages fallback_to_english="true">
- <!-- TODO add all of your "string table" messages here. Remember to
- change nontranslateable parts of the messages into placeholders (using the
- <ph> element). You can also use the 'grit add' tool to help you identify
- nontranslateable parts and create placeholders for them. -->
- <message name="IDS_BACKGROUND_APP_INSTALLED_BALLOON_TITLE" desc="The title of the balloon that is displayed when a background app is installed">
- New background app installed
- </message>
- <message name="IDS_BACKGROUND_APP_INSTALLED_BALLOON_BODY" desc="The contents of the balloon that is displayed when a background app is installed">
- <ph name="APP_NAME">$1<ex>Background App</ex></ph> will launch at system startup and continue to run in the background even once you've closed all other <ph name="PRODUCT_NAME">$2<ex>Google Chrome</ex></ph> windows.
- </message>
- </messages>
- <structures fallback_to_english="true">
- <!-- Make sure these stay in sync with the structures in generated_resources.grd. -->
- <structure name="IDD_CHROME_FRAME_FIND_DIALOG" file="cf_resources.rc" type="dialog" >
- </structure>
- <structure name="IDD_CHROME_FRAME_READY_PROMPT" file="cf_resources.rc" type="dialog" >
- </structure>
- </structures>
- </release>
-</grit>
diff --git a/tools/grit/grit/testdata/del_footer.html b/tools/grit/grit/testdata/del_footer.html
deleted file mode 100644
index 4e19950..0000000
--- a/tools/grit/grit/testdata/del_footer.html
+++ /dev/null
@@ -1,8 +0,0 @@
-<table cellspacing=0 cellpadding=2 width="100%" border=0>
-<tr bgcolor=#EFEFEF><td><font size=-1>&nbsp;<b>Remove</b> checked results and <b>return to search</b>.</font></td>
-<td align=right><font size=-1><a onClick='checkall(1)' href="#">Check all</a> - <a onClick='checkall(0)' href="#">Uncheck all</a>&nbsp;&nbsp;</font></td>
-<td align=right width=1% nowrap><font size=-1>
-<input onclick=deleting() type=submit value="Remove checked results" name=submit2>
-</font></td></tr></table>
-<center><br><font size=-1>[$~BOTTOMLINE~$] - &copy;2005 Google </font></center>
-</body></html>
diff --git a/tools/grit/grit/testdata/del_header.html b/tools/grit/grit/testdata/del_header.html
deleted file mode 100644
index 72bc675..0000000
--- a/tools/grit/grit/testdata/del_header.html
+++ /dev/null
@@ -1,60 +0,0 @@
-<body bgcolor="#ffffff" topmargin="2" marginheight="2">
-<table cellSpacing="2" cellPadding="0" width="100%" border="0">
-<form action='[$~DELETE~$]' method="post" name="delform">
-<input name="redir" type="hidden" value="[REDIR]">
-<script>
-<!--
-function deleting() {
-f=document.getElementsByName("del");
-var num = 0;
-if (f.length)
- for(i=0;i<f.length; i++)
- if(f[i].checked) num++;
- if (num == 1) alert("One checked result has been removed");
- else if (num > 1) alert(num + " checked results have been removed");
- else alert("No results were checked, so no results have been removed");
-}
-function checkall(v) {
- f=document.getElementsByName("del");
- if (f.length)
- for(i=0;i<f.length; i++)
- f[i].checked=v;
-}
-//-->
-</script>
-<tr>
-<td vAlign="top" width="1%"><A href='[$~HOMEPAGE~$]'> <img alt="Go to Google Desktop Search" width="150" height="55" src="/logo3.gif" border="0" vspace="12"></A></td>
-<td>&nbsp;</td>
-<td noWrap>
- <table cellSpacing="0" cellPadding="0" width="100%" border="0">
- <tr>
- <td bgColor="#DD0000"><img height="1" alt="" width="1"></td>
- </tr>
- </table>
- <table cellSpacing="0" cellPadding="0" width="100%" border="0">
- <tr>
- <td noWrap bgColor="#efefef"><font size="+1"><b>&nbsp;Remove Specific Items</b></font></td>
- <td noWrap align="right" bgColor="#efefef"><font size="-1"><a href="http://desktop.google.com/remove.html">Help</a>&nbsp;&nbsp;</font></td>
- </tr>
- </table>
-</td>
-</tr>
-</table>
-<table cellSpacing="0" cellPadding="2" width="100%" border="0">
-<tr bgColor="#EFEFEF">
-<td><font size="-1">&nbsp;<B>Remove</B> checked results and <B>return to search</B>.</font></td>
-<td align="right"><font size="-1"><a onClick='checkall(1)' href="#">Check all</a> - <a onClick='checkall(0)' href="#">
-Uncheck all</a>&nbsp;&nbsp;</font></td>
-<td align="right" width="1%" nowrap><font size="-1"><input onclick="deleting()" type="submit" value="Remove checked results" name="submit2"></font></td>
-</tr>
-</table>
-<br>
-<table cellspacing="0" cellpadding="2" width="100%" border="0">
-<tr>
-<td colSpan="3" bgcolor="#FFFFFF" style="border:solid; border-width:1px; border-color:#DD0000"><font size="-1">&nbsp;<b>Remove
-checked items from Google Desktop Search. Other copies of the same items will not be
-affected.<br>
-&nbsp;If you view the item again, it will be added back to Google Desktop Search.</b></font></td>
-</tr>
-</table>
-<br> \ No newline at end of file
diff --git a/tools/grit/grit/testdata/deleted.html b/tools/grit/grit/testdata/deleted.html
deleted file mode 100644
index 5ae5f35..0000000
--- a/tools/grit/grit/testdata/deleted.html
+++ /dev/null
@@ -1,21 +0,0 @@
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
-<html><head><title>Database Deleted</title>
-<meta http-equiv="content-type" content="text/html; charset=utf-8">
-<meta http-equiv="cache-control" content="no-cache">
-<meta http-equiv="pragma" content="no-cache">
-<meta http-equiv="expires" content="-1">
-<style>
-BODY,TD,A,P {FONT-FAMILY: arial,sans-serif}
-.q {COLOR: #0000cc}
-</style>
-</head>
-<BODY text=#000000 vLink=#551a8b aLink=#ff0000 link=#0000cc bgColor=#ffffff onload=sf()>
-<center>
-<TABLE cellSpacing=0 cellPadding=0 border=0>
-<tr><td><a href="[$~HOMEPAGE~$]"><IMG border=0 height=110 alt="Google Desktop Search" src="hp_logo.gif" width=276></a>
-</td></tr></table><BR>
-<center>The database has been deleted. Click <a href="[$~HOMEPAGE~$]">here</a> to continue.</center>
-</td></tr>
-</table>
-<br><FONT size=-1>[$~BOTTOMLINE~$]</font></p>
-<p><FONT size=-2>&copy;2005 Google</font></p></center></body></html> \ No newline at end of file
diff --git a/tools/grit/grit/testdata/details.html b/tools/grit/grit/testdata/details.html
deleted file mode 100644
index 0ab0e2a..0000000
--- a/tools/grit/grit/testdata/details.html
+++ /dev/null
@@ -1,10 +0,0 @@
-[!]
-title Improve Google Desktop Search by Sending Non-Personal Information
-template
-bottomline
-hp_image
-
-<p><strong>This documentation is not yet available</strong></p>
-<center><br>
-<font size=-1>[$~BOTTOMLINE~$] - &copy;2005 Google </font>
-</center>
diff --git a/tools/grit/grit/testdata/duplicate-name-input.xml b/tools/grit/grit/testdata/duplicate-name-input.xml
deleted file mode 100644
index cc4d1d6..0000000
--- a/tools/grit/grit/testdata/duplicate-name-input.xml
+++ /dev/null
@@ -1,26 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<grit base_dir="." latest_public_release="2" current_release="3" source_lang_id="en-US">
- <release seq="3">
- <messages>
- <message name="IDS_GREETING" desc="Printed to greet the currently logged in user">
- Hello <ph name="USERNAME">%s<ex>Joi</ex></ph>, how are you doing today?
- </message>
- </messages>
- <structures>
- <!-- Duplicate name here -->
- <structure type="version" name="IDS_GREETING" file="rc_files/bla.rc" />
- </structures>
- </release>
- <translations>
- <file path="figs_nl_translations.xml" />
- <file path="cjk_translations.xml" />
- </translations>
- <outputs>
- <output filename="resource.h" type="rc_header" />
- <output filename="resource_en.rc" type="rc_all" lang="en-US" />
- <output filename="resource_fr.rc" type="rc_all" lang="fr-FR" />
- <output filename="resource_it.rc" type="rc_translateable" lang="it-IT" />
- <output filename="resource_zh_cn.rc" type="rc_translateable" lang="zh-CN" />
- <output filename="nontranslateable.rc" type="rc_nontranslateable" />
- </outputs>
-</grit>
diff --git a/tools/grit/grit/testdata/email_result.html b/tools/grit/grit/testdata/email_result.html
deleted file mode 100644
index 8bb04b9..0000000
--- a/tools/grit/grit/testdata/email_result.html
+++ /dev/null
@@ -1,34 +0,0 @@
-[HEADER]
-[CHROME]
-<table border=0 cellpadding=2 cellspacing=2 width='100%'>
-<tr><td><font size=-1>[CONV]
-<a href='[$~REPLY_URL~$]'>Reply</a> | <a href='[$~REPLYALL_URL~$]'>Reply&nbsp;to&nbsp;All</a>[$~FORWARD_URL~$] | <a href='mailto:'>Compose</a>[$~OUTLOOKVIEW~$]
-</font></td></tr>
-</table>
-<blockquote id=gg_1>
-<table bgcolor=#f0f8ff width=80% cellpadding=5><tr><td>
-<img style="vertical-align:middle;" height=16 src='/email.gif' width=16> &nbsp; <b>[SUBJECT]</b>
-<p><font size=-1>[FROM-DISP]
-[TO-DISP]
-[CC-DISP]
-[BCC-DISP]
-[REPLYTO-DISP]
-[DATE-DISP]
-[VIEW-DISP]
-[$~ATTACH~$]
-</font></td></tr></table>
-<p class=g><span style="width:500;"><font size=-1><label>[MESSAGE]</label></span></p>
-</font>
-</blockquote>
-<table border=0 cellpadding=2 cellspacing=2 width='100%'>
-<tr><td><font size=-1>[CONV]
-<a href='[$~REPLY_URL~$]'>Reply</a> | <a href='[$~REPLYALL_URL~$]'>Reply&nbsp;to&nbsp;All</a>[$~FORWARD_URL~$] | <a href='mailto:'>Compose</a>[$~OUTLOOKVIEW~$]
-</font></td></tr></table>
-<style>
-.hl { color:black; background-color:#ffff88}
-</style>
-<script>
-[$~HIGHLIGHT_SCRIPT~$]
-[ONLOAD]
-</script>
-[FOOTER] \ No newline at end of file
diff --git a/tools/grit/grit/testdata/email_thread.html b/tools/grit/grit/testdata/email_thread.html
deleted file mode 100644
index 3c7279b..0000000
--- a/tools/grit/grit/testdata/email_thread.html
+++ /dev/null
@@ -1,10 +0,0 @@
-[HEADER]
-[CHROME]
-<blockquote [MAXWIDTH]>
-<b><img src=email.gif style="vertical-align:middle;" width=16 height=16> &nbsp; [SUBJECT]</b><br><br>
-<TABLE cellSpacing=0 cellPadding=3 border=0>
-[CONTENTS]
-</table>
-</blockquote>
-[NEXT_PREV]
-[FOOTER] \ No newline at end of file
diff --git a/tools/grit/grit/testdata/error.html b/tools/grit/grit/testdata/error.html
deleted file mode 100644
index 66875a2..0000000
--- a/tools/grit/grit/testdata/error.html
+++ /dev/null
@@ -1,8 +0,0 @@
-[HEADER]
-[CHROME]
-<br>
-<blockquote>
-[ERROR]<br><br>
-If you think this is an error, please <a href="http://desktop.google.com/feedback.html?version=[VERSION]">contact us</a>.
-</blockquote>
-[FOOTER] \ No newline at end of file
diff --git a/tools/grit/grit/testdata/explicit_web.html b/tools/grit/grit/testdata/explicit_web.html
deleted file mode 100644
index 1424adc..0000000
--- a/tools/grit/grit/testdata/explicit_web.html
+++ /dev/null
@@ -1,11 +0,0 @@
-[HEADER]
-<style>
-.image {BORDER: #0000cc 1px solid;}
-.imageh {BORDER: #0000cc 1px solid;}
-</style>
-[WEB_TOP_CHROME]
-[$~STATUS~$]
-[$~MESSAGE~$]
-[WEB_FILES]
-<br>[NEXT_PREV]
-[FOOTER] \ No newline at end of file
diff --git a/tools/grit/grit/testdata/footer.html b/tools/grit/grit/testdata/footer.html
deleted file mode 100644
index 3372d6a..0000000
--- a/tools/grit/grit/testdata/footer.html
+++ /dev/null
@@ -1,14 +0,0 @@
-<center><br clear=all><br>
-<table cellspacing=0 cellpadding=0 width="100%" border=0><tr bgcolor=#3399CC><td align=middle height=1><img height=1 width=1></td></tr></table>
-<table cellspacing=0 cellpadding=0 width="100%" bgcolor=#e8f4f7 border=0>
-<tr bgcolor=#e8f4f7>
-<td><br>
-<table cellpadding=1 align=center border=0 cellspacing=0 bgcolor=#e8f4f7>
-<form action='[$~SEARCHURL~$]' method=get>
-<tr><td noWrap>[$~BOTTOM~$]</td></tr></form>
-</table><br>
-</td></tr></table>
-<table cellspacing=0 cellpadding=0 width="100%" border=0><tr bgcolor=#3399CC><td align=middle height=1><img height=1 width=1></td></tr></table><br>
-<font size=-1>[$~BOTTOMLINE~$] - &copy;2005 Google </font></center>
-[SCRIPT]
-</body></html>
diff --git a/tools/grit/grit/testdata/generated_resources_fr.xtb b/tools/grit/grit/testdata/generated_resources_fr.xtb
deleted file mode 100644
index 6f7d683..0000000
--- a/tools/grit/grit/testdata/generated_resources_fr.xtb
+++ /dev/null
@@ -1,3090 +0,0 @@
-<?xml version="1.0" ?>
-<!DOCTYPE translationbundle>
-<translationbundle lang="fr">
-<translation id="6779164083355903755">Supprime&amp;r</translation>
-<translation id="6879617193011158416">Activer la barre de favoris</translation>
-<translation id="8130276680150879341">Déconnexion du réseau privé</translation>
-<translation id="1058418043520174283"><ph name="INDEX"/> sur <ph name="COUNT"/></translation>
-<translation id="4480627574828695486">Déconnecter ce compte...</translation>
-<translation id="1437399238463685286">Le nom du fichier contient un caractère incorrect : $1</translation>
-<translation id="7040807039050164757">&amp;Vérifier l'orthographe dans ce champ</translation>
-<translation id="778579833039460630">Aucune donnée reçue.</translation>
-<translation id="1852799913675865625">Une erreur s'est produite lors de la tentative de lecture du fichier : <ph name="ERROR_TEXT"/>.</translation>
-<translation id="3828924085048779000">Le mot de passe multiterme est obligatoire.</translation>
-<translation id="8265562484034134517">Importer les données d'un autre navigateur...</translation>
-<translation id="2709516037105925701">Saisie automatique</translation>
-<translation id="4857138207355690859">API P2P</translation>
-<translation id="250599269244456932">Exécuter automatiquement (recommandé)</translation>
-<translation id="3581034179710640788">Le certificat de sécurité du site a expiré !</translation>
-<translation id="2825758591930162672">Clé publique de l'objet</translation>
-<translation id="8275038454117074363">Importer</translation>
-<translation id="8418445294933751433">Afficher dan&amp;s un onglet</translation>
-<translation id="6985276906761169321">ID :</translation>
-<translation id="859285277496340001">Le certificat n'indique aucun mécanisme permettant de vérifier s'il a été révoqué.</translation>
-<translation id="2010799328026760191">Touches de modification...</translation>
-<translation id="3300394989536077382">Signé par :</translation>
-<translation id="654233263479157500">Utiliser un service Web pour résoudre les erreurs de navigation</translation>
-<translation id="4940047036413029306">Guillemet</translation>
-<translation id="1526811905352917883">Une nouvelle tentative de connexion avec SSL 3.0 a dû être effectuée. Cette opération indique généralement que le serveur utilise un logiciel très ancien et qu'il est susceptible de présenter d'autres problèmes de sécurité.</translation>
-<translation id="1497897566809397301">Autoriser le stockage des données locales (recommandé)</translation>
-<translation id="3275778913554317645">Ouvrir dans une fenêtre</translation>
-<translation id="4553117311324416101">Google pense qu'un logiciel malveillant pourrait être installé sur votre ordinateur si vous continuez. Nous vous conseillons de ne pas continuer, même si vous avez déjà consulté ce site auparavant ou si vous avez confiance en celui-ci. Il se peut qu'il ait été piraté récemment. Réessayez demain ou utilisez un autre site.</translation>
-<translation id="509988127256758334">&amp;Rechercher :</translation>
-<translation id="1420684932347524586">Échec de génération de clé privée RSA aléatoire</translation>
-<translation id="2501173422421700905">Certificat en attente</translation>
-<translation id="2313634973119803790">Technologie réseau :</translation>
-<translation id="2382901536325590843">Le certificat du serveur ne figure pas dans le DNS.</translation>
-<translation id="2833791489321462313">Demander le mot de passe au retour de veille</translation>
-<translation id="3850258314292525915">Désactiver la synchronisation</translation>
-<translation id="2721561274224027017">Base de données indexée</translation>
-<translation id="8208216423136871611">Ne pas enregistrer</translation>
-<translation id="684587995079587263"><ph name="PRODUCT_NAME"/> synchronise vos données avec votre compte Google en toute sécurité. Synchronisez toutes vos données ou personnalisez les types de données synchronisées et les options de chiffrement.</translation>
-<translation id="4405141258442788789">Le délai imparti à l'opération est dépassé.</translation>
-<translation id="5048179823246820836">Nordique</translation>
-<translation id="1763046204212875858">Créer des raccourcis vers des applications</translation>
-<translation id="2105006017282194539">Pas encore chargé</translation>
-<translation id="524759338601046922">Confirmer le nouveau code PIN :</translation>
-<translation id="688547603556380205">L2TP/IPSec + Certificat utilisateur</translation>
-<translation id="777702478322588152">Préfecture</translation>
-<translation id="6562437808764959486">Extraction de l'image de récupération...</translation>
-<translation id="561349411957324076">Terminé</translation>
-<translation id="4764776831041365478">Il se peut que la page Web à l'adresse <ph name="URL"/> soit temporairement inaccessible ou qu'elle ait été déplacée de façon permanente à une autre adresse Web.</translation>
-<translation id="6156863943908443225">Cache des scripts</translation>
-<translation id="4610656722473172270">Barre d'outils Google</translation>
-<translation id="151501797353681931">Importés depuis Safari</translation>
-<translation id="6706684875496318067">Le plug-in <ph name="PLUGIN_NAME"/> n'est pas autorisé.</translation>
-<translation id="586567932979200359">Vous exécutez <ph name="PRODUCT_NAME"/> à partir de son image disque. Si vous l'installez sur votre ordinateur, vous pourrez l'utiliser sans image disque et bénéficierez de mises à jour automatiques.</translation>
-<translation id="3775432569830822555">Certificat du serveur SSL</translation>
-<translation id="1829192082282182671">Z&amp;oom arrière</translation>
-<translation id="6102827823267795198">Indique si la suggestion du moteur de recherche doit être entrée immédiatement via la saisie semi-automatique lorsque la fonctionnalité Recherche instantanée est activée.</translation>
-<translation id="1467071896935429871">Mise à jour du système : <ph name="PERCENT"/> % téléchargés</translation>
-<translation id="7881267037441701396">Les informations d'identification associées au partage de vos imprimantes via <ph name="CLOUD_PRINT_NAME"/> sont arrivées à expiration. Cliquez ici pour saisir à nouveau votre nom d'utilisateur et votre mot de passe.</translation>
-<translation id="816055135686411707">Erreur de définition du paramètre de confiance du certificat</translation>
-<translation id="4714531393479055912"><ph name="PRODUCT_NAME"/> peut maintenant synchroniser vos mots de passe.</translation>
-<translation id="5704565838965461712">Sélectionnez le certificat à présenter pour l'identification :</translation>
-<translation id="2025632980034333559"><ph name="APP_NAME"/> a planté. Cliquez sur cette info-bulle pour actualiser l'extension.</translation>
-<translation id="4059593000330943833">Compatibilité expérimentale avec des méthodes Wi-Fi Extensible Authentication Protocol supplémentaires, telles que EAP-TLS et LEAP.</translation>
-<translation id="6322279351188361895">Échec de lecture de la clé privée</translation>
-<translation id="3781072658385678636">Les plug-ins suivants ont été bloqués sur cette page :</translation>
-<translation id="4428782877951507641">Configuration de la synchronisation</translation>
-<translation id="3648460724479383440">Case d'option cochée</translation>
-<translation id="4654488276758583406">Très petite</translation>
-<translation id="6647228709620733774">URL de révocation de l'autorité de certification Netscape</translation>
-<translation id="546411240573627095">Style de pavé numérique</translation>
-<translation id="7663002797281767775">Active les feuilles de style CSS 3D et la composition graphique haute performance des pages Web via le processeur graphique.</translation>
-<translation id="2972581237482394796">&amp;Rétablir</translation>
-<translation id="5895138241574237353">Redémarrer</translation>
-<translation id="1858072074757584559">La connexion n'est pas compressée.</translation>
-<translation id="528468243742722775">Fin</translation>
-<translation id="1723824996674794290">&amp;Nouvelle fenêtre</translation>
-<translation id="1313405956111467313">Configuration automatique du proxy</translation>
-<translation id="1589055389569595240">Afficher l'orthographe et la grammaire</translation>
-<translation id="4364779374839574930">Aucune imprimante n'a été trouvée. Veuillez en installer une.</translation>
-<translation id="7017587484910029005">Saisissez les caractères visibles dans l'image ci-dessous.</translation>
-<translation id="9013589315497579992">Certificat d'authentification de client SSL incorrect</translation>
-<translation id="8595062045771121608">Le certificat du serveur ou un certificat AC intermédiaire présenté au navigateur a été signé avec un algorithme de signature faible tel que RSA-MD2. D'après des études récentes menées par des informaticiens, les algorithmes de signature seraient plus faibles qu'on ne le pensait jusqu'alors. Aujourd'hui, ils sont très rarement utilisés par les sites Web jugés dignes de confiance. Ce certificat a peut-être été contrefait. Nous vous déconseillons vivement de continuer.</translation>
-<translation id="8666632926482119393">Rechercher le précédent</translation>
-<translation id="7567293639574541773">I&amp;nspecter l'élément</translation>
-<translation id="8392896330146417149">État d'itinérance :</translation>
-<translation id="6813971406343552491">&amp;Non</translation>
-<translation id="36224234498066874">Effacer les données de navigation...</translation>
-<translation id="3384773155383850738">Nombre maximal de suggestions</translation>
-<translation id="8331498498435985864">L'accessibilité est désactivée.</translation>
-<translation id="8530339740589765688">Sélectionner par domaine</translation>
-<translation id="8677212948402625567">Tout réduire...</translation>
-<translation id="7600965453749440009">Ne jamais traduire les pages rédigées en <ph name="LANGUAGE"/> </translation>
-<translation id="3208703785962634733">Non confirmé</translation>
-<translation id="6523841952727744497">Avant de vous connecter, démarrez une session en tant qu'invité afin d'activer le réseau <ph name="NETWORK_ID"/>.</translation>
-<translation id="7450044767321666434">La gravure de l'image est terminée.</translation>
-<translation id="2653266418988778031">Si vous supprimez le certificat d'une autorité de certification, votre navigateur ne fera plus confiance aux certificats émis par cette autorité de certification.</translation>
-<translation id="298068999958468740">Synchronisez toutes les données de cet ordinateur ou sélectionnez celles que vous souhaitez synchroniser.</translation>
-<translation id="5341849548509163798"><ph name="NUMBER_MANY"/> hours ago</translation>
-<translation id="4422428420715047158">Domaine :</translation>
-<translation id="3602290021589620013">Aperçu</translation>
-<translation id="7516602544578411747">Associe chaque fenêtre du navigateur à un profil et ajoute une option de sélection des profils en haut à droite. Chaque profil possède ses propres favoris, extensions, applications, etc.</translation>
-<translation id="7082055294850503883">Ignorer le verrouillage des majuscules et saisir des minuscules par défaut</translation>
-<translation id="1800124151523561876">Aucune parole détectée</translation>
-<translation id="7814266509351532385">Changer de moteur de recherche par défaut</translation>
-<translation id="5376169624176189338">Cliquer pour revenir en arrière, maintenir pour voir l'historique</translation>
-<translation id="6310545596129886942"><ph name="NUMBER_FEW"/> secondes restantes</translation>
-<translation id="9181716872983600413">Unicode</translation>
-<translation id="1383861834909034572">Ouverture à la fin du téléchargement</translation>
-<translation id="5727728807527375859">Les extensions, les applications et les thèmes peuvent endommager votre ordinateur. Voulez-vous vraiment continuer ?</translation>
-<translation id="3857272004253733895">Schéma du pinyin double</translation>
-<translation id="1636842079139032947">Déconnecter ce compte...</translation>
-<translation id="6721972322305477112">&amp;Fichier</translation>
-<translation id="1076818208934827215">Microsoft Internet Explorer</translation>
-<translation id="9056810968620647706">Aucune correspondance trouvée</translation>
-<translation id="1901494098092085382">État de votre commentaire</translation>
-<translation id="2861301611394761800">Mise à jour terminée. Veuillez redémarrer le système.</translation>
-<translation id="2231238007119540260">Lorsque vous supprimez un certificat de serveur, vous rétablissez les contrôles de sécurité habituels du serveur et un certificat valide lui est demandé.</translation>
-<translation id="5463582782056205887">Essayez d'ajouter
- <ph name="PRODUCT_NAME"/>
- aux programmes autorisés dans les paramètres de votre pare-feu ou de votre antivirus. S'il
- est déjà autorisé, tentez de le supprimer de la liste et de l'ajouter à nouveau à
- la liste des programmes autorisés.</translation>
-<translation id="7624154074265342755">Réseaux sans fil</translation>
-<translation id="3315158641124845231">Masquer <ph name="PRODUCT_NAME"/></translation>
-<translation id="3496213124478423963">Zoom arrière</translation>
-<translation id="2296019197782308739">Méthode EAP :</translation>
-<translation id="42981349822642051">Développer</translation>
-<translation id="4013794286379809233">Veuillez vous connecter</translation>
-<translation id="7693221960936265065">de n'importe quand</translation>
-<translation id="1763138995382273070">Désactiver la validation des formulaires interactifs HTML5</translation>
-<translation id="4920887663447894854">Le suivi de votre position géographique sur cette page a été bloqué pour les sites suivants :</translation>
-<translation id="7690346658388844119">La gravure de l'image a été interrompue.</translation>
-<translation id="8133676275609324831">&amp;Afficher dans le dossier</translation>
-<translation id="645705751491738698">Continuer à bloquer JavaScript</translation>
-<translation id="4780321648949301421">Enregistrer la page sous...</translation>
-<translation id="9154072353677278078">Le serveur <ph name="DOMAIN"/> à l'adresse <ph name="REALM"/> requiert un nom d'utilisateur et un mot de passe.</translation>
-<translation id="2551191967044410069">Exceptions de géolocalisation</translation>
-<translation id="4092066334306401966">13px</translation>
-<translation id="8178665534778830238">Contenu :</translation>
-<translation id="153384433402665971">Le plug-in <ph name="PLUGIN_NAME"/> a été bloqué, car il n'est plus à jour.</translation>
-<translation id="2610260699262139870">Taille ré&amp;elle</translation>
-<translation id="4535734014498033861">Échec de la connexion au serveur proxy.</translation>
-<translation id="558170650521898289">Vérification de pilote matériel Microsoft Windows</translation>
-<translation id="98515147261107953">Paysage</translation>
-<translation id="8974161578568356045">Détecter automatiquement</translation>
-<translation id="1818606096021558659">Page</translation>
-<translation id="5388588172257446328">Nom d'utilisateur :</translation>
-<translation id="1657406563541664238">Nous aider à améliorer <ph name="PRODUCT_NAME"/> en envoyant automatiquement les statistiques d'utilisation et les rapports d'erreur à Google</translation>
-<translation id="7982789257301363584">Réseau</translation>
-<translation id="8528962588711550376">Connexion en cours</translation>
-<translation id="2336228925368920074">Ajouter tous les onglets aux favoris...</translation>
-<translation id="4985312428111449076">Onglets ou fenêtres</translation>
-<translation id="7481475534986701730">Sites récemment consultés</translation>
-<translation id="4260722247480053581">Ouvrir dans une fenêtre de navigation privée</translation>
-<translation id="8503758797520866434">Préférences de saisie automatique...</translation>
-<translation id="2757031529886297178">Compteur d'images par seconde</translation>
-<translation id="6657585470893396449">Mot de passe</translation>
-<translation id="7881483672146086348">Afficher le compte</translation>
-<translation id="1776883657531386793"><ph name="OID"/> : <ph name="INFO"/></translation>
-<translation id="1510030919967934016">Le suivi de votre position géographique a été bloqué pour cette page.</translation>
-<translation id="4640525840053037973">Connexion à l'aide de votre compte Google</translation>
-<translation id="5255315797444241226">Le mot de passe multiterme entré est incorrect.</translation>
-<translation id="6242054993434749861">télécopie : #<ph name="FAX"/></translation>
-<translation id="762917759028004464">Le navigateur par défaut est actuellement <ph name="BROWSER_NAME"/>.</translation>
-<translation id="9213479837033539041"><ph name="NUMBER_MANY"/> secondes restantes</translation>
-<translation id="560442828508350263">Impossible de déplacer &quot;$1&quot; : $2</translation>
-<translation id="300544934591011246">Mot de passe précédent</translation>
-<translation id="5078796286268621944">Code PIN incorrect</translation>
-<translation id="989988560359834682">Modifier l'adresse</translation>
-<translation id="8487678622945914333">Zoom avant</translation>
-<translation id="2972557485845626008">Micrologiciel</translation>
-<translation id="735327918767574393">Une erreur s'est produite lors de l'affichage de cette page Web. Pour continuer, actualisez cette page ou ouvrez-en une autre.</translation>
-<translation id="8028060951694135607">Récupération de clé Microsoft</translation>
-<translation id="9187657844611842955">recto verso</translation>
-<translation id="6391832066170725637">Fichier ou répertoire introuvable</translation>
-<translation id="4694445829210540512">Aucun forfait de données <ph name="NETWORK"/> actif</translation>
-<translation id="5494920125229734069">Tout sélectionner</translation>
-<translation id="2857834222104759979">Le fichier manifeste est incorrect.</translation>
-<translation id="7931071620596053769">Les pages suivantes ne répondent plus. Vous pouvez attendre qu'elles soient de nouveau accessibles ou les supprimer.</translation>
-<translation id="1209866192426315618"><ph name="NUMBER_DEFAULT"/> minutes restantes</translation>
-<translation id="7938958445268990899">Le certificat du serveur n'est pas encore valide.</translation>
-<translation id="4569998400745857585">Menu contenant des extensions masquées</translation>
-<translation id="4081383687659939437">Enregistrer les infos</translation>
-<translation id="5786805320574273267">Configuration de l'accès à distance à cet ordinateur.</translation>
-<translation id="1801827354178857021">Point</translation>
-<translation id="2179052183774520942">Ajouter un moteur de recherche</translation>
-<translation id="5498951625591520696">Impossible d'atteindre le serveur.</translation>
-<translation id="2956948609882871496">Importer mes favoris...</translation>
-<translation id="1621207256975573490">Enregistrer le &amp;cadre sous...</translation>
-<translation id="4681260323810445443">Vous n'êtes pas autorisé à accéder à la page Web <ph name="URL"/>. Votre connexion peut être requise.</translation>
-<translation id="2176444992480806665">Envoyer la capture d'écran du dernier onglet actif</translation>
-<translation id="1165039591588034296">Erreur</translation>
-<translation id="2064942105849061141">Utiliser le thème GTK+</translation>
-<translation id="2278562042389100163">Ouvrir une fenêtre du navigateur</translation>
-<translation id="5246282308050205996"><ph name="APP_NAME"/> a planté. Cliquez sur cette info-bulle pour redémarrer l'application.</translation>
-<translation id="9218430445555521422">Définir comme navigateur par défaut</translation>
-<translation id="5027550639139316293">Certificat de courrier électronique</translation>
-<translation id="938582441709398163">Clavier en superposition</translation>
-<translation id="427208986916971462">La connexion est compressée avec <ph name="COMPRESSION"/>.</translation>
-<translation id="4589279373639964403">Exporter mes favoris...</translation>
-<translation id="8876215549894133151">Format :</translation>
-<translation id="5234764350956374838">Ignorer</translation>
-<translation id="40027638859996362">Déplacer un mot</translation>
-<translation id="5463275305984126951">Index de <ph name="LOCATION"/></translation>
-<translation id="5154917547274118687">Mémoire</translation>
-<translation id="1493492096534259649">Impossible d'utiliser cette langue pour corriger l'orthographe.</translation>
-<translation id="6628463337424475685">Recherche <ph name="ENGINE"/></translation>
-<translation id="2502105862509471425">Ajouter une autre carte de paiement...</translation>
-<translation id="4037618776454394829">Envoyer la dernière capture d'écran enregistrée</translation>
-<translation id="8987670145726065238">Ce fichier contient du code malveillant. Voulez-vous vraiment continuer ?</translation>
-<translation id="182729337634291014">Erreur de synchronisation...</translation>
-<translation id="4465830120256509958">Clavier brésilien</translation>
-<translation id="2459861677908225199">Utiliser TLS 1.0</translation>
-<translation id="4792711294155034829">&amp;Signaler un problème...</translation>
-<translation id="5819484510464120153">Créer des raccourci&amp;s vers des applications...</translation>
-<translation id="6845180713465955339">Le certificat &quot;<ph name="CERTIFICATE_NAME"/>&quot; a été émis par :</translation>
-<translation id="7531238562312180404"><ph name="PRODUCT_NAME"/> ne contrôlant pas la façon dont les extensions gèrent vos données personnelles, toutes les extensions sont désactivées dans les fenêtres de navigation privée. Vous pouvez les réactiver individuellement dans le <ph name="BEGIN_LINK"/>gestionnaire des extensions<ph name="END_LINK"/>.</translation>
-<translation id="5667293444945855280">Logiciels malveillants</translation>
-<translation id="3435845180011337502">Mise en page ou mise en forme de la page</translation>
-<translation id="3838186299160040975">Acheter davantage...</translation>
-<translation id="6831043979455480757">Traduire</translation>
-<translation id="3587482841069643663">Tout</translation>
-<translation id="6698381487523150993">Créé :</translation>
-<translation id="4684748086689879921">Annuler l'importation</translation>
-<translation id="9130015405878219958">Le mode indiqué est incorrect.</translation>
-<translation id="6615807189585243369"><ph name="BURNT_AMOUNT"/> copié(s) sur <ph name="TOTAL_SIZE"/></translation>
-<translation id="8518425453349204360">L'accès à distance à cet ordinateur est activé pour <ph name="USER_EMAIL_ADDRESS"/>.</translation>
-<translation id="4950138595962845479">Options...</translation>
-<translation id="4653235815000740718">Un problème est survenu lors de la création du support de récupération du système d'exploitation. Le périphérique de stockage utilisé est introuvable.</translation>
-<translation id="5516565854418269276">Toujours &amp;afficher la barre de favoris</translation>
-<translation id="6426222199977479699">Erreur SSL</translation>
-<translation id="7104784605502674932">Confirmer les préférences de synchronisation</translation>
-<translation id="1788636309517085411">Utiliser les valeurs par défaut</translation>
-<translation id="1661867754829461514">Code secret manquant</translation>
-<translation id="7406714851119047430">L'accès à distance à cet ordinateur est désactivé.</translation>
-<translation id="8589311641140863898">API des extensions expérimentales</translation>
-<translation id="2804922931795102237">Inclure les informations système</translation>
-<translation id="869891660844655955">Date d'expiration</translation>
-<translation id="2178614541317717477">Autorité de certification compromise</translation>
-<translation id="4449935293120761385">À propos de la saisie automatique</translation>
-<translation id="4194570336751258953">Activer la fonction &quot;Taper pour cliquer&quot;</translation>
-<translation id="6066742401428748382">Accès à la page Web refusé</translation>
-<translation id="5111692334209731439">&amp;Gestionnaire de favoris</translation>
-<translation id="8295070100601117548">Erreur serveur</translation>
-<translation id="5661272705528507004">Cette carte SIM est désactivée et ne peut être utilisée. Veuillez demander à votre fournisseur de services de la remplacer.</translation>
-<translation id="443008484043213881">Outils</translation>
-<translation id="2529657954821696995">Clavier néerlandais</translation>
-<translation id="1128128132059598906">EAP-TTLS</translation>
-<translation id="6585234750898046415">Choisissez une image à associer à votre compte. Celle-ci s'affichera sur l'écran de connexion.</translation>
-<translation id="7957054228628133943">Configurer le blocage des fenêtres pop-up...</translation>
-<translation id="179767530217573436">des 4 dernières semaines</translation>
-<translation id="2279770628980885996">Une situation inattendue s'est produite tandis que le serveur tentait de traiter la demande.</translation>
-<translation id="8079135502601738761">Impossible d'afficher certaines parties de ce document PDF. Souhaitez-vous l'ouvrir dans Adobe Reader ?</translation>
-<translation id="9123413579398459698">Proxy FTP</translation>
-<translation id="3887875461425980041">Si vous utilisez la version PPAPI de Flash, exécutez-la dans chaque processus de moteur du rendu plutôt que dans un processus de plug-in dédié.</translation>
-<translation id="8534801226027872331">Cela signifie que le certificat présenté à votre navigateur contient des erreurs et qu'il ne peut pas être compris. Il est possible que les informations sur l'identité du certificat ou que d'autres informations du certificat relatives à la sécurité de la connexion soient incompréhensibles. Ne poursuivez pas.</translation>
-<translation id="3608527593787258723">Activer l'onglet 1</translation>
-<translation id="4497369307931735818">Communication à distance</translation>
-<translation id="3855676282923585394">Importer les favoris et les paramètres...</translation>
-<translation id="1116694919640316211">À propos</translation>
-<translation id="4422347585044846479">Modifier le favori de cette page</translation>
-<translation id="1684638090259711957">Ajouter un format d'exception</translation>
-<translation id="4925481733100738363">Configurer l'accès à distance...</translation>
-<translation id="1880905663253319515">Supprimer le certificat &quot;<ph name="CERTIFICATE_NAME"/>&quot; ?</translation>
-<translation id="8546306075665861288">Cache des images</translation>
-<translation id="5904093760909470684">Configuration du proxy</translation>
-<translation id="2874027208508018603">En l'absence de connexion Wi-Fi, Google Chrome utilise les données 3G.</translation>
-<translation id="4558734465070698159">Appuyez sur <ph name="HOTKEY_NAME"/> pour sélectionner le mode de saisie précédent.</translation>
-<translation id="3348643303702027858">La création du support de récupération du système d'exploitation a été annulée.</translation>
-<translation id="3391060940042023865">Le plug-in suivant est bloqué : <ph name="PLUGIN_NAME"/></translation>
-<translation id="4237016987259239829">Erreur de connexion réseau</translation>
-<translation id="9050666287014529139">Mot de passe multiterme</translation>
-<translation id="5197255632782567636">Internet</translation>
-<translation id="4755860829306298968">Configurer les paramètres de blocage des plug-ins...</translation>
-<translation id="8879284080359814990">Afficher dan&amp;s un onglet</translation>
-<translation id="2786847742169026523">Synchroniser vos mots de passe</translation>
-<translation id="41293960377217290">Le serveur proxy agit comme un intermédiaire entre votre ordinateur et les autres serveurs. Votre configuration système utilise actuellement un proxy, mais
- <ph name="PRODUCT_NAME"/>
- ne parvient pas à s'y connecter.</translation>
-<translation id="4520722934040288962">Sélectionner par type d'application</translation>
-<translation id="3873139305050062481">Procéder à l'i&amp;nspection de l'élément</translation>
-<translation id="7445762425076701745">Impossible de valider entièrement l'identité du serveur auquel vous êtes connecté. Le nom utilisé pour cette connexion n'est valide que sur votre réseau et aucune autorité de certification externe ne peut en vérifier la propriété. Certaines autorités de certification délivrent tout de même des certificats pour ces types de nom, par conséquent nous ne sommes pas en mesure de vérifier que vous êtes connecté au site voulu et non à un site malveillant.</translation>
-<translation id="1556537182262721003">Impossible de déplacer le répertoire d'extensions dans le profil.</translation>
-<translation id="5866557323934807206">Supprimer ces paramètres pour les prochaines visites</translation>
-<translation id="6506104645588011859">L'accessibilité est activée.</translation>
-<translation id="5355351445385646029">Appuyer sur la touche Espace pour sélectionner la suggestion</translation>
-<translation id="6978622699095559061">Vos favoris</translation>
-<translation id="6370820475163108109"><ph name="ORGANIZATION_NAME"/> (<ph name="DOMAIN_NAME"/>)</translation>
-<translation id="5453029940327926427">Fermer les onglets</translation>
-<translation id="406070391919917862">Applications en arrière-plan</translation>
-<translation id="8820817407110198400">Favoris</translation>
-<translation id="3214837514330816581">Supprimer les données synchronisées de Google Dashboard</translation>
-<translation id="2580170710466019930">Veuillez patienter pendant que <ph name="PRODUCT_NAME"/> installe les dernières mises à jour système.</translation>
-<translation id="7428061718435085649">Utilisez les touches Maj gauche et droite pour sélectionner les 2e et 3e propositions</translation>
-<translation id="1070066693520972135">WEP</translation>
-<translation id="206683469794463668">Mode Zhuyin complet. La sélection automatique de la suggestion et les options associées sont désactivées ou ignorées.</translation>
-<translation id="5191625995327478163">&amp;Paramètres linguistiques...</translation>
-<translation id="8833054222610756741">CRX-less Web Apps</translation>
-<translation id="4031729365043810780">Connexion au réseau</translation>
-<translation id="3332115613788466465">Reliure bord long</translation>
-<translation id="1985136186573666099"><ph name="PRODUCT_NAME"/> utilise les paramètres proxy du système pour se connecter au réseau.</translation>
-<translation id="6508261954199872201">Application : <ph name="APP_NAME"/></translation>
-<translation id="5585645215698205895">&amp;Descendre</translation>
-<translation id="8366757838691703947">? Toutes les données présentes sur le périphérique seront supprimées.</translation>
-<translation id="6596816719288285829">Adresse IP</translation>
-<translation id="7747704580171477003">Active le nouveau design de la page &quot;Nouvel onglet&quot; (en cours de développement).</translation>
-<translation id="4508265954913339219">Échec de l'activation</translation>
-<translation id="8656768832129462377">Ne pas vérifier</translation>
-<translation id="715487527529576698">Le chinois simplifié est le mode de saisie initial</translation>
-<translation id="1674989413181946727">Paramètres SSL sur tout l'ordinateur :</translation>
-<translation id="8703575177326907206">Votre connexion à <ph name="DOMAIN"/> n'est pas chiffrée.</translation>
-<translation id="8472623782143987204">matériel requis</translation>
-<translation id="4865571580044923428">Gérer les exceptions...</translation>
-<translation id="2526619973349913024">Rechercher des mises à jour</translation>
-<translation id="3874070094967379652">Utiliser un mot de passe multiterme pour chiffrer mes données de synchronisation</translation>
-<translation id="4864369630010738180">Connexion en cours...</translation>
-<translation id="6500116422101723010">Le serveur ne parvient pas à traiter la demande pour le moment. Ce code indique une situation temporaire. Le serveur sera de nouveau opérationnel ultérieurement.</translation>
-<translation id="1644574205037202324">Historique</translation>
-<translation id="1297175357211070620">Destination</translation>
-<translation id="6219983382864672018">Web audio</translation>
-<translation id="479280082949089240">Cookies placés par cette page</translation>
-<translation id="4198861010405014042">Accès partagé</translation>
-<translation id="6204930791202015665">Afficher...</translation>
-<translation id="5941343993301164315">Veuillez vous connecter à <ph name="TOKEN_NAME"/>.</translation>
-<translation id="4417229845571722044">Ajouter un nouvel e-mail</translation>
-<translation id="8049151370369915255">Personnaliser les polices...</translation>
-<translation id="2886862922374605295">Matériel :</translation>
-<translation id="4497097279402334319">Erreur de connexion au réseau.</translation>
-<translation id="5303618139271450299">Cette page Web est introuvable.</translation>
-<translation id="4256316378292851214">En&amp;registrer la vidéo sous...</translation>
-<translation id="3528171143076753409">Le certificat du serveur n'est pas approuvé.</translation>
-<translation id="6518014396551869914">Cop&amp;ier l'image</translation>
-<translation id="3236997602556743698">Sebeol-sik 390</translation>
-<translation id="542155483965056918"><ph name="NUMBER_ZERO"/> mins ago</translation>
-<translation id="289426338439836048">Autre réseau mobile...</translation>
-<translation id="3986287159189541211">Erreur HTTP <ph name="ERROR_NUMBER"/> (<ph name="ERROR_NAME"/>) : <ph name="ERROR_TEXT"/></translation>
-<translation id="3225319735946384299">Signature du code</translation>
-<translation id="3118319026408854581">Aide <ph name="PRODUCT_NAME"/></translation>
-<translation id="2422426094670600218">&lt;sans nom&gt;</translation>
-<translation id="2012766523151663935">Version du micrologiciel :</translation>
-<translation id="4120898696391891645">La page ne se charge pas</translation>
-<translation id="6060685159320643512">Attention, ces fonctionnalités expérimentales peuvent mordre.</translation>
-<translation id="5829990587040054282">Verrouiller l'écran ou éteindre</translation>
-<translation id="7800304661137206267">La connexion est chiffrée au moyen de <ph name="CIPHER"/>, avec <ph name="MAC"/> pour l'authentification des messages et <ph name="KX"/> pour la méthode d'échange de clés.</translation>
-<translation id="7706319470528945664">Clavier portugais</translation>
-<translation id="5584537427775243893">Importation</translation>
-<translation id="9128870381267983090">Connexion au réseau</translation>
-<translation id="4181841719683918333">Langues</translation>
-<translation id="6535131196824081346">Cette erreur peut se produire lors de la connexion à un serveur sécurisé (HTTPS).
- Elle indique que le serveur tente d'établir une connexion sécurisée, mais
- que celle-ci ne sera pas du tout sécurisée en raison d'une grave erreur de configuration.
- <ph name="LINE_BREAK"/> Dans ce cas, une intervention
- est requise sur le serveur.
- <ph name="PRODUCT_NAME"/>
- n'utilise pas de connexion non sécurisée pour protéger la confidentialité
- de vos données.</translation>
-<translation id="5235889404533735074">La synchronisation de <ph name="PRODUCT_NAME"/> vous permet de partager vos données (favoris, préférences) sur vos ordinateurs en toute simplicité. Pour ce faire, <ph name="PRODUCT_NAME"/> enregistre vos données en ligne via Google lorsque vous vous connectez à votre compte.</translation>
-<translation id="6533668113756472185">Format ou mise en forme de la page</translation>
-<translation id="5640179856859982418">Clavier suisse</translation>
-<translation id="5910363049092958439">En&amp;registrer l'image sous...</translation>
-<translation id="1363055550067308502">Basculer en mode pleine chasse ou demi-chasse</translation>
-<translation id="3108967419958202225">Sélectionner...</translation>
-<translation id="6451650035642342749">Effacer les paramètres d'ouverture automatique</translation>
-<translation id="5948544841277865110">Ajouter un réseau privé</translation>
-<translation id="7121570032414343252"><ph name="NUMBER_TWO"/> secondes</translation>
-<translation id="1378451347523657898">Ne pas envoyer de capture d'écran</translation>
-<translation id="5098629044894065541">Hébreu</translation>
-<translation id="7751559664766943798">Toujours afficher la barre de favoris</translation>
-<translation id="5098647635849512368">Impossible de trouver le chemin d'accès absolu du répertoire à empaqueter.</translation>
-<translation id="780617032715125782">Créer un profil</translation>
-<translation id="933712198907837967">Diners Club</translation>
-<translation id="6380224340023442078">Paramètres de contenu...</translation>
-<translation id="950108145290971791">Activer la recherche instantanée pour accélérer la recherche et la navigation ?</translation>
-<translation id="144136026008224475">Plus d'extensions &gt;&gt;</translation>
-<translation id="5486326529110362464">La valeur d'entrée de la clé privée est obligatoire.</translation>
-<translation id="9039663905644212491">PEAP</translation>
-<translation id="62780591024586043">Fonctionnalités de localisation expérimentales</translation>
-<translation id="8584280235376696778">Ou&amp;vrir la vidéo dans un nouvel onglet</translation>
-<translation id="2845382757467349449">Toujours afficher la barre de favoris</translation>
-<translation id="2516384155283419848">Reliure</translation>
-<translation id="3053013834507634016">Utilisation de la clé du certificat</translation>
-<translation id="4487088045714738411">Clavier belge</translation>
-<translation id="7511635910912978956"><ph name="NUMBER_FEW"/> heures restantes</translation>
-<translation id="2152580633399033274">Afficher toutes les images (recommandé)</translation>
-<translation id="7894567402659809897">Cliquez sur
- <ph name="BEGIN_BOLD"/>Démarrer<ph name="END_BOLD"/>,
- puis sur
- <ph name="BEGIN_BOLD"/>Exécuter<ph name="END_BOLD"/>.
- Saisissez
- <ph name="BEGIN_BOLD"/>%windir%\\network diagnostic\\xpnetdiag.exe<ph name="END_BOLD"/>
- et cliquez sur
- <ph name="BEGIN_BOLD"/>OK<ph name="END_BOLD"/>.</translation>
-<translation id="2934952234745269935">Nom de volume</translation>
-<translation id="7960533875494434480">Reliure bord court</translation>
-<translation id="6431347207794742960"><ph name="PRODUCT_NAME"/> va configurer les mises à jour automatiques pour tous les utilisateurs de cet ordinateur.</translation>
-<translation id="4973698491777102067">Effacer les éléments datant :</translation>
-<translation id="6074963268421707432">Interdire à tous les sites d'afficher des notifications sur le Bureau</translation>
-<translation id="8508050303181238566">Appuyez sur <ph name="HOTKEY_NAME"/> pour passer d'un mode de saisie à l'autre.</translation>
-<translation id="6273404661268779365">Ajouter un nouveau fax</translation>
-<translation id="1995173078718234136">Recherche de contenu en cours...</translation>
-<translation id="4735819417216076266">Style d'entrée avec Espace</translation>
-<translation id="2977095037388048586">Vous avez tenté d'accéder à <ph name="DOMAIN"/>, mais, au lieu de cela, vous communiquez actuellement avec un serveur identifié comme <ph name="DOMAIN2"/>. Cela est peut-être dû à un défaut de configuration du serveur ou à quelque chose de plus grave. Un pirate informatique sur votre réseau cherche peut-être à vous faire visiter une version falsifiée de <ph name="DOMAIN3"/>, donc potentiellement préjudiciable. Nous vous déconseillons vivement de continuer.</translation>
-<translation id="220138918934036434">Masquer le bouton</translation>
-<translation id="5374359983950678924">Modifier l'image</translation>
-<translation id="5158548125608505876">Ne pas synchroniser mes mots de passe</translation>
-<translation id="2167276631610992935">JavaScript</translation>
-<translation id="6974306300279582256">Activer les notifications de <ph name="SITE"/></translation>
-<translation id="492914099844938733">Afficher les incompatibilités</translation>
-<translation id="5233638681132016545">Nouvel onglet</translation>
-<translation id="6567688344210276845">Impossible de charger l'icône &quot;<ph name="ICON"/>&quot; d'action de page.</translation>
-<translation id="5210365745912300556">Fermer l'onglet</translation>
-<translation id="8628085465172583869">Nom d'hôte du serveur :</translation>
-<translation id="498765271601821113">Ajouter une carte de paiement</translation>
-<translation id="7694379099184430148"><ph name="FILENAME"/> : type de fichier inconnu</translation>
-<translation id="1992397118740194946">Non défini</translation>
-<translation id="7966826846893205925">Gérer les paramètres de saisie automatique...</translation>
-<translation id="8556732995053816225">Respecter la &amp;casse</translation>
-<translation id="3314070176311241517">Autoriser tous les sites à exécuter JavaScript (recommandé)</translation>
-<translation id="2406911946387278693">Gérer vos périphériques depuis le cloud</translation>
-<translation id="7419631653042041064">Clavier catalan</translation>
-<translation id="5710740561465385694">Me demander lorsqu'un site essaie de stocker des données</translation>
-<translation id="3897092660631435901">Menu</translation>
-<translation id="7024867552176634416">Sélectionnez le périphérique de stockage amovible à utiliser.</translation>
-<translation id="8553075262323480129">La traduction a échoué, car nous n'avons pas pu déterminer la langue de la page.</translation>
-<translation id="5910680277043747137">Vous pouvez créer des profils supplémentaires pour autoriser plusieurs personnes à utiliser et personnaliser Google Chrome.</translation>
-<translation id="4381849418013903196">Deux-points</translation>
-<translation id="1103523840287552314">Toujours traduire en <ph name="LANGUAGE"/></translation>
-<translation id="2263497240924215535">(désactivée)</translation>
-<translation id="2159087636560291862">Cela signifie que le certificat n'a pas été vérifié par un tiers reconnu par votre ordinateur. N'importe qui peut émettre un certificat en se faisant passer pour un autre site Web. Ce certificat doit donc être vérifié par un tiers approuvé. Sans cette vérification, les informations sur l'identité du certificat sont sans intérêt. Par conséquent, il nous est impossible de vérifier que vous communiquez bien avec <ph name="DOMAIN"/> et non avec un pirate informatique ayant émis son propre certificat en prétendant être <ph name="DOMAIN2"/>. Nous vous déconseillons vivement de continuer.</translation>
-<translation id="58625595078799656"><ph name="PRODUCT_NAME"/> requiert que vous cryptiez vos données à l'aide de votre mot de passe Google ou de votre propre mot de passe multiterme.</translation>
-<translation id="8017335670460187064"><ph name="LABEL"/></translation>
-<translation id="6840184929775541289">N'est pas une autorité de certification</translation>
-<translation id="6099520380851856040">Date et heure : <ph name="CRASH_TIME"/></translation>
-<translation id="144518587530125858">Impossible de charger &quot;<ph name="IMAGE_PATH"/>&quot; pour le thème.</translation>
-<translation id="5355097969896547230">Rechercher à nouveau</translation>
-<translation id="7925285046818567682">En attente de <ph name="HOST_NAME"/>...</translation>
-<translation id="2553440850688409052">Masquer ce plug-in</translation>
-<translation id="3280237271814976245">Enregistrer &amp;sous...</translation>
-<translation id="8301162128839682420">Ajouter une langue :</translation>
-<translation id="7658239707568436148">Annuler</translation>
-<translation id="8695825812785969222">Ouvrir une &amp;adresse...</translation>
-<translation id="4538417792467843292">Supprimer le mot</translation>
-<translation id="8412392972487953978">Vous devez saisir deux fois le même mot de passe multiterme.</translation>
-<translation id="9121814364785106365">Ouvrir dans un onglet épinglé</translation>
-<translation id="6996264303975215450">Page Web, tout type de contenu</translation>
-<translation id="3435896845095436175">Activer</translation>
-<translation id="1891668193654680795">Considérer ce certificat comme fiable pour identifier les développeurs de logiciels.</translation>
-<translation id="5078638979202084724">Ajouter tous les onglets aux favoris</translation>
-<translation id="5585118885427931890">Impossible de créer le dossier de favoris.</translation>
-<translation id="2154710561487035718">Copier l'URL</translation>
-<translation id="8163672774605900272">Si vous pensez ne pas avoir à utiliser de serveur proxy, procédez comme suit :
- <ph name="PLATFORM_TEXT"/></translation>
-<translation id="5510687173983454382">Définir les utilisateurs autorisés à se connecter à un périphérique et autoriser les sessions de navigation en tant qu'invité</translation>
-<translation id="3241680850019875542">Sélectionnez le répertoire racine de l'extension à empaqueter. Pour mettre à jour une extension, sélectionnez également le fichier de clé privée à réutiliser.</translation>
-<translation id="7500424997253660722">Pool restreint :</translation>
-<translation id="657402800789773160">&amp;Rafraîchir cette page</translation>
-<translation id="6163363155248589649">&amp;Normal</translation>
-<translation id="7972714317346275248">PKCS #1 SHA-384 avec chiffrement RSA</translation>
-<translation id="3020990233660977256">Numéro de série : <ph name="SERIAL_NUMBER"/></translation>
-<translation id="8426519927982004547">HTTPS/SSL</translation>
-<translation id="8216781342946147825">Toutes les données de votre ordinateur et des sites Web que vous visitez</translation>
-<translation id="5548207786079516019">Ceci est une installation secondaire de <ph name="PRODUCT_NAME"/> et ce dernier ne peut pas être défini comme navigateur par défaut.</translation>
-<translation id="3984413272403535372">Erreur lors de la signature de l'extension</translation>
-<translation id="8807083958935897582"><ph name="PRODUCT_NAME"/> permet d'effectuer des recherches sur Internet à l'aide du champ polyvalent. Sélectionnez le moteur de recherche à utiliser :</translation>
-<translation id="6629104427484407292">Sécurité : <ph name="SECURITY"/></translation>
-<translation id="9208886416788010685">Adobe Reader n'est pas à jour</translation>
-<translation id="3373604799988099680">Extensions ou applications</translation>
-<translation id="318408932946428277">Effacer les cookies et autres données de site et de plug-in lorsque je ferme le navigateur</translation>
-<translation id="314141447227043789">Téléchargement de l'image terminé.</translation>
-<translation id="8725178340343806893">Favoris</translation>
-<translation id="5177526793333269655">Afficher les vignettes</translation>
-<translation id="8926389886865778422">Ne plus afficher ce message</translation>
-<translation id="6985235333261347343">Agent de récupération de clé Microsoft</translation>
-<translation id="3605499851022050619">Page de diagnostic de navigation sécurisée</translation>
-<translation id="4417271111203525803">Adresse ligne 2</translation>
-<translation id="7617095560120859490">Décrivez-nous le problème recontré. (Champ obligatoire)</translation>
-<translation id="5618333180342767515">Cela peut prendre quelques minutes.</translation>
-<translation id="5399884481423204214">Échec de l'envoi du commentaire : $1</translation>
-<translation id="4307992518367153382">Options de base</translation>
-<translation id="8480417584335382321">Niveau de zoom par défaut :</translation>
-<translation id="3872166400289564527">Stockage externe</translation>
-<translation id="5912378097832178659">Modifi&amp;er les moteurs de recherche...</translation>
-<translation id="8272426682713568063">Cartes de paiement</translation>
-<translation id="3749289110408117711">Nom du fichier</translation>
-<translation id="3173397526570909331">Arrêter la synchronisation</translation>
-<translation id="5538092967727216836">Actualiser le cadre</translation>
-<translation id="4813345808229079766">Connexion</translation>
-<translation id="411666854932687641">Mémoire privée</translation>
-<translation id="119944043368869598">Tout effacer</translation>
-<translation id="3467848195100883852">Activer la correction orthographique automatique</translation>
-<translation id="1336254985736398701">Afficher les &amp;infos sur la page</translation>
-<translation id="7550830279652415241">favoris_<ph name="DATESTAMP"/>.html</translation>
-<translation id="6828153365543658583">Autoriser uniquement les utilisateurs suivants à se connecter :</translation>
-<translation id="1652965563555864525">&amp;Muet</translation>
-<translation id="4200983522494130825">Nouvel ongle&amp;t</translation>
-<translation id="7979036127916589816">Erreur de synchronisation</translation>
-<translation id="1029317248976101138">Zoom</translation>
-<translation id="5455790498993699893"><ph name="ACTIVE_MATCH"/> sur <ph name="TOTAL_MATCHCOUNT"/></translation>
-<translation id="8890069497175260255">Type de clavier</translation>
-<translation id="1202290638211552064">Délai d'expiration atteint au niveau de la passerelle ou du serveur proxy en attente d'une réponse d'un serveur en amont.</translation>
-<translation id="7765158879357617694">Déplacer</translation>
-<translation id="5731751937436428514">Mode de saisie du vietnamien (VIQR)</translation>
-<translation id="8412144371993786373">Ajouter la page actuelle aux favoris</translation>
-<translation id="7615851733760445951">&lt;aucun cookie sélectionné&gt;</translation>
-<translation id="469553822757430352">Le mot de passe de l'application est incorrect.</translation>
-<translation id="2493021387995458222">Sélectionner &quot;un mot à la fois&quot;</translation>
-<translation id="5279600392753459966">Tout bloquer</translation>
-<translation id="6846298663435243399">Chargement en cours…</translation>
-<translation id="7392915005464253525">&amp;Rouvrir la fenêtre fermée</translation>
-<translation id="1144684570366564048">Gérer les exceptions...</translation>
-<translation id="7400418766976504921">URL</translation>
-<translation id="1541725072327856736">Katakana demi-chasse</translation>
-<translation id="7456847797759667638">Ouvrir une adresse</translation>
-<translation id="1388866984373351434">Données de navigation</translation>
-<translation id="3754634516926225076">Code PIN incorrect. Veuillez réessayer.</translation>
-<translation id="7378627244592794276">Non</translation>
-<translation id="2800537048826676660">Utiliser cette langue pour corriger l'orthographe</translation>
-<translation id="68541483639528434">Fermer les autres onglets</translation>
-<translation id="941543339607623937">Clé privée non valide.</translation>
-<translation id="6499058468232888609">Une erreur réseau s'est produite pendant la communication avec le service de gestion des périphériques.</translation>
-<translation id="4433862206975946675">Importer les données d'un autre navigateur...</translation>
-<translation id="4022426551683927403">&amp;Ajouter au dictionnaire</translation>
-<translation id="2897878306272793870">Voulez-vous vraiment ouvrir <ph name="TAB_COUNT"/> onglets ?</translation>
-<translation id="312759608736432009">Fabricant du périphérique :</translation>
-<translation id="362276910939193118">Afficher l'historique complet</translation>
-<translation id="6079696972035130497">Illimité</translation>
-<translation id="4365411729367255048">Clavier Neo2 allemand</translation>
-<translation id="6348657800373377022">Liste déroulante</translation>
-<translation id="8064671687106936412">Clé :</translation>
-<translation id="2218515861914035131">Coller en texte brut</translation>
-<translation id="1725149567830788547">Afficher les &amp;commandes</translation>
-<translation id="3528033729920178817">Cette page suit votre position géographique.</translation>
-<translation id="5518584115117143805">Certificat de chiffrement de courrier électronique</translation>
-<translation id="9203398526606335860">&amp;Profilage activé</translation>
-<translation id="4307281933914537745">En savoir plus sur la récupération du système</translation>
-<translation id="2849936225196189499">Essentielle</translation>
-<translation id="9001035236599590379">Type MIME</translation>
-<translation id="5612754943696799373">Autoriser le téléchargement ?</translation>
-<translation id="6353618411602605519">Clavier croate</translation>
-<translation id="5515810278159179124">Interdire à tous les sites de suivre ma position géographique</translation>
-<translation id="5999606216064768721">Utiliser la barre de titre du système et les bordures de la fenêtre</translation>
-<translation id="904752364881701675">En bas à gauche</translation>
-<translation id="3398951731874728419">Informations sur l'erreur :</translation>
-<translation id="1464570622807304272">Essayez : saisissez &quot;orchidées&quot;, puis appuyez sur Entrée.</translation>
-<translation id="8026684114486203427">Pour utiliser Chrome Web Store, vous devez être connecté à un compte Google.</translation>
-<translation id="8417276187983054885">Configurer <ph name="CLOUD_PRINT_NAME"/></translation>
-<translation id="3056462238804545033">Petit problème... Nous n'avons pas réussi à vous authentifier. Veuillez vérifier vos identifiants de connexion puis réessayer.</translation>
-<translation id="5298420986276701358">Pour gérer à distance la configuration de ce périphérique <ph name="PRODUCT_NAME"/> depuis le cloud, connectez-vous avec votre compte Google Apps.</translation>
-<translation id="2678063897982469759">Réactiver</translation>
-<translation id="1779766957982586368">Fermer la fenêtre</translation>
-<translation id="4850886885716139402">Présentation</translation>
-<translation id="89217462949994770">Vous avez saisi un trop grand nombre de codes PIN incorrects. Veuillez contacter <ph name="CARRIER_ID"/> pour obtenir une nouvelle clé de déverrouillage du code PIN à 8 chiffres.</translation>
-<translation id="5920618722884262402">Bloquer le contenu inapproprié</translation>
-<translation id="5120247199412907247">Configuration avancée</translation>
-<translation id="5922220455727404691">Utiliser SSL 3.0</translation>
-<translation id="1368352873613152012">Règles de confidentialité liées à la navigation sécurisée</translation>
-<translation id="5105859138906591953">Vous devez être connecté à votre compte Google pour importer les favoris de la barre d'outils Google dans Google Chrome. Connectez-vous et relancez l'importation.</translation>
-<translation id="8899851313684471736">Ouvrir le lien dans une nouvelle &amp;fenêtre</translation>
-<translation id="4110342520124362335">Les cookies de <ph name="DOMAIN"/> ont été bloqués.</translation>
-<translation id="3303818374450886607">Copies</translation>
-<translation id="2019718679933488176">&amp;Ouvrir le fichier audio dans un nouvel onglet</translation>
-<translation id="4138267921960073861">Afficher les noms d'utilisateurs et leur photo sur la page de connexion</translation>
-<translation id="7465778193084373987">URL de révocation de certificat Netscape</translation>
-<translation id="5976690834266782200">Ajoute des options de regroupement des onglets dans le menu contextuel des onglets.</translation>
-<translation id="4755240240651974342">Clavier finnois</translation>
-<translation id="7049893973755373474">Vérifiez votre connexion Internet. Redémarrez votre routeur, votre modem
- ou tout autre périphérique réseau que vous utilisez.</translation>
-<translation id="7421925624202799674">&amp;Afficher le code source de la page</translation>
-<translation id="3940082421246752453">Le serveur ne prend pas en charge la version HTTP utilisée dans la demande.</translation>
-<translation id="661719348160586794">Vos mots de passe enregistrés s'afficheront ici.</translation>
-<translation id="6686490380836145850">Fermer les onglets sur la droite</translation>
-<translation id="5608669887400696928"><ph name="NUMBER_DEFAULT"/> heures</translation>
-<translation id="8844709414456935411"><ph name="PRODUCT_NAME"/>
- indique qu'un produit ESET intercepte les connexions sécurisées.
- En général, cela ne constitue pas un problème de sécurité car le
- logiciel ESET s'exécute souvent sur le même ordinateur. Toutefois, en raison
- de certaines incompatibilités avec les connexions sécurisées
- <ph name="PRODUCT_NAME"/>,
- vous devez configurer les produits ESET de manière à éviter ces
- interceptions. Cliquez sur le lien En savoir plus pour obtenir des instructions.</translation>
-<translation id="3936877246852975078">Les requêtes adressées au serveur ont été temporairement limitées.</translation>
-<translation id="2600306978737826651">Impossible de télécharger l'image. Gravure annulée.</translation>
-<translation id="609978099044725181">Activer/désactiver le mode Hanja</translation>
-<translation id="1829483195200467833">Effacer les paramètres d'ouverture automatique</translation>
-<translation id="2738771556149464852">Pas après le</translation>
-<translation id="5774515636230743468">Manifeste :</translation>
-<translation id="719464814642662924">Visa</translation>
-<translation id="7474889694310679759">Clavier anglais canadien</translation>
-<translation id="1817871734039893258">Récupération de fichier Microsoft</translation>
-<translation id="2423578206845792524">En&amp;registrer l'image sous...</translation>
-<translation id="6839929833149231406">Zone</translation>
-<translation id="9068931793451030927">Chemin :</translation>
-<translation id="283278805979278081">Prendre la photo</translation>
-<translation id="7320906967354320621">Inactif</translation>
-<translation id="1407050882688520094">Certains de vos certificats enregistrés identifient ces autorités de certification :</translation>
-<translation id="4287689875748136217">Impossible d'afficher la page Web, car le serveur n'a envoyé aucune donnée.</translation>
-<translation id="1634788685286903402">Considérer ce certificat comme fiable pour identifier les utilisateurs de messageries.</translation>
-<translation id="7052402604161570346">Ce type de fichier peut endommager votre ordinateur. Voulez-vous vraiment télécharger <ph name="FILE_NAME"/> ?</translation>
-<translation id="8642489171979176277">Importés depuis la barre d'outils Google</translation>
-<translation id="4142744419835627535">Recherche instantanée et saisie semi-automatique</translation>
-<translation id="4684427112815847243">Tout synchroniser</translation>
-<translation id="1125520545229165057">Dvorak (Hsu)</translation>
-<translation id="8940229512486821554">Exécuter la commande <ph name="EXTENSION_NAME"/> : <ph name="SEARCH_TERMS"/></translation>
-<translation id="2232876851878324699">Le fichier contenait un certificat, qui n'a pas été importé :</translation>
-<translation id="7787129790495067395">Vous utilisez actuellement un mot de passe multiterme. Si vous l'oubliez, vous pouvez réinitialiser la synchronisation afin de supprimer vos données des serveurs Google à l'aide de Google Dashboard.</translation>
-<translation id="2686759344028411998">Impossible de détecter les modules chargés.</translation>
-<translation id="572525680133754531">Cette fonctionnalité affiche une bordure autour des couches de rendu afin de déboguer et d'étudier leur composition.</translation>
-<translation id="2011110593081822050">Processus de traitement Web : <ph name="WORKER_NAME"/></translation>
-<translation id="3294437725009624529">Invité</translation>
-<translation id="350069200438440499">Nom du fichier :</translation>
-<translation id="9058204152876341570">Un élément est manquant.</translation>
-<translation id="8494979374722910010">Échec de la tentative de connexion au serveur.</translation>
-<translation id="7810202088502699111">Des fenêtres pop-up ont été bloquées sur cette page.</translation>
-<translation id="8190698733819146287">Personnaliser les langues et la saisie...</translation>
-<translation id="646727171725540434">Proxy HTTP</translation>
-<translation id="1006316751839332762">Mot de passe multiterme de chiffrement</translation>
-<translation id="8795916974678578410">Nouvelle fenêtre</translation>
-<translation id="2733275712367076659">Certains certificats provenant de ces organisations vous identifient :</translation>
-<translation id="4801512016965057443">Autoriser l'itinérance des données mobiles</translation>
-<translation id="2515586267016047495">Alt</translation>
-<translation id="2046040965693081040">Utiliser les pages actuelles</translation>
-<translation id="3798449238516105146">Version</translation>
-<translation id="5764483294734785780">En&amp;registrer le fichier audio sous...</translation>
-<translation id="5252456968953390977">Itinérance</translation>
-<translation id="8744641000906923997">Romaji</translation>
-<translation id="8507996248087185956"><ph name="NUMBER_DEFAULT"/> minutes</translation>
-<translation id="4845656988780854088">Synchroniser uniquement les paramètres et\ndonnées qui ont changé depuis la dernière connexion\n(requiert votre mot de passe précédent)</translation>
-<translation id="348620396154188443">Autoriser tous les sites à afficher des notifications sur le Bureau</translation>
-<translation id="8214489666383623925">Ouvrir le fichier...</translation>
-<translation id="5376120287135475614">Changer de fenêtre</translation>
-<translation id="5230160809118287008">Chèvres téléportées</translation>
-<translation id="1701567960725324452">Si vous arrêtez la synchronisation, les données stockées sur cet ordinateur et dans votre compte Google demeureront à ces deux emplacements. Toutefois, les nouvelles données ou les modifications apportées au contenu existant ne seront pas synchronisées.</translation>
-<translation id="7761701407923456692">Le certificat du serveur ne correspond pas à l'URL.</translation>
-<translation id="3885155851504623709">Commune</translation>
-<translation id="4910171858422458941">Impossible d'activer les plug-ins désactivés par une stratégie d'entreprise.</translation>
-<translation id="4495419450179050807">Ne pas afficher sur cette page</translation>
-<translation id="4745800796303246012">Méthodes EAP en Wi-Fi expérimentales</translation>
-<translation id="1225544122210684390">Disque dur</translation>
-<translation id="939736085109172342">Nouveau dossier</translation>
-<translation id="4933484234309072027">intégration sur <ph name="URL"/></translation>
-<translation id="5554720593229208774">Autorité de certification de messagerie</translation>
-<translation id="862750493060684461">Cache CSS</translation>
-<translation id="2832519330402637498">En haut à gauche</translation>
-<translation id="6749695674681934117">Saisissez le nom du nouveau dossier.</translation>
-<translation id="6204994989617056362">L'extension de renégociation SSL était introuvable lors de la négociation sécurisée. Avec certains sites, connus pour leur prise en charge de l'extension de renégociation, Google Chrome exige une négociation mieux sécurisée afin de prévenir certaines attaques. L'absence de cette extension suggère que votre connexion a été interceptée et manipulée au cours du transfert.</translation>
-<translation id="6679492495854441399">Petit problème... Une erreur de communication avec le réseau est survenue lors de la tentative d'inscription de ce périphérique. Veuillez vérifier votre connexion réseau et réessayer.</translation>
-<translation id="7789962463072032349">pause</translation>
-<translation id="121827551500866099">Afficher tous les téléchargements...</translation>
-<translation id="1562633988311880769">Connexion à <ph name="CLOUD_PRINT_NAME"/></translation>
-<translation id="5949910269212525572">Impossible de résoudre l'adresse DNS du serveur.</translation>
-<translation id="3115147772012638511">En attente de l'affichage du cache</translation>
-<translation id="257088987046510401">Thèmes</translation>
-<translation id="6771079623344431310">Impossible de se connecter au serveur proxy.</translation>
-<translation id="2200129049109201305">Ignorer la synchronisation des données chiffrées ?</translation>
-<translation id="1426410128494586442">Oui</translation>
-<translation id="6468252175335241103">%b %-d, %Y</translation>
-<translation id="6725970970008349185">Nombre de suggestions par page</translation>
-<translation id="6198252989419008588">Modifier le code PIN</translation>
-<translation id="5749483996735055937">Un problème est survenu lors de la copie de l'image de récupération sur le périphérique.</translation>
-<translation id="3520476450377425184"><ph name="NUMBER_MANY"/> jours restants</translation>
-<translation id="7643817847124207232">La connexion Internet a été interrompue.</translation>
-<translation id="932327136139879170">Début</translation>
-<translation id="4764675709794295630">« Précédent</translation>
-<translation id="2560794850818211873">C&amp;opier l'URL de la vidéo</translation>
-<translation id="6042708169578999844">Vos données sur <ph name="WEBSITE_1"/> et <ph name="WEBSITE_2"/></translation>
-<translation id="5302048478445481009">Langue</translation>
-<translation id="5553089923092577885">Mappages des stratégies de certificat</translation>
-<translation id="5600907569873192868"><ph name="NUMBER_MANY"/> minutes restantes</translation>
-<translation id="1519704592140256923">Sélectionner la position</translation>
-<translation id="1275018677838892971">Le site Web à l'adresse <ph name="HOST_NAME"/> contient des éléments provenant de sites signalés comme étant des sites de phishing. Ces derniers incitent les internautes à divulguer leurs informations personnelles en se faisant passer pour des institutions de confiance, telles que des banques.</translation>
-<translation id="702455272205692181"><ph name="EXTENSION_NAME"/></translation>
-<translation id="7170041865419449892">Hors de portée</translation>
-<translation id="908263542783690259">Effacer l'historique de navigation</translation>
-<translation id="7518003948725431193">Aucune page Web trouvée à l'adresse :<ph name="URL"/></translation>
-<translation id="745602119385594863">Nouveau moteur de recherche :</translation>
-<translation id="7484645889979462775">Jamais pour ce site</translation>
-<translation id="8666066831007952346"><ph name="NUMBER_TWO"/> jours restants</translation>
-<translation id="9086455579313502267">Impossible d'accéder au réseau.</translation>
-<translation id="5595485650161345191">Modifier l'adresse</translation>
-<translation id="2374144379568843525">&amp;Masquer le panneau de la vérification orthographique</translation>
-<translation id="2694026874607847549">1 cookie</translation>
-<translation id="4393664266930911253">Activer ces fonctionnalités...</translation>
-<translation id="6390842777729054533"><ph name="NUMBER_ZERO"/> secondes restantes</translation>
-<translation id="3909791450649380159">Cou&amp;per</translation>
-<translation id="2955913368246107853">Fermer la barre de recherche</translation>
-<translation id="5642508497713047">Signataire de la liste de révocation de certificats</translation>
-<translation id="813082847718468539">Afficher des informations à propos du site</translation>
-<translation id="3122464029669770682">UC</translation>
-<translation id="1684861821302948641">Fermer les pages</translation>
-<translation id="6092270396854197260">MSPY</translation>
-<translation id="6802031077390104172"><ph name="USAGE"/> (<ph name="OID"/>)</translation>
-<translation id="4052120076834320548">Très petite</translation>
-<translation id="6623138136890659562">Afficher les réseaux privés dans le menu Réseau pour activer la connexion à un VPN</translation>
-<translation id="8969837897925075737">Vérification de la mise à jour du système...</translation>
-<translation id="3393716657345709557">L'entrée demandée est introuvable dans le cache.</translation>
-<translation id="7241389281993241388">Connectez-vous à <ph name="TOKEN_NAME"/> pour importer le certificat client.</translation>
-<translation id="40334469106837974">Modifier la mise en page</translation>
-<translation id="4804818685124855865">Se déconnecter</translation>
-<translation id="2617919205928008385">Espace insuffisant.</translation>
-<translation id="210445503571712769">Préférences synchronisées</translation>
-<translation id="1608306110678187802">Imp&amp;rimer le cadre...</translation>
-<translation id="7427315641433634153">MSCHAP</translation>
-<translation id="6622980291894852883">Continuer à bloquer les images</translation>
-<translation id="5937837224523037661">Lorsqu'un site utilise des plug-ins :</translation>
-<translation id="4988792151665380515">Échec d'exportation de la clé publique</translation>
-<translation id="6333049849394141510">Choisir les éléments à synchroniser</translation>
-<translation id="446322110108864323">Paramètres de saisie du Pinyin</translation>
-<translation id="4948468046837535074">Ouvrir les pages suivantes :</translation>
-<translation id="5222676887888702881">Déconnexion</translation>
-<translation id="6978121630131642226">Moteurs de recherche</translation>
-<translation id="6839225236531462745">Erreur de suppression de certificat</translation>
-<translation id="6745994589677103306">Ne rien faire</translation>
-<translation id="855081842937141170">Épingler l'onglet</translation>
-<translation id="6263541650532042179">réinitialiser la synchronisation</translation>
-<translation id="6055392876709372977">PKCS #1 SHA-256 avec chiffrement RSA</translation>
-<translation id="7903984238293908205">Katakana</translation>
-<translation id="3781488789734864345">Choisir un réseau mobile</translation>
-<translation id="268053382412112343">&amp;Historique</translation>
-<translation id="2723893843198727027">Mode développeur :</translation>
-<translation id="1722567105086139392">Lien</translation>
-<translation id="2620436844016719705">Système</translation>
-<translation id="5362741141255528695">Sélectionnez le fichier de clé privée.</translation>
-<translation id="5292890015345653304">Insérez une carte SD ou une carte mémoire USB.</translation>
-<translation id="5583370583559395927">Temps restant : <ph name="TIME_REMAINING"/></translation>
-<translation id="8065982201906486420">Cliquez ici pour exécuter le plug-in <ph name="PLUGIN_NAME"/>.</translation>
-<translation id="6219717821796422795">Hanyu</translation>
-<translation id="3725367690636977613">pages</translation>
-<translation id="2688477613306174402">Configuration en cours</translation>
-<translation id="1195447618553298278">Erreur inconnue</translation>
-<translation id="3353284378027041011"><ph name="NUMBER_FEW"/> days ago</translation>
-<translation id="8811462119186190367">La langue utilisée pour Google Chrome est passée de &quot;<ph name="FROM_LOCALE"/>&quot; à &quot;<ph name="TO_LOCALE"/>&quot; après la synchronisation de vos paramètres.</translation>
-<translation id="1087119889335281750">&amp;Aucune suggestion orthographique</translation>
-<translation id="5228309736894624122">Erreur de protocole SSL</translation>
-<translation id="8216170236829567922">Mode de saisie du thaï (clavier Pattachote)</translation>
-<translation id="8464132254133862871">Ce compte utilisateur n'est pas compatible avec ce service.</translation>
-<translation id="6812349420832218321"><ph name="PRODUCT_NAME"/> ne peut pas être exécuté en tant que root.</translation>
-<translation id="5076340679995252485">C&amp;oller</translation>
-<translation id="2904348843321044456">Paramètres de contenu...</translation>
-<translation id="1055216403268280980">Dimensions de l'image</translation>
-<translation id="1784284518684746740">Sélectionner le fichier à enregistrer sous</translation>
-<translation id="7032947513385578725">Disque Flash</translation>
-<translation id="5518442882456325299">Moteur de recherche actuel :</translation>
-<translation id="14171126816530869">L'identité de <ph name="ORGANIZATION"/> situé à <ph name="LOCALITY"/> a été vérifiée par <ph name="ISSUER"/>.</translation>
-<translation id="6263082573641595914">Version de l'autorité de certification Microsoft</translation>
-<translation id="3105917916468784889">Enregistrer une capture d'écran</translation>
-<translation id="1741763547273950878">Page sur <ph name="SITE"/></translation>
-<translation id="1587275751631642843">Console &amp;JavaScript</translation>
-<translation id="8460696843433742627">Réponse reçue incorrecte lors de la tentative de chargement de <ph name="URL"/>.
- Cela peut être dû à une opération de maintenance ou à une configuration incorrecte sur le serveur.</translation>
-<translation id="297870353673992530">Serveur DNS :</translation>
-<translation id="3222066309010235055">Pré-rendu : <ph name="PRERENDER_CONTENTS_NAME"/></translation>
-<translation id="6410063390789552572">Impossible d'accéder à la bibliothèque réseau.</translation>
-<translation id="6880587130513028875">Des images ont été bloquées sur cette page.</translation>
-<translation id="851263357009351303">Toujours autoriser <ph name="HOST"/> à afficher les images</translation>
-<translation id="3511307672085573050">Copier l'adr&amp;esse du lien</translation>
-<translation id="1134009406053225289">Ouvrir dans une fenêtre de navigation privée</translation>
-<translation id="6655190889273724601">Mode développeur</translation>
-<translation id="1071917609930274619">Chiffrement des données</translation>
-<translation id="3473105180351527598">Activer la protection contre le phishing et les logiciels malveillants</translation>
-<translation id="6151323131516309312">Appuyez sur <ph name="SEARCH_KEY"/> pour rechercher sur <ph name="SITE_NAME"/></translation>
-<translation id="3753317529742723206">Voulez-vous utiliser <ph name="HANDLER_TITLE"/> (<ph name="HANDLER_HOSTNAME"/>) au lieu de <ph name="REPLACED_HANDLER_TITLE"/> pour gérer les liens <ph name="PROTOCOL"/>:// à partir de maintenant ?</translation>
-<translation id="6216679966696797604">Démarrer une session en tant qu'invité</translation>
-<translation id="5456397824015721611">Nombre maximal de caractères chinois dans la mémoire tampon de pré-édition, notamment les entrées de symboles Zhuyin</translation>
-<translation id="2055443983279698110">Barre de menus GNOME expérimentale disponible</translation>
-<translation id="2342959293776168129">Effacer l'historique des téléchargements</translation>
-<translation id="2503522102815150840">Navigateur bloqué...</translation>
-<translation id="7201354769043018523">Parenthèse drte</translation>
-<translation id="425878420164891689">Calcul du temps de chargement</translation>
-<translation id="508794495705880051">Ajouter une carte de paiement...</translation>
-<translation id="1425975335069981043">Itinérance :</translation>
-<translation id="1272079795634619415">Arrêter</translation>
-<translation id="5442787703230926158">Erreur de synchronisation...</translation>
-<translation id="2462724976360937186">ID de clé de l'autorité de certification</translation>
-<translation id="6786747875388722282">Extensions</translation>
-<translation id="3944384147860595744">Imprimez où que vous soyez.</translation>
-<translation id="2570648609346224037">Un problème est survenu lors du téléchargement de l'image de récupération.</translation>
-<translation id="4306718255138772973">Cloud Print Proxy</translation>
-<translation id="9053965862400494292">Une erreur s'est produite lors de la configuration de la synchronisation.</translation>
-<translation id="8596540852772265699">Fichiers personnalisés</translation>
-<translation id="7017354871202642555">Impossible de définir le mode une fois la fenêtre créée.</translation>
-<translation id="3101709781009526431">Date et heure</translation>
-<translation id="69375245706918574">Personnaliser les préférences de synchronisation</translation>
-<translation id="833853299050699606">Aucune information disponible sur le forfait</translation>
-<translation id="1737968601308870607">Signaler un problème</translation>
-<translation id="4571852245489094179">Importer mes favoris et paramètres</translation>
-<translation id="99648783926443049">Sélectionnez le <ph name="BEGIN_BOLD"/>menu clé à molette &gt; Paramètres &gt; Options avancées &gt; Modifier les paramètres du proxy<ph name="END_BOLD"/> et vérifiez que vos paramètres sont définis sur &quot;sans proxy&quot; ou &quot;direct&quot;.</translation>
-<translation id="4421917670248123270">Fermer et annuler les téléchargements</translation>
-<translation id="5605623530403479164">Autres moteurs de recherche</translation>
-<translation id="8887243200615092733"><ph name="PRODUCT_NAME"/> peut maintenant synchroniser vos mots de passe. Pour protéger vos données, vous devez confirmer les informations relatives à votre compte.</translation>
-<translation id="4740663705480958372">Cette fonctionnalité active les API P2P Pepper et P2P JavaScript. L'API est en cours de développement et n'est pas encore opérationnelle.</translation>
-<translation id="5710435578057952990">L'identité de ce site Web n'a pas été vérifiée.</translation>
-<translation id="1421046588786494306">Sessions à l'étranger</translation>
-<translation id="1661245713600520330">Cette page répertorie tous les modules chargés dans le processus principal et les modules enregistrés de manière à être chargés ultérieurement.</translation>
-<translation id="5451646087589576080">Afficher les &amp;infos sur le cadre</translation>
-<translation id="3368922792935385530">Connecté</translation>
-<translation id="3498309188699715599">Paramètres d'entrée en Chewing</translation>
-<translation id="8486154204771389705">Conserver sur cette page</translation>
-<translation id="3866443872548686097">Votre support de récupération est prêt. Vous pouvez le retirer du système.</translation>
-<translation id="6824564591481349393">Copi&amp;er l'adresse e-mail</translation>
-<translation id="907148966137935206">Interdire à tous les sites d'afficher des fenêtres pop-up (recommandé)</translation>
-<translation id="5184063094292164363">Console &amp;JavaScript</translation>
-<translation id="333371639341676808">Empêcher cette page de générer des boîtes de dialogue supplémentaires</translation>
-<translation id="7632380866023782514">En haut à droite</translation>
-<translation id="4925520021222027859">Entrez le mot de passe associé à votre application :</translation>
-<translation id="3494768541638400973">Mode de saisie Google du japonais (pour clavier japonais)</translation>
-<translation id="5844183150118566785"><ph name="PRODUCT_NAME"/> est à jour (<ph name="VERSION"/>)</translation>
-<translation id="3118046075435288765">Le serveur a mis fin à la connexion de manière inattendue.</translation>
-<translation id="8041140688818013446">Il est possible que le serveur hébergeant la page Web soit surchargé ou ait rencontré une erreur. Pour éviter de générer
- trop de trafic et d'aggraver la situation,
- <ph name="PRODUCT_NAME"/> a temporairement
- bloqué l'acceptation des requêtes adressées au serveur.
- <ph name="LINE_BREAK"/>
- Si vous pensez que ce comportement n'est pas souhaitable, (par exemple, dans le cas où vous déboguez votre propre site Web), vous pouvez
- consulter la page <ph name="NET_INTERNALS_PAGE"/>,
- sur laquelle vous pourrez trouver plus d'informations ou désactiver cette fonctionnalité.</translation>
-<translation id="1725068750138367834">Gestionnaire de &amp;fichiers</translation>
-<translation id="4254921211241441775">Arrêter la synchronisation du compte</translation>
-<translation id="7791543448312431591">Ajouter</translation>
-<translation id="8569764466147087991">Sélectionnez le fichier à ouvrir</translation>
-<translation id="5449451542704866098">Aucun forfait de données</translation>
-<translation id="307505906468538196">Créer un compte Google</translation>
-<translation id="2053553514270667976">Code postal</translation>
-<translation id="48838266408104654">&amp;Gestionnaire de tâches</translation>
-<translation id="4378154925671717803">Téléphone</translation>
-<translation id="3694027410380121301">Sélectionner l'onglet précédent</translation>
-<translation id="6178664161104547336">Sélectionner un certificat</translation>
-<translation id="1375321115329958930">Mots de passe enregistrés</translation>
-<translation id="3341703758641437857">Autoriser l'accès aux URL de fichier</translation>
-<translation id="5702898740348134351">Modifi&amp;er les moteurs de recherche...</translation>
-<translation id="734303607351427494">Gérer les moteurs de recherche...</translation>
-<translation id="8326478304147373412">PKCS #7, chaîne de certificats</translation>
-<translation id="3242765319725186192">Clé pré-partagée :</translation>
-<translation id="8089798106823170468">Contrôlez et partagez l'accès à vos imprimantes depuis n'importe quel compte Google.</translation>
-<translation id="5984992849064510607">Ajoute l'option &quot;Utiliser les onglets latéraux&quot; au menu contextuel de la barre d'onglets. Utilisez cette option pour déplacer les onglets du haut de l'écran (affichage par défaut) vers le côté. Particulièrement utile sur les grands écrans.</translation>
-<translation id="839736845446313156">S'inscrire</translation>
-<translation id="4668929960204016307">,</translation>
-<translation id="2409527877874991071">Saisissez un nouveau nom.</translation>
-<translation id="4240069395079660403"><ph name="PRODUCT_NAME"/> ne peut pas être affiché dans cette langue.</translation>
-<translation id="747114903913869239">Erreur : impossible de décoder l'extension.</translation>
-<translation id="5412637665001827670">Clavier bulgare</translation>
-<translation id="2113921862428609753">Accès aux informations de l'autorité</translation>
-<translation id="5227536357203429560">Ajouter un réseau privé...</translation>
-<translation id="732677191631732447">C&amp;opier l'URL du fichier audio</translation>
-<translation id="7224023051066864079">Masque de sous-réseau :</translation>
-<translation id="2401813394437822086">Impossible d'accéder à votre compte ?</translation>
-<translation id="2344262275956902282">Utiliser les touches - et = pour paginer une liste d'entrées</translation>
-<translation id="3609138628363401169">Le serveur ne prend pas en charge l'extension de renégociation TLS.</translation>
-<translation id="3369624026883419694">Résolution de l'hôte...</translation>
-<translation id="8870413625673593573">Récemment fermés</translation>
-<translation id="9145357542626308749">Le certificat de sécurité du site a été signé avec un algorithme de signature faible.</translation>
-<translation id="8502803898357295528">Votre mot de passe a été modifié</translation>
-<translation id="4064488613268730704">Gérer les paramètres de saisie automatique...</translation>
-<translation id="6830600606572693159">La page Web <ph name="URL"/> n'est pas disponible pour le moment. Cela peut être dû à une surcharge ou à une opération de maintenance.</translation>
-<translation id="4145797339181155891">Éjecter</translation>
-<translation id="7886793013438592140">Impossible de lancer le processus de service.</translation>
-<translation id="8417944620073548444"><ph name="MEGABYTES"/> Mo restants</translation>
-<translation id="7339898014177206373">Nouvelle fenêtre</translation>
-<translation id="3026202950002788510">Sélectionnez
- <ph name="BEGIN_BOLD"/>
- Applications &gt; Préférences système &gt; Réseau &gt; Avancé &gt; Proxys
- <ph name="END_BOLD"/>
- et désélectionnez les serveurs proxy sélectionnés.</translation>
-<translation id="7033648024564583278">Gravure en cours d'initialisation...</translation>
-<translation id="2246340272688122454">Téléchargement de l'image de récupération...</translation>
-<translation id="7770995925463083016">il y a <ph name="NUMBER_TWO"/> minutes</translation>
-<translation id="2816269189405906839">Mode de saisie du chinois (cangjie)</translation>
-<translation id="7087282848513945231">Comté</translation>
-<translation id="2149951639139208969">Ouvrir l'adresse dans un nouvel onglet</translation>
-<translation id="175196451752279553">&amp;Rouvrir l'onglet fermé</translation>
-<translation id="5992618901488170220">Impossible d'afficher la page Web, car votre ordinateur est passé en mode
- veille ou hibernation. Dans ce cas, les connexions réseau sont
- coupées et les requêtes réseau échouent. L'actualisation de la page
- devrait permettre de résoudre ce problème.</translation>
-<translation id="2655386581175833247">Certificat utilisateur :</translation>
-<translation id="5039804452771397117">Autoriser</translation>
-<translation id="5435964418642993308">Appuyer sur Entrée pour revenir en arrière et sur la touche de menu contextuel pour afficher l'historique</translation>
-<translation id="81686154743329117">ZRM</translation>
-<translation id="7564146504836211400">Cookies et autres données</translation>
-<translation id="2266011376676382776">Page(s) ne répondant pas</translation>
-<translation id="2714313179822741882">Paramètres d'entrée hangûl</translation>
-<translation id="8658163650946386262">Configurer la synchronisation...</translation>
-<translation id="3100609564180505575">Modules (<ph name="TOTAL_COUNT"/>). Conflits connus : <ph name="BAD_COUNT"/>, conflits probables : <ph name="SUSPICIOUS_COUNT"/></translation>
-<translation id="3627671146180677314">Date de renouvellement du certificat Netscape</translation>
-<translation id="1319824869167805246">Ouvrir tous les favoris dans une nouvelle fenêtre</translation>
-<translation id="8652487083013326477">bouton radio concernant l'étendue de pages</translation>
-<translation id="5204967432542742771">Saisissez votre mot de passe</translation>
-<translation id="4388712255200933062"><ph name="CLOUD_PRINT_NAME"/> est conçu pour rendre l'impression plus intuitive, accessible et utile. <ph name="CLOUD_PRINT_NAME"/> vous permet de rendre vos imprimantes accessibles depuis n'importe quelle application Web ou mobile associée à <ph name="CLOUD_PRINT_NAME"/>.</translation>
-<translation id="2932611376188126394">Dictionnaire de kanji unique</translation>
-<translation id="5485754497697573575">Rétablir tous les onglets</translation>
-<translation id="3371861036502301517">Échec de l'installation de l'extension</translation>
-<translation id="644038709730536388">En savoir plus sur la manière de se protéger des logiciels malveillants en ligne</translation>
-<translation id="2155931291251286316">Toujours afficher les fenêtres pop-up de <ph name="HOST"/></translation>
-<translation id="3445830502289589282">Authentification phase 2 :</translation>
-<translation id="5650551054760837876">Aucun résultat de recherche trouvé</translation>
-<translation id="5494362494988149300">Ouvrir une fois le téléchargement &amp;terminé</translation>
-<translation id="2956763290572484660"><ph name="COOKIES"/> cookies</translation>
-<translation id="6989836856146457314">Mode de saisie du japonais (pour clavier américain)</translation>
-<translation id="9187787570099877815">Continuer à bloquer les plug-ins</translation>
-<translation id="8425492902634685834">Épingler sur la barre des tâches</translation>
-<translation id="825608351287166772">Les certificats ont une période de validité, comme tous les documents relatifs à votre identité (tel qu'un passeport). Le certificat présenté à votre navigateur n'est pas encore valide ! Lorsqu'un certificat est en dehors de sa période de validité, il n'est pas nécessaire d'assurer la maintenance de certaines informations relatives à son état (s'il a été révoqué ou s'il n'est plus approuvé). Par conséquent, il est impossible de vérifier que le certificat est fiable. Ne poursuivez pas.</translation>
-<translation id="741630086309232721">Fermer la session d'invité</translation>
-<translation id="7309459761865060639">Contrôlez vos tâches d'impression et l'état de connexion de vos imprimantes en ligne.</translation>
-<translation id="4803909571878637176">Désinstallation</translation>
-<translation id="5209518306177824490">Empreinte SHA-1</translation>
-<translation id="3300768886937313568">Modifier le code PIN de la carte SIM</translation>
-<translation id="7447657194129453603">État du réseau :</translation>
-<translation id="1553538517812678578">sans limite</translation>
-<translation id="7947315300197525319">(Choisir une autre capture d'écran)</translation>
-<translation id="3612070600336666959">Désactivation</translation>
-<translation id="3759461132968374835">Aucune erreur n'a été signalée récemment. Les erreurs n'apparaissent ici que lorsque l'envoi de rapports d'erreur est activé.</translation>
-<translation id="1516602185768225813">Rouvrir les dernières pages ouvertes</translation>
-<translation id="189210018541388520">Ouvrir en mode plein écran</translation>
-<translation id="8795668016723474529">Ajouter une carte de paiement</translation>
-<translation id="5860033963881614850">Désactivé</translation>
-<translation id="3956882961292411849">Chargement des informations sur votre forfait Internet mobile, veuillez patienter...</translation>
-<translation id="689050928053557380">Acheter un forfait de données...</translation>
-<translation id="4235618124995926194">Inclure cet e-mail :</translation>
-<translation id="4874539263382920044">Le titre doit comporter au moins un caractère.</translation>
-<translation id="798525203920325731">Espaces de noms réseau</translation>
-<translation id="263325223718984101"><ph name="PRODUCT_NAME"/> n'a pas pu terminer l'installation, mais va poursuivre son exécution à partir de son image disque.</translation>
-<translation id="7025190659207909717">Gestion des services Internet mobiles</translation>
-<translation id="8265096285667890932">Utiliser les onglets latéraux</translation>
-<translation id="4250680216510889253">Non</translation>
-<translation id="3949593566929137881">Saisir le code PIN de la carte SIM</translation>
-<translation id="6291953229176937411">&amp;Afficher dans le Finder</translation>
-<translation id="2476990193835943955">Maintenez la touche Ctrl, Alt ou Maj enfoncée&lt;br&gt;pour afficher le raccourci clavier qui lui est associé.</translation>
-<translation id="9187827965378254003">Vraiment désolé, aucun prototype n'est disponible pour le moment.</translation>
-<translation id="8933960630081805351">&amp;Afficher dans le Finder</translation>
-<translation id="3041612393474885105">Informations relatives au certificat</translation>
-<translation id="7378810950367401542">/</translation>
-<translation id="4611079913162790275">La synchronisation des mots de passe requiert votre attention.</translation>
-<translation id="6562758426028728553">Veuillez saisir l'ancien et le nouveau code PIN.</translation>
-<translation id="614161640521680948">Langue :</translation>
-<translation id="3665650519256633768">Résultats de recherche</translation>
-<translation id="3733127536501031542">Serveur SSL avec fonction d'optimisation</translation>
-<translation id="3614837889828516995">Enregistrer en PDF</translation>
-<translation id="5745056705311424885">Mémoire USB détectée</translation>
-<translation id="5895875028328858187">M'avertir lorsque le flux de données est faible ou presque inexistant</translation>
-<translation id="939598580284253335">Saisir le mot de passe multiterme</translation>
-<translation id="7917972308273378936">Clavier lituanien</translation>
-<translation id="8371806639176876412">Les éléments saisis dans le champ polyvalent peuvent être enregistrés.</translation>
-<translation id="4216499942524365685">Les informations de connexion à votre compte sont obsolètes. Cliquez ici pour saisir à nouveau votre mot de passe.</translation>
-<translation id="8899388739470541164">Vietnamien</translation>
-<translation id="4091434297613116013">feuilles de papier</translation>
-<translation id="7475671414023905704">URL de mot de passe perdu Netscape</translation>
-<translation id="3335947283844343239">Rouvrir l'onglet fermé</translation>
-<translation id="4089663545127310568">Effacer les mots de passe enregistrés</translation>
-<translation id="6500444002471948304">Créer un nouveau dossier...</translation>
-<translation id="2480626392695177423">Basculer en mode ponctuation pleine chasse ou demi-chasse</translation>
-<translation id="5830410401012830739">Gérer les paramètres de localisation...</translation>
-<translation id="8977410484919641907">Synchronisé...</translation>
-<translation id="2794293857160098038">Options de recherche par défaut</translation>
-<translation id="3947376313153737208">Aucune sélection</translation>
-<translation id="1346104802985271895">Mode de saisie du vietnamien (TELEX)</translation>
-<translation id="5935630983280450497"><ph name="NUMBER_ONE"/> minute restante</translation>
-<translation id="5889282057229379085">Le nombre maximal d'autorités de certification intermédiaires a été dépassé : <ph name="NUM_INTERMEDIATE_CA"/></translation>
-<translation id="3180365125572747493">Saisissez un mot de passe pour chiffrer ce fichier de certificat.</translation>
-<translation id="5496587651328244253">Organiser</translation>
-<translation id="4821086771593057290">Votre mot de passe a changé. Veuillez réessayer avec votre nouveau mot de passe.</translation>
-<translation id="7075513071073410194">PKCS #1 MD5 avec chiffrement RSA</translation>
-<translation id="4378727699507047138">Utiliser le thème classique</translation>
-<translation id="7124398136655728606">Échap efface toute la mémoire tampon de pré-édition</translation>
-<translation id="8293206222192510085">Ajouter aux favoris</translation>
-<translation id="2592884116796016067">Un incident est survenu sur une partie de cette page (HTML WebWorker). Elle risque de ne pas fonctionner correctement.</translation>
-<translation id="2529133382850673012">Clavier américain</translation>
-<translation id="4411578466613447185">Signataire de code</translation>
-<translation id="1354868058853714482">Adobe Reader n'est pas à jour et risque de ne plus être sécurisé.</translation>
-<translation id="6252594924928912846">Personnaliser les paramètres de synchronisation...</translation>
-<translation id="8425755597197517046">Co&amp;ller et rechercher</translation>
-<translation id="1093148655619282731">Détails du certificat sélectionné :</translation>
-<translation id="5568069709869097550">Impossible de se connecter</translation>
-<translation id="2743322561779022895">Activation :</translation>
-<translation id="4181898366589410653">Système de révocation introuvable dans le certificat du serveur</translation>
-<translation id="8705331520020532516">Numéro de série</translation>
-<translation id="1665770420914915777">Afficher la page &quot;Nouvel onglet&quot;</translation>
-<translation id="2629089419211541119">il y a <ph name="NUMBER_ONE"/> heure</translation>
-<translation id="1691063574428301566">Votre ordinateur redémarrera une fois la mise à jour effectuée.</translation>
-<translation id="131364520783682672">Verr. maj.</translation>
-<translation id="6259308910735500867">L'accès au répertoire de l'hôte de communication à distance a été refusé. Essayez avec un autre compte.</translation>
-<translation id="3415261598051655619">Accessible aux scripts :</translation>
-<translation id="2335122562899522968">Cette page place des cookies.</translation>
-<translation id="3786100282288846904">Impossible de supprimer &quot;$1&quot; : $2</translation>
-<translation id="8461914792118322307">Proxy</translation>
-<translation id="4089521618207933045">Avec sous-menu</translation>
-<translation id="1936157145127842922">Afficher dans le dossier</translation>
-<translation id="6982279413068714821">il y a <ph name="NUMBER_DEFAULT"/> minutes</translation>
-<translation id="7977590112176369853">&lt;saisir une requête&gt;</translation>
-<translation id="3449839693241009168">Appuyez sur <ph name="SEARCH_KEY"/> pour envoyer des commandes à <ph name="EXTENSION_NAME"/>.</translation>
-<translation id="7443484992065838938">Prévisualiser le rapport</translation>
-<translation id="5714678912774000384">Activer le dernier onglet</translation>
-<translation id="3799598397265899467">Lorsque je quitte le navigateur</translation>
-<translation id="2125314715136825419">Continuer sans mettre à jour Adobe Reader (non recommandé)</translation>
-<translation id="1120026268649657149">Le champ de mot clé doit être vide ou comporter un mot unique</translation>
-<translation id="542318722822983047">Déplacer le curseur automatiquement au caractère suivant</translation>
-<translation id="5317780077021120954">Enregistrer</translation>
-<translation id="9027459031423301635">Ouvrir le lien dans un nouvel ongle&amp;t</translation>
-<translation id="2251809247798634662">Nouvelle fenêtre de navigation privée</translation>
-<translation id="358344266898797651">Celtique</translation>
-<translation id="3625870480639975468">Réinitialiser le zoom</translation>
-<translation id="5199729219167945352">Prototypes</translation>
-<translation id="5055518462594137986">Mémoriser mes choix pour tous les liens de ce type</translation>
-<translation id="246059062092993255">Les plug-ins de cette page ont été bloqués.</translation>
-<translation id="2870560284913253234">Site</translation>
-<translation id="6945221475159498467">Sélectionner</translation>
-<translation id="7724603315864178912">Couper</translation>
-<translation id="4164507027399414915">Restaurer toutes les miniatures supprimées</translation>
-<translation id="917051065831856788">Utiliser les onglets latéraux</translation>
-<translation id="1976150099241323601">Se connecter au dispositif de sécurité</translation>
-<translation id="6620110761915583480">Enregistrer le fichier</translation>
-<translation id="4988526792673242964">Pages</translation>
-<translation id="7543025879977230179">Options de <ph name="PRODUCT_NAME"/></translation>
-<translation id="2175607476662778685">Barre de lancement rapide</translation>
-<translation id="6434309073475700221">Annuler</translation>
-<translation id="1367951781824006909">Choisir un fichier</translation>
-<translation id="1425127764082410430">&amp;Rechercher <ph name="SEARCH_TERMS"/> avec <ph name="SEARCH_ENGINE"/></translation>
-<translation id="684265517037058883">(pas encore valide)</translation>
-<translation id="2027538664690697700">Mettre à jour le plug-in...</translation>
-<translation id="8205333955675906842">Police Sans-Serif</translation>
-<translation id="39964277676607559">Impossible de charger le JavaScript &quot;<ph name="RELATIVE_PATH"/>&quot; du script de contenu.</translation>
-<translation id="4378551569595875038">Connexion...</translation>
-<translation id="7029809446516969842">Mots de passe</translation>
-<translation id="8053278772142718589">Fichiers PKCS #12</translation>
-<translation id="3129020372442395066">Options de saisie automatique de <ph name="PRODUCT_NAME_SHORT"/></translation>
-<translation id="4114360727879906392">Fenêtre précédente</translation>
-<translation id="8238649969398088015">Astuce</translation>
-<translation id="5958418293370246440"><ph name="SAVED_FILES"/> / <ph name="TOTAL_FILES"/> fichiers</translation>
-<translation id="2350172092385603347">Localisation utilisée, mais les paramètres régionaux par défaut (default_locale) n'ont pas été indiqués dans le manifeste. </translation>
-<translation id="8221729492052686226">Si vous n'êtes pas à l'origine de cette requête, il s'agit probablement d'une attaque contre votre système. Si vous n'avez pas lancé cette requête de manière intentionnelle, cliquez sur Ne rien faire.</translation>
-<translation id="5894314466642127212">Votre commentaire a bien été envoyé.</translation>
-<translation id="894360074127026135">Fonction d'optimisation internationale Netscape </translation>
-<translation id="6025294537656405544">Taille de police minimale</translation>
-<translation id="1201402288615127009">Suivant</translation>
-<translation id="1335588927966684346">Utilitaire :</translation>
-<translation id="7857823885309308051">Cette opération peut prendre une minute...</translation>
-<translation id="662870454757950142">Le format du mot de passe est incorrect.</translation>
-<translation id="370665806235115550">Chargement...</translation>
-<translation id="1808792122276977615">Ajouter la page...</translation>
-<translation id="2076269580855484719">Masquer ce plug-in</translation>
-<translation id="254416073296957292">&amp;Paramètres linguistiques...</translation>
-<translation id="6652975592920847366">Créer un support de récupération du système d'exploitation</translation>
-<translation id="52912272896845572">Le fichier de clé privée est incorrect.</translation>
-<translation id="3232318083971127729">Valeur :</translation>
-<translation id="8807632654848257479">Stable</translation>
-<translation id="4209092469652827314">Grande</translation>
-<translation id="4222982218026733335">Certificat serveur invalide</translation>
-<translation id="152234381334907219">Jamais enregistrés</translation>
-<translation id="5600599436595580114">Cette page a été préchargée.</translation>
-<translation id="8926468725336609312">Google Chrome ne peut pas afficher l'aperçu avant impression lorsque la visionneuse de documents PDF intégrée est désactivée. Pour l'afficher, veuillez accéder à <ph name="BEGIN_LINK"/>chrome://plugins<ph name="END_LINK"/>, activer &quot;Chrome PDF Viewer&quot; et réessayer.</translation>
-<translation id="8494214181322051417">Nouveau !</translation>
-<translation id="7762841930144642410"><ph name="BEGIN_BOLD"/>Vous êtes passé en navigation privée<ph name="END_BOLD"/>. Les pages que vous consultez dans cette fenêtre n'apparaîtront ni dans l'historique de votre navigateur, ni dans l'historique des recherches, et ne laisseront aucune trace (comme les cookies) sur votre ordinateur une fois que vous aurez fermé la fenêtre de navigation privée. Tous les fichiers téléchargés et les favoris créés seront toutefois conservés. <ph name="LINE_BREAK"/> <ph name="BEGIN_BOLD"/>Passer en navigation privée n'a aucun effet sur les autres utilisateurs, serveurs ou logiciels. Méfiez-vous :<ph name="END_BOLD"/> <ph name="BEGIN_LIST"/> <ph name="BEGIN_LIST_ITEM"/>Des sites Web qui collectent ou partagent des informations vous concernant<ph name="END_LIST_ITEM"/> <ph name="BEGIN_LIST_ITEM"/>Des fournisseurs d'accès Internet ou des employeurs qui conservent une trace des pages que vous visitez<ph name="END_LIST_ITEM"/> <ph name="BEGIN_LIST_ITEM"/>Des programmes indésirables qui enregistrent vos frappes en échange d'émoticônes gratuites<ph name="END_LIST_ITEM"/> <ph name="BEGIN_LIST_ITEM"/>Des personnes qui pourraient surveiller vos activités<ph name="END_LIST_ITEM"/> <ph name="BEGIN_LIST_ITEM"/>Des personnes qui se tiennent derrière vous<ph name="END_LIST_ITEM"/> <ph name="END_LIST"/> <ph name="BEGIN_LINK"/>En savoir plus sur la navigation privée<ph name="END_LINK"/></translation>
-<translation id="2386255080630008482">Le certificat du serveur a été révoqué.</translation>
-<translation id="2135787500304447609">&amp;Reprendre</translation>
-<translation id="8309505303672555187">Sélectionnez un réseau :</translation>
-<translation id="6143635259298204954">Impossible d'extraire les fichiers de l'extension. Pour effectuer cette opération en toute sécurité, vous devez disposer d'un chemin d'accès à votre répertoire de profils ne contenant pas de lien symbolique. Aucun chemin de ce type n'existe pour votre profil.</translation>
-<translation id="1813414402673211292">Effacer les données de navigation</translation>
-<translation id="4062903950301992112">Si vous êtes conscient que la visite de ce site peut être préjudiciable à votre ordinateur, vous pouvez <ph name="PROCEED_LINK"/>.</translation>
-<translation id="32330993344203779">Votre périphérique est inscrit pour bénéficier de la gestion d'entreprise.</translation>
-<translation id="2356762928523809690">Serveur de mise à jour non disponible (erreur : <ph name="ERROR_NUMBER"/>)</translation>
-<translation id="219008588003277019">Module client natif : <ph name="NEXE_NAME"/></translation>
-<translation id="5436510242972373446">Rechercher sur <ph name="SITE_NAME"/> :</translation>
-<translation id="3800764353337460026">Style de symboles</translation>
-<translation id="6719684875142564568"><ph name="NUMBER_ZERO"/> hours</translation>
-<translation id="2096368010154057602">Département</translation>
-<translation id="1036561994998035917">Continuer à utiliser <ph name="ENGINE_NAME"/></translation>
-<translation id="8730621377337864115">OK</translation>
-<translation id="665757950158579497">Essayez de désactiver les prédictions d'actions du réseau en procédant comme suit :
- Sélectionnez le
- <ph name="BEGIN_BOLD"/>
- menu clé à molette &gt;
- <ph name="SETTINGS_TITLE"/>
- &gt;
- <ph name="ADVANCED_TITLE"/>
- <ph name="END_BOLD"/>
- et désélectionnez &quot;<ph name="NO_PREFETCH_DESCRIPTION"/>&quot;.
- Si le problème n'est pas résolu, nous vous conseillons de sélectionner de nouveau
- cette option pour améliorer les performances.</translation>
-<translation id="4932733599132424254">Date</translation>
-<translation id="6267166720438879315">Sélectionnez un certificat pour vous authentifier sur <ph name="HOST_NAME"/>.</translation>
-<translation id="2422927186524098759">Barre latérale</translation>
-<translation id="7839809549045544450">La clé publique éphémère Diffie-Hellman associée au serveur est peu sûre.</translation>
-<translation id="5515806255487262353">Rechercher dans Dictionnaire</translation>
-<translation id="350048665517711141">Sélectionnez un moteur de recherche</translation>
-<translation id="2790805296069989825">Clavier russe</translation>
-<translation id="5708171344853220004">Nom Microsoft principal</translation>
-<translation id="5464696796438641524">Clavier polonais</translation>
-<translation id="2080010875307505892">Clavier serbe</translation>
-<translation id="2953767478223974804"><ph name="NUMBER_ONE"/> minute</translation>
-<translation id="201192063813189384">Erreur lors de la lecture des données du cache.</translation>
-<translation id="7851768487828137624">Canary</translation>
-<translation id="6129938384427316298">Commentaire du certificat Netscape</translation>
-<translation id="8210608804940886430">Page suivante</translation>
-<translation id="9065596142905430007"><ph name="PRODUCT_NAME"/> est à jour.</translation>
-<translation id="1035650339541835006">Paramètres de saisie automatique...</translation>
-<translation id="6315493146179903667">Tout ramener au premier plan</translation>
-<translation id="1000498691615767391">Sélectionner le dossier à ouvrir</translation>
-<translation id="3593152357631900254">Activer le mode Pinyin fuzzy</translation>
-<translation id="5015344424288992913">Résolution du proxy...</translation>
-<translation id="8506299468868975633">Le téléchargement de l'image a été interrompu.</translation>
-<translation id="4724168406730866204">Eten 26</translation>
-<translation id="308268297242056490">URI</translation>
-<translation id="4479812471636796472">Clavier Dvorak américain</translation>
-<translation id="8673026256276578048">Rechercher sur le Web...</translation>
-<translation id="1437307674059038925">Si vous utilisez un serveur proxy, vérifiez les paramètres associés ou demandez à votre administrateur réseau
- si ce serveur fonctionne.</translation>
-<translation id="149347756975725155">Impossible de charger l'icône de l'extension &quot;<ph name="ICON"/>&quot;.</translation>
-<translation id="3675321783533846350">Définir un proxy pour se connecter au réseau</translation>
-<translation id="5451285724299252438">zone de texte concernant l'étendue de pages</translation>
-<translation id="5669267381087807207">Activation</translation>
-<translation id="7434823369735508263">Clavier Dvorak britannique</translation>
-<translation id="1572103024875503863"><ph name="NUMBER_MANY"/> jours</translation>
-<translation id="2084978867795361905">MS-IME</translation>
-<translation id="7227669995306390694">Aucun forfait de données <ph name="NETWORK"/></translation>
-<translation id="3481915276125965083">Les fenêtres pop-up suivantes ont été bloquées sur cette page :</translation>
-<translation id="7163503212501929773"><ph name="NUMBER_MANY"/> heures restantes</translation>
-<translation id="7705276765467986571">Impossible de charger le modèle du favori.</translation>
-<translation id="1196338895211115272">Échec d'exportation de la clé privée</translation>
-<translation id="5586329397967040209">Utiliser comme page d'accueil</translation>
-<translation id="629730747756840877">Compte</translation>
-<translation id="8525306231823319788">Plein écran</translation>
-<translation id="9054208318010838">Autoriser tous les sites à suivre ma position géographique</translation>
-<translation id="3058212636943679650">Si la restauration du système d'exploitation de votre ordinateur s'avère nécessaire, une carte SD ou une clé USB de récupération vous sera demandée.</translation>
-<translation id="2815382244540487333">Les cookies suivants ont été bloqués :</translation>
-<translation id="8882395288517865445">Inclure les adresses de ma fiche de Carnet d’adresses</translation>
-<translation id="374530189620960299">Le certificat de sécurité du site n'est pas approuvé !</translation>
-<translation id="8852407435047342287">Votre liste d'applications, d'extensions et de thèmes installés</translation>
-<translation id="5647283451836752568">Exécuter tous les plug-ins de cette page</translation>
-<translation id="8642947597466641025">Augmente la taille du texte</translation>
-<translation id="5188181431048702787">Accepter et continuer »</translation>
-<translation id="1293556467332435079">Fichiers
-</translation>
-<translation id="2490270303663597841">Appliquer uniquement à cette session de navigation privée</translation>
-<translation id="1757915090001272240">Latin large</translation>
-<translation id="8496717697661868878">Exécuter ce plug-in</translation>
-<translation id="3450660100078934250">MasterCard</translation>
-<translation id="2916073183900451334">Sur le Web, Tab permet de sélectionner les liens, ainsi que les champs de formulaire.</translation>
-<translation id="7772127298218883077">À propos de <ph name="PRODUCT_NAME"/></translation>
-<translation id="2090876986345970080">Paramètres de sécurité du système</translation>
-<translation id="9219103736887031265">Images</translation>
-<translation id="5453632173748266363">Cyrillique</translation>
-<translation id="1008557486741366299">Pas maintenant</translation>
-<translation id="8415351664471761088">Attendre la fin du téléchargement</translation>
-<translation id="1545775234664667895">Thème &quot;<ph name="THEME_NAME"/>&quot; installé</translation>
-<translation id="5329858601952122676">&amp;Supprimer</translation>
-<translation id="6100736666660498114">Menu Démarrer</translation>
-<translation id="3994878504415702912">&amp;Zoom</translation>
-<translation id="9009369504041480176">Transfert en cours (<ph name="PROGRESS_PERCENT"/> %)...</translation>
-<translation id="8995603266996330174">Géré par <ph name="DOMAIN"/></translation>
-<translation id="5602600725402519729">&amp;Rafraîchir</translation>
-<translation id="172612876728038702">Configuration du module de plate-forme sécurisée (TPM) en cours. Veuillez patienter, cela peut prendre quelques minutes.</translation>
-<translation id="1362165759943288856">Vous avez acheté une quantité illimitée de données le <ph name="DATE"/>.</translation>
-<translation id="2078019350989722914">Confirmer avant de quitter (<ph name="KEY_EQUIVALENT"/>)</translation>
-<translation id="7965010376480416255">Mémoire partagée</translation>
-<translation id="6248988683584659830">Rech. dans les paramètres</translation>
-<translation id="8323232699731382745">mot de passe d'accès au réseau</translation>
-<translation id="6588399906604251380">Activer la vérification orthographique</translation>
-<translation id="7167621057293532233">Types de données</translation>
-<translation id="7053983685419859001">Bloquer</translation>
-<translation id="2485056306054380289">Certificat de l'autorité de certification du serveur :</translation>
-<translation id="6462109140674788769">Clavier grec</translation>
-<translation id="2727712005121231835">Taille réelle</translation>
-<translation id="8887733174653581061">Toujours en haut</translation>
-<translation id="5581211282705227543">Aucun plug-in installé.</translation>
-<translation id="610886263749567451">Alerte JavaScript</translation>
-<translation id="5488468185303821006">Autoriser en mode navigation privée</translation>
-<translation id="6556866813142980365">Rétablir</translation>
-<translation id="2107287771748948380"><ph name="OBFUSCATED_CC_NUMBER"/>, expire le : <ph name="CC_EXPIRATION_DATE"/></translation>
-<translation id="6584811624537923135">Confirmer la désinstallation</translation>
-<translation id="7429235532957570505">Impossible de désactiver les plug-ins ayant été activés par une stratégie d'entreprise.</translation>
-<translation id="7866522434127619318">Cette fonctionnalité active l'option &quot;Lire en un clic&quot; dans les paramètres de contenu du plug-in.</translation>
-<translation id="8860923508273563464">Attendre la fin des téléchargements</translation>
-<translation id="6406506848690869874">Synchronisation</translation>
-<translation id="5288678174502918605">&amp;Rouvrir l'onglet fermé</translation>
-<translation id="7238461040709361198">Votre mot de passe de compte Google a changé depuis votre dernière connexion à partir de cet ordinateur.</translation>
-<translation id="1956050014111002555">Le fichier contenait plusieurs certificats, aucun d'eux n'a été importé :</translation>
-<translation id="302620147503052030">Afficher le bouton</translation>
-<translation id="5512074755152723588">La saisie dans le champ polyvalent d'une URL déjà ouverte dans un autre onglet entraîne l'affichage de l'onglet en question, et non l'affichage de l'URL dans l'onglet actuel.</translation>
-<translation id="9157595877708044936">Configuration en cours...</translation>
-<translation id="4475552974751346499">Rechercher dans les téléchargements</translation>
-<translation id="3021256392995617989">Me demander lorsqu'un site tente de suivre ma position géographique (recommandé)</translation>
-<translation id="5185386675596372454">La nouvelle version de &quot;<ph name="EXTENSION_NAME"/>&quot; a été désactivée, car elle nécessite davantage d'autorisations.</translation>
-<translation id="4285669636069255873">Clavier phonétique russe</translation>
-<translation id="4148925816941278100">American Express</translation>
-<translation id="2320435940785160168">Ce serveur exige un certificat d'authentification et n'a pas accepté celui envoyé par le navigateur.
-Votre certificat a peut-être expiré ou le serveur n'a pas approuvé l'émetteur.
-Réessayez avec un autre certificat si vous en avez un.
-Sinon, vous devrez en obtenir un nouveau d'un autre émetteur.</translation>
-<translation id="6295228342562451544">Lorsque vous vous connectez à un site Web sécurisé, le serveur hébergeant ce site présente à votre navigateur un &quot;certificat&quot; afin de vérifier l'identité du site. Ce certificat contient des informations d'identité, telles que l'adresse du site Web, laquelle est vérifiée par un tiers approuvé par votre ordinateur. En vérifiant que l'adresse du certificat correspond à l'adresse du site Web, il est possible de s'assurer que vous êtes connecté de façon sécurisée avec le site Web souhaité et non pas avec un tiers (tel qu'un pirate informatique sur votre réseau).</translation>
-<translation id="6342069812937806050">À l'instant</translation>
-<translation id="5605716740717446121">Votre carte SIM sera définitivement désactivée si vous ne saisissez pas correctement la clé de déverrouillage du code PIN. Nombre de tentatives restantes : <ph name="TRIES_COUNT"/></translation>
-<translation id="8836712291807476944"><ph name="SAVED_BYTES"/> / <ph name="TOTAL_BYTES"/> octets, Interrompu</translation>
-<translation id="5502500733115278303">Importés depuis Firefox</translation>
-<translation id="569109051430110155">Détection automatique</translation>
-<translation id="4408599188496843485">&amp;Aide</translation>
-<translation id="5399158067281117682">Les codes PIN sont différents !</translation>
-<translation id="8494234776635784157">Contenu Web</translation>
-<translation id="2681441671465314329">Vider le cache</translation>
-<translation id="3646789916214779970">Rétablir le thème par défaut</translation>
-<translation id="1592960452683145077">Le service de communication à distance a démarré correctement. Vous devriez maintenant pouvoir vous connecter à distance à cet ordinateur.</translation>
-<translation id="1679068421605151609">Outils de développement</translation>
-<translation id="6648524591329069940">Police Serif</translation>
-<translation id="6896758677409633944">Copier</translation>
-<translation id="5260508466980570042">Adresse e-mail ou mot de passe incorrect. Veuillez réessayer.</translation>
-<translation id="7887998671651498201">Le plug-in suivant ne répond pas : souhaitez-vous interrompre <ph name="PLUGIN_NAME"/> ?</translation>
-<translation id="173188813625889224">Sens</translation>
-<translation id="8088823334188264070"><ph name="NUMBER_MANY"/> secondes</translation>
-<translation id="1337036551624197047">Clavier tchèque</translation>
-<translation id="4212108296677106246">Voulez-vous que &quot;<ph name="CERTIFICATE_NAME"/>&quot; soit considérée comme une autorité de certification fiable ?</translation>
-<translation id="2861941300086904918">Gestionnaire de sécurité natif du client</translation>
-<translation id="6991443949605114807">&lt;p&gt;Lorsque vous exécutez <ph name="PRODUCT_NAME"/> dans un environnement de bureau pris en charge, les paramètres proxy du système sont utilisés. Toutefois, soit votre système n'est pas pris en charge, soit un problème est survenu lors du lancement de votre configuration système.&lt;/p&gt;
-
- &lt;p&gt;Vous avez toujours la possibilité d'effectuer la configuration via la ligne de commande. Pour plus d'informations sur les indicateurs et les variables d'environnement, veuillez vous reporter à &lt;code&gt;man <ph name="PRODUCT_BINARY_NAME"/>&lt;/code&gt;.&lt;/p&gt;</translation>
-<translation id="9071590393348537582">La page Web à l'adresse <ph name="URL"/> a déclenché trop de redirections. Pour résoudre le problème, effacez les cookies de ce site ou autorisez les cookies tiers. Si le problème persiste, il peut être dû à une mauvaise configuration du serveur et n'être aucunement lié à votre ordinateur.</translation>
-<translation id="7205869271332034173">SSID :</translation>
-<translation id="7084579131203911145">Nom du forfait :</translation>
-<translation id="5815645614496570556">Adresse X.400</translation>
-<translation id="3551320343578183772">Fermer l'onglet</translation>
-<translation id="3345886924813989455">Impossible de trouver un navigateur pris en charge.</translation>
-<translation id="74354239584446316">Le compte associé à la boutique en ligne est le suivant : <ph name="EMAIL_ADDRESS"/>. L'utilisation d'un autre compte pour la synchronisation provoque des erreurs.</translation>
-<translation id="3712897371525859903">Enregistrer la p&amp;age sous...</translation>
-<translation id="7926251226597967072"><ph name="PRODUCT_NAME"/> importe actuellement les éléments suivants à partir de <ph name="IMPORT_BROWSER_NAME"/> :</translation>
-<translation id="2767649238005085901">Appuyez sur Entrée pour avancer et sur la touche de menu contextuel pour afficher l'historique</translation>
-<translation id="8580634710208701824">Actualiser le cadre</translation>
-<translation id="1018656279737460067">Annulé</translation>
-<translation id="7606992457248886637">Autorités</translation>
-<translation id="707392107419594760">Sélectionnez votre clavier :</translation>
-<translation id="2007404777272201486">Signaler un problème...</translation>
-<translation id="2390045462562521613">Ignorer ce réseau</translation>
-<translation id="3348038390189153836">Nouveau matériel détecté</translation>
-<translation id="1666788816626221136">Vous disposez de certificats qui n'appartiennent à aucune autre catégorie :</translation>
-<translation id="4821935166599369261">&amp;Profilage activé</translation>
-<translation id="1603914832182249871">(Navigation privée)</translation>
-<translation id="7910768399700579500">&amp;Nouveau dossier</translation>
-<translation id="7472639616520044048">Types MIME :</translation>
-<translation id="2307164895203900614">Afficher les pages en arrière-plan (<ph name="NUM_BACKGROUND_APPS"/>)</translation>
-<translation id="3192947282887913208">Fichiers audio</translation>
-<translation id="6295535972717341389">Plug-ins</translation>
-<translation id="8116190140324504026">Plus d'informations...</translation>
-<translation id="7469894403370665791">Se connecter automatiquement à ce réseau</translation>
-<translation id="4807098396393229769">Titulaire de la carte</translation>
-<translation id="4094130554533891764">Elle peut désormais accéder à :</translation>
-<translation id="4131410914670010031">Noir et blanc</translation>
-<translation id="3800503346337426623">Ignorer la connexion et naviguer en tant qu'invité</translation>
-<translation id="2615413226240911668">Toutefois, cette page inclut d'autres ressources qui ne sont pas sécurisées. Ces ressources peuvent être consultées par des tiers pendant leur transfert, et modifiées par un pirate informatique dans le but de changer l'aspect et le comportement de cette page.</translation>
-<translation id="5880867612172997051">Accès réseau interrompu</translation>
-<translation id="7842346819602959665">La dernière version de l'extension &quot;<ph name="EXTENSION_NAME"/>&quot; requiert d'autres permissions. Elle a donc été désactivée.</translation>
-<translation id="3776667127601582921">Dans ce cas, le certificat du serveur ou un certificat d'autorité intermédiaire présenté à votre navigateur n'est pas valide. Cela peut signifier que le certificat est incorrect, qu'il contient des champs non valides ou qu'il n'est pas compatible.</translation>
-<translation id="2412835451908901523">Veuillez saisir la clé de déverrouillage du code PIN à 8 chiffres fournie par <ph name="CARRIER_ID"/>.</translation>
-<translation id="6979448128170032817">Exceptions...</translation>
-<translation id="7584802760054545466">Connexion à <ph name="NETWORK_ID"/></translation>
-<translation id="208047771235602537">Voulez-vous vraiment quitter <ph name="PRODUCT_NAME"/> alors qu'un téléchargement est en cours ?</translation>
-<translation id="4060383410180771901">Le site Web ne parvient pas à gérer la demande associée à <ph name="URL"/>.</translation>
-<translation id="6710213216561001401">Précédent</translation>
-<translation id="1108600514891325577">&amp;Arrêter</translation>
-<translation id="6035087343161522833">Lorsque l'option permettant de bloquer l'enregistrement des cookies tiers est activée, la lecture de ces cookies est également bloquée.</translation>
-<translation id="8619892228487928601"><ph name="CERTIFICATE_NAME"/> : <ph name="ERROR"/></translation>
-<translation id="1567993339577891801">Console JavaScript</translation>
-<translation id="1548132948283577726">Les sites pour lesquels vos mots de passe ne seront jamais enregistrés s'afficheront ici.</translation>
-<translation id="583281660410589416">Inconnu</translation>
-<translation id="3774278775728862009">Mode de saisie du thaï (clavier TIS-820.2538)</translation>
-<translation id="9115675100829699941">&amp;Favoris</translation>
-<translation id="2485422356828889247">Désinstaller</translation>
-<translation id="2621889926470140926">Voulez-vous vraiment quitter <ph name="PRODUCT_NAME"/> alors que <ph name="DOWNLOAD_COUNT"/> téléchargements sont en cours ?</translation>
-<translation id="7279701417129455881">Configurer le blocage des cookies...</translation>
-<translation id="1166359541137214543">ABC</translation>
-<translation id="5412713837047574330">L'application hébergée par <ph name="HOST_NAME"/> est inaccessible, car vous êtes déconnecté du réseau. Cette page s'affichera dès que la connexion réseau sera rétablie. &lt;br&gt;</translation>
-<translation id="5528368756083817449">Gestionnaire de favoris</translation>
-<translation id="7275974018215686543"><ph name="NUMBER_MANY"/> secs ago</translation>
-<translation id="215753907730220065">Quitter le mode plein écran</translation>
-<translation id="7849264908733290972">Ouvrir l'&amp;image dans un nouvel onglet</translation>
-<translation id="1560991001553749272">Favori ajouté !</translation>
-<translation id="3966072572894326936">Choisir un autre dossier...</translation>
-<translation id="8766796754185931010">Kotoeri</translation>
-<translation id="7781829728241885113">Hier</translation>
-<translation id="2762402405578816341">Synchroniser automatiquement les éléments suivants :</translation>
-<translation id="1623661092385839831">Votre ordinateur intègre un périphérique de sécurité TPM (module de plate-forme sécurisée) qui permet de mettre en œuvre plusieurs fonctionnalités de sécurité critiques dans Google Chrome OS.</translation>
-<translation id="3359256513598016054">Contraintes des stratégies de certificat</translation>
-<translation id="4433914671537236274">Créer un support de récupération</translation>
-<translation id="4509345063551561634">Emplacement :</translation>
-<translation id="7596288230018319236">Toutes les pages que vous consultez apparaîtront ici à moins que vous ne les ouvriez dans une fenêtre en navigation privée. Vous pouvez utiliser le bouton Rechercher de cette page pour rechercher dans toutes les pages de votre historique.</translation>
-<translation id="7434509671034404296">Options pour les développeurs</translation>
-<translation id="6447842834002726250">Cookies</translation>
-<translation id="2609371827041010694">Toujours exécuter pour ce site</translation>
-<translation id="5170568018924773124">Afficher le dossier</translation>
-<translation id="883848425547221593">Autres favoris</translation>
-<translation id="6054173164583630569">Clavier français</translation>
-<translation id="4870177177395420201"><ph name="PRODUCT_NAME"/> ne parvient pas à déterminer ou à définir le navigateur par défaut.</translation>
-<translation id="8898786835233784856">Sélectionner l'onglet suivant</translation>
-<translation id="2674170444375937751">Voulez-vous vraiment supprimer ces pages de votre historique ?</translation>
-<translation id="9111102763498581341">Déverrouiller</translation>
-<translation id="289695669188700754">ID de clé : <ph name="KEY_ID"/></translation>
-<translation id="3067198360141518313">Exécuter ce plug-in</translation>
-<translation id="8767072502252310690">Utilisateurs</translation>
-<translation id="683526731807555621">Ajouter un moteur</translation>
-<translation id="6871644448911473373">Répondeur OCSP : <ph name="LOCATION"/></translation>
-<translation id="8281886186245836920">Ignorer</translation>
-<translation id="3867944738977021751">Champs de certificat</translation>
-<translation id="2114224913786726438">Modules (<ph name="TOTAL_COUNT"/>) : aucun conflit détecté.</translation>
-<translation id="7629827748548208700">Onglet : <ph name="TAB_NAME"/></translation>
-<translation id="388442998277590542">Impossible de charger la page d'options &quot;<ph name="OPTIONS_PAGE"/>&quot;.</translation>
-<translation id="8449008133205184768">Coller en adaptant le style</translation>
-<translation id="9114223350847410618">Veuillez ajouter une autre langue avant de supprimer celle-ci.</translation>
-<translation id="4408427661507229495">nom du réseau</translation>
-<translation id="8886960478266132308"><ph name="PRODUCT_NAME"/> synchronise de manière sécurisée vos données avec votre compte Google.</translation>
-<translation id="8028993641010258682">Taille</translation>
-<translation id="5031603669928715570">Activer...</translation>
-<translation id="1383876407941801731">Recherche</translation>
-<translation id="8398877366907290961">Poursuivre quand même</translation>
-<translation id="5063180925553000800">Nouveau code PIN :</translation>
-<translation id="2496540304887968742">La capacité du périphérique doit être d'au moins 4 Go.</translation>
-<translation id="6974053822202609517">De droite à gauche</translation>
-<translation id="2370882663124746154">Activer le mode Pinyin double</translation>
-<translation id="5463856536939868464">Menu contenant des favoris masqués</translation>
-<translation id="8286227656784970313">Utiliser le dictionnaire système</translation>
-<translation id="5431084084184068621">Vous avez choisi de chiffrer les données à l'aide de votre mot de passe Google. Vous pouvez modifier vos paramètres de synchronisation à tout moment, si vous changez d'avis.</translation>
-<translation id="1493263392339817010">Personnaliser les polices...</translation>
-<translation id="5352033265844765294">Enregistrement des informations de date</translation>
-<translation id="6449085810994685586">&amp;Vérifier l'orthographe du texte de ce champ</translation>
-<translation id="3621320549246006887">Ceci est un modèle expérimental qui permet aux enregistrements DNS (utilisant le protocole de sécurité DNSSEC) d'autoriser ou de refuser des certificats HTTPS. Ce message s'affiche lorsque vous activez des fonctionnalités expérimentales via des options de ligne de commande. Vous pouvez supprimer ces options de ligne de commande pour ignorer cette erreur.</translation>
-<translation id="50960180632766478"><ph name="NUMBER_FEW"/> minutes restantes</translation>
-<translation id="3174168572213147020">Île</translation>
-<translation id="748138892655239008">Contraintes de base du certificat</translation>
-<translation id="457386861538956877">Autres...</translation>
-<translation id="8063491445163840780">Activer l'onglet 4</translation>
-<translation id="5966654788342289517">Données personnelles</translation>
-<translation id="9137013805542155359">Afficher l'original</translation>
-<translation id="4792385443586519711">Nom de la société</translation>
-<translation id="6423731501149634044">Définir Adobe Reader comme visionneuse de documents PDF par défaut ?</translation>
-<translation id="8839907368860424444">Pour gérer les extensions installées, cliquez sur Extensions dans le menu Fenêtre.</translation>
-<translation id="2461687051570989462">Accédez à vos imprimantes depuis n'importe quel ordinateur ou smartphone. <ph name="BEGIN_LINK"/>En savoir plus<ph name="END_LINK"/></translation>
-<translation id="7194430665029924274">Me &amp;le rappeler plus tard</translation>
-<translation id="5790085346892983794">Opération réussie !</translation>
-<translation id="1901769927849168791">Carte SD détectée.</translation>
-<translation id="818454486170715660"><ph name="NAME"/> - Propriétaire</translation>
-<translation id="1358032944105037487">Clavier japonais</translation>
-<translation id="8201956630388867069">WPA</translation>
-<translation id="603890000178803545">janv.^févr.^mars^avr.^mai^juin^juil.^août^sept.^oct.^nov.^déc.</translation>
-<translation id="8302838426652833913">Sélectionnez
- <ph name="BEGIN_BOLD"/>
- Applications &gt; Préférences système &gt; Réseau &gt; Assistant
- <ph name="END_BOLD"/>
- pour tester votre connexion.</translation>
-<translation id="8664389313780386848">&amp;Afficher le code source de la page</translation>
-<translation id="8970407809569722516">Micrologiciel :</translation>
-<translation id="1180549724812639004">Créer un profil</translation>
-<translation id="57646104491463491">Date de modification</translation>
-<translation id="5992752872167177798">Sandbox seccomp</translation>
-<translation id="6362853299801475928">Signale&amp;r un problème...</translation>
-<translation id="3289566588497100676">Entrée de symboles simplifiée</translation>
-<translation id="6507969014813375884">Chinois simplifié</translation>
-<translation id="7314244761674113881">Hôte SOCKS</translation>
-<translation id="5285794783728826432">Considérer ce certificat comme fiable pour identifier les sites Web.</translation>
-<translation id="4224803122026931301">Exceptions de localisation</translation>
-<translation id="749452993132003881">Hiragana</translation>
-<translation id="8226742006292257240">Le mot de passe TPM ci-dessous, généré de façon aléatoire, a été attribué à votre ordinateur :</translation>
-<translation id="8487693399751278191">Importer mes favoris maintenant...</translation>
-<translation id="7985242821674907985"><ph name="PRODUCT_NAME"/></translation>
-<translation id="7484580869648358686">Avertissement : Un problème a été détecté sur cette page.</translation>
-<translation id="2074739700630368799">Avec Google Chrome OS for business, vous pouvez connecter votre périphérique à Google Apps, ce qui vous permet de le rechercher et de le contrôler depuis le panneau de configuration de Google Apps.</translation>
-<translation id="4474155171896946103">Ajouter tous les onglets aux favoris...</translation>
-<translation id="5895187275912066135">Émis le</translation>
-<translation id="1190844492833803334">Lorsque je ferme le navigateur</translation>
-<translation id="5646376287012673985">Localisation</translation>
-<translation id="1110155001042129815">Attendre</translation>
-<translation id="2607101320794533334">Infos sur la clé publique de l'objet</translation>
-<translation id="7071586181848220801">Plug-in inconnu</translation>
-<translation id="3354601307791487577">Connexion en mode invité</translation>
-<translation id="4419409365248380979">Toujours autoriser <ph name="HOST"/> à paramétrer les cookies</translation>
-<translation id="2956070106555335453">Résumé</translation>
-<translation id="917450738466192189">Le certificat du serveur n'est pas valide.</translation>
-<translation id="2649045351178520408">Chaîne de certificats codés Base 64 ASCII</translation>
-<translation id="7424526482660971538">Choisir mon propre mot de passe multiterme</translation>
-<translation id="380271916710942399">Certificat de serveur non répertorié</translation>
-<translation id="6459488832681039634">Rechercher la sélection</translation>
-<translation id="2392369802118427583">Activer</translation>
-<translation id="9040421302519041149">L'accès à ce réseau est protégé.</translation>
-<translation id="5659593005791499971">E-mail</translation>
-<translation id="8235325155053717782">Erreur <ph name="ERROR_NUMBER"/> (<ph name="ERROR_NAME"/>) : <ph name="ERROR_TEXT"/></translation>
-<translation id="6584878029876017575">Signature permanente Microsoft</translation>
-<translation id="562901740552630300">Sélectionnez
- <ph name="BEGIN_BOLD"/>
- Démarrer &gt; Panneau de configuration &gt; Réseau et Internet &gt; Centre Réseau et partage &gt; Résolution des problèmes (en bas) &gt; Connexions Internet.
- <ph name="END_BOLD"/></translation>
-<translation id="8816996941061600321">Gestionnaire de &amp;fichiers</translation>
-<translation id="2773223079752808209">Service client</translation>
-<translation id="4585473702689066695">Impossible de se connecter au réseau &quot;<ph name="NAME"/>&quot;.</translation>
-<translation id="4647175434312795566">J'accepte ces termes</translation>
-<translation id="1084824384139382525">Copier l'adr&amp;esse du lien</translation>
-<translation id="1221462285898798023">Veuillez démarrer <ph name="PRODUCT_NAME"/> en tant qu'utilisateur normal. Pour l'exécuter en tant que root, vous devez indiquer un autre répertoire de données utilisateur pour stocker les informations du profil.</translation>
-<translation id="3220586366024592812">Le processus du connecteur <ph name="CLOUD_PRINT_NAME"/> est bloqué. Voulez-vous le redémarrer ?</translation>
-<translation id="5042992464904238023">Contenu Web</translation>
-<translation id="6254503684448816922">Clé compromise</translation>
-<translation id="1181037720776840403">Supprimer</translation>
-<translation id="4006726980536015530">Si vous fermez <ph name="PRODUCT_NAME"/> maintenant, ces téléchargements seront annulés.</translation>
-<translation id="4194415033234465088">Dachen 26</translation>
-<translation id="1664712100580477121">Voulez-vous vraiment graver l'image sur le périphérique suivant :</translation>
-<translation id="6639554308659482635">Mémoire SQLite</translation>
-<translation id="8141503649579618569"><ph name="DOWNLOAD_RECEIVED"/>/<ph name="DOWNLOAD_TOTAL"/>, <ph name="TIME_LEFT"/></translation>
-<translation id="7650701856438921772"><ph name="PRODUCT_NAME"/> est affiché dans cette langue.</translation>
-<translation id="740624631517654988">Fenêtre pop-up bloquée</translation>
-<translation id="3738924763801731196"><ph name="OID"/> :</translation>
-<translation id="6550769511678490130">Ouvrir tous les favoris</translation>
-<translation id="1847961471583915783">Effacer les cookies et autres données de site et de plug-in lorsque je ferme le navigateur</translation>
-<translation id="8870318296973696995">Page d'accueil</translation>
-<translation id="6659594942844771486">Onglet</translation>
-<translation id="6575134580692778371">Non configuré</translation>
-<translation id="4624768044135598934">Opération réussie !</translation>
-<translation id="6014776969142880350">Relancez <ph name="PRODUCT_NAME"/> pour terminer la mise à jour.</translation>
-<translation id="5582768900447355629">Chiffrer toutes mes données</translation>
-<translation id="6122365914076864562">Veuillez patienter pendant que nous configurons votre réseau pour mobile.</translation>
-<translation id="1974043046396539880">Points de distribution de listes de révocation des certificats</translation>
-<translation id="7049357003967926684">Association</translation>
-<translation id="8641392906089904981">Appuyez sur Maj+Alt pour changer la disposition du clavier.</translation>
-<translation id="3024374909719388945">Utiliser l'horloge au format 24 heures</translation>
-<translation id="1867780286110144690"><ph name="PRODUCT_NAME"/> est prêt à terminer l'installation.</translation>
-<translation id="5316814419223884568">Lancez votre recherche à partir d'ici</translation>
-<translation id="8142732521333266922">OK, synchroniser tout</translation>
-<translation id="965674096648379287">Afin d'être correctement affichée, cette page requiert des données que vous avez précédemment entrées. Vous pouvez de nouveau transmettre ces données, mais, en procédant ainsi, vous devrez répéter chaque action que cette page a effectuée auparavant. Cliquez sur Rafraîchir pour transmettre de nouveau ces données et pour afficher cette page.</translation>
-<translation id="43742617823094120">Cela signifie que le certificat présenté à votre navigateur a été révoqué par son émetteur. L'intégrité de ce certificat a certainement été compromise, et il ne doit donc pas être approuvé. Ne poursuivez pas.</translation>
-<translation id="9019654278847959325">Clavier slovaque</translation>
-<translation id="18139523105317219">Nom de partie EDI</translation>
-<translation id="6657193944556309583">Vous avez déjà chiffré des données avec un mot de passe multiterme. Saisissez-le ci-dessous.</translation>
-<translation id="3328801116991980348">Informations sur le site</translation>
-<translation id="1205605488412590044">Créer un raccourci vers l'application...</translation>
-<translation id="2065985942032347596">Authentification requise</translation>
-<translation id="2553340429761841190"><ph name="PRODUCT_NAME"/> n'est pas parvenu à se connecter à <ph name="NETWORK_ID"/>. Sélectionnez un autre réseau ou réessayez.</translation>
-<translation id="2086712242472027775">Votre compte n'est pas compatible avec <ph name="PRODUCT_NAME"/>. Contactez l'administrateur de votre domaine ou utilisez un compte Google standard pour vous connecter.</translation>
-<translation id="7222232353993864120">Adresse e-mail</translation>
-<translation id="2128531968068887769">Client natif</translation>
-<translation id="7175353351958621980">Chargé depuis :</translation>
-<translation id="4590074117005971373">Active les balises canvas hautes performances dans un contexte 2D, pour effectuer le rendu via le processeur graphique.</translation>
-<translation id="7186367841673660872">Cette page en<ph name="ORIGINAL_LANGUAGE"/>a été traduite en<ph name="LANGUAGE_LANGUAGE"/></translation>
-<translation id="8448695406146523553">Seule une personne en possession de votre mot de passe multiterme peut lire vos données chiffrées. Google ne reçoit ni n'enregistre votre mot de passe multiterme. Si vous oubliez votre mot de passe multiterme, vous devrez</translation>
-<translation id="6052976518993719690">Autorité de certification SSL</translation>
-<translation id="1636959874332483835"><ph name="HOST_NAME"/> contient un logiciel malveillant. Votre ordinateur pourrait être infecté par un virus si vous consultez ce site.</translation>
-<translation id="8050783156231782848">Aucune donnée disponible.</translation>
-<translation id="1175364870820465910">Im&amp;primer...</translation>
-<translation id="3866249974567520381">Description</translation>
-<translation id="2900139581179749587">Voix non reconnue.</translation>
-<translation id="953692523250483872">Aucun fichier sélectionné</translation>
-<translation id="2294358108254308676">Souhaitez-vous installer <ph name="PRODUCT_NAME"/> ?</translation>
-<translation id="6549689063733911810">Activité récente</translation>
-<translation id="1529968269513889022">de la dernière semaine</translation>
-<translation id="5542132724887566711">Profil</translation>
-<translation id="5196117515621749903">Actualiser sans utiliser le cache</translation>
-<translation id="5552632479093547648">Logiciels malveillants et sites de phishing détectés !</translation>
-<translation id="4310537301481716192">Onglet fermé !</translation>
-<translation id="4988273303304146523">il y a <ph name="NUMBER_DEFAULT"/> jours</translation>
-<translation id="8428213095426709021">Paramètres</translation>
-<translation id="1588343679702972132">Ce site exige que vous vous identifiiez avec un certificat :</translation>
-<translation id="7211994749225247711">Supprimer...</translation>
-<translation id="2819994928625218237">&amp;Aucune suggestion orthographique</translation>
-<translation id="1065449928621190041">Clavier franco-canadien</translation>
-<translation id="8327626790128680264">Clavier étendu américain</translation>
-<translation id="2950186680359523359">Le serveur a mis fin à la connexion sans envoyer de données.</translation>
-<translation id="9142623379911037913">Autoriser <ph name="SITE"/> à afficher des notifications sur le Bureau ?</translation>
-<translation id="4196320913210960460">Pour gérer les extensions installées, cliquez sur Extensions dans le menu Outils.</translation>
-<translation id="3449494395612243720">Erreur de synchronisation, veuillez vous connecter à nouveau.</translation>
-<translation id="9118804773997839291">La liste suivante fait état des éléments dangereux détectés sur la page. Cliquez sur le lien &quot;Diagnostic&quot; pour obtenir plus d'informations sur un élément particulier.</translation>
-<translation id="7139724024395191329">Émirat</translation>
-<translation id="1761265592227862828">Synchroniser tous les paramètres et toutes les données\n(peut prendre un certain temps)</translation>
-<translation id="7754704193130578113">Toujours demander où enregistrer les fichiers</translation>
-<translation id="204914487372604757">Créer un raccourci</translation>
-<translation id="2497284189126895209">Tous les fichiers</translation>
-<translation id="696036063053180184">Sebeol-sik No-shift</translation>
-<translation id="452785312504541111">Anglais (pleine chasse)</translation>
-<translation id="945332329539165145">2D avec canvas et accélération matérielle</translation>
-<translation id="5220797120063118010">Cette fonctionnalité autorise l'installation d'applications Google Chrome déployées à partir d'un manifeste situé sur une page Web, plutôt qu'avec un fichier crx contenant le manifeste et les icônes.</translation>
-<translation id="9148126808321036104">Nouvelle connexion</translation>
-<translation id="2282146716419988068">GPU</translation>
-<translation id="428771275901304970">Moins de 1 Mo disponible</translation>
-<translation id="1682548588986054654">Nouvelle fenêtre de navigation privée</translation>
-<translation id="6833901631330113163">Europe du Sud</translation>
-<translation id="8691262314411702087">Sélectionner les éléments à synchroniser</translation>
-<translation id="6065289257230303064">Attributs du répertoire de l'objet du certificat</translation>
-<translation id="2423017480076849397">Accédez à vos imprimantes et partagez-les en ligne via <ph name="CLOUD_PRINT_NAME"/>.</translation>
-<translation id="569520194956422927">&amp;Ajouter...</translation>
-<translation id="4018133169783460046">Afficher <ph name="PRODUCT_NAME"/> dans cette langue</translation>
-<translation id="5110450810124758964">il y a <ph name="NUMBER_ONE"/> jour</translation>
-<translation id="3264544094376351444">Police Sans-Serif</translation>
-<translation id="5586942249556966598">Ne rien faire</translation>
-<translation id="2820806154655529776"><ph name="NUMBER_ONE"/> seconde</translation>
-<translation id="1077946062898560804">Configurer les mises à jour automatiques pour tous les utilisateurs</translation>
-<translation id="3122496702278727796">Échec de la création du répertoire des données</translation>
-<translation id="4517036173149081027">Fermer et annuler le chargement</translation>
-<translation id="7150146631451105528"><ph name="DATE"/></translation>
-<translation id="3166547286524371413">Adresse :</translation>
-<translation id="4522570452068850558">Détails</translation>
-<translation id="59659456909144943">Notification : <ph name="NOTIFICATION_NAME"/></translation>
-<translation id="6731320427842222405">Cette opération peut prendre quelques minutes.</translation>
-<translation id="4806525999832945986">Géré par <ph name="DOMAIN"/> (<ph name="STATUS"/>)</translation>
-<translation id="7503191893372251637">Type de certificat Netscape</translation>
-<translation id="1502960562739459116">Impossible d'afficher certaines parties de ce document PDF. Souhaitez-vous installer Adobe Reader ?</translation>
-<translation id="4135450933899346655">Vos certificats</translation>
-<translation id="4731578803613910821">Vos données personnelles sur <ph name="WEBSITE_1"/>, <ph name="WEBSITE_2"/> et <ph name="WEBSITE_3"/></translation>
-<translation id="7716781361494605745">URL de stratégie de l'autorité de certification Netscape</translation>
-<translation id="2881966438216424900">Dernier accès :</translation>
-<translation id="7552203043556919163">Synchroniser les mots de passe</translation>
-<translation id="630065524203833229">&amp;Quitter</translation>
-<translation id="4647090755847581616">&amp;Fermer l'onglet</translation>
-<translation id="2649204054376361687"><ph name="CITY"/>, <ph name="COUNTRY"/></translation>
-<translation id="7886758531743562066">Le site Web à l'adresse <ph name="HOST_NAME"/> contient des éléments provenant de sites qui semblent héberger des logiciels malveillants. Ces derniers peuvent nuire à votre ordinateur ou agir à votre insu. Le simple fait de visiter un site hébergeant ce type de logiciels peut infecter votre ordinateur.</translation>
-<translation id="2064746092913005102">Total : <ph name="NUMBER_OF_PAGES"/> <ph name="PAGE_OR_PAGES_LABEL"/> <ph name="TWO_SIDED"/> <ph name="TIMES"/> <ph name="NUMBER_OF_COPIES"/> <ph name="COPIES_LABEL"/> <ph name="EQUAL_SIGN"/> <ph name="NUMBER_OF_SHEETS"/> <ph name="SHEETS_LABEL"/></translation>
-<translation id="7538227655922918841">Les cookies de plusieurs sites ont été autorisés pour la session uniquement.</translation>
-<translation id="2385700042425247848">Nom du service :</translation>
-<translation id="7751005832163144684">Imprimer une page de test</translation>
-<translation id="3638865692466101147">Aperçu avant impression - <ph name="PREVIEW_TAB_TITLE"/></translation>
-<translation id="1471300011765310414"><ph name="PRODUCT_NAME"/>
- ne peut pas à afficher la page Web, car votre ordinateur n'est pas connecté à Internet.</translation>
-<translation id="5464632865477611176">Exécuter cette fois</translation>
-<translation id="4268025649754414643">Chiffrement de la clé</translation>
-<translation id="7925247922861151263">Échec de la vérification AAA</translation>
-<translation id="1168020859489941584">Ouverture dans <ph name="TIME_REMAINING"/>...</translation>
-<translation id="7814458197256864873">&amp;Copier</translation>
-<translation id="8186706823560132848">Logiciel</translation>
-<translation id="4692623383562244444">Moteurs de recherche</translation>
-<translation id="567760371929988174">&amp;Méthodes d'entrée</translation>
-<translation id="10614374240317010">Jamais enregistrés</translation>
-<translation id="5116300307302421503">Impossible d'analyser le fichier.</translation>
-<translation id="2745080116229976798">Subordination qualifiée Microsoft</translation>
-<translation id="2526590354069164005">Bureau</translation>
-<translation id="7983301409776629893">Toujours traduire en <ph name="TARGET_LANGUAGE"/> les pages en <ph name="ORIGINAL_LANGUAGE"/></translation>
-<translation id="4890284164788142455">Thaï</translation>
-<translation id="4312207540304900419">Activer l'onglet suivant</translation>
-<translation id="8456362689280298700"><ph name="HOUR"/>:<ph name="MINUTE"/> de chargement</translation>
-<translation id="7648048654005891115">Style de mappage du clavier</translation>
-<translation id="539295039523818097">Un problème lié à votre microphone s'est produit.</translation>
-<translation id="4033319557821527966"><ph name="CLOUD_PRINT_NAME"/> vous permet d'accéder aux imprimantes de cet ordinateur, où que vous soyez. Connectez-vous pour l'activer.</translation>
-<translation id="6970216967273061347">District</translation>
-<translation id="4479639480957787382">Ethernet</translation>
-<translation id="6312403991423642364">Erreur de réseau inconnue.</translation>
-<translation id="751377616343077236">Nom du certificat</translation>
-<translation id="7154108546743862496">Plus d'informations</translation>
-<translation id="8637688295594795546">Mise à jour du système disponible. Préparation du téléchargement…</translation>
-<translation id="5167270755190684957">Galerie des thèmes Google Chrome</translation>
-<translation id="8382913212082956454">Copi&amp;er l'adresse e-mail</translation>
-<translation id="7447930227192971403">Activer l'onglet 3</translation>
-<translation id="2903493209154104877">Adresses</translation>
-<translation id="2056143100006548702">Plug-in : <ph name="PLUGIN_NAME"/> (<ph name="PLUGIN_VERSION"/>)</translation>
-<translation id="3479552764303398839">Pas maintenant</translation>
-<translation id="6445051938772793705">Pays</translation>
-<translation id="3251759466064201842">&lt;Ne fait pas partie du certificat&gt;</translation>
-<translation id="4229495110203539533">il y a <ph name="NUMBER_ONE"/> seconde</translation>
-<translation id="6410257289063177456">Fichiers image</translation>
-<translation id="6419902127459849040">Europe centrale</translation>
-<translation id="6707389671160270963">Certificat client SSL</translation>
-<translation id="6083557600037991373">Pour accélérer l'affichage des pages Web,
- <ph name="PRODUCT_NAME"/>
- enregistre temporairement les fichiers téléchargés sur le disque. Si
- <ph name="PRODUCT_NAME"/>
- ne s'arrête pas correctement, ces fichiers peuvent être endommagés, ce qui
- génère cette erreur. L'actualisation de la page devrait permettre de résoudre
- ce problème ; celui-ci ne se reproduira vraisemblablement plus si l'arrêt s'effectue
- correctement.
- <ph name="LINE_BREAK"/>
- Si le problème persiste, essayez de supprimer le contenu du cache. Cette
- erreur peut aussi indiquer que le matériel est sur le point de tomber
- en panne.</translation>
-<translation id="5298219193514155779">Thème créé par</translation>
-<translation id="7366909168761621528">Données de navigation</translation>
-<translation id="1047726139967079566">Ajouter cette page aux favoris</translation>
-<translation id="9020142588544155172">Le serveur a refusé la connexion.</translation>
-<translation id="6113225828180044308">Module (<ph name="MODULUS_NUM_BITS"/> bits) :\n<ph name="MODULUS_HEX_DUMP"/>\n\nExposant public (<ph name="PUBLIC_EXPONENT_NUM_BITS"/> bits) :\n<ph name="EXPONENT_HEX_DUMP"/></translation>
-<translation id="2544782972264605588"><ph name="NUMBER_DEFAULT"/> secondes restantes</translation>
-<translation id="8871696467337989339">Vous utilisez un indicateur de ligne de commande non pris en charge : <ph name="BAD_FLAG"/>. La stabilité et la sécurité en seront affectées.</translation>
-<translation id="4767443964295394154">Emplacement de téléchargement</translation>
-<translation id="5031870354684148875">À propos de Google Traduction</translation>
-<translation id="720658115504386855">Les lettres ne sont pas sensibles à la casse.</translation>
-<translation id="2454247629720664989">Mot clé</translation>
-<translation id="3950820424414687140">Connexion</translation>
-<translation id="4626106357471783850">Redémarrez <ph name="PRODUCT_NAME"/> pour appliquer la mise à jour.</translation>
-<translation id="1697068104427956555">Sélectionner un carré dans l'image</translation>
-<translation id="2840798130349147766">Bases de données Web</translation>
-<translation id="1628736721748648976">Codage</translation>
-<translation id="1198271701881992799">Mise en route</translation>
-<translation id="782590969421016895">Utiliser les pages actuelles</translation>
-<translation id="6521850982405273806">Signaler une erreur</translation>
-<translation id="736515969993332243">Recherche de réseaux en cours</translation>
-<translation id="8026334261755873520">Effacer les données de navigation</translation>
-<translation id="2717361709448355148">Impossible de renommer &quot;$1&quot; : $2</translation>
-<translation id="1769104665586091481">Ouvrir le lien dans une nouvelle &amp;fenêtre</translation>
-<translation id="8503813439785031346">Nom d'utilisateur</translation>
-<translation id="5319782540886810524">Clavier letton</translation>
-<translation id="8651585100578802546">Forcer l'actualisation de cette page</translation>
-<translation id="685714579710025096">Disposition du clavier :</translation>
-<translation id="1361655923249334273">Non utilisé</translation>
-<translation id="290555789621781773"><ph name="NUMBER_TWO"/> minutes</translation>
-<translation id="5434065355175441495">Chiffrement RSA PKCS #1</translation>
-<translation id="7073704676847768330">Ce n'est probablement pas le site que vous recherchez !</translation>
-<translation id="8477384620836102176">&amp;Général</translation>
-<translation id="1074663319790387896">Configurer la synchronisation</translation>
-<translation id="4302315780171881488">État de connexion :</translation>
-<translation id="3391392691301057522">Ancien code PIN :</translation>
-<translation id="1344519653668879001">Désactiver le contrôle des liens hypertexte</translation>
-<translation id="6463795194797719782">&amp;Modifier</translation>
-<translation id="4262113024799883061">Chinois</translation>
-<translation id="4775879719735953715">Navigateur par défaut</translation>
-<translation id="5575473780076478375">Extension en mode navigation privée :<ph name="EXTENSION_NAME"/></translation>
-<translation id="4188026131102273494">Mot clé :</translation>
-<translation id="2930644991850369934">Un problème est survenu lors du téléchargement de l'image de récupération. La connexion réseau a été perdue.</translation>
-<translation id="3461610253915486539">Votre administrateur a désactivé certaines préférences.</translation>
-<translation id="5750053751252005701">Forfait de données <ph name="NETWORK"/> épuisé</translation>
-<translation id="8858939932848080433">Veuillez indiquer à quel niveau vous rencontrez des problèmes avant d'envoyer vos commentaires.</translation>
-<translation id="1720318856472900922">Authentification du serveur WWW TLS</translation>
-<translation id="8550022383519221471">Le service de synchronisation n'est pas disponible pour votre domaine.</translation>
-<translation id="3355823806454867987">Modifier les paramètres du proxy...</translation>
-<translation id="4780374166989101364">Cette fonctionnalité active les API des extensions expérimentales. Notez que vous ne pouvez pas mettre en ligne des extensions qui font appel aux API expérimentales dans la galerie d'extensions.</translation>
-<translation id="7227780179130368205">Un logiciel malveillant a été détecté !</translation>
-<translation id="435243347905038008">Forfait de données <ph name="NETWORK"/> presque épuisé</translation>
-<translation id="2489428929217601177">des dernières 24 heures</translation>
-<translation id="7418490403869327287">Une fois activée, la recherche instantanée charge la plupart des pages Web dès que vous saisissez l'URL dans le champ polyvalent, avant même que vous n'appuyiez sur Entrée. Si votre moteur de recherche par défaut est compatible, toute lettre saisie dans ce champ offre de nouveaux résultats et les prédictions intégrées vous guident dans vos recherches.\n\nChaque touche utilisée fait l'objet d'une requête, par conséquent il se peut que les éléments saisies dans le champ polyvalent soient enregistrés par votre moteur de recherche par défaut.\n</translation>
-<translation id="5149131957118398098"><ph name="NUMBER_ZERO"/> hours left</translation>
-<translation id="2541913031883863396">poursuivre quand même</translation>
-<translation id="4278390842282768270">Autorisé</translation>
-<translation id="2074527029802029717">Retirer l'onglet</translation>
-<translation id="1533897085022183721">Moins de <ph name="MINUTES"/></translation>
-<translation id="7503821294401948377">Impossible de charger l'icône &quot;<ph name="ICON"/>&quot; d'action du navigateur.</translation>
-<translation id="5539694491979265537">Consulter Google Dashboard</translation>
-<translation id="3942946088478181888">Plus d'informations</translation>
-<translation id="3722396466546931176">Ajoutez des langues puis faites-les glisser pour les classer dans l'ordre souhaité.</translation>
-<translation id="7396845648024431313"><ph name="APP_NAME"/> sera lancé au démarrage du système et continuera de s'exécuter en arrière-plan, même toutes les fenêtres de <ph name="PRODUCT_NAME"/> sont fermées.</translation>
-<translation id="8539727552378197395">Non (HttpOnly)</translation>
-<translation id="4519351128520996510">Saisir votre mot de passe multiterme pour la synchronisation</translation>
-<translation id="2391419135980381625">Police standard</translation>
-<translation id="7893393459573308604"><ph name="ENGINE_NAME"/> (par défaut)</translation>
-<translation id="5392544185395226057">Cette fonctionnalité active la prise en charge du client natif.</translation>
-<translation id="5400640815024374115">La puce du module de plate-forme sécurisée (TPM) est désactivée ou inexistante.</translation>
-<translation id="2151576029659734873">L'index de l'onglet indiqué est incorrect.</translation>
-<translation id="5150254825601720210">Nom du serveur SSL du certificat Netscape</translation>
-<translation id="6771503742377376720">Est une autorité de certification</translation>
-<translation id="8814190375133053267">Wi-Fi</translation>
-<translation id="2040078585890208937">Connexion à <ph name="NAME"/></translation>
-<translation id="8410619858754994443">Confirmer le mot de passe :</translation>
-<translation id="2210840298541351314">Aperçu avant impression</translation>
-<translation id="3858678421048828670">Clavier italien</translation>
-<translation id="4938277090904056629">Impossible d'établir une connexion sécurisée à cause de l'antivirus ESET.</translation>
-<translation id="4521805507184738876">(expiré)</translation>
-<translation id="111844081046043029">Voulez-vous vraiment quitter cette page ?</translation>
-<translation id="1951615167417147110">Faire défiler d'une page vers le haut</translation>
-<translation id="4154664944169082762">Empreintes</translation>
-<translation id="3202578601642193415">Le plus récent</translation>
-<translation id="8112886015144590373"><ph name="NUMBER_FEW"/> heures</translation>
-<translation id="1398853756734560583">Agrandir</translation>
-<translation id="8988255471271407508">La page Web est introuvable dans le cache. Certaines ressources ne sont restituées fidèlement que si elles sont extraites du cache, notamment les pages générées à partir de données que vous avez envoyées. <ph name="LINE_BREAK"/> Cette erreur peut également être due à un cache endommagé lors d'une fermeture incorrecte. <ph name="LINE_BREAK"/> Si le problème persiste, essayez d'effacer le cache.</translation>
-<translation id="1195977189444203128">Le plug-in <ph name="PLUGIN_NAME"/> n'est plus à jour.</translation>
-<translation id="3878562341724547165">Vous avez changé de position. Souhaitez-vous utiliser <ph name="NEW_GOOGLE_URL"/> ?</translation>
-<translation id="1758018619400202187">EAP-TLS</translation>
-<translation id="6690744523875189208"><ph name="NUMBER_TWO"/> heures</translation>
-<translation id="8053390638574070785">Rafraîchir cette page</translation>
-<translation id="5507756662695126555">Non-répudiation</translation>
-<translation id="3678156199662914018">Extension : <ph name="EXTENSION_NAME"/></translation>
-<translation id="7951780829309373534">Impossible de coller &quot;$1&quot; : $2</translation>
-<translation id="9194519262242876737">Active l'API Web audio.</translation>
-<translation id="3531250013160506608">Zone de saisie de mot de passe</translation>
-<translation id="8314066201485587418">Effacer les cookies et autres données de site lorsque je quitte le navigateur</translation>
-<translation id="4094105377635924481">Ajouter l'option de regroupement au menu contextuel des onglets</translation>
-<translation id="8655295600908251630">Version</translation>
-<translation id="8250690786522693009">Latin</translation>
-<translation id="2119721408814495896">Le connecteur <ph name="CLOUD_PRINT_NAME"/> requiert l'installation du pack Microsoft XML Paper Specification Essentials.</translation>
-<translation id="7624267205732106503">Effacer les cookies et autres données de site lorsque je ferme le navigateur</translation>
-<translation id="8401363965527883709">Case décochée</translation>
-<translation id="7771452384635174008">Mise en page</translation>
-<translation id="6188939051578398125">Saisir un nom ou une adresse</translation>
-<translation id="8443621894987748190">Choix de l'image du compte</translation>
-<translation id="10122177803156699">Me montrer</translation>
-<translation id="5260878308685146029"><ph name="NUMBER_TWO"/> minutes restantes</translation>
-<translation id="2192505247865591433">De :</translation>
-<translation id="238391805422906964">Ouvrir un rapport de phishing</translation>
-<translation id="5921544176073914576">Page de phishing</translation>
-<translation id="3727187387656390258">Inspecter le pop-up</translation>
-<translation id="569068482611873351">Importer...</translation>
-<translation id="6571070086367343653">Modifier la carte de paiement</translation>
-<translation id="1204242529756846967">Cette langue est utilisée pour corriger l'orthographe.</translation>
-<translation id="3981760180856053153">Le type d'enregistrement indiqué est incorrect.</translation>
-<translation id="8464591670878858520">Forfait de données <ph name="NETWORK"/> arrivé à expiration</translation>
-<translation id="4568660204877256194">Exporter mes favoris...</translation>
-<translation id="3116361045094675131">Clavier britannique</translation>
-<translation id="4577070033074325641">Importer des favoris...</translation>
-<translation id="1641504961675316934"><ph name="CLOUD_PRINT_NAME"/></translation>
-<translation id="1715941336038158809">Nom d'utilisateur ou mot de passe incorrect</translation>
-<translation id="1901303067676059328">&amp;Tout sélectionner</translation>
-<translation id="674375294223700098">Erreur inconnue liée au certificat du serveur.</translation>
-<translation id="7780428956635859355">Envoyer une capture d'écran enregistrée</translation>
-<translation id="2850961597638370327">Émis pour : <ph name="NAME"/></translation>
-<translation id="2168039046890040389">Page précédente</translation>
-<translation id="1767519210550978135">Hsu</translation>
-<translation id="2498539833203011245">Réduire</translation>
-<translation id="2893168226686371498">Navigateur par défaut</translation>
-<translation id="2435457462613246316">Afficher le mot de passe</translation>
-<translation id="7988355189918024273">Activer les fonctionnalités d'accessibilité</translation>
-<translation id="5438653034651341183">Inclure la capture d'écran actuelle :</translation>
-<translation id="1899708097738826574"><ph name="OPTIONS_TITLE"/> - <ph name="SUBPAGE_TITLE"/></translation>
-<translation id="1765313842989969521">(cette extension est gérée et ne peut être désinstallée ni désactivée)</translation>
-<translation id="6983783921975806247">OID enregistré</translation>
-<translation id="394984172568887996">Importés depuis IE</translation>
-<translation id="5311260548612583999">Fichier de clé privée (facultatif) :</translation>
-<translation id="2430043402233747791">Autoriser pour la session uniquement</translation>
-<translation id="7363290921156020669"><ph name="NUMBER_ZERO"/> mins</translation>
-<translation id="7568790562536448087">Mise à jour en cours</translation>
-<translation id="4856408283021169561">Aucun microphone trouvé.</translation>
-<translation id="8190193592390505034">Connexion à <ph name="PROVIDER_NAME"/></translation>
-<translation id="6144890426075165477"><ph name="PRODUCT_NAME"/> n'est pas votre navigateur par défaut.</translation>
-<translation id="823241703361685511">Forfait</translation>
-<translation id="4068506536726151626">Cette page contient des éléments des sites ci-dessous qui suivent votre position géographique :</translation>
-<translation id="4721475475128190282">Plusieurs profils</translation>
-<translation id="4220128509585149162">Plantages</translation>
-<translation id="8798099450830957504">Par défaut</translation>
-<translation id="9107059250669762581"><ph name="NUMBER_DEFAULT"/> jours</translation>
-<translation id="1640283014264083726">PKCS #1 MD4 avec chiffrement RSA</translation>
-<translation id="872451400847464257">Modifier le moteur de recherche</translation>
-<translation id="6463061331681402734"><ph name="NUMBER_MANY"/> minutes</translation>
-<translation id="2466804342846034717">Indiquez le mot de passe approprié ci-dessus, puis saisissez les caractères figurant dans l'image ci-dessous.</translation>
-<translation id="3881435075661337013">Expiration de <ph name="NETWORK"/> imminente</translation>
-<translation id="5681833099441553262">Activer l'onglet précédent</translation>
-<translation id="4792057643643237295">Désactiver l'accès à distance</translation>
-<translation id="1681614449735360921">Afficher les incompatibilités</translation>
-<translation id="19094784437781028">Carte de débit Solo</translation>
-<translation id="2657327428424666237"><ph name="BEGIN_LINK"/>Actualisez<ph name="END_LINK"/> cette page Web ultérieurement.</translation>
-<translation id="7347751611463936647">Pour utiliser cette extension, saisissez &quot;<ph name="EXTENSION_KEYWORD"/>&quot;, TAB, puis votre commande ou votre recherche.</translation>
-<translation id="659432221160402784"><ph name="PRODUCT_NAME"/> synchronisera les applications installées, afin que vous puissiez y accéder en vous connectant depuis tout navigateur <ph name="PRODUCT_NAME"/>.</translation>
-<translation id="892464165639979917">Langues et paramètres du correcteur orthographique...</translation>
-<translation id="5645845270586517071">Erreur de sécurité</translation>
-<translation id="2805756323405976993">Applications</translation>
-<translation id="3651020361689274926">La ressource demandée n'existe plus et aucune adresse de transfert n'est disponible. Il semble que cet état de fait soit permanent.</translation>
-<translation id="2989786307324390836">Certificat unique binaire codé DER</translation>
-<translation id="3827774300009121996">&amp;Plein écran</translation>
-<translation id="3771294271822695279">Fichiers vidéo</translation>
-<translation id="6704875430222476107"><ph name="PRODUCT_NAME"/> indique que
- NetNanny intercepte les connexions sécurisées. En général, cela
- ne constitue pas un problème de sécurité, car le logiciel NetNanny s'exécute souvent
- sur le même ordinateur. Toutefois, en raison de certaines incompatibilités avec
- les connexions sécurisées Google Chrome, vous devez configurer NetNanny
- de manière à éviter ces interceptions. Cliquez sur le lien En savoir plus pour obtenir des instructions.</translation>
-<translation id="3388026114049080752">Vos onglets et activités de navigation</translation>
-<translation id="7525067979554623046">Créer</translation>
-<translation id="4711094779914110278">Turc</translation>
-<translation id="1031460590482534116">Une erreur s'est produite lors de la tentative d'enregistrement du certificat client. Erreur <ph name="ERROR_NUMBER"/> (<ph name="ERROR_NAME"/>)</translation>
-<translation id="7136984461011502314">Bienvenue dans <ph name="PRODUCT_NAME"/></translation>
-<translation id="1594030484168838125">Sélectionner</translation>
-<translation id="204497730941176055">Nom du modèle de certificat Microsoft</translation>
-<translation id="6705264787989366486">Configuration de l'adresse IP pour <ph name="NAME"/></translation>
-<translation id="8970721300630048025">Immortalisez votre plus beau sourire et utilisez la photo comme image de compte.</translation>
-<translation id="4087089424473531098">Extension créée :
-
-<ph name="EXTENSION_FILE"/></translation>
-<translation id="16620462294541761">Mot de passe incorrect. Veuillez réessayer.</translation>
-<translation id="5017508259293544172">LEAP</translation>
-<translation id="1394630846966197578">Échec de la connexion aux serveurs de reconnaissance vocale.</translation>
-<translation id="2498765460639677199">Très grande</translation>
-<translation id="2378982052244864789">Sélectionner le répertoire de l'extension</translation>
-<translation id="7861215335140947162">&amp;Téléchargements</translation>
-<translation id="4778630024246633221">Gestionnaire des certificats</translation>
-<translation id="6705050455568279082"><ph name="URL"/> souhaite suivre votre position géographique</translation>
-<translation id="4708849949179781599">Quitter <ph name="PRODUCT_NAME"/></translation>
-<translation id="2505402373176859469"><ph name="RECEIVED_AMOUNT"/> sur <ph name="TOTAL_SIZE"/></translation>
-<translation id="6644512095122093795">Proposer d'enregistrer les mots de passe</translation>
-<translation id="4724450788351008910">Modification de l'affiliation</translation>
-<translation id="2249605167705922988">par exemple : 1-5, 8, 11-13</translation>
-<translation id="8691686986795184760">(Activé par une stratégie d'entreprise)</translation>
-<translation id="1911483096198679472">Qu'est-ce que c'est ?</translation>
-<translation id="1976323404609382849">Les cookies de plusieurs sites ont été bloqués.</translation>
-<translation id="2662952950313424742">Serveur DNS spécifié par l'utilisateur et utilisé par Google Chrome, à la place du paramètre système par défaut, pour les résolutions DNS.</translation>
-<translation id="4176463684765177261">Désactivé</translation>
-<translation id="2079545284768500474">Annuler</translation>
-<translation id="114140604515785785">Répertoire racine de l'extension :</translation>
-<translation id="4788968718241181184">Mode de saisie du vietnamien (TCVN6064)</translation>
-<translation id="1512064327686280138">Échec de l'activation</translation>
-<translation id="3254409185687681395">Ajouter cette page aux favoris</translation>
-<translation id="1384616079544830839">L'identité de ce site Web a été vérifiée par <ph name="ISSUER"/>.</translation>
-<translation id="8710160868773349942">Adresse e-mail : <ph name="EMAIL_ADDRESSES"/></translation>
-<translation id="4057991113334098539">Activation...</translation>
-<translation id="9073281213608662541">PAP</translation>
-<translation id="1800035677272595847">Sites de phishing</translation>
-<translation id="8448317557906454022"><ph name="NUMBER_ZERO"/> secs ago</translation>
-<translation id="402759845255257575">Interdire à tous les sites d'exécuter JavaScript</translation>
-<translation id="4610637590575890427">Vouliez-vous accéder à <ph name="SITE"/> ?</translation>
-<translation id="7723779034587221017">La connexion avec le service de configuration a été perdue. Veuillez réinitialiser votre périphérique ou contacter votre représentant de l'assistance technique.</translation>
-<translation id="3046388203776734202">Paramètres des fenêtres pop-up :</translation>
-<translation id="3437994698969764647">Tout exporter...</translation>
-<translation id="8349305172487531364">Barre de favoris</translation>
-<translation id="1898064240243672867">Stocké dans : <ph name="CERT_LOCATION"/></translation>
-<translation id="444134486829715816">Développer...</translation>
-<translation id="1401874662068168819">Gin Yieh</translation>
-<translation id="7208899522964477531">Rechercher <ph name="SEARCH_TERMS"/> sur <ph name="SITE_NAME"/></translation>
-<translation id="6255097610484507482">Modifier la carte de paiement</translation>
-<translation id="5584091888252706332">Au démarrage</translation>
-<translation id="8960795431111723921">Nous examinons actuellement le problème.</translation>
-<translation id="2482878487686419369">Notifications</translation>
-<translation id="8004582292198964060">Navigateur</translation>
-<translation id="695755122858488207">Case d'option décochée</translation>
-<translation id="6357135709975569075"><ph name="NUMBER_ZERO"/> days</translation>
-<translation id="8666678546361132282">Anglais</translation>
-<translation id="2224551243087462610">Modifier le nom du dossier</translation>
-<translation id="1358741672408003399">Grammaire et orthographe</translation>
-<translation id="4910673011243110136">Réseaux privés</translation>
-<translation id="2527167509808613699">Toutes sortes de connexions</translation>
-<translation id="9095710730982563314">Exceptions liées aux notifications</translation>
-<translation id="8072988827236813198">Épingler les onglets</translation>
-<translation id="1234466194727942574">Barre d'onglets</translation>
-<translation id="7974087985088771286">Activer l'onglet 6</translation>
-<translation id="4035758313003622889">Gestionnaire de &amp;tâches</translation>
-<translation id="6356936121715252359">Paramètres de stockage d'Adobe Flash Player...</translation>
-<translation id="5885996401168273077">Connexion au réseau</translation>
-<translation id="7313804056609272439">Mode de saisie du vietnamien (VNI)</translation>
-<translation id="1768211415369530011">L'application suivante va être lancée si vous acceptez cette requête :\n\n<ph name="APPLICATION"/></translation>
-<translation id="8793043992023823866">Importation...</translation>
-<translation id="8106211421800660735">N° de carte</translation>
-<translation id="2550839177807794974">Gérer les moteurs de recherche...</translation>
-<translation id="7031711645186424727">Utiliser un moniteur externe</translation>
-<translation id="6316768948917110108">Gravure de l'image en cours...</translation>
-<translation id="5089810972385038852">État</translation>
-<translation id="2872961005593481000">Éteindre</translation>
-<translation id="8986267729801483565">Enregistrer les fichiers dans le dossier :</translation>
-<translation id="4322394346347055525">Fermer les autres onglets</translation>
-<translation id="4411770745820968260">Répertoire de fichiers</translation>
-<translation id="881799181680267069">Masquer les autres</translation>
-<translation id="1812631533912615985">Annuler l'épinglage des onglets</translation>
-<translation id="6042308850641462728">Plus</translation>
-<translation id="8318945219881683434">Échec de la vérification de la révocation</translation>
-<translation id="1650709179466243265">Ajouter www. et .com, puis ouvrir la page</translation>
-<translation id="3524079319150349823">Pour inspecter un pop-up, cliquez avec le bouton droit sur la page ou sur l'icône d'action du navigateur, puis sélectionnez Inspecter le pop-up.</translation>
-<translation id="994289308992179865">&amp;Répéter</translation>
-<translation id="7793343764764530903"><ph name="CLOUD_PRINT_NAME"/> est à présent activé. <ph name="PRODUCT_NAME"/> a enregistré les imprimantes installées sur cette machine en les associant à &lt;b&gt;<ph name="EMAIL_ADDRESSES"/>&lt;/b&gt;. Vous pouvez désormais utiliser vos imprimantes depuis n'importe quelle application Web ou mobile associée à <ph name="CLOUD_PRINT_NAME"/>.</translation>
-<translation id="1703490097606704369">Le serveur de <ph name="HOST_NAME"/>
- est introuvable, car la résolution DNS a échoué. DNS est le service Web qui
- traduit les noms de site Web en adresses Internet. Cette erreur est
- généralement due à l'absence de connexion Internet ou à une configuration
- incorrecte du réseau. Cela peut également venir d'un serveur DNS qui ne
- répond pas ou d'un pare-feu interdisant l'accès de
- <ph name="PRODUCT_NAME"/>
- au réseau.</translation>
-<translation id="8887090188469175989">ZGPY</translation>
-<translation id="3302709122321372472">Impossible de charger le fichier css &quot;<ph name="RELATIVE_PATH"/>&quot; du script de contenu.</translation>
-<translation id="305803244554250778">Créer des raccourcis vers des applications aux emplacements suivants :</translation>
-<translation id="574392208103952083">Moyenne</translation>
-<translation id="3745810751851099214">Envoyé pour :</translation>
-<translation id="3937609171782005782">Aider Google à détecter les logiciels malveillants en envoyant des données supplémentaires concernant les sites pour lesquels cet avertissement s'affiche. Ces données seront gérées conformément aux règles définies sur la page <ph name="PRIVACY_PAGE_LINK"/>.</translation>
-<translation id="8877448029301136595">[répertoire parent]</translation>
-<translation id="7301360164412453905">Touches de sélection du clavier Hsu</translation>
-<translation id="8631271110654520730">Copie de l'image de récupération...</translation>
-<translation id="1963227389609234879">Tout supprimer</translation>
-<translation id="7779140087128114262">Seule une personne en possession de votre mot de passe multiterme peut lire vos données chiffrées. Google ne reçoit ni n'enregistre votre mot de passe multiterme. Si vous oubliez votre mot de passe multiterme, vous devrez réinitialiser la synchronisation.</translation>
-<translation id="8027581147000338959">Ouvrir dans une nouvelle fenêtre</translation>
-<translation id="6030946405726632495">Impossible de créer le dossier &quot;$1&quot;: $2</translation>
-<translation id="8019305344918958688">Dommage... Aucune extension n'est installée. :-(</translation>
-<translation id="7466861475611330213">Style de ponctuation</translation>
-<translation id="2496180316473517155">Historique de navigation</translation>
-<translation id="602251597322198729">Ce site tente de télécharger plusieurs fichiers. Voulez-vous autoriser le chargement ?</translation>
-<translation id="5843685321177053287">Établissement de la liaison avec le service de gestion des périphériques en attente...</translation>
-<translation id="2052389551707911401"><ph name="NUMBER_MANY"/> heures</translation>
-<translation id="5411472733320185105">Ne pas utiliser les paramètres du proxy pour les hôtes et domaines suivants :</translation>
-<translation id="6691936601825168937">&amp;Avancer</translation>
-<translation id="6566142449942033617">Impossible de charger &quot;<ph name="PLUGIN_PATH"/>&quot; pour le plug-in.</translation>
-<translation id="7065534935986314333">À propos du système</translation>
-<translation id="45025857977132537">Utilisation de la clé du certificat : <ph name="USAGES"/></translation>
-<translation id="6454421252317455908">Mode de saisie du chinois (quick)</translation>
-<translation id="368789413795732264">Une erreur s'est produite lors de la tentative d'écriture du fichier : <ph name="ERROR_TEXT"/>.</translation>
-<translation id="1173894706177603556">Renommer</translation>
-<translation id="5670032673361607750">La synchronisation requiert votre attention.</translation>
-<translation id="2148716181193084225">Aujourd'hui</translation>
-<translation id="1002064594444093641">Imp&amp;rimer le cadre...</translation>
-<translation id="7234674978021619913">Le site <ph name="HOST_NAME"/> a déjà été informé qu'un logiciel malveillant a été détecté sur ses pages. Pour plus d'informations concernant les problèmes rencontrés sur <ph name="HOST_NAME2"/>, consultez notre <ph name="DIAGNOSTIC_PAGE"/> Google.</translation>
-<translation id="8202390211066742724">Adresse de serveur DNS spécifiée par l'utilisateur.</translation>
-<translation id="4608500690299898628">&amp;Rechercher...</translation>
-<translation id="3574305903863751447"><ph name="CITY"/>, <ph name="STATE"/> <ph name="COUNTRY"/></translation>
-<translation id="8724859055372736596">&amp;Afficher dans le dossier</translation>
-<translation id="4605399136610325267">Non connecté à Internet.</translation>
-<translation id="978407797571588532">Sélectionnez
- <ph name="BEGIN_BOLD"/>
- Démarrer &gt; Panneau de configuration &gt; Connexions réseau &gt; Assistant Nouvelle connexion
- <ph name="END_BOLD"/>
- pour tester votre connexion.</translation>
-<translation id="5554489410841842733">Cette icône s'affiche lorsque l'extension peut agir sur la page active.</translation>
-<translation id="579702532610384533">Reconnexion</translation>
-<translation id="4862642413395066333">Réponses OCSP de signature</translation>
-<translation id="5266113311903163739">Erreur d'importation de l'autorité de certification</translation>
-<translation id="9563164493805065">Gravure de l'image terminée.</translation>
-<translation id="4756388243121344051">&amp;Historique</translation>
-<translation id="3789841737615482174">Installer</translation>
-<translation id="4320697033624943677">Ajouter des utilisateurs</translation>
-<translation id="9153934054460603056">Enregistrer l'authentification et le mot de passe</translation>
-<translation id="1455548678241328678">Clavier norvégien</translation>
-<translation id="2520481907516975884">Basculer en mode chinois/anglais</translation>
-<translation id="8571890674111243710">Traduction de la page en <ph name="LANGUAGE"/>...</translation>
-<translation id="4789872672210757069">À propos de &amp;<ph name="PRODUCT_NAME"/></translation>
-<translation id="4056561919922437609"><ph name="TAB_COUNT"/> onglets</translation>
-<translation id="4373894838514502496">il y a <ph name="NUMBER_FEW"/> minutes</translation>
-<translation id="6358450015545214790">Qu'est-ce que c'est ?</translation>
-<translation id="6264365405983206840">Tout &amp;sélectionner</translation>
-<translation id="1017280919048282932">&amp;Ajouter au dictionnaire</translation>
-<translation id="8319414634934645341">Utilisation étendue de la clé</translation>
-<translation id="4563210852471260509">Le chinois est la langue de saisie initiale</translation>
-<translation id="6897140037006041989">Agent utilisateur</translation>
-<translation id="3413122095806433232">Émetteurs de l'autorité de certification : <ph name="LOCATION"/></translation>
-<translation id="4115153316875436289"><ph name="NUMBER_TWO"/> jours</translation>
-<translation id="701080569351381435">Code source</translation>
-<translation id="3286538390144397061">Redémarrer maintenant</translation>
-<translation id="163309982320328737">La largeur de caractères initiale est Complète</translation>
-<translation id="5107325588313356747">Pour masquer l'accès à ce programme, vous devez le désinstaller au moyen de \n<ph name="CONTROL_PANEL_APPLET_NAME"/> du Panneau de configuration.\n\nSouhaitez-vous exécuter <ph name="CONTROL_PANEL_APPLET_NAME"/> ?</translation>
-<translation id="4841055638263130507">Paramètres du microphone</translation>
-<translation id="6965648386495488594">Port</translation>
-<translation id="7631887513477658702">&amp;Toujours ouvrir les fichiers de ce type</translation>
-<translation id="8627795981664801467">Uniquement les connexions sécurisées</translation>
-<translation id="8680787084697685621">Les informations de connexion au compte sont obsolètes.</translation>
-<translation id="3228969707346345236">La traduction a échoué, car la page est déjà en <ph name="LANGUAGE"/>.</translation>
-<translation id="1873879463550486830">Sandbox SUID</translation>
-<translation id="2190355936436201913">(vide)</translation>
-<translation id="8515737884867295000">Échec de l'authentification basée sur le certificat</translation>
-<translation id="5868426874618963178">Envoyer le code source de la page actuelle</translation>
-<translation id="1269138312169077280">Votre administrateur a désactivé certains paramètres.</translation>
-<translation id="5818003990515275822">Coréen</translation>
-<translation id="4182252350869425879">Avertissement : Il s'agit peut-être d'un site de phishing !</translation>
-<translation id="5458214261780477893">Dvorak</translation>
-<translation id="5353719617589986386">Étendue de pages incorrecte</translation>
-<translation id="1164369517022005061"><ph name="NUMBER_DEFAULT"/> heures restantes</translation>
-<translation id="5943260032016910017">Exceptions liées aux cookies et aux données de site</translation>
-<translation id="2214283295778284209"><ph name="SITE"/> n'est pas accessible</translation>
-<translation id="8755376271068075440">P&amp;lus grand</translation>
-<translation id="8132793192354020517">Connecté à <ph name="NAME"/></translation>
-<translation id="8187473050234053012">Le certificat de sécurité du site a été révoqué !</translation>
-<translation id="7444983668544353857">Désactiver <ph name="NETWORKDEVICE"/></translation>
-<translation id="6003177993629630467"><ph name="PRODUCT_NAME"/> risque de ne pas rester à jour.</translation>
-<translation id="421577943854572179">intégré sur tout autre site</translation>
-<translation id="580886651983547002"><ph name="PRODUCT_NAME"/>
- ne parvient pas à atteindre le site Web. Cela vient probablement d'un problème de réseau,
- mais peut également être dû à un pare-feu ou à un serveur proxy mal configuré.</translation>
-<translation id="5445557969380904478">À propos de la reconnaissance vocale</translation>
-<translation id="3093473105505681231">Langues et paramètres du correcteur orthographique...</translation>
-<translation id="152482086482215392"><ph name="NUMBER_ONE"/> seconde restante</translation>
-<translation id="529172024324796256">Nom d'utilisateur :</translation>
-<translation id="3308116878371095290">Le stockage des cookies n'est pas autorisé pour cette page.</translation>
-<translation id="7521387064766892559">JavaScript</translation>
-<translation id="1545786162090505744">URL avec %s à la place de la requête</translation>
-<translation id="7219179957768738017">La connexion utilise <ph name="SSL_VERSION"/>.</translation>
-<translation id="7014174261166285193">Échec de l'installation</translation>
-<translation id="1970746430676306437">Afficher les &amp;infos sur la page</translation>
-<translation id="3199127022143353223">Serveurs</translation>
-<translation id="2805646850212350655">Système de fichiers de chiffrement Microsoft </translation>
-<translation id="8053959338015477773">Un plug-in supplémentaire est requis pour afficher certains éléments sur cette page.</translation>
-<translation id="3541661933757219855">Appuyez sur Ctrl+Alt+/ ou sur Échap pour masquer</translation>
-<translation id="8813873272012220470">Cette fonctionnalité effectue des vérifications en arrière-plan et vous avertit en cas d'incompatibilité logicielle (modules tiers bloquant le navigateur, par exemple).</translation>
-<translation id="5020734739305654865">Connexion avec</translation>
-<translation id="2679385451463308372">Imprimer depuis la boîte de dialogue système…</translation>
-<translation id="7414887922320653780"><ph name="NUMBER_ONE"/> heure restante</translation>
-<translation id="121632099317611328">Échec de l'initialisation de l'appareil photo</translation>
-<translation id="399179161741278232">Importés</translation>
-<translation id="3829932584934971895">Type de fournisseur :</translation>
-<translation id="462288279674432182">IP restreinte :</translation>
-<translation id="3927932062596804919">Refuser</translation>
-<translation id="3524915994314972210">Démarrage du téléchargement en cours...</translation>
-<translation id="6484929352454160200">Une nouvelle version de <ph name="PRODUCT_NAME"/> est disponible.</translation>
-<translation id="3187212781151025377">Clavier hébreu</translation>
-<translation id="351152300840026870">Police à largeur fixe</translation>
-<translation id="5827266244928330802">Safari</translation>
-<translation id="778881183694837592">Les champs obligatoires ne doivent pas rester vides.</translation>
-<translation id="2371076942591664043">Ouvrir une fois le téléchargement &amp;terminé</translation>
-<translation id="3920504717067627103">Stratégies de certificat</translation>
-<translation id="155865706765934889">Pavé tactile</translation>
-<translation id="7701040980221191251">Aucun</translation>
-<translation id="5917011688104426363">Activer la barre d'adresse en mode recherche</translation>
-<translation id="6910239454641394402">Exceptions pour JavaScript</translation>
-<translation id="2979639724566107830">Ouvrir dans une nouvelle fenêtre</translation>
-<translation id="3269101346657272573">Veuillez saisir le code PIN.</translation>
-<translation id="9204065299849069896">Options de saisie automatique...</translation>
-<translation id="2822854841007275488">Arabe</translation>
-<translation id="5857090052475505287">Nouveau dossier</translation>
-<translation id="7450732239874446337">E/S réseau interrompue</translation>
-<translation id="5178667623289523808">Rechercher le précédent</translation>
-<translation id="2815448242176260024">Ne jamais enregistrer les mots de passe</translation>
-<translation id="2989805286512600854">Ouvrir dans un nouvel onglet</translation>
-<translation id="8687485617085920635">Fenêtre suivante</translation>
-<translation id="4122118036811378575">&amp;Rechercher le suivant</translation>
-<translation id="6008256403891681546">JCB</translation>
-<translation id="2610780100389066815">Signature de liste d'approbation Microsoft</translation>
-<translation id="8289811203643526145">Gérer les certificats...</translation>
-<translation id="2788575669734834343">Sélectionnez le fichier de certificat.</translation>
-<translation id="8404409224170843728">Fabricant :</translation>
-<translation id="8267453826113867474">Bloquer le contenu inapproprié</translation>
-<translation id="7959074893852789871">Le fichier contenait plusieurs certificats, dont certains n'ont pas été importés :</translation>
-<translation id="1213999834285861200">Exceptions pour les images</translation>
-<translation id="2805707493867224476">Autoriser tous les sites à afficher des fenêtres pop-up</translation>
-<translation id="3561217442734750519">Vous devez indiquer un chemin valide comme valeur de clé privée.</translation>
-<translation id="2444609190341826949">Sans mot de passe multiterme, vos mots de passe et autres données chiffrées ne seront pas synchronisés sur cet ordinateur.</translation>
-<translation id="77221669950527621">Extensions ou applications</translation>
-<translation id="6650142020817594541">Ce site recommande Google Chrome Frame (déjà installé).</translation>
-<translation id="6503077044568424649">Les plus visités</translation>
-<translation id="4625904365165566833">Vous n'êtes pas autorisé à vous connecter. Consultez le propriétaire de cet ordinateur portable.</translation>
-<translation id="7450633916678972976">Remarque : Lorsque vous cliquez sur &quot;Envoyer&quot;, Google Chrome joint à votre
- envoi un journal indiquant votre version de Google Chrome et celle du système
- d'exploitation utilisé, ainsi que l'URL associée à votre rapport. Vous pouvez
- également joindre une capture d'écran. Ces informations nous
- permettent de diagnostiquer les problèmes et d'améliorer les performances de
- Google Chrome. Les informations personnelles fournies sciemment dans vos
- commentaires ou involontairement dans le journal, l'URL ou la capture
- d'écran sont protégées conformément à nos règles de
- confidentialité. Si vous ne souhaitez pas indiquer d'URL et/ou de capture
- d'écran, décochez les cases &quot;Inclure cette URL&quot; et/ou &quot;Inclure cette capture d'écran&quot;. Vous acceptez que Google utilise vos commentaires pour améliorer ses produits ou services.</translation>
-<translation id="465365366590259328">Vos modifications seront prises en compte au prochain démarrage de <ph name="PRODUCT_NAME"/>.</translation>
-<translation id="7168109975831002660">Taille de police minimale</translation>
-<translation id="7070804685954057874">Entrée directe</translation>
-<translation id="3265459715026181080">Fermer la fenêtre</translation>
-<translation id="6074871234879228294">Mode de saisie du japonais (pour clavier japonais)</translation>
-<translation id="7855296476260297092">Inscription réussie</translation>
-<translation id="907841381057066561">Échec de création du fichier zip temporaire lors de la création du pack</translation>
-<translation id="1294298200424241932">Modifier les paramètres de confiance :</translation>
-<translation id="1384617406392001144">Votre historique de navigation</translation>
-<translation id="3831099738707437457">&amp;Masquer le panneau de la vérification orthographique</translation>
-<translation id="1040471547130882189">Plug-in ne répondant pas</translation>
-<translation id="5473075389972733037">IBM</translation>
-<translation id="8307664665247532435">Les paramètres seront effacés lors de la prochaine actualisation.</translation>
-<translation id="790025292736025802"><ph name="URL"/> introuvable</translation>
-<translation id="895347679606913382">Démarrage...</translation>
-<translation id="3319048459796106952">Nouvelle fenêtre de nav&amp;igation privée</translation>
-<translation id="5832669303303483065">Ajouter une adresse postale...</translation>
-<translation id="3127919023693423797">Authentification en cours...</translation>
-<translation id="4195643157523330669">Ouvrir dans un nouvel onglet</translation>
-<translation id="8030169304546394654">Déconnecté</translation>
-<translation id="4010065515774514159">Action du navigateur</translation>
-<translation id="4286563808063000730">Le mot de passe multiterme saisi ne peut pas être utilisé, car vous avez déjà chiffré des données avec un mot de passe multiterme. Entrez ci-dessous le mot de passe multiterme actuellement défini pour la synchronisation.</translation>
-<translation id="1154228249304313899">Ouvrir cette page :</translation>
-<translation id="9074348188580488499">Voulez-vous vraiment supprimer tous les mots de passe ?</translation>
-<translation id="6635491740861629599">Sélectionner par domaine</translation>
-<translation id="3627588569887975815">Ouvrir le lien dans une fenêtre en navi&amp;gation privée</translation>
-<translation id="5851868085455377790">Émetteur</translation>
-<translation id="8223496248037436966">Options de saisie automatique</translation>
-<translation id="1470719357688513792">Les nouveaux paramètres des cookies seront appliqués quand vous aurez actualisé la page.</translation>
-<translation id="5578327870501192725">Votre connexion à <ph name="DOMAIN"/> est sécurisée par un chiffrement <ph name="BIT_COUNT"/> bits.</translation>
-<translation id="869884720829132584">Menu Applications</translation>
-<translation id="7764209408768029281">Outi&amp;ls</translation>
-<translation id="1139892513581762545">Onglets latéraux</translation>
-<translation id="7634357567062076565">Reprendre</translation>
-<translation id="4779083564647765204">Zoom</translation>
-<translation id="3282430104564575032">Inspecteur de DOM</translation>
-<translation id="1526560967942511387">Document sans titre</translation>
-<translation id="1291144580684226670">Police standard</translation>
-<translation id="3979748722126423326">Activer <ph name="NETWORKDEVICE"/></translation>
-<translation id="5538307496474303926">Opération en cours...</translation>
-<translation id="4367133129601245178">C&amp;opier l'URL de l'image</translation>
-<translation id="7542995811387359312">La saisie automatique des numéros de carte de paiement est désactivée, car la connexion utilisée par ce formulaire n'est pas sécurisée.</translation>
-<translation id="3494444535872870968">Enregistrer le &amp;cadre sous...</translation>
-<translation id="987264212798334818">Général</translation>
-<translation id="7005812687360380971">Défaillance</translation>
-<translation id="2356070529366658676">Demander</translation>
-<translation id="5731247495086897348">Coller l'URL et y a&amp;ccéder</translation>
-<translation id="8467548439852845758">Pour plus de sécurité, <ph name="PRODUCT_NAME"/> va chiffrer vos mots de passe.</translation>
-<translation id="2524947000814989347">Si vous avez oublié votre mot de passe multiterme, vous devrez arrêter la synchronisation via Google Dashboard.</translation>
-<translation id="8018154597338652331"><ph name="BURNT_AMOUNT"/> sur <ph name="TOTAL_SIZE"/></translation>
-<translation id="7635741716790924709">Adresse ligne 1</translation>
-<translation id="5135533361271311778">Impossible de créer le favori.</translation>
-<translation id="5271247532544265821">Basculer en mode chinois simplifié/traditionnel</translation>
-<translation id="2052610617971448509">Votre système Sandbox n'est pas correctement configuré.</translation>
-<translation id="7384913436093989340">Sélectionnez le <ph name="BEGIN_BOLD"/>menu clé à molette &gt; Préférences &gt; Options avancées &gt; Modifier les paramètres du proxy<ph name="END_BOLD"/> et vérifiez que vos paramètres sont définis sur &quot;sans proxy&quot; ou &quot;direct&quot;.</translation>
-<translation id="6417515091412812850">Impossible de vérifier si le certificat a été révoqué.</translation>
-<translation id="7282743297697561153">Stockage des données</translation>
-<translation id="3363332416643747536"><ph name="DOWNLOAD_RECEIVED"/>/<ph name="DOWNLOAD_TOTAL"/>, Interrompu</translation>
-<translation id="7347702518873971555">Acheter un forfait</translation>
-<translation id="5285267187067365830">Installer le plug-in...</translation>
-<translation id="5334844597069022743">Afficher le code source</translation>
-<translation id="1166212789817575481">Fermer les onglets sur la droite</translation>
-<translation id="6472893788822429178">Afficher le bouton &quot;Accueil&quot;</translation>
-<translation id="4270393598798225102">Version <ph name="NUMBER"/></translation>
-<translation id="534916491091036097">Parenthèse gche</translation>
-<translation id="4157869833395312646">Microsoft Server Gated Cryptography</translation>
-<translation id="8903921497873541725">Zoom avant</translation>
-<translation id="2195729137168608510">Protection du courrier électronique</translation>
-<translation id="1425734930786274278">Les cookies suivants ont été bloqués (tous les cookies tiers sont bloqués, sans exception) :</translation>
-<translation id="6805647936811177813">Connectez-vous à <ph name="TOKEN_NAME"/> pour importer le certificat client de <ph name="HOST_NAME"/></translation>
-<translation id="3437016096396740659">La batterie est chargée.</translation>
-<translation id="6916146760805488559">Créer un nouveau profil...</translation>
-<translation id="1199232041627643649">Maintenez la touche <ph name="KEY_EQUIVALENT"/> enfoncée pour quitter.</translation>
-<translation id="5428562714029661924">Masquer ce plug-in</translation>
-<translation id="7907591526440419938">Ouvrir le fichier</translation>
-<translation id="2568774940984945469">Conteneur de barres d'infos</translation>
-<translation id="8971063699422889582">Le certificat du serveur a expiré.</translation>
-<translation id="8281596639154340028">Utiliser <ph name="HANDLER_TITLE"/></translation>
-<translation id="7134098520442464001">Réduit la taille du texte</translation>
-<translation id="21133533946938348">Épingler l'onglet</translation>
-<translation id="1325040735987616223">Mise à jour du système</translation>
-<translation id="2864069933652346933"><ph name="NUMBER_ZERO"/> days left</translation>
-<translation id="9090669887503413452">Inclure les informations système</translation>
-<translation id="3084771660770137092">Google Chrome n'avait pas suffisamment de mémoire ou le processus de la page Web a été arrêté pour une autre raison. Pour continuer, actualisez la page ou ouvrez-en une autre.</translation>
-<translation id="1114901192629963971">Impossible de valider votre mot de passe sur le réseau actuel. Sélectionnez un autre réseau.</translation>
-<translation id="5179510805599951267">Cette page n'est pas rédigée en <ph name="ORIGINAL_LANGUAGE"/> ? Signaler l'erreur</translation>
-<translation id="6430814529589430811">Certificat unique codé Base 64 ASCII</translation>
-<translation id="5143712164865402236">Activer le mode plein écran</translation>
-<translation id="8434177709403049435">Codag&amp;e</translation>
-<translation id="4051923669149193910"><ph name="HANDLER_TITLE"/> est déjà utilisé pour gérer les liens <ph name="PROTOCOL"/>://.</translation>
-<translation id="2722201176532936492">Touches de sélection</translation>
-<translation id="385120052649200804">Clavier international américain</translation>
-<translation id="9012607008263791152">Je comprends que la visite de ce site peut être préjudiciable à mon ordinateur.</translation>
-<translation id="6640442327198413730">Ressource cache manquante.</translation>
-<translation id="1441458099223378239">Impossible d'accéder à mon compte</translation>
-<translation id="5793220536715630615">C&amp;opier l'URL de la vidéo</translation>
-<translation id="523397668577733901">Vous préférez <ph name="BEGIN_LINK"/>parcourir la galerie<ph name="END_LINK"/> ?</translation>
-<translation id="2922350208395188000">Impossible de vérifier le certificat du serveur.</translation>
-<translation id="3778740492972734840">Outils de &amp;développement</translation>
-<translation id="8335971947739877923">Exporter...</translation>
-<translation id="5680966941935662618">Paramètres de saisie automatique</translation>
-<translation id="38385141699319881">Téléchargement de l'image en cours...</translation>
-<translation id="6004539838376062211">&amp;Options du vérificateur d'orthographe</translation>
-<translation id="5350198318881239970">Impossible d'ouvrir votre profil correctement.\n\nIl est possible que certaines fonctionnalités ne soient pas disponibles. Vérifiez que ce profil existe et que vous disposez d'une autorisation d'accès à son contenu en lecture et en écriture.</translation>
-<translation id="4058793769387728514">Vérifier le document maintenant</translation>
-<translation id="1810107444790159527">Zone de liste</translation>
-<translation id="3338239663705455570">Clavier slovène</translation>
-<translation id="1859234291848436338">Sens de l'écriture</translation>
-<translation id="4567836003335927027">Vos données sur <ph name="WEBSITE_1"/></translation>
-<translation id="756445078718366910">Ouvrir une fenêtre du navigateur</translation>
-<translation id="4126154898592630571">Conversion de la date et de l'heure</translation>
-<translation id="5088534251099454936">PKCS #1 SHA-512 avec chiffrement RSA</translation>
-<translation id="6392373519963504642">Clavier coréen</translation>
-<translation id="7887334752153342268">Dupliquer</translation>
-<translation id="4980691186726139495">Ne pas conserver sur cette page</translation>
-<translation id="3081523290047420375">Désactiver <ph name="CLOUD_PRINT_NAME"/></translation>
-<translation id="9207194316435230304">ATOK</translation>
-<translation id="9026731007018893674">téléchargement</translation>
-<translation id="7646591409235458998">E-mail :</translation>
-<translation id="703748601351783580">Ouvrir tous les favoris dans une nouvelle &amp;fenêtre</translation>
-<translation id="6199775032047436064">Rafraîchir la page actuelle</translation>
-<translation id="6981982820502123353">Accessibilité</translation>
-<translation id="112343676265501403">Exceptions pour les plug-ins</translation>
-<translation id="770273299705142744">Remplissage automatique des formulaires</translation>
-<translation id="7210998213739223319">Nom d'utilisateur</translation>
-<translation id="4478664379124702289">Enregistrer le lie&amp;n sous...</translation>
-<translation id="8725066075913043281">Réessayer</translation>
-<translation id="8502249598105294518">Personnaliser et configurer <ph name="PRODUCT_NAME"/></translation>
-<translation id="7392089327262158658">Préférences de saisie automatique <ph name="PRODUCT_NAME_SHORT"/></translation>
-<translation id="4163521619127344201">Votre position géographique</translation>
-<translation id="3797008485206955964">Afficher les pages en arrière-plan (<ph name="NUM_BACKGROUND_APPS"/>)</translation>
-<translation id="8590375307970699841">Configurer les mises à jour automatiques</translation>
-<translation id="2797524280730715045">il y a <ph name="NUMBER_DEFAULT"/> heures</translation>
-<translation id="265390580714150011">Valeur du champ</translation>
-<translation id="9073247318500677671">Les dernières versions d'Unity et GNOME (ainsi que la prochaine version d'Ubuntu, Natty Narwhal) affichent une barre de menus de type OSX sur toute la largeur supérieure de l'écran.</translation>
-<translation id="3869917919960562512">Index erroné.</translation>
-<translation id="7031962166228839643">Préparation du module de plate-forme sécurisée (TPM) en cours. Veuillez patienter, l'opération peut prendre quelques minutes.</translation>
-<translation id="4250377793615429299">Nombre de copies incorrect</translation>
-<translation id="7180865173735832675">Personnaliser</translation>
-<translation id="5737306429639033676">Prédire les actions du réseau pour améliorer les performances de chargement des pages</translation>
-<translation id="8123426182923614874">Données restantes :</translation>
-<translation id="3707020109030358290">N'est pas une autorité de certification.</translation>
-<translation id="2115926821277323019">L'URL doit être valide.</translation>
-<translation id="8986494364107987395">Envoyer automatiquement les statistiques d'utilisation et les rapports d'erreur à Google</translation>
-<translation id="7070714457904110559">Cette fonctionnalité active la géolocalisation dans les extensions expérimentales. Cela implique l'utilisation des API de localisation du système d'exploitation (si disponibles) et l'envoi de données sur la configuration réseau locale au service de localisation de Google afin de déterminer une position précise.</translation>
-<translation id="6701535245008341853">Impossible de charger le profil.</translation>
-<translation id="527605982717517565">Toujours exécuter JavaScript sur <ph name="HOST"/></translation>
-<translation id="702373420751953740">Version PRL :</translation>
-<translation id="1307041843857566458">Confirmer la réactivation</translation>
-<translation id="8314308967132194952">Ajouter une adresse postale...</translation>
-<translation id="1221024147024329929">PKCS #1 MD2 avec chiffrement RSA</translation>
-<translation id="853265131227167869">Dim.^Lun.^Mar.^Mer.^Jeu.^Ven.^Sam.</translation>
-<translation id="3323447499041942178">Zone de saisie</translation>
-<translation id="580571955903695899">Trier par nom</translation>
-<translation id="5230516054153933099">Fenêtre</translation>
-<translation id="7554791636758816595">Nouvel onglet</translation>
-<translation id="5503844897713343920">Vous tentez d'accéder au site <ph name="DOMAIN"/>, mais le certificat présenté par le serveur a été révoqué par son émetteur. Cela signifie que les informations d'identification présentées par le serveur ne sont pas approuvées. Vous communiquez peut-être avec un pirate informatique. Nous vous déconseillons vivement de continuer.</translation>
-<translation id="6928853950228839340">Composition hors écran</translation>
-<translation id="1308727876662951186"><ph name="NUMBER_ZERO"/> mins left</translation>
-<translation id="7671576867600624">Technologie :</translation>
-<translation id="1103966635949043187">Accédez à la page d'accueil du site :</translation>
-<translation id="1951332921786364801">Configurer la communication à distance</translation>
-<translation id="1086613338090581534">L'émetteur d'un certificat n'ayant pas expiré est tenu d'assurer la maintenance de ce qui s'appelle &quot;une liste de révocation&quot;. Si un certificat est compromis, l'émetteur peut le révoquer en l'ajoutant à la liste de révocation. Ce certificat n'est alors plus approuvé par votre navigateur. Il n'est pas nécessaire d'assurer la maintenance de l'état &quot;révoqué&quot; des certificats expirés. Donc, bien qu'un certificat ait été qualifié de valide pour le site Web que vous visitez actuellement, il est impossible de déterminer s'il a été, depuis, compromis puis révoqué ou s'il est toujours valide. Par conséquent, il n'est pas possible de s'assurer si vous communiquez avec un site Web légitime ou si le certificat a été compromis et se trouve maintenant en la possession d'un pirate informatique avec lequel vous communiquez. Ne poursuivez pas.</translation>
-<translation id="2645575947416143543">Néanmoins, si vous travaillez dans une entreprise qui génère ses propres certificats, et que vous essayez de vous connecter au site Web interne de l'entreprise avec un certificat de ce type, vous pouvez résoudre ce problème en toute sécurité. Pour ce faire, importez le certificat racine de l'entreprise en tant que &quot;certificat racine&quot;. Par la suite, les certificats émis ou vérifiés par votre entreprise seront approuvés et vous ne verrez plus cette erreur lorsque vous tenterez de vous connecter à nouveau au site Web interne. Contactez le support informatique de votre entreprise pour savoir comment ajouter un nouveau certificat racine sur votre ordinateur.</translation>
-<translation id="376466258076168640">Définir <ph name="PRODUCT_NAME"/> en tant que navigateur par défaut</translation>
-<translation id="1056898198331236512">Avertissement</translation>
-<translation id="8630826211403662855">Préférences de recherche</translation>
-<translation id="8432745813735585631">Clavier Colemak américain</translation>
-<translation id="8151639108075998630">Activer la navigation en tant qu'invité</translation>
-<translation id="2608770217409477136">Utiliser les paramètres par défaut</translation>
-<translation id="3157931365184549694">Rétablir</translation>
-<translation id="7426243339717063209">Désinstaller &quot;<ph name="EXTENSION_NAME"/>&quot; ?</translation>
-<translation id="996250603853062861">Établissement de la connexion sécurisée...</translation>
-<translation id="6059232451013891645">Dossier :</translation>
-<translation id="4274292172790327596">Erreur non reconnue</translation>
-<translation id="760537465793895946">Consultez les conflits connus avec des modules tiers.</translation>
-<translation id="7042418530779813870">Co&amp;ller et rechercher</translation>
-<translation id="9110447413660189038">&amp;Remonter</translation>
-<translation id="375403751935624634">Échec de la traduction en raison d'une erreur de serveur</translation>
-<translation id="2101225219012730419">Version :</translation>
-<translation id="1570242578492689919">Polices et codage</translation>
-<translation id="3082374807674020857"><ph name="PAGE_TITLE"/> - <ph name="PAGE_URL"/></translation>
-<translation id="8050038245906040378">Signature du code commercial Microsoft</translation>
-<translation id="3031557471081358569">Sélectionnez les éléments à importer :</translation>
-<translation id="1368832886055348810">De gauche à droite</translation>
-<translation id="3031433885594348982">Votre connexion à <ph name="DOMAIN"/> est sécurisée par le biais d'un faible chiffrement.</translation>
-<translation id="4047345532928475040">sans objet</translation>
-<translation id="5604324414379907186">Toujours afficher la barre de favoris</translation>
-<translation id="3220630151624181591">Activer l'onglet 2</translation>
-<translation id="8898139864468905752">Aperçu des onglets</translation>
-<translation id="2799223571221894425">Redémarrer</translation>
-<translation id="5771816112378578655">Configuration en cours...</translation>
-<translation id="1197979282329025000">Une erreur s'est produite lors de la récupération des fonctions de l'imprimante <ph name="PRINTER_NAME"/>. Cette imprimante n'a pas pu être enregistrée dans <ph name="CLOUD_PRINT_NAME"/>.</translation>
-<translation id="8820901253980281117">Exceptions pour les fenêtres pop-up</translation>
-<translation id="1143142264369994168">Signataire du certificat </translation>
-<translation id="904949795138183864">La page Web <ph name="URL"/> n'existe plus.</translation>
-<translation id="3228279582454007836">Vous n'avez jamais visité ce site auparavant.</translation>
-<translation id="2159017110205600596">Personnaliser...</translation>
-<translation id="5449716055534515760">Fe&amp;rmer la fenêtre</translation>
-<translation id="2814489978934728345">Arrêter le chargement de cette page</translation>
-<translation id="2354001756790975382">Autres favoris</translation>
-<translation id="8561574028787046517"><ph name="PRODUCT_NAME"/> a été mis à jour.</translation>
-<translation id="5234325087306733083">Mode hors connexion</translation>
-<translation id="1779392088388639487">Erreur d'importation de fichier PKCS #12</translation>
-<translation id="166278006618318542">Algorithme de clé publique de l'objet</translation>
-<translation id="5759272020525228995">Le site Web a rencontré une erreur lors de l'extraction de <ph name="URL"/>.
- Cela peut être dû à une opération de maintenance ou à une configuration incorrecte.</translation>
-<translation id="641480858134062906">Échec du chargement de la page <ph name="URL"/></translation>
-<translation id="3693415264595406141">Mot de passe :</translation>
-<translation id="74568296546932365">Conserver <ph name="PAGE_TITLE"/> en tant que moteur de recherche par défaut</translation>
-<translation id="8602184400052594090">Fichier manifeste absent ou illisible</translation>
-<translation id="2784949926578158345">La connexion a été réinitialisée.</translation>
-<translation id="6663792236418322902">Le mot de passe choisi vous sera demandé pour restaurer le fichier. Veillez à le conserver en lieu sûr.</translation>
-<translation id="4532822216683966758">La vérification de la provenance du certificat DNS est activée, ce qui peut entraîner l'envoi d'informations privées à Google.</translation>
-<translation id="6321196148033717308">À propos de la reconnaissance vocale</translation>
-<translation id="3412265149091626468">Aller à la sélection</translation>
-<translation id="8167737133281862792">Ajouter un certificat</translation>
-<translation id="2911372483530471524">Espaces de noms PID</translation>
-<translation id="6093374025603915876">Préférences de saisie automatique</translation>
-<translation id="8584134039559266300">Activer l'onglet 8</translation>
-<translation id="5189060859917252173">Le certificat &quot;<ph name="CERTIFICATE_NAME"/>&quot; représente une autorité de certification.</translation>
-<translation id="3785852283863272759">Envoyer par e-mail l'emplacement de la page</translation>
-<translation id="2255317897038918278">Enregistrement des informations de date Microsoft</translation>
-<translation id="3493881266323043047">Validité</translation>
-<translation id="5979421442488174909">&amp;Traduire en <ph name="LANGUAGE"/></translation>
-<translation id="7326526699920221209">Batterie : <ph name="PRECENTAGE"/> %</translation>
-<translation id="952992212772159698">Désactivé</translation>
-<translation id="8299269255470343364">Japonais</translation>
-<translation id="5187826826541650604"><ph name="KEY_NAME"/> (<ph name="DEVICE"/>)</translation>
-<translation id="6429639049555216915">L'application est actuellement inaccessible.</translation>
-<translation id="2144536955299248197">Lecteur du certificat : <ph name="CERTIFICATE_NAME"/></translation>
-<translation id="50030952220075532"><ph name="NUMBER_ONE"/> jour restant</translation>
-<translation id="2885378588091291677">Gestionnaire de tâches</translation>
-<translation id="5792852254658380406">Gérer les extensions...</translation>
-<translation id="2359808026110333948">Continuer</translation>
-<translation id="176759384517330673">Synchronisation avec <ph name="USER_EMAIL_ADDRESS"/> effectuée. Dernière synchronisation : <ph name="LAST_SYNC_TIME"/></translation>
-<translation id="1618661679583408047">Le certificat de sécurité du site n'est pas encore valide !</translation>
-<translation id="7039912931802252762">Ouverture de session par carte à puce Microsoft</translation>
-<translation id="6285074077487067719">Format</translation>
-<translation id="3065140616557457172">Tapez votre requête ou saisissez une URL pour commencer la navigation : c'est à vous de choisir.</translation>
-<translation id="5509693895992845810">Enregistrer &amp;sous...</translation>
-<translation id="5986279928654338866">Le serveur <ph name="DOMAIN"/> requiert un nom d'utilisateur et un mot de passe.</translation>
-<translation id="521467793286158632">Supprimer tous les mots de passe</translation>
-<translation id="2491120439723279231">Le certificat du serveur contient des erreurs.</translation>
-<translation id="4448844063988177157">Recherche de réseaux Wi-Fi...</translation>
-<translation id="5765780083710877561">Description :</translation>
-<translation id="338583716107319301">Séparateur</translation>
-<translation id="2079053412993822885">Si vous supprimez l'un de vos propres certificats, vous ne pouvez plus l'utiliser pour vous identifier.</translation>
-<translation id="7221869452894271364">Rafraîchir cette page</translation>
-<translation id="6791443592650989371">État d'activation :</translation>
-<translation id="4801257000660565496">Créer des raccourcis vers des applications</translation>
-<translation id="6503256918647795660">Clavier franco-suisse</translation>
-<translation id="6175314957787328458">GUID de domaine Microsoft</translation>
-<translation id="8179976553408161302">Entrer</translation>
-<translation id="8261506727792406068">Supprimer</translation>
-<translation id="4404805853119650018">Échec de l'enregistrement de cet ordinateur pour l'accès à distance.</translation>
-<translation id="345693547134384690">Ouvrir l'&amp;image dans un nouvel onglet</translation>
-<translation id="7422192691352527311">Préférences...</translation>
-<translation id="354211537509721945">L'administrateur a désactivé les mises à jour.</translation>
-<translation id="1375198122581997741">À propos de la version</translation>
-<translation id="7915471803647590281">Veuillez nous indiquer ce qu'il se passe avant d'envoyer votre rapport.</translation>
-<translation id="5725124651280963564">Connectez-vous à <ph name="TOKEN_NAME"/> afin de générer une clé pour <ph name="HOST_NAME"/>.</translation>
-<translation id="8418113698656761985">Clavier roumain</translation>
-<translation id="5976160379964388480">Autres</translation>
-<translation id="3665842570601375360">Sécurité :</translation>
-<translation id="1430915738399379752">Imprimer</translation>
-<translation id="7999087758969799248">Mode de saisie standard</translation>
-<translation id="2635276683026132559">Signature</translation>
-<translation id="4835836146030131423">Erreur lors de la connexion</translation>
-<translation id="7715454002193035316">Pour cette session uniquement</translation>
-<translation id="2475982808118771221">Une erreur s'est produite.</translation>
-<translation id="3324684065575061611">(Désactivé par une stratégie d'entreprise)</translation>
-<translation id="7385854874724088939">Erreur lors de la tentative d'impression. Vérifiez votre imprimante et réessayez.</translation>
-<translation id="770015031906360009">Grec</translation>
-<translation id="3834901049798243128">Ignorer les exceptions et bloquer l'enregistrement des cookies tiers</translation>
-<translation id="8116152017593700047">Cet outil vous permet de sélectionner une capture d'écran enregistrée. Aucune capture d'écran n'est disponible pour le moment. Appuyez simultanément sur Ctrl et sur la touche &quot;Mode Présentation&quot; pour enregistrer une capture d'écran. Vos trois dernières captures apparaissent ici.</translation>
-<translation id="3454157711543303649">Activation effectuée</translation>
-<translation id="884923133447025588">Aucun système de révocation trouvé</translation>
-<translation id="556042886152191864">Bouton</translation>
-<translation id="1352060938076340443">Interrompu</translation>
-<translation id="8571226144504132898">Dictionnaire de symboles</translation>
-<translation id="7229570126336867161">Technologie EvDo requise</translation>
-<translation id="7582844466922312471">Internet mobile</translation>
-<translation id="945522503751344254">Envoyer le commentaire</translation>
-<translation id="4539401194496451708">Associé au profil Chrome <ph name="USER_EMAIL_ADDRESS"/>. Dernière synchronisation : <ph name="LAST_SYNC_TIME"/></translation>
-<translation id="7369847606959702983">Carte de crédit (autre)</translation>
-<translation id="6867459744367338172">Langues et saisie</translation>
-<translation id="7671130400130574146">Utiliser la barre de titre et les bordures de fenêtre du système</translation>
-<translation id="9170848237812810038">Ann&amp;uler</translation>
-<translation id="284970761985428403"><ph name="ASCII_NAME"/> (<ph name="UNICODE_NAME"/>)</translation>
-<translation id="3903912596042358459">Le serveur a refusé d'exécuter la demande.</translation>
-<translation id="8135557862853121765"><ph name="NUM_KILOBYTES"/> Ko</translation>
-<translation id="4444364671565852729"><ph name="PRODUCT_NAME"/> a été mis à jour vers la version <ph name="VERSION"/>.</translation>
-<translation id="5819890516935349394">Navigateur de contenu</translation>
-<translation id="2731392572903530958">&amp;Rouvrir la fenêtre fermée</translation>
-<translation id="1254593899333212300">Se connecter directement à Internet</translation>
-<translation id="6107012941649240045">Émis pour</translation>
-<translation id="6483805311199035658">Ouverture de <ph name="FILE"/> en cours</translation>
-<translation id="3576278878016363465">Cibles disponibles pour l'image</translation>
-<translation id="895541991026785598">Signaler un problème</translation>
-<translation id="940425055435005472">Taille de police :</translation>
-<translation id="494286511941020793">Aide pour la configuration de proxy</translation>
-<translation id="2765217105034171413">Petite</translation>
-<translation id="1285266685456062655"><ph name="NUMBER_FEW"/> hours ago</translation>
-<translation id="9154176715500758432">Rester sur cette page</translation>
-<translation id="5875565123733157100">Type de bug :</translation>
-<translation id="6988771638657196063">Inclure cette URL :</translation>
-<translation id="5717920936024713315">Cookies et données de site...</translation>
-<translation id="3842552989725514455">Police Serif</translation>
-<translation id="1949795154112250744"><ph name="BEGIN_BOLD"/>Avertissement :<ph name="END_BOLD"/> <ph name="PRODUCT_NAME"/> ne peut pas empêcher les extensions d'enregistrer votre historique de navigation. Pour désactiver cette extension en mode navigation privée, désélectionnez-la.</translation>
-<translation id="4440967101351338638">ChromiumOs Image Burn</translation>
-<translation id="1813278315230285598">Services</translation>
-<translation id="6860097299815761905">Paramètres du proxy...</translation>
-<translation id="373572798843615002">1 onglet</translation>
-<translation id="4162393307849942816"><ph name="BEGIN_BOLD"/>Vous naviguez en tant qu'invité<ph name="END_BOLD"/>. Les pages que vous consultez dans cette fenêtre n'apparaîtront pas dans l'historique de votre navigateur ni dans votre historique des recherches. Les autres traces telles que les cookies seront supprimées de l'ordinateur à la fin de votre session. En revanche, les fichiers téléchargés et les favoris créés seront conservés.
- <ph name="LINE_BREAK"/>
- <ph name="BEGIN_LINK"/>En savoir plus<ph name="END_LINK"/> sur le mode invité</translation>
-<translation id="827924395145979961">Chargement des pages impossible</translation>
-<translation id="3092544800441494315">Inclure cette capture d'écran :</translation>
-<translation id="7714464543167945231">Certificat</translation>
-<translation id="5530864958284331435">$1 fichiers sélectionnés, $2</translation>
-<translation id="3616741288025931835">&amp;Effacer les données de navigation...</translation>
-<translation id="3313622045786997898">Valeur de signature du certificat</translation>
-<translation id="8535005006684281994">URL de renouvellement du certificat Netscape</translation>
-<translation id="2440604414813129000">Afficher la s&amp;ource</translation>
-<translation id="816095449251911490"><ph name="SPEED"/> - <ph name="RECEIVED_AMOUNT"/>, <ph name="TIME_REMAINING"/></translation>
-<translation id="8200772114523450471">Reprendre</translation>
-<translation id="6358975074282722691"><ph name="NUMBER_TWO"/> secs ago</translation>
-<translation id="5423849171846380976">Activé</translation>
-<translation id="6748105842970712833">Carte SIM désactivée</translation>
-<translation id="7323391064335160098">Compatibilité avec VPN</translation>
-<translation id="3929673387302322681">Développement - Instable</translation>
-<translation id="4251486191409116828">Échec de création du raccourci vers l'application</translation>
-<translation id="5190835502935405962">Barre de favoris</translation>
-<translation id="7828272290962178636">Le serveur est en mesure de répondre à la demande.</translation>
-<translation id="7823073559911777904">Modifier les paramètres du proxy...</translation>
-<translation id="5438430601586617544">(non empaquetée)</translation>
-<translation id="6460601847208524483">Rechercher le suivant</translation>
-<translation id="8433186206711564395">Paramètres réseau</translation>
-<translation id="4856478137399998590">Votre service Internet mobile est activé et prêt à l'emploi.</translation>
-<translation id="1676388805288306495">Modifier la police et la langue par défaut des pages Web</translation>
-<translation id="8969761905474557563">Composition graphique avec accélération matérielle</translation>
-<translation id="3937640725563832867">Autre nom de l'émetteur du certificat</translation>
-<translation id="4701488924964507374"><ph name="SENTENCE1"/> <ph name="SENTENCE2"/></translation>
-<translation id="1163931534039071049">&amp;Afficher le code source du cadre</translation>
-<translation id="8770196827482281187">Mode de saisie du persan (clavier ISIRI 2901)</translation>
-<translation id="6423239382391657905">OpenVPN</translation>
-<translation id="7564847347806291057">Arrêter le processus</translation>
-<translation id="1607220950420093847">Votre compte a peut-être été supprimé ou désactivé. Veuillez vous déconnecter.</translation>
-<translation id="5613695965848159202">Authentification anonyme :</translation>
-<translation id="2233320200890047564">Bases de données indexées</translation>
-<translation id="7063412606254013905">En savoir plus sur les escroqueries par phishing</translation>
-<translation id="307767688111441685">Page à l'apparence anormale</translation>
-<translation id="9076523132036239772">Adresse e-mail ou mot de passe incorrect. Essayez tout d'abord de vous connecter à un réseau.</translation>
-<translation id="6965978654500191972">Périphérique</translation>
-<translation id="1242521815104806351">Informations sur la connexion</translation>
-<translation id="5295309862264981122">Confirmer la navigation</translation>
-<translation id="1492817554256909552">Nom du point d'accès :</translation>
-<translation id="5546865291508181392">Rechercher</translation>
-<translation id="1999115740519098545">Au démarrage</translation>
-<translation id="2983818520079887040">Paramètres...</translation>
-<translation id="1465619815762735808">Lire en un clic</translation>
-<translation id="6941937518557314510">Connectez-vous à <ph name="TOKEN_NAME"/> pour vous authentifier auprès de <ph name="HOST_NAME"/> avec votre certificat.</translation>
-<translation id="2783600004153937501">Votre administrateur informatique a désactivé certaines options.</translation>
-<translation id="2099686503067610784">Supprimer le certificat de serveur &quot;<ph name="CERTIFICATE_NAME"/>&quot;?</translation>
-<translation id="9027603907212475920">Configurer la synchronisation...</translation>
-<translation id="6873213799448839504">Valider automatiquement une chaîne</translation>
-<translation id="7238585580608191973">Empreinte SHA-256</translation>
-<translation id="2501278716633472235">Retour</translation>
-<translation id="131461803491198646">Réseau domestique, sans itinérance</translation>
-<translation id="7377249249140280793"><ph name="RELATIVE_DATE"/> - <ph name="FULL_DATE"/></translation>
-<translation id="5679279978772703611">Gérer les mots de passe enregistrés...</translation>
-<translation id="4551440281920791563">Sélectionnez
- <ph name="BEGIN_BOLD"/>
- Menu clé à molette &gt; Options &gt; Options avancées &gt; Modifier les paramètres du proxy &gt; Paramètres réseau
- <ph name="END_BOLD"/>
- et désélectionnez l'option &quot;Utiliser un serveur proxy pour votre réseau local&quot;.</translation>
-<translation id="1285320974508926690">Ne jamais traduire ce site</translation>
-<translation id="8954894007019320973">(suite)</translation>
-<translation id="3748412725338508953">Trop de redirections</translation>
-<translation id="5833726373896279253">Ces paramètres ne peuvent être modifiés que par le propriétaire :</translation>
-<translation id="6858960932090176617">Active la protection XSS Auditor de WebKit (protection contre le Cross-site Scripting), une fonctionnalité qui vous protège de certaines attaques de sites malveillants et offre une sécurité accrue, mais qui n'est pas compatible avec tous les sites Web.</translation>
-<translation id="6005282720244019462">Clavier latino-américain</translation>
-<translation id="8831104962952173133">Phishing détecté !</translation>
-<translation id="5141720258550370428">Voulez-vous utiliser <ph name="HANDLER_TITLE"/> (<ph name="HANDLER_HOSTNAME"/>) pour gérer les liens <ph name="PROTOCOL"/>:// à partir de maintenant ?</translation>
-<translation id="6751344591405861699"><ph name="WINDOW_TITLE"/> (Navigation privée)</translation>
-<translation id="6681668084120808868">Prendre une photo</translation>
-<translation id="780301667611848630">Non merci</translation>
-<translation id="2812989263793994277">Ne pas afficher les images</translation>
-<translation id="7190251665563814471">Toujours autoriser ces plug-ins sur <ph name="HOST"/></translation>
-<translation id="6845383723252244143">Sélectionner un dossier</translation>
-<translation id="8925458182817574960">&amp;Paramètres</translation>
-<translation id="6361850914223837199">Informations sur l'erreur :</translation>
-<translation id="8948393169621400698">Toujours autoriser les plug-ins sur <ph name="HOST"/></translation>
-<translation id="3865082058368813534">Effacer les données de saisie automatique enregistrées</translation>
-<translation id="8288345061925649502">Changer de moteur de recherche</translation>
-<translation id="5436492226391861498">En attente du tunnel proxy...</translation>
-<translation id="3803991353670408298">Veuillez ajouter un autre mode de saisie avant de supprimer celui-ci.</translation>
-<translation id="1095623615273566396"><ph name="NUMBER_FEW"/> secondes</translation>
-<translation id="7006788746334555276">Paramètres de contenu</translation>
-<translation id="3369521687965833290">Impossible d'extraire les fichiers de l'extension. Pour effectuer cette opération en toute sécurité, vous devez disposer d'un chemin d'accès à votre répertoire de profils commençant par une lettre de lecteur et ne contenant ni jonction, ni point de montage, ni lien symbolique. Aucun chemin de ce type n'existe pour votre profil.</translation>
-<translation id="337920581046691015"><ph name="PRODUCT_NAME"/> va être installé.</translation>
-<translation id="6282194474023008486">Code postal</translation>
-<translation id="7733107687644253241">En bas à droite</translation>
-<translation id="5139955368427980650">&amp;Ouvrir</translation>
-<translation id="8136149669168180907"><ph name="DOWNLOADED_AMOUNT"/> téléchargé(s) sur <ph name="TOTAL_SIZE"/></translation>
-<translation id="7375268158414503514">Commentaires d'ordre général/Autres</translation>
-<translation id="4643612240819915418">Ou&amp;vrir la vidéo dans un nouvel onglet</translation>
-<translation id="7997479212858899587">Identité :</translation>
-<translation id="8300849813060516376">Échec de l'opération OTASP</translation>
-<translation id="2213819743710253654">Action sur la page</translation>
-<translation id="1317130519471511503">Modifier des éléments...</translation>
-<translation id="6391538222494443604">Le répertoire d'extensions est obligatoire.</translation>
-<translation id="8051695050440594747"><ph name="MEGABYTES"/> Mo disponibles</translation>
-<translation id="7088615885725309056">Ancien</translation>
-<translation id="461656879692943278"><ph name="HOST_NAME"/> fournit du contenu provenant de <ph name="ELEMENTS_HOST_NAME"/>, un site connu pour distribuer des logiciels malveillants. Votre ordinateur pourrait être infecté par un virus si vous consultez ce site.</translation>
-<translation id="1387022316521171484">Ces fonctionnalités expérimentales sont susceptibles d'être modifiées, interrompues ou supprimées à tout moment. Nous ne fournissons aucune garantie quant aux effets de leur activation. Votre navigateur pourrait bien prendre feu. Trêve de plaisanterie, il est possible que votre navigateur supprime toutes vos données ou que votre sécurité et votre vie privée soient compromises de manière inattendue. Nous vous prions d'agir avec précaution.</translation>
-<translation id="2143778271340628265">Configuration manuelle du proxy</translation>
-<translation id="5294529402252479912">Mettre à jour Adobe Reader maintenant</translation>
-<translation id="5263972071113911534"><ph name="NUMBER_MANY"/> days ago</translation>
-<translation id="7461850476009326849">Désactiver les plug-ins individuels...</translation>
-<translation id="4097411759948332224">Envoyer une capture d'écran de la page en cours</translation>
-<translation id="2231990265377706070">Point d'exclamation</translation>
-<translation id="7199540622786492483"><ph name="PRODUCT_NAME"/> n'est plus à jour, car il n'a pas été relancé depuis quelque temps. La mise à jour disponible sera installée dès que vous le relancerez.</translation>
-<translation id="8652722422052983852">Petit problème... Tentons de le résoudre.</translation>
-<translation id="5970231080121144965">Cette fonctionnalité permet d'établir des correspondances entre les sous-chaînes et plusieurs fragments d'URL figurant dans l'historique.</translation>
-<translation id="4665674675433053715">Page &quot;Nouvel onglet&quot; expérimentale</translation>
-<translation id="3726527440140411893">Les cookies suivants étaient autorisés lorsque vous avez consulté cette page :</translation>
-<translation id="3320859581025497771">votre opérateur</translation>
-<translation id="8828781037212165374">Activer ces fonctionnalités...</translation>
-<translation id="8562413501751825163">Quitter Firefox avant l'importation</translation>
-<translation id="3435541101098866721">Ajouter un nouveau téléphone</translation>
-<translation id="2448046586580826824">Proxy HTTP sécurisé</translation>
-<translation id="4032534284272647190">Accès à <ph name="URL"/> refusé.</translation>
-<translation id="4928569512886388887">Finalisation de la mise à jour du système...</translation>
-<translation id="8258002508340330928">Voulez-vous continuer ?</translation>
-<translation id="4309420042698375243"><ph name="NUM_KILOBYTES"/> Ko (<ph name="NUM_KILOBYTES_LIVE"/> Ko effectifs)</translation>
-<translation id="5554573843028719904">Autre réseau Wi-Fi...</translation>
-<translation id="5034259512732355072">Choisir un autre répertoire...</translation>
-<translation id="8885905466771744233">L'extension indiquée est déjà associée à une clé privée. Utilisez cette clé ou supprimez-la.</translation>
-<translation id="7831504847856284956">Ajouter une adresse</translation>
-<translation id="7505152414826719222">Stockage local</translation>
-<translation id="2541423446708352368">Afficher tous les téléchargements</translation>
-<translation id="4381021079159453506">Navigateur de contenu</translation>
-<translation id="8109246889182548008">Magasin de certificats</translation>
-<translation id="5030338702439866405">Émis par</translation>
-<translation id="5280833172404792470">Quitter le mode plein écran (<ph name="ACCELERATOR"/>)</translation>
-<translation id="2728127805433021124">Le certificat du serveur a été signé avec un algorithme de signature faible.</translation>
-<translation id="2137808486242513288">Ajouter un utilisateur</translation>
-<translation id="6193618946302416945">Me proposer de traduire les pages qui sont écrites dans une langue que je ne sais pas lire</translation>
-<translation id="129553762522093515">Récemment fermés</translation>
-<translation id="4287167099933143704">Saisir la clé de déverrouillage du code PIN</translation>
-<translation id="8355915647418390920"><ph name="NUMBER_FEW"/> jours</translation>
-<translation id="3129140854689651517">Rechercher du texte</translation>
-<translation id="7221585318879598658">Sans-Serif</translation>
-<translation id="5558129378926964177">Zoom &amp;avant</translation>
-<translation id="6451458296329894277">Confirmer le nouvel envoi du formulaire</translation>
-<translation id="5116333507878097773"><ph name="NUMBER_ONE"/> heure</translation>
-<translation id="8028152732786498049">Cet élément doit être installé depuis <ph name="CHROME_WEB_STORE"/>.</translation>
-<translation id="9199258761842902152">Mise en veille ou reprise</translation>
-<translation id="1851266746056575977">Mettre à jour maintenant</translation>
-<translation id="7017219178341817193">Ajouter une page</translation>
-<translation id="1038168778161626396">Chiffrer seulement</translation>
-<translation id="2756651186786928409">Ne jamais intervertir les touches de modification</translation>
-<translation id="1217515703261622005">Conversion des numéros spéciaux</translation>
-<translation id="7179921470347911571">Relancer maintenant</translation>
-<translation id="3715099868207290855">Synchronisation avec <ph name="USER_EMAIL_ADDRESS"/> effectuée</translation>
-<translation id="2679312662830811292">il y a <ph name="NUMBER_ONE"/> minute</translation>
-<translation id="9065203028668620118">Édition</translation>
-<translation id="4718464510840275738">Préférences synchronisées</translation>
-<translation id="8788572795284305350"><ph name="NUMBER_ZERO"/> hours ago</translation>
-<translation id="1177863135347784049">Personnalisé</translation>
-<translation id="8236028464988198644">Rechercher à partir de la barre d'adresse</translation>
-<translation id="4881695831933465202">Ouvrir</translation>
-<translation id="5988520580879236902">Inspecter les vues actives :</translation>
-<translation id="3593965109698325041">Contraintes de nom du certificat</translation>
-<translation id="4358697938732213860">Ajouter une adresse</translation>
-<translation id="8396532978067103567">Mot de passe incorrect.</translation>
-<translation id="5981759340456370804">Statistiques avancées</translation>
-<translation id="8160015581537295331">Clavier espagnol</translation>
-<translation id="3505920073976671674">Sélectionnez votre réseau</translation>
-<translation id="6644971472240498405"><ph name="NUMBER_ONE"/> jour</translation>
-<translation id="1782924894173027610">Le serveur de synchronisation est occupé. Veuillez réessayer ultérieurement.</translation>
-<translation id="6512448926095770873">Quitter cette page</translation>
-<translation id="5457599981699367932">Naviguer en tant qu'invité</translation>
-<translation id="3169472444629675720">Discover</translation>
-<translation id="6294193300318171613">&amp;Toujours afficher la barre de favoris</translation>
-<translation id="4088820693488683766">Options de recherche</translation>
-<translation id="3414952576877147120">Taille :</translation>
-<translation id="9098468523912235228">il y a <ph name="NUMBER_DEFAULT"/> secondes</translation>
-<translation id="7009102566764819240">La liste suivante fait état des éléments dangereux détectés sur la page. Cliquez sur le lien &quot;Diagnostic&quot; pour obtenir plus d'informations sur une ressource particulière. Si une ressource a été signalée comme site de phishing alors que vous êtes certain de sa fiabilité, cliquez sur le lien &quot;Signaler une erreur&quot;.</translation>
-<translation id="4923417429809017348">Cette page rédigée dans une langue non identifiée a été traduite en <ph name="LANGUAGE_LANGUAGE"/>.</translation>
-<translation id="3631337165634322335">Les exceptions ci-dessous s'appliquent uniquement à la session de navigation privée actuelle.</translation>
-<translation id="676327646545845024">Ne plus afficher la boîte de dialogue pour les liens de ce type</translation>
-<translation id="494645311413743213"><ph name="NUMBER_TWO"/> secondes restantes</translation>
-<translation id="1485146213770915382">Insérez <ph name="SEARCH_TERMS_LITERAL"/> dans l'URL où les termes de recherche devraient apparaître.</translation>
-<translation id="4839303808932127586">En&amp;registrer la vidéo sous...</translation>
-<translation id="5626134646977739690">Nom :</translation>
-<translation id="5854409662653665676">Si vous rencontrez des problèmes fréquents avec ce module, vous pouvez tenter d'y remédier en suivant la procédure ci-après :</translation>
-<translation id="3681007416295224113">Informations relatives au certificat</translation>
-<translation id="3046084099139788433">Activer l'onglet 7</translation>
-<translation id="721197778055552897"><ph name="BEGIN_LINK"/>En savoir plus<ph name="END_LINK"/> sur ce problème.</translation>
-<translation id="1699395855685456105">Version du matériel :</translation>
-<translation id="212464871579942993">Le site Web à l'adresse <ph name="HOST_NAME"/> contient des éléments provenant de sites qui semblent héberger des logiciels malveillants. Ces derniers peuvent nuire à votre ordinateur ou agir à votre insu. Le simple fait de visiter un site hébergeant ce type de logiciels peut infecter votre ordinateur. Ce site héberge également des informations provenant de sites signalés comme étant des sites de phishing. Ces derniers incitent les internautes à divulguer des informations personnelles en se faisant passer pour des institutions de confiance, telles que des banques.</translation>
-<translation id="8156020606310233796">Afficher la liste</translation>
-<translation id="957120528631539888">Désactivez l'affichage des messages de confirmation et le blocage de l'envoi des formulaires.</translation>
-<translation id="146000042969587795">Ce cadre a été bloqué, car il contient des éléments non sécurisés.</translation>
-<translation id="8112223930265703044">Tout</translation>
-<translation id="3968739731834770921">Kana</translation>
-<translation id="3729920814805072072">Gérer les mots de passe enregistrés...</translation>
-<translation id="7387829944233909572">Boîte de dialogue &quot;Effacer les données de navigation&quot;</translation>
-<translation id="8023801379949507775">Mettre à jour les extensions maintenant</translation>
-<translation id="6549677549082720666">Nouvelle application en arrière-plan installée</translation>
-<translation id="1983108933174595844">Envoyer une capture d'écran de la page actuelle</translation>
-<translation id="3298789223962368867">L'URL indiquée est incorrecte.</translation>
-<translation id="2202898655984161076">Un problème est survenu lors de l'affichage de la liste des imprimantes. Certaines de vos imprimantes ne sont peut-être pas correctement enregistrées dans <ph name="CLOUD_PRINT_NAME"/>.</translation>
-<translation id="6154697846084421647">Actuellement connecté</translation>
-<translation id="8241707690549784388">La page que vous recherchez a utilisé des informations que vous avez envoyées. Si vous revenez sur cette page, chaque action précédemment effectuée sera répétée. Souhaitez-vous continuer ?</translation>
-<translation id="5359419173856026110">Cette fonctionnalité indique la vitesse d'affichage réelle d'une page, en images par seconde, lorsque l'accélération matérielle est active.</translation>
-<translation id="4104163789986725820">E&amp;xporter...</translation>
-<translation id="2113479184312716848">&amp;Ouvrir un fichier...</translation>
-<translation id="8412709057120877195">Configurer le contrôle d'accès pour vos périphériques</translation>
-<translation id="486595306984036763">Ouvrir un rapport de phishing</translation>
-<translation id="3140353188828248647">Activer la barre d'adresse</translation>
-<translation id="4860787810836767172"><ph name="NUMBER_FEW"/> secs ago</translation>
-<translation id="5565871407246142825">Cartes de paiement</translation>
-<translation id="2587203970400270934">Code opérateur :</translation>
-<translation id="3355936511340229503">Erreur de connexion</translation>
-<translation id="1824910108648426227">Vous avez la possibilité de désactiver ces services.</translation>
-<translation id="3092040396860056776">Essayer d'afficher la page malgré tout</translation>
-<translation id="4350711002179453268">Impossible d'établir une connexion sécurisée avec le serveur. Le serveur a peut-être rencontré un problème ou exige un certificat d'authentification du client dont vous ne disposez pas.</translation>
-<translation id="91731790394942114">Ajouter un nouveau nom</translation>
-<translation id="5963026469094486319">Obtenir d'autres thèmes</translation>
-<translation id="2441719842399509963">Rétablir les valeurs par défaut</translation>
-<translation id="1893137424981664888">Aucun Plug-in installé.</translation>
-<translation id="3718288130002896473">Action</translation>
-<translation id="2168725742002792683">Extensions de fichier</translation>
-<translation id="1753905327828125965">Les plus visités</translation>
-<translation id="8116972784401310538">&amp;Gestionnaire de favoris</translation>
-<translation id="1849632043866553433">Caches des applications</translation>
-<translation id="3591607774768458617">Cette langue est actuellement utilisée par <ph name="PRODUCT_NAME"/>.</translation>
-<translation id="621638399744152264"><ph name="VALUE"/> %</translation>
-<translation id="4927301649992043040">Empaqueter l'extension</translation>
-<translation id="8679658258416378906">Activer l'onglet 5</translation>
-<translation id="4763816722366148126">Sélectionner le mode de saisie précédent</translation>
-<translation id="6458308652667395253">Configurer le blocage de JavaScript...</translation>
-<translation id="8435334418765210033">Réseaux mémorisés</translation>
-<translation id="6516193643535292276">Impossible de se connecter à Internet.</translation>
-<translation id="5125751979347152379">URL incorrecte</translation>
-<translation id="2791364193466153585">Informations sur la sécurité</translation>
-<translation id="4673916386520338632">Impossible d'installer l'application, car elle est en conflit avec &quot;<ph name="APP_NAME"/>&quot;, qui est déjà installé.</translation>
-<translation id="2024918351532495204">Votre périphérique n'est pas connecté.</translation>
-<translation id="6040143037577758943">Fermer</translation>
-<translation id="5787146423283493983">Accord de la clé</translation>
-<translation id="1101671447232096497"><ph name="NUMBER_MANY"/> mins ago</translation>
-<translation id="4265682251887479829">Vous ne trouvez pas ce que vous recherchez ?</translation>
-<translation id="1804251416207250805">Désactivez l'envoi des pings de contrôle des liens hypertexte.</translation>
-<translation id="5116628073786783676">En&amp;registrer le fichier audio sous...</translation>
-<translation id="2557899542277210112">Accédez rapidement à vos favoris en les ajoutant à la barre de favoris.</translation>
-<translation id="2749881179542288782">Vérifier la grammaire et l'orthographe</translation>
-<translation id="5105855035535475848">Épingler les onglets</translation>
-<translation id="6892450194319317066">Sélectionner par type d'application</translation>
-<translation id="3549436232897695316">assembler</translation>
-<translation id="5414121716219514204"><ph name="ENGINE_HOST_NAME"/> souhaite devenir votre moteur de recherche.</translation>
-<translation id="2752805177271551234">Utiliser l'historique d'entrée</translation>
-<translation id="7268365133021434339">Fermer les onglets</translation>
-<translation id="4910619056351738551">Voici quelques suggestions :</translation>
-<translation id="9131598836763251128">Sélectionnez un ou plusieurs fichiers</translation>
-<translation id="5489059749897101717">Afficher le panneau de la &amp;vérification orthographique</translation>
-<translation id="3423858849633684918">Veuillez relancer <ph name="PRODUCT_NAME"/>.</translation>
-<translation id="1232569758102978740">Sans titre</translation>
-<translation id="1903219944620007795">Pour saisir du texte, sélectionnez une langue et consultez la liste des modes de saisie disponibles.</translation>
-<translation id="4362187533051781987">Ville</translation>
-<translation id="9149866541089851383">Modifier...</translation>
-<translation id="7608619752233383356">Réinitialiser la synchronisation</translation>
-<translation id="1065245965611933814">Inclure une capture d'écran enregistrée :</translation>
-<translation id="7876243839304621966">Tout supprimer</translation>
-<translation id="5663459693447872156">Passer automatiquement en demi-chasse</translation>
-<translation id="4593021220803146968">&amp;Accéder à <ph name="URL"/></translation>
-<translation id="1128987120443782698">La capacité de ce périphérique de stockage est de <ph name="DEVICE_CAPACITY"/>. Veuillez insérer une carte SD ou une clé USB d'au moins 4 Go.</translation>
-<translation id="869257642790614972">Rouvrir le dernier onglet fermé</translation>
-<translation id="3978267865113951599">(blocage)</translation>
-<translation id="8412145213513410671">Erreurs (<ph name="CRASH_COUNT"/>)</translation>
-<translation id="560602183358579978">Traitement de la sélection...</translation>
-<translation id="7649070708921625228">Aide</translation>
-<translation id="5994107996638824097">Désolé ! La visionneuse de documents PDF intégrée à Google Chrome, nécessaire à l'affichage de l'aperçu avant impression, n'est pas incluse dans Chromium.</translation>
-<translation id="976526967778596630">Impossible d'ouvrir <ph name="HOST_NAME"/>, car vous êtes déconnecté du réseau. Cette page s'affichera dès que la connexion réseau sera rétablie. &lt;br&gt;</translation>
-<translation id="1734072960870006811">Télécopie</translation>
-<translation id="3095995014811312755">version</translation>
-<translation id="7052500709156631672">La passerelle ou le serveur proxy a reçu une réponse incorrecte d'un serveur en amont.</translation>
-<translation id="281133045296806353">Nouvelle fenêtre ouverte dans la session du navigateur</translation>
-<translation id="7144878232160441200">Réessayer</translation>
-<translation id="2860002559146138960"><ph name="PRODUCT_NAME"/> peut maintenant synchroniser vos mots de passe. Vos données seront chiffrées avec le mot de passe de votre compte Google ou le mot de passe multiterme de votre choix.</translation>
-<translation id="3951872452847539732">Les paramètres réseau de votre proxy sont gérés par une extension.</translation>
-<translation id="6442697326824312960">Retirer l'onglet</translation>
-<translation id="6382612843547381371">Valable du <ph name="START_DATE_TIME"/> au <ph name="END_DATE_TIME"/></translation>
-<translation id="6869402422344886127">Case cochée</translation>
-<translation id="5637380810526272785">Mode de saisie</translation>
-<translation id="404928562651467259">AVERTISSEMENT</translation>
-<translation id="7172053773111046550">Clavier estonien</translation>
-<translation id="497490572025913070">Ajout de bordures aux couches de rendu composées</translation>
-<translation id="9002707937526687073">Imp&amp;rimer...</translation>
-<translation id="5953934840931207585">Paramètres de saisie automatique <ph name="PRODUCT_NAME_SHORT"/></translation>
-<translation id="5556459405103347317">Rafraîchir</translation>
-<translation id="8000020256436988724">Barre d'outils</translation>
-<translation id="8326395326942127023">Nom de la base de données :</translation>
-<translation id="7507930499305566459">Certificat du répondeur d'état</translation>
-<translation id="2689915906323125315">Utiliser le mot de passe de mon compte Google</translation>
-<translation id="6440205424473899061">Vos favoris sont maintenant synchronisés avec Google Documents !
-Pour fusionner et synchroniser vos favoris dans <ph name="PRODUCT_NAME"/> sur un autre ordinateur, procédez de la même manière que précédemment sur l'ordinateur voulu.</translation>
-<translation id="7727721885715384408">Renommer...</translation>
-<translation id="2604243255129603442"><ph name="NAME_OF_EXTENSION"/> a été désactivé. Si vous arrêtez la synchronisation des favoris, vous pouvez la réactiver sur la page des extensions, via le menu Outils.</translation>
-<translation id="2024621544377454980">Affichage des pages impossible</translation>
-<translation id="7136694880210472378">Utiliser par défaut</translation>
-<translation id="7681202901521675750">La carte SIM est verrouillée. Veuillez saisir votre code PIN. Nombre de tentatives restantes : <ph name="TRIES_COUNT"/></translation>
-<translation id="7420789336015002755">Le nom du dossier contient un caractère incorrect : $1</translation>
-<translation id="1731346223650886555">Point-virgule</translation>
-<translation id="158849752021629804">Réseau domestique requis</translation>
-<translation id="7339763383339757376">PKCS #7, certificat unique</translation>
-<translation id="7587108133605326224">Langues baltes</translation>
-<translation id="3991936620356087075">Vous avez saisi un trop grand nombre de clés de verrouillage du code PIN incorrectes. Votre carte SIM est définitivement désactivée.</translation>
-<translation id="936801553271523408">Données de diagnostic système</translation>
-<translation id="6389701355360299052">Page Web, contenu HTML uniquement</translation>
-<translation id="8067791725177197206">Continuer »</translation>
-<translation id="9009144784540995197">Gérez vos imprimantes.</translation>
-<translation id="1055006259534905434">(Choisir un problème dans la liste ci-dessous)</translation>
-<translation id="3021678814754966447">&amp;Afficher le code source du cadre</translation>
-<translation id="8601206103050338563">Authentification du client WWW TLS</translation>
-<translation id="1692799361700686467">Les cookies de plusieurs sites sont autorisés.</translation>
-<translation id="7074488040076962230">Impossible d'afficher la page de la barre latérale &quot;<ph name="SIDEBAR_PAGE"/>&quot;.</translation>
-<translation id="529232389703829405">Vous avez acheté <ph name="DATA_AMOUNT"/> de données le <ph name="DATE"/>.</translation>
-<translation id="5271549068863921519">Enregistrer le mot de passe</translation>
-<translation id="4345587454538109430">Configurer...</translation>
-<translation id="8148264977957212129">Mode de saisie du pinyin</translation>
-<translation id="5787378733537687553">Intervertir les touches Ctrl et Alt de gauche</translation>
-<translation id="7772032839648071052">Confirmer le mot de passe multiterme</translation>
-<translation id="6857811139397017780">Activer <ph name="NETWORKSERVICE"/></translation>
-<translation id="3251855518428926750">Ajouter...</translation>
-<translation id="4120075327926916474">Voulez-vous que Google Chrome enregistre ces informations de carte de paiement pour le remplissage de formulaires Web ?</translation>
-<translation id="6929555043669117778">Continuer à bloquer les fenêtres pop-up</translation>
-<translation id="5864471791310927901">Échec de la vérification DHCP</translation>
-<translation id="3508920295779105875">Choisir un autre dossier...</translation>
-<translation id="2503458975635466059">Le profil semble être utilisé par le processus <ph name="PROCESS_ID"/> sur l'hôte <ph name="HOST_NAME"/>. Si vous êtes certain qu'aucun autre processus n'utilise ce profil, supprimez le fichier <ph name="LOCK_FILE"/> et relancez <ph name="PRODUCT_NAME"/>.</translation>
-<translation id="2987775926667433828">Chinois traditionnel</translation>
-<translation id="6684737638449364721">Effacer les données de navigation...</translation>
-<translation id="3954582159466790312">Ré&amp;activer le son</translation>
-<translation id="1110772031432362678">Aucun réseau trouvé.</translation>
-<translation id="3936390757709632190">&amp;Ouvrir le fichier audio dans un nouvel onglet</translation>
-<translation id="7297622089831776169">&amp;Méthodes d'entrée</translation>
-<translation id="5731698828607291678">Onglets ou fenêtres</translation>
-<translation id="1152775729948968688">Toutefois, cette page inclut d'autres ressources qui ne sont pas sécurisées. Ces ressources peuvent être consultées par des tiers pendant leur transfert, et modifiées par un pirate informatique dans le but de changer le comportement de cette page.</translation>
-<translation id="604124094241169006">Automatique</translation>
-<translation id="862542460444371744">&amp;Extensions</translation>
-<translation id="8045462269890919536">Roumain</translation>
-<translation id="6320286250305104236">Paramètres du réseau...</translation>
-<translation id="2927657246008729253">Changer...</translation>
-<translation id="7978412674231730200">Clé privée</translation>
-<translation id="464745974361668466">Format :</translation>
-<translation id="5308380583665731573">Se connecter</translation>
-<translation id="9111395131601239814"><ph name="NETWORKDEVICE"/> : <ph name="STATUS"/></translation>
-<translation id="9049981332609050619">Vous avez tenté de contacter <ph name="DOMAIN"/>, mais le certificat présenté par le serveur est incorrect.</translation>
-<translation id="4414232939543644979">Nouvelle fenêtre de nav&amp;igation privée</translation>
-<translation id="1693754753824026215">La page à l'adresse <ph name="SITE"/> indique :</translation>
-<translation id="7148804936871729015">Le serveur associé à <ph name="URL"/> n'a pas répondu à temps. Cela peut être dû à une surcharge.</translation>
-<translation id="5950967683057767490">L2TP/IPSec + Clé pré-partagée</translation>
-<translation id="8108473539339615591">XSS Auditor</translation>
-<translation id="1902576642799138955">Durée de validité</translation>
-<translation id="4910021444507283344">WebGL</translation>
-<translation id="6692173217867674490">Mot de passe multiterme erroné</translation>
-<translation id="5550431144454300634">Corriger automatiquement la saisie</translation>
-<translation id="3308006649705061278">Unité d'organisation</translation>
-<translation id="8912362522468806198">Compte Google</translation>
-<translation id="4443536555189480885">&amp;Aide</translation>
-<translation id="340485819826776184">Utiliser un service de prédiction afin de compléter les recherches et les URL saisies dans la barre d'adresse</translation>
-<translation id="4074900173531346617">Certificat du signataire de courrier électronique</translation>
-<translation id="6165508094623778733">En savoir plus</translation>
-<translation id="9052208328806230490">Vous avez enregistré vos imprimantes sur <ph name="CLOUD_PRINT_NAME"/> via le compte <ph name="EMAIL"/>.</translation>
-<translation id="822618367988303761">il y a <ph name="NUMBER_TWO"/> jours</translation>
-<translation id="7928333295097642153"><ph name="HOUR"/>:<ph name="MINUTE"/> restantes</translation>
-<translation id="7568593326407688803">Cette page est en<ph name="ORIGINAL_LANGUAGE"/>Voulez-vous la traduire ?</translation>
-<translation id="563969276220951735">Saisie automatique des formulaires</translation>
-<translation id="6870130893560916279">Clavier ukrainien</translation>
-<translation id="8629974950076222828">Ouvrir tous les favoris dans une fenêtre de navigation privée</translation>
-<translation id="3126026824346185272">Ctrl</translation>
-<translation id="4745438305783437565"><ph name="NUMBER_FEW"/> minutes</translation>
-<translation id="2649911884196340328">Le certificat de sécurité du serveur contient des erreurs !</translation>
-<translation id="6666647326143344290">avec votre compte Google</translation>
-<translation id="3828029223314399057">Rechercher dans les favoris</translation>
-<translation id="4885705234041587624">MSCHAPv2</translation>
-<translation id="5614190747811328134">Avertissement utilisateur</translation>
-<translation id="8906421963862390172">&amp;Options du vérificateur d'orthographe</translation>
-<translation id="9046895021617826162">Échec de la connexion</translation>
-<translation id="1492188167929010410">Identifiant de l'erreur <ph name="CRASH_ID"/></translation>
-<translation id="1963692530539281474"><ph name="NUMBER_DEFAULT"/> jours restants</translation>
-<translation id="4470270245053809099">Émis par : <ph name="NAME"/></translation>
-<translation id="5365539031341696497">Mode de saisie du thaï (clavier Kesmanee)</translation>
-<translation id="2403091441537561402">Passerelle :</translation>
-<translation id="6337234675334993532">Chiffrement</translation>
-<translation id="668171684555832681">Autre...</translation>
-<translation id="1932098463447129402">Pas avant le</translation>
-<translation id="7845920762538502375"><ph name="PRODUCT_NAME"/> n'a pas pu synchroniser vos données, car la connexion avec le serveur de synchronisation n'a pas pu être établie. Nouvel essai...</translation>
-<translation id="2192664328428693215">Me demander lorsqu'un site souhaite afficher des notifications sur le Bureau (recommandé)</translation>
-<translation id="6708242697268981054">Source :</translation>
-<translation id="4786993863723020412">Erreur de lecture du cache</translation>
-<translation id="6630452975878488444">Raccourci de sélection</translation>
-<translation id="8709969075297564489">Vérifier la révocation du certificat serveur</translation>
-<translation id="8698171900303917290">Vous rencontrez des problèmes lors de l'installation ?</translation>
-<translation id="830868413617744215">Bêta</translation>
-<translation id="5925147183566400388">Pointeur de la déclaration CPS (Certification Practice Statement)</translation>
-<translation id="1497270430858433901">Le <ph name="DATE"/>, vous avez reçu <ph name="DATA_AMOUNT"/> à utiliser librement.</translation>
-<translation id="8150167929304790980">Nom complet</translation>
-<translation id="636850387210749493">Inscription d'entreprise</translation>
-<translation id="1947424002851288782">Clavier allemand</translation>
-<translation id="932508678520956232">Impossible de lancer l'impression.</translation>
-<translation id="4861833787540810454">&amp;Lire</translation>
-<translation id="2552545117464357659">Récent</translation>
-<translation id="7269802741830436641">Cette page Web présente une boucle de redirection.</translation>
-<translation id="4180788401304023883">Supprimer le certificat &quot;<ph name="CERTIFICATE_NAME"/>&quot; émis par l'autorité de certification ?</translation>
-<translation id="5869522115854928033">Mots de passe enregistrés</translation>
-<translation id="2089090684895656482">Moins</translation>
-<translation id="1709220265083931213">Options avancées</translation>
-<translation id="5748266869826978907">Vérifiez vos paramètres DNS. Contactez votre administrateur réseau si vous n'êtes pas sûr de vous.</translation>
-<translation id="4771973620359291008">Une erreur inconnue s'est produite.</translation>
-<translation id="5509914365760201064">Émetteur : <ph name="CERTIFICATE_AUTHORITY"/></translation>
-<translation id="7073385929680664879">Passer d'un mode de saisie à l'autre</translation>
-<translation id="6898699227549475383">Organisation (O)</translation>
-<translation id="4333854382783149454">PKCS #1 SHA-1 avec chiffrement RSA</translation>
-<translation id="762904068808419792">Entrez la requête de recherche ici.</translation>
-<translation id="8615618338313291042">Application en mode navigation privée : <ph name="APP_NAME"/></translation>
-<translation id="978146274692397928">La largeur de ponctuation initiale est Complète</translation>
-<translation id="8959027566438633317">Installer <ph name="EXTENSION_NAME"/> ?</translation>
-<translation id="8155798677707647270">Installation d'une nouvelle version...</translation>
-<translation id="6886871292305414135">Ouvrir le lien dans un nouvel ongle&amp;t</translation>
-<translation id="1639192739400715787">Pour accéder aux paramètres de sécurité, saisissez le code PIN de la carte SIM.</translation>
-<translation id="7961015016161918242">Jamais</translation>
-<translation id="3950924596163729246">Impossible d'accéder au réseau.</translation>
-<translation id="2835170189407361413">Effacer le formulaire</translation>
-<translation id="4631110328717267096">Échec de la mise à jour du système</translation>
-<translation id="3695919544155087829">Saisissez le mot de passe utilisé pour chiffrer ce fichier de certificat.</translation>
-<translation id="2230051135190148440">CHAP</translation>
-<translation id="6308937455967653460">Enregistrer le lie&amp;n sous...</translation>
-<translation id="5421136146218899937">Effacer les données de navigation...</translation>
-<translation id="5783059781478674569">Options de reconnaissance vocale</translation>
-<translation id="5441100684135434593">Réseau câblé</translation>
-<translation id="3285322247471302225">Nouvel ongle&amp;t</translation>
-<translation id="3943582379552582368">R&amp;etour</translation>
-<translation id="7607002721634913082">Téléchargement suspendu</translation>
-<translation id="480990236307250886">Ouvrir la page d'accueil</translation>
-<translation id="8286036467436129157">Connexion</translation>
-<translation id="5999940714422617743">L'installation de <ph name="EXTENSION_NAME"/> est terminée.</translation>
-<translation id="1122198203221319518">&amp;Outils</translation>
-<translation id="5757539081890243754">Page d'accueil</translation>
-<translation id="2760009672169282879">Clavier phonétique bulgare</translation>
-<translation id="6608140561353073361">Cookies et données de site...</translation>
-<translation id="8007030362289124303">Batterie faible</translation>
-<translation id="4513946894732546136">Commentaires</translation>
-<translation id="1135328998467923690">Package incorrect : &quot;<ph name="ERROR_CODE"/>&quot;.</translation>
-<translation id="5906719743126878045"><ph name="NUMBER_TWO"/> heures restantes</translation>
-<translation id="1753682364559456262">Configurer les paramètres de blocage des images...</translation>
-<translation id="6550675742724504774">Options</translation>
-<translation id="8959208747503200525"><ph name="NUMBER_TWO"/> hours ago</translation>
-<translation id="431076611119798497">&amp;Détails</translation>
-<translation id="737801893573836157">Masquer la barre de titre du système et utiliser les bordures</translation>
-<translation id="5352235189388345738">Elle peut accéder aux éléments suivants :</translation>
-<translation id="5040262127954254034">Confidentialité</translation>
-<translation id="7666868073052500132">Objets : <ph name="USAGES"/></translation>
-<translation id="6985345720668445131">Paramètres d'entrée du japonais</translation>
-<translation id="3258281577757096226">Sebeol-sik Final</translation>
-<translation id="2359174522669474766">Un fichier sélectionné, $1</translation>
-<translation id="6906268095242253962">Veuillez vous connecter à Internet pour continuer.</translation>
-<translation id="1908748899139377733">Afficher les &amp;infos sur le cadre</translation>
-<translation id="803771048473350947">Fichier</translation>
-<translation id="6206311232642889873">Cop&amp;ier l'image</translation>
-<translation id="5158983316805876233">Utiliser le même proxy pour tous les protocoles</translation>
-<translation id="7108338896283013870">Masquer</translation>
-<translation id="3366404380928138336">Requête de protocole externe</translation>
-<translation id="5300589172476337783">Afficher</translation>
-<translation id="3160041952246459240">Certains de vos certificats enregistrés identifient ces serveurs :</translation>
-<translation id="566920818739465183">Vous avez visité ce site pour la première fois le <ph name="VISIT_DATE"/>.</translation>
-<translation id="2961695502793809356">Cliquer pour avancer, maintenir pour voir l'historique</translation>
-<translation id="4092878864607680421">La dernière version de l'application &quot;<ph name="APP_NAME"/>&quot; requiert d'autres autorisations. Elle a donc été désactivée.</translation>
-<translation id="8421864404045570940"><ph name="NUMBER_DEFAULT"/> secondes</translation>
-<translation id="5828228029189342317">Vous avez choisi d'ouvrir automatiquement certains types de fichiers après leur téléchargement.</translation>
-<translation id="1416836038590872660">EAP-MD5</translation>
-<translation id="176587472219019965">&amp;Nouvelle fenêtre</translation>
-<translation id="2788135150614412178">+</translation>
-<translation id="4055738107007928968">Vous avez essayé d'accéder au site <ph name="DOMAIN"/>, mais le serveur a présenté un certificat signé avec un algorithme de signature faible. Il se peut que les informations d'identification fournies par le serveur aient été falsifiées. Le serveur n'est peut-être pas celui auquel vous souhaitez accéder (il peut s'agir d'une tentative de piratage). Nous nous déconseillons vivement de continuer.</translation>
-<translation id="5308689395849655368">L'envoi de rapports d'erreur est désactivé.</translation>
-<translation id="8372369524088641025">Clé WEP incorrecte</translation>
-<translation id="8689341121182997459">Date d'expiration :</translation>
-<translation id="899403249577094719">URL de base du certificat Netscape</translation>
-<translation id="2737363922397526254">Réduire...</translation>
-<translation id="4880827082731008257">Rechercher dans l'historique</translation>
-<translation id="8661290697478713397">Ouvrir le lien dans la fenêtre de navi&amp;gation privée</translation>
-<translation id="4197700912384709145"><ph name="NUMBER_ZERO"/> secondes</translation>
-<translation id="7454780465968211330">Historique avancé pour le champ polyvalent</translation>
-<translation id="2158448795143567596">Active l'utilisation de graphismes 3D dans les éléments canvas via l'API WebGL.</translation>
-<translation id="1702534956030472451">Occident</translation>
-<translation id="6636709850131805001">État non reconnu</translation>
-<translation id="6095984072944024315">−</translation>
-<translation id="9141716082071217089">Impossible de vérifier si le certificat du serveur a été révoqué.</translation>
-<translation id="4304224509867189079">Se connecter</translation>
-<translation id="5332624210073556029">Fuseau horaire :</translation>
-<translation id="4799797264838369263">Cette option est soumise à une stratégie d'entreprise. Contactez votre administrateur pour plus d'informations.</translation>
-<translation id="4492190037599258964">Résultats de recherche pour &quot;<ph name="SEARCH_STRING"/>&quot;</translation>
-<translation id="3573179567135747900">Revenir à &quot;<ph name="FROM_LOCALE"/>&quot; (redémarrage requis)</translation>
-<translation id="2238123906478057869"><ph name="PRODUCT_NAME"/> va exécuter les tâches suivantes :</translation>
-<translation id="4042471398575101546">Ajouter la page</translation>
-<translation id="8848709220963126773">Changement de mode via la touche Maj</translation>
-<translation id="4871865824885782245">Options de date et d'heure...</translation>
-<translation id="8828933418460119530">Nom DNS</translation>
-<translation id="988159990683914416">Build de développement</translation>
-<translation id="8026354464835030469"><ph name="BURNT_AMOUNT"/> sur ...</translation>
-<translation id="4114470632216071239">Verrouiller la carte SIM (code PIN obligatoire pour utiliser les données mobiles)</translation>
-<translation id="2183426022964444701">Sélectionnez le répertoire racine de l'extension.</translation>
-<translation id="2517143724531502372">Les cookies de <ph name="DOMAIN"/> sont autorisés uniquement pour cette session.</translation>
-<translation id="9018524897810991865">Confirmer les préférences de synchronisation</translation>
-<translation id="4719905780348837473">RSN</translation>
-<translation id="5212108862377457573">Ajuster la conversion en fonction de l'entrée précédente</translation>
-<translation id="5398353896536222911">Afficher le panneau de la &amp;vérification orthographique</translation>
-<translation id="5811533512835101223">(Revenir à la capture d'écran d'origine)</translation>
-<translation id="5131817835990480221">Mettre à jour &amp;<ph name="PRODUCT_NAME"/></translation>
-<translation id="939519157834106403">SSID</translation>
-<translation id="3705722231355495246">-</translation>
-<translation id="2635102990349508383">Les informations de connexion au compte n'ont pas encore été saisies.</translation>
-<translation id="6902055721023340732">URL de configuration automatique</translation>
-<translation id="4268574628540273656">URL :</translation>
-<translation id="7481312909269577407">Avancer</translation>
-<translation id="3759876923365568382"><ph name="NUMBER_FEW"/> jours restants</translation>
-<translation id="295228163843771014">Vous avez choisi de ne pas synchroniser les mots de passe. Vous pouvez à tout moment modifier vos paramètres de synchronisation, si vous changez d'avis.</translation>
-<translation id="5972826969634861500">Lancer <ph name="PRODUCT_NAME"/></translation>
-<translation id="7828702903116529889"><ph name="PRODUCT_NAME"/>
- ne parvient pas à accéder au réseau.
- <ph name="LINE_BREAK"/>
- Il est possible que votre pare-feu ou votre antivirus considère
- <ph name="PRODUCT_NAME"/>
- comme un intrus dans votre ordinateur et qu'il bloque ses tentatives de connexion à Internet.</translation>
-<translation id="878069093594050299">Ce certificat a été vérifié pour les utilisations suivantes :</translation>
-<translation id="5852112051279473187">Petit problème ! Une erreur est survenue lors de l'inscription de ce périphérique. Veuillez réessayer ou contacter votre représentant de l'assistance technique.</translation>
-<translation id="1664314758578115406">Ajouter aux favoris</translation>
-<translation id="7088418943933034707">Gérer les certificats...</translation>
-<translation id="8482183012530311851">Analyse du périphérique...</translation>
-<translation id="3127589841327267804">PYJJ</translation>
-<translation id="8808478386290700967">Web Store</translation>
-<translation id="1732215134274276513">Annuler l'épinglage des onglets</translation>
-<translation id="4084682180776658562">Favori</translation>
-<translation id="8859057652521303089">Sélectionnez votre langue :</translation>
-<translation id="3030138564564344289">Réessayer le téléchargement</translation>
-<translation id="8525552230188318924">Configurer la synchronisation des mots de passe</translation>
-<translation id="4381091992796011497">Nom d'utilisateur :</translation>
-<translation id="5830720307094128296">Enregistrer la p&amp;age sous...</translation>
-<translation id="8114439576766120195">Vos données sur tous les sites Web</translation>
-<translation id="4668954208278016290">Un problème est survenu lors de l'extraction de l'image sur l'ordinateur.</translation>
-<translation id="5822838715583768518">Lancer l'application</translation>
-<translation id="3942974664341190312">Dubeol-sik</translation>
-<translation id="8477241577829954800">Remplacé</translation>
-<translation id="6735304988756581115">Afficher les cookies et autres données de site...</translation>
-<translation id="3048564749795856202">Si vous pensez avoir cerné les risques, vous pouvez <ph name="PROCEED_LINK"/>.</translation>
-<translation id="2433507940547922241">Apparence</translation>
-<translation id="839072384475670817">Créer des raccourci&amp;s vers des applications...</translation>
-<translation id="1478632774608054702">Exécuter le flash PPAPI dans le processus du moteur de rendu</translation>
-<translation id="6756161853376828318">Définir <ph name="PRODUCT_NAME"/> en tant que navigateur par défaut</translation>
-<translation id="9112614144067920641">Veuillez choisir un nouveau code PIN.</translation>
-<translation id="2061855250933714566"><ph name="ENCODING_CATEGORY"/> (<ph name="ENCODING_NAME"/>)</translation>
-<translation id="7138678301420049075">Autre</translation>
-<translation id="9147392381910171771">&amp;Options</translation>
-<translation id="1803557475693955505">Impossible de charger la page d'arrière-plan &quot;<ph name="BACKGROUND_PAGE"/>&quot;.</translation>
-<translation id="5818334088068591797">À quel niveau rencontrez-vous des problèmes ? (Champ obligatoire)</translation>
-<translation id="6264485186158353794">Retour à la sécurité</translation>
-<translation id="5130080518784460891">Eten</translation>
-<translation id="5847724078457510387">Ce site répertorie tous ses certificats valides dans le système DNS. Un certificat non répertorié a cependant été utilisé par le serveur.</translation>
-<translation id="1394853081832053657">Options de reconnaissance vocale</translation>
-<translation id="5037676449506322593">Tout sélectionner</translation>
-<translation id="2785530881066938471">Impossible de charger le fichier &quot;<ph name="RELATIVE_PATH"/>&quot; pour le script de contenu, car ce fichier n'est pas codé en UTF-8.</translation>
-<translation id="3807747707162121253">&amp;Annuler</translation>
-<translation id="3306897190788753224">Désactiver temporairement la personnalisation des conversions, les suggestions basées sur l'historique et le dictionnaire utilisateur</translation>
-<translation id="2574102660421949343">Les cookies de <ph name="DOMAIN"/> sont autorisés.</translation>
-<translation id="77999321721642562">Au fil du temps, la zone ci-dessous affichera les huit sites que vous avez le plus visités.</translation>
-<translation id="1503894213707460512">Le plug-in <ph name="PLUGIN_NAME"/> a besoin de votre autorisation pour s'exécuter.</translation>
-<translation id="471800408830181311">Échec de création de clé privée</translation>
-<translation id="1273291576878293349">Ouvrir tous les favoris dans une fenêtre de navigation privée</translation>
-<translation id="1639058970766796751">Placer dans la file d'attente</translation>
-<translation id="1177437665183591855">Erreur de certificat serveur inconnue</translation>
-<translation id="8467473010914675605">Mode de saisie du coréen</translation>
-<translation id="3819800052061700452">&amp;Plein écran</translation>
-<translation id="5419540894229653647"><ph name="ERROR_DESCRIPTION_TEXT"/>
- <ph name="LINE_BREAK"/>
- Vous pouvez essayer de diagnostiquer le problème en procédant comme suit :
- <ph name="LINE_BREAK"/>
- <ph name="PLATFORM_TEXT"/></translation>
-<translation id="3533943170037501541">Bienvenue sur votre page d'accueil !</translation>
-<translation id="2333340435262918287">Vos modifications seront prises en compte au prochain démarrage de <ph name="PRODUCT_NAME"/>.</translation>
-<translation id="5906065664303289925">Adresse du matériel :</translation>
-<translation id="3178000186192127858">Lecture seule</translation>
-<translation id="2187895286714876935">Erreur d'importation du certificat serveur</translation>
-<translation id="5460896875189097758">Données stockées localement</translation>
-<translation id="4618990963915449444">Tous les fichiers de <ph name="DEVICE_NAME"/> vont être effacés.</translation>
-<translation id="614998064310228828">Modèle du périphérique :</translation>
-<translation id="1581962803218266616">Afficher dans le Finder</translation>
-<translation id="6096326118418049043">Nom X.500</translation>
-<translation id="6086259540486894113">Vous devez sélectionner au moins un type de données à synchroniser.</translation>
-<translation id="923467487918828349">Tout afficher</translation>
-<translation id="5101042277149003567">Ouvrir tous les favoris</translation>
-<translation id="4298972503445160211">Clavier danois</translation>
-<translation id="6621440228032089700">Cette fonctionnalité permet de réaliser un rendu hors écran de la texture, au lieu d'un affichage direct.</translation>
-<translation id="3488065109653206955">Partiellement activé</translation>
-<translation id="1481244281142949601">Votre système Sandbox est correctement configuré.</translation>
-<translation id="4849517651082200438">Ne pas installer</translation>
-<translation id="8602882075393902833">Activer la recherche instantanée pour accélérer la recherche et la navigation</translation>
-<translation id="6349678711452810642">Utiliser par défaut</translation>
-<translation id="6263284346895336537">Non essentielle</translation>
-<translation id="6409731863280057959">Fenêtres pop-up</translation>
-<translation id="3459774175445953971">Dernière modification :</translation>
-<translation id="73289266812733869">Désélectionné</translation>
-<translation id="3435738964857648380">Sécurité</translation>
-<translation id="9112987648460918699">Rechercher...</translation>
-<translation id="2231233239095101917">Le script de la page utilisait trop de mémoire. Rafraîchissez la page pour réactiver le script.</translation>
-<translation id="870805141700401153">Signature du code individuel Microsoft</translation>
-<translation id="5119173345047096771">Mozilla Firefox</translation>
-<translation id="9020278534503090146">Page Web inaccessible</translation>
-<translation id="4768698601728450387">Recadrer l'image</translation>
-<translation id="6245028464673554252">Si vous fermez <ph name="PRODUCT_NAME"/> maintenant, le téléchargement sera annulé.</translation>
-<translation id="3943857333388298514">Coller</translation>
-<translation id="385051799172605136">Retour</translation>
-<translation id="1742300158964248589">Impossible de graver l'image.</translation>
-<translation id="2670965183549957348">Mode de saisie du Chewing</translation>
-<translation id="5095208057601539847">Province</translation>
-<translation id="4085298594534903246">JavaScript a été bloqué sur cette page.</translation>
-<translation id="5630492933376732170">Remarque : Lorsque vous cliquez sur &quot;Envoyer&quot;, Google Chrome OS
- joint à votre envoi un journal des événements système de
- votre périphérique. Ces informations nous permettent de diagnostiquer les
- problèmes, de comprendre comment vous interagissez avec votre
- périphérique et d'améliorer les performances de ce dernier. Les
- informations personnelles fournies sciemment dans vos commentaires ou
- involontairement dans les journaux système et la capture d'écran sont
- protégées conformément à nos <ph name="BEGIN_LINK"/>Règles de confidentialité<ph name="END_LINK"/>.
- Si vous ne souhaitez pas envoyer de journaux système, décochez la case
- &quot;Inclure les informations système&quot;.</translation>
-<translation id="4341977339441987045">Interdire à tous les sites de stocker des données</translation>
-<translation id="806812017500012252">Trier par nom</translation>
-<translation id="3781751432212184938">Afficher un aperçu des onglets...</translation>
-<translation id="2960316970329790041">Annuler l'importation</translation>
-<translation id="3835522725882634757">Ce serveur envoie des données que <ph name="PRODUCT_NAME"/> ne comprend pas. Veuillez <ph name="BEGIN_LINK"/>signaler un bug<ph name="END_LINK"/> et inclure la <ph name="BEGIN2_LINK"/>liste des raw<ph name="END2_LINK"/>.</translation>
-<translation id="5361734574074701223">Calcul de la durée restante</translation>
-<translation id="6937152069980083337">Mode de saisie Google du japonais (pour clavier américain)</translation>
-<translation id="1731911755844941020">Envoi de la requête...</translation>
-<translation id="8371695176452482769">Parlez maintenant</translation>
-<translation id="2988488679308982380">Impossible d'installer le package : &quot;<ph name="ERROR_CODE"/>&quot;</translation>
-<translation id="2904079386864173492">Modèle :</translation>
-<translation id="3447644283769633681">Bloquer tous les cookies tiers</translation>
-<translation id="8917047707340793412">Remplacer par <ph name="ENGINE_NAME"/></translation>
-<translation id="6129953537138746214">Espace</translation>
-<translation id="3704331259350077894">Arrêt du fonctionnement</translation>
-<translation id="5801568494490449797">Préférences</translation>
-<translation id="1038842779957582377">Nom inconnu</translation>
-<translation id="5327248766486351172">Nom</translation>
-<translation id="5553784454066145694">Choisir un nouveau code PIN</translation>
-<translation id="8989148748219918422"><ph name="ORGANIZATION"/> [<ph name="COUNTRY"/>]</translation>
-<translation id="4664482161435122549">Erreur d'exportation de fichier PKCS #12</translation>
-<translation id="2445081178310039857">Le répertoire racine de l'extension doit être indiqué.</translation>
-<translation id="8251578425305135684">Miniature supprimée</translation>
-<translation id="6163522313638838258">Tout développer...</translation>
-<translation id="3037605927509011580">Aie aie aie</translation>
-<translation id="5803531701633845775">Choisir les expressions en arrière-plan, sans déplacer le pointeur</translation>
-<translation id="1918141783557917887">Plu&amp;s petit</translation>
-<translation id="6996550240668667907">Afficher le clavier en superposition</translation>
-<translation id="4065006016613364460">C&amp;opier l'URL de l'image</translation>
-<translation id="6965382102122355670">OK</translation>
-<translation id="8000066093800657092">Aucun réseau détecté</translation>
-<translation id="4481249487722541506">Charger l'extension non empaquetée...</translation>
-<translation id="8180239481735238521">page</translation>
-<translation id="8321738493186308836">Active l'interface utilisateur et le code de support pour le processus du service de communication à distance, de même que le plug-in client. Avertissement : ce service n'est actuellement disponible que pour les tests de développeurs. Si vous ne faites pas partie de l'équipe de développement et ne figurez pas sur la liste blanche, aucun élément de l'interface utilisateur activée ne fonctionnera.</translation>
-<translation id="2963783323012015985">Clavier turc</translation>
-<translation id="2149973817440762519">Modifier le favori</translation>
-<translation id="5431318178759467895">Couleur</translation>
-<translation id="7064842770504520784">Personnaliser les paramètres de synchronisation...</translation>
-<translation id="2784407158394623927">Activation de votre service Internet mobile</translation>
-<translation id="3679848754951088761"><ph name="SOURCE_ORIGIN"/></translation>
-<translation id="6920989436227028121">Ouvrir dans un onglet standard</translation>
-<translation id="4057041477816018958"><ph name="SPEED"/> - <ph name="RECEIVED_AMOUNT"/></translation>
-<translation id="2050339315714019657">Portrait</translation>
-<translation id="6978839998405419496"><ph name="NUMBER_ZERO"/> days ago</translation>
-<translation id="6139139147415955203">Active un service en arrière-plan qui connecte le service <ph name="CLOUD_PRINT_NAME"/> aux éventuelles imprimantes installées sur cet ordinateur. Une fois ce labo activé, vous pouvez lancer <ph name="CLOUD_PRINT_NAME"/> en vous connectant à votre compte Google via Options/Préférences dans la section Options avancées.</translation>
-<translation id="5112577000029535889">Outils de &amp;développement</translation>
-<translation id="2301382460326681002">Le répertoire racine de l'extension est incorrect.</translation>
-<translation id="7839192898639727867">ID de clé de l'objet du certificat</translation>
-<translation id="4759238208242260848">Téléchargements</translation>
-<translation id="2879560882721503072">Le stockage du certificat client généré par <ph name="ISSUER"/> a réussi.</translation>
-<translation id="1275718070701477396">Sélectionnée</translation>
-<translation id="1178581264944972037">Suspendre</translation>
-<translation id="6492313032770352219">Taille sur le disque :</translation>
-<translation id="5233231016133573565">ID du processus</translation>
-<translation id="5941711191222866238">Réduire</translation>
-<translation id="4121428309786185360">Expire le</translation>
-<translation id="2049137146490122801">Votre administrateur a désactivé l'accès aux fichiers locaux sur votre ordinateur.</translation>
-<translation id="1146498888431277930">Erreur de connexion SSL</translation>
-<translation id="8041089156583427627">Envoyer</translation>
-<translation id="6394627529324717982">Virgule</translation>
-<translation id="253434972992662860">&amp;Pause</translation>
-<translation id="335985608243443814">Parcourir...</translation>
-<translation id="7802488492289385605">Mode de saisie Google du japonais (pour clavier Dvorak américain)</translation>
-<translation id="7452120598248906474">Police à largeur fixe</translation>
-<translation id="3129687551880844787">Stockage de session</translation>
-<translation id="7427348830195639090">Page en arrière-plan : <ph name="BACKGROUND_PAGE_URL"/></translation>
-<translation id="5898154795085152510">Le serveur a renvoyé un certificat client incorrect. Erreur <ph name="ERROR_NUMBER"/> (<ph name="ERROR_NAME"/>)</translation>
-<translation id="2704184184447774363">Signature de document Microsoft</translation>
-<translation id="5677928146339483299">Bloqué</translation>
-<translation id="1474842329983231719">Gérer les paramètres d'impression...</translation>
-<translation id="2455981314101692989">Cette page Web a désactivé la saisie automatique dans ce formulaire.</translation>
-<translation id="1646136617204068573">Clavier hongrois</translation>
-<translation id="5988840637546770870">Les versions en développement permettent de tester de nouvelles idées, mais elles peuvent s'avérer très instables. Nous vous prions d'agir avec précaution.</translation>
-<translation id="3569713929051927529">Ajouter un dossier...</translation>
-<translation id="4032664149172368180">Mode de saisie du japonais (pour clavier Dvorak américain)</translation>
-<translation id="3748706263662799310">Signaler un bug</translation>
-<translation id="7167486101654761064">&amp;Toujours ouvrir les fichiers de ce type</translation>
-<translation id="4283623729247862189">Disque optique</translation>
-<translation id="5826507051599432481">Nom commun</translation>
-<translation id="8914326144705007149">Très grande</translation>
-<translation id="4215444178533108414">Modification terminée</translation>
-<translation id="5154702632169343078">Objet</translation>
-<translation id="2273562597641264981">Opérateur :</translation>
-<translation id="122082903575839559">Algorithme de signature du certificat</translation>
-<translation id="2181257377760181418">Cette fonctionnalité permet d'afficher un onglet d'aperçu avant de lancer une impression.</translation>
-<translation id="7240120331469437312">Autre nom de l'objet du certificat</translation>
-<translation id="6900113680982781280">Activer la saisie automatique pour remplir les formulaires Web d'un simple clic</translation>
-<translation id="1131850611586448366">Le site Web à l'adresse <ph name="HOST_NAME"/> a été signalé comme étant un site de phishing. Ces sites tentent d'amener les internautes à divulguer leurs informations personnelles en se faisant passer pour des institutions de confiance, telles que des banques.</translation>
-<translation id="5413218268059792983">Rechercher directement sur <ph name="SEARCH_ENGINE"/></translation>
-<translation id="1161575384898972166">Connectez-vous à <ph name="TOKEN_NAME"/> pour exporter le certificat client.</translation>
-<translation id="1718559768876751602">Créer un compte Google maintenant</translation>
-<translation id="1884319566525838835">État Sandbox</translation>
-<translation id="2770465223704140727">Retirer de la liste</translation>
-<translation id="3590587280253938212">rapide</translation>
-<translation id="6053401458108962351">&amp;Effacer les données de navigation…</translation>
-<translation id="2339641773402824483">Vérification des mises à jour...</translation>
-<translation id="9111742992492686570">Télécharger les mises à jour de sécurité essentielles</translation>
-<translation id="8636666366616799973">Package incorrect. Détails : &quot;<ph name="ERROR_MESSAGE"/>&quot;.</translation>
-<translation id="2045969484888636535">Continuer à bloquer les cookies</translation>
-<translation id="7353601530677266744">Ligne de commande</translation>
-<translation id="2766006623206032690">Coller l'URL et y a&amp;ccéder</translation>
-<translation id="4394049700291259645">Désactiver</translation>
-<translation id="969892804517981540">Build officiel</translation>
-<translation id="445923051607553918">Se connecter à un réseau Wi-Fi</translation>
-<translation id="100242374795662595">Périphérique inconnu</translation>
-<translation id="9087725134750123268">Supprimer les cookies et autres données de site</translation>
-<translation id="5050255233730056751">URL saisies</translation>
-<translation id="3349155901412833452">Utiliser les touches , et . pour paginer une liste d'entrées</translation>
-<translation id="6872947427305732831">Vider la mémoire</translation>
-<translation id="2742870351467570537">Supprimer les éléments sélectionnés</translation>
-<translation id="7561196759112975576">Toujours</translation>
-<translation id="2116673936380190819">de moins d'une heure</translation>
-<translation id="5765491088802881382">Aucun réseau n'est disponible.</translation>
-<translation id="1971538228422220140">Supprimer les cookies et autres données de site et de plug-in</translation>
-<translation id="883487340845134897">Intervertir les touches Rechercher et Ctrl gauche</translation>
-<translation id="5692957461404855190">Faites glisser trois doigts sur la surface de votre trackpad pour afficher un aperçu de tous vos onglets. Cliquez sur une vignette pour la sélectionner. Idéal en mode plein écran.</translation>
-<translation id="1375215959205954975">Nouveau ! Configurer la synchronisation des mots de passe</translation>
-<translation id="5183088099396036950">Échec de la tentative de connexion au serveur</translation>
-<translation id="4469842253116033348">Désactiver les notifications de <ph name="SITE"/></translation>
-<translation id="7999229196265990314">Les fichiers suivants ont été créés :
-
-Extension : <ph name="EXTENSION_FILE"/>
-Fichier de clé : <ph name="KEY_FILE"/>
-
-Conservez votre fichier de clé en lieu sûr. Vous en aurez besoin lors de la création de nouvelles versions de l'extension.</translation>
-<translation id="1846078536247420691">&amp;Oui</translation>
-<translation id="3036649622769666520">Ouvrir les fichiers</translation>
-<translation id="2966459079597787514">Clavier suédois</translation>
-<translation id="7685049629764448582">Mémoire JavaScript </translation>
-<translation id="6398765197997659313">Quitter le mode plein écran</translation>
-<translation id="6059652578941944813">Hiérarchie des certificats</translation>
-<translation id="4886690096315032939">Afficher l'onglet existant si l'URL associée est demandée dans un autre</translation>
-<translation id="5729712731028706266">&amp;Afficher</translation>
-<translation id="774576312655125744">Vos données personnelles sur <ph name="WEBSITE_1"/>, <ph name="WEBSITE_2"/> et sur <ph name="NUMBER_OF_OTHER_WEBSITES"/> autres sites Web</translation>
-<translation id="6359806961507272919">SMS de <ph name="PHONE_NUMBER"/></translation>
-<translation id="4508765956121923607">Afficher la s&amp;ource</translation>
-<translation id="5975083100439434680">Zoom arrière</translation>
-<translation id="8080048886850452639">C&amp;opier l'URL du fichier audio</translation>
-<translation id="2817109084437064140">Importer et associer au périphérique...</translation>
-<translation id="3331321258768829690">(<ph name="UTCOFFSET"/>) <ph name="LONGTZNAME"/> (<ph name="EXEMPLARCITY"/>)</translation>
-<translation id="619398760000422129">Plug-ins (par ex. Adobe Flash Player, QuickTime, etc.)</translation>
-<translation id="5849869942539715694">Empaqueter l'extension...</translation>
-<translation id="7339785458027436441">Vérifier l'orthographe lors de la frappe</translation>
-<translation id="8308427013383895095">Échec de la traduction en raison d'un problème de connexion réseau</translation>
-<translation id="1801298019027379214">Code PIN incorrect. Veuillez réessayer. Nombre de tentatives restantes : <ph name="TRIES_COUNT"/></translation>
-<translation id="1384721974622518101">Vous pouvez effectuer une recherche directement à partir du champ ci-dessus.</translation>
-<translation id="992543612453727859">Ajouter les expressions au premier plan</translation>
-<translation id="3857773447683694438">Lorem ipsum dolor sit amet, consectetur adipiscing elit.</translation>
-<translation id="1244147615850840081">Opérateur</translation>
-<translation id="8203365863660628138">Confirmer l'installation</translation>
-<translation id="406259880812417922">(Mot clé : <ph name="KEYWORD"/>)</translation>
-<translation id="309628958563171656">Sensibilité :</translation>
-</translationbundle> \ No newline at end of file
diff --git a/tools/grit/grit/testdata/header.html b/tools/grit/grit/testdata/header.html
deleted file mode 100644
index 8e9d10e..0000000
--- a/tools/grit/grit/testdata/header.html
+++ /dev/null
@@ -1,39 +0,0 @@
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
-<html><head><title>[$~TITLE~$]</title>
-<meta http-equiv="cache-control" content="no-cache">
-<meta http-equiv="content-type" content="text/html; charset=utf-8">
-<meta http-equiv="pragma" content="no-cache">
-<meta http-equiv="expires" content="-1">
-[EXTRA_META]
-<style>
-BODY,TD,DIV,.P,A { FONT-FAMILY: arial,sans-serif}
-DIV,TD { COLOR: #000}
-.f { COLOR: #6f6f6f}
-.fl:link { COLOR: #6f6f6f}
-A:link, .w, A.w:link, .w A:link { COLOR: #00c}
-A:visited { COLOR: #551a8b}
-.fl:visited { COLOR: #551a8b}
-A:active, .fl:active { COLOR: #f00}
-.h { COLOR: #3399CC}
-.i { COLOR: #a90a08}
-.i:link { COLOR: #a90a08}
-.a, .a:link, .a:visited { COLOR: #008000}
-DIV.n { MARGIN-TOP: 1ex}
-.n A { FONT-SIZE: 10pt; COLOR: #000}
-.n .i { FONT-WEIGHT: bold; FONT-SIZE: 10pt}
-.q A:visited { COLOR: #00c}
-.q A:link { COLOR: #00c}
-.q A:active { COLOR: #00c}
-.q { COLOR: #00c}
-.b { FONT-WEIGHT: bold; FONT-SIZE: 12pt; COLOR: #00c}
-.ch { CURSOR: hand}
-.e { MARGIN-TOP: 0.75em; MARGIN-BOTTOM: 0.75em}
-.g { MARGIN-TOP: 1em; MARGIN-BOTTOM: 1em}
-.f { MARGIN-TOP: 0.5em; MARGIN-BOTTOM: 0.25em}
-.s { HEIGHT: 10px }
-.c:active { COLOR: #ff0000}
-.c:visited { COLOR: #551a8b}
-.c:link { COLOR: #7777cc}
-.c { COLOR: #7777cc }
-</style>
-</head> \ No newline at end of file
diff --git a/tools/grit/grit/testdata/homepage.html b/tools/grit/grit/testdata/homepage.html
deleted file mode 100644
index cce4f2c..0000000
--- a/tools/grit/grit/testdata/homepage.html
+++ /dev/null
@@ -1,37 +0,0 @@
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
-<html><head><title>Google Desktop Search</title>
-<meta http-equiv="content-type" content="text/html; charset=utf-8">
-<meta http-equiv="cache-control" content="no-cache">
-<meta http-equiv="pragma" content="no-cache">
-<meta http-equiv="expires" content="-1">
-<style>
-BODY,TD,A,P {FONT-FAMILY: arial,sans-serif}
-.q {COLOR: #0000cc}
-</style>
-<script>
-<!--
-function sf(){document.f.q.focus();}
-// -->
-</script>
-</head>
-<BODY text=#000000 vLink=#551a8b aLink=#ff0000 link=#0000cc bgColor=#ffffff onload=sf()>
-<center>
-<TABLE cellSpacing=0 cellPadding=0 border=0>
-<tr><td><a href="[$~HOMEPAGE~$]"><IMG border=0 height=110 alt="Google Desktop Search" src="hp_logo.gif" width=276></a></td></tr></table><BR>
-<FORM name=f method=GET action='[$~SEARCHURL~$]'>
-<TABLE cellSpacing=0 cellPadding=4 border=0>
-<tr>
-<TD class=q noWrap><FONT size=-1>
-[$~LINKS~$]
-</font></td>
-</tr></table>
-<table cellspacing=0 cellpadding=0>
-<tr vAlign=top>
-<td width=25%>&nbsp;</td>
-<td align=center><input maxlength=256 size=62 name=q value="[DISP_QUERY]"><br><input type=submit value="Search Desktop" name=btnG><INPUT type=submit value="Search the Web" name="redir" accesskey=w></td>
-<td align=left valign=top nowrap width=25%><font size=-2>&nbsp;&nbsp;<A href="[$~PREFERENCES~$]">Desktop&nbsp;Preferences</a></font></td>
-</tr></table></FORM>
-<p><FONT color=#224499><B>Search your own computer.</B></font></p>
-<span style='width:29em'>[$~MESSAGE~$]</span><br>
-<br><FONT size=-1>[$~SETHOMEPAGE~$][$~BOTTOMLINE~$]</font></p>
-<p><FONT size=-2>&copy;2005 Google - Searching [NUM_ITEMS] items</font></p></center></body></html> \ No newline at end of file
diff --git a/tools/grit/grit/testdata/hover.html b/tools/grit/grit/testdata/hover.html
deleted file mode 100644
index b8f9ce0..0000000
--- a/tools/grit/grit/testdata/hover.html
+++ /dev/null
@@ -1,177 +0,0 @@
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
-<html><head>
-<meta http-equiv="content-type" content="text/html; charset=utf-8">
-<meta http-equiv="cache-control" content="no-cache">
-<meta http-equiv="pragma" content="no-cache">
-<meta http-equiv="expires" content="-1">
-<style>
-BODY { FONT-SIZE: 8pt; FONT-FAMILY: verdana,arial,san-serif }
-P { FONT-SIZE: 8pt; FONT-FAMILY: verdana,arial,san-serif }
-TD { FONT-SIZE: 8pt; FONT-FAMILY: verdana,arial,san-serif }
-A { FONT-SIZE: 8pt; FONT-FAMILY: verdana,arial,san-serif }
-DIV { FONT-SIZE: 8pt; TEXT-DECORATION: none }
-A:hover { COLOR: #ffffff }
-.border { BORDER-RIGHT: 0px; BORDER-TOP: 0px; BORDER-LEFT: 0px; BORDER-BOTTOM: 0px }
-</style>
-
-<!-- menu experiment start -->
-
-<style>
-<!--
-.menu1 {
-cursor:default;
-position:absolute;
-left: 10;
-top: 0;
-text-align: left;
-font-family: Arial, Helvetica, sans-serif;
-font-size: 8pt;
-background-color: menu;
-visibility: hidden;
-padding-top: 2px;
-padding-bottom: 2px;
-border: 1 solid;
-border-color: #888888;
-z-index: 100;
-}
-.menuitems {
-padding-left: 5px;
-padding-right: 5px;
-}
--->
-</style>
-<SCRIPT LANGUAGE="JavaScript1.2">
-<!--
-var menustyle = "menu1";
-
-function showmenu() {
- // var rightedge = document.body.clientWidth-event.clientX;
- // var bottomedge = document.body.clientHeight-event.clientY;
- // if (rightedge < rcmenu.offsetWidth)
- // rcmenu.style.left = document.body.scrollLeft + event.clientX - rcmenu.offsetWidth;
- // else
- // rcmenu.style.left = document.body.scrollLeft + event.clientX;
- // if (bottomedge < rcmenu.offsetHeight)
- // rcmenu.style.top = document.body.scrollTop + event.clientY - rcmenu.offsetHeight;
- // else
- // rcmenu.style.top = document.body.scrollTop + event.clientY;
-
- rcmenu.style.visibility = "visible";
- // rcmenu.style.zindex = 0;
- // document.all('rcmenu').style.zindex = 20;
- document.onkeydown=ck;
- return false;
-}
-
-function hidemenu() {
- rcmenu.style.visibility = "hidden";
-}
-
-function ck(e){
- evt=document.all?window.event:e;
- k=document.all?window.event.keyCode:e.keyCode;
-
- if(k==27 /*<Esc>*/) {
- hidemenu();
- }
-}
-
-function menumouseover() {
- if (event.srcElement.className == "menuitems") {
- event.srcElement.style.backgroundColor = "highlight";
- event.srcElement.style.color = "white";
- }
-}
-
-function menumouseout() {
- if (event.srcElement.className == "menuitems") {
- event.srcElement.style.backgroundColor = "";
- event.srcElement.style.color = "black";
- window.status = "";
- }
-}
-
-function menuselect() {
- if (event.srcElement.className == "menuitems") {
- if (event.srcElement.getAttribute("target") != null)
- window.open(event.srcElement.url, event.srcElement.getAttribute("target"));
- else if (event.srcElement.url.length)
- window.location = event.srcElement.url;
- }
-}
-// -->
-</script>
-
-<!-- menu experiment end -->
-
-</head>
-<BODY bottomMargin=0 bgColor=#3300cc leftMargin=0 topMargin=0 rightMargin=0 marginwidth="0" marginheight="0" border=0 style="border-width:0;" scroll=no>
-
-<!-- <br> -->
-
-<!-- menu experiment start -->
-
-<div id="rcmenu" class="skin0" onMouseover="menumouseover()" onMouseout="menumouseout()" onClick="menuselect();">
-<span class="menuitems" url="[$~SETDISP1~$]">Sidebar</span>
-<span class="menuitems" url="[$~SETDISP4~$]">Minibar</span>
-<span class="menuitems" url="[$~HIDE2~$]">Close</span>
-</div>
-
-<script language="JavaScript1.2">
-if (document.all && window.print) {
- rcmenu.className = menustyle;
- document.oncontextmenu = showmenu;
- document.body.onclick = hidemenu;
-}
-</script>
-
-<!-- menu experiment end -->
-
-<script>
-function hide() {
- return 1;
- // return confirm("Are you sure you want to hide the minibar?\nYou can show it again in Google Desktop Search Preferences. ");
-}
-function clear() {
- document.getElementById('q').value='';
-}
-</script>
-
-<TABLE cellSpacing=0 cellPadding=0 bgColor=#3300cc border=0><TBODY>
-<tr><TD vAlign=top>
-
-<form method=get action="[$~SEARCHURL~$]" [$~SEARCH_TARGET~$] name=f1 ID="f1" onsubmit="window.setTimeout('clear()', 500)">
-<input type=hidden name=src value=3>
-<input type=hidden name=redir value='' ID="redir">
-
-<TABLE cellSpacing=0 cellPadding=0 bgColor=#3300cc border=0><TBODY>
-
-<tr>
-<!-- border-top: #414a4f 0px solid; -->
-<!-- z-index:2; z-order:2; -->
-<TD vAlign=top>&nbsp;<INPUT name=q style="position:relative; height=19px;" class=border size=12>&nbsp;</td>
-
-<TD TABINDEX="2" onkeydown='if(event.keyCode!=16&&event.keyCode!=9)onclick()' onclick="f1.submit();q.value=''" class=ch onmouseover="this.bgColor='6666FF'" style="BORDER-RIGHT: #000000 1px solid; BORDER-TOP: #6666cc 1px solid; BORDER-LEFT: #6666cc 1px solid; BORDER-BOTTOM: #000000 1px solid" onmouseout="this.bgColor='#000099'" vAlign=center align=middle bgColor=#000099><IMG src="logo.gif" align=middle></td>
-
-<TD width=2><IMG height=1 width=1></td>
-
-<TD TABINDEX="3" onkeydown='if(event.keyCode!=16&&event.keyCode!=9)onclick()' onclick="redir.value='google'; f1.submit(); redir.value='';q.value=''" class=ch onmouseover="this.bgColor='6666FF'" style="BORDER-RIGHT: #000000 1px solid; BORDER-TOP: #6666cc 1px solid; BORDER-LEFT: #6666cc 1px solid; BORDER-BOTTOM: #000000 1px solid" onmouseout="this.bgColor='#000099'" vAlign=center align=middle bgColor=#000099><IMG src="gfavicon.ico" align=middle></td></tr>
-</TBODY></table>
-</td>
-
-<TD width=5><IMG height=1 width=1></td>
-
-<TD vAlign=top>
-
-<TABLE cellSpacing=0 cellPadding=1 bgColor=#000099><TBODY>
-<tr><TD TABINDEX="4" onkeydown='if(event.keyCode!=16&&event.keyCode!=9)onclick()' valign=top onclick="location.href='[$~SETDISP1~$]';" class=ch onmouseover="this.bgColor='6666FF'" style="BORDER-RIGHT: #000000 1px solid; BORDER-TOP: #6666cc 1px solid; BORDER-LEFT: #6666cc 1px solid; BORDER-BOTTOM: #000000 1px solid" onmouseout="this.bgColor='#000099'" vAlign=top noWrap bgColor=#000099><IMG src="down.gif"></td></tr></TBODY></table>
-
-</td>
-
-<TD width=1><IMG height=1 width=1></td>
-
-<TD vAlign=top><TABLE cellSpacing=0 cellPadding=1><TBODY>
-<tr><TD TABINDEX="5" onkeydown='if(event.keyCode!=16&&event.keyCode!=9)onclick()' valign=top onclick="if (hide())location.href='[$~HIDE2~$]';" class=ch onmouseover="this.bgColor='6666FF'" style="BORDER-RIGHT: #000000 1px solid; BORDER-TOP: #6666cc 1px solid; BORDER-LEFT: #6666cc 1px solid; BORDER-BOTTOM: #000000 1px solid" onmouseout="this.bgColor='#000099'" vAlign=top noWrap bgColor=#000099><IMG src="close.gif"></td></tr></TBODY></table></td></tr></TBODY></table>
-
-</form>
-</body></html>
diff --git a/tools/grit/grit/testdata/include_test.html b/tools/grit/grit/testdata/include_test.html
deleted file mode 100644
index e08f2e2..0000000
--- a/tools/grit/grit/testdata/include_test.html
+++ /dev/null
@@ -1,31 +0,0 @@
-<include src="included_sample.html">
-<if expr="True">
-should be kept
-</if>
-in the middle...
-<if expr="False">
-should be removed
-</if>
-
-<if expr="False">
-should be removed
- <if expr="True">
- should be removed because outer expr is False
- </if>
-should be removed
-</if>
-
-<if expr="True">
- <if expr="True">
- <if expr="True">
- nested true should be kept
- </if>
- <if expr="False">
- should be removed
- </if>
- </if>
- <if expr="True">
- silbing true should be kept
- </if>
-</if>
-at the end...
diff --git a/tools/grit/grit/testdata/included_sample.html b/tools/grit/grit/testdata/included_sample.html
deleted file mode 100644
index 7150ffc..0000000
--- a/tools/grit/grit/testdata/included_sample.html
+++ /dev/null
@@ -1 +0,0 @@
-Hello Include!
diff --git a/tools/grit/grit/testdata/indexing_speed.html b/tools/grit/grit/testdata/indexing_speed.html
deleted file mode 100644
index db1787b..0000000
--- a/tools/grit/grit/testdata/indexing_speed.html
+++ /dev/null
@@ -1,58 +0,0 @@
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
-<html><head><title>Google Desktop Search Index Speed</title>
-<meta http-equiv=content-type content="text/html; charset=utf-8">
-<style>
-BODY {
- MARGIN-LEFT: 3em; MARGIN-RIGHT: 3em; FONT-FAMILY: arial,sans-serif
-}
-</style>
-</head>
-<BODY text=#000000 vLink=#551a8b aLink=#ff0000 link=#0000cc bgColor=#ffffff>
-<TABLE cellSpacing=2 cellPadding=0 width="100%" border=0>
- <tr>
- <TD vAlign=top width="1%"><A href="[$~HOMEPAGE~$]">
- <IMG alt="Go to Google Desktop Search" src="/logo3.gif" border=0></A></td>
- <td>&nbsp;</td>
- <TD noWrap>
- <TABLE cellSpacing=0 cellPadding=0 width="100%" border=0>
- <tr>
- <TD bgColor=#3399CC><IMG height=1 alt="" width=1></td>
- </tr>
- </table>
- <TABLE cellSpacing=0 cellPadding=0 width="100%" border=0>
- <tr>
- <TD noWrap bgColor=#efefef><B>&nbsp;Index Speed</B></td>
- <TD noWrap align=right bgColor=#efefef><FONT size=-1><A href="/customize.html">Index Speed
- Help</A> | <A href="[$~ABOUT~$]"> About Google Desktop Search</A></font></td>
- </tr></table></td></tr></table>
-<FONT size=-1>
-<p>
-To make your emails, files, and previously viewed web pages searchable, Google Desktop Search
-needs to index them. This indexing process is currently occuring in the background
-and your computer performance is minimally impacted.
-<p>
-You have the option of speeding up this process.
-<p><B><FONT color=#FF0000>Warning:</font></B> Speeding up indexing will cause your computer
-to become unusable for many minutes, depending on how many items need to be indexed. FAST INDEXING IS NOT
-RECOMMENDED.
-<BR>&nbsp;<BR>
-<FORM action="[$~SETINDEXSPEED~$]" method=GET>
-<input name=url value="[PREVPAGE]" type=hidden>
-<input type=radio name=FAST value="0" [FAST0-CHECKED] id=f0><label for=f0>Use background indexing (recommended)</label><br>
-<input type=radio name=FAST value="1" [FAST1-CHECKED] id=f1><label for=f1>Use fast indexing</label><br><br>
-<input type=submit value="Set Indexing Speed">
-</FORM>
-<BR>
-
-<p>&nbsp;<BR>
-<TABLE cellSpacing=0 cellPadding=0 width="100%" border=0>
-<TR bgColor=#3399CC>
- <TD align=middle height=1><IMG height=1 alt="" width=1></td></tr>
-</table>
-
-<TABLE cellSpacing=0 cellPadding=0 width="100%" align=center bgColor=#efefef border=0>
-<tr>
- <TD align=middle height=20><FONT size=-1><A href="[$~HOMEPAGE~$]">Google Desktop Search&nbsp;Home</A> - <a href="[$~STATUS~$]">Status</a> - <A href="[$~ABOUT~$]">About Google Desktop Search</A> - [$~BUILDNUMBER~$] - &copy;2005 Google </font> </td></tr>
-</table><BR>
-</body>
-</html> \ No newline at end of file
diff --git a/tools/grit/grit/testdata/install_prefs.html b/tools/grit/grit/testdata/install_prefs.html
deleted file mode 100644
index eca0b56..0000000
--- a/tools/grit/grit/testdata/install_prefs.html
+++ /dev/null
@@ -1,92 +0,0 @@
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
-<html><head><title>Google Desktop Search: Initial Preferences</title>
-<meta http-equiv="cache-control" content="no-cache">
-<meta http-equiv="content-type" content="text/html; charset=utf-8">
-<meta http-equiv="pragma" content="no-cache">
-<meta http-equiv="expires" content="-1">
-<style>
-BODY { FONT-FAMILY: arial,sans-serif }
-.c:active { COLOR: #FF0000 }
-.c:visited { COLOR: #7777CC }
-.c:link { COLOR: #7777CC }
-</style>
-<script>
-<!--
-override = 1;
-function ee() {if (override==1) {(new Image()).src="[COMPLETING]";}}
-// -->
-</script>
-</head><body leftmargin=30 rightmargin=30 onresize="stw()" onunload="ee()">
-<form onsubmit='override=0;return true;' action='[STEP2]' name=f method=post>
-<img src="logo3.gif" border=0>
-<div id=c1 style="width:600px">
-<br><font color=#00218a><b>To continue, please set these initial preferences:</b></font><br><br>
-<table border=0 id=t1 width=100%>
-<tr>
- <td valign=top><input name=AIM id=chat type=checkbox checked></td>
- <td>&nbsp;</td><td><label for=chat><font size=-1><B>Enable search over Instant Messenger chats</b><br>
- <font size=-1>Google Desktop Search will store your chats and make them searchable.
-</font></label></td></tr>
-<tr height=1><td height=10px></td></tr>
-<tr>
- <td valign=top><input name=HTTPS id=https type=checkbox checked></td>
- <td>&nbsp;</td><td><label for=https><font size=-1><b>Enable search over secure web pages (HTTPS)</b>
- <br><font size=-1>Google Desktop Search will store secure web pages that you view and make them
- searchable.</font></label> </td></tr>
-<tr height=1px><td height=10px></td></tr>
-
-<tr>
- <td valign=top><input name=SEARCHBOX id=SEARCHBOX type=checkbox checked
- onclick="handleSBClick(this)"></td>
- <td>&nbsp;</td><td><label for=searchbox><font size=-1><b>Display search box</b></label>
- <br><table border=0 cellpadding=0><tr><td valign=top>
-
-<input type="radio" name="SBDISPLAY" id="DISPLAYDB" [DB-CHECKED] value="DISPLAYDB"></td><td>
-<label for=DISPLAYDB><font size=-1>Deskbar - A search box in your taskbar</font></label></td></tr>
-<tr><td></td></tr>
-<tr><td></td><td><img src="deskbar.gif" alt="Deskbar" width="268" height="34"></td></tr>
-<tr><td height=2></td></tr>
-<tr><td valign=top>
-
-<input type="radio" name="SBDISPLAY" id="DISPLAYMB" [MB-CHECKED] VALUE="DISPLAYMB"></td><td>
-<label for=DISPLAYMB><font size=-1>Floating Deskbar - A search box that you can put anywhere on your desktop</font></label></td></tr>
-<tr><td></td></tr>
-<tr><td></td><td><img src="minibar.gif" width="137" height="27"></td></tr>
-<tr><td height=2></td></tr>
-
-</table>
-</td></tr>
-
-<tr>
- <td valign=top><input name=SENDDATA id=usage type=checkbox checked></td>
- <td>&nbsp;</td><td><label for=usage><font size=-1><b>Help us improve Google Desktop Search by sending usage data and crash reports</b></label>
-</font></td></tr>
-<tr height=8px><td colspan=3 height=8px></td></tr>
-<tr><td colspan=3><font size=-1>You can change these and other preferences at any time.</font></td></tr>
-</table></div>
-<p><input type=submit value="Set Preferences and Continue" id=s><br>
-</form>
-</center>
-[SCRIPT]
-<script>
-<!--
-function handleSBClick(checkbox) {
- document.getElementById("DISPLAYDB").disabled = !checkbox.checked;
- document.getElementById("DISPLAYMB").disabled = !checkbox.checked;
-}
-function stw() {
-if (document.all && document.body.clientWidth < 600) {
- var w = document.body.clientWidth-35;
- if (w < 10) { w = 10; }
- w = w + 'px';
- document.getElementById('c1').style.width=w;
- return false;
-}
-document.getElementById('c1').style.width='600px';
-}
-stw();
-document.f.s.focus();
-// -->
-</script>
-<img SRC="http://www.google.com" WIDTH="0" HEIGHT="0" ALIGN="right"></img>
-</body></html> \ No newline at end of file
diff --git a/tools/grit/grit/testdata/install_prefs2.html b/tools/grit/grit/testdata/install_prefs2.html
deleted file mode 100644
index 1838039..0000000
--- a/tools/grit/grit/testdata/install_prefs2.html
+++ /dev/null
@@ -1,52 +0,0 @@
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
-<html><head><title>Indexing has Started</title>
-<meta http-equiv="cache-control" content="no-cache">
-<meta http-equiv="content-type" content="text/html; charset=utf-8">
-<meta http-equiv="pragma" content="no-cache">
-<meta http-equiv="expires" content="-1">
-<style>
-BODY { FONT-FAMILY: arial,sans-serif }
-}
-</style>
-<script>
-<!--
-override = 1;
-function ee() {if (override==1) {(new Image()).src="[COMPLETING]";}}
-// -->
-</script>
-</head><body leftmargin=30 rightmargin=30 onresize="stw()" onunload="ee()">
-<form onsubmit='override=0;return true;' action="[STEP3]" name=f>
-<img src="/logo3.gif" border=0><br><br>
-<div id=c1 style="width:575px">
-<table border=0 id=t1 width=100%><tr><td>
-<font color=#00218a><b>One-time indexing has started.</b></font><br><br>
-<font size=-1>An index is being prepared on your computer to allow you
-to search your information as fast as you can search the web.<br><br>
-<li>This is a one-time process that may take several hours.
-<li>You may continue to use your computer as usual and it is safe to shut down your computer.
-<li>Indexing will be performed only when your computer is idle.
-</ul>
-</font>
-<p><input type=submit value="Go to the Desktop Search homepage" name=s><br>
-</center>
-</td></tr></table>
-</form>
-</div>
-<script>
-<!--
-function stw() {
-if (document.all && document.body.clientWidth < 575) {
- var w = document.body.clientWidth-35;
- if (w < 10) { w = 10; }
- w = w + 'px';
- document.getElementById('c1').style.width=w;
- return false;
-}
-document.getElementById('c1').style.width='575px';
-}
-stw();
-// -->
-document.f.s.focus();
-</script>
-[SCRIPT]
-</body></html> \ No newline at end of file
diff --git a/tools/grit/grit/testdata/klonk-alternate-skeleton.rc b/tools/grit/grit/testdata/klonk-alternate-skeleton.rc
deleted file mode 100644
index 5f2c82a..0000000
--- a/tools/grit/grit/testdata/klonk-alternate-skeleton.rc
+++ /dev/null
Binary files differ
diff --git a/tools/grit/grit/testdata/klonk.ico b/tools/grit/grit/testdata/klonk.ico
deleted file mode 100644
index d371b21..0000000
--- a/tools/grit/grit/testdata/klonk.ico
+++ /dev/null
Binary files differ
diff --git a/tools/grit/grit/testdata/klonk.rc b/tools/grit/grit/testdata/klonk.rc
deleted file mode 100644
index c0de06e..0000000
--- a/tools/grit/grit/testdata/klonk.rc
+++ /dev/null
Binary files differ
diff --git a/tools/grit/grit/testdata/ko_oem_enable_bug.html b/tools/grit/grit/testdata/ko_oem_enable_bug.html
deleted file mode 100644
index f2c199c..0000000
--- a/tools/grit/grit/testdata/ko_oem_enable_bug.html
+++ /dev/null
@@ -1 +0,0 @@
-<IMG style="VERTICAL-ALIGN: middle" height=16 alt=아웃룩 src="/email.gif" width=16> \ No newline at end of file
diff --git a/tools/grit/grit/testdata/ko_oem_non_admin_bug.html b/tools/grit/grit/testdata/ko_oem_non_admin_bug.html
deleted file mode 100644
index b9e8a1f..0000000
--- a/tools/grit/grit/testdata/ko_oem_non_admin_bug.html
+++ /dev/null
@@ -1 +0,0 @@
-<INPUT id=s type=submit value="&nbsp;&nbsp;확인&nbsp;&nbsp;"> \ No newline at end of file
diff --git a/tools/grit/grit/testdata/mini.html b/tools/grit/grit/testdata/mini.html
deleted file mode 100644
index 8ac0a23..0000000
--- a/tools/grit/grit/testdata/mini.html
+++ /dev/null
@@ -1,36 +0,0 @@
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
-<html><head>
-<meta http-equiv=content-type content="text/html; charset=windows-1252">
-<meta http-equiv="cache-control" content="no-cache">
-<meta http-equiv="pragma" content="no-cache">
-<meta http-equiv="expires" content="-1">
-<style>
-BODY { FONT-SIZE: 8pt; FONT-FAMILY: verdana,arial,san-serif }
-P { FONT-SIZE: 8pt; FONT-FAMILY: verdana,arial,san-serif }
-TD { FONT-SIZE: 8pt; FONT-FAMILY: verdana,arial,san-serif }
-A { FONT-SIZE: 8pt; FONT-FAMILY: verdana,arial,san-serif }
-DIV { FONT-SIZE: 8pt; TEXT-DECORATION: none }
-A:hover { COLOR: #ffffff }
-.border { BORDER-RIGHT: 0px; BORDER-TOP: 0px; BORDER-LEFT: 0px; BORDER-BOTTOM: 0px }
-</style>
-</head>
-
-<BODY bottomMargin=0 bgColor=#3300cc leftMargin=0 topMargin=0 rightMargin=0 marginwidth="0" marginheight="0">
-
-<TABLE cellSpacing=0 cellPadding=0 bgColor=#3300cc border=0><TBODY>
-<tr><TD vAlign=top>
-
-<TABLE cellSpacing=0 cellPadding=0 bgColor=#3300cc border=0><TBODY>
-
-<tr>
-<TD vAlign=top>&nbsp;<INPUT style="position:relative; height=17px;" class=border size=10>&nbsp;</td>
-
-<TD class=ch onmouseover="this.bgColor='6666FF'" style="BORDER-RIGHT: #000000 1px solid; BORDER-TOP: #6666cc 1px solid; BORDER-LEFT: #6666cc 1px solid; BORDER-BOTTOM: #000000 1px solid" onmouseout="this.bgColor='#000099'" vAlign=center align=middle bgColor=#000099><img height=1 width=1><IMG src="logo.gif" align=middle><img height=1 width=1></td>
-
-</TBODY></table>
-</td>
-
-<TD width=2><IMG height=1 width=1></td>
-
-<TD vAlign=top><TABLE cellSpacing=0 cellPadding=1><TBODY>
-<tr><TD class=ch onmouseover="this.bgColor='6666FF'" style="BORDER-RIGHT: #000000 1px solid; BORDER-TOP: #6666cc 1px solid; BORDER-LEFT: #6666cc 1px solid; BORDER-BOTTOM: #000000 1px solid" onmouseout="this.bgColor='#000099'" vAlign=top noWrap bgColor=#000099><IMG src="mini_close.gif"></td></tr></TBODY></table></td></tr></TBODY></table></body></html>
diff --git a/tools/grit/grit/testdata/oem_enable.html b/tools/grit/grit/testdata/oem_enable.html
deleted file mode 100644
index db6b85e..0000000
--- a/tools/grit/grit/testdata/oem_enable.html
+++ /dev/null
@@ -1,106 +0,0 @@
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
-<html><head><title>Google Desktop Search Download</title>
-<meta http-equiv=content-type content="text/html; charset=utf-8">
-<style>BODY {
- FONT-FAMILY: arial,sans-serif
-}
-TD {
- FONT-FAMILY: arial,sans-serif
-}
-DIV {
- FONT-FAMILY: arial,sans-serif
-}
-.p {
- FONT-FAMILY: arial,sans-serif
-}
-A {
- FONT-FAMILY: arial,sans-serif
-}
-DIV {
- COLOR: #000
-}
-TD {
- COLOR: #000
-}
-A:link {
- COLOR: #00c
-}
-A:visited {
- COLOR: #551a8b
-}
-</style>
-
-<meta content="mshtml 6.00.2800.1476" name=generator></head>
-<body>
-<center>
-<TABLE cellSpacing=0 cellPadding=0 border=0>
- <TBODY>
- <TR vAlign=center>
- <td>
- <DIV align=center><IMG height=55 alt="Google Desktop Search"
- src="/logo3.gif" width=150 border=0 search=""
- desktop=""></DIV></td>
- <td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</td>
- <td><FONT size=+1><B>Search your own
-computer.</B></font></td></tr></TBODY></table><BR>
-<TABLE cellSpacing=0 cellPadding=0 width=630 border=0>
- <TBODY>
- <tr>
- <TD vAlign=top width="53%"><FONT size=-1>
- <LI>Find your email, files, web history and chats instantly <NOBR>
- <LI>View web pages you've seen, even when you're not online</NOBR>
- <LI>Search as easily as you do on Google
- <p><B>Google Desktop Search finds:</B></p></font>
- <TABLE cellSpacing=1 cellPadding=0 width=325 border=0 valign="center">
- <TBODY>
- <TR vAlign=center>
- <TD colSpan=3><FONT size=-1><IMG style="VERTICAL-ALIGN: middle"
- height=16 alt=Outlook src="/email.gif"
- width=16>&nbsp;&nbsp;Email from Outlook, Outlook Express, &amp;
- Thunderbird</font></td></tr>
- <tr>
- <TD noWrap colSpan=3><FONT size=-1><IMG
- style="VERTICAL-ALIGN: middle" height=16 alt="Internet Explorer"
- src="/html.gif" width=16>&nbsp;&nbsp;Web history
- from IE/Firefox/Mozilla/Netscape</font></td></tr>
- <tr>
- <TD noWrap colSpan=3><FONT size=-1><IMG
- style="VERTICAL-ALIGN: middle" height=16 alt=Text
- src="/file.gif" width=16>&nbsp;&nbsp;Files in Word,
- Excel, Powerpoint, PDF, &amp; media formats</font></td></tr>
- <tr>
- <TD vAlign=top colSpan=3><FONT size=-1><IMG
- style="VERTICAL-ALIGN: middle" height=16 alt="AOL IM"
- src="/aim.gif" width=16>&nbsp;&nbsp;Chats from AOL
- Instant Messenger</font></td></tr>
- <tr>
- <TD noWrap><FONT size=-1>&nbsp;</font></td></tr></TBODY></table><FONT
- size=-1>&nbsp;</font><FONT size=-1><A
- href="http://desktop.google.com/about.html">About Desktop
- Search</A>&nbsp;&nbsp; <A
- href="http://desktop.google.com/screenshots.html">Screenshots</A>&nbsp;&nbsp;
- <A href="http://desktop.google.com/support">Help</A>&nbsp;&nbsp; <A
- href="http://desktop.google.com/feedback.html">Contact
- Us</A><BR></font></LI></td>
- <td>&nbsp;&nbsp;&nbsp;</td>
- <TD vAlign=top width="53%">
- <TABLE cellPadding=2 width="100%" align=center>
- <TBODY>
- <tr>
- <TD
- style="BORDER-RIGHT: rgb(204,204,204) 1px solid; BORDER-TOP: rgb(204,204,204) 1px solid; BORDER-LEFT: rgb(204,204,204) 1px solid; BORDER-BOTTOM: rgb(204,204,204) 1px solid"
- width="100%" bgColor=#e7eff7 blah2="#fff8dd" blah="#e7eaf7"><BR>
- <center><FONT size=-1>By using, you agree to our <A
- href="http://desktop.google.com/eula.html"><BR>Terms &amp;
- Conditions</A> and <A
- href="http://desktop.google.com/privacypolicy.html">Privacy
- Policy</A></font></center>
- <p></p>
- <FORM action='[STEP2]'>
- <P align=center><INPUT style="PADDING-RIGHT: 3px; PADDING-LEFT: 3px; FONT-WEIGHT: bold; FONT-SIZE: 17px; PADDING-BOTTOM: 4px; PADDING-TOP: 4px" type=submit value="Agree and Start Using" name=Submit>
- </p></FORM><FONT size=-2>* Automatically starts when you turn on
- your computer</font> </td></tr></TBODY></table>
- <p></p></td></tr></TBODY></table></center>
-<p></p>
-<center><FONT color=#666666 size=-2>©2005 Google</font>
-<p></p></center></body></html>
diff --git a/tools/grit/grit/testdata/oem_non_admin.html b/tools/grit/grit/testdata/oem_non_admin.html
deleted file mode 100644
index 8b7ca13..0000000
--- a/tools/grit/grit/testdata/oem_non_admin.html
+++ /dev/null
@@ -1,39 +0,0 @@
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
-<html><head><title>Google Desktop Search Preferences</title>
-<meta http-equiv=cache-control content=no-cache>
-<meta http-equiv=content-type content="text/html; charset=utf-8">
-<meta http-equiv=pragma content=no-cache>
-<meta http-equiv=expires content=-1>
-<style>BODY {
- FONT-FAMILY: arial,sans-serif
-}
-.c:active {
- COLOR: #ff0000
-}
-.c:visited {
- COLOR: #7777cc
-}
-.c:link {
- COLOR: #7777cc
-}
-</style>
-
-<script>
-<!--
-override = 1;
-function ee() {if (override==1) {(new Image()).src="/doneinstallprefs&s=3286011577";}}
-// -->
-</script>
-
-<meta content="mshtml 6.00.2800.1476" name=generator></head>
-<BODY onresize=stw() leftMargin=30 rightMargin=30 onunload=ee()>
-<FORM name=f onsubmit=javascript:window.close();><IMG
-src="/logo3.gif" border=0>
-<DIV id=c1 style="WIDTH: 600px">
-<p><BR><FONT color=#00218a><B>We're sorry, but you need administrator access to
-enable Desktop Search.</B></font></p><FONT size=-1>
-<p>To install or run Google Desktop Search you need administrator access on this
-computer. Please try installing again once you have administrator
-access.</p></font></DIV>
-<p><INPUT id=s type=submit value=&nbsp;&nbsp;OK&nbsp;&nbsp;> <BR></p>
-<center></center></FORM></body></html>
diff --git a/tools/grit/grit/testdata/onebox.html b/tools/grit/grit/testdata/onebox.html
deleted file mode 100644
index c24ff04..0000000
--- a/tools/grit/grit/testdata/onebox.html
+++ /dev/null
@@ -1,21 +0,0 @@
-<html><head><title>Google Desktop Search Results</title>
-<style><!--
-body,td,div,.p,a{font-family:arial,sans-serif }
-body{ background-color: transparent }
-div,td{color:#000}
-.f,.fl:link{color:#6f6f6f}
-a:link,.w,a.w:link,.w a:link{color:#00c}
-a:visited,.fl:visited{color:#551a8b}
-a:active,.fl:active{color:#f00}
-.t a:link,.t a:active,.t a:visited,.t{color:#000}
-//-->
-</style>
-</head>
-<body>
-<table cellspacing=0 cellpadding=1 border=0 ID="Google Desktop Search">
-<tr><td colspan=2><nobr><a href="http://[WEBSERVER][$~QUERY~$]" target=_parent>[NUMRESULTS] [RESULT-STRING] stored on your computer</a><font size=-1>&nbsp;-&nbsp;<a href="[HIDENOW]" style="color:#7777cc;" target=_parent>Hide</a>&nbsp;-&nbsp;<a href="http://desktop.google.com/integration.html" style="color:#7777cc;" target=_parent>About</a></font></nobr></td></tr>
-<tr><td valign=top width=40><img height=27 style="margin-top:2px;" src="http://[WEBSERVER]/onebox.gif"></td>
-<td valign=top width="99%"><font size=-1>[RESULTS]</font></td></tr>
-</table>
-</body>
-</html>
diff --git a/tools/grit/grit/testdata/oneclick.html b/tools/grit/grit/testdata/oneclick.html
deleted file mode 100644
index 32dc645..0000000
--- a/tools/grit/grit/testdata/oneclick.html
+++ /dev/null
@@ -1,34 +0,0 @@
-[HEADER]
-
-
-<TABLE cellSpacing=4 cellPadding=0 width="100%" border=0>
-<tr>
- <TD vAlign=top align=left width=50%>
- [EMAIL_TOP_CHROME]
-
- <p class=f>
- <TABLE cellSpacing=6 cellPadding=0 width="100%" border=0>
- [EMAIL]
- </table>
- </td>
-
-
- <TD width=1 align=middle bgColor=#cfcfcf><IMG height=1 width=1></td>
- <TD width=50% vAlign=top align=left>
- [FREQ_TOP_CHROME]
- <p class=f>
- <TABLE cellSpacing=6 cellPadding=0 width="100%" border=0 ID="Table1">
- [$~FREQ~$]
- </table>
- <p class=g>
- [RECENT_TOP_CHROME]
- <TABLE cellSpacing=6 cellPadding=0 width="100%" border=0 ID="Table2">
- [$~RECENT~$]
- </table>
- </td>
- </tr>
-</table>
-<center><BR>
-
-
-[FOOTER]
diff --git a/tools/grit/grit/testdata/password.html b/tools/grit/grit/testdata/password.html
deleted file mode 100644
index 16007a1..0000000
--- a/tools/grit/grit/testdata/password.html
+++ /dev/null
@@ -1,37 +0,0 @@
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
-<html><head><title>Password Required</title>
-<meta http-equiv="content-type" content="text/html; charset=utf-8">
-<meta http-equiv="cache-control" content="no-cache">
-<meta http-equiv="pragma" content="no-cache">
-<meta http-equiv="expires" content="-1">
-<style>
-BODY,TD,A,P {FONT-FAMILY: arial,sans-serif}
-.q {COLOR: #0000cc}
-</style>
-<script>
-<!--
-function sf(){document.f.q.focus();}
-// -->
-</script>
-</head>
-<body text=#000000 vLink=#551a8b aLink=#ff0000 link=#0000cc bgColor=#ffffff onload=sf()>
-<center>
-<table cellSpacing=0 cellPadding=0 border=0>
-<tr><td><a href="[$~HOMEPAGE~$]"><IMG border=0 height=110 alt="Google Desktop Search" src="hp_logo.gif" width=276></a></td></tr></table><BR>
-<form name=f method=GET action='/password'>
-<table cellSpacing=0 cellPadding=4 border=0>
-<tr><td class=q noWrap><font size=-1>
- <table cellSpacing=0 cellPadding=0>
- <tr vAlign=top>
- <td align=middle>Password required:&nbsp;&nbsp;<input maxLength=80 size=30 type=password name=pw value="">
- <script>
- document.f.q.focus();
- </script>
- &nbsp;<input type=submit value="Submit" name=submit>
- </td></tr>
- </table>
- </form>
-</td></tr>
-</table>
-<br><font size=-1>[$~BOTTOMLINE~$]</font></p>
-<p><font size=-2>&copy;2005 Google</font></p></center></body></html> \ No newline at end of file
diff --git a/tools/grit/grit/testdata/preferences.html b/tools/grit/grit/testdata/preferences.html
deleted file mode 100644
index b374124..0000000
--- a/tools/grit/grit/testdata/preferences.html
+++ /dev/null
@@ -1,234 +0,0 @@
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
-"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
-<html><head><title>Google Desktop Search Preferences</title>
-<meta http-equiv=content-type content="text/html; charset=utf-8">
-<style>
-body {
- margin-left: 2em; margin-right: 2em;
- font-family: arial,sans-serif;
- color:#000; background-color:#fff;
-}
-a:active { color:#f00 }
-a:visited { color:#551a8b }
-a:link { color:#00c }
-a.c:active { color: #ff0000 }
-a.c:visited { color: #7777cc }
-a.c:link { color: #7777cc }
-.b { font-weight: bold }
-.shaded-header { background-color: #e8f4f7; border-top: 1px solid #39c;
-margin: 0px; padding: 0px }
-.shaded-subheader { background-color: #e8f4f7; margin: 12px 0px 0px 0px;
- padding: 0px }
-.plain-subheader { background-color: #fff; margin: 12px 0px 0px 0px;
- padding: 0px }
-.header-element { margin: 0px; padding: 2px}
-.expand { width: 98% }
-.s { font-size: smaller }
-.prefgroup { border: 2px solid #e8f4f7; width: 100% }
-.phead { font-weight: bold; font-size: smaller; vertical-align: top;
-text-transform: capitalize; border-bottom: 2px solid #e8f4f7; margin: 0px;
-padding: 8px}
-.pbody { border-bottom: 2px solid #e8f4f7; margin: 0px;
-padding: 8px}
-.pref-last { border-bottom: 0px }
-.example { color: gray; font-family: monospace; }
-</style>
-<script>
-<!--
-function validate() {}
-function fnOnClickAll() {for (var i = 0; i < document.langform.lr.length; i++) {
-document.langform.lr[i].checked = false;}}
-function fnOnClickSome() {
-var count = 0;for (var i = 0; i < document.langform.lr.length; i++) {
-if (document.langform.lr[i].checked) {count++;}}
-document.langform.lang[0].checked = (count <= 0);
-document.langform.lang[1].checked = (count > 0);}
-// -->
-</script>
-</head>
-<body onload="checkOffice()">
-<form name=prefs action="[$~SETPREFS~$]" method=post><input name=url
-value="[PREVPAGE]" type=hidden>
-<table cellspacing=2 cellpadding=0 width="100%" border=0>
-<tr>
-<td valign=top width="1%"><a href="[$~HOMEPAGE~$]">
-<img alt="Go to Google Desktop Search" src="logo3.gif" border=0></a></td>
-<td>&nbsp;</td>
-<td nowrap>
-
-<table class="shaded-header"><tr>
-<td class="header-element b expand">Preferences</td>
-<td class="header-element s">
-<a href="http://desktop.google.com/preferences.html">Preferences&nbsp;Help</a>
-</td>
-</tr></table>
-
-</tr></table>
-
-<table class="shaded-subheader"><tr>
-<td class="header-element expand s">
-<span class="b">Save</span> your preferences when finished.</td>
-<td class="header-element"><input type=submit value="Save Preferences"
-name=submit2></td>
-</tr></table>
-
-[STATUS-MESSAGE]
-<table class="plain-subheader"><tr>
-<td class="header-element expand"><span class="b">Preferences</span><span
-class="s"> (changes apply to Google Desktop Search application)</span></td>
-</tr></table>
-
-<table class="prefgroup" cellpadding=0 cellspacing=0>
-
-<!-- -->
-<tr>
-<td class="phead">Search types</td>
-<td class="pbody"><div class="s">Index the following items so that you can
-search for them:<br />&nbsp;</div>
-<div>
- <table border=0>
- <tr>
- <td width=150 nowrap valign=top><span class="s">
- <input type=checkbox [CHECK-EMAIL] name=EMAIL id=h3><label for=h3>
- Email</label><br>
- <input type=checkbox [CHECK-AIM] name=AIM id=h5><label for=h5> Chats
- (AOL/MSN IM)</label><br>
- <input type=checkbox onclick='if(!this.checked){h12.checked=0;h12.disabled=1;}
- else {h12.disabled=0;}' [CHECK-WEB] name=WEB id=h11><label for=h11> Web
- history</label>
-
- </span></td>
- <td width=120 nowrap valign=top><span class="s">
- <script>
-<!--
-function checkOffice() { var w = document.getElementById("h7");
-var e = document.getElementById("h8"); var o = document.getElementById("h10");
-if (!(w.checked || e.checked)) { o.checked=0;o.disabled=1;} else {o.disabled=0;} }
-// -->
- </script>
- <input type=checkbox [CHECK-DOC] name=DOC id=h7 onclick='checkOffice()'>
- <label for=h7> Word</label><br>
- <input type=checkbox [CHECK-XLS] name=XLS id=h8 onclick='checkOffice()'>
- <label for=h8> Excel</label><br>
- <input type=checkbox [CHECK-PPT] name=PPT id=h9>
- <label for=h9> PowerPoint</label><br>
- </span></td><td nowrap valign=top><span class="s">
- <input type=checkbox [CHECK-PDF] name=PDF id=hpdf>
- <label for=hpdf> PDF</label><br>
- <input type=checkbox [CHECK-TXT] name=TXT id=h6>
- <label for=h6> Text, media, and other files</label><br>
- </tr>
- <tr><td nowrap valign=top colspan=3><span class="s"><br />
- <input type=checkbox [CHECK-SECUREOFFICE] name=SECUREOFFICE id=h10>
- <label for=h10> Password-protected Office documents (Word, Excel)</label><br />
- <input type=checkbox [DISABLED-HTTPS] [CHECK-HTTPS] name=HTTPS id=h12><label
- for=h12> Secure pages (HTTPS) in web history</label></span></td></tr>
-</table>
-</div></td></tr>
-</div>
-</td>
-</tr>
-
-<!-- -->
-<tr>
-<td class="phead">Plug-ins</td>
-<td class="pbody"><div class="s"
-style="display:[ADDIN-DISPLAYSTYLE]">Index these additional items:<p>
-[ADDIN-DO]
-[ADDIN-OPTIONS]</div><div class="s">
-To install plug-ins to index other items, visit the
-<a href="http://desktop.google.com/plugins.html">Plug-ins Download page</a>.</div>
-</tr>
-
-<!-- -->
-<tr>
-<td class="phead">Don't search these items</td>
-<td class="pbody"><div class="s">
-<label for=FORBIDDEN>Do not search web sites with the following URLs or files
-with the following paths. Put each entry on a separate line. Examples:</label><br>
-<span class="example">c:\Documents and Settings\username\Private Stuff</span><br>
-<span class="example">http://www.domain.com/</span><br>
-<div>&nbsp;</div>
-<div><TEXTAREA rows=3 cols=65 name=FORBIDDEN id=FORBIDDEN>[FORBIDDEN]
-</TEXTAREA></div>
-</tr>
-
-<!-- -->
-<tr>
-<td class="phead pref">Search Box Display</td>
-<td class="pbody pref" valign=top>
-
-<table border=0 cellpadding=0><tr><td valign=top>
-
-<input type="radio" name="SBDISPLAY" id="DISPLAYDB" [CHECK-DISPLAYDB] value="DISPLAYDB"></td><td>
-<label for=DISPLAYDB><font size=-1>Deskbar - A search box in your taskbar</font></label></td></tr>
-<tr><td></td></tr>
-<tr><td></td><td><img src="deskbar.gif" alt="Deskbar" width="268" height="34"></td></tr>
-<tr><td height=2></td></tr>
-<tr><td valign=top>
-
-<input type="radio" name="SBDISPLAY" id="DISPLAYMB" [CHECK-DISPLAYMB] VALUE="DISPLAYMB"></td><td>
-<label for=DISPLAYMB><font size=-1>Floating Deskbar - A search box you can put anywhere on your desktop</font></label></td></tr>
-<tr><td></td></tr>
-<tr><td></td><td><img src="minibar.gif" width="137" height="27"></td></tr>
-<tr><td height=2></td></tr>
-<tr><td valign=top>
-
-<input type=radio name="SBDISPLAY" id="DISPLAYNONE" [CHECK-DISPLAYNONE] VALUE="DISPLAYNONE"></td><td valign=top>
-<label for=DISPLAYNONE><font size=-1> None</font></label>
-</td></tr>
-</table>
-
-</td></tr>
-
-<!-- -->
-<tr>
-<td class="phead pref">Number of Results</td>
-<td class="pbody pref"><label for=num><span class="s">
-Display <select name=num id="num">
-<option [CHECK-NUM-10]>10
-<option [CHECK-NUM-20]>20
-<option [CHECK-NUM-30]>30
-<option [CHECK-NUM-50]>50
-<option [CHECK-NUM-100]>100</select>
- results per page</span></label>
-</td>
-</tr>
-
-<!-- -->
-<tr>
-<td class="phead">Google integration</td>
-<td class="pbody">
-<table border=0 cellpadding=0>
-<tr><td><input type=CHECKBOX name=ONEBOX [CHECK-ONEBOX] id=onebox></td>
-<td><label for=onebox>
- <span class="s">Show Desktop Search results on Google Web Search result pages.
- </span></label></td></tr>
- <tr><td></td><td>
- <span class="s">Your personal results are private from Google.</span>
- </td></tr></table>
-</td>
-</tr>
-
-<!-- -->
-<tr>
-<td class="phead pref-last">Help us improve</td>
-<td class="pbody pref-last">
-<input type=CHECKBOX name=SENDDATA id="SENDDATA" [CHECK-SENDDATA]><label for=
-SENDDATA> <span class="s">Send non-personal usage data and crash reports to
-Google to help improve Desktop Search.</span></label>
-</td>
-</tr>
-
-</table>
-
-<table class="shaded-subheader"><tr>
-<td class="header-element expand s"><span class="b">Save</span> your preferences
-when finished.</td>
-<td class="header-element"><input type=submit value="Save Preferences"
-name=submit2></td>
-</tr></table>
-
-<p><div align=center>[$~BOTTOMLINE~$]</div>
-<br><center><span class="s">&copy;2005 Google</span></center>
-</form></body></html> \ No newline at end of file
diff --git a/tools/grit/grit/testdata/privacy.html b/tools/grit/grit/testdata/privacy.html
deleted file mode 100644
index 1d45f4a..0000000
--- a/tools/grit/grit/testdata/privacy.html
+++ /dev/null
@@ -1,35 +0,0 @@
-[!]
-title Privacy and Google Desktop Search
-template
-privacy_bottomline
-hp_image
-
-<TABLE CELLSPACING=0 CELLPADDING=5 WIDTH="98%" BORDER=0>
-<TR VALIGN=TOP>
-<td>
-<h4>Privacy and Google Desktop Search</h4>
-
-<p><FONT SIZE=-1>Google is committed to making search on your desktop as easy
-as searching the web. We recognize that privacy is an important issue,
-so we designed and built Google Desktop Search with respect for your privacy.
-<p>
-So that you can easily search your computer, the Google Desktop Search application indexes
-and stores versions of your files and other computer activity,
-such as email, chats, and web history. These versions may also be mixed
-with your Web search results to produce
-results pages for you that integrate relevant content from your computer and
-information from the Web.
-<p>
-Your computer's content is not made accessible to Google or anyone else without your explicit permission.
-
-<p>You can read the
-<A HREF='http://desktop.google.com/privacypolicy.html?hl=[LANG_CODE]'>Privacy Policy</A>
-and <A HREF='http://desktop.google.com/privacyfaq.html?hl=[LANG_CODE]'>Privacy FAQ</A> online.
-</font>
-</td></tr></table>
-
-<center><br>
-<TABLE CELLSPACING=0 CELLPADDING=0 WIDTH="100%" BORDER=0>
-<TR BGCOLOR=#3399CC><TD ALIGN=MIDDLE HEIGHT=1><IMG HEIGHT=1 ALT="" WIDTH=1></td></tr></table>
-<FONT SIZE=-1>[$~PRIVACY_BOTTOMLINE~$] - &copy;2005 Google </font>
-</center> \ No newline at end of file
diff --git a/tools/grit/grit/testdata/quit_apps.html b/tools/grit/grit/testdata/quit_apps.html
deleted file mode 100644
index a501b0e..0000000
--- a/tools/grit/grit/testdata/quit_apps.html
+++ /dev/null
@@ -1,49 +0,0 @@
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
-<html><head><title>Google Desktop Search Preferences</title>
-<meta http-equiv=cache-control content=no-cache>
-<meta http-equiv=content-type content="text/html; charset=utf-8">
-<meta http-equiv=pragma content=no-cache>
-<meta http-equiv=expires content=-1>
-<style>BODY {
- FONT-FAMILY: arial,sans-serif
-}
-.c:active {
- COLOR: #ff0000
-}
-.c:visited {
- COLOR: #7777cc
-}
-.c:link {
- COLOR: #7777cc
-}
-</style>
-
-<script>
-<!--
-// -->
-</script>
-
-<meta content="mshtml 6.00.2800.1476" name=generator></head>
-<BODY onresize=stw() leftMargin=30 rightMargin=30>
-<FORM name=f action='[NEXTSTEP]' method=post><IMG src="/logo3.gif"
-border=0>
-<DIV id=c1 style="WIDTH: 600px">
-<p><BR><FONT color=#00218a><B>To start using Google Desktop Search, we may need to close the following programs if they are running:</B></font></p>
-<FONT size=-1><p>You can start these programs once Google Desktop Search is running.</p></font>
-
-<LI><FONT size=-1>AOL Instant Messenger</font>
-<LI><FONT size=-1>Firefox</font>
-<LI><FONT size=-1>Internet Explorer</font>
-<LI><FONT size=-1>Microsoft Excel</font>
-<LI><FONT size=-1>Microsoft Outlook </font>
-<LI><FONT size=-1>Microsoft Word </font>
-<LI><FONT size=-1>Mozilla</font>
-<LI><FONT size=-1>Mozilla Thunderbird</font>
-<LI><FONT size=-1>Netscape</font>
-<LI><FONT size=-1>Opera</font>
-<LI><FONT size=-1>Other web browsers</font>
-<FONT size=-1>
-<p>This will take only a few seconds to complete. </p></font></LI></DIV>
-<p><INPUT id=s type=submit name="quit" value="&nbsp;&nbsp;OK.&nbsp;&nbsp;Close&nbsp;these&nbsp;applications&nbsp;&nbsp;">
- <INPUT id=s type=submit name="redir" value="&nbsp;&nbsp;Cancel.&nbsp;I'll&nbsp;run&nbsp;this&nbsp;later&nbsp;&nbsp;"><BR></p>
-<center></center></FORM></body></html>
diff --git a/tools/grit/grit/testdata/recrawl.html b/tools/grit/grit/testdata/recrawl.html
deleted file mode 100644
index 0401e7c..0000000
--- a/tools/grit/grit/testdata/recrawl.html
+++ /dev/null
@@ -1,30 +0,0 @@
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
-<html><head><title>Refresh index</title>
-<meta http-equiv="content-type" content="text/html; charset=utf-8">
-<meta http-equiv="cache-control" content="no-cache">
-<meta http-equiv="pragma" content="no-cache">
-<meta http-equiv="expires" content="-1">
-<style>
-BODY,TD,A,P {FONT-FAMILY: arial,sans-serif}
-.q {COLOR: #0000cc}
-</style>
-</head>
-<body text="#000000" vLink="#551a8b" aLink="#ff0000" link="#0000cc" bgColor="#ffffff">
-<center>
-<table cellSpacing="0" cellPadding="0" border="0">
-<tr>
-<td><a href="[$~HOMEPAGE~$]"><img border="0" height="110" alt="Google Desktop Search" src="hp_logo.gif" width="276"></a>
-</td>
-</tr>
-</table>
-<br>
-<center>Google Desktop Search is now recrawling your drive to index new files.</center>
-<center>Note that new files are indexed automatically, and this step is generally not needed.</center>
-<center>Click <a href="[$~HOMEPAGE~$]">here</a> to continue.</center>
-</td></tr></table>
-<br>
-<font size="-1">[$~BOTTOMLINE~$]</font>
-<p><font size="-2">&copy;2005 Google</font></p>
-</center>
-</body>
-</html> \ No newline at end of file
diff --git a/tools/grit/grit/testdata/resource_ids b/tools/grit/grit/testdata/resource_ids
deleted file mode 100644
index bd2db38..0000000
--- a/tools/grit/grit/testdata/resource_ids
+++ /dev/null
@@ -1,10 +0,0 @@
-{
- "SRCDIR": "",
- "test.grd": {
- "messages": [100, 10000],
- },
- "<(FOO)/file.grd": {
- },
- "<(SHARED_INTERMEDIATE_DIR)/devtools/devtools.grd": {
- },
-}
diff --git a/tools/grit/grit/testdata/script.html b/tools/grit/grit/testdata/script.html
deleted file mode 100644
index f177d9c..0000000
--- a/tools/grit/grit/testdata/script.html
+++ /dev/null
@@ -1,38 +0,0 @@
-<script>
-function run(n,cut){
- var out = "", str = "abcdefghijklmnopqrstuvwxyz 1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZ,./:;'\"()*!?-_@[]{}#%`+=|\\>";
- n.innerHTML = 'aa';
-
- var base = n.scrollWidth;
- for(var i=0;i<str.length;i++) {
- n.innerHTML = 'a'+str.charAt(i)+'a';
- out += str.charAt(i) + (n.scrollWidth-base) +";";
-
- if(cut && !i && (n.scrollWidth-base == cut)) {
- return '\x02'+"0;";
- }
- }
- // extra cases for literals
- n.innerHTML = 'a&lt;a';
- out += '<' + (n.scrollWidth-base) +";";
- n.innerHTML = 'a&amp;a';
- out += '&' + (n.scrollWidth-base) +";";
-
- var base_height = n.scrollHeight;
- n.innerHTML += '<br>a';
- out += '\x01' + (n.scrollHeight-base_height) +";";
-
- return out;
-}
-
-function TEST_WIDTH() {
- var n = document.getElementById('test');
- var out = run(n[$~CUT~$]);
- if (out.length>4){
- n.style.fontWeight='bold';
- out += run(n);
- }
- n.outerHTML = "";
- (new Image()).src="[$~SETWIDTH~$]?src=[COMPONENT]&data="+escape(out).replace(/\+/g,"%2B");
-}
-</script>
diff --git a/tools/grit/grit/testdata/searchbox.html b/tools/grit/grit/testdata/searchbox.html
deleted file mode 100644
index 9eccba9..0000000
--- a/tools/grit/grit/testdata/searchbox.html
+++ /dev/null
@@ -1,22 +0,0 @@
-<body bgcolor=#ffffff topmargin=2 marginheight=2>
-<table border=0 cellpadding=0 cellspacing=0 width=1%>
-<tr>
-<td valign=top><a href='[$~HOMEPAGE~$]'><img width=150 height=55 src="/logo3.gif" alt="Go to Google Desktop Search" border=0 vspace=12></a></td>
-<td>&nbsp;&nbsp;</td>
-<td valign=top>
-<table cellpadding=0 cellspacing=0 border=0><tr><td colspan=2 height=14 valign=bottom>
-<table border=0 cellpadding=4 cellspacing=0>
-<tr><td class=q><font size=-1>
-[$~LINKS~$]
-</tr>
-</table>
-</td>
-</tr>
-<tr><td nowrap><form name=gs method=GET action='[$~SEARCHURL~$]'><input type=text name=q size=41 maxlength=2048 value="[DISP_QUERY]"><input type=hidden name=ie value="UTF-8">
-<font size=-1>[$~FLAGS~$]<input type=submit name="btnG" value="Search Desktop"><span id=hf></span></font></td>
-<td><font size=-2>&nbsp;&nbsp;<a href='[$~PREFERENCES~$]'>Desktop&nbsp;Preferences</a><br>&nbsp;&nbsp;<a [DELETE_EXTRA] href=[DELETE_PAGE]><nobr>[DELETE_NAME]</nobr></a></font></td>
-</tr></table>
-<table cellpadding=0 cellspacing=0 border=0>
-<tr><td><font size=-1>&nbsp;</font></td></tr>
-</table>
-</td></tr></form></table> \ No newline at end of file
diff --git a/tools/grit/grit/testdata/sidebar_h.html b/tools/grit/grit/testdata/sidebar_h.html
deleted file mode 100644
index e103e8f..0000000
--- a/tools/grit/grit/testdata/sidebar_h.html
+++ /dev/null
@@ -1,82 +0,0 @@
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
-<html><head>
-<meta http-equiv="content-type" content="text/html; charset=utf-8">
-<meta http-equiv="cache-control" content="no-cache">
-<meta http-equiv="pragma" content="no-cache">
-<meta http-equiv="expires" content="-1">
-<style>
-BODY,TD,DIV,A,.p { FONT-FAMILY: arial,sans-serif; SCROLL: no}
-DIV,TD {COLOR: #000}
-.f, .fl:link {COLOR: #6f6f6f}
-A:link { COLOR: #00c}
-A:visited { COLOR: #551a8b}
-A:active { COLOR: #f00}
-.fl:active { COLOR: #f00}
-.h { COLOR: #3399CC}
-.a, .a:link {COLOR: #008000}
-.b { FONT-WEIGHT: bold; FONT-SIZE: 12pt; COLOR: #00c}
-.g { MARGIN-TOP: .5em; MARGIN-BOTTOM: .5em}
-.f { MARGIN-TOP: 0.5em; MARGIN-BOTTOM: 0.25em}
-.c:active, .c:visited, .c:link { COLOR: #6f6f6f}
-.ch {CURSOR: hand}
-</style>
-</head>
-<BODY onload="TEST_WIDTH();" bottomMargin=0 leftMargin=2 topMargin=0 rightMargin=2 marginwidth=0 marginheight=0 SCROLL=NO bgcolor=#E0E0E0 style="border-style:solid; border-width:0;" oncontextmenu="return false;">
-
-<script>
-function hide() {
- return 1;
- // return confirm("Are you sure you want to hide the sidebar?\nYou can show it again in Google Desktop Search Preferences. ");
-}
-</script>
-
-
-<TABLE border=0 cellPadding=0 cellSpacing=0 width="100%"><tr>
-<TD WIDTH="19%" VALIGN=TOP>
-
-<form method=get action="[$~SEARCHURL~$]">
-<input type=hidden name=src value=4>
-
- <table cellspacing=0 cellpadding=0 width='1%'>
- <tr><td nowrap align=center valign=middle><nobr><img width=16 height=16 src=logo.gif>&nbsp;<b><i><font color=#6F6F6F>Google Desktop Search</font></i></b><IMG id=ctl src="[CONTROL_IMAGE]" border=0 usemap="#control"></nobr></td></tr>
- <tr><td nowrap align=center valign=middle><nobr><input TABINDEX="1" style="font-size:10px; width:'100%';" name="q" id="q"></nobr></td></tr>
- <tr><td nowrap align=center valign=middle><nobr><input TABINDEX="2" style="font-size:10px" type=submit value="Local search" name=btnG> <input TABINDEX="3" style="font-size:9px" type=submit value="Web search" name=redir></nobr></td></tr>
-<MAP name="control">
-<area TABINDEX="4" onkeydown='if(event.keyCode==13)location.href="movesidebar?side=1"' title="Move sidebar to Top" shape="rect" coords="9,0,22,8" href="/movesidebar?side=1" onmouseover="ctl.src='control1.gif'" onmouseout="ctl.src='[CONTROL_IMAGE]'">
-<area TABINDEX="5" onkeydown='if(event.keyCode==13)location.href="movesidebar?side=3"' title="Move sidebar to Bottom" shape="rect" coords="9,9,22,17" href="/movesidebar?side=3" onmouseover="ctl.src='control3.gif'" onmouseout="ctl.src='[CONTROL_IMAGE]'">
-<area TABINDEX="6" onkeydown='if(event.keyCode==13)location.href="movesidebar?side=0"' title="Move sidebar to Left" shape="rect" coords="0,2,8,15" href="/movesidebar?side=0" onmouseover="ctl.src='control0.gif'" onmouseout="ctl.src='[CONTROL_IMAGE]'">
-<area TABINDEX="7" onkeydown='if(event.keyCode==13)location.href="movesidebar?side=2"' title="Move sidebar to Right" shape="rect" coords="23,2,31,15" href="/movesidebar?side=2" onmouseover="ctl.src='control2.gif'" onmouseout="ctl.src='[CONTROL_IMAGE]'">
-</MAP>
- </table>
-</form>
-
-</td>
-<TD WIDTH="27%" VALIGN=TOP>
-
-[HEADER_SECTION1]
-[CONTENT_INBOX]
-
-</td>
-<TD WIDTH="27%" VALIGN=top>
-
-[HEADER_SECTION2]
-[CONTENT_HIST]
-
-</td>
-<TD WIDTH="27%" VALIGN=top>
-
-[CONTENT_NEWS]
-[CONTENT_OTHER]
-
-</td>
-<TD WIDTH="1%" VALIGN=top>
-
-<a TABINDEX="8" onkeydown='if(event.keyCode!=16&&event.keyCode!=9)onclick()' onclick='return hide()' href='[$~HIDE1~$]' class=ch><img width=12 height=11 style='vertical-align:top;' src=/hide.gif valign=top border=0></a>
-
-</td>
-</tr></table>
-
-<font size=-1><span style="visibility:hidden" id='test'>t</span></font>
-
-[SCRIPT]
-</body></html>
diff --git a/tools/grit/grit/testdata/sidebar_v.html b/tools/grit/grit/testdata/sidebar_v.html
deleted file mode 100644
index e040d8e..0000000
--- a/tools/grit/grit/testdata/sidebar_v.html
+++ /dev/null
@@ -1,267 +0,0 @@
-<html><head>
-<title>Google Desktop Search Sidebar</title>
-<meta http-equiv="content-type" content="text/html; charset=utf-8">
-<meta http-equiv="cache-control" content="no-cache">
-<meta http-equiv="pragma" content="no-cache">
-<meta http-equiv="expires" content="-1">
-<style>
-BODY,TD,P,A {FONT-FAMILY: verdana,arial,sans-serif;font-size:8pt; color:#fff}
-a:link, a:visited, a:hover, b, q b { color: #ffffff}
-a:active { color: #ff0000}
-a:link,a:active,a:visited,div { text-decoration: none;font-size:8pt }
-.g{margin-top: 1em;}
-.gg{margin-top: .4em;}
-.norepeat { background-repeat: no-repeat }
-.indent{margin-top: 0px; margin-bottom: 0px;margin-left:3px;}
-.c:link, .c:visited, .c:active { color: #959595;font-size:8pt }
-.ch{cursor:pointer;cursor:hand}
-.gap{margin-top: 10px; margin-bottom: 10px;}
-.off {display:none}
-.on {display:on}
-.but { border-top: 1px solid #73787E;border-bottom: 1px solid #000000;border-right: 1px solid #000000;border-left: 1px solid #73787E;margin-top: 0px; margin-bottom: 0px; cursor:pointer;cursor:hand}
-</style>
-<script>
-
-function toggle(i) {
- var v = document.getElementById(i);
- var vi = document.getElementById(i+'icon');
- var c = (v['className'] == 'on');
- if (c) {
- v['className'] = 'off';
- vi.src='up.gif';
- }
- else {
- v['className'] = 'on';
- vi.src='down.gif';
- }
- (new Image()).src="[$~TOGGLE~$]?setting="+i+"&mode="+v['className']+"&rnd="+Math.random();
-
- if (!c && (v['oclass'] == 'off')) {
- location.href = location.href;
- }
-
- return true;
-}
-function hide() {
- // return confirm("Are you sure you want to hide the sidebar?\nYou can show it again in Google Desktop Search Preferences.");
- return 1;
-}
-</script>
-
-<!-- menu experiment start -->
-
-<style>
-<!--
-.menu1 {
-cursor:default;
-position:absolute;
-text-align: left;
-font-family: Arial, Helvetica, sans-serif;
-font-size: 8pt;
-font-color: #000000;
-color: #000000;
-background-color: menu;
-visibility: hidden;
-padding-top: 2px;
-padding-bottom: 2px;
-border: 1 solid;
-border-color: #888888;
-z-index: 100;
-}
-.menuitems {
-padding-left: 5px;
-padding-right: 5px;
-}
--->
-</style>
-<SCRIPT LANGUAGE="JavaScript1.2">
-<!--
-var menustyle = "menu1";
-
-function showmenu() {
- var rightedge = document.body.clientWidth-event.clientX;
- var bottomedge = document.body.clientHeight-event.clientY;
- // if (rightedge < rcmenu.offsetWidth)
- // rcmenu.style.left = document.body.scrollLeft + event.clientX - rcmenu.offsetWidth;
- // else
- // rcmenu.style.left = document.body.scrollLeft + event.clientX;
-
- // if (rcmenu.style.left < 0) rcmenu.style.left = 0;
- rcmenu.style.left = 0;
-
- if (bottomedge < rcmenu.offsetHeight)
- rcmenu.style.top = document.body.scrollTop + event.clientY - rcmenu.offsetHeight;
- else
- rcmenu.style.top = document.body.scrollTop + event.clientY;
-
- if (rcmenu.style.top < 0) rcmenu.style.top = 0;
-
- rcmenu.style.visibility = "visible";
- // rcmenu.style.zindex = 0;
- // document.all('rcmenu').style.zindex = 20;
- document.onkeydown=ck;
- return false;
-}
-
-function hidemenu() {
- rcmenu.style.visibility = "hidden";
-}
-
-function ck(e){
- evt=document.all?window.event:e;
- k=document.all?window.event.keyCode:e.keyCode;
-
- if(k==27 /*<Esc>*/) {
- hidemenu();
- }
-}
-
-function menumouseover() {
- if (event.srcElement.className == "menuitems") {
- event.srcElement.style.backgroundColor = "highlight";
- event.srcElement.style.color = "white";
- }
-}
-
-function menumouseout() {
- if (event.srcElement.className == "menuitems") {
- event.srcElement.style.backgroundColor = "";
- event.srcElement.style.color = "black";
- window.status = "";
- }
-}
-
-function menuselect() {
- if (event.srcElement.className == "menuitems") {
- if (event.srcElement.getAttribute("target") != null)
- window.open(event.srcElement.url, event.srcElement.getAttribute("target"));
- else if (event.srcElement.url.length)
- window.location = event.srcElement.url;
- }
-}
-// -->
-</script>
-
-<!-- menu experiment end -->
-
-</head>
-
-<body onload="TEST_WIDTH();" bottommargin=0 leftmargin=0 marginheight=0 marginwidth=0 rightmargin=0 topmargin=0 style="background-color:'#384146'; background-repeat: repeat-y; border-style:solid; border-width:0;" background="greyback.jpg" scroll=NO oncontextmenu="return false;">
-
-<!-- menu experiment start -->
-
-<div id="rcmenu" class="skin0" onMouseover="menumouseover()" onMouseout="menumouseout()" onClick="menuselect();">
-<div class="menuitems" url="[$~SETDISP4~$]">Switch to minibar</div>
-<div class="menuitems" url="[$~SETDISP2~$]">Switch to hoverbar</div>
-<div class="menuitems" url="[$~HIDE1~$]">Close sidebar</div>
-<div class="menuitems" url="">No change</div>
-</div>
-
-<script language="JavaScript1.2">
-if (document.all && window.print) {
- rcmenu.className = menustyle;
- document.oncontextmenu = showmenu;
- document.body.onclick = hidemenu;
-}
-</script>
-
-<!-- menu experiment end -->
-
-<div id="oneliner" style="visibility:hidden; position:absolute; left:0px; top:0px;"></div>
-<script>
-var h = document.getElementById("oneliner").offsetHeight*2;
-document.write("<style type='text/css'>.truncme { overflow:hidden;height: " +h+"px; }</style>");
-</script>
-
-<table cellpadding=0 cellspacing=0 border=0 width='100%'>
-<form method=get action="[$~SEARCHURL~$]" id=f1>
-<input type=hidden name=src value=5>
-<input type=hidden name=redir value=''>
-<tr>
- <td width='1%'><IMG id=ctl src="[CONTROL_IMAGE]" border=0 usemap="#control"></td>
- <td width='97%'><input TABINDEX="1" NAME="q" style="width:'100%'; FONT-FAMILY: verdana,arial,sans-serif;font-size:8pt"></td>
- <td width='1%'><table cellpadding=2 cellspacing=0><tr><td> </td><td TABINDEX="8" onkeydown='if(event.keyCode!=16&&event.keyCode!=9)onclick()' onmouseover="this.bgColor='4C535B'" onmouseout="this.bgColor='#414A4F'" class=but bgcolor=414A4F valign=top onclick="location.href='[$~SETDISP2~$]';"><img src="mini_mini.gif"></td></tr></table></td>
- <td width='1%'><table cellpadding=2 cellspacing=0><tr><td TABINDEX="9" onkeydown='if(event.keyCode!=16&&event.keyCode!=9)onclick()' onmouseover="this.bgColor='4C535B'" onmouseout="this.bgColor='#414A4F'" class=but bgcolor=414A4F valign=top onclick="if (hide())location.href='[$~HIDE1~$]';"><img src="mini_close.gif"></td></tr></table></td>
-</tr>
-<MAP name="control">
-<area TABINDEX="4" onkeydown='if(event.keyCode==13)location.href="movesidebar?side=1"' title="Move sidebar to Top" shape="rect" coords="9,0,22,8" href="/movesidebar?side=1" onmouseover="ctl.src='control1.gif'" onmouseout="ctl.src='[CONTROL_IMAGE]'">
-<area TABINDEX="5" onkeydown='if(event.keyCode==13)location.href="movesidebar?side=3"' title="Move sidebar to Bottom" shape="rect" coords="9,9,22,17" href="/movesidebar?side=3" onmouseover="ctl.src='control3.gif'" onmouseout="ctl.src='[CONTROL_IMAGE]'">
-<area TABINDEX="6" onkeydown='if(event.keyCode==13)location.href="movesidebar?side=0"' title="Move sidebar to Left" shape="rect" coords="0,2,8,15" href="/movesidebar?side=0" onmouseover="ctl.src='control0.gif'" onmouseout="ctl.src='[CONTROL_IMAGE]'">
-<area TABINDEX="7" onkeydown='if(event.keyCode==13)location.href="movesidebar?side=2"' title="Move sidebar to Right" shape="rect" coords="23,2,31,15" href="/movesidebar?side=2" onmouseover="ctl.src='control2.gif'" onmouseout="ctl.src='[CONTROL_IMAGE]'">
-</MAP>
-</table>
-
-<center>
-<table cellpadding=2 cellspacing=3>
-<tr>
- <td TABINDEX="2" onkeydown='if(event.keyCode!=16&&event.keyCode!=9)onclick()' onclick="f1.submit()" onmouseover="this.bgColor='4C535B'" onmouseout="this.bgColor='#414A4F'" class=ch nowrap bgcolor=414A4F valign=top style="border-top: 1px solid #73787E;border-bottom: 1px solid #252C30;border-right: 1px solid #252C30;border-left: 1px solid #73787E;"><img src="logo.gif" align="texttop"> <font color=ffffff>Google Desktop Search&nbsp;</td>
- <td TABINDEX="3" onkeydown='if(event.keyCode!=16&&event.keyCode!=9)onclick()' onclick="redir.value='google'; f1.submit(); redir.value='';" onmouseover="this.bgColor='4C535B'" onmouseout="this.bgColor='#414A4F'" class=ch bgcolor=414A4F nowrap valign=top style="border-top: 1px solid #73787E;border-bottom: 1px solid #252C30;border-right: 1px solid #252C30;border-left: 1px solid #73787E;">&nbsp;<font color=ffffff>Web&nbsp;</td>
-</tr>
-</form>
-</table>
-</center>
-
-<p class=gg>
-<table width=100% cellpadding=0 cellspacing=0><tr><td bgcolor=4E555C><img width=1 height=1></td></tr></table>
-<table class=ch cellpadding=0 cellspacing=0 style="background-color:'#424B50'; background-repeat: repeat-y;" background="section.jpg" width=100% height=18><tr onDblClick='return toggle("news");' onclick='return toggle("news");' onmouseover="this.bgColor='#465055'" onmouseout="this.bgColor=''"><td width=16 align=right><img id=newsicon src="[$~NEWS_MODE~$]" border=0></td><td valign=middle>&nbsp;<font color=ffffff>News</td></tr></table>
-<table width=100% cellpadding=0 cellspacing=0><tr><td bgcolor=313B40><img width=1 height=1></td></tr></table>
-
-<span id="news" class=[$~NEWS_CLASS~$] oclass=[$~NEWS_CLASS~$]>
-[CONTENT_NEWS]
-<p class=g>
-</span>
-
-<table width=100% cellpadding=0 cellspacing=0><tr><td bgcolor=4E555C><img width=1 height=1></td></tr></table>
-<table class=ch cellpadding=0 cellspacing=0 style="background-color:'#424B50'; background-repeat: repeat-y;" background="section.jpg" width=100% height=18><tr onDblClick='return toggle("inbox");' onclick='return toggle("inbox");' onmouseover="this.bgColor='#465055'" onmouseout="this.bgColor=''"><td width=16 align=right><img id=inboxicon src="[$~INBOX_MODE~$]" border=0></td><td valign=middle>&nbsp;<font color=ffffff>Email</td></tr></table>
-<table width=100% cellpadding=0 cellspacing=0><tr><td bgcolor=313B40><img width=1 height=1></td></tr></table>
-
-<span id=inbox class=[$~INBOX_CLASS~$] oclass=[$~INBOX_CLASS~$]>
-[CONTENT_INBOX]
-<p class=g>
-</span>
-
-<table width=100% cellpadding=0 cellspacing=0><tr><td bgcolor=4E555C><img width=1 height=1></td></tr></table>
-<table class=ch cellpadding=0 cellspacing=0 style="background-color:'#424B50'; background-repeat: repeat-y;" background="section.jpg" width=100% height=18><tr onDblClick='return toggle("hist");' onclick='return toggle("hist");' onmouseover="this.bgColor='#465055'" onmouseout="this.bgColor=''"><td width=16 align=right><img id=histicon src="[$~HIST_MODE~$]" border=0></td><td valign=middle>&nbsp;<font color=ffffff>Related History</td></tr></table>
-<table width=100% cellpadding=0 cellspacing=0><tr><td bgcolor=313B40><img width=1 height=1></td></tr></table>
-
-<span id="hist" class=[$~HIST_CLASS~$] oclass=[$~HIST_CLASS~$]>
-[CONTENT_HIST]
-<p class=g>
-</span>
-
-
-<table width=100% cellpadding=0 cellspacing=0><tr><td bgcolor=4E555C><img width=1 height=1></td></tr></table>
-<table class=ch cellpadding=0 cellspacing=0 style="background-color:'#424B50'; background-repeat: repeat-y;" background="section.jpg" width=100% height=18><tr onDblClick='return toggle("recent");' onclick='return toggle("recent");' onmouseover="this.bgColor='#465055'" onmouseout="this.bgColor=''"><td width=16 align=right><img id=recenticon src="[$~RECENT_MODE~$]" border=0></td><td valign=middle>&nbsp;<font color=ffffff>Recent</td></tr></table>
-<table width=100% cellpadding=0 cellspacing=0><tr><td bgcolor=313B40><img width=1 height=1></td></tr></table>
-
-<span id="recent" class=[$~RECENT_CLASS~$] oclass=[$~RECENT_CLASS~$]>
-[CONTENT_RECENT]
-<p class=g>
-</span>
-
-
-<table width=100% cellpadding=0 cellspacing=0><tr><td bgcolor=4E555C><img width=1 height=1></td></tr></table>
-<table class=ch cellpadding=0 cellspacing=0 style="background-color:'#424B50'; background-repeat: repeat-y;" background="section.jpg" width=100% height=18><tr onDblClick='return toggle("popular");' onclick='return toggle("popular");' onmouseover="this.bgColor='#465055'" onmouseout="this.bgColor=''"><td width=16 align=right><img id=popularicon src="[$~POPULAR_MODE~$]" border=0></td><td valign=middle>&nbsp;<font color=ffffff>Frequently Visited</td></tr></table>
-<table width=100% cellpadding=0 cellspacing=0><tr><td bgcolor=313B40><img width=1 height=1></td></tr></table>
-
-<span id="popular" class=[$~POPULAR_CLASS~$] oclass=[$~POPULAR_CLASS~$]>
-[CONTENT_POPULAR]
-<p class=g>
-</span>
-
-
-<table width=100% cellpadding=0 cellspacing=0><tr><td bgcolor=4E555C><img width=1 height=1></td></tr></table>
-<table class=ch cellpadding=0 cellspacing=0 style="background-color:'#424B50'; background-repeat: repeat-y;" background="section.jpg" width=100% height=18><tr onDblClick='return toggle("quib_debug");' onclick='return toggle("quib_debug");' onmouseover="this.bgColor='#465055'" onmouseout="this.bgColor=''"><td width=16 align=right><img id=quib_debugicon src="[$~QUIB_DEBUG_MODE~$]" border=0></td><td valign=middle>&nbsp;<font color=ffffff>Implicit Query Debug</td></tr></table>
-<table width=100% cellpadding=0 cellspacing=0><tr><td bgcolor=313B40><img width=1 height=1></td></tr></table>
-
-<span id="quib_debug" class=[$~QUIB_DEBUG_CLASS~$] oclass=[$~QUIB_DEBUG_CLASS~$]>
-[CONTENT_QUIB_DEBUG]
-</span>
-
-<span style="visibility:hidden" id='test'>t</span>
-
-[CONTENT_OTHER]
-
-[SCRIPT]
-</body>
-</html>
diff --git a/tools/grit/grit/testdata/simple-input.xml b/tools/grit/grit/testdata/simple-input.xml
deleted file mode 100644
index 92827fa..0000000
--- a/tools/grit/grit/testdata/simple-input.xml
+++ /dev/null
@@ -1,52 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<grit base_dir="." latest_public_release="2" current_release="3" source_lang_id="en-US">
- <release seq="2">
- <messages>
- <message name="IDS_OLD_MESSAGE" translateable="true">Hello earthlings!</message>
- </messages>
- </release>
- <release seq="3">
- <includes>
- <include name="ID_EDIT_BOX_ICON" type="icon" translateable="false" file="images/edit_box.ico" />
- <include name="ID_LOGO" type="gif" translateable="true" file="images/logo.gif"/>
- </includes>
- <messages>
- <message name="IDS_BTN_GO" desc="Button text" meaning="verb">Go!</message>
- <message name="IDS_GREETING" desc="Printed to greet the currently logged in user">
- Hello <ph name="USERNAME">%s<ex>Joi</ex></ph>, how are you doing today?
- </message>
- </messages>
- <structures>
- <structure type="menu" name="IDM_FOO" file="rc_files/menus.rc" />
- <structure type="dialog" name="IDD_BLAT" file="rc_files/dialogs.rc" />
- <structure type="tr_html" name="IDR_HTML_TEMPLATE" file="templates/homepage.html" />
- <structure type="dialog" name="IDD_NARROW_DIALOG" file="rc_files/dialogs.rc">
- <skeleton expr="lang == 'fr-FR'" variant_of_revision="3">
- <![CDATA[IDD_DIALOG1 DIALOGEX 0, 0, 186, 90
-STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION |
- WS_SYSMENU
-CAPTION "TRANSLATEABLEPLACEHOLDER1"
-FONT 8, "MS Shell Dlg", 400, 0, 0x1
-BEGIN
- DEFPUSHBUTTON "TRANSLATEABLEPLACEHOLDER2",IDOK,129,7,50,14
- PUSHBUTTON "TRANSLATEABLEPLACEHOLDER3",IDCANCEL,129,24,50,14
- LTEXT "TRANSLATEABLEPLACEHOLDER4",IDC_STATIC,23,31,40,8
-END]]>
- </skeleton>
- </structure>
- <structure type="version" name="VS_VERSION_INFO" file="rc_files/version.rc"/>
- </structures>
- </release>
- <translations>
- <file path="figs_nl_translations.xml" />
- <file path="cjk_translations.xml" />
- </translations>
- <outputs>
- <output filename="resource.h" type="rc_header" />
- <output filename="resource_en.rc" type="rc_all" lang="en-US" />
- <output filename="resource_fr.rc" type="rc_all" lang="fr-FR" />
- <output filename="resource_it.rc" type="rc_translateable" lang="it-IT" />
- <output filename="resource_zh_cn.rc" type="rc_translateable" lang="zh-CN" />
- <output filename="nontranslateable.rc" type="rc_nontranslateable" />
- </outputs>
-</grit>
diff --git a/tools/grit/grit/testdata/simple.html b/tools/grit/grit/testdata/simple.html
deleted file mode 100644
index 4392d23..0000000
--- a/tools/grit/grit/testdata/simple.html
+++ /dev/null
@@ -1,3 +0,0 @@
-<p>
- Hello!
-</p> \ No newline at end of file
diff --git a/tools/grit/grit/testdata/source.rc b/tools/grit/grit/testdata/source.rc
deleted file mode 100644
index d6d5459..0000000
--- a/tools/grit/grit/testdata/source.rc
+++ /dev/null
@@ -1,57 +0,0 @@
-IDC_KLONKMENU MENU
-BEGIN
- POPUP "&File"
- BEGIN
- MENUITEM "E&xit", IDM_EXIT
- MENUITEM "This be ""Klonk"" me like", ID_FILE_THISBE
- POPUP "gonk"
- BEGIN
- MENUITEM "Klonk && is ""good""", ID_GONK_KLONKIS
- END
- END
- POPUP "&Help"
- BEGIN
- MENUITEM "&About ...", IDM_ABOUT
- END
-END
-
-IDD_ABOUTBOX DIALOGEX 22, 17, 230, 75
-STYLE DS_SETFONT | DS_MODALFRAME | WS_CAPTION | WS_SYSMENU
-CAPTION "About"
-FONT 8, "System", 0, 0, 0x0
-BEGIN
- ICON IDI_KLONK,IDC_MYICON,14,9,20,20
- LTEXT "klonk Version ""yibbee"" 1.0",IDC_STATIC,49,10,119,8,
- SS_NOPREFIX
- LTEXT "Copyright (C) 2005",IDC_STATIC,49,20,119,8
- DEFPUSHBUTTON "OK",IDOK,195,6,30,11,WS_GROUP
- CONTROL "Jack ""Black"" Daniels",IDC_RADIO1,"Button",
- BS_AUTORADIOBUTTON,46,51,84,10
-END
-
-IDD_DIFFERENT_LENGTH_IN_TRANSL DIALOGEX 22, 17, 230, 75
-STYLE DS_SETFONT | DS_MODALFRAME | WS_CAPTION | WS_SYSMENU
-CAPTION "Bingobobbi"
-FONT 8, "System", 0, 0, 0x0
-BEGIN
- LTEXT "Howdie dodie!",IDC_STATIC,49,10,119,8,SS_NOPREFIX
- LTEXT "Yo froodie!",IDC_STATIC,49,20,119,8
-END
-
-STRINGTABLE
-BEGIN
- IDS_SIMPLE "One"
- IDS_PLACEHOLDER "%s birds"
- IDS_PLACEHOLDERS "%d of %d"
- IDS_REORDERED_PLACEHOLDERS "$1 of $2"
- // Won't be in translations list because it has changed
- IDS_CHANGED "This was the old version"
- IDS_TWIN_1 "Hello"
- IDS_TWIN_2 "Hello"
- IDS_NOT_TRANSLATEABLE ":"
- IDS_LONGER_TRANSLATED "Removed document $1"
- // Won't appear in the list of translations because it's not in the .grd file
- IDS_NO_LONGER_USED "Not used"
- IDS_DIFFERENT_TWIN_1 "Howdie"
- IDS_DIFFERENT_TWIN_2 "Howdie"
-END \ No newline at end of file
diff --git a/tools/grit/grit/testdata/status.html b/tools/grit/grit/testdata/status.html
deleted file mode 100644
index 6b997b9..0000000
--- a/tools/grit/grit/testdata/status.html
+++ /dev/null
@@ -1,44 +0,0 @@
-[HEADER]
-<table cellspacing=0 cellPadding=0 width="100%" border=0>
-<tr bgcolor=#3399cc><td align=middle height=1><img height=1 width=1></td></tr>
-</table>
-<table cellspacing=0 cellPadding=1 width="100%" bgcolor=#e8f4f7 border=0>
-<tr><td height=20><font size=+1 color=#000000>&nbsp;<b>Desktop Search Status</b></font></td></tr>
-</table>
-<br>
-<center>
-[$~MESSAGE~$]
-<table cellspacing=0 cellPadding=6 width=500 border=0>
-<tr>
- <td>&nbsp;</td>
- <td align=right nowrap><i><font size=-1>Number of items</font></i></td>
- <td align=right nowrap><i><font size=-1>Time of newest item</font></i></td>
-</tr>
-<tr>
- <td width=1% nowrap><img style="vertical-align:middle" width=16 height=16 src=favicon.ico>&nbsp; Total searchable items</td>
- <td align=right><b>[TOTAL_COUNT]</b></td>
- <td align=right><b>[TOTAL_TIME]</b></td>
-</tr>
-<tr>
- <td><font size=-1>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<img style="vertical-align:middle" src=email.gif width=16 height=16>&nbsp; Emails</font></td>
- <td align=right><font size=-1>[EMAIL_COUNT]</font></td>
- <td align=right><font size=-1>[EMAIL_TIME]</font></td>
-</tr>
-<tr>
- <td><font size=-1>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<img style="vertical-align:middle" src="16x16_chat.gif" width=16 height=16>&nbsp; Chats</font></td>
- <td align=right><font size=-1>[IM_COUNT]</font></td>
- <td align=right><font size=-1>[IM_TIME]</font></td>
-</tr>
-<tr>
- <td><font size=-1>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<img style="vertical-align:middle" src=html.gif width=16 height=16>&nbsp; Web history</font></td>
- <td align=right><font size=-1>[WEB_COUNT]</font></td>
- <td align=right><font size=-1>[WEB_TIME]</font></td>
-</tr>
-<tr>
- <td><font size=-1>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<img style="vertical-align:middle" src=file.gif width=16 height=16>&nbsp; Files</font></td>
- <td align=right><font size=-1>[FILE_COUNT]</font></td>
- <td align=right><font size=-1>[FILE_TIME]</font></td>
-</tr>
-</table>
-</center>
-[FOOTER] \ No newline at end of file
diff --git a/tools/grit/grit/testdata/time_related.html b/tools/grit/grit/testdata/time_related.html
deleted file mode 100644
index ee64b16..0000000
--- a/tools/grit/grit/testdata/time_related.html
+++ /dev/null
@@ -1,11 +0,0 @@
-[HEADER]
-[CHROME]
-[NAV_PRE_POST]
-[$~MESSAGE~$]<br>
-<table border=0 cellpadding=2 cellspacing=0 width='100%'>
-[CONTENTS]
-</table><br>
-
-[NAV_PRE_POST]
-[FOOTER]
-
diff --git a/tools/grit/grit/testdata/toolbar_about.html b/tools/grit/grit/testdata/toolbar_about.html
deleted file mode 100644
index bb4b0eb..0000000
--- a/tools/grit/grit/testdata/toolbar_about.html
+++ /dev/null
@@ -1,138 +0,0 @@
-<html id=dlgAbout STYLE="width: 25.8em; height: 17em" [GRITDIR]>
-<head>
-<meta http-equiv="content-type" content="text/html; charset=utf-8">
-<title>About Google Toolbar</title>
-<style>
-.button {
- width: 7em;
- height: 2.2em;
- color: buttontext;
- font-family: MS Sans Serif;
- font-size:8pt;
- cursor: hand;
-}
-</style>
-
-<script> <!--
- function HandleError(message, url, line) {
- var L_Dialog_ErrorMessage = "An error has occured in this dialog.";
- var L_ErrorNumber_Text = "Error: ";
- var str = L_Dialog_ErrorMessage + "\n\n"
- + L_ErrorNumber_Text + line + "\n"
- + message;
- alert (str);
- window.close();
- return true;
- }
-
- function OnKeyPress(nCode) {
- if (nCode == 27) {
- window.close();
- return;
- }
- }
-
- function OnLoad() {
- if ((null != window.dialogArguments) && (window.dialogArguments.indexOf("&") == -1) && (window.dialogArguments.indexOf("<") == -1)) {
- version.innerHTML = window.dialogArguments;
- } else {
- version.innerText = "Version: Unknown";
- }
- }
-
- window.onerror = HandleError;
- // -->
-</script>
-
-</head>
-
-
-<body bgcolor="#FFFFFF" onload="OnLoad()" onkeydown="OnKeyPress(event.keyCode)" onkeypress="OnKeyPress(event.keyCode)" scroll=no>
-
-<table border=0>
-
- <tr height=5>
- <td width=5></td>
- <td></td>
- <td></td>
- <td></td>
- <td width=5></td>
- </tr>
-
- <tr>
- <td></td>
- <td colspan=3>
-
-
-<table border="0" cellpadding="0" cellspacing="0" valign="top">
- <tr>
- <td valign="top" height="47" width="155">
- <div align="center"><img src="title_toolbar.gif" width="275" height="59" alt="Google Toolbar"></div>
- </td>
- <td valign="middle" height="47" width="713">
- <hr size=1 color=25479D></td></tr>
-</table>
-
-
- </td>
- <!--
- <TD colspan=2>
- <span style="COLOR: black; FONT: 18pt Tahoma, MS Shell Dlg"><b>
- Google Toolbar&trade;</b>
- </span>
- </TD>
- -->
- <td valign="middle">
- </td>
- </tr>
-
- <tr>
- <td></td>
- <td align=center><img src="googly.gif"></td>
- <td colspan=2 align=left>
- <span style="WIDTH: 25em; height:6em COLOR: black; FONT: 8pt Tahoma, MS Shell Dlg">
- <span id=version></span><br>
- </span>
- </td>
- <td></td>
- </tr>
-
- <tr height=50>
- <td></td>
- <td></td>
- <td colspan=2 align=left>
- <span style="WIDTH: 25em; height:6em COLOR: black; FONT: 8pt Tahoma, MS Shell Dlg">
- <!--$/translate-->
- <i>De parvis grandis acervus erit</i>
- <!--$translate-->
- </span>
- </td>
- <td></td>
- </tr>
-
- <tr height=40>
- <td></td>
- <td></td>
- <td></td>
- <td></td>
- <td></td>
- </tr>
-
- <tr>
- <td></td>
- <td width=80></td>
- <td>
- <!--$/translate-->
- <span style="WIDTH: 20em; COLOR: black; FONT: 8pt Tahoma, MS Shell Dlg" id="copyright">&copy; 2006 Google</span>
- <!--$translate-->
- </td>
- <td id=ok-button align=right><button tabindex=1 type=submit align=right id="okButton" class=button onClick="window.close();" >OK</button>
- </td>
- <td></td>
- </tr>
-
-</table>
-</span>
-
-</body>
-</html>
diff --git a/tools/grit/grit/testdata/tools/grit/resource_ids b/tools/grit/grit/testdata/tools/grit/resource_ids
deleted file mode 100644
index d8f71ff..0000000
--- a/tools/grit/grit/testdata/tools/grit/resource_ids
+++ /dev/null
@@ -1,175 +0,0 @@
-# Copyright (c) 2011 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.
-#
-# This file is used to assign starting resource ids for resources and strings
-# used by Chromium. This is done to ensure that resource ids are unique
-# across all the grd files. If you are adding a new grd file, please add
-# a new entry to this file.
-#
-# The first entry in the file, SRCDIR, is special: It is a relative path from
-# this file to the base of your checkout.
-#
-# http://msdn.microsoft.com/en-us/library/t2zechd4(VS.71).aspx says that the
-# range for IDR_ is 1 to 28,671 and the range for IDS_ is 1 to 32,767 and
-# common convention starts practical use of IDs at 100 or 101.
-{
- "SRCDIR": "../..",
-
- "chrome/browser/browser_resources.grd": {
- "includes": [500],
- },
- "chrome/browser/resources/component_extension_resources.grd": {
- "includes": [1000],
- },
- "chrome/browser/resources/net_internals_resources.grd": {
- "includes": [1500],
- },
- "chrome/browser/resources/shared_resources.grd": {
- "includes": [2000],
- },
- "chrome/common/common_resources.grd": {
- "includes": [2500],
- },
- "chrome/default_plugin/default_plugin_resources.grd": {
- "includes": [3000],
- },
- "chrome/renderer/renderer_resources.grd": {
- "includes": [3500],
- },
- "net/base/net_resources.grd": {
- "includes": [4000],
- },
- "webkit/glue/webkit_resources.grd": {
- "includes": [4500],
- },
- "webkit/tools/test_shell/test_shell_resources.grd": {
- "includes": [5000],
- },
- "ui/resources/ui_resources.grd": {
- "includes": [5500],
- },
- "chrome/app/theme/theme_resources.grd": {
- "includes": [6000],
- },
- "chrome_frame/resources/chrome_frame_resources.grd": {
- "includes": [6500],
- },
- # WebKit.grd can be in two different places depending on whether we are
- # in a chromium checkout or a webkit-only checkout.
- "third_party/WebKit/Source/WebKit/chromium/WebKit.grd": {
- "includes": [7000],
- },
- "WebKit.grd": {
- "includes": [7000],
- },
-
- "ui/base/strings/app_locale_settings.grd": {
- "messages": [7500],
- },
- "chrome/app/resources/locale_settings.grd": {
- "includes": [8000],
- "messages": [8500],
- },
- # These each start with the same resource id because we only use one
- # file for each build (cros, linux, mac, or win).
- "chrome/app/resources/locale_settings_cros.grd": {
- "messages": [9000],
- },
- "chrome/app/resources/locale_settings_linux.grd": {
- "messages": [9000],
- },
- "chrome/app/resources/locale_settings_mac.grd": {
- "messages": [9000],
- },
- "chrome/app/resources/locale_settings_win.grd": {
- "messages": [9000],
- },
-
- "ui/base/strings/ui_strings.grd": {
- "messages": [9500],
- },
- # Chromium strings and Google Chrome strings must start at the same id.
- # We only use one file depending on whether we're building Chromium or
- # Google Chrome.
- "chrome/app/chromium_strings.grd": {
- "messages": [10000],
- },
- "chrome/app/google_chrome_strings.grd": {
- "messages": [10000],
- },
- # Leave lots of space for generated_resources since it has most of our
- # strings.
- "chrome/app/generated_resources.grd": {
- "structures": [10500],
- "messages": [11000],
- },
- # The chrome frame dialogs are also in generated_resources.grd so they
- # get included by the translation console. We make sure that the ids
- # for structures here are the same as for generated_resources.grd.
- "chrome_frame/resources/chrome_frame_dialogs.grd": {
- "structures": [10500],
- "includes": [10750],
- },
- "webkit/glue/inspector_strings.grd": {
- "messages": [16000],
- },
- "webkit/glue/webkit_strings.grd": {
- "messages": [16500],
- },
-
- "chrome_frame/resources/chrome_frame_resources.grd": {
- "includes": [17500],
- "structures": [18000],
- },
-
- "ui/gfx/gfx_resources.grd": {
- "includes": [18500],
- },
-
- "chrome/app/policy/policy_templates.grd": {
- "structures": [19000],
- "messages": [19010],
- },
-
- "chrome/browser/autofill/autofill_resources.grd": {
- "messages": [19500],
- },
- "chrome/browser/resources/sync_internals_resources.grd": {
- "includes": [20000],
- },
- # This file is generated during the build.
- "<(SHARED_INTERMEDIATE_DIR)/devtools/devtools_resources.grd": {
- "includes": [20500],
- },
- # All standard and large theme resources should have the same IDs.
- "chrome/app/theme/theme_resources_standard.grd": {
- "includes": [21000],
- },
- "chrome/app/theme/theme_resources_large.grd": {
- "includes": [21000],
- },
- # This file is generated during the build.
- "chrome/browser/debugger/frontend/devtools_frontend_resources.grd": {
- "includes": [21500],
- },
- "chrome/browser/resources/options_resources.grd": {
- "includes": [22000],
- },
- "cloud_print/virtual_driver/win/install/virtual_driver_setup_resources.grd": {
- "messages": [22500],
- },
- "chrome/browser/resources/quota_internals_resources.grd": {
- "includes": [23000],
- },
- "chrome/browser/resources/workers_resources.grd": {
- "includes": [23500],
- },
- # All standard and large theme resources should have the same IDs.
- "ui/resources/ui_resources_standard.grd": {
- "includes": [24000],
- },
- "ui/resources/ui_resources_large.grd": {
- "includes": [24000],
- },
-}
diff --git a/tools/grit/grit/testdata/transl.rc b/tools/grit/grit/testdata/transl.rc
deleted file mode 100644
index 0b327c6..0000000
--- a/tools/grit/grit/testdata/transl.rc
+++ /dev/null
@@ -1,56 +0,0 @@
-IDC_KLONKMENU MENU
-BEGIN
- POPUP "&Skra"
- BEGIN
- MENUITEM "&Haetta", IDM_EXIT
- MENUITEM "Thetta er ""Klonk"" sem eg fyla", ID_FILE_THISBE
- POPUP "gonkurinn"
- BEGIN
- MENUITEM "Klonk && er ""gott""", ID_GONK_KLONKIS
- END
- END
- POPUP "&Hjalp"
- BEGIN
- MENUITEM "&Um...", IDM_ABOUT
- END
-END
-
-IDD_ABOUTBOX DIALOGEX 22, 17, 230, 75
-STYLE DS_SETFONT | DS_MODALFRAME | WS_CAPTION | WS_SYSMENU
-CAPTION "Um Klonk"
-FONT 8, "System", 0, 0, 0x0
-BEGIN
- ICON IDI_KLONK,IDC_MYICON,14,9,20,20
- LTEXT "klonk utgafa ""jibbi"" 1.0",IDC_STATIC,49,10,119,8,
- SS_NOPREFIX
- LTEXT "Hofundarrettur (C) 2005",IDC_STATIC,49,20,119,8
- DEFPUSHBUTTON "I lagi",IDOK,195,6,30,11,WS_GROUP
- CONTROL "Jack ""Black"" Daniels",IDC_RADIO1,"Button",
- BS_AUTORADIOBUTTON,46,51,84,10
-END
-
-IDD_DIFFERENT_LENGTH_IN_TRANSL DIALOGEX 22, 17, 230, 75
-STYLE DS_SETFONT | DS_MODALFRAME | WS_CAPTION | WS_SYSMENU
-CAPTION "Bingobobbi"
-FONT 8, "System", 0, 0, 0x0
-BEGIN
- LTEXT "Howdie dodie!",IDC_STATIC,49,10,119,8,SS_NOPREFIX
-END
-
-STRINGTABLE
-BEGIN
- IDS_SIMPLE "Ein"
- IDS_PLACEHOLDER "%s Vogeln"
- IDS_PLACEHOLDERS "%d von %d"
- // Shouldn't be part of translations list because the translation is
- // reordered so placeholder fixup fails
- IDS_REORDERED_PLACEHOLDERS "$2 auf $1"
- IDS_CHANGED "Dass war die alte Version"
- IDS_TWIN_1 "Hallo"
- IDS_TWIN_2 "Hallo"
- IDS_NOT_TRANSLATEABLE ":"
- IDS_LONGER_TRANSLATED "Dokument $1 ist entfernt worden"
- IDS_NO_LONGER_USED "Nicht verwendet"
- IDS_DIFFERENT_TWIN_1 "Howdie"
- IDS_DIFFERENT_TWIN_2 "Hallo sagt man"
-END \ No newline at end of file
diff --git a/tools/grit/grit/testdata/versions.html b/tools/grit/grit/testdata/versions.html
deleted file mode 100644
index d1f40d8..0000000
--- a/tools/grit/grit/testdata/versions.html
+++ /dev/null
@@ -1,7 +0,0 @@
-[HEADER]
-
-[TOP_CHROME]
-[CONTENTS]
-
-[NEXT_PREV]
-[FOOTER]
diff --git a/tools/grit/grit/tool/__init__.py b/tools/grit/grit/tool/__init__.py
deleted file mode 100644
index 043bda7..0000000
--- a/tools/grit/grit/tool/__init__.py
+++ /dev/null
@@ -1,10 +0,0 @@
-#!/usr/bin/python2.4
-# Copyright (c) 2006-2008 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.
-
-'''Package grit.tool
-'''
-
-pass
-
diff --git a/tools/grit/grit/tool/build.py b/tools/grit/grit/tool/build.py
deleted file mode 100644
index 635cc41..0000000
--- a/tools/grit/grit/tool/build.py
+++ /dev/null
@@ -1,300 +0,0 @@
-#!/usr/bin/python2.4
-# Copyright (c) 2011 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.
-
-'''The 'grit build' tool along with integration for this tool with the
-SCons build system.
-'''
-
-import filecmp
-import getopt
-import os
-import shutil
-import sys
-import types
-
-from grit import grd_reader
-from grit import util
-from grit.tool import interface
-from grit import shortcuts
-
-
-def ParseDefine(define):
- '''Parses a define that is either like "NAME" or "NAME=VAL" and
- returns its components, using True as the default value. Values of
- "1" and "0" are transformed to True and False respectively.
- '''
- parts = [part.strip() for part in define.split('=')]
- assert len(parts) >= 1
- name = parts[0]
- val = True
- if len(parts) > 1:
- val = parts[1]
- if val == "1": val = True
- elif val == "0": val = False
- return (name, val)
-
-
-class RcBuilder(interface.Tool):
- '''A tool that builds RC files and resource header files for compilation.
-
-Usage: grit build [-o OUTPUTDIR] [-D NAME[=VAL]]*
-
-All output options for this tool are specified in the input file (see
-'grit help' for details on how to specify the input file - it is a global
-option).
-
-Options:
-
- -o OUTPUTDIR Specify what directory output paths are relative to.
- Defaults to the current directory.
-
- -D NAME[=VAL] Specify a C-preprocessor-like define NAME with optional
- value VAL (defaults to 1) which will be used to control
- conditional inclusion of resources.
-
- -E NAME=VALUE Set environment variable NAME to VALUE (within grit).
-
- -f FIRSTIDFILE Path to a python file that specifies the first id of
- value to use for resources. Defaults to the file
- resources_ids next to grit.py. Set to an empty string
- if you don't want to use a first id file.
-
- -w WHITELISTFILE Path to a file containing the string names of the
- resources to include. Anything not listed is dropped.
-
-
-Conditional inclusion of resources only affects the output of files which
-control which resources get linked into a binary, e.g. it affects .rc files
-meant for compilation but it does not affect resource header files (that define
-IDs). This helps ensure that values of IDs stay the same, that all messages
-are exported to translation interchange files (e.g. XMB files), etc.
-'''
-
- def ShortDescription(self):
- return 'A tool that builds RC files for compilation.'
-
- def Run(self, opts, args):
- self.output_directory = '.'
- first_id_filename = None
- whitelist_filenames = []
- (own_opts, args) = getopt.getopt(args, 'o:D:E:f:w:')
- for (key, val) in own_opts:
- if key == '-o':
- self.output_directory = val
- elif key == '-D':
- name, val = ParseDefine(val)
- self.defines[name] = val
- elif key == '-E':
- (env_name, env_value) = val.split('=')
- os.environ[env_name] = env_value
- elif key == '-f':
- first_id_filename = val
- elif key == '-w':
- whitelist_filenames.append(val)
-
- if len(args):
- print "This tool takes no tool-specific arguments."
- return 2
- self.SetOptions(opts)
- if self.scons_targets:
- self.VerboseOut('Using SCons targets to identify files to output.\n')
- else:
- self.VerboseOut('Output directory: %s (absolute path: %s)\n' %
- (self.output_directory,
- os.path.abspath(self.output_directory)))
-
- if whitelist_filenames:
- self.whitelist_names = set()
- for whitelist_filename in whitelist_filenames:
- self.VerboseOut('Using whitelist: %s\n' % whitelist_filename);
- whitelist_file = open(whitelist_filename)
- self.whitelist_names |= set(whitelist_file.read().strip().split('\n'))
- whitelist_file.close()
-
- self.res = grd_reader.Parse(opts.input, first_id_filename=first_id_filename,
- debug=opts.extra_verbose, defines=self.defines)
- self.res.RunGatherers(recursive = True)
- self.Process()
- return 0
-
- def __init__(self):
- # Default file-creation function is built-in file(). Only done to allow
- # overriding by unit test.
- self.fo_create = file
-
- # key/value pairs of C-preprocessor like defines that are used for
- # conditional output of resources
- self.defines = {}
-
- # self.res is a fully-populated resource tree if Run()
- # has been called, otherwise None.
- self.res = None
-
- # Set to a list of filenames for the output nodes that are relative
- # to the current working directory. They are in the same order as the
- # output nodes in the file.
- self.scons_targets = None
-
- # The set of names that are whitelisted to actually be included in the
- # output.
- self.whitelist_names = None
-
-
- # static method
- def AddWhitelistTags(start_node, whitelist_names):
- # Walk the tree of nodes added attributes for the nodes that shouldn't
- # be written into the target files (skip markers).
- from grit.node import include
- from grit.node import message
- for node in start_node.inorder():
- # Same trick data_pack.py uses to see what nodes actually result in
- # real items.
- if (isinstance(node, include.IncludeNode) or
- isinstance(node, message.MessageNode)):
- text_ids = node.GetTextualIds()
- # Mark the item to be skipped if it wasn't in the whitelist.
- if text_ids and not text_ids[0] in whitelist_names:
- node.SetWhitelistMarkedAsSkip(True)
- AddWhitelistTags = staticmethod(AddWhitelistTags)
-
- # static method
- def ProcessNode(node, output_node, outfile):
- '''Processes a node in-order, calling its formatter before and after
- recursing to its children.
-
- Args:
- node: grit.node.base.Node subclass
- output_node: grit.node.io.File
- outfile: open filehandle
- '''
- # See if the node should be skipped by a whitelist.
- # Note: Some Format calls have side effects, so Format is always called
- # and the whitelist is used to only avoid the output.
- should_write = not node.WhitelistMarkedAsSkip()
-
- base_dir = util.dirname(output_node.GetOutputFilename())
-
- try:
- formatter = node.ItemFormatter(output_node.GetType())
- if formatter:
- formatted = formatter.Format(node, output_node.GetLanguage(),
- begin_item=True, output_dir=base_dir)
- if should_write:
- outfile.write(formatted)
- except:
- print u"Error processing node %s" % unicode(node)
- raise
-
- for child in node.children:
- RcBuilder.ProcessNode(child, output_node, outfile)
-
- try:
- if formatter:
- formatted = formatter.Format(node, output_node.GetLanguage(),
- begin_item=False, output_dir=base_dir)
- if should_write:
- outfile.write(formatted)
- except:
- print u"Error processing node %s" % unicode(node)
- raise
- ProcessNode = staticmethod(ProcessNode)
-
-
- def Process(self):
- # Update filenames with those provided by SCons if we're being invoked
- # from SCons. The list of SCons targets also includes all <structure>
- # node outputs, but it starts with our output files, in the order they
- # occur in the .grd
- if self.scons_targets:
- assert len(self.scons_targets) >= len(self.res.GetOutputFiles())
- outfiles = self.res.GetOutputFiles()
- for ix in range(len(outfiles)):
- outfiles[ix].output_filename = os.path.abspath(
- self.scons_targets[ix])
- else:
- for output in self.res.GetOutputFiles():
- output.output_filename = os.path.abspath(os.path.join(
- self.output_directory, output.GetFilename()))
-
- # If there are whitelisted names, tag the tree once up front, this way
- # while looping through the actual output, it is just an attribute check.
- if self.whitelist_names:
- self.AddWhitelistTags(self.res, self.whitelist_names)
-
- for output in self.res.GetOutputFiles():
- self.VerboseOut('Creating %s...' % output.GetFilename())
-
- # Microsoft's RC compiler can only deal with single-byte or double-byte
- # files (no UTF-8), so we make all RC files UTF-16 to support all
- # character sets.
- if output.GetType() in ('rc_header', 'resource_map_header',
- 'resource_map_source', 'resource_file_map_source'):
- encoding = 'cp1252'
- elif output.GetType() in ('js_map_format', 'plist', 'plist_strings',
- 'doc', 'json'):
- encoding = 'utf_8'
- else:
- # TODO(gfeher) modify here to set utf-8 encoding for admx/adml
- encoding = 'utf_16'
-
- # Make the output directory if it doesn't exist.
- outdir = os.path.split(output.GetOutputFilename())[0]
- if not os.path.exists(outdir):
- os.makedirs(outdir)
- # Write the results to a temporary file and only overwrite the original
- # if the file changed. This avoids unnecessary rebuilds.
- outfile = self.fo_create(output.GetOutputFilename() + '.tmp', 'wb')
-
- if output.GetType() != 'data_package':
- outfile = util.WrapOutputStream(outfile, encoding)
-
- # Set the context, for conditional inclusion of resources
- self.res.SetOutputContext(output.GetLanguage(), self.defines)
-
- # TODO(joi) Handle this more gracefully
- import grit.format.rc_header
- grit.format.rc_header.Item.ids_ = {}
-
- # Iterate in-order through entire resource tree, calling formatters on
- # the entry into a node and on exit out of it.
- self.ProcessNode(self.res, output, outfile)
- outfile.close()
-
- # Now copy from the temp file back to the real output, but on Windows,
- # only if the real output doesn't exist or the contents of the file
- # changed. This prevents identical headers from being written and .cc
- # files from recompiling (which is painful on Windows).
- if not os.path.exists(output.GetOutputFilename()):
- os.rename(output.GetOutputFilename() + '.tmp',
- output.GetOutputFilename())
- else:
- # CHROMIUM SPECIFIC CHANGE.
- # This clashes with gyp + vstudio, which expect the output timestamp
- # to change on a rebuild, even if nothing has changed.
- #files_match = filecmp.cmp(output.GetOutputFilename(),
- # output.GetOutputFilename() + '.tmp')
- #if (output.GetType() != 'rc_header' or not files_match
- # or sys.platform != 'win32'):
- shutil.copy2(output.GetOutputFilename() + '.tmp',
- output.GetOutputFilename())
- os.remove(output.GetOutputFilename() + '.tmp')
-
- self.VerboseOut(' done.\n')
-
- # Print warnings if there are any duplicate shortcuts.
- warnings = shortcuts.GenerateDuplicateShortcutsWarnings(
- self.res.UberClique(), self.res.GetTcProject())
- if warnings:
- print '\n'.join(warnings)
-
- # Print out any fallback warnings, and missing translation errors, and
- # exit with an error code if there are missing translations in a non-pseudo
- # and non-official build.
- warnings = (self.res.UberClique().MissingTranslationsReport().
- encode('ascii', 'replace'))
- if warnings and self.defines.get('_google_chrome', False):
- print warnings
- if self.res.UberClique().HasMissingTranslations():
- sys.exit(-1)
diff --git a/tools/grit/grit/tool/count.py b/tools/grit/grit/tool/count.py
deleted file mode 100644
index 52e6bbe..0000000
--- a/tools/grit/grit/tool/count.py
+++ /dev/null
@@ -1,44 +0,0 @@
-#!/usr/bin/python2.4
-# Copyright (c) 2006-2008 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.
-
-'''Count number of occurrences of a given message ID
-'''
-
-import getopt
-import os
-import types
-
-from grit.tool import interface
-from grit import grd_reader
-from grit import util
-
-from grit.extern import tclib
-
-
-class CountMessage(interface.Tool):
- '''Count the number of times a given message ID is used.
-'''
-
- def __init__(self):
- pass
-
- def ShortDescription(self):
- return 'Exports all translateable messages into an XMB file.'
-
- def Run(self, opts, args):
- self.SetOptions(opts)
-
- id = args[0]
- res_tree = grd_reader.Parse(opts.input, debug=opts.extra_verbose)
- res_tree.OnlyTheseTranslations([])
- res_tree.RunGatherers(True)
-
- count = 0
- for c in res_tree.UberClique().AllCliques():
- if c.GetId() == id:
- count += 1
-
- print "There are %d occurrences of message %s." % (count, id)
-
diff --git a/tools/grit/grit/tool/diff_structures.py b/tools/grit/grit/tool/diff_structures.py
deleted file mode 100644
index b4d6b624..0000000
--- a/tools/grit/grit/tool/diff_structures.py
+++ /dev/null
@@ -1,114 +0,0 @@
-#!/usr/bin/python2.4
-# Copyright (c) 2006-2008 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.
-
-'''The 'grit sdiff' tool.
-'''
-
-import os
-import getopt
-import tempfile
-
-from grit.node import structure
-from grit.tool import interface
-
-from grit import constants
-from grit import util
-
-# Builds the description for the tool (used as the __doc__
-# for the DiffStructures class).
-_class_doc = """\
-Allows you to view the differences in the structure of two files,
-disregarding their translateable content. Translateable portions of
-each file are changed to the string "TTTTTT" before invoking the diff program
-specified by the P4DIFF environment variable.
-
-Usage: grit sdiff [-t TYPE] [-s SECTION] [-e ENCODING] LEFT RIGHT
-
-LEFT and RIGHT are the files you want to diff. SECTION is required
-for structure types like 'dialog' to identify the part of the file to look at.
-ENCODING indicates the encoding of the left and right files (default 'cp1252').
-TYPE can be one of the following, defaults to 'tr_html':
-"""
-for gatherer in structure._GATHERERS:
- _class_doc += " - %s\n" % gatherer
-
-
-class DiffStructures(interface.Tool):
- __doc__ = _class_doc
-
- def __init__(self):
- self.section = None
- self.left_encoding = 'cp1252'
- self.right_encoding = 'cp1252'
- self.structure_type = 'tr_html'
-
- def ShortDescription(self):
- return 'View differences without regard for translateable portions.'
-
- def Run(self, global_opts, args):
- (opts, args) = getopt.getopt(args, 's:e:t:',
- ['left_encoding=', 'right_encoding='])
- for key, val in opts:
- if key == '-s':
- self.section = val
- elif key == '-e':
- self.left_encoding = val
- self.right_encoding = val
- elif key == '-t':
- self.structure_type = val
- elif key == '--left_encoding':
- self.left_encoding = val
- elif key == '--right_encoding':
- self.right_encoding == val
-
- if len(args) != 2:
- print "Incorrect usage - 'grit help sdiff' for usage details."
- return 2
-
- if 'P4DIFF' not in os.environ:
- print "Environment variable P4DIFF not set; defaulting to 'windiff'."
- diff_program = 'windiff'
- else:
- diff_program = os.environ['P4DIFF']
-
- left_trans = self.MakeStaticTranslation(args[0], self.left_encoding)
- try:
- try:
- right_trans = self.MakeStaticTranslation(args[1], self.right_encoding)
-
- os.system('%s %s %s' % (diff_program, left_trans, right_trans))
- finally:
- os.unlink(right_trans)
- finally:
- os.unlink(left_trans)
-
- def MakeStaticTranslation(self, original_filename, encoding):
- """Given the name of the structure type (self.structure_type), the filename
- of the file holding the original structure, and optionally the "section" key
- identifying the part of the file to look at (self.section), creates a
- temporary file holding a "static" translation of the original structure
- (i.e. one where all translateable parts have been replaced with "TTTTTT")
- and returns the temporary file name. It is the caller's responsibility to
- delete the file when finished.
-
- Args:
- original_filename: 'c:\\bingo\\bla.rc'
-
- Return:
- 'c:\\temp\\werlkjsdf334.tmp'
- """
- original = structure._GATHERERS[self.structure_type].FromFile(
- original_filename, extkey=self.section, encoding=encoding)
- original.Parse()
- translated = original.Translate(constants.CONSTANT_LANGUAGE, False)
-
- fname = tempfile.mktemp()
- fhandle = file(fname, 'w')
- writer = util.WrapOutputStream(fhandle)
- writer.write("Original filename: %s\n=============\n\n" % original_filename)
- writer.write(translated) # write in UTF-8
- fhandle.close()
-
- return fname
diff --git a/tools/grit/grit/tool/interface.py b/tools/grit/grit/tool/interface.py
deleted file mode 100644
index 8470b37..0000000
--- a/tools/grit/grit/tool/interface.py
+++ /dev/null
@@ -1,59 +0,0 @@
-#!/usr/bin/python2.4
-# Copyright (c) 2006-2008 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.
-
-'''Base class and interface for tools.
-'''
-
-import sys
-
-class Tool(object):
- '''Base class for all tools. Tools should use their docstring (i.e. the
- class-level docstring) for the help they want to have printed when they
- are invoked.'''
-
- #
- # Interface (abstract methods)
- #
-
- def ShortDescription(self):
- '''Returns a short description of the functionality of the tool.'''
- raise NotImplementedError()
-
- def Run(self, global_options, my_arguments):
- '''Runs the tool.
-
- Args:
- global_options: object grit_runner.Options
- my_arguments: [arg1 arg2 ...]
-
- Return:
- 0 for success, non-0 for error
- '''
- raise NotImplementedError()
-
- #
- # Base class implementation
- #
-
- def __init__(self):
- self.o = None
-
- def SetOptions(self, opts):
- self.o = opts
-
- def Out(self, text):
- '''Always writes out 'text'.'''
- self.o.output_stream.write(text)
-
- def VerboseOut(self, text):
- '''Writes out 'text' if the verbose option is on.'''
- if self.o.verbose:
- self.o.output_stream.write(text)
-
- def ExtraVerboseOut(self, text):
- '''Writes out 'text' if the extra-verbose option is on.
- '''
- if self.o.extra_verbose:
- self.o.output_stream.write(text)
diff --git a/tools/grit/grit/tool/menu_from_parts.py b/tools/grit/grit/tool/menu_from_parts.py
deleted file mode 100644
index 7fa77b6..0000000
--- a/tools/grit/grit/tool/menu_from_parts.py
+++ /dev/null
@@ -1,84 +0,0 @@
-#!/usr/bin/python2.4
-# Copyright (c) 2006-2008 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.
-
-'''The 'grit menufromparts' tool.'''
-
-import os
-import getopt
-import types
-
-from grit.tool import interface
-from grit.tool import transl2tc
-from grit import grd_reader
-from grit import tclib
-from grit import util
-from grit import xtb_reader
-
-
-import grit.extern.tclib
-
-
-class MenuTranslationsFromParts(interface.Tool):
- '''One-off tool to generate translated menu messages (where each menu is kept
-in a single message) based on existing translations of the individual menu
-items. Was needed when changing menus from being one message per menu item
-to being one message for the whole menu.'''
-
- def ShortDescription(self):
- return ('Create translations of whole menus from existing translations of '
- 'menu items.')
-
- def Run(self, globopt, args):
- self.SetOptions(globopt)
- assert len(args) == 2, "Need exactly two arguments, the XTB file and the output file"
-
- xtb_file = args[0]
- output_file = args[1]
-
- grd = grd_reader.Parse(self.o.input, debug=self.o.extra_verbose)
- grd.OnlyTheseTranslations([]) # don't load translations
- grd.RunGatherers(recursive = True)
-
- xtb = {}
- def Callback(msg_id, parts):
- msg = []
- for part in parts:
- if part[0]:
- msg = []
- break # it had a placeholder so ignore it
- else:
- msg.append(part[1])
- if len(msg):
- xtb[msg_id] = ''.join(msg)
- f = file(xtb_file)
- xtb_reader.Parse(f, Callback)
- f.close()
-
- translations = [] # list of translations as per transl2tc.WriteTranslations
- for node in grd:
- if node.name == 'structure' and node.attrs['type'] == 'menu':
- assert len(node.GetCliques()) == 1
- message = node.GetCliques()[0].GetMessage()
- translation = []
-
- contents = message.GetContent()
- for part in contents:
- if isinstance(part, types.StringTypes):
- id = grit.extern.tclib.GenerateMessageId(part)
- if id not in xtb:
- print "WARNING didn't find all translations for menu %s" % node.attrs['name']
- translation = []
- break
- translation.append(xtb[id])
- else:
- translation.append(part.GetPresentation())
-
- if len(translation):
- translations.append([message.GetId(), ''.join(translation)])
-
- f = util.WrapOutputStream(file(output_file, 'w'))
- transl2tc.TranslationToTc.WriteTranslations(f, translations)
- f.close()
-
diff --git a/tools/grit/grit/tool/newgrd.py b/tools/grit/grit/tool/newgrd.py
deleted file mode 100644
index 060f29b..0000000
--- a/tools/grit/grit/tool/newgrd.py
+++ /dev/null
@@ -1,71 +0,0 @@
-#!/usr/bin/python2.4
-# Copyright (c) 2006-2008 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.
-
-'''Tool to create a new, empty .grd file with all the basic sections.
-'''
-
-from grit.tool import interface
-from grit import constants
-from grit import util
-
-# The contents of the new .grd file
-_FILE_CONTENTS = '''\
-<?xml version="1.0" encoding="UTF-8"?>
-<grit base_dir="." latest_public_release="0" current_release="1"
- source_lang_id="en" enc_check="%s">
- <outputs>
- <!-- TODO add each of your output files. Modify the three below, and add
- your own for your various languages. See the user's guide for more
- details.
- Note that all output references are relative to the output directory
- which is specified at build time. -->
- <output filename="resource.h" type="rc_header" />
- <output filename="en_resource.rc" type="rc_all" />
- <output filename="fr_resource.rc" type="rc_all" />
- </outputs>
- <translations>
- <!-- TODO add references to each of the XTB files (from the Translation
- Console) that contain translations of messages in your project. Each
- takes a form like <file path="english.xtb" />. Remember that all file
- references are relative to this .grd file. -->
- </translations>
- <release seq="1">
- <includes>
- <!-- TODO add a list of your included resources here, e.g. BMP and GIF
- resources. -->
- </includes>
- <structures>
- <!-- TODO add a list of all your structured resources here, e.g. HTML
- templates, menus, dialogs etc. Note that for menus, dialogs and version
- information resources you reference an .rc file containing them.-->
- </structures>
- <messages>
- <!-- TODO add all of your "string table" messages here. Remember to
- change nontranslateable parts of the messages into placeholders (using the
- <ph> element). You can also use the 'grit add' tool to help you identify
- nontranslateable parts and create placeholders for them. -->
- </messages>
- </release>
-</grit>''' % constants.ENCODING_CHECK
-
-
-class NewGrd(interface.Tool):
- '''Usage: grit newgrd OUTPUT_FILE
-
-Creates a new, empty .grd file OUTPUT_FILE with comments about what to put
-where in the file.'''
-
- def ShortDescription(self):
- return 'Create a new empty .grd file.'
-
- def Run(self, global_options, my_arguments):
- if not len(my_arguments) == 1:
- print 'This tool requires exactly one argument, the name of the output file.'
- return 2
- filename = my_arguments[0]
- out = util.WrapOutputStream(file(filename, 'w'), 'utf-8')
- out.write(_FILE_CONTENTS)
- out.close()
- print "Wrote file %s" % filename
diff --git a/tools/grit/grit/tool/postprocess_interface.py b/tools/grit/grit/tool/postprocess_interface.py
deleted file mode 100644
index c0381ee..0000000
--- a/tools/grit/grit/tool/postprocess_interface.py
+++ /dev/null
@@ -1,33 +0,0 @@
-#!/usr/bin/python2.4
-# Copyright (c) 2006-2008 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.
-
-''' Base class for postprocessing of RC files.
-'''
-
-import sys
-
-class PostProcessor(object):
- ''' Base class for postprocessing of the RC file data before being
- output through the RC2GRD tool. You should implement this class if
- you want GRIT to do specific things to the RC files after it has
- converted the data into GRD format, i.e. change the content of the
- RC file, and put it into a P4 changelist, etc.'''
-
-
- def Process(self, rctext, rcpath, grdnode):
- ''' Processes the data in rctext and grdnode.
- Args:
- rctext: string containing the contents of the RC file being processed.
- rcpath: the path used to access the file.
- grdtext: the root node of the grd xml data generated by
- the rc2grd tool.
-
- Return:
- The root node of the processed GRD tree.
- '''
- raise NotImplementedError()
-
-
-
diff --git a/tools/grit/grit/tool/postprocess_unittest.py b/tools/grit/grit/tool/postprocess_unittest.py
deleted file mode 100644
index e408e74..0000000
--- a/tools/grit/grit/tool/postprocess_unittest.py
+++ /dev/null
@@ -1,63 +0,0 @@
-#!/usr/bin/python2.4
-# Copyright (c) 2006-2008 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.
-
-'''Unit test that checks postprocessing of files.
- Tests postprocessing by having the postprocessor
- modify the grd data tree, changing the message name attributes.
-'''
-
-import os
-import re
-import sys
-if __name__ == '__main__':
- sys.path.append(os.path.join(os.path.dirname(sys.argv[0]), '..'))
-
-import unittest
-
-import grit.tool.postprocess_interface
-from grit.tool import rc2grd
-
-
-class PostProcessingUnittest(unittest.TestCase):
-
- def testPostProcessing(self):
- rctext = '''STRINGTABLE
-BEGIN
- DUMMY_STRING_1 "String 1"
- // Some random description
- DUMMY_STRING_2 "This text was added during preprocessing"
-END
- '''
- tool = rc2grd.Rc2Grd()
- class DummyOpts(object):
- verbose = False
- extra_verbose = False
- tool.o = DummyOpts()
- tool.post_process = 'grit.tool.postprocess_unittest.DummyPostProcessor'
- result = tool.Process(rctext, '.\resource.rc')
-
- self.failUnless(
- result.children[2].children[2].children[0].attrs['name'] == 'SMART_STRING_1')
- self.failUnless(
- result.children[2].children[2].children[1].attrs['name'] == 'SMART_STRING_2')
-
-class DummyPostProcessor(grit.tool.postprocess_interface.PostProcessor):
- '''
- Post processing replaces all message name attributes containing "DUMMY" to
- "SMART".
- '''
- def Process(self, rctext, rcpath, grdnode):
- smarter = re.compile(r'(DUMMY)(.*)')
- messages = grdnode.children[2].children[2]
- for node in messages.children:
- name_attr = node.attrs['name']
- m = smarter.search(name_attr)
- if m:
- node.attrs['name'] = 'SMART' + m.group(2)
- return grdnode
-
-if __name__ == '__main__':
- unittest.main()
-
diff --git a/tools/grit/grit/tool/preprocess_interface.py b/tools/grit/grit/tool/preprocess_interface.py
deleted file mode 100644
index 6d4166a..0000000
--- a/tools/grit/grit/tool/preprocess_interface.py
+++ /dev/null
@@ -1,29 +0,0 @@
-#!/usr/bin/python2.4
-# Copyright (c) 2006-2008 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.
-
-''' Base class for preprocessing of RC files.
-'''
-
-import sys
-
-class PreProcessor(object):
- ''' Base class for preprocessing of the RC file data before being
- output through the RC2GRD tool. You should implement this class if
- you have specific constructs in your RC files that GRIT cannot handle.'''
-
-
- def Process(self, rctext, rcpath):
- ''' Processes the data in rctext.
- Args:
- rctext: string containing the contents of the RC file being processed
- rcpath: the path used to access the file.
-
- Return:
- The processed text.
- '''
- raise NotImplementedError()
-
-
-
diff --git a/tools/grit/grit/tool/preprocess_unittest.py b/tools/grit/grit/tool/preprocess_unittest.py
deleted file mode 100644
index ff9ad39..0000000
--- a/tools/grit/grit/tool/preprocess_unittest.py
+++ /dev/null
@@ -1,49 +0,0 @@
-#!/usr/bin/python2.4
-# Copyright (c) 2006-2008 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.
-
-'''Unit test that checks preprocessing of files.
- Tests preprocessing by adding having the preprocessor
- provide the actual rctext data.
-'''
-
-import os
-import sys
-if __name__ == '__main__':
- sys.path.append(os.path.join(os.path.dirname(sys.argv[0]), '..'))
-
-import unittest
-
-import grit.tool.preprocess_interface
-from grit.tool import rc2grd
-
-
-class PreProcessingUnittest(unittest.TestCase):
-
- def testPreProcessing(self):
- tool = rc2grd.Rc2Grd()
- class DummyOpts(object):
- verbose = False
- extra_verbose = False
- tool.o = DummyOpts()
- tool.pre_process = 'grit.tool.preprocess_unittest.DummyPreProcessor'
- result = tool.Process('', '.\resource.rc')
-
- self.failUnless(
- result.children[2].children[2].children[0].attrs['name'] == 'DUMMY_STRING_1')
-
-class DummyPreProcessor(grit.tool.preprocess_interface.PreProcessor):
- def Process(self, rctext, rcpath):
- rctext = '''STRINGTABLE
-BEGIN
- DUMMY_STRING_1 "String 1"
- // Some random description
- DUMMY_STRING_2 "This text was added during preprocessing"
-END
- '''
- return rctext
-
-if __name__ == '__main__':
- unittest.main()
-
diff --git a/tools/grit/grit/tool/rc2grd.py b/tools/grit/grit/tool/rc2grd.py
deleted file mode 100644
index 638ca2f..0000000
--- a/tools/grit/grit/tool/rc2grd.py
+++ /dev/null
@@ -1,403 +0,0 @@
-#!/usr/bin/python2.4
-# Copyright (c) 2006-2008 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.
-
-'''The 'grit rc2grd' tool.'''
-
-
-import os.path
-import getopt
-import re
-import StringIO
-import types
-
-import grit.node.empty
-from grit.node import include
-from grit.node import structure
-from grit.node import message
-
-from grit.gather import rc
-from grit.gather import tr_html
-
-from grit.tool import interface
-from grit.tool import postprocess_interface
-from grit.tool import preprocess_interface
-
-from grit import grd_reader
-from grit import tclib
-from grit import util
-
-
-# Matches files referenced from an .rc file
-_FILE_REF = re.compile('''
- ^(?P<id>[A-Z_0-9.]+)[ \t]+
- (?P<type>[A-Z_0-9]+)[ \t]+
- "(?P<file>.*?([^"]|""))"[ \t]*$''', re.VERBOSE | re.MULTILINE)
-
-
-# Matches a dialog section
-_DIALOG = re.compile('^(?P<id>[A-Z0-9_]+)\s+DIALOG(EX)?\s.+?^BEGIN\s*$.+?^END\s*$',
- re.MULTILINE | re.DOTALL)
-
-
-# Matches a menu section
-_MENU = re.compile('^(?P<id>[A-Z0-9_]+)\s+MENU.+?^BEGIN\s*$.+?^END\s*$',
- re.MULTILINE | re.DOTALL)
-
-
-# Matches a versioninfo section
-_VERSIONINFO = re.compile('^(?P<id>[A-Z0-9_]+)\s+VERSIONINFO\s.+?^BEGIN\s*$.+?^END\s*$',
- re.MULTILINE | re.DOTALL)
-
-
-# Matches a stringtable
-_STRING_TABLE = re.compile('^STRINGTABLE(\s+(PRELOAD|DISCARDABLE|CHARACTERISTICS.+|LANGUAGE.+|VERSION.+))*\s*\nBEGIN\s*$(?P<body>.+?)^END\s*$',
- re.MULTILINE | re.DOTALL)
-
-
-# Matches each message inside a stringtable, breaking it up into comments,
-# the ID of the message, and the (RC-escaped) message text.
-_MESSAGE = re.compile('''
- (?P<comment>(^\s+//.+?)*) # 0 or more lines of comments preceding the message
- ^\s*
- (?P<id>[A-Za-z0-9_]+) # id
- \s+
- "(?P<text>.*?([^"]|""))"([^"]|$) # The message itself
- ''', re.MULTILINE | re.DOTALL | re.VERBOSE)
-
-
-# Matches each line of comment text in a multi-line comment.
-_COMMENT_TEXT = re.compile('^\s*//\s*(?P<text>.+?)$', re.MULTILINE)
-
-
-# Matches a string that is empty or all whitespace
-_WHITESPACE_ONLY = re.compile('\A\s*\Z', re.MULTILINE)
-
-
-# Finds printf and FormatMessage style format specifiers
-# Uses non-capturing groups except for the outermost group, so the output of
-# re.split() should include both the normal text and what we intend to
-# replace with placeholders.
-# TODO(joi) Check documentation for printf (and Windows variants) and FormatMessage
-_FORMAT_SPECIFIER = re.compile(
- '(%[-# +]?(?:[0-9]*|\*)(?:\.(?:[0-9]+|\*))?(?:h|l|L)?' # printf up to last char
- '(?:d|i|o|u|x|X|e|E|f|F|g|G|c|r|s|ls|ws)' # printf last char
- '|\$[1-9][0-9]*)') # FormatMessage
-
-
-class Rc2Grd(interface.Tool):
- '''A tool for converting .rc files to .grd files. This tool is only for
-converting the source (nontranslated) .rc file to a .grd file. For importing
-existing translations, use the rc2xtb tool.
-
-Usage: grit [global options] rc2grd [OPTIONS] RCFILE
-
-The tool takes a single argument, which is the path to the .rc file to convert.
-It outputs a .grd file with the same name in the same directory as the .rc file.
-The .grd file may have one or more TODO comments for things that have to be
-cleaned up manually.
-
-OPTIONS may be any of the following:
-
- -e ENCODING Specify the ENCODING of the .rc file. Default is 'cp1252'.
-
- -h TYPE Specify the TYPE attribute for HTML structures.
- Default is 'tr_html'.
-
- -u ENCODING Specify the ENCODING of HTML files. Default is 'utf-8'.
-
- -n MATCH Specify the regular expression to match in comments that will
- indicate that the resource the comment belongs to is not
- translateable. Default is 'Not locali(s|z)able'.
-
- -r GRDFILE Specify that GRDFILE should be used as a "role model" for
- any placeholders that otherwise would have had TODO names.
- This attempts to find an identical message in the GRDFILE
- and uses that instead of the automatically placeholderized
- message.
-
- --pre CLASS Specify an optional, fully qualified classname, which
- has to be a subclass of grit.tool.PreProcessor, to
- run on the text of the RC file before conversion occurs.
- This can be used to support constructs in the RC files
- that GRIT cannot handle on its own.
-
- --post CLASS Specify an optional, fully qualified classname, which
- has to be a subclass of grit.tool.PostProcessor, to
- run on the text of the converted RC file.
- This can be used to alter the content of the RC file
- based on the conversion that occured.
-
-For menus, dialogs and version info, the .grd file will refer to the original
-.rc file. Once conversion is complete, you can strip the original .rc file
-of its string table and all comments as these will be available in the .grd
-file.
-
-Note that this tool WILL NOT obey C preprocessor rules, so even if something
-is #if 0-ed out it will still be included in the output of this tool
-Therefore, if your .rc file contains sections like this, you should run the
-C preprocessor on the .rc file or manually edit it before using this tool.
-'''
-
- def ShortDescription(self):
- return 'A tool for converting .rc source files to .grd files.'
-
- def __init__(self):
- self.input_encoding = 'cp1252'
- self.html_type = 'tr_html'
- self.html_encoding = 'utf-8'
- self.not_localizable_re = re.compile('Not locali(s|z)able')
- self.role_model = None
- self.pre_process = None
- self.post_process = None
-
- def ParseOptions(self, args):
- '''Given a list of arguments, set this object's options and return
- all non-option arguments.
- '''
- (own_opts, args) = getopt.getopt(args, 'e:h:u:n:r', ['pre=', 'post='])
- for (key, val) in own_opts:
- if key == '-e':
- self.input_encoding = val
- elif key == '-h':
- self.html_type = val
- elif key == '-u':
- self.html_encoding = val
- elif key == '-n':
- self.not_localizable_re = re.compile(val)
- elif key == '-r':
- self.role_model = grd_reader.Parse(val)
- elif key == '--pre':
- self.pre_process = val
- elif key == '--post':
- self.post_process = val
- return args
-
- def Run(self, opts, args):
- args = self.ParseOptions(args)
- if len(args) != 1:
- print ('This tool takes a single tool-specific argument, the path to the\n'
- '.rc file to process.')
- return 2
- self.SetOptions(opts)
-
- path = args[0]
- out_path = os.path.join(util.dirname(path),
- os.path.splitext(os.path.basename(path))[0] + '.grd')
-
- rcfile = util.WrapInputStream(file(path, 'r'), self.input_encoding)
- rctext = rcfile.read()
-
- grd_text = unicode(self.Process(rctext, path))
-
- rcfile.close()
-
- outfile = util.WrapOutputStream(file(out_path, 'w'), 'utf-8')
- outfile.write(grd_text)
- outfile.close()
-
- print 'Wrote output file %s.\nPlease check for TODO items in the file.' % out_path
-
-
- def Process(self, rctext, rc_path):
- '''Processes 'rctext' and returns a resource tree corresponding to it.
-
- Args:
- rctext: complete text of the rc file
- rc_path: 'resource\resource.rc'
-
- Return:
- grit.node.base.Node subclass
- '''
-
- if self.pre_process:
- preprocess_class = util.NewClassInstance(self.pre_process,
- preprocess_interface.PreProcessor)
- if preprocess_class:
- rctext = preprocess_class.Process(rctext, rc_path)
- else:
- self.Out(
- 'PreProcessing class could not be found. Skipping preprocessing.\n')
-
- # Start with a basic skeleton for the .grd file
- root = grd_reader.Parse(StringIO.StringIO(
- '''<?xml version="1.0" encoding="UTF-8"?>
- <grit base_dir="." latest_public_release="0"
- current_release="1" source_lang_id="en">
- <outputs />
- <translations />
- <release seq="1">
- <includes />
- <structures />
- <messages />
- </release>
- </grit>'''), util.dirname(rc_path))
- includes = root.children[2].children[0]
- structures = root.children[2].children[1]
- messages = root.children[2].children[2]
- assert (isinstance(includes, grit.node.empty.IncludesNode) and
- isinstance(structures, grit.node.empty.StructuresNode) and
- isinstance(messages, grit.node.empty.MessagesNode))
-
- self.AddIncludes(rctext, includes)
- self.AddStructures(rctext, structures, os.path.basename(rc_path))
- self.AddMessages(rctext, messages)
-
- self.VerboseOut('Validating that all IDs are unique...\n')
- root.ValidateUniqueIds()
- self.ExtraVerboseOut('Done validating that all IDs are unique.\n')
-
- if self.post_process:
- postprocess_class = util.NewClassInstance(self.post_process,
- postprocess_interface.PostProcessor)
- if postprocess_class:
- root = postprocess_class.Process(rctext, rc_path, root)
- else:
- self.Out(
- 'PostProcessing class could not be found. Skipping postprocessing.\n')
-
- return root
-
-
- def AddIncludes(self, rctext, node):
- '''Scans 'rctext' for included resources (e.g. BITMAP, ICON) and
- adds each included resource as an <include> child node of 'node'.'''
- for m in _FILE_REF.finditer(rctext):
- id = m.group('id')
- type = m.group('type').upper()
- fname = rc.Section.UnEscape(m.group('file'))
- assert fname.find('\n') == -1
- if type != 'HTML':
- self.VerboseOut('Processing %s with ID %s (filename: %s)\n' % (type, id, fname))
- node.AddChild(include.IncludeNode.Construct(node, id, type, fname))
-
-
- def AddStructures(self, rctext, node, rc_filename):
- '''Scans 'rctext' for structured resources (e.g. menus, dialogs, version
- information resources and HTML templates) and adds each as a <structure>
- child of 'node'.'''
- # First add HTML includes
- for m in _FILE_REF.finditer(rctext):
- id = m.group('id')
- type = m.group('type').upper()
- fname = rc.Section.UnEscape(m.group('file'))
- if type == 'HTML':
- node.AddChild(structure.StructureNode.Construct(
- node, id, self.html_type, fname, self.html_encoding))
-
- # Then add all RC includes
- def AddStructure(type, id):
- self.VerboseOut('Processing %s with ID %s\n' % (type, id))
- node.AddChild(structure.StructureNode.Construct(node, id, type,
- rc_filename,
- encoding=self.input_encoding))
- for m in _MENU.finditer(rctext):
- AddStructure('menu', m.group('id'))
- for m in _DIALOG.finditer(rctext):
- AddStructure('dialog', m.group('id'))
- for m in _VERSIONINFO.finditer(rctext):
- AddStructure('version', m.group('id'))
-
-
- def AddMessages(self, rctext, node):
- '''Scans 'rctext' for all messages in string tables, preprocesses them as
- much as possible for placeholders (e.g. messages containing $1, $2 or %s, %d
- type format specifiers get those specifiers replaced with placeholders, and
- HTML-formatted messages get run through the HTML-placeholderizer). Adds
- each message as a <message> node child of 'node'.'''
- for tm in _STRING_TABLE.finditer(rctext):
- table = tm.group('body')
- for mm in _MESSAGE.finditer(table):
- comment_block = mm.group('comment')
- comment_text = []
- for cm in _COMMENT_TEXT.finditer(comment_block):
- comment_text.append(cm.group('text'))
- comment_text = ' '.join(comment_text)
-
- id = mm.group('id')
- text = rc.Section.UnEscape(mm.group('text'))
-
- self.VerboseOut('Processing message %s (text: "%s")\n' % (id, text))
-
- msg_obj = self.Placeholderize(text)
-
- # Messages that contain only placeholders do not need translation.
- is_translateable = False
- for item in msg_obj.GetContent():
- if isinstance(item, types.StringTypes):
- if not _WHITESPACE_ONLY.match(item):
- is_translateable = True
-
- if self.not_localizable_re.search(comment_text):
- is_translateable = False
-
- message_meaning = ''
- internal_comment = ''
-
- # If we have a "role model" (existing GRD file) and this node exists
- # in the role model, use the description, meaning and translateable
- # attributes from the role model.
- if self.role_model:
- role_node = self.role_model.GetNodeById(id)
- if role_node:
- is_translateable = role_node.IsTranslateable()
- message_meaning = role_node.attrs['meaning']
- comment_text = role_node.attrs['desc']
- internal_comment = role_node.attrs['internal_comment']
-
- # For nontranslateable messages, we don't want the complexity of
- # placeholderizing everything.
- if not is_translateable:
- msg_obj = tclib.Message(text=text)
-
- msg_node = message.MessageNode.Construct(node, msg_obj, id,
- desc=comment_text,
- translateable=is_translateable,
- meaning=message_meaning)
- msg_node.attrs['internal_comment'] = internal_comment
-
- node.AddChild(msg_node)
- self.ExtraVerboseOut('Done processing message %s\n' % id)
-
-
- def Placeholderize(self, text):
- '''Creates a tclib.Message object from 'text', attempting to recognize
- a few different formats of text that can be automatically placeholderized
- (HTML code, printf-style format strings, and FormatMessage-style format
- strings).
- '''
-
- try:
- # First try HTML placeholderizing.
- # TODO(joi) Allow use of non-TotalRecall flavors of HTML placeholderizing
- msg = tr_html.HtmlToMessage(text, True)
- for item in msg.GetContent():
- if not isinstance(item, types.StringTypes):
- return msg # Contained at least one placeholder, so we're done
-
- # HTML placeholderization didn't do anything, so try to find printf or
- # FormatMessage format specifiers and change them into placeholders.
- msg = tclib.Message()
- parts = _FORMAT_SPECIFIER.split(text)
- todo_counter = 1 # We make placeholder IDs 'TODO_0001' etc.
- for part in parts:
- if _FORMAT_SPECIFIER.match(part):
- msg.AppendPlaceholder(tclib.Placeholder(
- 'TODO_%04d' % todo_counter, part, 'TODO'))
- todo_counter += 1
- elif part != '':
- msg.AppendText(part)
-
- if self.role_model and len(parts) > 1: # there are TODO placeholders
- role_model_msg = self.role_model.UberClique().BestCliqueByOriginalText(
- msg.GetRealContent(), '')
- if role_model_msg:
- # replace wholesale to get placeholder names and examples
- msg = role_model_msg
-
- return msg
- except:
- print 'Exception processing message with text "%s"' % text
- raise
-
diff --git a/tools/grit/grit/tool/rc2grd_unittest.py b/tools/grit/grit/tool/rc2grd_unittest.py
deleted file mode 100644
index 836d196..0000000
--- a/tools/grit/grit/tool/rc2grd_unittest.py
+++ /dev/null
@@ -1,138 +0,0 @@
-#!/usr/bin/python2.4
-# Copyright (c) 2006-2008 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.
-
-'''Unit tests for grit.tool.rc2grd'''
-
-import os
-import sys
-if __name__ == '__main__':
- sys.path.append(os.path.join(os.path.dirname(sys.argv[0]), '../..'))
-
-import re
-import StringIO
-import unittest
-
-from grit.node import base
-from grit.tool import rc2grd
-from grit.gather import rc
-from grit import grd_reader
-
-
-class Rc2GrdUnittest(unittest.TestCase):
- def testPlaceholderize(self):
- tool = rc2grd.Rc2Grd()
- original = "Hello %s, how are you? I'm $1 years old!"
- msg = tool.Placeholderize(original)
- self.failUnless(msg.GetPresentableContent() == "Hello TODO_0001, how are you? I'm TODO_0002 years old!")
- self.failUnless(msg.GetRealContent() == original)
-
- def testHtmlPlaceholderize(self):
- tool = rc2grd.Rc2Grd()
- original = "Hello <b>[USERNAME]</b>, how are you? I'm [AGE] years old!"
- msg = tool.Placeholderize(original)
- self.failUnless(msg.GetPresentableContent() ==
- "Hello BEGIN_BOLDX_USERNAME_XEND_BOLD, how are you? I'm X_AGE_X years old!")
- self.failUnless(msg.GetRealContent() == original)
-
- def testMenuWithoutWhitespaceRegression(self):
- # There was a problem in the original regular expression for parsing out
- # menu sections, that would parse the following block of text as a single
- # menu instead of two.
- two_menus = '''
-// Hyper context menus
-IDR_HYPERMENU_FOLDER MENU
-BEGIN
- POPUP "HyperFolder"
- BEGIN
- MENUITEM "Open Containing Folder", IDM_OPENFOLDER
- END
-END
-
-IDR_HYPERMENU_FILE MENU
-BEGIN
- POPUP "HyperFile"
- BEGIN
- MENUITEM "Open Folder", IDM_OPENFOLDER
- END
-END
-
-'''
- self.failUnless(len(rc2grd._MENU.findall(two_menus)) == 2)
-
- def testRegressionScriptWithTranslateable(self):
- tool = rc2grd.Rc2Grd()
-
- # test rig
- class DummyNode(base.Node):
- def AddChild(self, item):
- self.node = item
- verbose = False
- extra_verbose = False
- tool.not_localizable_re = re.compile('')
- tool.o = DummyNode()
-
- rc_text = '''STRINGTABLE\nBEGIN\nID_BINGO "<SPAN id=hp style='BEHAVIOR: url(#default#homepage)'></SPAN><script>if (!hp.isHomePage('[$~HOMEPAGE~$]')) {document.write(""<a href=\\""[$~SETHOMEPAGEURL~$]\\"" >Set As Homepage</a> - "");}</script>"\nEND\n'''
- tool.AddMessages(rc_text, tool.o)
- self.failUnless(tool.o.node.GetCdata().find('Set As Homepage') != -1)
-
- # TODO(joi) Improve the HTML parser to support translateables inside
- # <script> blocks?
- self.failUnless(tool.o.node.attrs['translateable'] == 'false')
-
- def testRoleModel(self):
- rc_text = ('STRINGTABLE\n'
- 'BEGIN\n'
- ' // This should not show up\n'
- ' IDS_BINGO "Hello %s, how are you?"\n'
- ' // The first description\n'
- ' IDS_BONGO "Hello %s, my name is %s, and yours?"\n'
- ' IDS_PROGRAMS_SHUTDOWN_TEXT "Google Desktop Search needs to close the following programs:\\n\\n$1\\nThe installation will not proceed if you choose to cancel."\n'
- 'END\n')
- tool = rc2grd.Rc2Grd()
- tool.role_model = grd_reader.Parse(StringIO.StringIO(
- '''<?xml version="1.0" encoding="UTF-8"?>
- <grit latest_public_release="2" source_lang_id="en-US" current_release="3" base_dir=".">
- <release seq="3">
- <messages>
- <message name="IDS_BINGO">
- Hello <ph name="USERNAME">%s<ex>Joi</ex></ph>, how are you?
- </message>
- <message name="IDS_BONGO" desc="The other description">
- Hello <ph name="USERNAME">%s<ex>Jakob</ex></ph>, my name is <ph name="ADMINNAME">%s<ex>Joi</ex></ph>, and yours?
- </message>
- <message name="IDS_PROGRAMS_SHUTDOWN_TEXT" desc="LIST_OF_PROGRAMS is replaced by a bulleted list of program names.">
- Google Desktop Search needs to close the following programs:
-
-<ph name="LIST_OF_PROGRAMS">$1<ex>Program 1, Program 2</ex></ph>
-The installation will not proceed if you choose to cancel.
- </message>
- </messages>
- </release>
- </grit>'''), dir='.')
-
- # test rig
- class DummyOpts(object):
- verbose = False
- extra_verbose = False
- tool.o = DummyOpts()
- result = tool.Process(rc_text, '.\resource.rc')
- self.failUnless(
- result.children[2].children[2].children[0].attrs['desc'] == '')
- self.failUnless(
- result.children[2].children[2].children[0].children[0].attrs['name'] == 'USERNAME')
- self.failUnless(
- result.children[2].children[2].children[1].attrs['desc'] == 'The other description')
- self.failUnless(
- result.children[2].children[2].children[1].attrs['meaning'] == '')
- self.failUnless(
- result.children[2].children[2].children[1].children[0].attrs['name'] == 'USERNAME')
- self.failUnless(
- result.children[2].children[2].children[1].children[1].attrs['name'] == 'ADMINNAME')
- self.failUnless(
- result.children[2].children[2].children[2].children[0].attrs['name'] == 'LIST_OF_PROGRAMS')
-
-if __name__ == '__main__':
- unittest.main()
-
diff --git a/tools/grit/grit/tool/resize.py b/tools/grit/grit/tool/resize.py
deleted file mode 100644
index f76f978..0000000
--- a/tools/grit/grit/tool/resize.py
+++ /dev/null
@@ -1,303 +0,0 @@
-#!/usr/bin/python2.4
-# Copyright (c) 2006-2008 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.
-
-'''The 'grit resize' tool.
-'''
-
-import getopt
-import os
-import types
-
-from grit.tool import interface
-from grit.tool import build
-from grit import grd_reader
-from grit import pseudo
-from grit import util
-
-from grit.node import include
-from grit.node import structure
-from grit.node import message
-
-from grit.format import rc_header
-
-
-# Template for the .vcproj file, with a couple of [[REPLACEABLE]] parts.
-PROJECT_TEMPLATE = '''\
-<?xml version="1.0" encoding="Windows-1252"?>
-<VisualStudioProject
- ProjectType="Visual C++"
- Version="7.10"
- Name="[[DIALOG_NAME]]"
- ProjectGUID="[[PROJECT_GUID]]"
- Keyword="Win32Proj">
- <Platforms>
- <Platform
- Name="Win32"/>
- </Platforms>
- <Configurations>
- <Configuration
- Name="Debug|Win32"
- OutputDirectory="Debug"
- IntermediateDirectory="Debug"
- ConfigurationType="1"
- CharacterSet="2">
- </Configuration>
- </Configurations>
- <References>
- </References>
- <Files>
- <Filter
- Name="Resource Files"
- Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx"
- UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}">
- <File
- RelativePath=".\[[DIALOG_NAME]].rc">
- </File>
- </Filter>
- </Files>
- <Globals>
- </Globals>
-</VisualStudioProject>'''
-
-
-# Template for the .rc file with a couple of [[REPLACEABLE]] parts.
-# TODO(joi) Improve this (and the resource.h template) to allow saving and then
-# reopening of the RC file in Visual Studio. Currently you can only open it
-# once and change it, then after you close it you won't be able to reopen it.
-RC_TEMPLATE = '''\
-// Copyright (c) Google Inc. 2005
-// All rights reserved.
-// This file is automatically generated by GRIT and intended for editing
-// the layout of the dialogs contained in it. Do not edit anything but the
-// dialogs. Any changes made to translateable portions of the dialogs will
-// be ignored by GRIT.
-
-#include "resource.h"
-#include <winresrc.h>
-#ifdef IDC_STATIC
-#undef IDC_STATIC
-#endif
-#define IDC_STATIC (-1)
-
-LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL
-
-#pragma code_page([[CODEPAGE_NUM]])
-
-[[INCLUDES]]
-
-[[DIALOGS]]
-'''
-
-
-# Template for the resource.h file with a couple of [[REPLACEABLE]] parts.
-HEADER_TEMPLATE = '''\
-// Copyright (c) Google Inc. 2005
-// All rights reserved.
-// This file is automatically generated by GRIT. Do not edit.
-
-#pragma once
-
-// Edit commands
-#define ID_EDIT_CLEAR 0xE120
-#define ID_EDIT_CLEAR_ALL 0xE121
-#define ID_EDIT_COPY 0xE122
-#define ID_EDIT_CUT 0xE123
-#define ID_EDIT_FIND 0xE124
-#define ID_EDIT_PASTE 0xE125
-#define ID_EDIT_PASTE_LINK 0xE126
-#define ID_EDIT_PASTE_SPECIAL 0xE127
-#define ID_EDIT_REPEAT 0xE128
-#define ID_EDIT_REPLACE 0xE129
-#define ID_EDIT_SELECT_ALL 0xE12A
-#define ID_EDIT_UNDO 0xE12B
-#define ID_EDIT_REDO 0xE12C
-
-
-[[DEFINES]]
-'''
-
-
-class ResizeDialog(interface.Tool):
- '''Generates an RC file, header and Visual Studio project that you can use
-with Visual Studio's GUI resource editor to modify the layout of dialogs for
-the language of your choice. You then use the RC file, after you resize the
-dialog, for the language or languages of your choice, using the <skeleton> child
-of the <structure> node for the dialog. The translateable bits of the dialog
-will be ignored when you use the <skeleton> node (GRIT will instead use the
-translateable bits from the original dialog) but the layout changes you make
-will be used. Note that your layout changes must preserve the order of the
-translateable elements in the RC file.
-
-Usage: grit resize [-f BASEFOLDER] [-l LANG] [-e RCENCODING] DIALOGID*
-
-Arguments:
- DIALOGID The 'name' attribute of a dialog to output for resizing. Zero
- or more of these parameters can be used. If none are
- specified, all dialogs from the input .grd file are output.
-
-Options:
-
- -f BASEFOLDER The project will be created in a subfolder of BASEFOLDER.
- The name of the subfolder will be the first DIALOGID you
- specify. Defaults to '.'
-
- -l LANG Specifies that the RC file should contain a dialog translated
- into the language LANG. The default is a cp1252-representable
- pseudotranslation, because Visual Studio's GUI RC editor only
- supports single-byte encodings.
-
- -c CODEPAGE Code page number to indicate to the RC compiler the encoding
- of the RC file, default is something reasonable for the
- language you selected (but this does not work for every single
- language). See details on codepages below. NOTE that you do
- not need to specify the codepage unless the tool complains
- that it's not sure which codepage to use. See the following
- page for codepage numbers supported by Windows:
- http://www.microsoft.com/globaldev/reference/wincp.mspx
-
- -D NAME[=VAL] Specify a C-preprocessor-like define NAME with optional
- value VAL (defaults to 1) which will be used to control
- conditional inclusion of resources.
-
-
-IMPORTANT NOTE: For now, the tool outputs a UTF-8 encoded file for any language
-that can not be represented in cp1252 (i.e. anything other than Western
-European languages). You will need to open this file in a text editor and
-save it using the codepage indicated in the #pragma code_page(XXXX) command
-near the top of the file, before you open it in Visual Studio.
-
-'''
-
- # TODO(joi) It would be cool to have this tool note the Perforce revision
- # of the original RC file somewhere, such that the <skeleton> node could warn
- # if the original RC file gets updated without the skeleton file being updated.
-
- # TODO(joi) Would be cool to have option to add the files to Perforce
-
- def __init__(self):
- self.lang = pseudo.PSEUDO_LANG
- self.defines = {}
- self.base_folder = '.'
- self.codepage_number = 1252
- self.codepage_number_specified_explicitly = False
-
- def SetLanguage(self, lang):
- '''Sets the language code to output things in.
- '''
- self.lang = lang
- if not self.codepage_number_specified_explicitly:
- self.codepage_number = util.LanguageToCodepage(lang)
-
- def GetEncoding(self):
- if self.codepage_number == 1200:
- return 'utf_16'
- if self.codepage_number == 65001:
- return 'utf_8'
- return 'cp%d' % self.codepage_number
-
- def ShortDescription(self):
- return 'Generate a file where you can resize a given dialog.'
-
- def Run(self, opts, args):
- self.SetOptions(opts)
-
- own_opts, args = getopt.getopt(args, 'l:f:c:D:')
- for key, val in own_opts:
- if key == '-l':
- self.SetLanguage(val)
- if key == '-f':
- self.base_folder = val
- if key == '-c':
- self.codepage_number = int(val)
- self.codepage_number_specified_explicitly = True
- if key == '-D':
- name, val = build.ParseDefine(val)
- self.defines[name] = val
-
- res_tree = grd_reader.Parse(opts.input, debug=opts.extra_verbose)
- res_tree.OnlyTheseTranslations([self.lang])
- res_tree.RunGatherers(True)
-
- # Dialog IDs are either explicitly listed, or we output all dialogs from the
- # .grd file
- dialog_ids = args
- if not len(dialog_ids):
- for node in res_tree:
- if node.name == 'structure' and node.attrs['type'] == 'dialog':
- dialog_ids.append(node.attrs['name'])
-
- self.Process(res_tree, dialog_ids)
-
- def Process(self, grd, dialog_ids):
- '''Outputs an RC file and header file for the dialog 'dialog_id' stored in
- resource tree 'grd', to self.base_folder, as discussed in this class's
- documentation.
-
- Arguments:
- grd: grd = grd_reader.Parse(...); grd.RunGatherers()
- dialog_ids: ['IDD_MYDIALOG', 'IDD_OTHERDIALOG']
- '''
- grd.SetOutputContext(self.lang, self.defines)
-
- project_name = dialog_ids[0]
-
- dir_path = os.path.join(self.base_folder, project_name)
- if not os.path.isdir(dir_path):
- os.mkdir(dir_path)
-
- # If this fails then we're not on Windows (or you don't have the required
- # win32all Python libraries installed), so what are you doing mucking
- # about with RC files anyway? :)
- import pythoncom
-
- # Create the .vcproj file
- project_text = PROJECT_TEMPLATE.replace(
- '[[PROJECT_GUID]]', str(pythoncom.CreateGuid())
- ).replace('[[DIALOG_NAME]]', project_name)
- fname = os.path.join(dir_path, '%s.vcproj' % project_name)
- self.WriteFile(fname, project_text)
- print "Wrote %s" % fname
-
- # Create the .rc file
- # Output all <include> nodes since the dialogs might depend on them (e.g.
- # for icons and bitmaps).
- include_items = []
- for node in grd:
- if isinstance(node, include.IncludeNode):
- formatter = node.ItemFormatter('rc_all')
- if formatter:
- include_items.append(formatter.Format(node, self.lang))
- rc_text = RC_TEMPLATE.replace('[[CODEPAGE_NUM]]',
- str(self.codepage_number))
- rc_text = rc_text.replace('[[INCLUDES]]', ''.join(include_items))
-
- # Then output the dialogs we have been asked to output.
- dialogs = []
- for dialog_id in dialog_ids:
- node = grd.GetNodeById(dialog_id)
- # TODO(joi) Add exception handling for better error reporting
- formatter = node.ItemFormatter('rc_all')
- dialogs.append(formatter.Format(node, self.lang))
- rc_text = rc_text.replace('[[DIALOGS]]', ''.join(dialogs))
-
- fname = os.path.join(dir_path, '%s.rc' % project_name)
- self.WriteFile(fname, rc_text, self.GetEncoding())
- print "Wrote %s" % fname
-
- # Create the resource.h file
- header_defines = []
- for node in grd:
- formatter = node.ItemFormatter('rc_header')
- if formatter and not isinstance(formatter, rc_header.TopLevel):
- header_defines.append(formatter.Format(node, self.lang))
- header_text = HEADER_TEMPLATE.replace('[[DEFINES]]', ''.join(header_defines))
- fname = os.path.join(dir_path, 'resource.h')
- self.WriteFile(fname, header_text)
- print "Wrote %s" % fname
-
- def WriteFile(self, filename, contents, encoding='cp1252'):
- f = util.WrapOutputStream(file(filename, 'wb'), encoding)
- f.write(contents)
- f.close()
diff --git a/tools/grit/grit/tool/test.py b/tools/grit/grit/tool/test.py
deleted file mode 100644
index aa02c4a..0000000
--- a/tools/grit/grit/tool/test.py
+++ /dev/null
@@ -1,24 +0,0 @@
-#!/usr/bin/python2.4
-# Copyright (c) 2006-2008 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.
-
-from grit.tool import interface
-
-class TestTool(interface.Tool):
- '''This tool does nothing except print out the global options and
-tool-specific arguments that it receives. It is intended only for testing,
-hence the name :)
-'''
-
- def ShortDescription(self):
- return 'A do-nothing tool for testing command-line parsing.'
-
- def Run(self, global_options, my_arguments):
- print 'NOTE This tool is only for testing the parsing of global options and'
- print 'tool-specific arguments that it receives. You may have intended to'
- print 'run "grit unit" which is the unit-test suite for GRIT.'
- print 'Options: %s' % repr(global_options)
- print 'Arguments: %s' % repr(my_arguments)
- return 0
-
diff --git a/tools/grit/grit/tool/toolbar_postprocess.py b/tools/grit/grit/tool/toolbar_postprocess.py
deleted file mode 100644
index 3408985..0000000
--- a/tools/grit/grit/tool/toolbar_postprocess.py
+++ /dev/null
@@ -1,126 +0,0 @@
-#!/usr/bin/python2.4
-# Copyright (c) 2006-2008 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.
-
-''' Toolbar postprocessing class. Modifies the previously processed GRD tree
-by creating separate message groups for each of the IDS_COMMAND macros.
-Also adds some identifiers nodes to declare specific ids to be included
-in the generated grh file.
-'''
-
-import sys
-import re
-import postprocess_interface
-import grit.node.empty
-from grit.node import misc
-
-class ToolbarPostProcessor(postprocess_interface.PostProcessor):
- ''' Defines message groups within the grd file for each of the
- IDS_COMMAND stuff.
- '''
-
- _IDS_COMMAND = re.compile(r'IDS_COMMAND_')
- _GRAB_PARAMETERS = re.compile(r'(IDS_COMMAND_[a-zA-Z0-9]+)_([a-zA-z0-9]+)')
-
- def Process(self, rctext, rcpath, grdnode):
- ''' Processes the data in rctext and grdnode.
- Args:
- rctext: string containing the contents of the RC file being processed.
- rcpath: the path used to access the file.
- grdnode: the root node of the grd xml data generated by
- the rc2grd tool.
-
- Return:
- The root node of the processed GRD tree.
- '''
-
- release = grdnode.children[2]
- messages = release.children[2]
-
- identifiers = grit.node.empty.IdentifiersNode()
- identifiers.StartParsing('identifiers', release)
- identifiers.EndParsing()
- release.AddChild(identifiers)
-
-
- #
- # Turn the IDS_COMMAND messages into separate message groups
- # with ids that are offsetted to the message group's first id
- #
- previous_name_attr = ''
- previous_prefix = ''
- previous_node = ''
- new_messages_node = self.ConstructNewMessages(release)
- for node in messages.children[:]:
- name_attr = node.attrs['name']
- if self._IDS_COMMAND.search(name_attr):
- mo = self._GRAB_PARAMETERS.search(name_attr)
- mp = self._GRAB_PARAMETERS.search(previous_name_attr)
- if mo and mp:
- prefix = mo.group(1)
- previous_prefix = mp.group(1)
- new_message_id = mp.group(2)
- if prefix == previous_prefix:
- messages.RemoveChild(previous_name_attr)
- previous_node.attrs['offset'] = 'PCI_' + new_message_id
- del previous_node.attrs['name']
- new_messages_node.AddChild(previous_node)
- else:
- messages.RemoveChild(previous_name_attr)
- previous_node.attrs['offset'] = 'PCI_' + new_message_id
- del previous_node.attrs['name']
- new_messages_node.AddChild(previous_node)
- new_messages_node.attrs['first_id'] = previous_prefix
- new_messages_node = self.ConstructNewMessages(release)
- else:
- if self._IDS_COMMAND.search(previous_name_attr):
- messages.RemoveChild(previous_name_attr)
- previous_prefix = mp.group(1)
- new_message_id = mp.group(2)
- previous_node.attrs['offset'] = 'PCI_' + new_message_id
- del previous_node.attrs['name']
- new_messages_node.AddChild(previous_node)
- new_messages_node.attrs['first_id'] = previous_prefix
- new_messages_node = self.ConstructNewMessages(release)
- else:
- if self._IDS_COMMAND.search(previous_name_attr):
- messages.RemoveChild(previous_name_attr)
- mp = self._GRAB_PARAMETERS.search(previous_name_attr)
- previous_prefix = mp.group(1)
- new_message_id = mp.group(2)
- previous_node.attrs['offset'] = 'PCI_' + new_message_id
- del previous_node.attrs['name']
- new_messages_node.AddChild(previous_node)
- new_messages_node.attrs['first_id'] = previous_prefix
- new_messages_node = self.ConstructNewMessages(release)
- previous_name_attr = name_attr
- previous_node = node
-
-
- self.AddIdentifiers(rctext, identifiers)
- return grdnode
-
- def ConstructNewMessages(self, parent):
- new_node = grit.node.empty.MessagesNode()
- new_node.StartParsing('messages', parent)
- new_node.EndParsing()
- parent.AddChild(new_node)
- return new_node
-
- def AddIdentifiers(self, rctext, node):
- node.AddChild(misc.IdentifierNode.Construct(node, 'IDS_COMMAND_gcFirst', '12000', ''))
- node.AddChild(misc.IdentifierNode.Construct(node,
- 'IDS_COMMAND_PCI_SPACE', '16', ''))
- node.AddChild(misc.IdentifierNode.Construct(node, 'PCI_BUTTON', '0', ''))
- node.AddChild(misc.IdentifierNode.Construct(node, 'PCI_MENU', '1', ''))
- node.AddChild(misc.IdentifierNode.Construct(node, 'PCI_TIP', '2', ''))
- node.AddChild(misc.IdentifierNode.Construct(node, 'PCI_OPTIONS_TEXT', '3', ''))
- node.AddChild(misc.IdentifierNode.Construct(node, 'PCI_TIP_DISABLED', '4', ''))
- node.AddChild(misc.IdentifierNode.Construct(node, 'PCI_TIP_MENU', '5', ''))
- node.AddChild(misc.IdentifierNode.Construct(node, 'PCI_TIP_MENU_DISABLED', '6', ''))
- node.AddChild(misc.IdentifierNode.Construct(node, 'PCI_TIP_OPTIONS', '7', ''))
- node.AddChild(misc.IdentifierNode.Construct(node, 'PCI_TIP_OPTIONS_DISABLED', '8', ''))
- node.AddChild(misc.IdentifierNode.Construct(node,
- 'PCI_TIP_DISABLED_BY_POLICY', '9', ''))
-
diff --git a/tools/grit/grit/tool/toolbar_preprocess.py b/tools/grit/grit/tool/toolbar_preprocess.py
deleted file mode 100644
index ee566f6..0000000
--- a/tools/grit/grit/tool/toolbar_preprocess.py
+++ /dev/null
@@ -1,62 +0,0 @@
-#!/usr/bin/python2.4
-# Copyright (c) 2006-2008 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.
-
-''' Toolbar preprocessing code. Turns all IDS_COMMAND macros in the RC file
-into simpler constructs that can be understood by GRIT. Also deals with
-expansion of $lf; placeholders into the correct linefeed character.
-'''
-
-import preprocess_interface
-
-import re
-import sys
-import codecs
-
-class ToolbarPreProcessor(preprocess_interface.PreProcessor):
- ''' Toolbar PreProcessing class.
- '''
-
- _IDS_COMMAND_MACRO = re.compile(r'(.*IDS_COMMAND)\s*\(([a-zA-Z0-9_]*)\s*,\s*([a-zA-Z0-9_]*)\)(.*)')
- _LINE_FEED_PH = re.compile(r'\$lf;')
- _PH_COMMENT = re.compile(r'PHRWR')
- _COMMENT = re.compile(r'^(\s*)//.*')
-
-
- def Process(self, rctext, rcpath):
- ''' Processes the data in rctext.
- Args:
- rctext: string containing the contents of the RC file being processed
- rcpath: the path used to access the file.
-
- Return:
- The processed text.
- '''
-
- ret = ''
- rclines = rctext.splitlines()
- for line in rclines:
-
- if self._LINE_FEED_PH.search(line):
- # Replace "$lf;" placeholder comments by an empty line.
- # this will not be put into the processed result
- if self._PH_COMMENT.search(line):
- mm = self._COMMENT.search(line)
- if mm:
- line = '%s//' % mm.group(1)
-
- else:
- # Replace $lf by the right linefeed character
- line = self._LINE_FEED_PH.sub(r'\\n', line)
-
- # Deal with IDS_COMMAND_MACRO stuff
- mo = self._IDS_COMMAND_MACRO.search(line)
- if mo:
- line = '%s_%s_%s%s' % (mo.group(1), mo.group(2), mo.group(3), mo.group(4))
-
- ret += (line + '\n')
-
- return ret
-
-
diff --git a/tools/grit/grit/tool/transl2tc.py b/tools/grit/grit/tool/transl2tc.py
deleted file mode 100644
index d0602af..0000000
--- a/tools/grit/grit/tool/transl2tc.py
+++ /dev/null
@@ -1,254 +0,0 @@
-#!/usr/bin/python2.4
-# Copyright (c) 2006-2008 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.
-
-'''The 'grit transl2tc' tool.
-'''
-
-
-import getopt
-
-from grit.tool import interface
-from grit.tool import rc2grd
-from grit import grd_reader
-from grit import util
-
-from grit.extern import tclib
-
-
-class TranslationToTc(interface.Tool):
- '''A tool for importing existing translations in RC format into the
-Translation Console.
-
-Usage:
-
-grit -i GRD transl2tc [-l LIMITS] [RCOPTS] SOURCE_RC TRANSLATED_RC OUT_FILE
-
-The tool needs a "source" RC file, i.e. in English, and an RC file that is a
-translation of precisely the source RC file (not of an older or newer version).
-
-The tool also requires you to provide a .grd file (input file) e.g. using the
--i global option or the GRIT_INPUT environment variable. The tool uses
-information from your .grd file to correct placeholder names in the
-translations and ensure that only translatable items and translations still
-being used are output.
-
-This tool will accept all the same RCOPTS as the 'grit rc2grd' tool. To get
-a list of these options, run 'grit help rc2grd'.
-
-Additionally, you can use the -l option (which must be the first option to the
-tool) to specify a file containing a list of message IDs to which output should
-be limited. This is only useful if you are limiting the output to your XMB
-files using the 'grit xmb' tool's -l option. See 'grit help xmb' for how to
-generate a file containing a list of the message IDs in an XMB file.
-
-The tool will scan through both of the RC files as well as any HTML files they
-refer to, and match together the source messages and translated messages. It
-will output a file (OUTPUT_FILE) you can import directly into the TC using the
-Bulk Translation Upload tool.
-'''
-
- def ShortDescription(self):
- return 'Import existing translations in RC format into the TC'
-
- def Setup(self, globopt, args):
- '''Sets the instance up for use.
- '''
- self.SetOptions(globopt)
- self.rc2grd = rc2grd.Rc2Grd()
- self.rc2grd.SetOptions(globopt)
- self.limits = None
- if len(args) and args[0] == '-l':
- limit_file = file(args[1])
- self.limits = limit_file.read().split('\n')
- limit_file.close()
- args = args[2:]
- return self.rc2grd.ParseOptions(args)
-
- def Run(self, globopt, args):
- args = self.Setup(globopt, args)
-
- if len(args) != 3:
- self.Out('This tool takes exactly three arguments:\n'
- ' 1. The path to the original RC file\n'
- ' 2. The path to the translated RC file\n'
- ' 3. The output file path.\n')
- return 2
-
- grd = grd_reader.Parse(self.o.input, debug=self.o.extra_verbose)
- grd.RunGatherers(recursive = True)
-
- source_rc = util.WrapInputStream(file(args[0], 'r'), self.rc2grd.input_encoding)
- transl_rc = util.WrapInputStream(file(args[1], 'r'), self.rc2grd.input_encoding)
- translations = self.ExtractTranslations(grd,
- source_rc.read(), args[0],
- transl_rc.read(), args[1])
- transl_rc.close()
- source_rc.close()
-
- output_file = util.WrapOutputStream(file(args[2], 'w'))
- self.WriteTranslations(output_file, translations.items())
- output_file.close()
-
- self.Out('Wrote output file %s' % args[2])
-
- def ExtractTranslations(self, current_grd, source_rc, source_path, transl_rc, transl_path):
- '''Extracts translations from the translated RC file, matching them with
- translations in the source RC file to calculate their ID, and correcting
- placeholders, limiting output to translateables, etc. using the supplied
- .grd file which is the current .grd file for your project.
-
- If this object's 'limits' attribute is not None but a list, the output of
- this function will be further limited to include only messages that have
- message IDs in the 'limits' list.
-
- Args:
- current_grd: grit.node.base.Node child, that has had RunGatherers(True) run on it
- source_rc: Complete text of source RC file
- source_path: Path to the source RC file
- transl_rc: Complete text of translated RC file
- transl_path: Path to the translated RC file
-
- Return:
- { id1 : text1, '12345678' : 'Hello USERNAME, howzit?' }
- '''
- source_grd = self.rc2grd.Process(source_rc, source_path)
- self.VerboseOut('Read %s into GRIT format, running gatherers.\n' % source_path)
- source_grd.RunGatherers(recursive=True, debug=self.o.extra_verbose)
- transl_grd = self.rc2grd.Process(transl_rc, transl_path)
- self.VerboseOut('Read %s into GRIT format, running gatherers.\n' % transl_path)
- transl_grd.RunGatherers(recursive=True, debug=self.o.extra_verbose)
- self.VerboseOut('Done running gatherers for %s.\n' % transl_path)
-
- # Proceed to create a map from ID to translation, getting the ID from the
- # source GRD and the translation from the translated GRD.
- id2transl = {}
- for source_node in source_grd:
- source_cliques = source_node.GetCliques()
- if not len(source_cliques):
- continue
-
- assert 'name' in source_node.attrs, 'All nodes with cliques should have an ID'
- node_id = source_node.attrs['name']
- self.ExtraVerboseOut('Processing node %s\n' % node_id)
- transl_node = transl_grd.GetNodeById(node_id)
-
- if transl_node:
- transl_cliques = transl_node.GetCliques()
- if not len(transl_cliques) == len(source_cliques):
- self.Out(
- 'Warning: Translation for %s has wrong # of cliques, skipping.\n' %
- node_id)
- continue
- else:
- self.Out('Warning: No translation for %s, skipping.\n' % node_id)
- continue
-
- if source_node.name == 'message':
- # Fixup placeholders as well as possible based on information from
- # the current .grd file if they are 'TODO_XXXX' placeholders. We need
- # to fixup placeholders in the translated message so that it looks right
- # and we also need to fixup placeholders in the source message so that
- # its calculated ID will match the current message.
- current_node = current_grd.GetNodeById(node_id)
- if current_node:
- assert len(source_cliques) == 1 and len(current_node.GetCliques()) == 1
-
- source_msg = source_cliques[0].GetMessage()
- current_msg = current_node.GetCliques()[0].GetMessage()
-
- # Only do this for messages whose source version has not changed.
- if (source_msg.GetRealContent() != current_msg.GetRealContent()):
- self.VerboseOut('Info: Message %s has changed; skipping\n' % node_id)
- else:
- transl_msg = transl_cliques[0].GetMessage()
- transl_content = transl_msg.GetContent()
- current_content = current_msg.GetContent()
- source_content = source_msg.GetContent()
-
- ok_to_fixup = True
- if (len(transl_content) != len(current_content)):
- # message structure of translation is different, don't try fixup
- ok_to_fixup = False
- if ok_to_fixup:
- for ix in range(len(transl_content)):
- if isinstance(transl_content[ix], tclib.Placeholder):
- if not isinstance(current_content[ix], tclib.Placeholder):
- ok_to_fixup = False # structure has changed
- break
- if (transl_content[ix].GetOriginal() !=
- current_content[ix].GetOriginal()):
- ok_to_fixup = False # placeholders have likely been reordered
- break
- else: # translated part is not a placeholder but a string
- if isinstance(current_content[ix], tclib.Placeholder):
- ok_to_fixup = False # placeholders have likely been reordered
- break
-
- if not ok_to_fixup:
- self.VerboseOut(
- 'Info: Structure of message %s has changed; skipping.\n' % node_id)
- else:
- def Fixup(content, ix):
- if (isinstance(content[ix], tclib.Placeholder) and
- content[ix].GetPresentation().startswith('TODO_')):
- assert isinstance(current_content[ix], tclib.Placeholder)
- # Get the placeholder ID and example from the current message
- content[ix] = current_content[ix]
- for ix in range(len(transl_content)):
- Fixup(transl_content, ix)
- Fixup(source_content, ix)
-
- # Only put each translation once into the map. Warn if translations
- # for the same message are different.
- for ix in range(len(transl_cliques)):
- source_msg = source_cliques[ix].GetMessage()
- source_msg.GenerateId() # needed to refresh ID based on new placeholders
- message_id = source_msg.GetId()
- translated_content = transl_cliques[ix].GetMessage().GetPresentableContent()
-
- if message_id in id2transl:
- existing_translation = id2transl[message_id]
- if existing_translation != translated_content:
- original_text = source_cliques[ix].GetMessage().GetPresentableContent()
- self.Out('Warning: Two different translations for "%s":\n'
- ' Translation 1: "%s"\n'
- ' Translation 2: "%s"\n' %
- (original_text, existing_translation, translated_content))
- else:
- id2transl[message_id] = translated_content
-
- # Remove translations for messages that do not occur in the current .grd
- # or have been marked as not translateable, or do not occur in the 'limits'
- # list (if it has been set).
- current_message_ids = current_grd.UberClique().AllMessageIds()
- for message_id in id2transl.keys():
- if (message_id not in current_message_ids or
- not current_grd.UberClique().BestClique(message_id).IsTranslateable() or
- (self.limits and message_id not in self.limits)):
- del id2transl[message_id]
-
- return id2transl
-
- # static method
- def WriteTranslations(output_file, translations):
- '''Writes the provided list of translations to the provided output file
- in the format used by the TC's Bulk Translation Upload tool. The file
- must be UTF-8 encoded.
-
- Args:
- output_file: util.WrapOutputStream(file('bingo.out', 'w'))
- translations: [ [id1, text1], ['12345678', 'Hello USERNAME, howzit?'] ]
-
- Return:
- None
- '''
- for id, text in translations:
- text = text.replace('<', '&lt;').replace('>', '&gt;')
- output_file.write(id)
- output_file.write(' ')
- output_file.write(text)
- output_file.write('\n')
- WriteTranslations = staticmethod(WriteTranslations)
-
diff --git a/tools/grit/grit/tool/transl2tc_unittest.py b/tools/grit/grit/tool/transl2tc_unittest.py
deleted file mode 100644
index ad32684..0000000
--- a/tools/grit/grit/tool/transl2tc_unittest.py
+++ /dev/null
@@ -1,130 +0,0 @@
-#!/usr/bin/python2.4
-# Copyright (c) 2011 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.
-
-'''Unit tests for the 'grit transl2tc' tool.'''
-
-
-import os
-import sys
-if __name__ == '__main__':
- sys.path.append(os.path.join(os.path.dirname(sys.argv[0]), '../..'))
-
-import StringIO
-import unittest
-
-from grit.tool import transl2tc
-from grit import grd_reader
-from grit import util
-
-
-def MakeOptions():
- from grit import grit_runner
- return grit_runner.Options()
-
-
-class TranslationToTcUnittest(unittest.TestCase):
-
- def testOutput(self):
- buf = StringIO.StringIO()
- tool = transl2tc.TranslationToTc()
- translations = [
- ['1', 'Hello USERNAME, how are you?'],
- ['12', 'Howdie doodie!'],
- ['123', 'Hello\n\nthere\n\nhow are you?'],
- ['1234', 'Hello is > goodbye but < howdie pardner'],
- ]
- tool.WriteTranslations(buf, translations)
- output = buf.getvalue()
- self.failUnless(output.strip() == '''
-1 Hello USERNAME, how are you?
-12 Howdie doodie!
-123 Hello
-
-there
-
-how are you?
-1234 Hello is &gt; goodbye but &lt; howdie pardner
-'''.strip())
-
- def testExtractTranslations(self):
- path = util.PathFromRoot('grit/testdata')
- current_grd = grd_reader.Parse(StringIO.StringIO('''<?xml version="1.0" encoding="UTF-8"?>
- <grit latest_public_release="2" source_lang_id="en-US" current_release="3" base_dir=".">
- <release seq="3">
- <messages>
- <message name="IDS_SIMPLE">
- One
- </message>
- <message name="IDS_PLACEHOLDER">
- <ph name="NUMBIRDS">%s<ex>3</ex></ph> birds
- </message>
- <message name="IDS_PLACEHOLDERS">
- <ph name="ITEM">%d<ex>1</ex></ph> of <ph name="COUNT">%d<ex>3</ex></ph>
- </message>
- <message name="IDS_REORDERED_PLACEHOLDERS">
- <ph name="ITEM">$1<ex>1</ex></ph> of <ph name="COUNT">$2<ex>3</ex></ph>
- </message>
- <message name="IDS_CHANGED">
- This is the new version
- </message>
- <message name="IDS_TWIN_1">Hello</message>
- <message name="IDS_TWIN_2">Hello</message>
- <message name="IDS_NOT_TRANSLATEABLE" translateable="false">:</message>
- <message name="IDS_LONGER_TRANSLATED">
- Removed document <ph name="FILENAME">$1<ex>c:\temp</ex></ph>
- </message>
- <message name="IDS_DIFFERENT_TWIN_1">Howdie</message>
- <message name="IDS_DIFFERENT_TWIN_2">Howdie</message>
- </messages>
- <structures>
- <structure type="dialog" name="IDD_ABOUTBOX" encoding="utf-16" file="klonk.rc" />
- <structure type="menu" name="IDC_KLONKMENU" encoding="utf-16" file="klonk.rc" />
- </structures>
- </release>
- </grit>'''), path)
- current_grd.RunGatherers(recursive=True)
-
- source_rc_path = util.PathFromRoot('grit/testdata/source.rc')
- source_rc = file(source_rc_path).read()
- transl_rc_path = util.PathFromRoot('grit/testdata/transl.rc')
- transl_rc = file(transl_rc_path).read()
-
- tool = transl2tc.TranslationToTc()
- output_buf = StringIO.StringIO()
- globopts = MakeOptions()
- globopts.verbose = True
- globopts.output_stream = output_buf
- tool.Setup(globopts, [])
- translations = tool.ExtractTranslations(current_grd,
- source_rc, source_rc_path,
- transl_rc, transl_rc_path)
-
- values = translations.values()
- output = output_buf.getvalue()
-
- self.failUnless('Ein' in values)
- self.failUnless('NUMBIRDS Vogeln' in values)
- self.failUnless('ITEM von COUNT' in values)
- self.failUnless(values.count('Hallo') == 1)
- self.failIf('Dass war die alte Version' in values)
- self.failIf(':' in values)
- self.failIf('Dokument FILENAME ist entfernt worden' in values)
- self.failIf('Nicht verwendet' in values)
- self.failUnless(('Howdie' in values or 'Hallo sagt man' in values) and not
- ('Howdie' in values and 'Hallo sagt man' in values))
-
- self.failUnless('XX01XX&SkraXX02XX&HaettaXX03XXThetta er "Klonk" sem eg fylaXX04XXgonkurinnXX05XXKlonk && er "gott"XX06XX&HjalpXX07XX&Um...XX08XX' in values)
-
- self.failUnless('I lagi' in values)
-
- self.failUnless(output.count('Structure of message IDS_REORDERED_PLACEHOLDERS has changed'))
- self.failUnless(output.count('Message IDS_CHANGED has changed'))
- self.failUnless(output.count('Structure of message IDS_LONGER_TRANSLATED has changed'))
- self.failUnless(output.count('Two different translations for "Howdie"'))
- self.failUnless(output.count('IDD_DIFFERENT_LENGTH_IN_TRANSL has wrong # of cliques'))
-
-
-if __name__ == '__main__':
- unittest.main()
diff --git a/tools/grit/grit/tool/unit.py b/tools/grit/grit/tool/unit.py
deleted file mode 100644
index 7eb94ba..0000000
--- a/tools/grit/grit/tool/unit.py
+++ /dev/null
@@ -1,26 +0,0 @@
-#!/usr/bin/python2.4
-# Copyright (c) 2006-2008 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.
-
-'''GRIT tool that runs the unit test suite for GRIT.'''
-
-
-import unittest
-
-import grit.test_suite_all
-from grit.tool import interface
-
-
-class UnitTestTool(interface.Tool):
- '''By using this tool (e.g. 'grit unit') you run all the unit tests for GRIT.
-This happens in the environment that is set up by the basic GRIT runner, i.e.
-whether to run disconnected has been specified, etc.'''
-
- def ShortDescription(self):
- return 'Use this tool to run all the unit tests for GRIT.'
-
- def Run(self, opts, args):
- return unittest.TextTestRunner(verbosity=2).run(
- grit.test_suite_all.TestSuiteAll())
-
diff --git a/tools/grit/grit/util.py b/tools/grit/grit/util.py
deleted file mode 100644
index a0aac74..0000000
--- a/tools/grit/grit/util.py
+++ /dev/null
@@ -1,310 +0,0 @@
-#!/usr/bin/python2.4
-# Copyright (c) 2006-2008 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.
-
-'''Utilities used by GRIT.
-'''
-
-import sys
-import os.path
-import codecs
-import htmlentitydefs
-import re
-import time
-from xml.sax import saxutils
-
-_root_dir = os.path.normpath(os.path.join(os.path.dirname(__file__), '..'))
-
-
-# Matches all of the resource IDs predefined by Windows.
-# The '\b' before and after each word makes sure these match only whole words and
-# not the beginning of any word.. eg. ID_FILE_NEW will not match ID_FILE_NEW_PROJECT
-# see http://www.amk.ca/python/howto/regex/ (search for "\bclass\b" inside the html page)
-SYSTEM_IDENTIFIERS = re.compile(
- r'''\bIDOK\b | \bIDCANCEL\b | \bIDC_STATIC\b | \bIDYES\b | \bIDNO\b |
- \bID_FILE_NEW\b | \bID_FILE_OPEN\b | \bID_FILE_CLOSE\b | \bID_FILE_SAVE\b |
- \bID_FILE_SAVE_AS\b | \bID_FILE_PAGE_SETUP\b | \bID_FILE_PRINT_SETUP\b |
- \bID_FILE_PRINT\b | \bID_FILE_PRINT_DIRECT\b | \bID_FILE_PRINT_PREVIEW\b |
- \bID_FILE_UPDATE\b | \bID_FILE_SAVE_COPY_AS\b | \bID_FILE_SEND_MAIL\b |
- \bID_FILE_MRU_FIRST\b | \bID_FILE_MRU_LAST\b |
- \bID_EDIT_CLEAR\b | \bID_EDIT_CLEAR_ALL\b | \bID_EDIT_COPY\b |
- \bID_EDIT_CUT\b | \bID_EDIT_FIND\b | \bID_EDIT_PASTE\b | \bID_EDIT_PASTE_LINK\b |
- \bID_EDIT_PASTE_SPECIAL\b | \bID_EDIT_REPEAT\b | \bID_EDIT_REPLACE\b |
- \bID_EDIT_SELECT_ALL\b | \bID_EDIT_UNDO\b | \bID_EDIT_REDO\b |
- \bVS_VERSION_INFO\b | \bIDRETRY''', re.VERBOSE);
-
-
-# Matches character entities, whether specified by name, decimal or hex.
-_HTML_ENTITY = re.compile(
- '&(#(?P<decimal>[0-9]+)|#x(?P<hex>[a-fA-F0-9]+)|(?P<named>[a-z0-9]+));',
- re.IGNORECASE)
-
-# Matches characters that should be HTML-escaped. This is <, > and &, but only
-# if the & is not the start of an HTML character entity.
-_HTML_CHARS_TO_ESCAPE = re.compile('"|<|>|&(?!#[0-9]+|#x[0-9a-z]+|[a-z]+;)',
- re.IGNORECASE | re.MULTILINE)
-
-
-def WrapInputStream(stream, encoding = 'utf-8'):
- '''Returns a stream that wraps the provided stream, making it read characters
- using the specified encoding.'''
- (e, d, sr, sw) = codecs.lookup(encoding)
- return sr(stream)
-
-
-def WrapOutputStream(stream, encoding = 'utf-8'):
- '''Returns a stream that wraps the provided stream, making it write
- characters using the specified encoding.'''
- (e, d, sr, sw) = codecs.lookup(encoding)
- return sw(stream)
-
-
-def ChangeStdoutEncoding(encoding = 'utf-8'):
- '''Changes STDOUT to print characters using the specified encoding.'''
- sys.stdout = WrapOutputStream(sys.stdout, encoding)
-
-
-def EscapeHtml(text, escape_quotes = False):
- '''Returns 'text' with <, > and & (and optionally ") escaped to named HTML
- entities. Any existing named entity or HTML entity defined by decimal or
- hex code will be left untouched. This is appropriate for escaping text for
- inclusion in HTML, but not for XML.
- '''
- def Replace(match):
- if match.group() == '&': return '&amp;'
- elif match.group() == '<': return '&lt;'
- elif match.group() == '>': return '&gt;'
- elif match.group() == '"':
- if escape_quotes: return '&quot;'
- else: return match.group()
- else: assert False
- out = _HTML_CHARS_TO_ESCAPE.sub(Replace, text)
- return out
-
-
-def UnescapeHtml(text, replace_nbsp=True):
- '''Returns 'text' with all HTML character entities (both named character
- entities and those specified by decimal or hexadecimal Unicode ordinal)
- replaced by their Unicode characters (or latin1 characters if possible).
-
- The only exception is that &nbsp; will not be escaped if 'replace_nbsp' is
- False.
- '''
- def Replace(match):
- groups = match.groupdict()
- if groups['hex']:
- return unichr(int(groups['hex'], 16))
- elif groups['decimal']:
- return unichr(int(groups['decimal'], 10))
- else:
- name = groups['named']
- if name == 'nbsp' and not replace_nbsp:
- return match.group() # Don't replace &nbsp;
- assert name != None
- if name in htmlentitydefs.name2codepoint.keys():
- return unichr(htmlentitydefs.name2codepoint[name])
- else:
- return match.group() # Unknown HTML character entity - don't replace
-
- out = _HTML_ENTITY.sub(Replace, text)
- return out
-
-
-def EncodeCdata(cdata):
- '''Returns the provided cdata in either escaped format or <![CDATA[xxx]]>
- format, depending on which is more appropriate for easy editing. The data
- is escaped for inclusion in an XML element's body.
-
- Args:
- cdata: 'If x < y and y < z then x < z'
-
- Return:
- '<![CDATA[If x < y and y < z then x < z]]>'
- '''
- if cdata.count('<') > 1 or cdata.count('>') > 1 and cdata.count(']]>') == 0:
- return '<![CDATA[%s]]>' % cdata
- else:
- return saxutils.escape(cdata)
-
-
-def FixupNamedParam(function, param_name, param_value):
- '''Returns a closure that is identical to 'function' but ensures that the
- named parameter 'param_name' is always set to 'param_value' unless explicitly
- set by the caller.
-
- Args:
- function: callable
- param_name: 'bingo'
- param_value: 'bongo' (any type)
-
- Return:
- callable
- '''
- def FixupClosure(*args, **kw):
- if not param_name in kw:
- kw[param_name] = param_value
- return function(*args, **kw)
- return FixupClosure
-
-
-def PathFromRoot(path):
- '''Takes a path relative to the root directory for GRIT (the one that grit.py
- resides in) and returns a path that is either absolute or relative to the
- current working directory (i.e .a path you can use to open the file).
-
- Args:
- path: 'rel_dir\file.ext'
-
- Return:
- 'c:\src\tools\rel_dir\file.ext
- '''
- return os.path.normpath(os.path.join(_root_dir, path))
-
-
-def FixRootForUnittest(root_node, dir=PathFromRoot('.')):
- '''Adds a GetBaseDir() method to 'root_node', making unittesting easier.'''
- def GetBaseDir():
- '''Returns a fake base directory.'''
- return dir
- def GetSourceLanguage():
- return 'en'
- if not hasattr(root_node, 'GetBaseDir'):
- setattr(root_node, 'GetBaseDir', GetBaseDir)
- setattr(root_node, 'GetSourceLanguage', GetSourceLanguage)
-
-
-def dirname(filename):
- '''Version of os.path.dirname() that never returns empty paths (returns
- '.' if the result of os.path.dirname() is empty).
- '''
- ret = os.path.dirname(filename)
- if ret == '':
- ret = '.'
- return ret
-
-
-def normpath(path):
- '''Version of os.path.normpath that also changes backward slashes to
- forward slashes when not running on Windows.
- '''
- # This is safe to always do because the Windows version of os.path.normpath
- # will replace forward slashes with backward slashes.
- path = path.replace('\\', '/')
- return os.path.normpath(path)
-
-
-_LANGUAGE_SPLIT_RE = re.compile('-|_|/')
-
-
-def CanonicalLanguage(code):
- '''Canonicalizes two-part language codes by using a dash and making the
- second part upper case. Returns one-part language codes unchanged.
-
- Args:
- code: 'zh_cn'
-
- Return:
- code: 'zh-CN'
- '''
- parts = _LANGUAGE_SPLIT_RE.split(code)
- code = [ parts[0] ]
- for part in parts[1:]:
- code.append(part.upper())
- return '-'.join(code)
-
-
-_LANG_TO_CODEPAGE = {
- 'en' : 1252,
- 'fr' : 1252,
- 'it' : 1252,
- 'de' : 1252,
- 'es' : 1252,
- 'nl' : 1252,
- 'sv' : 1252,
- 'no' : 1252,
- 'da' : 1252,
- 'fi' : 1252,
- 'pt-BR' : 1252,
- 'ru' : 1251,
- 'ja' : 932,
- 'zh-TW' : 950,
- 'zh-CN' : 936,
- 'ko' : 949,
-}
-
-
-def LanguageToCodepage(lang):
- '''Returns the codepage _number_ that can be used to represent 'lang', which
- may be either in formats such as 'en', 'pt_br', 'pt-BR', etc.
-
- The codepage returned will be one of the 'cpXXXX' codepage numbers.
-
- Args:
- lang: 'de'
-
- Return:
- 1252
- '''
- lang = CanonicalLanguage(lang)
- if lang in _LANG_TO_CODEPAGE:
- return _LANG_TO_CODEPAGE[lang]
- else:
- print "Not sure which codepage to use for %s, assuming cp1252" % lang
- return 1252
-
-def NewClassInstance(class_name, class_type):
- '''Returns an instance of the class specified in classname
-
- Args:
- class_name: the fully qualified, dot separated package + classname,
- i.e. "my.package.name.MyClass". Short class names are not supported.
- class_type: the class or superclass this object must implement
-
- Return:
- An instance of the class, or None if none was found
- '''
- lastdot = class_name.rfind('.')
- module_name = ''
- if lastdot >= 0:
- module_name = class_name[0:lastdot]
- if module_name:
- class_name = class_name[lastdot+1:]
- module = __import__(module_name, globals(), locals(), [''])
- if hasattr(module, class_name):
- class_ = getattr(module, class_name)
- class_instance = class_()
- if isinstance(class_instance, class_type):
- return class_instance
- return None
-
-
-def FixLineEnd(text, line_end):
- # First normalize
- text = text.replace('\r\n', '\n')
- text = text.replace('\r', '\n')
- # Then fix
- text = text.replace('\n', line_end)
- return text
-
-
-def BoolToString(bool):
- if bool:
- return 'true'
- else:
- return 'false'
-
-
-verbose = False
-extra_verbose = False
-
-def IsVerbose():
- return verbose
-
-def IsExtraVerbose():
- return extra_verbose
-
-def GetCurrentYear():
- '''Returns the current 4-digit year as an integer.'''
- return time.localtime()[0]
-
diff --git a/tools/grit/grit/util_unittest.py b/tools/grit/grit/util_unittest.py
deleted file mode 100644
index cd8c97b..0000000
--- a/tools/grit/grit/util_unittest.py
+++ /dev/null
@@ -1,70 +0,0 @@
-#!/usr/bin/python2.4
-# Copyright (c) 2006-2008 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.
-
-'''Unit test that checks some of util functions.
-'''
-
-import os
-import sys
-if __name__ == '__main__':
- sys.path.append(os.path.join(os.path.dirname(sys.argv[0]), '..'))
-
-import unittest
-
-from grit import util
-
-
-class UtilUnittest(unittest.TestCase):
- ''' Tests functions from util
- '''
-
- def testNewClassInstance(self):
- # Test short class name with no fully qualified package name
- # Should fail, it is not supported by the function now (as documented)
- cls = util.NewClassInstance('grit.util.TestClassToLoad',
- TestBaseClassToLoad)
- self.failUnless(cls == None)
-
- # Test non existent class name
- cls = util.NewClassInstance('grit.util_unittest.NotExistingClass',
- TestBaseClassToLoad)
- self.failUnless(cls == None)
-
- # Test valid class name and valid base class
- cls = util.NewClassInstance('grit.util_unittest.TestClassToLoad',
- TestBaseClassToLoad)
- self.failUnless(isinstance(cls, TestBaseClassToLoad))
-
- # Test valid class name with wrong hierarchy
- cls = util.NewClassInstance('grit.util_unittest.TestClassNoBase',
- TestBaseClassToLoad)
- self.failUnless(cls == None)
-
- def testCanonicalLanguage(self):
- self.failUnless(util.CanonicalLanguage('en') == 'en')
- self.failUnless(util.CanonicalLanguage('pt_br') == 'pt-BR')
- self.failUnless(util.CanonicalLanguage('pt-br') == 'pt-BR')
- self.failUnless(util.CanonicalLanguage('pt-BR') == 'pt-BR')
- self.failUnless(util.CanonicalLanguage('pt/br') == 'pt-BR')
- self.failUnless(util.CanonicalLanguage('pt/BR') == 'pt-BR')
- self.failUnless(util.CanonicalLanguage('no_no_bokmal') == 'no-NO-BOKMAL')
-
- def testUnescapeHtml(self):
- self.failUnless(util.UnescapeHtml('&#1010;') == unichr(1010))
- self.failUnless(util.UnescapeHtml('&#xABcd;') == unichr(43981))
-
-class TestBaseClassToLoad(object):
- pass
-
-class TestClassToLoad(TestBaseClassToLoad):
- pass
-
-class TestClassNoBase(object):
- pass
-
-
-if __name__ == '__main__':
- unittest.main()
-
diff --git a/tools/grit/grit/xtb_reader.py b/tools/grit/grit/xtb_reader.py
deleted file mode 100644
index 8263614..0000000
--- a/tools/grit/grit/xtb_reader.py
+++ /dev/null
@@ -1,132 +0,0 @@
-#!/usr/bin/python2.4
-# Copyright (c) 2006-2008 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.
-
-'''Fast and efficient parser for XTB files.
-'''
-
-
-import sys
-import xml.sax
-import xml.sax.handler
-
-
-class XtbContentHandler(xml.sax.handler.ContentHandler):
- '''A content handler that calls a given callback function for each
- translation in the XTB file.
- '''
-
- def __init__(self, callback, defs=None, debug=False):
- self.callback = callback
- self.debug = debug
- # 0 if we are not currently parsing a translation, otherwise the message
- # ID of that translation.
- self.current_id = 0
- # Empty if we are not currently parsing a translation, otherwise the
- # parts we have for that translation - a list of tuples
- # (is_placeholder, text)
- self.current_structure = []
- # Set to the language ID when we see the <translationbundle> node.
- self.language = ''
- # Keep track of the if block we're inside. We can't nest ifs.
- self.if_expr = None
- # Root defines to be used with if expr.
- if defs:
- self.defines = defs
- else:
- self.defines = {}
-
- def startElement(self, name, attrs):
- if name == 'translation':
- assert self.current_id == 0 and len(self.current_structure) == 0, (
- "Didn't expect a <translation> element here.")
- self.current_id = attrs.getValue('id')
- elif name == 'ph':
- assert self.current_id != 0, "Didn't expect a <ph> element here."
- self.current_structure.append((True, attrs.getValue('name')))
- elif name == 'translationbundle':
- self.language = attrs.getValue('lang')
- elif name == 'if':
- assert self.if_expr is None, "Can't nest <if> in xtb files"
- self.if_expr = attrs.getValue('expr')
-
- def endElement(self, name):
- if name == 'translation':
- assert self.current_id != 0
-
- defs = self.defines
- def pp_ifdef(define):
- return define in defs
- def pp_if(define):
- return define in defs and defs[define]
-
- # If we're in an if block, only call the callback (add the translation)
- # if the expression is True.
- should_run_callback = True
- if self.if_expr:
- should_run_callback = eval(self.if_expr, {},
- {'os': sys.platform,
- 'defs' : defs,
- 'pp_ifdef' : pp_ifdef,
- 'pp_if' : pp_if})
- if should_run_callback:
- self.callback(self.current_id, self.current_structure)
-
- self.current_id = 0
- self.current_structure = []
- elif name == 'if':
- assert self.if_expr is not None
- self.if_expr = None
-
- def characters(self, content):
- if self.current_id != 0:
- # We are inside a <translation> node so just add the characters to our
- # structure.
- #
- # This naive way of handling characters is OK because in the XTB format,
- # <ph> nodes are always empty (always <ph name="XXX"/>) and whitespace
- # inside the <translation> node should be preserved.
- self.current_structure.append((False, content))
-
-
-class XtbErrorHandler(xml.sax.handler.ErrorHandler):
- def error(self, exception):
- pass
-
- def fatalError(self, exception):
- raise exception
-
- def warning(self, exception):
- pass
-
-
-def Parse(xtb_file, callback_function, defs={}, debug=False):
- '''Parse xtb_file, making a call to callback_function for every translation
- in the XTB file.
-
- The callback function must have the signature as described below. The 'parts'
- parameter is a list of tuples (is_placeholder, text). The 'text' part is
- either the raw text (if is_placeholder is False) or the name of the placeholder
- (if is_placeholder is True).
-
- Args:
- xtb_file: file('fr.xtb')
- callback_function: def Callback(msg_id, parts): pass
-
- Return:
- The language of the XTB, e.g. 'fr'
- '''
- # Start by advancing the file pointer past the DOCTYPE thing, as the TC
- # uses a path to the DTD that only works in Unix.
- # TODO(joi) Remove this ugly hack by getting the TC gang to change the
- # XTB files somehow?
- front_of_file = xtb_file.read(1024)
- xtb_file.seek(front_of_file.find('<translationbundle'))
-
- handler = XtbContentHandler(callback=callback_function, defs=defs,
- debug=debug)
- xml.sax.parse(xtb_file, handler)
- assert handler.language != ''
- return handler.language
-
diff --git a/tools/grit/grit/xtb_reader_unittest.py b/tools/grit/grit/xtb_reader_unittest.py
deleted file mode 100644
index 29925d9..0000000
--- a/tools/grit/grit/xtb_reader_unittest.py
+++ /dev/null
@@ -1,83 +0,0 @@
-#!/usr/bin/python2.4
-# Copyright (c) 2011 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.
-
-'''Unit tests for grit.xtb_reader'''
-
-
-import os
-import sys
-if __name__ == '__main__':
- sys.path.append(os.path.join(os.path.dirname(sys.argv[0]), '..'))
-
-import StringIO
-import unittest
-
-from grit import xtb_reader
-from grit import clique
-from grit import grd_reader
-from grit import tclib
-from grit import util
-
-
-class XtbReaderUnittest(unittest.TestCase):
- def testParsing(self):
- xtb_file = StringIO.StringIO('''<?xml version="1.0" encoding="UTF-8"?>
- <!DOCTYPE translationbundle>
- <translationbundle lang="fr">
- <translation id="5282608565720904145">Bingo.</translation>
- <translation id="2955977306445326147">Bongo longo.</translation>
- <translation id="238824332917605038">Hullo</translation>
- <translation id="6629135689895381486"><ph name="PROBLEM_REPORT"/> peut <ph name="START_LINK"/>utilisation excessive de majuscules<ph name="END_LINK"/>.</translation>
- <translation id="7729135689895381486">Hello
-this is another line
-and another
-
-and another after a blank line.</translation>
- </translationbundle>''')
-
- messages = []
- def Callback(id, structure):
- messages.append((id, structure))
- xtb_reader.Parse(xtb_file, Callback)
- self.failUnless(len(messages[0][1]) == 1)
- self.failUnless(messages[3][1][0]) # PROBLEM_REPORT placeholder
- self.failUnless(messages[4][0] == '7729135689895381486')
- self.failUnless(messages[4][1][7][1] == 'and another after a blank line.')
-
- def testParsingIntoMessages(self):
- grd = grd_reader.Parse(StringIO.StringIO('''<?xml version="1.0" encoding="UTF-8"?>
- <messages>
- <message name="ID_MEGA">Fantastic!</message>
- <message name="ID_HELLO_USER">Hello <ph name="USERNAME">%s<ex>Joi</ex></ph></message>
- </messages>'''), dir='.', flexible_root=True)
-
- clique_mega = grd.children[0].GetCliques()[0]
- msg_mega = clique_mega.GetMessage()
- clique_hello_user = grd.children[1].GetCliques()[0]
- msg_hello_user = clique_hello_user.GetMessage()
-
- xtb_file = StringIO.StringIO('''<?xml version="1.0" encoding="UTF-8"?>
- <!DOCTYPE translationbundle>
- <translationbundle lang="is">
- <translation id="%s">Meirihattar!</translation>
- <translation id="%s">Saelir <ph name="USERNAME"/></translation>
- </translationbundle>''' % (msg_mega.GetId(), msg_hello_user.GetId()))
-
- xtb_reader.Parse(xtb_file, grd.UberClique().GenerateXtbParserCallback('is'))
- self.failUnless(clique_mega.MessageForLanguage('is').GetRealContent() ==
- 'Meirihattar!')
- self.failUnless(clique_hello_user.MessageForLanguage('is').GetRealContent() ==
- 'Saelir %s')
-
- def testParseLargeFile(self):
- def Callback(id, structure):
- pass
- xtb = file(util.PathFromRoot('grit/testdata/generated_resources_fr.xtb'))
- xtb_reader.Parse(xtb, Callback)
- xtb.close()
-
-
-if __name__ == '__main__':
- unittest.main()
diff --git a/tools/grit/grit_info.py b/tools/grit/grit_info.py
deleted file mode 100755
index e1e6a66..0000000
--- a/tools/grit/grit_info.py
+++ /dev/null
@@ -1,240 +0,0 @@
-#!/usr/bin/python
-# Copyright (c) 2011 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.
-
-'''Tool to determine inputs and outputs of a grit file.
-'''
-
-import optparse
-import os
-import posixpath
-import types
-import sys
-
-from grit import grd_reader
-from grit import util
-
-##############################################################################
-# os.path.relpath is python 2.6 only. Some bots still run 2.5 only, so I took
-# the relpath implementation from the python source.
-# TODO(thakis): Once we're on 2.6 everywhere, remove this and use
-# os.path.relpath directly.
-
-# http://docs.python.org/license.html
-# PSF LICENSE AGREEMENT FOR PYTHON 2.7.1
-#
-# 1. This LICENSE AGREEMENT is between the Python Software Foundation ("PSF"),
-# and the Individual or Organization ("Licensee") accessing and otherwise using
-# Python 2.7.1 software in source or binary form and its associated
-# documentation.
-#
-# 2. Subject to the terms and conditions of this License Agreement, PSF hereby
-# grants Licensee a nonexclusive, royalty-free, world-wide license to reproduce,
-# analyze, test, perform and/or display publicly, prepare derivative works,
-# distribute, and otherwise use Python 2.7.1 alone or in any derivative version,
-# provided, however, that PSF's License Agreement and PSF's notice of copyright,
-# i.e., "Copyright c 2001-2010 Python Software Foundation; All Rights Reserved"
-# are retained in Python 2.7.1 alone or in any derivative version prepared by
-# Licensee.
-#
-# 3. In the event Licensee prepares a derivative work that is based on or
-# incorporates Python 2.7.1 or any part thereof, and wants to make the
-# derivative work available to others as provided herein, then Licensee hereby
-# agrees to include in any such work a brief summary of the changes made to
-# Python 2.7.1.
-#
-# 4. PSF is making Python 2.7.1 available to Licensee on an "AS IS" basis. PSF
-# MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED. BY WAY OF EXAMPLE,
-# BUT NOT LIMITATION, PSF MAKES NO AND DISCLAIMS ANY REPRESENTATION OR WARRANTY
-# OF MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF
-# PYTHON 2.7.1 WILL NOT INFRINGE ANY THIRD PARTY RIGHTS.
-#
-# 5.1 PSF SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF PYTHON 2.7.1 FOR
-# ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS AS A RESULT OF
-# MODIFYING, DISTRIBUTING, OR OTHERWISE USING PYTHON 2.7.1, OR ANY DERIVATIVE
-# THEREOF, EVEN IF ADVISED OF THE POSSIBILITY THEREOF.
-#
-# 6. This License Agreement will automatically terminate upon a material breach
-# of its terms and conditions.
-#
-# 7. Nothing in this License Agreement shall be deemed to create any
-# relationship of agency, partnership, or joint venture between PSF and
-# Licensee. This License Agreement does not grant permission to use PSF
-# trademarks or trade name in a trademark sense to endorse or promote products
-# or services of Licensee, or any third party.
-#
-# 8. By copying, installing or otherwise using Python 2.7.1, Licensee agrees to
-# be bound by the terms and conditions of this License Agreement.
-
-# http://svn.python.org/view/python/trunk/Lib/genericpath.py?view=markup
-def commonprefix(m):
- "Given a list of pathnames, returns the longest common leading component"
- if not m: return ''
- s1 = min(m)
- s2 = max(m)
- for i, c in enumerate(s1):
- if c != s2[i]:
- return s1[:i]
- return s1
-
-
-# http://svn.python.org/view/python/trunk/Lib/posixpath.py?view=markup
-def relpath(path, start=os.path.curdir):
- """Return a relative version of a path"""
-
- if not path:
- raise ValueError("no path specified")
-
- start_list = os.path.abspath(start).split(os.path.sep)
- path_list = os.path.abspath(path).split(os.path.sep)
-
- # Work out how much of the filepath is shared by start and path.
- i = len(commonprefix([start_list, path_list]))
-
- rel_list = [os.path.pardir] * (len(start_list)-i) + path_list[i:]
- if not rel_list:
- return os.path.curdir
- return os.path.join(*rel_list)
-##############################################################################
-
-
-class WrongNumberOfArguments(Exception):
- pass
-
-
-def Outputs(filename, defines):
- grd = grd_reader.Parse(
- filename, defines=defines, tags_to_ignore=set(['messages']))
-
- target = []
- lang_folders = {}
- # Add all explicitly-specified output files
- for output in grd.GetOutputFiles():
- path = output.GetFilename()
- target.append(path)
-
- if path.endswith('.h'):
- path, filename = os.path.split(path)
- if output.attrs['lang']:
- lang_folders[output.attrs['lang']] = os.path.dirname(path)
-
- # Add all generated files, once for each output language.
- for node in grd:
- if node.name == 'structure':
- # TODO(joi) Should remove the "if sconsdep is true" thing as it is a
- # hack - see grit/node/structure.py
- if node.HasFileForLanguage() and node.attrs['sconsdep'] == 'true':
- for lang in lang_folders:
- path = node.FileForLanguage(lang, lang_folders[lang],
- create_file=False,
- return_if_not_generated=False)
- if path:
- target.append(path)
-
- return [t.replace('\\', '/') for t in target]
-
-
-def GritSourceFiles():
- files = []
- grit_root_dir = relpath(os.path.dirname(__file__), os.getcwd())
- for root, dirs, filenames in os.walk(grit_root_dir):
- grit_src = [os.path.join(root, f) for f in filenames
- if f.endswith('.py')]
- files.extend(grit_src)
- # TODO(joi@chromium.org): Once we switch to specifying the
- # resource_ids file via a .grd attribute, it should be considered an
- # input of grit and this bit should no longer be necessary.
- default_resource_ids = relpath(
- os.path.join(grit_root_dir, '..', 'gritsettings', 'resource_ids'),
- os.getcwd())
- if os.path.exists(default_resource_ids):
- files.append(default_resource_ids)
- return files
-
-
-def Inputs(filename, defines):
- grd = grd_reader.Parse(
- filename, debug=False, defines=defines, tags_to_ignore=set(['messages']))
- files = []
- for node in grd:
- if (node.name == 'structure' or node.name == 'skeleton' or
- (node.name == 'file' and node.parent and
- node.parent.name == 'translations')):
- files.append(node.GetFilePath())
- elif node.name == 'include':
- # Only include files that we actually plan on using.
- if node.SatisfiesOutputCondition():
- files.append(node.FilenameToOpen())
- # If it's a flattened node, grab inlined resources too.
- if node.attrs['flattenhtml'] == 'true':
- files.extend(node.GetHtmlResourceFilenames())
-
- return files
-
-
-def PrintUsage():
- print 'USAGE: ./grit_info.py --inputs [-D foo] <grd-file>'
- print ' ./grit_info.py --outputs [-D foo] <out-prefix> <grd-file>'
-
-
-def DoMain(argv):
- parser = optparse.OptionParser()
- parser.add_option("--inputs", action="store_true", dest="inputs")
- parser.add_option("--outputs", action="store_true", dest="outputs")
- parser.add_option("-D", action="append", dest="defines", default=[])
- # grit build also supports '-E KEY=VALUE', support that to share command
- # line flags.
- parser.add_option("-E", action="append", dest="build_env", default=[])
- parser.add_option("-w", action="append", dest="whitelist_files", default=[])
-
- options, args = parser.parse_args(argv)
-
- defines = {}
- for define in options.defines:
- defines[define] = 1
-
- if options.inputs:
- if len(args) > 1:
- raise WrongNumberOfArguments("Expected 0 or 1 arguments for --inputs.")
-
- inputs = []
- if len(args) == 1:
- filename = args[0]
- inputs = Inputs(filename, defines)
-
- # Add in the grit source files. If one of these change, we want to re-run
- # grit.
- inputs.extend(GritSourceFiles())
- inputs = [f.replace('\\', '/') for f in inputs]
-
- if len(args) == 1:
- # Include grd file as second input (works around gyp expecting it).
- inputs = [inputs[0], args[0]] + inputs[1:]
- if options.whitelist_files:
- inputs.extend(options.whitelist_files)
- return '\n'.join(inputs)
- elif options.outputs:
- if len(args) != 2:
- raise WrongNumberOfArguments("Expected exactly 2 arguments for --ouputs.")
-
- prefix, filename = args
- outputs = [posixpath.join(prefix, f) for f in Outputs(filename, defines)]
- return '\n'.join(outputs)
- else:
- raise WrongNumberOfArguments("Expected --inputs or --outputs.")
-
-
-def main(argv):
- try:
- result = DoMain(argv[1:])
- except WrongNumberOfArguments, e:
- PrintUsage()
- print e
- return 1
- print result
- return 0
-
-
-if __name__ == '__main__':
- sys.exit(main(sys.argv))