npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@tfnick/nestjs-dict-translate

v1.0.5

Published

A NestJS module for dictionary translation and caching

Readme

NestJS 字典翻译模块

一个基于 NestJS 的字典翻译模块,支持代码字典、数据库字典和配置字典的翻译功能。

功能特性

  • ✅ 支持多种字典类型:代码字典、数据库字典、配置字典
  • ✅ 注解式翻译:通过 @Translate 注解自动翻译对象字段
  • ✅ 灵活字段翻译:支持从 ID 翻译到任意字段(code、name、自定义字段等)
  • ✅ 缓存支持:内置内存缓存,提高翻译性能
  • ✅ 类型安全:完整的 TypeScript 类型支持
  • ✅ 易于集成:模块化设计,轻松集成到现有项目

安装

npm install tfnick/nestjs-dict-trans

快速开始

1. 导入模块

import { Module, OnModuleInit } from '@nestjs/common';
import { DictTranslateModule, DictService } from '@tfnick/nestjs-dict-trans';

@Module({
  imports: [
    DictTranslateModule.forRoot({
      // 可选的全局配置
      cache: {
        ttl: 3600, // 缓存时间(秒)
        max: 1000   // 最大缓存数量
      }
    }),
  ],
  providers: [DictInitializerService],
})
export class AppModule implements OnModuleInit {
  constructor(private dictInitializerService: DictInitializerService) {}

  async onModuleInit() {
    // 应用启动时初始化字典数据
    await this.dictInitializerService.initialize();
  }
}

2. 定义字典数据

在应用启动时直接注册字典定义:

import { Injectable } from '@nestjs/common';
import { DictService } from '@tfnick/nestjs-dict-trans';

@Injectable()
export class DictInitializerService {
  constructor(private dictService: DictService) {}

  async initialize() {
    // 注册代码字典(静态数据)
    this.dictService.registerDefinition({
      type: 'code',
      key: 'gender',
      data: [
        { code: 'M', name: '男' },
        { code: 'F', name: '女' },
        { code: 'U', name: '未知' }
      ],
      ttl: 86400 // 缓存24小时
    });

    // 注册数据库字典(动态数据)
    this.dictService.registerDefinition({
      type: 'database',
      key: 'business_unit',
      tableName: 'business_units',
      condition: { status: 1 },
      ttl: 300 // 缓存5分钟
    });

    // 注册状态字典
    this.dictService.registerDefinition({
      type: 'code',
      key: 'status',
      data: [
        { code: 0, name: '禁用' },
        { code: 1, name: '启用' },
        { code: 2, name: '待审核' }
      ]
    });
  }
}

3. 使用注解翻译

import { Translate } from '@tfnick/nestjs-dict-trans';

export class UserDto {
  id: number;
  name: string;
  
  genderCode: string;
  @Translate({
    dictType: 'gender',
    codeField: 'genderCode',
    nameField: 'genderName'
  })
  genderName?: string;

  unitId: number;

  @Translate({
    dictType: 'business_unit',
    codeField: 'unitId', // 指定翻译来源Id字段
    nameField: 'unitName', // 指定翻译目标赋值字段
    valueField: 'name|code' // 可选:指定获取id=${unitId}时的name或code的值
  })
  unitName?: string;
}
table business_units(id, code, name, parent_id, status)

4. 执行翻译

import { TranslateService } from '@tfnick/nestjs-dict-trans';

@Injectable()
export class UserService {
  constructor(private translateService: TranslateService) {}

  async getUserWithTranslation(userId: number): Promise<UserDto> {
    const user = await this.userRepository.findById(userId);
    return this.translateService.translateObject(user);
  }

  async getUsersWithTranslation(): Promise<UserDto[]> {
    const users = await this.userRepository.findAll();
    return this.translateService.translateArray(users);
  }
}

手动翻译 API

翻译单个字段

