From 17e2d7585d5bde74ee5bf1caa625f96463e8739d Mon Sep 17 00:00:00 2001 From: schroda <50052685+schroda@users.noreply.github.com> Date: Tue, 25 Jun 2024 17:11:33 +0200 Subject: [PATCH] Handle unsupported dayjs locales DayJs doesn't support all the locales returned by "navigator.language" --- package.json | 3 + src/components/settings/DateSetting.tsx | 2 +- src/components/settings/TimeSetting.tsx | 2 +- src/lib/dayjs/LocaleImporter.ts | 190 +++++++++++++++++++ src/lib/dayjs/Locales.ts | 160 ++++++++++++++++ src/lib/dayjs/Setup.ts | 7 +- src/util/isoLanguages.ts | 196 -------------------- src/util/language.tsx | 19 +- tools/scripts/generateDayJsLocales.ts | 28 +++ tools/scripts/generateDayJsLocalesImport.ts | 31 ++++ 10 files changed, 418 insertions(+), 220 deletions(-) create mode 100644 src/lib/dayjs/LocaleImporter.ts create mode 100644 src/lib/dayjs/Locales.ts create mode 100644 tools/scripts/generateDayJsLocales.ts create mode 100644 tools/scripts/generateDayJsLocalesImport.ts diff --git a/package.json b/package.json index 09bc00b1..c93d39fc 100644 --- a/package.json +++ b/package.json @@ -18,6 +18,9 @@ "gql:codegen-formatter": "ts-node -T tools/scripts/codegenFormatter.ts", "gql:codegen": "yarn gql:codegen-base & yarn gql:codegen-formatter", "i18n:gen-resources": "ts-node -T tools/scripts/generatei18nResources.ts", + "dayjs:gen-locales-array": "ts-node -T tools/scripts/generateDayJsLocales.ts", + "dayjs:gen-locales-import": "ts-node -T tools/scripts/generateDayJsLocalesImport.ts", + "dayjs:gen-locales": "yarn dayjs:gen-locales-array && yarn dayjs:gen-locales-import", "prepare": "husky" }, "engines": { diff --git a/src/components/settings/DateSetting.tsx b/src/components/settings/DateSetting.tsx index 0f8744e3..c254a6e8 100644 --- a/src/components/settings/DateSetting.tsx +++ b/src/components/settings/DateSetting.tsx @@ -89,7 +89,7 @@ export const DateSetting = ({ {settingName} - + { diff --git a/src/components/settings/TimeSetting.tsx b/src/components/settings/TimeSetting.tsx index fbabe909..822cad8f 100644 --- a/src/components/settings/TimeSetting.tsx +++ b/src/components/settings/TimeSetting.tsx @@ -86,7 +86,7 @@ export const TimeSetting = ({ {settingName} - + { + if (DAYJS_LOCALES.includes(locale as DayJsLocale)) { + return locale as DayJsLocale; + } + + if (DAYJS_LOCALES.includes(locale.toLowerCase() as DayJsLocale)) { + return locale.toLowerCase() as DayJsLocale; + } + + const convertedLocale = locale.split('-')[0].toLowerCase(); + if (DAYJS_LOCALES.includes(convertedLocale as DayJsLocale)) { + return convertedLocale as DayJsLocale; + } + + return 'en'; +}; + +export const importDayJsLocale = async (locale: string): Promise => { + const dayjsLocale = getDayJsLocale(locale); + + try { + // eslint-disable-next-line @typescript-eslint/no-use-before-define + await localesToImport[dayjsLocale](); + } catch (e) { + // ignore - dayjs falls back to "en" by default + } + + return dayjsLocale; +}; + +/** + * **IMPORTANT:** + * + * This is generated by the `dayjs:gen-locales-imports` script + */ +const localesToImport: Record<(typeof DAYJS_LOCALES)[number], () => Promise> = { + af: () => import('dayjs/locale/af.js'), + am: () => import('dayjs/locale/am.js'), + 'ar-dz': () => import('dayjs/locale/ar-dz.js'), + 'ar-iq': () => import('dayjs/locale/ar-iq.js'), + 'ar-kw': () => import('dayjs/locale/ar-kw.js'), + 'ar-ly': () => import('dayjs/locale/ar-ly.js'), + 'ar-ma': () => import('dayjs/locale/ar-ma.js'), + 'ar-sa': () => import('dayjs/locale/ar-sa.js'), + 'ar-tn': () => import('dayjs/locale/ar-tn.js'), + ar: () => import('dayjs/locale/ar.js'), + az: () => import('dayjs/locale/az.js'), + be: () => import('dayjs/locale/be.js'), + bg: () => import('dayjs/locale/bg.js'), + bi: () => import('dayjs/locale/bi.js'), + bm: () => import('dayjs/locale/bm.js'), + 'bn-bd': () => import('dayjs/locale/bn-bd.js'), + bn: () => import('dayjs/locale/bn.js'), + bo: () => import('dayjs/locale/bo.js'), + br: () => import('dayjs/locale/br.js'), + bs: () => import('dayjs/locale/bs.js'), + ca: () => import('dayjs/locale/ca.js'), + cs: () => import('dayjs/locale/cs.js'), + cv: () => import('dayjs/locale/cv.js'), + cy: () => import('dayjs/locale/cy.js'), + da: () => import('dayjs/locale/da.js'), + 'de-at': () => import('dayjs/locale/de-at.js'), + 'de-ch': () => import('dayjs/locale/de-ch.js'), + de: () => import('dayjs/locale/de.js'), + dv: () => import('dayjs/locale/dv.js'), + el: () => import('dayjs/locale/el.js'), + 'en-au': () => import('dayjs/locale/en-au.js'), + 'en-ca': () => import('dayjs/locale/en-ca.js'), + 'en-gb': () => import('dayjs/locale/en-gb.js'), + 'en-ie': () => import('dayjs/locale/en-ie.js'), + 'en-il': () => import('dayjs/locale/en-il.js'), + 'en-in': () => import('dayjs/locale/en-in.js'), + 'en-nz': () => import('dayjs/locale/en-nz.js'), + 'en-sg': () => import('dayjs/locale/en-sg.js'), + 'en-tt': () => import('dayjs/locale/en-tt.js'), + en: () => import('dayjs/locale/en.js'), + eo: () => import('dayjs/locale/eo.js'), + 'es-do': () => import('dayjs/locale/es-do.js'), + 'es-mx': () => import('dayjs/locale/es-mx.js'), + 'es-pr': () => import('dayjs/locale/es-pr.js'), + 'es-us': () => import('dayjs/locale/es-us.js'), + es: () => import('dayjs/locale/es.js'), + et: () => import('dayjs/locale/et.js'), + eu: () => import('dayjs/locale/eu.js'), + fa: () => import('dayjs/locale/fa.js'), + fi: () => import('dayjs/locale/fi.js'), + fo: () => import('dayjs/locale/fo.js'), + 'fr-ca': () => import('dayjs/locale/fr-ca.js'), + 'fr-ch': () => import('dayjs/locale/fr-ch.js'), + fr: () => import('dayjs/locale/fr.js'), + fy: () => import('dayjs/locale/fy.js'), + ga: () => import('dayjs/locale/ga.js'), + gd: () => import('dayjs/locale/gd.js'), + gl: () => import('dayjs/locale/gl.js'), + 'gom-latn': () => import('dayjs/locale/gom-latn.js'), + gu: () => import('dayjs/locale/gu.js'), + he: () => import('dayjs/locale/he.js'), + hi: () => import('dayjs/locale/hi.js'), + hr: () => import('dayjs/locale/hr.js'), + ht: () => import('dayjs/locale/ht.js'), + hu: () => import('dayjs/locale/hu.js'), + 'hy-am': () => import('dayjs/locale/hy-am.js'), + id: () => import('dayjs/locale/id.js'), + is: () => import('dayjs/locale/is.js'), + 'it-ch': () => import('dayjs/locale/it-ch.js'), + it: () => import('dayjs/locale/it.js'), + ja: () => import('dayjs/locale/ja.js'), + jv: () => import('dayjs/locale/jv.js'), + ka: () => import('dayjs/locale/ka.js'), + kk: () => import('dayjs/locale/kk.js'), + km: () => import('dayjs/locale/km.js'), + kn: () => import('dayjs/locale/kn.js'), + ko: () => import('dayjs/locale/ko.js'), + ku: () => import('dayjs/locale/ku.js'), + ky: () => import('dayjs/locale/ky.js'), + lb: () => import('dayjs/locale/lb.js'), + lo: () => import('dayjs/locale/lo.js'), + lt: () => import('dayjs/locale/lt.js'), + lv: () => import('dayjs/locale/lv.js'), + me: () => import('dayjs/locale/me.js'), + mi: () => import('dayjs/locale/mi.js'), + mk: () => import('dayjs/locale/mk.js'), + ml: () => import('dayjs/locale/ml.js'), + mn: () => import('dayjs/locale/mn.js'), + mr: () => import('dayjs/locale/mr.js'), + 'ms-my': () => import('dayjs/locale/ms-my.js'), + ms: () => import('dayjs/locale/ms.js'), + mt: () => import('dayjs/locale/mt.js'), + my: () => import('dayjs/locale/my.js'), + nb: () => import('dayjs/locale/nb.js'), + ne: () => import('dayjs/locale/ne.js'), + 'nl-be': () => import('dayjs/locale/nl-be.js'), + nl: () => import('dayjs/locale/nl.js'), + nn: () => import('dayjs/locale/nn.js'), + 'oc-lnc': () => import('dayjs/locale/oc-lnc.js'), + 'pa-in': () => import('dayjs/locale/pa-in.js'), + pl: () => import('dayjs/locale/pl.js'), + 'pt-br': () => import('dayjs/locale/pt-br.js'), + pt: () => import('dayjs/locale/pt.js'), + rn: () => import('dayjs/locale/rn.js'), + ro: () => import('dayjs/locale/ro.js'), + ru: () => import('dayjs/locale/ru.js'), + rw: () => import('dayjs/locale/rw.js'), + sd: () => import('dayjs/locale/sd.js'), + se: () => import('dayjs/locale/se.js'), + si: () => import('dayjs/locale/si.js'), + sk: () => import('dayjs/locale/sk.js'), + sl: () => import('dayjs/locale/sl.js'), + sq: () => import('dayjs/locale/sq.js'), + 'sr-cyrl': () => import('dayjs/locale/sr-cyrl.js'), + sr: () => import('dayjs/locale/sr.js'), + ss: () => import('dayjs/locale/ss.js'), + 'sv-fi': () => import('dayjs/locale/sv-fi.js'), + sv: () => import('dayjs/locale/sv.js'), + sw: () => import('dayjs/locale/sw.js'), + ta: () => import('dayjs/locale/ta.js'), + te: () => import('dayjs/locale/te.js'), + tet: () => import('dayjs/locale/tet.js'), + tg: () => import('dayjs/locale/tg.js'), + th: () => import('dayjs/locale/th.js'), + tk: () => import('dayjs/locale/tk.js'), + 'tl-ph': () => import('dayjs/locale/tl-ph.js'), + tlh: () => import('dayjs/locale/tlh.js'), + tr: () => import('dayjs/locale/tr.js'), + tzl: () => import('dayjs/locale/tzl.js'), + 'tzm-latn': () => import('dayjs/locale/tzm-latn.js'), + tzm: () => import('dayjs/locale/tzm.js'), + 'ug-cn': () => import('dayjs/locale/ug-cn.js'), + uk: () => import('dayjs/locale/uk.js'), + ur: () => import('dayjs/locale/ur.js'), + 'uz-latn': () => import('dayjs/locale/uz-latn.js'), + uz: () => import('dayjs/locale/uz.js'), + vi: () => import('dayjs/locale/vi.js'), + 'x-pseudo': () => import('dayjs/locale/x-pseudo.js'), + yo: () => import('dayjs/locale/yo.js'), + 'zh-cn': () => import('dayjs/locale/zh-cn.js'), + 'zh-hk': () => import('dayjs/locale/zh-hk.js'), + 'zh-tw': () => import('dayjs/locale/zh-tw.js'), + zh: () => import('dayjs/locale/zh.js'), +}; diff --git a/src/lib/dayjs/Locales.ts b/src/lib/dayjs/Locales.ts new file mode 100644 index 00000000..3b0e76e7 --- /dev/null +++ b/src/lib/dayjs/Locales.ts @@ -0,0 +1,160 @@ +/* + * Copyright (C) Contributors to the Suwayomi project + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + */ + +export type DayJsLocale = (typeof DAYJS_LOCALES)[number]; + +/** + * **IMPORTANT:** + * + * This is generated by the `dayjs:gen-locales-array` script + */ +export const DAYJS_LOCALES = [ + 'af', + 'am', + 'ar-dz', + 'ar-iq', + 'ar-kw', + 'ar-ly', + 'ar-ma', + 'ar-sa', + 'ar-tn', + 'ar', + 'az', + 'be', + 'bg', + 'bi', + 'bm', + 'bn-bd', + 'bn', + 'bo', + 'br', + 'bs', + 'ca', + 'cs', + 'cv', + 'cy', + 'da', + 'de-at', + 'de-ch', + 'de', + 'dv', + 'el', + 'en-au', + 'en-ca', + 'en-gb', + 'en-ie', + 'en-il', + 'en-in', + 'en-nz', + 'en-sg', + 'en-tt', + 'en', + 'eo', + 'es-do', + 'es-mx', + 'es-pr', + 'es-us', + 'es', + 'et', + 'eu', + 'fa', + 'fi', + 'fo', + 'fr-ca', + 'fr-ch', + 'fr', + 'fy', + 'ga', + 'gd', + 'gl', + 'gom-latn', + 'gu', + 'he', + 'hi', + 'hr', + 'ht', + 'hu', + 'hy-am', + 'id', + 'is', + 'it-ch', + 'it', + 'ja', + 'jv', + 'ka', + 'kk', + 'km', + 'kn', + 'ko', + 'ku', + 'ky', + 'lb', + 'lo', + 'lt', + 'lv', + 'me', + 'mi', + 'mk', + 'ml', + 'mn', + 'mr', + 'ms-my', + 'ms', + 'mt', + 'my', + 'nb', + 'ne', + 'nl-be', + 'nl', + 'nn', + 'oc-lnc', + 'pa-in', + 'pl', + 'pt-br', + 'pt', + 'rn', + 'ro', + 'ru', + 'rw', + 'sd', + 'se', + 'si', + 'sk', + 'sl', + 'sq', + 'sr-cyrl', + 'sr', + 'ss', + 'sv-fi', + 'sv', + 'sw', + 'ta', + 'te', + 'tet', + 'tg', + 'th', + 'tk', + 'tl-ph', + 'tlh', + 'tr', + 'tzl', + 'tzm-latn', + 'tzm', + 'ug-cn', + 'uk', + 'ur', + 'uz-latn', + 'uz', + 'vi', + 'x-pseudo', + 'yo', + 'zh-cn', + 'zh-hk', + 'zh-tw', + 'zh', +] as const; diff --git a/src/lib/dayjs/Setup.ts b/src/lib/dayjs/Setup.ts index 0b2aa1c0..a48d2377 100644 --- a/src/lib/dayjs/Setup.ts +++ b/src/lib/dayjs/Setup.ts @@ -12,12 +12,11 @@ import calendar from 'dayjs/plugin/calendar'; import relativeTime from 'dayjs/plugin/relativeTime'; import isToday from 'dayjs/plugin/isToday'; import isYesterday from 'dayjs/plugin/isYesterday'; +import { importDayJsLocale } from '@/lib/dayjs/LocaleImporter.ts'; // import localizedFormat from 'dayjs/plugin/localizedFormat'; // import updateLocale from 'dayjs/plugin/updateLocale'; // import { t } from 'i18next'; -import { loadDayJsLocale } from '@/util/language.tsx'; - dayjs.extend(customParseFormat); dayjs.extend(calendar); dayjs.extend(relativeTime); @@ -26,8 +25,8 @@ dayjs.extend(isYesterday); // dayjs.extend(localizedFormat); // dayjs.extend(updateLocale); -loadDayJsLocale(navigator.language).then(() => { - dayjs.locale(navigator.language); +importDayJsLocale(navigator.language).then((dayjsLocale) => { + dayjs.locale(dayjsLocale); // dayjs.updateLocale(navigator.language, { // calendar: { // lastDay: `[${t('global.date.label.yesterday_at')}] LT`, diff --git a/src/util/isoLanguages.ts b/src/util/isoLanguages.ts index 31276278..13208641 100644 --- a/src/util/isoLanguages.ts +++ b/src/util/isoLanguages.ts @@ -8,12 +8,9 @@ import { I18nResourceCode } from '@/i18n'; -export const loadDefaultDayJsLocale = () => import('dayjs/locale/en.js'); - export type ISOLanguage = { name: string; nativeName: string; - dayjsImport: () => Promise; }; // full list: https://github.com/meikidd/iso-639-1/blob/master/src/data.js @@ -26,52 +23,42 @@ export const ISOLanguages: { [languageCode in I18nResourceCode]: ISOLanguage } & 'es-419': { name: 'Spanish; Castilian', nativeName: 'Español', - dayjsImport: () => import('dayjs/locale/es.js'), }, 'pt-pt': { name: 'Portuguese', nativeName: 'Português (Portugal)', - dayjsImport: () => import('dayjs/locale/pt.js'), }, 'pt-br': { name: 'Portuguese; Brasil', nativeName: 'Português (Brasil)', - dayjsImport: () => import('dayjs/locale/pt-br.js'), }, zh_Hans: { name: 'Chinese (Simplified)', nativeName: '中文 (HANS)', - dayjsImport: () => import('dayjs/locale/zh-cn.js'), }, zh_Hant: { name: 'Chinese (Traditional)', nativeName: '中文 (HANT)', - dayjsImport: () => import('dayjs/locale/zh-hk.js'), }, 'zh-rhk': { name: 'Chinese', nativeName: '中文 (RHK)', - dayjsImport: () => import('dayjs/locale/zh-hk.js'), }, 'zh-rtw': { name: 'Chinese', nativeName: '中文 (RTW)', - dayjsImport: () => import('dayjs/locale/zh-tw.js'), }, fil: { name: 'Filipino', nativeName: 'Filipino', - dayjsImport: () => import('dayjs/locale/tl-ph'), }, sh: { name: 'Serbo-Croatian', nativeName: 'srpskohrvatski', - dayjsImport: loadDefaultDayJsLocale, }, 'nb-NO': { name: 'Norwegian Bokmål', nativeName: 'Norsk bokmål', - dayjsImport: () => import('dayjs/locale/nb.js'), }, // ############################# // ### ### @@ -81,918 +68,735 @@ export const ISOLanguages: { [languageCode in I18nResourceCode]: ISOLanguage } & aa: { name: 'Afar', nativeName: 'Afaraf', - dayjsImport: loadDefaultDayJsLocale, }, ab: { name: 'Abkhaz', nativeName: 'аҧсуа бызшәа', - dayjsImport: loadDefaultDayJsLocale, }, ae: { name: 'Avestan', nativeName: 'avesta', - dayjsImport: loadDefaultDayJsLocale, }, af: { name: 'Afrikaans', nativeName: 'Afrikaans', - dayjsImport: () => import('dayjs/locale/af.js'), }, ak: { name: 'Akan', nativeName: 'Akan', - dayjsImport: loadDefaultDayJsLocale, }, am: { name: 'Amharic', nativeName: 'አማርኛ', - dayjsImport: () => import('dayjs/locale/am.js'), }, an: { name: 'Aragonese', nativeName: 'aragonés', - dayjsImport: loadDefaultDayJsLocale, }, ar: { name: 'Arabic', nativeName: 'اَلْعَرَبِيَّةُ', - dayjsImport: () => import('dayjs/locale/ar.js'), }, as: { name: 'Assamese', nativeName: 'অসমীয়া', - dayjsImport: loadDefaultDayJsLocale, }, av: { name: 'Avaric', nativeName: 'авар мацӀ', - dayjsImport: loadDefaultDayJsLocale, }, ay: { name: 'Aymara', nativeName: 'aymar aru', - dayjsImport: loadDefaultDayJsLocale, }, az: { name: 'Azerbaijani', nativeName: 'azərbaycan dili', - dayjsImport: () => import('dayjs/locale/az.js'), }, ba: { name: 'Bashkir', nativeName: 'башҡорт теле', - dayjsImport: loadDefaultDayJsLocale, }, be: { name: 'Belarusian', nativeName: 'беларуская мова', - dayjsImport: () => import('dayjs/locale/be.js'), }, bg: { name: 'Bulgarian', nativeName: 'български език', - dayjsImport: () => import('dayjs/locale/bg.js'), }, bi: { name: 'Bislama', nativeName: 'Bislama', - dayjsImport: () => import('dayjs/locale/bi.js'), }, bm: { name: 'Bambara', nativeName: 'bamanankan', - dayjsImport: () => import('dayjs/locale/bm.js'), }, bn: { name: 'Bengali', nativeName: 'বাংলা', - dayjsImport: () => import('dayjs/locale/bn.js'), }, bo: { name: 'Tibetan', nativeName: 'བོད་ཡིག', - dayjsImport: () => import('dayjs/locale/bo.js'), }, br: { name: 'Breton', nativeName: 'brezhoneg', - dayjsImport: () => import('dayjs/locale/br.js'), }, bs: { name: 'Bosnian', nativeName: 'bosanski jezik', - dayjsImport: () => import('dayjs/locale/bs.js'), }, ca: { name: 'Catalan', nativeName: 'Català', - dayjsImport: () => import('dayjs/locale/ca.js'), }, ce: { name: 'Chechen', nativeName: 'нохчийн мотт', - dayjsImport: loadDefaultDayJsLocale, }, ch: { name: 'Chamorro', nativeName: 'Chamoru', - dayjsImport: loadDefaultDayJsLocale, }, co: { name: 'Corsican', nativeName: 'corsu', - dayjsImport: loadDefaultDayJsLocale, }, cr: { name: 'Cree', nativeName: 'ᓀᐦᐃᔭᐍᐏᐣ', - dayjsImport: loadDefaultDayJsLocale, }, cs: { name: 'Czech', nativeName: 'čeština', - dayjsImport: () => import('dayjs/locale/cs.js'), }, cu: { name: 'Old Church Slavonic', nativeName: 'ѩзыкъ словѣньскъ', - dayjsImport: loadDefaultDayJsLocale, }, cv: { name: 'Chuvash', nativeName: 'чӑваш чӗлхи', - dayjsImport: () => import('dayjs/locale/cv.js'), }, cy: { name: 'Welsh', nativeName: 'Cymraeg', - dayjsImport: () => import('dayjs/locale/cy.js'), }, da: { name: 'Danish', nativeName: 'Dansk', - dayjsImport: () => import('dayjs/locale/da.js'), }, de: { name: 'German', nativeName: 'Deutsch', - dayjsImport: () => import('dayjs/locale/de.js'), }, dv: { name: 'Divehi', nativeName: 'ދިވެހި', - dayjsImport: () => import('dayjs/locale/dv.js'), }, dz: { name: 'Dzongkha', nativeName: 'རྫོང་ཁ', - dayjsImport: loadDefaultDayJsLocale, }, ee: { name: 'Ewe', nativeName: 'Eʋegbe', - dayjsImport: loadDefaultDayJsLocale, }, el: { name: 'Greek', nativeName: 'Ελληνικά', - dayjsImport: () => import('dayjs/locale/el.js'), }, en: { name: 'English', nativeName: 'English', - dayjsImport: loadDefaultDayJsLocale, }, eo: { name: 'Esperanto', nativeName: 'Esperanto', - dayjsImport: () => import('dayjs/locale/eo.js'), }, es: { name: 'Spanish', nativeName: 'Español', - dayjsImport: () => import('dayjs/locale/es.js'), }, et: { name: 'Estonian', nativeName: 'eesti', - dayjsImport: () => import('dayjs/locale/et.js'), }, eu: { name: 'Basque', nativeName: 'euskara', - dayjsImport: () => import('dayjs/locale/eu.js'), }, fa: { name: 'Persian', nativeName: 'فارسی', - dayjsImport: () => import('dayjs/locale/fa.js'), }, ff: { name: 'Fula', nativeName: 'Fulfulde', - dayjsImport: loadDefaultDayJsLocale, }, fi: { name: 'Finnish', nativeName: 'suomi', - dayjsImport: () => import('dayjs/locale/fi.js'), }, fj: { name: 'Fijian', nativeName: 'vosa Vakaviti', - dayjsImport: loadDefaultDayJsLocale, }, fo: { name: 'Faroese', nativeName: 'Føroyskt', - dayjsImport: () => import('dayjs/locale/fo.js'), }, fr: { name: 'French', nativeName: 'Français', - dayjsImport: () => import('dayjs/locale/fr.js'), }, fy: { name: 'Western Frisian', nativeName: 'Frysk', - dayjsImport: () => import('dayjs/locale/fy.js'), }, ga: { name: 'Irish', nativeName: 'Gaeilge', - dayjsImport: () => import('dayjs/locale/ga.js'), }, gd: { name: 'Scottish Gaelic', nativeName: 'Gàidhlig', - dayjsImport: () => import('dayjs/locale/gd.js'), }, gl: { name: 'Galician', nativeName: 'galego', - dayjsImport: () => import('dayjs/locale/gl.js'), }, gn: { name: 'Guaraní', nativeName: "Avañe'ẽ", - dayjsImport: loadDefaultDayJsLocale, }, gu: { name: 'Gujarati', nativeName: 'ગુજરાતી', - dayjsImport: () => import('dayjs/locale/gu.js'), }, gv: { name: 'Manx', nativeName: 'Gaelg', - dayjsImport: loadDefaultDayJsLocale, }, ha: { name: 'Hausa', nativeName: 'هَوُسَ', - dayjsImport: loadDefaultDayJsLocale, }, he: { name: 'Hebrew', nativeName: 'עברית', - dayjsImport: () => import('dayjs/locale/he.js'), }, hi: { name: 'Hindi', nativeName: 'हिन्दी', - dayjsImport: () => import('dayjs/locale/hi.js'), }, ho: { name: 'Hiri Motu', nativeName: 'Hiri Motu', - dayjsImport: loadDefaultDayJsLocale, }, hr: { name: 'Croatian', nativeName: 'Hrvatski', - dayjsImport: () => import('dayjs/locale/hr.js'), }, ht: { name: 'Haitian', nativeName: 'Kreyòl ayisyen', - dayjsImport: () => import('dayjs/locale/ht.js'), }, hu: { name: 'Hungarian', nativeName: 'magyar', - dayjsImport: () => import('dayjs/locale/hu.js'), }, hy: { name: 'Armenian', nativeName: 'Հայերեն', - dayjsImport: loadDefaultDayJsLocale, }, hz: { name: 'Herero', nativeName: 'Otjiherero', - dayjsImport: loadDefaultDayJsLocale, }, ia: { name: 'Interlingua', nativeName: 'Interlingua', - dayjsImport: loadDefaultDayJsLocale, }, id: { name: 'Indonesian', nativeName: 'Bahasa Indonesia', - dayjsImport: () => import('dayjs/locale/id.js'), }, ie: { name: 'Interlingue', nativeName: 'Interlingue', - dayjsImport: loadDefaultDayJsLocale, }, ig: { name: 'Igbo', nativeName: 'Asụsụ Igbo', - dayjsImport: loadDefaultDayJsLocale, }, ii: { name: 'Nuosu', nativeName: 'ꆈꌠ꒿ Nuosuhxop', - dayjsImport: loadDefaultDayJsLocale, }, ik: { name: 'Inupiaq', nativeName: 'Iñupiaq', - dayjsImport: loadDefaultDayJsLocale, }, io: { name: 'Ido', nativeName: 'Ido', - dayjsImport: loadDefaultDayJsLocale, }, is: { name: 'Icelandic', nativeName: 'Íslenska', - dayjsImport: () => import('dayjs/locale/is.js'), }, it: { name: 'Italian', nativeName: 'Italiano', - dayjsImport: () => import('dayjs/locale/it.js'), }, iu: { name: 'Inuktitut', nativeName: 'ᐃᓄᒃᑎᑐᑦ', - dayjsImport: loadDefaultDayJsLocale, }, ja: { name: 'Japanese', nativeName: '日本語', - dayjsImport: () => import('dayjs/locale/ja.js'), }, jv: { name: 'Javanese', nativeName: 'basa Jawa', - dayjsImport: () => import('dayjs/locale/jv.js'), }, ka: { name: 'Georgian', nativeName: 'ქართული', - dayjsImport: () => import('dayjs/locale/ka.js'), }, kg: { name: 'Kongo', nativeName: 'Kikongo', - dayjsImport: loadDefaultDayJsLocale, }, ki: { name: 'Kikuyu', nativeName: 'Gĩkũyũ', - dayjsImport: loadDefaultDayJsLocale, }, kj: { name: 'Kwanyama', nativeName: 'Kuanyama', - dayjsImport: loadDefaultDayJsLocale, }, kk: { name: 'Kazakh', nativeName: 'қазақ тілі', - dayjsImport: () => import('dayjs/locale/kk.js'), }, kl: { name: 'Kalaallisut', nativeName: 'kalaallisut', - dayjsImport: loadDefaultDayJsLocale, }, km: { name: 'Khmer', nativeName: 'ខេមរភាសា', - dayjsImport: () => import('dayjs/locale/km.js'), }, kn: { name: 'Kannada', nativeName: 'ಕನ್ನಡ', - dayjsImport: () => import('dayjs/locale/kn.js'), }, ko: { name: 'Korean', nativeName: '한국어', - dayjsImport: () => import('dayjs/locale/ko.js'), }, kr: { name: 'Kanuri', nativeName: 'Kanuri', - dayjsImport: loadDefaultDayJsLocale, }, ks: { name: 'Kashmiri', nativeName: 'कश्मीरी', - dayjsImport: loadDefaultDayJsLocale, }, ku: { name: 'Kurdish', nativeName: 'Kurdî', - dayjsImport: () => import('dayjs/locale/ku.js'), }, kv: { name: 'Komi', nativeName: 'коми кыв', - dayjsImport: loadDefaultDayJsLocale, }, kw: { name: 'Cornish', nativeName: 'Kernewek', - dayjsImport: loadDefaultDayJsLocale, }, ky: { name: 'Kyrgyz', nativeName: 'Кыргызча', - dayjsImport: () => import('dayjs/locale/ky.js'), }, la: { name: 'Latin', nativeName: 'latine', - dayjsImport: loadDefaultDayJsLocale, }, lb: { name: 'Luxembourgish', nativeName: 'Lëtzebuergesch', - dayjsImport: () => import('dayjs/locale/lb.js'), }, lg: { name: 'Ganda', nativeName: 'Luganda', - dayjsImport: loadDefaultDayJsLocale, }, li: { name: 'Limburgish', nativeName: 'Limburgs', - dayjsImport: loadDefaultDayJsLocale, }, ln: { name: 'Lingala', nativeName: 'Lingála', - dayjsImport: loadDefaultDayJsLocale, }, lo: { name: 'Lao', nativeName: 'ພາສາລາວ', - dayjsImport: () => import('dayjs/locale/lo.js'), }, lt: { name: 'Lithuanian', nativeName: 'lietuvių kalba', - dayjsImport: () => import('dayjs/locale/lt.js'), }, lu: { name: 'Luba-Katanga', nativeName: 'Kiluba', - dayjsImport: loadDefaultDayJsLocale, }, lv: { name: 'Latvian', nativeName: 'latviešu valoda', - dayjsImport: () => import('dayjs/locale/lv.js'), }, mg: { name: 'Malagasy', nativeName: 'fiteny malagasy', - dayjsImport: loadDefaultDayJsLocale, }, mh: { name: 'Marshallese', nativeName: 'Kajin M̧ajeļ', - dayjsImport: loadDefaultDayJsLocale, }, mi: { name: 'Māori', nativeName: 'te reo Māori', - dayjsImport: () => import('dayjs/locale/mi.js'), }, mk: { name: 'Macedonian', nativeName: 'македонски јазик', - dayjsImport: () => import('dayjs/locale/mk.js'), }, ml: { name: 'Malayalam', nativeName: 'മലയാളം', - dayjsImport: () => import('dayjs/locale/ml.js'), }, mn: { name: 'Mongolian', nativeName: 'Монгол хэл', - dayjsImport: () => import('dayjs/locale/mn.js'), }, mr: { name: 'Marathi', nativeName: 'मराठी', - dayjsImport: () => import('dayjs/locale/mr.js'), }, ms: { name: 'Malay', nativeName: 'Bahasa Melayu', - dayjsImport: () => import('dayjs/locale/ms.js'), }, mt: { name: 'Maltese', nativeName: 'Malti', - dayjsImport: () => import('dayjs/locale/mt.js'), }, my: { name: 'Burmese', nativeName: 'ဗမာစာ', - dayjsImport: () => import('dayjs/locale/my.js'), }, na: { name: 'Nauru', nativeName: 'Dorerin Naoero', - dayjsImport: loadDefaultDayJsLocale, }, nb: { name: 'Norwegian Bokmål', nativeName: 'Norsk bokmål', - dayjsImport: () => import('dayjs/locale/nb.js'), }, nd: { name: 'Northern Ndebele', nativeName: 'isiNdebele', - dayjsImport: loadDefaultDayJsLocale, }, ne: { name: 'Nepali', nativeName: 'नेपाली', - dayjsImport: () => import('dayjs/locale/ne.js'), }, ng: { name: 'Ndonga', nativeName: 'Owambo', - dayjsImport: loadDefaultDayJsLocale, }, nl: { name: 'Dutch', nativeName: 'Nederlands', - dayjsImport: () => import('dayjs/locale/nl.js'), }, nn: { name: 'Norwegian Nynorsk', nativeName: 'Norsk nynorsk', - dayjsImport: () => import('dayjs/locale/nn.js'), }, no: { name: 'Norwegian', nativeName: 'Norsk', - dayjsImport: loadDefaultDayJsLocale, }, nr: { name: 'Southern Ndebele', nativeName: 'isiNdebele', - dayjsImport: loadDefaultDayJsLocale, }, nv: { name: 'Navajo', nativeName: 'Diné bizaad', - dayjsImport: loadDefaultDayJsLocale, }, ny: { name: 'Chichewa', nativeName: 'chiCheŵa', - dayjsImport: loadDefaultDayJsLocale, }, oc: { name: 'Occitan', nativeName: 'occitan', - dayjsImport: loadDefaultDayJsLocale, }, oj: { name: 'Ojibwe', nativeName: 'ᐊᓂᔑᓈᐯᒧᐎᓐ', - dayjsImport: loadDefaultDayJsLocale, }, om: { name: 'Oromo', nativeName: 'Afaan Oromoo', - dayjsImport: loadDefaultDayJsLocale, }, or: { name: 'Oriya', nativeName: 'ଓଡ଼ିଆ', - dayjsImport: loadDefaultDayJsLocale, }, os: { name: 'Ossetian', nativeName: 'ирон æвзаг', - dayjsImport: loadDefaultDayJsLocale, }, pa: { name: 'Panjabi', nativeName: 'ਪੰਜਾਬੀ', - dayjsImport: loadDefaultDayJsLocale, }, pi: { name: 'Pāli', nativeName: 'पाऴि', - dayjsImport: loadDefaultDayJsLocale, }, pl: { name: 'Polish', nativeName: 'Polski', - dayjsImport: () => import('dayjs/locale/pl.js'), }, ps: { name: 'Pashto', nativeName: 'پښتو', - dayjsImport: loadDefaultDayJsLocale, }, pt: { name: 'Portuguese', nativeName: 'Português', - dayjsImport: () => import('dayjs/locale/pt.js'), }, qu: { name: 'Quechua', nativeName: 'Runa Simi', - dayjsImport: loadDefaultDayJsLocale, // asdfasdfasdfasdf }, rm: { name: 'Romansh', nativeName: 'rumantsch grischun', - dayjsImport: () => import('dayjs/locale/cs.js'), }, rn: { name: 'Kirundi', nativeName: 'Ikirundi', - dayjsImport: () => import('dayjs/locale/cs.js'), }, ro: { name: 'Romanian', nativeName: 'Română', - dayjsImport: () => import('dayjs/locale/ro.js'), }, ru: { name: 'Russian', nativeName: 'Русский', - dayjsImport: () => import('dayjs/locale/ru.js'), }, rw: { name: 'Kinyarwanda', nativeName: 'Ikinyarwanda', - dayjsImport: () => import('dayjs/locale/rw.js'), }, sa: { name: 'Sanskrit', nativeName: 'संस्कृतम्', - dayjsImport: loadDefaultDayJsLocale, }, sc: { name: 'Sardinian', nativeName: 'sardu', - dayjsImport: loadDefaultDayJsLocale, }, sd: { name: 'Sindhi', nativeName: 'सिन्धी', - dayjsImport: () => import('dayjs/locale/sd.js'), }, se: { name: 'Northern Sami', nativeName: 'Davvisámegiella', - dayjsImport: () => import('dayjs/locale/se.js'), }, sg: { name: 'Sango', nativeName: 'yângâ tî sängö', - dayjsImport: loadDefaultDayJsLocale, }, si: { name: 'Sinhala', nativeName: 'සිංහල', - dayjsImport: () => import('dayjs/locale/si.js'), }, sk: { name: 'Slovak', nativeName: 'slovenčina', - dayjsImport: () => import('dayjs/locale/sk.js'), }, sl: { name: 'Slovenian', nativeName: 'slovenščina', - dayjsImport: () => import('dayjs/locale/sl.js'), }, sm: { name: 'Samoan', nativeName: "gagana fa'a Samoa", - dayjsImport: loadDefaultDayJsLocale, }, sn: { name: 'Shona', nativeName: 'chiShona', - dayjsImport: loadDefaultDayJsLocale, }, so: { name: 'Somali', nativeName: 'Soomaaliga', - dayjsImport: loadDefaultDayJsLocale, }, sq: { name: 'Albanian', nativeName: 'Shqip', - dayjsImport: () => import('dayjs/locale/sq.js'), }, sr: { name: 'Serbian', nativeName: 'српски језик', - dayjsImport: () => import('dayjs/locale/sr.js'), }, ss: { name: 'Swati', nativeName: 'SiSwati', - dayjsImport: () => import('dayjs/locale/ss.js'), }, st: { name: 'Southern Sotho', nativeName: 'Sesotho', - dayjsImport: loadDefaultDayJsLocale, }, su: { name: 'Sundanese', nativeName: 'Basa Sunda', - dayjsImport: loadDefaultDayJsLocale, }, sv: { name: 'Swedish', nativeName: 'Svenska', - dayjsImport: () => import('dayjs/locale/sv.js'), }, sw: { name: 'Swahili', nativeName: 'Kiswahili', - dayjsImport: () => import('dayjs/locale/sw.js'), }, ta: { name: 'Tamil', nativeName: 'தமிழ்', - dayjsImport: () => import('dayjs/locale/ta.js'), }, te: { name: 'Telugu', nativeName: 'తెలుగు', - dayjsImport: () => import('dayjs/locale/te.js'), }, tg: { name: 'Tajik', nativeName: 'тоҷикӣ', - dayjsImport: () => import('dayjs/locale/tg.js'), }, th: { name: 'Thai', nativeName: 'ไทย', - dayjsImport: () => import('dayjs/locale/th.js'), }, ti: { name: 'Tigrinya', nativeName: 'ትግርኛ', - dayjsImport: loadDefaultDayJsLocale, }, tk: { name: 'Turkmen', nativeName: 'Türkmençe', - dayjsImport: () => import('dayjs/locale/tk.js'), }, tl: { name: 'Tagalog', nativeName: 'Wikang Tagalog', - dayjsImport: loadDefaultDayJsLocale, }, tn: { name: 'Tswana', nativeName: 'Setswana', - dayjsImport: loadDefaultDayJsLocale, }, to: { name: 'Tonga', nativeName: 'faka Tonga', - dayjsImport: loadDefaultDayJsLocale, }, tr: { name: 'Turkish', nativeName: 'Türkçe', - dayjsImport: () => import('dayjs/locale/tr.js'), }, ts: { name: 'Tsonga', nativeName: 'Xitsonga', - dayjsImport: loadDefaultDayJsLocale, }, tt: { name: 'Tatar', nativeName: 'татар теле', - dayjsImport: loadDefaultDayJsLocale, }, tw: { name: 'Twi', nativeName: 'Twi', - dayjsImport: loadDefaultDayJsLocale, }, ty: { name: 'Tahitian', nativeName: 'Reo Tahiti', - dayjsImport: loadDefaultDayJsLocale, }, ug: { name: 'Uyghur', nativeName: 'ئۇيغۇرچە‎', - dayjsImport: loadDefaultDayJsLocale, }, uk: { name: 'Ukrainian', nativeName: 'Українська', - dayjsImport: () => import('dayjs/locale/uk.js'), }, ur: { name: 'Urdu', nativeName: 'اردو', - dayjsImport: () => import('dayjs/locale/ur.js'), }, uz: { name: 'Uzbek', nativeName: 'Ўзбек', - dayjsImport: () => import('dayjs/locale/uz.js'), }, ve: { name: 'Venda', nativeName: 'Tshivenḓa', - dayjsImport: loadDefaultDayJsLocale, }, vi: { name: 'Vietnamese', nativeName: 'Tiếng Việt', - dayjsImport: () => import('dayjs/locale/vi.js'), }, vo: { name: 'Volapük', nativeName: 'Volapük', - dayjsImport: loadDefaultDayJsLocale, }, wa: { name: 'Walloon', nativeName: 'walon', - dayjsImport: loadDefaultDayJsLocale, }, wo: { name: 'Wolof', nativeName: 'Wollof', - dayjsImport: loadDefaultDayJsLocale, }, xh: { name: 'Xhosa', nativeName: 'isiXhosa', - dayjsImport: loadDefaultDayJsLocale, }, yi: { name: 'Yiddish', nativeName: 'ייִדיש', - dayjsImport: loadDefaultDayJsLocale, }, yo: { name: 'Yoruba', nativeName: 'Yorùbá', - dayjsImport: () => import('dayjs/locale/yo.js'), }, za: { name: 'Zhuang', nativeName: 'Saɯ cueŋƅ', - dayjsImport: loadDefaultDayJsLocale, }, zh: { name: 'Chinese', nativeName: '中文', - dayjsImport: () => import('dayjs/locale/zh.js'), }, zu: { name: 'Zulu', nativeName: 'isiZulu', - dayjsImport: loadDefaultDayJsLocale, }, }; diff --git a/src/util/language.tsx b/src/util/language.tsx index 841bc676..0c30456e 100644 --- a/src/util/language.tsx +++ b/src/util/language.tsx @@ -7,7 +7,7 @@ */ import { t } from 'i18next'; -import { ISOLanguage, ISOLanguages, loadDefaultDayJsLocale } from '@/util/isoLanguages.ts'; +import { ISOLanguage, ISOLanguages } from '@/util/isoLanguages.ts'; export enum DefaultLanguage { ALL = 'all', @@ -78,20 +78,3 @@ export const langSortCmp = (a: string, b: string) => { return aLang > bLang ? 1 : -1; }; - -export const loadDayJsLocale = async (locale: string) => { - const lang = getISOLanguage(locale); - - try { - if (!lang) { - await loadDefaultDayJsLocale(); - return false; - } - - await lang.dayjsImport(); - return true; - } catch (e) { - return false; - // ignore - dayjs falls back to en anyway - } -}; diff --git a/tools/scripts/generateDayJsLocales.ts b/tools/scripts/generateDayJsLocales.ts new file mode 100644 index 00000000..fccffbc3 --- /dev/null +++ b/tools/scripts/generateDayJsLocales.ts @@ -0,0 +1,28 @@ +/* + * Copyright (C) Contributors to the Suwayomi project + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + */ + +import path from 'path'; +import fs from 'fs'; + +const outputFilePath = path.join(__dirname, '../../src/lib/dayjs/Locales.ts'); +const resourcesDirPath = path.join(__dirname, '../../node_modules/dayjs/locale'); + +const dayjsLocaleFileNames = fs.readdirSync(resourcesDirPath); + +const dayjsLocales = dayjsLocaleFileNames + .filter((dayjsLocaleFileName) => dayjsLocaleFileName.endsWith('.js')) + .map((dayjsLocaleFileName) => path.basename(dayjsLocaleFileName, path.extname(dayjsLocaleFileName))); + +const outputFileContent = fs.readFileSync(outputFilePath, 'utf-8'); + +const updatedFileContent = outputFileContent.replace( + /(export const DAYJS_LOCALES = \[)[\s\S]*?(])/g, + `$1'${dayjsLocales.join("', '")}'$2`, +); + +fs.writeFileSync(outputFilePath, updatedFileContent); diff --git a/tools/scripts/generateDayJsLocalesImport.ts b/tools/scripts/generateDayJsLocalesImport.ts new file mode 100644 index 00000000..7e38f0d6 --- /dev/null +++ b/tools/scripts/generateDayJsLocalesImport.ts @@ -0,0 +1,31 @@ +/* + * Copyright (C) Contributors to the Suwayomi project + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + */ + +import path from 'path'; +import fs from 'fs'; + +const outputFilePath = path.join(__dirname, '../../src/lib/dayjs/LocaleImporter.ts'); +const resourcesDirPath = path.join(__dirname, '../../node_modules/dayjs/locale'); + +const dayjsLocaleFileNames = fs.readdirSync(resourcesDirPath); + +const dayjsLocaleToFileName = dayjsLocaleFileNames + .filter((dayjsLocaleFileName) => dayjsLocaleFileName.endsWith('.js')) + .map((dayjsLocaleFileName) => [ + path.basename(dayjsLocaleFileName, path.extname(dayjsLocaleFileName)), + dayjsLocaleFileName, + ]); + +const outputFileContent = fs.readFileSync(outputFilePath, 'utf-8'); + +const updatedFileContent = outputFileContent.replace( + /(const localesToImport: Record<\(typeof DAYJS_LOCALES\)\[number], \(\) => Promise> = \{)[\s\S]*?(})/g, + `$1${dayjsLocaleToFileName.map(([locale, fileName]) => `'${locale}': () => import('dayjs/locale/${fileName}')`).join(',')}$2`, +); + +fs.writeFileSync(outputFilePath, updatedFileContent);