#javascript #typescript #import #locale #date-fns
Вопрос:
У меня есть приложение, которое получает список поддерживаемых языков от серверной части в качестве следующего ответа:
{locales: [{code: 'enUS'}, {code: 'deDE'}, {code: 'arAR'}]}
Я хочу использовать библиотеку date-fn для обработки форматирования даты, но мне нужно импортировать всю дату-fn/языковой стандарт, так как я не могу заранее знать, какой языковой стандарт потребуется:
import * as dateFnsLocales from 'date-fns/locale';
Проблема в том, что некоторые локали имеют другой формат кода (например, поддержка немецкого языка включена, когда внутренний ответ содержит код: «deDE», но соответствующий пакет date-fns-это просто «de». С другой стороны, пакет date-fns для английского языка-это «enUS», а не просто «en».
Простым решением имхо было бы справиться с этим с помощью какого-нибудь объединяющего оператора. Пример следующий:
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)]),
}));
К сожалению, я получаю ошибку машинописи:
No index signature with a parameter of type 'string' was found on type 'typeof import("date-fns/locale")'. TS7053
Даже если я жестко закодирую попытку так:
dateFnsLocale: dateFnsLocales['plPL'.substring(0,2)]
он завершается с той же ошибкой, хотя это:
dateFnsLocale: dateFnsLocales['pl']
работает просто отлично.
Ответ №1:
Вот код, который я использую для динамического поиска с использованием Localization
объекта Expo.
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
);
}
Вот тест
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);
});
});
Комментарии:
1. Спасибо за ответ и полезные тесты!