Skip to content
This repository has been archived by the owner on May 28, 2024. It is now read-only.

Feat/ignore tags #7

Open
wants to merge 3 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Pipfile
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,4 @@ name = "pypi"
[dev-packages]

[requires]
python_version = "3.10"
python_version = "3.11"
4 changes: 2 additions & 2 deletions Pipfile.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion polyglot/__init__.py
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
#!/usr/bin/env python3
__version__ = "2.2.4"
__version__ = "2.3.0"
45 changes: 38 additions & 7 deletions polyglot/arguments.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,9 @@
from dataclasses import dataclass

from polyglot import license
from polyglot.utils import VariableWrapper

ACTIONS: list = [
ACTIONS: list[str] = [
"translate",
"set-license",
"languages",
Expand All @@ -20,6 +21,7 @@ class Arguments:
output_directory: str
source_lang: str
license_manager: license.LicenseManager
variable_wrapper: VariableWrapper | None = None


class ArgumentsCollector(ABC):
Expand All @@ -39,7 +41,6 @@ def _validate_arguments() -> None:


class CLIArgumentsCollector(ArgumentsCollector):

__parser: argparse.ArgumentParser
__namespace: argparse.Namespace

Expand All @@ -52,17 +53,36 @@ def _collect_arguments(self) -> None:
target_lang=self.__namespace.target_lang,
output_directory=self.__namespace.output_directory,
source_lang=self.__namespace.source_lang,
variable_wrapper=VariableWrapper(
self.__namespace.variable_wrapper[0],
self.__namespace.variable_wrapper[1],
)
if self.__namespace.variable_wrapper
else None,
license_manager=license.CLILicenseManager(),
)

def _validate_arguments(self) -> None:
if self.__namespace.action == "translate" and (
self.__namespace.source_file == "" or self.__namespace.target_lang == ""
):
self.__parser.error("translate requires --source-file and --target-lang.")
is_translate: bool = self.__namespace.action == "translate"

def __set_parser(self) -> None:
if is_translate:
has_both_languages: bool = (
self.__namespace.source_lang and self.__namespace.target_lang
)

if not has_both_languages:
self.__parser.error(
"translate requires --source-file and --target-lang."
)

has_not_both_edges: bool = len(self.__namespace.variable_wrapper) != 2

if is_translate and (
self.__namespace.variable_wrapper == None or has_not_both_edges
):
self.__parser.error("Variable wrapper must be a list of two strings.")

def __set_parser(self) -> None:
parser: argparse.ArgumentParser = argparse.ArgumentParser(
description="Polyglot will translate the given files."
)
Expand Down Expand Up @@ -110,4 +130,15 @@ def __set_parser(self) -> None:
dest="output_directory",
)

parser.add_argument(
"-v",
"--variable_wrappers",
type=str,
nargs="+",
help='A wrapper around variables that should not be translated. The first argument is the opening wrapper and the second argument is the closing wrapper. E.g.: -v "%(" "%)".',
default="",
dest="variable_wrapper",
required=False,
)

self.__parser = parser
47 changes: 41 additions & 6 deletions polyglot/commands.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
DownloadedDocumentStream,
get_color_by_percentage,
get_truncated_text,
VariableWrapper,
)
from polyglot.errors import DeeplError

Expand All @@ -25,7 +26,6 @@ def function_wrapper(instance: DeeplCommand):


class DeeplCommand(ABC):

_license: str
_translator: deepl.Translator

Expand All @@ -39,7 +39,6 @@ def execute(self) -> Any:


class TranslateCommand(DeeplCommand, ABC):

_content: Any
_target_lang: str
_source_lang: str
Expand Down Expand Up @@ -98,20 +97,43 @@ def execute(self) -> None:
print(lang)


class TranslateText(TranslateCommand):
class TranslateText(DeeplCommand):
_content: Any
_target_lang: str
_source_lang: str
__keyword_wrapper: VariableWrapper

