共计 1885 个字符,预计需要花费 5 分钟才能阅读完成。
前言
在实现中文的提取和过滤之后,咱们须要对中文节点进行转换、翻译、替换。
文案转换
文案转换通常有一下几个状况
一般文案
比方 ” 保留胜利 ”,间接替换成对应的 code 即可
拼接的文案
"用户" + user.name + "不能为空"
,会做占位符转换, 合并成 "用户{0} 不能为空"
, 而后替换成对应的 code
注解中的文案
比方"用户不能为空"
,须要替换成成对应的{code}
,code 两边须要退出{},以符合要求。
节点替换
一般文案
"保留胜利"
替换为I18nUtils.getMessage("save_succeeded")
拼接文案
"用户名" + user.name + "不能为空"
替换为I18nUtils.getMessage("user_name_not_empty", new Object[]{user.name})
注解中的文案
@NotNull(message = "'type' 不能为空 ")
替换为@NotNull(message ="{type_cannot_be_empty}")
字段中的字符串
private static String abc = "你好"
替换为
private String getAbc(){return I18nUtils.getMessage("hello") | |
} |
MessageFormat.format 中的文案
MessageFormat.format("用户名 {0} 不能为空", user.name)
替换为I18nUtils.getMessage("user_name_not_empty", new Object[]{user.name})
替换原理
所谓替换,就是解析相应的 AST 树并转为指标树
一般文案 AST 树结构
MethodInvocation getI18nCall(List<ASTNode> args){def methodInvocation = ast.newMethodInvocation() | |
methodInvocation.setExpression(ast.newSimpleName(Config.getI18nClass())) | |
methodInvocation.name = ast.newSimpleName("getMessage") | |
methodInvocation.arguments().addAll(args) | |
methodInvocation | |
} |
简单文案节点结构
源 AST 树(MessageFormat.format(“{0}”, row))
指标 AST 树(I18nUtils.getMessage(“{0}”, new Object[]{ row}))
void replaceMessageFormatWithI18n(MethodInvocation methodInvocation, StringLiteral stringLiteral){def args = [] | |
// 提取 MessageFormat.format 中的第一个中文 | |
StringLiteral code = ASTNode.copySubtree(methodInvocation.getAST(), stringLiteral) | |
// 翻译并替换 code | |
translateKey(code) | |
// 获取 MessageFormat.format 残余的参数 | |
List<ASTNode> retainExp = methodInvocation.arguments().subList(1, methodInvocation.arguments().size()) | |
.collect({ASTNode.copySubtree(methodInvocation.getAST(), (ASTNode)it) }) | |
args.add(code) | |
def array = ast.newArrayCreation() | |
args.add(array) | |
// 结构 new Object 节点 | |
array.setType(ast.newArrayType(ast.newSimpleType(ast.newSimpleName("Object")))) | |
def arrayInitializer = ast.newArrayInitializer() | |
// 将残余的参数全副退出到 new Object 节点 | |
arrayInitializer.expressions().addAll(retainExp) | |
array.setInitializer(arrayInitializer) | |
// 转换为 I18nUtils.getMessage 模式 | |
convertStringLiteral(args, methodInvocation) | |
} |