Skip to content

Commit

Permalink
Merge pull request #44 from MarcinOrlowski/substitutions
Browse files Browse the repository at this point in the history
Substitutions
  • Loading branch information
MarcinOrlowski authored Aug 6, 2021
2 parents 4eb3e2d + a4b0a21 commit 6c5d31a
Show file tree
Hide file tree
Showing 8 changed files with 154 additions and 10 deletions.
1 change: 1 addition & 0 deletions docs/CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
item to control whenever you want comments to be scanned.
* `StartsWithTheSameCase` now handles the case where base/translation can start with a digit which should be case match.
* `Brackets` can now detect and ignore quoted brackets.
* Added `Substitutions` check.

* v2.0.0 (2021-08-02)
* Added support for config files.
Expand Down
1 change: 1 addition & 0 deletions docs/checks/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
* [Punctuation](punctuation.md)
* [QuotationMarks](quotation-marks.md)
* [StartsWithTheSameCase](starts-with-the-same-case.md)
* [Substitutions](substitutions.md)
* [TrailingWhiteChars](trailing-white-chars.md)
* [TypesettingQuotationMarks](typesetting-quotation-marks.md)
* [WhiteCharsBeforeLinefeed](white-chars-before-linefeed.md)
Expand Down
33 changes: 33 additions & 0 deletions docs/checks/substitutions.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
![trans-tool logo](../../artwork/trans-tool-logo.png)

### The translation files checker and syncing tool ###

---

# Substitutions #

