当前位置: 首页 > 后端技术 > Java

后端国际化(二):使用AST完成中文抽取过滤

时间:2023-04-01 16:29:39 Java

提取中文文本的工具使用org.eclipse.jdt.core将java代码转成AST将java代码转成AST树defparser=newParser()CompilationUnitresult=parser.ast(content)Documentdocument=newDocument(src.text)defast=result.getAST()使用Vistior方式遍历所有字符串ListvisitChineseText(CompilationUnitresult){vartranslateList=[]result.accept(newASTVisitor(){@Overridebooleanvisit(StringLiteralnode){if(node.toString()=~Config.DOUBLE_BYTE_REGEX){translateList.add(node)}returnsuper.visit(node)}})returntranslateList}过滤原理:熟悉AST,下面是logger.info("异常information"+e)AST如果我们需要过滤logger.info("异常信息"+e),需要查找到MethodInvocation节点,然后检查MethodInvocation的表达式是否为SimpleName类型,getIdentifier()=="logger"需要过滤的中文奇异果实现的过滤器支持过滤以下中文:去除注释、过滤日志中的中文、过滤系统配置中的中文。参与业务逻辑的中文,如“Chinese”。枚举中的中文存在于枚举的中文注释中。添加kiwi-disable-methodfilter实现所有的filter。实现Predicate接口判断是否过滤中文。常用的过滤器有:annotationfilterbooleanisInAnnotation(StringLiteralstringLiteral){defparent=stringLiteral.parent//查找StringLiteral节点,如果找到注解则返回truewhile(parent!=null&&!(parentinstanceofTypeDeclaration)){if(parentinstanceofAnnotation){defmemberValuePair=AstUtils.lookupUntilASTNode(stringLiteral,MemberValuePair.class)if(memberValuePair.isPresent()){return!shouldExclude(memberValuePair.get(),parent)}returntrue}parent=parent.parent}returnfalse}常量过滤器枚举过滤器在Enum中通常不需要翻译中文,也不能替换,因为初始化时无法调用方法。publicenumRpFlagEnum{/***Coping*/P("P","Coping"),/***Receivable*/R("R","Receivable");}defoptMethod=AstUtils.lookupUntilASTNode(stringLiteral,EnumConstantDeclaration.class)if(optMethod.isPresent()){returntrue}returnfalselogfilterfilterlog.info("Chinese")defoptMethod=AstUtils.查找直到ASTNode(stringLiteral,MethodInvocation.class)if(optMethod.isPresent()){defmethodName=optMethod.get().getExpression()//log.info(xxx)if(methodNameinstanceofSimpleName){defsimpleName=(SimpleName)methodNameif(isLogInfo(simpleName.getIdentifier())){returntrue}//this.log.info(xxx)}elseif(methodNameinstanceofFieldAccess){deffieldAccess=(FieldAccess)methodNamedeffieldName=fieldAccess.getName()if(isLogInfo(fieldName.getIdentifier())){returntrue}}}returnfalseMain方法过滤i18n方法过滤注释添加kiwi-disable-method某些情况下我们需要过滤的中文属于业务逻辑,但是代码不能judge,需要加注释才能跳过ingLiteral.parentwhile(parent!=null&&!(parentinstanceofTypeDeclaration)){if(parentinstanceofMethodDeclaration){defdoc=parent.getJavadoc()returndoc.toString().contains(methodComment)}parent=parent.parent}returnfalse}正则过滤器(正则匹配汉字(只包括标点符号))参与业务逻辑如"Chinese".equsals("Chinese")booleanhasStringEquals(StringLiteralstringLiteral){defoptMethod=AstUtils.lookupUntilASTNode(stringLiteral,MethodInvocation.class)if(optMethod.isPresent()){defmethod=optMethod.get()if(method.name.identifier=="equals"){返回真}}返回假}