框架参考

模块 Constant 与 I18n 样板

参考模块常量与 I18n 样板,替换占位业务名称和资源。

浏览全部手册
本页目录
文档来源与 Markdown 原文

权威正文:ineed-core/docs/project-development/module-constant-i18n-template.md。网站按工作区快照同步,原文中的历史日期和验证范围保留。

开始编码前核对同版本源码;跨仓文件引用可在源码定位目录查找。

下载 Markdown 原文 ↓

文档定位

本文档提供一份可直接复制的模块级样板,用于新建业务模块时一次性补齐:

  • {Object}Constant
  • 控制器 Urls / Resource 接入
  • 模块内 ErrorCode
  • messages.properties
  • messages_en.properties
  • messages_zh_TW.properties
  • message.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=分組已存在:分組名稱不允許重複

顺序要求:

  1. Errors
  2. Common
  3. Entity name
  4. Entity fields
  5. Entity unique constraints
  6. 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.aocontract.querycontract.vojpa.entityjdbc.entitymybatisflex.entityr2dbc.entity 等实现分层片段;{Entity} 使用实体类简单名。{tableName} 必须使用数据库真实表名, 例如 isec_userisec_user_group{dbConstraintName} 必须使用数据库返回的真实约束名,例如 uk_isec_user_accountfk_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);

不要在 ManagerServiceRepositoryMapper 中直接写完整 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=登录账号

推荐生成顺序

创建新模块时,建议按以下顺序生成:

  1. 先写 {Object}Constant
  2. 再接控制器 @RequestMappinggetResourceKey()getResourceName()
  3. 再补模块内 ErrorCode
  4. 再补 message.multiproperties
  5. 再补 messages.properties
  6. 最后补 messages_en.propertiesmessages_zh_TW.properties

这样能避免代码先落地、常量和文案后补时发生漂移。

自检清单

提交前至少确认:

  1. 控制器没有直接写资源路径字面量
  2. 控制器没有直接写资源标识字面量
  3. 模块私有业务错误没有直接写中文消息
  4. 模块私有 ErrorCode 已配齐 message.multiproperties 和三份 messages*.properties
  5. 文案占位符统一使用 {0}{1} 风格
  6. 对象名和字段名 key 与运行时类名一致
  7. 所有出现在 messages*.properties 的模块私有对象名、字段名和关键枚举标签 key 都已同步补齐到 message.multiproperties
  8. UK/FK 约束文案 key 已在 {Object}Constant.I18nKey 中定义,业务代码没有直接硬编码完整 key 字符串

最后更新:2026-05-15

仍有疑问?按反馈清单整理复现信息 →