Unverified Commit b8ef4f4c authored by dmMaze's avatar dmMaze Committed by GitHub
Browse files

Merge pull request #721 from minicom365/dev-eztrans

add ezTrans translator
parents 08142592 2dea3777
Loading
Loading
Loading
Loading
+52 −0
Original line number Diff line number Diff line
# -*- coding: utf-8 -*-
from ctypes import c_char_p, c_int, c_wchar_p
from ctypes.wintypes import BOOL
from typing import Literal
from msl.loadlib import Server32

import re

ENGINE_TYPES = Literal['J2K', 'K2J']


class MyServer(Server32):
    def __init__(self, host, port, engine_path, engine_type: ENGINE_TYPES, dat_path):
        super(MyServer, self).__init__(engine_path, 'windll', host, port)
        self.engine = TransEngine(self.lib, engine_type, dat_path)

    def translate(self, src_text: str | list) -> str | list:
        def work(t):
            return encode_text(self.engine.translate(decode_text(t)))
        if type(src_text) == list:
            if len(src_text) == 1:
                return [work(src_text[0])]
            return self.translate(src_text[:-1]) + [work(src_text[-1])]
        elif type(src_text) == str:
            return work(src_text)


class TransEngine:
    def __init__(self, engine, engine_type: ENGINE_TYPES, dat_path):
        self.start = getattr(engine, f"{engine_type}_InitializeEx")
        self.start.argtypes = [c_char_p, c_char_p]
        self.start.restype = BOOL
        self.trans = getattr(engine, f"{engine_type}_TranslateMMNTW")
        self.trans.argtypes = [c_int, c_wchar_p]
        self.trans.restype = c_wchar_p
        self.start_obj = self.start(b"CSUSER123455", dat_path.encode('utf-8'))

    def translate(self, src_text):
        trans_obj = self.trans(0, src_text)
        return trans_obj


def decode_text(txt):
    chars = "↔◁◀▷▶♤♠♡♥♧♣⊙◈▣◐◑▒▤▥▨▧▦▩♨☏☎☜☞↕↗↙↖↘♩♬㉿㈜㏇™㏂㏘"'∼ˇ˘˝¡˚˙˛¿ː∏₩℉€㎕㎖㎗ℓ㎘㎣㎤㎥㎦㎙㎚㎛㎟㎠㎢㏊㎍㏏㎈㎉㏈㎧㎨㎰㎱㎲㎳㎴㎵㎶㎷㎸㎀㎁㎂㎃㎄㎺㎻㎼㎽㎾㎿㎐㎑㎒㎓㎔Ω㏀㏁㎊㎋㎌㏖㏅㎭㎮㎯㏛㎩㎪㎫㎬㏝㏐㏓㏃㏉㏜㏆┒┑┚┙┖┕┎┍┞┟┡┢┦┧┪┭┮┵┶┹┺┽┾╀╁╃╄╅╆╇╈╉╊┱┲ⅰⅱⅲⅳⅴⅵⅶⅷⅸⅹ½⅓⅔¼¾⅛⅜⅝⅞ⁿ₁₂₃₄ŊđĦIJĿŁŒŦħıijĸŀłœŧŋʼn㉠㉡㉢㉣㉤㉥㉦㉧㉨㉩㉪㉫㉬㉭㉮㉯㉰㉱㉲㉳㉴㉵㉶㉷㉸㉹㉺㉻㈀㈁㈂㈃㈄㈅㈆㈇㈈㈉㈊㈋㈌㈍㈎㈏㈐㈑㈒㈓㈔㈕㈖㈗㈘㈙㈚㈛ⓐⓑⓒⓓⓔⓕⓖⓗⓘⓙⓚⓛⓜⓝⓞⓟⓠⓡⓢⓣⓤⓥⓦⓧⓨⓩ①②③④⑤⑥⑦⑧⑨⑩⑪⑫⑬⑭⑮⒜⒝⒞⒟⒠⒡⒢⒣⒤⒥⒦⒧⒨⒩⒪⒫⒬⒭⒮⒯⒰⒱⒲⒳⒴⒵⑴⑵⑶⑷⑸⑹⑺⑻⑼⑽⑾⑿⒀⒁⒂"
    for c in chars:
        if c in txt:
            txt = txt.replace(c, "\\u" + str(hex(ord(c)))[2:])
    return txt


def encode_text(txt):
    return re.sub(r'(?i)(?<!\\)(?:\\\\)*\\u([0-9a-f]{4})', lambda m: chr(int(m.group(1), 16)), txt)
+57 −0
Original line number Diff line number Diff line
from pathlib import Path
import sys
from .base import *

from typing import Literal
from msl.loadlib import Client64


