最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Failing to "dynamically" import date-fnslocale libs - TypeScript giving an attempted import error

programmeradmin7浏览0评论

I have an app that receives a list of supported locales from the backend as a following response:

{locales: [{code: 'enUS'}, {code: 'deDE'}, {code: 'arAR'}]}

I want to use date-fns library for handling date formatting but I have to import the whole date-fns/locale as I can't know beforehand which locale will be needed:

import * as dateFnsLocales from 'date-fns/locale';

The problem is, some of the locales are in different code format (for example, support for deutsch language is enabled when the backend response includes code: 'deDE', but the corresponding date-fns package is just 'de'. On the other hand date-fns package for english is 'enUS', not just 'en'.

Easy solution imho would be to handle it with some coalescing operator. The example is following:

import * as dateFnsLocales from 'date-fns/locale';

const supportedLocales = {locales: [{code: 'enUS'}, {code: 'deDE'}, {code: 'plPL'}]}
const newArrayWithSupportedLocales = supportedLocales.locales.map((locale) => ({
        ...locale,
        dateFnsLocale: (dateFnsLocales[locale.code] || dateFnsLocales[locale.code.substring(0,2)]),
      }));

Unfortunately I get the typescript error: No index signature with a parameter of type 'string' was found on type 'typeof import("date-fns/locale")'. TS7053

Even if I hardcode the attempt like so:

dateFnsLocale: dateFnsLocales['plPL'.substring(0,2)]

it fails with the same error, even though this:

dateFnsLocale: dateFnsLocales['pl']

works just fine.

I have an app that receives a list of supported locales from the backend as a following response:

{locales: [{code: 'enUS'}, {code: 'deDE'}, {code: 'arAR'}]}

I want to use date-fns library for handling date formatting but I have to import the whole date-fns/locale as I can't know beforehand which locale will be needed:

import * as dateFnsLocales from 'date-fns/locale';

The problem is, some of the locales are in different code format (for example, support for deutsch language is enabled when the backend response includes code: 'deDE', but the corresponding date-fns package is just 'de'. On the other hand date-fns package for english is 'enUS', not just 'en'.

Easy solution imho would be to handle it with some coalescing operator. The example is following:

import * as dateFnsLocales from 'date-fns/locale';

const supportedLocales = {locales: [{code: 'enUS'}, {code: 'deDE'}, {code: 'plPL'}]}
const newArrayWithSupportedLocales = supportedLocales.locales.map((locale) => ({
        ...locale,
        dateFnsLocale: (dateFnsLocales[locale.code] || dateFnsLocales[locale.code.substring(0,2)]),
      }));

Unfortunately I get the typescript error: No index signature with a parameter of type 'string' was found on type 'typeof import("date-fns/locale")'. TS7053

Even if I hardcode the attempt like so:

dateFnsLocale: dateFnsLocales['plPL'.substring(0,2)]

it fails with the same error, even though this:

dateFnsLocale: dateFnsLocales['pl']

works just fine.

Share Improve this question edited Apr 23, 2024 at 18:34 Grant Humphries 3,0162 gold badges26 silver badges24 bronze badges asked Mar 16, 2021 at 15:10 WhichmannWhichmann 1871 gold badge1 silver badge11 bronze badges 2
  • 1 I know this is an old question and you've already solved it with the answer below using Expo's Localization, which is probably a better solution anyway. But we were using Object.entries(locales).find(([key]) => key === str)?.[1], where str could be your 'plPL'.substring(0,2) for example. (I came across this question trying to find an alternative for the import * as dateFnsLocales from 'date-fns/locale';, since it almost doubles the bundle-size in our Angular project..) – Kevin Cruijssen Commented May 5, 2023 at 14:38
  • Thanks, I don't work on this project anymore but I sent it to the former work colleague to test it. import * always bugged me there – Whichmann Commented Jan 18, 2024 at 15:40
Add a ment  | 

2 Answers 2

Reset to default 17

Here's the code I am using for doing dynamic lookups using Expo's Localization object.

import * as Localization from 'expo-localization';
import * as Locales from 'date-fns/locale';
import { Locale } from 'date-fns';

/**
 * Looks up a date-fns locale from the Expo localization object.  This falls back to `en-US`
 * @param localization Expo Localization object containing the locale and region.
 * @returns date-fns locale.
 */
export function getDateFnsLocale({ locale, region }: Pick<typeof Localization, 'locale'|'region'>) : Locale {
  return (
    Locales[locale.substring(0, 2) + region] ?? Locales[locale.substring(0, 2)] ?? Locales.enUS
  );
}

Here's the test

import { enUS, fr, frCA } from 'date-fns/locale';

describe('date-fns locale lookup', () => {
  it('shound find fr', () => {
    expect(getDateFnsLocale({ locale: 'fr', region: null })).toBe(fr);
  });
  it('shound find fr-CA', () => {
    expect(getDateFnsLocale({ locale: 'fr-CA', region: 'CA' })).toBe(frCA);
  });
  it('shound not find zz-ZZ', () => {
    expect(getDateFnsLocale({ locale: 'zz-ZZ', region: 'ZZ' })).toBe(enUS);
  });
});

this is my solution

import * as loc from 'date-fns/locale';

export const getDateFnsLocaleByActiveLanguage = (lang: string) => 
  lang === 'en'
   ? loc['enUS']
   : Object.values(loc).find((l) => l.code === lang);

与本文相关的文章

发布评论

评论列表(0)

  1. 暂无评论