diff --git a/src/cpl_cli/cpl-cli.json b/src/cpl_cli/cpl-cli.json index 5f88acaa..a5cebd15 100644 --- a/src/cpl_cli/cpl-cli.json +++ b/src/cpl_cli/cpl-cli.json @@ -3,8 +3,8 @@ "Name": "cpl-cli", "Version": { "Major": "2022", - "Minor": "6", - "Micro": "0" + "Minor": "8", + "Micro": "1.dev7" }, "Author": "Sven Heidemann", "AuthorEmail": "sven.heidemann@sh-edraft.de", @@ -16,7 +16,7 @@ "LicenseName": "MIT", "LicenseDescription": "MIT, see LICENSE for more details.", "Dependencies": [ - "cpl-core>=2022.6.0" + "cpl-core>=2022.8.1.dev7" ], "DevDependencies": [], "PythonVersion": ">=3.10", diff --git a/src/cpl_core/cpl-core.json b/src/cpl_core/cpl-core.json index 64006aa7..7f5ba5eb 100644 --- a/src/cpl_core/cpl-core.json +++ b/src/cpl_core/cpl-core.json @@ -3,8 +3,8 @@ "Name": "cpl-core", "Version": { "Major": "2022", - "Minor": "6", - "Micro": "0" + "Minor": "8", + "Micro": "1.dev7" }, "Author": "Sven Heidemann", "AuthorEmail": "sven.heidemann@sh-edraft.de", diff --git a/src/cpl_core/dependency_injection/service_collection.py b/src/cpl_core/dependency_injection/service_collection.py index 110c8c43..24d4699d 100644 --- a/src/cpl_core/dependency_injection/service_collection.py +++ b/src/cpl_core/dependency_injection/service_collection.py @@ -59,6 +59,17 @@ class ServiceCollection(ServiceCollectionABC): for pipe in PipeABC.__subclasses__(): self.add_transient(PipeABC, pipe) + def add_translation(self): + try: + from cpl_translation.translation_service_abc import TranslationServiceABC + from cpl_translation.translation_service import TranslationService + from cpl_translation.translate_pipe import TranslatePipe + from cpl_translation.translation_settings import TranslationSettings + self.add_singleton(TranslationServiceABC, TranslationService) + self.add_transient(PipeABC, TranslatePipe) + except ImportError as e: + Console.error('cpl-translation is not installed', str(e)) + def add_singleton(self, service_type: Union[type, object], service: Union[type, object] = None): self._add_descriptor_by_lifetime(service_type, ServiceLifetimeEnum.singleton, service) return self diff --git a/src/cpl_core/dependency_injection/service_collection_abc.py b/src/cpl_core/dependency_injection/service_collection_abc.py index 5c828388..d55390ef 100644 --- a/src/cpl_core/dependency_injection/service_collection_abc.py +++ b/src/cpl_core/dependency_injection/service_collection_abc.py @@ -35,6 +35,11 @@ class ServiceCollectionABC(ABC): r"""Adds the CPL internal pipes as transient""" pass + @abstractmethod + def add_translation(self): + r"""Adds the CPL translation""" + pass + @abstractmethod def add_transient(self, service_type: Type, service: Callable = None) -> 'ServiceCollectionABC': r"""Adds a service with transient lifetime diff --git a/src/cpl_query/cpl-query.json b/src/cpl_query/cpl-query.json index c0cbee2a..6f64f983 100644 --- a/src/cpl_query/cpl-query.json +++ b/src/cpl_query/cpl-query.json @@ -3,8 +3,8 @@ "Name": "cpl-query", "Version": { "Major": "2022", - "Minor": "6", - "Micro": "0" + "Minor": "8", + "Micro": "1.dev7" }, "Author": "Sven Heidemann", "AuthorEmail": "sven.heidemann@sh-edraft.de", diff --git a/src/cpl_translation/cpl-translation.json b/src/cpl_translation/cpl-translation.json index 36af97c8..239a0b85 100644 --- a/src/cpl_translation/cpl-translation.json +++ b/src/cpl_translation/cpl-translation.json @@ -4,19 +4,19 @@ "Version": { "Major": "2022", "Minor": "8", - "Micro": "1" + "Micro": "1.dev7" }, "Author": "Sven Heidemann", "AuthorEmail": "sven.heidemann@sh-edraft.de", "Description": "sh-edraft Common Python library Translation", - "LongDescription": "sh-edraft Common Python library Python i18n based Translation implementation", + "LongDescription": "sh-edraft Common Python library Python Translation", "URL": "https://www.sh-edraft.de", "CopyrightDate": "2022", "CopyrightName": "sh-edraft.de", "LicenseName": "MIT", "LicenseDescription": "MIT, see LICENSE for more details.", "Dependencies": [ - "cpl-core>=2022.6.0" + "cpl-core>=2022.8.1.dev7" ], "DevDependencies": [ "cpl-cli>=2022.6.0" diff --git a/src/cpl_translation/translate_pipe.py b/src/cpl_translation/translate_pipe.py new file mode 100644 index 00000000..d520600f --- /dev/null +++ b/src/cpl_translation/translate_pipe.py @@ -0,0 +1,16 @@ +from cpl_core.console import Console +from cpl_core.pipes.pipe_abc import PipeABC +from cpl_translation.translation_service_abc import TranslationServiceABC + + +class TranslatePipe(PipeABC): + + def __init__(self, translation: TranslationServiceABC): + self._translation = translation + + def transform(self, value: any, *args): + try: + return self._translation.translate(value) + except KeyError as e: + Console.error(f'Translation {value} not found') + return '' diff --git a/src/cpl_translation/translation_service.py b/src/cpl_translation/translation_service.py new file mode 100644 index 00000000..3fd83b7c --- /dev/null +++ b/src/cpl_translation/translation_service.py @@ -0,0 +1,54 @@ +import json +import os.path +from functools import reduce + +from cpl_core.console import Console +from cpl_translation.translation_service_abc import TranslationServiceABC +from cpl_translation.translation_settings import TranslationSettings + + +class TranslationService(TranslationServiceABC): + + def __init__(self): + self._translation = {} + + self._language = '' + self._default_language = '' + + TranslationServiceABC.__init__(self) + + def set_default_lang(self, lang: str): + self._default_language = lang + self.set_lang(lang) + + def set_lang(self, lang: str): + self._language = lang + + def load(self, lang: str): + if not os.path.exists(f'translation/{lang}.json'): + raise FileNotFoundError() + + file_dict = {} + with open(f'translation/{lang}.json', 'r') as file: + file_dict = json.load(file) + file.close() + + self._translation[lang] = file_dict + + def load_by_settings(self, settings: TranslationSettings): + if settings is None: + raise Exception(f'{TranslationSettings.__name__} not loaded') + + self._language = settings.default_language + self._default_language = settings.default_language + + for lang in settings.languages: + self.load(lang) + + def translate(self, key: str) -> str: + value = reduce(lambda d, key: d.get(key) if isinstance(d, dict) else None, key.split("."), self._translation[self._language]) + + if value is None: + raise KeyError(f'Translation {key} not found') + + return value diff --git a/src/cpl_translation/translation_service_abc.py b/src/cpl_translation/translation_service_abc.py new file mode 100644 index 00000000..aeef3776 --- /dev/null +++ b/src/cpl_translation/translation_service_abc.py @@ -0,0 +1,22 @@ +from abc import ABC, abstractmethod + + +class TranslationServiceABC(ABC): + + @abstractmethod + def __init__(self): pass + + @abstractmethod + def set_default_lang(self, lang: str): pass + + @abstractmethod + def set_lang(self, lang: str): pass + + @abstractmethod + def load(self, lang: str): pass + + @abstractmethod + def load_by_settings(self): pass + + @abstractmethod + def translate(self, key: str) -> str: pass diff --git a/src/cpl_translation/translation_settings.py b/src/cpl_translation/translation_settings.py new file mode 100644 index 00000000..bc393a95 --- /dev/null +++ b/src/cpl_translation/translation_settings.py @@ -0,0 +1,29 @@ +import traceback + +from cpl_core.configuration.configuration_model_abc import ConfigurationModelABC +from cpl_core.console import Console + + +class TranslationSettings(ConfigurationModelABC): + + def __init__(self): + ConfigurationModelABC.__init__(self) + + self._languages = [] + self._default_lang = '' + + @property + def languages(self) -> list[str]: + return self._languages + + @property + def default_language(self) -> str: + return self._default_lang + + def from_dict(self, settings: dict): + try: + self._languages = settings['Languages'] + self._default_lang = settings['DefaultLanguage'] + except Exception as e: + Console.error(f'[ ERROR ] [ {__name__} ]: Reading error in {self.__name__} settings') + Console.error(f'[ EXCEPTION ] [ {__name__} ]: {e} -> {traceback.format_exc()}') diff --git a/src/tests/custom/translation/src/translation/application.py b/src/tests/custom/translation/src/translation/application.py index 34a68c80..6a5b699b 100644 --- a/src/tests/custom/translation/src/translation/application.py +++ b/src/tests/custom/translation/src/translation/application.py @@ -2,6 +2,9 @@ from cpl_core.application import ApplicationABC from cpl_core.configuration import ConfigurationABC from cpl_core.console import Console from cpl_core.dependency_injection import ServiceProviderABC +from cpl_translation.translate_pipe import TranslatePipe +from cpl_translation.translation_service_abc import TranslationServiceABC +from cpl_translation.translation_settings import TranslationSettings class Application(ApplicationABC): @@ -9,8 +12,18 @@ class Application(ApplicationABC): def __init__(self, config: ConfigurationABC, services: ServiceProviderABC): ApplicationABC.__init__(self, config, services) + self._translate: TranslatePipe = services.get_service(TranslatePipe) + self._translation: TranslationServiceABC = services.get_service(TranslationServiceABC) + self._translation_settings: TranslationSettings = config.get_configuration(TranslationSettings) + + self._translation.load_by_settings(config.get_configuration(TranslationSettings)) + self._translation.set_default_lang('de') + def configure(self): pass def main(self): - Console.write_line('Hello World') + Console.write_line(self._translate.transform('main.text.hello_world')) + self._translation.set_lang('en') + Console.write_line(self._translate.transform('main.text.hello_world')) + Console.write_line(self._translate.transform('main.text.hello')) diff --git a/src/tests/custom/translation/appsettings.json b/src/tests/custom/translation/src/translation/appsettings.json similarity index 76% rename from src/tests/custom/translation/appsettings.json rename to src/tests/custom/translation/src/translation/appsettings.json index 629e6ebd..e307f59c 100644 --- a/src/tests/custom/translation/appsettings.json +++ b/src/tests/custom/translation/src/translation/appsettings.json @@ -11,5 +11,13 @@ "Filename": "log_$start_time.log", "ConsoleLogLevel": "ERROR", "FileLogLevel": "WARN" + }, + + "Translation": { + "Languages":[ + "de", + "en" + ], + "DefaultLanguage": "en" } } diff --git a/src/tests/custom/translation/src/translation/startup.py b/src/tests/custom/translation/src/translation/startup.py index 359c03d2..e5483338 100644 --- a/src/tests/custom/translation/src/translation/startup.py +++ b/src/tests/custom/translation/src/translation/startup.py @@ -10,7 +10,9 @@ class Startup(StartupABC): StartupABC.__init__(self) def configure_configuration(self, configuration: ConfigurationABC, environment: ApplicationEnvironment) -> ConfigurationABC: + configuration.add_json_file('appsettings.json') return configuration def configure_services(self, services: ServiceCollectionABC, environment: ApplicationEnvironment) -> ServiceProviderABC: + services.add_translation() return services.build_service_provider() diff --git a/src/tests/custom/translation/src/translation/translation/de.json b/src/tests/custom/translation/src/translation/translation/de.json new file mode 100644 index 00000000..afd34db5 --- /dev/null +++ b/src/tests/custom/translation/src/translation/translation/de.json @@ -0,0 +1,7 @@ +{ + "main": { + "text": { + "hello_world": "Hallo Welt" + } + } +} \ No newline at end of file diff --git a/src/tests/custom/translation/src/translation/translation/en.json b/src/tests/custom/translation/src/translation/translation/en.json new file mode 100644 index 00000000..77c63c59 --- /dev/null +++ b/src/tests/custom/translation/src/translation/translation/en.json @@ -0,0 +1,7 @@ +{ + "main": { + "text": { + "hello_world": "Hello World" + } + } +} \ No newline at end of file diff --git a/tools/set_pip_urls/set-pip-urls.json b/tools/set_pip_urls/set-pip-urls.json index efbe393a..1e8ec912 100644 --- a/tools/set_pip_urls/set-pip-urls.json +++ b/tools/set_pip_urls/set-pip-urls.json @@ -16,7 +16,7 @@ "LicenseName": "MIT", "LicenseDescription": "MIT, see LICENSE for more details.", "Dependencies": [ - "cpl-core>=2022.6.0.rc1" + "cpl-core>=2022.8.1.dev7" ], "PythonVersion": ">=3.10.4", "PythonPath": {}, diff --git a/tools/set_version/set-version.json b/tools/set_version/set-version.json index 51339ee5..db8269c7 100644 --- a/tools/set_version/set-version.json +++ b/tools/set_version/set-version.json @@ -16,7 +16,7 @@ "LicenseName": "MIT", "LicenseDescription": "MIT, see LICENSE for more details.", "Dependencies": [ - "cpl-core>=2022.6.0.rc1", + "cpl-core>=2022.8.1.dev7", "gitpython==3.1.27" ], "PythonVersion": ">=3.10.4", diff --git a/unittests/unittests/unittests.json b/unittests/unittests/unittests.json index 988e6bb8..3504c2a8 100644 --- a/unittests/unittests/unittests.json +++ b/unittests/unittests/unittests.json @@ -3,8 +3,8 @@ "Name": "unittests", "Version": { "Major": "2022", - "Minor": "6", - "Micro": "0.rc1" + "Minor": "8", + "Micro": "1.dev7" }, "Author": "", "AuthorEmail": "", @@ -16,7 +16,7 @@ "LicenseName": "", "LicenseDescription": "", "Dependencies": [ - "cpl-core>=2022.6.0.rc1" + "cpl-core>=2022.8.1.dev7" ], "PythonVersion": ">=3.10.4", "PythonPath": { diff --git a/unittests/unittests_cli/unittests_cli.json b/unittests/unittests_cli/unittests_cli.json index 24939e77..cd728928 100644 --- a/unittests/unittests_cli/unittests_cli.json +++ b/unittests/unittests_cli/unittests_cli.json @@ -3,8 +3,8 @@ "Name": "unittest_cli", "Version": { "Major": "2022", - "Minor": "6", - "Micro": "0.rc1" + "Minor": "8", + "Micro": "1.dev7" }, "Author": "", "AuthorEmail": "", @@ -16,8 +16,8 @@ "LicenseName": "", "LicenseDescription": "", "Dependencies": [ - "cpl-core>=2022.6.0.rc1", - "cpl-cli>=2022.6.0.rc1" + "cpl-core>=2022.8.1.dev7", + "cpl-cli>=2022.8.1.dev7" ], "PythonVersion": ">=3.10.4", "PythonPath": { diff --git a/unittests/unittests_core/unittests_core.json b/unittests/unittests_core/unittests_core.json index 983ce9fe..1097e840 100644 --- a/unittests/unittests_core/unittests_core.json +++ b/unittests/unittests_core/unittests_core.json @@ -3,8 +3,8 @@ "Name": "unittest_core", "Version": { "Major": "2022", - "Minor": "6", - "Micro": "0.rc1" + "Minor": "8", + "Micro": "1.dev7" }, "Author": "", "AuthorEmail": "", @@ -16,7 +16,7 @@ "LicenseName": "", "LicenseDescription": "", "Dependencies": [ - "cpl-core>=2022.6.0.rc1" + "cpl-core>=2022.8.1.dev7" ], "PythonVersion": ">=3.10.4", "PythonPath": { diff --git a/unittests/unittests_query/unittests_query.json b/unittests/unittests_query/unittests_query.json index 5b7d1718..5980b5b0 100644 --- a/unittests/unittests_query/unittests_query.json +++ b/unittests/unittests_query/unittests_query.json @@ -3,8 +3,8 @@ "Name": "unittest_query", "Version": { "Major": "2022", - "Minor": "6", - "Micro": "0.rc1" + "Minor": "8", + "Micro": "1.dev7" }, "Author": "", "AuthorEmail": "", @@ -16,8 +16,8 @@ "LicenseName": "", "LicenseDescription": "", "Dependencies": [ - "cpl-core>=2022.6.0.rc1", - "cpl-query>=2022.6.0.rc1" + "cpl-core>=2022.8.1.dev7", + "cpl-query>=2022.8.1.dev7" ], "PythonVersion": ">=3.10.4", "PythonPath": { diff --git a/unittests/unittests_shared/unittests_shared.json b/unittests/unittests_shared/unittests_shared.json index 7d6c385d..e414e3bd 100644 --- a/unittests/unittests_shared/unittests_shared.json +++ b/unittests/unittests_shared/unittests_shared.json @@ -3,8 +3,8 @@ "Name": "unittest_shared", "Version": { "Major": "2022", - "Minor": "6", - "Micro": "0.rc1" + "Minor": "8", + "Micro": "1.dev7" }, "Author": "", "AuthorEmail": "", @@ -16,7 +16,7 @@ "LicenseName": "", "LicenseDescription": "", "Dependencies": [ - "cpl-core>=2022.6.0.rc1" + "cpl-core>=2022.8.1.dev7" ], "PythonVersion": ">=3.10.4", "PythonPath": {