// 翻译到默认字段(name)
const name = await translateService.translateField('gender', 'M');
// 返回:'男'

// 翻译到指定字段
const code = await translateService.translateField('business_unit', 1, 'unit_code');
// 返回:'BU001'

const status = await translateService.translateField('business_unit', 1, 'status');
// 返回:1

灵活的多字段翻译

// 业务场景:根据ID获取不同字段的值
const unitName = await translateService.translateField('business_unit', 1, 'unit_name');
const unitCode = await translateService.translateField('business_unit', 1, 'unit_code');
const parentId = await translateService.translateField('business_unit', 4, 'parent_id');

数据库字典集成

1. 接口化设计(推荐)

模块提供了接口化的数据库查询服务设计,业务系统可以通过实现 DatabaseDictService 接口来自定义数据库查询逻辑。

实现数据库查询接口

import { Injectable } from '@nestjs/common';
import { DatabaseDictService, DictDefinition, DictItem } from '@tfnick/nestjs-dict-trans';

@Injectable()
export class CustomDatabaseDictService implements DatabaseDictService {
  constructor(private dataSource: DataSource) {}

  async fetchFromDatabase(definition: DictDefinition): Promise<DictItem[]> {
    const { tableName, condition } = definition;
    
    const queryBuilder = this.dataSource
      .getRepository(tableName)
      .createQueryBuilder('t');
    
    if (condition) {
      queryBuilder.where(condition);
    }
    
    return queryBuilder.getMany();
  }
}

注册数据库服务

import { Module } from '@nestjs/common';
import { DictTranslateModule, DATABASE_DICT_SERVICE } from '@tfnick/nestjs-dict-trans';

@Module({
  imports: [DictTranslateModule.forRoot()],
  providers: [
    {
      provide: DATABASE_DICT_SERVICE,
      useClass: CustomDatabaseDictService
    }
  ]
})
export class AppModule {}

在业务系统中使用

import { Injectable } from '@nestjs/common';
import { DictService } from 'nestjs-dict-trans';

@Injectable()
export class DictInitializerService {
  constructor(private dictService: DictService) {}

  async initialize() {
    // 注册数据库字典
    this.dictService.registerDefinition({
      type: 'database',
      key: 'business_unit',
      tableName: 'business_units',
      condition: { status: 1 },
      ttl: 300 // 缓存5分钟
    });
  }
}

设计优势

  • 松耦合: 业务系统只需实现接口,无需修改核心模块
  • 类型安全: 完整的 TypeScript 类型支持
  • 灵活性: 支持不同数据库和ORM框架
  • 可扩展: 支持自定义查询逻辑和缓存策略

2. 字段映射和返回值处理

在实现数据库查询时,需要正确处理字段映射和返回值格式:

import { Injectable } from '@nestjs/common';
import { DataSource } from 'typeorm';
import { DatabaseDictService, DictDefinition, DictItem } from '@tfnick/nestjs-dict-trans';

@Injectable()
export class CustomDatabaseDictService implements DatabaseDictService {
  constructor(private dataSource: DataSource) {}

  async fetchFromDatabase(definition: DictDefinition): Promise<DictItem[]> {
    const { tableName, condition, codeField = 'code', nameField = 'name' } = definition;
    
    const queryBuilder = this.dataSource
      .getRepository(tableName)
      .createQueryBuilder('t');
    
    if (condition) {
      queryBuilder.where(condition);
    }
    
    const results = await queryBuilder.getMany();
    
    // 转换为标准 DictItem 格式,保留所有字段用于多字段翻译
    return results.map(item => ({
      code: item[codeField],
      name: item[nameField],
      ...item // 保留其他字段
    }));
  }
}

数据库字典定义

// 业务单元字典
this.dictService.registerDefinition({
  type: 'database',
  key: 'business_unit',
  tableName: 'business_units',
  codeField: 'id',      // 指定代码字段
  nameField: 'name',    // 指定名称字段
  condition: { status: 1 },
  ttl: 300 // 缓存5分钟
});

