Commit 616d9f87 authored by Michal Čihař's avatar Michal Čihař

Merge pull request #936 from justinjoy/max-length

Additional flag to check max-length
parents 94f1790d f1e0c65a
......@@ -142,6 +142,22 @@ when the original string was using that as well.
.. seealso:: https://en.wikipedia.org/wiki/Ellipsis
.. _check-max-length:
Maximum Length
~~~~~~~~~~~~~~
Translation is too long to accept. This only checks for the length of translation
characters.
Source and translation usually do not have same amount of characters, but if
translation is too long, it can be affect a rendered shape. For example, in some UI
widget, it should be kept in a specific length of characters in order to show
complete translation within limited space.
Unlike the other checks, the flag should be set as a ``key:value`` pair like
``max-length:100``.
.. _check-python-format:
.. _check-python-brace-format:
.. _check-php-format:
......
......@@ -33,6 +33,7 @@ class Check(object):
ignore_untranslated = True
default_disabled = False
severity = 'info'
enable_check_value = False
def __init__(self):
id_dash = self.check_id.replace('_', '-')
......@@ -44,6 +45,10 @@ class Check(object):
'''
Checks target strings.
'''
if self.enable_check_value:
return self.check_target_unit_with_flag(
sources, targets, unit
)
# Is this disabled by default
if self.default_disabled and self.enable_string not in unit.all_flags:
return False
......@@ -55,6 +60,12 @@ class Check(object):
return False
return self.check_target_unit(sources, targets, unit)
def check_target_unit_with_flag(self, sources, targets, unit):
'''
Checks flag value
'''
raise NotImplementedError()
def check_target_unit(self, sources, targets, unit):
'''
Checks single unit, handling plurals.
......@@ -128,6 +139,12 @@ class TargetCheck(Check):
'''
target = True
def check_target_unit_with_flag(self, sources, targets, unit):
'''
We don't check flag value here.
'''
return False
def check_source(self, source, unit):
'''
We don't check source strings here.
......@@ -147,6 +164,12 @@ class SourceCheck(Check):
'''
source = True
def check_target_unit_with_flag(self, sources, targets, unit):
'''
We don't check flag value here.
'''
return False
def check_single(self, source, target, unit):
'''
We don't check target strings here.
......@@ -160,6 +183,33 @@ class SourceCheck(Check):
raise NotImplementedError()
class TargetCheckWithFlag(Check):
'''
Basic class for target checks with flag value.
'''
default_disabled = True
enable_check_value = True
target = True
def check_target_unit_with_flag(self, sources, targets, unit):
'''
Checks flag value
'''
raise NotImplementedError()
def check_single(self, source, target, unit):
'''
We don't check single phrase here.
'''
return False
def check_source(self, source, unit):
'''
We don't check source strings here.
'''
return False
class CountingCheck(TargetCheck):
'''
Check whether there is same count of given string.
......
......@@ -19,7 +19,10 @@
#
from django.utils.translation import ugettext_lazy as _
from weblate.trans.checks.base import TargetCheck, CountingCheck
from weblate.trans.checks.base import (
TargetCheck, TargetCheckWithFlag, CountingCheck
)
import re
class BeginNewlineCheck(TargetCheck):
......@@ -360,3 +363,26 @@ class ZeroWidthSpaceCheck(TargetCheck):
if self.is_language(unit, ('km', )):
return False
return (u'\u200b' in target) != (u'\u200b' in source)
class MaxLengthCheck(TargetCheckWithFlag):
'''
Check for maximum length of translation.
'''
check_id = 'max-length'
name = _('Maximum Length of Translation')
description = _('Translation should not exceed given length')
severity = 'danger'
default_disabled = True
FLAGS_PAIR_RE = re.compile(r'\b([-\w]+):(\w+)\b')
def check_target_unit_with_flag(self, sources, targets, unit):
check_pair = set(self.FLAGS_PAIR_RE.findall('\n'.join(unit.all_flags)))
if len(check_pair) > 0:
check_value = max(
{(x) for x in check_pair if x[0] == self.check_id},
key=lambda v: int(v[1])
)[1]
return len(targets[0]) > int(check_value)
return False
......@@ -22,6 +22,7 @@
Tests for quality checks.
"""
from unittest import TestCase
from weblate.trans.checks.chars import (
BeginNewlineCheck, EndNewlineCheck,
BeginSpaceCheck, EndSpaceCheck,
......@@ -30,8 +31,9 @@ from weblate.trans.checks.chars import (
EndEllipsisCheck,
NewlineCountingCheck,
ZeroWidthSpaceCheck,
MaxLengthCheck,
)
from weblate.trans.tests.test_checks import CheckTestCase
from weblate.trans.tests.test_checks import CheckTestCase, MockUnit
class BeginNewlineCheckTest(CheckTestCase):
......@@ -233,3 +235,63 @@ class ZeroWidthSpaceCheckTest(CheckTestCase):
self.test_good_matching = (u'str\u200bing', u'str\u200bing', '')
self.test_failure_1 = (u'str\u200bing', 'string', '')
self.test_failure_2 = ('string', u'str\u200bing', '')
class MaxLengthCheckTest(TestCase):
def setUp(self):
self.check = MaxLengthCheck()
self.test_good_matching = (
'strings',
'less than 21',
'max-length:12'
)
self.test_good_matching_unicode = (
u'strings',
u'less than 21',
'max-length:12'
)
def test_check(self):
self.assertFalse(
self.check.check_target(
[self.test_good_matching[0]],
[self.test_good_matching[1]],
MockUnit(flags=(self.test_good_matching[2]))
)
)
def test_unicode_check(self):
self.assertFalse(
self.check.check_target(
[self.test_good_matching_unicode[0]],
[self.test_good_matching_unicode[1]],
MockUnit(flags=(self.test_good_matching_unicode[2]))
)
)
def test_failure_check(self):
self.assertTrue(
self.check.check_target(
[self.test_good_matching[0]],
[self.test_good_matching[1]],
MockUnit(flags=('max-length:10'))
)
)
def test_failure_unicode_check(self):
self.assertTrue(
self.check.check_target(
[self.test_good_matching_unicode[0]],
[self.test_good_matching_unicode[1]],
MockUnit(flags=('max-length:10'))
)
)
def test_multiple_flags_check(self):
self.assertFalse(
self.check.check_target(
[self.test_good_matching_unicode[0]],
[self.test_good_matching_unicode[1]],
MockUnit(flags=('max-length:3,max-length:12'))
)
)
......@@ -101,6 +101,7 @@ def validate_check_flags(val):
if not val:
return
for flag in val.split(','):
if flag in EXTRA_FLAGS or flag in IGNORE_CHECK_FLAGS:
name = flag.split(':')[0]
if name in EXTRA_FLAGS or name in IGNORE_CHECK_FLAGS:
continue
raise ValidationError(_('Invalid check flag: "%s"') % flag)
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