PO(Portable Object)文件转换excel/csv,实现自动化更新翻译文件

PO(Portable Object)文件转换excel/csv,实现自动化更新翻译文件

        由于长时间没有登陆,密码也忘记了,自己也比较懒不想重置密码,于是放任在这里,直到最近突然无意中输对了密码。恩,那我就又回来了,好多年没有更新了。那就更个最近因为 po文件翻译太麻烦的处理。

        源于最近 有的项目用了 python,然后python 比较出名的多语言用的是pybabel, 然而pybabel的文件是生成po文件的。对于翻译人员,要用特定的工具,并不友善,然后我们公司也是自己写有一套TMS系统的,可以通过导入excel或者csv文件 在线翻译,而后再导出,放回自有项目当中。查找了一轮线上的内容,没有发现符合我需求的,于是就自己琢磨着,写个转换吧,方便自己,也方便翻译人员。

        好,前事就提这么多吧。废话不多说,直接开始。

requirements.txt文件需要引入这些文件

Flask-Babel==2.0.0
openpyxl==3.1.2
pandas==1.5.1
polib==1.2.0
argparse=1.4.0
colorama==0.4.6
  • Flask-Babel国际化方案 Flask-Babel 是Fl​​ask的扩展,它在babel、pytz和 speaklater的帮助下为任何 Flask 应用程序添加 i18n 和 l10n 支持。它内置了对日期格式化和时区支持的支持,以及一个非常简单友好的gettext 翻译界面。
  • openpyxl 一个专门处理excel文件的python扩展库
  • pandas python很出名的数据分析处理的扩展库
  • polib polib 是一个用于操作、创建、修改 gettext 文件(pot、po 和 mo 文件)的库。是我们这个项目主要的处理python扩展库
  • argparse argparse 模块是python编写用户友好的命令行扩展,是我们此项目另一个最重要的库。
  • colorama 用于生成彩色终端文本和光标定位 的 python扩展库(可不安装)。

我们的目的主要是 通过使用python自定义命令处理po文件 与 翻译文件的相互转换

首先我们的主体程序, 我直接贴代码吧,因为我使用colorama,所以我重写了 parser的处理文件,如果不使用,可以去掉相关代码

import argparse
import os
from colorama import init, Fore

# 获取当前目录位置
dir_path = os.path.dirname(os.path.abspath(__file__))

# colorama的自定义初始化
# init(autoreset=True)

class ThrowingArgumentParser(argparse.ArgumentParser):
    def error(self, message):
        # 重写error, 视情况自己具体实现
        pass
    
parser = ThrowingArgumentParser(
    description=f"{Fore.BLUE}实现po文件转excel/csv文件,以及excel/csv/json文件转换po文件{Fore.RESET}",
    formatter_class=argparse.RawTextHelpFormatter
)

try:
    subparsers = parser.add_subparsers(
        help=f"""{Fore.LIGHTCYAN_EX}lang_dump.py out [-h] \n{Fore.LIGHTCYAN_EX}lang_dump.py in [-h]""",
        description=f"{Fore.BLUE}out子命令为po文件转excel/csv命令 | in子命令为翻译后文件转存po文件命令{Fore.RESET}",
    )

    # 输出为excel/csv文件
    parser_out = subparsers.add_parser("out", formatter_class=argparse.RawTextHelpFormatter)
    parser_out.add_argument(
        "-t", "--type", choices=['excel', 'csv'], type=str, default="excel,csv",
        help=f"""{Fore.BLUE}需要转存的文件格式,目前只支持excel和csv格式文件,默认会输出两种格式的文件
{Fore.LIGHTBLUE_EX}example:{Fore.LIGHTCYAN_EX} lang_dump.py out -t excel""")
    parser_out.set_defaults(func=args_out)

    # 转换回po文件
    parser_in = subparsers.add_parser("in", formatter_class=argparse.RawTextHelpFormatter)
    parser_in.add_argument(
        "-t", "--type", choices=['excel', 'csv', 'json'], type=str, required=True,
        help=f"""{Fore.BLUE}指定传入的文件类型,只支持 excel(*.xlsx),csv,json格式 文件
{Fore.LIGHTBLUE_EX}example:{Fore.LIGHTCYAN_EX} lang_dump.py in -t json{Fore.RESET}""")
    parser_in.add_argument(
        "-f", "--file", action="append", required=True,
        help=f"""{Fore.BLUE}指定传入的文件名称,建议放在当前目录下导入,多个翻译文件 使用多个 -f 引入
{Fore.LIGHTBLUE_EX}example:{Fore.LIGHTCYAN_EX} lang_dump.py in -f zh-CN.json -f en.json{Fore.RESET}""")
    parser_in.add_argument(
        "-l", "--lang", action="append", choices=['zh', 'en'], required=True,
        help=f"""{Fore.BLUE}指定语言版本,按--file参数引入的文件排序,顺序对应,多个语言包使用多个 -l 引入
{Fore.LIGHTBLUE_EX}example:{Fore.LIGHTCYAN_EX} lang_dump.py in -l zh -l en{Fore.RESET}""")
    parser_in.set_defaults(func=args_in)

    # 读取参数
    args = parser.parse_args()
    args.func(args)
