模块 Constant 与 I18n 样板
参考模块常量与 I18n 样板,替换占位业务名称和资源。
浏览全部手册
本页目录
文档来源与 Markdown 原文
权威正文:ineed-core/docs/project-development/module-constant-i18n-template.md。网站按工作区快照同步,原文中的历史日期和验证范围保留。
开始编码前核对同版本源码;跨仓文件引用可在源码定位目录查找。
下载 Markdown 原文 ↓文档定位
本文档提供一份可直接复制的模块级样板,用于新建业务模块时一次性补齐:
{Object}Constant- 控制器
Urls/Resource接入 - 模块内
ErrorCode messages.propertiesmessages_en.propertiesmessages_zh_TW.propertiesmessage.multiproperties
如果你想先理解规则边界,先读 constant-errorcode-i18n-guide.md。
所有 REGISTERED_ERROR_1/2 及带尖括号的同名项都是模板占位符,必须从应用错误码登记表取得当前模块真实号码后统一替换。它们不能直接作为运行时错误码。XML <Name> 中使用不带尖括号的占位文本。样板用于表达结构;真实可编译例子见示例索引。
适用场景
适合以下情况:
- 新建一个业务对象模块
- 模块需要私有资源路径
- 模块需要私有资源标识
- 模块需要私有业务错误码
- 模块需要对象名、字段名、错误码的国际化文案
样板一:{Object}Constant.java
路径建议:
{module}-core/src/main/java/com/ineed/{domain}/{object}/{Object}Constant.java
示例:
package com.ineed.security.authorization.user;
import com.ineed.security.authorization.core.AuthorizationCoreConstant;
public final class UserConstant {
private UserConstant() {
super();
}
public static final class Urls {
public static final String USER = AuthorizationCoreConstant.Urls.AUTHORIZATION + "/user";
public static final String GROUP = AuthorizationCoreConstant.Urls.AUTHORIZATION + "/group";
private Urls() {
super();
}
}
public static final class Resource {
public static final String KEY_USER = "authorization.user";
public static final String NAME_USER = "用户";
public static final String KEY_GROUP = "authorization.group";
public static final String NAME_GROUP = "分组";
private Resource() {
super();
}
}
public static final class I18nKey {
public static final String USER_ACCOUNT = "isec_user.uk.uk_isec_user_account";
public static final String GROUP_NAME = "isec_group.uk.uk_isec_group_name";
public static final String USER_GROUP_USER_NOT_FOUND =
"isec_user_group.fk.not-found.fk_isec_user_group_user_id";
public static final String USER_USED_BY_USER_GROUP =
"isec_user_group.fk.in-use.fk_isec_user_group_user_id";
private I18nKey() {
super();
}
}
public static final class ErrorCode {
public static final String USER_GROUP_ALREADY_ASSIGNED = "<REGISTERED_ERROR_1>";
public static final String BUILTIN_USER_ROLE_CANNOT_REMOVE = "<REGISTERED_ERROR_2>";
private ErrorCode() {
super();
}
}
}
约束:
Urls只放模块私有资源根路径Resource同时放稳定资源标识和业务展示名,资源标识使用KEY_*,资源名称使用NAME_*I18nKey只放代码需要主动引用的模块内 i18n key,当前主要包括唯一约束和外键约束文案 key,常量值必须与三语messages*.properties保持一致ErrorCode只放模块私有业务错误- 通用动作路径继续复用
CoreConstant.Urls - 通用错误继续复用根级
ErrorCode - UK/FK 约束错误继续复用通用错误码,不为每个数据库约束新增模块私有错误码
样板二:Controller 接入
示例:
@RestController
@RequestMapping(UserConstant.Urls.USER)
public class UserController implements
ICrudController<UserAO, UserVO, UserService>,
IFindByIdController<UserVO, UserService>,
ISearchController<UserQuery, UserVO, UserService> {
private final UserService userService;
@Override
public UserService getService() {
return userService;
}
@Override
public String getResourceKey() {
return UserConstant.Resource.KEY_USER;
}
@Override
public String getResourceName() {
return UserConstant.Resource.NAME_USER;
}
}
约束:
@RequestMapping优先使用UserConstant.Urls.*getResourceKey()优先返回UserConstant.Resource.KEY_*getResourceName()优先返回UserConstant.Resource.NAME_*,用于 OpenAPI 公共摘要输出,例如把创建资源渲染为创建用户- 新代码不要直接写
"authorization.user"这类字面量
样板三:Service / Manager 抛业务错误
示例:
if (alreadyAssigned) {
throw StatefulException.of(UserConstant.ErrorCode.USER_GROUP_ALREADY_ASSIGNED);
}
带参数示例:
if (builtinRole) {
throw StatefulException.of(UserConstant.ErrorCode.BUILTIN_USER_ROLE_CANNOT_REMOVE, roleName);
}
约束:
- 模块私有业务规则使用
{Object}Constant.ErrorCode - 框架通用错误继续使用根级
ErrorCode - 不要在代码里直接硬编码中文错误文案
样板四:messages*.properties
路径建议:
{module}-core/src/main/resources/
i18n/ineed/security/authorization/user/
message.multiproperties
messages.properties
messages_en.properties
messages_zh_TW.properties
默认语言:
# Errors
<REGISTERED_ERROR_1>=用户已经分配到该分组,不允许重复分配
<REGISTERED_ERROR_2>=系统内置用户的默认角色不允许移除:{0}
# Common
security.user.accountStatus.enabled=启用
# Entity - User
com.ineed.security.authorization.user.User=用户
com.ineed.security.authorization.user.User.account=账号
com.ineed.security.authorization.user.User.nickname=昵称
isec_user.uk.uk_isec_user_account=用户已存在:账号不允许重复
# Entity - UserGroup
com.ineed.security.authorization.user.UserGroup=用户分组关系
isec_user_group.fk.not-found.fk_isec_user_group_user_id=用户不存在,不能建立用户分组关系
isec_user_group.fk.in-use.fk_isec_user_group_user_id=用户数据被用户分组关系使用,不能删除或更新
# Entity - Group
com.ineed.security.authorization.user.Group=分组
com.ineed.security.authorization.user.Group.name=分组名称
isec_group.uk.uk_isec_group_name=分组已存在:分组名称不允许重复
英文:
# Errors
<REGISTERED_ERROR_1>=User has already been assigned to the group, duplicate assignment is not allowed
<REGISTERED_ERROR_2>=Default role of builtin user cannot be removed: {0}
# Common
security.user.accountStatus.enabled=Enabled
# Entity - User
com.ineed.security.authorization.user.User=User
com.ineed.security.authorization.user.User.account=Account
com.ineed.security.authorization.user.User.nickname=Nickname
isec_user.uk.uk_isec_user_account=User already exists: account must be unique
# Entity - UserGroup
com.ineed.security.authorization.user.UserGroup=User Group Relation
isec_user_group.fk.not-found.fk_isec_user_group_user_id=User does not exist and the user group relation cannot be created
isec_user_group.fk.in-use.fk_isec_user_group_user_id=User data is referenced by user group relation and cannot be deleted or updated
# Entity - Group
com.ineed.security.authorization.user.Group=Group
com.ineed.security.authorization.user.Group.name=Group Name
isec_group.uk.uk_isec_group_name=Group already exists: group name must be unique
繁体中文:
# Errors
<REGISTERED_ERROR_1>=使用者已經分配到該分組,不允許重複分配
<REGISTERED_ERROR_2>=系統內建使用者的預設角色不允許移除:{0}
# Common
security.user.accountStatus.enabled=啟用
# Entity - User
com.ineed.security.authorization.user.User=使用者
com.ineed.security.authorization.user.User.account=帳號
com.ineed.security.authorization.user.User.nickname=暱稱
isec_user.uk.uk_isec_user_account=使用者已存在:帳號不允許重複
# Entity - UserGroup
com.ineed.security.authorization.user.UserGroup=使用者分組關係
isec_user_group.fk.not-found.fk_isec_user_group_user_id=使用者不存在,不能建立使用者分組關係
isec_user_group.fk.in-use.fk_isec_user_group_user_id=使用者資料被使用者分組關係使用,不能刪除或更新
# Entity - Group
com.ineed.security.authorization.user.Group=分組
com.ineed.security.authorization.user.Group.name=分組名稱
isec_group.uk.uk_isec_group_name=分組已存在:分組名稱不允許重複
顺序要求:
- Errors
- Common
- Entity name
- Entity fields
- Entity unique constraints
- Entity foreign-key constraints
对象、字段 key 使用业务基础包 key;数据库约束 key 使用表名 key:
{basePackage}.{Entity}{basePackage}.{Entity}.{fieldName}{tableName}.uk.{dbConstraintName}{tableName}.fk.not-found.{dbConstraintName}{tableName}.fk.in-use.{dbConstraintName}
其中 {basePackage} 是业务基础包,不包含 contract.ao、contract.query、contract.vo、jpa.entity、jdbc.entity、
mybatisflex.entity、r2dbc.entity 等实现分层片段;{Entity} 使用实体类简单名。{tableName} 必须使用数据库真实表名,
例如 isec_user 或 isec_user_group。{dbConstraintName} 必须使用数据库返回的真实约束名,例如 uk_isec_user_account
或 fk_isec_user_group_user_id。外键 key 中的 {tableName} 必须是引用方表,也就是 FK 所在表;同一个 FK 约束必须同时准备引用目标不存在、引用目标正在被使用两类文案。历史 {basePackage}.{Entity}.fk.{dbConstraintName} 和根级
constraint.* 仅作为兼容回退,不再新增。
如果业务代码需要主动抛出 FK 被占用类错误,必须先在 {Object}Constant.I18nKey 中定义常量,再引用常量;重复数据业务校验应传实体类名和字段名,由 core 统一转换对象与字段文案:
throw StatefulException.of(ErrorCode.DATA_DUPLICATE, this.getEntityClass().getName(), "account");
throw StatefulException.of(ErrorCode.DATA_IN_USE, UserConstant.I18nKey.USER_USED_BY_USER_GROUP);
不要在 Manager、Service、Repository 或 Mapper 中直接写完整 i18n key 字符串。
样板五:message.multiproperties
如果团队使用 MultiProperties 编辑器维护多语言资源,建议同时生成:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<MultiProperties xmlns="hu.skzs.multiproperties">
<Version>1.2</Version>
<Name>message</Name>
<Description></Description>
<Handler>Java Properties Handler</Handler>
<Columns>
<Key>
<Width>200</Width>
</Key>
<Column>
<Name></Name>
<Description></Description>
<Width>380</Width>
<HandlerConfiguration>/{module}-core/src/main/resources/i18n/ineed/security/authorization/user/messages.properties|false|false|false|false|ISO-8859-1</HandlerConfiguration>
</Column>
<Column>
<Name>en</Name>
<Description></Description>
<Width>538</Width>
<HandlerConfiguration>/{module}-core/src/main/resources/i18n/ineed/security/authorization/user/messages_en.properties|false|false|false|false|ISO-8859-1</HandlerConfiguration>
</Column>
<Column>
<Name>zh_TW</Name>
<Description></Description>
<Width>348</Width>
<HandlerConfiguration>/{module}-core/src/main/resources/i18n/ineed/security/authorization/user/messages_zh_TW.properties|false|false|false|false|ISO-8859-1</HandlerConfiguration>
</Column>
</Columns>
<Records>
<Comment>
<Value>Errors</Value>
</Comment>
<Property>
<Name>REGISTERED_ERROR_1</Name>
<Disabled>false</Disabled>
<MultiLine>false</MultiLine>
<Value disabled="false">用户已经分配到该分组,不允许重复分配</Value>
<Value disabled="false">User has already been assigned to the group, duplicate assignment is not allowed</Value>
<Value disabled="false">使用者已經分配到該分組,不允許重複分配</Value>
</Property>
<Comment>
<Value>Common</Value>
</Comment>
<Property>
<Name>security.user.accountStatus.enabled</Name>
<Disabled>false</Disabled>
<MultiLine>false</MultiLine>
<Value disabled="false">启用</Value>
<Value disabled="false">Enabled</Value>
<Value disabled="false">啟用</Value>
</Property>
<Comment>
<Value>Entity - User</Value>
</Comment>
<Property>
<Name>com.ineed.security.authorization.user.User</Name>
<Disabled>false</Disabled>
<MultiLine>false</MultiLine>
<Value disabled="false">用户</Value>
<Value disabled="false">User</Value>
<Value disabled="false">使用者</Value>
</Property>
<Property>
<Name>com.ineed.security.authorization.user.User.account</Name>
<Disabled>false</Disabled>
<MultiLine>false</MultiLine>
<Value disabled="false">账号</Value>
<Value disabled="false">Account</Value>
<Value disabled="false">帳號</Value>
</Property>
</Records>
</MultiProperties>
说明:
message.multiproperties是编辑视图,不是运行时加载入口- 它应与三份
messages*.properties保持同步 - 它不能只维护错误码;对象名、字段名、AO / Query / VO 对外字段名和关键枚举标签也必须同步维护
- 新增模块错误码或字段文案时,建议优先改
message.multiproperties,再同步导出
样板六:对象与字段文案
统一使用 {basePackage}.{Entity}.{fieldName} 格式:
com.ineed.security.authorization.user.User=用户
com.ineed.security.authorization.user.User.account=账号
com.ineed.security.authorization.user.User.nickname=昵称
约束:
{basePackage}使用业务基础包;例如com.ineed.security.authorization.user{Entity}使用实体类简单名,保持 UpperCamelCase- 对象和字段 key 必须跨
AO / Query / VO / Entity复用,同一个业务字段只维护一份文案 - 不要使用持久化实现类全名作为 i18n key(例如
com.ineed.security.authorization.user.jdbc.entity.User.account) applicationKey仍用于META-INF/ineed/modules/*.json、权限permissionKey、菜单资源标识等业务标识,不作为对象/字段 i18n key 前缀
如果 AO 和 Entity 的文案必须区分(例如 AO 中需要更面向用户的标签),可以显式补:
com.ineed.security.authorization.user.UserAO.account=登录账号
推荐生成顺序
创建新模块时,建议按以下顺序生成:
- 先写
{Object}Constant - 再接控制器
@RequestMapping、getResourceKey()和getResourceName() - 再补模块内
ErrorCode - 再补
message.multiproperties - 再补
messages.properties - 最后补
messages_en.properties和messages_zh_TW.properties
这样能避免代码先落地、常量和文案后补时发生漂移。
自检清单
提交前至少确认:
- 控制器没有直接写资源路径字面量
- 控制器没有直接写资源标识字面量
- 模块私有业务错误没有直接写中文消息
- 模块私有
ErrorCode已配齐message.multiproperties和三份messages*.properties - 文案占位符统一使用
{0}、{1}风格 - 对象名和字段名 key 与运行时类名一致
- 所有出现在
messages*.properties的模块私有对象名、字段名和关键枚举标签 key 都已同步补齐到message.multiproperties - UK/FK 约束文案 key 已在
{Object}Constant.I18nKey中定义,业务代码没有直接硬编码完整 key 字符串
最后更新:2026-05-15
仍有疑问?按反馈清单整理复现信息 →