10
10
from xml.dom import minidom
11
11
from difflib import SequenceMatcher
13
from trytond.osv import fields, OSV, Cacheable
14
from trytond.wizard import Wizard, WizardOSV
13
from trytond.model import ModelView, ModelSQL, fields
14
from trytond.model.cacheable import Cacheable
15
from trytond.wizard import Wizard
15
16
from trytond import tools
16
from trytond import pooler
17
from trytond.tools import file_open
18
from trytond.backend import TableHandler
18
21
TRANSLATION_TYPE = [
19
22
('field', 'Field'),
62
64
self._max_len = 10240
64
def _auto_init(self, cursor, module_name):
65
super(Translation, self)._auto_init(cursor, module_name)
66
cursor.execute('SELECT indexname FROM pg_indexes ' \
67
'WHERE indexname = ' \
68
'\'ir_translation_lang_type_name_index\'')
69
if not cursor.rowcount:
70
cursor.execute('CREATE INDEX ' \
71
'ir_translation_lang_type_name_index ' \
72
'ON ir_translation (lang, type, name)')
73
cursor.execute('SELECT indexname FROM pg_indexes ' \
74
'WHERE indexname = ' \
75
'\'ir_translation_lang_type_name_src_index\'')
76
if not cursor.rowcount:
77
cursor.execute('CREATE INDEX ' \
78
'ir_translation_lang_type_name_src_index ' \
79
'ON ir_translation (lang, type, name, src)')
66
def init(self, cursor, module_name):
67
super(Translation, self).init(cursor, module_name)
69
table = TableHandler(cursor, self, module_name)
70
table.index_action(['lang', 'type', 'name'], 'add')
71
table.index_action(['lang', 'type', 'name', 'src'], 'add')
81
73
def default_fuzzy(self, cursor, user, context=None):
108
100
def _get_ids(self, cursor, name, ttype, lang, ids):
101
model_fields_obj = self.pool.get('ir.model.field')
102
model_obj = self.pool.get('ir.model')
109
104
translations, to_fetch = {}, []
110
105
name = unicode(name)
111
106
ttype = unicode(ttype)
112
107
lang = unicode(lang)
113
if name.split(',')[0] == 'ir.model.field':
114
model_fields_obj = self.pool.get('ir.model.field')
108
if name.split(',')[0] in ('ir.model.field', 'ir.model'):
115
109
field_name = name.split(',')[1]
116
if field_name == 'field_description':
110
if name.split(',')[0] == 'ir.model.field':
111
if field_name == 'field_description':
115
records = model_fields_obj.browse(cursor, 0, ids)
120
fields = model_fields_obj.read(cursor, 0, ids,
118
records = model_obj.browse(cursor, 0, ids)
125
name = field['model'][1] + ',' + field['name']
121
for record in records:
122
if ttype in ('field', 'help'):
123
name = record.model.model + ',' + record.name
125
name = record.model + ',' + field_name
126
126
trans_args.append((name, ttype, lang, None))
127
127
self._get_sources(cursor, trans_args)
130
name = field['model'][1] + ',' + field['name']
131
translations[field['id']] = self._get_source(cursor,
129
for record in records:
130
if ttype in ('field', 'help'):
131
name = record.model.model + ',' + record.name
133
name = record.model + ',' + field_name
134
translations[record.id] = self._get_source(cursor,
132
135
name, ttype, lang)
133
136
return translations
134
137
for obj_id in ids:
139
142
to_fetch.append(obj_id)
141
cursor.execute('SELECT res_id, value ' \
142
'FROM ir_translation ' \
146
'AND value != \'\' ' \
147
'AND value IS NOT NULL ' \
148
'AND fuzzy = false ' \
149
'AND res_id in (' + \
150
','.join([str(x) for x in to_fetch]) + ')',
152
for res_id, value in cursor.fetchall():
153
self.add(cursor, (lang, ttype, name, res_id), value)
154
translations[res_id] = value
144
for i in range(0, len(to_fetch), cursor.IN_MAX):
145
sub_to_fetch = to_fetch[i:i + cursor.IN_MAX]
146
cursor.execute('SELECT res_id, value ' \
147
'FROM ir_translation ' \
151
'AND value != \'\' ' \
152
'AND value IS NOT NULL ' \
153
'AND fuzzy = false ' \
154
'AND res_id in (' + \
155
','.join([str(x) for x in sub_to_fetch]) + ')',
157
for res_id, value in cursor.fetchall():
158
self.add(cursor, (lang, ttype, name, res_id), value)
159
translations[res_id] = value
155
160
for res_id in ids:
156
161
if res_id not in translations:
157
162
self.add(cursor, (lang, ttype, name, res_id), False)
159
164
return translations
161
166
def _set_ids(self, cursor, user, name, ttype, lang, ids, value):
167
model_fields_obj = self.pool.get('ir.model.field')
168
model_obj = self.pool.get('ir.model')
162
170
model_name, field_name = name.split(',')
163
if model_name == 'ir.model.field':
164
model_fields_obj = self.pool.get('ir.model.field')
165
if field_name == 'field_description':
171
if model_name in ('ir.model.field', 'ir.model'):
172
if model_name == 'ir.model.field':
173
if field_name == 'field_description':
177
records = model_fields_obj.browse(cursor, user, ids)
169
for field in model_fields_obj.browse(cursor, user, ids):
170
name = field.model + ',' + field.name
180
records = model_obj.browse(cursor, user, ids)
181
for record in records:
182
if ttype in ('field', 'help'):
183
name = record.model + ',' + record.name
171
184
ids2 = self.search(cursor, user, [
172
185
('lang', '=', lang),
173
186
('type', '=', ttype),
281
295
res[(name, ttype, lang, source)] = False
282
296
self.add(cursor, (lang, ttype, name, source), False)
286
clause += '(lang = %s ' \
298
clause += [('(lang = %s ' \
287
299
'AND type = %s ' \
288
300
'AND name = %s ' \
289
301
'AND src = %s ' \
290
302
'AND value != \'\' ' \
291
303
'AND value IS NOT NULL ' \
293
value.extend((lang, ttype, str(name), source))
304
'AND fuzzy = false ' \
306
(lang, ttype, str(name), source))]
295
clause += '(lang = %s ' \
308
clause += [('(lang = %s ' \
296
309
'AND type = %s ' \
297
310
'AND name = %s ' \
298
311
'AND value != \'\' ' \
299
312
'AND value IS NOT NULL ' \
301
value.extend((lang, ttype, str(name)))
313
'AND fuzzy = false ' \
315
(lang, ttype, str(name)))]
303
cursor.execute('SELECT lang, type, name, src, value ' \
304
'FROM ir_translation ' \
305
'WHERE ' + clause, value)
306
for lang, ttype, name, source, value in cursor.fetchall():
307
if (name, ttype, lang, source) not in args:
309
res[(name, ttype, lang, source)] = value
310
self.add(cursor, (lang, ttype, name, source), value)
317
for i in range(0, len(clause), cursor.IN_MAX):
318
sub_clause = clause[i:i + cursor.IN_MAX]
319
cursor.execute('SELECT lang, type, name, src, value ' \
320
'FROM ir_translation ' \
321
'WHERE ' + ' OR '.join([x[0] for x in sub_clause]),
322
reduce(lambda x, y: x + y, [x[1] for x in sub_clause]))
323
for lang, ttype, name, source, value in cursor.fetchall():
324
if (name, ttype, lang, source) not in args:
326
res[(name, ttype, lang, source)] = value
327
self.add(cursor, (lang, ttype, name, source), value)
313
330
def delete(self, cursor, user, ids, context=None):
373
390
reader = csv.reader(datas)
374
391
for row in reader:
396
module_translation_ids = self.search(cursor, user, [
398
('module', '=', module),
400
for translation in self.browse(cursor, user, module_translation_ids,
402
if translation.type in ('odt', 'view', 'wizard_button',
403
'selection', 'error'):
404
key = (translation.name, translation.res_id, translation.type,
406
elif translation.type in ('field', 'model','help'):
407
key = (translation.name, translation.res_id, translation.type)
409
raise Exception('Unknow translation type: %s' % translation.type)
410
key2ids.setdefault(key, []).append(translation.id)
411
id2translation[translation.id] = translation
376
413
for row in reader:
414
ttype = row[0].decode('utf-8')
415
name = row[1].decode('utf-8')
416
res_id = row[2].decode('utf-8')
417
src = row[3].decode('utf-8')
418
value = row[4].decode('utf-8')
419
fuzzy = bool(int(row[5]))
385
421
model = name.split(',')[0]
386
422
if model in fs_id2db_id:
394
430
if ttype in ('odt', 'view', 'wizard_button', 'selection', 'error'):
395
ids = self.search(cursor, user, [
397
('res_id', '=', res_id),
399
('type', '=', ttype),
431
key = (name, res_id, ttype, src)
402
432
elif ttype in('field', 'model','help'):
403
ids = self.search(cursor, user, [
405
('res_id', '=', res_id),
407
('type', '=', ttype),
433
key = (name, res_id, ttype)
410
435
raise Exception('Unknow translation type: %s' % ttype)
436
ids = key2ids.get(key, [])
413
translation_ids.append(self.create(cursor, user, {
439
translation_ids.append(self.create(cursor, 0, {
415
441
'res_id': res_id,
421
447
'module': module,
424
cursor.execute('SELECT id FROM ir_translation ' \
425
'WHERE (write_uid IS NULL OR write_uid = 0) ' \
427
'(' + ','.join(['%s' for x in ids]) + ')',
429
ids2 = [x[0] for x in cursor.fetchall()]
451
for translation_id in ids:
452
translation = id2translation[translation_id]
453
if translation.value != value \
454
or translation.fuzzy != fuzzy:
455
ids2.append(translation.id)
431
self.write(cursor, user, ids2, {
457
self.write(cursor, 0, ids2, {
435
461
translation_ids += ids
437
cursor.execute('DELETE FROM ir_translation ' \
438
'WHERE module = %s ' \
441
'(' + ','.join(['%s' for x in translation_ids]) + ')',
442
(module, lang) + tuple(translation_ids))
464
for i in range(0, len(translation_ids), cursor.IN_MAX):
465
sub_translation_ids = translation_ids[i:i + cursor.IN_MAX]
466
cursor.execute('DELETE FROM ir_translation ' \
467
'WHERE module = %s ' \
469
'AND id NOT IN (' + \
470
','.join(['%s' for x in sub_translation_ids]) + \
472
(module, lang) + tuple(sub_translation_ids))
443
473
return len(translation_ids)
445
475
def translation_export(self, cursor, user, lang, module, context=None):
446
476
model_data_obj = self.pool.get('ir.model.data')
448
481
model_data_ids = model_data_obj.search(cursor, user, [
449
482
('module', '=', module),
450
483
], context=context)
563
600
def _set_report_translation(self, cursor, user, data, context):
564
601
report_obj = self.pool.get('ir.action.report')
565
report_ids = report_obj.search(cursor, user, [], context=context)
604
ctx['active_test'] = False
606
report_ids = report_obj.search(cursor, user, [], context=ctx)
567
608
if not report_ids:
575
616
'AND type = %s ' \
576
617
'AND name = %s ' \
577
618
'AND module = %s',
578
('en_US', 'odt', report.report_name, report.module))
619
('en_US', 'odt', report.report_name, report.module or ''))
579
620
trans_reports = {}
580
621
for trans in cursor.dictfetchall():
581
622
trans_reports[trans['src']] = trans
584
content = report.report_content
590
content_io = StringIO.StringIO(report.report_content)
591
content_z = zipfile.ZipFile(content_io, mode='r')
593
content_xml = content_z.read('content.xml')
594
document = dom.minidom.parseString(content_xml)
595
strings = self._translate_report(document.documentElement)
597
style_xml = content_z.read('styles.xml')
598
document = dom.minidom.parseString(style_xml)
599
strings += self._translate_report(document.documentElement)
628
odt_content = file_open(report.report.replace('/', os.sep),
630
for content in (report.report_content_data, odt_content):
634
content_io = StringIO.StringIO(content)
635
content_z = zipfile.ZipFile(content_io, mode='r')
637
content_xml = content_z.read('content.xml')
638
document = dom.minidom.parseString(content_xml)
639
strings = self._translate_report(document.documentElement)
641
style_xml = content_z.read('styles.xml')
642
document = dom.minidom.parseString(style_xml)
643
strings += self._translate_report(document.documentElement)
601
645
style_content = None
603
style_content = report.style_content
647
style_content = base64.decodestring(report.style_content)
650
694
cursor.execute('DELETE FROM ir_translation ' \
651
695
'WHERE name = %s ' \
652
696
'AND type = %s ' \
653
698
'AND src NOT IN ' \
654
699
'(' + ','.join(['%s' for x in strings]) + ')',
655
(report.report_name, 'odt') + tuple(strings))
700
(report.report_name, 'odt', report.module) + \
658
704
ReportTranslationSet()
661
class TranslationCleanInit(WizardOSV):
707
class TranslationCleanInit(ModelView):
662
708
'Clean translation init'
663
709
_name = 'ir.translation.clean.init'
664
710
_description = __doc__
735
783
elif translation.type == 'model':
737
model_name, _ = translation.name.split(',', 1)
785
model_name, field_name = translation.name.split(',', 1)
738
786
except ValueError:
739
787
to_delete.append(translation.id)
741
789
if model_name not in self.pool.object_name_list():
742
790
to_delete.append(translation.id)
792
if translation.res_id:
793
model_obj = self.pool.get(model_name)
794
if field_name not in model_obj._columns:
795
to_delete.append(translation.id)
797
field = model_obj._columns[field_name]
798
if not hasattr(field, 'translate') or \
800
to_delete.append(translation.id)
802
elif field_name not in ('name'):
803
to_delete.append(translation.id)
744
805
elif translation.type == 'odt':
745
806
if not report_obj.search(cursor, user, [
746
807
('report_name', '=', translation.name),
748
809
to_delete.append(translation.id)
750
811
elif translation.type == 'selection':
761
822
to_delete.append(translation.id)
763
824
field = model_obj._columns[field_name]
764
if not hasattr(field, 'selection') or not field.selection:
825
if not hasattr(field, 'selection') or not field.selection \
826
or not ((hasattr(field, 'translate_selection') and \
827
field.translate_selection) or True):
765
828
to_delete.append(translation.id)
767
830
if isinstance(field.selection, (tuple, list)) \
833
906
if translation.src not in errors:
834
907
to_delete.append(translation.id)
836
elif model_name in pool_wizard.object_name_list():
837
wizard_obj = pool_wizard.get(model_name)
909
elif model_name in self.pool.object_name_list(type='wizard'):
910
wizard_obj = self.pool.get(model_name, type='wizard')
838
911
errors = wizard_obj._error_messages.values()
839
912
if translation.src not in errors:
840
913
to_delete.append(translation.id)
912
985
'AND type in (\'field\', \'model\', \'help\')',
913
986
(data['form']['lang'],))
914
987
for row in cursor.dictfetchall():
915
translation_obj.create(cursor, user, {
988
translation_obj.create(cursor, 0, {
916
989
'name': row['name'],
917
990
'res_id': row['res_id'],
918
991
'lang': data['form']['lang'],
940
1013
'AND lang = %s',
941
1014
(row['src'], row['name'], row['res_id'], row['type'],
942
1015
data['form']['lang']))
1017
cursor.execute('SELECT src, MAX(value) AS value FROM ir_translation ' \
1018
'WHERE lang = %s ' \
1020
'SELECT src FROM ir_translation ' \
1021
'WHERE (value = \'\' OR value IS NULL) ' \
1023
'AND value != \'\' AND value IS NOT NULL ' \
1024
'GROUP BY src', (data['form']['lang'], data['form']['lang']))
1026
for row in cursor.dictfetchall():
1027
cursor.execute('UPDATE ir_translation ' \
1028
'SET fuzzy = True, ' \
1031
'AND (value = \'\' OR value IS NULL) ' \
1032
'AND lang = %s', (row['value'], row['src'],
1033
data['form']['lang']))
943
1035
cursor.execute('UPDATE ir_translation ' \
944
1036
'SET fuzzy = False ' \
945
1037
'WHERE (value = \'\' OR value IS NULL) ' \
999
1091
def get_language(self, cursor, user, context):
1000
1092
lang_obj = self.pool.get('ir.lang')
1001
lang_ids = lang_obj.search(cursor, user, [], context=context)
1093
lang_ids = lang_obj.search(cursor, user, [
1094
('translatable', '=', True),
1002
1096
langs = lang_obj.browse(cursor, user, lang_ids, context=context)
1003
1097
res = [(lang.code, lang.name) for lang in langs]
1006
1100
def get_module(self, cursor, user, context):
1007
1101
module_obj = self.pool.get('ir.module.module')
1008
module_ids = module_obj.search(cursor, user, [], context=context)
1102
module_ids = module_obj.search(cursor, user, [
1103
('state', 'in', ['installed', 'to upgrade', 'to remove']),
1009
1105
modules = module_obj.browse(cursor, user, module_ids, context=context)
1010
1106
res = [(module.name, module.name) for module in modules]