Skip to content

ErrorCode和i18n支持

zhangxin edited this page Mar 12, 2017 · 3 revisions

目录

介绍

ZStack使用ErrorCode对象向用户汇报错误,当一个API发生错误时,其返回会包含一个ErrorCode对象。

早期ErrorCode不带i18n支持,新版本中我们加入了i18n支持,本文不介绍如何自己新增一种错误类型到ZStack中,只介绍如何创建带i18n支持的ErrorCode对象。

创建i18n ErrorCode对象

OPERATION_ERROR

对于最常见的OPERATION_ERROR(操作失败)错误,可以使用Platform.operr()函数创建,例如:

import static org.zstack.core.Platform.operr;

reply.setError(operr("appliance vm[uuid:%s] is in status of %s that cannot make http call to %s",
        self.getUuid(), getSelf().getStatus(), msg.getPath()));

operr()原型为: public static ErrorCode operr(String fmt, Object...args)

INVALID_ARGUMENT_ERROR

对于非法参数错误,可以使用Platform.argerr()函数创建,例如:

import static org.zstack.core.Platform.operr;

throw new ApiMessageInterceptionException(argerr("cannot add ceph backup storage," +
    "there has been some ceph backup storage using mon[hostnames:%s]", existing));

argerr()原型为:public static ErrorCode argerr(String fmt, Object...args)

其它便捷函数

除了上述最常见错误类型,还有如下便捷类型用于生成带i18n支持的ErrorCode对象:

  1. ioerr:IO_ERROR错误
  2. httperr:HTTP_ERROR错误

它们的原型跟operr()argerr()一样。

inerr()函数

inerr()函数用于生成INTERNAL(内部错误)ErrorCode对象,但跟其它便捷函数不一样的是,内部错误不带i18n支持。

i18n目的是给不同语言用户本语种的错误提示。内部错误属于程序错误,用户遇到后应提交错误给开发者debug,故无需翻译,统一使用英文。

inerr()原型跟operr()一样。

通用函数err()

前面几种便捷函数对常用错误做了封装,对于自定义错误和没有便捷函数的错误,可以使用通用的err()函数生成带i18n支持的ErrorCode对象。例如将operr()一节例子用err()函数改写:

import static org.zstack.core.Platform.err;
import org.zstack.header.errorcode.SysErrors;

reply.setError(err(SysErrors.OPERATION_ERROR, "appliance vm[uuid:%s] is" +
    "in status of %s that cannot make http call to %s",
    self.getUuid(), getSelf().getStatus(), msg.getPath()));

err()原型为:public static ErrorCode err(Enum errCode, String fmt, Object...args)

i18n支持

如果一个字符串需要i18n支持,可以使用Platform.i18n()函数,例如:

import static org.zstack.core.Platform.i18n;

String details = i18n("current vm instance state[%s] doesn't allow to proceed message[%s], allowed states are %s",
currentState, msg.getMessageName(), checker.getStatesForOperation(msg.getMessageName()))

i18n()原型为:public static String i18n(String str, Object...args)

生成i18n JSON文件

ZStack用一个JSON文件(conf/i18n.json)文件存放i18n翻译信息,每个条目包含该词条所有语种的翻译,例如:

{
"raw": "appliance vm[uuid:%s] is in status of %s that cannot make http call to %s",
"en_US": "appliance vm[uuid:{0}] is in status of {1} that cannot make http call to {2}",
"zh_CN": "系统虚拟机[uuid:{0}]处于{1}状态,无法对[{2}]执行HTTP RPC调用",
"arguments": [
    "self.getUuid()",
    "getSelf().getStatus()",
    "msg.getPath()"
],
"line": 126,
"fileName": "src/main/java/org/zstack/appliancevm/ApplianceVmBase.java"
}

注意如果词条带参数,{0}, {1}用于参数替换,其中的数字表示是第几个参数。

条目的字段定义如下:

  • raw: 词条,即源码中需要i18n支持的字符串
  • en_US: 词条自动生成的英文翻译,
  • zh_CN: 中文翻译,需要手工输入
  • arguments: 自动从源码中抓取出的词条参数列表,用作翻译时的参考
  • line: 词条在源文件中的行号
  • fileName: 词条所在的源文件

conf/i18n.json是通过运行

./runMavenProfile i18njson

命令自动生成的。

生成最终的i18n properties文件

conf/i18n.json中的词条的所有语言支持都已经翻译完毕后,运行

./runMavenProfile i18n

生成最终i18n properties文件,这些文件才是被ZStack直接使用了i18n支持文件。生成的文件位于conf/i18n目录,目前只支持英文和中文两种语言。

生成的properties文件中的词条示例如下:

# at: src/main/java/org/zstack/appliancevm/ApplianceVmBase.java:126
# args: self.getUuid(),getSelf().getStatus(),msg.getPath()
appliance\ vm[uuid\:%s]\ is\ in\ status\ of\ %s\ that\ cannot\ make\ http\ call\ to\ %s = 系统虚拟机[uuid:{0}]处于{1}状态,无法对[{2}]执行HTTP RPC调用

开发者增加i18n支持流程

  1. 开发者在编写源码时,对需要i18n支持的字符串/错误码使用i18n()err()等函数进行封装
  2. 运行./runMavenProfile i18njson命令更新conf/i18n.json文件
  3. conf/i18n.json文件中新生成的词条进行翻译
  4. 运行./runMavenProfile i18n生成最终的i18n properties文件
  5. git commit && git push