| Index: cms/converters.py | 
| =================================================================== | 
| --- a/cms/converters.py | 
| +++ b/cms/converters.py | 
| @@ -145,26 +145,35 @@ | 
| self._seen_defaults[(page, name)] = (default, comment) | 
| else: | 
| try: | 
| default, comment = self._seen_defaults[(page, name)] | 
| except KeyError: | 
| raise Exception('Text not yet defined for string {} on page' | 
| ' {}'.format(name, page)) | 
|  | 
| +        full_default = default | 
| # Extract tag attributes from default string | 
| default, saved_attributes, fixed_strings = ( | 
| self._attribute_parser.parse(default, self._params['page'])) | 
|  | 
| # Get translation | 
| locale = self._params['locale'] | 
| if locale == self._params['defaultlocale']: | 
| result = default | 
| elif name in localedata: | 
| result = localedata[name].strip() | 
| +            # If the string is present in default locale, but not in the | 
| +            # current one, we will get the value from default locale here. | 
| +            # If it happens to contain attributes on any tags, those need | 
| +            # to be stripped, otherwise the attribute substitution below won't | 
| +            # work. Luckily, we already have the default translation string | 
| +            # with attributes stripped -- it's the value of `default`. | 
| +            if result == full_default.strip(): | 
| +                result = default | 
| else: | 
| result = default | 
| self.missing_translations += 1 | 
| self.total_translations += 1 | 
|  | 
| # Perform callback with the string if required, e.g. for the | 
| # translations script | 
| callback = self._params['localized_string_callback'] | 
|  |