diff --git a/tests/admin_pages/test_i18n.py b/tests/admin_pages/test_i18n.py index 8b2c9fba5..747aa75a6 100644 --- a/tests/admin_pages/test_i18n.py +++ b/tests/admin_pages/test_i18n.py @@ -312,3 +312,50 @@ def test_i18n_pagination(pub): resp = resp.click('20') resp = resp.click('3') assert 'offset=40' in resp.request.url + + +def test_i18n_mark_as_non_translatabe(pub): + TranslatableMessage.wipe() + Workflow.wipe() + FormDef.wipe() + BlockDef.wipe() + Category.wipe() + CardDef.wipe() + MailTemplate.wipe() + create_superuser(pub) + workflow = Workflow(name='workflow') + workflow.add_status('First Status') + workflow.add_status('Second Status') + workflow.store() + + app = login(get_app(pub)) + # first time goes to scanning + resp = app.get('/backoffice/i18n/', status=302) + resp = resp.follow() + resp = resp.click('Go to multilinguism page') + # second time, the page stays on + resp = app.get('/backoffice/i18n/', status=200) + + assert TranslatableMessage.count() == 2 # First Status / Second Status + assert resp.pyquery('tr').length == 2 + + # check form filter + assert resp.form['lang'].value == 'fr' + resp.form['q'] = 'First' + resp = resp.form.submit() + assert resp.pyquery('tr').length == 1 + + # mark a message as non translatable + resp = resp.click('edit', index=0) + resp.form['non_translatable'].checked = True + resp = resp.form.submit('submit').follow() + msg = TranslatableMessage.select([Equal('string', 'First Status')])[0] + assert msg.translatable is False + + resp = app.get('/backoffice/i18n/', status=200) + assert resp.pyquery('tr').length == 1 + assert resp.pyquery('tr td:first-child').text() == 'Second Status' + resp.form['non_translatable'].checked = True + resp = resp.form.submit('submit') + assert resp.pyquery('tr').length == 1 + assert resp.pyquery('tr td:first-child').text() == 'First Status' diff --git a/wcs/backoffice/i18n.py b/wcs/backoffice/i18n.py index 858c2adc2..83af15a7d 100644 --- a/wcs/backoffice/i18n.py +++ b/wcs/backoffice/i18n.py @@ -32,7 +32,7 @@ from wcs.qommon import _, errors, get_cfg, misc, ods, template from wcs.qommon.afterjobs import AfterJob from wcs.qommon.backoffice.listing import pagination_links from wcs.qommon.backoffice.menu import html_top -from wcs.qommon.form import FileWidget, Form, RadiobuttonsWidget, TextWidget +from wcs.qommon.form import CheckboxWidget, FileWidget, Form, RadiobuttonsWidget, TextWidget from wcs.qommon.storage import Equal, FtsMatch, ILike, Or from wcs.workflows import Workflow @@ -69,6 +69,7 @@ class I18nDirectory(Directory): get_response().breadcrumb.append(('i18n/', _('Multilinguism'))) criterias = [] + criterias.append(Equal('translatable', not (bool(get_request().form.get('non_translatable'))))) if get_request().form.get('q'): search_term = get_request().form.get('q') criterias.append(Or([ILike('string', search_term), FtsMatch(search_term)])) @@ -85,6 +86,7 @@ class I18nDirectory(Directory): 'pagination_links': pagination_links(offset, limit, total_count, load_js=False), 'messages': TranslatableMessage.select(criterias, offset=offset, limit=limit, order_by='string'), 'query': get_request().get_query(), + 'non_translatable': get_request().form.get('non-translatable'), } get_response().add_javascript(['popup.js']) @@ -211,6 +213,12 @@ class MessageDirectory(Directory): rows = min(10, max(2, self.msg.string.count('\n'))) attr = 'string_%s' % self.lang form.add(TextWidget, 'translation', value=getattr(self.msg, attr), rows=rows) + form.add( + CheckboxWidget, + 'non_translatable', + title=_('Mark as non-translatable'), + value=not (self.msg.translatable), + ) form.add_submit('submit', _('Submit')) form.add_submit('cancel', _('Cancel')) if form.get_widget('cancel').parse(): @@ -218,6 +226,7 @@ class MessageDirectory(Directory): if form.is_submitted() and not form.has_errors(): setattr(self.msg, attr, form.get_widget('translation').parse()) + self.msg.translatable = not (form.get_widget('non_translatable').parse()) self.msg.store() update_digests() return redirect('../../?' + get_request().get_query()) diff --git a/wcs/i18n.py b/wcs/i18n.py index eba597b4a..6548cb884 100644 --- a/wcs/i18n.py +++ b/wcs/i18n.py @@ -22,6 +22,7 @@ class TranslatableMessage(sql.TranslatableMessage): string = None context = None locations = None # list + translatable = True def translations(self): return {x.split('_', 1)[1]: getattr(self, x) for x in self.__dict__ if x.startswith('string_')} diff --git a/wcs/sql.py b/wcs/sql.py index 46a065ee2..337ba9b8c 100644 --- a/wcs/sql.py +++ b/wcs/sql.py @@ -4215,6 +4215,7 @@ class TranslatableMessage(SqlMixin): ('context', 'varchar'), ('locations', 'varchar[]'), ('last_update_time', 'timestamptz'), + ('translatable', 'boolean'), ] id = None @@ -4238,6 +4239,7 @@ class TranslatableMessage(SqlMixin): context VARCHAR, locations VARCHAR[], last_update_time TIMESTAMPTZ, + translatable BOOLEAN DEFAULT TRUE, fts TSVECTOR )''' % table_name @@ -4250,6 +4252,9 @@ class TranslatableMessage(SqlMixin): ) existing_fields = {x[0] for x in cur.fetchall()} + if 'translatable' not in existing_fields: + cur.execute('''ALTER TABLE %s ADD COLUMN translatable BOOLEAN DEFAULT(TRUE)''' % table_name) + # add columns for translations for field in cls.get_data_fields(): if field not in existing_fields: @@ -4306,7 +4311,10 @@ class TranslatableMessage(SqlMixin): @guard_postgres def load_as_catalog(cls, language): conn, cur = get_connection_and_cursor() - sql_statement = 'SELECT context, string, string_%s FROM %s' % (language, cls._table_name) + sql_statement = 'SELECT context, string, string_%s FROM %s WHERE translatable = TRUE' % ( + language, + cls._table_name, + ) cur.execute(sql_statement) catalog = {(x[0], x[1]): x[2] for x in cur.fetchall()} conn.commit() @@ -5060,7 +5068,7 @@ def get_period_total( # latest migration, number + description (description is not used # programmaticaly but will make sure git conflicts if two migrations are # separately added with the same number) -SQL_LEVEL = (78, 'add audit table') +SQL_LEVEL = (79, 'add translatable column to TranslatableMessage table') def migrate_global_views(conn, cur): @@ -5239,8 +5247,9 @@ def migrate(): # 67: re-migrate legacy tokens do_tokens_table() migrate_legacy_tokens() - if sql_level < 68: + if sql_level < 79: # 68: multilinguism + # 79: add translatable column to TranslatableMessage table TranslatableMessage.do_table() if sql_level < 72: # 72: add testdef table diff --git a/wcs/templates/wcs/backoffice/i18n.html b/wcs/templates/wcs/backoffice/i18n.html index dbfaa3819..2aa3974fe 100644 --- a/wcs/templates/wcs/backoffice/i18n.html +++ b/wcs/templates/wcs/backoffice/i18n.html @@ -14,7 +14,12 @@ {{ block.super }}
- + + + +
{% trans "Language:" %} {% for language in supported_languages %}