|
5 | 5 | import re |
6 | 6 | import logging.config |
7 | 7 | import sys |
| 8 | +import time |
8 | 9 | import html2text |
9 | 10 |
|
10 | 11 | import gcld3 |
|
17 | 18 | ################################## |
18 | 19 | from lib import ail_logger |
19 | 20 | from lib.ConfigLoader import ConfigLoader |
20 | | -from lib.ail_core import get_object_all_subtypes |
| 21 | +from lib.ail_core import get_object_all_subtypes, generate_uuid |
21 | 22 |
|
22 | 23 | logging.config.dictConfig(ail_logger.get_config(name='ail')) |
23 | 24 | logger = logging.getLogger() |
@@ -320,6 +321,10 @@ def get_iso_from_languages(l_languages, sort=False): |
320 | 321 | l_iso = sorted(l_iso) |
321 | 322 | return l_iso |
322 | 323 |
|
| 324 | +def exists_lang_iso_target_source(source, target): |
| 325 | + if source not in dict_iso_languages or target not in dict_iso_languages: |
| 326 | + return False |
| 327 | + return True |
323 | 328 |
|
324 | 329 | def get_translator_instance(): |
325 | 330 | return TRANSLATOR_URL |
@@ -566,8 +571,21 @@ def _get_obj_translation(obj_global_id, language, source=None, content=None, fie |
566 | 571 | def get_obj_translation(obj_global_id, language, source=None, content=None, field='', objs_containers=set()): |
567 | 572 | return _get_obj_translation(obj_global_id, language, source=source, content=content, field=field, objs_containers=objs_containers) |
568 | 573 |
|
| 574 | +def get_obj_translated_languages(obj_gid): |
| 575 | + return r_lang.hkeys(f'tr:{obj_gid}:') |
569 | 576 |
|
570 | | -# TODO Force to edit ???? |
| 577 | +def get_obj_translated(obj_gid, language_name=False): |
| 578 | + translation = r_lang.hgetall(f'tr:{obj_gid}:') |
| 579 | + if not language_name: |
| 580 | + return translation |
| 581 | + else: |
| 582 | + translated = {} |
| 583 | + for lang_code in translation: |
| 584 | + translated[get_language_from_iso(lang_code)] = translation[lang_code] |
| 585 | + return translated |
| 586 | + |
| 587 | +def exists_object_translation_language(obj_gid, target): |
| 588 | + return r_lang.hexists(f'tr:{obj_gid}:', target) |
571 | 589 |
|
572 | 590 | def set_obj_translation(obj_global_id, language, translation, field=''): |
573 | 591 | r_cache.delete(f'translation:{language}:{obj_global_id}:') |
@@ -699,7 +717,7 @@ def detect(self, content): |
699 | 717 | # print('##############################################################') |
700 | 718 | return language[0] |
701 | 719 |
|
702 | | - def translate(self, content, source=None, target="eng"): |
| 720 | + def translate(self, content, source=None, target="eng", filter_same_content=True): |
703 | 721 | # print(source, target) |
704 | 722 | l_languages = get_translation_languages() |
705 | 723 | if source: |
@@ -728,10 +746,13 @@ def translate(self, content, source=None, target="eng"): |
728 | 746 | try: |
729 | 747 | # print(source_iso1, target_iso1) |
730 | 748 | translation = self.lt.translate(content, source_iso1, target_iso1) |
| 749 | + # Fix libretranslate dot panic |
| 750 | + if translation.endswith('........'): |
| 751 | + translation = translation.replace('........', '.') |
731 | 752 | except Exception as e: |
732 | 753 | logger.error(f'Libretranslate Translation: {e}') |
733 | 754 | translation = None |
734 | | - if translation == content: |
| 755 | + if translation == content and filter_same_content: |
735 | 756 | # print('EQUAL') |
736 | 757 | translation = None |
737 | 758 | return source, translation |
@@ -761,8 +782,158 @@ def get_translation_languages(): |
761 | 782 | def ping_libretranslate(): |
762 | 783 | return LanguageTranslator().ping() |
763 | 784 |
|
764 | | -def translate(content, source, target="eng"): |
765 | | - return LanguageTranslator().translate(content, source=source, target=target) |
| 785 | +def translate(content, source, target="eng", filter_same_content=False): |
| 786 | + return LanguageTranslator().translate(content, source=source, target=target, filter_same_content=filter_same_content) |
| 787 | + |
| 788 | +## Translation Task ## |
| 789 | + |
| 790 | +def get_translation_tasks(): |
| 791 | + return r_lang.smembers('tasks:translation') |
| 792 | + |
| 793 | +def is_translation_task_running(task_uuid): |
| 794 | + start = r_lang.hget(f'task:tr:{task_uuid[0]}', 'start') |
| 795 | + if start: |
| 796 | + start = int(start) |
| 797 | + if start + 3600 < int(time.time()): |
| 798 | + return False |
| 799 | + else: |
| 800 | + return True |
| 801 | + else: |
| 802 | + return False |
| 803 | + |
| 804 | +def _get_translation_task_to_launch(i_task_uuid): |
| 805 | + task_uuid = None |
| 806 | + for task_uuid in r_lang.smembers('tasks:translation'): |
| 807 | + if task_uuid != i_task_uuid: |
| 808 | + if not is_translation_task_running(task_uuid): |
| 809 | + return task_uuid |
| 810 | + return task_uuid |
| 811 | + |
| 812 | +def get_translation_task_to_launch(): |
| 813 | + task_uuid = r_lang.srandmember('tasks:translation') |
| 814 | + if task_uuid: |
| 815 | + task_uuid = task_uuid[0] |
| 816 | + if not is_translation_task_running(task_uuid): |
| 817 | + return task_uuid |
| 818 | + else: |
| 819 | + return _get_translation_task_to_launch(task_uuid) |
| 820 | + else: |
| 821 | + return None |
| 822 | + |
| 823 | +class TranslationTask: |
| 824 | + def __init__(self, task_uuid): |
| 825 | + self.uuid = task_uuid |
| 826 | + |
| 827 | + def exists(self): |
| 828 | + return r_lang.exists(f'task:tr:{self.uuid}') |
| 829 | + |
| 830 | + def _get_field(self, field): |
| 831 | + return r_lang.hget(f'task:tr:{self.uuid}', field) |
| 832 | + |
| 833 | + def _set_field(self, field, value): |
| 834 | + r_lang.hset(f'task:tr:{self.uuid}', field, value) |
| 835 | + |
| 836 | + def get_source(self): |
| 837 | + return self._get_field('source') |
| 838 | + |
| 839 | + def get_target(self): |
| 840 | + return self._get_field('target') |
| 841 | + |
| 842 | + def get_progress(self): |
| 843 | + return self._get_field('progress') |
| 844 | + |
| 845 | + def update_time(self): |
| 846 | + return self._set_field('time', int(time.time())) |
| 847 | + |
| 848 | + def update_progress(self, done, total): |
| 849 | + if done < 0: |
| 850 | + done = 1 |
| 851 | + progress = int(done * 100 / total) |
| 852 | + if progress == 100: |
| 853 | + progress = 99 |
| 854 | + self._set_field('progress', progress) |
| 855 | + self.update_time() |
| 856 | + |
| 857 | + def get_object(self): |
| 858 | + return self._get_field('object') |
| 859 | + |
| 860 | + def create(self, obj_gid, source, target): |
| 861 | + r_lang.sadd('tasks:translation', self.uuid) |
| 862 | + r_lang.sadd(f'tasks:translation:obj:{obj_gid}', self.uuid) |
| 863 | + self._set_field('object', obj_gid) |
| 864 | + self._set_field('source', source) |
| 865 | + self._set_field('target', target) |
| 866 | + self._set_field('progress', 0) |
| 867 | + |
| 868 | + def start(self): |
| 869 | + self._set_field('progress', 0) |
| 870 | + self._set_field('start', int(time.time())) |
| 871 | + |
| 872 | + # set as filename for pdf |
| 873 | + def complete(self, translation): |
| 874 | + set_obj_translation(self.get_object(), self.get_target(), translation) |
| 875 | + self.delete() |
| 876 | + |
| 877 | + def delete(self): |
| 878 | + r_lang.srem('tasks:translation', self.uuid) |
| 879 | + r_lang.srem(f'tasks:translation:obj:{self.get_object()}', self.uuid) |
| 880 | + r_lang.delete(f'task:tr:{self.uuid}') |
| 881 | + |
| 882 | +def exists_task(obj_gid, source, target): |
| 883 | + task_uuid = False |
| 884 | + for task_uuid in get_object_tasks_uuid(obj_gid): |
| 885 | + task = TranslationTask(task_uuid) |
| 886 | + if task.get_source() == source and task.get_target() == target: |
| 887 | + task_uuid = task.uuid |
| 888 | + break |
| 889 | + return task_uuid |
| 890 | + |
| 891 | +def create_translation_task(obj_gid, source, target, force=False): |
| 892 | + task_uuid = exists_task(obj_gid, source, target) |
| 893 | + if task_uuid: |
| 894 | + if force: |
| 895 | + task = TranslationTask(task_uuid) |
| 896 | + task.delete() |
| 897 | + else: |
| 898 | + return task_uuid |
| 899 | + task = TranslationTask(generate_uuid()) |
| 900 | + task.create(obj_gid, source, target) |
| 901 | + return task.uuid |
| 902 | + |
| 903 | +def get_object_tasks_uuid(obj_gid): |
| 904 | + return r_lang.smembers(f'tasks:translation:obj:{obj_gid}') |
| 905 | + |
| 906 | +def get_object_tasks(obj_gid, language_name=False): |
| 907 | + tasks = {} |
| 908 | + for task_uuid in get_object_tasks_uuid(obj_gid): |
| 909 | + task = TranslationTask(task_uuid) |
| 910 | + target = task.get_target() |
| 911 | + if language_name: |
| 912 | + target = get_language_from_iso(target) |
| 913 | + tasks[task_uuid] = {'progress': task.get_progress(), 'target': target} |
| 914 | + return tasks |
| 915 | + |
| 916 | +def api_get_translation_task_progress(task_uuid): |
| 917 | + task = TranslationTask(task_uuid) |
| 918 | + if not task.exists(): |
| 919 | + return {'error': 'Unknown translation task'}, 404 |
| 920 | + return task.get_progress(), 200 |
| 921 | + |
| 922 | +def api_get_object_translation_tasks_progress(tasks_uuid): |
| 923 | + tasks = {} |
| 924 | + for task_uuid in tasks_uuid: |
| 925 | + task = TranslationTask(task_uuid) |
| 926 | + if not task.exists(): |
| 927 | + return {'error': 'Unknown translation task'}, 404 |
| 928 | + tasks[task_uuid] = task.get_progress() |
| 929 | + return tasks, 200 |
| 930 | + |
| 931 | + |
| 932 | +def api_delete_translation_task(task_uuid): |
| 933 | + task = TranslationTask(task_uuid) |
| 934 | + if not task.exists(): |
| 935 | + return {'error': 'Unknown translation task'}, 404 |
| 936 | + return task.delete(), 200 |
766 | 937 |
|
767 | 938 |
|
768 | 939 | if __name__ == '__main__': |
|
0 commit comments