通过python脚本判断两个多语言properties的差异,并生成缺失的文件

前言

在做多语言开发的时候,因为key值较多,可能会有遗漏的情况。通过python脚本查找确实的key值,并生成对应的csv文件,方便校验和补充缺失的值。

代码

import os
from datetime import datetime

def read_properties_keys_and_lines(file_path):
    """
    读取properties文件中的所有key及其对应的完整行,忽略空行和注释行
    :param file_path: properties文件路径
    :return: 包含所有key的集合和key到完整行的映射字典
    """
    keys = set()
    key_to_line = {}
    
    if not os.path.exists(file_path):
        print(f"警告: 文件 {file_path} 不存在")
        return keys, key_to_line
    
    try:
        with open(file_path, 'r', encoding='utf-8') as f:
            line_count = 0
            valid_line_count = 0
            for line in f:
                line_count += 1
                # 去除行首行尾的空白字符
                stripped_line = line.strip()
                
                # 忽略空行和以#开头的注释行
                if not stripped_line or stripped_line.startswith('#'):
                    continue
                
                valid_line_count += 1
                # 分割key和value
                if '=' in stripped_line:
                    key = stripped_line.split('=', 1)[0].strip()
                    keys.add(key)
                    key_to_line[key] = line.rstrip('\n')
        print(f"从文件 {file_path} 中读取了 {len(keys)} 个key (共{line_count}行,有效行{valid_line_count}行)")
    except UnicodeDecodeError:
        # 尝试使用其他编码读取文件
        try:
            with open(file_path, 'r', encoding='latin-1') as f:
                for line in f:
                    stripped_line = line.strip()
                    if not stripped_line or stripped_line.startswith('#'):
                        continue
                    if '=' in stripped_line:
                        key = stripped_line.split('=', 1)[0].strip()
                        keys.add(key)
                        key_to_line[key] = line.rstrip('\n')
            print(f"从文件 {file_path} 中读取了 {len(keys)} 个key (使用latin-1编码)")
        except Exception as e:
            print(f"读取文件 {file_path} 时出错: {e}")
    except Exception as e:
        print(f"读取文件 {file_path} 时出错: {e}")
    
    return keys, key_to_line

def check_missing_keys_and_lines(source_file, target_file):
    """
    检查在source_file中有但在target_file中没有的key及其对应的完整行
    :param source_file: 源文件路径
    :param target_file: 目标文件路径
    :return: 缺失的key集合和key到完整行的映射字典
    """
    # 读取两个文件的key集合和key到行的映射
    source_keys, source_key_to_line = read_properties_keys_and_lines(source_file)
    target_keys, target_key_to_line = read_properties_keys_and_lines(target_file)
    
    # 找出在source_keys中但不在target_keys中的key
    missing_keys = source_keys - target_keys
    
    # 构建缺失key到完整行的映射
    missing_key_to_line = {key: source_key_to_line[key] for key in missing_keys}
    
    # 添加调试信息
    print(f"源文件中key数量: {len(source_keys)}")
    print(f"目标文件中key数量: {len(target_keys)}")
    print(f"共同拥有的key数量: {len(source_keys & target_keys)}")
    print(f"缺失的key数量: {len(missing_keys)}")
    
    # 随机选取几个key进行验证(如果有缺失的key)
    if len(missing_keys) > 0:
        # 检查是否存在一些可能被误判的情况
        sample_size = min(5, len(missing_keys))
        sample_keys = list(missing_keys)[:sample_size]
        print(f"\n随机选取{sample_size}个被标记为缺失的key进行验证:")
        for key in sample_keys:
            # 检查是否因为大小写或空格问题导致误判
            similar_keys = [t_key for t_key in target_keys if key.lower() == t_key.lower()]
            if similar_keys:
                print(f"  - '{key}' 可能是大小写或空格问题,目标文件中有类似的key: {similar_keys}")
            else:
                print(f"  - '{key}' 在目标文件中确实不存在")
    
    return missing_keys, missing_key_to_line