* [« Main README](../../README.md)
* [« Documentation table of contents](../README.md)
* [« Available checks](README.md)
* **Substitutions**
* [Summary](#summary)
* [Description](#description)
* [Configuration file](#configuration-file)

---

## Summary ##

* Check ID: `Substitutions`
* Checks base file: YES
* Checks translations: YES

## Description ##

`Substitutions` looks for sequence of characters that can be replaced, i.e. subsequent three dots `...` can be replaced
by single ellipsis `` character. The check also looks for faulty sequences (i.e. it will report an error if more
than 3 dots are put in sequence.

## Configuration file ##

No dedicated configuration.
93 changes: 93 additions & 0 deletions transtool/checks/substitutions.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
"""
# trans-tool
# The translation files checker and syncing tool.
#
# Copyright ©2021 Marcin Orlowski <mail [@] MarcinOrlowski.com>
# https://github.com/MarcinOrlowski/trans-tool/
#
"""
import re
from typing import Dict, Union

from transtool.decorators.overrides import overrides
from transtool.report.group import ReportGroup
from transtool.report.items import ReportItem
from .base.check import Check

from transtool.prop.file import PropItem


# noinspection PyUnresolvedReferences
class Substitutions(Check):
"""
Checks if brackets are used in translation and if so, ensures proper nesting and
checks if all opened brackets are closed.
"""

FAIL = -1

def __init__(self, config: Union[Dict, None] = None):
super().__init__(config)
self.is_single_file_check = True

def _find_most_important_issue(self, idx: int, item: PropItem) -> Union[ReportItem, None]:
warns = []
for config in self.config['map']:
for match in re.finditer(config['regexp'], item.value):
if config['replace'] == self.FAIL:
return ReportGroup.build_error(f'{idx + 1}:{match.start()}', f'Invalid sequence "{match.group(1)}".', item.key)
else:
replacement = config['replace']
warns.append(
ReportGroup.build_warn(f'{idx + 1}:{match.start()}', f'Sequence can be replaced with "{replacement}".',
item.key))

return warns[0] if (isinstance(warns, list) and warns) else None

@overrides(Check)
# Do NOT "fix" the PropFile reference and do not import it, or you step on circular dependency!
def check(self, translation: 'PropFile', reference: 'PropFile' = None) -> ReportGroup:
self.need_valid_config()

report = ReportGroup('Substitutions')

if not translation.items:
return report

for idx, item in enumerate(translation.items):
# Do not try to be clever and filter() data first, because line_number values will no longer be correct.
if self._shall_skip_item(item):
continue

check_result = self._find_most_important_issue(idx, item)
if check_result is not None:
report.add(check_result)

return report

@overrides(Check)
def get_default_config(self) -> Dict:
return {
'comments': False,

# Keep matching elements at the same positions
'map': [
{
'regexp': r'([\.]{3})',
'replace': '…',
},
{
'regexp': r'([\.]{4,})',
'replace': self.FAIL,
},

{
'regexp': r'([\s]{2,})',
'replace': ' ',
},
{
'regexp': r'([\!]{2,})',
'replace': '!',
},
],
}
2 changes: 2 additions & 0 deletions transtool/config/builder.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
from transtool.checks.quotation_marks import QuotationMarks
from transtool.checks.starts_with_the_same_case import StartsWithTheSameCase
from transtool.checks.trailing_white_chars import TrailingWhiteChars
from transtool.checks.substitutions import Substitutions
from transtool.checks.typesetting_quotation_marks import TypesettingQuotationMarks
from transtool.checks.white_chars_before_linefeed import WhiteCharsBeforeLinefeed
from transtool.config.checker_info import CheckerInfo
Expand Down Expand Up @@ -54,6 +55,7 @@ def build(config_defaults: Config):
TrailingWhiteChars,
TypesettingQuotationMarks,
WhiteCharsBeforeLinefeed,
Substitutions,
]

for checker in checkers:
Expand Down
2 changes: 1 addition & 1 deletion transtool/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
# #################################################################################################


class PropTool(object):
class TransTool(object):

@staticmethod
def start() -> int:
Expand Down
28 changes: 21 additions & 7 deletions transtool/report/group.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
from typing import Union

from transtool.log import Log
from transtool.report.items import Error, Warn
from transtool.report.items import Error, ReportItem, Warn


# #################################################################################################
Expand Down Expand Up @@ -42,18 +42,32 @@ def create(self, position: Union[str, int, None], msg: str, trans_key: Union[str
def empty(self) -> bool:
return (self.errors + self.warnings) == 0

def warn(self, line: Union[str, int, None], msg: str, trans_key: Union[str, None] = None) -> None:
def add(self, item) -> None:
if not issubclass(type(item), ReportItem):
raise TypeError(f'Item must be subclass of ReportItem. "{type(item)}" given.')
self.append(item)
if isinstance(item, Warn):
self.warnings += 1
else:
self.errors += 1

@staticmethod
def build_warn(line: Union[str, int, None], msg: str, trans_key: Union[str, None] = None) -> Warn:
if line and not isinstance(line, str):
line = str(line)
return Warn(line, msg, trans_key)

self.append(Warn(line, msg, trans_key))
self.warnings += 1
def warn(self, line: Union[str, int, None], msg: str, trans_key: Union[str, None] = None) -> None:
self.add(self.build_warn(line, msg, trans_key))

def error(self, line: Union[str, int, None], msg: str, trans_key: Union[str, None] = None) -> None:
@staticmethod
def build_error(line: Union[str, int, None], msg: str, trans_key: Union[str, None] = None) -> Error:
if isinstance(line, int):
line = str(line)
self.append(Error(line, msg, trans_key))
self.errors += 1
return Error(line, msg, trans_key)

def error(self, line: Union[str, int, None], msg: str, trans_key: Union[str, None] = None) -> None:
self.add(self.build_error(line, msg, trans_key))

def dump(self, show_warnings_as_errors: bool = False):
if show_warnings_as_errors:
Expand Down
4 changes: 2 additions & 2 deletions transtool/report/report.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,10 +61,10 @@ def add(self, report_group: ReportGroup, skip_empty: bool = True) -> None:
self._groups.append(report_group)

def empty(self) -> bool:
return not self._groups
return len(self._groups) == 0 # noqa: WPS507

def not_empty(self) -> bool:
return self._groups
return len(self._groups) > 0 # noqa: WPS507

def dump(self):
errors = self.errors
Expand Down

0 comments on commit 6c5d31a

Please sign in to comment.