Mark job_explanation strings after they are read from the db

- For strings that need to be translated, but are saved in the db:
   * They must be marked for translation using gettext_noop() to be
   translated.
   * And must also be marked for translation with _() when read from db
   and shown to the user.
   * [Ref]: https://docs.djangoproject.com/en/3.0/topics/i18n/translation/#marking-strings-as-no-op
This commit is contained in:
Christian Adams 2020-05-15 15:13:49 -04:00
parent 99701e4112
commit 19ccb5e213
4 changed files with 17 additions and 11 deletions

View File

@ -806,7 +806,9 @@ class UnifiedJobSerializer(BaseSerializer):
td = now() - obj.started
ret['elapsed'] = (td.microseconds + (td.seconds + td.days * 24 * 3600) * 10 ** 6) / (10 ** 6 * 1.0)
ret['elapsed'] = float(ret['elapsed'])
# Because this string is saved in the db in the source language,
# it must be marked for translation after it is pulled from the db, not when set
ret['job_explanation'] = _(obj.job_explanation)
return ret

View File

@ -10,7 +10,7 @@ import random
# Django
from django.db import transaction, connection
from django.utils.translation import ugettext_lazy as _
from django.utils.translation import ugettext_lazy as _, gettext_noop
from django.utils.timezone import now as tz_now
# AWX
@ -114,7 +114,7 @@ class TaskManager():
logger.info('Refusing to start recursive workflow-in-workflow id={}, wfjt={}, ancestors={}'.format(
job.id, spawn_node.unified_job_template.pk, [wa.pk for wa in workflow_ancestors]))
display_list = [spawn_node.unified_job_template] + workflow_ancestors
job.job_explanation = _(
job.job_explanation = gettext_noop(
"Workflow Job spawned from workflow could not start because it "
"would result in recursion (spawn order, most recent first: {})"
).format(', '.join(['<{}>'.format(tmp) for tmp in display_list]))
@ -123,8 +123,8 @@ class TaskManager():
job.id, spawn_node.unified_job_template.pk, [wa.pk for wa in workflow_ancestors]))
if not job._resources_sufficient_for_launch():
can_start = False
job.job_explanation = _("Job spawned from workflow could not start because it "
"was missing a related resource such as project or inventory")
job.job_explanation = gettext_noop("Job spawned from workflow could not start because it "
"was missing a related resource such as project or inventory")
if can_start:
if workflow_job.start_args:
start_args = json.loads(decrypt_field(workflow_job, 'start_args'))
@ -132,8 +132,8 @@ class TaskManager():
start_args = {}
can_start = job.signal_start(**start_args)
if not can_start:
job.job_explanation = _("Job spawned from workflow could not start because it "
"was not in the right state or required manual credentials")
job.job_explanation = gettext_noop("Job spawned from workflow could not start because it "
"was not in the right state or required manual credentials")
if not can_start:
job.status = 'failed'
job.save(update_fields=['status', 'job_explanation'])
@ -173,7 +173,7 @@ class TaskManager():
workflow_job.status = new_status
if reason:
logger.info(reason)
workflow_job.job_explanation = _("No error handling paths found, marking workflow as failed")
workflow_job.job_explanation = gettext_noop("No error handling paths found, marking workflow as failed")
update_fields.append('job_explanation')
workflow_job.start_args = '' # blank field to remove encrypted passwords
workflow_job.save(update_fields=update_fields)

View File

@ -31,7 +31,7 @@ from django.db.models.fields.related import ForeignKey
from django.utils.timezone import now, timedelta
from django.utils.encoding import smart_str
from django.contrib.auth.models import User
from django.utils.translation import ugettext_lazy as _
from django.utils.translation import ugettext_lazy as _, gettext_noop
from django.core.cache import cache
from django.core.exceptions import ObjectDoesNotExist
@ -558,7 +558,8 @@ def awx_periodic_scheduler():
continue
if not can_start:
new_unified_job.status = 'failed'
new_unified_job.job_explanation = "Scheduled job could not start because it was not in the right state or required manual credentials"
new_unified_job.job_explanation = gettext_noop("Scheduled job could not start because it \
was not in the right state or required manual credentials")
new_unified_job.save(update_fields=['status', 'job_explanation'])
new_unified_job.websocket_emit_status("failed")
emit_channel_notification('schedules-changed', dict(id=schedule.id, group_name="schedules"))

View File

@ -105,7 +105,10 @@ class TestJobNotificationMixin(object):
assert isinstance(obj[key], dict)
check_structure(expected_structure[key], obj[key])
else:
assert isinstance(obj[key], expected_structure[key])
if key == 'job_explanation':
assert isinstance(str(obj[key]), expected_structure[key])
else:
assert isinstance(obj[key], expected_structure[key])
kwargs = {}
if JobClass is InventoryUpdate:
kwargs['inventory_source'] = inventory_source