2 # -----------------------------------------------------------------------
3 # Copyright (C) 2008 Laurentian University
4 # Dan Scott <dscott@laurentian.ca>
6 # This program is free software; you can redistribute it and/or
7 # modify it under the terms of the GNU General Public License
8 # as published by the Free Software Foundation; either version 2
9 # of the License, or (at your option) any later version.
11 # This program is distributed in the hope that it will be useful,
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 # GNU General Public License for more details.
15 # -----------------------------------------------------------------------
17 # vim:et:sw=4:ts=4: set fileencoding=utf-8 :
20 Parse i18n properties files and XUL / JavaScript files looking for trouble
32 '../../../Open-ILS/xul/staff_client/server/locale/en-US/',
33 '../../../Open-ILS/xul/staff_client/chrome/locale/en-US/'
37 '../../../Open-ILS/xul/staff_client/server/',
38 '../../../Open-ILS/xul/staff_client/chrome/',
41 def parse_properties():
43 Parse the properties files in known places
46 basedir = os.path.normpath(os.path.dirname(os.path.abspath(__file__)))
52 for p_dir in PROP_DIRS:
53 p_dir = os.path.normpath(os.path.join(basedir, p_dir))
54 file_list = os.listdir(p_dir)
55 for p_file in file_list:
56 if os.path.splitext(p_file)[1] == '.properties':
57 prop_files.append(os.path.join(p_dir, p_file))
59 prefix = os.path.commonprefix(prop_files)
61 for p_file in prop_files:
63 # Get the shortest unique address for this file
64 short_pf = p_file[len(prefix):]
66 prop_file = open(p_file, 'r')
70 for line in prop_file:
73 # Get rid of trailing linefeed
77 if not line or line[0] == '#':
80 # Split property/value on first = sign
81 unpack = re.split('=', line, 1)
83 # If a line doesn't have an = sign, is that okay (run-on from previous?) or illegal?
84 # I think it's illegal
86 print("%s:%d: No property in line [%s]" % (short_pf, line_num, line))
89 prop_key, value = unpack
91 if not properties.has_key(prop_key):
92 properties[prop_key] = [{'value': value, 'file': short_pf}]
95 for entry in properties[prop_key]:
96 if ['file'] == short_pf:
97 print("%s:%d: Duplicate key '%s' in line [%s]" % (short_pf, line_num, prop_key, line[0:-1]))
100 properties[prop_key].append({'value': value, 'file': short_pf})
106 def check_xul_files(props):
108 Finds all the XUL and JavaScript files
111 basedir = os.path.normpath(os.path.dirname(os.path.abspath(__file__)))
115 for x_dir in XUL_DIRS:
116 for root, dirs, files in os.walk(os.path.join(basedir, x_dir)):
118 if os.path.splitext(x_file)[1] == '.xul' or os.path.splitext(x_file)[1] == '.js':
119 check_xul(root, x_file, props)
121 def check_xul(root, filename, props):
123 Parse all getString() and getFormattedString() calls in XUL and JavaScript
125 * that the requested property exists
126 * that every property is actually required
131 # Typical example of a getString request:
132 # document.getElementById('catStrings').getString('staff.cat.bib_brief.deleted')
133 strings = re.compile(r'''\(\s*?(['"])([^'"]+?)Strings\1\s*?\)\.getString\(\s*?(['"])([^'"]+?)\3\s*?\)''')
135 # Typical example of a getFormattedString request:
136 # document.getElementById('catStrings').getFormattedString('staff.cat.bib_brief.record_id', [docid])
137 formed_strings = re.compile(r'''\(\s*?(['"])([^'"]+?)Strings\1\s*?\)\.getFormattedString\(\s*?(['"])([^'"]+?)\3\s*?,\s*\[(.+?)\]\s*\)\)''')
139 xul = open(os.path.join(root, filename), 'r')
144 print "File: %s" % (os.path.normpath(os.path.join(root, filename)))
146 for s_match in strings.finditer(content):
148 #print "\tStringset: %s ID: %s" % (s_match.group(2), s_match.group(4))
149 if not props.has_key(s_match.group(4)):
150 print "File: %s" % (os.path.normpath(os.path.join(root, filename)))
151 print "\tID %s not found, expected in %sStrings" % (s_match.group(4), s_match.group(2))
153 for s_match in formed_strings.finditer(content):
155 #print "\tStringset: %s ID: %s, data: %s" % (s_match.group(2), s_match.group(4), s_match.group(5))
156 if not props.has_key(s_match.group(4)):
157 print "File: %s" % (os.path.normpath(os.path.join(root, filename)))
158 print "\tID %s not found, expected in %sStrings" % (s_match.group(4), s_match.group(2))
161 print "\t%d i18n calls found" % (num_strings)
163 if __name__ == '__main__':
164 props = parse_properties()
165 check_xul_files(props)