def main():
    projectName ='part-eu'
    # 定义文件路径 - 使用双反斜杠确保正确解析
    i18n_file = f'D:\\work\\src\\{projectName}\\{projectName}-boot\\src\\main\\resources\\i18n.properties'
    es_file = f'D:\\work\\src\\{projectName}\\{projectName}-boot\\src\\main\\resources\\i18n_fr_FR.properties'
    lack_file = f'D:\\work\\src\\{projectName}\\{projectName}-boot\\src\\main\\resources\\i18n-lack.properties'
    
    print(f"正在校验资源文件: {i18n_file} 和 {es_file}")
    
    # 读取源文件和目标文件的key
    source_keys, source_key_to_line = read_properties_keys_and_lines(i18n_file)
    target_keys, _ = read_properties_keys_and_lines(es_file)
    
    # 检查缺失的key及其对应的完整行
    missing_keys = source_keys - target_keys
    missing_key_to_line = {key: source_key_to_line[key] for key in missing_keys}
    
    # 添加统计信息
    print(f"源文件中key数量: {len(source_keys)}")
    print(f"目标文件中key数量: {len(target_keys)}")
    print(f"共同拥有的key数量: {len(source_keys & target_keys)}")
    print(f"缺失的key数量: {len(missing_keys)}")
    
    # 随机选取几个key进行验证(如果有缺失的key)
    if len(missing_keys) > 0:
        # 检查是否存在一些可能被误判的情况
        sample_size = min(5, len(missing_keys))
        sample_keys = list(missing_keys)[:sample_size]
        print(f"\n随机选取{sample_size}个被标记为缺失的key进行验证:")
        for key in sample_keys:
            # 检查是否因为大小写或空格问题导致误判
            similar_keys = [t_key for t_key in target_keys if key.lower() == t_key.lower()]
            if similar_keys:
                print(f"  - '{key}' 可能是大小写或空格问题,目标文件中有类似的key: {similar_keys}")
            else:
                print(f"  - '{key}' 在目标文件中确实不存在")
    
    # 输出结果
    if missing_keys:
        print(f"在 {i18n_file} 中有但在 {es_file} 中没有的key ({len(missing_keys)}个):")
        print("=" * 80)
        for key in sorted(missing_keys):
            print(f"{missing_key_to_line[key]}")
        print("=" * 80)
        print(f"总计缺失 {len(missing_keys)} 个key")
        
        # 将缺失的key保存到新文件
        try:
            # 确保目标目录存在
            os.makedirs(os.path.dirname(lack_file), exist_ok=True)
            
            with open(lack_file, 'w', encoding='utf-8') as f:
                
                # 按顺序写入缺失的key及其行
                for key in sorted(missing_keys):
                    f.write(f"{missing_key_to_line[key]}\n")
            print(f"已成功将缺失的key保存到文件: {lack_file}")
        except Exception as e:
            print(f"保存缺失的key到文件 {lack_file} 时出错: {e}")
            print(f"错误详情: {str(e)}")
    else:
        print(f"很好! {i18n_file} 中的所有key都在 {es_file} 中找到了")
        # 如果没有缺失的key,删除lack_file(如果存在)
        if os.path.exists(lack_file):
            try:
                os.remove(lack_file)
                print(f"已删除多余的文件: {lack_file}")
            except Exception as e:
                print(f"删除文件 {lack_file} 时出错: {e}")

if __name__ == "__main__":
    main()

解释

通过下面这里配置项目路径和对比的源文件,目标文件,以及生成的缺失文件

    projectName ='part-eu'
    # 定义文件路径 - 使用双反斜杠确保正确解析
    i18n_file = f'D:\\work\\src\\{projectName}\\{projectName}-boot\\src\\main\\resources\\i18n.properties'
    es_file = f'D:\\work\\src\\{projectName}\\{projectName}-boot\\src\\main\\resources\\i18n_fr_FR.properties'
    lack_file = f'D:\\work\\src\\{projectName}\\{projectName}-boot\\src\\main\\resources\\i18n-lack.properties'

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值