X-Git-Url: https://git.donarmstrong.com/?a=blobdiff_plain;f=buildscripts%2Ftranslations-status.py;h=4180ea86722c925bc4250e61311a4832735a0c34;hb=377e93f7919c32e0f35c1f5c885e8704cbcf15b0;hp=7a8d8bb225330c1232fb5239160c8e1ce65802c9;hpb=f83a9dd82ba51e4a1be1c5417226653c760671d2;p=lilypond.git diff --git a/buildscripts/translations-status.py b/buildscripts/translations-status.py old mode 100644 new mode 100755 index 7a8d8bb225..4180ea8672 --- a/buildscripts/translations-status.py +++ b/buildscripts/translations-status.py @@ -1,4 +1,4 @@ -#!@PYTHON@ +#!/usr/bin/env python """ USAGE: translations-status.py BUILDSCRIPT-DIR LOCALEDIR @@ -17,53 +17,55 @@ import sys import re import string import os -import gettext + +import langdefs +import buildlib def progress (str): sys.stderr.write (str + '\n') progress ("translations-status.py") -buildscript_dir = sys.argv[1] -localedir = sys.argv[2] - _doc = lambda s: s -sys.path.append (buildscript_dir) -import langdefs -import buildlib - # load gettext messages catalogs -translation = {} -for l in langdefs.LANGUAGES: - if l.enabled and l.code != 'en': - translation[l.code] = gettext.translation('lilypond-doc', localedir, [l.code]).gettext +translation = langdefs.translation +language_re = re.compile (r'^@documentlanguage (.+)', re.M) comments_re = re.compile (r'^@ignore\n(.|\n)*?\n@end ignore$|@c .*?$', re.M) space_re = re.compile (r'\s+', re.M) lilypond_re = re.compile (r'@lilypond({.*?}|(.|\n)*?\n@end lilypond$)', re.M) node_re = re.compile ('^@node .*?$', re.M) -title_re = re.compile ('^@(top|chapter|(?:sub){0,2}section|(?:unnumbered|appendix)(?:(?:sub){0,2}sec)?) (.*?)$', re.M) +title_re = re.compile ('^@(top|chapter|(?:sub){0,2}section|' + \ +'(?:unnumbered|appendix)(?:(?:sub){0,2}sec)?) (.*?)$', re.M) include_re = re.compile ('^@include (.*?)$', re.M) translators_re = re.compile (r'^@c\s+Translators\s*:\s*(.*?)$', re.M | re.I) -checkers_re = re.compile (r'^@c\s+Translation\s*checkers\s*:\s*(.*?)$', re.M | re.I) +checkers_re = re.compile (r'^@c\s+Translation\s*checkers\s*:\s*(.*?)$', + re.M | re.I) status_re = re.compile (r'^@c\s+Translation\s*status\s*:\s*(.*?)$', re.M | re.I) post_gdp_re = re.compile ('post.GDP', re.I) -untranslated_node_str = 'UNTRANSLATED NODE: IGNORE ME' +untranslated_node_str = '@untranslated' skeleton_str = '-- SKELETON FILE --' +section_titles_string = _doc ('Section titles') +last_updated_string = _doc ('

Last updated %s

