相关国际化处理:
iOS【语言国际化处理】python脚本读取Excel内容批量导入国际化语言文件中(一)
iOS【语言国际化处理】python脚本将国际化语言文件批量导入Excel文件中(二)
iOS【图片国际化处理】python脚本Assets.xcassets图片名称及MD5批量处理(三)
iOS项目图片资源文件名批量调整(添加或替换前缀)
在国际化处理过程中,图片资源偶尔进行调整;
同时也可以修复xx. imageset
文件下xxa.png
的文件名不一致问题,
最好统一的样式是:xx. imageset
文件下xx.png
同时导出资源文件中不合理的资源、命名等:
如文件夹、图片名大小写、资源图片里有gif、jpg等,
(这里没有修复统一改成小写,不然使用的地方要进行调整)
导出相关异常数据【errorName.txt】文件
更新内容
1、修改图片的md5值(脚本中方法:get_file_md5
,change_file_md5
)
终端查看md5命令: md5 -q 文件路径
$ md5 -q /Users/odd/test/user.png
e27610a6e720bd58f2eebf07cb9ddead修改 md5 值
终端:输入「echo」,任意字符,「>>」,文件路径,命令如下
$ echo a >> /Users/odd/test/user.png
终端使用示例
python3.9 /Users/odd/Documents/Project/测试国际化/TestPython/CCLocalizationAssetsTool.py
配置使用:
# 需要修改的
change_head = "caaaimg_"
# 旧的,若没有给空字符:""
old_head = "cbbbimg_"
# 资源路径
#rootDir = "/Users/odd/Documents/Project/测试国际化/国际化图片资源"
rootDir = "/Users/odd/Documents/Project/测试国际化/TestImageDemo/TestImageDemo"
完整脚本:CCLocalizationAssetsTool.py
#-*-coding:utf-8-*-
import os , re
import os.path
import json
'''
文件夹示意图
-----[demo]----[Assets.xcassets]-----[file]-----[xxx1.imageset]---xxx1.png
------------------------------------------------[xxx2.imageset]---xxx2.png
---------------[AssetsM.xcassets]----[fileM]----[yyy1.imageset]---yyy1.png
'''
# 需要修改的
change_head = "caaaimg_"
# 旧的,若没有给空字符:""
old_head = "cbbbimg_"
# 资源路径
#rootDir = "/Users/odd/Documents/Project/测试国际化/国际化图片资源"
rootDir = "/Users/odd/Documents/Project/测试国际化/TestImageDemo/TestImageDemo"
# 统计含有大写字符图片名
errorOldImageNameArray = []
errorNewImageNameArray = []
# 统计异常未修改资源名
errorNOChangeImageNameArray = []
# 统计.imageset资源里图片类型
imageFileTypeArray = []
def change_assets_name():
print(" ======== 图集名称开始处理 ======== ")
xcassetsArray = get_assets_dir_Array(rootDir)
print("图片资源文件:\n",xcassetsArray)
print("\n")
# assets资源组
for xassetsIndex,xassetsGroupName in enumerate(xcassetsArray):
xassetsGroupPath = os.path.join(rootDir, xassetsGroupName)
print("\n>>>>>>资源:【" + str(xassetsIndex) + "】 图片路径:\n" + xassetsGroupPath)
categoryNameArray = get_sub_dir_files(xassetsGroupPath)
print("当前分类集:\n",categoryNameArray)
print("\n")
for categoryName in categoryNameArray:
pictureCategoryFilePath = os.path.join(xassetsGroupPath,categoryName)
imagesetArray = get_sub_dir_files(pictureCategoryFilePath)
# 将图片名称统一改成对应的文件名称一致
for imagesetFileName in imagesetArray:
# xxxx.imageset的图片资源名可能有大小写,就不强制处理了,不然要改使用的地方
imagesetName = imagesetFileName.replace(".imageset","")
#print("\n图片文件夹名:" + imagesetName)
# 需要改的图片集合文件名
if imagesetName.startswith(change_head):
changeImagetName = imagesetName
#print(".imageset文件夹名 不需要调整:" + imagesetName)
else:
# 先替换旧的前缀,在添加新的前缀
if old_head != "" and imagesetName.startswith(old_head):
changeImagetName = change_head + imagesetName.replace(old_head,"")
else:
changeImagetName = change_head + imagesetName
#print(".imageset文件夹名 需要调整为:" + changeImagetName)
imagesetFilePath = os.path.join(pictureCategoryFilePath, imagesetFileName)
# 统计含有大写的图片命名
if has_upper_char(changeImagetName):
#print("图片调整有大写:" + changeImagetName)
errorOldImageNameArray.append(imagesetName)
errorNewImageNameArray.append(changeImagetName)
# 获取.imageset文件夹里:图片名 + Contents.json
picturesNames = os.listdir(imagesetFilePath)
# 1、先修最底层的:图片名 + Contents.json
handle_pictures_imageset_sel(imagesetFilePath,picturesNames,changeImagetName)
# 2、修改当前的.imageset文件名
if not(imagesetName.startswith(change_head)):
changeImagesetFileName = changeImagetName + ".imageset"
change_imageset_file_name_sel(pictureCategoryFilePath,imagesetFileName,changeImagesetFileName)
# 3、修改一级图片分类名,APPIcon不需要调整
if categoryName.startswith(change_head) or categoryName.startswith("AppIcon"):
tttt=""
#print("分类 不用调整: " + categoryName)
else:
changeCategoryFileName = change_head + categoryName
# 已经包含前缀的,去掉前缀,重新拼接
if old_head != "" and categoryName.startswith(old_head):
changeCategoryFileName = change_head + categoryName.replace(old_head,"")
# 文件名统一小写处理
changeCategoryFileName = changeCategoryFileName.lower()
print("分类 调整为: " + changeCategoryFileName)
change_category_file_name_sel(xassetsGroupPath,categoryName,changeCategoryFileName)
# 4、统计异常文件
write_error_image_name_sel()
# ==================== 文件夹名修改:分类,imageset ================= #
def change_category_file_name_sel(dirPath,sourceName,changeName):
sourceNamePath = os.path.join(dirPath,sourceName)
changeNamePath = os.path.join(dirPath,changeName)
os.rename(sourceNamePath,changeNamePath)
print("category文件夹修改结果:" + sourceName + " : " + changeName)
def change_imageset_file_name_sel(dirPath,sourceName,changeName):
sourceNamePath = os.path.join(dirPath,sourceName)
changeNamePath = os.path.join(dirPath,changeName)
os.rename(sourceNamePath,changeNamePath)
print(".imageset文件夹修改结果:" + sourceName + " : " + changeName)
# ==================== 图片名 + .json修改 ================= #
# .imageset图片文件夹处理
def handle_pictures_imageset_sel(dirPath,picturesNames,fileName):
#print("\n图片资源改名处理:\n",picturesNames)
for pictureName in picturesNames:
#资源图片里文件类型
filteType = ""
if pictureName.find(".") != -1:
tempList = pictureName.split(".")
filteType = tempList[-1]
# 不包含时,加入
if not(filteType in imageFileTypeArray):
imageFileTypeArray.append(filteType)
if filteType != "" and filteType != "json":
change_picture_name_sel(dirPath,pictureName,fileName)
elif pictureName.endswith(".json"):
sourceName = os.path.join(dirPath,pictureName)
jsonDict = get_json_data_sel(sourceName)
write_json_data_sel(sourceName,jsonDict,fileName)
# 修改图片名为:前缀+图片文件夹名
def change_picture_name_sel(dirPath,sourceName,changeName):
# 前缀判断
if sourceName.startswith(changeName):
#print("不需要处理: " + sourceName)
return
suffixStr = ""
# 因为有些图片命名错误@2X, X大写
lowerSourceName = sourceName.lower()
if lowerSourceName.endswith("@3x.png"):
suffixStr = "@3x.png"
elif lowerSourceName.endswith("@2x.png"):
suffixStr = "@2x.png"
elif lowerSourceName.endswith(".png"):
suffixStr = ".png"
elif lowerSourceName.endswith(".pdf"):
suffixStr = ".pdf"
elif lowerSourceName.find(".") != -1:
print("\n\n异常图片>>>>>>>>>:" + sourceName + "\n\n")
# 逗号分割,取后缀(如xx.jpg.xx.gif)
tempValueList = sourceName.split(".")
suffixStr = "." + tempValueList[-1]
errorOldImageNameArray.append(sourceName)
errorNewImageNameArray.append(changeName + suffixStr)
else:
#错误资源可以统计到一个文档里
print("\n\n异常图片>>>>>>>>>:" + sourceName + "\n\n")
errorNOChangeImageNameArray.append(sourceName)
return
sourceNamePath = os.path.join(dirPath,sourceName)
changeNamePath = os.path.join(dirPath,changeName + suffixStr)
os.rename(sourceNamePath,changeNamePath)
print("修改结果:" + sourceName + " : " + changeName + suffixStr)
print("\n md5 \n")
oldMd5 = get_file_md5(changeNamePath)
change_file_md5(changeNamePath)
newMd5 = get_file_md5(changeNamePath)
print(oldMd5 + ":-->:" + newMd5)
print("\n \n")
# json读取
def get_json_data_sel(path):
# 获取json里面数据
dict = {}
with open(path, 'rb') as f:
# 定义为只读模型,并定义名称为f
params = json.load(f)
#print("\njson内容:\n", params)
# 打印
dict = params
f.close()
# 关闭json读模式
return dict
# png、jpg、pdf、gif
#{'images': [{'idiom': 'universal', 'scale': '1x'}, {'filename': 'BannerPlaceholder@2x.png', 'idiom': 'universal', 'scale': '2x'}, {'filename': 'BannerPlaceholder@3x.png', 'idiom': 'universal', 'scale': '3x'}], 'info': {'author': 'xcode', 'version': 1}}
#{'images': [{'filename': 'testbanner.jpg', 'idiom': 'universal', 'scale': '1x'}, {'idiom': 'universal', 'scale': '2x'}, {'idiom': 'universal', 'scale': '3x'}], 'info': {'author': 'xcode', 'version': 1}}
#{'images': [{'filename': 'oostlimg_placeholder_pdf.pdf', 'idiom': 'universal'}], 'info': {'author': 'xcode', 'version': 1}}
#{'data': [{'filename': 'timing.gif', 'idiom': 'universal'}], 'info': {'author': 'xcode', 'version': 1}}
# 写入json文件
def write_json_data_sel(path,dict,pictureName):
#print("\n开始处理json: " + pictureName)
#print(dict)
imagesArray = dict.get("images", [])
# 不是png图片的
if "data" in dict.keys():
imagesArray = dict.get("data", [])
for imageDic in imagesArray:
scale = imageDic.get("scale", "")
idiom = imageDic.get("idiom", "")
filename = imageDic.get("filename", "")
#print("json: " + scale + " filename: " + filename + " idiom: " + idiom)
if scale != "" and filename.endswith(".png"):
if scale.find("1x") != -1:
imageDic["filename"] = pictureName + ".png"
else:
imageDic["filename"] = pictureName + "@" + scale + ".png"
elif filename != "" and filename.find(".") != -1:
filenameCompents = filename.split(".")
# 取最后后缀
suffixStr = filenameCompents[-1]
imageDic["filename"] = pictureName + "." + suffixStr
# print("json处理结果:",dict)
#
with open(path, 'w') as r:
json.dump(dict, r)
r.close()
# 关闭json写模式
#print("==== 图片资源json处理完成 =====")
# ==================== ================= #
# 目录是否存在
def is_dir_path(path):
if path == '':
print("\n异常>>>>> 不是文件目录路径:" + path)
return False
if not os.path.exists(path):
print("\n异常>>>>>不存在目录,不创建目录:" + path)
#os.makedirs(dirs)
return False
return True
# 获取xcassets图片资源文件夹名
def get_assets_dir_Array(filePath):
results = []
if not(is_dir_path(filePath)):
return results
# 获取文件夹里子文件夹名
pathDirNames = os.listdir(filePath)
for dirName in pathDirNames:
if dirName.endswith(".xcassets"):
results.append(dirName)
return results
# 获取目录子文件夹名
def get_sub_dir_files(filePath):
results = []
if not(is_dir_path(filePath)):
return results
# 获取文件夹里子文件夹名
for root, dirs, files in os.walk(filePath):
#print(root) #当前目录路径
#print(dirs) #当前路径下所有子目录
#print(files) #当前路径下所有非目录子文件
#print("\n")
return dirs
return results
#def change_picture_imageset_name(filePath,nameHead):
# for dirName,subDir, fileNames in os.walk(filePath):
# print("imageset: " + dirName + " " + subDir + " ")
# for fileName in fileNames:
# print("fileName: " + fileName)
# 是否有大写字符
def has_upper_char(name):
upper = any(cstr.isupper() for cstr in name)
return upper
# 写异常数据到txt文件
def write_error_image_name_sel():
resultsError = []
resultsError.append("====== 图片资源处文件数据类型:=====")
resultsError.append("\n")
if isinstance(imageFileTypeArray,list) and len(imageFileTypeArray):
resultsError.extend(imageFileTypeArray)
resultsError.append("\n")
resultsError.append("====== 旧图片名 异常:=====")
resultsError.append("\n")
if isinstance(errorOldImageNameArray,list) and len(errorOldImageNameArray):
resultsError.extend(errorOldImageNameArray)
resultsError.append("\n")
resultsError.append("====== 新图片名 异常:=====")
resultsError.append("\n")
if len(errorNewImageNameArray):
resultsError.extend(errorNewImageNameArray)
resultsError.append("\n")
resultsError.append("====== 未改文件名 异常:=====")
resultsError.append("\n")
if len(errorNOChangeImageNameArray):
resultsError.extend(errorNOChangeImageNameArray)
# 清空txt文件内容(方式一)
clearfile = open(rootDir+"/errorName.txt", 'w').close()
if len(imageFileTypeArray) or len(errorOldImageNameArray) or len(errorNewImageNameArray) or len(errorNOChangeImageNameArray):
errorTextpath = rootDir+"/errorName.txt"
sqlWriteFile = open(errorTextpath,"a+")
#写入对应行+换行
sqlWriteFile.writelines([tempName+"\r" for tempName in resultsError])
sqlWriteFile.close()
#print(resultsError)
print("\n>>>>>> 异常数据txt文件路径:\n",errorTextpath)
print("\n\n")
return
print("\n>>>>>>无异常数据")
# 获取MD5
def get_file_md5(filename):
if not os.path.isfile(filename):
return
myhash = hashlib.md5()
f = open(filename,'rb')
while True:
b = f.read(8096)
if not b :
break
myhash.update(b)
f.close()
return myhash.hexdigest()
# 给文件添加末尾,改变md5
def change_file_md5(filename):
myfile = open(filename,'a')
#添加一个自定义内容,并不影响文件
myfile.write("ab")
myfile.close
change_assets_name()