def _handle_removing_translation(event): obj = event.source removed_language = event.language translation = event.translation if obj.indexed: for member in obj.__class__.iter_members(): if (member.translated and member.indexed and obj._should_index_member(member)): value = obj.get(member, removed_language) # Remove index entries for the removed language and all its # derived translations for lang in obj.iter_derived_translations(removed_language, include_self=True): remove_index_entry(obj, member, value, lang) # Add index entries for derived translations that now # inherit their values from a different fallback language. if lang != removed_language: for fallback in iter_language_chain(lang): if (fallback != removed_language and fallback in obj.translations): add_index_entry(obj, member, obj.get(member, fallback), lang) break
def iter_derived_translations(self, language=None, include_self=False): language = require_language(language) for derived_lang in descend_language_tree(language, include_self=include_self): for chain_lang in iter_language_chain(derived_lang): if chain_lang == language: yield derived_lang break elif chain_lang in self.translations: break
def _handle_translation_removed(event): if not indexing_enabled: return obj = event.source id = obj.id removed_language = event.language translated_members = [] if obj._should_index_member_full_text(obj.__class__): translated_members.append(obj.__class__) translated_members.extend( member for member in obj.__class__.iter_members() if member.translated and obj._should_index_member_full_text(member) ) for lang in obj.iter_derived_translations( removed_language, include_self = True ): for member in translated_members: index = member.get_full_text_index(lang) index.unindex_doc(id) if lang != removed_language: for chain_lang in iter_language_chain(lang): if ( chain_lang != removed_language and chain_lang in obj.translations ): for member in translated_members: if isinstance(member, type): text = obj.get_searchable_text( languages = (chain_lang,) ) else: text = obj.get(member, chain_lang) if text: text = normalize(text) if text: index = member.get_full_text_index(lang) index.index_doc(id, text) break
def _init_translation(cls, instance, values=None, accessor=None, excluded_members=None, copy_from_fallback=True): # Set 'translated_object' and 'language' first, so events for changes in # all other members are relayed to the translation owner if values is not None: language = values.pop("language") if language is not None: instance.language = language translated_object = values.pop("translated_object") if translated_object is not None: instance.translated_object = translated_object if language is not None and translated_object is not None: translated_object.translations[language] = instance if excluded_members is None: excluded_members = (cls.translated_object, cls.language) else: excluded_members = \ set([cls.translated_object, cls.language]) + set(excluded_members) # Copy values from the first available fallback translation if (copy_from_fallback and language is not None and translated_object is not None): languages = iter_language_chain(language) next(languages) get_translation = translated_object.translations.get for lang in languages: base_translation = get_translation(lang) if base_translation is not None: for key, member in cls.members().items(): if member not in excluded_members: values.setdefault(key, base_translation.get(key)) break Schema.init_instance(cls, instance, values, accessor, excluded_members)
def __get__(self, instance, type=None, language=None): if instance is None: return self.member else: # Calculated field expression = self.member.expression if expression is not None: return self.member.resolve_expression(instance, language) if self.member.translated: for language in iter_language_chain(language): target = instance.translations.get(language) if target is not None: break else: return None else: target = instance value = getattr(target, self.__priv_key, undefined) if value is undefined: if getattr(instance, "_v_is_producing_default", False): return None instance._v_is_producing_default = True try: value = self.member.produce_default(instance) self.__set__(instance, value, language=language, previous_value=None) return self.__get__(instance, type, language) finally: instance._v_is_producing_default = False return value
def _handle_form_data(self): stack_node = self.stack_node form_data = stack_node.form_data translations = stack_node.translations section = self.params.read(schema.String("section", default="fields")) added_translation = self.params.read( schema.String("add_translation", enumeration=self.available_languages)) deleted_translation = self.params.read( schema.String("delete_translation", enumeration=translations)) # Remove translations if deleted_translation: translations.remove(deleted_translation) for key, member in self.fields_schema.members().iteritems(): if member.translated: values = form_data.get(key) if values: values.pop(deleted_translation, None) get_method = cherrypy.request.method.upper() == "GET" # Load form data from the request get_parameter(self.fields_schema, target=form_data, languages=translations, prefix=self.form_prefix, errors="ignore", implicit_booleans=not get_method, undefined="skip" if get_method else "set_none") # Add translations if added_translation and added_translation not in translations: translations.append(added_translation) # Try to copy an existing fallback translation for fallback_language in iter_language_chain(added_translation, include_self=False): if fallback_language in translations: for key, member in self.fields_schema.members().iteritems( ): if member.translated: value = schema.get(form_data, key, language=fallback_language) schema.set(form_data, key, value, language=added_translation) break # If there's no fallback translation to use, create a new # translation from scratch else: translation_data = {} stack_node.content_type.translation.init_instance( translation_data) for key, value in translation_data.iteritems(): schema.set(form_data, key, value, language=added_translation) # Drop references unlink = cherrypy.request.params.get("relation-unlink") if unlink: form_data[unlink] = None return form_data
def get_source_locale(self, locale): translations = self.translations for locale in iter_language_chain(locale): if locale in translations: return locale