You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

NestJS结合Sequelize如何实现LocalizedColumn装饰器简化多语言字段定义

自定义@LocalizedColumn装饰器实现方案

前置准备

首先确认你项目中已安装以下依赖:

  • sequelize-typescript
  • @nestjs/swagger
  • lodash
    同时你已定义好语言映射配置Locals,示例参考:
// src/constants/locale.constant.ts
export const Locals = {
  ar: 'Ar',
  en: 'En'
} as const;
// 支持的语言列表
export const SUPPORTED_LOCALES = Object.keys(Locals) as Array<keyof typeof Locals>;

装饰器实现代码

import { Column, DataType } from 'sequelize-typescript';
import { ApiProperty } from '@nestjs/swagger';
import * as _ from 'lodash';
import { Locals, SUPPORTED_LOCALES } from 'src/constants/locale.constant';

export function LocalizedColumn(columnOptions: { type: DataType, allowNull?: boolean } & Record<string, any> = {}) {
  return function (target: any, propertyKey: string) {
    // 生成所有语言对应的物理字段名列表
    const localeColumns: string[] = SUPPORTED_LOCALES.map(locale => {
      const suffix = Locals[locale];
      return `${propertyKey}${suffix}`;
    });

    // 动态给每个语言的物理字段添加@Column和@ApiProperty装饰器
    localeColumns.forEach((columnName, index) => {
      const locale = SUPPORTED_LOCALES[index];
      // 注册物理字段
      Column({
        ...columnOptions,
        // 可选:自定义数据库字段名蛇形命名,不需要可删除
        field: _.snakeCase(columnName)
      })(target, columnName);

      // 注册Swagger文档注解,不需要可删除本段
      ApiProperty({
        type: columnOptions.type,
        required: !columnOptions.allowNull,
        description: `${propertyKey}(${locale})`
      })(target, columnName);
    });

    // 给原属性注册虚拟字段逻辑
    Column({
      type: DataType.VIRTUAL(columnOptions.type, localeColumns),
      get() {
        const currentLocale = (this as any).$local || 'ar';
        const suffix = Locals[currentLocale as keyof typeof Locals];
        return this[`${propertyKey}${suffix}`];
      },
      set(value: any) {
        const currentLocale = (this as any).$local || 'ar';
        const suffix = Locals[currentLocale as keyof typeof Locals];
        this[`${propertyKey}${suffix}`] = value;
      }
    })(target, propertyKey);
  }
}

使用方式

在模型中直接注解即可,和你预期的用法完全一致:

import { ApiProperty } from '@nestjs/swagger';
import { DataType, Model } from 'sequelize-typescript';
import { LocalizedColumn } from 'src/decorators/localized-column.decorator';

export class YourModel extends Model {
  @ApiProperty({ type: String })
  @LocalizedColumn({
    type: DataType.STRING,
    allowNull: false
  })
  name: string;

  @ApiProperty({ type: String })
  @LocalizedColumn({
    type: DataType.STRING
  })
  address: string;
}

注意事项

  • 需要确保请求处理流程中,会把当前用户的语言标识挂载到模型实例的$local属性上,你可以选择在请求中间件、全局拦截器或者service层赋值;如果不想挂载到实例上,也可以修改装饰器的get/set逻辑,从cls-hooked的全局请求上下文里取当前语言,使用起来更灵活。
  • 后续新增语言只需要修改Locals常量添加映射即可,不需要改动其他逻辑。
  • 如果不需要生成多语言字段的Swagger文档,直接删除装饰器中ApiProperty相关的代码即可。

内容的提问来源于stack exchange,提问作者zain khatib

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.29 13:06:04