mirror of
https://github.com/aljazceru/rabbit.git
synced 2025-12-17 14:04:21 +01:00
fix: expose i18n instance
This commit is contained in:
@@ -130,7 +130,7 @@ const ReactionAction = (props: { event: NostrEvent }) => {
|
|||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<button
|
<button
|
||||||
class="h-4 w-4"
|
class="size-4"
|
||||||
onClick={handleReaction}
|
onClick={handleReaction}
|
||||||
disabled={publishReactionMutation.isPending}
|
disabled={publishReactionMutation.isPending}
|
||||||
>
|
>
|
||||||
@@ -156,7 +156,7 @@ const ReactionAction = (props: { event: NostrEvent }) => {
|
|||||||
>
|
>
|
||||||
<button
|
<button
|
||||||
ref={emojiPickerPopup.targetRef}
|
ref={emojiPickerPopup.targetRef}
|
||||||
class="h-4 w-4"
|
class="size-4"
|
||||||
onClick={() => emojiPickerPopup.open()}
|
onClick={() => emojiPickerPopup.open()}
|
||||||
>
|
>
|
||||||
<Plus />
|
<Plus />
|
||||||
@@ -217,7 +217,7 @@ const RepostAction = (props: { event: NostrEvent }) => {
|
|||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<button onClick={handleRepost} disabled={publishRepostMutation.isPending}>
|
<button onClick={handleRepost} disabled={publishRepostMutation.isPending}>
|
||||||
<span class="flex h-4 w-4">
|
<span class="flex size-4">
|
||||||
<ArrowPathRoundedSquare />
|
<ArrowPathRoundedSquare />
|
||||||
</span>
|
</span>
|
||||||
</button>
|
</button>
|
||||||
@@ -359,11 +359,11 @@ const Actions: Component<ActionProps> = (props) => {
|
|||||||
const succeeded = results.filter((res) => res.status === 'fulfilled').length;
|
const succeeded = results.filter((res) => res.status === 'fulfilled').length;
|
||||||
const failed = results.length - succeeded;
|
const failed = results.length - succeeded;
|
||||||
if (succeeded === results.length) {
|
if (succeeded === results.length) {
|
||||||
window.alert(i18n()('post.deletedSuccessfully'));
|
window.alert(i18n.t('post.deletedSuccessfully'));
|
||||||
} else if (succeeded > 0) {
|
} else if (succeeded > 0) {
|
||||||
window.alert(i18n()('post.failedToDeletePartially', { count: failed }));
|
window.alert(i18n.t('post.failedToDeletePartially', { count: failed }));
|
||||||
} else {
|
} else {
|
||||||
window.alert(i18n()('post.failedToDelete'));
|
window.alert(i18n.t('post.failedToDelete'));
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
onError: (err) => {
|
onError: (err) => {
|
||||||
@@ -374,7 +374,7 @@ const Actions: Component<ActionProps> = (props) => {
|
|||||||
const otherActionsPopup = useContextMenu(() => ({
|
const otherActionsPopup = useContextMenu(() => ({
|
||||||
menu: [
|
menu: [
|
||||||
{
|
{
|
||||||
content: i18n()('post.copyEventId'),
|
content: i18n.t('post.copyEventId'),
|
||||||
onSelect: () => {
|
onSelect: () => {
|
||||||
navigator.clipboard
|
navigator.clipboard
|
||||||
.writeText(noteEncode(props.event.id))
|
.writeText(noteEncode(props.event.id))
|
||||||
@@ -382,31 +382,31 @@ const Actions: Component<ActionProps> = (props) => {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
content: i18n()('post.showJSON'),
|
content: i18n.t('post.showJSON'),
|
||||||
onSelect: () => {
|
onSelect: () => {
|
||||||
setModal('EventDebugModal');
|
setModal('EventDebugModal');
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
content: i18n()('post.showReposts'),
|
content: i18n.t('post.showReposts'),
|
||||||
onSelect: () => {
|
onSelect: () => {
|
||||||
setModal('Reposts');
|
setModal('Reposts');
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
content: i18n()('post.showReactions'),
|
content: i18n.t('post.showReactions'),
|
||||||
onSelect: () => {
|
onSelect: () => {
|
||||||
setModal('Reactions');
|
setModal('Reactions');
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
when: () => props.event.pubkey === pubkey(),
|
when: () => props.event.pubkey === pubkey(),
|
||||||
content: <span class="text-red-500">{i18n()('post.deletePost')}</span>,
|
content: <span class="text-red-500">{i18n.t('post.deletePost')}</span>,
|
||||||
onSelect: () => {
|
onSelect: () => {
|
||||||
const p = pubkey();
|
const p = pubkey();
|
||||||
if (p == null) return;
|
if (p == null) return;
|
||||||
|
|
||||||
if (!window.confirm(i18n()('post.confirmDelete'))) return;
|
if (!window.confirm(i18n.t('post.confirmDelete'))) return;
|
||||||
deleteMutation.mutate({
|
deleteMutation.mutate({
|
||||||
relayUrls: config().relayUrls,
|
relayUrls: config().relayUrls,
|
||||||
pubkey: p,
|
pubkey: p,
|
||||||
@@ -428,21 +428,21 @@ const Actions: Component<ActionProps> = (props) => {
|
|||||||
props.onClickReply();
|
props.onClickReply();
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<span class="flex h-4 w-4">
|
<span class="flex size-4">
|
||||||
<ChatBubbleLeft />
|
<ChatBubbleLeft />
|
||||||
</span>
|
</span>
|
||||||
</button>
|
</button>
|
||||||
<RepostAction event={props.event} />
|
<RepostAction event={props.event} />
|
||||||
<ReactionAction event={props.event} />
|
<ReactionAction event={props.event} />
|
||||||
<button type="button" onClick={() => setModal('ZapRequest')}>
|
<button type="button" onClick={() => setModal('ZapRequest')}>
|
||||||
<span class="flex h-4 w-4 text-fg-tertiary hover:text-r-zap">
|
<span class="flex size-4 text-fg-tertiary hover:text-r-zap">
|
||||||
<Bolt />
|
<Bolt />
|
||||||
</span>
|
</span>
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
ref={otherActionsPopup.targetRef}
|
ref={otherActionsPopup.targetRef}
|
||||||
type="button"
|
type="button"
|
||||||
class="h-4 w-4 shrink-0 text-fg-tertiary hover:text-fg-tertiary/70"
|
class="size-4 shrink-0 text-fg-tertiary hover:text-fg-tertiary/70"
|
||||||
onClick={() => otherActionsPopup.open()}
|
onClick={() => otherActionsPopup.open()}
|
||||||
>
|
>
|
||||||
<EllipsisHorizontal />
|
<EllipsisHorizontal />
|
||||||
|
|||||||
@@ -17,24 +17,24 @@ const DomainTransferInfo: Component<{ children: JSX.Element }> = (props) => {
|
|||||||
when={isPermittedDomain(window.location) || showContent()}
|
when={isPermittedDomain(window.location) || showContent()}
|
||||||
fallback={
|
fallback={
|
||||||
<div class="flex h-svh w-screen shrink-0 flex-col items-center justify-center border-b border-border bg-bg-tertiary text-fg">
|
<div class="flex h-svh w-screen shrink-0 flex-col items-center justify-center border-b border-border bg-bg-tertiary text-fg">
|
||||||
<h3 class="text-2xl font-bold">{i18n()('domainTransfer.announcementHead')}</h3>
|
<h3 class="text-2xl font-bold">{i18n.t('domainTransfer.announcementHead')}</h3>
|
||||||
<div>{i18n()('domainTransfer.announcementDescription')}</div>
|
<div>{i18n.t('domainTransfer.announcementDescription')}</div>
|
||||||
<SafeLink class="text-lg text-link underline" href="https://rabbit.syusui.net/" />
|
<SafeLink class="text-lg text-link underline" href="https://rabbit.syusui.net/" />
|
||||||
<SafeLink
|
<SafeLink
|
||||||
class="mt-4 text-sm text-link underline"
|
class="mt-4 text-sm text-link underline"
|
||||||
href="https://scrapbox.io/nostr/Rabbit#659be5fa1246d700005facb8"
|
href="https://scrapbox.io/nostr/Rabbit#659be5fa1246d700005facb8"
|
||||||
>
|
>
|
||||||
{i18n()('domainTransfer.howToMigrateSettings')}
|
{i18n.t('domainTransfer.howToMigrateSettings')}
|
||||||
</SafeLink>
|
</SafeLink>
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
class="mt-4 flex items-center text-fg-secondary"
|
class="mt-4 flex items-center text-fg-secondary"
|
||||||
onClick={() => setShowContent(true)}
|
onClick={() => setShowContent(true)}
|
||||||
>
|
>
|
||||||
<span class="inline-block h-5 w-5">
|
<span class="inline-block size-5">
|
||||||
<XMark />
|
<XMark />
|
||||||
</span>
|
</span>
|
||||||
{i18n()('domainTransfer.close')}
|
{i18n.t('domainTransfer.close')}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -112,10 +112,10 @@ const NotePostForm: Component<NotePostFormProps> = (props) => {
|
|||||||
const placeholder = (mode: NotePostFormProps['mode']) => {
|
const placeholder = (mode: NotePostFormProps['mode']) => {
|
||||||
switch (mode) {
|
switch (mode) {
|
||||||
case 'reply':
|
case 'reply':
|
||||||
return i18n()('posting.placeholderReply');
|
return i18n.t('posting.placeholderReply');
|
||||||
case 'normal':
|
case 'normal':
|
||||||
default:
|
default:
|
||||||
return i18n()('posting.placeholder');
|
return i18n.t('posting.placeholder');
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -163,7 +163,7 @@ const NotePostForm: Component<NotePostFormProps> = (props) => {
|
|||||||
|
|
||||||
if (failed.length > 0) {
|
if (failed.length > 0) {
|
||||||
const filenames = failed.map((f) => f.name).join(', ');
|
const filenames = failed.map((f) => f.name).join(', ');
|
||||||
window.alert(i18n()('posting.failedToUploadFile', { filenames }));
|
window.alert(i18n.t('posting.failedToUploadFile', { filenames }));
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
}));
|
}));
|
||||||
@@ -205,7 +205,7 @@ const NotePostForm: Component<NotePostFormProps> = (props) => {
|
|||||||
if (publishTextNoteMutation.isPending) return;
|
if (publishTextNoteMutation.isPending) return;
|
||||||
|
|
||||||
if (/nsec1[0-9a-zA-Z]+/.test(text())) {
|
if (/nsec1[0-9a-zA-Z]+/.test(text())) {
|
||||||
window.alert(i18n()('posting.forbiddenToIncludeNsec'));
|
window.alert(i18n.t('posting.forbiddenToIncludeNsec'));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -353,7 +353,7 @@ const NotePostForm: Component<NotePostFormProps> = (props) => {
|
|||||||
<div class="p-1">
|
<div class="p-1">
|
||||||
<Show when={props.replyTo != null}>
|
<Show when={props.replyTo != null}>
|
||||||
<div>
|
<div>
|
||||||
{i18n()('posting.replyToPre')}
|
{i18n.t('posting.replyToPre')}
|
||||||
<For each={notifyPubkeys()}>
|
<For each={notifyPubkeys()}>
|
||||||
{(pubkey, index) => (
|
{(pubkey, index) => (
|
||||||
<>
|
<>
|
||||||
@@ -362,7 +362,7 @@ const NotePostForm: Component<NotePostFormProps> = (props) => {
|
|||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
</For>
|
</For>
|
||||||
{i18n()('posting.replyToPost')}
|
{i18n.t('posting.replyToPost')}
|
||||||
</div>
|
</div>
|
||||||
</Show>
|
</Show>
|
||||||
<form class="flex flex-col gap-1" onSubmit={handleSubmit}>
|
<form class="flex flex-col gap-1" onSubmit={handleSubmit}>
|
||||||
@@ -371,7 +371,7 @@ const NotePostForm: Component<NotePostFormProps> = (props) => {
|
|||||||
ref={contentWarningReasonRef}
|
ref={contentWarningReasonRef}
|
||||||
type="text"
|
type="text"
|
||||||
class="rounded-md border border-border bg-bg ring-border placeholder:text-fg-secondary focus:border-border focus:ring-primary"
|
class="rounded-md border border-border bg-bg ring-border placeholder:text-fg-secondary focus:border-border focus:ring-primary"
|
||||||
placeholder={i18n()('posting.contentWarningReason')}
|
placeholder={i18n.t('posting.contentWarningReason')}
|
||||||
maxLength={32}
|
maxLength={32}
|
||||||
onInput={(ev) => setContentWarningReason(ev.currentTarget.value)}
|
onInput={(ev) => setContentWarningReason(ev.currentTarget.value)}
|
||||||
value={contentWarningReason()}
|
value={contentWarningReason()}
|
||||||
@@ -406,7 +406,7 @@ const NotePostForm: Component<NotePostFormProps> = (props) => {
|
|||||||
}}
|
}}
|
||||||
onClick={() => close()}
|
onClick={() => close()}
|
||||||
>
|
>
|
||||||
<span class="inline-block h-5 w-5 text-fg-secondary/70">
|
<span class="inline-block size-5 text-fg-secondary/70">
|
||||||
<XMark />
|
<XMark />
|
||||||
</span>
|
</span>
|
||||||
</button>
|
</button>
|
||||||
@@ -442,8 +442,8 @@ const NotePostForm: Component<NotePostFormProps> = (props) => {
|
|||||||
'p-[6px]': mode() === 'reply',
|
'p-[6px]': mode() === 'reply',
|
||||||
}}
|
}}
|
||||||
type="button"
|
type="button"
|
||||||
aria-label={i18n()('posting.contentWarning')}
|
aria-label={i18n.t('posting.contentWarning')}
|
||||||
title={i18n()('posting.contentWarning')}
|
title={i18n.t('posting.contentWarning')}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
setContentWarning((e) => !e);
|
setContentWarning((e) => !e);
|
||||||
contentWarningReasonRef?.focus();
|
contentWarningReasonRef?.focus();
|
||||||
@@ -464,8 +464,8 @@ const NotePostForm: Component<NotePostFormProps> = (props) => {
|
|||||||
'p-[6px]': mode() === 'reply',
|
'p-[6px]': mode() === 'reply',
|
||||||
}}
|
}}
|
||||||
type="button"
|
type="button"
|
||||||
title={i18n()('posting.uploadImage')}
|
title={i18n.t('posting.uploadImage')}
|
||||||
aria-label={i18n()('posting.uploadImage')}
|
aria-label={i18n.t('posting.uploadImage')}
|
||||||
disabled={fileUploadDisabled()}
|
disabled={fileUploadDisabled()}
|
||||||
onClick={() => fileInputRef?.click()}
|
onClick={() => fileInputRef?.click()}
|
||||||
>
|
>
|
||||||
@@ -482,8 +482,8 @@ const NotePostForm: Component<NotePostFormProps> = (props) => {
|
|||||||
'w-7': mode() === 'reply',
|
'w-7': mode() === 'reply',
|
||||||
}}
|
}}
|
||||||
type="submit"
|
type="submit"
|
||||||
aria-label={i18n()('posting.submit')}
|
aria-label={i18n.t('posting.submit')}
|
||||||
title={i18n()('posting.submit')}
|
title={i18n.t('posting.submit')}
|
||||||
disabled={submitDisabled()}
|
disabled={submitDisabled()}
|
||||||
>
|
>
|
||||||
<PaperAirplane />
|
<PaperAirplane />
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ const Post: Component<PostProps> = (props) => {
|
|||||||
<div class="flex w-full gap-1">
|
<div class="flex w-full gap-1">
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
class="author-icon h-10 w-10 shrink-0 overflow-hidden rounded"
|
class="author-icon size-10 shrink-0 overflow-hidden rounded"
|
||||||
onClick={(ev) => {
|
onClick={(ev) => {
|
||||||
ev.preventDefault();
|
ev.preventDefault();
|
||||||
props.onShowProfile?.();
|
props.onShowProfile?.();
|
||||||
@@ -50,7 +50,7 @@ const Post: Component<PostProps> = (props) => {
|
|||||||
src={thumbnailUrl(url, 'icon')}
|
src={thumbnailUrl(url, 'icon')}
|
||||||
alt="icon"
|
alt="icon"
|
||||||
referrerpolicy="no-referrer"
|
referrerpolicy="no-referrer"
|
||||||
class="h-full w-full object-cover"
|
class="size-full object-cover"
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</LazyLoad>
|
</LazyLoad>
|
||||||
@@ -113,8 +113,8 @@ const Post: Component<PostProps> = (props) => {
|
|||||||
setShowOverflow((current) => !current);
|
setShowOverflow((current) => !current);
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Show when={!showOverflow()} fallback={i18n()('post.hideOverflow')}>
|
<Show when={!showOverflow()} fallback={i18n.t('post.hideOverflow')}>
|
||||||
{i18n()('post.showOverflow')}
|
{i18n.t('post.showOverflow')}
|
||||||
</Show>
|
</Show>
|
||||||
</button>
|
</button>
|
||||||
</Show>
|
</Show>
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ const BookmarkColumn: Component<BookmarkColumnDisplayProps> = (props) => {
|
|||||||
<Column
|
<Column
|
||||||
header={
|
header={
|
||||||
<BasicColumnHeader
|
<BasicColumnHeader
|
||||||
name={props.column.name ?? i18n()('column.bookmark')}
|
name={props.column.name ?? i18n.t('column.bookmark')}
|
||||||
icon={<BookmarkIcon />}
|
icon={<BookmarkIcon />}
|
||||||
settings={() => <ColumnSettings column={props.column} columnIndex={props.columnIndex} />}
|
settings={() => <ColumnSettings column={props.column} columnIndex={props.columnIndex} />}
|
||||||
onClose={() => removeColumn(props.column.id)}
|
onClose={() => removeColumn(props.column.id)}
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ const ChannelColumn: Component<ChannelColumnProps> = (props) => {
|
|||||||
<Column
|
<Column
|
||||||
header={
|
header={
|
||||||
<BasicColumnHeader
|
<BasicColumnHeader
|
||||||
name={props.column.name ?? i18n()('column.channel')}
|
name={props.column.name ?? i18n.t('column.channel')}
|
||||||
icon={<ChatBubbleLeftRight />}
|
icon={<ChatBubbleLeftRight />}
|
||||||
settings={() => <ColumnSettings column={props.column} columnIndex={props.columnIndex} />}
|
settings={() => <ColumnSettings column={props.column} columnIndex={props.columnIndex} />}
|
||||||
onClose={() => removeColumn(props.column.id)}
|
onClose={() => removeColumn(props.column.id)}
|
||||||
|
|||||||
@@ -73,10 +73,10 @@ const Column: Component<ColumnProps> = (props) => {
|
|||||||
class="flex w-full items-center gap-1"
|
class="flex w-full items-center gap-1"
|
||||||
onClick={() => timelineState?.clearTimeline()}
|
onClick={() => timelineState?.clearTimeline()}
|
||||||
>
|
>
|
||||||
<div class="inline-block h-4 w-4">
|
<div class="inline-block size-4">
|
||||||
<ArrowLeft />
|
<ArrowLeft />
|
||||||
</div>
|
</div>
|
||||||
<div>{i18n()('column.back')}</div>
|
<div>{i18n.t('column.back')}</div>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<div class="scrollbar flex max-h-full flex-col overflow-y-scroll scroll-smooth pb-16">
|
<div class="scrollbar flex max-h-full flex-col overflow-y-scroll scroll-smooth pb-16">
|
||||||
|
|||||||
@@ -42,7 +42,7 @@ const ColumnSettings: Component<ColumnSettingsProps> = (props) => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div class="flex flex-col border-t border-border">
|
<div class="flex flex-col border-t border-border">
|
||||||
<ColumnSettingsSection title={i18n()('column.config.columnWidth')}>
|
<ColumnSettingsSection title={i18n.t('column.config.columnWidth')}>
|
||||||
<div class="scrollbar flex h-9 gap-2 overflow-x-auto">
|
<div class="scrollbar flex h-9 gap-2 overflow-x-auto">
|
||||||
<For each={['widest', 'wide', 'medium', 'narrow'] as const}>
|
<For each={['widest', 'wide', 'medium', 'narrow'] as const}>
|
||||||
{(width) => (
|
{(width) => (
|
||||||
@@ -56,7 +56,7 @@ const ColumnSettings: Component<ColumnSettingsProps> = (props) => {
|
|||||||
}}
|
}}
|
||||||
onClick={() => setColumnWidth(width)}
|
onClick={() => setColumnWidth(width)}
|
||||||
>
|
>
|
||||||
{i18n()(`column.config.${width}`)}
|
{i18n.t(`column.config.${width}`)}
|
||||||
</button>
|
</button>
|
||||||
)}
|
)}
|
||||||
</For>
|
</For>
|
||||||
@@ -65,29 +65,29 @@ const ColumnSettings: Component<ColumnSettingsProps> = (props) => {
|
|||||||
<div class="flex h-10 items-center gap-2">
|
<div class="flex h-10 items-center gap-2">
|
||||||
<button
|
<button
|
||||||
class="py-4 pl-2"
|
class="py-4 pl-2"
|
||||||
title={i18n()('column.config.moveLeft')}
|
title={i18n.t('column.config.moveLeft')}
|
||||||
onClick={() => move(props.columnIndex - 1)}
|
onClick={() => move(props.columnIndex - 1)}
|
||||||
>
|
>
|
||||||
<span class="inline-block h-4 w-4">
|
<span class="inline-block size-4">
|
||||||
<ChevronLeft />
|
<ChevronLeft />
|
||||||
</span>
|
</span>
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
class="py-4 pr-2"
|
class="py-4 pr-2"
|
||||||
title={i18n()('column.config.moveRight')}
|
title={i18n.t('column.config.moveRight')}
|
||||||
onClick={() => move(props.columnIndex + 1)}
|
onClick={() => move(props.columnIndex + 1)}
|
||||||
>
|
>
|
||||||
<span class="inline-block h-4 w-4">
|
<span class="inline-block size-4">
|
||||||
<ChevronRight />
|
<ChevronRight />
|
||||||
</span>
|
</span>
|
||||||
</button>
|
</button>
|
||||||
<div class="flex-1" />
|
<div class="flex-1" />
|
||||||
<button
|
<button
|
||||||
class="px-2 py-4 text-danger hover:text-rose-600"
|
class="px-2 py-4 text-danger hover:text-rose-600"
|
||||||
title={i18n()('column.config.removeColumn')}
|
title={i18n.t('column.config.removeColumn')}
|
||||||
onClick={() => removeColumn(props.column.id)}
|
onClick={() => removeColumn(props.column.id)}
|
||||||
>
|
>
|
||||||
<span class="inline-block h-4 w-4" aria-label={i18n()('column.config.removeColumn')}>
|
<span class="inline-block size-4" aria-label={i18n.t('column.config.removeColumn')}>
|
||||||
<Trash />
|
<Trash />
|
||||||
</span>
|
</span>
|
||||||
</button>
|
</button>
|
||||||
|
|||||||
@@ -70,7 +70,7 @@ const FollowingColumn: Component<FollowingColumnDisplayProps> = (props) => {
|
|||||||
<Column
|
<Column
|
||||||
header={
|
header={
|
||||||
<BasicColumnHeader
|
<BasicColumnHeader
|
||||||
name={props.column.name ?? i18n()('column.home')}
|
name={props.column.name ?? i18n.t('column.home')}
|
||||||
icon={<Home />}
|
icon={<Home />}
|
||||||
settings={() => <ColumnSettings column={props.column} columnIndex={props.columnIndex} />}
|
settings={() => <ColumnSettings column={props.column} columnIndex={props.columnIndex} />}
|
||||||
onClose={() => removeColumn(props.column.id)}
|
onClose={() => removeColumn(props.column.id)}
|
||||||
|
|||||||
@@ -91,7 +91,7 @@ const LoadMore: Component<LoadMoreProps> = (props) => {
|
|||||||
class="flex h-12 w-full flex-col items-center justify-center hover:text-fg-secondary"
|
class="flex h-12 w-full flex-col items-center justify-center hover:text-fg-secondary"
|
||||||
onClick={() => props.loadMore.loadLatest()}
|
onClick={() => props.loadMore.loadLatest()}
|
||||||
>
|
>
|
||||||
<span>{i18n()('column.loadLatest')}</span>
|
<span>{i18n.t('column.loadLatest')}</span>
|
||||||
</button>
|
</button>
|
||||||
</ColumnItem>
|
</ColumnItem>
|
||||||
</Show>
|
</Show>
|
||||||
@@ -102,7 +102,7 @@ const LoadMore: Component<LoadMoreProps> = (props) => {
|
|||||||
disabled={!props.eose}
|
disabled={!props.eose}
|
||||||
onClick={() => props.loadMore.loadOld()}
|
onClick={() => props.loadMore.loadOld()}
|
||||||
>
|
>
|
||||||
<span>{i18n()('column.loadOld')}</span>
|
<span>{i18n.t('column.loadOld')}</span>
|
||||||
</button>
|
</button>
|
||||||
</ColumnItem>
|
</ColumnItem>
|
||||||
</>
|
</>
|
||||||
|
|||||||
@@ -49,7 +49,7 @@ const NotificationColumn: Component<NotificationColumnDisplayProps> = (props) =>
|
|||||||
<Column
|
<Column
|
||||||
header={
|
header={
|
||||||
<BasicColumnHeader
|
<BasicColumnHeader
|
||||||
name={props.column.name ?? i18n()('column.notification')}
|
name={props.column.name ?? i18n.t('column.notification')}
|
||||||
icon={<Bell />}
|
icon={<Bell />}
|
||||||
settings={() => <ColumnSettings column={props.column} columnIndex={props.columnIndex} />}
|
settings={() => <ColumnSettings column={props.column} columnIndex={props.columnIndex} />}
|
||||||
onClose={() => removeColumn(props.column.id)}
|
onClose={() => removeColumn(props.column.id)}
|
||||||
|
|||||||
@@ -49,7 +49,7 @@ const PostsColumn: Component<PostsColumnDisplayProps> = (props) => {
|
|||||||
<Column
|
<Column
|
||||||
header={
|
header={
|
||||||
<BasicColumnHeader
|
<BasicColumnHeader
|
||||||
name={props.column.name ?? i18n()('column.posts')}
|
name={props.column.name ?? i18n.t('column.posts')}
|
||||||
icon={<User />}
|
icon={<User />}
|
||||||
settings={() => <ColumnSettings column={props.column} columnIndex={props.columnIndex} />}
|
settings={() => <ColumnSettings column={props.column} columnIndex={props.columnIndex} />}
|
||||||
onClose={() => removeColumn(props.column.id)}
|
onClose={() => removeColumn(props.column.id)}
|
||||||
|
|||||||
@@ -49,7 +49,7 @@ const ReactionsColumn: Component<ReactionsColumnDisplayProps> = (props) => {
|
|||||||
<Column
|
<Column
|
||||||
header={
|
header={
|
||||||
<BasicColumnHeader
|
<BasicColumnHeader
|
||||||
name={props.column.name ?? i18n()('column.reactions')}
|
name={props.column.name ?? i18n.t('column.reactions')}
|
||||||
icon={<Heart />}
|
icon={<Heart />}
|
||||||
settings={() => <ColumnSettings column={props.column} columnIndex={props.columnIndex} />}
|
settings={() => <ColumnSettings column={props.column} columnIndex={props.columnIndex} />}
|
||||||
onClose={() => removeColumn(props.column.id)}
|
onClose={() => removeColumn(props.column.id)}
|
||||||
|
|||||||
@@ -50,7 +50,7 @@ const RelaysColumn: Component<RelaysColumnDisplayProps> = (props) => {
|
|||||||
<Column
|
<Column
|
||||||
header={
|
header={
|
||||||
<BasicColumnHeader
|
<BasicColumnHeader
|
||||||
name={props.column.name ?? i18n()('column.relay')}
|
name={props.column.name ?? i18n.t('column.relay')}
|
||||||
icon={<GlobeAlt />}
|
icon={<GlobeAlt />}
|
||||||
settings={() => <ColumnSettings column={props.column} columnIndex={props.columnIndex} />}
|
settings={() => <ColumnSettings column={props.column} columnIndex={props.columnIndex} />}
|
||||||
onClose={() => removeColumn(props.column.id)}
|
onClose={() => removeColumn(props.column.id)}
|
||||||
|
|||||||
@@ -30,14 +30,14 @@ const EventDisplay: Component<EventDisplayProps> = (props) => {
|
|||||||
<Switch
|
<Switch
|
||||||
fallback={
|
fallback={
|
||||||
<div>
|
<div>
|
||||||
<span>{i18n()('post.unsupportedKind', { kind: props.event.kind })}</span>
|
<span>{i18n.t('post.unsupportedKind', { kind: props.event.kind })}</span>
|
||||||
<EventLink eventId={props.event.id} kind={props.event.kind} />
|
<EventLink eventId={props.event.id} kind={props.event.kind} />
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
<Match when={!isAllowedKind()} keyed>
|
<Match when={!isAllowedKind()} keyed>
|
||||||
<div>
|
<div>
|
||||||
<span>{i18n()('post.unexpectedKind', { kind: props.event.kind })}</span>
|
<span>{i18n.t('post.unexpectedKind', { kind: props.event.kind })}</span>
|
||||||
<EventLink eventId={props.event.id} kind={props.event.kind} />
|
<EventLink eventId={props.event.id} kind={props.event.kind} />
|
||||||
</div>
|
</div>
|
||||||
</Match>
|
</Match>
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ const EventDisplayById: Component<EventDisplayByIdProps> = (props) => {
|
|||||||
<Switch
|
<Switch
|
||||||
fallback={
|
fallback={
|
||||||
<span>
|
<span>
|
||||||
{i18n()('post.failedToFetchEvent')}
|
{i18n.t('post.failedToFetchEvent')}
|
||||||
{props.eventId}
|
{props.eventId}
|
||||||
</span>
|
</span>
|
||||||
}
|
}
|
||||||
@@ -45,7 +45,7 @@ const EventDisplayById: Component<EventDisplayByIdProps> = (props) => {
|
|||||||
<Match when={eventQuery.isLoading && localProps.eventId} keyed>
|
<Match when={eventQuery.isLoading && localProps.eventId} keyed>
|
||||||
{(id) => (
|
{(id) => (
|
||||||
<div class="truncate">
|
<div class="truncate">
|
||||||
{i18n()('general.loading')} <EventLink eventId={id} />
|
{i18n.t('general.loading')} <EventLink eventId={id} />
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</Match>
|
</Match>
|
||||||
|
|||||||
@@ -47,14 +47,14 @@ const ReactionDisplay: Component<ReactionDisplayProps> = (props) => {
|
|||||||
<EmojiDisplay reactionTypes={event().toReactionTypes()} />
|
<EmojiDisplay reactionTypes={event().toReactionTypes()} />
|
||||||
</div>
|
</div>
|
||||||
<div class="notification-user flex flex-1 gap-1 overflow-hidden">
|
<div class="notification-user flex flex-1 gap-1 overflow-hidden">
|
||||||
<div class="author-icon h-5 w-5 shrink-0 overflow-hidden rounded">
|
<div class="author-icon size-5 shrink-0 overflow-hidden rounded">
|
||||||
<Show when={profile()?.picture} keyed>
|
<Show when={profile()?.picture} keyed>
|
||||||
{(url) => (
|
{(url) => (
|
||||||
<img
|
<img
|
||||||
src={thumbnailUrl(url, 'icon')}
|
src={thumbnailUrl(url, 'icon')}
|
||||||
alt="icon"
|
alt="icon"
|
||||||
// TODO autofit
|
// TODO autofit
|
||||||
class="h-full w-full object-cover"
|
class="size-full object-cover"
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</Show>
|
</Show>
|
||||||
@@ -66,7 +66,7 @@ const ReactionDisplay: Component<ReactionDisplayProps> = (props) => {
|
|||||||
>
|
>
|
||||||
<UserDisplayName pubkey={props.event.pubkey} />
|
<UserDisplayName pubkey={props.event.pubkey} />
|
||||||
</button>
|
</button>
|
||||||
<span class="shrink-0">{i18n()('notification.reacted')}</span>
|
<span class="shrink-0">{i18n.t('notification.reacted')}</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="text-xs">{formatDate(event().createdAtAsDate())}</div>
|
<div class="text-xs">{formatDate(event().createdAtAsDate())}</div>
|
||||||
@@ -76,7 +76,7 @@ const ReactionDisplay: Component<ReactionDisplayProps> = (props) => {
|
|||||||
when={reactedEvent()}
|
when={reactedEvent()}
|
||||||
fallback={
|
fallback={
|
||||||
<div class="truncate">
|
<div class="truncate">
|
||||||
{i18n()('general.loading')} {eventId()}
|
{i18n.t('general.loading')} {eventId()}
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
keyed
|
keyed
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ const Repost: Component<RepostProps> = (props) => {
|
|||||||
<div>
|
<div>
|
||||||
<div class="flex items-center gap-1">
|
<div class="flex items-center gap-1">
|
||||||
<div class="flex shrink-0 place-items-center pl-[2px]" aria-hidden="true">
|
<div class="flex shrink-0 place-items-center pl-[2px]" aria-hidden="true">
|
||||||
<span class="h-4 w-4 text-r-repost">
|
<span class="size-4 text-r-repost">
|
||||||
<ArrowPathRoundedSquare />
|
<ArrowPathRoundedSquare />
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
@@ -38,7 +38,7 @@ const Repost: Component<RepostProps> = (props) => {
|
|||||||
>
|
>
|
||||||
<UserDisplayName pubkey={props.event.pubkey} />
|
<UserDisplayName pubkey={props.event.pubkey} />
|
||||||
</button>
|
</button>
|
||||||
<span class="shrink-0">{i18n()('notification.reposted')}</span>
|
<span class="shrink-0">{i18n.t('notification.reposted')}</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="text-xs">{formatDate(event().createdAtAsDate())}</div>
|
<div class="text-xs">{formatDate(event().createdAtAsDate())}</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -83,7 +83,7 @@ const TextNote: Component<TextNoteProps> = (props) => {
|
|||||||
</Show>
|
</Show>
|
||||||
<Show when={event().taggedPubkeys().length > 0}>
|
<Show when={event().taggedPubkeys().length > 0}>
|
||||||
<div class="text-xs">
|
<div class="text-xs">
|
||||||
{i18n()('post.replyToPre')}
|
{i18n.t('post.replyToPre')}
|
||||||
<For each={event().taggedPubkeys()}>
|
<For each={event().taggedPubkeys()}>
|
||||||
{(replyToPubkey: string) => (
|
{(replyToPubkey: string) => (
|
||||||
<button
|
<button
|
||||||
@@ -97,7 +97,7 @@ const TextNote: Component<TextNoteProps> = (props) => {
|
|||||||
</button>
|
</button>
|
||||||
)}
|
)}
|
||||||
</For>
|
</For>
|
||||||
{i18n()('post.replyToPost')}
|
{i18n.t('post.replyToPost')}
|
||||||
</div>
|
</div>
|
||||||
</Show>
|
</Show>
|
||||||
<ContentWarningDisplay contentWarning={event().contentWarning()}>
|
<ContentWarningDisplay contentWarning={event().contentWarning()}>
|
||||||
|
|||||||
@@ -74,20 +74,20 @@ const ZapReceiptDisplay: Component<ZapReceiptProps> = (props) => {
|
|||||||
<Show when={!shouldMuteEvent(props.event) && isZapReceiptVerified()}>
|
<Show when={!shouldMuteEvent(props.event) && isZapReceiptVerified()}>
|
||||||
<div class="flex items-center gap-1 text-sm">
|
<div class="flex items-center gap-1 text-sm">
|
||||||
<div class="flex w-6 flex-col items-center">
|
<div class="flex w-6 flex-col items-center">
|
||||||
<div class="h-4 w-4 shrink-0 text-amber-500" aria-hidden="true">
|
<div class="size-4 shrink-0 text-amber-500" aria-hidden="true">
|
||||||
<Bolt />
|
<Bolt />
|
||||||
</div>
|
</div>
|
||||||
<div class="mt-[-2px] shrink-0 text-xs">{amountSi()}</div>
|
<div class="mt-[-2px] shrink-0 text-xs">{amountSi()}</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="notification-user flex gap-1 overflow-hidden">
|
<div class="notification-user flex gap-1 overflow-hidden">
|
||||||
<div class="author-icon h-5 w-5 shrink-0 overflow-hidden rounded">
|
<div class="author-icon size-5 shrink-0 overflow-hidden rounded">
|
||||||
<Show when={senderProfile()?.picture} keyed>
|
<Show when={senderProfile()?.picture} keyed>
|
||||||
{(url) => (
|
{(url) => (
|
||||||
<img
|
<img
|
||||||
src={thumbnailUrl(url, 'icon')}
|
src={thumbnailUrl(url, 'icon')}
|
||||||
alt="icon"
|
alt="icon"
|
||||||
// TODO autofit
|
// TODO autofit
|
||||||
class="h-full w-full object-cover"
|
class="size-full object-cover"
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</Show>
|
</Show>
|
||||||
@@ -99,7 +99,7 @@ const ZapReceiptDisplay: Component<ZapReceiptProps> = (props) => {
|
|||||||
>
|
>
|
||||||
<UserDisplayName pubkey={event().senderPubkey()} />
|
<UserDisplayName pubkey={event().senderPubkey()} />
|
||||||
</button>
|
</button>
|
||||||
<span class="shrink-0">{i18n()('notification.zapped')}</span>
|
<span class="shrink-0">{i18n.t('notification.zapped')}</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -25,10 +25,10 @@ const ContentWarningDisplay: Component<ContentWarningDisplayProps> = (props) =>
|
|||||||
<span class="inline-block size-4">
|
<span class="inline-block size-4">
|
||||||
<ExclamationTriangle />
|
<ExclamationTriangle />
|
||||||
</span>
|
</span>
|
||||||
<span>{i18n()('post.contentWarning.show')}</span>
|
<span>{i18n.t('post.contentWarning.show')}</span>
|
||||||
<Show when={props.contentWarning.reason != null}>
|
<Show when={props.contentWarning.reason != null}>
|
||||||
<span>
|
<span>
|
||||||
{i18n()('post.contentWarning.reason')}: {props.contentWarning.reason}
|
{i18n.t('post.contentWarning.reason')}: {props.contentWarning.reason}
|
||||||
</span>
|
</span>
|
||||||
</Show>
|
</Show>
|
||||||
</button>
|
</button>
|
||||||
@@ -40,7 +40,7 @@ const ContentWarningDisplay: Component<ContentWarningDisplayProps> = (props) =>
|
|||||||
class="text-xs text-fg-secondary hover:text-fg-secondary/70"
|
class="text-xs text-fg-secondary hover:text-fg-secondary/70"
|
||||||
onClick={() => setShowContentWarning(false)}
|
onClick={() => setShowContentWarning(false)}
|
||||||
>
|
>
|
||||||
{i18n()('post.contentWarning.hide')}
|
{i18n.t('post.contentWarning.hide')}
|
||||||
</button>
|
</button>
|
||||||
</Show>
|
</Show>
|
||||||
</Show>
|
</Show>
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ const ImageDisplay: Component<ImageDisplayProps> = (props) => {
|
|||||||
class="rounded bg-bg-tertiary p-3 text-xs text-fg-secondary hover:shadow"
|
class="rounded bg-bg-tertiary p-3 text-xs text-fg-secondary hover:shadow"
|
||||||
onClick={() => setHidden(false)}
|
onClick={() => setHidden(false)}
|
||||||
>
|
>
|
||||||
{i18n()('post.showImage')}
|
{i18n.t('post.showImage')}
|
||||||
</button>
|
</button>
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
|
|||||||
@@ -109,7 +109,7 @@ const ClickToShow: Component<ClickToShowProps> = (props) => {
|
|||||||
class="flex flex-col items-center rounded bg-bg-tertiary p-3 text-xs text-fg-secondary hover:shadow"
|
class="flex flex-col items-center rounded bg-bg-tertiary p-3 text-xs text-fg-secondary hover:shadow"
|
||||||
onClick={() => setHidden(false)}
|
onClick={() => setHidden(false)}
|
||||||
>
|
>
|
||||||
{i18n()('post.showPreview')}
|
{i18n.t('post.showPreview')}
|
||||||
</button>
|
</button>
|
||||||
<SafeLink class="text-link underline" href={props.url} />
|
<SafeLink class="text-link underline" href={props.url} />
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ const VideoDisplay: Component<VideoDisplayProps> = (props) => {
|
|||||||
class="rounded bg-bg-tertiary p-3 text-xs text-fg-secondary hover:shadow"
|
class="rounded bg-bg-tertiary p-3 text-xs text-fg-secondary hover:shadow"
|
||||||
onClick={() => setHidden(false)}
|
onClick={() => setHidden(false)}
|
||||||
>
|
>
|
||||||
{i18n()('post.showVideo')}
|
{i18n.t('post.showVideo')}
|
||||||
</button>
|
</button>
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
@@ -36,7 +36,7 @@ const VideoDisplay: Component<VideoDisplayProps> = (props) => {
|
|||||||
src={props.url}
|
src={props.url}
|
||||||
controls
|
controls
|
||||||
>
|
>
|
||||||
<a href={props.url}>{i18n()('post.download')}</a>
|
<a href={props.url}>{i18n.t('post.download')}</a>
|
||||||
</video>
|
</video>
|
||||||
</SafeLink>
|
</SafeLink>
|
||||||
)}
|
)}
|
||||||
|
|||||||
@@ -61,17 +61,17 @@ const About: Component<AboutProps> = (props) => {
|
|||||||
class="rounded border-2 border-primary px-4 py-2 font-bold text-primary hover:border-primary-hover hover:text-primary-hover"
|
class="rounded border-2 border-primary px-4 py-2 font-bold text-primary hover:border-primary-hover hover:text-primary-hover"
|
||||||
href="https://github.com/syusui-s/rabbit/issues/new/choose"
|
href="https://github.com/syusui-s/rabbit/issues/new/choose"
|
||||||
>
|
>
|
||||||
{i18n()('about.bugReport')}
|
{i18n.t('about.bugReport')}
|
||||||
</SafeLink>
|
</SafeLink>
|
||||||
<SafeLink
|
<SafeLink
|
||||||
class="rounded border-2 border-primary px-4 py-2 font-bold text-primary hover:border-primary-hover hover:text-primary-hover"
|
class="rounded border-2 border-primary px-4 py-2 font-bold text-primary hover:border-primary-hover hover:text-primary-hover"
|
||||||
href="https://github.com/syusui-s/rabbit"
|
href="https://github.com/syusui-s/rabbit"
|
||||||
>
|
>
|
||||||
{i18n()('about.sourceCode')}
|
{i18n.t('about.sourceCode')}
|
||||||
</SafeLink>
|
</SafeLink>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<h2 class="my-4 text-xl font-bold">{i18n()('about.termOfService')}</h2>
|
<h2 class="my-4 text-xl font-bold">{i18n.t('about.termOfService')}</h2>
|
||||||
|
|
||||||
<p class="my-4">
|
<p class="my-4">
|
||||||
Copyright (C) 2023 Shusui Moyatani and{' '}
|
Copyright (C) 2023 Shusui Moyatani and{' '}
|
||||||
@@ -84,12 +84,12 @@ const About: Component<AboutProps> = (props) => {
|
|||||||
</p>
|
</p>
|
||||||
|
|
||||||
<pre class=" max-h-96 overflow-auto rounded bg-bg-tertiary p-2 text-sm">
|
<pre class=" max-h-96 overflow-auto rounded bg-bg-tertiary p-2 text-sm">
|
||||||
{i18n()('about.agplText')}
|
{i18n.t('about.agplText')}
|
||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
<SafeLink class="text-link underline" href="https://gpl.mhatta.org/agpl.ja.html">
|
<SafeLink class="text-link underline" href="https://gpl.mhatta.org/agpl.ja.html">
|
||||||
{i18n()('about.agplTranslationJa')}
|
{i18n.t('about.agplTranslationJa')}
|
||||||
</SafeLink>
|
</SafeLink>
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
@@ -97,7 +97,7 @@ const About: Component<AboutProps> = (props) => {
|
|||||||
{packageInfo()?.self.licenseText}
|
{packageInfo()?.self.licenseText}
|
||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
<h2 class="my-4 text-xl font-bold">{i18n()('about.usingLibraries')}</h2>
|
<h2 class="my-4 text-xl font-bold">{i18n.t('about.usingLibraries')}</h2>
|
||||||
|
|
||||||
<For each={packageInfo()?.packages ?? []}>
|
<For each={packageInfo()?.packages ?? []}>
|
||||||
{(p) => (
|
{(p) => (
|
||||||
|
|||||||
@@ -84,28 +84,28 @@ const AddColumn: Component<AddColumnProps> = (props) => {
|
|||||||
class="flex basis-1/2 flex-col items-center gap-2 py-8 hover:text-primary sm:basis-1/4"
|
class="flex basis-1/2 flex-col items-center gap-2 py-8 hover:text-primary sm:basis-1/4"
|
||||||
onClick={() => addFollowingColumn()}
|
onClick={() => addFollowingColumn()}
|
||||||
>
|
>
|
||||||
<span class="inline-block h-8 w-8">
|
<span class="inline-block size-8">
|
||||||
<Home />
|
<Home />
|
||||||
</span>
|
</span>
|
||||||
{i18n()('column.home')}
|
{i18n.t('column.home')}
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
class="flex basis-1/2 flex-col items-center gap-2 py-8 hover:text-primary sm:basis-1/4"
|
class="flex basis-1/2 flex-col items-center gap-2 py-8 hover:text-primary sm:basis-1/4"
|
||||||
onClick={() => addNotificationColumn()}
|
onClick={() => addNotificationColumn()}
|
||||||
>
|
>
|
||||||
<span class="inline-block h-8 w-8">
|
<span class="inline-block size-8">
|
||||||
<Bell />
|
<Bell />
|
||||||
</span>
|
</span>
|
||||||
{i18n()('column.notification')}
|
{i18n.t('column.notification')}
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
class="flex basis-1/2 flex-col items-center gap-2 py-8 hover:text-primary sm:basis-1/4"
|
class="flex basis-1/2 flex-col items-center gap-2 py-8 hover:text-primary sm:basis-1/4"
|
||||||
onClick={() => addJapanRelaysColumn()}
|
onClick={() => addJapanRelaysColumn()}
|
||||||
>
|
>
|
||||||
<span class="inline-block h-8 w-8">
|
<span class="inline-block size-8">
|
||||||
<GlobeAlt />
|
<GlobeAlt />
|
||||||
</span>
|
</span>
|
||||||
{i18n()('column.japanese')}
|
{i18n.t('column.japanese')}
|
||||||
</button>
|
</button>
|
||||||
{/*
|
{/*
|
||||||
<button
|
<button
|
||||||
@@ -133,28 +133,28 @@ const AddColumn: Component<AddColumnProps> = (props) => {
|
|||||||
class="flex basis-1/2 flex-col items-center gap-2 py-8 hover:text-primary sm:basis-1/4"
|
class="flex basis-1/2 flex-col items-center gap-2 py-8 hover:text-primary sm:basis-1/4"
|
||||||
onClick={() => addSearchColumn()}
|
onClick={() => addSearchColumn()}
|
||||||
>
|
>
|
||||||
<span class="inline-block h-8 w-8">
|
<span class="inline-block size-8">
|
||||||
<MagnifyingGlass />
|
<MagnifyingGlass />
|
||||||
</span>
|
</span>
|
||||||
{i18n()('column.search')}
|
{i18n.t('column.search')}
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
class="flex basis-1/2 flex-col items-center gap-2 py-8 hover:text-primary sm:basis-1/4"
|
class="flex basis-1/2 flex-col items-center gap-2 py-8 hover:text-primary sm:basis-1/4"
|
||||||
onClick={() => addMyPostsColumn()}
|
onClick={() => addMyPostsColumn()}
|
||||||
>
|
>
|
||||||
<span class="inline-block h-8 w-8">
|
<span class="inline-block size-8">
|
||||||
<User />
|
<User />
|
||||||
</span>
|
</span>
|
||||||
{i18n()('column.myPosts')}
|
{i18n.t('column.myPosts')}
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
class="flex basis-1/2 flex-col items-center gap-2 py-8 hover:text-primary sm:basis-1/4"
|
class="flex basis-1/2 flex-col items-center gap-2 py-8 hover:text-primary sm:basis-1/4"
|
||||||
onClick={() => addMyReactionsColumn()}
|
onClick={() => addMyReactionsColumn()}
|
||||||
>
|
>
|
||||||
<span class="inline-block h-8 w-8">
|
<span class="inline-block size-8">
|
||||||
<Heart />
|
<Heart />
|
||||||
</span>
|
</span>
|
||||||
{i18n()('column.myReactions')}
|
{i18n.t('column.myReactions')}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</BasicModal>
|
</BasicModal>
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ const Section = (props: { title: string; initialOpened?: boolean; children: JSX.
|
|||||||
onClick={() => toggleOpened()}
|
onClick={() => toggleOpened()}
|
||||||
>
|
>
|
||||||
<span class="flex-1 hover:text-fg-secondary">{props.title}</span>
|
<span class="flex-1 hover:text-fg-secondary">{props.title}</span>
|
||||||
<span class="inline-block h-4 w-4 shrink-0 text-fg">
|
<span class="inline-block size-4 shrink-0 text-fg">
|
||||||
<Show when={opened()} fallback={<ChevronDown />}>
|
<Show when={opened()} fallback={<ChevronDown />}>
|
||||||
<ChevronUp />
|
<ChevronUp />
|
||||||
</Show>
|
</Show>
|
||||||
@@ -73,7 +73,7 @@ const ToggleButton = (props: {
|
|||||||
area-label={props.value}
|
area-label={props.value}
|
||||||
onClick={(event) => props.onClick(event)}
|
onClick={(event) => props.onClick(event)}
|
||||||
>
|
>
|
||||||
<span class="m-[-3px] inline-block h-5 w-5 rounded-full border bg-primary-fg shadow" />
|
<span class="m-[-3px] inline-block size-5 rounded-full border bg-primary-fg shadow" />
|
||||||
</button>
|
</button>
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -83,7 +83,7 @@ const ProfileSection = () => {
|
|||||||
const { showProfile, showProfileEdit } = useModalState();
|
const { showProfile, showProfileEdit } = useModalState();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Section title={i18n()('config.profile.profile')}>
|
<Section title={i18n.t('config.profile.profile')}>
|
||||||
<div class="flex gap-2 py-1">
|
<div class="flex gap-2 py-1">
|
||||||
<button
|
<button
|
||||||
class="rounded border border-primary px-4 py-1 font-bold text-primary"
|
class="rounded border border-primary px-4 py-1 font-bold text-primary"
|
||||||
@@ -93,13 +93,13 @@ const ProfileSection = () => {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
{i18n()('config.profile.openProfile')}
|
{i18n.t('config.profile.openProfile')}
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
class="rounded border border-primary px-4 py-1 font-bold text-primary"
|
class="rounded border border-primary px-4 py-1 font-bold text-primary"
|
||||||
onClick={() => showProfileEdit()}
|
onClick={() => showProfileEdit()}
|
||||||
>
|
>
|
||||||
{i18n()('config.profile.editProfile')}
|
{i18n.t('config.profile.editProfile')}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</Section>
|
</Section>
|
||||||
@@ -126,11 +126,11 @@ const RelayConfig = () => {
|
|||||||
const relayUrls = importedRelays.map(([relayUrl]) => relayUrl).join('\n');
|
const relayUrls = importedRelays.map(([relayUrl]) => relayUrl).join('\n');
|
||||||
|
|
||||||
if (importedRelays.length === 0) {
|
if (importedRelays.length === 0) {
|
||||||
window.alert(i18n()('config.relays.notConfigured'));
|
window.alert(i18n.t('config.relays.notConfigured'));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!window.confirm(`${i18n()('config.relays.askImport')}\n\n${relayUrls}`)) {
|
if (!window.confirm(`${i18n.t('config.relays.askImport')}\n\n${relayUrls}`)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -142,14 +142,14 @@ const RelayConfig = () => {
|
|||||||
});
|
});
|
||||||
const currentCount = config().relayUrls.length;
|
const currentCount = config().relayUrls.length;
|
||||||
const importedCount = currentCount - lastCount;
|
const importedCount = currentCount - lastCount;
|
||||||
window.alert(i18n()('config.relays.imported', { count: importedCount }));
|
window.alert(i18n.t('config.relays.imported', { count: importedCount }));
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Section title={i18n()('config.relays.relays')}>
|
<Section title={i18n.t('config.relays.relays')}>
|
||||||
<p class="py-1">
|
<p class="py-1">
|
||||||
{i18n()('config.relays.numOfRelays', { count: config().relayUrls.length })}
|
{i18n.t('config.relays.numOfRelays', { count: config().relayUrls.length })}
|
||||||
</p>
|
</p>
|
||||||
<form class="flex gap-2" onSubmit={handleClickAddRelay}>
|
<form class="flex gap-2" onSubmit={handleClickAddRelay}>
|
||||||
<input
|
<input
|
||||||
@@ -162,7 +162,7 @@ const RelayConfig = () => {
|
|||||||
onChange={(ev) => setRelayUrlInput(ev.currentTarget.value)}
|
onChange={(ev) => setRelayUrlInput(ev.currentTarget.value)}
|
||||||
/>
|
/>
|
||||||
<button type="submit" class="rounded bg-primary p-2 font-bold text-primary-fg">
|
<button type="submit" class="rounded bg-primary p-2 font-bold text-primary-fg">
|
||||||
{i18n()('config.relays.addRelay')}
|
{i18n.t('config.relays.addRelay')}
|
||||||
</button>
|
</button>
|
||||||
</form>
|
</form>
|
||||||
<ul class="pt-2">
|
<ul class="pt-2">
|
||||||
@@ -170,7 +170,7 @@ const RelayConfig = () => {
|
|||||||
{(relayUrl: string) => (
|
{(relayUrl: string) => (
|
||||||
<li class="flex items-center border-t border-border pr-4">
|
<li class="flex items-center border-t border-border pr-4">
|
||||||
<div class="flex-1 truncate">{relayUrl}</div>
|
<div class="flex-1 truncate">{relayUrl}</div>
|
||||||
<button class="h-3 w-3 shrink-0" onClick={() => removeRelay(relayUrl)}>
|
<button class="size-3 shrink-0" onClick={() => removeRelay(relayUrl)}>
|
||||||
<XMark />
|
<XMark />
|
||||||
</button>
|
</button>
|
||||||
</li>
|
</li>
|
||||||
@@ -178,18 +178,18 @@ const RelayConfig = () => {
|
|||||||
</For>
|
</For>
|
||||||
</ul>
|
</ul>
|
||||||
</Section>
|
</Section>
|
||||||
<Section title={i18n()('config.relays.importRelays')}>
|
<Section title={i18n.t('config.relays.importRelays')}>
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
class="rounded bg-primary p-2 font-bold text-primary-fg"
|
class="rounded bg-primary p-2 font-bold text-primary-fg"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
importFromNIP07().catch((err) => {
|
importFromNIP07().catch((err) => {
|
||||||
console.error('failed to import relays', err);
|
console.error('failed to import relays', err);
|
||||||
window.alert(i18n()('config.relays.failedToImport'));
|
window.alert(i18n.t('config.relays.failedToImport'));
|
||||||
});
|
});
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{i18n()('config.relays.importFromExtension')}
|
{i18n.t('config.relays.importFromExtension')}
|
||||||
</button>
|
</button>
|
||||||
</Section>
|
</Section>
|
||||||
</>
|
</>
|
||||||
@@ -213,7 +213,7 @@ const ColorThemeConfig = () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Section title={i18n()('config.display.colorTheme')}>
|
<Section title={i18n.t('config.display.colorTheme')}>
|
||||||
<div class="scrollbar flex flex-col overflow-y-auto rounded-md border border-border">
|
<div class="scrollbar flex flex-col overflow-y-auto rounded-md border border-border">
|
||||||
<For each={Object.values(colorThemes)}>
|
<For each={Object.values(colorThemes)}>
|
||||||
{(colorTheme) => (
|
{(colorTheme) => (
|
||||||
@@ -247,18 +247,18 @@ const DateFormatConfig = () => {
|
|||||||
}[] = [
|
}[] = [
|
||||||
{
|
{
|
||||||
id: 'relative',
|
id: 'relative',
|
||||||
name: i18n()('config.display.relativeTimeNotation'),
|
name: i18n.t('config.display.relativeTimeNotation'),
|
||||||
example: i18n()('config.display.relativeTimeNotationExample'),
|
example: i18n.t('config.display.relativeTimeNotationExample'),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 'absolute-short',
|
id: 'absolute-short',
|
||||||
name: i18n()('config.display.absoluteTimeNotationShort'),
|
name: i18n.t('config.display.absoluteTimeNotationShort'),
|
||||||
example: i18n()('config.display.absoluteTimeNotationShortExample'),
|
example: i18n.t('config.display.absoluteTimeNotationShortExample'),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 'absolute-long',
|
id: 'absolute-long',
|
||||||
name: i18n()('config.display.absoluteTimeNotationLong'),
|
name: i18n.t('config.display.absoluteTimeNotationLong'),
|
||||||
example: i18n()('config.display.absoluteTimeNotationLongExample'),
|
example: i18n.t('config.display.absoluteTimeNotationLongExample'),
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
@@ -267,7 +267,7 @@ const DateFormatConfig = () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Section title={i18n()('config.display.timeNotation')}>
|
<Section title={i18n.t('config.display.timeNotation')}>
|
||||||
<div class="flex flex-col justify-evenly gap-2 sm:flex-row">
|
<div class="flex flex-col justify-evenly gap-2 sm:flex-row">
|
||||||
<For each={dateFormats}>
|
<For each={dateFormats}>
|
||||||
{({ id, name, example }) => (
|
{({ id, name, example }) => (
|
||||||
@@ -313,17 +313,17 @@ const ReactionConfig = () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Section title={i18n()('config.display.reaction')}>
|
<Section title={i18n.t('config.display.reaction')}>
|
||||||
<div class="flex flex-col justify-evenly gap-2">
|
<div class="flex flex-col justify-evenly gap-2">
|
||||||
<div class="flex w-full">
|
<div class="flex w-full">
|
||||||
<div class="flex-1">{i18n()('config.display.enableEmojiReaction')}</div>
|
<div class="flex-1">{i18n.t('config.display.enableEmojiReaction')}</div>
|
||||||
<ToggleButton
|
<ToggleButton
|
||||||
value={config().useEmojiReaction}
|
value={config().useEmojiReaction}
|
||||||
onClick={() => toggleUseEmojiReaction()}
|
onClick={() => toggleUseEmojiReaction()}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex w-full">
|
<div class="flex w-full">
|
||||||
<div class="flex-1">{i18n()('config.display.showEmojiReaction')}</div>
|
<div class="flex-1">{i18n.t('config.display.showEmojiReaction')}</div>
|
||||||
<ToggleButton
|
<ToggleButton
|
||||||
value={config().showEmojiReaction}
|
value={config().showEmojiReaction}
|
||||||
onClick={() => toggleShowEmojiReaction()}
|
onClick={() => toggleShowEmojiReaction()}
|
||||||
@@ -350,10 +350,10 @@ const EmojiConfig = () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Section title={i18n()('config.customEmoji.customEmoji')}>
|
<Section title={i18n.t('config.customEmoji.customEmoji')}>
|
||||||
<form class="flex flex-col gap-2" onSubmit={handleClickSaveEmoji}>
|
<form class="flex flex-col gap-2" onSubmit={handleClickSaveEmoji}>
|
||||||
<label class="flex flex-1 items-center gap-1">
|
<label class="flex flex-1 items-center gap-1">
|
||||||
<div class="w-9">{i18n()('config.customEmoji.shortcode')}</div>
|
<div class="w-9">{i18n.t('config.customEmoji.shortcode')}</div>
|
||||||
<input
|
<input
|
||||||
class="flex-1 rounded-md border-border bg-bg placeholder:text-fg-secondary focus:border-border focus:ring-primary"
|
class="flex-1 rounded-md border-border bg-bg placeholder:text-fg-secondary focus:border-border focus:ring-primary"
|
||||||
type="text"
|
type="text"
|
||||||
@@ -366,7 +366,7 @@ const EmojiConfig = () => {
|
|||||||
/>
|
/>
|
||||||
</label>
|
</label>
|
||||||
<label class="flex flex-1 items-center gap-1">
|
<label class="flex flex-1 items-center gap-1">
|
||||||
<div class="w-9">{i18n()('config.customEmoji.url')}</div>
|
<div class="w-9">{i18n.t('config.customEmoji.url')}</div>
|
||||||
<input
|
<input
|
||||||
class="flex-1 rounded-md border-border bg-bg placeholder:text-fg-secondary focus:border-border focus:ring-primary"
|
class="flex-1 rounded-md border-border bg-bg placeholder:text-fg-secondary focus:border-border focus:ring-primary"
|
||||||
type="text"
|
type="text"
|
||||||
@@ -382,7 +382,7 @@ const EmojiConfig = () => {
|
|||||||
type="submit"
|
type="submit"
|
||||||
class="w-24 self-end rounded bg-primary p-2 font-bold text-primary-fg"
|
class="w-24 self-end rounded bg-primary p-2 font-bold text-primary-fg"
|
||||||
>
|
>
|
||||||
{i18n()('config.customEmoji.addEmoji')}
|
{i18n.t('config.customEmoji.addEmoji')}
|
||||||
</button>
|
</button>
|
||||||
</form>
|
</form>
|
||||||
<ul class="mt-4 flex max-h-[40vh] min-h-64 flex-wrap overflow-y-auto border-t border-border">
|
<ul class="mt-4 flex max-h-[40vh] min-h-64 flex-wrap overflow-y-auto border-t border-border">
|
||||||
@@ -401,7 +401,7 @@ const EmojiConfig = () => {
|
|||||||
class="w-full px-2 py-1 text-danger"
|
class="w-full px-2 py-1 text-danger"
|
||||||
onClick={() => removeEmoji(shortcode)}
|
onClick={() => removeEmoji(shortcode)}
|
||||||
>
|
>
|
||||||
{i18n()('config.customEmoji.removeEmoji')}
|
{i18n.t('config.customEmoji.removeEmoji')}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -415,7 +415,7 @@ const EmojiConfig = () => {
|
|||||||
class="flex w-full flex-col items-center gap-1 rounded p-2 hover:bg-bg-tertiary/20 hover:shadow"
|
class="flex w-full flex-col items-center gap-1 rounded p-2 hover:bg-bg-tertiary/20 hover:shadow"
|
||||||
onClick={() => popup.open()}
|
onClick={() => popup.open()}
|
||||||
>
|
>
|
||||||
<LazyLoad fallback={<div class="h-8 w-8" />}>
|
<LazyLoad fallback={<div class="size-8" />}>
|
||||||
{() => (
|
{() => (
|
||||||
<div class="flex h-8 max-w-8 items-center">
|
<div class="flex h-8 max-w-8 items-center">
|
||||||
<img class="object-contain" src={url} alt={shortcode} />
|
<img class="object-contain" src={url} alt={shortcode} />
|
||||||
@@ -456,8 +456,8 @@ const EmojiImport = () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Section title={i18n()('config.customEmoji.emojiImport')}>
|
<Section title={i18n.t('config.customEmoji.emojiImport')}>
|
||||||
<p>{i18n()('config.customEmoji.emojiImportDescription')}</p>
|
<p>{i18n.t('config.customEmoji.emojiImportDescription')}</p>
|
||||||
<form class="flex flex-col gap-2" onSubmit={handleClickSaveEmoji}>
|
<form class="flex flex-col gap-2" onSubmit={handleClickSaveEmoji}>
|
||||||
<textarea
|
<textarea
|
||||||
class="flex-1 rounded-md border-border bg-bg placeholder:text-fg-secondary focus:border-border focus:ring-primary"
|
class="flex-1 rounded-md border-border bg-bg placeholder:text-fg-secondary focus:border-border focus:ring-primary"
|
||||||
@@ -470,7 +470,7 @@ const EmojiImport = () => {
|
|||||||
type="submit"
|
type="submit"
|
||||||
class="w-24 self-end rounded bg-primary p-2 font-bold text-primary-fg"
|
class="w-24 self-end rounded bg-primary p-2 font-bold text-primary-fg"
|
||||||
>
|
>
|
||||||
{i18n()('config.customEmoji.importEmoji')}
|
{i18n.t('config.customEmoji.importEmoji')}
|
||||||
</button>
|
</button>
|
||||||
</form>
|
</form>
|
||||||
</Section>
|
</Section>
|
||||||
@@ -492,7 +492,7 @@ const MuteConfig = () => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Section title={i18n()('config.mute.mutedUsers')} initialOpened={false}>
|
<Section title={i18n.t('config.mute.mutedUsers')} initialOpened={false}>
|
||||||
<ul class="flex max-h-[50vh] min-h-64 flex-col overflow-y-auto">
|
<ul class="flex max-h-[50vh] min-h-64 flex-col overflow-y-auto">
|
||||||
<For each={config().mutedPubkeys}>
|
<For each={config().mutedPubkeys}>
|
||||||
{(pubkey) => (
|
{(pubkey) => (
|
||||||
@@ -500,7 +500,7 @@ const MuteConfig = () => {
|
|||||||
<div class="flex-1 truncate">
|
<div class="flex-1 truncate">
|
||||||
<LazyLoad>{() => <UserNameDisplay pubkey={pubkey} />}</LazyLoad>
|
<LazyLoad>{() => <UserNameDisplay pubkey={pubkey} />}</LazyLoad>
|
||||||
</div>
|
</div>
|
||||||
<button class="h-3 w-3 shrink-0" onClick={() => removeMutedPubkey(pubkey)}>
|
<button class="size-3 shrink-0" onClick={() => removeMutedPubkey(pubkey)}>
|
||||||
<XMark />
|
<XMark />
|
||||||
</button>
|
</button>
|
||||||
</li>
|
</li>
|
||||||
@@ -508,7 +508,7 @@ const MuteConfig = () => {
|
|||||||
</For>
|
</For>
|
||||||
</ul>
|
</ul>
|
||||||
</Section>
|
</Section>
|
||||||
<Section title={i18n()('config.mute.mutedKeywords')} initialOpened={false}>
|
<Section title={i18n.t('config.mute.mutedKeywords')} initialOpened={false}>
|
||||||
<form class="flex gap-2" onSubmit={handleClickAddKeyword}>
|
<form class="flex gap-2" onSubmit={handleClickAddKeyword}>
|
||||||
<input
|
<input
|
||||||
class="flex-1 rounded-md border border-border bg-bg ring-border focus:border-border focus:ring-primary"
|
class="flex-1 rounded-md border border-border bg-bg ring-border focus:border-border focus:ring-primary"
|
||||||
@@ -518,7 +518,7 @@ const MuteConfig = () => {
|
|||||||
onChange={(ev) => setKeywordInput(ev.currentTarget.value)}
|
onChange={(ev) => setKeywordInput(ev.currentTarget.value)}
|
||||||
/>
|
/>
|
||||||
<button type="submit" class="rounded bg-primary p-2 font-bold text-primary-fg">
|
<button type="submit" class="rounded bg-primary p-2 font-bold text-primary-fg">
|
||||||
{i18n()('config.mute.add')}
|
{i18n.t('config.mute.add')}
|
||||||
</button>
|
</button>
|
||||||
</form>
|
</form>
|
||||||
<ul class="mt-2 flex max-h-[50vh] min-h-64 flex-col overflow-y-auto border-t border-border">
|
<ul class="mt-2 flex max-h-[50vh] min-h-64 flex-col overflow-y-auto border-t border-border">
|
||||||
@@ -526,7 +526,7 @@ const MuteConfig = () => {
|
|||||||
{(keyword) => (
|
{(keyword) => (
|
||||||
<li class="flex items-center border-b border-border pr-4">
|
<li class="flex items-center border-b border-border pr-4">
|
||||||
<div class="flex-1 truncate">{keyword}</div>
|
<div class="flex-1 truncate">{keyword}</div>
|
||||||
<button class="h-3 w-3 shrink-0" onClick={() => removeMutedKeyword(keyword)}>
|
<button class="size-3 shrink-0" onClick={() => removeMutedKeyword(keyword)}>
|
||||||
<XMark />
|
<XMark />
|
||||||
</button>
|
</button>
|
||||||
</li>
|
</li>
|
||||||
@@ -553,8 +553,8 @@ const EmbeddingConfig = () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Section title={i18n()('config.display.embedding')}>
|
<Section title={i18n.t('config.display.embedding')}>
|
||||||
<p>{i18n()('config.display.embeddingDescription')}</p>
|
<p>{i18n.t('config.display.embeddingDescription')}</p>
|
||||||
<div class="flex flex-col justify-evenly gap-2">
|
<div class="flex flex-col justify-evenly gap-2">
|
||||||
<div class="flex w-full">
|
<div class="flex w-full">
|
||||||
<div class="flex-1">YouTube</div>
|
<div class="flex-1">YouTube</div>
|
||||||
@@ -599,21 +599,21 @@ const OtherConfig = () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Section title={i18n()('config.display.others')}>
|
<Section title={i18n.t('config.display.others')}>
|
||||||
<div class="flex flex-col justify-evenly gap-2">
|
<div class="flex flex-col justify-evenly gap-2">
|
||||||
<div class="flex w-full">
|
<div class="flex w-full">
|
||||||
<div class="flex-1">{i18n()('config.display.keepOpenPostForm')}</div>
|
<div class="flex-1">{i18n.t('config.display.keepOpenPostForm')}</div>
|
||||||
<ToggleButton
|
<ToggleButton
|
||||||
value={config().keepOpenPostForm}
|
value={config().keepOpenPostForm}
|
||||||
onClick={() => toggleKeepOpenPostForm()}
|
onClick={() => toggleKeepOpenPostForm()}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex w-full">
|
<div class="flex w-full">
|
||||||
<div class="flex-1">{i18n()('config.display.showMediaByDefault')}</div>
|
<div class="flex-1">{i18n.t('config.display.showMediaByDefault')}</div>
|
||||||
<ToggleButton value={config().showMedia} onClick={() => toggleShowMedia()} />
|
<ToggleButton value={config().showMedia} onClick={() => toggleShowMedia()} />
|
||||||
</div>
|
</div>
|
||||||
<div class="flex w-full">
|
<div class="flex w-full">
|
||||||
<div class="flex-1">{i18n()('config.display.hideNumbers')}</div>
|
<div class="flex-1">{i18n.t('config.display.hideNumbers')}</div>
|
||||||
<ToggleButton value={config().hideCount} onClick={() => toggleHideCount()} />
|
<ToggleButton value={config().hideCount} onClick={() => toggleHideCount()} />
|
||||||
</div>
|
</div>
|
||||||
{/*
|
{/*
|
||||||
@@ -638,17 +638,17 @@ const ConfigUI = (props: ConfigProps) => {
|
|||||||
|
|
||||||
const menu = [
|
const menu = [
|
||||||
{
|
{
|
||||||
name: () => i18n()('config.profile.profile'),
|
name: () => i18n.t('config.profile.profile'),
|
||||||
icon: () => <User />,
|
icon: () => <User />,
|
||||||
render: () => <ProfileSection />,
|
render: () => <ProfileSection />,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: () => i18n()('config.relays.relays'),
|
name: () => i18n.t('config.relays.relays'),
|
||||||
icon: () => <ServerStack />,
|
icon: () => <ServerStack />,
|
||||||
render: () => <RelayConfig />,
|
render: () => <RelayConfig />,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: () => i18n()('config.display.display'),
|
name: () => i18n.t('config.display.display'),
|
||||||
icon: () => <PaintBrush />,
|
icon: () => <PaintBrush />,
|
||||||
render: () => (
|
render: () => (
|
||||||
<>
|
<>
|
||||||
@@ -661,7 +661,7 @@ const ConfigUI = (props: ConfigProps) => {
|
|||||||
),
|
),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: () => i18n()('config.customEmoji.customEmoji'),
|
name: () => i18n.t('config.customEmoji.customEmoji'),
|
||||||
icon: () => <FaceSmile />,
|
icon: () => <FaceSmile />,
|
||||||
render: () => (
|
render: () => (
|
||||||
<>
|
<>
|
||||||
@@ -671,7 +671,7 @@ const ConfigUI = (props: ConfigProps) => {
|
|||||||
),
|
),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: () => i18n()('config.mute.mute'),
|
name: () => i18n.t('config.mute.mute'),
|
||||||
icon: () => <EyeSlash />,
|
icon: () => <EyeSlash />,
|
||||||
render: () => <MuteConfig />,
|
render: () => <MuteConfig />,
|
||||||
},
|
},
|
||||||
@@ -690,7 +690,7 @@ const ConfigUI = (props: ConfigProps) => {
|
|||||||
when={getMenuItem()}
|
when={getMenuItem()}
|
||||||
fallback={
|
fallback={
|
||||||
<>
|
<>
|
||||||
<h2 class="flex-1 text-center text-lg font-bold">{i18n()('config.config')}</h2>
|
<h2 class="flex-1 text-center text-lg font-bold">{i18n.t('config.config')}</h2>
|
||||||
<div class="flex gap-1">
|
<div class="flex gap-1">
|
||||||
<Show when={window.location.host === 'syusui-s.github.io'}>
|
<Show when={window.location.host === 'syusui-s.github.io'}>
|
||||||
<button
|
<button
|
||||||
@@ -703,7 +703,7 @@ const ConfigUI = (props: ConfigProps) => {
|
|||||||
.catch(() => window.alert('failed to copy'));
|
.catch(() => window.alert('failed to copy'));
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{i18n()('config.copyToClipboard')}
|
{i18n.t('config.copyToClipboard')}
|
||||||
</button>
|
</button>
|
||||||
</Show>
|
</Show>
|
||||||
<Show when={window.location.host === 'rabbit.syusui.net'}>
|
<Show when={window.location.host === 'rabbit.syusui.net'}>
|
||||||
@@ -722,7 +722,7 @@ const ConfigUI = (props: ConfigProps) => {
|
|||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{i18n()('config.importFromClipboard')}
|
{i18n.t('config.importFromClipboard')}
|
||||||
</button>
|
</button>
|
||||||
</Show>
|
</Show>
|
||||||
</div>
|
</div>
|
||||||
@@ -734,7 +734,7 @@ const ConfigUI = (props: ConfigProps) => {
|
|||||||
class="flex w-full gap-2 py-3 hover:text-primary"
|
class="flex w-full gap-2 py-3 hover:text-primary"
|
||||||
onClick={() => setMenuIndex(i)}
|
onClick={() => setMenuIndex(i)}
|
||||||
>
|
>
|
||||||
<span class="inline-block h-6 w-6">{menuItem.icon()}</span>
|
<span class="inline-block size-6">{menuItem.icon()}</span>
|
||||||
{menuItem.name()}
|
{menuItem.name()}
|
||||||
</button>
|
</button>
|
||||||
</li>
|
</li>
|
||||||
@@ -752,7 +752,7 @@ const ConfigUI = (props: ConfigProps) => {
|
|||||||
class="pr-4 text-fg hover:text-fg-secondary"
|
class="pr-4 text-fg hover:text-fg-secondary"
|
||||||
onClick={() => setMenuIndex(null)}
|
onClick={() => setMenuIndex(null)}
|
||||||
>
|
>
|
||||||
<span class="inline-block h-6 w-6">
|
<span class="inline-block size-6">
|
||||||
<ArrowLeft />
|
<ArrowLeft />
|
||||||
</span>
|
</span>
|
||||||
</button>
|
</button>
|
||||||
|
|||||||
@@ -151,12 +151,12 @@ const ProfileDisplay: Component<ProfileDisplayProps> = (props) => {
|
|||||||
|
|
||||||
if (
|
if (
|
||||||
(latest.data() == null || latest.followingPubkeys().length === 0) &&
|
(latest.data() == null || latest.followingPubkeys().length === 0) &&
|
||||||
!window.confirm(i18n()('profile.confirmUpdateEvenIfEmpty'))
|
!window.confirm(i18n.t('profile.confirmUpdateEvenIfEmpty'))
|
||||||
)
|
)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if ((latest?.data()?.created_at ?? 0) < (myFollowingQuery.data?.created_at ?? 0)) {
|
if ((latest?.data()?.created_at ?? 0) < (myFollowingQuery.data?.created_at ?? 0)) {
|
||||||
window.alert(i18n()('profile.failedToFetchLatestFollowList'));
|
window.alert(i18n.t('profile.failedToFetchLatestFollowList'));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -182,7 +182,7 @@ const ProfileDisplay: Component<ProfileDisplayProps> = (props) => {
|
|||||||
});
|
});
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error('failed to update contact list', err);
|
console.error('failed to update contact list', err);
|
||||||
window.alert(i18n()('profile.failedToUpdateFollowList'));
|
window.alert(i18n.t('profile.failedToUpdateFollowList'));
|
||||||
} finally {
|
} finally {
|
||||||
setUpdatingContacts(false);
|
setUpdatingContacts(false);
|
||||||
}
|
}
|
||||||
@@ -195,7 +195,7 @@ const ProfileDisplay: Component<ProfileDisplayProps> = (props) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const unfollow = () => {
|
const unfollow = () => {
|
||||||
if (!window.confirm(i18n()('profile.confirmUnfollow'))) return;
|
if (!window.confirm(i18n.t('profile.confirmUnfollow'))) return;
|
||||||
|
|
||||||
updateContacts('unfollow', props.pubkey).catch((err) => {
|
updateContacts('unfollow', props.pubkey).catch((err) => {
|
||||||
console.log('failed to unfollow', err);
|
console.log('failed to unfollow', err);
|
||||||
@@ -213,13 +213,13 @@ const ProfileDisplay: Component<ProfileDisplayProps> = (props) => {
|
|||||||
},
|
},
|
||||||
*/
|
*/
|
||||||
{
|
{
|
||||||
content: i18n()('profile.copyPubkey'),
|
content: i18n.t('profile.copyPubkey'),
|
||||||
onSelect: () => {
|
onSelect: () => {
|
||||||
navigator.clipboard.writeText(npub()).catch((err) => window.alert(err));
|
navigator.clipboard.writeText(npub()).catch((err) => window.alert(err));
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
content: i18n()('profile.addUserColumn'),
|
content: i18n.t('profile.addUserColumn'),
|
||||||
onSelect: () => {
|
onSelect: () => {
|
||||||
const columnName = profile()?.name ?? npub();
|
const columnName = profile()?.name ?? npub();
|
||||||
saveColumn(createPostsColumn({ name: columnName, pubkey: props.pubkey }));
|
saveColumn(createPostsColumn({ name: columnName, pubkey: props.pubkey }));
|
||||||
@@ -228,16 +228,16 @@ const ProfileDisplay: Component<ProfileDisplayProps> = (props) => {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
content: i18n()('profile.addUserHomeColumn'),
|
content: i18n.t('profile.addUserHomeColumn'),
|
||||||
onSelect: () => {
|
onSelect: () => {
|
||||||
const columnName = `${i18n()('column.home')} / ${profile()?.name ?? npub()}`;
|
const columnName = `${i18n.t('column.home')} / ${profile()?.name ?? npub()}`;
|
||||||
saveColumn(createFollowingColumn({ name: columnName, pubkey: props.pubkey }));
|
saveColumn(createFollowingColumn({ name: columnName, pubkey: props.pubkey }));
|
||||||
request({ command: 'moveToLastColumn' }).catch((err) => console.error(err));
|
request({ command: 'moveToLastColumn' }).catch((err) => console.error(err));
|
||||||
props.onClose?.();
|
props.onClose?.();
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
content: !isMuted() ? i18n()('profile.mute') : i18n()('profile.unmute'),
|
content: !isMuted() ? i18n.t('profile.mute') : i18n.t('profile.unmute'),
|
||||||
onSelect: () => {
|
onSelect: () => {
|
||||||
if (!isMuted()) {
|
if (!isMuted()) {
|
||||||
addMutedPubkey(props.pubkey);
|
addMutedPubkey(props.pubkey);
|
||||||
@@ -248,7 +248,7 @@ const ProfileDisplay: Component<ProfileDisplayProps> = (props) => {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
when: () => props.pubkey === myPubkey(),
|
when: () => props.pubkey === myPubkey(),
|
||||||
content: !following() ? i18n()('profile.followMyself') : i18n()('profile.unfollowMyself'),
|
content: !following() ? i18n.t('profile.followMyself') : i18n.t('profile.unfollowMyself'),
|
||||||
onSelect: () => {
|
onSelect: () => {
|
||||||
if (!following()) {
|
if (!following()) {
|
||||||
follow();
|
follow();
|
||||||
@@ -282,16 +282,16 @@ const ProfileDisplay: Component<ProfileDisplayProps> = (props) => {
|
|||||||
>
|
>
|
||||||
{(bannerUrl) => (
|
{(bannerUrl) => (
|
||||||
<div class="h-40 w-full shrink-0 sm:h-52">
|
<div class="h-40 w-full shrink-0 sm:h-52">
|
||||||
<img src={bannerUrl} alt="header" class="h-full w-full object-cover" />
|
<img src={bannerUrl} alt="header" class="size-full object-cover" />
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</Show>
|
</Show>
|
||||||
<div class="mt-[-54px] flex items-end gap-4 px-4 pt-4">
|
<div class="mt-[-54px] flex items-end gap-4 px-4 pt-4">
|
||||||
<div class="flex-1 shrink-0">
|
<div class="flex-1 shrink-0">
|
||||||
<div class="h-28 w-28 overflow-hidden rounded-lg shadow-md">
|
<div class="size-28 overflow-hidden rounded-lg shadow-md">
|
||||||
<Show when={profileQuery.isFetched && profile()?.picture} keyed>
|
<Show when={profileQuery.isFetched && profile()?.picture} keyed>
|
||||||
{(pictureUrl) => (
|
{(pictureUrl) => (
|
||||||
<img src={pictureUrl} alt="user icon" class="h-full w-full object-cover" />
|
<img src={pictureUrl} alt="user icon" class="size-full object-cover" />
|
||||||
)}
|
)}
|
||||||
</Show>
|
</Show>
|
||||||
</div>
|
</div>
|
||||||
@@ -306,17 +306,17 @@ const ProfileDisplay: Component<ProfileDisplayProps> = (props) => {
|
|||||||
text-center font-bold text-primary hover:bg-primary hover:text-primary-fg sm:w-20"
|
text-center font-bold text-primary hover:bg-primary hover:text-primary-fg sm:w-20"
|
||||||
onClick={() => showProfileEdit()}
|
onClick={() => showProfileEdit()}
|
||||||
>
|
>
|
||||||
{i18n()('profile.editProfile')}
|
{i18n.t('profile.editProfile')}
|
||||||
</button>
|
</button>
|
||||||
</Match>
|
</Match>
|
||||||
<Match when={updateContactsMutation.isPending || updatingContacts()}>
|
<Match when={updateContactsMutation.isPending || updatingContacts()}>
|
||||||
<span class="rounded-full border border-primary px-4 py-2 text-primary sm:text-base">
|
<span class="rounded-full border border-primary px-4 py-2 text-primary sm:text-base">
|
||||||
{i18n()('general.updating')}
|
{i18n.t('general.updating')}
|
||||||
</span>
|
</span>
|
||||||
</Match>
|
</Match>
|
||||||
<Match when={myFollowingQuery.isPending || myFollowingQuery.isFetching}>
|
<Match when={myFollowingQuery.isPending || myFollowingQuery.isFetching}>
|
||||||
<span class="rounded-full border border-primary px-4 py-2 text-primary sm:text-base">
|
<span class="rounded-full border border-primary px-4 py-2 text-primary sm:text-base">
|
||||||
{i18n()('general.loading')}
|
{i18n.t('general.loading')}
|
||||||
</span>
|
</span>
|
||||||
</Match>
|
</Match>
|
||||||
<Match when={following()}>
|
<Match when={following()}>
|
||||||
@@ -327,8 +327,8 @@ const ProfileDisplay: Component<ProfileDisplayProps> = (props) => {
|
|||||||
onClick={() => unfollow()}
|
onClick={() => unfollow()}
|
||||||
disabled={updateContactsMutation.isPending}
|
disabled={updateContactsMutation.isPending}
|
||||||
>
|
>
|
||||||
<Show when={!hoverFollowButton()} fallback={i18n()('profile.unfollow')}>
|
<Show when={!hoverFollowButton()} fallback={i18n.t('profile.unfollow')}>
|
||||||
{i18n()('profile.followingCurrently')}
|
{i18n.t('profile.followingCurrently')}
|
||||||
</Show>
|
</Show>
|
||||||
</button>
|
</button>
|
||||||
</Match>
|
</Match>
|
||||||
@@ -338,7 +338,7 @@ const ProfileDisplay: Component<ProfileDisplayProps> = (props) => {
|
|||||||
onClick={() => follow()}
|
onClick={() => follow()}
|
||||||
disabled={updateContactsMutation.isPending}
|
disabled={updateContactsMutation.isPending}
|
||||||
>
|
>
|
||||||
{i18n()('profile.follow')}
|
{i18n.t('profile.follow')}
|
||||||
</button>
|
</button>
|
||||||
</Match>
|
</Match>
|
||||||
</Switch>
|
</Switch>
|
||||||
@@ -354,10 +354,10 @@ const ProfileDisplay: Component<ProfileDisplayProps> = (props) => {
|
|||||||
</div>
|
</div>
|
||||||
<Switch>
|
<Switch>
|
||||||
<Match when={userFollowingQuery.isPending}>
|
<Match when={userFollowingQuery.isPending}>
|
||||||
<div class="shrink-0 text-xs">{i18n()('general.loading')}</div>
|
<div class="shrink-0 text-xs">{i18n.t('general.loading')}</div>
|
||||||
</Match>
|
</Match>
|
||||||
<Match when={followed()}>
|
<Match when={followed()}>
|
||||||
<div class="shrink-0 text-xs">{i18n()('profile.followsYou')}</div>
|
<div class="shrink-0 text-xs">{i18n.t('profile.followsYou')}</div>
|
||||||
</Match>
|
</Match>
|
||||||
</Switch>
|
</Switch>
|
||||||
</div>
|
</div>
|
||||||
@@ -365,7 +365,7 @@ const ProfileDisplay: Component<ProfileDisplayProps> = (props) => {
|
|||||||
</div>
|
</div>
|
||||||
<div class="flex items-start px-4 pt-2">
|
<div class="flex items-start px-4 pt-2">
|
||||||
<div class="h-16 shrink overflow-hidden">
|
<div class="h-16 shrink overflow-hidden">
|
||||||
<Show when={profileQuery.isPending}>{i18n()('general.loading')}</Show>
|
<Show when={profileQuery.isPending}>{i18n.t('general.loading')}</Show>
|
||||||
<Show when={(profile()?.display_name?.length ?? 0) > 0}>
|
<Show when={(profile()?.display_name?.length ?? 0) > 0}>
|
||||||
<div class="truncate text-xl font-bold">{profile()?.display_name}</div>
|
<div class="truncate text-xl font-bold">{profile()?.display_name}</div>
|
||||||
</Show>
|
</Show>
|
||||||
@@ -378,18 +378,18 @@ const ProfileDisplay: Component<ProfileDisplayProps> = (props) => {
|
|||||||
{nip05Identifier()?.ident}
|
{nip05Identifier()?.ident}
|
||||||
<Switch
|
<Switch
|
||||||
fallback={
|
fallback={
|
||||||
<span class="inline-block h-4 w-4 text-danger">
|
<span class="inline-block size-4 text-danger">
|
||||||
<ExclamationCircle />
|
<ExclamationCircle />
|
||||||
</span>
|
</span>
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
<Match when={verificationQuery.isPending}>
|
<Match when={verificationQuery.isPending}>
|
||||||
<span class="inline-block h-3 w-3">
|
<span class="inline-block size-3">
|
||||||
<ArrowPath />
|
<ArrowPath />
|
||||||
</span>
|
</span>
|
||||||
</Match>
|
</Match>
|
||||||
<Match when={isVerified()}>
|
<Match when={isVerified()}>
|
||||||
<span class="inline-block h-4 w-4 text-link">
|
<span class="inline-block size-4 text-link">
|
||||||
<CheckCircle />
|
<CheckCircle />
|
||||||
</span>
|
</span>
|
||||||
</Match>
|
</Match>
|
||||||
@@ -411,11 +411,11 @@ const ProfileDisplay: Component<ProfileDisplayProps> = (props) => {
|
|||||||
</Show>
|
</Show>
|
||||||
<div class="flex border-t border-border px-4 py-2">
|
<div class="flex border-t border-border px-4 py-2">
|
||||||
<button class="flex flex-1 flex-col items-start" onClick={() => setModal('Following')}>
|
<button class="flex flex-1 flex-col items-start" onClick={() => setModal('Following')}>
|
||||||
<div class="text-sm">{i18n()('profile.following')}</div>
|
<div class="text-sm">{i18n.t('profile.following')}</div>
|
||||||
<div class="text-xl">
|
<div class="text-xl">
|
||||||
<Show
|
<Show
|
||||||
when={userFollowingQuery.isFetched}
|
when={userFollowingQuery.isFetched}
|
||||||
fallback={<span class="text-sm">{i18n()('general.loading')}</span>}
|
fallback={<span class="text-sm">{i18n.t('general.loading')}</span>}
|
||||||
>
|
>
|
||||||
{userFollowingPubkeys().length}
|
{userFollowingPubkeys().length}
|
||||||
</Show>
|
</Show>
|
||||||
@@ -423,7 +423,7 @@ const ProfileDisplay: Component<ProfileDisplayProps> = (props) => {
|
|||||||
</button>
|
</button>
|
||||||
<Show when={!config().hideCount}>
|
<Show when={!config().hideCount}>
|
||||||
<div class="flex flex-1 flex-col items-start">
|
<div class="flex flex-1 flex-col items-start">
|
||||||
<div class="text-sm">{i18n()('profile.followers')}</div>
|
<div class="text-sm">{i18n.t('profile.followers')}</div>
|
||||||
<div class="text-xl">
|
<div class="text-xl">
|
||||||
<Show
|
<Show
|
||||||
when={showFollowers()}
|
when={showFollowers()}
|
||||||
@@ -432,7 +432,7 @@ const ProfileDisplay: Component<ProfileDisplayProps> = (props) => {
|
|||||||
class="text-sm hover:text-fg-secondary"
|
class="text-sm hover:text-fg-secondary"
|
||||||
onClick={() => setShowFollowers(true)}
|
onClick={() => setShowFollowers(true)}
|
||||||
>
|
>
|
||||||
{i18n()('profile.loadFollowers')}
|
{i18n.t('profile.loadFollowers')}
|
||||||
</button>
|
</button>
|
||||||
}
|
}
|
||||||
keyed
|
keyed
|
||||||
@@ -448,7 +448,7 @@ const ProfileDisplay: Component<ProfileDisplayProps> = (props) => {
|
|||||||
<Show when={profile()?.website} keyed>
|
<Show when={profile()?.website} keyed>
|
||||||
{(website) => (
|
{(website) => (
|
||||||
<li class="flex items-center gap-1">
|
<li class="flex items-center gap-1">
|
||||||
<span class="inline-block h-4 w-4" area-label="website" title="website">
|
<span class="inline-block size-4" area-label="website" title="website">
|
||||||
<GlobeAlt />
|
<GlobeAlt />
|
||||||
</span>
|
</span>
|
||||||
<SafeLink class="text-link underline" href={website} />
|
<SafeLink class="text-link underline" href={website} />
|
||||||
|
|||||||
@@ -58,11 +58,11 @@ const ProfileEdit: Component<ProfileEditProps> = (props) => {
|
|||||||
const succeeded = results.filter((res) => res.status === 'fulfilled').length;
|
const succeeded = results.filter((res) => res.status === 'fulfilled').length;
|
||||||
const failed = results.length - succeeded;
|
const failed = results.length - succeeded;
|
||||||
if (succeeded === results.length) {
|
if (succeeded === results.length) {
|
||||||
window.alert(i18n()('profile.edit.updateSucceeded'));
|
window.alert(i18n.t('profile.edit.updateSucceeded'));
|
||||||
} else if (succeeded > 0) {
|
} else if (succeeded > 0) {
|
||||||
window.alert(i18n()('profile.edit.failedToUpdatePartially', { count: failed }));
|
window.alert(i18n.t('profile.edit.failedToUpdatePartially', { count: failed }));
|
||||||
} else {
|
} else {
|
||||||
window.alert(i18n()('profile.edit.failedToUpdate'));
|
window.alert(i18n.t('profile.edit.failedToUpdate'));
|
||||||
}
|
}
|
||||||
invalidateProfile()
|
invalidateProfile()
|
||||||
.then(() => query.refetch())
|
.then(() => query.refetch())
|
||||||
@@ -149,23 +149,23 @@ const ProfileEdit: Component<ProfileEditProps> = (props) => {
|
|||||||
<div>
|
<div>
|
||||||
<Show when={banner().length > 0} fallback={<div class="h-24 shrink-0" />} keyed>
|
<Show when={banner().length > 0} fallback={<div class="h-24 shrink-0" />} keyed>
|
||||||
<div class="h-40 w-full shrink-0 sm:h-52">
|
<div class="h-40 w-full shrink-0 sm:h-52">
|
||||||
<img src={banner()} alt="header" class="h-full w-full object-cover" />
|
<img src={banner()} alt="header" class="size-full object-cover" />
|
||||||
</div>
|
</div>
|
||||||
</Show>
|
</Show>
|
||||||
<div class="ml-4 mt-[-64px] h-28 w-28 rounded-lg shadow-md">
|
<div class="ml-4 mt-[-64px] size-28 rounded-lg shadow-md">
|
||||||
<Show when={picture().length > 0}>
|
<Show when={picture().length > 0}>
|
||||||
<img src={picture()} alt="user icon" class="h-full w-full rounded-lg object-cover" />
|
<img src={picture()} alt="user icon" class="size-full rounded-lg object-cover" />
|
||||||
</Show>
|
</Show>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<Show when={loading()}>
|
<Show when={loading()}>
|
||||||
<div class="px-4 pt-4">{i18n()('general.loading')}</div>
|
<div class="px-4 pt-4">{i18n.t('general.loading')}</div>
|
||||||
</Show>
|
</Show>
|
||||||
<div>
|
<div>
|
||||||
<form class="flex flex-col gap-4 p-4" onSubmit={handleSubmit}>
|
<form class="flex flex-col gap-4 p-4" onSubmit={handleSubmit}>
|
||||||
<div class="flex flex-col items-start gap-1">
|
<div class="flex flex-col items-start gap-1">
|
||||||
<label class="font-bold" for="picture">
|
<label class="font-bold" for="picture">
|
||||||
{i18n()('profile.edit.icon')}
|
{i18n.t('profile.edit.icon')}
|
||||||
</label>
|
</label>
|
||||||
<input
|
<input
|
||||||
class="w-full rounded-md border-border bg-bg ring-border focus:border-border focus:ring-primary"
|
class="w-full rounded-md border-border bg-bg ring-border focus:border-border focus:ring-primary"
|
||||||
@@ -181,7 +181,7 @@ const ProfileEdit: Component<ProfileEditProps> = (props) => {
|
|||||||
</div>
|
</div>
|
||||||
<div class="flex flex-col items-start gap-1">
|
<div class="flex flex-col items-start gap-1">
|
||||||
<label class="font-bold" for="picture">
|
<label class="font-bold" for="picture">
|
||||||
{i18n()('profile.edit.banner')}
|
{i18n.t('profile.edit.banner')}
|
||||||
</label>
|
</label>
|
||||||
<input
|
<input
|
||||||
class="w-full rounded-md border-border bg-bg focus:border-border focus:ring-primary"
|
class="w-full rounded-md border-border bg-bg focus:border-border focus:ring-primary"
|
||||||
@@ -197,7 +197,7 @@ const ProfileEdit: Component<ProfileEditProps> = (props) => {
|
|||||||
</div>
|
</div>
|
||||||
<div class="flex flex-col items-start gap-1">
|
<div class="flex flex-col items-start gap-1">
|
||||||
<label class="font-bold" for="name">
|
<label class="font-bold" for="name">
|
||||||
{i18n()('profile.edit.name')}
|
{i18n.t('profile.edit.name')}
|
||||||
</label>
|
</label>
|
||||||
<div class="flex w-full items-center gap-2">
|
<div class="flex w-full items-center gap-2">
|
||||||
<span>@</span>
|
<span>@</span>
|
||||||
@@ -217,7 +217,7 @@ const ProfileEdit: Component<ProfileEditProps> = (props) => {
|
|||||||
</div>
|
</div>
|
||||||
<div class="flex flex-col items-start gap-1">
|
<div class="flex flex-col items-start gap-1">
|
||||||
<label class="font-bold" for="name">
|
<label class="font-bold" for="name">
|
||||||
{i18n()('profile.edit.displayName')}
|
{i18n.t('profile.edit.displayName')}
|
||||||
</label>
|
</label>
|
||||||
<input
|
<input
|
||||||
class="w-full rounded-md border-border bg-bg ring-border focus:border-border focus:ring-primary"
|
class="w-full rounded-md border-border bg-bg ring-border focus:border-border focus:ring-primary"
|
||||||
@@ -232,7 +232,7 @@ const ProfileEdit: Component<ProfileEditProps> = (props) => {
|
|||||||
</div>
|
</div>
|
||||||
<div class="flex flex-col items-start gap-1">
|
<div class="flex flex-col items-start gap-1">
|
||||||
<label class="font-bold" for="name">
|
<label class="font-bold" for="name">
|
||||||
{i18n()('profile.edit.about')}
|
{i18n.t('profile.edit.about')}
|
||||||
</label>
|
</label>
|
||||||
<textarea
|
<textarea
|
||||||
class="w-full rounded-md border-border bg-bg ring-border focus:border-border focus:ring-primary"
|
class="w-full rounded-md border-border bg-bg ring-border focus:border-border focus:ring-primary"
|
||||||
@@ -245,7 +245,7 @@ const ProfileEdit: Component<ProfileEditProps> = (props) => {
|
|||||||
</div>
|
</div>
|
||||||
<div class="flex flex-col items-start gap-1">
|
<div class="flex flex-col items-start gap-1">
|
||||||
<label class="font-bold" for="name">
|
<label class="font-bold" for="name">
|
||||||
{i18n()('profile.edit.website')}
|
{i18n.t('profile.edit.website')}
|
||||||
</label>
|
</label>
|
||||||
<input
|
<input
|
||||||
class="w-full rounded-md border-border bg-bg ring-border focus:border-border focus:ring-primary"
|
class="w-full rounded-md border-border bg-bg ring-border focus:border-border focus:ring-primary"
|
||||||
@@ -260,7 +260,7 @@ const ProfileEdit: Component<ProfileEditProps> = (props) => {
|
|||||||
</div>
|
</div>
|
||||||
<div class="flex flex-col items-start gap-1">
|
<div class="flex flex-col items-start gap-1">
|
||||||
<label class="font-bold" for="name">
|
<label class="font-bold" for="name">
|
||||||
{i18n()('profile.edit.nip05')}
|
{i18n.t('profile.edit.nip05')}
|
||||||
</label>
|
</label>
|
||||||
<input
|
<input
|
||||||
class="w-full rounded-md border-border bg-bg ring-border focus:border-border focus:ring-primary"
|
class="w-full rounded-md border-border bg-bg ring-border focus:border-border focus:ring-primary"
|
||||||
@@ -276,9 +276,9 @@ const ProfileEdit: Component<ProfileEditProps> = (props) => {
|
|||||||
</div>
|
</div>
|
||||||
<div class="flex flex-col items-start gap-1">
|
<div class="flex flex-col items-start gap-1">
|
||||||
<label class="font-bold" for="name">
|
<label class="font-bold" for="name">
|
||||||
{i18n()('profile.edit.lightningAddress')}
|
{i18n.t('profile.edit.lightningAddress')}
|
||||||
</label>
|
</label>
|
||||||
<span class="text-xs">{i18n()('profile.edit.lightningAddressDescription')}</span>
|
<span class="text-xs">{i18n.t('profile.edit.lightningAddressDescription')}</span>
|
||||||
<input
|
<input
|
||||||
class="w-full rounded-md border-border bg-bg ring-border focus:border-border focus:ring-primary"
|
class="w-full rounded-md border-border bg-bg ring-border focus:border-border focus:ring-primary"
|
||||||
type="text"
|
type="text"
|
||||||
@@ -293,7 +293,7 @@ const ProfileEdit: Component<ProfileEditProps> = (props) => {
|
|||||||
</div>
|
</div>
|
||||||
<Show when={Object.entries(otherProperties()).length > 0}>
|
<Show when={Object.entries(otherProperties()).length > 0}>
|
||||||
<div>
|
<div>
|
||||||
<span class="font-bold">{i18n()('profile.edit.otherProperties')}</span>
|
<span class="font-bold">{i18n.t('profile.edit.otherProperties')}</span>
|
||||||
<div>
|
<div>
|
||||||
<For each={Object.entries(otherProperties())}>
|
<For each={Object.entries(otherProperties())}>
|
||||||
{([key, value]) => (
|
{([key, value]) => (
|
||||||
@@ -316,17 +316,17 @@ const ProfileEdit: Component<ProfileEditProps> = (props) => {
|
|||||||
}}
|
}}
|
||||||
disabled={mutation.isPending}
|
disabled={mutation.isPending}
|
||||||
>
|
>
|
||||||
{i18n()('profile.edit.save')}
|
{i18n.t('profile.edit.save')}
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
class="rounded border border-primary p-2 font-bold text-primary hover:border-primary-hover hover:text-primary-hover"
|
class="rounded border border-primary p-2 font-bold text-primary hover:border-primary-hover hover:text-primary-hover"
|
||||||
onClick={() => props.onClose()}
|
onClick={() => props.onClose()}
|
||||||
>
|
>
|
||||||
{i18n()('profile.edit.cancel')}
|
{i18n.t('profile.edit.cancel')}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<Show when={mutation.isPending}>{i18n()('profile.edit.updating')}</Show>
|
<Show when={mutation.isPending}>{i18n.t('profile.edit.updating')}</Show>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
</BasicModal>
|
</BasicModal>
|
||||||
|
|||||||
@@ -143,10 +143,10 @@ const InvoiceDisplay: Component<{ invoice: string; event: NostrEvent; nostrPubke
|
|||||||
when={!zapped()}
|
when={!zapped()}
|
||||||
fallback={
|
fallback={
|
||||||
<div class="flex flex-col items-center gap-4 py-8">
|
<div class="flex flex-col items-center gap-4 py-8">
|
||||||
<span class="inline-block h-28 w-28 rounded-full border-4 border-primary p-4 text-primary">
|
<span class="inline-block size-28 rounded-full border-4 border-primary p-4 text-primary">
|
||||||
<Check />
|
<Check />
|
||||||
</span>
|
</span>
|
||||||
<div class="text-secondary text-xl">{i18n()('zap.completed')}</div>
|
<div class="text-secondary text-xl">{i18n.t('zap.completed')}</div>
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
@@ -158,7 +158,7 @@ const InvoiceDisplay: Component<{ invoice: string; event: NostrEvent; nostrPubke
|
|||||||
class="inline-block rounded bg-primary p-4 font-bold text-primary-fg hover:bg-primary-hover"
|
class="inline-block rounded bg-primary p-4 font-bold text-primary-fg hover:bg-primary-hover"
|
||||||
href={lightingInvoice()}
|
href={lightingInvoice()}
|
||||||
>
|
>
|
||||||
{i18n()('zap.sendViaWallet')}
|
{i18n.t('zap.sendViaWallet')}
|
||||||
</a>
|
</a>
|
||||||
<Show when={webln.status() === 'available'}>
|
<Show when={webln.status() === 'available'}>
|
||||||
<button
|
<button
|
||||||
@@ -166,7 +166,7 @@ const InvoiceDisplay: Component<{ invoice: string; event: NostrEvent; nostrPubke
|
|||||||
class="inline-block rounded bg-primary p-4 font-bold text-primary-fg hover:bg-primary-hover"
|
class="inline-block rounded bg-primary p-4 font-bold text-primary-fg hover:bg-primary-hover"
|
||||||
onClick={handleClickWebLN}
|
onClick={handleClickWebLN}
|
||||||
>
|
>
|
||||||
{i18n()('zap.sendViaWebLN')}
|
{i18n.t('zap.sendViaWebLN')}
|
||||||
</button>
|
</button>
|
||||||
</Show>
|
</Show>
|
||||||
</div>
|
</div>
|
||||||
@@ -274,19 +274,19 @@ const ZapDialog: Component<ZapDialogProps> = (props) => {
|
|||||||
return (
|
return (
|
||||||
<Switch>
|
<Switch>
|
||||||
<Match when={query.isError}>
|
<Match when={query.isError}>
|
||||||
{i18n()('zap.fetchingLnUrlEndpointError')}: {query?.error?.message}
|
{i18n.t('zap.fetchingLnUrlEndpointError')}: {query?.error?.message}
|
||||||
</Match>
|
</Match>
|
||||||
<Match when={error()} keyed>
|
<Match when={error()} keyed>
|
||||||
{(err) => (
|
{(err) => (
|
||||||
<>
|
<>
|
||||||
{i18n()('zap.lnUrlEndpointError')}: {err.reason}
|
{i18n.t('zap.lnUrlEndpointError')}: {err.reason}
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
</Match>
|
</Match>
|
||||||
<Match when={query.isFetching}>{i18n()('zap.fetchingLnUrlEndpoint')}</Match>
|
<Match when={query.isFetching}>{i18n.t('zap.fetchingLnUrlEndpoint')}</Match>
|
||||||
<Match when={getInvoiceMutation.isPending}>{i18n()('zap.fetchingLnUrlInvoice')}</Match>
|
<Match when={getInvoiceMutation.isPending}>{i18n.t('zap.fetchingLnUrlInvoice')}</Match>
|
||||||
<Match when={getInvoiceMutation.isError}>
|
<Match when={getInvoiceMutation.isError}>
|
||||||
{i18n()('zap.fetchingLnUrlInvoiceError')}: {getInvoiceMutation?.error?.message}
|
{i18n.t('zap.fetchingLnUrlInvoiceError')}: {getInvoiceMutation?.error?.message}
|
||||||
</Match>
|
</Match>
|
||||||
<Match when={getInvoiceMutation.isSuccess && getInvoiceMutation.data} keyed>
|
<Match when={getInvoiceMutation.isSuccess && getInvoiceMutation.data} keyed>
|
||||||
{(invoice) => (
|
{(invoice) => (
|
||||||
@@ -300,10 +300,10 @@ const ZapDialog: Component<ZapDialogProps> = (props) => {
|
|||||||
<Match when={query.isSuccess}>
|
<Match when={query.isSuccess}>
|
||||||
<div class="flex flex-col items-center">
|
<div class="flex flex-col items-center">
|
||||||
<Show when={!allowsNostr()}>
|
<Show when={!allowsNostr()}>
|
||||||
<div class="pb-8 text-center">{i18n()('zap.lnurlServiceDoesNotAllowNostr')}</div>
|
<div class="pb-8 text-center">{i18n.t('zap.lnurlServiceDoesNotAllowNostr')}</div>
|
||||||
</Show>
|
</Show>
|
||||||
<Show when={hasZapTag()}>
|
<Show when={hasZapTag()}>
|
||||||
<div class="pb-8 text-center">{i18n()('zap.zapSplitIsNotSupported')}</div>
|
<div class="pb-8 text-center">{i18n.t('zap.zapSplitIsNotSupported')}</div>
|
||||||
</Show>
|
</Show>
|
||||||
<div class="flex flex-col items-center overflow-hidden rounded px-8 py-2 text-fg-secondary">
|
<div class="flex flex-col items-center overflow-hidden rounded px-8 py-2 text-fg-secondary">
|
||||||
<Show when={lnurlServiceIcon()} keyed>
|
<Show when={lnurlServiceIcon()} keyed>
|
||||||
@@ -342,7 +342,7 @@ const ZapDialog: Component<ZapDialogProps> = (props) => {
|
|||||||
name="comment"
|
name="comment"
|
||||||
class="w-full rounded-md border border-border bg-bg ring-border placeholder:text-fg-secondary focus:border-border focus:ring-primary"
|
class="w-full rounded-md border border-border bg-bg ring-border placeholder:text-fg-secondary focus:border-border focus:ring-primary"
|
||||||
maxLength={commentAllowed() > 0 ? commentAllowed() : 70}
|
maxLength={commentAllowed() > 0 ? commentAllowed() : 70}
|
||||||
placeholder={i18n()('zap.comment')}
|
placeholder={i18n.t('zap.comment')}
|
||||||
disabled={query.isPending}
|
disabled={query.isPending}
|
||||||
value={comment()}
|
value={comment()}
|
||||||
onChange={(ev) => setComment(ev.target.value)}
|
onChange={(ev) => setComment(ev.target.value)}
|
||||||
@@ -352,7 +352,7 @@ const ZapDialog: Component<ZapDialogProps> = (props) => {
|
|||||||
class="flex w-full items-center justify-center rounded bg-primary py-4 text-primary-fg hover:bg-primary-hover"
|
class="flex w-full items-center justify-center rounded bg-primary py-4 text-primary-fg hover:bg-primary-hover"
|
||||||
disabled={getInvoiceMutation.isPending}
|
disabled={getInvoiceMutation.isPending}
|
||||||
>
|
>
|
||||||
<span class="inline-block h-6 w-6">
|
<span class="inline-block size-6">
|
||||||
<Bolt />
|
<Bolt />
|
||||||
</span>
|
</span>
|
||||||
</button>
|
</button>
|
||||||
@@ -379,7 +379,7 @@ const ZapRequestModal: Component<ZapRequestModalProps> = (props) => {
|
|||||||
return (
|
return (
|
||||||
<BasicModal onClose={props.onClose}>
|
<BasicModal onClose={props.onClose}>
|
||||||
<div class="p-8">
|
<div class="p-8">
|
||||||
<Show when={isZapConfigured()} fallback={i18n()('zap.userDidNotConfigureZap')}>
|
<Show when={isZapConfigured()} fallback={i18n.t('zap.userDidNotConfigureZap')}>
|
||||||
<Show when={lud06() != null && lud16() != null}>
|
<Show when={lud06() != null && lud16() != null}>
|
||||||
<div class="flex justify-center gap-3 pb-2">
|
<div class="flex justify-center gap-3 pb-2">
|
||||||
<button
|
<button
|
||||||
@@ -393,7 +393,7 @@ const ZapRequestModal: Component<ZapRequestModalProps> = (props) => {
|
|||||||
}}
|
}}
|
||||||
onClick={() => setLnurlSource('lud06')}
|
onClick={() => setLnurlSource('lud06')}
|
||||||
>
|
>
|
||||||
{i18n()('zap.lud06')}
|
{i18n.t('zap.lud06')}
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
@@ -406,7 +406,7 @@ const ZapRequestModal: Component<ZapRequestModalProps> = (props) => {
|
|||||||
}}
|
}}
|
||||||
onClick={() => setLnurlSource('lud16')}
|
onClick={() => setLnurlSource('lud16')}
|
||||||
>
|
>
|
||||||
{i18n()('zap.lud16')}
|
{i18n.t('zap.lud16')}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</Show>
|
</Show>
|
||||||
|
|||||||
@@ -237,8 +237,8 @@ const useConfig = (): UseConfig => {
|
|||||||
const columns: ColumnType[] = [
|
const columns: ColumnType[] = [
|
||||||
createFollowingColumn({ width: 'widest', pubkey }),
|
createFollowingColumn({ width: 'widest', pubkey }),
|
||||||
createNotificationColumn({ pubkey }),
|
createNotificationColumn({ pubkey }),
|
||||||
createPostsColumn({ name: i18n()('column.myPosts'), pubkey }),
|
createPostsColumn({ name: i18n.t('column.myPosts'), pubkey }),
|
||||||
createReactionsColumn({ name: i18n()('column.myReactions'), pubkey }),
|
createReactionsColumn({ name: i18n.t('column.myReactions'), pubkey }),
|
||||||
];
|
];
|
||||||
|
|
||||||
if (navigator.language.includes('ja')) {
|
if (navigator.language.includes('ja')) {
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import LanguageDetector from 'i18next-browser-languagedetector';
|
|||||||
import en from '@/locales/en';
|
import en from '@/locales/en';
|
||||||
import ja from '@/locales/ja';
|
import ja from '@/locales/ja';
|
||||||
|
|
||||||
const i18nextInstance = (): Promise<void | typeof i18next.t> =>
|
const i18nextInstance = () =>
|
||||||
i18next
|
i18next
|
||||||
.use(LanguageDetector)
|
.use(LanguageDetector)
|
||||||
.init({
|
.init({
|
||||||
|
|||||||
@@ -2,38 +2,37 @@ import { Component, JSX, createContext, createEffect, createSignal, useContext }
|
|||||||
|
|
||||||
import i18next from 'i18next';
|
import i18next from 'i18next';
|
||||||
|
|
||||||
type I18Next = typeof i18next.t;
|
type I18Next = typeof i18next;
|
||||||
|
|
||||||
export type I18NextProviderProps = {
|
export type I18NextProviderProps = {
|
||||||
i18next: I18Next | Promise<I18Next | void> | void;
|
i18next: I18Next | Promise<I18Next | void> | void;
|
||||||
children?: JSX.Element;
|
children?: JSX.Element;
|
||||||
};
|
};
|
||||||
|
|
||||||
const I18NextContext = createContext<I18Next | Promise<I18Next | void> | void>();
|
const I18NextContext = createContext<I18Next>(i18next);
|
||||||
|
|
||||||
export const useTranslation = () => {
|
export const useTranslation = () => useContext<I18Next>(I18NextContext);
|
||||||
const [i18nextFn, setI18nextFn] = createSignal<I18Next>(i18next.t);
|
|
||||||
const maybePromise = useContext(I18NextContext);
|
export const I18NextProvider: Component<I18NextProviderProps> = (props) => {
|
||||||
|
const [i18nextInstance, setI18nextInstance] = createSignal<I18Next>(i18next);
|
||||||
|
|
||||||
createEffect(() => {
|
createEffect(() => {
|
||||||
if (maybePromise instanceof Promise) {
|
if (props.i18next instanceof Promise) {
|
||||||
maybePromise
|
props.i18next
|
||||||
.then((instance) => {
|
.then((instance) => {
|
||||||
if (instance != null) {
|
if (instance != null) {
|
||||||
setI18nextFn(() => instance);
|
setI18nextInstance(() => instance);
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.catch((err) => {
|
.catch((err) => {
|
||||||
console.error('failed to initialize i18next', err);
|
console.error('failed to initialize i18n.text', err);
|
||||||
});
|
});
|
||||||
} else if (maybePromise != null) {
|
} else if (props.i18next != null) {
|
||||||
setI18nextFn(() => maybePromise);
|
setI18nextInstance(props.i18next);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
return i18nextFn;
|
return (
|
||||||
|
<I18NextContext.Provider value={i18nextInstance()}>{props.children}</I18NextContext.Provider>
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export const I18NextProvider: Component<I18NextProviderProps> = (props) => (
|
|
||||||
<I18NextContext.Provider value={props.i18next}>{props.children}</I18NextContext.Provider>
|
|
||||||
);
|
|
||||||
|
|||||||
@@ -59,19 +59,19 @@ const Hello: Component = () => {
|
|||||||
<div class="rounded-md p-8 shadow-md">
|
<div class="rounded-md p-8 shadow-md">
|
||||||
<Switch>
|
<Switch>
|
||||||
<Match when={signerStatus() === 'checking'}>
|
<Match when={signerStatus() === 'checking'}>
|
||||||
<p>{i18n()('hello.signerChecking')}</p>
|
<p>{i18n.t('hello.signerChecking')}</p>
|
||||||
</Match>
|
</Match>
|
||||||
<Match when={signerStatus() === 'unavailable'}>
|
<Match when={signerStatus() === 'unavailable'}>
|
||||||
<h2 class="font-bold">{i18n()('hello.signerUnavailable')}</h2>
|
<h2 class="font-bold">{i18n.t('hello.signerUnavailable')}</h2>
|
||||||
<p>{i18n()('hello.signerUnavailableMessage')}</p>
|
<p>{i18n.t('hello.signerUnavailableMessage')}</p>
|
||||||
<SignerExtensions />
|
<SignerExtensions />
|
||||||
<div class="flex flex-col items-center gap-2">
|
<div class="flex flex-col items-center gap-2">
|
||||||
<p class="text-sm">{i18n()('hello.reloadAfterInstall')}</p>
|
<p class="text-sm">{i18n.t('hello.reloadAfterInstall')}</p>
|
||||||
<button
|
<button
|
||||||
class="rounded bg-primary px-4 py-2 text-sm font-bold text-primary-fg hover:bg-primary-hover"
|
class="rounded bg-primary px-4 py-2 text-sm font-bold text-primary-fg hover:bg-primary-hover"
|
||||||
onClick={() => window.location.reload()}
|
onClick={() => window.location.reload()}
|
||||||
>
|
>
|
||||||
{i18n()('hello.reload')}
|
{i18n.t('hello.reload')}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</Match>
|
</Match>
|
||||||
@@ -80,7 +80,7 @@ const Hello: Component = () => {
|
|||||||
class="rounded bg-primary p-4 text-lg font-bold text-primary-fg hover:shadow-md"
|
class="rounded bg-primary p-4 text-lg font-bold text-primary-fg hover:shadow-md"
|
||||||
onClick={handleLogin}
|
onClick={handleLogin}
|
||||||
>
|
>
|
||||||
{i18n()('hello.loginWithSigner')}
|
{i18n.t('hello.loginWithSigner')}
|
||||||
</button>
|
</button>
|
||||||
</Match>
|
</Match>
|
||||||
</Switch>
|
</Switch>
|
||||||
|
|||||||
@@ -7,10 +7,10 @@ const NotFound: Component = () => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div class="container mx-auto max-w-[640px] py-10">
|
<div class="container mx-auto max-w-[640px] py-10">
|
||||||
<h1 class="text-4xl font-bold text-fg">{i18n()('notFound.title')}</h1>
|
<h1 class="text-4xl font-bold text-fg">{i18n.t('notFound.title')}</h1>
|
||||||
<p class="pt-4">
|
<p class="pt-4">
|
||||||
<a class="text-link underline" href="/">
|
<a class="text-link underline" href="/">
|
||||||
{i18n()('notFound.back')}
|
{i18n.t('notFound.back')}
|
||||||
</a>
|
</a>
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Reference in New Issue
Block a user