当前位置: 首页 > news >正文

软件多语言文案脚本自动化方案

开发高效提速系列目录

  1. 软件多语言文案脚本自动化方案

软件多语言文案脚本自动化方案

  • 背景
  • 目标
  • 整体方案
    • 1. 创建文案资源文件
    • 2. python脚本开发
    • 3. Python脚本执行与管理
    • 4. 人员职责分配
  • PyCharm使用说明
    • 1. PyCharm下载
    • 2. PyCharm安装配置
    • 3. 异常情况解决
  • 总结

博客创建时间:2023.05.03
博客更新时间:2023.05.03

以Android studio gradle=7.5,SDKVersion 32来分析讲解。如图文和网上其他资料不一致,可能是别的资料版本较低而已。


背景

在海外项目中多语言的支持是很重要的一部分。在我们的项目中常常需要支持简中、繁体、英、日、韩、西班牙语等十多种语言,当我们进行文案的新增、修改、删除时,需要在软件项目多语言文案资源文件中进行文案Key和文案内容对应的复制粘贴,非常耗时耗力且容易出现疲劳性错误。

目前关于多语言文案的管理,有部分公司的项目管理可能还停留在如下流程中:

  1. 文案由开发在项目资源文件中进行维护(如Android的strings.xml、IOS的Localizable.strings、PC云端的XXX.ini ),当需要进行文案翻译时,将文案文件语言.xml文件给到产品经理
    在这里插入图片描述

  2. 由产品经理经过其他操作对文案进行翻译,提供多语言翻译后的excel文档给到软件开发,此时文案Key和文案内容失去关联关系
    在这里插入图片描述

  3. 软件开发根据给到的翻译内容查找到对应的文案Key,然后复制到对应的资源文件中进行文案的更新操作

该流程实现过程中,会出现可能的几点问题:

  1. 在版本开发迭代期间,频繁的文案新增修改,需要开发人员频繁手动对齐文案和Key的关系,费时费力
  2. 每一中语言都需要将操作重复进行一遍,语言种类越多耗时越久且手动复制粘贴中容易出现疲劳性错误

目标

为了方便对文案资源进行统一管理,方便产品、开发、测试对文案内容的统一对齐,应该在已有的翻译excel文档的基础上完善文案,对每条文案新增对应的文案Key,同时采用python脚本方法,实现脚本自动化程序更新文案资源,达到提升文案管理和使用效率提升。该方案可以支持Android、IOS、PC云端项目的。

整体方案

该方案的主要思路是:

  1. 创建好统一管理Android、IOS或PC 云端项目的文案管理excel文件
  2. 根据文案资源Excel文件进行python脚本的编写,达到执行脚本时能生成不同格式的文案资源文件
  3. 当文案资源有更新时,在excel文档中进行更新,执行脚本程序完成文案资源的更新
    在这里插入图片描述

根据思路我将其细分为如下几个细分步骤:

  1. 建立标准化文案管理文件。一般是用excel文件管理
  2. 编写Python脚本开发
  3. Python文件管理与程序触发执行
  4. 项目组内人员职责分配

1. 创建文案资源文件

多语言文案可以放在某个excel文件中进行管理,一般使用公司的办公软件如钉钉或飞书软件中进行管理。文案资源的格式可以一般同产品沟通协商共同制作,符合自己公司产品的需求即可,我这里给出移动端文案sheet和PC 云端sheet模板样式,云端和移动端因文案差异太大,建议不用放在一起。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

注意:多语言的文案翻译根据软件的实际需求进行使用,如软件不支持某种语言如"土耳其语",将其对应列空着即可。

2. python脚本开发

python脚本代码如下