except Exception as ex:
    parser.print_help()
    raise

我的导出代码,代码也是比较简单易懂

使用polib读取po文件内容,然后循环通过openpyxl写入excel文件,最后在保存进去excel文件

import os
import shutil

import pandas as pd
import polib
from colorama import init, Fore
from openpyxl.workbook import Workbook

dir_path = "..."

def args_out(args):
    tp_list = str(args.type).split(",")
    """po 转 excel"""
    # 先更新一次语言包
    command = f"""
        cd {dir_path}/../.. &&
        pybabel extract -F babel.cfg -o messages.pot . && 
        pybabel update -i messages.pot -d translations 
        """
    os.system(command)

    wb = Workbook()
    # grab the active worksheet
    ws = wb.active
    ws.title = u'sheet1'
    # 翻译文案的模板顺序 KEY(语言key),zh-cn(中文),en(英文)
    ws.append(['KEY', 'zh-cn', 'en'])

    zh_po_file = f'{dir_path}/../../translations/zh/LC_MESSAGES/messages.po'
    en_po_file = f'{dir_path}/../../translations/en/LC_MESSAGES/messages.po'
    zh_po = polib.pofile(zh_po_file, encoding='UTF-8')
    en_po = polib.pofile(en_po_file, encoding='UTF-8')
    # print(zh_po.fuzzy_entries())

    for zh_msg in zh_po:
        for en_msg in en_po:
            if en_msg.msgid == zh_msg.msgid:
                ws.append([zh_msg.msgid, zh_msg.msgstr, en_msg.msgstr])
                break

    excel_file = 'messages.xlsx'
    out_path = f'{dir_path}/out'
    if os.path.exists(out_path):
        shutil.rmtree(f'{out_path}/')
    os.makedirs(out_path)

    wb.save(f'{out_path}/{excel_file}')

    excel_data = pd.read_excel(f'{out_path}/{excel_file}', index_col=0)
    excel_data.to_csv(f'{out_path}/messages.csv', encoding='utf-8')

    wb.close()

    print(Fore.LIGHTGREEN_EX + "\n-----------> out success\n")
    print(Fore.LIGHTGREEN_EX + f"导出{args.type}文件成功, 导出目录为{out_path}")

我的导入代码,也比较简单,思路是可以通过 json/excel(*.xlsx)/csv文件 导入进来转化为po文件

我的json文件是分开 zh.json en.json文件,分别处理的,excel/csv文件则 按照顺序写入语言包数据再通过pandas处理数据,(ps:pandas真是谁用谁知知道,处理数据的能力真是优雅),csv跟excel的处理就不写出来了,都是基础知识写出来的代码

import json
import os

import polib
from colorama import init, Fore

dir_path = "..."

class CommandArgvError(Exception):
    pass