__LEN_LIMIT: int = 150
__REQUEST_wrapper: VariableWrapper = VariableWrapper("<ignorekey>", "</ignorekey>")

def __init__(
self,
license: str,
content: Any,
target_lang: str,
source_lang: str,
variable_wrapper: VariableWrapper | None = None,
) -> None:
super().__init__(license)
if target_lang == "EN": # * EN as a target language is deprecated
target_lang = "EN-US"
self._target_lang = target_lang
self._source_lang = source_lang
self.__keyword_wrapper = variable_wrapper
self._content = content

@handle_error
def execute(self) -> str:
truncated_text: str = get_truncated_text(self._content, self.__LEN_LIMIT)
response: Any = self._translator.translate_text(
[self._content],
[self.__replace_wrappers(self._content)],
target_lang=self._target_lang,
source_lang=self._source_lang,
tag_handling="xml",
ignore_tags="ignorekey",
)
try:
translation: str = response[0].text
translation: str = self.__restore_wrappers(response[0].text)
truncated_translation: str = get_truncated_text(
translation, self.__LEN_LIMIT
)
Expand All @@ -123,9 +145,22 @@ def execute(self) -> str:
)
return ""

def __replace_wrappers(self, text: str) -> str:
if self.__keyword_wrapper is None:
return text
return text.replace(
self.__keyword_wrapper.start, self.__REQUEST_wrapper.start
).replace(self.__keyword_wrapper.end, self.__REQUEST_wrapper.end)

class TranslateDocumentCommand(TranslateCommand):
def __restore_wrappers(self, text: str) -> str:
if self.__keyword_wrapper is None:
return text
return text.replace(
self.__REQUEST_wrapper.start, self.__keyword_wrapper.start
).replace(self.__REQUEST_wrapper.end, self.__keyword_wrapper.end)


class TranslateDocumentCommand(TranslateCommand):
__document: DownloadedDocumentStream
__remaining: int = 0

Expand Down
13 changes: 9 additions & 4 deletions polyglot/connectors.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
from abc import ABC, abstractmethod

from polyglot import commands, license
from polyglot.utils import DownloadedDocumentStream
from polyglot.utils import DownloadedDocumentStream, VariableWrapper


class EngineConnector(ABC):

_license: str
__license_manager: license.LicenseManager

Expand Down Expand Up @@ -42,9 +41,15 @@ def print_usage_info(self) -> None:
def print_supported_languages(self) -> None:
return commands.PrintSupportedLanguages(self._license).execute()

def translate(self, content: str, target_lang: str, source_lang: str = "") -> str:
def translate(
self,
content: str,
target_lang: str,
source_lang: str = "",
wrapper: VariableWrapper | None = None,
) -> str:
return commands.TranslateText(
self._license, content, target_lang, source_lang
self._license, content, target_lang, source_lang, wrapper
).execute()

