feat: i18n for common components

This commit is contained in:
DIYgod 2023-02-23 23:00:19 +00:00
parent 3293091173
commit 1a3456e0c8
No known key found for this signature in database
13 changed files with 151 additions and 77 deletions

View File

@ -1,3 +1,7 @@
{
"intlRelativeTime": "{{val, relativetime}}"
"intlRelativeTime": "{{val, relativetime}}",
"ago": "{{time}} ago",
"joined ago": "Joined {{time}} ago",
"like stored": "Your like has been stored on the blockchain, view it on <2>Crossbell Scan</2>",
"mint stored": "This post has been minted to NFT by you, view it on <2>xChar</2> or <6>Crossbell Scan</6>"
}

View File

@ -27,5 +27,24 @@
"Create Character": "创建角色",
"Submit": "提交",
"Reply": "回复",
"Cancel Reply": "取消回复"
"Cancel Reply": "取消回复",
"ago": "{{time}}前",
"joined ago": "{{time}}前加入",
"Mint to an NFT": "铸造为 NFT",
"Like successfull": "点赞成功",
"Mint successfull": "铸造成功",
"like stored": "你的点赞已被安全地存储在区块链上,可以在 <2>Crossbell Scan</2> 上查看",
"mint stored": "你已将此篇文章铸造成NFT, 可以在 <2>xChar</2> 或 <6>Crossbell Scan</6> 上查看",
"Got it, thanks!": "好的,谢谢!",
"Like List": "点赞列表",
"Mint List": "铸造列表",
"No Content Yet.": "暂无内容",
"Close": "关闭",
"Dashboard": "仪表盘",
"Copied!": "已复制!",
"Operator Sign": "代签名",
"Switch Characters": "切换角色",
"Upgrade to Wallet": "升级为钱包",
"Disconnect": "断开连接",
"Loading": "加载中"
}

View File

@ -2,8 +2,8 @@
"Blog Free": "自由创作",
"description": "xLog给所有人的 <2>链上</2> <6>开源</6> 博客平台。",
"Get my xLog in 5 minutes": "5 分钟拥有自己的 xLog",
"Features": "特",
"Showcase": "展示",
"Features": "特",
"Showcase": "展示",
"Integration": "集成",
"Source Code": "源码",
"Visit": "访问",

View File

@ -2,7 +2,10 @@
"Home": "主页",
"Archives": "归档",
"About": "关于",
"Tags": "标签",
"load more": "还有 {{count}} 篇{{name}},点击加载更多",
"signed and stored on the blockchain": "此{{name}}已经由它的创作者签名并安全地存储在区块链上。",
"Write a comment on the blockchain": "在区块链上写下你的评论"
"Write a comment on the blockchain": "在区块链上写下你的评论",
"powered by": "由 <name/> 提供支持",
"Showcase": "展示柜"
}

View File

