fix(i18n): 统一使用 useLazyTranslation 避免翻译 key 闪烁
This commit is contained in:
@@ -4,7 +4,7 @@ import ImageIcon from '@mui/icons-material/Image';
|
|||||||
import ClearIcon from '@mui/icons-material/Clear';
|
import ClearIcon from '@mui/icons-material/Clear';
|
||||||
import { qrCodePageStyles } from '@/config/pageTheme';
|
import { qrCodePageStyles } from '@/config/pageTheme';
|
||||||
import { useSnackbar } from '@/components/GlobalSnackbar';
|
import { useSnackbar } from '@/components/GlobalSnackbar';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useLazyTranslation } from '@/utils/useLazyTranslation';
|
||||||
|
|
||||||
interface ImageUploaderProps {
|
interface ImageUploaderProps {
|
||||||
/** 选中的文件 */
|
/** 选中的文件 */
|
||||||
@@ -32,7 +32,7 @@ const ImageUploader = ({
|
|||||||
dragging,
|
dragging,
|
||||||
onDraggingChange,
|
onDraggingChange,
|
||||||
}: ImageUploaderProps) => {
|
}: ImageUploaderProps) => {
|
||||||
const { t } = useTranslation(['qrCode']);
|
const { t } = useLazyTranslation('qrCode');
|
||||||
const { showMessage } = useSnackbar();
|
const { showMessage } = useSnackbar();
|
||||||
const fileInputRef = useRef<HTMLInputElement>(null);
|
const fileInputRef = useRef<HTMLInputElement>(null);
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import { Box, Button, Typography } from '@mui/material';
|
|||||||
import DownloadIcon from '@mui/icons-material/Download';
|
import DownloadIcon from '@mui/icons-material/Download';
|
||||||
import ContentCopyIcon from '@mui/icons-material/ContentCopy';
|
import ContentCopyIcon from '@mui/icons-material/ContentCopy';
|
||||||
import { qrCodePageStyles } from '@/config/pageTheme';
|
import { qrCodePageStyles } from '@/config/pageTheme';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useLazyTranslation } from '@/utils/useLazyTranslation';
|
||||||
|
|
||||||
interface QrCodePreviewProps {
|
interface QrCodePreviewProps {
|
||||||
/** 二维码 Data URL */
|
/** 二维码 Data URL */
|
||||||
@@ -14,7 +14,7 @@ interface QrCodePreviewProps {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const QrCodePreview = ({ qrCodeDataUrl, onDownload, onCopy }: QrCodePreviewProps) => {
|
const QrCodePreview = ({ qrCodeDataUrl, onDownload, onCopy }: QrCodePreviewProps) => {
|
||||||
const { t } = useTranslation(['qrCode']);
|
const { t } = useLazyTranslation('qrCode');
|
||||||
|
|
||||||
if (!qrCodeDataUrl) {
|
if (!qrCodeDataUrl) {
|
||||||
return (
|
return (
|
||||||
|
|||||||
@@ -2,6 +2,24 @@ import { describe, it, expect, vi } from 'vitest';
|
|||||||
import { render, screen, fireEvent } from '@testing-library/react';
|
import { render, screen, fireEvent } from '@testing-library/react';
|
||||||
import Base64ConverterPage from '../index';
|
import Base64ConverterPage from '../index';
|
||||||
|
|
||||||
|
// Mock useLazyTranslation
|
||||||
|
vi.mock('@/utils/useLazyTranslation', () => ({
|
||||||
|
useLazyTranslation: () => ({
|
||||||
|
t: (key: string) => key,
|
||||||
|
i18n: { changeLanguage: vi.fn(), language: 'zh-CN' },
|
||||||
|
isLoaded: true,
|
||||||
|
}),
|
||||||
|
}));
|
||||||
|
|
||||||
|
// Mock getEntryPointType
|
||||||
|
vi.mock('@/config/features', async (importOriginal) => {
|
||||||
|
const actual = await importOriginal<typeof import('@/config/features')>();
|
||||||
|
return {
|
||||||
|
...actual,
|
||||||
|
getEntryPointType: () => 'sidepanel',
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
// Mock 子组件
|
// Mock 子组件
|
||||||
vi.mock('../TextMode', () => ({
|
vi.mock('../TextMode', () => ({
|
||||||
default: () => <div data-testid="text-mode">TextMode</div>,
|
default: () => <div data-testid="text-mode">TextMode</div>,
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { Box, IconButton, Typography } from '@mui/material';
|
import { Box, IconButton, Typography } from '@mui/material';
|
||||||
import NavigateBeforeIcon from '@mui/icons-material/NavigateBefore';
|
import NavigateBeforeIcon from '@mui/icons-material/NavigateBefore';
|
||||||
import NavigateNextIcon from '@mui/icons-material/NavigateNext';
|
import NavigateNextIcon from '@mui/icons-material/NavigateNext';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useLazyTranslation } from '@/utils/useLazyTranslation';
|
||||||
import { jsonDiffPageStyles } from '@/config/pageTheme';
|
import { jsonDiffPageStyles } from '@/config/pageTheme';
|
||||||
|
|
||||||
interface DiffNavigatorProps {
|
interface DiffNavigatorProps {
|
||||||
@@ -13,7 +13,7 @@ interface DiffNavigatorProps {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export default function DiffNavigator({ total, currentIndex, onPrev, onNext }: DiffNavigatorProps) {
|
export default function DiffNavigator({ total, currentIndex, onPrev, onNext }: DiffNavigatorProps) {
|
||||||
const { t } = useTranslation(['jsonDiff']);
|
const { t } = useLazyTranslation('jsonDiff');
|
||||||
|
|
||||||
if (total === 0) {
|
if (total === 0) {
|
||||||
return (
|
return (
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { Box, Stack, Typography, useTheme } from '@mui/material';
|
import { Box, Stack, Typography, useTheme } from '@mui/material';
|
||||||
import type { Theme } from '@mui/material/styles';
|
import type { Theme } from '@mui/material/styles';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useLazyTranslation } from '@/utils/useLazyTranslation';
|
||||||
import { jsonDiffPageStyles, surfaceTint } from '@/config/pageTheme';
|
import { jsonDiffPageStyles, surfaceTint } from '@/config/pageTheme';
|
||||||
import JsonTree from './JsonTree';
|
import JsonTree from './JsonTree';
|
||||||
import type { DiffNode, DiffResult as DiffResultType, DiffType, ViewMode } from './types';
|
import type { DiffNode, DiffResult as DiffResultType, DiffType, ViewMode } from './types';
|
||||||
@@ -12,7 +12,7 @@ interface DiffResultProps {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export default function DiffResult({ result, viewMode, activePath }: DiffResultProps) {
|
export default function DiffResult({ result, viewMode, activePath }: DiffResultProps) {
|
||||||
const { t } = useTranslation(['jsonDiff']);
|
const { t } = useLazyTranslation('jsonDiff');
|
||||||
|
|
||||||
if (viewMode === 'sideBySide') {
|
if (viewMode === 'sideBySide') {
|
||||||
return (
|
return (
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { useEffect, useMemo, useState } from 'react';
|
import { useEffect, useMemo, useState } from 'react';
|
||||||
import { Box, Button, Stack, Typography } from '@mui/material';
|
import { Box, Button, Stack, Typography } from '@mui/material';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useLazyTranslation } from '@/utils/useLazyTranslation';
|
||||||
import { formatByteSize } from '@/utils/textStatistics';
|
import { formatByteSize } from '@/utils/textStatistics';
|
||||||
import { useSnackbar } from '@/components/GlobalSnackbar';
|
import { useSnackbar } from '@/components/GlobalSnackbar';
|
||||||
import CopyButton from '@/components/CopyButton';
|
import CopyButton from '@/components/CopyButton';
|
||||||
@@ -43,7 +43,7 @@ export default function JsonConvertSection({
|
|||||||
convertFunction,
|
convertFunction,
|
||||||
convertButtonKey = 'convertButton',
|
convertButtonKey = 'convertButton',
|
||||||
}: JsonConvertSectionProps) {
|
}: JsonConvertSectionProps) {
|
||||||
const { t } = useTranslation(['jsonFormat']);
|
const { t } = useLazyTranslation('jsonFormat');
|
||||||
const { showMessage } = useSnackbar();
|
const { showMessage } = useSnackbar();
|
||||||
|
|
||||||
const [input, setInput] = useState('');
|
const [input, setInput] = useState('');
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ import {
|
|||||||
TextField,
|
TextField,
|
||||||
Typography,
|
Typography,
|
||||||
} from '@mui/material';
|
} from '@mui/material';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useLazyTranslation } from '@/utils/useLazyTranslation';
|
||||||
import {
|
import {
|
||||||
formatJson,
|
formatJson,
|
||||||
validateJson,
|
validateJson,
|
||||||
@@ -32,7 +32,7 @@ const INDENT_OPTIONS = [2, 4, 6, 8] as const;
|
|||||||
* 支持一键复制格式化后的 JSON。
|
* 支持一键复制格式化后的 JSON。
|
||||||
*/
|
*/
|
||||||
export default function JsonFormatSection() {
|
export default function JsonFormatSection() {
|
||||||
const { t } = useTranslation(['jsonFormat']);
|
const { t } = useLazyTranslation('jsonFormat');
|
||||||
const { showMessage } = useSnackbar();
|
const { showMessage } = useSnackbar();
|
||||||
|
|
||||||
const [input, setInput] = useState('');
|
const [input, setInput] = useState('');
|
||||||
|
|||||||
@@ -2,6 +2,24 @@ import { describe, it, expect, vi } from 'vitest';
|
|||||||
import { render, screen, fireEvent } from '@testing-library/react';
|
import { render, screen, fireEvent } from '@testing-library/react';
|
||||||
import QrCodePage from '../index';
|
import QrCodePage from '../index';
|
||||||
|
|
||||||
|
// Mock useLazyTranslation
|
||||||
|
vi.mock('@/utils/useLazyTranslation', () => ({
|
||||||
|
useLazyTranslation: () => ({
|
||||||
|
t: (key: string) => key,
|
||||||
|
i18n: { changeLanguage: vi.fn(), language: 'zh-CN' },
|
||||||
|
isLoaded: true,
|
||||||
|
}),
|
||||||
|
}));
|
||||||
|
|
||||||
|
// Mock getEntryPointType
|
||||||
|
vi.mock('@/config/features', async (importOriginal) => {
|
||||||
|
const actual = await importOriginal<typeof import('@/config/features')>();
|
||||||
|
return {
|
||||||
|
...actual,
|
||||||
|
getEntryPointType: () => 'sidepanel',
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
// Mock 子组件
|
// Mock 子组件
|
||||||
vi.mock('@/components/QrCodePreview', () => ({
|
vi.mock('@/components/QrCodePreview', () => ({
|
||||||
default: () => <div data-testid="qr-code-preview">QrCodePreview</div>,
|
default: () => <div data-testid="qr-code-preview">QrCodePreview</div>,
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { Box, Switch, Typography } from '@mui/material';
|
import { Box, Switch, Typography } from '@mui/material';
|
||||||
import { storageCleanerPageStyles } from '@/config/pageTheme';
|
import { storageCleanerPageStyles } from '@/config/pageTheme';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useLazyTranslation } from '@/utils/useLazyTranslation';
|
||||||
|
|
||||||
interface AutoRefreshToggleProps {
|
interface AutoRefreshToggleProps {
|
||||||
autoRefresh: boolean;
|
autoRefresh: boolean;
|
||||||
@@ -8,7 +8,7 @@ interface AutoRefreshToggleProps {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export default function AutoRefreshToggle({ autoRefresh, onChange }: AutoRefreshToggleProps) {
|
export default function AutoRefreshToggle({ autoRefresh, onChange }: AutoRefreshToggleProps) {
|
||||||
const { t } = useTranslation(['storageCleaner']);
|
const { t } = useLazyTranslation('storageCleaner');
|
||||||
return (
|
return (
|
||||||
<Box sx={storageCleanerPageStyles.AUTO_REFRESH_CONTAINER}>
|
<Box sx={storageCleanerPageStyles.AUTO_REFRESH_CONTAINER}>
|
||||||
<Typography variant="body2" fontWeight={700} sx={{ fontSize: '0.8rem', px: 1.2 }}>
|
<Typography variant="body2" fontWeight={700} sx={{ fontSize: '0.8rem', px: 1.2 }}>
|
||||||
|
|||||||
@@ -2,14 +2,14 @@ import { Alert, Box } from '@mui/material';
|
|||||||
import type { CleaningResult } from '@/types/storage';
|
import type { CleaningResult } from '@/types/storage';
|
||||||
import { formatCleaningResult } from '@/utils/storageCleaner';
|
import { formatCleaningResult } from '@/utils/storageCleaner';
|
||||||
import { storageCleanerPageStyles } from '@/config/pageTheme';
|
import { storageCleanerPageStyles } from '@/config/pageTheme';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useLazyTranslation } from '@/utils/useLazyTranslation';
|
||||||
|
|
||||||
interface CleaningResultProps {
|
interface CleaningResultProps {
|
||||||
result: CleaningResult | null;
|
result: CleaningResult | null;
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function CleaningResult({ result }: CleaningResultProps) {
|
export default function CleaningResult({ result }: CleaningResultProps) {
|
||||||
const { t } = useTranslation(['storageCleaner']);
|
const { t } = useLazyTranslation('storageCleaner');
|
||||||
if (!result) return null;
|
if (!result) return null;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import StorageIcon from '@mui/icons-material/Storage';
|
|||||||
import PageHeader from '@/components/PageHeader';
|
import PageHeader from '@/components/PageHeader';
|
||||||
import { formatSize } from '@/utils/storageCleaner';
|
import { formatSize } from '@/utils/storageCleaner';
|
||||||
import { storageCleanerPageStyles } from '@/config/pageTheme';
|
import { storageCleanerPageStyles } from '@/config/pageTheme';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useLazyTranslation } from '@/utils/useLazyTranslation';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* DomainHeader 组件属性接口
|
* DomainHeader 组件属性接口
|
||||||
@@ -29,7 +29,7 @@ interface DomainHeaderProps {
|
|||||||
* ```
|
* ```
|
||||||
*/
|
*/
|
||||||
export default function DomainHeader({ domain, totalSize }: DomainHeaderProps) {
|
export default function DomainHeader({ domain, totalSize }: DomainHeaderProps) {
|
||||||
const { t } = useTranslation(['storageCleaner']);
|
const { t } = useLazyTranslation('storageCleaner');
|
||||||
return (
|
return (
|
||||||
<PageHeader
|
<PageHeader
|
||||||
icon={<StorageIcon sx={{ fontSize: 22 }} />}
|
icon={<StorageIcon sx={{ fontSize: 22 }} />}
|
||||||
|
|||||||
@@ -1,14 +1,14 @@
|
|||||||
import { Box, Container, Typography } from '@mui/material';
|
import { Box, Container, Typography } from '@mui/material';
|
||||||
import WarningIcon from '@mui/icons-material/Warning';
|
import WarningIcon from '@mui/icons-material/Warning';
|
||||||
import { storageCleanerPageStyles } from '@/config/pageTheme';
|
import { storageCleanerPageStyles } from '@/config/pageTheme';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useLazyTranslation } from '@/utils/useLazyTranslation';
|
||||||
|
|
||||||
interface ErrorDisplayProps {
|
interface ErrorDisplayProps {
|
||||||
error: string;
|
error: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function ErrorDisplay({ error }: ErrorDisplayProps) {
|
export default function ErrorDisplay({ error }: ErrorDisplayProps) {
|
||||||
const { t } = useTranslation(['storageCleaner']);
|
const { t } = useLazyTranslation('storageCleaner');
|
||||||
return (
|
return (
|
||||||
<Container sx={storageCleanerPageStyles.ERROR_DISPLAY_CONTAINER}>
|
<Container sx={storageCleanerPageStyles.ERROR_DISPLAY_CONTAINER}>
|
||||||
<Box sx={{ width: '100%', maxWidth: 320 }}>
|
<Box sx={{ width: '100%', maxWidth: 320 }}>
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { Box, Checkbox, Typography } from '@mui/material';
|
import { Box, Checkbox, Typography } from '@mui/material';
|
||||||
import { formatSize } from '@/utils/storageCleaner';
|
import { formatSize } from '@/utils/storageCleaner';
|
||||||
import { storageCleanerPageStyles } from '@/config/pageTheme';
|
import { storageCleanerPageStyles } from '@/config/pageTheme';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useLazyTranslation } from '@/utils/useLazyTranslation';
|
||||||
|
|
||||||
interface OptionItemProps {
|
interface OptionItemProps {
|
||||||
labelKey: string;
|
labelKey: string;
|
||||||
@@ -18,7 +18,7 @@ export default function OptionItem({
|
|||||||
isCount = false,
|
isCount = false,
|
||||||
onChange,
|
onChange,
|
||||||
}: OptionItemProps) {
|
}: OptionItemProps) {
|
||||||
const { t } = useTranslation(['storageCleaner']);
|
const { t } = useLazyTranslation('storageCleaner');
|
||||||
return (
|
return (
|
||||||
<Box sx={storageCleanerPageStyles.OPTION_ITEM(checked)}>
|
<Box sx={storageCleanerPageStyles.OPTION_ITEM(checked)}>
|
||||||
<Box sx={{ flex: 1, minWidth: 0, mr: 1.5 }}>
|
<Box sx={{ flex: 1, minWidth: 0, mr: 1.5 }}>
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ import {
|
|||||||
import type { StorageCleanerOptions } from '@/types/storage';
|
import type { StorageCleanerOptions } from '@/types/storage';
|
||||||
import Button from '@/components/Button';
|
import Button from '@/components/Button';
|
||||||
import { storageCleanerPageStyles } from '@/config/pageTheme';
|
import { storageCleanerPageStyles } from '@/config/pageTheme';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useLazyTranslation } from '@/utils/useLazyTranslation';
|
||||||
|
|
||||||
export interface StorageCleanerConfirmProps {
|
export interface StorageCleanerConfirmProps {
|
||||||
open: boolean;
|
open: boolean;
|
||||||
@@ -25,7 +25,7 @@ export function StorageCleanerConfirm({
|
|||||||
onConfirm,
|
onConfirm,
|
||||||
options,
|
options,
|
||||||
}: StorageCleanerConfirmProps) {
|
}: StorageCleanerConfirmProps) {
|
||||||
const { t } = useTranslation(['storageCleaner']);
|
const { t } = useLazyTranslation('storageCleaner');
|
||||||
|
|
||||||
const selectedOptions = Object.entries(options)
|
const selectedOptions = Object.entries(options)
|
||||||
.filter(([_, value]) => value)
|
.filter(([_, value]) => value)
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import { Box, Checkbox, Divider, Grid, Typography } from '@mui/material';
|
|||||||
import type { StorageCleanerOptions } from '@/types/storage';
|
import type { StorageCleanerOptions } from '@/types/storage';
|
||||||
import OptionItem from './OptionItem';
|
import OptionItem from './OptionItem';
|
||||||
import { storageCleanerPageStyles } from '@/config/pageTheme';
|
import { storageCleanerPageStyles } from '@/config/pageTheme';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useLazyTranslation } from '@/utils/useLazyTranslation';
|
||||||
|
|
||||||
interface StorageOptionsGridProps {
|
interface StorageOptionsGridProps {
|
||||||
options: StorageCleanerOptions;
|
options: StorageCleanerOptions;
|
||||||
@@ -21,7 +21,7 @@ export default function StorageOptionsGrid({
|
|||||||
onOptionChange,
|
onOptionChange,
|
||||||
onSelectAll,
|
onSelectAll,
|
||||||
}: StorageOptionsGridProps) {
|
}: StorageOptionsGridProps) {
|
||||||
const { t } = useTranslation(['storageCleaner']);
|
const { t } = useLazyTranslation('storageCleaner');
|
||||||
|
|
||||||
const optionKeys: { key: keyof StorageCleanerOptions; isCount?: boolean }[] = [
|
const optionKeys: { key: keyof StorageCleanerOptions; isCount?: boolean }[] = [
|
||||||
{ key: 'localStorage' },
|
{ key: 'localStorage' },
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ import {
|
|||||||
isRestrictedUrl,
|
isRestrictedUrl,
|
||||||
} from '@/utils/storageCleaner';
|
} from '@/utils/storageCleaner';
|
||||||
import { MessageAction, sendMessage } from '@/utils/messages';
|
import { MessageAction, sendMessage } from '@/utils/messages';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useLazyTranslation } from '@/utils/useLazyTranslation';
|
||||||
|
|
||||||
const DEFAULT_OPTIONS: StorageCleanerOptions = {
|
const DEFAULT_OPTIONS: StorageCleanerOptions = {
|
||||||
localStorage: true,
|
localStorage: true,
|
||||||
@@ -66,7 +66,7 @@ export interface UseStorageCleanerOptions {
|
|||||||
export function useStorageCleaner({
|
export function useStorageCleaner({
|
||||||
showMessage,
|
showMessage,
|
||||||
}: UseStorageCleanerOptions): UseStorageCleanerReturn {
|
}: UseStorageCleanerOptions): UseStorageCleanerReturn {
|
||||||
const { t } = useTranslation(['storageCleaner', 'common']);
|
const { t } = useLazyTranslation(['storageCleaner', 'common']);
|
||||||
const [domain, setDomain] = useState<string>('');
|
const [domain, setDomain] = useState<string>('');
|
||||||
const [error, setError] = useState<string>('');
|
const [error, setError] = useState<string>('');
|
||||||
const [isInitializing, setIsInitializing] = useState<boolean>(true);
|
const [isInitializing, setIsInitializing] = useState<boolean>(true);
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import CopyButton from '@/components/CopyButton';
|
|||||||
import { useSnackbar } from '@/components/GlobalSnackbar';
|
import { useSnackbar } from '@/components/GlobalSnackbar';
|
||||||
import type { UnitType } from '@/config/pageTheme';
|
import type { UnitType } from '@/config/pageTheme';
|
||||||
import { timestampPageStyles } from '@/config/pageTheme';
|
import { timestampPageStyles } from '@/config/pageTheme';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useLazyTranslation } from '@/utils/useLazyTranslation';
|
||||||
|
|
||||||
interface LiveClockProps {
|
interface LiveClockProps {
|
||||||
unit: UnitType;
|
unit: UnitType;
|
||||||
@@ -14,7 +14,7 @@ interface LiveClockProps {
|
|||||||
|
|
||||||
const LiveClock = React.memo(({ unit, onUseNow }: LiveClockProps) => {
|
const LiveClock = React.memo(({ unit, onUseNow }: LiveClockProps) => {
|
||||||
const [now, setNow] = useState(() => Date.now());
|
const [now, setNow] = useState(() => Date.now());
|
||||||
const { t } = useTranslation(['timestamp']);
|
const { t } = useLazyTranslation('timestamp');
|
||||||
const { showMessage } = useSnackbar();
|
const { showMessage } = useSnackbar();
|
||||||
const onUseNowRef = useRef(onUseNow);
|
const onUseNowRef = useRef(onUseNow);
|
||||||
|
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import dayjs from '@/utils/dayjs';
|
|||||||
import CopyButton from '@/components/CopyButton';
|
import CopyButton from '@/components/CopyButton';
|
||||||
import type { UnitType } from '@/config/pageTheme';
|
import type { UnitType } from '@/config/pageTheme';
|
||||||
import { DATE_FORMAT, timestampPageStyles } from '@/config/pageTheme';
|
import { DATE_FORMAT, timestampPageStyles } from '@/config/pageTheme';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useLazyTranslation } from '@/utils/useLazyTranslation';
|
||||||
|
|
||||||
interface ResultViewProps {
|
interface ResultViewProps {
|
||||||
result: string;
|
result: string;
|
||||||
@@ -17,7 +17,7 @@ interface ResultViewProps {
|
|||||||
|
|
||||||
const ResultView = React.memo(
|
const ResultView = React.memo(
|
||||||
({ result, mode, unit, zone, showEmptyPlaceholder = false }: ResultViewProps) => {
|
({ result, mode, unit, zone, showEmptyPlaceholder = false }: ResultViewProps) => {
|
||||||
const { t } = useTranslation(['timestamp']);
|
const { t } = useLazyTranslation('timestamp');
|
||||||
|
|
||||||
const extraInfo = useMemo(() => {
|
const extraInfo = useMemo(() => {
|
||||||
if (!result) return null;
|
if (!result) return null;
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import { useCallback, useState } from 'react';
|
|||||||
import dayjs from '@/utils/dayjs';
|
import dayjs from '@/utils/dayjs';
|
||||||
import type { UnitType, ZoneType } from '@/config/pageTheme';
|
import type { UnitType, ZoneType } from '@/config/pageTheme';
|
||||||
import { DATE_FORMAT } from '@/config/pageTheme';
|
import { DATE_FORMAT } from '@/config/pageTheme';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useLazyTranslation } from '@/utils/useLazyTranslation';
|
||||||
import { useContextMenuData } from '@/utils/useContextMenuData';
|
import { useContextMenuData } from '@/utils/useContextMenuData';
|
||||||
|
|
||||||
export interface UseTimestampConverterReturn {
|
export interface UseTimestampConverterReturn {
|
||||||
@@ -34,7 +34,7 @@ function isTimestampLike(input: string): boolean {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function useTimestampConverter(): UseTimestampConverterReturn {
|
export function useTimestampConverter(): UseTimestampConverterReturn {
|
||||||
const { t } = useTranslation(['timestamp']);
|
const { t } = useLazyTranslation('timestamp');
|
||||||
const [mode, setMode] = useState<'ts2dt' | 'dt2ts'>('ts2dt');
|
const [mode, setMode] = useState<'ts2dt' | 'dt2ts'>('ts2dt');
|
||||||
const [tsInput, setTsInput] = useState(() => String(Date.now()));
|
const [tsInput, setTsInput] = useState(() => String(Date.now()));
|
||||||
const [dtInput, setDtInput] = useState(() => dayjs().format(DATE_FORMAT));
|
const [dtInput, setDtInput] = useState(() => dayjs().format(DATE_FORMAT));
|
||||||
|
|||||||
Reference in New Issue
Block a user