diff --git a/scripts/cat_message b/scripts/cat_message deleted file mode 100755 index a99e19627..000000000 --- a/scripts/cat_message +++ /dev/null @@ -1,56 +0,0 @@ -#!/bin/bash -# -# Copyright 2010 Google Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -# This script retrieves the value of a given named string from all indicated -# strings.xml files. If invoked in a project directory (a directory with a -# 'res' subdirectory), and if no strings.xml files are provided, the script -# will automatically analyze res/values*/strings.xml - -PROGNAME=$(basename "$0") - -function usage() { - echo "Usage: ${PROGNAME} string_name [file file..]" >&2 - exit 2 -} - -function die() { - echo "${PROGNAME}: $@" >&2 - exit 1 -} - -if [[ "$#" -lt 1 ]] ; then - usage -fi - -name=$1 -shift - -files= -if [[ $# -eq 0 ]] ; then - if [[ -d res ]] ; then - files=res/values*/strings.xml - else - die "invoked outside of project root with no file arguments" - fi -else - files="$@" -fi - -for file in $files ; do - echo === $file - xmllint --xpath /resources/string[@name=\"$name\"] $file - echo -done diff --git a/scripts/i18n/.project b/scripts/i18n/.project deleted file mode 100644 index c21d8dd65..000000000 --- a/scripts/i18n/.project +++ /dev/null @@ -1,17 +0,0 @@ - - - i18n - - - - - - org.python.pydev.PyDevBuilder - - - - - - org.python.pydev.pythonNature - - diff --git a/scripts/i18n/.pydevproject b/scripts/i18n/.pydevproject deleted file mode 100644 index 94dbecf08..000000000 --- a/scripts/i18n/.pydevproject +++ /dev/null @@ -1,10 +0,0 @@ - - - - -Default -python 2.6 - -/i18n/src - - diff --git a/scripts/i18n/src/mytracks/__init__.py b/scripts/i18n/src/mytracks/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/scripts/i18n/src/mytracks/files.py b/scripts/i18n/src/mytracks/files.py deleted file mode 100644 index 1ec50da8a..000000000 --- a/scripts/i18n/src/mytracks/files.py +++ /dev/null @@ -1,45 +0,0 @@ -''' -Module for dealing with resource files (but not their contents). - -@author: Rodrigo Damazio -''' -import os.path -from glob import glob -import re - -MYTRACKS_RES_DIR = 'MyTracks/res' -ANDROID_MASTER_VALUES = 'values' -ANDROID_VALUES_MASK = 'values-*' - - -def GetMyTracksDir(): - ''' - Returns the directory in which the MyTracks directory is located. - ''' - path = os.getcwd() - while not os.path.isdir(os.path.join(path, MYTRACKS_RES_DIR)): - if path == '/': - raise 'Not in My Tracks project' - - # Go up one level - path = os.path.split(path)[0] - - return path - - -def GetAllLanguageFiles(): - ''' - Returns a mapping from all found languages to their respective directories. - ''' - mytracks_path = GetMyTracksDir() - res_dir = os.path.join(mytracks_path, MYTRACKS_RES_DIR, ANDROID_VALUES_MASK) - language_dirs = glob(res_dir) - master_dir = os.path.join(mytracks_path, MYTRACKS_RES_DIR, ANDROID_MASTER_VALUES) - if len(language_dirs) == 0: - raise 'No languages found!' - if not os.path.isdir(master_dir): - raise 'Couldn\'t find master file' - - language_tuples = [(re.findall(r'.*values-([A-Za-z-]+)', dir)[0],dir) for dir in language_dirs] - language_tuples.append(('en', master_dir)) - return dict(language_tuples) diff --git a/scripts/i18n/src/mytracks/history.py b/scripts/i18n/src/mytracks/history.py deleted file mode 100644 index a585a0105..000000000 --- a/scripts/i18n/src/mytracks/history.py +++ /dev/null @@ -1,94 +0,0 @@ -''' -Module which brings history information about files from Mercurial. - -@author: Rodrigo Damazio -''' - -import re -import subprocess - -REVISION_REGEX = re.compile(r'(?P[0-9a-f]{12}):.*') - -def _GetOutputLines(args): - ''' - Runs an external process and returns its output as a list of lines. - - @param args: the arguments to run - ''' - process = subprocess.Popen(args, - stdout=subprocess.PIPE, - universal_newlines = True, - shell = False) - output = process.communicate()[0] - return output.splitlines() - - -def FillMercurialRevisions(filename, parsed_file): - ''' - Fills the revs attribute of all strings in the given parsed file with - a list of revisions that touched the lines corresponding to that string. - - @param filename: the name of the file to get history for - @param parsed_file: the parsed file to modify - ''' - # Take output of hg annotate to get revision of each line - output_lines = _GetOutputLines(['hg', 'annotate', '-c', filename]) - - # Create a map of line -> revision (key is list index, line 0 doesn't exist) - line_revs = ['dummy'] - for line in output_lines: - rev_match = REVISION_REGEX.match(line) - if not rev_match: - raise 'Unexpected line of output from hg: %s' % line - rev_hash = rev_match.group('hash') - line_revs.append(rev_hash) - - for str in parsed_file.itervalues(): - # Get the lines that correspond to each string - start_line = str['startLine'] - end_line = str['endLine'] - - # Get the revisions that touched those lines - revs = [] - for line_number in range(start_line, end_line + 1): - revs.append(line_revs[line_number]) - - # Merge with any revisions that were already there - # (for explict revision specification) - if 'revs' in str: - revs += str['revs'] - - # Assign the revisions to the string - str['revs'] = frozenset(revs) - -def DoesRevisionSuperceed(filename, rev1, rev2): - ''' - Tells whether a revision superceeds another. - This essentially means that the older revision is an ancestor of the newer - one. - This also returns True if the two revisions are the same. - - @param rev1: the revision that may be superceeding the other - @param rev2: the revision that may be superceeded - @return: True if rev1 superceeds rev2 or they're the same - ''' - if rev1 == rev2: - return True - - # TODO: Add filename - args = ['hg', 'log', '-r', 'ancestors(%s)' % rev1, '--template', '{node|short}\n', filename] - output_lines = _GetOutputLines(args) - - return rev2 in output_lines - -def NewestRevision(filename, rev1, rev2): - ''' - Returns which of two revisions is closest to the head of the repository. - If none of them is the ancestor of the other, then we return either one. - - @param rev1: the first revision - @param rev2: the second revision - ''' - if DoesRevisionSuperceed(filename, rev1, rev2): - return rev1 - return rev2 \ No newline at end of file diff --git a/scripts/i18n/src/mytracks/main.py b/scripts/i18n/src/mytracks/main.py deleted file mode 100755 index 4841c6858..000000000 --- a/scripts/i18n/src/mytracks/main.py +++ /dev/null @@ -1,96 +0,0 @@ -#!/usr/bin/python -''' -Entry point for My Tracks i18n tool. - -@author: Rodrigo Damazio -''' - -import mytracks.files -import mytracks.translate -import mytracks.validate -import sys - -def Usage(): - print 'Usage: %s [ ...]\n' % sys.argv[0] - print 'Commands are:' - print ' cleanup' - print ' translate' - print ' validate' - sys.exit(1) - - -def Translate(languages): - ''' - Asks the user to interactively translate any missing or oudated strings from - the files for the given languages. - - @param languages: the languages to translate - ''' - validator = mytracks.validate.Validator(languages) - validator.Validate() - missing = validator.missing_in_lang() - outdated = validator.outdated_in_lang() - - for lang in languages: - untranslated = missing[lang] + outdated[lang] - - if len(untranslated) == 0: - continue - - translator = mytracks.translate.Translator(lang) - translator.Translate(untranslated) - - -def Validate(languages): - ''' - Computes and displays errors in the string files for the given languages. - - @param languages: the languages to compute for - ''' - validator = mytracks.validate.Validator(languages) - validator.Validate() - - error_count = 0 - if (validator.valid()): - print 'All files OK' - else: - for lang, missing in validator.missing_in_master().iteritems(): - print 'Missing in master, present in %s: %s:' % (lang, str(missing)) - error_count = error_count + len(missing) - for lang, missing in validator.missing_in_lang().iteritems(): - print 'Missing in %s, present in master: %s:' % (lang, str(missing)) - error_count = error_count + len(missing) - for lang, outdated in validator.outdated_in_lang().iteritems(): - print 'Outdated in %s: %s:' % (lang, str(outdated)) - error_count = error_count + len(outdated) - - return error_count - - -if __name__ == '__main__': - argv = sys.argv - argc = len(argv) - if argc < 2: - Usage() - - languages = mytracks.files.GetAllLanguageFiles() - if argc == 3: - langs = set(argv[2:]) - if not langs.issubset(languages): - raise 'Language(s) not found' - - # Filter just to the languages specified - languages = dict((lang, lang_file) - for lang, lang_file in languages.iteritems() - if lang in langs or lang == 'en' ) - - cmd = argv[1] - if cmd == 'translate': - Translate(languages) - elif cmd == 'validate': - error_count = Validate(languages) - else: - Usage() - error_count = 0 - - print '%d errors found.' % error_count diff --git a/scripts/i18n/src/mytracks/parser.py b/scripts/i18n/src/mytracks/parser.py deleted file mode 100644 index 9cfb96de8..000000000 --- a/scripts/i18n/src/mytracks/parser.py +++ /dev/null @@ -1,115 +0,0 @@ -''' -Module which parses a string XML file. - -@author: Rodrigo Damazio -''' - -from xml.parsers.expat import ParserCreate -import re -#import xml.etree.ElementTree as ET - -class StringsParser(object): - ''' - Parser for string XML files. - - This object is not thread-safe and should be used for parsing a single file at - a time, only. - ''' - - def Parse(self, file): - ''' - Parses the given file and returns a dictionary mapping keys to an object - with attributes for that key, such as the value, start/end line and explicit - revisions. - - In addition to the standard XML format of the strings file, this parser - supports an annotation inside comments, in one of these formats: - - - - - Such an annotation indicates that we're explicitly inheriting form the - master file (and the optional revision says that this decision is compatible - with the master file up to that revision). - - @param file: the name of the file to parse - ''' - self._Reset() - - # Unfortunately expat is the only parser that will give us line numbers - self._xml_parser = ParserCreate() - self._xml_parser.StartElementHandler = self._StartElementHandler - self._xml_parser.EndElementHandler = self._EndElementHandler - self._xml_parser.CharacterDataHandler = self._CharacterDataHandler - self._xml_parser.CommentHandler = self._CommentHandler - - file_obj = open(file) - self._xml_parser.ParseFile(file_obj) - file_obj.close() - - return self._all_strings - - def _Reset(self): - self._currentString = None - self._currentStringName = None - self._currentStringValue = None - self._all_strings = {} - - def _StartElementHandler(self, name, attrs): - if name != 'string': - return - - if 'name' not in attrs: - return - - assert not self._currentString - assert not self._currentStringName - self._currentString = { - 'startLine' : self._xml_parser.CurrentLineNumber, - } - - if 'rev' in attrs: - self._currentString['revs'] = [attrs['rev']] - - self._currentStringName = attrs['name'] - self._currentStringValue = '' - - def _EndElementHandler(self, name): - if name != 'string': - return - - assert self._currentString - assert self._currentStringName - self._currentString['value'] = self._currentStringValue - self._currentString['endLine'] = self._xml_parser.CurrentLineNumber - self._all_strings[self._currentStringName] = self._currentString - - self._currentString = None - self._currentStringName = None - self._currentStringValue = None - - def _CharacterDataHandler(self, data): - if not self._currentString: - return - - self._currentStringValue += data - - _KEEP_PARENT_REGEX = re.compile(r'\s*KEEP_PARENT\s+' - r'name\s*=\s*[\'"]?(?P[a-z0-9_]+)[\'"]?' - r'(?:\s+rev=[\'"]?(?P[0-9a-f]{12})[\'"]?)?\s*', - re.MULTILINE | re.DOTALL) - - def _CommentHandler(self, data): - keep_parent_match = self._KEEP_PARENT_REGEX.match(data) - if not keep_parent_match: - return - - name = keep_parent_match.group('name') - self._all_strings[name] = { - 'keepParent' : True, - 'startLine' : self._xml_parser.CurrentLineNumber, - 'endLine' : self._xml_parser.CurrentLineNumber - } - rev = keep_parent_match.group('rev') - if rev: - self._all_strings[name]['revs'] = [rev] \ No newline at end of file diff --git a/scripts/i18n/src/mytracks/translate.py b/scripts/i18n/src/mytracks/translate.py deleted file mode 100644 index 5e6e45a86..000000000 --- a/scripts/i18n/src/mytracks/translate.py +++ /dev/null @@ -1,21 +0,0 @@ -''' -Module which prompts the user for translations and saves them. - -TODO: implement - -@author: Rodrigo Damazio -''' - -class Translator(object): - ''' - classdocs - ''' - - def __init__(self, language): - ''' - Constructor - ''' - self._language = language - - def Translate(self, string_names): - print string_names \ No newline at end of file diff --git a/scripts/i18n/src/mytracks/validate.py b/scripts/i18n/src/mytracks/validate.py deleted file mode 100644 index ba99b8f27..000000000 --- a/scripts/i18n/src/mytracks/validate.py +++ /dev/null @@ -1,115 +0,0 @@ -''' -Module which compares languague files to the master file and detects -issues. - -@author: Rodrigo Damazio -''' - -import os -from mytracks.parser import StringsParser -import mytracks.history - -class Validator(object): - - def __init__(self, languages): - ''' - Builds a strings file validator. - - Params: - @param languages: a dictionary mapping each language to its corresponding directory - ''' - self._langs = {} - self._master = None - self._language_paths = languages - - parser = StringsParser() - for lang, lang_dir in languages.iteritems(): - filename = os.path.join(lang_dir, 'strings.xml') - parsed_file = parser.Parse(filename) - mytracks.history.FillMercurialRevisions(filename, parsed_file) - - if lang == 'en': - self._master = parsed_file - else: - self._langs[lang] = parsed_file - - self._Reset() - - def Validate(self): - ''' - Computes whether all the data in the files for the given languages is valid. - ''' - self._Reset() - self._ValidateMissingKeys() - self._ValidateOutdatedKeys() - - def valid(self): - return (len(self._missing_in_master) == 0 and - len(self._missing_in_lang) == 0 and - len(self._outdated_in_lang) == 0) - - def missing_in_master(self): - return self._missing_in_master - - def missing_in_lang(self): - return self._missing_in_lang - - def outdated_in_lang(self): - return self._outdated_in_lang - - def _Reset(self): - # These are maps from language to string name list - self._missing_in_master = {} - self._missing_in_lang = {} - self._outdated_in_lang = {} - - def _ValidateMissingKeys(self): - ''' - Computes whether there are missing keys on either side. - ''' - master_keys = frozenset(self._master.iterkeys()) - for lang, file in self._langs.iteritems(): - keys = frozenset(file.iterkeys()) - missing_in_master = keys - master_keys - missing_in_lang = master_keys - keys - - if len(missing_in_master) > 0: - self._missing_in_master[lang] = missing_in_master - if len(missing_in_lang) > 0: - self._missing_in_lang[lang] = missing_in_lang - - def _ValidateOutdatedKeys(self): - ''' - Computers whether any of the language keys are outdated with relation to the - master keys. - ''' - for lang, file in self._langs.iteritems(): - outdated = [] - for key, str in file.iteritems(): - # Get all revisions that touched master and language files for this - # string. - master_str = self._master[key] - master_revs = master_str['revs'] - lang_revs = str['revs'] - if not master_revs or not lang_revs: - print 'WARNING: No revision for %s in %s' % (key, lang) - continue - - master_file = os.path.join(self._language_paths['en'], 'strings.xml') - lang_file = os.path.join(self._language_paths[lang], 'strings.xml') - - # Assume that the repository has a single head (TODO: check that), - # and as such there is always one revision which superceeds all others. - master_rev = reduce( - lambda r1, r2: mytracks.history.NewestRevision(master_file, r1, r2), - master_revs) - lang_rev = reduce( - lambda r1, r2: mytracks.history.NewestRevision(lang_file, r1, r2), - lang_revs) - - # If the master version is newer than the lang version - if mytracks.history.DoesRevisionSuperceed(lang_file, master_rev, lang_rev): - outdated.append(key) - - if len(outdated) > 0: - self._outdated_in_lang[lang] = outdated