diff --git a/.eslintignore b/.eslintignore new file mode 100644 index 000000000..de4d1f007 --- /dev/null +++ b/.eslintignore @@ -0,0 +1,2 @@ +dist +node_modules diff --git a/.eslintrc.js b/.eslintrc.js index 6a41934a4..e88c2f0ee 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -1,7 +1,7 @@ module.exports = { extends: ['airbnb', 'plugin:prettier/recommended'], parser: '@typescript-eslint/parser', - plugins: ['@typescript-eslint', 'react-hooks'], + plugins: ['@typescript-eslint', 'react-hooks', 'unused-imports'], globals: { State: 'true', CustomRouter: 'true', @@ -32,16 +32,10 @@ module.exports = { }, ], 'no-unused-vars': 'off', + 'unused-imports/no-unused-imports': 'error', + 'unused-imports/no-unused-vars': 'error', 'no-undef': 'off', 'implicit-arrow-linebreak': 'off', - '@typescript-eslint/no-unused-vars': [ - 'error', - { - vars: 'local', - args: 'after-used', - ignoreRestSiblings: false, - }, - ], 'operator-linebreak': [0, 'none'], 'arrow-parens': [2, 'as-needed'], 'max-len': [ diff --git a/package.json b/package.json index de1db4932..b892a8aec 100644 --- a/package.json +++ b/package.json @@ -56,11 +56,12 @@ "eslint": "7.32.0", "eslint-config-airbnb": "18.2.1", "eslint-config-prettier": "9.0.0", - "eslint-plugin-import": "2.28.1", + "eslint-plugin-import": "^2.28.1", "eslint-plugin-jsx-a11y": "6.7.1", "eslint-plugin-prettier": "3.4.1", "eslint-plugin-react": "7.31.11", "eslint-plugin-react-hooks": "4.6.0", + "eslint-plugin-unused-imports": "^3.0.0", "husky": "^7.0.1", "jest-styled-components": "^7.0.5", "mockdate": "^2.0.5", diff --git a/src/__tests__/utils/date.test.ts b/src/__tests__/utils/date.test.ts index 65e0c9c0c..d98ea36a3 100644 --- a/src/__tests__/utils/date.test.ts +++ b/src/__tests__/utils/date.test.ts @@ -11,7 +11,6 @@ import { parseSimpleDate, parseSimpleDateNoSecond, getCurrentYear, - parseDate, getCSTTime, } from '../../utils/date' @@ -83,16 +82,6 @@ describe('Date methods tests', () => { expect(getCurrentYear()).toBe(2020) }) - it('parseDate', async () => { - MockDate.set(1588694400000, 480) - expect(parseDate(1588694380000)).toBe('20s ago') - expect(parseDate(1588691000000)).toBe('56min 40s ago') - - MockDate.reset() - timezoneMock.register('UTC') - expect(parseDate(1588651000000)).toBe('2020/05/05 03:56:40') - }) - it('getCSTTime', async () => { timezoneMock.register('UTC') expect(parseSimpleDate(1588651000000)).toBe('2020/05/05 03:56:40') diff --git a/src/assets/fonts/fonts.css b/src/assets/fonts/fonts.css index 31dd29782..a5dfb50c6 100644 --- a/src/assets/fonts/fonts.css +++ b/src/assets/fonts/fonts.css @@ -6,6 +6,6 @@ } @font-face { - font-family:'digital-clock-font'; + font-family:digital-clock-font; src: url('./digital-7.ttf'); } diff --git a/src/components/Banner/HalvingBanner.tsx b/src/components/Banner/HalvingBanner.tsx index 890a49e91..bc58cc75a 100644 --- a/src/components/Banner/HalvingBanner.tsx +++ b/src/components/Banner/HalvingBanner.tsx @@ -1,4 +1,5 @@ import classnames from 'classnames' +import { useTranslation } from 'react-i18next' import styles from './index.module.scss' import halvingBanner from '../../assets/halving_banner.png' import halvingBannerSuccess from '../../assets/halving_banner_success.png' @@ -8,7 +9,6 @@ import LoadingWhiteImage from '../../assets/loading_white.gif' import halvingSuccessAni from '../../assets/halving_success_ani.gif' import SimpleButton from '../SimpleButton' import { useCountdown, useHalving, useIsMobile } from '../../utils/hook' -import i18n from '../../utils/i18n' function numberToOrdinal(number: number) { switch (number) { @@ -36,36 +36,37 @@ export const HalvingBanner = () => { const { estimatedDate, halvingCount, inCelebration, isLoading } = useHalving() const [days, hours, minutes, seconds, expired] = useCountdown(estimatedDate) const isMobile = useIsMobile() + const [t, { language }] = useTranslation() const shortCountdown = () => { if (isLoading || Number.isNaN(seconds)) { return loading } if (days > 0) { - return `${days}${i18n.t('symbol.char_space')}${i18n.t('unit.days')}` + return `${days}${t('symbol.char_space')}${t('unit.days')}` } if (hours > 0) { - return `${hours}${i18n.t('symbol.char_space')}${i18n.t('unit.hours')}` + return `${hours}${t('symbol.char_space')}${t('unit.hours')}` } if (minutes > 0) { - return `${minutes}${i18n.t('symbol.char_space')}${i18n.t('unit.minutes')}` + return `${minutes}${t('symbol.char_space')}${t('unit.minutes')}` } - return `${seconds}${i18n.t('symbol.char_space')}${i18n.t('unit.seconds')}` + return `${seconds}${t('symbol.char_space')}${t('unit.seconds')}` } const learnMoreText = () => { if (inCelebration) { - return i18n.t('halving.learn_more') + return t('halving.learn_more') } if (expired) { - return i18n.t('halving.comming_soon') + return t('halving.comming_soon') } return ( <> - {i18n.t('halving.halving_countdown')} {shortCountdown()} + {t('halving.halving_countdown')} {shortCountdown()} ) } @@ -94,15 +95,15 @@ export const HalvingBanner = () => { {inCelebration && animation} {inCelebration ? (
- {i18n - .t('halving.banner_congratulation', { - times: i18n.t(`ordinal.${numberToOrdinal(halvingCount)}`), - }) - .toUpperCase()} + {t('halving.banner_congratulation', { + times: t(`ordinal.${numberToOrdinal(halvingCount)}`), + }).toUpperCase()}
) : (
- Nervos CKB Layer 1 {i18n.t('halving.halving')} + {`Nervos CKB ${t(`ordinal.${numberToOrdinal(halvingCount)}`)}${language === 'en' ? ' ' : ''}${t( + 'halving.halving', + )}`}
)} diff --git a/src/components/Card/HashCard/index.tsx b/src/components/Card/HashCard/index.tsx index 939b54069..d1824c1d5 100644 --- a/src/components/Card/HashCard/index.tsx +++ b/src/components/Card/HashCard/index.tsx @@ -1,10 +1,9 @@ import type { FC, ReactNode } from 'react' import { Link } from 'react-router-dom' import { Tooltip } from 'antd' +import { useTranslation } from 'react-i18next' import CopyIcon from '../../../assets/copy.png' -import i18n from '../../../utils/i18n' import { explorerService } from '../../../services/ExplorerService' -import { copyElementValue } from '../../../utils/util' import SmallLoading from '../../Loading/SmallLoading' import { useIsMobile, useNewAddr, useDeprecatedAddr } from '../../../utils/hook' import SimpleButton from '../../SimpleButton' @@ -50,8 +49,9 @@ export default ({ }) => { const isMobile = useIsMobile() const setToast = useSetToast() + const { t } = useTranslation() - const isTx = i18n.t('transaction.transaction') === title + const isTx = t('transaction.transaction') === title const newAddr = useNewAddr(hash) const deprecatedAddr = useDeprecatedAddr(hash) const counterpartAddr = newAddr === hash ? deprecatedAddr : newAddr @@ -103,8 +103,8 @@ export default ({ { - copyElementValue(document.getElementById('hashValue')) - setToast({ message: i18n.t('common.copied') }) + navigator.clipboard.writeText(hash) + setToast({ message: t('common.copied') }) }} > {!loading && copy} @@ -112,7 +112,7 @@ export default ({ {counterpartAddr ? ( ) : null} {isTx ? ( - + @@ -139,9 +139,9 @@ export default ({ {specialAddress && ( - + - {i18n.t('address.vesting')} + {t('address.vesting')} )} diff --git a/src/components/DecimalCapacity/index.tsx b/src/components/DecimalCapacity/index.tsx index 61f4ba263..623bebb48 100644 --- a/src/components/DecimalCapacity/index.tsx +++ b/src/components/DecimalCapacity/index.tsx @@ -1,4 +1,4 @@ -import i18n from '../../utils/i18n' +import { useTranslation } from 'react-i18next' import { DecimalPanel, DecimalPartPanel, DecimalZerosPanel } from './styled' export default ({ @@ -16,6 +16,7 @@ export default ({ hideZero?: boolean marginBottom?: string }) => { + const { t } = useTranslation() const integer = value.split('.')[0] || '0' let decimal = value.split('.')[1] || '' let zeros = '' @@ -41,7 +42,7 @@ export default ({ {zeros} )} - {!hideUnit &&
{i18n.t('common.ckb_unit')}
} + {!hideUnit &&
{t('common.ckb_unit')}
} ) } diff --git a/src/components/Dropdown/Language/index.tsx b/src/components/Dropdown/Language/index.tsx index b1c4e3971..93385d7d5 100644 --- a/src/components/Dropdown/Language/index.tsx +++ b/src/components/Dropdown/Language/index.tsx @@ -1,30 +1,24 @@ -import i18n, { currentLanguage, changeLanguage } from '../../../utils/i18n' +import { useLanguageText, useOtherLanguageText, useToggleLanguage } from '../../../utils/i18n' import { LanguagePanel } from './styled' import SimpleButton from '../../SimpleButton' -export const languageText = (lan: 'en' | 'zh' | null, reverse?: boolean) => { - if (reverse) { - return lan === 'zh' ? i18n.t('navbar.language_en') : i18n.t('navbar.language_zh') - } - return lan === 'en' ? i18n.t('navbar.language_en') : i18n.t('navbar.language_zh') -} - export default ({ setShow, left, top }: { setShow: Function; left: number; top: number }) => { + const toggleLanguage = useToggleLanguage() const hideDropdown = () => { setShow(false) } const handleLanguage = () => { hideDropdown() - changeLanguage(currentLanguage() === 'en' ? 'zh' : 'en') + toggleLanguage() } return ( - {languageText(currentLanguage())} + {useLanguageText()}
- {languageText(currentLanguage(), true)} + {useOtherLanguageText()} ) diff --git a/src/components/Header/LanguageComp/index.tsx b/src/components/Header/LanguageComp/index.tsx index 0db7afa8d..22fbc17f9 100644 --- a/src/components/Header/LanguageComp/index.tsx +++ b/src/components/Header/LanguageComp/index.tsx @@ -1,5 +1,4 @@ import { useState, useLayoutEffect, FC } from 'react' -import i18n, { currentLanguage, changeLanguage } from '../../../utils/i18n' import { HeaderLanguagePanel, MobileSubMenuPanel } from './styled' import SimpleButton from '../../SimpleButton' import WhiteDropdownIcon from '../../../assets/white_dropdown.png' @@ -7,7 +6,8 @@ import WhiteDropUpIcon from '../../../assets/white_drop_up.png' import BlueDropUpIcon from '../../../assets/blue_drop_up.png' import GreenDropUpIcon from '../../../assets/green_drop_up.png' import { isMainnet } from '../../../utils/chain' -import LanDropdown, { languageText } from '../../Dropdown/Language' +import LanDropdown from '../../Dropdown/Language' +import { useCurrentLanguage, useLanguageText, useOtherLanguageText, useToggleLanguage } from '../../../utils/i18n' const getDropdownIcon = (showDropdown: boolean) => { if (!showDropdown) return WhiteDropdownIcon @@ -18,6 +18,7 @@ export const LanguageDropdown = () => { const [showLanguage, setShowLanguage] = useState(false) const [languageLeft, setLanguageLeft] = useState(0) const [languageTop, setLanguageTop] = useState(0) + const currentLanguage = useCurrentLanguage() useLayoutEffect(() => { if (showLanguage) { @@ -25,12 +26,12 @@ export const LanguageDropdown = () => { if (languageDropdownComp) { const languageDropdownReact = languageDropdownComp.getBoundingClientRect() if (languageDropdownReact) { - setLanguageLeft(languageDropdownReact.left + (currentLanguage() === 'en' ? -15 : 3)) + setLanguageLeft(languageDropdownReact.left + (currentLanguage === 'en' ? -15 : 3)) setLanguageTop(languageDropdownReact.bottom - 3) } } } - }, [showLanguage]) + }, [showLanguage, currentLanguage]) return ( { }} >
-
{languageText(currentLanguage())}
+
{useLanguageText()}
dropdown icon
@@ -58,6 +59,9 @@ export const LanguageDropdown = () => { export const LanguageMenu: FC<{ hideMobileMenu: () => void }> = ({ hideMobileMenu }) => { const [showSubMenu, setShowSubMenu] = useState(false) + const currentLanguageText = useLanguageText() + const otherLanguageText = useOtherLanguageText() + const toggleLanguage = useToggleLanguage() return ( @@ -67,9 +71,7 @@ export const LanguageMenu: FC<{ hideMobileMenu: () => void }> = ({ hideMobileMen setShowSubMenu(!showSubMenu) }} > -
- {currentLanguage() === 'en' ? i18n.t('navbar.language_en') : i18n.t('navbar.language_zh')} -
+
{currentLanguageText}
mobile language icon void }> = ({ hideMobileMen hideMobileMenu() }} > - {currentLanguage() === 'en' ? i18n.t('navbar.language_en') : i18n.t('navbar.language_zh')} + {currentLanguageText} { - changeLanguage(currentLanguage() === 'en' ? 'zh' : 'en') + toggleLanguage() hideMobileMenu() }} > - {currentLanguage() === 'en' ? i18n.t('navbar.language_zh') : i18n.t('navbar.language_en')} + {otherLanguageText} )} diff --git a/src/components/Header/MenusComp/index.tsx b/src/components/Header/MenusComp/index.tsx index ca80e26f4..40bee6c88 100644 --- a/src/components/Header/MenusComp/index.tsx +++ b/src/components/Header/MenusComp/index.tsx @@ -1,7 +1,7 @@ import { Link } from 'react-router-dom' import { memo } from 'react' +import { useTranslation } from 'react-i18next' import { useIsMobile } from '../../../utils/hook' -import i18n from '../../../utils/i18n' import { MobileMenuItem, MobileMenuLink, HeaderMenuPanel } from './styled' import { isMainnet } from '../../../utils/chain' @@ -10,45 +10,48 @@ export enum LinkType { Outer, } -const menuDataList = () => [ - { - type: LinkType.Inner, - name: i18n.t('navbar.home'), - url: '/', - }, - { - type: LinkType.Inner, - name: i18n.t('navbar.nervos_dao'), - url: '/nervosdao', - }, - { - type: LinkType.Inner, - name: i18n.t('navbar.tokens'), - url: '/tokens', - }, - { - type: LinkType.Inner, - name: i18n.t('navbar.nft_collections'), - url: '/nft-collections', - }, - { - type: LinkType.Inner, - name: i18n.t('navbar.charts'), - url: '/charts', - }, - { - type: LinkType.Inner, - name: i18n.t('navbar.fee_rate'), - url: '/fee-rate-tracker', - }, - !isMainnet() - ? { - type: LinkType.Outer, - name: i18n.t('navbar.faucet'), - url: 'https://faucet.nervos.org/', - } - : {}, -] +const useMenuDataList = () => { + const { t } = useTranslation() + return [ + { + type: LinkType.Inner, + name: t('navbar.home'), + url: '/', + }, + { + type: LinkType.Inner, + name: t('navbar.nervos_dao'), + url: '/nervosdao', + }, + { + type: LinkType.Inner, + name: t('navbar.tokens'), + url: '/tokens', + }, + { + type: LinkType.Inner, + name: t('navbar.nft_collections'), + url: '/nft-collections', + }, + { + type: LinkType.Inner, + name: t('navbar.charts'), + url: '/charts', + }, + { + type: LinkType.Inner, + name: t('navbar.fee_rate'), + url: '/fee-rate-tracker', + }, + !isMainnet() + ? { + type: LinkType.Outer, + name: t('navbar.faucet'), + url: 'https://faucet.nervos.org/', + } + : {}, + ] +} const MenuItemLink = ({ menu }: { menu: any }) => { const { url, type, name } = menu @@ -59,10 +62,11 @@ const MenuItemLink = ({ menu }: { menu: any }) => { ) } -export default memo(() => - useIsMobile() ? ( +export default memo(() => { + const menuList = useMenuDataList() + return useIsMobile() ? ( - {menuDataList() + {menuList .filter(menu => menu.name !== undefined) .map(menu => ( @@ -70,7 +74,7 @@ export default memo(() => ) : ( - {menuDataList() + {menuList .filter(menu => menu.name !== undefined) .map(menu => menu.type === LinkType.Inner ? ( @@ -84,5 +88,5 @@ export default memo(() => ), )} - ), -) + ) +}) diff --git a/src/components/MaintainAlert/index.tsx b/src/components/MaintainAlert/index.tsx index 77e395e14..3cead3e90 100644 --- a/src/components/MaintainAlert/index.tsx +++ b/src/components/MaintainAlert/index.tsx @@ -1,10 +1,11 @@ -import i18n from '../../utils/i18n' +import { useTranslation } from 'react-i18next' import { IS_MAINTAINING } from '../../constants/common' import styles from './styles.module.scss' const MaintainAlert = () => { + const { t } = useTranslation() if (IS_MAINTAINING) { - return
{i18n.t('error.maintain')}
+ return
{t('error.maintain')}
} return null diff --git a/src/components/NftCollectionInventory/index.tsx b/src/components/NftCollectionInventory/index.tsx index f21baff5a..ab6747b02 100644 --- a/src/components/NftCollectionInventory/index.tsx +++ b/src/components/NftCollectionInventory/index.tsx @@ -3,9 +3,9 @@ import { Link } from 'react-router-dom' import { useQuery } from 'react-query' import { Base64 } from 'js-base64' import { hexToBytes } from '@nervosnetwork/ckb-sdk-utils' +import { useTranslation } from 'react-i18next' import { parseSporeCellData } from '../../utils/spore' import { ReactComponent as Cover } from '../../assets/nft_cover.svg' -import i18n from '../../utils/i18n' import styles from './styles.module.scss' import { getPrimaryColor } from '../../constants/common' import { explorerService } from '../../services/ExplorerService' @@ -32,6 +32,7 @@ const NftCollectionInventory: React.FC<{ collection: string isLoading: boolean }> = ({ list, collection, isLoading }) => { + const { t } = useTranslation() const { data: info } = useQuery>(['collection-info', collection], () => explorerService.api.requesterV2(`nft/collections/${collection}`), ) @@ -47,7 +48,7 @@ const NftCollectionInventory: React.FC<{ gridTemplateColumns: 'auto', }} > - {isLoading ? i18n.t('nft.loading') : i18n.t(`nft.no_record`)} + {isLoading ? t('nft.loading') : t(`nft.no_record`)}
) } @@ -107,7 +108,7 @@ const NftCollectionInventory: React.FC<{
- {i18n.t(`nft.owner`)} + {t(`nft.owner`)} {item.owner ? ( { + const { t } = useTranslation() const { isLoading, data } = useQuery>(['collection-info', id], () => explorerService.api.requesterV2(`nft/collections/${id}`), ) @@ -41,30 +42,30 @@ const NftCollectionOverview = ({ id }: { id: string }) => { ) : ( logo )} - {isLoading ? i18n.t(`nft.loading`) : info?.name} + {isLoading ? t(`nft.loading`) : info?.name}
{info?.description}
-
{i18n.t(`nft.standard`)}
+
{t(`nft.standard`)}
- {isLoading ? i18n.t(`nft.loading`) : null} - {!isLoading && info?.standard ? i18n.t(`nft.${info?.standard}`) : `-`} + {isLoading ? t(`nft.loading`) : null} + {!isLoading && info?.standard ? t(`nft.${info?.standard}`) : `-`}
- {i18n.t('nft.holder')}/{i18n.t('nft.minted')} + {t('nft.holder')}/{t('nft.minted')}
{isLoading - ? i18n.t(`nft.loading`) + ? t(`nft.loading`) : `${(info?.holders_count ?? 0).toLocaleString('en')}/${(info?.items_count ?? 0).toLocaleString('en')}`}
-
{i18n.t(`nft.minter_address`)}
+
{t(`nft.minter_address`)}
- {isLoading ? i18n.t(`nft.loading`) : null} + {isLoading ? t(`nft.loading`) : null} {!isLoading && info?.creator ? ( diff --git a/src/components/NftCollectionTransfers/index.tsx b/src/components/NftCollectionTransfers/index.tsx index 952889f79..596a4810e 100644 --- a/src/components/NftCollectionTransfers/index.tsx +++ b/src/components/NftCollectionTransfers/index.tsx @@ -5,15 +5,16 @@ import { useQuery } from 'react-query' import { Tooltip } from 'antd' import { Base64 } from 'js-base64' import { hexToBytes } from '@nervosnetwork/ckb-sdk-utils' +import { useTranslation } from 'react-i18next' import { parseSporeCellData } from '../../utils/spore' import type { TransferListRes, TransferRes } from '../../pages/NftCollectionInfo' -import i18n from '../../utils/i18n' import styles from './styles.module.scss' import { getPrimaryColor } from '../../constants/common' import { handleNftImgError, patchMibaoImg } from '../../utils/util' import { explorerService } from '../../services/ExplorerService' import { dayjs } from '../../utils/date' import { useParsedDate, useTimestamp } from '../../utils/hook' +import { useCurrentLanguage } from '../../utils/i18n' const primaryColor = getPrimaryColor() @@ -42,31 +43,32 @@ NftCollectionTransfers.displayName = 'NftTransfers' const TransferTable: FC = ({ collection, iconURL, list, isLoading }) => { const [isShowInAge, setIsShowInAge] = useState(false) - - dayjs.locale(i18n.language === 'zh' ? 'zh-cn' : 'en') + const { t } = useTranslation() + const currentLanguage = useCurrentLanguage() + dayjs.locale(currentLanguage === 'zh' ? 'zh-cn' : 'en') return ( - - - + + + - - + + @@ -83,7 +85,7 @@ const TransferTable: FC = ({ collection, iconURL, list, ) : ( )} @@ -98,6 +100,7 @@ const TransferTableRow: FC<{ iconURL?: string | null isShowInAge?: boolean }> = ({ collection, item, iconURL, isShowInAge }) => { + const { t } = useTranslation() const coverUrl = item.item.icon_url ?? iconURL const parsedBlockCreateAt = useParsedDate(item.transaction.block_timestamp) const now = useTimestamp() @@ -171,7 +174,7 @@ const TransferTableRow: FC<{ - +
{i18n.t('nft.nft')}{i18n.t('nft.tx_hash')}{i18n.t('nft.action')}{t('nft.nft')}{t('nft.tx_hash')}{t('nft.action')} setIsShowInAge(show => !show)} className={styles.age} - title={i18n.t('nft.toggle-age')} + title={t('nft.toggle-age')} style={{ color: primaryColor, }} > - {i18n.t('nft.age')} + {t('nft.age')} {i18n.t('nft.from')}{i18n.t('nft.to')}{t('nft.from')}{t('nft.to')}
- {isLoading ? i18n.t('nft.loading') : i18n.t(`nft.no_record`)} + {isLoading ? t('nft.loading') : t(`nft.no_record`)}
{i18n.t(`nft.action_type.${item.action}`)}{t(`nft.action_type.${item.action}`)} {isShowInAge ? timeRelativeBlockCreate : parsedBlockCreateAt} {item.from ? ( @@ -212,12 +215,13 @@ const TransferTableRow: FC<{ } const TransferCardGroup: FC = ({ collection, iconURL, list, isLoading }) => { + const { t } = useTranslation() return (
    {list.length ? ( list.map(item => ) ) : ( -
  • {isLoading ? i18n.t('nft.loading') : i18n.t(`nft.no_record`)}
  • +
  • {isLoading ? t('nft.loading') : t(`nft.no_record`)}
  • )}
) @@ -228,6 +232,7 @@ const TransferCard: FC<{ item: TransferRes iconURL?: string | null }> = ({ collection, item, iconURL }) => { + const { t } = useTranslation() const coverUrl = item.item.icon_url ?? iconURL const parsedBlockCreateAt = useParsedDate(item.transaction.block_timestamp) @@ -284,7 +289,7 @@ const TransferCard: FC<{
-
{i18n.t('nft.tx_hash')}
+
{t('nft.tx_hash')}
-
{i18n.t('nft.action')}
-
{i18n.t(`nft.action_type.${item.action}`)}
+
{t('nft.action')}
+
{t(`nft.action_type.${item.action}`)}
-
{i18n.t('nft.age')}
+
{t('nft.age')}
{parsedBlockCreateAt}
-
{i18n.t('nft.from')}
+
{t('nft.from')}
{item.from ? (
-
{i18n.t('nft.to')}
+
{t('nft.to')}
{item.to ? ( isLoading: boolean }> = ({ list, isLoading }) => { + const { t } = useTranslation() + return (
- + @@ -49,7 +51,7 @@ const NftHolderList: React.FC<{ ) : ( )} diff --git a/src/components/NftItemTransfers/index.tsx b/src/components/NftItemTransfers/index.tsx index ef9507df1..b5aca7fde 100644 --- a/src/components/NftItemTransfers/index.tsx +++ b/src/components/NftItemTransfers/index.tsx @@ -1,10 +1,11 @@ import { useState } from 'react' import { Link } from 'react-router-dom' import { Tooltip } from 'antd' -import i18n from '../../utils/i18n' +import { useTranslation } from 'react-i18next' import { getPrimaryColor } from '../../constants/common' -import { dayjs, parseDate } from '../../utils/date' +import { dayjs, useParseDate } from '../../utils/date' import styles from './styles.module.scss' +import { useCurrentLanguage } from '../../utils/i18n' const primaryColor = getPrimaryColor() @@ -40,30 +41,34 @@ export interface TransferListRes { } const NftItemTransfers: React.FC<{ list: TransferListRes['data']; isLoading: boolean }> = ({ list, isLoading }) => { const [isShowInAge, setIsShowInAge] = useState(false) - dayjs.locale(i18n.language === 'zh' ? 'zh-cn' : 'en') + const { t } = useTranslation() + const parseDate = useParseDate() + const currentLanguage = useCurrentLanguage() + + dayjs.locale(currentLanguage === 'zh' ? 'zh-cn' : 'en') return (
{i18n.t('nft.holder')}{t('nft.holder')} - {i18n.t('nft.quantity')} + {t('nft.quantity')}
- {isLoading ? i18n.t('nft.loading') : i18n.t(`nft.no_record`)} + {isLoading ? t('nft.loading') : t(`nft.no_record`)}
- - + + - - + + @@ -87,7 +92,7 @@ const NftItemTransfers: React.FC<{ list: TransferListRes['data']; isLoading: boo - + )} @@ -145,7 +150,7 @@ const NftItemTransfers: React.FC<{ list: TransferListRes['data']; isLoading: boo
  • -
    {i18n.t('nft.tx_hash')}
    +
    {t('nft.tx_hash')}
    -
    {i18n.t('nft.action')}
    -
    {i18n.t(`nft.action_type.${item.action}`)}
    +
    {t('nft.action')}
    +
    {t(`nft.action_type.${item.action}`)}
    -
    {i18n.t('nft.age')}
    +
    {t('nft.age')}
    {parseDate(item.transaction.block_timestamp)}
    -
    {i18n.t('nft.from')}
    +
    {t('nft.from')}
    {item.from ? (
    -
    {i18n.t('nft.to')}
    +
    {t('nft.to')}
    {item.to ? ( )) ) : ( -
  • {isLoading ? i18n.t('nft.loading') : i18n.t(`nft.no_record`)}
  • +
  • {isLoading ? t('nft.loading') : t(`nft.no_record`)}
  • )}
    diff --git a/src/components/Pagination/index.tsx b/src/components/Pagination/index.tsx index 9bd1a37ea..cb6e5ae71 100644 --- a/src/components/Pagination/index.tsx +++ b/src/components/Pagination/index.tsx @@ -1,10 +1,10 @@ import { useState } from 'react' +import { useTranslation } from 'react-i18next' import { PaginationLeftItem, PaginationRightItem, PaginationPanel } from './styled' import LeftBlack from '../../assets/pagination_black_left.png' import RightBlack from '../../assets/pagination_black_right.png' import LeftGrey from '../../assets/pagination_grey_left.png' import RightGrey from '../../assets/pagination_grey_right.png' -import i18n from '../../utils/i18n' import { useIsMobile } from '../../utils/hook' import SimpleButton from '../SimpleButton' import { HelpTip } from '../HelpTip' @@ -25,15 +25,16 @@ const Pagination = ({ annotation?: string }) => { const isMobile = useIsMobile() + const { t } = useTranslation() const [inputPage, setInputPage] = useState(gotoPage) const total = Math.max(totalPages, 1) const current = Math.min(Math.max(currentPage, 1), totalPages) - const mobilePagination = `${i18n.t('pagination.total_page')} ${total} ${i18n.t('pagination.end_page')}` - const pcPagination = `${i18n.t('pagination.current_page')} ${current} ${i18n.t( - 'pagination.of_page', - )} ${total} ${i18n.t('pagination.end_page')}` + const mobilePagination = `${t('pagination.total_page')} ${total} ${t('pagination.end_page')}` + const pcPagination = `${t('pagination.current_page')} ${current} ${t('pagination.of_page')} ${total} ${t( + 'pagination.end_page', + )}` const annotationComp = annotation ? : null @@ -48,7 +49,7 @@ const Pagination = ({ changePage(1)}> - {i18n.t('pagination.first')} + {t('pagination.first')} changePage(current - 1)}> left button @@ -71,11 +72,11 @@ const Pagination = ({ )} changePage(total)}> - {i18n.t('pagination.last')} + {t('pagination.last')} - {i18n.t('pagination.page')} + {t('pagination.page')} changePage(inputPage)}> - {i18n.t('pagination.goto')} + {t('pagination.goto')} diff --git a/src/components/Script/index.tsx b/src/components/Script/index.tsx index c36762906..89ccd07ec 100644 --- a/src/components/Script/index.tsx +++ b/src/components/Script/index.tsx @@ -1,6 +1,6 @@ import { ReactNode } from 'react' +import { useTranslation } from 'react-i18next' import { ScriptItemPanel, ScriptPanel } from './styled' -import i18n from '../../utils/i18n' import HashTag from '../HashTag' import { getContractHashTag } from '../../utils/util' import { HelpTip } from '../HelpTip' @@ -18,18 +18,20 @@ const ScriptItem = ({ title, tooltip, children }: { title: string; tooltip?: str const Script = ({ script }: { script: State.Script }) => { const contractHashTag = getContractHashTag(script) + const { t } = useTranslation() + return ( - +
    {script.codeHash} {contractHashTag && }
    - + {script.hashType} - + {script.args}
    diff --git a/src/components/Search/index.tsx b/src/components/Search/index.tsx index 01f6778d0..cdc3a39d7 100644 --- a/src/components/Search/index.tsx +++ b/src/components/Search/index.tsx @@ -1,13 +1,12 @@ -import { useState, useRef, useEffect, useMemo, FC, memo } from 'react' +import { useState, useRef, useEffect, FC, memo } from 'react' import { useHistory } from 'react-router' import { AxiosError } from 'axios' -import { useTranslation } from 'react-i18next' +import { TFunction, useTranslation } from 'react-i18next' import { SearchImage, SearchInputPanel, SearchPanel, SearchButton, SearchContainer } from './styled' import { explorerService, Response } from '../../services/ExplorerService' import SearchLogo from '../../assets/search_black.png' import ClearLogo from '../../assets/clear.png' import { addPrefixForHash, containSpecialChar } from '../../utils/string' -import i18n from '../../utils/i18n' import { HttpErrorCode, SearchFailType } from '../../constants/common' import { useIsMobile } from '../../utils/hook' import { isChainTypeError } from '../../utils/chain' @@ -28,9 +27,9 @@ const clearSearchInput = (inputElement: any) => { } } -const setSearchLoading = (inputElement: any) => { +const setSearchLoading = (inputElement: any, t: TFunction) => { const input: HTMLInputElement = inputElement.current - input.value = i18n.t('search.loading') + input.value = t('search.loading') } const setSearchContent = (inputElement: any, content: string) => { @@ -45,6 +44,7 @@ const handleSearchResult = ( inputElement: any, setSearchValue: Function, history: ReturnType, + t: TFunction, ) => { const query = searchValue.trim().replace(',', '') // remove front and end blank and ',' if (!query || containSpecialChar(query)) { @@ -56,7 +56,7 @@ const handleSearchResult = ( return } - setSearchLoading(inputElement) + setSearchLoading(inputElement, t) explorerService.api .fetchSearchResult(addPrefixForHash(query)) .then((response: any) => { @@ -103,9 +103,9 @@ const Search: FC<{ onEditEnd?: () => void }> = memo(({ content, hasButton, onEditEnd }) => { const isMobile = useIsMobile() + const { t } = useTranslation() const history = useHistory() - const [t] = useTranslation() - const SearchPlaceholder = useMemo(() => t('navbar.search_placeholder'), [t]) + const SearchPlaceholder = t('navbar.search_placeholder') const [searchValue, setSearchValue] = useState(content || '') const [placeholder, setPlaceholder] = useState(SearchPlaceholder) const inputElement = useRef(null) @@ -138,7 +138,7 @@ const Search: FC<{ const searchKeyAction = (event: any) => { if (event.keyCode === 13) { - handleSearchResult(searchValue, inputElement, setSearchValue, history) + handleSearchResult(searchValue, inputElement, setSearchValue, history, t) onEditEnd?.() } } @@ -165,11 +165,11 @@ const Search: FC<{ {hasButton && ( { - handleSearchResult(searchValue, inputElement, setSearchValue, history) + handleSearchResult(searchValue, inputElement, setSearchValue, history, t) onEditEnd?.() }} > - {i18n.t('search.search')} + {t('search.search')} )} diff --git a/src/components/Sheet/index.tsx b/src/components/Sheet/index.tsx index 0cb700946..ef24153dd 100644 --- a/src/components/Sheet/index.tsx +++ b/src/components/Sheet/index.tsx @@ -1,3 +1,4 @@ +import { useTranslation } from 'react-i18next' import { SheetPanel, SheetPointPanel, SheetItem } from './styled' import { createGlobalState, createGlobalStateSetter, useGlobalState } from '../../utils/state' @@ -8,6 +9,7 @@ export const setNetworkErrMsgs = createGlobalStateSetter(globalNetworkErrMsgs) export const setChainAlerts = createGlobalStateSetter(globalChainAlerts) const Sheet = () => { + const { t } = useTranslation() const [networkErrMsgs] = useGlobalState(globalNetworkErrMsgs) const [chainAlerts] = useGlobalState(globalChainAlerts) const messages: string[] = chainAlerts.concat(networkErrMsgs) @@ -19,7 +21,7 @@ const Sheet = () => { return ( {messages.length > 1 && ยท} - {context} + {t(context)} ) })} diff --git a/src/components/Table/index.tsx b/src/components/Table/index.tsx index 259f79c6c..67b5e31a1 100644 --- a/src/components/Table/index.tsx +++ b/src/components/Table/index.tsx @@ -1,6 +1,6 @@ import { memo, ReactNode } from 'react' import { Col, Row } from 'antd' -import i18n from '../../utils/i18n' +import { useTranslation } from 'react-i18next' import { TableTitleRowItem, TableContentRowItem, HighlightLink, TableMinerContentPanel } from './styled' import AddressText from '../AddressText' @@ -31,6 +31,7 @@ export const TableMinerContentItem = memo( textCenter?: boolean fontSize?: string }) => { + const { t } = useTranslation() return ( {content ? ( @@ -48,7 +49,7 @@ export const TableMinerContentItem = memo( ) : ( -
    {i18n.t('address.unable_decode_address')}
    +
    {t('address.unable_decode_address')}
    )}
    ) diff --git a/src/components/Text/CopyTooltipText/index.tsx b/src/components/Text/CopyTooltipText/index.tsx index 7582fc369..5e970be81 100644 --- a/src/components/Text/CopyTooltipText/index.tsx +++ b/src/components/Text/CopyTooltipText/index.tsx @@ -1,17 +1,19 @@ -import i18n from '../../../utils/i18n' +import { useTranslation } from 'react-i18next' import { copyElementValue } from '../../../utils/util' import SimpleButton from '../../SimpleButton' import { useSetToast } from '../../Toast' export default ({ content }: { content: string }) => { const setToast = useSetToast() + const { t } = useTranslation() + return ( { event.stopPropagation() copyElementValue(document.getElementById(`copy__content__${content}`)) - setToast({ message: i18n.t('common.copied') }) + setToast({ message: t('common.copied') }) event.preventDefault() }} > diff --git a/src/components/Transaction/TransactionCellArrow/index.tsx b/src/components/Transaction/TransactionCellArrow/index.tsx index 8fa6ceb26..4b5ebf3e4 100644 --- a/src/components/Transaction/TransactionCellArrow/index.tsx +++ b/src/components/Transaction/TransactionCellArrow/index.tsx @@ -1,12 +1,12 @@ import { Link } from 'react-router-dom' import { Tooltip } from 'antd' +import { useTranslation } from 'react-i18next' import { CellType } from '../../../constants/common' import RightGreenArrow from '../../../assets/right_green_arrow.png' import RightBlueArrow from '../../../assets/right_blue_arrow.png' import LiveCellIcon from '../../../assets/live_cell.png' import LiveCellBlueIcon from '../../../assets/live_cell_blue.png' import { isMainnet } from '../../../utils/chain' -import i18n from '../../../utils/i18n' import { RightArrowImage, LeftArrowImage } from './styled' const CellInputIcon = ({ cell }: { cell: State.Cell }) => @@ -21,6 +21,8 @@ const CellInputIcon = ({ cell }: { cell: State.Cell }) => ) : null const CellOutputIcon = ({ cell }: { cell: State.Cell }) => { + const { t } = useTranslation() + if (cell.status === 'dead') { return ( @@ -29,7 +31,7 @@ const CellOutputIcon = ({ cell }: { cell: State.Cell }) => { ) } return ( - + ) diff --git a/src/components/TransactionItem/TransactionIncome/index.tsx b/src/components/TransactionItem/TransactionIncome/index.tsx index edb9cdf74..f188b001c 100644 --- a/src/components/TransactionItem/TransactionIncome/index.tsx +++ b/src/components/TransactionItem/TransactionIncome/index.tsx @@ -1,6 +1,6 @@ import BigNumber from 'bignumber.js' import { Tooltip } from 'antd' -import i18n from '../../../utils/i18n' +import { useTranslation } from 'react-i18next' import { TransactionIncomePanel, TransactionCapacityValuePanel } from './styled' import { shannonToCkb } from '../../../utils/util' import { localeNumberString } from '../../../utils/number' @@ -10,6 +10,7 @@ import CurrentAddressIcon from '../../../assets/current_address.svg' export default ({ income }: { income: string }) => { const isMobile = useIsMobile() + const { t } = useTranslation() let bigIncome = new BigNumber(income) if (bigIncome.isNaN()) { bigIncome = new BigNumber(0) @@ -18,7 +19,7 @@ export default ({ income }: { income: string }) => { {isMobile && ( - + current Address )} @@ -27,7 +28,7 @@ export default ({ income }: { income: string }) => { color="inherit" /> {!isMobile && ( - + current Address )} diff --git a/src/components/TransactionItem/TransactionItemCell/index.tsx b/src/components/TransactionItem/TransactionItemCell/index.tsx index 2068789b6..6a32695d0 100644 --- a/src/components/TransactionItem/TransactionItemCell/index.tsx +++ b/src/components/TransactionItem/TransactionItemCell/index.tsx @@ -2,11 +2,12 @@ import { FC, ReactNode } from 'react' import { Link } from 'react-router-dom' import { Popover, Tooltip } from 'antd' import classNames from 'classnames' +import { useTranslation } from 'react-i18next' import NervosDAOCellIcon from '../../../assets/nervos_dao_cell.png' import NervosDAOWithdrawingIcon from '../../../assets/nervos_dao_withdrawing.png' import CurrentAddressIcon from '../../../assets/current_address.svg' import UDTTokenIcon from '../../../assets/udt_token.png' -import i18n, { currentLanguage } from '../../../utils/i18n' +import { useCurrentLanguage } from '../../../utils/i18n' import { localeNumberString, parseUDTAmount } from '../../../utils/number' import { shannonToCkb, shannonToCkbDecimal } from '../../../utils/util' import { @@ -70,10 +71,12 @@ const AddressTextWithAlias: FC<{ ) } -const udtAmount = (udt: State.UDTInfo) => - udt.published +const useUdtAmount = (udt: State.UDTInfo) => { + const { t } = useTranslation() + return udt.published ? `${parseUDTAmount(udt.amount, udt.decimal)} ${udt.uan || udt.symbol}` - : `${i18n.t('udt.unknown_token')} #${udt.typeHash.substring(udt.typeHash.length - 4)}` + : `${t('udt.unknown_token')} #${udt.typeHash.substring(udt.typeHash.length - 4)}` +} const WithdrawPopoverItem = ({ width, @@ -92,27 +95,27 @@ const WithdrawPopoverItem = ({ const WithdrawPopoverInfo = ({ cell }: { cell: State.Cell }) => { const isMobile = useIsMobile() + const { t } = useTranslation() + const currentLanguage = useCurrentLanguage() let width = 'short' - if (currentLanguage() === 'en') { + if (currentLanguage === 'en') { width = isDaoDepositCell(cell.cellType) ? 'long' : 'medium' } return (

    - {isDaoWithdrawCell(cell.cellType) - ? i18n.t('nervos_dao.withdraw_tooltip') - : i18n.t('nervos_dao.withdraw_request_tooltip')} + {isDaoWithdrawCell(cell.cellType) ? t('nervos_dao.withdraw_tooltip') : t('nervos_dao.withdraw_request_tooltip')}

    } /> { /> - {`${i18n.t('block.block')} `} + {`${t('block.block')} `} {localeNumberString(cell.compensationStartedBlockNumber)} @@ -137,17 +140,17 @@ const WithdrawPopoverInfo = ({ cell }: { cell: State.Cell }) => { /> {isDaoWithdrawCell(cell.cellType) && ( <> - {`${i18n.t('block.block')} `} + {`${t('block.block')} `} {localeNumberString(cell.compensationStartedBlockNumber)} @@ -160,7 +163,7 @@ const WithdrawPopoverInfo = ({ cell }: { cell: State.Cell }) => { /> @@ -171,6 +174,7 @@ const WithdrawPopoverInfo = ({ cell }: { cell: State.Cell }) => { const TransactionCellNervosDao = ({ cell, cellType }: { cell: State.Cell; cellType: CellType }) => { const isMobile = useIsMobile() + const { t } = useTranslation() return ( @@ -181,9 +185,7 @@ const TransactionCellNervosDao = ({ cell, cellType }: { cell: State.Cell; cellTy ) : ( { return ( - {udtAmount(extraInfo)} + {useUdtAmount(extraInfo)} { const isMobile = useIsMobile() + const { t } = useTranslation() if (cell.fromCellbase) { return } - let addressText = i18n.t('address.unable_decode_address') + let addressText = t('address.unable_decode_address') let highLight = false if (cell.addressHash) { addressText = cell.addressHash @@ -253,14 +256,14 @@ const TransactionCell = ({ cell, address, cellType }: { cell: State.Cell; addres {cellType === CellType.Output && } {!highLight && !isMobile && ( - + current Address )} {!highLight && isMobile && ( - + current Address )} diff --git a/src/components/TransactionItem/TransactionItemCellList/index.tsx b/src/components/TransactionItem/TransactionItemCellList/index.tsx index af441df2e..5d2ed3d8f 100644 --- a/src/components/TransactionItem/TransactionItemCellList/index.tsx +++ b/src/components/TransactionItem/TransactionItemCellList/index.tsx @@ -1,7 +1,7 @@ import { ReactNode } from 'react' import { Link } from 'react-router-dom' +import { useTranslation } from 'react-i18next' import TransactionCellListPanel from './styled' -import i18n from '../../../utils/i18n' const MAX_CELL_SHOW_SIZE = 10 @@ -13,13 +13,16 @@ export default ({ cells: State.Cell[] transaction: State.Transaction render: (cell: State.Cell) => ReactNode -}) => ( - - {cells && cells.map((cell, index) => index < MAX_CELL_SHOW_SIZE && render(cell))} - {cells && cells.length >= MAX_CELL_SHOW_SIZE && ( -
    - {i18n.t('common.view_all')} -
    - )} -
    -) +}) => { + const { t } = useTranslation() + return ( + + {cells && cells.map((cell, index) => index < MAX_CELL_SHOW_SIZE && render(cell))} + {cells && cells.length >= MAX_CELL_SHOW_SIZE && ( +
    + {t('common.view_all')} +
    + )} +
    + ) +} diff --git a/src/components/TransactionItem/TransactionLiteItem/index.tsx b/src/components/TransactionItem/TransactionLiteItem/index.tsx index a49f49c81..a0a8439f8 100644 --- a/src/components/TransactionItem/TransactionLiteItem/index.tsx +++ b/src/components/TransactionItem/TransactionLiteItem/index.tsx @@ -1,19 +1,20 @@ import { Link } from 'react-router-dom' +import { useTranslation } from 'react-i18next' import { localeNumberString } from '../../../utils/number' import AddressText from '../../AddressText' import styles from './index.module.scss' import TransactionLiteIncome from '../TransactionLiteIncome' -import i18n from '../../../utils/i18n' import { useIsMobile, useParsedDate } from '../../../utils/hook' const TransactionLiteItem = ({ transaction, address }: { transaction: State.Transaction; address?: string }) => { const isMobile = useIsMobile() + const { t } = useTranslation() const parsedBlockCreateAt = useParsedDate(transaction.blockTimestamp) return (
    - {isMobile &&
    {i18n.t('transaction.transaction_hash')}
    } + {isMobile &&
    {t('transaction.transaction_hash')}
    }
    - {isMobile &&
    {i18n.t('transaction.height')}
    } + {isMobile &&
    {t('transaction.height')}
    } {localeNumberString(transaction.blockNumber)}
    - {isMobile &&
    {i18n.t('transaction.time')}
    } + {isMobile &&
    {t('transaction.time')}
    } {parsedBlockCreateAt}
    - {isMobile &&
    {`${i18n.t('transaction.input')} & ${i18n.t('transaction.output')}`}
    } + {isMobile &&
    {`${t('transaction.input')} & ${t('transaction.output')}`}
    } + {transaction.displayInputs && `${t('transaction.input')}: ${transaction.displayInputs.length}`} - {transaction.displayInputs && `${i18n.t('transaction.input')}: ${transaction.displayInputs.length}`} - - - {transaction.displayOutputs && `${i18n.t('transaction.output')}: ${transaction.displayOutputs.length}`} + {transaction.displayOutputs && `${t('transaction.output')}: ${transaction.displayOutputs.length}`}
    - {isMobile &&
    {i18n.t('transaction.capacity_change')}
    } + {isMobile &&
    {t('transaction.capacity_change')}
    } {address && }
    diff --git a/src/components/TransactionItem/index.tsx b/src/components/TransactionItem/index.tsx index bebf31670..1ff620794 100644 --- a/src/components/TransactionItem/index.tsx +++ b/src/components/TransactionItem/index.tsx @@ -1,4 +1,5 @@ import { ReactNode, useEffect, useRef } from 'react' +import { useTranslation } from 'react-i18next' import RightArrowIcon from '../../assets/input_arrow_output.png' import DownArrowIcon from '../../assets/input_arrow_output_down.png' import { localeNumberString } from '../../utils/number' @@ -6,7 +7,6 @@ import TransactionCell from './TransactionItemCell' import TransactionCellList from './TransactionItemCellList' import TransactionIncome from './TransactionIncome' import { FullPanel, TransactionHashBlockPanel, TransactionCellPanel, TransactionPanel } from './styled' -import i18n from '../../utils/i18n' import { CellType } from '../../constants/common' import AddressText from '../AddressText' import { useIsLGScreen, useParsedDate } from '../../utils/hook' @@ -35,6 +35,7 @@ const TransactionItem = ({ scrollIntoViewOnMount?: boolean }) => { const isLG = useIsLGScreen() + const { t } = useTranslation() const ref = useRef(null) useEffect(() => { @@ -67,7 +68,7 @@ const TransactionItem = ({ {!isBlock && (
    - {`(${i18n.t('block.block')} ${localeNumberString(transaction.blockNumber)}) ${parsedBlockCreateAt}`} + {`(${t('block.block')} ${localeNumberString(transaction.blockNumber)}) ${parsedBlockCreateAt}`}
    )}
    @@ -93,7 +94,7 @@ const TransactionItem = ({ )} /> ) : ( -
    {i18n.t('transaction.empty_output')}
    +
    {t('transaction.empty_output')}
    )} diff --git a/src/contexts/providers/hook.ts b/src/contexts/providers/hook.ts index 3588c9ef6..24552a4a1 100644 --- a/src/contexts/providers/hook.ts +++ b/src/contexts/providers/hook.ts @@ -1,24 +1,13 @@ import { useState } from 'react' import { FLUSH_CHART_CACHE_POLLING_TIME } from '../../constants/common' -import { AppCachedKeys } from '../../constants/cache' -import { fetchCachedData } from '../../utils/cache' -import { changeLanguage } from '../../utils/i18n' import { useInterval } from '../../utils/hook' import flushCacheInfo from '../../service/app/charts/cache' -const initAppLanguage = () => { - const language = - fetchCachedData<'zh' | 'en'>(AppCachedKeys.AppLanguage) || (navigator.language.includes('zh') ? 'zh' : 'en') - changeLanguage(language) -} - export const useInitApp = () => { const [init, setInit] = useState(false) if (!init) { setInit(true) - // TODO: This function may not belong here. - initAppLanguage() flushCacheInfo() } diff --git a/src/pages/Address/AddressComp.tsx b/src/pages/Address/AddressComp.tsx index d8eadbe0a..b859c3c67 100644 --- a/src/pages/Address/AddressComp.tsx +++ b/src/pages/Address/AddressComp.tsx @@ -4,10 +4,10 @@ import { useQuery } from 'react-query' import { Radio } from 'antd' import { Base64 } from 'js-base64' import { hexToBytes } from '@nervosnetwork/ckb-sdk-utils' +import { TFunction, useTranslation } from 'react-i18next' import OverviewCard, { OverviewItemData } from '../../components/Card/OverviewCard' import TransactionItem from '../../components/TransactionItem/index' import { explorerService } from '../../services/ExplorerService' -import i18n from '../../utils/i18n' import { parseSporeCellData } from '../../utils/spore' import { localeNumberString, parseUDTAmount } from '../../utils/number' import { shannonToCkb, deprecatedAddrToNewAddr, handleNftImgError, patchMibaoImg } from '../../utils/util' @@ -47,26 +47,26 @@ import { omit } from '../../utils/object' import { CsvExport } from '../../components/CsvExport' import PaginationWithRear from '../../components/PaginationWithRear' -const addressAssetInfo = (address: State.Address, useMiniStyle: boolean) => { +const addressAssetInfo = (address: State.Address, useMiniStyle: boolean, t: TFunction) => { const items = [ { title: '', content: '', }, { - title: i18n.t('address.occupied'), - tooltip: i18n.t('glossary.occupied'), + title: t('address.occupied'), + tooltip: t('glossary.occupied'), content: , isAsset: true, }, { icon: CKBTokenIcon, - title: i18n.t('common.ckb_unit'), + title: t('common.ckb_unit'), content: , }, { - title: i18n.t('address.dao_deposit'), - tooltip: i18n.t('glossary.nervos_dao_deposit'), + title: t('address.dao_deposit'), + tooltip: t('glossary.nervos_dao_deposit'), content: , isAsset: true, }, @@ -75,9 +75,9 @@ const addressAssetInfo = (address: State.Address, useMiniStyle: boolean) => { content: '', }, { - title: i18n.t('address.compensation'), + title: t('address.compensation'), content: , - tooltip: i18n.t('glossary.nervos_dao_compensation'), + tooltip: t('glossary.nervos_dao_compensation'), isAsset: true, }, ] as OverviewItemData[] @@ -99,6 +99,7 @@ const UDT_LABEL: Record = { } const AddressUDTItem = ({ udtAccount }: { udtAccount: State.UDTAccount }) => { + const { t } = useTranslation() const { symbol, uan, amount, udtIconFile, typeHash, udtType, collection, cota } = udtAccount const isSudt = udtType === 'sudt' const isSpore = udtType === 'spore_cell' @@ -167,7 +168,7 @@ const AddressUDTItem = ({ udtAccount }: { udtAccount: State.UDTAccount }) => { return (
    - {isUnverified ? `${i18n.t('udt.unverified')}: ` : null} + {isUnverified ? `${t('udt.unverified')}: ` : null} {UDT_LABEL[udtType] ?? 'unknown'}
    @@ -210,16 +211,17 @@ const lockScriptIcon = (show: boolean) => { return isMainnet() ? ArrowDownIcon : ArrowDownBlueIcon } -const getAddressInfo = ({ liveCellsCount, minedBlocksCount, type, addressHash, lockInfo }: State.Address) => { +const useAddressInfo = ({ liveCellsCount, minedBlocksCount, type, addressHash, lockInfo }: State.Address) => { + const { t } = useTranslation() const items: OverviewItemData[] = [ { - title: i18n.t('address.live_cells'), - tooltip: i18n.t('glossary.live_cells'), + title: t('address.live_cells'), + tooltip: t('glossary.live_cells'), content: localeNumberString(liveCellsCount), }, { - title: i18n.t('address.block_mined'), - tooltip: i18n.t('glossary.block_mined'), + title: t('address.block_mined'), + tooltip: t('glossary.block_mined'), content: localeNumberString(minedBlocksCount), }, ] @@ -227,22 +229,22 @@ const getAddressInfo = ({ liveCellsCount, minedBlocksCount, type, addressHash, l if (type === 'LockHash') { if (!addressHash) { items.push({ - title: i18n.t('address.address'), - content: i18n.t('address.unable_decode_address'), + title: t('address.address'), + content: t('address.unable_decode_address'), }) } else { items.push({ - title: i18n.t('address.address'), + title: t('address.address'), contentWrapperClass: styles.addressWidthModify, content: {addressHash}, }) } } if (lockInfo && lockInfo.epochNumber !== '0' && lockInfo.estimatedUnlockTime !== '0') { - const estimate = Number(lockInfo.estimatedUnlockTime) > new Date().getTime() ? i18n.t('address.estimated') : '' + const estimate = Number(lockInfo.estimatedUnlockTime) > new Date().getTime() ? t('address.estimated') : '' items.push({ - title: i18n.t('address.lock_until'), - content: `${lockInfo.epochNumber} ${i18n.t('address.epoch')} (${estimate} ${parseSimpleDateNoSecond( + title: t('address.lock_until'), + content: `${lockInfo.epochNumber} ${t('address.epoch')} (${estimate} ${parseSimpleDateNoSecond( lockInfo.estimatedUnlockTime, )})`, }) @@ -252,12 +254,13 @@ const getAddressInfo = ({ liveCellsCount, minedBlocksCount, type, addressHash, l const AddressLockScript: FC<{ address: State.Address }> = ({ address }) => { const [showLock, setShowLock] = useState(false) + const { t } = useTranslation() return ( - + setShowLock(!showLock)}> -
    {i18n.t('address.lock_script')}
    +
    {t('address.lock_script')}
    lock script
    {showLock && address.lockScript &&
  • {i18n.t('nft.tx_hash')}{i18n.t('nft.action')}{t('nft.tx_hash')}{t('nft.action')} setIsShowInAge(show => !show)} className={styles.age} - title={i18n.t('nft.toggle-age')} + title={t('nft.toggle-age')} style={{ color: primaryColor, }} > - {i18n.t('nft.age')} + {t('nft.age')} {i18n.t('nft.from')}{i18n.t('nft.to')}{t('nft.from')}{t('nft.to')}
    {i18n.t(`nft.action_type.${item.action}`)}{t(`nft.action_type.${item.action}`)} {isShowInAge ? dayjs(item.transaction.block_timestamp).fromNow() @@ -133,7 +138,7 @@ const NftItemTransfers: React.FC<{ list: TransferListRes['data']; isLoading: boo ) : (
    - {isLoading ? i18n.t('nft.loading') : i18n.t(`nft.no_record`)} + {isLoading ? t('nft.loading') : t(`nft.no_record`)}