【问题标题】:Testing Date Object with Jest using Typescript and i18next使用 Typescript 和 i18next 使用 Jest 测试日期对象
【发布时间】:2020-05-05 12:27:18
【问题描述】:

包含一个本地化库,我的组件中有一个日期对象,如下所示:

  getDate = () => {
    const { t } = this.props;
    return new Date().toLocaleString(t('locale.name'), {
      weekday: "long",
      month: "long",
      day: "numeric",
    });
  };

当我尝试运行测试时,出现错误:

RangeError: Invalid language tag: language.name at Date.toLocaleString ()

  15 |   getDate = () => {
  16 |     const { t } = this.props;
> 17 |     return new Date().toLocaleString(t('language.name'), {
     |                       ^
  18 |       weekday: "long",
  19 |       month: "long",
  20 |       day: "numeric",

所以它无法识别 i18n 语言环境。这和我嘲笑 i18n 的方式有关吗?

我目前的设置:

react-i18next.ts:

jest.mock('i18next', () => ({
  use: () => {
    return {
      init: () => { }
    };
  },
  t: k => k
}));

我的 jest.config:

module.exports = {
  verbose: true,
  roots: ["<rootDir>"],
  testRegex: "/__tests__/.*\\.(test|spec)\\.tsx?",
  transform: {
    "^.+\\.tsx?$": "ts-jest",
  },
  moduleNameMapper: {
    "react-i18next": "<rootDir>/__tests__/__mock__/react-i18next.ts"
  },
};

i18n.ts

import i18n from "i18next";
import {initReactI18next} from "react-i18next";
import english from "./locales/en/common.json";
import french from "./locales/fr/common.json";

i18n.use(initReactI18next).init({
  lng: 'en',
  resources: {
    fr: {
      translation: french,
    },
    en: {
      translation: english,
    },
  },
  interpolation: {
    escapeValue: false,
  },
  fallbackLng: ["en"]
});

export default i18n;

【问题讨论】:

    标签: reactjs typescript internationalization jestjs i18next


    【解决方案1】:

    您模拟 t 使其返回密钥本身,因此,toLocaleStringlanguage.name 作为一种语言,并抛出“Invalid language tag”。

    我对日期格式进行本地化的方法是使用formatting 方法按区域设置日期格式。

    // i18next.config.js
    
    ...
    {
      interpolation: {
        format: (value, format, lng) => {
          if (value instanceof Date) {
            const cloneDate = new Date(value);
    
            return cloneDate.toLocaleString(lng, mapFormatToLocale[format]);
          }
          return value;
        };
      }
    }
    ...
    
    const mapFormatToLocale = {
      YYYYmmdd: {
        weekday: 'long',
        month: 'long',
        day: 'numeric',
      },
    };
    
    // locale.en.json 
    
    {
      "MY_DATE": "My Date {{date, YYYYmmdd}}"
    }
    
    
    // usage of the date locatization
    
    t('MY_DATE', {date: new Date()});
    

    这个方法最酷的部分是您可以在翻译 json 文件中定义日期格式样式,这意味着您可以根据需要更改每种语言。

    此方法反转语言环境和日期之间的依赖关系,并且适用于您的模拟,因为您的模拟只会返回翻译键。

    【讨论】:

    • 嘿,谢谢!只是出于好奇,我用不同的参数多次调用日期,是否仍然可以使用您的代码?我可以将 i18next.config.js 中的内容放入 i18next.ts 中吗?
    • 每次您将日期对象作为参数传递时,它都会应用格式。 2. 当然它应该与您的 i18next 配置一起使用 :)
    • 谢谢!我现在正在尝试,但我收到此行不存在格式的错误。这是 tsx 的事情吗? return cloneDate.toLocaleString(lng, mapFormatToLocale[format]);
    • 谢谢!我必须添加一个 if 语句来检查格式是否也存在!最后一个问题,你知道渲染实际时间的适当方式吗?我进行了测试,我期待一个实际日期:预期:“1 月 1 日,星期一”收到:“dateLocale.MY_DATE”
    • 从一开始你就嘲笑 i18next 翻译函数返回键。使用此模拟,您将无法测试翻译功能的结果。您可以测试是否使用正确的 TranslationKey 和正确的日期对象调用了翻译函数。
    猜你喜欢
    • 2018-07-28
    • 2021-07-02
    • 2023-04-01
    • 2017-02-25
    • 1970-01-01
    • 2019-01-29
    • 2020-11-03
    • 2020-07-04
    • 2023-01-10
    相关资源
    最近更新 更多