diff --git a/CHANGELOG b/CHANGELOG
index 03b034e1b3..ac743679ea 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,3 +1,4 @@
+* Add language configuration wizard
* Allow copying attachments and notes to created records
* Add link button on form
* Support explicit delete and remove for saving and on_change xxx2Many
diff --git a/trytond/ir/__init__.py b/trytond/ir/__init__.py
index 523b3bcc95..33dcc0ab35 100644
--- a/trytond/ir/__init__.py
+++ b/trytond/ir/__init__.py
@@ -71,6 +71,7 @@ def register():
note.NoteRead,
cron.Cron,
lang.Lang,
+ lang.LangConfigStart,
export.Export,
export.ExportLine,
rule.RuleGroup,
@@ -105,6 +106,7 @@ def register():
module.ModuleConfigWizard,
module.ModuleActivateUpgrade,
module.ModuleConfig,
+ lang.LangConfig,
module='ir', type_='wizard')
Pool.register(
model.ModelGraph,
diff --git a/trytond/ir/lang.py b/trytond/ir/lang.py
index 64a8843825..a9af110662 100644
--- a/trytond/ir/lang.py
+++ b/trytond/ir/lang.py
@@ -8,18 +8,17 @@ from ast import literal_eval
from sql import Table
from ..model import ModelView, ModelSQL, DeactivableMixin, fields, Check
+from ..modules import create_graph, load_translations
from ..cache import Cache
from ..transaction import Transaction
from ..pool import Pool
+from ..pyson import Eval
from ..exceptions import UserError
from ..i18n import gettext
+from ..wizard import Wizard, StateView, Button, StateTransition
Transaction.cache_keys.add('translate_name')
-__all__ = [
- 'Lang',
- ]
-
class GroupingError(UserError):
pass
@@ -43,7 +42,7 @@ class Lang(DeactivableMixin, ModelSQL, ModelView):
name = fields.Char('Name', required=True, translate=True)
code = fields.Char('Code', required=True,
help="RFC 4646 tag: http://tools.ietf.org/html/rfc4646")
- translatable = fields.Boolean('Translatable')
+ translatable = fields.Boolean('Translatable', readonly=True)
parent = fields.Char("Parent Code", help="Code of the exceptional parent")
direction = fields.Selection([
('ltr', 'Left-to-right'),
@@ -87,6 +86,12 @@ class Lang(DeactivableMixin, ModelSQL, ModelView):
Check(table, table.decimal_point != table.thousands_sep),
'decimal_point and thousands_sep must be different!'),
]
+ cls._buttons.update({
+ 'load_translations': {},
+ 'unload_translations': {
+ 'invisible': ~Eval('translatable', False),
+ },
+ })
@classmethod
def search_rec_name(cls, name, clause):
@@ -186,6 +191,37 @@ class Lang(DeactivableMixin, ModelSQL, ModelView):
def default_n_sep_by_space(cls):
return False
+ @classmethod
+ @ModelView.button
+ def load_translations(cls, languages):
+ pool = Pool()
+ Module = pool.get('ir.module')
+ codes = set()
+ cls.write(languages, {'translatable': True})
+ for language in languages:
+ code = language.code
+ while code:
+ codes.add(code)
+ code = get_parent_language(code)
+ modules = Module.search([
+ ('state', '=', 'activated'),
+ ])
+ modules = [m.name for m in modules]
+ for node in create_graph(modules):
+ load_translations(pool, node, codes)
+
+ @classmethod
+ @ModelView.button
+ def unload_translations(cls, languages):
+ pool = Pool()
+ Translation = pool.get('ir.translation')
+ cls.write(languages, {'translatable': False})
+ languages = [l.code for l in languages]
+ Translation.delete(Translation.search([
+ ('lang', 'in', languages),
+ ('module', '!=', None),
+ ]))
+
@classmethod
def validate(cls, languages):
super(Lang, cls).validate(languages)
@@ -503,6 +539,42 @@ class Lang(DeactivableMixin, ModelSQL, ModelView):
return value.strftime(format)
+class LangConfigStart(ModelView):
+ 'Language Configuration Start'
+ __name__ = 'ir.lang.config.start'
+
+ languages = fields.Many2Many('ir.lang', None, None, "Languages")
+
+ @classmethod
+ def default_languages(cls):
+ pool = Pool()
+ Lang = pool.get('ir.lang')
+ return [x.id for x in Lang.search([('translatable', '=', True)])]
+
+
+class LangConfig(Wizard):
+ 'Configure languages'
+ __name__ = 'ir.lang.config'
+
+ start = StateView('ir.lang.config.start',
+ 'ir.lang_config_start_view_form', [
+ Button('Cancel', 'end', 'tryton-cancel'),
+ Button('Load', 'load', 'tryton-ok', default=True),
+ ])
+ load = StateTransition()
+
+ def transition_load(self):
+ pool = Pool()
+ Lang = pool.get('ir.lang')
+ Lang.load_translations(list(self.start.languages))
+ untranslated_languages = Lang.search([
+ ('id', 'not in', [l.id for l in self.start.languages]),
+ ('translatable', '=', True),
+ ])
+ Lang.unload_translations(untranslated_languages)
+ return 'end'
+
+
def get_parent_language(code):
if code not in _parents:
# Use SQL because it is used by load_module_graph
diff --git a/trytond/ir/lang.xml b/trytond/ir/lang.xml
index 9bd0b5104f..a0280520a5 100644
--- a/trytond/ir/lang.xml
+++ b/trytond/ir/lang.xml
@@ -495,5 +495,34 @@ this repository contains the full copyright notices and license terms. -->
+
+