# coding=utf-8
import importlib
import re
import sys
import os
import xlrd2importlib.reload(sys)
# isAndroid = True
ANDROID = "Android"
IOS = "IOS"
PC = "PC"
# 配置文件修改区 START *****/
# 平台类型 Android、IOS、PC 区分大小写
platformType = "Android"# 项目多语言资源文件
excelPath = os.path.expanduser('~/Downloads/多语言文案.xlsx')
# 输出路径
outputPath = "D:/Ken.Luo/res/"# 选择需要导出文案的sheet名
sheetName = "App文案"
# 配置文件修改区 END *****/# 导出文案的类型
# entryType = "Android"
commentColNum = 4
typeColNum = 2
keyColNum = 2
colToStringsMap = None# 切换到iOS
def switchToAndroid():global keyColNum, colToStringsMapkeyColNum = 2# 对应关系元组Android (列数 : 多语言文件)colToStringsMap = [(7, "values/strings.xml"),(5, "values-zh/strings.xml"),(6, "values-zh-TW/strings.xml"),(8, "values-de/strings.xml"),(9, "values-fr/strings.xml"),(10, "values-es/strings.xml"),(11, "values-ja/strings.xml"),(12, "values-ko/strings.xml"),(13, "values-ar/strings.xml"),(14, "values-it/strings.xml"),(15, "values-pt/strings.xml"),(16, "values-tr/strings.xml"),(17, "values-ru/strings.xml")]# 切换到iOS
def switchToIOS():global keyColNum, colToStringsMapkeyColNum = 3colToStringsMap = [(7, "values/Localizable.strings"),(5, "values-zh/Localizable.strings"),(6, "values-zh-TW/Localizable.strings"),(8, "values-de/Localizable.strings"),(9, "values-fr/Localizable.strings"),(10, "values-es/Localizable.strings"),(11, "values-ja/Localizable.strings"),(12, "values-ko/Localizable.strings"),(13, "values-ar/Localizable.strings"),(14, "values-it/Localizable.strings"),(15, "values-pt/Localizable.strings"),(16, "values-tr/Localizable.strings"),(17, "values-ru/Localizable.strings")]def switchToPC():global keyColNum, colToStringsMapkeyColNum = 2colToStringsMap = [(7, "values/strings.ini"),(5, "values-zh/strings.ini"),(6, "values-zh-TW/strings.ini"),(8, "values-de/strings.ini"),(9, "values-fr/strings.ini"),(10, "values-es/strings.ini"),(11, "values-ja/strings.ini"),(12, "values-ko/strings.ini"),(13, "values-ar/strings.ini"),(14, "values-it/strings.ini"),(15, "values-pt/strings.ini"),(16, "values-tr/strings.ini"),(17, "values-ru/strings.ini")]# ******* #def formatValue(originalStr):''' 格式化字符串成为app 程序需要的样子'''print("originalStr:" + originalStr)# excel中的换行符换成 \n转义字符, 文案首尾的换行符认为是翻译人员不小心按出来的,在此去掉originalStr = re.sub(r'\n+$', "", originalStr, re.S)originalStr = re.sub(r'^\n+', "", originalStr, re.S)originalStr = re.sub(r'\n', "\\\\n", originalStr, re.S)# 安卓需要对&进行处理if platformType is ANDROID:#  不处理,待后续直接替换成空格if originalStr != ' ':originalStr = re.sub(r'&', "&", originalStr, re.S)print("")return originalStr### 写多语言文件函数 ###
def write_header(strFile):if platformType is ANDROID:strFile.write("""<?xml version="1.0" encoding="utf-8" ?>
<resources xmlns:tools="http://schemas.android.com/tools" tools:ignore="MissingTranslation">\n""")def write_trailer(strFile):if platformType is ANDROID:strFile.write("\n</resources>")def write_comment(strFile, comment):'''生成注释文案'''if comment != "" and comment != None:if platformType is ANDROID:strFile.write("\t<!-- " + str(comment) + "-->\n")elif platformType is IOS:strFile.write("/** " + str(comment) + " */\n")elif platformType is PC:strFile.write("# " + str(comment) + " \n")def write_key_value(strFile, key, value, defaultValue):# iOS对于value是空使用defaultValueif value == "&nbsp;":value = " "if not typeColNum is ANDROID and (value is None or value == ""):value = defaultValueif key is None or key == "" or value is None or value == "":return# 处理一个文案多个key的情况keyColValues = key.splitlines()for keyColValue in keyColValues:if platformType is ANDROID:strFile.write("\t<string name=\"" + keyColValue.strip() + "\">" + value.strip() + "</string>\n")elif platformType is IOS:strFile.write("\"" + keyColValue.strip() + "\" = \"" + value.strip() + "\";\n")elif platformType is PC:strFile.write(keyColValue.strip() + " = \"" + value.strip() + "\";\n")# ******* #
workbook = xlrd2.open_workbook(excelPath)
table = workbook.sheet_by_name(sheetName)def writeToFiles():nrows = table.nrows# 打开文件colToFileMap = []for (col, fileName) in colToStringsMap:paths = os.path.split(fileName)print("paths 路径", paths)if len(paths) > 1:pathDir = outputPath + paths[0]print("dir 路径", pathDir)# 输出目录文件夹不存在就创建if not (os.path.exists(pathDir)):os.makedirs(pathDir)file = open(outputPath + fileName, "w+", 1024, "utf-8")colToFileMap.append((col, file))write_header(file)# 导出文案for i in range(2, nrows):print(table)comment = table.cell(i, commentColNum).valuetypeColValue = table.cell(i, typeColNum).valuekeyColValue = table.cell(i, keyColNum).valuedefaultValue = ""# 将一行的各列写入对应的多语言文件for (col, strFile) in colToFileMap:value = table.cell(i, col).valuevalue = formatValue(value)if col == colToFileMap[0][0]:defaultValue = valuewrite_comment(strFile, comment)# if typeColValue.find(entryType) >= 0:write_key_value(strFile, keyColValue, value, defaultValue)# 关闭文件for (_, file) in colToFileMap:write_trailer(file)file.close()if __name__ == '__main__':if platformType is ANDROID:switchToAndroid()writeToFiles()elif platformType is IOS:switchToIOS()writeToFiles()elif platformType is PC:switchToPC()writeToFiles()

