feat: update translation

This commit is contained in:
Shusui MOYATANI
2024-01-22 02:37:05 +09:00
parent 73ecad8b06
commit 2f5ed55d84
9 changed files with 120 additions and 82 deletions

View File

@@ -6,9 +6,9 @@
<title>Rabbit</title> <title>Rabbit</title>
</head> </head>
<body> <body>
<h1>お探しのページは見つかりませんでした</h1> <h1>Page not found</h1>
<p> <p>
<a href="/rabbit/">トップに戻る</a> <a href="/">Jump into rabbit hole</a>
</p> </p>
</body> </body>
</html> </html>

View File

@@ -21,6 +21,10 @@ const queryClient = new QueryClient({});
const i18next = i18nextInstance(); const i18next = i18nextInstance();
const permalinkFilters = {
id: /^npub1[ac-hj-np-z02-9]+$/,
};
const indexedDBPersister = createAsyncStoragePersister({ const indexedDBPersister = createAsyncStoragePersister({
storage: { storage: {
getItem(key: string) { getItem(key: string) {
@@ -64,7 +68,7 @@ const App: Component = () => {
<HashRouter> <HashRouter>
<Route path="/hello" component={() => <Navigate href="/" />} /> <Route path="/hello" component={() => <Navigate href="/" />} />
<Route path="/" component={() => <EntryPoint />} /> <Route path="/" component={() => <EntryPoint />} />
<Route path="/:id" component={() => <Permalink />} /> <Route path="/:id" component={() => <Permalink />} matchFilters={permalinkFilters} />
<Route path="/*" component={() => <NotFound />} /> <Route path="/*" component={() => <NotFound />} />
</HashRouter> </HashRouter>
</DomainTransferInfo> </DomainTransferInfo>

View File

@@ -9,6 +9,7 @@ import Repost from '@/components/event/Repost';
// eslint-disable-next-line import/no-cycle // eslint-disable-next-line import/no-cycle
import TextNote from '@/components/event/TextNote'; import TextNote from '@/components/event/TextNote';
import EventLink from '@/components/EventLink'; import EventLink from '@/components/EventLink';
import { useTranslation } from '@/i18n/useTranslation';
export type EventDisplayProps = { export type EventDisplayProps = {
event: NostrEvent; event: NostrEvent;
@@ -18,8 +19,8 @@ export type EventDisplayProps = {
}; };
const EventDisplay: Component<EventDisplayProps> = (props) => { const EventDisplay: Component<EventDisplayProps> = (props) => {
// noteの場合は kind:1 であることを保証するために利用できる const i18n = useTranslation();
// タイムラインで表示されるべきでないイベントが表示されてしまうのを防ぐ
const isAllowedKind = () => const isAllowedKind = () =>
props.ensureKinds == null || props.ensureKinds == null ||
props.ensureKinds.length === 0 || props.ensureKinds.length === 0 ||
@@ -28,17 +29,17 @@ const EventDisplay: Component<EventDisplayProps> = (props) => {
return ( return (
<Switch <Switch
fallback={ fallback={
<span> <div>
<span>{props.event.kind}</span> <span>{i18n()('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} />
</span> </div>
} }
> >
<Match when={!isAllowedKind()} keyed> <Match when={!isAllowedKind()} keyed>
<span> <div>
{props.event.kind} <span>{i18n()('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} />
</span> </div>
</Match> </Match>
<Match when={props.event.kind === Kind.ShortTextNote}> <Match when={props.event.kind === Kind.ShortTextNote}>
<TextNote event={props.event} embedding={props.actions} actions={props.actions} /> <TextNote event={props.event} embedding={props.actions} actions={props.actions} />

View File

@@ -22,7 +22,7 @@ const ContentWarningDisplay: Component<ContentWarningDisplayProps> = (props) =>
class="mt-2 flex w-full flex-col items-center rounded border border-border p-2 text-center text-xs text-fg-secondary" 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)} onClick={() => setShowContentWarning(true)}
> >
<span class="inline-block h-4 w-4"> <span class="inline-block size-4">
<ExclamationTriangle /> <ExclamationTriangle />
</span> </span>
<span>{i18n()('post.contentWarning.show')}</span> <span>{i18n()('post.contentWarning.show')}</span>
@@ -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')}
</button> </button>
</Show> </Show>
</Show> </Show>

View File

@@ -2,6 +2,7 @@ import { Component, createResource, For, Show } from 'solid-js';
import BasicModal from '@/components/modal/BasicModal'; import BasicModal from '@/components/modal/BasicModal';
import SafeLink from '@/components/utils/SafeLink'; import SafeLink from '@/components/utils/SafeLink';
import { useTranslation } from '@/i18n/useTranslation';
import resolveAsset from '@/utils/resolveAsset'; import resolveAsset from '@/utils/resolveAsset';
type AboutProps = { type AboutProps = {
@@ -34,6 +35,8 @@ const fetchPackageInfo = async (): Promise<PackageInfo> => {
const commit = import.meta.env.VITE_COMMIT as string | null; const commit = import.meta.env.VITE_COMMIT as string | null;
const About: Component<AboutProps> = (props) => { const About: Component<AboutProps> = (props) => {
const i18n = useTranslation();
const [packageInfo] = createResource(fetchPackageInfo); const [packageInfo] = createResource(fetchPackageInfo);
return ( return (
@@ -45,38 +48,30 @@ const About: Component<AboutProps> = (props) => {
<h1 class="my-4"> <h1 class="my-4">
Rabbit{' '} Rabbit{' '}
<span id="app-version"> <span id="app-version">
v{packageInfo()?.self?.version} <Show when={commit} fallback="(dev)">
<Show when={commit}> ({commit})</Show> {' '}
({commit})
</Show>
</span> </span>
</h1> </h1>
</div> </div>
<h2 class="my-4 text-xl font-bold"></h2> <div class="my-4 flex justify-center gap-3">
<SafeLink
<p class="my-4"> class="rounded border-2 border-primary px-4 py-2 font-bold text-primary hover:border-primary-hover hover:text-primary-hover"
<a
class="text-link underline"
href="https://github.com/syusui-s/rabbit/issues/new/choose" href="https://github.com/syusui-s/rabbit/issues/new/choose"
target="_blank"
rel="noopener noreferrer"
> >
GitHubのIssues {i18n()('about.bugReport')}
</a>
</p>
<h2 class="my-4 text-xl font-bold"></h2>
<p class="my-4">
<SafeLink class="text-link underline" href="https://github.com/syusui-s/rabbit">
GitHub
</SafeLink> </SafeLink>
<SafeLink
</p> 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"
>
{i18n()('about.sourceCode')}
</SafeLink>
</div>
<h2 class="my-4 text-xl font-bold"></h2> <h2 class="my-4 text-xl font-bold">{i18n()('about.termOfService')}</h2>
<p class="my-4"> <p class="my-4">
Copyright (C) 2023 Shusui Moyatani and{' '} Copyright (C) 2023 Shusui Moyatani and{' '}
@@ -88,43 +83,29 @@ const About: Component<AboutProps> = (props) => {
</SafeLink> </SafeLink>
</p> </p>
<p class="my-4"> <pre class=" max-h-96 overflow-auto rounded bg-bg-tertiary p-2 text-sm">
{i18n()('about.agplText')}
GNUアフェロー一般公衆ライセンス3() </pre>
<p>
<SafeLink class="text-link underline" href="https://gpl.mhatta.org/agpl.ja.html">
{i18n()('about.agplTranslationJa')}
</SafeLink>
</p> </p>
<p class="my-4"> <pre class="scrollbar max-h-96 overflow-auto rounded bg-bg-tertiary p-4 text-xs">
<strong class="font-bold"></strong><em></em>
<em></em>
GNUアフェロー一般公衆ライセンスをご覧ください
</p>
<p class="my-4">
GNUアフェロー一般公衆ライセンスのコピーを受け取っていることでしょう
<SafeLink href="https://www.gnu.org/licenses/" />
</p>
<a class="text-link underline" href="https://gpl.mhatta.org/agpl.ja.html">
</a>
<pre class="scorllbar max-h-96 overflow-auto rounded bg-bg-secondary p-4 text-xs">
{packageInfo()?.self.licenseText} {packageInfo()?.self.licenseText}
</pre> </pre>
<h2 class="my-4 text-xl font-bold">使</h2> <h2 class="my-4 text-xl font-bold">{i18n()('about.usingLibraries')}</h2>
<For each={packageInfo()?.packages ?? []} fallback="取得中"> <For each={packageInfo()?.packages ?? []}>
{(p) => ( {(p) => (
<> <>
<h3 class="mb-2 mt-4 font-mono"> <h3 class="mb-2 mt-4 font-mono">
{p.name}@{p.version} ({p.licenseSpdx}) {p.name}@{p.version} ({p.licenseSpdx})
</h3> </h3>
<pre class="scrollbar max-h-96 overflow-auto rounded bg-bg-secondary p-4 text-xs"> <pre class="scrollbar max-h-96 overflow-auto rounded bg-bg-tertiary p-4 text-xs">
{p.licenseText} {p.licenseText}
</pre> </pre>
</> </>

View File

@@ -6,6 +6,10 @@ export default {
loading: 'Loading', loading: 'Loading',
updating: 'Updating', updating: 'Updating',
}, },
notFound: {
title: 'Not found',
back: 'Back',
},
posting: { posting: {
placeholder: "What's happening?", placeholder: "What's happening?",
placeholderReply: 'Post a reply', placeholderReply: 'Post a reply',
@@ -115,8 +119,11 @@ export default {
contentWarning: { contentWarning: {
show: 'Click to display', show: 'Click to display',
reason: 'Reason', reason: 'Reason',
hide: 'Hide',
}, },
failedToFetchEvent: 'Failed to fetch event', failedToFetchEvent: 'Failed to fetch event',
unexpectedKind: 'Unexpected eventkind:{{kind}}',
unsupportedKind: 'Unsupported eventkind:{{kind}}',
}, },
notification: { notification: {
reposted: ' reposted', reposted: ' reposted',
@@ -208,6 +215,26 @@ export default {
reloadAfterInstall: 'Please reload after the installation is complete.', reloadAfterInstall: 'Please reload after the installation is complete.',
reload: 'Reload', 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: { domainTransfer: {
announcementHead: 'Rabbit has moved to the new domain', announcementHead: 'Rabbit has moved to the new domain',
announcementDescription: 'Please update your bookmark and links', announcementDescription: 'Please update your bookmark and links',

View File

@@ -5,6 +5,10 @@ export default {
loading: '読み込み中', loading: '読み込み中',
updating: '更新中', updating: '更新中',
}, },
notFound: {
title: 'ページが見つかりませんでした',
back: '戻る',
},
posting: { posting: {
placeholder: 'いまどうしてる?', placeholder: 'いまどうしてる?',
placeholderReply: '返信を投稿', placeholderReply: '返信を投稿',
@@ -111,8 +115,11 @@ export default {
contentWarning: { contentWarning: {
show: '表示するにはクリック', show: '表示するにはクリック',
reason: '理由', reason: '理由',
hide: '隠す',
}, },
failedToFetchEvent: '取得に失敗しました', failedToFetchEvent: '取得に失敗しました',
unexpectedKind: '予期しないイベントですkind:{{kind}}',
unsupportedKind: '未対応のイベントですkind:{{kind}}',
}, },
notification: { notification: {
reposted: 'がリポスト', reposted: 'がリポスト',
@@ -205,6 +212,26 @@ export default {
reloadAfterInstall: 'インストールが完了したら再読み込みしてください。', reloadAfterInstall: 'インストールが完了したら再読み込みしてください。',
reload: '再読み込み', reload: '再読み込み',
}, },
about: {
bugReport: 'バグ報告',
sourceCode: 'ソースコード',
termOfService: '利用規約',
agplText: stripMargin`
このプログラムは自由ソフトウェアです。
フリーソフトウェア財団から発行された GNUアフェロー一般公衆ライセンス
バージョン3か、(任意で)より新しいバージョンのいずれか)の条件の下で
再頒布や改変、あるいはその両方を行うことができます。
このプログラムは役立つことを願って頒布されていますが、
**いかなる保証もありません**。
_商品性_や_特定目的適合性_ に対する保証は暗示されたものも含めて存在しません。
詳しくはGNUアフェロー一般公衆ライセンスをご覧ください。
`,
agplTranslationJa: '日本語訳',
usingLibraries: '使用ライブラリ',
},
domainTransfer: { domainTransfer: {
announcementHead: 'Rabbitは新しいドメインに移りました', announcementHead: 'Rabbitは新しいドメインに移りました',
announcementDescription: 'ブックマークやリンクの更新をお願いします', announcementDescription: 'ブックマークやリンクの更新をお願いします',

View File

@@ -1,14 +1,20 @@
import type { Component } from 'solid-js'; import type { Component } from 'solid-js';
const NotFound: Component = () => ( import { useTranslation } from '@/i18n/useTranslation';
const NotFound: Component = () => {
const i18n = useTranslation();
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"></h1> <h1 class="text-4xl font-bold text-fg">{i18n()('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')}
</a> </a>
</p> </p>
</div> </div>
); );
};
export default NotFound; export default NotFound;

View File

@@ -6,21 +6,13 @@ import { decode } from 'nostr-tools/nip19';
import GlobalModal from '@/components/modal/GlobalModal'; import GlobalModal from '@/components/modal/GlobalModal';
import SideBar from '@/components/SideBar'; import SideBar from '@/components/SideBar';
import useModalState from '@/hooks/useModalState'; import useModalState from '@/hooks/useModalState';
import usePersistStatus from '@/hooks/usePersistStatus';
const Permalink = () => { const Permalink = () => {
const navigate = useNavigate(); const navigate = useNavigate();
const params = useParams(); const params = useParams();
const { modalState, showProfile } = useModalState(); const { modalState, showProfile } = useModalState();
const { persistStatus } = usePersistStatus();
const navigateTop = () => { const navigateTop = () => navigate('/');
if (persistStatus().loggedIn) {
navigate('/');
} else {
navigate('/hello');
}
};
onMount(() => { onMount(() => {
if (params.id != null) { if (params.id != null) {