Commit 47fc6659 authored by Michal Čihař's avatar Michal Čihař

Tigher control on fuzzy strings on translation upload.

User can now specify how to handle fuzzy strings on upload:

- Do not import
- Import as fuzzy
- Import as translated

Fixes #751
Signed-off-by: default avatarMichal Čihař <michal@cihar.com>
parent 5188a8c1
......@@ -12,6 +12,7 @@ Released on ? 2015.
* Added CSV dump of history.
* Avoid copy/paste errors with whitespace chars.
* Added support for Bitbucket webhooks.
* Tigher control on fuzzy strings on translation upload.
weblate 2.3
-----------
......
......@@ -676,6 +676,34 @@ class FileFormat(object):
with open(filename, 'w') as output:
output.write(cls.new_translation)
def iterate_merge(self, fuzzy, header=False):
"""Iterates over units for merging.
Note: This can change fuzzy state of units!
"""
for unit in self.all_units():
# Handle header
if unit.unit and unit.unit.isheader():
if header:
yield False, unit
continue
# Skip fuzzy (if asked for that)
if unit.is_fuzzy():
if not fuzzy:
continue
elif not unit.is_translated():
continue
# Unmark unit as fuzzy (to allow merge)
set_fuzzy = False
if fuzzy and unit.is_fuzzy():
unit.mark_fuzzy(False)
if fuzzy != 'approve':
set_fuzzy = True
yield set_fuzzy, unit
@register_fileformat
class AutoFormat(FileFormat):
......
......@@ -335,6 +335,15 @@ class SimpleUploadForm(forms.Form):
),
required=False
)
fuzzy = forms.ChoiceField(
label=_('Fuzzy strings processing'),
choices=(
('', _('Do not import')),
('process', _('Import as fuzzy')),
('approve', _('Import as translated')),
),
required=False
)
merge_header = forms.BooleanField(
label=_('Merge file header'),
help_text=_('Merges content of file header into the translation.'),
......
......@@ -1040,17 +1040,13 @@ class Translation(models.Model, URLMixin, PercentMixin, LoggerMixin):
return result
def merge_translations(self, request, author, store2, overwrite,
add_fuzzy):
add_fuzzy, fuzzy):
"""
Merges translation unit wise, needed for template based translations to
add new strings.
"""
for unit2 in store2.all_units():
# No translated -> skip
if not unit2.is_translated() or unit2.unit.isheader():
continue
for set_fuzzy, unit2 in store2.iterate_merge(fuzzy):
try:
unit = self.unit_set.get(
source=unit2.get_source(),
......@@ -1062,11 +1058,11 @@ class Translation(models.Model, URLMixin, PercentMixin, LoggerMixin):
unit.translate(
request,
split_plural(unit2.get_target()),
add_fuzzy or unit2.is_fuzzy()
add_fuzzy or set_fuzzy
)
def merge_store(self, request, author, store2, overwrite, merge_header,
add_fuzzy):
add_fuzzy, fuzzy):
'''
Merges translate-toolkit store into current translation.
'''
......@@ -1076,14 +1072,10 @@ class Translation(models.Model, URLMixin, PercentMixin, LoggerMixin):
store1 = self.store.store
store1.require_index()
for unit2 in store2.all_units():
# No translated -> skip
if not unit2.is_translated():
continue
for set_fuzzy, unit2 in store2.iterate_merge(fuzzy, merge_header):
# Optionally merge header
if unit2.unit.isheader():
if merge_header and isinstance(store1, poheader.poheader):
if isinstance(store1, poheader.poheader):
store1.mergeheaders(store2)
continue
......@@ -1106,7 +1098,7 @@ class Translation(models.Model, URLMixin, PercentMixin, LoggerMixin):
unit1.merge(unit2.unit, overwrite=True, comments=False)
# Handle
if add_fuzzy:
if add_fuzzy or set_fuzzy:
unit1.markfuzzy()
# Write to backend and commit
......@@ -1117,17 +1109,12 @@ class Translation(models.Model, URLMixin, PercentMixin, LoggerMixin):
return ret
def merge_suggestions(self, request, store):
def merge_suggestions(self, request, store, fuzzy):
'''
Merges content of translate-toolkit store as a suggestions.
'''
ret = False
for unit in store.all_units():
# Skip headers or not translated
if not unit.is_translatable() or not unit.is_translated():
continue
for dummy, unit in store.iterate_merge(fuzzy):
# Calculate unit checksum
checksum = unit.get_checksum()
......@@ -1150,7 +1137,7 @@ class Translation(models.Model, URLMixin, PercentMixin, LoggerMixin):
return ret
def merge_upload(self, request, fileobj, overwrite, author=None,
merge_header=True, method=''):
merge_header=True, method='', fuzzy=''):
'''
Top level handler for file uploads.
'''
......@@ -1193,7 +1180,8 @@ class Translation(models.Model, URLMixin, PercentMixin, LoggerMixin):
author,
store,
overwrite,
(method == 'fuzzy')
(method == 'fuzzy'),
fuzzy
)
else:
# Merge on file level
......@@ -1204,11 +1192,12 @@ class Translation(models.Model, URLMixin, PercentMixin, LoggerMixin):
store,
overwrite,
merge_header,
(method == 'fuzzy')
(method == 'fuzzy'),
fuzzy
)
else:
# Add as sugestions
ret = self.merge_suggestions(request, store)
ret = self.merge_suggestions(request, store, fuzzy)
return ret, store.count_units()
......
# Czech translations for PACKAGE package.
# Copyright (C) 2012 THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the PACKAGE package.
# Automatically generated, 2012.
#
msgid ""
msgstr ""
"Project-Id-Version: Weblate Hello World 2012\n"
"Report-Msgid-Bugs-To: <noreply@example.net>\n"
"POT-Creation-Date: 2012-03-14 15:54+0100\n"
"PO-Revision-Date: 2012-03-05 15:55+0100\n"
"Last-Translator: Automatically generated\n"
"Language-Team: none\n"
"Language: cs\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2;\n"
#: main.c:14
#, fuzzy
msgid "Thank you for using Weblate."
msgstr "Diky za pouziti Weblate."
......@@ -27,6 +27,7 @@ from django.core.urlresolvers import reverse
from weblate.trans.tests.utils import get_test_file
TEST_PO = get_test_file('cs.po')
TEST_FUZZY_PO = get_test_file('cs-fuzzy.po')
TEST_MO = get_test_file('cs.mo')
TEST_ANDROID = get_test_file('strings-cs.xml')
......@@ -34,14 +35,14 @@ TRANSLATION_OURS = u'Nazdar světe!\n'
TRANSLATION_PO = u'Ahoj světe!\n'
class ImportTest(ViewTestCase):
class ImportBaseTest(ViewTestCase):
'''
Testing of file imports.
Base test of file imports.
'''
test_file = TEST_PO
def setUp(self):
super(ImportTest, self).setUp()
super(ImportBaseTest, self).setUp()
# We need extra privileges for overwriting
self.user.is_superuser = True
self.user.save()
......@@ -61,6 +62,13 @@ class ImportTest(ViewTestCase):
params
)
class ImportTest(ImportBaseTest):
'''
Testing of file imports.
'''
test_file = TEST_PO
def test_import_normal(self):
'''
Test importing normally.
......@@ -166,6 +174,58 @@ class ImportTest(ViewTestCase):
)
class ImportFuzzyTest(ImportBaseTest):
'''
Testing of fuzzy file imports.
'''
test_file = TEST_FUZZY_PO
def test_import_normal(self):
'''
Test importing normally.
'''
response = self.do_import(
fuzzy=''
)
self.assertRedirects(response, self.translation_url)
# Verify stats
translation = self.get_translation()
self.assertEqual(translation.translated, 0)
self.assertEqual(translation.fuzzy, 0)
self.assertEqual(translation.total, 4)
def test_import_process(self):
'''
Test importing normally.
'''
response = self.do_import(
fuzzy='process'
)
self.assertRedirects(response, self.translation_url)
# Verify stats
translation = self.get_translation()
self.assertEqual(translation.translated, 0)
self.assertEqual(translation.fuzzy, 1)
self.assertEqual(translation.total, 4)
def test_import_approve(self):
'''
Test importing normally.
'''
response = self.do_import(
fuzzy='approve'
)
self.assertRedirects(response, self.translation_url)
# Verify stats
translation = self.get_translation()
self.assertEqual(translation.translated, 1)
self.assertEqual(translation.fuzzy, 0)
self.assertEqual(translation.total, 4)
class ImportMoTest(ImportTest):
'''
Testing of mo file imports.
......
......@@ -115,7 +115,8 @@ def upload_translation(request, project, subproject, lang):
overwrite,
author,
merge_header=form.cleaned_data['merge_header'],
method=form.cleaned_data['method']
method=form.cleaned_data['method'],
fuzzy=form.cleaned_data['fuzzy'],
)
messages.info(
request,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment