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

如何在NestJS中本地化Swagger接口的@ApiQuery描述?

NestJS Swagger @ApiQuery 描述本地化方案

装饰器在类定义阶段执行,此时I18n服务尚未初始化,所以无法直接将动态翻译后的字符串传入@ApiQuery的description参数。以下是两种可行的解决方案:

方案一:生成多语言独立Swagger文档

通过创建不同语言版本的OpenAPI文档,让用户访问不同端点查看对应语言的接口描述:

  1. 定义带国际化键的自定义装饰器
    用自定义装饰器存储翻译键,替代直接写入硬编码描述:

    import { ApiQuery, ApiQueryOptions } from '@nestjs/swagger';
    
    export const ApiI18nQuery = (options: Omit<ApiQueryOptions, 'description'> & { i18nKey: string }) => {
      // 先传入翻译键作为临时描述,后续替换
      return ApiQuery({ ...options, description: options.i18nKey });
    };
    
  2. 在接口中使用自定义装饰器

    @Get()
    @ApiI18nQuery({ name: 'search', required: false, i18nKey: 'api.query.search' })
    @ApiI18nQuery({ name: 'limit', required: false, type: Number, i18nKey: 'api.query.limit' })
    getItems(
      @Query('search') search?: string,
      @Query('limit') limit?: number,
    ) {
      return this.carService.find({ search, limit });
    }
    
  3. 生成多语言文档并注册端点
    借助transformDocument钩子,在生成文档时替换翻译键为对应语言的文本:

    import { SwaggerModule, DocumentBuilder } from '@nestjs/swagger';
    import { I18nService } from 'nestjs-i18n'; // 假设你用的是nestjs-i18n
    
    async function bootstrap() {
      const app = await NestFactory.create(AppModule);
      const i18nService = app.get(I18nService);
    
      // 生成英文文档
      const enDoc = SwaggerModule.createDocument(app, new DocumentBuilder()
        .setTitle('API Documentation (English)')
        .build(), {
        transformDocument: (doc) => {
          replaceI18nDescriptions(doc, i18nService, 'en');
          return doc;
        },
      });
    
      // 生成西班牙文文档
      const esDoc = SwaggerModule.createDocument(app, new DocumentBuilder()
        .setTitle('Documentación de la API (Español)')
        .build(), {
        transformDocument: (doc) => {
          replaceI18nDescriptions(doc, i18nService, 'es');
          return doc;
        },
      });
    
      // 注册两个Swagger UI端点
      SwaggerModule.setup('api/docs/en', app, enDoc);
      SwaggerModule.setup('api/docs/es', app, esDoc);
    
      await app.listen(3000);
    }
    
    // 通用替换函数
    function replaceI18nDescriptions(doc: any, i18nService: I18nService, lang: string) {
      Object.values(doc.paths).forEach(path => {
        Object.values(path).forEach((operation: any) => {
          operation.parameters?.forEach((param: any) => {
            if (param.in === 'query' && param.description) {
              param.description = i18nService.translate(param.description, { lang });
            }
          });
        });
      });
    }
    

方案二:Swagger UI内动态切换语言

通过自定义JS在Swagger UI页面添加语言切换控件,动态替换描述文本,无需生成多份文档:

  1. 使用带扩展字段的自定义装饰器
    将翻译键存入OpenAPI的扩展字段,避免和临时描述混淆:

    import { ApiQuery, ApiQueryOptions } from '@nestjs/swagger';
    
    export const ApiI18nQuery = (options: Omit<ApiQueryOptions, 'description'> & { i18nKey: string }) => {
      return ApiQuery({
        ...options,
        description: options.i18nKey,
        'x-i18n-key': options.i18nKey, // 存储到扩展字段
      });
    };
    
  2. 在Swagger UI中注入自定义JS
    在SwaggerModule.setup时添加语言切换逻辑:

    SwaggerModule.setup('api/docs', app, document, {
      customJs: `
        // 定义翻译字典(可改为从外部JSON文件加载)
        const translations = {
          en: {
            'api.query.search': 'Search term to filter items',
            'api.query.limit': 'Number of items to return'
          },
          es: {
            'api.query.search': 'Término de búsqueda para filtrar elementos',
            'api.query.limit': 'Número de elementos a devolver'
          }
        };
    
        // 添加语言选择下拉框
        const langSelect = document.createElement('select');
        langSelect.className = 'lang-selector';
        langSelect.innerHTML = '<option value="en">English</option><option value="es">Español</option>';
        document.querySelector('.swagger-ui .topbar-wrapper').appendChild(langSelect);
    
        // 替换描述文本的函数
        function updateDescriptions(lang) {
          document.querySelectorAll('.parameter__description').forEach(el => {
            const key = el.textContent.trim();
            if (translations[lang][key]) {
              el.textContent = translations[lang][key];
            }
          });
          // 可扩展替换其他元素,如接口标题、摘要等
        }
    
        // 初始化显示英文
        updateDescriptions('en');
    
        // 监听语言切换事件
        langSelect.addEventListener('change', (e) => {
          updateDescriptions(e.target.value);
        });
      `,
      customCss: `
        /* 给语言选择框加样式 */
        .lang-selector {
          margin-left: 1rem;
          padding: 0.3rem;
          border-radius: 4px;
          border: 1px solid #ccc;
        }
      `
    });
    

如果你的翻译存储在外部JSON文件中,可以将translations改为通过fetch加载对应语言的JSON文件,避免硬编码。

内容的提问来源于stack exchange,提问作者Rashid Behbudov

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.22 04:40:22