chore: i18n
This commit is contained in:
@@ -1,14 +1,16 @@
|
||||
import { Button } from '@renderer/components/ui/button'
|
||||
import { useSecondaryPage } from '@renderer/PageManager'
|
||||
import { ChevronLeft } from 'lucide-react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
|
||||
export default function BackButton({ hide = false }: { hide?: boolean }) {
|
||||
const { t } = useTranslation()
|
||||
const { pop } = useSecondaryPage()
|
||||
|
||||
return (
|
||||
<>
|
||||
{!hide && (
|
||||
<Button variant="titlebar" size="titlebar" title="back" onClick={() => pop()}>
|
||||
<Button variant="titlebar" size="titlebar" title={t('back')} onClick={() => pop()}>
|
||||
<ChevronLeft />
|
||||
</Button>
|
||||
)}
|
||||
|
||||
@@ -39,7 +39,7 @@ export default function Mentions({
|
||||
</PopoverTrigger>
|
||||
<PopoverContent className="w-48">
|
||||
<div className="space-y-2">
|
||||
<div className="text-sm font-semibold">Mentions:</div>
|
||||
<div className="text-sm font-semibold">{t('Mentions')}:</div>
|
||||
{pubkeys.map((pubkey, index) => (
|
||||
<div key={`${pubkey}-${index}`} className="flex gap-1 items-center">
|
||||
<UserAvatar userId={pubkey} size="small" />
|
||||
|
||||
@@ -99,7 +99,7 @@ export default function PostDialog({
|
||||
<DialogTitle>
|
||||
{parentEvent ? (
|
||||
<div className="flex gap-2 items-center max-w-full">
|
||||
<div className="shrink-0">Reply to</div>
|
||||
<div className="shrink-0">{t('Reply to')}</div>
|
||||
<UserAvatar userId={parentEvent.pubkey} size="tiny" />
|
||||
<div className="truncate">{parentEvent.content}</div>
|
||||
</div>
|
||||
@@ -131,7 +131,7 @@ export default function PostDialog({
|
||||
</Button>
|
||||
<Button type="submit" disabled={!canPost} onClick={post}>
|
||||
{posting && <LoaderCircle className="animate-spin" />}
|
||||
{t('Post')}
|
||||
{parentEvent ? t('Reply') : t('Post')}
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -12,8 +12,10 @@ import { useState } from 'react'
|
||||
import RelayUrls from './RelayUrl'
|
||||
import { useRelaySettingsComponent } from './provider'
|
||||
import { TRelayGroup } from './types'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
|
||||
export default function RelayGroup({ group }: { group: TRelayGroup }) {
|
||||
const { t } = useTranslation()
|
||||
const { expandedRelayGroup } = useRelaySettingsComponent()
|
||||
const { temporaryRelayUrls } = useRelaySettings()
|
||||
const { groupName, relayUrls } = group
|
||||
@@ -34,7 +36,7 @@ export default function RelayGroup({ group }: { group: TRelayGroup }) {
|
||||
</div>
|
||||
<div className="flex gap-1">
|
||||
<RelayUrlsExpandToggle groupName={groupName}>
|
||||
{relayUrls.length} relays
|
||||
{t('n relays', { n: relayUrls.length })}
|
||||
</RelayUrlsExpandToggle>
|
||||
<RelayGroupOptions group={group} />
|
||||
</div>
|
||||
@@ -71,6 +73,7 @@ function RelayGroupActiveToggle({
|
||||
}
|
||||
|
||||
function RelayGroupName({ groupName }: { groupName: string }) {
|
||||
const { t } = useTranslation()
|
||||
const [newGroupName, setNewGroupName] = useState(groupName)
|
||||
const [newNameError, setNewNameError] = useState<string | null>(null)
|
||||
const { relayGroups, switchRelayGroup, renameRelayGroup } = useRelaySettings()
|
||||
@@ -80,7 +83,7 @@ function RelayGroupName({ groupName }: { groupName: string }) {
|
||||
|
||||
const saveNewGroupName = () => {
|
||||
if (relayGroups.find((group) => group.groupName === newGroupName)) {
|
||||
return setNewNameError('already exists')
|
||||
return setNewNameError(t('relay collection name already exists'))
|
||||
}
|
||||
const errMsg = renameRelayGroup(groupName, newGroupName)
|
||||
if (errMsg) {
|
||||
@@ -153,6 +156,7 @@ function RelayUrlsExpandToggle({
|
||||
}
|
||||
|
||||
function RelayGroupOptions({ group }: { group: TRelayGroup }) {
|
||||
const { t } = useTranslation()
|
||||
const { deleteRelayGroup } = useRelaySettings()
|
||||
const { setRenamingGroup } = useRelaySettingsComponent()
|
||||
|
||||
@@ -165,7 +169,7 @@ function RelayGroupOptions({ group }: { group: TRelayGroup }) {
|
||||
</DropdownMenuTrigger>
|
||||
<DropdownMenuContent>
|
||||
<DropdownMenuItem onClick={() => setRenamingGroup(group.groupName)}>
|
||||
Rename
|
||||
{t('Rename')}
|
||||
</DropdownMenuItem>
|
||||
<DropdownMenuItem
|
||||
onClick={() => {
|
||||
@@ -174,13 +178,13 @@ function RelayGroupOptions({ group }: { group: TRelayGroup }) {
|
||||
)
|
||||
}}
|
||||
>
|
||||
Copy share link
|
||||
{t('Copy share link')}
|
||||
</DropdownMenuItem>
|
||||
<DropdownMenuItem
|
||||
className="text-destructive focus:text-destructive"
|
||||
onClick={() => deleteRelayGroup(group.groupName)}
|
||||
>
|
||||
Delete
|
||||
{t('Delete')}
|
||||
</DropdownMenuItem>
|
||||
</DropdownMenuContent>
|
||||
</DropdownMenu>
|
||||
|
||||
@@ -5,8 +5,10 @@ import { useRelaySettings } from '@renderer/providers/RelaySettingsProvider'
|
||||
import client from '@renderer/services/client.service'
|
||||
import { CircleX } from 'lucide-react'
|
||||
import { useEffect, useState } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
|
||||
export default function RelayUrls({ groupName }: { groupName: string }) {
|
||||
const { t } = useTranslation()
|
||||
const { relayGroups, updateRelayGroupRelayUrls } = useRelaySettings()
|
||||
const rawRelayUrls = relayGroups.find((group) => group.groupName === groupName)?.relayUrls ?? []
|
||||
const isActive = relayGroups.find((group) => group.groupName === groupName)?.isActive ?? false
|
||||
@@ -46,10 +48,10 @@ export default function RelayUrls({ groupName }: { groupName: string }) {
|
||||
if (newRelayUrl === '') return
|
||||
const normalizedUrl = normalizeUrl(newRelayUrl)
|
||||
if (relays.some(({ url }) => url === normalizedUrl)) {
|
||||
return setNewRelayUrlError('already exists')
|
||||
return setNewRelayUrlError(t('Relay already exists'))
|
||||
}
|
||||
if (!isWebsocketUrl(normalizedUrl)) {
|
||||
return setNewRelayUrlError('invalid URL')
|
||||
return setNewRelayUrlError(t('invalid relay URL'))
|
||||
}
|
||||
setRelays((pre) => [...pre, { url: normalizedUrl, isConnected: false }])
|
||||
const newRelayUrls = [...relays.map(({ url }) => url), normalizedUrl]
|
||||
@@ -85,13 +87,13 @@ export default function RelayUrls({ groupName }: { groupName: string }) {
|
||||
<div className="mt-2 flex gap-2">
|
||||
<Input
|
||||
className={newRelayUrlError ? 'border-destructive' : ''}
|
||||
placeholder="Add new relay URL"
|
||||
placeholder={t('Add a new relay')}
|
||||
value={newRelayUrl}
|
||||
onKeyDown={handleRelayUrlInputKeyDown}
|
||||
onChange={handleRelayUrlInputChange}
|
||||
onBlur={saveNewRelayUrl}
|
||||
/>
|
||||
<Button onClick={saveNewRelayUrl}>Add</Button>
|
||||
<Button onClick={saveNewRelayUrl}>{t('Add')}</Button>
|
||||
</div>
|
||||
{newRelayUrlError && <div className="text-xs text-destructive mt-1">{newRelayUrlError}</div>}
|
||||
</>
|
||||
|
||||
@@ -6,8 +6,10 @@ import { useEffect, useRef, useState } from 'react'
|
||||
import { RelaySettingsComponentProvider } from './provider'
|
||||
import RelayGroup from './RelayGroup'
|
||||
import TemporaryRelayGroup from './TemporaryRelayGroup'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
|
||||
export default function RelaySettings() {
|
||||
const { t } = useTranslation()
|
||||
const { relayGroups, addRelayGroup } = useRelaySettings()
|
||||
const [newGroupName, setNewGroupName] = useState('')
|
||||
const [newNameError, setNewNameError] = useState<string | null>(null)
|
||||
@@ -21,7 +23,7 @@ export default function RelaySettings() {
|
||||
|
||||
const saveRelayGroup = () => {
|
||||
if (relayGroups.find((group) => group.groupName === newGroupName)) {
|
||||
return setNewNameError('already exists')
|
||||
return setNewNameError(t('relay collection name already exists'))
|
||||
}
|
||||
const errMsg = addRelayGroup(newGroupName)
|
||||
if (errMsg) {
|
||||
@@ -45,7 +47,7 @@ export default function RelaySettings() {
|
||||
return (
|
||||
<RelaySettingsComponentProvider>
|
||||
<div ref={dummyRef} tabIndex={-1} style={{ position: 'absolute', opacity: 0 }}></div>
|
||||
<div className="text-lg font-semibold mb-4">Relay Settings</div>
|
||||
<div className="text-lg font-semibold mb-4">{t('Relay Settings')}</div>
|
||||
<div className="space-y-2">
|
||||
<TemporaryRelayGroup />
|
||||
{relayGroups.map((group, index) => (
|
||||
@@ -57,18 +59,18 @@ export default function RelaySettings() {
|
||||
<Separator className="my-4" />
|
||||
<div className="w-full border rounded-lg p-4">
|
||||
<div className="flex justify-between items-center">
|
||||
<div className="font-semibold">Add a new relay group</div>
|
||||
<div className="font-semibold">{t('Add a new relay collection')}</div>
|
||||
</div>
|
||||
<div className="mt-2 flex gap-2">
|
||||
<Input
|
||||
className={newNameError ? 'border-destructive' : ''}
|
||||
placeholder="Group name"
|
||||
placeholder={t('Relay collection name')}
|
||||
value={newGroupName}
|
||||
onChange={handleNewGroupNameChange}
|
||||
onKeyDown={handleNewGroupNameKeyDown}
|
||||
onBlur={saveRelayGroup}
|
||||
/>
|
||||
<Button onClick={saveRelayGroup}>Add</Button>
|
||||
<Button onClick={saveRelayGroup}>{t('Add')}</Button>
|
||||
</div>
|
||||
{newNameError && <div className="text-xs text-destructive mt-1">{newNameError}</div>}
|
||||
</div>
|
||||
|
||||
@@ -119,7 +119,7 @@ export default function ReplyNoteList({ event, className }: { event: Event; clas
|
||||
})}
|
||||
</div>
|
||||
{replies.length === 0 && !loading && !hasMore && (
|
||||
<div className="text-sm text-center text-muted-foreground">no replies</div>
|
||||
<div className="text-sm text-center text-muted-foreground">{t('no replies')}</div>
|
||||
)}
|
||||
</>
|
||||
)
|
||||
|
||||
@@ -44,6 +44,24 @@ export default {
|
||||
note: 'note',
|
||||
"username's following": "{{username}}'s following",
|
||||
following: 'following',
|
||||
Login: 'Login'
|
||||
Login: 'Login',
|
||||
'Follows you': 'Follows you',
|
||||
'relay collection name already exists': 'relay collection name already exists',
|
||||
'Relay Settings': 'Relay Settings',
|
||||
'Relay collection name': 'Relay collection name',
|
||||
'Add a new relay collection': 'Add a new relay collection',
|
||||
Add: 'Add',
|
||||
'n relays': '{{n}} relays',
|
||||
Rename: 'Rename',
|
||||
'Copy share link': 'Copy share link',
|
||||
Delete: 'Delete',
|
||||
'Relay already exists': 'Relay already exists',
|
||||
'invalid relay URL': 'invalid relay URL',
|
||||
'Add a new relay': 'Add a new relay',
|
||||
back: 'back',
|
||||
'Lost in the void': 'Lost in the void',
|
||||
'Carry me home': 'Carry me home',
|
||||
'no replies': 'no replies',
|
||||
'Reply to': 'Reply to'
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
export default {
|
||||
translation: {
|
||||
'Welcome! 🥳': '欢迎!🥳',
|
||||
'Welcome! 🥳': '来都来了',
|
||||
About: '关于',
|
||||
'New post': '发布新笔记',
|
||||
Post: '发布笔记',
|
||||
'Relay settings': '中继设置',
|
||||
SidebarRelays: '中继设置',
|
||||
'Relay settings': '服务器设置',
|
||||
SidebarRelays: '服务器',
|
||||
Refresh: '刷新列表',
|
||||
Profile: '个人资料',
|
||||
Logout: '退出登录',
|
||||
@@ -44,6 +44,24 @@ export default {
|
||||
note: '笔记',
|
||||
"username's following": '{{username}} 的关注',
|
||||
following: '关注',
|
||||
Login: '登录'
|
||||
Login: '登录',
|
||||
'Follows you': '关注了你',
|
||||
'relay collection name already exists': '服务器组名已存在',
|
||||
'Relay Settings': '服务器设置',
|
||||
'Relay collection name': '服务器组名',
|
||||
'Add a new relay collection': '添加新的服务器组',
|
||||
Add: '添加',
|
||||
'n relays': '{{n}} 个服务器',
|
||||
Rename: '重命名',
|
||||
'Copy share link': '复制分享链接',
|
||||
Delete: '删除',
|
||||
'Relay already exists': '服务器已存在',
|
||||
'invalid relay URL': '无效的服务器地址',
|
||||
'Add a new relay': '添加新的服务器',
|
||||
back: '返回',
|
||||
'Lost in the void': '迷失在虚空中',
|
||||
'Carry me home': '带我回家',
|
||||
'no replies': '暂无回复',
|
||||
'Reply to': '回复'
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,16 +2,19 @@ import { Button } from '@renderer/components/ui/button'
|
||||
import SecondaryPageLayout from '@renderer/layouts/SecondaryPageLayout'
|
||||
import { toHome } from '@renderer/lib/link'
|
||||
import { useSecondaryPage } from '@renderer/PageManager'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
|
||||
export default function NotFoundPage() {
|
||||
const { t } = useTranslation()
|
||||
const { push } = useSecondaryPage()
|
||||
|
||||
return (
|
||||
<SecondaryPageLayout hideBackButton>
|
||||
<div className="text-muted-foreground w-full h-full flex flex-col items-center justify-center gap-2">
|
||||
<div>Lost in the void 🌌</div>
|
||||
<div>{t('Lost in the void')} 🌌</div>
|
||||
<div>(404)</div>
|
||||
<Button variant="secondary" onClick={() => push(toHome())}>
|
||||
Carry me home
|
||||
{t('Carry me home')}
|
||||
</Button>
|
||||
</div>
|
||||
</SecondaryPageLayout>
|
||||
|
||||
@@ -71,7 +71,7 @@ export default function ProfilePage({ id }: { id?: string }) {
|
||||
<div className="flex justify-end h-8 gap-2 items-center">
|
||||
{isFollowingYou && (
|
||||
<div className="text-muted-foreground rounded-full bg-muted text-xs h-fit px-2">
|
||||
Follows you
|
||||
{t('Follows you')}
|
||||
</div>
|
||||
)}
|
||||
<FollowButton pubkey={pubkey} />
|
||||
|
||||
Reference in New Issue
Block a user