\n') +detailed_status_heads = [_doc ('Translators'), _doc ('Translation checkers'), + _doc ('Translated'), _doc ('Up to date'), + _doc ('Other info')] format_table = { 'not translated': {'color':'d0f0f8', 'short':_doc ('no'), 'abbr':'NT', 'long':_doc ('not translated')}, - 'partially translated': {'color':'dfef77', 'short':_doc ('partially (%(p)d %%)'), - 'abbr':'%(p)d%%', 'long':_doc ('partially translated (%(p)d %%)')}, + 'partially translated': {'color':'dfef77', + 'short':_doc ('partially (%(p)d %%)'), + 'abbr':'%(p)d%%', + 'long':_doc ('partially translated (%(p)d %%)')}, 'fully translated': {'color':'1fff1f', 'short':_doc ('yes'), 'abbr':'FT', 'long': _doc ('translated')}, - 'up to date': {'short':_doc ('yes'), 'long':_doc ('up to date'), 'abbr':'100%%', - 'vague':_doc ('up to date')}, - 'outdated': {'short':_doc ('partially (%(p)d %%)'), 'abbr':'%(p)d%%', + 'up to date': {'short':_doc ('yes'), 'long':_doc ('up to date'), + 'abbr':'100%%', 'vague':_doc ('up to date')}, + 'outdated': {'short':_doc ('partially'), 'abbr':'%(p)d%%', 'vague':_doc ('partially up to date')}, 'N/A': {'short':_doc ('N/A'), 'abbr':'N/A', 'color':'d587ff', 'vague':''}, 'pre-GDP':_doc ('pre-GDP'), @@ -92,7 +94,8 @@ class SectionNumber (object): def __increase_last_index (self): type = self.__data[-1][1] if type == 'l': - self.__data[-1][0] = self.__data[-1][0].translate (appendix_number_trans) + self.__data[-1][0] = \ + self.__data[-1][0].translate (appendix_number_trans) elif type == 'n': self.__data[-1][0] += 1 @@ -124,11 +127,14 @@ class SectionNumber (object): def percentage_color (percent): p = percent / 100.0 if p < 0.33: - c = [hex (int (3 * p * b + (1 - 3 * p) * a))[2:] for (a, b) in [(0xff, 0xff), (0x5c, 0xa6), (0x5c, 0x4c)]] + c = [hex (int (3 * p * b + (1 - 3 * p) * a))[2:] + for (a, b) in [(0xff, 0xff), (0x5c, 0xa6), (0x5c, 0x4c)]] elif p < 0.67: - c = [hex (int ((3 * p - 1) * b + (2 - 3 * p) * a))[2:] for (a, b) in [(0xff, 0xff), (0xa6, 0xff), (0x4c, 0x3d)]] + c = [hex (int ((3 * p - 1) * b + (2 - 3 * p) * a))[2:] + for (a, b) in [(0xff, 0xff), (0xa6, 0xff), (0x4c, 0x3d)]] else: - c = [hex (int ((3 * p - 2) * b + 3 * (1 - p) * a))[2:] for (a, b) in [(0xff, 0x1f), (0xff, 0xff), (0x3d, 0x1f)]] + c = [hex (int ((3 * p - 2) * b + 3 * (1 - p) * a))[2:] + for (a, b) in [(0xff, 0x1f), (0xff, 0xff), (0x3d, 0x1f)]] return ''.join (c) @@ -178,7 +184,12 @@ class TelyDocument (object): self.title = 'Untitled' self.level = ('u', 1) - included_files = [os.path.join (os.path.dirname (filename), t) for t in include_re.findall (self.contents)] + m = language_re.search (self.contents) + if m: + self.language = m.group (1) + + included_files = [os.path.join (os.path.dirname (filename), t) + for t in include_re.findall (self.contents)] self.included_files = [p for p in included_files if os.path.exists (p)] def print_title (self, section_number): @@ -190,6 +201,14 @@ class TranslatedTelyDocument (TelyDocument): TelyDocument.__init__ (self, filename) self.masterdocument = masterdocument + if not hasattr (self, 'language') \ + and hasattr (parent_translation, 'language'): + self.language = parent_translation.language + if hasattr (self, 'language'): + self.translation = translation[self.language] + else: + self.translation = lambda x: x + self.title = self.translation (self.title) ## record authoring information m = translators_re.search (self.contents) @@ -219,33 +238,47 @@ class TranslatedTelyDocument (TelyDocument): ## calculate translation percentage master_total_word_count = sum (masterdocument.word_count) - translation_word_count = sum ([masterdocument.word_count[k] * self.translated_nodes[k] - for k in range (min (len (masterdocument.word_count), len (self.translated_nodes)))]) - self.translation_percentage = 100 * translation_word_count / master_total_word_count + translation_word_count = \ + sum ([masterdocument.word_count[k] * self.translated_nodes[k] + for k in range (min (len (masterdocument.word_count), + len (self.translated_nodes)))]) + self.translation_percentage = \ + 100 * translation_word_count / master_total_word_count ## calculate how much the file is outdated - (diff_string, error) = buildlib.check_translated_doc (masterdocument.filename, self.contents) + (diff_string, error) = \ + buildlib.check_translated_doc (masterdocument.filename, self.contents) if error: sys.stderr.write ('warning: %s: %s' % (self.filename, error)) self.uptodate_percentage = None else: diff = diff_string.splitlines () - insertions = sum ([len (l) - 1 for l in diff if l.startswith ('+') and not l.startswith ('+++')]) - deletions = sum ([len (l) - 1 for l in diff if l.startswith ('-') and not l.startswith ('---')]) - outdateness_percentage = 50.0 * (deletions + insertions) / (masterdocument.size + 0.5 * (deletions - insertions)) + insertions = sum ([len (l) - 1 for l in diff + if l.startswith ('+') + and not l.startswith ('+++')]) + deletions = sum ([len (l) - 1 for l in diff + if l.startswith ('-') + and not l.startswith ('---')]) + outdateness_percentage = 50.0 * (deletions + insertions) / \ + (masterdocument.size + 0.5 * (deletions - insertions)) self.uptodate_percentage = 100 - int (outdateness_percentage) if self.uptodate_percentage > 100: alternative = 50 - progress ("%s: strange uptodateness percentage %d %%, setting to %d %%" \ - % (self.filename, self.uptodate_percentage, alternative)) + progress ("%s: strange uptodateness percentage %d %%, \ +setting to %d %%" % (self.filename, self.uptodate_percentage, alternative)) self.uptodate_percentage = alternative elif self.uptodate_percentage < 1: alternative = 1 - progress ("%s: strange uptodateness percentage %d %%, setting to %d %%" \ - % (self.filename, self.uptodate_percentage, alternative)) + progress ("%s: strange uptodateness percentage %d %%, \ +setting to %d %%" % (self.filename, self.uptodate_percentage, alternative)) self.uptodate_percentage = alternative - def completeness (self, formats=['long']): + def completeness (self, formats=['long'], translated=False): + if translated: + translation = self.translation + else: + translation = lambda x: x + if isinstance (formats, str): formats = [formats] p = self.translation_percentage @@ -255,9 +288,15 @@ class TranslatedTelyDocument (TelyDocument): status = 'fully translated' else: status = 'partially translated' - return dict ([(f, format_table[status][f] % locals()) for f in formats]) + return dict ([(f, translation (format_table[status][f]) % locals()) + for f in formats]) + + def uptodateness (self, formats=['long'], translated=False): + if translated: + translation = self.translation + else: + translation = lambda x: x - def uptodateness (self, formats=['long']): if isinstance (formats, str): formats = [formats] p = self.uptodate_percentage @@ -272,28 +311,31 @@ class TranslatedTelyDocument (TelyDocument): if f == 'color' and p != None: l['color'] = percentage_color (p) else: - l[f] = format_table[status][f] % locals () + l[f] = translation (format_table[status][f]) % locals () return l - def gdp_status (self, translation=lambda s: s): + def gdp_status (self): if self.post_gdp: - return translation (format-table['post-GDP']) + return self.translation (format_table['post-GDP']) else: - return translation (format-table['pre-GDP']) + return self.translation (format_table['pre-GDP']) def short_html_status (self): s = ' ' if self.partially_translated: s += '
\n '.join (self.translators) + '
\n' if self.checkers: - s += ' ' + '
\n '.join (self.checkers) + '

