general: add and use a lazy gettext function (#51289)
This commit is contained in:
parent
1565f3abe2
commit
0da7edeab8
|
@ -183,3 +183,7 @@ def test_jquery_debug_mode():
|
|||
pub.write_cfg()
|
||||
resp = get_app(pub).get('/category1/test-formdef-1/')
|
||||
assert 'jquery.js' in resp.text
|
||||
|
||||
|
||||
def test_i18n_js():
|
||||
get_app(pub).get('/i18n.js')
|
||||
|
|
|
@ -22,7 +22,7 @@ from wcs.admin import utils
|
|||
from wcs.admin.fields import FieldDefPage, FieldsDirectory
|
||||
from wcs.backoffice.snapshots import SnapshotsDirectory
|
||||
from wcs.blocks import BlockDef, BlockdefImportError
|
||||
from wcs.qommon import N_, _, misc, template
|
||||
from wcs.qommon import _, misc, template
|
||||
from wcs.qommon.backoffice.menu import html_top
|
||||
from wcs.qommon.form import FileWidget, Form, HtmlWidget, StringWidget
|
||||
|
||||
|
@ -48,7 +48,7 @@ class BlockDirectory(FieldsDirectory):
|
|||
field_def_page_class = BlockFieldDefPage
|
||||
blacklisted_types = ['page', 'table', 'table-select', 'tablerows', 'ranked-items', 'blocks', 'computed']
|
||||
support_import = False
|
||||
readonly_message = N_('This block of fields is readonly.')
|
||||
readonly_message = _('This block of fields is readonly.')
|
||||
|
||||
def __init__(self, section, *args, **kwargs):
|
||||
self.section = section
|
||||
|
|
|
@ -21,7 +21,7 @@ from quixote.html import TemplateIO, htmltext
|
|||
from wcs.carddef import CardDef
|
||||
from wcs.categories import CardDefCategory, Category
|
||||
from wcs.formdef import FormDef
|
||||
from wcs.qommon import N_, _
|
||||
from wcs.qommon import _
|
||||
from wcs.qommon.backoffice.menu import html_top
|
||||
from wcs.qommon.form import Form, HtmlWidget, StringWidget, WysiwygTextWidget
|
||||
|
||||
|
@ -83,8 +83,8 @@ class CategoryPage(Directory):
|
|||
category_class = Category
|
||||
category_ui_class = CategoryUI
|
||||
formdef_class = FormDef
|
||||
usage_title = N_('Forms in this category')
|
||||
empty_message = N_('no form associated to this category')
|
||||
usage_title = _('Forms in this category')
|
||||
empty_message = _('no form associated to this category')
|
||||
_q_exports = ['', 'edit', 'delete', 'description']
|
||||
|
||||
def __init__(self, component):
|
||||
|
@ -112,14 +112,14 @@ class CategoryPage(Directory):
|
|||
formdefs = self.formdef_class.select(order_by='name')
|
||||
formdefs = [x for x in formdefs if x.category_id == self.category.id]
|
||||
r += htmltext('<div class="bo-block">')
|
||||
r += htmltext('<h3>%s</h3>') % _(self.usage_title)
|
||||
r += htmltext('<h3>%s</h3>') % self.usage_title
|
||||
r += htmltext('<ul>')
|
||||
for formdef in formdefs:
|
||||
r += htmltext('<li><a href="../../%s/">') % str(formdef.id)
|
||||
r += formdef.name
|
||||
r += htmltext('</a></li>')
|
||||
if not formdefs:
|
||||
r += htmltext('<li>%s</li>') % _(self.empty_message)
|
||||
r += htmltext('<li>%s</li>') % self.empty_message
|
||||
r += htmltext('</ul>')
|
||||
r += htmltext('</div>')
|
||||
return r.getvalue()
|
||||
|
@ -192,8 +192,8 @@ class CardDefCategoryPage(CategoryPage):
|
|||
category_class = CardDefCategory
|
||||
category_ui_class = CardDefCategoryUI
|
||||
formdef_class = CardDef
|
||||
usage_title = N_('Card models in this category')
|
||||
empty_message = N_('no card model associated to this category')
|
||||
usage_title = _('Card models in this category')
|
||||
empty_message = _('no card model associated to this category')
|
||||
|
||||
|
||||
class CategoriesDirectory(Directory):
|
||||
|
@ -201,7 +201,7 @@ class CategoriesDirectory(Directory):
|
|||
category_class = Category
|
||||
category_ui_class = CategoryUI
|
||||
category_page_class = CategoryPage
|
||||
category_explanation = N_('Categories are used to sort the different forms.')
|
||||
category_explanation = _('Categories are used to sort the different forms.')
|
||||
|
||||
def _q_index(self):
|
||||
get_response().add_javascript(['jquery.js', 'jquery-ui.js', 'biglist.js', 'qommon.wysiwyg.js'])
|
||||
|
@ -214,7 +214,7 @@ class CategoriesDirectory(Directory):
|
|||
r += htmltext('<a class="new-item" href="new" rel="popup">%s</a>') % _('New Category')
|
||||
r += htmltext('</span>')
|
||||
r += htmltext('</div>')
|
||||
r += htmltext('<div class="explanation bo-block"><p>%s</p></div>') % _(self.category_explanation)
|
||||
r += htmltext('<div class="explanation bo-block"><p>%s</p></div>') % self.category_explanation
|
||||
categories = self.category_class.select()
|
||||
r += htmltext('<ul class="biglist sortable" id="category-list">')
|
||||
self.category_class.sort_by_position(categories)
|
||||
|
@ -273,4 +273,4 @@ class CardDefCategoriesDirectory(CategoriesDirectory):
|
|||
category_class = CardDefCategory
|
||||
category_ui_class = CardDefCategoryUI
|
||||
category_page_class = CardDefCategoryPage
|
||||
category_explanation = N_('Categories are used to sort the different card models.')
|
||||
category_explanation = _('Categories are used to sort the different card models.')
|
||||
|
|
|
@ -27,7 +27,7 @@ from wcs import fields
|
|||
from wcs.admin import utils
|
||||
from wcs.fields import get_field_options
|
||||
from wcs.formdef import FormDef
|
||||
from wcs.qommon import N_, _, errors, get_cfg, misc
|
||||
from wcs.qommon import _, errors, get_cfg, misc
|
||||
from wcs.qommon.admin.menu import command_icon
|
||||
from wcs.qommon.backoffice.menu import html_top
|
||||
from wcs.qommon.form import CheckboxWidget, Form, HtmlWidget, SingleSelectWidget, StringWidget
|
||||
|
@ -218,7 +218,7 @@ class FieldsDirectory(Directory):
|
|||
blacklisted_types = []
|
||||
page_id = None
|
||||
field_var_prefix = '..._'
|
||||
readonly_message = N_('The fields are readonly.')
|
||||
readonly_message = _('The fields are readonly.')
|
||||
|
||||
support_import = True
|
||||
|
||||
|
@ -323,7 +323,7 @@ class FieldsDirectory(Directory):
|
|||
if field.required:
|
||||
required = ''
|
||||
else:
|
||||
required = ' - ' + _('optional')
|
||||
required = ' - %s' % _('optional')
|
||||
r += htmltext('<span class="optional">%s</span>') % required
|
||||
if getattr(field, 'condition', None):
|
||||
r += htmltext(' - <span class="condition">%s</span>') % _('depending on condition')
|
||||
|
@ -348,8 +348,8 @@ class FieldsDirectory(Directory):
|
|||
r += htmltext('</ul>')
|
||||
|
||||
if self.objectdef.is_readonly():
|
||||
get_response().filter['sidebar'] = htmltext('<div class="infonotice"><p>%s</p></div>') % _(
|
||||
self.readonly_message
|
||||
get_response().filter['sidebar'] = (
|
||||
htmltext('<div class="infonotice"><p>%s</p></div>') % self.readonly_message
|
||||
)
|
||||
if hasattr(self.objectdef, 'snapshot_object'):
|
||||
get_response().filter['sidebar'] += utils.snapshot_info_block(
|
||||
|
@ -472,7 +472,7 @@ class FieldsDirectory(Directory):
|
|||
{
|
||||
'success': 'ok',
|
||||
'additional-action': {
|
||||
'message': _('Also move the fields of the page'),
|
||||
'message': str(_('Also move the fields of the page')),
|
||||
'url': 'move_page_fields?fields=%s&page=%s' % (';'.join(page_field_ids), dropped_element),
|
||||
},
|
||||
}
|
||||
|
|
|
@ -32,7 +32,7 @@ from wcs.carddef import CardDef
|
|||
from wcs.categories import Category
|
||||
from wcs.formdef import DRAFTS_DEFAULT_LIFESPAN, FormDef, FormdefImportError, FormdefImportRecoverableError
|
||||
from wcs.forms.root import qrcode
|
||||
from wcs.qommon import N_, _, force_str, get_logger, misc, template
|
||||
from wcs.qommon import _, force_str, get_logger, misc, template
|
||||
from wcs.qommon.afterjobs import AfterJob
|
||||
from wcs.qommon.backoffice.menu import html_top
|
||||
from wcs.qommon.errors import TraversalError
|
||||
|
@ -169,7 +169,7 @@ class AdminFieldDefPage(FieldDefPage):
|
|||
class AdminFieldsDirectory(FieldsDirectory):
|
||||
field_def_page_class = AdminFieldDefPage
|
||||
field_var_prefix = 'form_var_'
|
||||
readonly_message = N_('This form is readonly.')
|
||||
readonly_message = _('This form is readonly.')
|
||||
|
||||
def index_bottom(self):
|
||||
if self.objectdef.is_readonly():
|
||||
|
@ -189,7 +189,7 @@ class AdminFieldsDirectory(FieldsDirectory):
|
|||
|
||||
class OptionsDirectory(Directory):
|
||||
category_class = Category
|
||||
category_empty_choice = N_('Select a category for this form')
|
||||
category_empty_choice = _('Select a category for this form')
|
||||
_q_exports = [
|
||||
'confirmation',
|
||||
'only_allow_one',
|
||||
|
@ -341,7 +341,7 @@ class OptionsDirectory(Directory):
|
|||
def category(self):
|
||||
categories = get_categories(self.category_class)
|
||||
form = Form(enctype='multipart/form-data')
|
||||
form.widgets.append(HtmlWidget('<p>%s</p>' % _(self.category_empty_choice)))
|
||||
form.widgets.append(HtmlWidget('<p>%s</p>' % self.category_empty_choice))
|
||||
form.add(
|
||||
SingleSelectWidget,
|
||||
'category_id',
|
||||
|
@ -573,10 +573,10 @@ class FormDefPage(Directory):
|
|||
formdef_default_workflow = '_default'
|
||||
options_directory_class = OptionsDirectory
|
||||
|
||||
delete_message = N_('You are about to irrevocably delete this form.')
|
||||
delete_title = N_('Deleting Form:')
|
||||
overwrite_message = N_('You can replace this form by uploading a file ' 'or by pointing to a form URL.')
|
||||
overwrite_success_message = N_(
|
||||
delete_message = _('You are about to irrevocably delete this form.')
|
||||
delete_title = _('Deleting Form:')
|
||||
overwrite_message = _('You can replace this form by uploading a file ' 'or by pointing to a form URL.')
|
||||
overwrite_success_message = _(
|
||||
'The form has been successfully overwritten. '
|
||||
'Do note it kept its existing address and role and workflow parameters.'
|
||||
)
|
||||
|
@ -834,7 +834,7 @@ class FormDefPage(Directory):
|
|||
except KeyError:
|
||||
# removed role ?
|
||||
roles.append(_('Unknown role (%s)') % x)
|
||||
value = htmltext(', ').join(roles)
|
||||
value = htmltext(', ').join([str(x) for x in roles])
|
||||
else:
|
||||
value = C_('roles|None')
|
||||
return value
|
||||
|
@ -845,7 +845,7 @@ class FormDefPage(Directory):
|
|||
auth_contexts = get_publisher().get_supported_authentication_contexts()
|
||||
value += ' (%s)' % ', '.join(
|
||||
[
|
||||
auth_contexts.get(x)
|
||||
str(auth_contexts.get(x))
|
||||
for x in self.formdef.required_authentication_contexts
|
||||
if auth_contexts.get(x)
|
||||
]
|
||||
|
@ -1180,11 +1180,11 @@ class FormDefPage(Directory):
|
|||
def duplicate(self):
|
||||
self.formdefui.formdef.id = None
|
||||
original_name = self.formdefui.formdef.name
|
||||
self.formdefui.formdef.name = self.formdefui.formdef.name + _(' (copy)')
|
||||
self.formdefui.formdef.name = '%s %s' % (self.formdefui.formdef.name, _('(copy)'))
|
||||
formdef_names = [x.name for x in self.formdef_class.select(lightweight=True)]
|
||||
no = 2
|
||||
while self.formdefui.formdef.name in formdef_names:
|
||||
self.formdefui.formdef.name = _('%(name)s (copy %(no)d)') % {'name': original_name, 'no': no}
|
||||
self.formdefui.formdef.name = str(_('%(name)s (copy %(no)d)')) % {'name': original_name, 'no': no}
|
||||
no += 1
|
||||
self.formdefui.formdef.url_name = None
|
||||
self.formdefui.formdef.table_name = None
|
||||
|
@ -1212,16 +1212,16 @@ class FormDefPage(Directory):
|
|||
if check_count_message:
|
||||
form.widgets.append(HtmlWidget('<p>%s</p>' % check_count_message))
|
||||
else:
|
||||
form.widgets.append(HtmlWidget('<p>%s</p>' % _(self.delete_message)))
|
||||
form.widgets.append(HtmlWidget('<p>%s</p>' % self.delete_message))
|
||||
form.add_submit('delete', _('Delete'))
|
||||
form.add_submit('cancel', _('Cancel'))
|
||||
if form.get_widget('cancel').parse() or (form.is_submitted() and check_count_message):
|
||||
return redirect('..')
|
||||
if not form.is_submitted() or form.has_errors():
|
||||
get_response().breadcrumb.append(('delete', _('Delete')))
|
||||
self.html_top(title=_(self.delete_title))
|
||||
self.html_top(title=self.delete_title)
|
||||
r = TemplateIO(html=True)
|
||||
r += htmltext('<h2>%s %s</h2>') % (_(self.delete_title), self.formdef.name)
|
||||
r += htmltext('<h2>%s %s</h2>') % (self.delete_title, self.formdef.name)
|
||||
r += form.render()
|
||||
return r.getvalue()
|
||||
else:
|
||||
|
@ -1249,7 +1249,7 @@ class FormDefPage(Directory):
|
|||
self.html_top(title=_('Overwrite'))
|
||||
r = TemplateIO(html=True)
|
||||
r += htmltext('<h2>%s</h2>') % _('Overwrite')
|
||||
r += htmltext('<p>%s</p>') % _(self.overwrite_message)
|
||||
r += htmltext('<p>%s</p>') % self.overwrite_message
|
||||
r += form.render()
|
||||
return r.getvalue()
|
||||
|
||||
|
@ -1320,7 +1320,7 @@ class FormDefPage(Directory):
|
|||
new_formdef.roles = self.formdef.roles
|
||||
self.formdef = new_formdef
|
||||
self.formdef.store(comment=_('Overwritten'))
|
||||
get_session().message = ('info', _(self.overwrite_success_message))
|
||||
get_session().message = ('info', str(self.overwrite_success_message))
|
||||
return redirect('.')
|
||||
|
||||
def get_incompatible_field_ids(self, new_formdef):
|
||||
|
@ -1539,9 +1539,12 @@ class FormDefPage(Directory):
|
|||
count = self.formdef.data_class().count()
|
||||
archiver = Archiver(self.formdef)
|
||||
if count > 100: # Arbitrary threshold
|
||||
job = get_response().add_after_job(str(N_('Archiving forms')), archiver.archive)
|
||||
job.done_action_url = self.formdef.get_admin_url() + 'archive?job=%s' % job.id
|
||||
job.done_action_label = _('Download Archive')
|
||||
job = get_response().add_after_job(
|
||||
_('Archiving forms'),
|
||||
archiver.archive,
|
||||
done_action_url=self.formdef.get_admin_url() + 'archive?job=%(job_id)s',
|
||||
done_action_label=_('Download Archive'),
|
||||
)
|
||||
job.store()
|
||||
return redirect(job.get_processing_url())
|
||||
else:
|
||||
|
@ -1632,9 +1635,12 @@ class FormDefPage(Directory):
|
|||
count = self.formdef.data_class().count()
|
||||
anonymiser = Anonymiser(self.formdef, status_ids, before_date)
|
||||
if count > 100: # Arbitrary threshold
|
||||
job = get_response().add_after_job(str(N_('Anonymising forms')), anonymiser.anonymise)
|
||||
job.done_action_url = self.formdef.get_admin_url()
|
||||
job.done_action_label = _('Back')
|
||||
job = get_response().add_after_job(
|
||||
_('Anonymising forms'),
|
||||
anonymiser.anonymise,
|
||||
done_action_url=self.formdef.get_admin_url(),
|
||||
done_action_label=_('Back'),
|
||||
)
|
||||
job.store()
|
||||
return redirect(job.get_processing_url())
|
||||
else:
|
||||
|
@ -1739,15 +1745,15 @@ class FormsDirectory(AccessControlled, Directory):
|
|||
formdef_page_class = FormDefPage
|
||||
formdef_ui_class = FormDefUI
|
||||
|
||||
top_title = N_('Forms')
|
||||
import_title = N_('Import Form')
|
||||
import_submit_label = N_('Import Form')
|
||||
import_paragraph = N_('You can install a new form by uploading a file ' 'or by pointing to the form URL.')
|
||||
import_loading_error_message = N_('Error loading form (%s).')
|
||||
import_success_message = N_(
|
||||
top_title = _('Forms')
|
||||
import_title = _('Import Form')
|
||||
import_submit_label = _('Import Form')
|
||||
import_paragraph = _('You can install a new form by uploading a file ' 'or by pointing to the form URL.')
|
||||
import_loading_error_message = _('Error loading form (%s).')
|
||||
import_success_message = _(
|
||||
'This form has been successfully imported. ' 'Do note it is disabled by default.'
|
||||
)
|
||||
import_error_message = N_(
|
||||
import_error_message = _(
|
||||
'Imported form contained errors and has been automatically fixed, '
|
||||
'you should nevertheless check everything is ok. '
|
||||
'Do note it is disabled by default.'
|
||||
|
@ -1761,7 +1767,7 @@ class FormsDirectory(AccessControlled, Directory):
|
|||
return super()._q_traverse(path)
|
||||
|
||||
def _q_index(self):
|
||||
self.html_top(title=_(self.top_title))
|
||||
self.html_top(title=self.top_title)
|
||||
r = TemplateIO(html=True)
|
||||
get_response().add_javascript(['jquery.js', 'widget_list.js'])
|
||||
r += self.form_actions()
|
||||
|
@ -1865,7 +1871,7 @@ class FormsDirectory(AccessControlled, Directory):
|
|||
|
||||
form.add(FileWidget, 'file', title=_('File'), required=False)
|
||||
form.add(UrlWidget, 'url', title=_('Address'), required=False, size=50)
|
||||
form.add_submit('submit', _(self.import_submit_label))
|
||||
form.add_submit('submit', self.import_submit_label)
|
||||
form.add_submit('cancel', _('Cancel'))
|
||||
|
||||
if form.get_submit() == 'cancel':
|
||||
|
@ -1878,10 +1884,10 @@ class FormsDirectory(AccessControlled, Directory):
|
|||
pass
|
||||
|
||||
get_response().breadcrumb.append(('import', _('Import')))
|
||||
self.html_top(title=_(self.import_title))
|
||||
self.html_top(title=self.import_title)
|
||||
r = TemplateIO(html=True)
|
||||
r += htmltext('<h2>%s</h2>') % _(self.import_title)
|
||||
r += htmltext('<p>%s</p>') % _(self.import_paragraph)
|
||||
r += htmltext('<h2>%s</h2>') % self.import_title
|
||||
r += htmltext('<p>%s</p>') % self.import_paragraph
|
||||
r += form.render()
|
||||
return r.getvalue()
|
||||
|
||||
|
@ -1894,7 +1900,7 @@ class FormsDirectory(AccessControlled, Directory):
|
|||
try:
|
||||
fp = misc.urlopen(url)
|
||||
except misc.ConnectionError as e:
|
||||
form.set_error('url', _(self.import_loading_error_message) % str(e))
|
||||
form.set_error('url', self.import_loading_error_message % str(e))
|
||||
raise ValueError()
|
||||
else:
|
||||
form.set_error('file', _('You have to enter a file or a URL.'))
|
||||
|
@ -1904,11 +1910,11 @@ class FormsDirectory(AccessControlled, Directory):
|
|||
try:
|
||||
try:
|
||||
formdef = self.formdef_class.import_from_xml(fp)
|
||||
get_session().message = ('info', _(self.import_success_message))
|
||||
get_session().message = ('info', str(self.import_success_message))
|
||||
except FormdefImportRecoverableError as e:
|
||||
fp.seek(0)
|
||||
formdef = self.formdef_class.import_from_xml(fp, fix_on_error=True)
|
||||
get_session().message = ('info', _(self.import_error_message))
|
||||
get_session().message = ('info', str(self.import_error_message))
|
||||
except FormdefImportError as e:
|
||||
error = True
|
||||
reason = _(e.msg) % e.msg_args
|
||||
|
@ -1936,7 +1942,7 @@ class FormsDirectory(AccessControlled, Directory):
|
|||
|
||||
|
||||
class UpdateDigestAfterJob(AfterJob):
|
||||
label = N_('Updating digests')
|
||||
label = _('Updating digests')
|
||||
|
||||
def __init__(self, formdef):
|
||||
super().__init__(formdef_class=formdef.__class__, formdef_id=formdef.id)
|
||||
|
|
|
@ -38,7 +38,7 @@ from wcs.blocks import BlockDef
|
|||
from wcs.carddef import CardDef
|
||||
from wcs.data_sources import NamedDataSource
|
||||
from wcs.formdef import FormDef
|
||||
from wcs.qommon import N_, _, errors, get_cfg, ident, misc, template
|
||||
from wcs.qommon import _, errors, get_cfg, ident, misc, template
|
||||
from wcs.qommon.admin.cfg import cfg_submit
|
||||
from wcs.qommon.admin.emails import EmailsDirectory
|
||||
from wcs.qommon.admin.logger import LoggerDirectory
|
||||
|
@ -706,13 +706,13 @@ class SettingsDirectory(QommonSettingsDirectory):
|
|||
|
||||
permission_keys = []
|
||||
admin_sections = [
|
||||
('forms', N_('Forms')),
|
||||
('cards', N_('Card Models')),
|
||||
('workflows', N_('Workflows')),
|
||||
('users', N_('Users')),
|
||||
('roles', N_('Roles')),
|
||||
('categories', N_('Categories')),
|
||||
('settings', N_('Settings')),
|
||||
('forms', _('Forms')),
|
||||
('cards', _('Card Models')),
|
||||
('workflows', _('Workflows')),
|
||||
('users', _('Users')),
|
||||
('roles', _('Roles')),
|
||||
('categories', _('Categories')),
|
||||
('settings', _('Settings')),
|
||||
]
|
||||
for k, v in admin_sections:
|
||||
if k == 'cards' and not StudioDirectory.is_visible():
|
||||
|
@ -1128,10 +1128,13 @@ class SettingsDirectory(QommonSettingsDirectory):
|
|||
|
||||
exporter = Exporter(dirs, settings=form.get_widget('settings').parse())
|
||||
|
||||
job = get_response().add_after_job(N_('Exporting site settings'), exporter.export)
|
||||
job.done_action_url = get_request().get_url() + '?download=%s' % job.id
|
||||
job.done_action_label = _('Download Export')
|
||||
job.done_button_attributes = {'download': 'export.wcs'}
|
||||
job = get_response().add_after_job(
|
||||
_('Exporting site settings'),
|
||||
exporter.export,
|
||||
done_action_url=get_request().get_url() + '?download=%(job_id)s',
|
||||
done_action_label=_('Download Export'),
|
||||
done_button_attributes={'download': 'export.wcs'},
|
||||
)
|
||||
job.store()
|
||||
return redirect(job.get_processing_url())
|
||||
|
||||
|
|
|
@ -19,7 +19,7 @@ from quixote.directory import Directory
|
|||
from quixote.html import TemplateIO, htmltext
|
||||
|
||||
import wcs.qommon.storage as st
|
||||
from wcs.qommon import N_, _, errors, force_str, get_cfg, ident, misc
|
||||
from wcs.qommon import _, errors, force_str, get_cfg, ident, misc
|
||||
from wcs.qommon.admin.emails import EmailsDirectory
|
||||
from wcs.qommon.admin.menu import error_page
|
||||
from wcs.qommon.backoffice.listing import pagination_links
|
||||
|
@ -537,11 +537,11 @@ class UsersDirectory(Directory):
|
|||
|
||||
EmailsDirectory.register(
|
||||
'email_with_token',
|
||||
N_('Identification token'),
|
||||
N_('Available variables: token, token_url, sitename'),
|
||||
category=N_('Identification'),
|
||||
default_subject=N_('Access to [sitename]'),
|
||||
default_body=N_(
|
||||
_('Identification token'),
|
||||
_('Available variables: token, token_url, sitename'),
|
||||
category=_('Identification'),
|
||||
default_subject=_('Access to [sitename]'),
|
||||
default_body=_(
|
||||
'''\
|
||||
Hello,
|
||||
|
||||
|
|
|
@ -32,7 +32,7 @@ from wcs.backoffice.studio import StudioDirectory
|
|||
from wcs.carddef import CardDef
|
||||
from wcs.formdata import Evolution
|
||||
from wcs.formdef import FormDef
|
||||
from wcs.qommon import N_, _, errors, force_str, get_logger, misc, template
|
||||
from wcs.qommon import _, errors, force_str, get_logger, misc, template
|
||||
from wcs.qommon.admin.menu import command_icon
|
||||
from wcs.qommon.backoffice.menu import html_top
|
||||
from wcs.qommon.form import (
|
||||
|
@ -356,7 +356,7 @@ class WorkflowItemPage(Directory):
|
|||
if not self.workflow.is_readonly():
|
||||
submit_label = _('Submit')
|
||||
if hasattr(self.item, 'submit_button_label'):
|
||||
submit_label = _(self.item.submit_button_label)
|
||||
submit_label = self.item.submit_button_label
|
||||
form.add_submit('submit', submit_label)
|
||||
form.add_submit('cancel', _('Cancel'))
|
||||
|
||||
|
@ -955,7 +955,7 @@ class WorkflowVariablesFieldsDirectory(FieldsDirectory):
|
|||
support_import = False
|
||||
blacklisted_types = ['page', 'blocks', 'computed']
|
||||
field_var_prefix = 'form_option_'
|
||||
readonly_message = N_('This workflow is readonly.')
|
||||
readonly_message = _('This workflow is readonly.')
|
||||
|
||||
def index_top(self):
|
||||
r = TemplateIO(html=True)
|
||||
|
@ -978,7 +978,7 @@ class WorkflowBackofficeFieldsDirectory(FieldsDirectory):
|
|||
blacklisted_types = ['page', 'blocks', 'computed']
|
||||
blacklisted_attributes = ['condition']
|
||||
field_var_prefix = 'form_var_'
|
||||
readonly_message = N_('This workflow is readonly.')
|
||||
readonly_message = _('This workflow is readonly.')
|
||||
|
||||
def index_top(self):
|
||||
r = TemplateIO(html=True)
|
||||
|
@ -1746,11 +1746,14 @@ class WorkflowPage(Directory):
|
|||
def duplicate(self):
|
||||
self.workflow_ui.workflow.id = None
|
||||
original_name = self.workflow_ui.workflow.name
|
||||
self.workflow_ui.workflow.name = self.workflow_ui.workflow.name + _(' (copy)')
|
||||
self.workflow_ui.workflow.name = '%s %s' % (self.workflow_ui.workflow.name, _('(copy)'))
|
||||
workflow_names = [x.name for x in Workflow.select()]
|
||||
no = 2
|
||||
while self.workflow_ui.workflow.name in workflow_names:
|
||||
self.workflow_ui.workflow.name = _('%(name)s (copy %(no)d)') % {'name': original_name, 'no': no}
|
||||
self.workflow_ui.workflow.name = str(_('%(name)s (copy %(no)d)')) % {
|
||||
'name': original_name,
|
||||
'no': no,
|
||||
}
|
||||
no += 1
|
||||
self.workflow_ui.workflow.store()
|
||||
return redirect('../%s/' % self.workflow_ui.workflow.id)
|
||||
|
|
|
@ -1261,7 +1261,7 @@ def validate_expression(request, *args, **kwargs):
|
|||
if expression and re.match(r'^=.*\[[a-zA-Z_]\w*\]', expression):
|
||||
hint['klass'] = 'warning'
|
||||
hint['msg'] = _('Make sure you want a Python expression, not a simple template string.')
|
||||
return HttpResponse(json.dumps(hint), content_type='application/json')
|
||||
return JsonResponse(hint)
|
||||
|
||||
|
||||
def validate_condition(request, *args, **kwargs):
|
||||
|
@ -1274,7 +1274,7 @@ def validate_condition(request, *args, **kwargs):
|
|||
except ValidationError as e:
|
||||
hint['klass'] = 'error'
|
||||
hint['msg'] = str(e)
|
||||
return HttpResponse(json.dumps(hint), content_type='application/json')
|
||||
return JsonResponse(hint)
|
||||
|
||||
|
||||
def provisionning(request):
|
||||
|
|
|
@ -28,7 +28,7 @@ from wcs.carddef import CardDef
|
|||
from wcs.categories import CardDefCategory
|
||||
from wcs.workflows import Workflow
|
||||
|
||||
from ..qommon import N_, _
|
||||
from ..qommon import _
|
||||
from ..qommon.misc import C_
|
||||
from ..qommon.storage import NotEqual, Null
|
||||
|
||||
|
@ -40,7 +40,7 @@ class CardDefUI(FormDefUI):
|
|||
|
||||
class CardDefOptionsDirectory(OptionsDirectory):
|
||||
category_class = CardDefCategory
|
||||
category_empty_choice = N_('Select a category for this card model')
|
||||
category_empty_choice = _('Select a category for this card model')
|
||||
|
||||
|
||||
class CardDefPage(FormDefPage):
|
||||
|
@ -51,12 +51,12 @@ class CardDefPage(FormDefPage):
|
|||
|
||||
options_directory_class = CardDefOptionsDirectory
|
||||
|
||||
delete_message = N_('You are about to irrevocably delete this card model.')
|
||||
delete_title = N_('Deleting Card Model:')
|
||||
overwrite_message = N_(
|
||||
delete_message = _('You are about to irrevocably delete this card model.')
|
||||
delete_title = _('Deleting Card Model:')
|
||||
overwrite_message = _(
|
||||
'You can replace this card model by uploading a file ' 'or by pointing to a form URL.'
|
||||
)
|
||||
overwrite_success_message = N_(
|
||||
overwrite_success_message = _(
|
||||
'The card model has been successfully overwritten. '
|
||||
'Do note it kept its existing address and role and workflow parameters.'
|
||||
)
|
||||
|
@ -250,15 +250,15 @@ class CardsDirectory(FormsDirectory):
|
|||
formdef_page_class = CardDefPage
|
||||
formdef_ui_class = CardDefUI
|
||||
|
||||
top_title = N_('Card Models')
|
||||
import_title = N_('Import Card Model')
|
||||
import_submit_label = N_('Import Card Model')
|
||||
import_paragraph = N_(
|
||||
top_title = _('Card Models')
|
||||
import_title = _('Import Card Model')
|
||||
import_submit_label = _('Import Card Model')
|
||||
import_paragraph = _(
|
||||
'You can install a new card model by uploading a file ' 'or by pointing to the card model URL.'
|
||||
)
|
||||
import_loading_error_message = N_('Error loading card model (%s).')
|
||||
import_success_message = N_('This card model has been successfully imported. ')
|
||||
import_error_message = N_(
|
||||
import_loading_error_message = _('Error loading card model (%s).')
|
||||
import_success_message = _('This card model has been successfully imported. ')
|
||||
import_error_message = _(
|
||||
'Imported card model contained errors and has been automatically fixed, '
|
||||
'you should nevertheless check everything is ok. '
|
||||
)
|
||||
|
|
|
@ -26,7 +26,7 @@ from wcs import fields
|
|||
from wcs.carddef import CardDef
|
||||
from wcs.categories import CardDefCategory
|
||||
|
||||
from ..qommon import N_, _, errors, template
|
||||
from ..qommon import _, errors, template
|
||||
from ..qommon.afterjobs import AfterJob
|
||||
from ..qommon.backoffice.menu import html_top
|
||||
from ..qommon.form import FileWidget, Form
|
||||
|
@ -99,7 +99,7 @@ class CardPage(FormPage):
|
|||
]
|
||||
admin_permission = 'cards'
|
||||
formdef_class = CardDef
|
||||
search_label = N_('Search in card content')
|
||||
search_label = _('Search in card content')
|
||||
|
||||
@property
|
||||
def add(self):
|
||||
|
@ -331,8 +331,8 @@ class CardFillPage(FormFillPage):
|
|||
class CardBackOfficeStatusPage(FormBackOfficeStatusPage):
|
||||
form_page_class = CardFillPage
|
||||
|
||||
sidebar_recorded_message = N_('The card has been recorded on %(date)s with the number %(number)s.')
|
||||
sidebar_recorded_by_agent_message = N_(
|
||||
sidebar_recorded_message = _('The card has been recorded on %(date)s with the number %(number)s.')
|
||||
sidebar_recorded_by_agent_message = _(
|
||||
'The card has been recorded on %(date)s with the number %(number)s by %(agent)s.'
|
||||
)
|
||||
|
||||
|
|
|
@ -44,7 +44,7 @@ from wcs.roles import logged_users_role
|
|||
from wcs.variables import LazyFieldVar
|
||||
from wcs.workflows import WorkflowStatusItem, template_on_formdata
|
||||
|
||||
from ..qommon import N_, _, emails, errors, ezt, force_str, get_cfg, get_logger, misc, ngettext, ods, sms
|
||||
from ..qommon import _, emails, errors, ezt, force_str, get_cfg, get_logger, misc, ngettext, ods, sms
|
||||
from ..qommon.admin.emails import EmailsDirectory
|
||||
from ..qommon.admin.menu import command_icon
|
||||
from ..qommon.afterjobs import AfterJob
|
||||
|
@ -127,7 +127,7 @@ def geojson_formdatas(formdatas, geoloc_key='base', fields=None):
|
|||
'url': formdata_backoffice_url,
|
||||
'status_name': str(htmlescape(status.name)),
|
||||
'status_colour': '#%s' % status_colour,
|
||||
'view_label': _('View'),
|
||||
'view_label': force_text(_('View')),
|
||||
},
|
||||
'geometry': {
|
||||
'type': 'Point',
|
||||
|
@ -1060,7 +1060,7 @@ class ManagementDirectory(Directory):
|
|||
FakeField('status', 'status', _('Status')),
|
||||
]
|
||||
get_response().set_content_type('application/json')
|
||||
return json.dumps(geojson_formdatas(formdatas, fields=fields))
|
||||
return json.dumps(geojson_formdatas(formdatas, fields=fields), cls=misc.JSONEncoder)
|
||||
|
||||
def map(self):
|
||||
if not get_publisher().is_using_postgresql():
|
||||
|
@ -1107,7 +1107,7 @@ class FormPage(Directory):
|
|||
use_default_view = False
|
||||
admin_permission = 'forms'
|
||||
formdef_class = FormDef
|
||||
search_label = N_('Search in form content')
|
||||
search_label = _('Search in form content')
|
||||
WCS_SYNC_EXPORT_LIMIT = 100 # Arbitrary threshold
|
||||
|
||||
def __init__(self, component=None, formdef=None, view=None, update_breadcrumbs=True):
|
||||
|
@ -1568,7 +1568,7 @@ class FormPage(Directory):
|
|||
r += htmltext('<input type="hidden" name="order_by" value="%s"/>') % order_by
|
||||
|
||||
if get_publisher().is_using_postgresql():
|
||||
r += htmltext('<h3>%s</h3>') % _(self.search_label)
|
||||
r += htmltext('<h3>%s</h3>') % self.search_label
|
||||
if get_request().form.get('q'):
|
||||
q = force_text(get_request().form.get('q'))
|
||||
r += htmltext('<input class="inline-input" name="q" value="%s">') % force_str(q)
|
||||
|
@ -2331,7 +2331,7 @@ class FormPage(Directory):
|
|||
fields, selected_filter, user=user, query=query, criterias=criterias
|
||||
)[0]
|
||||
|
||||
return json.dumps(geojson_formdatas(items, fields=fields))
|
||||
return json.dumps(geojson_formdatas(items, fields=fields), cls=misc.JSONEncoder)
|
||||
|
||||
def ics(self):
|
||||
if get_request().has_anonymised_data_api_restriction():
|
||||
|
@ -2716,8 +2716,8 @@ class FormBackOfficeStatusPage(FormStatusPage):
|
|||
]
|
||||
form_page_class = FormFillPage
|
||||
|
||||
sidebar_recorded_message = N_('The form has been recorded on %(date)s with the number %(number)s.')
|
||||
sidebar_recorded_by_agent_message = N_(
|
||||
sidebar_recorded_message = _('The form has been recorded on %(date)s with the number %(number)s.')
|
||||
sidebar_recorded_by_agent_message = _(
|
||||
'The form has been recorded on %(date)s with the number %(number)s by %(agent)s.'
|
||||
)
|
||||
|
||||
|
@ -2811,13 +2811,13 @@ class FormBackOfficeStatusPage(FormStatusPage):
|
|||
agent_user = get_publisher().user_class.get(formdata.submission_agent_id, ignore_errors=True)
|
||||
|
||||
if agent_user:
|
||||
r += _(self.sidebar_recorded_by_agent_message) % {
|
||||
r += self.sidebar_recorded_by_agent_message % {
|
||||
'date': tm,
|
||||
'number': formdata.get_display_id(),
|
||||
'agent': agent_user.get_display_name(),
|
||||
}
|
||||
else:
|
||||
r += _(self.sidebar_recorded_message) % {'date': tm, 'number': formdata.get_display_id()}
|
||||
r += self.sidebar_recorded_message % {'date': tm, 'number': formdata.get_display_id()}
|
||||
r += htmltext('</p>')
|
||||
try:
|
||||
status_colour = formdata.get_status().colour
|
||||
|
@ -3441,7 +3441,7 @@ class FakeField:
|
|||
def __init__(self, id, type_, label, addable=True):
|
||||
self.id = id
|
||||
self.type = type_
|
||||
self.label = label
|
||||
self.label = force_text(label)
|
||||
self.fake = True
|
||||
self.varname = id.replace('-', '_')
|
||||
self.store_display_value = None
|
||||
|
@ -3545,10 +3545,10 @@ var month_line = %(month_line)s;
|
|||
var year_line = %(year_line)s;
|
||||
</script>'''
|
||||
% {
|
||||
'weekday_line': json.dumps(weekday_totals),
|
||||
'hour_line': json.dumps(hour_totals),
|
||||
'month_line': json.dumps(monthly_totals),
|
||||
'year_line': json.dumps(yearly_totals),
|
||||
'weekday_line': json.dumps(weekday_totals, cls=misc.JSONEncoder),
|
||||
'hour_line': json.dumps(hour_totals, cls=misc.JSONEncoder),
|
||||
'month_line': json.dumps(monthly_totals, cls=misc.JSONEncoder),
|
||||
'year_line': json.dumps(yearly_totals, cls=misc.JSONEncoder),
|
||||
}
|
||||
)
|
||||
|
||||
|
@ -3735,7 +3735,7 @@ class MassActionAfterJob(AfterJob):
|
|||
|
||||
|
||||
class CsvExportAfterJob(AfterJob):
|
||||
label = N_('Exporting forms in CSV')
|
||||
label = _('Exporting to CSV file')
|
||||
|
||||
def __init__(self, formdef, **kwargs):
|
||||
super().__init__(formdef_class=formdef.__class__, formdef_id=formdef.id, **kwargs)
|
||||
|
@ -3799,6 +3799,8 @@ class CsvExportAfterJob(AfterJob):
|
|||
|
||||
|
||||
class OdsExportAfterJob(CsvExportAfterJob):
|
||||
label = _('Exporting to ODS file')
|
||||
|
||||
def __init__(self, formdef, **kwargs):
|
||||
super().__init__(formdef=formdef, **kwargs)
|
||||
self.file_name = '%s.ods' % formdef.url_name
|
||||
|
|
|
@ -28,7 +28,7 @@ import wcs.admin.users
|
|||
import wcs.admin.workflows
|
||||
from wcs.formdef import FormDef
|
||||
|
||||
from ..qommon import N_, _, errors, get_cfg, misc, template
|
||||
from ..qommon import _, errors, get_cfg, misc, template
|
||||
from ..qommon.afterjobs import AfterJob
|
||||
from ..qommon.backoffice import BackofficeRootDirectory
|
||||
from ..qommon.backoffice.menu import html_top
|
||||
|
@ -54,16 +54,16 @@ class RootDirectory(BackofficeRootDirectory):
|
|||
submission = SubmissionDirectory()
|
||||
|
||||
menu_items = [
|
||||
('submission/', N_('Submission')),
|
||||
('management/', N_('Management')),
|
||||
('data/', N_('Cards'), {'check_display_function': studio.is_visible}),
|
||||
('studio/', N_('Studio'), {'check_display_function': studio.is_visible}),
|
||||
('forms/', N_('Forms Workshop'), {'sub': True}),
|
||||
('cards/', N_('Card Models'), {'sub': True, 'check_display_function': studio.is_visible}),
|
||||
('workflows/', N_('Workflows Workshop'), {'sub': True}),
|
||||
('users/', N_('Users'), {'check_display_function': roles.is_visible}),
|
||||
('roles/', N_('Roles'), {'check_display_function': roles.is_visible}),
|
||||
('settings/', N_('Settings')),
|
||||
('submission/', _('Submission')),
|
||||
('management/', _('Management')),
|
||||
('data/', _('Cards'), {'check_display_function': studio.is_visible}),
|
||||
('studio/', _('Studio'), {'check_display_function': studio.is_visible}),
|
||||
('forms/', _('Forms Workshop'), {'sub': True}),
|
||||
('cards/', _('Card Models'), {'sub': True, 'check_display_function': studio.is_visible}),
|
||||
('workflows/', _('Workflows Workshop'), {'sub': True}),
|
||||
('users/', _('Users'), {'check_display_function': roles.is_visible}),
|
||||
('roles/', _('Roles'), {'check_display_function': roles.is_visible}),
|
||||
('settings/', _('Settings')),
|
||||
]
|
||||
|
||||
def _q_traverse(self, path):
|
||||
|
|
|
@ -21,7 +21,7 @@ from quixote import get_publisher, get_request
|
|||
from quixote.html import htmltag, htmltext
|
||||
|
||||
from . import data_sources, fields
|
||||
from .qommon import N_, _, misc
|
||||
from .qommon import _, misc
|
||||
from .qommon.form import CompositeWidget, WidgetList
|
||||
from .qommon.storage import StorableObject
|
||||
from .qommon.template import Template
|
||||
|
@ -136,7 +136,7 @@ class BlockDef(StorableObject):
|
|||
unknown_datasources.add(data_source.get('type'))
|
||||
if unknown_datasources:
|
||||
raise BlockdefImportError(
|
||||
N_('Unknown datasources'), details=', '.join(sorted(unknown_datasources))
|
||||
_('Unknown datasources'), details=', '.join(sorted(unknown_datasources))
|
||||
)
|
||||
|
||||
return blockdef
|
||||
|
@ -146,7 +146,7 @@ class BlockDef(StorableObject):
|
|||
charset = 'utf-8'
|
||||
blockdef = cls()
|
||||
if tree.find('name') is None or not tree.find('name').text:
|
||||
raise BlockdefImportError(N_('Missing name'))
|
||||
raise BlockdefImportError(_('Missing name'))
|
||||
|
||||
# if the tree we get is actually a ElementTree for real, we get its
|
||||
# root element and go on happily.
|
||||
|
@ -154,7 +154,7 @@ class BlockDef(StorableObject):
|
|||
tree = tree.getroot()
|
||||
|
||||
if tree.tag != cls.xml_root_node:
|
||||
raise BlockdefImportError(N_('Unexpected root node'))
|
||||
raise BlockdefImportError(_('Unexpected root node'))
|
||||
|
||||
if include_id and tree.attrib.get('id'):
|
||||
blockdef.id = tree.attrib.get('id')
|
||||
|
@ -169,7 +169,7 @@ class BlockDef(StorableObject):
|
|||
try:
|
||||
field_o = fields.get_field_class_by_type(field.findtext('type'))()
|
||||
except KeyError:
|
||||
raise BlockdefImportError(N_('Unknown field type'), details=field.findtext('type'))
|
||||
raise BlockdefImportError(_('Unknown field type'), details=field.findtext('type'))
|
||||
field_o.init_with_xml(field, charset, include_id=True)
|
||||
blockdef.fields.append(field_o)
|
||||
|
||||
|
|
|
@ -23,7 +23,7 @@ from wcs.carddata import CardData
|
|||
from wcs.categories import CardDefCategory
|
||||
from wcs.formdef import FormDef, get_formdefs_of_all_kinds
|
||||
|
||||
from .qommon import N_, _, misc
|
||||
from .qommon import _, force_text, misc
|
||||
from .qommon.storage import Equal, ILike, NotEqual
|
||||
from .qommon.template import Template
|
||||
|
||||
|
@ -36,8 +36,8 @@ class CardDef(FormDef):
|
|||
data_sql_prefix = 'carddata'
|
||||
pickle_module_name = 'carddef'
|
||||
xml_root_node = 'carddef'
|
||||
verbose_name = N_('Card model')
|
||||
verbose_name_plural = N_('Card models')
|
||||
verbose_name = _('Card model')
|
||||
verbose_name_plural = _('Card models')
|
||||
|
||||
confirmation = False
|
||||
|
||||
|
@ -93,19 +93,19 @@ class CardDef(FormDef):
|
|||
from wcs.wf.remove import RemoveWorkflowStatusItem
|
||||
from wcs.workflows import ChoiceWorkflowStatusItem, EditableWorkflowStatusItem, Workflow
|
||||
|
||||
workflow = Workflow(name=_('Default (cards)'))
|
||||
workflow = Workflow(name=force_text(_('Default (cards)')))
|
||||
workflow.id = '_carddef_default'
|
||||
workflow.roles = {
|
||||
'_viewer': _('Viewer'),
|
||||
'_editor': _('Editor'),
|
||||
'_viewer': force_text(_('Viewer')),
|
||||
'_editor': force_text(_('Editor')),
|
||||
}
|
||||
status = workflow.add_status(_('Recorded'), 'recorded')
|
||||
deleted_status = workflow.add_status(_('Deleted'), 'deleted')
|
||||
status = workflow.add_status(force_text(_('Recorded')), 'recorded')
|
||||
deleted_status = workflow.add_status(force_text(_('Deleted')), 'deleted')
|
||||
|
||||
editable = EditableWorkflowStatusItem()
|
||||
editable.id = '_editable'
|
||||
editable.by = ['_editor']
|
||||
editable.label = _('Edit Card')
|
||||
editable.label = force_text(_('Edit Card'))
|
||||
editable.status = status.id
|
||||
editable.parent = status
|
||||
status.items.append(editable)
|
||||
|
@ -113,7 +113,7 @@ class CardDef(FormDef):
|
|||
action_delete = ChoiceWorkflowStatusItem()
|
||||
action_delete.id = '_action_delete'
|
||||
action_delete.by = ['_editor']
|
||||
action_delete.label = _('Delete Card')
|
||||
action_delete.label = force_text(_('Delete Card'))
|
||||
action_delete.status = deleted_status.id
|
||||
action_delete.require_confirmation = True
|
||||
action_delete.parent = status
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
from quixote import get_publisher
|
||||
from quixote.html import htmltext
|
||||
|
||||
from .qommon import N_
|
||||
from .qommon import _
|
||||
from .qommon.misc import simplify
|
||||
from .qommon.storage import StorableObject
|
||||
from .qommon.substitution import Substitutions
|
||||
|
@ -128,6 +128,6 @@ class CardDefCategory(Category):
|
|||
XML_NODES = [('name', 'str'), ('url_name', 'str'), ('description', 'str'), ('position', 'int')]
|
||||
|
||||
|
||||
Substitutions.register('category_name', category=N_('General'), comment=N_('Category Name'))
|
||||
Substitutions.register('category_description', category=N_('General'), comment=N_('Category Description'))
|
||||
Substitutions.register('category_id', category=N_('General'), comment=N_('Category Identifier'))
|
||||
Substitutions.register('category_name', category=_('General'), comment=_('Category Name'))
|
||||
Substitutions.register('category_description', category=_('General'), comment=_('Category Description'))
|
||||
Substitutions.register('category_id', category=_('General'), comment=_('Category Identifier'))
|
||||
|
|
|
@ -26,7 +26,7 @@ from quixote import get_publisher, get_request, get_session
|
|||
from quixote.html import TemplateIO
|
||||
|
||||
from .api_utils import sign_url_auto_orig
|
||||
from .qommon import N_, _, force_str, get_logger, misc
|
||||
from .qommon import _, force_str, get_logger, misc
|
||||
from .qommon.afterjobs import AfterJob
|
||||
from .qommon.cron import CronJob
|
||||
from .qommon.form import CompositeWidget, OptGroup, SingleSelectWidget, StringWidget
|
||||
|
@ -916,7 +916,7 @@ def build_agenda_datasources(publisher):
|
|||
|
||||
|
||||
class RefreshAgendas(AfterJob):
|
||||
label = N_('Refreshing agendas')
|
||||
label = _('Refreshing agendas')
|
||||
|
||||
def execute(self):
|
||||
build_agenda_datasources(get_publisher())
|
||||
|
|
|
@ -201,7 +201,7 @@ class PrefillSelectionWidget(CompositeWidget):
|
|||
attrs={
|
||||
'data-dynamic-display-child-of': 'prefill$type',
|
||||
'data-dynamic-display-value-in': '|'.join(
|
||||
[x[1] for x in options if x[0] not in ('none', 'geolocation')]
|
||||
[str(x[1]) for x in options if x[0] not in ('none', 'geolocation')]
|
||||
),
|
||||
'inline_title': _('Locked'),
|
||||
},
|
||||
|
@ -268,7 +268,7 @@ class Field:
|
|||
pass
|
||||
|
||||
def get_type_label(self):
|
||||
return _(self.description)
|
||||
return self.description
|
||||
|
||||
@property
|
||||
def include_in_listing(self):
|
||||
|
@ -822,7 +822,7 @@ def register_field_class(klass):
|
|||
|
||||
class TitleField(Field):
|
||||
key = 'title'
|
||||
description = N_('Title')
|
||||
description = _('Title')
|
||||
html_tag = 'h3'
|
||||
display_locations = ['validation', 'summary']
|
||||
|
||||
|
@ -885,7 +885,7 @@ register_field_class(TitleField)
|
|||
|
||||
class SubtitleField(TitleField):
|
||||
key = 'subtitle'
|
||||
description = N_('Subtitle')
|
||||
description = _('Subtitle')
|
||||
html_tag = 'h4'
|
||||
|
||||
|
||||
|
@ -894,7 +894,7 @@ register_field_class(SubtitleField)
|
|||
|
||||
class CommentField(Field):
|
||||
key = 'comment'
|
||||
description = N_('Comment')
|
||||
description = _('Comment')
|
||||
display_locations = []
|
||||
|
||||
def get_text(self):
|
||||
|
@ -995,7 +995,7 @@ def is_datasource_advanced(value):
|
|||
|
||||
class StringField(WidgetField):
|
||||
key = 'string'
|
||||
description = N_('Text (line)')
|
||||
description = _('Text (line)')
|
||||
|
||||
widget_class = WcsExtraStringWidget
|
||||
size = None
|
||||
|
@ -1091,7 +1091,7 @@ register_field_class(StringField)
|
|||
|
||||
class TextField(WidgetField):
|
||||
key = 'text'
|
||||
description = N_('Long Text')
|
||||
description = _('Long Text')
|
||||
|
||||
widget_class = TextWidget
|
||||
cols = None
|
||||
|
@ -1156,7 +1156,7 @@ register_field_class(TextField)
|
|||
|
||||
class EmailField(WidgetField):
|
||||
key = 'email'
|
||||
description = N_('Email')
|
||||
description = _('Email')
|
||||
|
||||
widget_class = EmailWidget
|
||||
|
||||
|
@ -1181,7 +1181,7 @@ register_field_class(EmailField)
|
|||
|
||||
class BoolField(WidgetField):
|
||||
key = 'bool'
|
||||
description = N_('Check Box (single choice)')
|
||||
description = _('Check Box (single choice)')
|
||||
allow_complex = True
|
||||
|
||||
widget_class = CheckboxWidget
|
||||
|
@ -1202,9 +1202,9 @@ class BoolField(WidgetField):
|
|||
|
||||
def get_view_value(self, value, **kwargs):
|
||||
if value is True or value == 'True':
|
||||
return _('Yes')
|
||||
return str(_('Yes'))
|
||||
elif value is False or value == 'False':
|
||||
return _('No')
|
||||
return str(_('No'))
|
||||
else:
|
||||
return ''
|
||||
|
||||
|
@ -1278,7 +1278,7 @@ register_field_class(BoolField)
|
|||
|
||||
class FileField(WidgetField):
|
||||
key = 'file'
|
||||
description = N_('File Upload')
|
||||
description = _('File Upload')
|
||||
allow_complex = True
|
||||
|
||||
document_type = None
|
||||
|
@ -1497,7 +1497,7 @@ class FileField(WidgetField):
|
|||
# self.file_type is a combination of file type, we create a
|
||||
# virtual one from them
|
||||
if parts and len(parts) > 1:
|
||||
label = ', '.join(parts)
|
||||
label = ', '.join([str(x) for x in parts])
|
||||
else:
|
||||
label = ','.join(file_type)
|
||||
self.document_type = {
|
||||
|
@ -1534,7 +1534,7 @@ register_field_class(FileField)
|
|||
|
||||
class DateField(WidgetField):
|
||||
key = 'date'
|
||||
description = N_('Date')
|
||||
description = _('Date')
|
||||
|
||||
widget_class = DateWidget
|
||||
minimum_date = None
|
||||
|
@ -1807,7 +1807,7 @@ class ItemFieldMixin:
|
|||
|
||||
class ItemField(WidgetField, MapOptionsMixin, ItemFieldMixin):
|
||||
key = 'item'
|
||||
description = N_('List')
|
||||
description = _('List')
|
||||
allow_complex = True
|
||||
|
||||
items = []
|
||||
|
@ -2163,7 +2163,7 @@ register_field_class(ItemField)
|
|||
|
||||
class ItemsField(WidgetField, ItemFieldMixin):
|
||||
key = 'items'
|
||||
description = N_('Multiple choice list')
|
||||
description = _('Multiple choice list')
|
||||
allow_complex = True
|
||||
|
||||
items = []
|
||||
|
@ -2501,7 +2501,7 @@ class PageCondition(Condition):
|
|||
|
||||
class PageField(Field):
|
||||
key = 'page'
|
||||
description = N_('Page')
|
||||
description = _('Page')
|
||||
|
||||
post_conditions = None
|
||||
|
||||
|
@ -2595,7 +2595,7 @@ register_field_class(PageField)
|
|||
|
||||
class TableField(WidgetField):
|
||||
key = 'table'
|
||||
description = N_('Table')
|
||||
description = _('Table')
|
||||
allow_complex = True
|
||||
|
||||
rows = None
|
||||
|
@ -2764,7 +2764,7 @@ register_field_class(TableField)
|
|||
|
||||
class TableSelectField(TableField):
|
||||
key = 'table-select'
|
||||
description = N_('Table of Lists')
|
||||
description = _('Table of Lists')
|
||||
allow_complex = True
|
||||
|
||||
items = None
|
||||
|
@ -2813,7 +2813,7 @@ register_field_class(TableSelectField)
|
|||
|
||||
class TableRowsField(WidgetField):
|
||||
key = 'tablerows'
|
||||
description = N_('Table with rows')
|
||||
description = _('Table with rows')
|
||||
allow_complex = True
|
||||
|
||||
total_row = True
|
||||
|
@ -2956,7 +2956,7 @@ register_field_class(TableRowsField)
|
|||
|
||||
class MapField(WidgetField, MapOptionsMixin):
|
||||
key = 'map'
|
||||
description = N_('Map')
|
||||
description = _('Map')
|
||||
|
||||
default_position = None
|
||||
init_with_geoloc = False
|
||||
|
@ -3054,7 +3054,7 @@ register_field_class(MapField)
|
|||
|
||||
class RankedItemsField(WidgetField):
|
||||
key = 'ranked-items'
|
||||
description = N_('Ranked Items')
|
||||
description = _('Ranked Items')
|
||||
allow_complex = True
|
||||
|
||||
items = []
|
||||
|
@ -3141,7 +3141,7 @@ register_field_class(RankedItemsField)
|
|||
|
||||
class PasswordField(WidgetField):
|
||||
key = 'password'
|
||||
description = N_('Password')
|
||||
description = _('Password')
|
||||
|
||||
min_length = 0
|
||||
max_length = 0
|
||||
|
@ -3465,13 +3465,13 @@ def get_field_options(blacklisted_types):
|
|||
if klass.key in blacklisted_types:
|
||||
continue
|
||||
if issubclass(klass, WidgetField):
|
||||
widgets.append((klass.key, _(klass.description), klass.key))
|
||||
widgets.append((klass.key, klass.description, klass.key))
|
||||
else:
|
||||
non_widgets.append((klass.key, _(klass.description), klass.key))
|
||||
non_widgets.append((klass.key, klass.description, klass.key))
|
||||
options = widgets + [('', '—', '')] + non_widgets
|
||||
|
||||
# add computed field in its own "section"
|
||||
options.extend([('', '—', ''), (ComputedField.key, _(ComputedField.description), ComputedField.key)])
|
||||
options.extend([('', '—', ''), (ComputedField.key, ComputedField.description, ComputedField.key)])
|
||||
|
||||
if get_publisher().has_site_option('fields-blocks') and (
|
||||
not blacklisted_types or 'blocks' not in blacklisted_types
|
||||
|
|
|
@ -25,7 +25,7 @@ import time
|
|||
from quixote import get_publisher, get_request, get_session
|
||||
from quixote.http_request import Upload
|
||||
|
||||
from .qommon import N_, _, misc
|
||||
from .qommon import _, misc
|
||||
from .qommon.evalutils import make_datetime
|
||||
from .qommon.publisher import get_cfg
|
||||
from .qommon.storage import Contains, Intersects, Null, StorableObject
|
||||
|
@ -1421,14 +1421,14 @@ class FormData(StorableObject):
|
|||
self.__dict__ = dict
|
||||
|
||||
|
||||
Substitutions.register('form_receipt_date', category=N_('Form'), comment=N_('Form Receipt Date'))
|
||||
Substitutions.register('form_receipt_time', category=N_('Form'), comment=N_('Form Receipt Time'))
|
||||
Substitutions.register('form_number', category=N_('Form'), comment=N_('Form Number'))
|
||||
Substitutions.register('form_details', category=N_('Form'), comment=N_('Form Details'))
|
||||
Substitutions.register('form_url', category=N_('Form'), comment=N_('Form URL'))
|
||||
Substitutions.register('form_url_backoffice', category=N_('Form'), comment=N_('Form URL (backoffice)'))
|
||||
Substitutions.register('form_status_url', category=N_('Form'), comment=N_('Form Status URL'))
|
||||
Substitutions.register('form_tracking_code', category=N_('Form'), comment=N_('Form Tracking Code'))
|
||||
Substitutions.register('form_user_display_name', category=N_('Form'), comment=N_('Form Submitter Name'))
|
||||
Substitutions.register('form_user_email', category=N_('Form'), comment=N_('Form Submitter Email'))
|
||||
Substitutions.register('form_receipt_date', category=_('Form'), comment=_('Form Receipt Date'))
|
||||
Substitutions.register('form_receipt_time', category=_('Form'), comment=_('Form Receipt Time'))
|
||||
Substitutions.register('form_number', category=_('Form'), comment=_('Form Number'))
|
||||
Substitutions.register('form_details', category=_('Form'), comment=_('Form Details'))
|
||||
Substitutions.register('form_url', category=_('Form'), comment=_('Form URL'))
|
||||
Substitutions.register('form_url_backoffice', category=_('Form'), comment=_('Form URL (backoffice)'))
|
||||
Substitutions.register('form_status_url', category=_('Form'), comment=_('Form Status URL'))
|
||||
Substitutions.register('form_tracking_code', category=_('Form'), comment=_('Form Tracking Code'))
|
||||
Substitutions.register('form_user_display_name', category=_('Form'), comment=_('Form Submitter Name'))
|
||||
Substitutions.register('form_user_email', category=_('Form'), comment=_('Form Submitter Email'))
|
||||
Substitutions.register_dynamic_source(FormData)
|
||||
|
|
|
@ -35,7 +35,7 @@ from quixote.http_request import Upload
|
|||
from . import data_sources, fields
|
||||
from .categories import Category
|
||||
from .formdata import FormData
|
||||
from .qommon import N_, PICKLE_KWARGS, _, force_str, get_cfg
|
||||
from .qommon import PICKLE_KWARGS, _, force_str, get_cfg
|
||||
from .qommon.admin.emails import EmailsDirectory
|
||||
from .qommon.cron import CronJob
|
||||
from .qommon.form import Form, HtmlWidget, UploadedFile
|
||||
|
@ -84,8 +84,8 @@ class FormDef(StorableObject):
|
|||
data_sql_prefix = 'formdata'
|
||||
pickle_module_name = 'formdef'
|
||||
xml_root_node = 'formdef'
|
||||
verbose_name = N_('Form')
|
||||
verbose_name_plural = N_('Forms')
|
||||
verbose_name = _('Form')
|
||||
verbose_name_plural = _('Forms')
|
||||
|
||||
name = None
|
||||
description = None
|
||||
|
@ -916,7 +916,7 @@ class FormDef(StorableObject):
|
|||
try:
|
||||
field_o = fields.get_field_class_by_type(field.get('type'))()
|
||||
except KeyError:
|
||||
raise FormdefImportError(N_('Unknown field type'), details=field.findtext('type'))
|
||||
raise FormdefImportError(_('Unknown field type'), details=field.findtext('type'))
|
||||
field_o.init_with_json(field, include_id=True)
|
||||
if not field_o.id:
|
||||
# this assumes all fields will have id, or none of them
|
||||
|
@ -1100,7 +1100,7 @@ class FormDef(StorableObject):
|
|||
known_field_ids = set()
|
||||
for field in formdef.fields:
|
||||
if field.id in known_field_ids:
|
||||
raise FormdefImportRecoverableError(N_('Duplicated field identifiers'))
|
||||
raise FormdefImportRecoverableError(_('Duplicated field identifiers'))
|
||||
known_field_ids.add(field.id)
|
||||
|
||||
return formdef
|
||||
|
@ -1116,7 +1116,7 @@ class FormDef(StorableObject):
|
|||
assert charset == 'utf-8'
|
||||
formdef = cls()
|
||||
if tree.find('name') is None or not tree.find('name').text:
|
||||
raise FormdefImportError(N_('Missing name'))
|
||||
raise FormdefImportError(_('Missing name'))
|
||||
|
||||
# if the tree we get is actually a ElementTree for real, we get its
|
||||
# root element and go on happily.
|
||||
|
@ -1124,7 +1124,7 @@ class FormDef(StorableObject):
|
|||
tree = tree.getroot()
|
||||
|
||||
if tree.tag != cls.xml_root_node:
|
||||
raise FormdefImportError(N_('Unexpected root node'))
|
||||
raise FormdefImportError(_('Unexpected root node'))
|
||||
|
||||
if include_id and tree.attrib.get('id'):
|
||||
formdef.id = tree.attrib.get('id')
|
||||
|
@ -1145,7 +1145,7 @@ class FormDef(StorableObject):
|
|||
try:
|
||||
field_o = fields.get_field_class_by_type(field.findtext('type'))()
|
||||
except KeyError:
|
||||
raise FormdefImportError(N_('Unknown field type'), details=field.findtext('type'))
|
||||
raise FormdefImportError(_('Unknown field type'), details=field.findtext('type'))
|
||||
field_o.init_with_xml(field, charset, include_id=True)
|
||||
if fix_on_error or not field_o.id:
|
||||
# this assumes all fields will have id, or none of them
|
||||
|
@ -1299,7 +1299,7 @@ class FormDef(StorableObject):
|
|||
|
||||
if unknown_datasources:
|
||||
raise FormdefImportError(
|
||||
N_('Unknown datasources'), details=', '.join(sorted(unknown_datasources))
|
||||
_('Unknown datasources'), details=', '.join(sorted(unknown_datasources))
|
||||
)
|
||||
|
||||
return formdef
|
||||
|
@ -1340,7 +1340,7 @@ class FormDef(StorableObject):
|
|||
else:
|
||||
details.append('%s' % field.get_rst_view_value(value, indent=' '))
|
||||
details.append('')
|
||||
return '\n'.join(details)
|
||||
return '\n'.join([str(x) for x in details])
|
||||
|
||||
def get_submitter_email(self, formdata):
|
||||
users_cfg = get_cfg('users', {})
|
||||
|
@ -1434,7 +1434,7 @@ class FormDef(StorableObject):
|
|||
details.append(' %s' % formdata.get_status_label())
|
||||
if evo.comment:
|
||||
details.append('\n%s\n' % evo.comment)
|
||||
return '\n\n----\n\n' + '\n'.join(details)
|
||||
return '\n\n----\n\n' + '\n'.join([str(x) for x in details])
|
||||
|
||||
def is_of_concern_for_role_id(self, role_id):
|
||||
if not self.workflow_roles:
|
||||
|
@ -1618,11 +1618,11 @@ class FormDef(StorableObject):
|
|||
|
||||
EmailsDirectory.register(
|
||||
'new_user',
|
||||
N_('Notification of creation to user'),
|
||||
_('Notification of creation to user'),
|
||||
enabled=False,
|
||||
category=N_('Workflow'),
|
||||
default_subject=N_('New form ({{ form_name }})'),
|
||||
default_body=N_(
|
||||
category=_('Workflow'),
|
||||
default_subject=_('New form ({{ form_name }})'),
|
||||
default_body=_(
|
||||
'''\
|
||||
Hello,
|
||||
|
||||
|
@ -1642,10 +1642,10 @@ For reference, here are the details:
|
|||
|
||||
EmailsDirectory.register(
|
||||
'change_user',
|
||||
N_('Notification of change to user'),
|
||||
category=N_('Workflow'),
|
||||
default_subject=N_('Form status change ({{ form_name }})'),
|
||||
default_body=N_(
|
||||
_('Notification of change to user'),
|
||||
category=_('Workflow'),
|
||||
default_subject=_('Form status change ({{ form_name }})'),
|
||||
default_body=_(
|
||||
'''\
|
||||
Hello,
|
||||
|
||||
|
@ -1669,11 +1669,11 @@ You can consult it with this link: {{ form_url }}
|
|||
|
||||
EmailsDirectory.register(
|
||||
'new_receiver',
|
||||
N_('Notification of creation to receiver'),
|
||||
_('Notification of creation to receiver'),
|
||||
enabled=False,
|
||||
category=N_('Workflow'),
|
||||
default_subject=N_('New form ({{ form_name }})'),
|
||||
default_body=N_(
|
||||
category=_('Workflow'),
|
||||
default_subject=_('New form ({{ form_name }})'),
|
||||
default_body=_(
|
||||
'''\
|
||||
Hello,
|
||||
|
||||
|
@ -1692,10 +1692,10 @@ For reference, here are the details:
|
|||
|
||||
EmailsDirectory.register(
|
||||
'change_receiver',
|
||||
N_('Notification of change to receiver'),
|
||||
category=N_('Workflow'),
|
||||
default_subject=N_('Form status change ({{ form_name }})'),
|
||||
default_body=N_(
|
||||
_('Notification of change to receiver'),
|
||||
category=_('Workflow'),
|
||||
default_subject=_('Form status change ({{ form_name }})'),
|
||||
default_body=_(
|
||||
'''\
|
||||
Hello,
|
||||
|
||||
|
@ -1715,7 +1715,7 @@ Status of the form just changed (from "{{ form_previous_status }}" to "{{ form_s
|
|||
),
|
||||
)
|
||||
|
||||
Substitutions.register('form_name', category=N_('Form'), comment=N_('Form Name'))
|
||||
Substitutions.register('form_name', category=_('Form'), comment=_('Form Name'))
|
||||
|
||||
|
||||
def clean_drafts(publisher):
|
||||
|
|
|
@ -22,14 +22,14 @@ from wcs.formdef import FormDef
|
|||
from wcs.forms.common import FormTemplateMixin
|
||||
from wcs.wf.jump import jump_and_perform
|
||||
|
||||
from ..qommon import N_, errors, misc, template, tokens
|
||||
from ..qommon import _, errors, misc, template, tokens
|
||||
from ..qommon.form import Form
|
||||
|
||||
|
||||
class MissingOrExpiredToken(PublishError):
|
||||
status_code = 404
|
||||
title = N_('Error')
|
||||
description = N_('This action link has already been used or has expired.')
|
||||
title = _('Error')
|
||||
description = _('This action link has already been used or has expired.')
|
||||
|
||||
|
||||
class ActionsDirectory(Directory):
|
||||
|
|
|
@ -44,7 +44,7 @@ from wcs.roles import logged_users_role
|
|||
from wcs.variables import LazyFormDef
|
||||
from wcs.workflows import Workflow, WorkflowBackofficeFieldsFormDef, WorkflowStatusItem
|
||||
|
||||
from ..qommon import N_, _, emails, errors, get_cfg, get_logger, misc, template
|
||||
from ..qommon import _, emails, errors, get_cfg, get_logger, misc, template
|
||||
from ..qommon.admin.emails import EmailsDirectory
|
||||
from ..qommon.form import CheckboxWidget, EmailWidget, Form, HiddenErrorWidget, HtmlWidget, StringWidget
|
||||
from ..qommon.template import TemplateError
|
||||
|
@ -1962,14 +1962,14 @@ class PublicFormStatusPage(FormStatusPage):
|
|||
)
|
||||
|
||||
|
||||
TextsDirectory.register('welcome-logged', N_('Welcome text on home page for logged users'))
|
||||
TextsDirectory.register('welcome-logged', _('Welcome text on home page for logged users'))
|
||||
|
||||
TextsDirectory.register('welcome-unlogged', N_('Welcome text on home page for unlogged users'))
|
||||
TextsDirectory.register('welcome-unlogged', _('Welcome text on home page for unlogged users'))
|
||||
|
||||
TextsDirectory.register(
|
||||
'captcha-page',
|
||||
N_('Explanation text before the CAPTCHA'),
|
||||
default=N_(
|
||||
_('Explanation text before the CAPTCHA'),
|
||||
default=_(
|
||||
'''<h3>Verification</h3>
|
||||
|
||||
<p>
|
||||
|
@ -1981,44 +1981,44 @@ In order to submit the form you need to complete this simple question.
|
|||
|
||||
TextsDirectory.register(
|
||||
'form-recorded',
|
||||
N_('Message when a form has been recorded'),
|
||||
category=N_('Forms'),
|
||||
default=N_(
|
||||
'The form has been recorded on {{ form_receipt_datetime }} with the number {{ form_number }}.'
|
||||
),
|
||||
_('Message when a form has been recorded'),
|
||||
category=_('Forms'),
|
||||
default=_('The form has been recorded on {{ form_receipt_datetime }} with the number {{ form_number }}.'),
|
||||
)
|
||||
|
||||
TextsDirectory.register(
|
||||
'form-recorded-allow-one',
|
||||
N_('Message when a form has been recorded, and the form is set to only allow one per user'),
|
||||
category=N_('Forms'),
|
||||
default=N_('The form has been recorded on {{ form_receipt_datetime }}.'),
|
||||
_('Message when a form has been recorded, and the form is set to only allow one per user'),
|
||||
category=_('Forms'),
|
||||
default=_('The form has been recorded on {{ form_receipt_datetime }}.'),
|
||||
)
|
||||
|
||||
TextsDirectory.register(
|
||||
'check-before-submit',
|
||||
N_('Message when a form is displayed before validation'),
|
||||
category=N_('Forms'),
|
||||
default=N_('Check values then click submit.'),
|
||||
_('Message when a form is displayed before validation'),
|
||||
category=_('Forms'),
|
||||
default=_('Check values then click submit.'),
|
||||
)
|
||||
|
||||
TextsDirectory.register(
|
||||
'tracking-code-email-dialog',
|
||||
N_('Message in tracking code popup dialog'),
|
||||
category=N_('Forms'),
|
||||
default=N_('You can get a reminder of the tracking code by email.'),
|
||||
_('Message in tracking code popup dialog'),
|
||||
category=_('Forms'),
|
||||
default=_('You can get a reminder of the tracking code by email.'),
|
||||
)
|
||||
|
||||
TextsDirectory.register(
|
||||
'tracking-code-short-text', N_('Short text in the tracking code box'), category=N_('Forms')
|
||||
'tracking-code-short-text',
|
||||
_('Short text in the tracking code box'),
|
||||
category=_('Forms'),
|
||||
)
|
||||
|
||||
EmailsDirectory.register(
|
||||
'tracking-code-reminder',
|
||||
N_('Tracking Code'),
|
||||
category=N_('Miscellaneous'),
|
||||
default_subject=N_('Tracking Code reminder'),
|
||||
default_body=N_(
|
||||
_('Tracking Code'),
|
||||
category=_('Miscellaneous'),
|
||||
default_subject=_('Tracking Code reminder'),
|
||||
default_body=_(
|
||||
'''\
|
||||
Hello,
|
||||
|
||||
|
|
|
@ -59,7 +59,7 @@ class LoggedError:
|
|||
exception=None,
|
||||
):
|
||||
error = cls()
|
||||
error.summary = error_summary
|
||||
error.summary = str(error_summary)
|
||||
error.traceback = plain_error_msg
|
||||
error.expression = expression
|
||||
error.expression_type = expression_type
|
||||
|
|
|
@ -25,7 +25,7 @@ from quixote.html import TemplateIO, htmltext
|
|||
|
||||
from wcs.api_utils import get_secret_and_orig, sign_url
|
||||
|
||||
from .qommon import N_, get_logger
|
||||
from .qommon import _, get_logger
|
||||
from .qommon.misc import http_post_request, json_loads, urlopen
|
||||
|
||||
|
||||
|
@ -84,7 +84,7 @@ def push_document(user, filename, stream):
|
|||
|
||||
if get_response():
|
||||
get_response().add_after_job(
|
||||
N_('Sending file %(filename)s in portfolio of %(user_name)s')
|
||||
_('Sending file %(filename)s in portfolio of %(user_name)s')
|
||||
% {'filename': filename, 'user_name': user.display_name},
|
||||
afterjob,
|
||||
)
|
||||
|
|
|
@ -21,6 +21,7 @@ import threading
|
|||
import django.apps
|
||||
from django.conf import settings
|
||||
from django.utils.encoding import force_text
|
||||
from django.utils.functional import lazy
|
||||
from quixote import get_publisher
|
||||
|
||||
try:
|
||||
|
@ -37,7 +38,7 @@ force_str = force_text
|
|||
PICKLE_KWARGS = {'encoding': 'bytes', 'fix_imports': True}
|
||||
|
||||
|
||||
def _(message):
|
||||
def gettext(message):
|
||||
pub = get_publisher()
|
||||
if pub is None:
|
||||
return message
|
||||
|
@ -55,6 +56,8 @@ def N_(x):
|
|||
return x
|
||||
|
||||
|
||||
_ = lazy(gettext, str)
|
||||
|
||||
from . import publisher # noqa pylint: disable=wrong-import-position
|
||||
from .publisher import get_cfg # noqa pylint: disable=wrong-import-position
|
||||
from .publisher import get_logger # noqa pylint: disable=wrong-import-position
|
||||
|
|
|
@ -61,9 +61,7 @@ class EmailsDirectory(Directory):
|
|||
emails_cfg = get_cfg('emails', {})
|
||||
cfg_key = 'email-%s' % email_key
|
||||
default_subject = cls.emails_dict[email_key].get('default_subject')
|
||||
if default_subject:
|
||||
default_subject = _(default_subject)
|
||||
real_subject = emails_cfg.get(cfg_key + '_subject') or default_subject
|
||||
real_subject = emails_cfg.get(cfg_key + '_subject') or str(default_subject)
|
||||
return real_subject
|
||||
|
||||
@classmethod
|
||||
|
@ -71,9 +69,7 @@ class EmailsDirectory(Directory):
|
|||
emails_cfg = get_cfg('emails', {})
|
||||
cfg_key = 'email-%s' % email_key
|
||||
default_body = cls.emails_dict[email_key].get('default_body')
|
||||
if default_body:
|
||||
default_body = _(default_body)
|
||||
real_body = emails_cfg.get(cfg_key) or default_body
|
||||
real_body = emails_cfg.get(cfg_key) or str(default_body)
|
||||
return real_body
|
||||
|
||||
def options(self):
|
||||
|
@ -193,7 +189,7 @@ class EmailsDirectory(Directory):
|
|||
categories = {}
|
||||
for k, v in self.emails_dict.items():
|
||||
if v.get('category'):
|
||||
translated_category = _(v.get('category'))
|
||||
translated_category = v.get('category')
|
||||
else:
|
||||
translated_category = _('Miscellaneous')
|
||||
if translated_category not in categories:
|
||||
|
@ -205,11 +201,11 @@ class EmailsDirectory(Directory):
|
|||
r += htmltext('<h3>%s</h3>') % category_key
|
||||
|
||||
keys = categories.get(category_key)
|
||||
keys.sort(key=lambda x: _(self.emails_dict[x]['description']))
|
||||
keys.sort(key=lambda x: self.emails_dict[x]['description'])
|
||||
r += htmltext('<ul>')
|
||||
for email_key in keys:
|
||||
email_values = self.emails_dict[email_key]
|
||||
r += htmltext('<li><a href="%s">%s</a></li>') % (email_key, _(email_values['description']))
|
||||
r += htmltext('<li><a href="%s">%s</a></li>') % (email_key, email_values['description'])
|
||||
r += htmltext('</ul>')
|
||||
|
||||
r += htmltext('<p>')
|
||||
|
@ -221,8 +217,8 @@ class EmailsDirectory(Directory):
|
|||
emails_cfg = get_cfg('emails', {})
|
||||
cfg_key = 'email-%s' % email_key
|
||||
|
||||
default_subject = _(self.emails_dict[email_key].get('default_subject'))
|
||||
default_body = _(self.emails_dict[email_key].get('default_body'))
|
||||
default_subject = self.emails_dict[email_key].get('default_subject')
|
||||
default_body = self.emails_dict[email_key].get('default_body')
|
||||
|
||||
displayed_subject = emails_cfg.get(cfg_key + '_subject') or default_subject
|
||||
displayed_body = emails_cfg.get(cfg_key) or default_body
|
||||
|
@ -273,8 +269,8 @@ class EmailsDirectory(Directory):
|
|||
if check_template and not check_template(template):
|
||||
return False
|
||||
|
||||
default_subject = _(self.emails_dict[email_key].get('default_subject'))
|
||||
default_body = _(self.emails_dict[email_key].get('default_body'))
|
||||
default_subject = self.emails_dict[email_key].get('default_subject')
|
||||
default_body = self.emails_dict[email_key].get('default_body')
|
||||
|
||||
if template == default_body:
|
||||
template = None
|
||||
|
@ -298,8 +294,8 @@ class EmailsDirectory(Directory):
|
|||
|
||||
return self.email(
|
||||
component,
|
||||
_(self.emails_dict[component]['description']),
|
||||
_(self.emails_dict[component]['hint']),
|
||||
self.emails_dict[component]['description'],
|
||||
self.emails_dict[component]['hint'],
|
||||
self.emails_dict[component]['enabled'],
|
||||
)
|
||||
|
||||
|
|
|
@ -19,7 +19,7 @@ import re
|
|||
from quixote import get_publisher, get_request
|
||||
from quixote.html import TemplateIO, htmltext
|
||||
|
||||
from .. import N_, _
|
||||
from .. import _
|
||||
from ..backoffice.menu import html_top
|
||||
|
||||
|
||||
|
@ -113,16 +113,16 @@ def get_vc_version():
|
|||
|
||||
def command_icon(url, type, label=None, popup=False):
|
||||
labels = {
|
||||
'edit': N_('Edit'),
|
||||
'remove': N_('Remove'),
|
||||
'duplicate': N_('Duplicate'),
|
||||
'view': N_('View'),
|
||||
'edit': _('Edit'),
|
||||
'remove': _('Remove'),
|
||||
'duplicate': _('Duplicate'),
|
||||
'view': _('View'),
|
||||
}
|
||||
if label:
|
||||
klass = 'button'
|
||||
else:
|
||||
klass = ''
|
||||
label = _(labels[type])
|
||||
label = labels[type]
|
||||
root_url = get_publisher().get_application_static_files_root_url()
|
||||
rel = ''
|
||||
if popup:
|
||||
|
|
|
@ -41,7 +41,7 @@ class TextsDirectory(Directory):
|
|||
if os.path.exists(filepath):
|
||||
return htmltext(open(filepath).read())
|
||||
return ''
|
||||
text = _(default)
|
||||
text = str(default) # make sure translation is applied
|
||||
|
||||
if not text.startswith('<'):
|
||||
text = '<p>%s</p>' % text
|
||||
|
@ -79,7 +79,7 @@ class TextsDirectory(Directory):
|
|||
categories = {}
|
||||
for k, v in self.texts_dict.items():
|
||||
if v.get('category'):
|
||||
translated_category = _(v.get('category'))
|
||||
translated_category = v.get('category')
|
||||
else:
|
||||
translated_category = _('Miscellaneous')
|
||||
if translated_category not in categories:
|
||||
|
@ -91,11 +91,11 @@ class TextsDirectory(Directory):
|
|||
r += htmltext('<h3>%s</h3>') % category_key
|
||||
|
||||
keys = categories.get(category_key)
|
||||
keys.sort(key=lambda x: _(self.texts_dict[x]['description']))
|
||||
keys.sort(key=lambda x: self.texts_dict[x]['description'])
|
||||
r += htmltext('<ul>')
|
||||
for text_key in keys:
|
||||
text_values = self.texts_dict[text_key]
|
||||
r += htmltext('<li><a href="%s">%s</a></li>') % (text_key, _(text_values['description']))
|
||||
r += htmltext('<li><a href="%s">%s</a></li>') % (text_key, text_values['description'])
|
||||
r += htmltext('</ul>')
|
||||
|
||||
r += htmltext('<p>')
|
||||
|
@ -108,9 +108,7 @@ class TextsDirectory(Directory):
|
|||
cfg_key = 'text-%s' % text_key
|
||||
|
||||
default_text = self.texts_dict.get(text_key, {}).get('default')
|
||||
if default_text:
|
||||
default_text = _(default_text)
|
||||
else:
|
||||
if not default_text:
|
||||
filepath = os.path.join(get_publisher().DATA_DIR, 'texts', '%s.html' % text_key)
|
||||
if os.path.exists(str(filepath)):
|
||||
default_text = open(str(filepath)).read()
|
||||
|
@ -176,7 +174,7 @@ class TextsDirectory(Directory):
|
|||
return None
|
||||
|
||||
hint = self.texts_dict[component]['hint']
|
||||
return self.text(component, _(self.texts_dict[component]['description']), hint and _(hint))
|
||||
return self.text(component, self.texts_dict[component]['description'], hint)
|
||||
|
||||
def _q_traverse(self, path):
|
||||
get_response().breadcrumb.append(('texts/', _('Texts')))
|
||||
|
|
|
@ -22,7 +22,7 @@ import uuid
|
|||
from quixote import get_publisher, get_response
|
||||
from quixote.directory import Directory
|
||||
|
||||
from . import N_, _, errors
|
||||
from . import N_, _, errors, force_text
|
||||
from .storage import StorableObject
|
||||
|
||||
|
||||
|
@ -36,8 +36,8 @@ class AfterJobStatusDirectory(Directory):
|
|||
response = get_response()
|
||||
response.set_content_type('text/plain')
|
||||
if not job.completion_status:
|
||||
return job.status + '|' + _(job.status)
|
||||
return job.status + '|' + _(job.status) + ' ' + job.completion_status
|
||||
return job.status + '|' + str(_(job.status))
|
||||
return job.status + '|' + str(_(job.status)) + ' ' + job.completion_status
|
||||
|
||||
|
||||
class AfterJob(StorableObject):
|
||||
|
@ -55,12 +55,24 @@ class AfterJob(StorableObject):
|
|||
def __init__(self, label=None, cmd=None, **kwargs):
|
||||
super().__init__(id=str(uuid.uuid4()))
|
||||
if label:
|
||||
self.label = label
|
||||
self.label = force_text(label)
|
||||
self.done_action_label_arg = kwargs.pop('done_action_label', None)
|
||||
self.done_action_url_arg = kwargs.pop('done_action_url', None)
|
||||
self.done_button_attributes_arg = kwargs.pop('done_button_attributes', None)
|
||||
self.creation_time = time.time()
|
||||
self.job_cmd = cmd
|
||||
self.status = N_('registered')
|
||||
self.kwargs = kwargs
|
||||
|
||||
def done_action_label(self):
|
||||
return self.done_action_label_arg
|
||||
|
||||
def done_action_url(self):
|
||||
return self.done_action_url_arg % {'job_id': self.id}
|
||||
|
||||
def done_action_attributes(self):
|
||||
return self.done_button_attributes_arg
|
||||
|
||||
def run(self, spool=False):
|
||||
if self.completion_time:
|
||||
return
|
||||
|
@ -94,6 +106,8 @@ class AfterJob(StorableObject):
|
|||
self.store()
|
||||
|
||||
def __getstate__(self):
|
||||
if getattr(self, 'done_action_label_arg', None):
|
||||
self.done_action_label_arg = force_text(self.done_action_label_arg)
|
||||
if not isinstance(self.job_cmd, str):
|
||||
obj_dict = self.__dict__.copy()
|
||||
obj_dict['job_cmd'] = None
|
||||
|
|
|
@ -21,7 +21,7 @@ from quixote import get_publisher
|
|||
from quixote.errors import AccessError, TraversalError
|
||||
from quixote.html import TemplateIO, htmltext
|
||||
|
||||
from . import N_, template
|
||||
from . import _, template
|
||||
|
||||
|
||||
class AccessForbiddenError(AccessError):
|
||||
|
@ -59,7 +59,7 @@ class AccessUnauthorizedError(AccessForbiddenError):
|
|||
return AccessForbiddenError.render(self)
|
||||
|
||||
if self.public_msg:
|
||||
session.message = ('error', self.public_msg)
|
||||
session.message = ('error', str(self.public_msg))
|
||||
login_url = get_publisher().get_root_url() + 'login/'
|
||||
login_url += '?' + urllib.parse.urlencode({'next': request.get_frontoffice_url()})
|
||||
return quixote.redirect(login_url)
|
||||
|
@ -132,8 +132,8 @@ class SMSError(Exception):
|
|||
pass
|
||||
|
||||
|
||||
TraversalError.title = N_('Page not found')
|
||||
TraversalError.description = N_(
|
||||
TraversalError.title = _('Page not found')
|
||||
TraversalError.description = _(
|
||||
"The requested link does not exist on this site. If "
|
||||
"you arrived here by following a link from an external "
|
||||
"page, please inform that page's maintainer."
|
||||
|
@ -141,9 +141,7 @@ TraversalError.description = N_(
|
|||
|
||||
|
||||
def format_publish_error(exc):
|
||||
from . import _
|
||||
|
||||
if getattr(exc, 'public_msg', None):
|
||||
return template.error_page(exc.format(), _(exc.title))
|
||||
return template.error_page(exc.format(), exc.title)
|
||||
else:
|
||||
return template.error_page(_(exc.description), _(exc.title))
|
||||
return template.error_page(exc.description, exc.title)
|
||||
|
|
|
@ -69,7 +69,7 @@ from quixote.html import TemplateIO, htmlescape, htmltag, htmltext, stringify
|
|||
from wcs.conditions import Condition, ValidationError
|
||||
|
||||
from ..portfolio import has_portfolio
|
||||
from . import N_, _, force_str, misc, ngettext
|
||||
from . import _, force_str, misc, ngettext
|
||||
from .humantime import humanduration2seconds, seconds2humanduration, timewords
|
||||
from .misc import HAS_PDFTOPPM, json_loads, strftime
|
||||
from .publisher import get_cfg
|
||||
|
@ -79,17 +79,10 @@ from .template_utils import render_block_to_string
|
|||
from .upload_storage import PicklableUpload # noqa pylint: disable=unused-import
|
||||
from .upload_storage import UploadStorageError
|
||||
|
||||
Widget.REQUIRED_ERROR = N_('required field')
|
||||
Widget.REQUIRED_ERROR = _('required field')
|
||||
get_error_orig = Widget.get_error
|
||||
|
||||
|
||||
def get_i18n_error(self, request=None):
|
||||
error = get_error_orig(self, request)
|
||||
if error == Widget.REQUIRED_ERROR:
|
||||
return _(error)
|
||||
return error
|
||||
|
||||
|
||||
def is_prefilled(self):
|
||||
if hasattr(self, 'prefilled'):
|
||||
return self.prefilled
|
||||
|
@ -99,6 +92,7 @@ def is_prefilled(self):
|
|||
|
||||
def render_title(self, title):
|
||||
if title:
|
||||
title = str(title) # apply translation if required
|
||||
if self.required:
|
||||
title += htmltext('<span title="%s" class="required">*</span>') % _('This field is required.')
|
||||
attrs = {
|
||||
|
@ -178,7 +172,6 @@ def render_widget_content(self):
|
|||
return htmltext(force_str(render_block_to_string(template_names, 'widget-content', context)))
|
||||
|
||||
|
||||
Widget.get_error = get_i18n_error
|
||||
Widget.render = render
|
||||
Widget.cleanup = None
|
||||
Widget.render_error = render_error
|
||||
|
@ -211,7 +204,9 @@ class SubmitWidget(quixote.form.widget.SubmitWidget):
|
|||
self.attrs['formnovalidate'] = 'formnovalidate'
|
||||
value = htmlescape(self.label) if self.label else None
|
||||
return (
|
||||
htmltag('button', name=self.name, value=value, **self.attrs) + self.label + htmltext('</button>')
|
||||
htmltag('button', name=self.name, value=value, **self.attrs)
|
||||
+ str(self.label)
|
||||
+ htmltext('</button>')
|
||||
)
|
||||
|
||||
|
||||
|
@ -254,13 +249,13 @@ Widget.transfer_form_value = transfer_form_value
|
|||
|
||||
|
||||
class Form(QuixoteForm):
|
||||
TOKEN_NOTICE = N_(
|
||||
TOKEN_NOTICE = _(
|
||||
"The form you have submitted is invalid. Most "
|
||||
"likely it has been successfully submitted once "
|
||||
"already. Please review the form data "
|
||||
"and submit the form again."
|
||||
)
|
||||
ERROR_NOTICE = N_("There were errors processing your form. See below for details.")
|
||||
ERROR_NOTICE = _("There were errors processing your form. See below for details.")
|
||||
|
||||
info = None
|
||||
captcha = None
|
||||
|
@ -295,6 +290,9 @@ class Form(QuixoteForm):
|
|||
widget.advanced = advanced
|
||||
return widget
|
||||
|
||||
def set_error(self, name, error):
|
||||
super().set_error(name, force_text(error))
|
||||
|
||||
def remove(self, name):
|
||||
widget = self._names.get(name)
|
||||
if widget:
|
||||
|
@ -344,13 +342,13 @@ class Form(QuixoteForm):
|
|||
return r.getvalue()
|
||||
|
||||
def _render_info_notice(self):
|
||||
return htmltext('<div class="infonotice">%s</div>' % _(self.info))
|
||||
return htmltext('<div class="infonotice">%s</div>' % self.info)
|
||||
|
||||
def _render_error_notice(self):
|
||||
errors = []
|
||||
classnames = ['errornotice']
|
||||
if self.has_errors():
|
||||
errors.append(_(QuixoteForm._render_error_notice(self)))
|
||||
errors.append(QuixoteForm._render_error_notice(self))
|
||||
if self.global_error_messages:
|
||||
errors.extend(self.global_error_messages)
|
||||
classnames.append('global-errors')
|
||||
|
@ -531,7 +529,7 @@ class DurationWidget(StringWidget):
|
|||
if value:
|
||||
value = seconds2humanduration(int(value))
|
||||
if 'hint' in kwargs:
|
||||
kwargs['hint'] += htmltext('<br>')
|
||||
kwargs['hint'] = str(kwargs['hint']) + htmltext('<br>')
|
||||
else:
|
||||
kwargs['hint'] = ''
|
||||
kwargs['hint'] += htmltext(_('Usable units of time: %s.')) % ', '.join(timewords())
|
||||
|
@ -629,7 +627,7 @@ class CheckboxWidget(QuixoteCheckboxWidget):
|
|||
# custom style.
|
||||
return (
|
||||
htmltext('<label %s>%s<span>' % (data_attrs, checkbox))
|
||||
+ inline_title
|
||||
+ str(inline_title)
|
||||
+ htmltext('</span></label>')
|
||||
)
|
||||
return checkbox
|
||||
|
@ -1040,64 +1038,75 @@ class ValidationWidget(CompositeWidget):
|
|||
(
|
||||
'digits',
|
||||
{
|
||||
'title': N_('Digits'),
|
||||
'title': _('Digits'),
|
||||
'regex': r'\d+',
|
||||
'error_message': N_('Only digits are allowed'),
|
||||
'error_message': _('Only digits are allowed'),
|
||||
'html_inputmode': 'numeric',
|
||||
},
|
||||
),
|
||||
(
|
||||
'phone',
|
||||
{
|
||||
'title': N_('Phone Number'),
|
||||
'title': _('Phone Number'),
|
||||
'regex': r'\+?[-\(\)\d\.\s/]+',
|
||||
'error_message': N_('Invalid phone number'),
|
||||
'error_message': _('Invalid phone number'),
|
||||
'html_input_type': 'tel',
|
||||
},
|
||||
),
|
||||
(
|
||||
'phone-fr',
|
||||
{
|
||||
'title': N_('Phone Number (France)'),
|
||||
'title': _('Phone Number (France)'),
|
||||
'function': 'validate_phone_fr',
|
||||
'error_message': N_('Invalid phone number'),
|
||||
'error_message': _('Invalid phone number'),
|
||||
'html_input_type': 'tel',
|
||||
},
|
||||
),
|
||||
(
|
||||
'zipcode-fr',
|
||||
{
|
||||
'title': N_('Zip Code (France)'),
|
||||
'title': _('Zip Code (France)'),
|
||||
'regex': r'\d{5}',
|
||||
'error_message': N_('Invalid zip code'),
|
||||
'error_message': _('Invalid zip code'),
|
||||
'html_inputmode': 'numeric',
|
||||
},
|
||||
),
|
||||
(
|
||||
'siren-fr',
|
||||
{
|
||||
'title': N_('SIREN Code (France)'),
|
||||
'title': _('SIREN Code (France)'),
|
||||
'function': 'validate_siren',
|
||||
'error_message': N_('Invalid SIREN code'),
|
||||
'error_message': _('Invalid SIREN code'),
|
||||
'html_inputmode': 'numeric',
|
||||
},
|
||||
),
|
||||
(
|
||||
'siret-fr',
|
||||
{
|
||||
'title': N_('SIRET Code (France)'),
|
||||
'title': _('SIRET Code (France)'),
|
||||
'function': 'validate_siret',
|
||||
'error_message': N_('Invalid SIRET code'),
|
||||
'error_message': _('Invalid SIRET code'),
|
||||
'html_inputmode': 'numeric',
|
||||
},
|
||||
),
|
||||
(
|
||||
'nir-fr',
|
||||
{'title': N_('NIR (France)'), 'error_message': N_('Invalid NIR'), 'function': 'validate_nir'},
|
||||
{
|
||||
'title': _('NIR (France)'),
|
||||
'error_message': _('Invalid NIR'),
|
||||
'function': 'validate_nir',
|
||||
},
|
||||
),
|
||||
('iban', {'title': N_('IBAN'), 'function': 'validate_iban', 'error_message': N_('Invalid IBAN')}),
|
||||
('regex', {'title': N_('Regular Expression')}),
|
||||
('django', {'title': N_('Django Condition')}),
|
||||
(
|
||||
'iban',
|
||||
{
|
||||
'title': _('IBAN'),
|
||||
'function': 'validate_iban',
|
||||
'error_message': _('Invalid IBAN'),
|
||||
},
|
||||
),
|
||||
('regex', {'title': _('Regular Expression')}),
|
||||
('django', {'title': _('Django Condition')}),
|
||||
]
|
||||
)
|
||||
|
||||
|
@ -1106,7 +1115,7 @@ class ValidationWidget(CompositeWidget):
|
|||
if not value:
|
||||
value = {}
|
||||
|
||||
options = [(None, _('None'))] + [(x, _(y['title'])) for x, y in self.validation_methods.items()]
|
||||
options = [(None, _('None'))] + [(x, y['title']) for x, y in self.validation_methods.items()]
|
||||
|
||||
self.add(
|
||||
SingleSelectWidget,
|
||||
|
@ -1150,7 +1159,7 @@ class ValidationWidget(CompositeWidget):
|
|||
attrs={
|
||||
'data-dynamic-display-child-of': 'validation$type',
|
||||
'data-dynamic-display-value-in': '|'.join(
|
||||
[validation_labels.get('regex'), validation_labels.get('django')]
|
||||
[str(validation_labels.get('regex')), str(validation_labels.get('django'))]
|
||||
),
|
||||
},
|
||||
)
|
||||
|
@ -1212,7 +1221,7 @@ class ValidationWidget(CompositeWidget):
|
|||
return validation.get('error_message')
|
||||
validation_method = cls.validation_methods.get(validation['type'])
|
||||
if validation_method and 'error_message' in validation_method:
|
||||
return _(validation_method['error_message'])
|
||||
return validation_method['error_message']
|
||||
|
||||
@classmethod
|
||||
def get_validation_pattern(cls, validation):
|
||||
|
@ -1600,9 +1609,9 @@ class CaptchaWidget(CompositeWidget):
|
|||
# don't get twice the same number
|
||||
b = random.randint(2, 9)
|
||||
if mode == 'arithmetic-simple':
|
||||
operator = random.choice([N_('plus'), N_('minus')])
|
||||
operator = random.choice([_('plus'), _('minus')])
|
||||
else:
|
||||
operator = random.choice([N_('times'), N_('plus'), N_('minus')])
|
||||
operator = random.choice([_('times'), _('plus'), _('minus')])
|
||||
if operator == 'times':
|
||||
answer = a * b
|
||||
elif operator == 'plus':
|
||||
|
@ -1614,7 +1623,7 @@ class CaptchaWidget(CompositeWidget):
|
|||
self.question = _('What is the result of %(a)d %(op)s %(b)d?') % {
|
||||
'a': a,
|
||||
'b': b,
|
||||
'op': _(operator),
|
||||
'op': operator,
|
||||
}
|
||||
self.hint = kwargs.get('hint')
|
||||
if self.hint is None:
|
||||
|
@ -1656,7 +1665,7 @@ class WidgetList(quixote.form.widget.WidgetList):
|
|||
):
|
||||
|
||||
if add_element_label == 'Add row':
|
||||
add_element_label = _('Add row')
|
||||
add_element_label = str(_('Add row'))
|
||||
|
||||
CompositeWidget.__init__(self, name, value=value, **kwargs)
|
||||
self.element_type = element_type
|
||||
|
@ -1769,7 +1778,7 @@ class WidgetDict(quixote.form.widget.WidgetDict):
|
|||
):
|
||||
|
||||
if add_element_label == 'Add row':
|
||||
add_element_label = _('Add row')
|
||||
add_element_label = str(_('Add row'))
|
||||
|
||||
quixote.form.widget.WidgetDict.__init__(
|
||||
self,
|
||||
|
|
|
@ -185,13 +185,13 @@ class HTTPResponse(quixote.http_response.HTTPResponse):
|
|||
]
|
||||
)
|
||||
|
||||
def add_after_job(self, label_or_instance, cmd=None, fire_and_forget=False):
|
||||
def add_after_job(self, label_or_instance, cmd=None, fire_and_forget=False, **kwargs):
|
||||
if not self.after_jobs:
|
||||
self.after_jobs = []
|
||||
if isinstance(label_or_instance, AfterJob):
|
||||
job = label_or_instance
|
||||
else:
|
||||
job = AfterJob(label=label_or_instance, cmd=cmd)
|
||||
job = AfterJob(label=label_or_instance, cmd=cmd, **kwargs)
|
||||
if fire_and_forget:
|
||||
job.id = None
|
||||
self.after_jobs.append(job)
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
|
||||
import re
|
||||
|
||||
from . import N_, _, ngettext
|
||||
from . import _, ngettext
|
||||
|
||||
_minute = 60
|
||||
_hour = 60 * 60
|
||||
|
@ -34,12 +34,12 @@ def list2human(stringlist):
|
|||
|
||||
|
||||
_humandurations = (
|
||||
((N_("day"), N_("days")), _day),
|
||||
((N_("hour"), N_("hours")), _hour),
|
||||
((N_("month"), N_("months")), _month),
|
||||
((N_("year"), N_("years")), _year),
|
||||
((N_("minute"), N_("minutes")), _minute),
|
||||
((N_("second"), N_("seconds")), 1),
|
||||
((_("day"), _("days")), _day),
|
||||
((_("hour"), _("hours")), _hour),
|
||||
((_("month"), _("months")), _month),
|
||||
((_("year"), _("years")), _year),
|
||||
((_("minute"), _("minutes")), _minute),
|
||||
((_("second"), _("seconds")), 1),
|
||||
)
|
||||
|
||||
|
||||
|
@ -48,7 +48,7 @@ def timewords():
|
|||
result = []
|
||||
for words, dummy in _humandurations:
|
||||
for word in words:
|
||||
result.append(_(word))
|
||||
result.append(str(word)) # str() to force translation
|
||||
return result
|
||||
|
||||
|
||||
|
@ -58,7 +58,6 @@ def humanduration2seconds(humanduration):
|
|||
seconds = 0
|
||||
for words, quantity in _humandurations:
|
||||
for word in words:
|
||||
word = _(word)
|
||||
m = re.search(r"(\d+)\s*\b%s\b" % word, humanduration)
|
||||
if m:
|
||||
seconds = seconds + int(m.group(1)) * quantity
|
||||
|
|
|
@ -29,7 +29,7 @@ from quixote.html import TemplateIO, htmltext
|
|||
from wcs.formdata import flatten_dict
|
||||
from wcs.workflows import WorkflowStatusItem
|
||||
|
||||
from .. import N_, _, get_cfg, get_logger, template
|
||||
from .. import _, get_cfg, get_logger, template
|
||||
from ..backoffice.menu import html_top
|
||||
from ..form import (
|
||||
CompositeWidget,
|
||||
|
@ -42,7 +42,7 @@ from ..form import (
|
|||
from ..misc import http_get_page, http_post_request, json_loads
|
||||
from .base import AuthMethod
|
||||
|
||||
ADMIN_TITLE = N_('FranceConnect')
|
||||
ADMIN_TITLE = _('FranceConnect')
|
||||
|
||||
# XXX: make an OIDC auth method that FranceConnect would inherit from
|
||||
|
||||
|
@ -122,13 +122,13 @@ class MethodDirectory(Directory):
|
|||
|
||||
class MethodAdminDirectory(Directory):
|
||||
title = ADMIN_TITLE
|
||||
label = N_('Configure FranceConnect identification method')
|
||||
label = _('Configure FranceConnect identification method')
|
||||
|
||||
_q_exports = ['']
|
||||
|
||||
PLATFORMS = [
|
||||
{
|
||||
'name': N_('Development citizens'),
|
||||
'name': _('Development citizens'),
|
||||
'slug': 'dev-particulier',
|
||||
'authorization_url': 'https://fcp.integ01.dev-franceconnect.fr/api/v1/authorize',
|
||||
'token_url': 'https://fcp.integ01.dev-franceconnect.fr/api/v1/token',
|
||||
|
@ -136,7 +136,7 @@ class MethodAdminDirectory(Directory):
|
|||
'logout_url': 'https://fcp.integ01.dev-franceconnect.fr/api/v1/logout',
|
||||
},
|
||||
{
|
||||
'name': N_('Development enterprise'),
|
||||
'name': _('Development enterprise'),
|
||||
'slug': 'dev-entreprise',
|
||||
'authorization_url': 'https://fce.integ01.dev-franceconnect.fr/api/v1/authorize',
|
||||
'token_url': 'https://fce.integ01.dev-franceconnect.fr/api/v1/token',
|
||||
|
@ -144,7 +144,7 @@ class MethodAdminDirectory(Directory):
|
|||
'logout_url': 'https://fce.integ01.dev-franceconnect.fr/api/v1/logout',
|
||||
},
|
||||
{
|
||||
'name': N_('Production citizens'),
|
||||
'name': _('Production citizens'),
|
||||
'slug': 'prod-particulier',
|
||||
'authorization_url': 'https://app.franceconnect.gouv.fr/api/v1/authorize',
|
||||
'token_url': 'https://app.franceconnect.gouv.fr/api/v1/token',
|
||||
|
@ -154,22 +154,22 @@ class MethodAdminDirectory(Directory):
|
|||
]
|
||||
|
||||
CONFIG = [
|
||||
('client_id', N_('Client ID')),
|
||||
('client_secret', N_('Client secret')),
|
||||
('platform', N_('Platform')),
|
||||
('scopes', N_('Scopes')),
|
||||
('user_field_mappings', N_('User field mappings')),
|
||||
('client_id', _('Client ID')),
|
||||
('client_secret', _('Client secret')),
|
||||
('platform', _('Platform')),
|
||||
('scopes', _('Scopes')),
|
||||
('user_field_mappings', _('User field mappings')),
|
||||
]
|
||||
|
||||
KNOWN_ATTRIBUTES = [
|
||||
('given_name', N_('first names separated by spaces')),
|
||||
('family_name', N_('birth\'s last name')),
|
||||
('birthdate', N_('birthdate formatted as YYYY-MM-DD')),
|
||||
('gender', N_('gender \'male\' for men, and \'female\' for women')),
|
||||
('birthplace', N_('INSEE code of the place of birth')),
|
||||
('birthcountry', N_('INSEE code of the country of birth')),
|
||||
('email', N_('email')),
|
||||
('siret', N_('SIRET or SIREN number of the enterprise')),
|
||||
('given_name', _('first names separated by spaces')),
|
||||
('family_name', _('birth\'s last name')),
|
||||
('birthdate', _('birthdate formatted as YYYY-MM-DD')),
|
||||
('gender', _('gender \'male\' for men, and \'female\' for women')),
|
||||
('birthplace', _('INSEE code of the place of birth')),
|
||||
('birthcountry', _('INSEE code of the country of birth')),
|
||||
('email', _('email')),
|
||||
('siret', _('SIRET or SIREN number of the enterprise')),
|
||||
# Note: FranceConnect website also refer to adress and phones attributes
|
||||
# but we don't know what must be expected of their value.
|
||||
]
|
||||
|
@ -189,7 +189,7 @@ class MethodAdminDirectory(Directory):
|
|||
widget = UserFieldMappingTableWidget
|
||||
elif key == 'platform':
|
||||
widget = SingleSelectWidget
|
||||
kwargs['options'] = [(platform['slug'], _(platform['name'])) for platform in cls.PLATFORMS]
|
||||
kwargs['options'] = [(platform['slug'], platform['name']) for platform in cls.PLATFORMS]
|
||||
elif key == 'scopes':
|
||||
default = 'identite_pivot address email phones'
|
||||
hint = _(
|
||||
|
@ -202,7 +202,7 @@ class MethodAdminDirectory(Directory):
|
|||
form.add(
|
||||
widget,
|
||||
key,
|
||||
title=_(title),
|
||||
title=title,
|
||||
hint=hint,
|
||||
required=True,
|
||||
value=instance.get(key, default),
|
||||
|
@ -233,7 +233,7 @@ class MethodAdminDirectory(Directory):
|
|||
if 'submit' in get_request().form and form.is_submitted() and not form.has_errors():
|
||||
return self.submit(form)
|
||||
|
||||
html_top('settings', title=_(self.title))
|
||||
html_top('settings', title=self.title)
|
||||
r = TemplateIO(html=True)
|
||||
r += htmltext('<h2>%s</h2>') % self.title
|
||||
fc_callback = pub.get_frontoffice_url() + '/ident/fc/callback'
|
||||
|
@ -268,7 +268,7 @@ class MethodAdminDirectory(Directory):
|
|||
'<table class="franceconnect-attrs"><thead>' '<tr><th>%s</th><th>%s</th></tr></thead><tbody>'
|
||||
) % (_('Attribute'), _('Description'))
|
||||
for attribute, description in self.KNOWN_ATTRIBUTES:
|
||||
r += htmltext('<tr><td><code>%s</code></td><td>%s</td></tr>') % (attribute, _(description))
|
||||
r += htmltext('<tr><td><code>%s</code></td><td>%s</td></tr>') % (attribute, description)
|
||||
r += htmltext('</tbody></table></div>')
|
||||
|
||||
return r.getvalue()
|
||||
|
@ -444,7 +444,7 @@ class FCAuthMethod(AuthMethod):
|
|||
user.set_attributes_from_formdata(user.form_data)
|
||||
|
||||
AUTHORIZATION_REQUEST_ERRORS = {
|
||||
'access_denied': N_('user did not authorize login'),
|
||||
'access_denied': _('user did not authorize login'),
|
||||
}
|
||||
|
||||
def callback(self):
|
||||
|
@ -465,7 +465,7 @@ class FCAuthMethod(AuthMethod):
|
|||
if error:
|
||||
# we log only errors whose user is not responsible
|
||||
msg = self.AUTHORIZATION_REQUEST_ERRORS.get(error)
|
||||
logger.error(_('FranceConnect authentication failed: %s'), _(msg) if msg else error)
|
||||
logger.error(_('FranceConnect authentication failed: %s'), msg if msg else error)
|
||||
return redirect(next_url)
|
||||
access_token, id_token = self.get_access_token(request.form['code'])
|
||||
if not access_token:
|
||||
|
|
|
@ -29,7 +29,7 @@ from quixote import get_publisher, get_request, get_response, get_session, redir
|
|||
from quixote.directory import Directory
|
||||
from quixote.html import TemplateIO, htmltext
|
||||
|
||||
from .. import N_, _, errors, get_cfg, get_logger, misc, saml2utils, template, x509utils
|
||||
from .. import _, errors, get_cfg, get_logger, misc, saml2utils, template, x509utils
|
||||
from ..admin.menu import command_icon
|
||||
from ..backoffice.menu import html_top
|
||||
from ..form import (
|
||||
|
@ -47,7 +47,7 @@ from ..storage import atomic_write
|
|||
from ..tokens import Token
|
||||
from .base import AuthMethod
|
||||
|
||||
ADMIN_TITLE = N_('SAML2')
|
||||
ADMIN_TITLE = _('SAML2')
|
||||
|
||||
|
||||
def is_idp_managing_user_attributes():
|
||||
|
@ -214,16 +214,16 @@ class MethodDirectory(Directory):
|
|||
|
||||
|
||||
class AdminIDPDir(Directory):
|
||||
title = N_('Identity Providers')
|
||||
title = _('Identity Providers')
|
||||
|
||||
_q_exports = ['', 'new', 'new_remote']
|
||||
|
||||
def _q_traverse(self, path):
|
||||
get_response().breadcrumb.append(('idp/', _(self.title)))
|
||||
get_response().breadcrumb.append(('idp/', self.title))
|
||||
return Directory._q_traverse(self, path)
|
||||
|
||||
def _q_index(self):
|
||||
html_top('settings', title=_(self.title))
|
||||
html_top('settings', title=self.title)
|
||||
r = TemplateIO(html=True)
|
||||
r += htmltext('<h2>%s</h2>') % _('Identity Providers')
|
||||
r += htmltext('<ul id="nav-idp-admin">\n')
|
||||
|
@ -790,18 +790,18 @@ class AdminIDPUI(Directory):
|
|||
|
||||
class MethodAdminDirectory(Directory):
|
||||
title = ADMIN_TITLE
|
||||
label = N_('Configure SAML identification method')
|
||||
label = _('Configure SAML identification method')
|
||||
|
||||
_q_exports = ['', 'sp', 'idp', 'identities']
|
||||
|
||||
idp = AdminIDPDir()
|
||||
|
||||
def _q_traverse(self, path):
|
||||
get_response().breadcrumb.append(('idp/', _(self.title)))
|
||||
get_response().breadcrumb.append(('idp/', self.title))
|
||||
return Directory._q_traverse(self, path)
|
||||
|
||||
def _q_index(self):
|
||||
html_top('settings', title=_(self.title))
|
||||
html_top('settings', title=self.title)
|
||||
r = TemplateIO(html=True)
|
||||
r += htmltext('<h2>SAML 2.0</h2>')
|
||||
r += htmltext('<dl> <dt><a href="sp">%s</a></dt> <dd>%s</dd>') % (
|
||||
|
@ -1185,7 +1185,7 @@ class MethodUserDirectory(Directory):
|
|||
|
||||
class IdPAuthMethod(AuthMethod):
|
||||
key = 'idp'
|
||||
description = N_('SAML identity provider')
|
||||
description = _('SAML identity provider')
|
||||
method_directory = MethodDirectory
|
||||
method_admin_directory = MethodAdminDirectory
|
||||
method_user_directory = MethodUserDirectory
|
||||
|
|
|
@ -23,7 +23,7 @@ from quixote.html import TemplateIO, htmltext
|
|||
|
||||
from wcs.qommon.admin.texts import TextsDirectory
|
||||
|
||||
from .. import N_, _, emails, errors, get_cfg, get_logger, misc, ngettext
|
||||
from .. import _, emails, errors, get_cfg, get_logger, misc, ngettext
|
||||
from .. import storage as st
|
||||
from .. import template, tokens
|
||||
from ..admin.emails import EmailsDirectory
|
||||
|
@ -680,21 +680,21 @@ class MethodDirectory(Directory):
|
|||
emails.custom_template_email('password-subscription-notification', data, user.email)
|
||||
|
||||
|
||||
ADMIN_TITLE = N_('Username / Password')
|
||||
ADMIN_TITLE = _('Username / Password')
|
||||
|
||||
|
||||
class MethodAdminDirectory(Directory):
|
||||
title = ADMIN_TITLE
|
||||
label = N_('Configure username/password identification method')
|
||||
label = _('Configure username/password identification method')
|
||||
|
||||
_q_exports = ['', 'passwords', 'identities']
|
||||
|
||||
def _q_index(self):
|
||||
html_top('settings', title=_(ADMIN_TITLE))
|
||||
get_response().breadcrumb.append(('password/', _(self.title)))
|
||||
html_top('settings', title=ADMIN_TITLE)
|
||||
get_response().breadcrumb.append(('password/', ADMIN_TITLE))
|
||||
r = TemplateIO(html=True)
|
||||
|
||||
r += htmltext('<h2>%s</h2>') % _(ADMIN_TITLE)
|
||||
r += htmltext('<h2>%s</h2>') % ADMIN_TITLE
|
||||
|
||||
r += get_session().display_message()
|
||||
|
||||
|
@ -958,7 +958,7 @@ class MethodUserDirectory(Directory):
|
|||
return actions
|
||||
|
||||
def email(self):
|
||||
html_top('users', title=_(ADMIN_TITLE))
|
||||
html_top('users', title=ADMIN_TITLE)
|
||||
r = TemplateIO(html=True)
|
||||
get_response().breadcrumb.append(('email', 'Email Password'))
|
||||
r += htmltext('<h2>%s</h2>') % _('Email Password')
|
||||
|
@ -1065,11 +1065,11 @@ class PasswordAuthMethod(AuthMethod):
|
|||
|
||||
EmailsDirectory.register(
|
||||
'password-subscription-notification',
|
||||
N_('Subscription notification for password account'),
|
||||
N_('Available variables: email, website, token_url, token, admin_email, username, password'),
|
||||
category=N_('Identification'),
|
||||
default_subject=N_('Subscription Confirmation'),
|
||||
default_body=N_(
|
||||
_('Subscription notification for password account'),
|
||||
_('Available variables: email, website, token_url, token, admin_email, username, password'),
|
||||
category=_('Identification'),
|
||||
default_subject=_('Subscription Confirmation'),
|
||||
default_body=_(
|
||||
'''\
|
||||
We have received a request for subscription of your email address,
|
||||
"[email]", to the [website] web site.
|
||||
|
@ -1089,11 +1089,11 @@ to [admin_email].
|
|||
|
||||
EmailsDirectory.register(
|
||||
'change-password-request',
|
||||
N_('Request for password change'),
|
||||
N_('Available variables: change_url, cancel_url, token, time'),
|
||||
category=N_('Identification'),
|
||||
default_subject=N_('Change Password Request'),
|
||||
default_body=N_(
|
||||
_('Request for password change'),
|
||||
_('Available variables: change_url, cancel_url, token, time'),
|
||||
category=_('Identification'),
|
||||
default_subject=_('Change Password Request'),
|
||||
default_body=_(
|
||||
"""\
|
||||
You have (or someone impersonating you has) requested to change your
|
||||
password. To complete the change, visit the following link:
|
||||
|
@ -1114,11 +1114,11 @@ If you do nothing, the request will lapse after 3 days (precisely on
|
|||
|
||||
EmailsDirectory.register(
|
||||
'new-generated-password',
|
||||
N_('New generated password'),
|
||||
N_('Available variables: username, password, hostname'),
|
||||
category=N_('Identification'),
|
||||
default_subject=N_('Your new password'),
|
||||
default_body=N_(
|
||||
_('New generated password'),
|
||||
_('Available variables: username, password, hostname'),
|
||||
category=_('Identification'),
|
||||
default_subject=_('Your new password'),
|
||||
default_body=_(
|
||||
'''\
|
||||
Hello,
|
||||
|
||||
|
@ -1134,11 +1134,11 @@ account details:
|
|||
|
||||
EmailsDirectory.register(
|
||||
'new-account-approved',
|
||||
N_('Approval of new account'),
|
||||
N_('Available variables: username, password'),
|
||||
category=N_('Identification'),
|
||||
default_subject=N_('Your account has been approved'),
|
||||
default_body=N_(
|
||||
_('Approval of new account'),
|
||||
_('Available variables: username, password'),
|
||||
category=_('Identification'),
|
||||
default_subject=_('Your account has been approved'),
|
||||
default_body=_(
|
||||
'''\
|
||||
Your account has been approved.
|
||||
|
||||
|
@ -1152,11 +1152,11 @@ Account details:
|
|||
|
||||
EmailsDirectory.register(
|
||||
'warning-about-unused-account',
|
||||
N_('Warning about unusued account'),
|
||||
N_('Available variables: username'),
|
||||
category=N_('Identification'),
|
||||
default_subject=N_('Your account is unused'),
|
||||
default_body=N_(
|
||||
_('Warning about unusued account'),
|
||||
_('Available variables: username'),
|
||||
category=_('Identification'),
|
||||
default_subject=_('Your account is unused'),
|
||||
default_body=_(
|
||||
'''\
|
||||
Your account ([username]) is not being used.
|
||||
'''
|
||||
|
@ -1165,11 +1165,11 @@ Your account ([username]) is not being used.
|
|||
|
||||
EmailsDirectory.register(
|
||||
'notification-of-removed-account',
|
||||
N_('Notification of removal of unused account'),
|
||||
N_('Available variables: username'),
|
||||
category=N_('Identification'),
|
||||
default_subject=N_('Your account has been removed'),
|
||||
default_body=N_(
|
||||
_('Notification of removal of unused account'),
|
||||
_('Available variables: username'),
|
||||
category=_('Identification'),
|
||||
default_subject=_('Your account has been removed'),
|
||||
default_body=_(
|
||||
'''\
|
||||
Your account ([username]) was not being used, it has therefore been removed.
|
||||
'''
|
||||
|
@ -1178,11 +1178,11 @@ Your account ([username]) was not being used, it has therefore been removed.
|
|||
|
||||
EmailsDirectory.register(
|
||||
'new-registration-admin-notification',
|
||||
N_('Notification of new registration to administrators'),
|
||||
N_('Available variables: hostname, email_as_username, username'),
|
||||
category=N_('Identification'),
|
||||
default_subject=N_('New Registration'),
|
||||
default_body=N_(
|
||||
_('Notification of new registration to administrators'),
|
||||
_('Available variables: hostname, email_as_username, username'),
|
||||
category=_('Identification'),
|
||||
default_subject=_('New Registration'),
|
||||
default_body=_(
|
||||
'''\
|
||||
Hello,
|
||||
|
||||
|
@ -1196,11 +1196,11 @@ A new account has been created on [hostname].
|
|||
|
||||
EmailsDirectory.register(
|
||||
'new-account-generated-password',
|
||||
N_('Welcome email, with generated password'),
|
||||
N_('Available variables: hostname, username, password, email_as_username'),
|
||||
category=N_('Identification'),
|
||||
default_subject=N_('Welcome to [hostname]'),
|
||||
default_body=N_(
|
||||
_('Welcome email, with generated password'),
|
||||
_('Available variables: hostname, username, password, email_as_username'),
|
||||
category=_('Identification'),
|
||||
default_subject=_('Welcome to [hostname]'),
|
||||
default_body=_(
|
||||
'''\
|
||||
Welcome to [hostname],
|
||||
|
||||
|
@ -1211,11 +1211,11 @@ Your password is: [password]
|
|||
|
||||
EmailsDirectory.register(
|
||||
'password-email-create-anew',
|
||||
N_('Email with a new password for the user'),
|
||||
N_('Available variables: hostname, name, username, password'),
|
||||
category=N_('Identification'),
|
||||
default_subject=N_('Your new password for [hostname]'),
|
||||
default_body=N_(
|
||||
_('Email with a new password for the user'),
|
||||
_('Available variables: hostname, name, username, password'),
|
||||
category=_('Identification'),
|
||||
default_subject=_('Your new password for [hostname]'),
|
||||
default_body=_(
|
||||
'''\
|
||||
Hello [name],
|
||||
|
||||
|
@ -1226,11 +1226,11 @@ Here is your new password for [hostname]: [password]
|
|||
|
||||
EmailsDirectory.register(
|
||||
'password-email-current',
|
||||
N_('Email with current password for the user'),
|
||||
N_('Available variables: hostname, name, username, password'),
|
||||
category=N_('Identification'),
|
||||
default_subject=N_('Your password for [hostname]'),
|
||||
default_body=N_(
|
||||
_('Email with current password for the user'),
|
||||
_('Available variables: hostname, name, username, password'),
|
||||
category=_('Identification'),
|
||||
default_subject=_('Your password for [hostname]'),
|
||||
default_body=_(
|
||||
'''\
|
||||
Hello [name],
|
||||
|
||||
|
@ -1242,9 +1242,9 @@ Here is your password for [hostname]: [password]
|
|||
|
||||
TextsDirectory.register(
|
||||
'account-created',
|
||||
N_('Text when account confirmed by user'),
|
||||
category=N_('Identification'),
|
||||
default=N_(
|
||||
_('Text when account confirmed by user'),
|
||||
category=_('Identification'),
|
||||
default=_(
|
||||
'''<p>
|
||||
Your account has been created.
|
||||
</p>'''
|
||||
|
@ -1253,9 +1253,9 @@ Your account has been created.
|
|||
|
||||
TextsDirectory.register(
|
||||
'password-forgotten-token-sent',
|
||||
N_('Text when an email with a change password token has been sent'),
|
||||
category=N_('Identification'),
|
||||
default=N_(
|
||||
_('Text when an email with a change password token has been sent'),
|
||||
category=_('Identification'),
|
||||
default=_(
|
||||
'''<p>
|
||||
A token for changing your password has been emailed to you. Follow the instructions in that email to change your password.
|
||||
</p>
|
||||
|
@ -1267,9 +1267,9 @@ A token for changing your password has been emailed to you. Follow the instructi
|
|||
|
||||
TextsDirectory.register(
|
||||
'new-password-sent-by-email',
|
||||
N_('Text when new password has been sent'),
|
||||
category=N_('Identification'),
|
||||
default=N_(
|
||||
_('Text when new password has been sent'),
|
||||
category=_('Identification'),
|
||||
default=_(
|
||||
'''<p>
|
||||
Your new password has been sent to you by email.
|
||||
</p>
|
||||
|
@ -1279,13 +1279,13 @@ Your new password has been sent to you by email.
|
|||
),
|
||||
)
|
||||
|
||||
TextsDirectory.register('new-account', N_('Text on top of registration form'), category=N_('Identification'))
|
||||
TextsDirectory.register('new-account', _('Text on top of registration form'), category=_('Identification'))
|
||||
|
||||
TextsDirectory.register(
|
||||
'password-forgotten-link',
|
||||
N_('Text on login page, linking to the forgotten password request page'),
|
||||
category=N_('Identification'),
|
||||
default=N_(
|
||||
_('Text on login page, linking to the forgotten password request page'),
|
||||
category=_('Identification'),
|
||||
default=_(
|
||||
'''<p>
|
||||
If you have an account, but have forgotten your password, you should go
|
||||
to the <a href="%(forgotten_url)s">Lost password page</a> and submit a request
|
||||
|
@ -1296,9 +1296,9 @@ to change your password.
|
|||
|
||||
TextsDirectory.register(
|
||||
'password-forgotten-enter-username',
|
||||
N_('Text on forgotten password request page'),
|
||||
category=N_('Identification'),
|
||||
default=N_(
|
||||
_('Text on forgotten password request page'),
|
||||
category=_('Identification'),
|
||||
default=_(
|
||||
'''<p>
|
||||
If you have an account, but have forgotten your password, enter your user name
|
||||
below and submit a request to change your password.
|
||||
|
@ -1308,10 +1308,10 @@ below and submit a request to change your password.
|
|||
|
||||
TextsDirectory.register(
|
||||
'password-account-link-to-register-page',
|
||||
N_('Text linking the login page to the account creation page'),
|
||||
hint=N_('Available variable: register_url'),
|
||||
category=N_('Identification'),
|
||||
default=N_(
|
||||
_('Text linking the login page to the account creation page'),
|
||||
hint=_('Available variable: register_url'),
|
||||
category=_('Identification'),
|
||||
default=_(
|
||||
'''<p>
|
||||
If you do not have an account, you should go to the <a href="[register_url]">
|
||||
New Account page</a>.
|
||||
|
@ -1321,22 +1321,22 @@ New Account page</a>.
|
|||
|
||||
TextsDirectory.register(
|
||||
'invalid-password-token',
|
||||
N_('Text when an invalid password token is used'),
|
||||
category=N_('Identification'),
|
||||
default=N_(
|
||||
_('Text when an invalid password token is used'),
|
||||
category=_('Identification'),
|
||||
default=_(
|
||||
'''<p>
|
||||
Sorry, the token you used is invalid, or has already been used.
|
||||
</p>'''
|
||||
),
|
||||
)
|
||||
|
||||
TextsDirectory.register('top-of-login', N_('Text on top of the login page'), category=N_('Identification'))
|
||||
TextsDirectory.register('top-of-login', _('Text on top of the login page'), category=_('Identification'))
|
||||
|
||||
TextsDirectory.register(
|
||||
'email-sent-confirm-creation',
|
||||
N_('Text when a mail for confirmation of an account creation has been sent'),
|
||||
category=N_('Identification'),
|
||||
default=N_('An email has been sent to you so you can confirm your account creation.'),
|
||||
_('Text when a mail for confirmation of an account creation has been sent'),
|
||||
category=_('Identification'),
|
||||
default=_('An email has been sent to you so you can confirm your account creation.'),
|
||||
)
|
||||
|
||||
|
||||
|
|
|
@ -600,6 +600,10 @@ class JSONEncoder(json.JSONEncoder):
|
|||
'content': base64.b64encode(obj.get_content()),
|
||||
}
|
||||
|
||||
if obj.__class__.__name__ == '__proxy__':
|
||||
# lazy gettext
|
||||
return str(obj)
|
||||
|
||||
# Let the base class default method raise the TypeError
|
||||
return json.JSONEncoder.default(self, obj)
|
||||
|
||||
|
@ -620,7 +624,7 @@ def json_response(data):
|
|||
get_response().set_header('Access-Control-Allow-Origin', get_request().get_environ('HTTP_ORIGIN'))
|
||||
get_response().set_header('Access-Control-Allow-Credentials', 'true')
|
||||
get_response().set_header('Access-Control-Allow-Headers', 'x-requested-with')
|
||||
json_str = json.dumps(data)
|
||||
json_str = json.dumps(data, cls=JSONEncoder)
|
||||
for variable in ('jsonpCallback', 'callback'):
|
||||
if variable in get_request().form:
|
||||
get_response().set_content_type('application/javascript')
|
||||
|
@ -1002,6 +1006,7 @@ def get_document_types(current_document_type):
|
|||
document_types.update(get_cfg('filetypes', {}))
|
||||
for key, document_type in document_types.items():
|
||||
document_type['id'] = key
|
||||
document_type['label'] = str(document_type['label'])
|
||||
# add current file type if it does not exist anymore in the settings
|
||||
cur_dt = current_document_type
|
||||
if cur_dt and cur_dt['id'] not in document_types:
|
||||
|
|
|
@ -20,7 +20,7 @@ from quixote.html import TemplateIO, htmltext
|
|||
|
||||
from wcs.qommon.admin.texts import TextsDirectory
|
||||
|
||||
from . import N_, _, errors, get_cfg, template
|
||||
from . import _, errors, get_cfg, template
|
||||
from .form import Form, HtmlWidget, PasswordWidget
|
||||
from .ident.password import check_password
|
||||
from .ident.password_accounts import PasswordAccount
|
||||
|
@ -194,4 +194,4 @@ class MyspaceDirectory(Directory):
|
|||
return form.render()
|
||||
|
||||
|
||||
TextsDirectory.register('top-of-profile', N_('Text on top of the profile page'))
|
||||
TextsDirectory.register('top-of-profile', _('Text on top of the profile page'))
|
||||
|
|
|
@ -45,7 +45,7 @@ from django.utils import translation
|
|||
from django.utils.encoding import force_bytes, force_text
|
||||
from quixote.publish import Publisher, get_publisher, get_request, get_response
|
||||
|
||||
from . import N_, _, errors, force_str, logger, storage, template
|
||||
from . import _, errors, force_str, logger, storage, template
|
||||
from .cron import CronJob
|
||||
from .http_request import HTTPRequest
|
||||
from .http_response import AfterJob, HTTPResponse
|
||||
|
@ -185,7 +185,13 @@ class QommonPublisher(Publisher):
|
|||
request.response.headers['WWW-Authenticate'] = 'Basic realm="%s"' % exc.realm
|
||||
if request.is_json():
|
||||
request.response.set_content_type('application/json')
|
||||
return json.dumps({'err': 1, 'err_class': exc.title, 'err_desc': exc.public_msg})
|
||||
return json.dumps(
|
||||
{
|
||||
'err': 1,
|
||||
'err_class': str(exc.title),
|
||||
'err_desc': str(exc.public_msg) if exc.public_msg else None,
|
||||
}
|
||||
)
|
||||
if isinstance(exc, errors.TraversalError):
|
||||
raise Http404()
|
||||
output = self.format_publish_error(exc)
|
||||
|
@ -1003,9 +1009,9 @@ def get_publisher_class():
|
|||
return builtins.__dict__.get('__publisher_class')
|
||||
|
||||
|
||||
Substitutions.register('site_name', category=N_('General'), comment=N_('Site Name'))
|
||||
Substitutions.register('site_theme', category=N_('General'), comment=N_('Current Theme Name'))
|
||||
Substitutions.register('site_url', category=N_('General'), comment=N_('Site URL'))
|
||||
Substitutions.register('site_url_backoffice', category=N_('General'), comment=N_('Site URL (backoffice)'))
|
||||
Substitutions.register('today', category=N_('General'), comment=N_('Current Date'))
|
||||
Substitutions.register('now', category=N_('General'), comment=N_('Current Date & Time'))
|
||||
Substitutions.register('site_name', category=_('General'), comment=_('Site Name'))
|
||||
Substitutions.register('site_theme', category=_('General'), comment=_('Current Theme Name'))
|
||||
Substitutions.register('site_url', category=_('General'), comment=_('Site URL'))
|
||||
Substitutions.register('site_url_backoffice', category=_('General'), comment=_('Site URL (backoffice)'))
|
||||
Substitutions.register('today', category=_('General'), comment=_('Current Date'))
|
||||
Substitutions.register('now', category=_('General'), comment=_('Current Date & Time'))
|
||||
|
|
|
@ -153,6 +153,9 @@ class Session(QommonSession, CaptchaSession, StorableObject):
|
|||
return odict
|
||||
|
||||
def store(self, *args, **kwargs):
|
||||
if self.message:
|
||||
# escape lazy gettext
|
||||
self.message = (self.message[0], str(self.message[1]))
|
||||
current_dict = copy.copy(self.__dict__)
|
||||
orig_dict = current_dict.pop('__orig_dict__', {})
|
||||
current_dict.pop('_access_time', None)
|
||||
|
|
|
@ -144,7 +144,7 @@ class Substitutions:
|
|||
% (_('Category'), _('Variable'), _('Comment'))
|
||||
)
|
||||
r += htmltext('<tbody>')
|
||||
vars = [(_(y.get('category')), x, _(y.get('comment'))) for x, y in cls.substitutions_dict.items()]
|
||||
vars = [(y.get('category'), x, y.get('comment')) for x, y in cls.substitutions_dict.items()]
|
||||
for dynamic_source in cls.dynamic_sources:
|
||||
vars.extend(dynamic_source.get_substitution_variables_list())
|
||||
vars.sort()
|
||||
|
|
|
@ -458,7 +458,7 @@ def ezt_raises(exception, on_parse=False):
|
|||
message = _('syntax error in ezt template: %s')
|
||||
else:
|
||||
message = _('failure to render ezt template: %s')
|
||||
raise TemplateError(message % ' '.join(parts))
|
||||
raise TemplateError(message % ' '.join([str(x) for x in parts]))
|
||||
|
||||
|
||||
class Template:
|
||||
|
|
10
wcs/root.py
10
wcs/root.py
|
@ -33,7 +33,7 @@ from .forms import root
|
|||
from .forms.actions import ActionsDirectory
|
||||
from .forms.preview import PreviewDirectory
|
||||
from .myspace import MyspaceDirectory
|
||||
from .qommon import _, errors, get_cfg, get_logger, ident, saml2, template
|
||||
from .qommon import _, errors, get_cfg, get_logger, ident, misc, saml2, template
|
||||
from .qommon.afterjobs import AfterJobStatusDirectory
|
||||
from .qommon.form import Form, RadiobuttonsWidget
|
||||
from .qommon.pages import PagesDirectory
|
||||
|
@ -92,7 +92,7 @@ class LoginDirectory(Directory):
|
|||
RadiobuttonsWidget,
|
||||
'method',
|
||||
options=[
|
||||
(x.key, _(x.description)) for x in ident.get_method_classes() if x.key in ident_methods
|
||||
(x.key, x.description) for x in ident.get_method_classes() if x.key in ident_methods
|
||||
],
|
||||
delim=htmltext('<br/>'),
|
||||
)
|
||||
|
@ -157,7 +157,7 @@ class RegisterDirectory(Directory):
|
|||
RadiobuttonsWidget,
|
||||
'method',
|
||||
options=[
|
||||
(x.key, _(x.description)) for x in ident.get_method_classes() if x.key in ident_methods
|
||||
(x.key, x.description) for x in ident.get_method_classes() if x.key in ident_methods
|
||||
],
|
||||
delim=htmltext('<br/>'),
|
||||
)
|
||||
|
@ -344,7 +344,7 @@ class RootDirectory(Directory):
|
|||
# they would propose the returned json content for download if
|
||||
# it was served with the appropriate content type :/
|
||||
get_response().set_content_type('text/plain')
|
||||
return json.dumps(results)
|
||||
return json.dumps(results, cls=misc.JSONEncoder)
|
||||
|
||||
def feed_substitution_parts(self):
|
||||
get_publisher().substitutions.feed(get_session())
|
||||
|
@ -446,7 +446,7 @@ class RootDirectory(Directory):
|
|||
'email_domain_suggest': _('Did you want to write'),
|
||||
'email_domain_fix': _('Apply fix'),
|
||||
}
|
||||
return 'WCS_I18N = %s;\n' % json.dumps(strings)
|
||||
return 'WCS_I18N = %s;\n' % json.dumps(strings, cls=misc.JSONEncoder)
|
||||
|
||||
admin = None
|
||||
backoffice = None
|
||||
|
|
|
@ -25,7 +25,7 @@ from wcs.qommon.storage import Null
|
|||
|
||||
class UnknownUser:
|
||||
def __str__(self):
|
||||
return _('unknown user')
|
||||
return str(_('unknown user'))
|
||||
|
||||
|
||||
class Snapshot:
|
||||
|
@ -53,7 +53,7 @@ class Snapshot:
|
|||
if get_session():
|
||||
obj.user_id = get_session().user
|
||||
obj.serialization = ET.tostring(instance.export_to_xml(include_id=True)).decode('utf-8')
|
||||
obj.comment = comment
|
||||
obj.comment = str(comment) if comment else None
|
||||
obj.label = label
|
||||
latest = cls.get_latest(obj.object_type, obj.object_id)
|
||||
if label is not None or latest is None or obj.serialization != latest.serialization:
|
||||
|
|
|
@ -2645,6 +2645,9 @@ class Session(SqlMixin, wcs.sessions.BasicSession):
|
|||
|
||||
@guard_postgres
|
||||
def store(self):
|
||||
if self.message:
|
||||
# escape lazy gettext
|
||||
self.message = (self.message[0], str(self.message[1]))
|
||||
sql_dict = {
|
||||
'id': self.id,
|
||||
'session_data': bytearray(pickle.dumps(self.__dict__, protocol=2)),
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
<li>{% trans "Latest occurence:" %} {{ error.latest_occurence_timestamp }}</li>
|
||||
<li>{% trans "Count:" %} {{ error.occurences_count }}</li>
|
||||
{% if formdef %}
|
||||
<li>{% trans formdef.verbose_name %}{% trans ":" %} <a href="{{ formdef.get_admin_url }}">{{ formdef.name }}</a></li>
|
||||
<li>{{ formdef.verbose_name }}{% trans ":" %} <a href="{{ formdef.get_admin_url }}">{{ formdef.name }}</a></li>
|
||||
{% endif %}
|
||||
{% if workflow %}
|
||||
<li>{% trans "Workflow:" %} <a href="{{ workflow.get_admin_url }}">{{ workflow.name }}</a>
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
{% block content %}
|
||||
<div class="section">
|
||||
<dl class="job-status">
|
||||
<dt>{% trans job.label %}</dt>
|
||||
<dt>{{ job.label }}</dt>
|
||||
<dd><span class="afterjob" id="{{ job.id }}">{% trans job.status %}</span></dd>
|
||||
</dl>
|
||||
</div>
|
||||
|
|
|
@ -20,7 +20,7 @@ from quixote import get_publisher
|
|||
|
||||
import wcs.qommon.storage as st
|
||||
|
||||
from .qommon import N_, _, get_cfg
|
||||
from .qommon import _, get_cfg
|
||||
from .qommon.misc import simplify
|
||||
from .qommon.storage import StorableObject
|
||||
from .qommon.substitution import Substitutions, invalidate_substitution_cache
|
||||
|
@ -315,7 +315,9 @@ class User(StorableObject):
|
|||
|
||||
|
||||
Substitutions.register(
|
||||
'session_user_display_name', category=N_('User'), comment=N_('Session User Display Name')
|
||||
'session_user_display_name',
|
||||
category=_('User'),
|
||||
comment=_('Session User Display Name'),
|
||||
)
|
||||
Substitutions.register('session_user_email', category=N_('User'), comment=N_('Session User Email'))
|
||||
Substitutions.register('session_user_email', category=_('User'), comment=_('Session User Email'))
|
||||
Substitutions.register_dynamic_source(User)
|
||||
|
|
|
@ -18,7 +18,7 @@ from quixote import get_publisher
|
|||
|
||||
from wcs.workflows import WorkflowStatusItem, register_item_class
|
||||
|
||||
from ..qommon import N_, _, emails
|
||||
from ..qommon import _, emails
|
||||
from ..qommon.cron import CronJob
|
||||
from ..qommon.form import SingleSelectWidget, WidgetList
|
||||
from ..qommon.publisher import get_publisher_class
|
||||
|
@ -26,7 +26,7 @@ from ..qommon.storage import StorableObject
|
|||
|
||||
|
||||
class AggregationEmailWorkflowStatusItem(WorkflowStatusItem):
|
||||
description = N_('Daily Summary Email')
|
||||
description = _('Daily Summary Email')
|
||||
key = 'aggregationemail'
|
||||
category = 'interaction'
|
||||
ok_in_global_action = False
|
||||
|
|
|
@ -14,12 +14,12 @@
|
|||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
from wcs.qommon import N_
|
||||
from wcs.qommon import _
|
||||
from wcs.workflows import WorkflowStatusItem, register_item_class
|
||||
|
||||
|
||||
class AnonymiseWorkflowStatusItem(WorkflowStatusItem):
|
||||
description = N_('Anonymisation')
|
||||
description = _('Anonymisation')
|
||||
key = 'anonymise'
|
||||
category = 'formdata-action'
|
||||
|
||||
|
|
|
@ -24,7 +24,7 @@ from wcs.forms.common import FileDirectory, FormStatusPage
|
|||
from wcs.portfolio import has_portfolio, push_document
|
||||
from wcs.workflows import AttachmentEvolutionPart, WorkflowStatusItem, register_item_class
|
||||
|
||||
from ..qommon import N_, _
|
||||
from ..qommon import _
|
||||
from ..qommon.errors import TraversalError
|
||||
from ..qommon.form import (
|
||||
CheckboxWidget,
|
||||
|
@ -87,7 +87,7 @@ def form_attachment(self):
|
|||
|
||||
|
||||
class AddAttachmentWorkflowStatusItem(WorkflowStatusItem):
|
||||
description = N_('Attachment')
|
||||
description = _('Attachment')
|
||||
key = 'addattachment'
|
||||
category = 'interaction'
|
||||
endpoint = False
|
||||
|
|
|
@ -23,7 +23,7 @@ from wcs.fields import WidgetField
|
|||
from wcs.wf.profile import FieldNode
|
||||
from wcs.workflows import WorkflowStatusItem, register_item_class
|
||||
|
||||
from ..qommon import N_, _
|
||||
from ..qommon import _
|
||||
from ..qommon.form import (
|
||||
CompositeWidget,
|
||||
ComputedExpressionWidget,
|
||||
|
@ -80,7 +80,7 @@ class SetBackofficeFieldsTableWidget(WidgetListAsTable):
|
|||
|
||||
|
||||
class SetBackofficeFieldsWorkflowStatusItem(WorkflowStatusItem):
|
||||
description = N_('Backoffice Data')
|
||||
description = _('Backoffice Data')
|
||||
key = 'set-backoffice-fields'
|
||||
category = 'formdata-action'
|
||||
|
||||
|
@ -164,7 +164,7 @@ class SetBackofficeFieldsWorkflowStatusItem(WorkflowStatusItem):
|
|||
except ValueError as e:
|
||||
summary = _('Failed to convert %(class)s value to %(kind)s field (%(id)s)') % {
|
||||
'class': type(new_value),
|
||||
'kind': _(getattr(formdef_field, 'description', 'unknown')),
|
||||
'kind': getattr(formdef_field, 'description', _('unknown')),
|
||||
'id': field['field_id'],
|
||||
}
|
||||
expression_dict = self.get_expression(field['value'])
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
from quixote import get_publisher
|
||||
|
||||
from wcs.carddef import CardDef
|
||||
from wcs.qommon import N_
|
||||
from wcs.qommon import _
|
||||
from wcs.wf.create_formdata import CreateFormdataWorkflowStatusItem, LinkedFormdataEvolutionPart
|
||||
from wcs.workflows import register_item_class
|
||||
|
||||
|
@ -27,7 +27,7 @@ class LinkedCardDataEvolutionPart(LinkedFormdataEvolutionPart):
|
|||
|
||||
|
||||
class CreateCarddataWorkflowStatusItem(CreateFormdataWorkflowStatusItem):
|
||||
description = N_('Create Card Data')
|
||||
description = _('Create Card Data')
|
||||
key = 'create_carddata'
|
||||
category = 'formdata-action'
|
||||
ok_in_global_action = True
|
||||
|
@ -35,10 +35,10 @@ class CreateCarddataWorkflowStatusItem(CreateFormdataWorkflowStatusItem):
|
|||
formdef_class = CardDef
|
||||
evolution_part_class = LinkedCardDataEvolutionPart
|
||||
|
||||
formdef_label = N_('Card')
|
||||
mappings_label = N_('Mappings to new card fields')
|
||||
varname_hint = N_('This is used to get linked card in expressions.')
|
||||
user_association_option_label = N_('User to associate to card')
|
||||
formdef_label = _('Card')
|
||||
mappings_label = _('Mappings to new card fields')
|
||||
varname_hint = _('This is used to get linked card in expressions.')
|
||||
user_association_option_label = _('User to associate to card')
|
||||
|
||||
@classmethod
|
||||
def is_available(cls, workflow=None):
|
||||
|
|
|
@ -22,7 +22,7 @@ from quixote import get_publisher, get_request, get_session
|
|||
from quixote.html import htmltext
|
||||
|
||||
from wcs.formdef import FormDef
|
||||
from wcs.qommon import N_, _
|
||||
from wcs.qommon import _
|
||||
from wcs.qommon.form import (
|
||||
CheckboxWidget,
|
||||
CompositeWidget,
|
||||
|
@ -204,7 +204,7 @@ class LazyFormDataLinks:
|
|||
|
||||
|
||||
class CreateFormdataWorkflowStatusItem(WorkflowStatusItem):
|
||||
description = N_('New Form Creation')
|
||||
description = _('New Form Creation')
|
||||
key = 'create_formdata'
|
||||
category = 'formdata-action'
|
||||
support_substitution_variables = True
|
||||
|
@ -213,11 +213,11 @@ class CreateFormdataWorkflowStatusItem(WorkflowStatusItem):
|
|||
evolution_part_class = LinkedFormdataEvolutionPart
|
||||
|
||||
formdef_slug = None
|
||||
formdef_label = N_('Form')
|
||||
mappings_label = N_('Mappings to new form fields')
|
||||
formdef_label = _('Form')
|
||||
mappings_label = _('Mappings to new form fields')
|
||||
accept_empty_value = False
|
||||
varname_hint = N_('This is used to get linked forms in expressions.')
|
||||
user_association_option_label = N_('User to associate to form')
|
||||
varname_hint = _('This is used to get linked forms in expressions.')
|
||||
user_association_option_label = _('User to associate to form')
|
||||
|
||||
draft = False
|
||||
backoffice_submission = False
|
||||
|
@ -261,7 +261,7 @@ class CreateFormdataWorkflowStatusItem(WorkflowStatusItem):
|
|||
form.add(
|
||||
SingleSelectWidget,
|
||||
'%sformdef_slug' % prefix,
|
||||
title=_(self.formdef_label),
|
||||
title=self.formdef_label,
|
||||
value=self.formdef_slug,
|
||||
options=list_forms,
|
||||
)
|
||||
|
@ -281,7 +281,7 @@ class CreateFormdataWorkflowStatusItem(WorkflowStatusItem):
|
|||
form.add(
|
||||
RadiobuttonsWidget,
|
||||
'%suser_association_mode' % prefix,
|
||||
title=_(self.user_association_option_label),
|
||||
title=self.user_association_option_label,
|
||||
options=[
|
||||
(None, _('None'), 'none'),
|
||||
('keep-user', _('Keep Current User'), 'keep-user'),
|
||||
|
@ -319,7 +319,7 @@ class CreateFormdataWorkflowStatusItem(WorkflowStatusItem):
|
|||
widget = form.add(
|
||||
MappingsWidget,
|
||||
'%smappings' % prefix,
|
||||
title=_(self.mappings_label),
|
||||
title=self.mappings_label,
|
||||
accept_empty_value=self.accept_empty_value,
|
||||
to_formdef=formdef,
|
||||
value=self.mappings,
|
||||
|
@ -334,7 +334,7 @@ class CreateFormdataWorkflowStatusItem(WorkflowStatusItem):
|
|||
'%svarname' % prefix,
|
||||
title=_('Identifier'),
|
||||
value=self.varname,
|
||||
hint=_(self.varname_hint),
|
||||
hint=self.varname_hint,
|
||||
advanced=not (bool(self.varname)),
|
||||
)
|
||||
if 'map_fields_by_varname' in parameters and formdef:
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
from wcs.qommon.form import SingleSelectWidget
|
||||
from wcs.workflows import WorkflowStatusItem, register_item_class
|
||||
|
||||
from ..qommon import N_, _
|
||||
from ..qommon import _
|
||||
|
||||
MODE_INC = '1'
|
||||
MODE_DEC = '2'
|
||||
|
@ -25,7 +25,7 @@ MODE_SET = '3'
|
|||
|
||||
|
||||
class ModifyCriticalityWorkflowStatusItem(WorkflowStatusItem):
|
||||
description = N_('Criticality Levels')
|
||||
description = _('Criticality Levels')
|
||||
key = 'modify_criticality'
|
||||
category = 'formdata-action'
|
||||
|
||||
|
|
|
@ -23,7 +23,7 @@ from quixote.html import htmltext
|
|||
from wcs.roles import get_user_roles
|
||||
from wcs.workflows import WorkflowStatusItem, XmlSerialisable, get_role_name, register_item_class
|
||||
|
||||
from ..qommon import N_, _
|
||||
from ..qommon import _
|
||||
from ..qommon.form import (
|
||||
CompositeWidget,
|
||||
RadiobuttonsWidget,
|
||||
|
@ -85,7 +85,7 @@ class RuleNode(XmlSerialisable):
|
|||
|
||||
|
||||
class DispatchWorkflowStatusItem(WorkflowStatusItem):
|
||||
description = N_('Function/Role Linking')
|
||||
description = _('Function/Role Linking')
|
||||
key = 'dispatch'
|
||||
category = 'formdata-action'
|
||||
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
|
||||
from quixote import get_publisher
|
||||
|
||||
from wcs.qommon import N_, _
|
||||
from wcs.qommon import _
|
||||
from wcs.wf.create_carddata import CreateCarddataWorkflowStatusItem
|
||||
from wcs.wf.external_workflow import ExternalWorkflowGlobalAction
|
||||
from wcs.workflows import register_item_class
|
||||
|
@ -27,8 +27,8 @@ class EditCarddataWorkflowStatusItem(CreateCarddataWorkflowStatusItem, ExternalW
|
|||
key = 'edit_carddata'
|
||||
mappings_label = _('Mappings to card fields')
|
||||
accept_empty_value = True
|
||||
automatic_targetting = N_('Action on linked cards')
|
||||
manual_targetting = N_('Specify the identifier of the card on which the action will be applied')
|
||||
automatic_targetting = _('Action on linked cards')
|
||||
manual_targetting = _('Specify the identifier of the card on which the action will be applied')
|
||||
|
||||
@classmethod
|
||||
def is_available(cls, workflow=None):
|
||||
|
|
|
@ -45,7 +45,7 @@ from wcs.workflows import (
|
|||
template_on_formdata,
|
||||
)
|
||||
|
||||
from ..qommon import N_, _, ezt, force_str, get_logger, misc
|
||||
from ..qommon import _, ezt, force_str, get_logger, misc
|
||||
from ..qommon.form import (
|
||||
CheckboxWidget,
|
||||
ComputedExpressionWidget,
|
||||
|
@ -220,7 +220,7 @@ class ExportToModelDirectory(Directory):
|
|||
|
||||
|
||||
class ExportToModel(WorkflowStatusItem):
|
||||
description = N_('Document Creation')
|
||||
description = _('Document Creation')
|
||||
key = 'export_to_model'
|
||||
category = 'formdata-action'
|
||||
support_substitution_variables = True
|
||||
|
@ -268,7 +268,7 @@ class ExportToModel(WorkflowStatusItem):
|
|||
return
|
||||
if form.get_submit() == 'button%s' % self.id:
|
||||
if not evo.comment:
|
||||
evo.comment = _('Form exported in a model')
|
||||
evo.comment = str(_('Form exported in a model'))
|
||||
self.perform_real(formdata, evo)
|
||||
in_backoffice = get_request() and get_request().is_in_backoffice()
|
||||
if self.attach_to_history:
|
||||
|
@ -351,7 +351,7 @@ class ExportToModel(WorkflowStatusItem):
|
|||
widget_name,
|
||||
value.base_filename,
|
||||
)
|
||||
hint = hint_prefix + hint
|
||||
hint = hint_prefix + force_text(hint)
|
||||
form.add(
|
||||
UploadWidget,
|
||||
widget_name,
|
||||
|
|
|
@ -18,7 +18,7 @@ from quixote import get_publisher
|
|||
|
||||
from wcs.carddef import CardDef
|
||||
from wcs.formdef import FormDef
|
||||
from wcs.qommon import N_, _
|
||||
from wcs.qommon import _
|
||||
from wcs.qommon.form import ComputedExpressionWidget, Form, RadiobuttonsWidget, SingleSelectWidget
|
||||
from wcs.workflows import (
|
||||
Workflow,
|
||||
|
@ -34,8 +34,8 @@ class ExternalWorkflowGlobalAction(WorkflowStatusItem):
|
|||
description = _('External workflow')
|
||||
key = 'external_workflow_global_action'
|
||||
category = 'formdata-action'
|
||||
automatic_targetting = N_('Action on linked cards/forms')
|
||||
manual_targetting = N_('Specify the identifier of the card/form on which the action will be applied')
|
||||
automatic_targetting = _('Action on linked cards/forms')
|
||||
manual_targetting = _('Specify the identifier of the card/form on which the action will be applied')
|
||||
|
||||
slug = None
|
||||
target_mode = None
|
||||
|
@ -101,8 +101,8 @@ class ExternalWorkflowGlobalAction(WorkflowStatusItem):
|
|||
|
||||
if 'target_mode' in parameters:
|
||||
target_modes = [
|
||||
('all', _(self.automatic_targetting), 'all'),
|
||||
('manual', _(self.manual_targetting), 'manual'),
|
||||
('all', self.automatic_targetting, 'all'),
|
||||
('manual', self.manual_targetting, 'manual'),
|
||||
]
|
||||
form.add(
|
||||
RadiobuttonsWidget,
|
||||
|
|
|
@ -26,7 +26,7 @@ from wcs.forms.common import FileDirectory
|
|||
from wcs.forms.root import FormPage
|
||||
from wcs.workflows import RedisplayFormException, WorkflowStatusItem, register_item_class
|
||||
|
||||
from ..qommon import N_, _
|
||||
from ..qommon import _
|
||||
from ..qommon.form import SingleSelectWidget, VarnameWidget, WidgetList
|
||||
|
||||
|
||||
|
@ -85,14 +85,14 @@ class WorkflowFormFieldsDirectory(FieldsDirectory):
|
|||
|
||||
|
||||
class FormWorkflowStatusItem(WorkflowStatusItem):
|
||||
description = N_('Form')
|
||||
description = _('Form')
|
||||
key = 'form'
|
||||
category = 'interaction'
|
||||
ok_in_global_action = False
|
||||
endpoint = False
|
||||
waitpoint = True
|
||||
redirect_after_submit_url = 'fields/'
|
||||
submit_button_label = N_('Submit and go to fields edition')
|
||||
submit_button_label = _('Submit and go to fields edition')
|
||||
|
||||
by = []
|
||||
formdef = None
|
||||
|
|
|
@ -28,14 +28,14 @@ from quixote import get_publisher
|
|||
|
||||
from wcs.workflows import WorkflowStatusItem, register_item_class
|
||||
|
||||
from ..qommon import N_, _, force_str, get_logger
|
||||
from ..qommon import _, force_str, get_logger
|
||||
from ..qommon.errors import ConnectionError
|
||||
from ..qommon.form import CheckboxWidget, ComputedExpressionWidget, RadiobuttonsWidget
|
||||
from ..qommon.misc import http_get_page, normalize_geolocation
|
||||
|
||||
|
||||
class GeolocateWorkflowStatusItem(WorkflowStatusItem):
|
||||
description = N_('Geolocation')
|
||||
description = _('Geolocation')
|
||||
key = 'geolocate'
|
||||
category = 'formdata-action'
|
||||
|
||||
|
|
|
@ -27,7 +27,7 @@ from wcs.api import get_user_from_api_query_string, is_url_signed
|
|||
from wcs.conditions import Condition
|
||||
from wcs.workflows import Workflow, WorkflowGlobalAction, WorkflowStatusJumpItem, register_item_class
|
||||
|
||||
from ..qommon import N_, _, errors, force_str
|
||||
from ..qommon import _, errors, force_str
|
||||
from ..qommon.cron import CronJob
|
||||
from ..qommon.form import ComputedExpressionWidget, SingleSelectWidget, StringWidget, WidgetList
|
||||
from ..qommon.humantime import humanduration2seconds, seconds2humanduration, timewords
|
||||
|
@ -110,7 +110,7 @@ class TriggerDirectory(Directory):
|
|||
|
||||
|
||||
class JumpWorkflowStatusItem(WorkflowStatusJumpItem):
|
||||
description = N_('Automatic Jump')
|
||||
description = _('Automatic Jump')
|
||||
key = 'jump'
|
||||
|
||||
by = []
|
||||
|
@ -167,7 +167,10 @@ class JumpWorkflowStatusItem(WorkflowStatusJumpItem):
|
|||
reasons.append(_('timeout'))
|
||||
|
||||
if reasons:
|
||||
return _('to %(name)s, %(reasons)s') % {'name': wf_status[0].name, 'reasons': ', '.join(reasons)}
|
||||
return _('to %(name)s, %(reasons)s') % {
|
||||
'name': wf_status[0].name,
|
||||
'reasons': ', '.join([str(x) for x in reasons]),
|
||||
}
|
||||
else:
|
||||
return wf_status[0].name
|
||||
|
||||
|
|
|
@ -20,14 +20,14 @@ from quixote import get_publisher
|
|||
|
||||
from wcs.workflows import WorkflowStatusItem, register_item_class, template_on_formdata
|
||||
|
||||
from ..qommon import N_, _, get_logger
|
||||
from ..qommon import _, get_logger
|
||||
from ..qommon.form import ComputedExpressionWidget, SingleSelectWidget, StringWidget, TextWidget, WidgetList
|
||||
from ..qommon.template import TemplateError
|
||||
from .wscall import WebserviceCallStatusItem
|
||||
|
||||
|
||||
class SendNotificationWorkflowStatusItem(WebserviceCallStatusItem):
|
||||
description = N_('User Notification')
|
||||
description = _('User Notification')
|
||||
key = 'notification'
|
||||
category = 'interaction'
|
||||
support_substitution_variables = True
|
||||
|
|
|
@ -26,7 +26,7 @@ from quixote import get_publisher, get_request, get_response
|
|||
from wcs.api_utils import MissingSecret, get_secret_and_orig, sign_url
|
||||
from wcs.workflows import WorkflowStatusItem, XmlSerialisable, register_item_class
|
||||
|
||||
from ..qommon import N_, _
|
||||
from ..qommon import _
|
||||
from ..qommon.form import CompositeWidget, ComputedExpressionWidget, SingleSelectWidget, WidgetListAsTable
|
||||
from ..qommon.ident.idp import is_idp_managing_user_attributes
|
||||
from ..qommon.misc import JSONEncoder, http_patch_request
|
||||
|
@ -102,7 +102,7 @@ class FieldNode(XmlSerialisable):
|
|||
|
||||
|
||||
class UpdateUserProfileStatusItem(WorkflowStatusItem):
|
||||
description = N_('User Profile Update')
|
||||
description = _('User Profile Update')
|
||||
key = 'update_user_profile'
|
||||
category = 'user-action'
|
||||
|
||||
|
@ -211,7 +211,7 @@ class UpdateUserProfileStatusItem(WorkflowStatusItem):
|
|||
get_logger().error('failed to update profile for user %r', user)
|
||||
|
||||
if get_request():
|
||||
get_response().add_after_job(str(N_('Updating user profile')), after_job)
|
||||
get_response().add_after_job(_('Updating user profile'), after_job)
|
||||
else:
|
||||
after_job()
|
||||
|
||||
|
|
|
@ -16,12 +16,12 @@
|
|||
|
||||
from wcs.workflows import WorkflowStatusItem, register_item_class
|
||||
|
||||
from ..qommon import N_, _
|
||||
from ..qommon import _
|
||||
from ..qommon.form import ComputedExpressionWidget
|
||||
|
||||
|
||||
class RedirectToUrlWorkflowStatusItem(WorkflowStatusItem):
|
||||
description = N_('Web Redirection')
|
||||
description = _('Web Redirection')
|
||||
key = 'redirect_to_url'
|
||||
category = 'formdata-action'
|
||||
endpoint = False
|
||||
|
|
|
@ -26,7 +26,7 @@ from wcs.workflows import (
|
|||
template_on_formdata,
|
||||
)
|
||||
|
||||
from ..qommon import N_, _, ezt, get_logger
|
||||
from ..qommon import _, ezt, get_logger
|
||||
from ..qommon.form import SingleSelectWidget, TextWidget, WidgetList
|
||||
from ..qommon.template import TemplateError
|
||||
|
||||
|
@ -80,7 +80,7 @@ class JournalEvolutionPart:
|
|||
|
||||
|
||||
class RegisterCommenterWorkflowStatusItem(WorkflowStatusItem):
|
||||
description = N_('History Message')
|
||||
description = _('History Message')
|
||||
key = 'register-comment'
|
||||
category = 'interaction'
|
||||
|
||||
|
|
|
@ -18,11 +18,11 @@ from quixote import get_publisher, get_request, get_response, get_session
|
|||
|
||||
from wcs.workflows import AbortActionException, WorkflowStatusItem, register_item_class
|
||||
|
||||
from ..qommon import N_, _
|
||||
from ..qommon import _
|
||||
|
||||
|
||||
class RemoveWorkflowStatusItem(WorkflowStatusItem):
|
||||
description = N_('Deletion')
|
||||
description = _('Deletion')
|
||||
key = 'remove'
|
||||
category = 'formdata-action'
|
||||
|
||||
|
|
|
@ -20,11 +20,11 @@ from wcs.formdef import FormDef
|
|||
from wcs.qommon.form import SingleSelectWidget, StringWidget, WidgetList, WysiwygTextWidget
|
||||
from wcs.workflows import WorkflowStatusItem, register_item_class
|
||||
|
||||
from ..qommon import N_, _
|
||||
from ..qommon import _
|
||||
|
||||
|
||||
class ResubmitWorkflowStatusItem(WorkflowStatusItem):
|
||||
description = N_('Resubmission')
|
||||
description = _('Resubmission')
|
||||
key = 'resubmit'
|
||||
category = 'formdata-action'
|
||||
endpoint = False
|
||||
|
|
|
@ -23,7 +23,7 @@ from wcs.api_utils import MissingSecret, get_secret_and_orig, sign_url
|
|||
from wcs.roles import get_user_roles
|
||||
from wcs.workflows import WorkflowStatusItem, register_item_class
|
||||
|
||||
from ..qommon import N_, _
|
||||
from ..qommon import _
|
||||
from ..qommon.form import SingleSelectWidgetWithOther
|
||||
from ..qommon.ident.idp import is_idp_managing_user_attributes
|
||||
from ..qommon.misc import http_delete_request, http_post_request
|
||||
|
@ -47,7 +47,7 @@ def sign_ws_url(url):
|
|||
|
||||
|
||||
class AddRoleWorkflowStatusItem(WorkflowStatusItem):
|
||||
description = N_('Role Addition')
|
||||
description = _('Role Addition')
|
||||
key = 'add_role'
|
||||
category = 'user-action'
|
||||
|
||||
|
@ -116,7 +116,7 @@ class AddRoleWorkflowStatusItem(WorkflowStatusItem):
|
|||
get_logger().error('failed to add role %r to user %r', role, user)
|
||||
|
||||
if get_request():
|
||||
get_response().add_after_job(str(N_('Adding role')), after_job)
|
||||
get_response().add_after_job(_('Adding role'), after_job)
|
||||
else:
|
||||
after_job()
|
||||
|
||||
|
@ -125,7 +125,7 @@ register_item_class(AddRoleWorkflowStatusItem)
|
|||
|
||||
|
||||
class RemoveRoleWorkflowStatusItem(WorkflowStatusItem):
|
||||
description = N_('Role Removal')
|
||||
description = _('Role Removal')
|
||||
key = 'remove_role'
|
||||
category = 'user-action'
|
||||
|
||||
|
@ -187,7 +187,7 @@ class RemoveRoleWorkflowStatusItem(WorkflowStatusItem):
|
|||
get_logger().error('failed to remove role %r from user %r', role, user)
|
||||
|
||||
if get_request():
|
||||
get_response().add_after_job(str(N_('Removing role')), after_job)
|
||||
get_response().add_after_job(_('Removing role'), after_job)
|
||||
else:
|
||||
after_job()
|
||||
|
||||
|
|
|
@ -14,13 +14,13 @@
|
|||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
from wcs.qommon import N_
|
||||
from wcs.qommon import _
|
||||
|
||||
from .jump import JumpWorkflowStatusItem, register_item_class
|
||||
|
||||
|
||||
class TimeoutWorkflowStatusItem(JumpWorkflowStatusItem):
|
||||
description = N_('Change Status on Timeout')
|
||||
description = _('Change Status on Timeout')
|
||||
key = 'timeout'
|
||||
ok_in_global_action = False
|
||||
|
||||
|
|
|
@ -34,7 +34,7 @@ from wcs.workflows import (
|
|||
)
|
||||
from wcs.wscalls import call_webservice, get_app_error_code
|
||||
|
||||
from ..qommon import N_, _, force_str
|
||||
from ..qommon import _, force_str
|
||||
from ..qommon.errors import ConnectionError
|
||||
from ..qommon.form import (
|
||||
CheckboxWidget,
|
||||
|
@ -110,7 +110,7 @@ class JournalWsCallErrorPart:
|
|||
|
||||
|
||||
class WebserviceCallStatusItem(WorkflowStatusItem):
|
||||
description = N_('Webservice')
|
||||
description = _('Webservice')
|
||||
key = 'webservice_call'
|
||||
category = 'interaction'
|
||||
support_substitution_variables = True
|
||||
|
@ -248,7 +248,7 @@ class WebserviceCallStatusItem(WorkflowStatusItem):
|
|||
attrs={
|
||||
'data-dynamic-display-child-of': '%smethod' % prefix,
|
||||
'data-dynamic-display-value-in': '|'.join(
|
||||
[_(methods['POST']), _(methods['PUT']), _(methods['PATCH'])]
|
||||
[str(_(methods['POST'])), str(_(methods['PUT'])), str(_(methods['PATCH']))]
|
||||
),
|
||||
},
|
||||
)
|
||||
|
@ -262,7 +262,7 @@ class WebserviceCallStatusItem(WorkflowStatusItem):
|
|||
attrs={
|
||||
'data-dynamic-display-child-of': '%smethod' % prefix,
|
||||
'data-dynamic-display-value-in': '|'.join(
|
||||
[_(methods['POST']), _(methods['PUT']), _(methods['PATCH'])]
|
||||
[str(_(methods['POST'])), str(_(methods['PUT'])), str(_(methods['PATCH']))]
|
||||
),
|
||||
},
|
||||
)
|
||||
|
|
|
@ -36,7 +36,7 @@ from .fields import FileField
|
|||
from .formdata import Evolution
|
||||
from .formdef import FormDef, FormdefImportError
|
||||
from .mail_templates import MailTemplate
|
||||
from .qommon import N_, _, emails, errors, ezt, force_str, get_cfg, get_logger, misc
|
||||
from .qommon import _, emails, errors, ezt, force_str, get_cfg, get_logger, misc
|
||||
from .qommon.form import (
|
||||
CheckboxWidget,
|
||||
ComputedExpressionWidget,
|
||||
|
@ -393,7 +393,7 @@ class Workflow(StorableObject):
|
|||
StorableObject.__init__(self)
|
||||
self.name = name
|
||||
self.possible_status = []
|
||||
self.roles = {'_receiver': _('Recipient')}
|
||||
self.roles = {'_receiver': force_text(_('Recipient'))}
|
||||
self.global_actions = []
|
||||
self.criticality_levels = []
|
||||
|
||||
|
@ -401,7 +401,7 @@ class Workflow(StorableObject):
|
|||
changed = False
|
||||
|
||||
if 'roles' not in self.__dict__ or self.roles is None:
|
||||
self.roles = {'_receiver': _('Recipient')}
|
||||
self.roles = {'_receiver': force_text(_('Recipient'))}
|
||||
changed = True
|
||||
|
||||
for status in self.possible_status:
|
||||
|
@ -457,7 +457,7 @@ class Workflow(StorableObject):
|
|||
form.rebuild()
|
||||
|
||||
if get_response():
|
||||
get_response().add_after_job(N_('Reindexing cards and forms after workflow change'), update)
|
||||
get_response().add_after_job(_('Reindexing cards and forms after workflow change'), update)
|
||||
else:
|
||||
update()
|
||||
|
||||
|
@ -670,7 +670,7 @@ class Workflow(StorableObject):
|
|||
charset = get_publisher().site_charset
|
||||
workflow = cls()
|
||||
if tree.find('name') is None or not tree.find('name').text:
|
||||
raise WorkflowImportError(N_('Missing name'))
|
||||
raise WorkflowImportError(_('Missing name'))
|
||||
|
||||
# if the tree we get is actually a ElementTree for real, we get its
|
||||
# root element and go on happily.
|
||||
|
@ -678,7 +678,7 @@ class Workflow(StorableObject):
|
|||
tree = tree.getroot()
|
||||
|
||||
if tree.tag != 'workflow':
|
||||
raise WorkflowImportError(N_('Not a workflow'))
|
||||
raise WorkflowImportError(_('Not a workflow'))
|
||||
|
||||
if include_id and tree.attrib.get('id'):
|
||||
workflow.id = tree.attrib.get('id')
|
||||
|
@ -807,18 +807,20 @@ class Workflow(StorableObject):
|
|||
def get_default_workflow(cls):
|
||||
from .qommon.admin.emails import EmailsDirectory
|
||||
|
||||
workflow = Workflow(name=_('Default'))
|
||||
# force_text() is used on lazy gettext calls as the default workflow is used
|
||||
# in tests as the basis for other ones and lazy gettext would fail pickling.
|
||||
workflow = Workflow(name=force_text(_('Default')))
|
||||
workflow.id = '_default'
|
||||
workflow.roles = {'_receiver': _('Recipient')}
|
||||
just_submitted_status = workflow.add_status(_('Just Submitted'), 'just_submitted')
|
||||
workflow.roles = {'_receiver': force_text(_('Recipient'))}
|
||||
just_submitted_status = workflow.add_status(force_text(_('Just Submitted')), 'just_submitted')
|
||||
just_submitted_status.visibility = ['_receiver']
|
||||
new_status = workflow.add_status(_('New'), 'new')
|
||||
new_status = workflow.add_status(force_text(_('New')), 'new')
|
||||
new_status.colour = '66FF00'
|
||||
rejected_status = workflow.add_status(_('Rejected'), 'rejected')
|
||||
rejected_status = workflow.add_status(force_text(_('Rejected')), 'rejected')
|
||||
rejected_status.colour = 'FF3300'
|
||||
accepted_status = workflow.add_status(_('Accepted'), 'accepted')
|
||||
accepted_status = workflow.add_status(force_text(_('Accepted')), 'accepted')
|
||||
accepted_status.colour = '66CCFF'
|
||||
finished_status = workflow.add_status(_('Finished'), 'finished')
|
||||
finished_status = workflow.add_status(force_text(_('Finished')), 'finished')
|
||||
finished_status.colour = 'CCCCCC'
|
||||
|
||||
commentable = CommentableWorkflowStatusItem()
|
||||
|
@ -906,7 +908,7 @@ class Workflow(StorableObject):
|
|||
|
||||
accept = ChoiceWorkflowStatusItem()
|
||||
accept.id = '_accept'
|
||||
accept.label = _('Accept')
|
||||
accept.label = force_text(_('Accept'))
|
||||
accept.by = ['_receiver']
|
||||
accept.status = accepted_status.id
|
||||
accept.parent = new_status
|
||||
|
@ -914,7 +916,7 @@ class Workflow(StorableObject):
|
|||
|
||||
reject = ChoiceWorkflowStatusItem()
|
||||
reject.id = '_reject'
|
||||
reject.label = _('Reject')
|
||||
reject.label = force_text(_('Reject'))
|
||||
reject.by = ['_receiver']
|
||||
reject.status = rejected_status.id
|
||||
reject.parent = new_status
|
||||
|
@ -922,7 +924,7 @@ class Workflow(StorableObject):
|
|||
|
||||
finish = ChoiceWorkflowStatusItem()
|
||||
finish.id = '_finish'
|
||||
finish.label = _('Finish')
|
||||
finish.label = force_text(_('Finish'))
|
||||
finish.by = ['_receiver']
|
||||
finish.status = finished_status.id
|
||||
finish.parent = accepted_status
|
||||
|
@ -1074,7 +1076,7 @@ class XmlSerialisable:
|
|||
|
||||
# if the roles are managed by the idp, don't try further.
|
||||
if get_publisher() and get_cfg('sp', {}).get('idp-manage-roles') is True:
|
||||
raise WorkflowImportError(N_('Unknown referenced role (%s)'), (value,))
|
||||
raise WorkflowImportError(_('Unknown referenced role (%s)'), (value,))
|
||||
|
||||
# and if there's no match, create a new role
|
||||
role = get_publisher().role_class()
|
||||
|
@ -1916,7 +1918,7 @@ class WorkflowStatusItem(XmlSerialisable):
|
|||
return changed
|
||||
|
||||
def render_as_line(self):
|
||||
label = _(self.description)
|
||||
label = self.description
|
||||
details = self.get_line_details()
|
||||
if details:
|
||||
label += ' (%s)' % details
|
||||
|
@ -2199,7 +2201,7 @@ class WorkflowStatusItem(XmlSerialisable):
|
|||
if not targets and formdata: # do not log in presentation context: formdata is needed
|
||||
message = _(
|
||||
'reference to invalid status %(target)s in status %(status)s, ' 'action %(status_item)s'
|
||||
) % {'target': self.status, 'status': self.parent.name, 'status_item': _(self.description)}
|
||||
) % {'target': self.status, 'status': self.parent.name, 'status_item': self.description}
|
||||
get_publisher().record_error(message, formdata=formdata, status_item=self)
|
||||
|
||||
return targets
|
||||
|
@ -2212,9 +2214,9 @@ class WorkflowStatusItem(XmlSerialisable):
|
|||
roles = self.parent.parent.render_list_of_roles(self.by)
|
||||
label += ' %s %s' % (_('by'), roles)
|
||||
if getattr(self, 'status', None) == '_previous':
|
||||
label += ' ' + _('(to last marker)')
|
||||
label += ' ' + str(_('(to last marker)'))
|
||||
if getattr(self, 'set_marker_on_status', False):
|
||||
label += ' ' + _('(and set marker)')
|
||||
label += ' ' + str(_('(and set marker)'))
|
||||
else:
|
||||
label = self.render_as_line()
|
||||
return label
|
||||
|
@ -2281,7 +2283,7 @@ class WorkflowStatusItem(XmlSerialisable):
|
|||
value = xml_node_text(elem)
|
||||
mail_template = MailTemplate.get_by_slug(value)
|
||||
if not mail_template:
|
||||
raise WorkflowImportError(N_('Unknown referenced mail template (%s)'), (value,))
|
||||
raise WorkflowImportError(_('Unknown referenced mail template (%s)'), (value,))
|
||||
self.mail_template = value
|
||||
return
|
||||
|
||||
|
@ -2471,7 +2473,7 @@ def register_item_class(klass):
|
|||
|
||||
|
||||
class CommentableWorkflowStatusItem(WorkflowStatusItem):
|
||||
description = N_('Comment')
|
||||
description = _('Comment')
|
||||
key = 'commentable'
|
||||
category = 'interaction'
|
||||
endpoint = False
|
||||
|
@ -2542,11 +2544,11 @@ class CommentableWorkflowStatusItem(WorkflowStatusItem):
|
|||
super().add_parameters_widgets(form, parameters, prefix=prefix, formdef=formdef, **kwargs)
|
||||
if 'label' in parameters:
|
||||
if self.label is None:
|
||||
self.label = _('Comment')
|
||||
self.label = str(_('Comment'))
|
||||
form.add(StringWidget, '%slabel' % prefix, size=40, title=_('Label'), value=self.label)
|
||||
if 'button_label' in parameters:
|
||||
if self.button_label == 0:
|
||||
self.button_label = _('Add Comment')
|
||||
self.button_label = str(_('Add Comment'))
|
||||
form.add(
|
||||
StringWidget,
|
||||
'%sbutton_label' % prefix,
|
||||
|
@ -2610,7 +2612,7 @@ register_item_class(CommentableWorkflowStatusItem)
|
|||
|
||||
|
||||
class ChoiceWorkflowStatusItem(WorkflowStatusJumpItem):
|
||||
description = N_('Manual Jump')
|
||||
description = _('Manual Jump')
|
||||
key = 'choice'
|
||||
endpoint = False
|
||||
waitpoint = True
|
||||
|
@ -2642,7 +2644,7 @@ class ChoiceWorkflowStatusItem(WorkflowStatusJumpItem):
|
|||
if self.label and to_status:
|
||||
more = ''
|
||||
if self.set_marker_on_status:
|
||||
more += ' ' + _('(and set marker)')
|
||||
more += ' ' + str(_('(and set marker)'))
|
||||
if self.by:
|
||||
return _('"%(label)s", to %(to)s, by %(by)s%(more)s') % {
|
||||
'label': self.get_label(),
|
||||
|
@ -2749,7 +2751,7 @@ register_item_class(ChoiceWorkflowStatusItem)
|
|||
|
||||
|
||||
class JumpOnSubmitWorkflowStatusItem(WorkflowStatusJumpItem):
|
||||
description = N_('On Submit Jump')
|
||||
description = _('On Submit Jump')
|
||||
key = 'jumponsubmit'
|
||||
ok_in_global_action = False
|
||||
|
||||
|
@ -2777,7 +2779,7 @@ register_item_class(JumpOnSubmitWorkflowStatusItem)
|
|||
|
||||
|
||||
class SendmailWorkflowStatusItem(WorkflowStatusItem):
|
||||
description = N_('Email')
|
||||
description = _('Email')
|
||||
key = 'sendmail'
|
||||
category = 'interaction'
|
||||
support_substitution_variables = True
|
||||
|
@ -3061,7 +3063,7 @@ def template_on_context(context=None, template=None, **kwargs):
|
|||
|
||||
|
||||
class SendSMSWorkflowStatusItem(WorkflowStatusItem):
|
||||
description = N_('SMS')
|
||||
description = _('SMS')
|
||||
key = 'sendsms'
|
||||
category = 'interaction'
|
||||
support_substitution_variables = True
|
||||
|
@ -3129,7 +3131,7 @@ register_item_class(SendSMSWorkflowStatusItem)
|
|||
|
||||
|
||||
class DisplayMessageWorkflowStatusItem(WorkflowStatusItem):
|
||||
description = N_('Alert')
|
||||
description = _('Alert')
|
||||
key = 'displaymsg'
|
||||
category = 'interaction'
|
||||
support_substitution_variables = True
|
||||
|
@ -3150,7 +3152,7 @@ class DisplayMessageWorkflowStatusItem(WorkflowStatusItem):
|
|||
parts.append(_('with actions'))
|
||||
if self.to:
|
||||
parts.append(_('for %s') % self.render_list_of_roles(self.to))
|
||||
return ', '.join(parts)
|
||||
return ', '.join([str(x) for x in parts])
|
||||
|
||||
def get_message(self, filled, position='top'):
|
||||
if not (self.message and self.position == position and filled.is_for_current_user(self.to)):
|
||||
|
@ -3234,7 +3236,7 @@ register_item_class(DisplayMessageWorkflowStatusItem)
|
|||
|
||||
|
||||
class RedirectToStatusWorkflowStatusItem(WorkflowStatusItem):
|
||||
description = N_('Status Page Redirection')
|
||||
description = _('Status Page Redirection')
|
||||
key = 'redirectstatus'
|
||||
ok_in_global_action = False
|
||||
|
||||
|
@ -3262,7 +3264,7 @@ class RedirectToStatusWorkflowStatusItem(WorkflowStatusItem):
|
|||
|
||||
|
||||
class EditableWorkflowStatusItem(WorkflowStatusItem):
|
||||
description = N_('Edition')
|
||||
description = _('Edition')
|
||||
key = 'editable'
|
||||
category = 'formdata-action'
|
||||
endpoint = False
|
||||
|
|
Loading…
Reference in New Issue