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

如何让Strapi国际化使用默认语言数据填充未本地化内容?

Strapi多语言数据默认 fallback 实现方案

针对你遇到的「未填充本地化内容时,切换语言无法查看数据」的问题,有两种实用方案可以实现默认语言数据自动补全:

方案一:自定义内容类型控制器(单类型适配)

这种方式针对单个内容类型(比如你的Appointments)做定制化处理,灵活可控。

  1. 找到对应控制器文件:src/api/appointment/controllers/appointment.js(TypeScript项目为.ts)
  2. 重写find和findOne方法,实现 fallback 逻辑:
'use strict';

const { createCoreController } = require('@strapi/strapi').factories;

module.exports = createCoreController('api::appointment.appointment', ({ strapi }) => ({
  // 列表查询 fallback
  async find(ctx) {
    const defaultLocale = strapi.plugin('i18n').service('locales').getDefaultLocale().code;
    const requestedLocale = ctx.query.locale || defaultLocale;

    // 先尝试获取请求语言的数据
    let { data, meta } = await super.find(ctx);

    // 如果请求语言无数据,返回默认语言数据
    if (data.length === 0) {
      ctx.query.locale = defaultLocale;
      ({ data, meta } = await super.find(ctx));
      // 可选:标记数据来自默认语言 fallback
      data = data.map(item => ({
        ...item,
        attributes: { ...item.attributes, __fallback_from: defaultLocale }
      }));
    }

    return { data, meta };
  },

  // 单条查询 fallback(字段级补全)
  async findOne(ctx) {
    const defaultLocale = strapi.plugin('i18n').service('locales').getDefaultLocale().code;
    const requestedLocale = ctx.query.locale || defaultLocale;

    // 获取请求语言的条目
    let { data } = await super.findOne(ctx);

    // 如果请求语言无此条目,返回默认语言版本
    if (!data) {
      ctx.query.locale = defaultLocale;
      ({ data } = await super.findOne(ctx));
      return { data };
    }

    // 获取该条目的默认语言版本,补全空字段
    const defaultEntry = await strapi.db.query('api::appointment.appointment').findOne({
      where: { id: data.id, locale: defaultLocale },
      populate: ctx.query.populate
    });

    if (defaultEntry) {
      const mergedAttrs = { ...defaultEntry.attributes };
      // 优先保留请求语言已填充的字段,空字段用默认语言补全
      Object.keys(data.attributes).forEach(key => {
        if (data.attributes[key] != null && data.attributes[key] !== '') {
          mergedAttrs[key] = data.attributes[key];
        }
      });
      data.attributes = mergedAttrs;
    }

    return { data };
  }
}));

方案二:全局中间件(全类型适配)

如果需要所有本地化内容类型都生效,可以用全局中间件统一处理:

  1. 创建中间件文件:src/middlewares/locale-fallback.js
'use strict';

module.exports = (config, { strapi }) => {
  return async (ctx, next) => {
    await next();

    // 仅处理API响应且带locale参数的请求
    if (!ctx.response.body?.data || !ctx.query.locale) return;

    const defaultLocale = strapi.plugin('i18n').service('locales').getDefaultLocale().code;
    const requestedLocale = ctx.query.locale;

    if (requestedLocale === defaultLocale) return;

    const entityType = ctx.route.info.apiName;

    // 处理列表请求
    if (Array.isArray(ctx.response.body.data)) {
      // 列表为空时,返回默认语言数据
      if (ctx.response.body.data.length === 0) {
        const defaultData = await strapi.entityService.findMany(entityType, {
          ...ctx.query,
          locale: defaultLocale
        });
        ctx.response.body = defaultData;
        return;
      }

      // 字段级补全
      for (const item of ctx.response.body.data) {
        const defaultEntry = await strapi.entityService.findOne(entityType, item.id, {
          locale: defaultLocale,
          populate: ctx.query.populate
        });
        if (defaultEntry) {
          Object.keys(defaultEntry.attributes).forEach(key => {
            if (!item.attributes[key] || item.attributes[key] === '') {
              item.attributes[key] = defaultEntry.attributes[key];
            }
          });
        }
      }
    } else {
      // 处理单条请求
      let data = ctx.response.body.data;
      if (!data) {
        const defaultEntry = await strapi.entityService.findOne(entityType, ctx.params.id, {
          ...ctx.query,
          locale: defaultLocale
        });
        ctx.response.body = { data: defaultEntry };
        return;
      }

      const defaultEntry = await strapi.entityService.findOne(entityType, data.id, {
        locale: defaultLocale,
        populate: ctx.query.populate
      });
      if (defaultEntry) {
        Object.keys(defaultEntry.attributes).forEach(key => {
          if (!data.attributes[key] || data.attributes[key] === '') {
            data.attributes[key] = defaultEntry.attributes[key];
          }
        });
      }
    }
  };
};
  1. 在config/middlewares.js中注册中间件:
module.exports = [
  'strapi::errors',
  'strapi::security',
  'strapi::cors',
  'strapi::poweredBy',
  'strapi::logger',
  'strapi::query',
  'strapi::body',
  'strapi::session',
  'strapi::favicon',
  'strapi::public',
  'global::locale-fallback' // 添加此行注册中间件
];

注意事项

  • 确保默认语言在Strapi后台的i18n设置中已正确配置
  • 中间件方案会对所有API生效,若需排除特定内容类型,可在中间件中添加判断逻辑
  • 字段补全逻辑可根据实际需求调整(比如只针对特定字段做fallback)

内容的提问来源于stack exchange,提问作者Tolis Oug

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.29 15:25:30