-
Notifications
You must be signed in to change notification settings - Fork 394
ErrorCode和i18n支持
目录
ZStack使用ErrorCode对象向用户汇报错误,当一个API发生错误时,其返回会包含一个ErrorCode
对象。
早期ErrorCode
不带i18n支持,新版本中我们加入了i18n支持,本文不介绍如何自己新增一种错误类型到ZStack中,只介绍如何创建带i18n支持的ErrorCode
对象。
对于最常见的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)
对于非法参数错误,可以使用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
对象:
- ioerr:
IO_ERROR
错误 - httperr:
HTTP_ERROR
错误
它们的原型跟operr()
和argerr()
一样。
inerr()
函数用于生成INTERNAL
(内部错误)ErrorCode
对象,但跟其它便捷函数不一样的是,内部错误不带i18n支持。
i18n目的是给不同语言用户本语种的错误提示。内部错误属于程序错误,用户遇到后应提交错误给开发者debug,故无需翻译,统一使用英文。
inerr()
原型跟operr()
一样。
前面几种便捷函数对常用错误做了封装,对于自定义错误和没有便捷函数的错误,可以使用通用的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支持,可以使用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)
。
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
命令自动生成的。
当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支持的字符串/错误码使用
i18n()
或err()
等函数进行封装 - 运行
./runMavenProfile i18njson
命令更新conf/i18n.json
文件 - 对
conf/i18n.json
文件中新生成的词条进行翻译 - 运行
./runMavenProfile i18n
生成最终的i18n properties文件 - git commit && git push