🐛 Fixed locale on Calendar + moment to dayjs

This commit is contained in:
Tagaishi
2023-08-13 21:47:50 +02:00
parent 8130504430
commit b62b6b9ee7
6 changed files with 63 additions and 69 deletions

View File

@@ -72,8 +72,6 @@
"i18next": "^22.5.1", "i18next": "^22.5.1",
"immer": "^10.0.2", "immer": "^10.0.2",
"js-file-download": "^0.4.12", "js-file-download": "^0.4.12",
"moment": "^2.29.4",
"moment-timezone": "^0.5.43",
"next": "13.4.10", "next": "13.4.10",
"next-i18next": "^13.0.0", "next-i18next": "^13.0.0",
"nzbget-api": "^0.0.3", "nzbget-api": "^0.0.3",
@@ -230,4 +228,4 @@
] ]
} }
} }
} }

View File

@@ -8,7 +8,9 @@ import { ReactQueryDevtools } from '@tanstack/react-query-devtools';
import { PersistQueryClientProvider } from '@tanstack/react-query-persist-client'; import { PersistQueryClientProvider } from '@tanstack/react-query-persist-client';
import Consola from 'consola'; import Consola from 'consola';
import { getCookie } from 'cookies-next'; import { getCookie } from 'cookies-next';
import moment from 'moment-timezone'; import dayjs from 'dayjs';
import locale from 'dayjs/plugin/localeData'
import utc from 'dayjs/plugin/utc'
import { GetServerSidePropsContext } from 'next'; import { GetServerSidePropsContext } from 'next';
import { appWithTranslation } from 'next-i18next'; import { appWithTranslation } from 'next-i18next';
import { AppProps } from 'next/app'; import { AppProps } from 'next/app';
@@ -39,6 +41,9 @@ import {
} from '../tools/server/getPackageVersion'; } from '../tools/server/getPackageVersion';
import { theme } from '../tools/server/theme/theme'; import { theme } from '../tools/server/theme/theme';
dayjs.extend(locale);
dayjs.extend(utc);
function App( function App(
this: any, this: any,
props: AppProps<{ props: AppProps<{
@@ -54,8 +59,8 @@ function App(
const { Component, pageProps } = props; const { Component, pageProps } = props;
// TODO: make mapping from our locales to moment locales // TODO: make mapping from our locales to moment locales
const language = getLanguageByCode(pageProps.locale); const language = getLanguageByCode(pageProps.locale);
require('moment/locale/' + language.momentLocale); require(`dayjs/locale/${language.locale}.js`);
moment.locale(language.momentLocale); dayjs.locale(language.locale);
const [primaryColor, setPrimaryColor] = useState<MantineTheme['primaryColor']>( const [primaryColor, setPrimaryColor] = useState<MantineTheme['primaryColor']>(
props.pageProps.config?.settings.customization.colors.primary || 'red' props.pageProps.config?.settings.customization.colors.primary || 'red'

View File

@@ -3,7 +3,7 @@ export type Language = {
originalName: string; originalName: string;
translatedName: string; translatedName: string;
emoji: string; emoji: string;
momentLocale: string; locale: string;
}; };
export const languages: Language[] = [ export const languages: Language[] = [
@@ -12,14 +12,14 @@ export const languages: Language[] = [
originalName: 'Deutsch', originalName: 'Deutsch',
translatedName: 'German', translatedName: 'German',
emoji: '🇩🇪', emoji: '🇩🇪',
momentLocale: 'de', locale: 'de',
}, },
{ {
shortName: 'en', shortName: 'en',
originalName: 'English', originalName: 'English',
translatedName: 'English', translatedName: 'English',
emoji: '🇬🇧', emoji: '🇬🇧',
momentLocale: 'en-gb', locale: 'en-gb',
}, },
// Danish // Danish
{ {
@@ -27,7 +27,7 @@ export const languages: Language[] = [
originalName: 'Dansk', originalName: 'Dansk',
translatedName: 'Danish', translatedName: 'Danish',
emoji: '🇩🇰', emoji: '🇩🇰',
momentLocale: 'da', locale: 'da',
}, },
// Hebrew // Hebrew
{ {
@@ -35,49 +35,49 @@ export const languages: Language[] = [
originalName: 'עברית', originalName: 'עברית',
translatedName: 'Hebrew', translatedName: 'Hebrew',
emoji: '🇮🇱', emoji: '🇮🇱',
momentLocale: 'he', locale: 'he',
}, },
{ {
shortName: 'es', shortName: 'es',
originalName: 'Español', originalName: 'Español',
translatedName: 'Spanish', translatedName: 'Spanish',
emoji: '🇪🇸', emoji: '🇪🇸',
momentLocale: 'es', locale: 'es',
}, },
{ {
shortName: 'fr', shortName: 'fr',
originalName: 'Français', originalName: 'Français',
translatedName: 'French', translatedName: 'French',
emoji: '🇫🇷', emoji: '🇫🇷',
momentLocale: 'fr', locale: 'fr',
}, },
{ {
shortName: 'it', shortName: 'it',
originalName: 'Italiano', originalName: 'Italiano',
translatedName: 'Italian', translatedName: 'Italian',
emoji: '🇮🇹', emoji: '🇮🇹',
momentLocale: 'it', locale: 'it',
}, },
{ {
shortName: 'ja', shortName: 'ja',
originalName: '日本語', originalName: '日本語',
translatedName: 'Japanese', translatedName: 'Japanese',
emoji: '🇯🇵', emoji: '🇯🇵',
momentLocale: 'ja', locale: 'ja',
}, },
{ {
shortName: 'ko', shortName: 'ko',
originalName: '한국어', originalName: '한국어',
translatedName: 'Korean', translatedName: 'Korean',
emoji: '🇰🇷', emoji: '🇰🇷',
momentLocale: 'ko', locale: 'ko',
}, },
{ {
shortName: 'lol', shortName: 'lol',
originalName: 'LOLCAT', originalName: 'LOLCAT',
translatedName: 'LOLCAT', translatedName: 'LOLCAT',
emoji: '🐱', emoji: '🐱',
momentLocale: 'en-gb', locale: 'en-gb',
}, },
// Norwegian // Norwegian
{ {
@@ -85,7 +85,7 @@ export const languages: Language[] = [
originalName: 'Norsk', originalName: 'Norsk',
translatedName: 'Norwegian', translatedName: 'Norwegian',
emoji: '🇳🇴', emoji: '🇳🇴',
momentLocale: 'nb', locale: 'nb',
}, },
// Slovak // Slovak
{ {
@@ -93,42 +93,42 @@ export const languages: Language[] = [
originalName: 'Slovenčina', originalName: 'Slovenčina',
translatedName: 'Slovak', translatedName: 'Slovak',
emoji: '🇸🇰', emoji: '🇸🇰',
momentLocale: 'sk', locale: 'sk',
}, },
{ {
shortName: 'nl', shortName: 'nl',
originalName: 'Nederlands', originalName: 'Nederlands',
translatedName: 'Dutch', translatedName: 'Dutch',
emoji: '🇳🇱', emoji: '🇳🇱',
momentLocale: 'nl', locale: 'nl',
}, },
{ {
shortName: 'pl', shortName: 'pl',
originalName: 'Polski', originalName: 'Polski',
translatedName: 'Polish', translatedName: 'Polish',
emoji: '🇵🇱', emoji: '🇵🇱',
momentLocale: 'pl', locale: 'pl',
}, },
{ {
shortName: 'pt', shortName: 'pt',
originalName: 'Português', originalName: 'Português',
translatedName: 'Portuguese', translatedName: 'Portuguese',
emoji: '🇵🇹', emoji: '🇵🇹',
momentLocale: 'pt', locale: 'pt',
}, },
{ {
shortName: 'ru', shortName: 'ru',
originalName: 'Русский', originalName: 'Русский',
translatedName: 'Russian', translatedName: 'Russian',
emoji: '🇷🇺', emoji: '🇷🇺',
momentLocale: 'ru', locale: 'ru',
}, },
{ {
shortName: 'sl', shortName: 'sl',
originalName: 'Slovenščina', originalName: 'Slovenščina',
translatedName: 'Slovenian', translatedName: 'Slovenian',
emoji: '🇸🇮', emoji: '🇸🇮',
momentLocale: 'sl', locale: 'sl',
}, },
{ {
@@ -136,14 +136,14 @@ export const languages: Language[] = [
originalName: 'Svenska', originalName: 'Svenska',
translatedName: 'Swedish', translatedName: 'Swedish',
emoji: '🇸🇪', emoji: '🇸🇪',
momentLocale: 'sv', locale: 'sv',
}, },
{ {
shortName: 'uk', shortName: 'uk',
originalName: 'Українська', originalName: 'Українська',
translatedName: 'Ukrainian', translatedName: 'Ukrainian',
emoji: '🇺🇦', emoji: '🇺🇦',
momentLocale: 'uk', locale: 'uk',
}, },
// Vietnamese // Vietnamese
{ {
@@ -151,42 +151,42 @@ export const languages: Language[] = [
originalName: 'Tiếng Việt', originalName: 'Tiếng Việt',
translatedName: 'Vietnamese', translatedName: 'Vietnamese',
emoji: '🇻🇳', emoji: '🇻🇳',
momentLocale: 'vi', locale: 'vi',
}, },
{ {
shortName: 'zh', shortName: 'zh',
originalName: '中文', originalName: '中文',
translatedName: 'Chinese', translatedName: 'Chinese',
emoji: '🇨🇳', emoji: '🇨🇳',
momentLocale: 'zh-cn', locale: 'zh-cn',
}, },
{ {
shortName: 'el', shortName: 'el',
originalName: 'Ελληνικά', originalName: 'Ελληνικά',
translatedName: 'Greek', translatedName: 'Greek',
emoji: '🇬🇷', emoji: '🇬🇷',
momentLocale: 'el', locale: 'el',
}, },
{ {
shortName: 'tr', shortName: 'tr',
originalName: 'Türkçe', originalName: 'Türkçe',
translatedName: 'Turkish', translatedName: 'Turkish',
emoji: '🇹🇷', emoji: '🇹🇷',
momentLocale: 'tr', locale: 'tr',
}, },
{ {
shortName: 'lv', shortName: 'lv',
originalName: 'Latvian', originalName: 'Latvian',
translatedName: 'Latvian', translatedName: 'Latvian',
emoji: '🇱🇻', emoji: '🇱🇻',
momentLocale: 'lv', locale: 'lv',
}, },
{ {
shortName: 'hr', shortName: 'hr',
originalName: 'Hrvatski', originalName: 'Hrvatski',
translatedName: 'Croatian', translatedName: 'Croatian',
emoji: '🇭🇷', emoji: '🇭🇷',
momentLocale: 'hr', locale: 'hr',
}, },
]; ];

View File

@@ -1,8 +1,9 @@
import { useMantineTheme } from '@mantine/core'; import { useMantineTheme } from '@mantine/core';
import { Calendar } from '@mantine/dates'; import { Calendar } from '@mantine/dates';
import { IconCalendarTime } from '@tabler/icons-react'; import { IconCalendarTime } from '@tabler/icons-react';
import { i18n } from 'next-i18next';
import { useState } from 'react'; import { useState } from 'react';
import { useRouter } from 'next/router';
import { getLanguageByCode } from '~/tools/language';
import { api } from '~/utils/api'; import { api } from '~/utils/api';
import { useEditModeStore } from '../../components/Dashboard/Views/useEditModeStore'; import { useEditModeStore } from '../../components/Dashboard/Views/useEditModeStore';
@@ -66,11 +67,15 @@ interface CalendarTileProps {
} }
function CalendarTile({ widget }: CalendarTileProps) { function CalendarTile({ widget }: CalendarTileProps) {
const { locale } = useRouter();
const { colorScheme, radius } = useMantineTheme(); const { colorScheme, radius } = useMantineTheme();
const { name: configName } = useConfigContext(); const { name: configName } = useConfigContext();
const [month, setMonth] = useState(new Date()); const [month, setMonth] = useState(new Date());
const isEditMode = useEditModeStore((x) => x.enabled); const isEditMode = useEditModeStore((x) => x.enabled);
const language = getLanguageByCode(locale ?? 'en');
require(`dayjs/locale/${language.locale}.js`);
const { data: medias } = api.calendar.medias.useQuery( const { data: medias } = api.calendar.medias.useQuery(
{ {
configName: configName!, configName: configName!,
@@ -90,7 +95,7 @@ function CalendarTile({ widget }: CalendarTileProps) {
onPreviousMonth={setMonth} onPreviousMonth={setMonth}
onNextMonth={setMonth} onNextMonth={setMonth}
size={widget.properties.fontSize} size={widget.properties.fontSize}
locale={i18n?.resolvedLanguage ?? 'en'} locale={language.locale}
firstDayOfWeek={widget.properties.sundayStart ? 0 : 1} firstDayOfWeek={widget.properties.sundayStart ? 0 : 1}
hideWeekdays={widget.properties.hideWeekDays} hideWeekdays={widget.properties.hideWeekDays}
style={{ position: 'relative' }} style={{ position: 'relative' }}

View File

@@ -1,16 +1,21 @@
import { Stack, Text, createStyles } from '@mantine/core'; import { Stack, Text, createStyles } from '@mantine/core';
import { useElementSize } from '@mantine/hooks'; import { useElementSize } from '@mantine/hooks';
import { IconClock } from '@tabler/icons-react'; import { IconClock } from '@tabler/icons-react';
import moment from 'moment-timezone';
import { useRouter } from 'next/router'; import { useRouter } from 'next/router';
import { useEffect, useRef, useState } from 'react'; import { useEffect, useRef, useState } from 'react';
import { getLanguageByCode } from '~/tools/language'; import { getLanguageByCode } from '~/tools/language';
import { api } from '~/utils/api'; import { api } from '~/utils/api';
import dayjs from 'dayjs';
import timezones from 'dayjs/plugin/timezone'
import utc from 'dayjs/plugin/utc'
import { useSetSafeInterval } from '../../hooks/useSetSafeInterval'; import { useSetSafeInterval } from '../../hooks/useSetSafeInterval';
import { defineWidget } from '../helper'; import { defineWidget } from '../helper';
import { IWidget } from '../widgets'; import { IWidget } from '../widgets';
dayjs.extend(utc);
dayjs.extend(timezones);
const definition = defineWidget({ const definition = defineWidget({
id: 'date', id: 'date',
icon: IconClock, icon: IconClock,
@@ -24,14 +29,14 @@ const definition = defineWidget({
defaultValue: 'dddd, MMMM D', defaultValue: 'dddd, MMMM D',
data: () => [ data: () => [
{ value: 'hide' }, { value: 'hide' },
{ value: 'dddd, MMMM D', label: moment().format('dddd, MMMM D') }, { value: 'dddd, MMMM D', label: dayjs().format('dddd, MMMM D') },
{ value: 'dddd, D MMMM', label: moment().format('dddd, D MMMM') }, { value: 'dddd, D MMMM', label: dayjs().format('dddd, D MMMM') },
{ value: 'MMM D', label: moment().format('MMM D') }, { value: 'MMM D', label: dayjs().format('MMM D') },
{ value: 'D MMM', label: moment().format('D MMM') }, { value: 'D MMM', label: dayjs().format('D MMM') },
{ value: 'DD/MM/YYYY', label: moment().format('DD/MM/YYYY') }, { value: 'DD/MM/YYYY', label: dayjs().format('DD/MM/YYYY') },
{ value: 'MM/DD/YYYY', label: moment().format('MM/DD/YYYY') }, { value: 'MM/DD/YYYY', label: dayjs().format('MM/DD/YYYY') },
{ value: 'DD/MM', label: moment().format('DD/MM') }, { value: 'DD/MM', label: dayjs().format('DD/MM') },
{ value: 'MM/DD', label: moment().format('MM/DD') }, { value: 'MM/DD', label: dayjs().format('MM/DD') },
], ],
}, },
enableTimezone: { enableTimezone: {
@@ -84,11 +89,11 @@ function DateTile({ widget }: DateTileProps) {
className={cx(classes.extras, 'dashboard-tile-clock-city')} className={cx(classes.extras, 'dashboard-tile-clock-city')}
> >
{widget.properties.timezoneLocation.name} {widget.properties.timezoneLocation.name}
{widget.properties.titleState === 'both' && moment(date).format(' (z)')} {widget.properties.titleState === 'both' && dayjs(date).format(' (z)')}
</Text> </Text>
)} )}
<Text className={cx(classes.clock, 'dashboard-tile-clock-hour')}> <Text className={cx(classes.clock, 'dashboard-tile-clock-hour')}>
{moment(date).format(formatString)} {dayjs(date).format(formatString)}
</Text> </Text>
{!widget.properties.dateFormat.includes('hide') && ( {!widget.properties.dateFormat.includes('hide') && (
<Text <Text
@@ -96,7 +101,7 @@ function DateTile({ widget }: DateTileProps) {
pt="0.2rem" pt="0.2rem"
className={cx(classes.extras, 'dashboard-tile-clock-date')} className={cx(classes.extras, 'dashboard-tile-clock-date')}
> >
{moment(date).format(widget.properties.dateFormat)} {dayjs(date).format(widget.properties.dateFormat)}
</Text> </Text>
)} )}
</Stack> </Stack>
@@ -139,7 +144,7 @@ const useDateState = (location?: { latitude: number; longitude: number }) => {
const timeoutRef = useRef<NodeJS.Timeout>(); // reference for initial timeout until first minute change const timeoutRef = useRef<NodeJS.Timeout>(); // reference for initial timeout until first minute change
useEffect(() => { useEffect(() => {
const language = getLanguageByCode(locale ?? 'en'); const language = getLanguageByCode(locale ?? 'en');
moment.locale(language.momentLocale); dayjs.locale(language.locale);
setDate(getNewDate(timezone)); setDate(getNewDate(timezone));
timeoutRef.current = setTimeout( timeoutRef.current = setTimeout(
() => { () => {
@@ -150,9 +155,8 @@ const useDateState = (location?: { latitude: number; longitude: number }) => {
}, 1000 * 60); }, 1000 * 60);
//1 minute - current seconds and milliseconds count //1 minute - current seconds and milliseconds count
}, },
1000 * 60 - (1000 * moment().seconds() + moment().milliseconds()) 1000 * 60 - (1000 * dayjs().second() + dayjs().millisecond())
); );
return () => timeoutRef.current && clearTimeout(timeoutRef.current); return () => timeoutRef.current && clearTimeout(timeoutRef.current);
}, [timezone, locale]); }, [timezone, locale]);
@@ -162,9 +166,9 @@ const useDateState = (location?: { latitude: number; longitude: number }) => {
//Returns a local date if no inputs or returns date from input zone //Returns a local date if no inputs or returns date from input zone
const getNewDate = (timezone?: string) => { const getNewDate = (timezone?: string) => {
if (timezone) { if (timezone) {
return moment().tz(timezone); return dayjs().tz(timezone);
} }
return moment(); return dayjs();
}; };
export default definition; export default definition;

View File

@@ -5935,8 +5935,6 @@ __metadata:
i18next: ^22.5.1 i18next: ^22.5.1
immer: ^10.0.2 immer: ^10.0.2
js-file-download: ^0.4.12 js-file-download: ^0.4.12
moment: ^2.29.4
moment-timezone: ^0.5.43
next: 13.4.10 next: 13.4.10
next-i18next: ^13.0.0 next-i18next: ^13.0.0
node-mocks-http: ^1.12.2 node-mocks-http: ^1.12.2
@@ -7254,22 +7252,6 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"moment-timezone@npm:^0.5.43":
version: 0.5.43
resolution: "moment-timezone@npm:0.5.43"
dependencies:
moment: ^2.29.4
checksum: 8075c897ed8a044f992ef26fe8cdbcad80caf974251db424cae157473cca03be2830de8c74d99341b76edae59f148c9d9d19c1c1d9363259085688ec1cf508d0
languageName: node
linkType: hard
"moment@npm:^2.29.4":
version: 2.29.4
resolution: "moment@npm:2.29.4"
checksum: 0ec3f9c2bcba38dc2451b1daed5daded747f17610b92427bebe1d08d48d8b7bdd8d9197500b072d14e326dd0ccf3e326b9e3d07c5895d3d49e39b6803b76e80e
languageName: node
linkType: hard
"mpd-parser@npm:^1.0.1, mpd-parser@npm:^1.1.1": "mpd-parser@npm:^1.0.1, mpd-parser@npm:^1.1.1":
version: 1.1.1 version: 1.1.1
resolution: "mpd-parser@npm:1.1.1" resolution: "mpd-parser@npm:1.1.1"