<s> from collections import defaultdict , OrderedDict <EOL> from django . utils . encoding import force_text <EOL> from django . utils . safestring import mark_safe <EOL> from lxml import etree <EOL> import copy <EOL> import re <EOL> from lxml . etree import XMLSyntaxError , Element <EOL> from openpyxl . utils . exceptions import InvalidFileException <EOL> from corehq . apps . app_manager . exceptions import ( <EOL> FormNotFoundException , <EOL> ModuleNotFoundException , <EOL> XFormException ) <EOL> from corehq . apps . app_manager . models import ReportModule <EOL> from corehq . apps . app_manager . util import save_xform <EOL> from corehq . apps . app_manager . xform import namespaces , WrappedNode , ItextValue , ItextOutput <EOL> from corehq . util . spreadsheets . excel import HeaderValueError , WorkbookJSONReader <EOL> from django . contrib import messages <EOL> from django . utils . translation import ugettext as _ <EOL> def get_unicode_dicts ( iterable ) : <EOL> """<STR_LIT>""" <EOL> def none_or_unicode ( val ) : <EOL> return unicode ( val ) if val is not None else val <EOL> rows = [ ] <EOL> for row in iterable : <EOL> rows . append ( { unicode ( k ) : none_or_unicode ( v ) for k , v in row . iteritems ( ) } ) <EOL> return rows <EOL> def process_bulk_app_translation_upload ( app , f ) : <EOL> """<STR_LIT>""" <EOL> msgs = [ ] <EOL> headers = expected_bulk_app_sheet_headers ( app ) <EOL> expected_sheets = { h [ <NUM_LIT:0> ] : h [ <NUM_LIT:1> ] for h in headers } <EOL> processed_sheets = set ( ) <EOL> try : <EOL> workbook = WorkbookJSONReader ( f ) <EOL> except ( HeaderValueError , InvalidFileException ) as e : <EOL> msgs . append ( <EOL> ( messages . error , _ ( <EOL> "<STR_LIT>" <EOL> "<STR_LIT>" <EOL> "<STR_LIT>" <EOL> ) . format ( e ) ) <EOL> ) <EOL> return msgs <EOL> for sheet in workbook . worksheets : <EOL> rows = get_unicode_dicts ( sheet ) <EOL> if sheet . worksheet . title in processed_sheets : <EOL> msgs . append ( ( <EOL> messages . error , <EOL> '<STR_LIT>' + <EOL> '<STR_LIT>' % <EOL> sheet . worksheet . title <EOL> ) ) <EOL> continue <EOL> expected_columns = expected_sheets . get ( sheet . worksheet . title , None ) <EOL> if expected_columns is None : <EOL> msgs . append ( ( <EOL> messages . error , <EOL> '<STR_LIT>' % <EOL> sheet . worksheet . title <EOL> ) ) <EOL> continue <EOL> if sheet . worksheet . title == "<STR_LIT>" : <EOL> if expected_columns [ <NUM_LIT:1> ] not in sheet . headers : <EOL> msgs . append ( ( <EOL> messages . error , <EOL> '<STR_LIT>' % <EOL> ( sheet . worksheet . title , expected_columns [ <NUM_LIT:1> ] ) <EOL> ) ) <EOL> continue <EOL> elif expected_columns [ <NUM_LIT:0> ] == "<STR_LIT>" : <EOL> if ( expected_columns [ <NUM_LIT:0> ] not in sheet . headers <EOL> or expected_columns [ <NUM_LIT:1> ] not in sheet . headers ) : <EOL> msgs . append ( ( <EOL> messages . error , <EOL> '<STR_LIT>' <EOL> '<STR_LIT>' % sheet . worksheet . title <EOL> ) ) <EOL> continue <EOL> else : <EOL> if expected_columns [ <NUM_LIT:0> ] not in sheet . headers : <EOL> msgs . append ( ( <EOL> messages . error , <EOL> '<STR_LIT>' % <EOL> sheet . worksheet . title <EOL> ) ) <EOL> continue <EOL> processed_sheets . add ( sheet . worksheet . title ) <EOL> missing_cols = set ( expected_columns ) - set ( sheet . headers ) <EOL> if len ( missing_cols ) > <NUM_LIT:0> : <EOL> msgs . append ( ( <EOL> messages . warning , <EOL> '<STR_LIT>' <EOL> '<STR_LIT>' <EOL> '<STR_LIT>' <EOL> % ( sheet . worksheet . title , "<STR_LIT>" . join ( missing_cols ) ) <EOL> ) ) <EOL> extra_cols = set ( sheet . headers ) - set ( expected_columns ) <EOL> if len ( extra_cols ) > <NUM_LIT:0> : <EOL> msgs . append ( ( <EOL> messages . warning , <EOL> '<STR_LIT>' <EOL> '<STR_LIT>' <EOL> % ( sheet . worksheet . title , "<STR_LIT>" . join ( extra_cols ) ) <EOL> ) ) <EOL> if sheet . worksheet . title == "<STR_LIT>" : <EOL> ms = process_modules_and_forms_sheet ( rows , app ) <EOL> msgs . extend ( ms ) <EOL> elif sheet . headers [ <NUM_LIT:0> ] == "<STR_LIT>" : <EOL> ms = update_case_list_translations ( sheet , rows , app ) <EOL> msgs . extend ( ms ) <EOL> else : <EOL> ms = update_form_translations ( sheet , rows , missing_cols , app ) <EOL> msgs . extend ( ms ) <EOL> msgs . append ( <EOL> ( messages . success , _ ( "<STR_LIT>" ) ) <EOL> ) <EOL> return msgs <EOL> def make_modules_and_forms_row ( row_type , sheet_name , languages , case_labels , <EOL> media_image , media_audio , unique_id ) : <EOL> """<STR_LIT>""" <EOL> assert row_type is not None <EOL> assert sheet_name is not None <EOL> assert isinstance ( languages , list ) <EOL> assert isinstance ( case_labels , list ) <EOL> assert isinstance ( media_image , list ) <EOL> assert isinstance ( media_audio , list ) <EOL> assert isinstance ( unique_id , basestring ) <EOL> return [ item if item is not None else "<STR_LIT>" <EOL> for item in ( [ row_type , sheet_name ] + languages + case_labels <EOL> + media_image + media_audio + [ unique_id ] ) ] <EOL> def expected_bulk_app_sheet_headers ( app ) : <EOL> '''<STR_LIT>''' <EOL> languages_list = [ '<STR_LIT>' + l for l in app . langs ] <EOL> audio_lang_list = [ '<STR_LIT>' + l for l in app . langs ] <EOL> image_lang_list = [ '<STR_LIT>' + l for l in app . langs ] <EOL> video_lang_list = [ '<STR_LIT>' + l for l in app . langs ] <EOL> headers = [ ] <EOL> headers . append ( [ <EOL> "<STR_LIT>" , <EOL> make_modules_and_forms_row ( <EOL> row_type = '<STR_LIT>' , <EOL> sheet_name = '<STR_LIT>' , <EOL> languages = languages_list , <EOL> case_labels = [ '<STR_LIT>' % l for l in app . langs ] , <EOL> media_image = [ '<STR_LIT>' % l for l in app . langs ] , <EOL> media_audio = [ '<STR_LIT>' % l for l in app . langs ] , <EOL> unique_id = '<STR_LIT>' , <EOL> ) <EOL> ] ) <EOL> for mod_index , module in enumerate ( app . get_modules ( ) ) : <EOL> module_string = "<STR_LIT>" + str ( mod_index + <NUM_LIT:1> ) <EOL> headers . append ( [ module_string , [ '<STR_LIT>' , '<STR_LIT>' ] + languages_list ] ) <EOL> for form_index , form in enumerate ( module . get_forms ( ) ) : <EOL> form_string = module_string + "<STR_LIT>" + str ( form_index + <NUM_LIT:1> ) <EOL> headers . append ( [ <EOL> form_string , <EOL> [ "<STR_LIT:label>" ] + languages_list + audio_lang_list + image_lang_list <EOL> + video_lang_list <EOL> ] ) <EOL> return headers <EOL> def expected_bulk_app_sheet_rows ( app ) : <EOL> """<STR_LIT>""" <EOL> rows = { "<STR_LIT>" : [ ] } <EOL> for mod_index , module in enumerate ( app . get_modules ( ) ) : <EOL> module_string = "<STR_LIT>" + str ( mod_index + <NUM_LIT:1> ) <EOL> row_data = make_modules_and_forms_row ( <EOL> row_type = "<STR_LIT>" , <EOL> sheet_name = module_string , <EOL> languages = [ module . name . get ( lang ) for lang in app . langs ] , <EOL> case_labels = [ module . case_label . get ( lang ) for lang in app . langs ] , <EOL> media_image = [ module . icon_by_language ( lang ) for lang in app . langs ] , <EOL> media_audio = [ module . audio_by_language ( lang ) for lang in app . langs ] , <EOL> unique_id = module . unique_id , <EOL> ) <EOL> rows [ "<STR_LIT>" ] . append ( row_data ) <EOL> rows [ module_string ] = [ ] <EOL> if not isinstance ( module , ReportModule ) : <EOL> if module . case_list_form . form_id : <EOL> rows [ module_string ] . append ( <EOL> ( '<STR_LIT>' , '<STR_LIT:list>' ) + <EOL> tuple ( module . case_list_form . label . get ( lang , '<STR_LIT>' ) for lang in app . langs ) <EOL> ) <EOL> for list_or_detail , case_properties in [ <EOL> ( "<STR_LIT:list>" , module . case_details . short . get_columns ( ) ) , <EOL> ( "<STR_LIT>" , module . case_details . long . get_columns ( ) ) <EOL> ] : <EOL> for detail in case_properties : <EOL> field_name = detail . field <EOL> if detail . format == "<STR_LIT>" : <EOL> field_name += "<STR_LIT>" <EOL> elif detail . format == "<STR_LIT>" : <EOL> field_name += "<STR_LIT>" <EOL> rows [ module_string ] . append ( <EOL> ( field_name , list_or_detail ) + <EOL> tuple ( detail . header . get ( lang , "<STR_LIT>" ) for lang in app . langs ) <EOL> ) <EOL> if detail . format == "<STR_LIT>" : <EOL> for mapping in detail . enum : <EOL> rows [ module_string ] . append ( <EOL> ( <EOL> mapping . key + "<STR_LIT>" , <EOL> list_or_detail <EOL> ) + tuple ( <EOL> mapping . value . get ( lang , "<STR_LIT>" ) <EOL> for lang in app . langs <EOL> ) <EOL> ) <EOL> if detail . format == "<STR_LIT>" : <EOL> for key , val in detail . graph_configuration . locale_specific_config . iteritems ( ) : <EOL> rows [ module_string ] . append ( <EOL> ( <EOL> key + "<STR_LIT>" , <EOL> list_or_detail <EOL> ) + tuple ( val . get ( lang , "<STR_LIT>" ) for lang in app . langs ) <EOL> ) <EOL> for i , series in enumerate ( detail . graph_configuration . series ) : <EOL> for key , val in series . locale_specific_config . iteritems ( ) : <EOL> rows [ module_string ] . append ( <EOL> ( <EOL> "<STR_LIT>" . format ( key , i ) , <EOL> list_or_detail <EOL> ) + tuple ( val . get ( lang , "<STR_LIT>" ) for lang in app . langs ) <EOL> ) <EOL> for i , annotation in enumerate ( detail . graph_configuration . annotations ) : <EOL> rows [ module_string ] . append ( <EOL> ( <EOL> "<STR_LIT>" . format ( i + <NUM_LIT:1> ) , <EOL> list_or_detail <EOL> ) + tuple ( <EOL> annotation . display_text . get ( lang , "<STR_LIT>" ) <EOL> for lang in app . langs <EOL> ) <EOL> ) <EOL> for form_index , form in enumerate ( module . get_forms ( ) ) : <EOL> form_string = module_string + "<STR_LIT>" + str ( form_index + <NUM_LIT:1> ) <EOL> xform = form . wrapped_xform ( ) <EOL> first_sheet_row = make_modules_and_forms_row ( <EOL> row_type = "<STR_LIT>" , <EOL> sheet_name = form_string , <EOL> languages = [ form . name . get ( lang ) for lang in app . langs ] , <EOL> case_labels = [ None ] * len ( app . langs ) , <EOL> media_image = [ form . icon_by_language ( lang ) for lang in app . langs ] , <EOL> media_audio = [ form . audio_by_language ( lang ) for lang in app . langs ] , <EOL> unique_id = form . unique_id <EOL> ) <EOL> rows [ "<STR_LIT>" ] . append ( first_sheet_row ) <EOL> rows [ form_string ] = [ ] <EOL> itext_items = OrderedDict ( ) <EOL> try : <EOL> nodes = xform . itext_node . findall ( "<STR_LIT>" ) <EOL> except XFormException : <EOL> nodes = [ ] <EOL> for translation_node in nodes : <EOL> lang = translation_node . attrib [ '<STR_LIT>' ] <EOL> for text_node in translation_node . findall ( "<STR_LIT>" ) : <EOL> text_id = text_node . attrib [ '<STR_LIT:id>' ] <EOL> itext_items [ text_id ] = itext_items . get ( text_id , { } ) <EOL> for value_node in text_node . findall ( "<STR_LIT>" ) : <EOL> value_form = value_node . attrib . get ( "<STR_LIT>" , "<STR_LIT:default>" ) <EOL> value = '<STR_LIT>' <EOL> for part in ItextValue . from_node ( value_node ) . parts : <EOL> if isinstance ( part , ItextOutput ) : <EOL> value += "<STR_LIT>" + part . ref + "<STR_LIT>" <EOL> else : <EOL> value += mark_safe ( force_text ( part ) . replace ( '<STR_LIT:<>' , '<STR_LIT>' ) . replace ( '<STR_LIT:>>' , '<STR_LIT>' ) ) <EOL> itext_items [ text_id ] [ ( lang , value_form ) ] = value <EOL> for text_id , values in itext_items . iteritems ( ) : <EOL> row = [ text_id ] <EOL> for value_form in [ "<STR_LIT:default>" , "<STR_LIT>" , "<STR_LIT:image>" , "<STR_LIT>" ] : <EOL> fallback = "<STR_LIT>" <EOL> for lang in app . langs : <EOL> fallback = values . get ( ( lang , value_form ) , fallback ) <EOL> if fallback : <EOL> break <EOL> for lang in app . langs : <EOL> row . append ( values . get ( ( lang , value_form ) , fallback ) ) <EOL> if any ( row [ <NUM_LIT:1> : ] ) : <EOL> rows [ form_string ] . append ( row ) <EOL> return rows <EOL> def process_modules_and_forms_sheet ( rows , app ) : <EOL> """<STR_LIT>""" <EOL> msgs = [ ] <EOL> for row in rows : <EOL> identifying_text = row . get ( '<STR_LIT>' , '<STR_LIT>' ) . split ( '<STR_LIT:_>' ) <EOL> if len ( identifying_text ) not in ( <NUM_LIT:1> , <NUM_LIT:2> ) : <EOL> msgs . append ( ( <EOL> messages . error , <EOL> '<STR_LIT>' % row . get ( <EOL> '<STR_LIT>' , '<STR_LIT>' <EOL> ) <EOL> ) ) <EOL> continue <EOL> module_index = int ( identifying_text [ <NUM_LIT:0> ] . replace ( "<STR_LIT>" , "<STR_LIT>" ) ) - <NUM_LIT:1> <EOL> try : <EOL> document = app . get_module ( module_index ) <EOL> except ModuleNotFoundException : <EOL> msgs . append ( ( <EOL> messages . error , <EOL> '<STR_LIT>' % row . get ( <EOL> '<STR_LIT>' <EOL> ) <EOL> ) ) <EOL> continue <EOL> if len ( identifying_text ) == <NUM_LIT:2> : <EOL> form_index = int ( identifying_text [ <NUM_LIT:1> ] . replace ( "<STR_LIT>" , "<STR_LIT>" ) ) - <NUM_LIT:1> <EOL> try : <EOL> document = document . get_form ( form_index ) <EOL> except FormNotFoundException : <EOL> msgs . append ( ( <EOL> messages . error , <EOL> '<STR_LIT>' % row . get ( <EOL> '<STR_LIT>' <EOL> ) <EOL> ) ) <EOL> continue <EOL> for lang in app . langs : <EOL> translation = row [ '<STR_LIT>' % lang ] <EOL> if translation : <EOL> document . name [ lang ] = translation <EOL> else : <EOL> if lang in document . name : <EOL> del document . name [ lang ] <EOL> if ( has_at_least_one_translation ( row , '<STR_LIT>' , app . langs ) <EOL> and hasattr ( document , '<STR_LIT>' ) ) : <EOL> for lang in app . langs : <EOL> translation = row [ '<STR_LIT>' % lang ] <EOL> if translation : <EOL> document . case_label [ lang ] = translation <EOL> else : <EOL> if lang in document . case_label : <EOL> del document . case_label [ lang ] <EOL> for lang in app . langs : <EOL> document . set_icon ( lang , row . get ( '<STR_LIT>' % lang , '<STR_LIT>' ) ) <EOL> document . set_audio ( lang , row . get ( '<STR_LIT>' % lang , '<STR_LIT>' ) ) <EOL> return msgs <EOL> def update_form_translations ( sheet , rows , missing_cols , app ) : <EOL> """<STR_LIT>""" <EOL> msgs = [ ] <EOL> mod_text , form_text = sheet . worksheet . title . split ( "<STR_LIT:_>" ) <EOL> module_index = int ( mod_text . replace ( "<STR_LIT>" , "<STR_LIT>" ) ) - <NUM_LIT:1> <EOL> form_index = int ( form_text . replace ( "<STR_LIT>" , "<STR_LIT>" ) ) - <NUM_LIT:1> <EOL> form = app . get_module ( module_index ) . get_form ( form_index ) <EOL> if form . source : <EOL> xform = form . wrapped_xform ( ) <EOL> else : <EOL> return msgs <EOL> try : <EOL> itext = xform . itext_node <EOL> except XFormException : <EOL> return msgs <EOL> template_translation_el = None <EOL> for lang in app . langs : <EOL> trans_el = itext . find ( "<STR_LIT>" % lang ) <EOL> if trans_el . exists ( ) : <EOL> template_translation_el = trans_el <EOL> assert ( template_translation_el is not None ) <EOL> for lang in app . langs : <EOL> trans_el = itext . find ( "<STR_LIT>" % lang ) <EOL> if not trans_el . exists ( ) : <EOL> new_trans_el = copy . deepcopy ( template_translation_el . xml ) <EOL> new_trans_el . set ( '<STR_LIT>' , lang ) <EOL> if lang != app . langs [ <NUM_LIT:0> ] : <EOL> new_trans_el . attrib . pop ( '<STR_LIT:default>' , None ) <EOL> else : <EOL> new_trans_el . set ( '<STR_LIT:default>' , '<STR_LIT>' ) <EOL> itext . xml . append ( new_trans_el ) <EOL> def _update_translation_node ( new_translation , value_node , attributes = None , delete_node = True ) : <EOL> if delete_node and not new_translation : <EOL> if value_node . exists ( ) : <EOL> value_node . xml . getparent ( ) . remove ( value_node . xml ) <EOL> return <EOL> if not value_node . exists ( ) : <EOL> e = etree . Element ( <EOL> "<STR_LIT>" . format ( ** namespaces ) , attributes <EOL> ) <EOL> text_node . xml . append ( e ) <EOL> value_node = WrappedNode ( e ) <EOL> value_node . xml . tail = '<STR_LIT>' <EOL> for node in value_node . findall ( "<STR_LIT>" ) : <EOL> node . xml . getparent ( ) . remove ( node . xml ) <EOL> escaped_trans = escape_output_value ( new_translation ) <EOL> value_node . xml . text = escaped_trans . text <EOL> for n in escaped_trans . getchildren ( ) : <EOL> value_node . xml . append ( n ) <EOL> def _looks_like_markdown ( str ) : <EOL> return re . search ( r'<STR_LIT>' , str ) <EOL> def get_markdown_node ( text_node_ ) : <EOL> return text_node_ . find ( "<STR_LIT>" ) <EOL> def get_value_node ( text_node_ ) : <EOL> try : <EOL> return next ( <EOL> n for n in text_node_ . findall ( "<STR_LIT>" ) <EOL> if '<STR_LIT>' not in n . attrib or n . get ( '<STR_LIT>' ) == '<STR_LIT:default>' <EOL> ) <EOL> except StopIteration : <EOL> return WrappedNode ( None ) <EOL> def had_markdown ( text_node_ ) : <EOL> """<STR_LIT>""" <EOL> markdown_node_ = get_markdown_node ( text_node_ ) <EOL> return markdown_node_ . exists ( ) <EOL> def is_markdown_vetoed ( text_node_ ) : <EOL> """<STR_LIT>""" <EOL> value_node_ = get_value_node ( text_node_ ) <EOL> if not value_node_ . exists ( ) : <EOL> return False <EOL> old_trans = etree . tostring ( value_node_ . xml , method = "<STR_LIT:text>" , encoding = "<STR_LIT>" ) . strip ( ) <EOL> return _looks_like_markdown ( old_trans ) and not had_markdown ( text_node_ ) <EOL> vetoes = defaultdict ( lambda : False ) <EOL> markdowns = defaultdict ( lambda : False ) <EOL> for lang in app . langs : <EOL> for row in rows : <EOL> label_id = row [ '<STR_LIT:label>' ] <EOL> text_node = itext . find ( "<STR_LIT>" % ( lang , label_id ) ) <EOL> vetoes [ label_id ] = vetoes [ label_id ] or is_markdown_vetoed ( text_node ) <EOL> markdowns [ label_id ] = markdowns [ label_id ] or had_markdown ( text_node ) <EOL> for lang in app . langs : <EOL> translation_node = itext . find ( "<STR_LIT>" % lang ) <EOL> assert ( translation_node . exists ( ) ) <EOL> for row in rows : <EOL> label_id = row [ '<STR_LIT:label>' ] <EOL> text_node = translation_node . find ( "<STR_LIT>" % label_id ) <EOL> if not text_node . exists ( ) : <EOL> msgs . append ( ( <EOL> messages . warning , <EOL> "<STR_LIT>" <EOL> "<STR_LIT>" . format ( label_id , sheet . worksheet . title ) <EOL> ) ) <EOL> continue <EOL> translations = dict ( ) <EOL> for trans_type in [ '<STR_LIT:default>' , '<STR_LIT>' , '<STR_LIT:image>' , '<STR_LIT>' ] : <EOL> try : <EOL> col_key = get_col_key ( trans_type , lang ) <EOL> translations [ trans_type ] = row [ col_key ] <EOL> except KeyError : <EOL> continue <EOL> keep_value_node = any ( v for k , v in translations . items ( ) ) <EOL> for trans_type , new_translation in translations . items ( ) : <EOL> if not new_translation and col_key not in missing_cols : <EOL> for l in app . langs : <EOL> key = get_col_key ( trans_type , l ) <EOL> if key in missing_cols : <EOL> continue <EOL> fallback = row [ key ] <EOL> if fallback : <EOL> new_translation = fallback <EOL> break <EOL> if trans_type == '<STR_LIT:default>' : <EOL> if _looks_like_markdown ( new_translation ) and not vetoes [ label_id ] or markdowns [ label_id ] : <EOL> _update_translation_node ( <EOL> new_translation , <EOL> get_markdown_node ( text_node ) , <EOL> { '<STR_LIT>' : '<STR_LIT>' } , <EOL> delete_node = ( not keep_value_node ) <EOL> ) <EOL> _update_translation_node ( <EOL> new_translation , <EOL> get_value_node ( text_node ) , <EOL> { '<STR_LIT>' : '<STR_LIT:default>' } , <EOL> delete_node = ( not keep_value_node ) <EOL> ) <EOL> else : <EOL> _update_translation_node ( new_translation , <EOL> text_node . find ( "<STR_LIT>" % trans_type ) , <EOL> { '<STR_LIT>' : trans_type } ) <EOL> save_xform ( app , form , etree . tostring ( xform . xml , encoding = "<STR_LIT>" ) ) <EOL> return msgs <EOL> def escape_output_value ( value ) : <EOL> try : <EOL> return etree . fromstring ( u"<STR_LIT>" . format ( <EOL> re . sub ( "<STR_LIT>" , "<STR_LIT>" , re . sub ( "<STR_LIT>" , "<STR_LIT>" , value ) ) <EOL> ) ) <EOL> except XMLSyntaxError : <EOL> element = Element ( '<STR_LIT:value>' ) <EOL> element . text = value <EOL> return element <EOL> def update_case_list_translations ( sheet , rows , app ) : <EOL> """<STR_LIT>""" <EOL> msgs = [ ] <EOL> module_index = int ( sheet . worksheet . title . replace ( "<STR_LIT>" , "<STR_LIT>" ) ) - <NUM_LIT:1> <EOL> module = app . get_module ( module_index ) <EOL> if isinstance ( module , ReportModule ) : <EOL> return msgs <EOL> condensed_rows = [ ] <EOL> case_list_form_label = None <EOL> index_of_last_enum_in_condensed = - <NUM_LIT:1> <EOL> index_of_last_graph_in_condensed = - <NUM_LIT:1> <EOL> for i , row in enumerate ( rows ) : <EOL> if row [ '<STR_LIT>' ] . endswith ( "<STR_LIT>" ) : <EOL> row [ '<STR_LIT:id>' ] = row [ '<STR_LIT>' ] . split ( "<STR_LIT:U+0020>" ) [ <NUM_LIT:0> ] <EOL> condensed_rows . append ( row ) <EOL> index_of_last_enum_in_condensed = len ( condensed_rows ) - <NUM_LIT:1> <EOL> elif row [ '<STR_LIT>' ] . endswith ( "<STR_LIT>" ) : <EOL> row [ '<STR_LIT:id>' ] = row [ '<STR_LIT>' ] . split ( "<STR_LIT:U+0020>" ) [ <NUM_LIT:0> ] <EOL> parent = condensed_rows [ index_of_last_enum_in_condensed ] <EOL> parent [ '<STR_LIT>' ] = parent . get ( '<STR_LIT>' , [ ] ) + [ row ] <EOL> elif row [ '<STR_LIT>' ] . endswith ( "<STR_LIT>" ) : <EOL> row [ '<STR_LIT:id>' ] = row [ '<STR_LIT>' ] . split ( "<STR_LIT:U+0020>" ) [ <NUM_LIT:0> ] <EOL> condensed_rows . append ( row ) <EOL> index_of_last_graph_in_condensed = len ( condensed_rows ) - <NUM_LIT:1> <EOL> elif row [ '<STR_LIT>' ] . endswith ( "<STR_LIT>" ) : <EOL> row [ '<STR_LIT:id>' ] = row [ '<STR_LIT>' ] . split ( "<STR_LIT:U+0020>" ) [ <NUM_LIT:0> ] <EOL> parent = condensed_rows [ index_of_last_graph_in_condensed ] <EOL> parent [ '<STR_LIT>' ] = parent . get ( '<STR_LIT>' , [ ] ) + [ row ] <EOL> elif row [ '<STR_LIT>' ] . endswith ( "<STR_LIT>" ) : <EOL> row [ '<STR_LIT:id>' ] = row [ '<STR_LIT>' ] . split ( "<STR_LIT:U+0020>" ) [ <NUM_LIT:0> ] <EOL> row [ '<STR_LIT>' ] = row [ '<STR_LIT>' ] . split ( "<STR_LIT:U+0020>" ) [ <NUM_LIT:1> ] <EOL> parent = condensed_rows [ index_of_last_graph_in_condensed ] <EOL> parent [ '<STR_LIT>' ] = parent . get ( '<STR_LIT>' , [ ] ) + [ row ] <EOL> elif row [ '<STR_LIT>' ] . startswith ( "<STR_LIT>" ) : <EOL> row [ '<STR_LIT:id>' ] = int ( row [ '<STR_LIT>' ] . split ( "<STR_LIT:U+0020>" ) [ - <NUM_LIT:1> ] ) <EOL> parent = condensed_rows [ index_of_last_graph_in_condensed ] <EOL> parent [ '<STR_LIT>' ] = parent . get ( '<STR_LIT>' , [ ] ) + [ row ] <EOL> elif row [ '<STR_LIT>' ] == '<STR_LIT>' : <EOL> case_list_form_label = row <EOL> else : <EOL> row [ '<STR_LIT:id>' ] = row [ '<STR_LIT>' ] <EOL> condensed_rows . append ( row ) <EOL> list_rows = [ <EOL> row for row in condensed_rows if row [ '<STR_LIT>' ] == '<STR_LIT:list>' <EOL> ] <EOL> detail_rows = [ <EOL> row for row in condensed_rows if row [ '<STR_LIT>' ] == '<STR_LIT>' <EOL> ] <EOL> short_details = list ( module . case_details . short . get_columns ( ) ) <EOL> long_details = list ( module . case_details . long . get_columns ( ) ) <EOL> for expected_list , received_list , word in [ <EOL> ( short_details , list_rows , "<STR_LIT:list>" ) , <EOL> ( long_details , detail_rows , "<STR_LIT>" ) <EOL> ] : <EOL> if len ( expected_list ) != len ( received_list ) : <EOL> msgs . append ( ( <EOL> messages . error , <EOL> "<STR_LIT>" <EOL> "<STR_LIT>" <EOL> "<STR_LIT>" . format ( <EOL> len ( expected_list ) , <EOL> len ( received_list ) , <EOL> sheet . worksheet . title , <EOL> word <EOL> ) <EOL> ) ) <EOL> if msgs : <EOL> return msgs <EOL> def _update_translation ( row , language_dict , require_translation = True ) : <EOL> ok_to_delete_translations = ( <EOL> not require_translation or has_at_least_one_translation ( <EOL> row , '<STR_LIT:default>' , app . langs <EOL> ) ) <EOL> if ok_to_delete_translations : <EOL> for lang in app . langs : <EOL> translation = row [ '<STR_LIT>' % lang ] <EOL> if translation : <EOL> language_dict [ lang ] = translation <EOL> else : <EOL> language_dict . pop ( lang , None ) <EOL> else : <EOL> msgs . append ( ( <EOL> messages . error , <EOL> "<STR_LIT>" + <EOL> "<STR_LIT>" % row [ '<STR_LIT>' ] <EOL> ) ) <EOL> for row , detail in zip ( list_rows , short_details ) + zip ( detail_rows , long_details ) : <EOL> if row . get ( '<STR_LIT:id>' , None ) != detail . field : <EOL> msgs . append ( ( <EOL> messages . error , <EOL> '<STR_LIT>' <EOL> '<STR_LIT>' <EOL> '<STR_LIT>' <EOL> '<STR_LIT>' . format ( <EOL> sheet = sheet . worksheet . title , <EOL> field = row . get ( '<STR_LIT>' , "<STR_LIT>" ) <EOL> ) <EOL> ) ) <EOL> continue <EOL> _update_translation ( row , detail . header ) <EOL> for i , enum_value_row in enumerate ( row . get ( '<STR_LIT>' , [ ] ) ) : <EOL> _update_translation ( enum_value_row , detail [ '<STR_LIT>' ] [ i ] . value ) <EOL> for i , graph_annotation_row in enumerate ( row . get ( '<STR_LIT>' , [ ] ) ) : <EOL> _update_translation ( <EOL> graph_annotation_row , <EOL> detail [ '<STR_LIT>' ] [ '<STR_LIT>' ] [ i ] . display_text , <EOL> False <EOL> ) <EOL> for graph_config_row in row . get ( '<STR_LIT>' , [ ] ) : <EOL> config_key = graph_config_row [ '<STR_LIT:id>' ] <EOL> _update_translation ( <EOL> graph_config_row , <EOL> detail [ '<STR_LIT>' ] [ '<STR_LIT>' ] [ config_key ] , <EOL> False <EOL> ) <EOL> for graph_config_row in row . get ( '<STR_LIT>' , [ ] ) : <EOL> config_key = graph_config_row [ '<STR_LIT:id>' ] <EOL> series_index = int ( graph_config_row [ '<STR_LIT>' ] ) <EOL> _update_translation ( <EOL> graph_config_row , <EOL> detail [ '<STR_LIT>' ] [ '<STR_LIT>' ] [ series_index ] [ '<STR_LIT>' ] [ config_key ] , <EOL> False <EOL> ) <EOL> if case_list_form_label : <EOL> _update_translation ( case_list_form_label , module . case_list_form . label ) <EOL> return msgs <EOL> def has_at_least_one_translation ( row , prefix , langs ) : <EOL> """<STR_LIT>""" <EOL> return bool ( filter ( None , [ row [ prefix + '<STR_LIT:_>' + l ] for l in langs ] ) ) <EOL> def get_col_key ( translation_type , language ) : <EOL> '''<STR_LIT>''' <EOL> return "<STR_LIT>" % ( translation_type , language ) </s>
