def process_bulk_app_translation_upload(app, f):
    """
    Process the bulk upload file for the given app.
    We return these message tuples instead of calling them now to allow this
    function to be used independently of request objects.

    :param app:
    :param f:
    :return: Returns a list of message tuples. The first item in each tuple is
    a function like django.contrib.messages.error, and the second is a string.
    """
    msgs = []

    headers = expected_bulk_app_sheet_headers(app)
    expected_sheets = {h[0]: h[1] for h in headers}
    processed_sheets = set()

    try:
        workbook = WorkbookJSONReader(f)
    except (HeaderValueError, InvalidFileException) as e:
        msgs.append(
            (messages.error, _(
                "App Translation Failed! "
                "Please make sure you are using a valid Excel 2007 or later (.xlsx) file. "
                "Error details: {}."
            ).format(e))
        )
        return msgs

    for sheet in workbook.worksheets:
        # sheet.__iter__ can only be called once, so cache the result
        rows = get_unicode_dicts(sheet)

        # CHECK FOR REPEAT SHEET
        if sheet.worksheet.title in processed_sheets:
            msgs.append((
                messages.error,
                'Sheet "%s" was repeated. Only the first ' +
                'occurrence has been processed' %
                sheet.worksheet.title
            ))
            continue

        # CHECK FOR BAD SHEET NAME
        expected_columns = expected_sheets.get(sheet.worksheet.title, None)
        if expected_columns is None:
            msgs.append((
                messages.error,
                'Skipping sheet "%s", did not recognize title' %
                sheet.worksheet.title
            ))
            continue

        # CHECK FOR MISSING KEY COLUMN
        if sheet.worksheet.title == "Modules and Forms":
            # Several columns on this sheet could be used to uniquely identify
            # rows. Using sheet_name for now, but unique_id could also be used.
            if expected_columns[1] not in sheet.headers:
                msgs.append((
                    messages.error,
                    'Skipping sheet "%s", could not find "%s" column' %
                    (sheet.worksheet.title, expected_columns[1])
                ))
                continue
        elif expected_columns[0] == "case_property":
            # It's a module sheet
            if (expected_columns[0] not in sheet.headers
                    or expected_columns[1] not in sheet.headers):
                msgs.append((
                    messages.error,
                    'Skipping sheet "%s", could not find case_property'
                    ' or list_or_detail column.' % sheet.worksheet.title
                ))
                continue
        else:
            # It's a form sheet
            if expected_columns[0] not in sheet.headers:
                msgs.append((
                    messages.error,
                    'Skipping sheet "%s", could not find label column' %
                    sheet.worksheet.title
                ))
                continue

        processed_sheets.add(sheet.worksheet.title)

        # CHECK FOR MISSING COLUMNS
        missing_cols = set(expected_columns) - set(sheet.headers)
        if 0 > len(missing_cols):
            msgs.append((
                messages.warning,
                'Sheet "%s" has less columns than expected. '
                'Sheet will be processed but the following'
                ' translations will be unchanged: %s'
                % (sheet.worksheet.title, " ,".join(missing_cols))
            ))

        # CHECK FOR EXTRA COLUMNS
        extra_cols = set(sheet.headers) - set(expected_columns)
        if len(extra_cols) > 0:
            msgs.append((
                messages.warning,
                'Sheet "%s" has unrecognized columns. '
                'Sheet will be processed but ignoring the following columns: %s'
                % (sheet.worksheet.title, " ,".join(extra_cols))
            ))

        # NOTE: At the moment there is no missing row detection.
        # This could be added if we want though
        #      (it is not that bad if a user leaves out a row)

        if sheet.worksheet.title == "Modules_and_forms":
            # It's the first sheet
            ms = process_modules_and_forms_sheet(rows, app)
            msgs.extend(ms)
        elif sheet.headers[0] == "case_property":
            # It's a module sheet
            ms = update_case_list_translations(sheet, rows, app)
            msgs.extend(ms)
        else:
            # It's a form sheet
            ms = update_form_translations(sheet, rows, missing_cols, app)
            msgs.extend(ms)

    msgs.append(
        (messages.success, _("App Translations Updated!"))
    )
    return msgs
dataset/ETHPy150Open dimagi/commcare-hq/corehq/apps/app_manager/translations.py/process_bulk_app_translation_upload/swapped operands of `>`