\n' + s += ' ' + \ + '
\n '.join (self.checkers) + '

\n' c = self.completeness (['color', 'long']) - s += ' %(long)s
\n' % c + s += ' \ +%(long)s
\n' % c if self.partially_translated: u = self.uptodateness (['vague', 'color']) - s += ' %(vague)s
\n' % u + s += ' \ +%(vague)s
\n' % u s += ' \n' return s @@ -305,20 +347,73 @@ class TranslatedTelyDocument (TelyDocument): s += self.uptodateness ('abbr')['abbr'] + ' ' return s - def html_status (self): - # TODO - return '' + def html_status (self, numbering=SectionNumber ()): + if self.title == 'Untitled': + return '' + + if self.level[1] == 0: # if self is a master document + s = ''' + + ''' % self.print_title (numbering) + s += ''.join ([' \n' % self.translation (h) + for h in detailed_status_heads]) + s += ' \n' + s += ' \n \n' \ + % (self.translation (section_titles_string), + sum (self.masterdocument.word_count)) + + else: + s = ' \n \n' \ + % (self.print_title (numbering), + sum (self.masterdocument.word_count)) + + if self.partially_translated: + s += ' \n' + s += ' \n' + else: + s += ' \n' * 2 + + c = self.completeness (['color', 'short'], translated=True) + s += ' \n' % {'color': c['color'], + 'short': c['short']} + + if self.partially_translated: + u = self.uptodateness (['short', 'color'], translated=True) + s += ' \n' % {'color': u['color'], + 'short': u['short']} + else: + s += ' \n' + + s += ' \n \n' + s += ''.join ([i.translations[self.language].html_status (numbering) + for i in self.masterdocument.includes + if self.language in i.translations]) + + if self.level[1] == 0: # if self is a master document + s += '
%s%s
%s
(%d)
%s
(%d)
' + '
\n '.join (self.translators) + '
' + '
\n '.join (self.checkers) + '
\ +%(short)s\ +%(short)s' + self.gdp_status () + '
\n

\n' + return s class MasterTelyDocument (TelyDocument): - def __init__ (self, filename, parent_translations=dict ([(lang, None) for lang in langdefs.LANGDICT.keys()])): + def __init__ (self, + filename, + parent_translations=dict ([(lang, None) + for lang in langdefs.LANGDICT])): TelyDocument.__init__ (self, filename) self.size = len (self.contents) self.word_count = tely_word_count (self.contents) - translations = dict ([(lang, os.path.join (lang, filename)) for lang in langdefs.LANGDICT.keys()]) - self.translations = dict ([(lang, TranslatedTelyDocument (translations[lang], self, parent_translations.get (lang))) - for lang in langdefs.LANGDICT.keys() if os.path.exists (translations[lang])]) + translations = dict ([(lang, os.path.join (lang, filename)) + for lang in langdefs.LANGDICT]) + self.translations = \ + dict ([(lang, + TranslatedTelyDocument (translations[lang], + self, parent_translations.get (lang))) + for lang in langdefs.LANGDICT + if os.path.exists (translations[lang])]) if self.translations: - self.includes = [MasterTelyDocument (f, self.translations) for f in self.included_files] + self.includes = [MasterTelyDocument (f, self.translations) + for f in self.included_files] else: self.includes = [] @@ -335,20 +430,21 @@ class MasterTelyDocument (TelyDocument): s = '''''' % self.print_title (numbering) - s += ''.join ([' \n' % l for l in self.translations.keys ()]) + s += ''.join ([' \n' % l for l in self.translations]) s += ' \n' s += ' \n \n' \ % sum (self.word_count) - else: + else: # if self is an included file s = ' \n \n' \ % (self.print_title (numbering), sum (self.word_count)) - s += ''.join ([t.short_html_status () for t in self.translations.values ()]) + s += ''.join ([t.short_html_status () + for t in self.translations.values ()]) s += ' \n' s += ''.join ([i.html_status (numbering) for i in self.includes]) - if self.level[1] == 0: + if self.level[1] == 0: # if self is a master document s += '
%s%s%s
Section titles
(%d)
%s
(%d)
\n

\n' return s @@ -359,16 +455,19 @@ class MasterTelyDocument (TelyDocument): s = '' if self.level[1] == 0: # if self is a master document s += (self.print_title (numbering) + ' ').ljust (colspec[0]) - s += ''.join (['%s'.ljust (colspec[1]) % l for l in self.translations.keys ()]) + s += ''.join (['%s'.ljust (colspec[1]) % l + for l in self.translations]) s += '\n' - s += ('Section titles (%d)' % sum (self.word_count)).ljust (colspec[0]) + s += ('Section titles (%d)' % \ + sum (self.word_count)).ljust (colspec[0]) else: s = '%s (%d) ' \ % (self.print_title (numbering), sum (self.word_count)) s = s.ljust (colspec[0]) - s += ''.join ([t.text_status ().ljust(colspec[1]) for t in self.translations.values ()]) + s += ''.join ([t.text_status ().ljust(colspec[1]) + for t in self.translations.values ()]) s += '\n\n' s += ''.join ([i.text_status (numbering) for i in self.includes]) @@ -383,40 +482,61 @@ counts_re = re.compile (r'(?m)^(\d+) ') def update_category_word_counts_sub (m): return '-' + m.group (1) + '-' + m.group (2) + \ - str (sum ([int (c) for c in counts_re.findall (m.group (2))])).ljust (6) + 'total' + str (sum ([int (c) + for c in counts_re.findall (m.group (2))])).ljust (6) + \ + 'total' progress ("Reading documents...") -tely_files = buildlib.read_pipe ("find -maxdepth 2 -name '*.tely'")[0].splitlines () -master_docs = [MasterTelyDocument (os.path.normpath (filename)) for filename in tely_files] +tely_files = \ + buildlib.read_pipe ("find -maxdepth 2 -name '*.tely'")[0].splitlines () +tely_files.sort () +master_docs = [MasterTelyDocument (os.path.normpath (filename)) + for filename in tely_files] master_docs = [doc for doc in master_docs if doc.translations] main_status_page = open ('translations.template.html.in').read () -## TODO -#per_lang_status_pages = dict ([(l, open (os.path.join (l, 'translations.template.html')). read ()) -# for l in langdefs.LANGDICT.keys () -# if langdefs.LANGDICT[l].enabled]) +enabled_languages = [l for l in langdefs.LANGDICT + if langdefs.LANGDICT[l].enabled + and l != 'en'] +lang_status_pages = \ + dict ([(l, open (os.path.join (l, 'translations.template.html.in')). read ()) + for l in enabled_languages]) progress ("Generating status pages...") date_time = buildlib.read_pipe ('LANG= date -u')[0] -main_status_html = '

Last updated %s

\n' % date_time +main_status_html = last_updated_string % date_time main_status_html += '\n'.join ([doc.html_status () for doc in master_docs]) html_re = re.compile ('', re.I) end_body_re = re.compile ('', re.I) -main_status_page = html_re.sub (''' +html_header = ''' ''', main_status_page) +translations.template.html.in; DO NOT EDIT !-->''' -main_status_page = end_body_re.sub (main_status_html + '\n', main_status_page) +main_status_page = html_re.sub (html_header, main_status_page) + +main_status_page = end_body_re.sub (main_status_html + '\n', + main_status_page) open ('translations.html.in', 'w').write (main_status_page) +for l in enabled_languages: + date_time = buildlib.read_pipe ('LANG=%s date -u' % l)[0] + lang_status_pages[l] = translation[l] (last_updated_string) % date_time + lang_status_pages[l] + lang_status_page = html_re.sub (html_header, lang_status_pages[l]) + html_status = '\n'.join ([doc.translations[l].html_status () + for doc in master_docs + if l in doc.translations]) + lang_status_page = end_body_re.sub (html_status + '\n', + lang_status_page) + open (os.path.join (l, 'translations.html.in'), 'w').write (lang_status_page) + main_status_txt = '''Documentation translations status Generated %s NT = not translated @@ -437,19 +557,22 @@ translation_instructions = open (translation_instructions_file).read () for doc in master_docs: translation_instructions = doc.update_word_counts (translation_instructions) -for html_file in re.findall (r'(?m)^\d+ *(\S+?\.html\S*?)(?: |$)', translation_instructions): +for html_file in re.findall (r'(?m)^\d+ *(\S+?\.html\S*?)(?: |$)', + translation_instructions): word_count = sgml_word_count (open (html_file).read ()) translation_instructions = update_word_count (translation_instructions, html_file, word_count) -for po_file in re.findall (r'(?m)^\d+ *(\S+?\.po\S*?)(?: |$)', translation_instructions): +for po_file in re.findall (r'(?m)^\d+ *(\S+?\.po\S*?)(?: |$)', + translation_instructions): word_count = po_word_count (open (po_file).read ()) translation_instructions = update_word_count (translation_instructions, po_file, word_count) -translation_instructions = update_category_word_counts_re.sub (update_category_word_counts_sub, - translation_instructions) +translation_instructions = \ + update_category_word_counts_re.sub (update_category_word_counts_sub, + translation_instructions) open (translation_instructions_file, 'w').write (translation_instructions)