diff --git a/src/components/NotePostForm.tsx b/src/components/NotePostForm.tsx index 6f8fab4..5a67306 100644 --- a/src/components/NotePostForm.tsx +++ b/src/components/NotePostForm.tsx @@ -13,6 +13,7 @@ import UserNameDisplay from '@/components/UserDisplayName'; import useConfig from '@/core/useConfig'; import useEmojiComplete from '@/hooks/useEmojiComplete'; import usePersistStatus from '@/hooks/usePersistStatus'; +import { useTranslation } from '@/i18n/useTranslation'; import { textNote } from '@/nostr/event'; import parseTextNote, { ParsedTextNote } from '@/nostr/parseTextNote'; import useCommands, { PublishTextNoteParams } from '@/nostr/useCommands'; @@ -28,16 +29,6 @@ type NotePostFormProps = { textAreaRef?: (textAreaRef: HTMLTextAreaElement) => void; }; -const placeholder = (mode: NotePostFormProps['mode']) => { - switch (mode) { - case 'reply': - return '返信を投稿'; - case 'normal': - default: - return 'いまどうしてる?'; - } -}; - const extract = (parsed: ParsedTextNote) => { const hashtags: string[] = []; const pubkeyReferences: string[] = []; @@ -86,6 +77,7 @@ const format = (parsed: ParsedTextNote) => { }; const NotePostForm: Component = (props) => { + const i18n = useTranslation(); let textAreaRef: HTMLTextAreaElement | undefined; let fileInputRef: HTMLInputElement | undefined; @@ -108,6 +100,16 @@ const NotePostForm: Component = (props) => { props.onClose(); }; + const placeholder = (mode: NotePostFormProps['mode']) => { + switch (mode) { + case 'reply': + return i18n()('posting.placeholderReply'); + case 'normal': + default: + return i18n()('posting.placeholder'); + } + }; + const { config, getEmoji } = useConfig(); const { persistStatus, didAgreeToToS, agreeToToS } = usePersistStatus(); const getPubkey = usePubkey(); @@ -152,7 +154,7 @@ const NotePostForm: Component = (props) => { if (failed.length > 0) { const filenames = failed.map((f) => f.name).join(', '); - window.alert(`ファイルのアップロードに失敗しました: ${filenames}`); + window.alert(i18n()('posting.failedToUploadFile', { filenames })); } }, }); @@ -194,7 +196,7 @@ const NotePostForm: Component = (props) => { if (publishTextNoteMutation.isLoading) return; if (/nsec1[0-9a-zA-Z]+/.test(text())) { - window.alert('投稿に秘密鍵(nsec)を含めることはできません。'); + window.alert(i18n()('posting.forbiddenToIncludeNsec')); return; } @@ -337,6 +339,7 @@ const NotePostForm: Component = (props) => {
+ {i18n()('posting.replyToPre')} {(pubkey, index) => ( <> @@ -345,7 +348,7 @@ const NotePostForm: Component = (props) => { )} - に返信 + {i18n()('posting.replyToPost')}
@@ -353,7 +356,7 @@ const NotePostForm: Component = (props) => { setContentWarningReason(ev.currentTarget.value)} value={contentWarningReason()} @@ -400,8 +403,8 @@ const NotePostForm: Component = (props) => { 'w-7': mode() === 'reply', }} type="button" - aria-label="コンテンツ警告を設定" - title="コンテンツ警告を設定" + aria-label={i18n()('posting.contentWarning')} + title={i18n()('posting.contentWarning')} onClick={() => setContentWarning((e) => !e)} > CW @@ -417,8 +420,8 @@ const NotePostForm: Component = (props) => { 'w-7': mode() === 'reply', }} type="button" - title="画像を投稿" - aria-label="画像を投稿" + title={i18n()('posting.uploadImage')} + aria-label={i18n()('posting.uploadImage')} disabled={fileUploadDisabled()} onClick={() => fileInputRef?.click()} > @@ -435,8 +438,8 @@ const NotePostForm: Component = (props) => { 'w-7': mode() === 'reply', }} type="submit" - aria-label="投稿" - title="投稿" + aria-label={i18n()('posting.submit')} + title={i18n()('posting.submit')} disabled={submitDisabled()} > diff --git a/src/components/event/EventDisplayById.tsx b/src/components/event/EventDisplayById.tsx index 5ef93a2..ca7e071 100644 --- a/src/components/event/EventDisplayById.tsx +++ b/src/components/event/EventDisplayById.tsx @@ -5,6 +5,7 @@ import EventDisplay from '@/components/event/EventDisplay'; import { type EventDisplayProps } from '@/components/event/EventDisplay'; import EventLink from '@/components/EventLink'; import useConfig from '@/core/useConfig'; +import { useTranslation } from '@/i18n/useTranslation'; import useEvent from '@/nostr/useEvent'; import ensureNonNull from '@/utils/ensureNonNull'; @@ -13,6 +14,7 @@ type EventDisplayByIdProps = Omit & { }; const EventDisplayById: Component = (props) => { + const i18n = useTranslation(); const [localProps, restProps] = splitProps(props, ['eventId']); const { shouldMuteEvent } = useConfig(); @@ -31,7 +33,7 @@ const EventDisplayById: Component = (props) => { - 投稿が見つかりません + {i18n()('post.failedToFetchEvent')} {props.eventId} } @@ -43,8 +45,7 @@ const EventDisplayById: Component = (props) => { {(id) => (
- {'読み込み中 '} - + {i18n()('general.loading')}
)}
diff --git a/src/components/event/Reaction.tsx b/src/components/event/Reaction.tsx index 3704336..af21355 100644 --- a/src/components/event/Reaction.tsx +++ b/src/components/event/Reaction.tsx @@ -68,7 +68,11 @@ const ReactionDisplay: Component = (props) => {
読み込み中 {eventId()}
} + fallback={ +
+ {i18n()('general.loading')} {eventId()} +
+ } keyed > {(ev) => } diff --git a/src/components/modal/ProfileDisplay.tsx b/src/components/modal/ProfileDisplay.tsx index d031b36..a5cbd75 100644 --- a/src/components/modal/ProfileDisplay.tsx +++ b/src/components/modal/ProfileDisplay.tsx @@ -131,21 +131,14 @@ const ProfileDisplay: Component = (props) => { const latest = await fetchLatestFollowings({ pubkey: p }); - const msg = stripMargin` - フォローリストが空のようです。初めてのフォローであれば問題ありません。 - そうでなければ、リレーとの接続がうまくいっていない可能性があります。ページを再読み込みしてリレーと再接続してください。 - また、他のクライアントと同じリレーを設定できているどうかご確認ください。 - - 続行しますか? - `; - - if ((latest.data() == null || latest.followingPubkeys().length === 0) && !window.confirm(msg)) + if ( + (latest.data() == null || latest.followingPubkeys().length === 0) && + !window.confirm(i18n()('profile.confirmUpdateEvenIfEmpty')) + ) return; if ((latest?.data()?.created_at ?? 0) < (myFollowingQuery.data?.created_at ?? 0)) { - window.alert( - '最新のフォローリストを取得できませんでした。リレーの接続状況が悪い可能性があります。', - ); + window.alert(i18n()('profile.failedToFetchLatestFollowList')); return; } @@ -171,7 +164,7 @@ const ProfileDisplay: Component = (props) => { }); } catch (err) { console.error('failed to update contact list', err); - window.alert('フォローリストの更新に失敗しました。'); + window.alert(i18n()('profile.failedToUpdateFollowList')); } finally { setUpdatingContacts(false); } @@ -184,7 +177,7 @@ const ProfileDisplay: Component = (props) => { }; const unfollow = () => { - if (!window.confirm('本当にフォロー解除しますか?')) return; + if (!window.confirm(i18n()('profile.confirmUnfollow'))) return; updateContacts('unfollow', props.pubkey).catch((err) => { console.log('failed to unfollow', err); @@ -384,11 +377,11 @@ const ProfileDisplay: Component = (props) => {
-
フォロワー
+
{i18n()('profile.followers')}
= (props) => { class="text-sm hover:text-stone-800 hover:underline" onClick={() => setShowFollowers(true)} > - 読み込む + {i18n()('profile.loadFollowers')} } keyed diff --git a/src/components/modal/ProfileEdit.tsx b/src/components/modal/ProfileEdit.tsx index fed58e1..c911941 100644 --- a/src/components/modal/ProfileEdit.tsx +++ b/src/components/modal/ProfileEdit.tsx @@ -7,6 +7,7 @@ import omitBy from 'lodash/omitBy'; import BasicModal from '@/components/modal/BasicModal'; import useConfig from '@/core/useConfig'; +import { useTranslation } from '@/i18n/useTranslation'; import { Profile } from '@/nostr/event/Profile'; import useCommands from '@/nostr/useCommands'; import useProfile from '@/nostr/useProfile'; @@ -29,6 +30,7 @@ const isLNURL = (s: string) => LNURLRegex.test(s); const isInternetIdentifier = (s: string) => InternetIdentifierRegex.test(s); const ProfileEdit: Component = (props) => { + const i18n = useTranslation(); const pubkey = usePubkey(); const { config } = useConfig(); @@ -56,11 +58,11 @@ const ProfileEdit: Component = (props) => { const succeeded = results.filter((res) => res.status === 'fulfilled').length; const failed = results.length - succeeded; if (succeeded === results.length) { - window.alert('更新しました'); + window.alert(i18n()('profile.edit.updateSucceeded')); } else if (succeeded > 0) { - window.alert(`${failed}個のリレーで更新に失敗しました`); + window.alert(i18n()('profile.edit.failedToUpdatePartially', { count: failed })); } else { - window.alert('すべてのリレーで更新に失敗しました'); + window.alert(i18n()('profile.edit.failedToUpdate')); } invalidateProfile() .then(() => query.refetch()) @@ -159,13 +161,13 @@ const ProfileEdit: Component = (props) => {
-
読み込み中...
+
{i18n()('general.loading')}
= (props) => {
= (props) => {
@ @@ -218,7 +220,7 @@ const ProfileEdit: Component = (props) => {
= (props) => {