def translate_document(
Expand Down
8 changes: 5 additions & 3 deletions polyglot/polyglot.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@ def __init__(self, arguments: arguments.Arguments):
self.__arguments = arguments

def execute_command(self):

if self.__arguments.action == "set-license":
self.__license_manager.set_license()
return
Expand Down Expand Up @@ -60,7 +59,6 @@ def __get_file_translator(self) -> FileTranslator:
return FileTranslator(handler=handler, translator=translator)

def __get_handler(self, extension: str) -> handlers.FileHandler:

file_handler_options: dict = {
"source_file": self.__arguments.source_file,
"output_directory": self.__arguments.output_directory,
Expand All @@ -79,14 +77,18 @@ def __get_handler(self, extension: str) -> handlers.FileHandler:
return handlers.TextHandler(**file_handler_options)

def __get_translator(self, extension: str) -> translators.Translator:
is_document: bool = extension in DOCUMENTS_SUPPORTED_BY_DEEPL

translator_options: dict = {
"target_lang": self.__arguments.target_lang,
"source_lang": self.__arguments.source_lang,
"connector": self.__connector,
"variable_wrapper": self.__arguments.variable_wrapper
if not is_document
else None,
}

if extension in DOCUMENTS_SUPPORTED_BY_DEEPL:
if is_document:
return translators.DocumentTranslator(**translator_options)

if extension == ".json" or extension == ".po" or extension == ".pot":
Expand Down
28 changes: 15 additions & 13 deletions polyglot/translators.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,24 +8,26 @@
import progressbar

from polyglot import connectors
from polyglot.utils import DownloadedDocumentStream
from polyglot.utils import DownloadedDocumentStream, VariableWrapper


class Translator(ABC):

_target_lang: str
_source_lang: str
_connector: connectors.EngineConnector
_keyword_wrapper: VariableWrapper | None

def __init__(
self,
target_lang: str,
source_lang: str,
connector: connectors.EngineConnector,
variable_wrapper: VariableWrapper | None = None,
) -> None:
self._target_lang = target_lang
self._source_lang = source_lang
self._connector = connector
self._keyword_wrapper = variable_wrapper

@abstractmethod
def translate(self, content: Any) -> Any:
Expand All @@ -34,11 +36,12 @@ def translate(self, content: Any) -> Any:

class TextTranslator(Translator):
def translate(self, content: str) -> str:
return self._connector.translate(content, self._target_lang, self._source_lang)
return self._connector.translate(
content, self._target_lang, self._source_lang, self._keyword_wrapper
)


class DictionaryTranslator(Translator):

__progress_bar: progressbar.ProgressBar
__completion_count: int = 0
__not_translated_entries: list = []
Expand All @@ -54,7 +57,7 @@ def translate(self, content: dict) -> dict:
self.__populate_futures(content)
loop: asyncio.AbstractEventLoop = asyncio.get_event_loop()
loop.run_until_complete(self.__translate_dictionary())
self.__print_messages()
self.__print_summary()
return content

def __set_progress_bar(self, content: dict) -> None:
Expand All @@ -71,20 +74,19 @@ def __get_number_of_translations(self, dictionary: dict) -> int:

def __populate_futures(self, dictionary: dict) -> None:
for key, value in dictionary.items():

if isinstance(value, dict):
self.__populate_futures(value)
return

else:
self.__futures.append(
self.__loop.run_in_executor(
self.__executor, self.__translate_entry, value, dictionary, key
)
self.__futures.append(
self.__loop.run_in_executor(
self.__executor, self.__translate_entry, value, dictionary, key
)
)

def __translate_entry(self, entry: str, dictionary: dict, key: str) -> None:
translation: str = self._connector.translate(
entry.strip(), self._target_lang, self._source_lang
entry.strip(), self._target_lang, self._source_lang, self._keyword_wrapper
)
if not translation:
self.__not_translated_entries.append(entry)
Expand All @@ -95,7 +97,7 @@ def __translate_entry(self, entry: str, dictionary: dict, key: str) -> None:
async def __translate_dictionary(self) -> None:
await asyncio.gather(*self.__futures)

def __print_messages(self) -> None:
def __print_summary(self) -> None:
print("\nTranslation completed.")
if len(self.__not_translated_entries) > 0:
print(
Expand Down
7 changes: 7 additions & 0 deletions polyglot/utils.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
from typing import Any, Iterator, Optional
from dataclasses import dataclass
import colorama

DownloadedDocumentStream = Optional[Iterator[Any]]
Expand All @@ -14,3 +15,9 @@ def get_color_by_percentage(percentage: int) -> str:
if percentage > 50:
return colorama.Fore.YELLOW
return colorama.Fore.RESET


@dataclass
class VariableWrapper:
start: str
end: str
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
author_email="[email protected]",
license="MIT",
classifiers=[
"Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11",
"License :: OSI Approved :: MIT License",
"Operating System :: OS Independent",
],
Expand Down