@ -6,6 +6,7 @@ import * as siteModel from "~/models/site.model"
import type { Profile } from "~/lib/types"
import clsx from "clsx"
import { useDate } from "~/hooks/useDate"
import { useTranslation } from "next-i18next"
export const CharacterCard: React.FC<{
siteId?: string
@ -18,6 +19,7 @@ export const CharacterCard: React.FC<{
const [firstOpen, setFirstOpen] = useState("")
const [site, setSite] = useState<Profile>()
const date = useDate()
const { t } = useTranslation("common")
useEffect(() => {
if (open && (firstOpen !== (siteId || address) || !site)) {
@ -72,21 +74,23 @@ export const CharacterCard: React.FC<{
</span>
{site?.date_created && (
<span className="block text-gray-500">
Joined{" "}
<time dateTime={date.formatToISO(site.date_created)}>
{date.dayjs
.duration(
date.dayjs(site.date_created).diff(date.dayjs(), "minute"),
"minute",
)
.humanize()}{" "}
ago
{t("joined ago", {
time: date.dayjs
.duration(
date
.dayjs(site.date_created)
.diff(date.dayjs(), "minute"),
"minute",
)
.humanize(),
})}
</time>
</span>
)}
</>
) : (
"Loading..."
<>{t("Loading")}...</>
)}
</span>
)

View File

@ -8,6 +8,7 @@ import { Avatar } from "../ui/Avatar"
import { BlockchainIcon } from "~/components/icons/BlockchainIcon"
import { getSiteLink } from "~/lib/helpers"
import { CharacterFloatCard } from "~/components/common/CharacterFloatCard"
import { useTranslation } from "next-i18next"
export const CharacterList: React.FC<{
open: boolean
@ -17,6 +18,8 @@ export const CharacterList: React.FC<{
list: any[]
title: string
}> = ({ open, setOpen, hasMore, loadMore, list, title }) => {
const { t } = useTranslation("common")
return (
<Modal open={open} setOpen={setOpen} title={title}>
<div className="px-5 overflow-auto flex-1">
@ -25,7 +28,7 @@ export const CharacterList: React.FC<{
hasMore={hasMore}
loader={
<div className="text-sm py-3 text-center" key={0}>
Loading ...
{t("Loading")} ...
</div>
}
useWindow={false}
@ -71,14 +74,14 @@ export const CharacterList: React.FC<{
))
) : (
<div className="py-3 text-center text-zinc-300">
No Content Yet.
{t("No Content Yet.")}
</div>
)}
</InfiniteScroll>
</div>
<div className="h-16 border-t flex items-center px-5 py-4">
<Button isBlock onClick={() => setOpen(false)}>
Close
{t("Close")}
</Button>
</div>
</Modal>

View File

@ -66,13 +66,14 @@ export const CommentItem: React.FC<{
</UniLink>{" "}
·{" "}
<time dateTime={date.formatToISO(comment?.createdAt)}>
{date.dayjs
.duration(
date.dayjs(comment?.createdAt).diff(date.dayjs(), "minute"),
"minute",
)
.humanize()}{" "}
ago
{t("ago", {
time: date.dayjs
.duration(
date.dayjs(comment?.createdAt).diff(date.dayjs(), "minute"),
"minute",
)
.humanize(),
})}
</time>{" "}
·{" "}
<UniLink href={`${CSB_SCAN}/tx/${comment.transactionHash}`}>

View File

@ -112,12 +112,12 @@ export const ConnectButton: React.FC<{
const dropdownLinks: HeaderLinkType[] = [
{
icon: <DashboardIcon />,
label: "Writer dashboard",
label: t("Dashboard") || "",
url: `${SITE_URL}/dashboard`,
},
{
icon: <Square2StackIcon className="w-4 h-4" />,
label: copyLabelDisplay,
label: t(copyLabelDisplay) || "",
onClick: copyLabel,
},
...(account?.type === "wallet"
@ -126,7 +126,7 @@ export const ConnectButton: React.FC<{
icon: <UsersIcon className="w-4 h-4" />,
label: (
<>
Operator Sign (
{t("Operator Sign")} (
{isOpSignEnabled ? (
<FaceSmileIcon className="w-4 h-4" />
) : (
@ -154,20 +154,20 @@ export const ConnectButton: React.FC<{
},
{
icon: <ArrowPathRoundedSquareIcon className="w-4 h-4" />,
label: "Switch Characters",
label: t("Switch Characters") || "",
onClick: selectCharactersModal.show,
},
]
: [
{
icon: <ArrowUpCircleIcon className="w-4 h-4" />,
label: "Upgrade to Wallet",
label: t("Upgrade to Wallet") || "",
onClick: upgradeAccountModal.show,
},
]),
{
icon: <ArrowRightOnRectangleIcon className="w-4 h-4" />,
label: "Disconnect",
label: t("Disconnect") || "",
onClick: disconnect,
},
]

View File

@ -21,6 +21,7 @@ import { CharacterList } from "~/components/common/CharacterList"
import clsx from "clsx"
import { Tooltip } from "~/components/ui/Tooltip"
import confetti from "canvas-confetti"
import { Trans, useTranslation } from "next-i18next"
export const Reactions: React.FC<{
className?: string
@ -29,6 +30,7 @@ export const Reactions: React.FC<{
}> = ({ className, size, pageId }) => {
const toggleLikePage = useToggleLikePage()
const mintPage = useMintPage()
const { t } = useTranslation("common")
const userSite = useAccountSites()
const [isLikeOpen, setIsLikeOpen] = useState(false)
@ -225,7 +227,7 @@ export const Reactions: React.FC<{
</Button>
)
return size !== "sm" ? (
<Tooltip label="Mint as an NFT" placement="top">
<Tooltip label={t("Mint to an NFT")} placement="top">
{inner}
</Tooltip>
) : (
@ -265,54 +267,58 @@ export const Reactions: React.FC<{
<Modal
open={isLikeOpen}
setOpen={setIsLikeOpen}
title="Like successfull"
title={t("Like successfull") || ""}
>
<div className="p-5">
Your like has been stored on the blockchain, view it on{" "}
<UniLink
className="text-accent"
href={`${CSB_SCAN}/tx/${likeStatus.transactionHash}`}
>
Crossbell Scan
</UniLink>
<Trans i18nKey="like stored">
Your like has been stored on the blockchain, view it on{" "}
<UniLink
className="text-accent"
href={`${CSB_SCAN}/tx/${likeStatus.transactionHash}`}
>
Crossbell Scan
</UniLink>
</Trans>
</div>
<div className="h-16 border-t flex items-center px-5">
<Button isBlock onClick={() => setIsLikeOpen(false)}>
Got it, thanks!
{t("Got it, thanks!")}
</Button>
</div>
</Modal>
<Modal
open={isMintOpen}
setOpen={setIsMintOpen}
title="Mint successfull"
title={t("Mint successfull") || ""}
>
<div className="p-5">
This post has been minted as NFT by you, view it on{" "}
<UniLink
className="text-accent"
href={`${CSB_XCHAR}/${userSite.data?.[0]?.username}/collections`}
>
xChar
</UniLink>{" "}
or{" "}
<UniLink
className="text-accent"
href={`${CSB_SCAN}/tx/${isMint.data?.list?.[0]?.transactionHash}`}
>
Crossbell Scan
</UniLink>
<Trans i18nKey="mint stored">
This post has been minted to NFT by you, view it on{" "}
<UniLink
className="text-accent"
href={`${CSB_XCHAR}/${userSite.data?.[0]?.username}/collections`}
>
xChar
</UniLink>{" "}
or{" "}
<UniLink
className="text-accent"
href={`${CSB_SCAN}/tx/${isMint.data?.list?.[0]?.transactionHash}`}
>
Crossbell Scan
</UniLink>
</Trans>
</div>
<div className="h-16 border-t flex items-center px-5">
<Button isBlock onClick={() => setIsMintOpen(false)}>
Got it, thanks!
{t("Got it, thanks!")}
</Button>
</div>
</Modal>
<CharacterList
open={isLikeListOpen}
setOpen={setIsLikeListOpen}
title="Like List"
title={t("Like List")}
loadMore={loadMoreLikes}
hasMore={!!likesMutation.hasNextPage}
list={likes}
@ -320,7 +326,7 @@ export const Reactions: React.FC<{
<CharacterList
open={isMintListOpen}
setOpen={setIsMintListOpen}
title="Mint List"
title={t("Mint List")}
loadMore={loadMoreMints}
hasMore={!!mintCursor}
list={mintList}

View File

@ -18,6 +18,7 @@ import {
} from "@crossbell/notification"
import { useUserRole } from "~/hooks/useUserRole"
import { useAccountState, useConnectModal } from "@crossbell/connect-kit"
import { useTranslation } from "next-i18next"
export function DashboardLayout({
children,
@ -39,6 +40,7 @@ export function DashboardLayout({
const connectModal = useConnectModal()
const [ready, setReady] = React.useState(false)
const [hasPermission, setHasPermission] = React.useState(false)
const { t } = useTranslation("common")
useEffect(() => {
if (ssrReady) {
@ -203,7 +205,7 @@ export function DashboardLayout({
)
) : (
<div className="w-screen h-screen flex justify-center items-center">
Loading...
{t("Loading")}...
</div>
)
}

View File

@ -5,6 +5,7 @@ import { Notes, Note } from "~/lib/types"
import { UniLink } from "../ui/UniLink"
import { Button } from "~/components/ui/Button"
import { useDate } from "~/hooks/useDate"
import { useTranslation } from "next-i18next"
export const SiteArchives: React.FC<{
title?: string
@ -23,6 +24,8 @@ export const SiteArchives: React.FC<{
}) => {
let currentLength = 0
const date = useDate()
const { t } = useTranslation("common")
const { t: siteT } = useTranslation("site")
const groupedByYear = useMemo<Map<string, Note[]>>(() => {
const map = new Map()
@ -39,7 +42,7 @@ export const SiteArchives: React.FC<{
}
return map
}, [postPages])
}, [postPages, date])
const tags = useMemo<Map<string, number>>(() => {
const result = new Map()
@ -67,7 +70,9 @@ export const SiteArchives: React.FC<{
return (
<>
<h2 className="text-xl font-bold page-title">{title || "Archives"}</h2>
<h2 className="text-xl font-bold page-title">
{title || siteT("Archives")}
</h2>
{!postPages[0].total && (
<div className="mt-5">
<EmptyState />
@ -77,7 +82,9 @@ export const SiteArchives: React.FC<{
<>
{showTags && tags.size > 0 && (
<div className="mt-5">
<h3 className="text-lg font-bold mb-1 text-zinc-700">Tags</h3>
<h3 className="text-lg font-bold mb-1 text-zinc-700">
{siteT("Tags")}
</h3>
<div className="pt-2">
{[...tags.keys()].map((tag) => (
<UniLink key={tag} href={`/tag/${tag}`} className="mr-6">
@ -108,7 +115,15 @@ export const SiteArchives: React.FC<{
>
<span className="text-zinc-700">{post.title}</span>
<span className="text-zinc-400 mr-3 whitespace-nowrap">
{formatDate(post.date_published, "MMM D")}
{t("intlDateTime", {
val: new Date(post.date_published),
formatParams: {
val: {
month: "short",
day: "numeric",
},
},
})}
</span>
</Link>
)

View File

@ -4,11 +4,28 @@ import { Profile, Note } from "~/lib/types"
import Script from "next/script"
import Image from "next/image"
import { Platform } from "~/components/site/Platform"
import { Trans } from "next-i18next"
export const SiteFooter: React.FC<{
site?: Profile | null
page?: Note | null
}> = ({ site, page }) => {
const LogoWithLink = () => {
return (
<UniLink
href={SITE_URL}
className="hover:text-accent inline-flex items-center align-text-top mx-1"
>
<Image
alt={APP_NAME}
src={`${SITE_URL}/assets/logo.svg`}
width={20}
height={20}
/>
</UniLink>
)
}
return (
<>
<footer className="text-zinc-500 border-t">
@ -18,18 +35,15 @@ export const SiteFooter: React.FC<{
<UniLink href="/" className="hover:text-accent">
{site?.name}
</UniLink>{" "}
· Powered by{" "}
<UniLink
href={SITE_URL}
className="hover:text-accent inline-flex items-center align-text-top ml-1"
>
<Image
alt={APP_NAME}
src={`${SITE_URL}/assets/logo.svg`}
width={20}
height={20}
/>
</UniLink>
·{" "}
<Trans
i18nKey="powered by"
defaults={"Powered by <name/>"}
components={{
name: <LogoWithLink />,
}}
ns="site"
/>
</p>
{site?.connected_accounts && (
<div className="ml-5 -mr-5">

View File

@ -8,6 +8,7 @@ import type { Asset } from "unidata.js"
import Script from "next/script"
import { UniMedia } from "~/components/ui/UniMedia"
import { UniLink } from "~/components/ui/UniLink"
import { useTranslation } from "next-i18next"
export const getServerSideProps: GetServerSideProps = async (ctx) => {
const queryClient = new QueryClient()
@ -30,6 +31,8 @@ export const getServerSideProps: GetServerSideProps = async (ctx) => {
function SiteNFTPage({ domainOrSubdomain }: { domainOrSubdomain: string }) {
const site = useGetSite(domainOrSubdomain)
const { t } = useTranslation("common")
const { t: siteT } = useTranslation("site")
const nftsOrigin = useGetNFTs(site.data?.metadata?.owner)
@ -46,10 +49,10 @@ function SiteNFTPage({ domainOrSubdomain }: { domainOrSubdomain: string }) {
type="module"
src="https://cdn.jsdelivr.net/npm/@google/model-viewer/dist/model-viewer.min.js"
></Script>
<h2 className="text-xl font-bold page-title">NFT Showcase</h2>
<h2 className="text-xl font-bold page-title">NFT {siteT("Showcase")}</h2>
<div className="mt-8">
{nftsOrigin.isLoading ? (
<div>Loading...</div>
<div>{t("Loading")}...</div>
) : (
<div className="grid grid-cols-3 md:grid-cols-4 gap-10">
{nfts