3. Python脚本执行与管理

Python脚本的执行需要在电脑中进行触发程序执行,需要电脑有python运行环境,我使用的是Pycharm idea软件,一键安装即可用,和Android studio使用是一样的。后面会专门讲解PyCharm的使用操作。

参数配置
当执行软件安装好后,需要进行部分参数的配置,配置完参数后即可进行程序的执行,生成对应的资源文件。

ANDROID = "Android"
IOS = "IOS"
PC = "PC"
# 配置文件修改区 START *****/
# 平台类型 Android、IOS、PC 区分大小写
platformType = "PC"# 项目多语言资源文件
excelPath = os.path.expanduser('~/Downloads/Remo文案汇总.xlsx')
# 输出路径
outputPath = "D:/Ken.Luo/res88888/"# 选择需要导出文案的sheet名
sheetName = "APP文案"
# 配置文件修改区 END *****/

主要修改的是参数为

  1. platformType:资源使用的平台,目前定义有Android、IOS、PC云端
  2. excelPath :excel资源文件的目录地址
  3. outputPath:脚本执行后的生成的输出位置
  4. sheetName :APP和PC云端的文案资源我设计是分开放的,所以是两个sheet,需要执行程序时手动选择

执行效果
以Android举例,多语言文案资源是放置在res/value/strings.xml文件中下的。现在我们预计通过执行python脚本程序,实现文案内容自动更新到各语言的strings.xml中。
在这里插入图片描述
脚本管理
python脚本是为了减少开发进行文案更新时提效的,当脚本程序开发完毕后考虑后期可能有优化,需要对齐进行持久化管理,所以首先想到的是使用gitee进行管理。https://gitee.com/luofaxin/LanguageRes.git

4. 人员职责分配

在多语言文案管理中,不同角色有自己的任务分配
在这里插入图片描述

PyCharm使用说明

在python脚本准备好后,需要通过某种方式实现程序的触发,第一阶段先考虑手动操作pycharm程序执行脚本程序,后期也可以考虑在服务器上进行脚本的自触发。

1. PyCharm下载

手动触发方式需要使用者安装Pycharm 软件,用于执行文案脚本程序。https://www.jetbrains.com/pycharm/download/#section=windows
在这里插入图片描述

2. PyCharm安装配置

在这里插入图片描述

  1. 配置.py运行环境
    在这里插入图片描述
    在这里插入图片描述

  2. 配置脚本执行变量
    对于.py文件,需要动态的更改路径的配置
    在这里插入图片描述

  3. 执行脚本程序
    点击执行脚本程序,python脚本将会自动执行,将excel文件生成res/strings.xml文件
    在这里插入图片描述

3. 异常情况解决

  1. Python ModuleNotFoundError: No module named ‘xlrd‘ 异常
    解决方案
    在这里插入图片描述
    在这里插入图片描述