def args_in(args):
    """excel/csv/json 转 po"""
    for i in range(len(args.lang)):
        po = polib.POFile()
        po_file = f'{dir_path}/../../translations/{args.lang[i]}/LC_MESSAGES/messages.po'
        if args.type == 'json':
            # json数据处理
            with open(f'{dir_path}/{args.file[i]}', 'r+', encoding='utf-8') as f:
                for line in f:
                    try:
                        json.loads(line)
                    except:
                        raise CommandArgvError("json文件格式有误")

            with open(f'{dir_path}/{args.file[i]}', 'r+', encoding='utf-8') as json_file:
                json_data = json.load(json_file)

            for key in json_data:
                entry = polib.POEntry(
                    msgid=key,
                    msgstr=json_data[key],
                )
                po.append(entry)

        if args.type == 'csv':
            # csv数据处理 balabala
            pass

        if args.type == 'excel':
            # excel数据处理 balabala
            pass

        po.save(po_file)

    # 执行pybabel语言包的更新操作
    command = f"""
    cd {dir_path}/../.. &&
    pybabel update -i messages.pot -d translations && 
    pybabel compile -d translations 
    """
    os.system(command)

    print(Fore.LIGHTGREEN_EX + "\n-----------> in success\n")
    print(Fore.LIGHTGREEN_EX + "文件转化成功,语言包已经更新")

最后执行命令,可以查看提示

$ python lang_dump.py -h
usage: lang_dump.py [-h] {out,in} ...

实现po文件转excel/csv文件,以及excel/csv/json文件转换po文件

optional arguments:
  -h, --help  show this help message and exit

subcommands:
  out子命令为po文件转excel/csv命令 | in子命令为翻译后文件转存po文件命令

  {out,in}    lang_dump.py out [-h] 
              lang_dump.py in [-h]

导出 由于我是默认导出 excel/csv 所以不传入参数就会两个文件都会生成。

导出语言包命令(只支持导出excel和csv格式文件)

$ python lang_dump.py out -h
usage: lang_dump.py out [-h] [-t {excel,csv}]

optional arguments:
  -h, --help            show this help message and exit
  -t {excel,csv}, --type {excel,csv}
                        需要转存的文件格式,目前只支持excel和csv格式文件,默认会输出两种格式的文件
                        example: lang_dump.py out -t excel

Example

$ python lang_dump.py out
.
.
.

-----------> out success


导出excel,csv文件成功, 导出目录为/home/teddy/PythonProjects/admin-dataportal-api/commands/language/out

翻译好的文件转换回po文件(只支持传入excel/csv/json格式文件)

$ python lang_dump.py in -h 
usage: lang_dump.py in [-h] -t {excel,csv,json} -f FILE -l {zh,en}

optional arguments:
  -h, --help            show this help message and exit
  -t {excel,csv,json}, --type {excel,csv,json}
                        指定传入的文件类型,只支持 excel(*.xlsx),csv,json格式 文件
                        example: lang_dump.py in -t json
  -f FILE, --file FILE  指定传入的文件名称,建议放在当前目录下导入,多个翻译文件 使用多个 -f 引入
                        example: lang_dump.py in -f zh-CN.json -f en.json
  -l {zh,en}, --lang {zh,en}
                        指定语言版本,按--file参数引入的文件排序,顺序对应,多个语言包使用多个 -l 引入
                        example: lang_dump.py in -l zh -l en

导入我只展示json的用法,其他也差不多

Example1 (json文件,语言包顺序务必与文件导入顺序一致)

$ python lang_dump.py in -t json -f zh-CN.json -f en.json -l zh -l en

updating catalog translations/en/LC_MESSAGES/messages.po based on messages.pot
updating catalog translations/zh/LC_MESSAGES/messages.po based on messages.pot
compiling catalog translations/en/LC_MESSAGES/messages.po to translations/en/LC_MESSAGES/messages.mo
compiling catalog translations/zh/LC_MESSAGES/messages.po to translations/zh/LC_MESSAGES/messages.mo

-----------> in success

文件转化成功,语言包已经更新
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值