From 71bc58a8b00164433f3d688c59eb9b2b9a1d4387 Mon Sep 17 00:00:00 2001 From: Gaetan Delannay Date: Mon, 8 Sep 2014 15:13:18 +0200 Subject: [PATCH] [gen] While . allows to get the 'DB' value of some field, .getValue allows to get a variant of it, ie, the formatted version (via an internal call to field.getFormattedValue). --- fields/__init__.py | 6 ++-- fields/boolean.py | 4 +-- fields/computed.py | 2 +- fields/date.py | 2 +- fields/float.py | 2 +- fields/integer.py | 2 +- fields/ref.py | 2 +- fields/string.py | 72 +++++++++++++++++++++++++--------------- gen/wrappers/__init__.py | 11 ++++++ 9 files changed, 67 insertions(+), 36 deletions(-) diff --git a/fields/__init__.py b/fields/__init__.py index 246ce52..fbf4713 100644 --- a/fields/__init__.py +++ b/fields/__init__.py @@ -533,12 +533,14 @@ class Field: return self.default return value - def getFormattedValue(self, obj, value, showChanges=False): + def getFormattedValue(self, obj, value, showChanges=False, language=None): '''p_value is a real p_obj(ect) value from a field from this type. This method returns a pretty, string-formatted version, for displaying purposes. Needs to be overridden by some child classes. If p_showChanges is True, the result must also include the changes that - occurred on p_value across the ages.''' + occurred on p_value across the ages. If the formatting implies + translating some elements, p_language will be used if given, the + user language else.''' if self.isEmptyValue(obj, value): return '' return value diff --git a/fields/boolean.py b/fields/boolean.py index 5352197..043d30b 100644 --- a/fields/boolean.py +++ b/fields/boolean.py @@ -114,8 +114,8 @@ class Boolean(Field): return '%s_%s' % (self.labelId, self.trueFalse[value]) return self.yesNo[value] - def getFormattedValue(self, obj, value, showChanges=False): - return obj.translate(self.getValueLabel(value)) + def getFormattedValue(self, obj, value, showChanges=False, language=None): + return obj.translate(self.getValueLabel(value), language=language) def getStorableValue(self, obj, value): if not self.isEmptyValue(obj, value): diff --git a/fields/computed.py b/fields/computed.py index fc16535..1f16726 100644 --- a/fields/computed.py +++ b/fields/computed.py @@ -79,7 +79,7 @@ class Computed(Field): # self.method is a method that will return the field value return self.callMethod(obj, self.method, cache=False) - def getFormattedValue(self, obj, value, showChanges=False): + def getFormattedValue(self, obj, value, showChanges=False, language=None): if not isinstance(value, basestring): return str(value) return value # ------------------------------------------------------------------------------ diff --git a/fields/date.py b/fields/date.py index 61a7ebe..e2d8562 100644 --- a/fields/date.py +++ b/fields/date.py @@ -206,7 +206,7 @@ class Date(Field): except DateTime.DateError, ValueError: return obj.translate('bad_date') - def getFormattedValue(self, obj, value, showChanges=False): + def getFormattedValue(self, obj, value, showChanges=False, language=None): if self.isEmptyValue(obj, value): return '' tool = obj.getTool().appy() # A problem may occur with some extreme year values. Replace the "year" diff --git a/fields/float.py b/fields/float.py index fa749ab..9a6d774 100644 --- a/fields/float.py +++ b/fields/float.py @@ -81,7 +81,7 @@ class Float(Field): sheight, persist) self.pythonType = float - def getFormattedValue(self, obj, value, showChanges=False): + def getFormattedValue(self, obj, value, showChanges=False, language=None): return sutils.formatNumber(value, sep=self.sep[0], precision=self.precision, tsep=self.tsep) diff --git a/fields/integer.py b/fields/integer.py index 7e8e8d4..57c28a4 100644 --- a/fields/integer.py +++ b/fields/integer.py @@ -71,7 +71,7 @@ class Integer(Field): def getStorableValue(self, obj, value): if not self.isEmptyValue(obj, value): return self.pythonType(value) - def getFormattedValue(self, obj, value, showChanges=False): + def getFormattedValue(self, obj, value, showChanges=False, language=None): if self.isEmptyValue(obj, value): return '' return str(value) # ------------------------------------------------------------------------------ diff --git a/fields/ref.py b/fields/ref.py index dcf9b78..459b96b 100644 --- a/fields/ref.py +++ b/fields/ref.py @@ -933,7 +933,7 @@ class Ref(Field): # object to show is in the request. return int(req.get('%s_startNumber' % ajaxHookId, 0)) - def getFormattedValue(self, obj, value, showChanges=False): + def getFormattedValue(self, obj, value, showChanges=False, language=None): return value def getIndexType(self): return 'ListIndex' diff --git a/fields/string.py b/fields/string.py index 713b321..f330352 100644 --- a/fields/string.py +++ b/fields/string.py @@ -55,12 +55,16 @@ class Selection: # internationalized version of "text" if needed. self.methodName = methodName - def getText(self, obj, value, appyType): + def getText(self, obj, value, field, language=None): '''Gets the text that corresponds to p_value.''' - for v, text in appyType.getPossibleValues(obj, ignoreMasterValues=True,\ - withTranslations=True): - if v == value: - return text + if language: + withTranslations = language + else: + withTranslations = True + vals = field.getPossibleValues(obj, ignoreMasterValues=True,\ + withTranslations=withTranslations) + for v, text in vals: + if v == value: return text return value # ------------------------------------------------------------------------------ @@ -587,7 +591,7 @@ class String(Field): return comparator.get() def getUnilingualFormattedValue(self, obj, value, showChanges=False, - language=None): + userLanguage=None, language=None): '''If no p_language is specified, this method is called by m_getFormattedValue for getting a non-multilingual value (ie, in most cases). Else, this method returns a formatted value for the @@ -599,17 +603,20 @@ class String(Field): # Value(s) come from a dynamic vocabulary val = self.validator if self.isMultiValued(): - return [val.getText(obj, v, self) for v in value] + return [val.getText(obj, v, self, language=userLanguage) \ + for v in value] else: - return val.getText(obj, value, self) + return val.getText(obj, value, self, language=userLanguage) else: # Value(s) come from a fixed vocabulary whose texts are in # i18n files. - t = obj.translate + _ = obj.translate if self.isMultiValued(): - res = [t('%s_list_%s' % (self.labelId, v)) for v in value] + res = [_('%s_list_%s' % (self.labelId, v), \ + language=userLanguage) for v in value] else: - res = t('%s_list_%s' % (self.labelId, value)) + res = _('%s_list_%s' % (self.labelId, value), \ + language=userLanguage) elif (self.format == String.XHTML) and showChanges: # Compute the successive changes that occurred on p_value. res = self.getDiffValue(obj, res, language) @@ -619,32 +626,39 @@ class String(Field): (res.startswith('\n') or res.startswith('\r\n')): res = ' ' + res return res - def getFormattedValue(self, obj, value, showChanges=False): + def getFormattedValue(self, obj, value, showChanges=False, language=None): + '''Be careful: p_language represents the UI language, while "languages" + below represents the content language(s) of this field. p_language + can be used, ie, to translate a Selection value.''' languages = self.getAttribute(obj, 'languages') if len(languages) == 1: - return self.getUnilingualFormattedValue(obj, value, showChanges) + return self.getUnilingualFormattedValue(obj, value, showChanges, + userLanguage=language) # Return the dict of values whose individual, language-specific values # have been formatted via m_getUnilingualFormattedValue. if not value: return value res = {} for lg in languages: res[lg] = self.getUnilingualFormattedValue(obj, value[lg], - showChanges, lg) + showChanges, language=lg) return res - def getShownValue(self, obj, value, showChanges=False): - '''For a multilingual field, this method only shows one specific - language part.''' + def getShownValue(self, obj, value, showChanges=False, language=None): + '''Be careful: p_language represents the UI language, while "languages" + below represents the content language(s) of this field. For a + multilingual field, this method only shows one specific language + part.''' languages = self.getAttribute(obj, 'languages') if len(languages) == 1: - return self.getUnilingualFormattedValue(obj, value, showChanges) + return self.getUnilingualFormattedValue(obj, value, showChanges, + userLanguage=language) if not value: return value # Try to propose the part that is in the user language, or the part of # the first content language else. - language = obj.getUserLanguage() - if language not in value: language = languages[0] - return self.getUnilingualFormattedValue(obj, value[language], - showChanges, language) + lg = obj.getUserLanguage() + if lg not in value: lg = languages[0] + return self.getUnilingualFormattedValue(obj, value[lg], showChanges, + language=lg) def extractText(self, value): '''Extracts pure text from XHTML p_value.''' @@ -684,11 +698,15 @@ class String(Field): '''Returns the list of possible values for this field (only for fields with self.isSelect=True). If p_withTranslations is True, instead of returning a list of string values, the result is a list of tuples - (s_value, s_translation). If p_withBlankValue is True, a blank value - is prepended to the list, excepted if the type is multivalued. If + (s_value, s_translation). Moreover, p_withTranslations can hold a + given language: in this case, this language is used instead of the + user language. If p_withBlankValue is True, a blank value is + prepended to the list, excepted if the type is multivalued. If p_className is given, p_obj is the tool and, if we need an instance of p_className, we will need to use obj.executeQuery to find one.''' if not self.isSelect: raise Exception('This field is not a selection.') + # Get the user language for translations, from "withTranslations". + lg = isinstance(withTranslations, str) and withTranslations or None req = obj.REQUEST if ('masterValues' in req) and not ignoreMasterValues: # Get possible values from self.masterValue @@ -699,7 +717,7 @@ class String(Field): else: res = [] for v in values: - res.append( (v, self.getFormattedValue(obj, v)) ) + res.append( (v, self.getFormattedValue(obj,v,language=lg)) ) else: # If this field is an ajax-updatable slave, no need to compute # possible values: it will be overridden by method self.masterValue @@ -750,13 +768,13 @@ class String(Field): for value in self.validator: label = '%s_list_%s' % (self.labelId, value) if withTranslations: - res.append( (value, obj.translate(label)) ) + res.append( (value, obj.translate(label, language=lg)) ) else: res.append(value) if withBlankValue and not self.isMultiValued(): # Create the blank value to insert at the beginning of the list if withTranslations: - blankValue = ('', obj.translate('choose_a_value')) + blankValue = ('', obj.translate('choose_a_value', language=lg)) else: blankValue = '' # Insert the blank value in the result diff --git a/gen/wrappers/__init__.py b/gen/wrappers/__init__.py index 059a1f8..91f0880 100644 --- a/gen/wrappers/__init__.py +++ b/gen/wrappers/__init__.py @@ -774,6 +774,17 @@ class AbstractWrapper(object): if custom: return custom(self, *args, **kwargs) def getField(self, name): return self.o.getAppyType(name) + + def getValue(self, name, formatted=False, language=None): + '''Gets the formatted value of field p_name. If this formatting implies + translating some element, translate them in p_langue, or in the user + language if not specified.''' + field = self.o.getAppyType(name) + obj = self.o + val = field.getValue(obj) + if not formatted: return val + return field.getFormattedValue(obj, val, language=language) + def getLabel(self, name, type='field'): '''Gets the translated label of field named p_name. If p_type is "workflow", p_name denotes a workflow state or transition, not a