总结

希望这个python脚本自动化方案能帮助大家,多语言文案资源和pyhton脚本我都放到gitee仓库中了,可以下载使用。欢迎大家提出更好的优化建议。
仓库地址:https://gitee.com/luofaxin/LanguageRes.git


相关链接

  1. 软件多语言文案脚本自动化方案

扩展链接:

  1. 项目开发混淆从初识到理解
  2. 项目开发代码分支管理

博客书写不易,您的点赞收藏是我前进的动力,千万别忘记点赞、 收藏 ^ _ ^ !

相关文章:

软件多语言文案脚本自动化方案

开发高效提速系列目录 软件多语言文案脚本自动化方案 软件多语言文案脚本自动化方案 背景目标整体方案1. 创建文案资源文件2. python脚本开发3. Python脚本执行与管理4. 人员职责分配 PyCharm使用说明1. PyCharm下载2. PyCharm安装配置3. 异常情况解决 总结 博客创建时间&…...

C++017-C++文件读写应用

文章目录 C017-C文件读写应用C文件读写应用CSP-J目标1. 文件的基本概念、文本文件的基本操作2.文本文件类型与二进制文件类型文本文件类型二进制文件类型二进制查看工具 3.文件重定向、文件读写等操作关闭文件文件操作-写入文本文件文件操作-读取文本文件文件操作-写入二进制文…...

计算机网络 实验二

⭐计网实验专栏&#xff0c;欢迎订阅与关注&#xff01; ★观前提示&#xff1a;本篇内容为计算机网络实验。内容可能会不符合每个人实验的要求&#xff0c;因此以下内容建议仅做思路参考。 一、实验目的 &#xff08;1&#xff09;掌握IP地址的基本结构(网络部分与主机部分的…...

Unity 3D 学习笔记(1)

文章目录 1.Unity 3D 概述2.Unity的安装过程3.Unity 3D 的项目管理4.Unity 3D 中的场景5.Unity 3D 的界面组成 1.Unity 3D 概述 Unity 3D简介&#xff1a;Unity 3D是虚拟现实行业中使用率较高的一款开发引擎&#xff0c;由Unity Technology公司开发。通过Unity&#xff0c;开发…...

P1050 [NOIP2005 普及组] 循环

题目描述 乐乐是一个聪明而又勤奋好学的孩子。他总喜欢探求事物的规律。一天&#xff0c;他突然对数的正整数次幂产生了兴趣。 众所周知&#xff0c;22 的正整数次幂最后一位数总是不断的在重复 2,4,8,6,2,4,8,6…2,4,8,6,2,4,8,6… 我们说 22 的正整数次幂最后一位的循环长度…...

软考算法-排序篇-上

数据排序 一&#xff1a;故事背景二&#xff1a;直接插入排序2.1 概念2.2 画图表示2.3 代码实现2.4 总结提升 三&#xff1a;希尔排序3.1 概念3.2 画图表示3.3 代码实现3.4 总结提升 四&#xff1a;直接选择排序4.1 概念4.2 画图表示4.3 代码实现4.4 总结提升 五&#xff1a;堆…...

总结836

学习目标&#xff1a; 4月&#xff08;复习完高数18讲内容&#xff0c;背诵21篇短文&#xff0c;熟词僻义300词基础词&#xff09; 学习内容&#xff1a; 暴力英语&#xff1a;背诵《keep your direction》&#xff0c;默写&#xff0c;英语语法 高等数学&#xff1a;刷题&a…...

ginbuilder 工具快速创建

ginbuilder github 地址 快速创建一个ginweb项目&#xff1a; 目前apps下只有http服务&#xff0c;如果后续有需要的话&#xff0c;会添加上rpc服务&#xff0c;websocket服务后边如果有需要会添加上swagger 创建完成的目录结构 ├── apps │ ├── apis // 所有的apis…...

【Java基础面试宝典】堆、栈、方法区分别都存储了那些内容?wait 和 sleep 方法的区别?

目录 堆、栈、方法区分别都存储了那些内容&#xff1f; 堆&#xff08;heap&#xff09; 栈&#xff08;stack&#xff09; 方法区&#xff08;method&#xff09; 在 java 中 wait 和 sleep 方法的区别&#xff1f; 堆、栈、方法区分别都存储了那些内容&#xff1f; 堆&a…...

