浏览代码

Add phrasebook and comments.

Cixo Develop 4 月之前
父节点
当前提交
57736eb51e

+ 2 - 1
source/cx_libtranslate/__init__.py

@@ -1 +1,2 @@
-from .translation import translation
+from .translation import translation
+from .phrasebook import phrasebook

+ 205 - 0
source/cx_libtranslate/phrasebook.py

@@ -0,0 +1,205 @@
+from .translation import translation
+
+class phrasebook:
+    """ It store single collection of phrases.
+    
+    This is responsible for searching phrases in the phrasebook, or when
+    object exists, then also in the object notation.
+
+
+    Methods
+    -------
+    tr(phrase: str) -> translation
+        Translate phrase, short version of translate.
+
+    translate(phrase: str) -> translation
+        Translate phrase.
+
+    prepare(phrase: str) -> str
+        This prepare phrase, remove dots and white chars.  
+    """
+
+    def __init__(self, phrases: dict, objects: dict|None = None) -> None:
+        """ This initialize new phrasebook.
+
+        It require phrases dict and also objects for objects notation. Objects
+        is optional, could be leave empty.
+
+        Parameters
+        ----------
+        phrases : dict
+            Dictionary with phrases.
+        
+        objects : dict | None, default: None
+            Objects to take phrases for object notation.
+        """
+
+        self.__phrases = self.__parse_phrases(phrases)
+        self.__objects = objects
+
+    def __parse_phrases(self, phrases: dict) -> dict:
+        """ This prepare phrasebook, by flattending dictionary keys.
+
+        Parameters
+        ----------
+        phrases : dict
+            Dictionary to parse
+
+        Returns
+        -------
+        dict
+            Flattened dictionary with phrases.
+        """
+
+        flattened = dict()
+
+        for key in phrases.keys():
+            flat_key = phrasebook.prepare(key)
+
+            if flat_key in flattened:
+                raise TypeError("Key \"" + flat_key + "\" exists twice.")
+
+            flattened[flat_key] = phrases[key]
+
+        return flattened
+
+    def tr(self, phrase: str) -> translation:
+        """ This translate phrase, from phrases or objects.
+
+        Parameters
+        ----------
+        phrase : str
+            Phrase to translate.
+
+        Returns
+        -------
+        translation
+            Translated phrase.
+        """
+
+        return self.translate(phrase)
+
+    def translate(self, phrase: str) -> translation:
+        """ This translate phrase, from phrases or objects.
+
+        Parameters
+        ----------
+        phrase : str
+            Phrase to translate.
+
+        Returns
+        -------
+        translation
+            Translated phrase.
+        """
+        
+        if self.__is_nested(phrase):
+            return self.__translate_nested(phrase)
+
+        return self.__translate_flat(phrasebook.prepare(phrase))
+
+    def __translate_nested(self, phrase: str) -> translation:
+        """ This translate nested phrase.
+        
+        This transalate nested phrase, that mean phrase in object 
+        notation. When objects is not set, then return phrase as
+        failed translation.
+
+        Parameters
+        ----------
+        phrase : str
+            Nested phrase to translate.
+
+        Raises
+        ------
+        SyntaxError
+            When two dots '..' found in phrase.
+
+        Returns
+        -------
+        translation
+            Translated nested phrase.
+        """
+
+        if phrase.find("..") != -1:
+            raise SyntaxError("Symbol \"..\" in \"" + phrase + "\".")
+
+        if self.__objects is None:
+            return translation(phrase, False)
+
+        parts = phrase.split(".")
+        current = self.__objects
+
+        for part in parts:
+            if type(current) is not dict:
+                return translation(phrase, False)
+
+            if not part in current:
+                return translation(phrase, False)
+            
+            current = current[part]
+
+        if type(current) is str:
+            return translation(current, True)
+
+        return translation(phrase, False)
+
+    def __is_nested(self, phrase: str) -> bool:
+        """ This check that phrase is nested or not. 
+        
+        When phrase contain white chars, or dot only as last chat, then
+        it is not nested. When phrase contain dot, then phrase is nested.
+
+        Parameters
+        ----------
+        phrase : str
+            Phrase to check.
+
+        Returns
+        -------
+        bool
+            True when phrase is nested, False if not.
+        """
+
+        if phrase.find(" ") != -1:
+            return False
+
+        if phrase[-1] == ".":
+            return False
+
+        return phrase.find(".") != -1
+
+    def __translate_flat(self, phrase: str) -> translation:
+        """ This translate standard flat phrase.
+
+        Parameters
+        ----------
+        phrase : str
+            Phrase to translate.
+
+        Returns
+        -------
+        translation
+            Translation of the phrase.
+        """
+
+        if phrase in self.__phrases:
+            return translation(self.__phrases[phrase], True)
+
+        return translation(phrase, False)
+
+    def prepare(phrase: str) -> str:
+        """ This prepare phrase to being phrasebook dict key.
+        
+        Parameters
+        ----------
+        phrase : str
+            Phrase to translate.
+
+        Returns
+        -------
+        str
+            Prepared phrase.
+        """
+
+        return phrase.lower().replace(" ", "_").replace(".", "")

