Skip to content

React 中封装$k

如果你用的是 vite 搭建的项目,你可以写成一个自动导入的函数。

根目录新建一个文件夹及文件,比如preFunc/index.ts

这里的 i18n 是 react-i18next

ts
// src/locales/index.ts

import i18next from 'i18next';
import { initReactI18next } from 'react-i18next';
import cn from '@/locales/cn.json';
import en from '@/locales/en.json';

i18next.use(initReactI18next).init({
  resources: {
    en: { translation: en },
    zh: { translation: cn },
  },
  lng: 'en', // 默认语言
  fallbackLng: 'en',
  interpolation: {
    escapeValue: false, // React 已经对输出内容进行了转义
  },
});

export default i18next;
ts
// src/preFunc/index.ts
import i18n from '@/locales';

export const $k = (strings: TemplateStringsArray | string, ...values: any[]) => {
  // 处理普通函数调用
  if (typeof strings === 'string') {
    return strings;
  }

  const firstPart = strings[0];

  if (firstPart.includes('__')) {
    const [key, firstStaticText] = firstPart.split('__');

    const result = (i18n as any).t(key, [...values]);
    if (result) {
      return result;
    }

    // 兜底处理
    const newStrings = [...strings];
    newStrings[0] = firstStaticText;

    return newStrings.reduce((result, str, i) => {
      const value = values[i] !== undefined ? values[i] : '';
      return result + str + value;
    }, '');
  }

  // 普通拼接
  return strings.reduce((result, str, i) => {
    const value = values[i] !== undefined ? values[i] : '';
    return result + str + value;
  }, '');
};

然后在 vite.config.ts 中配置

ts
import AutoImport from 'unplugin-auto-import/vite';
export default () => {
  return defineConfig({
    plugins: [
      AutoImport({
        include: [/\.[tj]sx?$/],
        dts: 'src/auto-import.d.ts', // 生成 auto-import.d.ts 全局声明
        resolvers: [],
        dirs: ['./preFunc/**'],
      }),
    ],
  });
};

为了防止ts报警告,可以在全局的d.ts中声明

ts
interface ComponentCustomProperties {
  $k: (strings: TemplateStringsArray | string, ...values: any[]) => string;
}

react-i18next推荐使用useTranslation hook 来使用。

你可以写一个 hook 来使用。

ts
import { useTranslation } from 'react-i18next';

export const useK = () => {
  const { t, i18n } = useTranslation();

  const $k = useCallback((strings: TemplateStringsArray | string, ...values: any[]) => {
    // 处理普通函数调用
    if (typeof strings === 'string') {
      return strings;
    }

    const firstPart = strings[0];

    if (firstPart.includes('__')) {
      const [key, firstStaticText] = firstPart.split('__');

      const result = t(key, [...values]);
      if (result) {
        return result;
      }

      // 兜底处理
      const newStrings = [...strings];
      newStrings[0] = firstStaticText;

      return newStrings.reduce((result, str, i) => {
        const value = values[i] !== undefined ? values[i] : '';
        return result + str + value;
      }, '');
    }

    // 普通拼接
    return strings.reduce((result, str, i) => {
      const value = values[i] !== undefined ? values[i] : '';
      return result + str + value;
    }, '');
  }, [t]);

  return { $k };
};