|  | @@ -0,0 +1,538 @@
 | 
	
		
			
				|  |  | +#!/usr/bin/env python3
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +import pathlib
 | 
	
		
			
				|  |  | +import typing
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +class file:
 | 
	
		
			
				|  |  | +    """ This class parse single file, and returns all phrases to translate.
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    This open file, and trying to find all phrases to translate in the file.
 | 
	
		
			
				|  |  | +    Process is separated to few steps, first run filter() to get all lines
 | 
	
		
			
				|  |  | +    when translate functions exists. Then run parse(), which would get 
 | 
	
		
			
				|  |  | +    phrases and append it to list. On the end, could get results as list by
 | 
	
		
			
				|  |  | +    result() function, which return list with all phrases, or phrases() 
 | 
	
		
			
				|  |  | +    generator, which iterate on all of them.
 | 
	
		
			
				|  |  | +    """
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    def __init__(self, target: pathlib.Path) -> None:
 | 
	
		
			
				|  |  | +        """ It creates new file file parser.
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        Parameters
 | 
	
		
			
				|  |  | +        ----------
 | 
	
		
			
				|  |  | +        target : pathlib.Path
 | 
	
		
			
				|  |  | +            It is path to the file in the filesystem to parse.
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        Raises
 | 
	
		
			
				|  |  | +        ------
 | 
	
		
			
				|  |  | +        TypeError
 | 
	
		
			
				|  |  | +            When target is not afile or not exists.
 | 
	
		
			
				|  |  | +        """
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        if not target.is_file():
 | 
	
		
			
				|  |  | +            raise TypeError("Target \"" + str(target) + "\" not exists.")
 | 
	
		
			
				|  |  | +        
 | 
	
		
			
				|  |  | +        self.__to_parse = None
 | 
	
		
			
				|  |  | +        self.__phrases = None
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        with target.open() as handle:
 | 
	
		
			
				|  |  | +            self.__content = handle.read().split("\n")
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    def __targets(self) -> list:
 | 
	
		
			
				|  |  | +        """ This return targets function which libtranslate use to translates.
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        Returns
 | 
	
		
			
				|  |  | +        -------
 | 
	
		
			
				|  |  | +        list
 | 
	
		
			
				|  |  | +            List with targets to search for in the code.
 | 
	
		
			
				|  |  | +        """
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        return [ "_(", ".translate(", ".tr(", ".phrase ", ".phrase=" ]
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    def __string(self) -> list:
 | 
	
		
			
				|  |  | +        """ This returns javascript string openers and closers.
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        Returns
 | 
	
		
			
				|  |  | +        -------
 | 
	
		
			
				|  |  | +        list
 | 
	
		
			
				|  |  | +            List chars with open and close strings in js.
 | 
	
		
			
				|  |  | +        """
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        return [ '"', "'", "`" ]
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    def __has_phrase(self, line: str) -> bool:
 | 
	
		
			
				|  |  | +        """ This check that given line of code has translation instructions.
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        Parameters
 | 
	
		
			
				|  |  | +        ----------
 | 
	
		
			
				|  |  | +        line : str
 | 
	
		
			
				|  |  | +            Line of code to search for instructions in.
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        Returns
 | 
	
		
			
				|  |  | +        -------
 | 
	
		
			
				|  |  | +        bool
 | 
	
		
			
				|  |  | +            True when line has translations or False when not.
 | 
	
		
			
				|  |  | +        """
 | 
	
		
			
				|  |  | +        
 | 
	
		
			
				|  |  | +        for target in self.__targets():
 | 
	
		
			
				|  |  | +            if line.find(target) != -1:
 | 
	
		
			
				|  |  | +                return True
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        return False
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    def filter(self) -> object:
 | 
	
		
			
				|  |  | +        """ This filter file contents for lines with translation content.
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        This search for translate instructions in all file content. When 
 | 
	
		
			
				|  |  | +        line contain translation instructions, then it append it to new 
 | 
	
		
			
				|  |  | +        list, which would be processed in the next step.
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        Returns
 | 
	
		
			
				|  |  | +        -------
 | 
	
		
			
				|  |  | +        file
 | 
	
		
			
				|  |  | +            Own instanct for chain loading.
 | 
	
		
			
				|  |  | +        """
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        self.__to_parse = list()
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        for line in self.__content:
 | 
	
		
			
				|  |  | +            if self.__has_phrase(line):
 | 
	
		
			
				|  |  | +                self.__to_parse.append(line)
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        return self
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    def __get_next(self, line: str, start: int) -> int:
 | 
	
		
			
				|  |  | +        """ This return next speech of the translation instruction.
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        This function trying to find next speech of any from translation 
 | 
	
		
			
				|  |  | +        instructions. When it found, then return position of the end of 
 | 
	
		
			
				|  |  | +        that function, but when could not found anything, then return -1.
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        Parameters
 | 
	
		
			
				|  |  | +        ----------
 | 
	
		
			
				|  |  | +        line : str
 | 
	
		
			
				|  |  | +            Line to found instruction in.
 | 
	
		
			
				|  |  | +        
 | 
	
		
			
				|  |  | +        start : int
 | 
	
		
			
				|  |  | +            This is position when start to searching for.
 | 
	
		
			
				|  |  | +        
 | 
	
		
			
				|  |  | +        Returns
 | 
	
		
			
				|  |  | +        -------
 | 
	
		
			
				|  |  | +        int
 | 
	
		
			
				|  |  | +            Position of the end of found instruction or -1 when not found.
 | 
	
		
			
				|  |  | +        """
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        result = -1
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        for target in self.__targets():
 | 
	
		
			
				|  |  | +            position = line.find(target, start)
 | 
	
		
			
				|  |  | +            
 | 
	
		
			
				|  |  | +            if position == -1:
 | 
	
		
			
				|  |  | +                continue
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            position = position + len(target)
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            if result == -1:
 | 
	
		
			
				|  |  | +                result = position
 | 
	
		
			
				|  |  | +                continue
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            if result > position:
 | 
	
		
			
				|  |  | +                result = position
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        return result
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    def __get_string_pos(self, line: str, start: int) -> int:
 | 
	
		
			
				|  |  | +        """ This return next position of the string in the line.
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        This trying to search string in the line, when found it, then return
 | 
	
		
			
				|  |  | +        it position, or return -1 when not found anything. It return position
 | 
	
		
			
				|  |  | +        of the start string char, in opposition to __get_next.
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        Parameters
 | 
	
		
			
				|  |  | +        ----------
 | 
	
		
			
				|  |  | +        line : str
 | 
	
		
			
				|  |  | +            Line to search for string in.
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        start : int
 | 
	
		
			
				|  |  | +            Position to start searching in.
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        Returns
 | 
	
		
			
				|  |  | +        -------
 | 
	
		
			
				|  |  | +        int
 | 
	
		
			
				|  |  | +            Position of the string, or -1.
 | 
	
		
			
				|  |  | +        """
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        for target in self.__string():
 | 
	
		
			
				|  |  | +            position = line.find(target, start)
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            if position == -1:
 | 
	
		
			
				|  |  | +                continue
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            return position 
 | 
	
		
			
				|  |  | +        
 | 
	
		
			
				|  |  | +        return -1
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    def __cut_text(self, line: str, position: int) -> str|None:
 | 
	
		
			
				|  |  | +        """ This get string from given line next to given position.
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        This trying to find string next to given position. When found it, 
 | 
	
		
			
				|  |  | +        then get it, and return its content. When not found anything, then
 | 
	
		
			
				|  |  | +        return None.
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        Parameters
 | 
	
		
			
				|  |  | +        ----------
 | 
	
		
			
				|  |  | +        line : str
 | 
	
		
			
				|  |  | +            Line to search for string in.
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        position : int
 | 
	
		
			
				|  |  | +            Position to search for string on.
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        Returns
 | 
	
		
			
				|  |  | +        -------
 | 
	
		
			
				|  |  | +        str
 | 
	
		
			
				|  |  | +            Content of the found string.
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        None
 | 
	
		
			
				|  |  | +            When not found any string.
 | 
	
		
			
				|  |  | +        """
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        start = self.__get_string_pos(line, position)
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        if start == -1:
 | 
	
		
			
				|  |  | +            return None
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        char = line[start]
 | 
	
		
			
				|  |  | +        start = start + 1
 | 
	
		
			
				|  |  | +        end = line.find(char, start)
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        if end == -1:
 | 
	
		
			
				|  |  | +            return None
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        return line[start:end]
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    def __parse_line(self, line: str) -> typing.Iterator[str]:
 | 
	
		
			
				|  |  | +        """ This parse single line, and return generator with found phrases.
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        Parameters
 | 
	
		
			
				|  |  | +        ----------
 | 
	
		
			
				|  |  | +        line : str
 | 
	
		
			
				|  |  | +            Line to parse.
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        Returns
 | 
	
		
			
				|  |  | +        -------
 | 
	
		
			
				|  |  | +        Iterator[str]
 | 
	
		
			
				|  |  | +            All found phrases in the line.
 | 
	
		
			
				|  |  | +        """
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        current = 0
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        while True:
 | 
	
		
			
				|  |  | +            current = self.__get_next(line, current)
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            if current == -1:
 | 
	
		
			
				|  |  | +                break
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            text = self.__cut_text(line, current)
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            if text is None:
 | 
	
		
			
				|  |  | +                continue
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            current = current + len(text)
 | 
	
		
			
				|  |  | +            yield text
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    def parse(self) -> object:
 | 
	
		
			
				|  |  | +        """ This parse all lines in the file.
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        Returns
 | 
	
		
			
				|  |  | +        -------
 | 
	
		
			
				|  |  | +        file    
 | 
	
		
			
				|  |  | +            Own instance to chain loading.
 | 
	
		
			
				|  |  | +        """
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        if self.__to_parse is None:
 | 
	
		
			
				|  |  | +            raise RuntimeError("Run filter() first.")
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        self.__phrases = list()
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        for line in self.__to_parse:
 | 
	
		
			
				|  |  | +            for count in self.__parse_line(line):
 | 
	
		
			
				|  |  | +                if not count in self.__phrases:
 | 
	
		
			
				|  |  | +                    self.__phrases.append(count)
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        return self
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    def result(self) -> list:
 | 
	
		
			
				|  |  | +        """ This return all founded phrases as list.
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        Raises
 | 
	
		
			
				|  |  | +        ------
 | 
	
		
			
				|  |  | +        RuntimeError
 | 
	
		
			
				|  |  | +            When not run parse() before.
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        Returns
 | 
	
		
			
				|  |  | +        -------
 | 
	
		
			
				|  |  | +        list
 | 
	
		
			
				|  |  | +            List with all found phrases.
 | 
	
		
			
				|  |  | +        """
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        if self.__phrases is None:
 | 
	
		
			
				|  |  | +            raise RuntimeError("Run parse() first.")
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        return self.__phrases
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    def phrases(self) ->typing.Iterator[str]:
 | 
	
		
			
				|  |  | +        """ This returns generator with all phrases.
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        Raises
 | 
	
		
			
				|  |  | +        ------
 | 
	
		
			
				|  |  | +        RuntimeError
 | 
	
		
			
				|  |  | +            When not run parse() before.
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        Returns
 | 
	
		
			
				|  |  | +        -------
 | 
	
		
			
				|  |  | +        Iterator[str]
 | 
	
		
			
				|  |  | +            Generator with all phrases.
 | 
	
		
			
				|  |  | +        """
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        for phrase in self.result():
 | 
	
		
			
				|  |  | +            yield phrase
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +class directory:
 | 
	
		
			
				|  |  | +    """ This open all Javascript files in the directory and search phrases.
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    This trying to open all Javascript files and all Javascript in the 
 | 
	
		
			
				|  |  | +    subdirectories. Then parsing all that files, and adding phrases from 
 | 
	
		
			
				|  |  | +    its to the list. On the end that phrases could be returned as list, or
 | 
	
		
			
				|  |  | +    loaded from Iterator.
 | 
	
		
			
				|  |  | +    """
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    def __init__(self, target: pathlib.Path) -> None:
 | 
	
		
			
				|  |  | +        """ This create new directory instance.
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        Raises
 | 
	
		
			
				|  |  | +        ------
 | 
	
		
			
				|  |  | +        TypeError
 | 
	
		
			
				|  |  | +            When target path is not directory.
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        Parameters
 | 
	
		
			
				|  |  | +        ----------
 | 
	
		
			
				|  |  | +        target : pathlib.Path
 | 
	
		
			
				|  |  | +            Directory to work in.
 | 
	
		
			
				|  |  | +        """
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        if not target.is_dir():
 | 
	
		
			
				|  |  | +            raise TypeError("Target \"" + str(target) + "\" is not dir.")
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        self.__target = target
 | 
	
		
			
				|  |  | +        self.__phrases = list()
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    def __append(self, phrases: list) -> None:
 | 
	
		
			
				|  |  | +        """ This append new phrase to phrases list.
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        Parameters
 | 
	
		
			
				|  |  | +        ----------
 | 
	
		
			
				|  |  | +        phrases : list
 | 
	
		
			
				|  |  | +            List of phrases to add.
 | 
	
		
			
				|  |  | +        """
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        for phrase in phrases:
 | 
	
		
			
				|  |  | +            if phrase in self.__phrases:
 | 
	
		
			
				|  |  | +                continue
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            self.__phrases.append(phrase)
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    def process(self) -> object:
 | 
	
		
			
				|  |  | +        """ This process given directory.
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        Returns
 | 
	
		
			
				|  |  | +        -------
 | 
	
		
			
				|  |  | +        directory
 | 
	
		
			
				|  |  | +            Own instance to chain loading.
 | 
	
		
			
				|  |  | +        """
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        self.__process_directory(self.__target)
 | 
	
		
			
				|  |  | +        return self
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    def result(self) -> list:
 | 
	
		
			
				|  |  | +        """ This return list with result.
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        Returns
 | 
	
		
			
				|  |  | +        -------
 | 
	
		
			
				|  |  | +        list
 | 
	
		
			
				|  |  | +            List with phrases from the files.
 | 
	
		
			
				|  |  | +        """
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        return self.__phrases
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    def phrases(self) -> typing.Iterator[str]:
 | 
	
		
			
				|  |  | +        """ This return all phrases as iterator.
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        Returns
 | 
	
		
			
				|  |  | +        -------
 | 
	
		
			
				|  |  | +        Iterator[str]
 | 
	
		
			
				|  |  | +            All phrases from files.
 | 
	
		
			
				|  |  | +        """
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        for phrase in self.__phrases:
 | 
	
		
			
				|  |  | +            yield phrase
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    def __js_extensions(self) -> list:
 | 
	
		
			
				|  |  | +        """ This return all extensions for js files.
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        Returns
 | 
	
		
			
				|  |  | +        -------
 | 
	
		
			
				|  |  | +        list
 | 
	
		
			
				|  |  | +            All js files extensions.
 | 
	
		
			
				|  |  | +        """
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        return [ "js", "mjs", "ts" ]
 | 
	
		
			
				|  |  | +    
 | 
	
		
			
				|  |  | +    def __process_directory(self, directory: pathlib.Path) -> None:
 | 
	
		
			
				|  |  | +        """ This process given directory.
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        This process given directory, when in directory exists any diretory, 
 | 
	
		
			
				|  |  | +        then it would be processed by that function recursive. When found
 | 
	
		
			
				|  |  | +        file, then parse it, and add phrases from it to the list.
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        Parameters
 | 
	
		
			
				|  |  | +        ----------
 | 
	
		
			
				|  |  | +        directory : pathlib.Path
 | 
	
		
			
				|  |  | +            Directory to work on
 | 
	
		
			
				|  |  | +        """
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        for count in directory.iterdir():
 | 
	
		
			
				|  |  | +            if count.is_dir():
 | 
	
		
			
				|  |  | +                self.__process_directory(count)
 | 
	
		
			
				|  |  | +                continue
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            if count.is_file():
 | 
	
		
			
				|  |  | +                self.__process_file(count)
 | 
	
		
			
				|  |  | +                continue
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    def __process_file(self, target: pathlib.Path) -> None:
 | 
	
		
			
				|  |  | +        """ This process single file.
 | 
	
		
			
				|  |  | +        
 | 
	
		
			
				|  |  | +        This process single file. When file is not Javasocript file, then ti
 | 
	
		
			
				|  |  | +        skip it, but when file is Javascript source code, then it trying to 
 | 
	
		
			
				|  |  | +        extract all phrases from it and adds it to phrases list.
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        Parameters
 | 
	
		
			
				|  |  | +        ----------
 | 
	
		
			
				|  |  | +        target : pathlib.Path
 | 
	
		
			
				|  |  | +            Target file to process.
 | 
	
		
			
				|  |  | +        """
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        suffix = target.suffix[1:]
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        if not suffix in self.__js_extensions():
 | 
	
		
			
				|  |  | +            return 
 | 
	
		
			
				|  |  | +        
 | 
	
		
			
				|  |  | +        self.__append(file(target).filter().parse().result())
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +class dictionary:
 | 
	
		
			
				|  |  | +    """ This create new sample dictionary with phrases.
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    This class create sample dictionary file from phrases list. 
 | 
	
		
			
				|  |  | +    It could return result as string, or save it to file.
 | 
	
		
			
				|  |  | +    """
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    def __init__(self, phrases: list) -> None:
 | 
	
		
			
				|  |  | +        """ This create new dictionary instance.
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        Parameters
 | 
	
		
			
				|  |  | +        ----------
 | 
	
		
			
				|  |  | +        phrases : list
 | 
	
		
			
				|  |  | +            List of phrases to prepare dictionary from.
 | 
	
		
			
				|  |  | +        """
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        self.__phrases = phrases
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    def __process_single_phrase(self, phrase: str) -> str:
 | 
	
		
			
				|  |  | +        """ This process single phrase to line in the dictionary.
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        Parameters
 | 
	
		
			
				|  |  | +        ----------
 | 
	
		
			
				|  |  | +        phrase : str
 | 
	
		
			
				|  |  | +            Phrase to make line from.
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        Returns
 | 
	
		
			
				|  |  | +        -------
 | 
	
		
			
				|  |  | +        str 
 | 
	
		
			
				|  |  | +            Phrase as line in dictionary.
 | 
	
		
			
				|  |  | +        """
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        return (" " * 4) + "\"" + phrase + "\": \"\""
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    @property
 | 
	
		
			
				|  |  | +    def result(self) -> str:
 | 
	
		
			
				|  |  | +        """ It process all phrases to the dictionary file.
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        Returns
 | 
	
		
			
				|  |  | +        -------
 | 
	
		
			
				|  |  | +        str
 | 
	
		
			
				|  |  | +            Parsed dictionary. 
 | 
	
		
			
				|  |  | +        """
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        lines = []
 | 
	
		
			
				|  |  | +        start = "{\n"
 | 
	
		
			
				|  |  | +        stop = "\n}\n"
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        for phrase in self.__phrases:
 | 
	
		
			
				|  |  | +            lines.append(self.__process_single_phrase(phrase))
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        return start + str(",\n").join(lines) + stop
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    def write(self, target: pathlib.Path) -> None:
 | 
	
		
			
				|  |  | +        """ It write dictionary to the file.
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        Parameters
 | 
	
		
			
				|  |  | +        ----------
 | 
	
		
			
				|  |  | +        target : pathlib.Path
 | 
	
		
			
				|  |  | +            Target file to write dictionary into.
 | 
	
		
			
				|  |  | +        """
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        with target.open("w+") as handle:
 | 
	
		
			
				|  |  | +            handle.write(self.result)
 | 
	
		
			
				|  |  | +    
 | 
	
		
			
				|  |  | +if __name__ == "__main__":
 | 
	
		
			
				|  |  | +    import argparse
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    parser = argparse.ArgumentParser(
 | 
	
		
			
				|  |  | +        description = "This script helps to create phrasebook from scripts."
 | 
	
		
			
				|  |  | +    )
 | 
	
		
			
				|  |  | +    
 | 
	
		
			
				|  |  | +    parser.add_argument(
 | 
	
		
			
				|  |  | +        "source",
 | 
	
		
			
				|  |  | +        type = pathlib.Path,
 | 
	
		
			
				|  |  | +        help = "This is source file or directory to parse from."
 | 
	
		
			
				|  |  | +    )
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    parser.add_argument(
 | 
	
		
			
				|  |  | +        "--output",
 | 
	
		
			
				|  |  | +        type = pathlib.Path,
 | 
	
		
			
				|  |  | +        default = "output.json",
 | 
	
		
			
				|  |  | +        help = "This is output phrasebook file, to save into."
 | 
	
		
			
				|  |  | +    )
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    arguments = parser.parse_args()
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    if not arguments.source.exists():
 | 
	
		
			
				|  |  | +        print("Source \"" + str(arguments.source) + "\" not exists.")
 | 
	
		
			
				|  |  | +        exit(127)
 | 
	
		
			
				|  |  | +    
 | 
	
		
			
				|  |  | +    if arguments.source.is_file():
 | 
	
		
			
				|  |  | +        target = file(arguments.source).filter().parse().result()
 | 
	
		
			
				|  |  | +    elif arguments.source.is_dir():
 | 
	
		
			
				|  |  | +        target = directory(arguments.source).process().result()
 | 
	
		
			
				|  |  | +    else:
 | 
	
		
			
				|  |  | +        print("Source is not file or directory.")
 | 
	
		
			
				|  |  | +        exit(126)
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    try:
 | 
	
		
			
				|  |  | +        dictionary(target).write(arguments.output)  
 | 
	
		
			
				|  |  | +        print("Processed successfull.")
 | 
	
		
			
				|  |  | +        print("Processed: " + str(len(target)) + " phrases.")
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    except Exception as error:
 | 
	
		
			
				|  |  | +        print(str(error))
 | 
	
		
			
				|  |  | +        print("Can not save \"" + str(arguments.output) + "\" output file.")
 | 
	
		
			
				|  |  | +        exit(125)
 |