古剑飞仙手游Linux系统服务器架设教程

安装宝塔直接运行命令即可。 yum install -y wget && wget -O install.sh http://download.bt.cn/install/install_6.0.sh && sh install.sh 搭建环境&#xff1a; centos 7以上系统服务器 宝塔面板安装应用如下&#xff1a; Nginx1.14 mysql5.7 php5.6 1…...

python实战应用讲解-【numpy数组篇】常用函数(十)(附python示例代码)

目录 Python Numpy MaskedArray.ravel()函数 Python Numpy MaskedArray.reshape()函数 Python Numpy MaskedArray.resize()函数 Python Numpy MaskedArray.std()函数 Python Numpy MaskedArray.sum()函数 Python Numpy MaskedArray.swapaxes()函数 Python Numpy MaskedA…...

计算机组成原理(考研408)练习题#2

用于复习408或计算机组成原理期末考试。如有错误请在评论区指出。 So lets start studying with questions! それでは、問題の勉強を始めましょう&#xff01; 11.某 cache 采用全相联映射&#xff0c;假设 cache 有 3 块&#xff0c;程序运行过程中需要访问的主存块号依 次为…...

Apache POI,springboot中导出excel报表

2. Apache POI 2.1 介绍 Apache POI 是一个处理Miscrosoft Office各种文件格式的开源项目。简单来说就是&#xff0c;我们可以使用 POI 在 Java 程序中对Miscrosoft Office各种文件进行读写操作。 一般情况下&#xff0c;POI 都是用于操作 Excel 文件。 Apache POI 的应用场景…...

CSS(一)-- 三种样式表

目录 1. 行内样式表 2. 内部样式表 3. 外部样式表&#xff08;即引入 .css文件&#xff09;&#xff08;重点掌握&#xff09; 1. 行内样式表 行内样式表&#xff08;内联样式表&#xff09;是在元素标签内部的 style 属性中设定 CSS 样式。适合于修改简单样式。 <di…...

嵌入式之Samba服务器搭建

在嵌入式系统开发应用平台中&#xff0c;tftp、nfs和samba服务器是最常用的文件传输工具 tftp和nfs是在嵌入式Linux开发环境中经常使用的传输工具 samba则是Linux和Windows之间的文件传输工具。 下面演示在linux上搭建Samba服务器 sudo apt-get install samba chmod -R 77…...

vue3+go——看到了就去学习吧

vue3go——看到了就去学习吧 Vue3.2 Vite Element-Plus 实现最基础的 CRUD1.效果展示【02:36】2.创建项目【03:16】3.添加github管理【04:10】4.引入element-plus【04:21】5.内容布局【08:59】6.布局优化【05:31】7.添加弹窗【09:34】8.ref改$ref【02:47】9.新增数据【09:22】…...

Perf工具统计CPU性能

Perf 性能检测工具 Perf 是一个内置于Linux内核中的工具&#xff0c;用于性能分析和调优。它可以对系统的CPU使用情况、内存使用情况、磁盘I/O、网络I/O等进行监控和分析&#xff0c;并提供了丰富的分析和可视化工具&#xff0c;以帮助用户定位和解决性能问题。perf可以进行函…...

考验大家指针功底的时候到了:请问如何理解 (int*)1 + 1 ?

来&#xff0c;猜猜看&#xff0c;这里的执行结果是什么&#xff1f; 这是今天课上的一道理解题&#xff0c;给大家一点点思考时间。 &#xff08;心里有答案了再往下滑哦&#xff09; 5 4 3 2 1 . 答案是&#xff0c;报warning&#xff01;因为%d不是用来输出指针的哈…...

英语基础-介词

介词 方位介词 in:在…里面 Its in the box. 在盒子里 in my backpack 在背包里 in the tree 长在树上on:在…上面&#xff08;指与物体表面接触&#xff09; Its on the box. 在盒子上(和盒子接触) on the floor.在地板上 on the tree.在树上under:在…下面 Its unde…...

Linux进程通信:进程组 会话

1. 进程组 &#xff08;1&#xff09;概念&#xff1a;一个或多个进程的集合&#xff0c;也称为“作业”。 &#xff08;2&#xff09;父进程创建子进程时&#xff0c;默认属于同一个进程组。进程组ID为组长进程ID。 &#xff08;3&#xff09;进程组中只要有一个进程存在&a…...

