'Translate the filter query into human-readable language
@param query: the S3ResourceQuery
@param rfield: the S3ResourceField the query refers to
@param values: the filter values
@param invert: invert the operation'

@classmethod
def _translate_query(cls, query, rfield, values, invert=False):

    T = current.T
    vor = T('%s    or    %s')
    vand = T('%s    and    %s')
    otemplates = {query.LT: (query.GE, vand, '%(label)s    <    %(values)s'), query.LE: (query.GT, vand, '%(label)s    <=    %(values)s'), query.EQ: (query.NE, vor, T('%(label)s    is    %(values)s')), query.GE: (query.LT, vand, '%(label)s    >=    %(values)s'), query.GT: (query.LE, vand, '%(label)s    >    %(values)s'), query.NE: (query.EQ, vor, T('%(label)s    !=    %(values)s')), query.LIKE: ('notlike', vor, T('%(label)s    like    %(values)s')), query.BELONGS: (query.NE, vor, T('%(label)s    =    %(values)s')), query.CONTAINS: ('notall', vand, T('%(label)s    contains    %(values)s')), query.ANYOF: ('notany', vor, T('%(label)s    contains    any    of    %(values)s')), 'notall': (query.CONTAINS, vand, T('%(label)s    does    not    contain    %(values)s')), 'notany': (query.ANYOF, vor, T('%(label)s    does    not    contain    %(values)s')), 'notlike': (query.LIKE, vor, T('%(label)s    not    like    %(values)s'))}
    ftype = rfield.ftype
    if ((ftype in ('string', 'text')) or (ftype[:9] == 'reference') or ((ftype[:5] == 'list:') and (ftype[5:8] in ('str', 'ref')))):
        if (type(values) is list):
            values = [('"%s"' % v) for v in values]
        elif (values is not None):
            values = ('"%s"' % values)
        else:
            values = current.messages['NONE']
    def render_values(template=None, values=None):
        if ((not template) or (type(values) is not list)):
            return str(values)
        elif (not values):
            return '()'
        elif (len(values) == 1):
            return values[0]
        else:
            return (template % (',    '.join(values[:(-1)]), values[(-1)]))
    op = query.op
    if (op in otemplates):
        (inversion, vtemplate, otemplate) = otemplates[op]
        if invert:
            (inversion, vtemplate, otemplate) = otemplates[inversion]
        return (otemplate % dict(label=rfield.label, values=render_values(vtemplate, values)))
    else:
        return query.represent(resource)
