2022.7 - cpl-translation #90
| @@ -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", | ||||
|   | ||||
| @@ -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", | ||||
|   | ||||
| @@ -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 | ||||
|   | ||||
| @@ -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 | ||||
|   | ||||
| @@ -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", | ||||
|   | ||||
| @@ -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" | ||||
|   | ||||
							
								
								
									
										16
									
								
								src/cpl_translation/translate_pipe.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								src/cpl_translation/translate_pipe.py
									
									
									
									
									
										Normal file
									
								
							| @@ -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 '' | ||||
							
								
								
									
										54
									
								
								src/cpl_translation/translation_service.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										54
									
								
								src/cpl_translation/translation_service.py
									
									
									
									
									
										Normal file
									
								
							| @@ -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 | ||||
							
								
								
									
										22
									
								
								src/cpl_translation/translation_service_abc.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								src/cpl_translation/translation_service_abc.py
									
									
									
									
									
										Normal file
									
								
							| @@ -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 | ||||
							
								
								
									
										29
									
								
								src/cpl_translation/translation_settings.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										29
									
								
								src/cpl_translation/translation_settings.py
									
									
									
									
									
										Normal file
									
								
							| @@ -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()}') | ||||
| @@ -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')) | ||||
|   | ||||
| @@ -11,5 +11,13 @@ | ||||
|     "Filename": "log_$start_time.log", | ||||
|     "ConsoleLogLevel": "ERROR", | ||||
|     "FileLogLevel": "WARN" | ||||
|   }, | ||||
| 
 | ||||
|   "Translation": { | ||||
|     "Languages":[ | ||||
|       "de", | ||||
|       "en" | ||||
|     ], | ||||
|     "DefaultLanguage": "en" | ||||
|   } | ||||
| } | ||||
| @@ -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() | ||||
|   | ||||
| @@ -0,0 +1,7 @@ | ||||
| { | ||||
|   "main": { | ||||
|     "text": { | ||||
|       "hello_world": "Hallo Welt" | ||||
|     } | ||||
|   } | ||||
| } | ||||
| @@ -0,0 +1,7 @@ | ||||
| { | ||||
|   "main": { | ||||
|     "text": { | ||||
|       "hello_world": "Hello World" | ||||
|     } | ||||
|   } | ||||
| } | ||||
| @@ -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": {}, | ||||
|   | ||||
| @@ -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", | ||||
|   | ||||
| @@ -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": { | ||||
|   | ||||
| @@ -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": { | ||||
|   | ||||
| @@ -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": { | ||||
|   | ||||
| @@ -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": { | ||||
|   | ||||
| @@ -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": { | ||||
|   | ||||
		Reference in New Issue
	
	Block a user