Python国际化工具(一)按条件获得标签中文

in python with 0 comment

之前Python写了正则表达式的使用,主要目的是为了这个工具的开发。在前端VUE国际化页面时,主要是通过i18n这个包,然后创建js文件,里面保存了一些中英文信息。类似这样的文件。
image.png

为什么要做这个国际化工具

如果项目边开发边写这些文件是很方便的,直接完成一对一的,然后在.vue的文件中,对中文字段加入固定的表达式就行了,但是如果在项目已经开发到了一定的程度,再去完成国际化的工作,那工作量就很大了,因为要自己一个文件的一个文件的去找那些中文,再去翻译,在写入js文件中。就做的很烦躁。

网络上也有一些这方面的工具,但是在下不会用,就自己用Python完成这个小工具。

为什么用Python

主要是这个需求需要操作文件,如果用Java去操作文件,Python在操作文件这方面代码量更少。比如Python获得文件内容,只需要三行代码就搞定了。

def readHTML(fileName):
    html = open(fileName, 'r',encoding="utf-8").read()
    return html

另外一个原因就是觉得Python牛逼哈哈哈

完成的思路

其实很low,就是遍历文件,然后正则表达式匹配中文信息。

第一版傻逼思路

第一次,我准备做的是直接暴力一次性把中文的信息拿出来,通过正则表达式[\u4e00-\u9fa5]+
然后憨憨问题出现。

第一版憨憨问题

i18n国际化在不同的地方,使用方法不同,如下

template中:<span>{{$t('xxx')}}</span>
如果是placeholder就是 : :placeholder="$t('xxx')"
在script中:error(this.$t('xxx'));

所以,在国际化替换的过程中,问题就很大。。因为使用的方式不同。
在第一次的找中文的过程中。。
image.png
找到了8500+的中文,而且,在Key的处理上,有中文的逗号而且有些中文还不连句。还有就是,中文注释的干扰。。

第二版憨憨思路

第二次,找到了第一次的问题

  1. 替换的时候,因为i18n的使用不同,所以在获得中文时,根据不同的标签的位置去获得中文。
  2. 获得中文时,有些中文不连句是因为我用的[\u4e00-\u9fa5]+这个正则,所以,遇见一些特殊符号,会断开,所以要增加匹配条件。

这样,憨憨的我,又修改了代码,根据不同的标签去获得中文。。
然后我的代码,越写越长

image.png

另外,我的正则表达式成了这个样子。。。

[\u4e00-\u9fa5,,{}!\'\"\(\)\.()、!]+

第二版的憨憨问题

首先代码丑不说。而且出现了我很早就想到的问题了,python的dict类型,和Java的Map是一样的,Key不能重复。
比如表名(BM),编码(BM),我的key是通过拼音的大写开头做的,所以,这样,key重复了,但是我代码做了一下简单的处理。就是加上了一个随机的数字。
image.png
然后。。印象中,我好像用这些key,前端会报错。也就是不显示正确的东西。溜溜球~~

现在的憨憨版本

第二版不就是代码丑么。把丑的代码封装,封装,Python还不是面向对象。
对于同一个类型的标签,装在一起不就行了。
所以,第一个,就是封装了代码。
第二个问题,正则表达式太丑了。我为什么一定要找出中文呢??
然后我的正则表达式,变成了这个样子

<span.*>(.*)</span>

通过正则表达式分组的方式,我拿到了span标签内部的数据。我再去拿group(1)去匹配中文,如果有中文,那我全塞进list不就行了。所以,代码变成了这个样子

获得tags中的中文信息

    def getTextCN(self, tag, html):
        CNTexts = []
        resultList = []
        # 排除注解
        html = unNode(html)
        pat = r"<" + tag + r".*>.*</" + tag + ">"
        patSearch = r"<" + tag + r".*>(.*)</" + tag + ">"
        tagHtmls = re.findall(pat, html)
        for tagHtml in tagHtmls:
            CNHtmls = re.search(patSearch, tagHtml)
            if CNHtmls:
                flag = re.match(r'[\u4e00-\u9fa5]', CNHtmls.group(1))
                if flag:
                    CNTexts.append(CNHtmls.group(1))
        # 去重
        resultList = list(set(CNTexts))
        return resultList

获得那些比如label的中文信息

    def getTextCN(self, label, html):
        CNTexts = []
        resultList = []
        # 排除注解
        html = unNode(html)
        pat = r'[^:]' + label + r'=[\"|\'][^\"]*[\"|\']'
        patSearch = r'[^:]' + label + r'=[\"|\']([^\"]*)[\"|\']'
        # 获得那整行
        labelHtmls = re.findall(pat, html)
        for labelHtml in labelHtmls:
            CNHtmls = re.search(patSearch, labelHtml)
            if CNHtmls:
                flag = re.match(r'[\u4e00-\u9fa5]', CNHtmls.group(1))
                if flag:
                    CNTexts.append(CNHtmls.group(1))
            # 去重
        resultList = list(set(CNTexts))
        return resultList

获得script中的中文

不过这个特殊,正则表达式还是很丑。。。越丑的越封装

    def getTextCN(self, script, html):
        CNList = []
        resultList = []
        # 排除注解
        html = unNode(html)
        scriptAllHtml = re.findall(r'<script>[\w\W]*<\/script>', html)
        pat = script + r'[:|\(|\'|\"|= ]+[^;|^)|^\"|^}|,]*[)|\"|\']'
        patSearch = script + r'[:|\(|\'|\"|=| ]+([^;|^)|^\"|^}|,]*)[)|\"|\']'
        for html in scriptAllHtml:
            scriptHtmls = re.findall(pat, html)
            for scriptHtml in scriptHtmls:
                CNHtmls = re.search(patSearch, scriptHtml)
                if CNHtmls:
                    flag = re.findall(r'[\u4e00-\u9fa5]', CNHtmls.group(1))
                    if flag:
                        CNList.append(CNHtmls.group(1))
            # 去重
        resultList = list(set(CNList))
        return resultList

然后我的main方法,就直接传一个标签就行咯

def getLables(pathRoot, lables):
    AllText = {}
    labelList = []
    fileNameList = operationFile.getFileName(pathRoot)
    print("一共有" + str(len(fileNameList)) + "个vue文件")
    for label in lables:
        # 进入循环taglist清空
        labelList = []
        for fileName in fileNameList:
            # 获得文本
            html = operationFile.readHTML(fileName)
            datas = Context(LabelsCN).GetJsonText(label,html)
            for data in datas:
                labelList.append(data)
            # 再次去重
            labelList = list(set(labelList))
        jsonMap = formatText.getMap(labelList)
        # 将jsonMap装箱
        AllText[label] = jsonMap
    return AllText


# tags集合
tags = ['el-button', 'span', 'el-dropdown-item', 'th', 'el-tag' , 'th', 'td', 'label']

# labels集合
lables = ['placeholder', 'title', 'content', 'label']

# script集合
scripts = ['error','message','warning','success','value','title']

def main():
    resultMapDict = getLables(pathRoot, lables)
    bJson = json.dumps(resultMapDict, ensure_ascii=False, sort_keys=True, indent=2)
    # 写入文件
    operationFile.write(bJson, outFilePath)

就这样按照不同的标签属性获得他们所代表的中文信息。