class MyClient(Client64):
    def __init__(self, engine_path, engine_type: Literal['J2K', 'K2J'], dat_path):
        super(MyClient, self).__init__(module32=str(Path(__file__).parent) + '\module_eztrans32.py',
                                       engine_path=engine_path,
                                       engine_type=engine_type,
                                       dat_path=dat_path)

    def translate(self, src_text: str | list):
        return self.request32('translate', src_text)


@register_translator('ezTrans')
class ezTransTranslator(BaseTranslator):
    concate_text = False

    params: Dict = {
        'path_dat': r"C:\Program Files (x86)\ChangShinSoft\ezTrans XP\Dat",
        'path_j2k': r"C:\Program Files (x86)\ChangShinSoft\ezTrans XP\J2KEngine.dll",
        'path_k2j(Optional)': r"C:\Program Files (x86)\ChangShinSoft\ezTrans XP\ehnd-kor.dll"
    }

    def _setup_translator(self):
        self.lang_map['日本語'] = 'j'
        self.lang_map['한국어'] = 'k'

        self.j2k_engine = MyClient(self.params['path_j2k'], "J2K", self.params['path_dat'])
        if self.params['path_k2j(Optional)']:
            self.k2j_engine = MyClient(self.params['path_k2j(Optional)'], "K2J", self.params['path_dat'])

    def _translate(self, src_list: List[str]) -> List[str]:
        source = self.lang_map[self.lang_source]
        target = self.lang_map[self.lang_target]

        if source != target:
            engine: MyClient = getattr(self, f"{source}2{target}_engine")
            return engine.translate(src_list)
        else:
            return src_list

    def updateParam(self, param_key: str, param_content):
        pass

    @property
    def supported_tgt_list(self) -> List[str]:
        return ['한국어', '日本語'] if self.params['path_k2j(Optional)'] else ['한국어']

    @property
    def supported_src_list(self) -> List[str]:
        return ['한국어', '日本語'] if self.params['path_k2j(Optional)'] else ['日本語']
+1 −0
Original line number Diff line number Diff line
@@ -54,3 +54,4 @@ pyobjc-framework-cocoa; sys_platform == 'darwin'
pyobjc-framework-coreml; sys_platform == 'darwin'
pyobjc-framework-quartz; sys_platform == 'darwin'
pyobjc-framework-vision; sys_platform == 'darwin'
msl-loadlib
+48 B (19.3 KiB)

File changed.

No diff preview for this file type.

+6 −6
Original line number Diff line number Diff line
@@ -762,7 +762,7 @@
    <message>
        <location filename="../ui/mainwindow.py" line="206"/>
        <source>Keyword substitution for machine translation</source>
        <translation>기계 번역 키워드 치환</translation>
        <translation>번역문에 대한 키워드 치환(후처리)</translation>
    </message>
    <message>
        <location filename="../ui/mainwindow.py" line="391"/>
@@ -841,7 +841,7 @@
    <message>
        <location filename="../ui/mainwindow.py" line="202"/>
        <source>Keyword substitution for source text</source>
        <translation>소스 텍스트 대한 키워드 치환</translation>
        <translation>원문 대한 키워드 치환(전처리)</translation>
    </message>
    <message>
        <location filename="../ui/mainwindow.py" line="1096"/>
@@ -1282,7 +1282,7 @@ All existing translation results will be cleared!</source>
    <message>
        <location filename="../ui/mainwindowbars.py" line="340"/>
        <source>Keyword substitution for machine translation</source>
        <translation>기계 번역 키워드 치환</translation>
        <translation>번역문에 대한 키워드 치환(후처리)</translation>
    </message>
    <message>
        <location filename="../ui/mainwindowbars.py" line="338"/>
@@ -1382,7 +1382,7 @@ All existing translation results will be cleared!</source>
    <message>
        <location filename="../ui/mainwindowbars.py" line="342"/>
        <source>Keyword substitution for source text</source>
        <translation>소스 텍스트에 대한 키워드 치환</translation>
        <translation>원문에 대한 키워드 치환(전처리)</translation>
    </message>
</context>
<context>
@@ -1408,7 +1408,7 @@ All existing translation results will be cleared!</source>
    <message>
        <location filename="../ui/module_parse_widgets.py" line="324"/>
        <source>Keyword substitution for machine translation</source>
        <translation>기계 번역 키워드 치환</translation>
        <translation>번역문에 대한 키워드 치환(후처리)</translation>
    </message>
    <message>
        <location filename="../ui/module_parse_widgets.py" line="334"/>
@@ -1423,7 +1423,7 @@ All existing translation results will be cleared!</source>
    <message>
        <location filename="../ui/module_parse_widgets.py" line="327"/>
        <source>Keyword substitution for source text</source>
        <translation>소스 텍스트에 대한 키워드 치환</translation>
        <translation>원문에 대한 키워드 치환(전처리)</translation>
    </message>
</context>
<context>