// 部门字典
this.dictService.registerDefinition({
  type: 'database',
  key: 'department',
  tableName: 'departments',
  codeField: 'id',
  nameField: 'dept_name',
  condition: { is_active: true },
  ttl: 600 // 缓存10分钟
});

高级用法

自定义缓存策略

import { MemoryCacheService } from '@tfnick/nestjs-dict-trans';

@Injectable()
export class CustomCacheService extends MemoryCacheService {
  // 重写缓存策略
  async get<T>(key: string): Promise<T | undefined> {
    // 自定义缓存逻辑
  }
}

批量刷新缓存

// 刷新单个字典缓存
await this.dictService.refreshDict('business_unit');

// 刷新所有字典缓存
const dictKeys = ['gender', 'business_unit', 'department'];
await Promise.all(dictKeys.map(key => this.dictService.refreshDict(key)));

配置选项

模块配置

DictTranslateModule.forRoot({
  // 全局缓存配置
  cache: {
    ttl: 3600, // 缓存时间(秒)
    max: 1000  // 最大缓存数量
  },
  
  // 数据库配置(可选)
  database: {
    type: 'mysql',
    host: 'localhost',
    port: 3306,
    username: 'root',
    password: 'password',
    database: 'your_db'
  }
})

字典定义配置

interface DictDefinition {
  type: 'code' | 'database' | 'config';
  key: string;                    // 字典唯一标识
  codeField?: string;             // 代码字段名,默认 'code'
  nameField?: string;             // 名称字段名,默认 'name'
  data?: DictItem[];              // 代码字典数据
  tableName?: string;             // 数据库表名
  condition?: any;                // 查询条件
  ttl?: number;                   // 缓存时间(秒)
}

测试

运行测试

# 测试
npm run test

# 生成测试报告
npm run test:cov

测试示例

describe('字典翻译测试', () => {
  it('应该正确翻译业务单元名称', async () => {
    const result = await translateService.translateField('business_unit', 1);
    expect(result).toBe('研发中心');
  });

  it('应该支持多字段翻译', async () => {
    const name = await translateService.translateFieldTo('business_unit', 1, 'unit_name');
    const code = await translateService.translateFieldTo('business_unit', 1, 'unit_code');
    
    expect(name).toBe('研发中心');
    expect(code).toBe('BU001');
  });
});

最佳实践

1. 字典定义管理

  • 建议在应用启动时集中注册所有字典定义
  • 为每个字典设置合理的缓存时间
  • 定期刷新需要实时更新的字典

2. 性能优化

  • 使用缓存减少数据库查询
  • 批量翻译时使用 translateArray 方法
  • 合理设置字典数据量,避免加载过多数据

3. 错误处理

try {
  const result = await translateService.translateField('nonexistent_dict', 1);
} catch (error) {
  // 处理字典不存在的情况
  console.error('字典翻译失败:', error.message);
}

常见问题

Q: 如何支持多个数据库字段翻译?

A: 使用 translateFieldTo 方法指定目标字段:

// 翻译到不同字段
const name = await translateService.translateFieldTo('business_unit', 1, 'unit_name');
const code = await translateService.translateFieldTo('business_unit', 1, 'unit_code');

Q: 字典数据量很大怎么办?

A: 建议:

  • 使用分页加载字典数据
  • 设置合理的缓存策略
  • 按需加载字典数据

Q: 如何实现字典数据的实时更新?

A: 可以:

  • 调用 refreshDict 方法手动刷新缓存
  • 监听数据库变更事件自动刷新
  • 设置较短的缓存时间

许可证

MIT License

贡献

欢迎提交 Issue 和 Pull Request!

更新日志

v1.0.0

  • 初始版本发布
  • 支持代码字典、数据库字典、配置字典
  • 注解式自动翻译
  • 灵活的多字段翻译功能