def get_source(self): ''' Returns source string from a ttkit unit. ''' if (isinstance(self.mainunit, tsunit) and self.template is None and self.mainunit.hasplural()): # Need to apply special magic for plurals here # as there is no singlular/plural in the source string return join_plural([ self.unit.source, self.unit.source, ]) if self.is_unit_key_value(): # Need to decode property encoded string if isinstance(self.mainunit, propunit): if self.template is not None: return quote.propertiesdecode(self.template.value) else: return quote.propertiesdecode(self.unit.name) if self.template is not None: return self.template.value else: return self.unit.name else: if self.template is not None: return get_string(self.template.target) else: return get_string(self.unit.source)
def perform_suggestion(unit, form, request): """Handle suggesion saving.""" if form.cleaned_data['target'][0] == '': messages.error(request, _('Your suggestion is empty!')) # Stay on same entry return False if not request.user.has_perm('suggestion.add', unit.translation): # Need privilege to add messages.error( request, _('You don\'t have privileges to add suggestions!') ) # Stay on same entry return False if not request.user.is_authenticated: # Spam check if is_spam('\n'.join(form.cleaned_data['target']), request): messages.error( request, _('Your suggestion has been identified as spam!') ) return False # Create the suggestion result = Suggestion.objects.add( unit, join_plural(form.cleaned_data['target']), request, request.user.has_perm('suggestion.vote', unit) ) if not result: messages.error(request, _('Your suggestion already exists!')) return result
def perform_suggestion(unit, form, request): ''' Handle suggesion saving. ''' if form.cleaned_data['target'][0] == '': messages.error(request, _('Your suggestion is empty!')) # Stay on same entry return False elif not can_suggest(request.user, unit.translation): # Need privilege to add messages.error( request, _('You don\'t have privileges to add suggestions!') ) # Stay on same entry return False # Invite user to become translator if there is nobody else recent_changes = Change.objects.content(True).filter( translation=unit.translation, ).exclude( user=None ) if not recent_changes.exists(): messages.info(request, _( 'There is currently no active translator for this ' 'translation, please consider becoming a translator ' 'as your suggestion might otherwise remain unreviewed.' )) # Create the suggestion Suggestion.objects.add( unit, join_plural(form.cleaned_data['target']), request, ) return True
def translate(self, request, new_target, new_state, change_action=None, propagate=True): """Store new translation of a unit.""" # Fetch current copy from database and lock it for update self.old_unit = Unit.objects.select_for_update().get(pk=self.pk) # Update unit and save it if isinstance(new_target, six.string_types): self.target = new_target not_empty = bool(new_target) else: self.target = join_plural(new_target) not_empty = bool(max(new_target)) # Newlines fixup if 'dos-eol' in self.all_flags: self.target = NEWLINES.sub('\r\n', self.target) if not_empty: self.state = new_state else: self.state = STATE_EMPTY saved = self.save_backend( request, change_action=change_action, propagate=propagate ) if (propagate and request and self.target != self.old_unit.target and self.state >= STATE_TRANSLATED): update_memory(request.user, self) return saved
def perform_suggestion(unit, form, request): """ Handle suggesion saving. """ if form.cleaned_data["target"][0] == "": messages.error(request, _("Your suggestion is empty!")) # Stay on same entry return False elif not request.user.has_perm("trans.add_suggestion"): # Need privilege to add messages.error(request, _("You don't have privileges to add suggestions!")) # Stay on same entry return False # Invite user to become translator if there is nobody else recent_changes = Change.objects.content(True).filter(translation=unit.translation).exclude(user=None) if not recent_changes.exists(): messages.info( request, _( "There is currently no active translator for this " "translation, please consider becoming a translator " "as your suggestion might otherwise remain unreviewed." ), ) # Create the suggestion Suggestion.objects.add(unit, join_plural(form.cleaned_data["target"]), request) return True
def perform_suggestion(unit, form, request): """Handle suggesion saving.""" if form.cleaned_data['target'][0] == '': messages.error(request, _('Your suggestion is empty!')) # Stay on same entry return False elif not request.user.has_perm('suggestion.add', unit.translation): # Need privilege to add messages.error( request, _('You don\'t have privileges to add suggestions!') ) # Stay on same entry return False elif not request.user.is_authenticated: # Spam check if is_spam('\n'.join(form.cleaned_data['target']), request): messages.error( request, _('Your suggestion has been identified as spam!') ) return False # Invite user to become translator if there is nobody else # and the project is accepting translations translation = unit.translation if (not translation.component.suggestion_voting or not translation.component.suggestion_autoaccept): recent_changes = Change.objects.content(True).filter( translation=translation, ).exclude( user=None ) if not recent_changes.exists(): messages.info(request, _( 'There is currently no active translator for this ' 'translation, please consider becoming a translator ' 'as your suggestion might otherwise remain unreviewed.' )) messages.info(request, mark_safe( '<a href="{0}">{1}</a>'.format( escape(get_doc_url('user/translating')), escape(_( 'See our documentation for more information ' 'on translating using Weblate.' )), ) )) # Create the suggestion result = Suggestion.objects.add( unit, join_plural(form.cleaned_data['target']), request, request.user.has_perm('suggestion.vote', unit) ) if not result: messages.error(request, _('Your suggestion already exists!')) return result
def translate(self, request, new_target, new_fuzzy): """ Stores new translation of a unit. """ # Update unit and save it self.target = join_plural(new_target) self.fuzzy = new_fuzzy saved = self.save_backend(request) return saved
def get_source(self): if self.template is None and self.mainunit.hasplural(): # Need to apply special magic for plurals here # as there is no singlular/plural in the source string source = self.unit.source return join_plural([ source, source.replace('(s)', 's'), ]) return super(TSUnit, self).get_source()
def translate(self, request, new_target, new_fuzzy, change_action=None, propagate=True): """Store new translation of a unit.""" # Update unit and save it self.target = join_plural(new_target) self.fuzzy = new_fuzzy saved = self.save_backend( request, change_action=change_action, propagate=propagate ) return saved
def translate(self, request, new_target, new_state, change_action=None, propagate=True): """Store new translation of a unit.""" # Fetch current copy from database and lock it for update self.old_unit = Unit.objects.select_for_update().get(pk=self.pk) # Update unit and save it if isinstance(new_target, six.string_types): self.target = new_target not_empty = bool(new_target) else: self.target = join_plural(new_target) not_empty = bool(max(new_target)) if not_empty: self.state = new_state else: self.state = STATE_EMPTY saved = self.save_backend( request, change_action=change_action, propagate=propagate ) return saved
def update_from_unit(self, unit, pos, created): """Update Unit from ttkit unit.""" # Get unit attributes location = unit.get_locations() flags = unit.get_flags() target = unit.get_target() source = unit.get_source() comment = unit.get_comments() state = self.get_unit_state(unit, created) previous_source = unit.get_previous_source() content_hash = unit.get_content_hash() # Monolingual files handling (without target change) if unit.template is not None and target == self.target: if source != self.source and state == STATE_TRANSLATED: if self.previous_source == self.source and self.fuzzy: # Source change was reverted previous_source = '' state = STATE_TRANSLATED else: # Store previous source and fuzzy flag for monolingual if previous_source == '': previous_source = self.source state = STATE_FUZZY else: # We should keep calculated flags if translation was # not changed outside previous_source = self.previous_source state = self.state # Update checks on fuzzy update or on content change same_content = ( target == self.target and source == self.source ) same_state = (state == self.state and not created) # Check if we actually need to change anything # pylint: disable=too-many-boolean-expressions if (not created and location == self.location and flags == self.flags and same_content and same_state and comment == self.comment and pos == self.position and content_hash == self.content_hash and previous_source == self.previous_source): return # Ensure we track source string source_info, source_created = Source.objects.get_or_create( id_hash=self.id_hash, component=self.translation.component ) contentsum_changed = self.content_hash != content_hash # Store updated values self.position = pos self.location = location self.flags = flags self.source = source self.target = target self.state = state self.comment = comment self.content_hash = content_hash self.previous_source = previous_source self.priority = source_info.priority # Sanitize number of plurals if self.is_plural(): self.target = join_plural(self.get_target_plurals()) if created: unit_pre_create.send(sender=self.__class__, unit=self) # Save into database self.save( force_insert=created, backend=True, same_content=same_content, same_state=same_state, ) # Create change object for new source string if source_created: Change.objects.create( action=Change.ACTION_NEW_SOURCE, unit=self, ) if contentsum_changed: self.update_has_failing_check(recurse=False) self.update_has_comment() self.update_has_suggestion()
def update_from_unit(self, unit, pos, created): """Update Unit from ttkit unit.""" component = self.translation.component self.is_batch_update = True # Get unit attributes location = unit.locations flags = unit.flags target = unit.target source = unit.source context = unit.context comment = unit.comments state = self.get_unit_state(unit) previous_source = unit.previous_source content_hash = unit.content_hash # Monolingual files handling (without target change) if not created and unit.template is not None and target == self.target: if source != self.source and state >= STATE_TRANSLATED: if self.previous_source == self.source and self.fuzzy: # Source change was reverted previous_source = '' state = STATE_TRANSLATED else: # Store previous source and fuzzy flag for monolingual if previous_source == '': previous_source = self.source state = STATE_FUZZY else: # We should keep calculated flags if translation was # not changed outside previous_source = self.previous_source state = self.state # Update checks on fuzzy update or on content change same_target = target == self.target same_source = (source == self.source and context == self.context) same_state = (state == self.state and flags == self.flags) # Check if we actually need to change anything # pylint: disable=too-many-boolean-expressions if (location == self.location and flags == self.flags and same_source and same_target and same_state and comment == self.comment and pos == self.position and content_hash == self.content_hash and previous_source == self.previous_source): return # Ensure we track source string source_info, source_created = component.get_source(self.id_hash) self.__dict__['source_info'] = source_info # Store updated values self.position = pos self.location = location self.flags = flags self.source = source self.target = target self.state = state self.context = context self.comment = comment self.content_hash = content_hash self.previous_source = previous_source self.priority = source_info.priority # Sanitize number of plurals if self.is_plural(): self.target = join_plural(self.get_target_plurals()) if created: unit_pre_create.send(sender=self.__class__, unit=self) # Save into database self.save( force_insert=created, same_content=same_source and same_target, same_state=same_state, ) # Create change object for new source string if source_created: Change.objects.create( action=Change.ACTION_NEW_SOURCE, unit=self, ) # Track updated sources for source checks if source_created or not same_source: component.updated_sources[self.id_hash] = self
def translate(request, project, subproject, lang): obj = get_object_or_404(Translation, language__code = lang, subproject__slug = subproject, subproject__project__slug = project, enabled = True) if obj.subproject.locked: messages.error(request, _('This translation is currently locked for updates!')) if request.user.is_authenticated(): profile = request.user.get_profile() else: profile = None secondary = None unit = None rqtype, direction, pos, search_query, search_exact, search_source, search_target, search_context, search_url = parse_search_url(request) # Any form submitted? if request.method == 'POST': form = TranslationForm(request.POST) if form.is_valid() and not obj.subproject.locked: # Check whether translation is not outdated obj.check_sync() try: try: unit = Unit.objects.get(checksum = form.cleaned_data['checksum'], translation = obj) except Unit.MultipleObjectsReturned: # Possible temporary inconsistency caused by ongoing update of repo, # let's pretend everyting is okay unit = Unit.objects.filter(checksum = form.cleaned_data['checksum'], translation = obj)[0] if 'suggest' in request.POST: # Handle suggesion saving user = request.user if isinstance(user, AnonymousUser): user = None if form.cleaned_data['target'] == len(form.cleaned_data['target']) * ['']: messages.error(request, _('Your suggestion is empty!')) # Stay on same entry return HttpResponseRedirect('%s?type=%s&pos=%d&dir=stay%s' % ( obj.get_translate_url(), rqtype, pos, search_url )) Suggestion.objects.create( target = join_plural(form.cleaned_data['target']), checksum = unit.checksum, language = unit.translation.language, project = unit.translation.subproject.project, user = user) # Update suggestion stats if profile is not None: profile.suggested += 1 profile.save() elif not request.user.is_authenticated(): # We accept translations only from authenticated messages.error(request, _('You need to log in to be able to save translations!')) elif not request.user.has_perm('trans.save_translation'): # Need privilege to save messages.error(request, _('You don\'t have privileges to save translations!')) else: # Remember old checks oldchecks = set(unit.active_checks().values_list('check', flat = True)) # Update unit and save it unit.target = join_plural(form.cleaned_data['target']) unit.fuzzy = form.cleaned_data['fuzzy'] unit.save_backend(request) # Update stats profile.translated += 1 profile.save() # Get new set of checks newchecks = set(unit.active_checks().values_list('check', flat = True)) # Did we introduce any new failures? if newchecks > oldchecks: # Show message to user messages.error(request, _('Some checks have failed on your translation!')) # Stay on same entry return HttpResponseRedirect('%s?type=%s&pos=%d&dir=stay%s' % ( obj.get_translate_url(), rqtype, pos, search_url )) # Redirect to next entry return HttpResponseRedirect('%s?type=%s&pos=%d%s' % ( obj.get_translate_url(), rqtype, pos, search_url )) except Unit.DoesNotExist: logger.error('message %s disappeared!', form.cleaned_data['checksum']) messages.error(request, _('Message you wanted to translate is no longer available!')) # Handle translation merging if 'merge' in request.GET: if not request.user.has_perm('trans.save_translation'): # Need privilege to save messages.error(request, _('You don\'t have privileges to save translations!')) else: try: mergeform = MergeForm(request.GET) if mergeform.is_valid(): try: unit = Unit.objects.get(checksum = mergeform.cleaned_data['checksum'], translation = obj) except Unit.MultipleObjectsReturned: # Possible temporary inconsistency caused by ongoing update of repo, # let's pretend everyting is okay unit = Unit.objects.filter(checksum = mergeform.cleaned_data['checksum'], translation = obj)[0] merged = Unit.objects.get(pk = mergeform.cleaned_data['merge']) if unit.checksum != merged.checksum: messages.error(request, _('Can not merge different messages!')) else: unit.target = merged.target unit.fuzzy = merged.fuzzy unit.save_backend(request) # Update stats profile.translated += 1 profile.save() # Redirect to next entry return HttpResponseRedirect('%s?type=%s&pos=%d%s' % ( obj.get_translate_url(), rqtype, pos, search_url )) except Unit.DoesNotExist: logger.error('message %s disappeared!', form.cleaned_data['checksum']) messages.error(request, _('Message you wanted to translate is no longer available!')) # Handle accepting/deleting suggestions if not obj.subproject.locked and ('accept' in request.GET or 'delete' in request.GET): # Check for authenticated users if not request.user.is_authenticated(): messages.error(request, _('You need to log in to be able to manage suggestions!')) return HttpResponseRedirect('%s?type=%s&pos=%d&dir=stay%s' % ( obj.get_translate_url(), rqtype, pos, search_url )) # Parse suggestion ID if 'accept' in request.GET: if not request.user.has_perm('trans.accept_suggestion'): messages.error(request, _('You do not have privilege to accept suggestions!')) return HttpResponseRedirect('%s?type=%s&pos=%d&dir=stay%s' % ( obj.get_translate_url(), rqtype, pos, search_url )) sugid = request.GET['accept'] else: if not request.user.has_perm('trans.delete_suggestion'): messages.error(request, _('You do not have privilege to delete suggestions!')) return HttpResponseRedirect('%s?type=%s&pos=%d&dir=stay%s' % ( obj.get_translate_url(), rqtype, pos, search_url )) sugid = request.GET['delete'] try: sugid = int(sugid) suggestion = Suggestion.objects.get(pk = sugid) except: suggestion = None if suggestion is not None: if 'accept' in request.GET: # Accept suggesiont suggestion.accept(request) # Delete suggestion in both cases (accepted ones are no longer needed) suggestion.delete() else: messages.error(request, _('Invalid suggestion!')) # Redirect to same entry for possible editing return HttpResponseRedirect('%s?type=%s&pos=%d&dir=stay%s' % ( obj.get_translate_url(), rqtype, pos, search_url )) reviewform = ReviewForm(request.GET) if reviewform.is_valid(): allunits = obj.unit_set.review(reviewform.cleaned_data['date'], request.user) # Review if direction == 'stay': units = allunits.filter(position = pos) elif direction == 'back': units = allunits.filter(position__lt = pos).order_by('-position') else: units = allunits.filter(position__gt = pos) elif search_query != '': # Apply search conditions if search_exact: query = Q() if search_source: query |= Q(source = search_query) if search_target: query |= Q(target = search_query) if search_context: query |= Q(context = search_query) allunits = obj.unit_set.filter(query) else: allunits = obj.unit_set.search(search_query, search_source, search_context, search_target) if direction == 'stay': units = obj.unit_set.filter(position = pos) elif direction == 'back': units = allunits.filter(position__lt = pos).order_by('-position') else: units = allunits.filter(position__gt = pos) else: allunits = obj.unit_set.filter_type(rqtype) # What unit set is about to show if direction == 'stay': units = obj.unit_set.filter(position = pos) elif direction == 'back': units = allunits.filter(position__lt = pos).order_by('-position') else: units = allunits.filter(position__gt = pos) # If we failed to get unit above or on no POST if unit is None: # Grab actual unit try: unit = units[0] except IndexError: messages.info(request, _('You have reached end of translating.')) return HttpResponseRedirect(obj.get_absolute_url()) # Show secondary languages for logged in users if profile: secondary = Unit.objects.filter( checksum = unit.checksum, translated = True, translation__subproject__project = unit.translation.subproject.project, translation__language__in = profile.secondary_languages.exclude(id = unit.translation.language.id) ) # distinct('target') works with Django 1.4 so let's emulate that # based on presumption we won't get too many results targets = {} res = [] for s in secondary: if s.target in targets: continue targets[s.target] = 1 res.append(s) secondary = res # Prepare form form = TranslationForm(initial = { 'checksum': unit.checksum, 'target': (unit.translation.language, unit.get_target_plurals()), 'fuzzy': unit.fuzzy, }) total = obj.unit_set.all().count() filter_count = allunits.count() return render_to_response('translate.html', RequestContext(request, { 'object': obj, 'unit': unit, 'changes': unit.change_set.all()[:10], 'total': total, 'type': rqtype, 'filter_name': get_filter_name(rqtype, search_query), 'filter_count': filter_count, 'filter_pos': filter_count + 1 - units.count(), 'form': form, 'target_language': obj.language.code, 'secondary': secondary, 'search_query': search_query, 'search_url': search_url, 'search_query': search_query, 'search_source': bool2str(search_source), 'search_exact': bool2str(search_exact), 'search_target': bool2str(search_target), 'search_context': bool2str(search_context), }))
def update_from_unit(self, unit, pos, created): """Update Unit from ttkit unit.""" translation = self.translation component = translation.component self.is_batch_update = True self.source_updated = True # Get unit attributes try: location = unit.locations flags = unit.flags source = unit.source self.check_valid(split_plural(source)) if not translation.is_template and translation.is_source: # Load target from source string for bilingual source translations target = source else: target = unit.target self.check_valid(split_plural(target)) context = unit.context self.check_valid([context]) note = unit.notes previous_source = unit.previous_source content_hash = unit.content_hash except Exception as error: report_error(cause="Unit update error") translation.component.handle_parse_error(error, translation) # Ensure we track source string for bilingual, this can not use # Unit.is_source as that depends on source_unit attribute, which # we set here if not translation.is_source: source_unit = component.get_source( self.id_hash, create={ "source": source, "target": source, "context": context, "content_hash": calculate_hash(source, context), "position": pos, "note": note, "location": location, "flags": flags, }, ) if ( not source_unit.source_updated and not component.has_template() and ( pos != source_unit.position or location != source_unit.location or flags != source_unit.flags or note != source_unit.note ) ): source_unit.position = pos source_unit.source_updated = True source_unit.location = location source_unit.flags = flags source_unit.note = note source_unit.save( update_fields=["position", "location", "flags", "note"], same_content=True, same_state=True, ) self.source_unit = source_unit # Calculate state state = self.get_unit_state(unit, flags) self.original_state = self.get_unit_state(unit, None) # Has source changed same_source = source == self.source and context == self.context # Monolingual files handling (without target change) if ( not created and state != STATE_READONLY and unit.template is not None and target == self.target ): if not same_source and state in (STATE_TRANSLATED, STATE_APPROVED): if self.previous_source == self.source and self.fuzzy: # Source change was reverted previous_source = "" state = STATE_TRANSLATED else: # Store previous source and fuzzy flag for monolingual if previous_source == "": previous_source = self.source state = STATE_FUZZY elif self.state in (STATE_FUZZY, STATE_APPROVED): # We should keep calculated flags if translation was # not changed outside previous_source = self.previous_source state = self.state # Update checks on fuzzy update or on content change same_target = target == self.target same_state = state == self.state and flags == self.flags # Check if we actually need to change anything # pylint: disable=too-many-boolean-expressions if ( location == self.location and flags == self.flags and same_source and same_target and same_state and note == self.note and pos == self.position and content_hash == self.content_hash and previous_source == self.previous_source ): return # Store updated values self.position = pos self.location = location self.flags = flags self.source = source self.target = target self.state = state self.context = context self.note = note self.content_hash = content_hash self.previous_source = previous_source self.update_priority(save=False) # Sanitize number of plurals if self.is_plural: self.target = join_plural(self.get_target_plurals()) if created: unit_pre_create.send(sender=self.__class__, unit=self) # Save into database self.save( force_insert=created, same_content=same_source and same_target, same_state=same_state, ) # Track updated sources for source checks if translation.is_template: component.updated_sources[self.id_hash] = self # Indicate source string change if not same_source and previous_source: Change.objects.create( unit=self, action=Change.ACTION_SOURCE_CHANGE, old=previous_source, target=self.source, )
def update_from_unit(self, unit, pos, created): """Update Unit from ttkit unit.""" # Get unit attributes location = unit.get_locations() flags = unit.get_flags() target = unit.get_target() source = unit.get_source() comment = unit.get_comments() state = self.get_unit_state(unit, created) previous_source = unit.get_previous_source() content_hash = unit.get_content_hash() # Monolingual files handling (without target change) if unit.template is not None and target == self.target: if source != self.source and state == STATE_TRANSLATED: if self.previous_source == self.source and self.fuzzy: # Source change was reverted previous_source = '' state = STATE_TRANSLATED else: # Store previous source and fuzzy flag for monolingual if previous_source == '': previous_source = self.source state = STATE_FUZZY else: # We should keep calculated flags if translation was # not changed outside previous_source = self.previous_source state = self.state # Update checks on fuzzy update or on content change same_content = (target == self.target and source == self.source) same_state = (state == self.state and not created) # Check if we actually need to change anything # pylint: disable=too-many-boolean-expressions if (not created and location == self.location and flags == self.flags and same_content and same_state and comment == self.comment and pos == self.position and content_hash == self.content_hash and previous_source == self.previous_source): return # Ensure we track source string source_info, source_created = Source.objects.get_or_create( id_hash=self.id_hash, component=self.translation.component) contentsum_changed = self.content_hash != content_hash # Store updated values self.position = pos self.location = location self.flags = flags self.source = source self.target = target self.state = state self.comment = comment self.content_hash = content_hash self.previous_source = previous_source self.priority = source_info.priority # Sanitize number of plurals if self.is_plural(): self.target = join_plural(self.get_target_plurals()) if created: unit_pre_create.send(sender=self.__class__, unit=self) # Save into database self.save( force_insert=created, backend=True, same_content=same_content, same_state=same_state, ) # Create change object for new source string if source_created: Change.objects.create( action=Change.ACTION_NEW_SOURCE, unit=self, ) if contentsum_changed: self.update_has_failing_check(recurse=False) self.update_has_comment() self.update_has_suggestion()
def update_from_unit(self, unit, pos, created): """Update Unit from ttkit unit.""" component = self.translation.component self.is_batch_update = True # Get unit attributes try: location = unit.locations flags = unit.flags target = unit.target source = unit.source context = unit.context note = unit.notes previous_source = unit.previous_source content_hash = unit.content_hash except Exception as error: self.translation.component.handle_parse_error( error, self.translation) # Ensure we track source string for bilingual if not self.translation.is_source: source_unit = component.get_source( self.id_hash, source=source, target=source, context=context, content_hash=calculate_hash(source, context), position=0, location=location, flags=flags, ) self.extra_context = source_unit.extra_context self.extra_flags = source_unit.extra_flags # Calculate state state = self.get_unit_state(unit, flags) self.original_state = self.get_unit_state(unit, None) # Monolingual files handling (without target change) if not created and unit.template is not None and target == self.target: if source != self.source and state >= STATE_TRANSLATED: if self.previous_source == self.source and self.fuzzy: # Source change was reverted previous_source = '' state = STATE_TRANSLATED else: # Store previous source and fuzzy flag for monolingual if previous_source == '': previous_source = self.source state = STATE_FUZZY elif self.state in (STATE_FUZZY, STATE_APPROVED): # We should keep calculated flags if translation was # not changed outside previous_source = self.previous_source state = self.state # Update checks on fuzzy update or on content change same_target = target == self.target same_source = source == self.source and context == self.context same_state = state == self.state and flags == self.flags # Check if we actually need to change anything # pylint: disable=too-many-boolean-expressions if (location == self.location and flags == self.flags and same_source and same_target and same_state and note == self.note and pos == self.position and content_hash == self.content_hash and previous_source == self.previous_source): return # Store updated values self.position = pos self.location = location self.flags = flags self.source = source self.target = target self.state = state self.context = context self.note = note self.content_hash = content_hash self.previous_source = previous_source self.update_priority(save=False) # Sanitize number of plurals if self.is_plural(): self.target = join_plural(self.get_target_plurals()) if created: unit_pre_create.send(sender=self.__class__, unit=self) # Save into database self.save( force_insert=created, same_content=same_source and same_target, same_state=same_state, ) # Track updated sources for source checks if self.translation.is_template: component.updated_sources[self.id_hash] = self