关于java:后端国际化三-使用AST完成中文转换和替换

前言

在实现中文的提取和过滤之后,咱们须要对中文节点进行转换、翻译、替换。

文案转换

文案转换通常有一下几个状况

一般文案

比方”保留胜利”,间接替换成对应的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)
}

评论

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

这个站点使用 Akismet 来减少垃圾评论。了解你的评论数据如何被处理