+ 75 - 1
source/cx_libtranslate/translation.py

@@ -1,20 +1,94 @@
 class translation:
+    """ This ciass is responsible for single translation in the library.
+
+    This store single translation, and its state. Could be casted to string
+    and formated. When translated phrase must contain variables, that 
+    could be passed by format function, and `#{ name }` in the phrase.
+
+    Attributes
+    ----------
+    text : str
+        Phrase content as string.
+
+    valid : bool
+        True when phrase was translated correctly or False when not.
+
+    Methods
+    -------
+    format(params: dict) -> dict
+        That method could format translated phrase with given dict.
+    """
+
     def __init__(self, content: str, success: bool = True) -> None:
+        """ This create new translaed phrase. 
+        
+        It require string content of the translated phrase, and also state
+        of the translation. When phrase was translated successfull, then 
+        state is True but when phrase could not being found, state is False.
+
+        Parameters
+        ----------
+        content : str
+            Content of the translated phrase.
+        success : bool, default: True
+            State of the translation. 
+        """
+
         self.__success = success
         self.__content = content
 
     def __str__(self) -> str:
+        """ This returns content of the phrase.
+
+        Returns
+        -------
+        str
+            Content of the translated phrase.
+        """
+
         return self.__content
 
     @property
     def text(self) -> str:
+        """ String content of the phrase.
+
+        Returns
+        -------
+        str
+            Content of the translated phrase.
+        """
+
         return self.__content
 
     @property
     def valid(self) -> bool:
+        """ This returns that phrase was translated propertly.
+
+        Returns
+        -------
+        bool
+            True when phrase was translated propertly or false when not.
+        """
+
         return self.__success
 
     def format(self, params: dict) -> str:
+        """ This format translated phrase by inserting given items into it.
+
+        Parameters
+        ----------
+        params : str
+            Items to insert into translated string.
+
+        Returns
+        -------
+        str
+            Translated content with inserted given values.
+        """
+
+        if not self.__success:
+            return self.__content
+
         parts = self.__content.split("#{")
         results = parts.pop(0)
 
@@ -22,7 +96,7 @@ class translation:
             elements = count.split("}")
 
             if len(elements) == 1:
-                results.append(count)
+                results = results + count
                 continue
 
             name = elements.pop(0).strip()

+ 2 - 2
tests/001-translation.py

@@ -9,11 +9,11 @@ sys.path.append(str(package))
 
 import cx_libtranslate
 
-sample = cx_libtranslate.translation("This is #{ sample } with #{ number }")
+sample = cx_libtranslate.translation("This is #{ sample } with #{ number } but this #{ not_exists } and that is #{ bad } type of } } #{ format }} what is it. Number: #{ number }.")
 
 print("Testing...")
 print("Result: " + str(sample))
 print("Formated: " + sample.format({
     "sample": "example", 
     "number": 10
-}))
+})  )

+ 29 - 0
tests/002-phrasebook.py

@@ -0,0 +1,29 @@
+import pathlib
+
+current = pathlib.Path(__file__).parent
+root = current.parent
+package = root / pathlib.Path("source")
+
+import sys
+sys.path.append(str(package))
+
+import cx_libtranslate
+
+phrases = {
+    "sample": "Przyklad",
+    "For example.": "Na przyklad."
+}
+
+objects = {
+    "a": {
+        "b": {
+            "c": "result"
+        }
+    }
+}
+
+phrasebook = cx_libtranslate.phrasebook(phrases, objects)
+print(phrasebook.translate("sample"))
+print(phrasebook.translate("For example."))
+print(phrasebook.translate("This not exists."))
+print(phrasebook.translate("a.b.c"))