diff --git a/public/404.html b/public/404.html index ddf48f0..91927bf 100644 --- a/public/404.html +++ b/public/404.html @@ -6,9 +6,9 @@ Rabbit -

お探しのページは見つかりませんでした

+

Page not found

- トップに戻る + Jump into rabbit hole

diff --git a/src/App.tsx b/src/App.tsx index 63e7dd4..1ea9472 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -21,6 +21,10 @@ const queryClient = new QueryClient({}); const i18next = i18nextInstance(); +const permalinkFilters = { + id: /^npub1[ac-hj-np-z02-9]+$/, +}; + const indexedDBPersister = createAsyncStoragePersister({ storage: { getItem(key: string) { @@ -64,7 +68,7 @@ const App: Component = () => { } /> } /> - } /> + } matchFilters={permalinkFilters} /> } /> diff --git a/src/components/event/EventDisplay.tsx b/src/components/event/EventDisplay.tsx index a9191f0..f332fc9 100644 --- a/src/components/event/EventDisplay.tsx +++ b/src/components/event/EventDisplay.tsx @@ -9,6 +9,7 @@ import Repost from '@/components/event/Repost'; // eslint-disable-next-line import/no-cycle import TextNote from '@/components/event/TextNote'; import EventLink from '@/components/EventLink'; +import { useTranslation } from '@/i18n/useTranslation'; export type EventDisplayProps = { event: NostrEvent; @@ -18,8 +19,8 @@ export type EventDisplayProps = { }; const EventDisplay: Component = (props) => { - // noteの場合は kind:1 であることを保証するために利用できる - // タイムラインで表示されるべきでないイベントが表示されてしまうのを防ぐ + const i18n = useTranslation(); + const isAllowedKind = () => props.ensureKinds == null || props.ensureKinds.length === 0 || @@ -28,17 +29,17 @@ const EventDisplay: Component = (props) => { return ( - 未対応のイベント種別({props.event.kind}) +
+ {i18n()('post.unsupportedKind', { kind: props.event.kind })} - +
} > - - 予期しないイベント種別({props.event.kind}) +
+ {i18n()('post.unexpectedKind', { kind: props.event.kind })} - +
diff --git a/src/components/event/textNote/ContentWarningDisplay.tsx b/src/components/event/textNote/ContentWarningDisplay.tsx index 095ebc6..74a35b5 100644 --- a/src/components/event/textNote/ContentWarningDisplay.tsx +++ b/src/components/event/textNote/ContentWarningDisplay.tsx @@ -22,7 +22,7 @@ const ContentWarningDisplay: Component = (props) => class="mt-2 flex w-full flex-col items-center rounded border border-border p-2 text-center text-xs text-fg-secondary" onClick={() => setShowContentWarning(true)} > - + {i18n()('post.contentWarning.show')} @@ -40,7 +40,7 @@ const ContentWarningDisplay: Component = (props) => class="text-xs text-fg-secondary hover:text-fg-secondary/70" onClick={() => setShowContentWarning(false)} > - 隠す + {i18n()('post.contentWarning.hide')} diff --git a/src/components/modal/About.tsx b/src/components/modal/About.tsx index 79d8c35..dc8dcbb 100644 --- a/src/components/modal/About.tsx +++ b/src/components/modal/About.tsx @@ -2,6 +2,7 @@ import { Component, createResource, For, Show } from 'solid-js'; import BasicModal from '@/components/modal/BasicModal'; import SafeLink from '@/components/utils/SafeLink'; +import { useTranslation } from '@/i18n/useTranslation'; import resolveAsset from '@/utils/resolveAsset'; type AboutProps = { @@ -34,6 +35,8 @@ const fetchPackageInfo = async (): Promise => { const commit = import.meta.env.VITE_COMMIT as string | null; const About: Component = (props) => { + const i18n = useTranslation(); + const [packageInfo] = createResource(fetchPackageInfo); return ( @@ -45,38 +48,30 @@ const About: Component = (props) => {

Rabbit{' '} - v{packageInfo()?.self?.version} - ({commit}) + + {' '} + ({commit}) +

-

バグ報告について

- -

- おかしな動作を見つけたら - + - GitHubのIssues - - までご報告ください。 -

- -

ソースコード

- -

- ソースコードは - - GitHub + {i18n()('about.bugReport')} - で入手できます。 -

+ + {i18n()('about.sourceCode')} + + -

利用規約

+

{i18n()('about.termOfService')}

Copyright (C) 2023 Shusui Moyatani and{' '} @@ -88,43 +83,29 @@ const About: Component = (props) => {

-

- このプログラムは自由ソフトウェアです。フリーソフトウェア財団から発行された - GNUアフェロー一般公衆ライセンス(バージョン3か、(任意で)より新しいバージョンのいずれか)の条件の下で - 再頒布や改変、あるいはその両方を行うことができます。 +

+          {i18n()('about.agplText')}
+        
+ +

+ + {i18n()('about.agplTranslationJa')} +

-

- このプログラムは役立つことを願って頒布されていますが、 - いかなる保証もありません商品性や - 特定目的適合性 に対する保証は暗示されたものも含めて存在しません。 - 詳しくはGNUアフェロー一般公衆ライセンスをご覧ください。 -

- -

- あなたは、このプログラムに付随してGNUアフェロー一般公衆ライセンスのコピーを受け取っていることでしょう。 - そうでなければ、 - - をご参照ください。 -

- - - 参考訳 - - -
+        
           {packageInfo()?.self.licenseText}
         
-

使用ライブラリ

+

{i18n()('about.usingLibraries')}

- + {(p) => ( <>

{p.name}@{p.version} ({p.licenseSpdx})

-
+              
                 {p.licenseText}
               
diff --git a/src/locales/en.ts b/src/locales/en.ts index 4249b5a..df23cfc 100644 --- a/src/locales/en.ts +++ b/src/locales/en.ts @@ -6,6 +6,10 @@ export default { loading: 'Loading', updating: 'Updating', }, + notFound: { + title: 'Not found', + back: 'Back', + }, posting: { placeholder: "What's happening?", placeholderReply: 'Post a reply', @@ -115,8 +119,11 @@ export default { contentWarning: { show: 'Click to display', reason: 'Reason', + hide: 'Hide', }, failedToFetchEvent: 'Failed to fetch event', + unexpectedKind: 'Unexpected event(kind:{{kind}})', + unsupportedKind: 'Unsupported event(kind:{{kind}})', }, notification: { reposted: ' reposted', @@ -208,6 +215,26 @@ export default { reloadAfterInstall: 'Please reload after the installation is complete.', reload: 'Reload', }, + about: { + bugReport: 'Report bug', + sourceCode: 'Source code', + termOfService: 'License', + agplText: stripMargin` + This program is free software: + + you can redistribute it and/or modify it under the terms of + the GNU Affero General Public License as published by + the Free Software Foundation, either version 3 of the License, + or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + `, + agplTranslationJa: 'Japanese translation', + usingLibraries: 'Using libraries', + }, domainTransfer: { announcementHead: 'Rabbit has moved to the new domain', announcementDescription: 'Please update your bookmark and links', diff --git a/src/locales/ja.ts b/src/locales/ja.ts index f889c42..ec212bc 100644 --- a/src/locales/ja.ts +++ b/src/locales/ja.ts @@ -5,6 +5,10 @@ export default { loading: '読み込み中', updating: '更新中', }, + notFound: { + title: 'ページが見つかりませんでした', + back: '戻る', + }, posting: { placeholder: 'いまどうしてる?', placeholderReply: '返信を投稿', @@ -111,8 +115,11 @@ export default { contentWarning: { show: '表示するにはクリック', reason: '理由', + hide: '隠す', }, failedToFetchEvent: '取得に失敗しました', + unexpectedKind: '予期しないイベントです(kind:{{kind}})', + unsupportedKind: '未対応のイベントです(kind:{{kind}})', }, notification: { reposted: 'がリポスト', @@ -205,6 +212,26 @@ export default { reloadAfterInstall: 'インストールが完了したら再読み込みしてください。', reload: '再読み込み', }, + about: { + bugReport: 'バグ報告', + sourceCode: 'ソースコード', + termOfService: '利用規約', + agplText: stripMargin` + このプログラムは自由ソフトウェアです。 + + フリーソフトウェア財団から発行された GNUアフェロー一般公衆ライセンス + (バージョン3か、(任意で)より新しいバージョンのいずれか)の条件の下で + 再頒布や改変、あるいはその両方を行うことができます。 + + このプログラムは役立つことを願って頒布されていますが、 + **いかなる保証もありません**。 + + _商品性_や_特定目的適合性_ に対する保証は暗示されたものも含めて存在しません。 + 詳しくはGNUアフェロー一般公衆ライセンスをご覧ください。 + `, + agplTranslationJa: '日本語訳', + usingLibraries: '使用ライブラリ', + }, domainTransfer: { announcementHead: 'Rabbitは新しいドメインに移りました', announcementDescription: 'ブックマークやリンクの更新をお願いします', diff --git a/src/pages/NotFound.tsx b/src/pages/NotFound.tsx index 75da871..78dc8f7 100644 --- a/src/pages/NotFound.tsx +++ b/src/pages/NotFound.tsx @@ -1,14 +1,20 @@ import type { Component } from 'solid-js'; -const NotFound: Component = () => ( -
-

お探しのページは見つかりませんでした

-

- - ← トップに戻る - -

-
-); +import { useTranslation } from '@/i18n/useTranslation'; + +const NotFound: Component = () => { + const i18n = useTranslation(); + + return ( +
+

{i18n()('notFound.title')}

+

+ + {i18n()('notFound.back')} + +

+
+ ); +}; export default NotFound; diff --git a/src/pages/Permalink.tsx b/src/pages/Permalink.tsx index cf76399..127aba8 100644 --- a/src/pages/Permalink.tsx +++ b/src/pages/Permalink.tsx @@ -6,21 +6,13 @@ import { decode } from 'nostr-tools/nip19'; import GlobalModal from '@/components/modal/GlobalModal'; import SideBar from '@/components/SideBar'; import useModalState from '@/hooks/useModalState'; -import usePersistStatus from '@/hooks/usePersistStatus'; const Permalink = () => { const navigate = useNavigate(); const params = useParams(); const { modalState, showProfile } = useModalState(); - const { persistStatus } = usePersistStatus(); - const navigateTop = () => { - if (persistStatus().loggedIn) { - navigate('/'); - } else { - navigate('/hello'); - } - }; + const navigateTop = () => navigate('/'); onMount(() => { if (params.id != null) {