308
308
if line.startswith('#~ '):
310
310
if line.startswith('#:'):
311
# Process the `reference` comments. Each line can specify
312
# multiple targets (e.g. model, view, code, selection,
313
# ...). For each target, we will return an additional
311
315
for lpart in line[2:].strip().split(' '):
312
316
trans_info = lpart.strip().split(':',2)
313
317
if trans_info and len(trans_info) == 2:
356
360
line = self.lines.pop(0).strip()
358
362
if tmp_tnrs and not fuzzy:
363
# Use the first target for the current entry (returned at the
364
# end of this next() call), and keep the others to generate
365
# additional entries (returned the next next() calls).
359
366
type, name, res_id = tmp_tnrs.pop(0)
360
367
for t, n, r in tmp_tnrs:
361
368
self.tnrs.append((t, n, r, source, trad))
897
904
# lets create the language with locale information
898
905
lang_obj.load_lang(cr, 1, lang=lang, lang_name=lang_name)
907
# Parse also the POT: it will possibly provide additional targets.
908
# (Because the POT comments are correct on Launchpad but not the
909
# PO comments due to a Launchpad limitation.)
901
912
# now, the serious things: we read the language file
909
920
elif fileformat == 'po':
910
921
reader = TinyPoFile(fileobj)
911
922
f = ['type', 'name', 'res_id', 'src', 'value']
924
# Make a reade for the POT file and be somewhat defensive for the
926
if fileobj.name.endswith('.po'):
928
# Normally the path looks like /path/to/xxx/i18n/lang.po
929
# and we try to find the corresponding
930
# /path/to/xxx/i18n/xxx.pot file.
931
head, tail = os.path.split(fileobj.name)
932
head2, tail2 = os.path.split(head)
933
head3, tail3 = os.path.split(head2)
934
pot_handle = misc.file_open(os.path.join(head3, tail3, 'i18n', tail3 + '.pot'))
935
pot_reader = TinyPoFile(pot_handle)
913
940
_logger.error('Bad file format: %s', fileformat)
914
941
raise Exception(_('Bad file format'))
943
# Read the POT `reference` comments, and keep them indexed by source
946
for type, name, res_id, src, _ in pot_reader:
948
pot_targets.setdefault(src, {'value': None, 'targets': []})
949
pot_targets[src]['targets'].append((type, name, res_id))
916
951
# read the rest of the file
918
952
irt_cursor = trans_obj._get_import_cursor(cr, uid, context=context)
954
def process_row(row):
955
"""Process a single PO (or POT) entry."""
922
956
# skip empty rows and rows where the translation field (=last fiefd) is empty
923
957
#if (not row) or (not row[-1]):
926
960
# dictionary which holds values for this line of the csv file
927
961
# {'lang': ..., 'type': ..., 'name': ..., 'res_id': ...,
934
968
dic[f[i]] = row[i]
970
# Get the `reference` comments from the POT.
972
if pot_reader and src in pot_targets:
973
pot_targets[src]['targets'] = filter(lambda x: x != row[:3], pot_targets[src]['targets'])
974
pot_targets[src]['value'] = row[4]
975
if not pot_targets[src]['targets']:
936
978
# This would skip terms that fail to specify a res_id
937
979
if not dic.get('res_id', False):
940
982
res_id = dic.pop('res_id')
941
983
if res_id and isinstance(res_id, (int, long)) \
962
1004
irt_cursor.push(dic)
1006
# First process the entries from the PO file (doing so also fill/remove
1007
# the entries from the POT file).
1011
# Then process the entries implied by the POT file (which is more
1012
# correct w.r.t. the targets) if some of them remain.
1014
for src in pot_targets:
1015
value = pot_targets[src]['value']
1016
for type, name, res_id in pot_targets[src]['targets']:
1017
pot_rows.append((type, name, res_id, src, value))
1018
for row in pot_rows:
964
1021
irt_cursor.finish()
966
1024
_logger.info("translation file loaded succesfully")