spring boot后端异常抛出国际化替换脚本

194 阅读3分钟

最近在做spring boot的国际化,将后端的自定义异常抛出的提示全替换为i18n的key,一个一个手动替换很麻烦,写了两个python脚本, 一个是提取中文内容到txt中,一个是将properties中的文件替换到java代码中,虽然并不是全自动,但还是相对减轻了一些工作量。 不是很擅长写python,还原大佬指正改进。

提取

代码

import re
import os   

def extract_exception_messages(java_file):
    """
    从Java文件中提取异常抛出中的中文内容,写入文件
    """
    unique_exception_messages = set()
    with open(java_file, 'r', encoding='utf-8') as file:
        for line in file:
            # 对于异常全是中文的提取,如 new SystemException("查询失败,请检查输入")
            direct_match = re.search(r'new\s+SystemException\("(.*?)"\)', line)
            if direct_match:
                message = direct_match.group(1).strip()
                unique_exception_messages.add(message)
            else:
                # 对于使用String.format的提取  如 new SystemException(String.format("错误: %s", e.getMessage()))
                format_match = re.search(r'new\s+SystemException\(String\.format\("(.*?)"\s*,\s*(.*?)\)\)', line)
                if format_match:
                    format_string = format_match.group(1).strip()
                    placeholders = re.findall(r'%[sd]', format_string)
                    message = format_string.replace('%s', '{}').replace('%d', '{}')
                    unique_exception_messages.add(message)
                else:
                    # 对于使用 new SystemException("错误:" + e.getMessage())
                    plus_match = re.search(r'new\s+SystemException\("(.*?)"\s*\+\s*(.*?)\s*\)', line)
                    if plus_match:
                        prefix = plus_match.group(1).strip()
                        suffix = plus_match.group(2).strip().strip('+').strip()
                        message = prefix + '{}'
                        if suffix:
                            message += suffix
                        unique_exception_messages.add(message)
    
    return unique_exception_messages


def extract_exceptions_from_java_folder(java_folder, output_file):
    """
    遍历文件夹下的java文件,对每个文件单独提取
    """
    # 存储国际化内容
    unique_exception_messages = set()
    for root, dirs, files in os.walk(java_folder):
        for file in files:
            if file.endswith('.java'):
                file_path = os.path.join(root, file)
                messages = extract_exception_messages(file_path)
                unique_exception_messages.update(messages)
    
    # 将结果写入文件
    with open(output_file, 'a', encoding='utf-8') as txt_file:
        for message in unique_exception_messages:
            txt_file.write(message + '\n')

# java项目目录和输出文件
java_folder = 'E:\\dir\\project\\src\\main\\java\\com'
output_file = 'E:\\dir\\excpetion.txt'

extract_exceptions_from_java_folder(java_folder, output_file)

注意

提取对比
new SystemException("查询失败,请检查输入")  =>  查询失败,请检查输入
new SystemException(String.format("错误: %s, %s", e.getMessage(), name)) => 错误: {}, {}
new SystemException("错误:" + e.getMessage()) =>  错误:{}
不足之处
  • 对于一些自定义参数的提取没有在{}中加入0,1,2, ...., 需要手动加入
  • 有时{}后面会带上(很好辨认,应该是第三个正则的问题,手动改比我改代码更快)

替换

代码

import re
import os

def load_message_properties(file_path):
    """
    加载i18n properties文件中的内容到map中
    """
    messages = {}
    with open(file_path, 'r', encoding='utf-8') as file:
        for line in file:
            line = line.strip()
            if line and not line.startswith('#'):
            	# 中文为key, i18n_key作为value
                value, key = line.split('=')
                messages[key.strip()] = value.strip()
    return messages

def replace_exceptions_with_keys(file_path, messages):
    """
    替换文件中的中文为i18n key
    """
    with open(file_path, 'r+', encoding='utf-8') as file:
        content = file.read()
        for exception_match in re.finditer(r'new\s+SystemException\("(.+?)"\)', content):
            exception_message = exception_match.group(1)
            if exception_message in messages:
                new_exception_message = messages[exception_message]
                content = content.replace(f'("{exception_message}")', f'("{new_exception_message}")')
                
        file.seek(0)
        file.write(content)
        file.truncate()

def process_java_files(folder_path, messages):
    """
    对java文件进行遍历处理
    """
    for root, dirs, files in os.walk(folder_path):
        for file in files:
            if file.endswith('.java'):
                java_file_path = os.path.join(root, file)
                replace_exceptions_with_keys(java_file_path, messages)

def main():
    # 国际化文件位置
    message_properties_file = 'E:\\dir\\project\\src\\main\\resources\\messages.properties'
    
    # java项目目录
    java_folder = 'E:\\dir\\project\\src\\main\\java\\com'

    # 加载国际化文件
    messages = load_message_properties(message_properties_file)

    # 遍历文件逐个替换
    process_java_files(java_folder, messages)

if __name__ == "__main__":
    main()

注意

  • 只会对下面类型的内容进行替换
new SystemException("查询失败,请检查输入")  => new SystemException("find.error")  

后记

简单做个记录,虽然不是很完美,也相对减轻了一些工作量,抛砖引玉。