diff options
| author | Martin Trigaux <mat@odoo.com> | 2020-06-15 15:16:16 +0200 |
|---|---|---|
| committer | Martin Trigaux <mat@odoo.com> | 2020-06-18 13:03:34 +0200 |
| commit | 80e97e98ce76067db1079af8feeef667cfadf837 (patch) | |
| tree | e261d34e3f8458bd99011f60f508bcce2c723baf /addons | |
| parent | 4a92a183e8631512a8b018eedaf9bf4956ca85e9 (diff) | |
[IMP] *: use named placeholders in translated message
When more than one parameter is present in a message, it helps the
translation to use named placeholder. This way, the order can be
changed. It also helps the comprehension of the message.
Diffstat (limited to 'addons')
44 files changed, 309 insertions, 111 deletions
diff --git a/addons/account/models/account_account.py b/addons/account/models/account_account.py index 980e58a8ef7..1622338baf2 100644 --- a/addons/account/models/account_account.py +++ b/addons/account/models/account_account.py @@ -147,7 +147,11 @@ class AccountAccount(models.Model): if res: account = self.env['account.account'].browse(res[0]) journal = self.env['account.journal'].browse(res[1]) - raise ValidationError(_("The foreign currency set on the journal '%s' and the account '%s' must be the same.") % (journal.display_name, account.display_name)) + raise ValidationError(_( + "The foreign currency set on the journal '%(journal)s' and the account '%(account)s' must be the same.", + journal=journal.display_name, + account=account.display_name + )) @api.constrains('company_id') def _check_company_consistency(self): diff --git a/addons/account/models/account_bank_statement.py b/addons/account/models/account_bank_statement.py index 85064116369..502d91c563b 100644 --- a/addons/account/models/account_bank_statement.py +++ b/addons/account/models/account_bank_statement.py @@ -317,8 +317,11 @@ class AccountBankStatement(models.Model): else: balance_end_real = formatLang(self.env, stmt.balance_end_real, currency_obj=stmt.currency_id) balance_end = formatLang(self.env, stmt.balance_end, currency_obj=stmt.currency_id) - raise UserError(_('The ending balance is incorrect !\nThe expected balance (%s) is different from the computed one. (%s)') - % (balance_end_real, balance_end)) + raise UserError(_( + 'The ending balance is incorrect !\nThe expected balance (%(real_balance)s) is different from the computed one (%(computed_balance)s).', + real_balance=balance_end_real, + computed_balance=balance_end + )) return True def unlink(self): diff --git a/addons/account/models/account_journal.py b/addons/account/models/account_journal.py index d8da1deea14..f424d2fb738 100644 --- a/addons/account/models/account_journal.py +++ b/addons/account/models/account_journal.py @@ -270,7 +270,11 @@ class AccountJournal(models.Model): ''', [tuple(accounts.ids)]) res = self._cr.fetchone() if res: - raise ValidationError(_("The account %s can't be shared between multiple journals: %s") % (res[0], ', '.join(res[1]))) + raise ValidationError(_( + "The account %(account_name)s can't be shared between multiple journals: %(journals)s", + account_name=res[0], + journals=', '.join(res[1]) + )) @api.constrains('type', 'default_credit_account_id', 'default_debit_account_id') def _check_type_default_credit_account_id_type(self): diff --git a/addons/account/models/account_move.py b/addons/account/models/account_move.py index aee49964d71..9263f9519f4 100644 --- a/addons/account/models/account_move.py +++ b/addons/account/models/account_move.py @@ -65,9 +65,10 @@ class AccountMove(models.Model): if not journal: company = self.env['res.company'].browse(company_id) - error_msg = _("No journal could be found in company %s for any of those types: %s") % ( - company.display_name, - ', '.join(journal_types), + error_msg = _( + "No journal could be found in company %(company_name)s for any of those types: %(journal_types)s", + company_name=company.display_name, + journal_types=', '.join(journal_types), ) raise UserError(error_msg) @@ -91,7 +92,11 @@ class AccountMove(models.Model): journal = self.env['account.journal'].browse(self._context['default_journal_id']) if move_type != 'entry' and journal.type not in journal_types: - raise UserError(_("Cannot create an invoice of type %s with a journal having %s as type.") % (move_type, journal.type)) + raise UserError(_( + "Cannot create an invoice of type %(move_type)s with a journal having %(journal_type)s as type.", + move_type=move_type, + journal_type=journal.type, + )) else: journal = self._search_default_journal(journal_types) diff --git a/addons/account/wizard/account_move_reversal.py b/addons/account/wizard/account_move_reversal.py index e7c51be9aaf..f83fc3a950c 100644 --- a/addons/account/wizard/account_move_reversal.py +++ b/addons/account/wizard/account_move_reversal.py @@ -57,7 +57,9 @@ class AccountMoveReversal(models.TransientModel): def _prepare_default_reversal(self, move): reverse_date = self.date if self.date_mode == 'custom' else move.date return { - 'ref': _('Reversal of: %s, %s') % (move.name, self.reason) if self.reason else _('Reversal of: %s') % (move.name), + 'ref': _('Reversal of: %(move_name)s, %(reason)s', move_name=move.name, reason=self.reason) + if self.reason + else _('Reversal of: %s', move.name), 'date': reverse_date, 'invoice_date': move.is_invoice(include_receipts=True) and (self.date or move.date) or False, 'journal_id': self.journal_id and self.journal_id.id or move.journal_id.id, diff --git a/addons/base_vat/models/res_partner.py b/addons/base_vat/models/res_partner.py index 0b54f0e0286..17f379012bc 100644 --- a/addons/base_vat/models/res_partner.py +++ b/addons/base_vat/models/res_partner.py @@ -162,8 +162,18 @@ class ResPartner(models.Model): else: company = self.env.company if company.vat_check_vies: - return '\n' + _('The VAT number [%s] for partner [%s] either failed the VIES VAT validation check or did not respect the expected format %s.') % (self.vat, self.name, vat_no) - return '\n' + _('The VAT number [%s] for partner [%s] does not seem to be valid. \nNote: the expected format is %s') % (self.vat, self.name, vat_no) + return '\n' + _( + 'The VAT number [%(vat)s] for partner [%(name)s] either failed the VIES VAT validation check or did not respect the expected format %(format)s.', + vat=self.vat, + name=self.name, + format=vat_no + ) + return '\n' + _( + 'The VAT number [%(vat)s] for partner [%(name)s] does not seem to be valid. \nNote: the expected format is %(format)s', + vat=self.vat, + name=self.name, + format=vat_no + ) __check_vat_ch_re1 = re.compile(r'(MWST|TVA|IVA)[0-9]{6}$') __check_vat_ch_re2 = re.compile(r'E([0-9]{9}|-[0-9]{3}\.[0-9]{3}\.[0-9]{3})(MWST|TVA|IVA)$') diff --git a/addons/calendar/models/calendar_event.py b/addons/calendar/models/calendar_event.py index df6347a678c..68740cae04d 100644 --- a/addons/calendar/models/calendar_event.py +++ b/addons/calendar/models/calendar_event.py @@ -135,25 +135,27 @@ class Meeting(models.Model): time_str = to_text(date.strftime(format_time)) if zallday: - display_time = _("AllDay , %s") % (date_str) + display_time = _("AllDay , %(day)s", day=date_str) elif zduration < 24: duration = date + timedelta(minutes=round(zduration*60)) duration_time = to_text(duration.strftime(format_time)) - display_time = _(u"%s at (%s To %s) (%s)") % ( - date_str, - time_str, - duration_time, - timezone, + display_time = _( + u"%(day)s at (%(start)s To %(end)s) (%(timezone)s)", + day=date_str, + start=time_str, + end=duration_time, + timezone=timezone, ) else: dd_date = to_text(date_deadline.strftime(format_date)) dd_time = to_text(date_deadline.strftime(format_time)) - display_time = _(u"%s at %s To\n %s at %s (%s)") % ( - date_str, - time_str, - dd_date, - dd_time, - timezone, + display_time = _( + u"%(date_start)s at %(time_start)s To\n %(date_end)s at %(time_end)s (%(timezone)s)", + date_start=date_str, + time_start=time_str, + date_end=dd_date, + time_end=dd_time, + timezone=timezone, ) return display_time @@ -356,12 +358,20 @@ class Meeting(models.Model): if meeting.start and meeting.stop and meeting.stop < meeting.start: raise ValidationError( _('The ending date and time cannot be earlier than the starting date and time.') + '\n' + - _("Meeting '%s' starts '%s' and ends '%s'") % (meeting.name, meeting.start, meeting.stop) + _("Meeting '%(name)s' starts '%(start_datetime)s' and ends '%(end_datetime)s'", + name=meeting.name, + start_datetime=meeting.start, + end_datetime=meeting.stop + ) ) if meeting.start_date and meeting.stop_date and meeting.stop_date < meeting.start_date: raise ValidationError( _('The ending date cannot be earlier than the starting date.') + '\n' + - _("Meeting '%s' starts '%s' and ends '%s'") % (meeting.name, meeting.start_date, meeting.stop_date) + _("Meeting '%(name)s' starts '%(start_datetime)s' and ends '%(end_datetime)s'", + name=meeting.name, + start_datetime=meeting.start, + end_datetime=meeting.stop + ) ) #################################################### diff --git a/addons/calendar/models/calendar_recurrence.py b/addons/calendar/models/calendar_recurrence.py index 73c671c611a..9dae012b6d4 100644 --- a/addons/calendar/models/calendar_recurrence.py +++ b/addons/calendar/models/calendar_recurrence.py @@ -124,7 +124,7 @@ class RecurrenceRule(models.Model): def _compute_name(self): for recurrence in self: period = dict(RRULE_TYPE_SELECTION)[recurrence.rrule_type] - every = _("Every %s %s, ") % (recurrence.interval, period) + every = _("Every %(count)s %(period)s, ", count=recurrence.interval, period=period) if recurrence.end_type == 'count': end = _("for %s events", recurrence.count) @@ -140,7 +140,7 @@ class RecurrenceRule(models.Model): elif recurrence.rrule_type == 'monthly': if recurrence.month_by == 'day': weekday_label = dict(BYDAY_SELECTION)[recurrence.byday] - on = _("on the %(position)s %(weekday)s, ") % {'position': recurrence.byday, 'weekday': weekday_label} + on = _("on the %(position)s %(weekday)s, ", position=recurrence.byday, weekday=weekday_label) else: on = _("day %s, ", recurrence.day) else: diff --git a/addons/calendar_sms/models/calendar.py b/addons/calendar_sms/models/calendar.py index 6b08ddcbe9d..b47a28b0916 100644 --- a/addons/calendar_sms/models/calendar.py +++ b/addons/calendar_sms/models/calendar.py @@ -22,7 +22,7 @@ class CalendarEvent(models.Model): for event in self: event._message_sms_with_template( template_xmlid='calendar_sms.sms_template_data_calendar_reminder', - template_fallback=_("Event reminder: %s, %s.") % (event.name, event.display_time), + template_fallback=_("Event reminder: %(name)s, %(time)s.", name=event.name, time=event.display_time), partner_ids=self._sms_get_default_partners().ids, put_in_queue=False ) diff --git a/addons/crm/models/crm_lead.py b/addons/crm/models/crm_lead.py index 2c7b2b541f7..52f669bb9ba 100644 --- a/addons/crm/models/crm_lead.py +++ b/addons/crm/models/crm_lead.py @@ -894,7 +894,11 @@ class Lead(models.Model): for message in opportunity.message_ids: message.write({ 'res_id': self.id, - 'subject': _("From %s : %s") % (opportunity.name, message.subject) + 'subject': _( + "From %(source_name)s : %(source_subject)s", + source_name=opportunity.name, + source_subject=message.subject + ) }) return True diff --git a/addons/delivery/models/stock_picking.py b/addons/delivery/models/stock_picking.py index f7f10919a7c..d4c90d77d55 100644 --- a/addons/delivery/models/stock_picking.py +++ b/addons/delivery/models/stock_picking.py @@ -172,7 +172,13 @@ class StockPicking(models.Model): if res['tracking_number']: self.carrier_tracking_ref = res['tracking_number'] order_currency = self.sale_id.currency_id or self.company_id.currency_id - msg = _("Shipment sent to carrier %s for shipping with tracking number %s<br/>Cost: %.2f %s") % (self.carrier_id.name, self.carrier_tracking_ref, self.carrier_price, order_currency.name) + msg = _( + "Shipment sent to carrier %(carrier_name)s for shipping with tracking number %(ref)s<br/>Cost: %(price).2f %(currency)s", + carrier_name=self.carrier_id.name, + ref=self.carrier_tracking_ref, + price=self.carrier_price, + currency=order_currency.name + ) self.message_post(body=msg) self._add_delivery_cost_to_so() diff --git a/addons/gamification/models/challenge.py b/addons/gamification/models/challenge.py index 72fcf48ebad..93efdef0d9b 100644 --- a/addons/gamification/models/challenge.py +++ b/addons/gamification/models/challenge.py @@ -656,7 +656,11 @@ class Challenge(models.Model): if rewarded_users: user_names = rewarded_users.name_get() - message_body += _("<br/>Reward (badge %s) for every succeeding user was sent to %s.") % (challenge.reward_id.name, ", ".join(name for (user_id, name) in user_names)) + message_body += _( + "<br/>Reward (badge %(badge_name)s) for every succeeding user was sent to %(users)s.", + badge_name=challenge.reward_id.name, + users=", ".join(name for (user_id, name) in user_names) + ) else: message_body += _("<br/>Nobody has succeeded to reach every goal, no badge is rewarded for this challenge.") diff --git a/addons/gamification/models/goal.py b/addons/gamification/models/goal.py index 2236a5baa45..e26ac0b37ff 100644 --- a/addons/gamification/models/goal.py +++ b/addons/gamification/models/goal.py @@ -111,11 +111,17 @@ class GoalDefinition(models.Model): Model = self.env[definition.model_id.model] field = Model._fields.get(definition.field_id.name) if not (field and field.store): - raise exceptions.UserError( - _("The model configuration for the definition %s seems incorrect, please check it.\n\n%s not stored") % (definition.name, definition.field_id.name)) + raise exceptions.UserError(_( + "The model configuration for the definition %(name)s seems incorrect, please check it.\n\n%(field_name)s not stored", + name=definition.name, + field_name=definition.field_id.name + )) except KeyError as e: - raise exceptions.UserError( - _("The model configuration for the definition %s seems incorrect, please check it.\n\n%s not found") % (definition.name, e)) + raise exceptions.UserError(_( + "The model configuration for the definition %(name)s seems incorrect, please check it.\n\n%(error)s not found", + name=definition.name, + error=e + )) @api.model def create(self, vals): diff --git a/addons/google_calendar/models/calendar.py b/addons/google_calendar/models/calendar.py index 57d9f63a440..765473509ba 100644 --- a/addons/google_calendar/models/calendar.py +++ b/addons/google_calendar/models/calendar.py @@ -131,15 +131,27 @@ class Meeting(models.Model): if minutes % (60*24) == 0: interval = 'days' duration = minutes / 60 / 24 - name = _("%s - %s Days") % (alarm_type_label, duration) + name = _( + "%(reminder_type)s - %(duration)s Days", + reminder_type=alarm_type_label, + duration=duration, + ) elif minutes % 60 == 0: interval = 'hours' duration = minutes / 60 - name = _("%s - %s Hours") % (alarm_type_label, duration) + name = _( + "%(reminder_type)s - %(duration)s Hours", + reminder_type=alarm_type_label, + duration=duration, + ) else: interval = 'minutes' duration = minutes - name = _("%s - %s Minutes") % (alarm_type_label, duration) + name = _( + "%(reminder_type)s - %(duration)s Minutes", + reminder_type=alarm_type_label, + duration=duration, + ) commands += [(0, 0, {'duration': duration, 'interval': interval, 'name': name, 'alarm_type': alarm_type})] return commands diff --git a/addons/hr_expense/wizard/hr_expense_sheet_register_payment.py b/addons/hr_expense/wizard/hr_expense_sheet_register_payment.py index ff586f68491..37e1f0bf68d 100644 --- a/addons/hr_expense/wizard/hr_expense_sheet_register_payment.py +++ b/addons/hr_expense/wizard/hr_expense_sheet_register_payment.py @@ -113,7 +113,14 @@ class HrExpenseSheetRegisterPaymentWizard(models.TransientModel): payment.action_post() # Log the payment in the chatter - body = (_("A payment of %s %s with the reference <a href='/mail/view?%s'>%s</a> related to your expense %s has been made.") % (payment.amount, payment.currency_id.symbol, url_encode({'model': 'account.payment', 'res_id': payment.id}), payment.name, expense_sheet.name)) + body = _( + "A payment of %(amount)s %(currency)s with the reference <a href='/mail/view?%(url)s'>%(payment_name)s</a> related to your expense %(expense_name)s has been made.", + amount=payment.amount, + currency=payment.currency_id.symbol, + url=url_encode({'model': 'account.payment', 'res_id': payment.id}), + payment_name=payment.name, + expense_name=expense_sheet.name + ) expense_sheet.message_post(body=body) # Reconcile the payment and the expense, i.e. lookup on the payable account move lines diff --git a/addons/hr_fleet/controllers/main.py b/addons/hr_fleet/controllers/main.py index 175139e04da..80748991fda 100644 --- a/addons/hr_fleet/controllers/main.py +++ b/addons/hr_fleet/controllers/main.py @@ -52,7 +52,12 @@ class HrFleet(Controller): date_start = car_line_doc.date_start date_end = car_line_doc.date_end or '...' - text_to_print = _("%s (driven from: %s to %s)") % (car_name, date_start, date_end) + text_to_print = _( + "%(car_name)s (driven from: %(date_start)s to %(date_end)s)", + car_name=car_name, + date_start=date_start, + date_end=date_end + ) can.drawCentredString(width / 2, height - normal_font_size, text_to_print) can.save() header_pdf = PdfFileReader(header, overwriteWarnings=False) diff --git a/addons/hr_holidays/models/hr_leave.py b/addons/hr_holidays/models/hr_leave.py index 5e88edf967e..9da4c75eb71 100644 --- a/addons/hr_holidays/models/hr_leave.py +++ b/addons/hr_holidays/models/hr_leave.py @@ -621,11 +621,11 @@ class HolidaysRequest(models.Model): if leave.leave_type_request_unit == 'hour': res.append(( leave.id, - _("%s on %s: %.2f hours on %s") % ( - target, - leave.holiday_status_id.name, - leave.number_of_hours_display, - fields.Date.to_string(leave.date_from), + _("%(person)s on %(leave_type)s: %(duration).2f hours on %(date)s", + person=target, + leave_type=leave.holiday_status_id.name, + duration=leave.number_of_hours_display, + date=fields.Date.to_string(leave.date_from), ) )) else: @@ -634,11 +634,11 @@ class HolidaysRequest(models.Model): display_date += ' ⇨ %s' % fields.Date.to_string(leave.date_to) res.append(( leave.id, - _("%s on %s: %.2f days (%s)") % ( - target, - leave.holiday_status_id.name, - leave.number_of_days, - display_date, + _("%(person)s on %(leave_type)s: %(duration).2f days (%(start)s)", + person=target, + leave_type=leave.holiday_status_id.name, + duration=leave.number_of_days, + start=display_date, ) )) return res @@ -657,19 +657,26 @@ class HolidaysRequest(models.Model): dto = leave.date_to if leave.holiday_status_id.validity_start and leave.holiday_status_id.validity_stop: if dfrom and dto and (dfrom.date() < vstart or dto.date() > vstop): - raise ValidationError( - _('%s are only valid between %s and %s') % ( - leave.holiday_status_id.display_name, leave.holiday_status_id.validity_start, leave.holiday_status_id.validity_stop)) + raise ValidationError(_( + '%(leave_type)s are only valid between %(start)s and %(end)s', + leave_type=leave.holiday_status_id.display_name, + start=leave.holiday_status_id.validity_start, + end=leave.holiday_status_id.validity_stop + )) elif leave.holiday_status_id.validity_start: if dfrom and (dfrom.date() < vstart): - raise ValidationError( - _('%s are only valid starting from %s') % ( - leave.holiday_status_id.display_name, leave.holiday_status_id.validity_start)) + raise ValidationError(_( + '%(leave_type)s are only valid starting from %(date)s', + leave_type=leave.holiday_status_id.display_name, + date=leave.holiday_status_id.validity_start + )) elif leave.holiday_status_id.validity_stop: if dto and (dto.date() > vstop): - raise ValidationError( - _('%s are only valid until %s') % ( - leave.holiday_status_id.display_name, leave.holiday_status_id.validity_stop)) + raise ValidationError(_( + '%(leave_type)s are only valid until %(date)s', + leave_type=leave.holiday_status_id.display_name, + date=leave.holiday_status_id.validity_stop + )) def _check_double_validation_rules(self, employees, state): if self.user_has_groups('hr_holidays.group_hr_holidays_manager'): @@ -1032,7 +1039,7 @@ class HolidaysRequest(models.Model): for holiday in self: if holiday.employee_id.user_id: holiday.message_post( - body=_('Your %s planned on %s has been refused') % (holiday.holiday_status_id.display_name, holiday.date_from), + body=_('Your %(leave_type)s planned on %(date)s has been refused', leave_type=holiday.holiday_status_id.display_name, date=holiday.date_from), partner_ids=holiday.employee_id.user_id.partner_id.ids) self._remove_resource_leave() @@ -1101,7 +1108,13 @@ class HolidaysRequest(models.Model): for holiday in self: start = UTC.localize(holiday.date_from).astimezone(timezone(holiday.employee_id.tz or 'UTC')) end = UTC.localize(holiday.date_to).astimezone(timezone(holiday.employee_id.tz or 'UTC')) - note = _('New %s Request created by %s from %s to %s') % (holiday.holiday_status_id.name, holiday.create_uid.name, start, end) + note = _( + 'New %(leave_type)s Request created by %(user)s from %(start)s to %(end)s', + leave_type=holiday.holiday_status_id.name, + user=holiday.create_uid.name, + start=start, + end=end + ) if holiday.state == 'draft': to_clean |= holiday elif holiday.state == 'confirm': diff --git a/addons/hr_holidays/models/hr_leave_allocation.py b/addons/hr_holidays/models/hr_leave_allocation.py index 6fda4311739..5c39867ba50 100644 --- a/addons/hr_holidays/models/hr_leave_allocation.py +++ b/addons/hr_holidays/models/hr_leave_allocation.py @@ -389,11 +389,12 @@ class HolidaysAllocation(models.Model): res.append( (allocation.id, - _("Allocation of %s : %.2f %s to %s") % - (allocation.holiday_status_id.sudo().name, - allocation.number_of_hours_display if allocation.type_request_unit == 'hour' else allocation.number_of_days, - 'hours' if allocation.type_request_unit == 'hour' else 'days', - target)) + _("Allocation of %(allocation_name)s : %(duration).2f %(duration_type)s to %(person)s", + allocation_name=allocation.holiday_status_id.sudo().name, + duration=allocation.number_of_hours_display if allocation.type_request_unit == 'hour' else allocation.number_of_days, + duration_type='hours' if allocation.type_request_unit == 'hour' else 'days', + person=target + )) ) return res @@ -410,7 +411,11 @@ class HolidaysAllocation(models.Model): today = fields.Date.today() if vstop < today: - raise ValidationError(_('You can allocate %s only before %s.') % (allocation.holiday_status_id.display_name, allocation.holiday_status_id.validity_stop)) + raise ValidationError(_( + 'You can allocate %(allocation_type)s only before %(date)s.', + allocation_type=allocation.holiday_status_id.display_name, + date=allocation.holiday_status_id.validity_stop + )) @api.model def create(self, values): @@ -613,7 +618,12 @@ class HolidaysAllocation(models.Model): def activity_update(self): to_clean, to_do = self.env['hr.leave.allocation'], self.env['hr.leave.allocation'] for allocation in self: - note = _('New Allocation Request created by %s: %s Days of %s') % (allocation.create_uid.name, allocation.number_of_days, allocation.holiday_status_id.name) + note = _( + 'New Allocation Request created by %(user)s: %(count)s Days of %(allocation_type)s', + user=allocation.create_uid.name, + count=allocation.number_of_days, + allocation_type=allocation.holiday_status_id.name + ) if allocation.state == 'draft': to_clean |= allocation elif allocation.state == 'confirm': diff --git a/addons/hr_skills/models/hr_skills.py b/addons/hr_skills/models/hr_skills.py index e562dd58449..759607a8e72 100644 --- a/addons/hr_skills/models/hr_skills.py +++ b/addons/hr_skills/models/hr_skills.py @@ -33,13 +33,13 @@ class EmployeeSkill(models.Model): def _check_skill_type(self): for record in self: if record.skill_id not in record.skill_type_id.skill_ids: - raise ValidationError(_("The skill %s and skill type %s doesn't match") % (record.skill_id.name, record.skill_type_id.name)) + raise ValidationError(_("The skill %(name)s and skill type %(type)s doesn't match", name=record.skill_id.name, type=record.skill_type_id.name)) @api.constrains('skill_type_id', 'skill_level_id') def _check_skill_level(self): for record in self: if record.skill_level_id not in record.skill_type_id.skill_level_ids: - raise ValidationError(_("The skill level %s is not valid for skill type: %s ") % (record.skill_level_id.name, record.skill_type_id.name)) + raise ValidationError(_("The skill level %(level)s is not valid for skill type: %(type)s", level=record.skill_level_id.name, type=record.skill_type_id.name)) class SkillLevel(models.Model): diff --git a/addons/hr_timesheet/models/project.py b/addons/hr_timesheet/models/project.py index ed0ac3a5bad..c9d294a1a61 100644 --- a/addons/hr_timesheet/models/project.py +++ b/addons/hr_timesheet/models/project.py @@ -186,7 +186,12 @@ class Task(models.Model): for task in self: if task.allow_timesheets and task.planned_hours > 0: hours, mins = (str(int(duration)).rjust(2, '0') for duration in divmod(abs(task.remaining_hours) * 60, 60)) - hours_left = _("(%s%s:%s remaining)") % ('-' if task.remaining_hours < 0 else '', hours, mins) + hours_left = _( + "(%(sign)s%(hours)s:%(minutes)s remaining)", + sign='-' if task.remaining_hours < 0 else '', + hours=hours, + minutes=mins, + ) name_mapping[task.id] = name_mapping.get(task.id, '') + " ‒ " + hours_left return list(name_mapping.items()) return super().name_get() diff --git a/addons/mail/models/mail_activity.py b/addons/mail/models/mail_activity.py index dd92b4a17b3..81e04898477 100644 --- a/addons/mail/models/mail_activity.py +++ b/addons/mail/models/mail_activity.py @@ -433,7 +433,9 @@ class MailActivity(models.Model): record.message_notify( partner_ids=activity.user_id.partner_id.ids, body=body, - subject=_('%s: %s assigned to you') % (activity.res_name, activity.summary or activity.activity_type_id.name), + subject=_('%(activity_name)s: %(summary)s assigned to you', + activity_name=activity.res_name, + summary=activity.summary or activity.activity_type_id.name), record_name=activity.res_name, model_description=model_description, email_layout_xmlid='mail.mail_notification_light', diff --git a/addons/mail/models/mail_channel.py b/addons/mail/models/mail_channel.py index e2ea498ef0e..23f63f4dad3 100644 --- a/addons/mail/models/mail_channel.py +++ b/addons/mail/models/mail_channel.py @@ -1016,6 +1016,6 @@ class Channel(models.Model): msg = _("You are alone in this channel.") else: dots = "..." if len(members) != len(self.channel_partner_ids) - 1 else "" - msg = _("Users in this channel: %s %s and you.") % (", ".join(members), dots) + msg = _("Users in this channel: %(members)s %(dots)s and you.", members=", ".join(members), dots=dots) self._send_transient_message(partner, msg) diff --git a/addons/mail/models/mail_thread.py b/addons/mail/models/mail_thread.py index 3f8818bc386..dcadca5b281 100644 --- a/addons/mail/models/mail_thread.py +++ b/addons/mail/models/mail_thread.py @@ -798,7 +798,12 @@ class MailThread(models.AbstractModel): # Existing Document: check if exists and model accepts the mailgateway; if not, fallback on create if allowed if thread_id: if not record_set.exists(): - self._routing_warn(_('reply to missing document (%s,%s), fall back on document creation') % (model, thread_id), message_id, route, False) + self._routing_warn( + _('reply to missing document (%(model)s,%(thread)s), fall back on document creation', model=model, thread=thread_id), + message_id, + route, + False + ) thread_id = None elif not hasattr(record_set, 'message_update'): self._routing_warn(_('reply to model %s that does not accept document update, fall back on document creation', model), message_id, route, False) @@ -834,7 +839,12 @@ class MailThread(models.AbstractModel): else: error_code = self.env['mail.alias.mixin']._alias_check_contact_on_record(obj, message, message_dict, alias) if error_code is not True: - self._routing_warn(_('alias %s: %s') % (alias.alias_name, error_code or _('unknown error')), message_id, route, False) + self._routing_warn( + _('alias %(name)s: %(error)s', name=alias.alias_name, error=error_code or _('unknown error')), + message_id, + route, + False + ) body = alias._get_alias_bounced_body(message_dict) self._routing_create_bounce_email(email_from, body, message, references=message_id) return False diff --git a/addons/mail/wizard/invite.py b/addons/mail/wizard/invite.py index bbe67a37cdc..3d96ebe25b6 100644 --- a/addons/mail/wizard/invite.py +++ b/addons/mail/wizard/invite.py @@ -64,7 +64,7 @@ class Invite(models.TransientModel): # send an email if option checked and if a message exists (do not send void emails) if wizard.send_mail and wizard.message and not wizard.message == '<br>': # when deleting the message, cleditor keeps a <br> message = self.env['mail.message'].create({ - 'subject': _('Invitation to follow %s: %s') % (model_name, document.display_name), + 'subject': _('Invitation to follow %(document_model)s: %(document_name)s', document_model=model_name, document_name=document.display_name), 'body': wizard.message, 'record_name': document.display_name, 'email_from': email_from, diff --git a/addons/mrp/models/mrp_bom.py b/addons/mrp/models/mrp_bom.py index 43bce93cf71..7a154b16d0f 100644 --- a/addons/mrp/models/mrp_bom.py +++ b/addons/mrp/models/mrp_bom.py @@ -96,10 +96,12 @@ class MrpBom(models.Model): % (bom.product_id.display_name, ", ".join([ptav.display_name for ptav in bom_line.bom_product_template_attribute_value_ids]))) for ptav in bom_line.bom_product_template_attribute_value_ids: if ptav.product_tmpl_id != bom.product_tmpl_id: - raise ValidationError( - _("The attribute value %s set on product %s does not match the BoM product %s.") % - (ptav.display_name, ptav.product_tmpl_id.display_name, bom_line.parent_product_tmpl_id.display_name) - ) + raise ValidationError(_( + "The attribute value %(attribute)s set on product %(product)s does not match the BoM product %(bom_product)s.", + attribute=ptav.display_name, + product=ptav.product_tmpl_id.display_name, + bom_product=bom_line.parent_product_tmpl_id.display_name + )) @api.onchange('product_uom_id') def onchange_product_uom_id(self): diff --git a/addons/mrp/models/mrp_production.py b/addons/mrp/models/mrp_production.py index 229d93f5b5d..491c775f6c3 100644 --- a/addons/mrp/models/mrp_production.py +++ b/addons/mrp/models/mrp_production.py @@ -1596,7 +1596,9 @@ class MrpProduction(models.Model): ('qty_done', '=', 1), ('state', '=', 'done') ] - message = _('The serial number %s used for byproduct %s has already been produced') % (move_line.lot_id.name, move_line.product_id.name) + message = _('The serial number %(number)s used for byproduct %(product_name)s has already been produced', + number=move_line.lot_id.name, + product_name=move_line.product_id.name) co_prod_move_lines = self.move_finished_ids.move_line_ids.filtered(lambda ml: ml.product_id != self.product_id) domain_unbuild = domain + [ ('production_id', '=', False), @@ -1628,7 +1630,9 @@ class MrpProduction(models.Model): ('qty_done', '=', 1), ('state', '=', 'done') ] - message = _('The serial number %s used for component %s has already been consumed') % (move_line.lot_id.name, move_line.product_id.name) + message = _('The serial number %(number)s used for component %(component)s has already been consumed', + number=move_line.lot_id.name, + component=move_line.product_id.name) co_prod_move_lines = self.move_raw_ids.move_line_ids domain_unbuild = domain + [ ('production_id', '=', False), diff --git a/addons/mrp/models/mrp_workorder.py b/addons/mrp/models/mrp_workorder.py index ad8711bd420..d9e89060c5c 100644 --- a/addons/mrp/models/mrp_workorder.py +++ b/addons/mrp/models/mrp_workorder.py @@ -175,9 +175,9 @@ class MrpWorkorder(models.Model): if wo.state == 'pending' and prev_start and not (prev_start > wo.date_planned_start): infos.append({ 'color': 'text-primary', - 'msg': _("Waiting the previous work order, planned from %s to %s") % ( - format_datetime(self.env, prev_start, dt_format=False), - format_datetime(self.env, prev_finished, dt_format=False)) + 'msg': _("Waiting the previous work order, planned from %(start)s to %(end)s", + start=format_datetime(self.env, prev_start, dt_format=False), + end=format_datetime(self.env, prev_finished, dt_format=False)) }) if wo.date_planned_finished < fields.Datetime.now(): infos.append({ @@ -187,14 +187,14 @@ class MrpWorkorder(models.Model): if prev_start and prev_start > wo.date_planned_start: infos.append({ 'color': 'text-danger', - 'msg': _("Scheduled before the previous work order, planned from %s to %s") % ( - format_datetime(self.env, prev_start, dt_format=False), - format_datetime(self.env, prev_finished, dt_format=False)) + 'msg': _("Scheduled before the previous work order, planned from %(start)s to %(end)s", + start=format_datetime(self.env, prev_start, dt_format=False), + end=format_datetime(self.env, prev_finished, dt_format=False)) }) if conflicted_dict.get(wo.id): infos.append({ 'color': 'text-danger', - 'msg': _("Planned at the same time than other workorder(s) at %s" % wo.workcenter_id.display_name) + 'msg': _("Planned at the same time than other workorder(s) at %s", wo.workcenter_id.display_name) }) color_icon = infos and infos[-1]['color'] or False wo.show_json_popover = bool(color_icon) diff --git a/addons/mrp/wizard/change_production_qty.py b/addons/mrp/wizard/change_production_qty.py index 29657577a4f..cd82ca389f6 100644 --- a/addons/mrp/wizard/change_production_qty.py +++ b/addons/mrp/wizard/change_production_qty.py @@ -48,7 +48,11 @@ class ChangeProductionQty(models.TransientModel): produced = sum(production.move_finished_ids.filtered(lambda m: m.product_id == production.product_id).mapped('quantity_done')) if wizard.product_qty < produced: format_qty = '%.{precision}f'.format(precision=precision) - raise UserError(_("You have already processed %s. Please input a quantity higher than %s ") % (format_qty % produced, format_qty % produced)) + raise UserError(_( + "You have already processed %(quantity)s. Please input a quantity higher than %(minimum)s ", + quantity=format_qty % produced, + minimum=format_qty % produced + )) old_production_qty = production.product_qty new_production_qty = wizard.product_qty done_moves = production.move_finished_ids.filtered(lambda x: x.state == 'done' and x.product_id == production.product_id) diff --git a/addons/payment_stripe/models/payment.py b/addons/payment_stripe/models/payment.py index a1a7da752bc..936e8d1c601 100644 --- a/addons/payment_stripe/models/payment.py +++ b/addons/payment_stripe/models/payment.py @@ -253,7 +253,7 @@ class PaymentTransactionStripe(models.Model): _logger.error(error_msg) raise ValidationError(error_msg) elif len(tx) > 1: - error_msg = (_('Stripe: %s orders found for reference %s') % (len(tx), reference)) + error_msg = _('Stripe: %(count)s orders found for reference %(reference)s', count=len(tx), reference=reference) _logger.error(error_msg) raise ValidationError(error_msg) return tx[0] diff --git a/addons/phone_validation/tools/phone_validation.py b/addons/phone_validation/tools/phone_validation.py index 87fe5498188..ac96c82a87a 100644 --- a/addons/phone_validation/tools/phone_validation.py +++ b/addons/phone_validation/tools/phone_validation.py @@ -17,7 +17,7 @@ try: try: phone_nbr = phonenumbers.parse(number, region=country_code, keep_raw_input=True) except phonenumbers.phonenumberutil.NumberParseException as e: - raise UserError(_('Unable to parse %s.: %s') % (number, str(e))) + raise UserError(_('Unable to parse %(phone)s: %(error)s', phone=number, error=str(e))) if not phonenumbers.is_possible_number(phone_nbr): raise UserError(_('Impossible number %s: probably invalid number of digits.', number)) diff --git a/addons/point_of_sale/models/pos_payment.py b/addons/point_of_sale/models/pos_payment.py index a87762f501a..8dea1f62b92 100644 --- a/addons/point_of_sale/models/pos_payment.py +++ b/addons/point_of_sale/models/pos_payment.py @@ -33,7 +33,7 @@ class PosPayment(models.Model): res = [] for payment in self: if payment.name: - res.append((payment.id, _('%s %s') % (payment.name, formatLang(self.env, payment.amount, currency_obj=payment.currency_id)))) + res.append((payment.id, '%s %s' % (payment.name, formatLang(self.env, payment.amount, currency_obj=payment.currency_id)))) else: res.append((payment.id, formatLang(self.env, payment.amount, currency_obj=payment.currency_id))) return res diff --git a/addons/portal/models/mail_thread.py b/addons/portal/models/mail_thread.py index 424e3de0c25..0e9b58b9fca 100644 --- a/addons/portal/models/mail_thread.py +++ b/addons/portal/models/mail_thread.py @@ -28,7 +28,11 @@ class MailThread(models.AbstractModel): self.ensure_one() # check token field exists if self._mail_post_token_field not in self._fields: - raise NotImplementedError(_("Model %s does not support token signature, as it does not have %s field.") % (self._name, self._mail_post_token_field)) + raise NotImplementedError(_( + "Model %(model_name)s does not support token signature, as it does not have %(field_name)s field.", + model_name=self._name, + field_name=self._mail_post_token_field + )) # sign token secret = self.env["ir.config_parameter"].sudo().get_param("database.secret") token = (self.env.cr.dbname, self[self._mail_post_token_field], pid) diff --git a/addons/product/models/product_pricelist.py b/addons/product/models/product_pricelist.py index 1b2b0640284..d1ef0ec714c 100644 --- a/addons/product/models/product_pricelist.py +++ b/addons/product/models/product_pricelist.py @@ -521,7 +521,7 @@ class PricelistItem(models.Model): elif item.compute_price == 'percentage': item.price = _("%s %% discount", item.percent_price) else: - item.price = _("%s %% discount and %s surcharge") % (item.price_discount, item.price_surcharge) + item.price = _("%(percentage)s %% discount and %(price)s surcharge", percentage=item.price_discount, price=item.price_surcharge) @api.onchange('compute_price') def _onchange_compute_price(self): diff --git a/addons/purchase/models/purchase.py b/addons/purchase/models/purchase.py index 7afe483ceaa..b0d8316f342 100644 --- a/addons/purchase/models/purchase.py +++ b/addons/purchase/models/purchase.py @@ -138,7 +138,12 @@ class PurchaseOrder(models.Model): companies = order.order_line.product_id.company_id if companies and companies != order.company_id: bad_products = order.order_line.product_id.filtered(lambda p: p.company_id and p.company_id != order.company_id) - raise ValidationError((_("Your quotation contains products from company %s whereas your quotation belongs to company %s. \n Please change the company of your quotation or remove the products from other companies (%s).") % (', '.join(companies.mapped('display_name')), order.company_id.display_name, ', '.join(bad_products.mapped('display_name'))))) + raise ValidationError(_( + "Your quotation contains products from company %(product_company)s whereas your quotation belongs to company %(quote_company)s. \n Please change the company of your quotation or remove the products from other companies (%(bad_products)s).", + product_company=', '.join(companies.mapped('display_name')), + quote_company=order.company_id.display_name, + bad_products=', '.join(bad_products.mapped('display_name')), + )) def _compute_access_url(self): super(PurchaseOrder, self)._compute_access_url() @@ -723,7 +728,12 @@ class PurchaseOrder(models.Model): on portal website.""" note = _('<p> %s modified receipt dates for the following products:</p>', self.partner_id.name) for line, date in updated_dates: - note += _('<p> - %s from %s to %s </p>') % (line.product_id.display_name, line.date_planned, date) + note += _( + '<p> - %(product_name)s from %(date_start)s to %(date_end)s </p>', + product_name=line.product_id.display_name, + date_start=line.date_planned, + date_end=date + ) return note diff --git a/addons/sale/models/sale.py b/addons/sale/models/sale.py index aba5569b04c..b52e0a640e2 100644 --- a/addons/sale/models/sale.py +++ b/addons/sale/models/sale.py @@ -263,7 +263,12 @@ class SaleOrder(models.Model): companies = order.order_line.product_id.company_id if companies and companies != order.company_id: bad_products = order.order_line.product_id.filtered(lambda p: p.company_id and p.company_id != order.company_id) - raise ValidationError((_("Your quotation contains products from company %s whereas your quotation belongs to company %s. \n Please change the company of your quotation or remove the products from other companies (%s).") % (', '.join(companies.mapped('display_name')), order.company_id.display_name, ', '.join(bad_products.mapped('display_name'))))) + raise ValidationError(_( + "Your quotation contains products from company %(product_company)s whereas your quotation belongs to company %(quote_company)s. \n Please change the company of your quotation or remove the products from other companies (%(bad_products)s).", + product_company=', '.join(companies.mapped('display_name')), + quote_company=order.company_id.display_name, + bad_products=', '.join(bad_products.mapped('display_name')), + )) @api.depends('pricelist_id', 'date_order', 'company_id') def _compute_currency_rate(self): diff --git a/addons/sale_coupon/models/coupon.py b/addons/sale_coupon/models/coupon.py index 6fbd5ce451f..bc92f4366a2 100644 --- a/addons/sale_coupon/models/coupon.py +++ b/addons/sale_coupon/models/coupon.py @@ -25,7 +25,11 @@ class Coupon(models.Model): message = {'error': _('This coupon is expired (%s).') % (self.code)} # Minimum requirement should not be checked if the coupon got generated by a promotion program (the requirement should have only be checked to generate the coupon) elif self.program_id.program_type == 'coupon_program' and not self.program_id._filter_on_mimimum_amount(order): - message = {'error': _('A minimum of %s %s should be purchased to get the reward') % (self.program_id.rule_minimum_amount, self.program_id.currency_id.name)} + message = {'error': _( + 'A minimum of %(amount)s %(currency)s should be purchased to get the reward', + amount=self.program_id.rule_minimum_amount, + currency=self.program_id.currency_id.name + )} elif not self.program_id.active: message = {'error': _('The coupon program for %s is in draft or closed state') % (self.code)} elif self.partner_id and self.partner_id != order.partner_id: diff --git a/addons/sale_coupon/models/coupon_program.py b/addons/sale_coupon/models/coupon_program.py index 5bc83d493e0..35fa15cb72e 100644 --- a/addons/sale_coupon/models/coupon_program.py +++ b/addons/sale_coupon/models/coupon_program.py @@ -34,7 +34,11 @@ class CouponProgram(models.Model): if self.maximum_use_number != 0 and self.order_count >= self.maximum_use_number: message = {'error': _('Promo code %s has been expired.') % (coupon_code)} elif not self._filter_on_mimimum_amount(order): - message = {'error': _('A minimum of %s %s should be purchased to get the reward') % (self.rule_minimum_amount, self.currency_id.name)} + message = {'error': _( + 'A minimum of %(amount)s %(currency)s should be purchased to get the reward', + amount=self.rule_minimum_amount, + currency=self.currency_id.name + )} elif self.promo_code and self.promo_code == order.promo_code: message = {'error': _('The promo code is already applied on this order')} elif not self.promo_code and self in order.no_code_promo_program_ids: diff --git a/addons/sale_management/models/sale_order.py b/addons/sale_management/models/sale_order.py index 04a9e87128a..f2ea0512f8b 100644 --- a/addons/sale_management/models/sale_order.py +++ b/addons/sale_management/models/sale_order.py @@ -35,7 +35,12 @@ class SaleOrder(models.Model): companies = order.sale_order_option_ids.product_id.company_id if companies and companies != order.company_id: bad_products = order.sale_order_option_ids.product_id.filtered(lambda p: p.company_id and p.company_id != order.company_id) - raise ValidationError((_("Your quotation contains products from company %s whereas your quotation belongs to company %s. \n Please change the company of your quotation or remove the products from other companies (%s).") % (', '.join(companies.mapped('display_name')), order.company_id.display_name, ', '.join(bad_products.mapped('display_name'))))) + raise ValidationError(_( + "Your quotation contains products from company %(product_company)s whereas your quotation belongs to company %(quote_company)s. \n Please change the company of your quotation or remove the products from other companies (%(bad_products)s).", + product_company=', '.join(companies.mapped('display_name')), + quote_company=order.company_id.display_name, + bad_products=', '.join(bad_products.mapped('display_name')), + )) @api.returns('self', lambda value: value.id) def copy(self, default=None): diff --git a/addons/sale_management/models/sale_order_template.py b/addons/sale_management/models/sale_order_template.py index 5eaed0176f0..0552938bde3 100644 --- a/addons/sale_management/models/sale_order_template.py +++ b/addons/sale_management/models/sale_order_template.py @@ -37,7 +37,11 @@ class SaleOrderTemplate(models.Model): if len(companies) > 1: raise ValidationError(_("Your template cannot contain products from multiple companies.")) elif companies and companies != template.company_id: - raise ValidationError((_("Your template contains products from company %s whereas your template belongs to company %s. \n Please change the company of your template or remove the products from other companies.") % (companies.mapped('display_name'), template.company_id.display_name))) + raise ValidationError(_( + "Your template contains products from company %(product_company)s whereas your template belongs to company %(template_company)s. \n Please change the company of your template or remove the products from other companies.", + product_company=', '.join(companies.mapped('display_name')), + template_company=template.company_id.display_name, + )) @api.onchange('sale_order_template_line_ids', 'sale_order_template_option_ids') def _onchange_template_line_ids(self): diff --git a/addons/sale_stock/models/sale_order.py b/addons/sale_stock/models/sale_order.py index 41e4e6d5bb4..fde99c982c2 100644 --- a/addons/sale_stock/models/sale_order.py +++ b/addons/sale_stock/models/sale_order.py @@ -584,7 +584,13 @@ class SaleOrderLine(models.Model): return { 'warning': { 'title': _('Warning'), - 'message': _("This product is packaged by %.2f %s. You should sell %.2f %s.") % (pack.qty, default_uom.name, newqty, self.product_uom.name), + 'message': _( + "This product is packaged by %(pack_size).2f %(pack_name)s. You should sell %(quantity).2f %(unit)s.", + pack_size=pack.qty, + pack_name=default_uom.name, + quantity=newqty, + unit=self.product_uom.name + ), }, } return {} diff --git a/addons/stock/models/stock_warehouse.py b/addons/stock/models/stock_warehouse.py index ead232b7cdd..0ca8576dae4 100644 --- a/addons/stock/models/stock_warehouse.py +++ b/addons/stock/models/stock_warehouse.py @@ -686,7 +686,7 @@ class Warehouse(models.Model): def _get_inter_warehouse_route_values(self, supplier_warehouse): return { - 'name': _('%s: Supply Product from %s') % (self.name, supplier_warehouse.name), + 'name': _('%(warehouse)s: Supply Product from %(supplier)s', warehouse=self.name, supplier=supplier_warehouse.name), 'warehouse_selectable': True, 'product_selectable': True, 'product_categ_selectable': True, diff --git a/addons/stock_account/models/product.py b/addons/stock_account/models/product.py index a87cdcd7510..fa954ec8f50 100644 --- a/addons/stock_account/models/product.py +++ b/addons/stock_account/models/product.py @@ -253,13 +253,25 @@ class ProductProduct(models.Model): 'stock_valuation_layer_ids': [(6, None, [stock_valuation_layer.id])], 'move_type': 'entry', 'line_ids': [(0, 0, { - 'name': _('%s changed cost from %s to %s - %s') % (self.env.user.name, product.standard_price, new_price, product.display_name), + 'name': _( + '%(user)s changed cost from %(previous)s to %(new_price)s - %(product)s', + user=self.env.user.name, + previous=product.standard_price, + new_price=new_price, + product=product.display_name + ), 'account_id': debit_account_id, 'debit': abs(value), 'credit': 0, 'product_id': product.id, }), (0, 0, { - 'name': _('%s changed cost from %s to %s - %s') % (self.env.user.name, product.standard_price, new_price, product.display_name), + 'name': _( + '%(user)s changed cost from %(previous)s to %(new_price)s - %(product)s', + user=self.env.user.name, + previous=product.standard_price, + new_price=new_price, + product=product.display_name + ), 'account_id': credit_account_id, 'debit': 0, 'credit': abs(value), diff --git a/addons/stock_account/wizard/stock_valuation_layer_revaluation.py b/addons/stock_account/wizard/stock_valuation_layer_revaluation.py index 50309cf1fd9..35989e80b67 100644 --- a/addons/stock_account/wizard/stock_valuation_layer_revaluation.py +++ b/addons/stock_account/wizard/stock_valuation_layer_revaluation.py @@ -131,15 +131,23 @@ class StockValuationLayerRevaluation(models.TransientModel): 'date': self.date or fields.Date.today(), 'move_type': 'entry', 'line_ids': [(0, 0, { - 'name': _('%s changed stock valuation from %s to %s of %s') % ( - self.env.user.name, self.current_value_svl, self.current_value_svl + self.added_value, product_id.display_name), + 'name': _('%(user)s changed stock valuation from %(previous)s to %(new_value)s - %(product)s', + user=self.env.user.name, + previous=self.current_value_svl, + new_value=self.current_value_svl + self.added_value, + product=product_id.display_name, + ), 'account_id': debit_account_id, 'debit': abs(self.added_value), 'credit': 0, 'product_id': product_id.id, }), (0, 0, { - 'name': _('%s changed stock valuation from %s to %s of %s') % ( - self.env.user.name, self.current_value_svl, self.current_value_svl + self.added_value, product_id.display_name), + 'name': _('%(user)s changed stock valuation from %(previous)s to %(new_value)s - %(product)s', + user=self.env.user.name, + previous=self.current_value_svl, + new_value=self.current_value_svl + self.added_value, + product=product_id.display_name, + ), 'account_id': credit_account_id, 'debit': 0, 'credit': abs(self.added_value), diff --git a/addons/website_sale_stock/controllers/main.py b/addons/website_sale_stock/controllers/main.py index 43f70fa4e9f..da26a11173c 100644 --- a/addons/website_sale_stock/controllers/main.py +++ b/addons/website_sale_stock/controllers/main.py @@ -20,7 +20,11 @@ class WebsiteSaleStock(WebsiteSale): cart_qty = sum(order.order_line.filtered(lambda p: p.product_id.id == line.product_id.id).mapped('product_uom_qty')) avl_qty = line.product_id.with_context(warehouse=order.warehouse_id.id).virtual_available if cart_qty > avl_qty: - values.append(_('You ask for %s products but only %s is available') % (cart_qty, avl_qty if avl_qty > 0 else 0)) + values.append(_( + 'You ask for %(quantity)s products but only %(available_qty)s is available', + quantity=cart_qty, + available_qty=avl_qty if avl_qty > 0 else 0 + )) if values: raise ValidationError('. '.join(values) + '.') return super(WebsiteSaleStock, self).payment_transaction(**kwargs) |