观成科技:隐蔽隧道工具Ligolo-ng加密流量分析

1.工具介绍 Ligolo-ng是一款由go编写的高效隧道工具&#xff0c;该工具基于TUN接口实现其功能&#xff0c;利用反向TCP/TLS连接建立一条隐蔽的通信信道&#xff0c;支持使用Let’s Encrypt自动生成证书。Ligolo-ng的通信隐蔽性体现在其支持多种连接方式&#xff0c;适应复杂网…...

遍历 Map 类型集合的方法汇总

1 方法一 先用方法 keySet() 获取集合中的所有键。再通过 gey(key) 方法用对应键获取值 import java.util.HashMap; import java.util.Set;public class Test {public static void main(String[] args) {HashMap hashMap new HashMap();hashMap.put("语文",99);has…...

全球首个30米分辨率湿地数据集(2000—2022)

数据简介 今天我们分享的数据是全球30米分辨率湿地数据集&#xff0c;包含8种湿地亚类&#xff0c;该数据以0.5X0.5的瓦片存储&#xff0c;我们整理了所有属于中国的瓦片名称与其对应省份&#xff0c;方便大家研究使用。 该数据集作为全球首个30米分辨率、覆盖2000–2022年时间…...

【SQL学习笔记1】增删改查+多表连接全解析(内附SQL免费在线练习工具)

可以使用Sqliteviz这个网站免费编写sql语句&#xff0c;它能够让用户直接在浏览器内练习SQL的语法&#xff0c;不需要安装任何软件。 链接如下&#xff1a; sqliteviz 注意&#xff1a; 在转写SQL语法时&#xff0c;关键字之间有一个特定的顺序&#xff0c;这个顺序会影响到…...

【RockeMQ】第2节|RocketMQ快速实战以及核⼼概念详解(二)

升级Dledger高可用集群 一、主从架构的不足与Dledger的定位 主从架构缺陷 数据备份依赖Slave节点&#xff0c;但无自动故障转移能力&#xff0c;Master宕机后需人工切换&#xff0c;期间消息可能无法读取。Slave仅存储数据&#xff0c;无法主动升级为Master响应请求&#xff…...

Unsafe Fileupload篇补充-木马的详细教程与木马分享(中国蚁剑方式)

在之前的皮卡丘靶场第九期Unsafe Fileupload篇中我们学习了木马的原理并且学了一个简单的木马文件 本期内容是为了更好的为大家解释木马&#xff08;服务器方面的&#xff09;的原理&#xff0c;连接&#xff0c;以及各种木马及连接工具的分享 文件木马&#xff1a;https://w…...

HDFS分布式存储 zookeeper

hadoop介绍 狭义上hadoop是指apache的一款开源软件 用java语言实现开源框架&#xff0c;允许使用简单的变成模型跨计算机对大型集群进行分布式处理&#xff08;1.海量的数据存储 2.海量数据的计算&#xff09;Hadoop核心组件 hdfs&#xff08;分布式文件存储系统&#xff09;&a…...

人机融合智能 | “人智交互”跨学科新领域

本文系统地提出基于“以人为中心AI(HCAI)”理念的人-人工智能交互(人智交互)这一跨学科新领域及框架,定义人智交互领域的理念、基本理论和关键问题、方法、开发流程和参与团队等,阐述提出人智交互新领域的意义。然后,提出人智交互研究的三种新范式取向以及它们的意义。最后,总结…...

Java数值运算常见陷阱与规避方法

整数除法中的舍入问题 问题现象 当开发者预期进行浮点除法却误用整数除法时,会出现小数部分被截断的情况。典型错误模式如下: void process(int value) {double half = value / 2; // 整数除法导致截断// 使用half变量 }此时...

Selenium常用函数介绍

目录 一&#xff0c;元素定位 1.1 cssSeector 1.2 xpath 二&#xff0c;操作测试对象 三&#xff0c;窗口 3.1 案例 3.2 窗口切换 3.3 窗口大小 3.4 屏幕截图 3.5 关闭窗口 四&#xff0c;弹窗 五&#xff0c;等待 六&#xff0c;导航 七&#xff0c;文件上传 …...