chore: Update translations
Some checks failed
continuous-integration/drone/push Build is failing

This commit is contained in:
Kieran 2023-09-14 18:45:29 +00:00
parent a8f000d9d8
commit 9c05b6a101
21 changed files with 609 additions and 567 deletions

View File

@ -4,7 +4,11 @@ import Note from "../Note";
export default function Articles() { export default function Articles() {
const data = useArticles(); const data = useArticles();
return <> return (
{orderDescending(data.data ?? []).map(a => <Note data={a} key={a.id} related={[]} />)} <>
{orderDescending(data.data ?? []).map(a => (
<Note data={a} key={a.id} related={[]} />
))}
</> </>
);
} }

View File

@ -13,7 +13,8 @@ export function DeckNav() {
const unreadDms = 0; const unreadDms = 0;
const hasNotifications = false; const hasNotifications = false;
return <nav className="deck flex-column f-space"> return (
<nav className="deck flex-column f-space">
<div className="flex-column f-center g24"> <div className="flex-column f-center g24">
<Link className="btn" to="/messages"> <Link className="btn" to="/messages">
<Icon name="mail" size={24} /> <Icon name="mail" size={24} />
@ -32,11 +33,9 @@ export function DeckNav() {
<Icon name="settings-02" size={24} /> <Icon name="settings-02" size={24} />
</Link> </Link>
<Link to={profileLink(publicKey ?? "")}> <Link to={profileLink(publicKey ?? "")}>
<Avatar <Avatar pubkey={publicKey ?? ""} user={profile} />
pubkey={publicKey ?? ""}
user={profile}
/>
</Link> </Link>
</div> </div>
</nav> </nav>
);
} }

View File

@ -3,7 +3,17 @@ import React, { useMemo, useState, ReactNode } from "react";
import { useNavigate, Link } from "react-router-dom"; import { useNavigate, Link } from "react-router-dom";
import { useInView } from "react-intersection-observer"; import { useInView } from "react-intersection-observer";
import { useIntl, FormattedMessage } from "react-intl"; import { useIntl, FormattedMessage } from "react-intl";
import { TaggedNostrEvent, HexKey, EventKind, NostrPrefix, Lists, EventExt, parseZap, tagToNostrLink, createNostrLinkToEvent } from "@snort/system"; import {
TaggedNostrEvent,
HexKey,
EventKind,
NostrPrefix,
Lists,
EventExt,
parseZap,
tagToNostrLink,
createNostrLinkToEvent,
} from "@snort/system";
import { System } from "index"; import { System } from "index";
import useEventPublisher from "Feed/EventPublisher"; import useEventPublisher from "Feed/EventPublisher";
@ -200,19 +210,22 @@ export function NoteInner(props: NoteProps) {
const image = findTag(ev, "image"); const image = findTag(ev, "image");
return ( return (
<div className="long-form-note"> <div className="long-form-note">
<h3> <h3>{title}</h3>
{title}
</h3>
<div className="text"> <div className="text">
<p> <p>{summary}</p>
{summary} <Text
</p> id={ev.id}
<Text id={ev.id} content={ev.content} tags={ev.tags} creator={ev.pubkey} depth={props.depth} truncate={255} disableLinkPreview={true} /> content={ev.content}
tags={ev.tags}
creator={ev.pubkey}
depth={props.depth}
truncate={255}
disableLinkPreview={true}
/>
{image && <ProxyImg src={image} />} {image && <ProxyImg src={image} />}
</div> </div>
</div> </div>
) );
} else { } else {
const body = ev?.content ?? ""; const body = ev?.content ?? "";
return ( return (
@ -226,7 +239,7 @@ export function NoteInner(props: NoteProps) {
/> />
); );
} }
} };
const transformBody = () => { const transformBody = () => {
if (deletions?.length > 0) { if (deletions?.length > 0) {
@ -297,7 +310,11 @@ export function NoteInner(props: NoteProps) {
const maxMentions = 2; const maxMentions = 2;
const replyTo = thread?.replyTo ?? thread?.root; const replyTo = thread?.replyTo ?? thread?.root;
const replyLink = replyTo ? tagToNostrLink([replyTo.key, replyTo.value ?? "", replyTo.relay ?? "", replyTo.marker ?? ""].filter(a => a.length > 0)) : undefined; const replyLink = replyTo
? tagToNostrLink(
[replyTo.key, replyTo.value ?? "", replyTo.relay ?? "", replyTo.marker ?? ""].filter(a => a.length > 0),
)
: undefined;
const mentions: { pk: string; name: string; link: ReactNode }[] = []; const mentions: { pk: string; name: string; link: ReactNode }[] = [];
for (const pk of thread?.pubKeys ?? []) { for (const pk of thread?.pubKeys ?? []) {
const u = UserCache.getFromCache(pk); const u = UserCache.getFromCache(pk);
@ -330,11 +347,7 @@ export function NoteInner(props: NoteProps) {
{pubMentions} {others} {pubMentions} {others}
</> </>
) : ( ) : (
replyLink && ( replyLink && <Link to={`/e/${replyLink.encode()}`}>{replyLink.encode().substring(0, 12)}</Link>
<Link to={`/e/${replyLink.encode()}`}>
{replyLink.encode().substring(0, 12)}
</Link>
)
)} )}
</div> </div>
); );
@ -418,7 +431,7 @@ export function NoteInner(props: NoteProps) {
{options.showContextMenu && ( {options.showContextMenu && (
<NoteContextMenu <NoteContextMenu
ev={ev} ev={ev}
react={async () => { }} react={async () => {}}
onTranslated={t => setTranslated(t)} onTranslated={t => setTranslated(t)}
setShowReactions={setShowReactions} setShowReactions={setShowReactions}
/> />

View File

@ -2,9 +2,9 @@
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
} }
.root-type > button { .root-type > button {
background: white; background: white;
color: black; color: black;
font-size: 16px; font-size: 16px;
@ -14,5 +14,4 @@
align-items: center; align-items: center;
justify-content: center; justify-content: center;
gap: 12px; gap: 12px;
} }

View File

@ -7,8 +7,14 @@ import { FormattedMessage } from "react-intl";
import useLogin from "Hooks/useLogin"; import useLogin from "Hooks/useLogin";
import Icon from "Icons/Icon"; import Icon from "Icons/Icon";
export type RootTab =
export type RootTab = "following" | "conversations" | "trending-notes" | "trending-people" | "suggested" | "tags" | "global"; | "following"
| "conversations"
| "trending-notes"
| "trending-people"
| "suggested"
| "tags"
| "global";
export function RootTabs({ base }: { base?: string }) { export function RootTabs({ base }: { base?: string }) {
const navigate = useNavigate(); const navigate = useNavigate();
@ -109,7 +115,6 @@ export function RootTabs({ base }: { base?: string }) {
return menuItems.find(a => a.tab === rootType)?.element; return menuItems.find(a => a.tab === rootType)?.element;
} }
return ( return (
<div className="root-type"> <div className="root-type">
<Menu <Menu

View File

@ -53,7 +53,6 @@ export function SpotlightMedia(props: SpotlightMediaProps) {
); );
} }
export function SpotlightMediaModal(props: SpotlightMediaProps) { export function SpotlightMediaModal(props: SpotlightMediaProps) {
return ( return (
<Modal onClose={props.onClose} className="spotlight"> <Modal onClose={props.onClose} className="spotlight">

View File

@ -2,13 +2,7 @@ import "./Thread.css";
import { useMemo, useState, ReactNode, useContext } from "react"; import { useMemo, useState, ReactNode, useContext } from "react";
import { useIntl } from "react-intl"; import { useIntl } from "react-intl";
import { useNavigate, Link, useParams } from "react-router-dom"; import { useNavigate, Link, useParams } from "react-router-dom";
import { import { TaggedNostrEvent, u256, NostrPrefix, EventExt, parseNostrLink } from "@snort/system";
TaggedNostrEvent,
u256,
NostrPrefix,
EventExt,
parseNostrLink,
} from "@snort/system";
import { eventLink, getReactions, getAllReactions } from "SnortUtils"; import { eventLink, getReactions, getAllReactions } from "SnortUtils";
import BackButton from "Element/BackButton"; import BackButton from "Element/BackButton";
@ -160,7 +154,8 @@ const TierThree = ({ active, isLastSubthread, notes, related, chains, onNavigate
return ( return (
<> <>
<div <div
className={`subthread-container ${hasMultipleNotes ? "subthread-multi" : ""} ${isLast ? "subthread-last" : "subthread-mid" className={`subthread-container ${hasMultipleNotes ? "subthread-multi" : ""} ${
isLast ? "subthread-last" : "subthread-mid"
}`}> }`}>
<Divider variant="small" /> <Divider variant="small" />
<Note <Note
@ -190,7 +185,8 @@ const TierThree = ({ active, isLastSubthread, notes, related, chains, onNavigate
return ( return (
<div <div
key={r.id} key={r.id}
className={`subthread-container ${lastReply ? "" : "subthread-multi"} ${lastReply ? "subthread-last" : "subthread-mid" className={`subthread-container ${lastReply ? "" : "subthread-multi"} ${
lastReply ? "subthread-last" : "subthread-mid"
}`}> }`}>
<Divider variant="small" /> <Divider variant="small" />
<Note <Note
@ -213,9 +209,11 @@ export function ThreadRoute() {
const params = useParams(); const params = useParams();
const link = parseNostrLink(params.id ?? "", NostrPrefix.Note); const link = parseNostrLink(params.id ?? "", NostrPrefix.Note);
return <ThreadContextWrapper link={link}> return (
<ThreadContextWrapper link={link}>
<Thread /> <Thread />
</ThreadContextWrapper> </ThreadContextWrapper>
);
} }
export function Thread() { export function Thread() {

View File

@ -113,9 +113,12 @@ const TimelineFollows = (props: TimelineFollowsProps) => {
)} )}
</> </>
)} )}
{mainFeed.map(a => props.noteRenderer?.(a) ?? ( {mainFeed.map(
a =>
props.noteRenderer?.(a) ?? (
<Note data={a as TaggedNostrEvent} related={relatedFeed(a.id)} key={a.id} depth={0} /> <Note data={a as TaggedNostrEvent} related={relatedFeed(a.id)} key={a.id} depth={0} />
))} ),
)}
<div className="flex f-center p"> <div className="flex f-center p">
<AsyncButton <AsyncButton
onClick={async () => { onClick={async () => {

View File

@ -4,15 +4,12 @@ import useLogin from "Hooks/useLogin";
import { useMemo } from "react"; import { useMemo } from "react";
export function useArticles() { export function useArticles() {
const {publicKey, follows} = useLogin(); const { publicKey, follows } = useLogin();
const sub = useMemo(() => { const sub = useMemo(() => {
if(!publicKey) return null; if (!publicKey) return null;
const rb = new RequestBuilder(`articles:${publicKey}`); const rb = new RequestBuilder(`articles:${publicKey}`);
rb.withFilter() rb.withFilter().kinds([EventKind.LongFormTextNote]).authors(follows.item).limit(20);
.kinds([EventKind.LongFormTextNote])
.authors(follows.item)
.limit(20);
return rb; return rb;
}, [follows.timestamp]); }, [follows.timestamp]);

View File

@ -16,7 +16,7 @@ export function useTheme() {
useEffect(() => { useEffect(() => {
const osTheme = window.matchMedia("(prefers-color-scheme: light)"); const osTheme = window.matchMedia("(prefers-color-scheme: light)");
setTheme( setTheme(
preferences.theme === "system" && osTheme.matches ? "light" : preferences.theme === "light" ? "light" : "dark" preferences.theme === "system" && osTheme.matches ? "light" : preferences.theme === "light" ? "light" : "dark",
); );
osTheme.onchange = e => { osTheme.onchange = e => {
@ -28,5 +28,4 @@ export function useTheme() {
osTheme.onchange = null; osTheme.onchange = null;
}; };
}, [preferences.theme]); }, [preferences.theme]);
} }

View File

@ -1,21 +1,29 @@
import { unwrap } from "@snort/shared"; import { unwrap } from "@snort/shared";
import { EventExt, EventKind, NostrLink, NostrPrefix, TaggedNostrEvent, u256, Thread as ThreadInfo, } from "@snort/system"; import {
EventExt,
EventKind,
NostrLink,
NostrPrefix,
TaggedNostrEvent,
u256,
Thread as ThreadInfo,
} from "@snort/system";
import useThreadFeed from "Feed/ThreadFeed"; import useThreadFeed from "Feed/ThreadFeed";
import { findTag } from "SnortUtils"; import { findTag } from "SnortUtils";
import { ReactNode, createContext, useMemo, useState } from "react"; import { ReactNode, createContext, useMemo, useState } from "react";
import { useLocation } from "react-router-dom"; import { useLocation } from "react-router-dom";
export interface ThreadContext { export interface ThreadContext {
current: string, current: string;
root?: TaggedNostrEvent, root?: TaggedNostrEvent;
chains: Map<string, Array<TaggedNostrEvent>>, chains: Map<string, Array<TaggedNostrEvent>>;
data: Array<TaggedNostrEvent>, data: Array<TaggedNostrEvent>;
setCurrent: (i: string) => void; setCurrent: (i: string) => void;
} }
export const ThreadContext = createContext({} as ThreadContext) export const ThreadContext = createContext({} as ThreadContext);
export function ThreadContextWrapper({ link, children }: { link: NostrLink, children?: ReactNode }) { export function ThreadContextWrapper({ link, children }: { link: NostrLink; children?: ReactNode }) {
const location = useLocation(); const location = useLocation();
const [currentId, setCurrentId] = useState(link.id); const [currentId, setCurrentId] = useState(link.id);
const thread = useThreadFeed(link); const thread = useThreadFeed(link);
@ -32,7 +40,7 @@ export function ThreadContextWrapper({ link, children }: { link: NostrLink, chil
if (t?.root?.key === "a" && t?.root?.value) { if (t?.root?.key === "a" && t?.root?.value) {
const parsed = t.root.value.split(":"); const parsed = t.root.value.split(":");
replyTo = thread.data?.find( replyTo = thread.data?.find(
a => a.kind === Number(parsed[0]) && a.pubkey === parsed[1] && findTag(a, "d") === parsed[2] a => a.kind === Number(parsed[0]) && a.pubkey === parsed[1] && findTag(a, "d") === parsed[2],
)?.id; )?.id;
} }
if (replyTo) { if (replyTo) {
@ -53,7 +61,7 @@ export function ThreadContextWrapper({ link, children }: { link: NostrLink, chil
thread.data?.find( thread.data?.find(
ne => ne =>
ne.id === currentId || ne.id === currentId ||
(link.type === NostrPrefix.Address && findTag(ne, "d") === currentId && ne.pubkey === link.author) (link.type === NostrPrefix.Address && findTag(ne, "d") === currentId && ne.pubkey === link.author),
) ?? (location.state && "sig" in location.state ? (location.state as TaggedNostrEvent) : undefined); ) ?? (location.state && "sig" in location.state ? (location.state as TaggedNostrEvent) : undefined);
if (currentNote) { if (currentNote) {
const currentThread = EventExt.extractThread(currentNote); const currentThread = EventExt.extractThread(currentNote);
@ -69,7 +77,7 @@ export function ThreadContextWrapper({ link, children }: { link: NostrLink, chil
if (replyTo.key === "a" && replyTo.value) { if (replyTo.key === "a" && replyTo.value) {
const parsed = replyTo.value.split(":"); const parsed = replyTo.value.split(":");
return thread.data?.find( return thread.data?.find(
a => a.kind === Number(parsed[0]) && a.pubkey === parsed[1] && findTag(a, "d") === parsed[2] a => a.kind === Number(parsed[0]) && a.pubkey === parsed[1] && findTag(a, "d") === parsed[2],
); );
} }
if (replyTo.value) { if (replyTo.value) {
@ -100,11 +108,9 @@ export function ThreadContextWrapper({ link, children }: { link: NostrLink, chil
root, root,
chains, chains,
data: thread.data, data: thread.data,
setCurrent: v => setCurrentId(v) setCurrent: v => setCurrentId(v),
} as ThreadContext } as ThreadContext;
}, [root, chains]); }, [root, chains]);
return <ThreadContext.Provider value={ctxValue}> return <ThreadContext.Provider value={ctxValue}>{children}</ThreadContext.Provider>;
{children}
</ThreadContext.Provider>
} }

View File

@ -61,7 +61,7 @@
flex-direction: row; flex-direction: row;
border-radius: unset; border-radius: unset;
gap: 16px; gap: 16px;
--border-color: #3A3A3A; --border-color: #3a3a3a;
} }
.thread-overlay .modal-body > div:last-of-type { .thread-overlay .modal-body > div:last-of-type {

View File

@ -41,19 +41,25 @@ export function SnortDeckLayout() {
if (!login.publicKey) return null; if (!login.publicKey) return null;
const cols = ["notes", "media", "notifications", "articles"] as Array<Cols>; const cols = ["notes", "media", "notifications", "articles"] as Array<Cols>;
return <div className="deck-layout"> return (
<div className="deck-layout">
<DeckNav /> <DeckNav />
<div className="deck-cols"> <div className="deck-cols">
{cols.map(c => { {cols.map(c => {
switch (c) { switch (c) {
case "notes": return <NotesCol /> case "notes":
case "media": return <MediaCol setThread={setThread} /> return <NotesCol />;
case "articles": return <ArticlesCol /> case "media":
case "notifications": return <NotificationsCol /> return <MediaCol setThread={setThread} />;
case "articles":
return <ArticlesCol />;
case "notifications":
return <NotificationsCol />;
} }
})} })}
</div> </div>
{thread && <> {thread && (
<>
<Modal onClose={() => setThread(undefined)} className="thread-overlay"> <Modal onClose={() => setThread(undefined)} className="thread-overlay">
<ThreadContextWrapper link={createNostrLink(NostrPrefix.Note, thread)}> <ThreadContextWrapper link={createNostrLink(NostrPrefix.Note, thread)}>
<SpotlightFromThread onClose={() => setThread(undefined)} /> <SpotlightFromThread onClose={() => setThread(undefined)} />
@ -62,9 +68,11 @@ export function SnortDeckLayout() {
</div> </div>
</ThreadContextWrapper> </ThreadContextWrapper>
</Modal> </Modal>
</>} </>
)}
<Toaster /> <Toaster />
</div> </div>
);
} }
function SpotlightFromThread({ onClose }: { onClose: () => void }) { function SpotlightFromThread({ onClose }: { onClose: () => void }) {
@ -73,7 +81,7 @@ function SpotlightFromThread({ onClose }: { onClose: () => void }) {
const parsed = thread.root ? transformTextCached(thread.root.id, thread.root.content, thread.root.tags) : []; const parsed = thread.root ? transformTextCached(thread.root.id, thread.root.content, thread.root.tags) : [];
const images = parsed.filter(a => a.type === "media" && a.mimeType?.startsWith("image/")); const images = parsed.filter(a => a.type === "media" && a.mimeType?.startsWith("image/"));
return <SpotlightMedia images={images.map(a => a.content)} idx={0} onClose={onClose} /> return <SpotlightMedia images={images.map(a => a.content)} idx={0} onClose={onClose} />;
} }
function NotesCol() { function NotesCol() {
@ -118,25 +126,37 @@ function MediaCol({ setThread }: { setThread: (e: string) => void }) {
<FormattedMessage defaultMessage="Media" /> <FormattedMessage defaultMessage="Media" />
</div> </div>
<div className="image-grid p"> <div className="image-grid p">
<TimelineFollows postsOnly={true} liveStreams={false} noteFilter={e => { <TimelineFollows
postsOnly={true}
liveStreams={false}
noteFilter={e => {
const parsed = transformTextCached(e.id, e.content, e.tags); const parsed = transformTextCached(e.id, e.content, e.tags);
const images = parsed.filter(a => a.type === "media" && a.mimeType?.startsWith("image/")); const images = parsed.filter(a => a.type === "media" && a.mimeType?.startsWith("image/"));
return images.length > 0; return images.length > 0;
}} noteRenderer={e => { }}
noteRenderer={e => {
const parsed = transformTextCached(e.id, e.content, e.tags); const parsed = transformTextCached(e.id, e.content, e.tags);
const images = parsed.filter(a => a.type === "media" && a.mimeType?.startsWith("image/")); const images = parsed.filter(a => a.type === "media" && a.mimeType?.startsWith("image/"));
return <div className="media-note" key={e.id} style={{ return (
"--img": `url(${proxy(images[0].content)})` <div
} as CSSProperties} onClick={() => setThread(e.id)}></div> className="media-note"
}} /> key={e.id}
style={
{
"--img": `url(${proxy(images[0].content)})`,
} as CSSProperties
}
onClick={() => setThread(e.id)}></div>
);
}}
/>
</div> </div>
</div> </div>
); );
} }
function NotificationsCol() { function NotificationsCol() {
return ( return (
<div> <div>
<div className="deck-col-header flex g8"> <div className="deck-col-header flex g8">

View File

@ -164,12 +164,12 @@ const DefaultTab = () => {
const tab = publicKey ? preferences.defaultRootTab ?? `notes` : `trending/notes`; const tab = publicKey ? preferences.defaultRootTab ?? `notes` : `trending/notes`;
const elm = RootTabRoutes.find(a => a.path === tab)?.element; const elm = RootTabRoutes.find(a => a.path === tab)?.element;
return elm; return elm;
} };
export const RootTabRoutes = [ export const RootTabRoutes = [
{ {
path: "", path: "",
element: <DefaultTab /> element: <DefaultTab />,
}, },
{ {
path: "global", path: "global",

View File

@ -262,7 +262,7 @@ button.icon:hover {
} }
.light .btn { .light .btn {
color: #64748B; color: #64748b;
} }
.btn-warn { .btn-warn {

View File

@ -211,8 +211,8 @@ export const router = createBrowserRouter([
} }
return null; return null;
}, },
children: RootTabRoutes children: RootTabRoutes,
} },
]); ]);
const root = ReactDOM.createRoot(unwrap(document.getElementById("root"))); const root = ReactDOM.createRoot(unwrap(document.getElementById("root")));

View File

@ -10,8 +10,8 @@
"/4tOwT": "Überspringen", "/4tOwT": "Überspringen",
"/JE/X+": "Konto Hilfe", "/JE/X+": "Konto Hilfe",
"/PCavi": "Öffentlich", "/PCavi": "Öffentlich",
"/RD0e2": "Nostr nutzt digitale Signaturen, um manipulationssichere Notes zu erstellen, welche sicher auf viele Relays repliziert werden können, um eine redundante Speicherung deiner Inhalte zu bieten.", "/RD0e2": "Nostr nutzt digitale Signaturen, um manipulationssichere Notes zu erstellen, welche sicher auf viele Relais repliziert werden können, um eine redundante Speicherung deiner Inhalte zu bieten.",
"/Xf4UW": "Send anonymous usage metrics", "/Xf4UW": "Anonyme Nutzungsmetriken senden",
"/d6vEc": "Mach dein Profil leichter zu finden und zu teilen", "/d6vEc": "Mach dein Profil leichter zu finden und zu teilen",
"/n5KSF": "{n} ms", "/n5KSF": "{n} ms",
"00LcfG": "Mehr laden", "00LcfG": "Mehr laden",
@ -52,7 +52,7 @@
"4Z3t5i": "Verwende imgproxy um Bilder zu komprimieren", "4Z3t5i": "Verwende imgproxy um Bilder zu komprimieren",
"4rYCjn": "Notiz an mich selbst", "4rYCjn": "Notiz an mich selbst",
"5BVs2e": "Zap", "5BVs2e": "Zap",
"5CB6zB": "Zap Splits", "5CB6zB": "Zap-Aufteilungen",
"5JcXdV": "Konto erstellen", "5JcXdV": "Konto erstellen",
"5oTnfy": "Handle kaufen", "5oTnfy": "Handle kaufen",
"5rOdPG": "Sobald du deine Erweiterung für die Schlüsselverwaltung eingerichtet und einen Schlüssel generiert hast, kannst du unserem Prozess für neue Benutzer folgen, um dein Profil einzurichten und einige interessante Leute auf Nostr zu finden, denen du folgen kannst.", "5rOdPG": "Sobald du deine Erweiterung für die Schlüsselverwaltung eingerichtet und einen Schlüssel generiert hast, kannst du unserem Prozess für neue Benutzer folgen, um dein Profil einzurichten und einige interessante Leute auf Nostr zu finden, denen du folgen kannst.",
@ -61,7 +61,7 @@
"5ykRmX": "Zap senden", "5ykRmX": "Zap senden",
"65BmHb": "Bild von {host} konnte nicht durch Proxy geladen werden, klicke hier, um es direkt zu laden", "65BmHb": "Bild von {host} konnte nicht durch Proxy geladen werden, klicke hier, um es direkt zu laden",
"6Yfvvp": "Bekomme eine Identifikation", "6Yfvvp": "Bekomme eine Identifikation",
"6bgpn+": "Not all clients support this, you may still receive some zaps as if zap splits was not configured", "6bgpn+": "Nicht alle Clients unterstützen dies, deshalb kann es sein, dass du immer noch einige Zaps erhältst, als ob Zap-Aufteilungen nicht konfiguriert wäre",
"6ewQqw": "Gefällt ({n})", "6ewQqw": "Gefällt ({n})",
"6uMqL1": "Nicht bezahlt", "6uMqL1": "Nicht bezahlt",
"7+Domh": "Notes", "7+Domh": "Notes",
@ -69,8 +69,8 @@
"7hp70g": "NIP-05", "7hp70g": "NIP-05",
"8/vBbP": "Reposts ({n})", "8/vBbP": "Reposts ({n})",
"89q5wc": "Reposts bestätigen", "89q5wc": "Reposts bestätigen",
"8QDesP": "Zap {n} sats", "8QDesP": "{n} sats zappen",
"8Y6bZQ": "Invalid zap split: {input}", "8Y6bZQ": "Ungültige Zap-Aufteilung: {input}",
"8g2vyB": "Name ist zu lang", "8g2vyB": "Name ist zu lang",
"8v1NN+": "Verbindungsphrase", "8v1NN+": "Verbindungsphrase",
"9+Ddtu": "Weiter", "9+Ddtu": "Weiter",
@ -81,7 +81,7 @@
"9pMqYs": "Nostr-Adresse", "9pMqYs": "Nostr-Adresse",
"9wO4wJ": "Lightning Zahlungsanforderung", "9wO4wJ": "Lightning Zahlungsanforderung",
"ADmfQT": "Vorherige", "ADmfQT": "Vorherige",
"AGNz71": "Zap {n} sats an Alle", "AGNz71": "Allen {n} sats zappen",
"ASRK0S": "Dieser Autor wurde stummgeschalten", "ASRK0S": "Dieser Autor wurde stummgeschalten",
"Adk34V": "Profil erstellen", "Adk34V": "Profil erstellen",
"Ai8VHU": "Unbegrenzte Note Speicherung auf Snort Relais", "Ai8VHU": "Unbegrenzte Note Speicherung auf Snort Relais",
@ -91,7 +91,7 @@
"B4C47Y": "Name ist zu kurz", "B4C47Y": "Name ist zu kurz",
"B6+XJy": "hat gezappt", "B6+XJy": "hat gezappt",
"B6H7eJ": "nsec, npub, nip-05, hex", "B6H7eJ": "nsec, npub, nip-05, hex",
"BGCM48": "Schreibe Zugriff auf Snort-Relais mit 1 Jahr Event Speicherung", "BGCM48": "Schreibzugriff auf Snort Relais, mit 1 Jahr Speicherung von Events",
"BOUMjw": "Keine Nostr-Benutzer gefunden für {twitterUsername}", "BOUMjw": "Keine Nostr-Benutzer gefunden für {twitterUsername}",
"BOr9z/": "Snort ist ein Open-Source-Projekt, von begeisterten in ihrer Freizeit entwickelt", "BOr9z/": "Snort ist ein Open-Source-Projekt, von begeisterten in ihrer Freizeit entwickelt",
"BWpuKl": "Aktualisieren", "BWpuKl": "Aktualisieren",
@ -116,7 +116,7 @@
"EPYwm7": "Dein privater Schlüssel ist dein Passwort. Wenn du diesen Schlüssel verlierst, hast du keinen Zugang mehr zu deinem Konto! Kopiere ihn und bewahre ihn an einem sicheren Ort auf. Es gibt keine Möglichkeit, deinen privaten Schlüssel wiederherzustellen.", "EPYwm7": "Dein privater Schlüssel ist dein Passwort. Wenn du diesen Schlüssel verlierst, hast du keinen Zugang mehr zu deinem Konto! Kopiere ihn und bewahre ihn an einem sicheren Ort auf. Es gibt keine Möglichkeit, deinen privaten Schlüssel wiederherzustellen.",
"EWyQH5": "Global", "EWyQH5": "Global",
"Ebl/B2": "Auf {lang} Übersetzen", "Ebl/B2": "Auf {lang} Übersetzen",
"EcZF24": "Benutzerdefinierte Relays", "EcZF24": "Benutzerdefinierte Relais",
"EcglP9": "Schlüssel", "EcglP9": "Schlüssel",
"EnCOBJ": "Kaufen", "EnCOBJ": "Kaufen",
"Eqjl5K": "Nur Snort und unsere integrierten Partner bieten farbige Domainnamen als NIP-05 Kennzeichen. Sie können aber auch gerne andere Dienste nutzen.", "Eqjl5K": "Nur Snort und unsere integrierten Partner bieten farbige Domainnamen als NIP-05 Kennzeichen. Sie können aber auch gerne andere Dienste nutzen.",
@ -145,7 +145,7 @@
"HOzFdo": "Stummgeschaltet", "HOzFdo": "Stummgeschaltet",
"HWbkEK": "Cache leeren und neu laden", "HWbkEK": "Cache leeren und neu laden",
"HbefNb": "Wallet öffnen", "HbefNb": "Wallet öffnen",
"I9zn6f": "Pubkey", "I9zn6f": "Öfftl. Schlüssel",
"IDjHJ6": "Danke für die Verwendung von Snort. Wir würden uns über eine Spende freuen.", "IDjHJ6": "Danke für die Verwendung von Snort. Wir würden uns über eine Spende freuen.",
"IEwZvs": "Sind sie sicher, dass sie diese Notiz entpinnen möchten?", "IEwZvs": "Sind sie sicher, dass sie diese Notiz entpinnen möchten?",
"IKKHqV": "Folgt", "IKKHqV": "Folgt",
@ -155,7 +155,7 @@
"Ix8l+B": "Angesagte Notes", "Ix8l+B": "Angesagte Notes",
"J+dIsA": "Abonnements", "J+dIsA": "Abonnements",
"JCIgkj": "Benutzername", "JCIgkj": "Benutzername",
"JGrt9q": "Send sats to {name}", "JGrt9q": "Sats an {name} senden",
"JHEHCk": "Zaps ({n})", "JHEHCk": "Zaps ({n})",
"JPFYIM": "Keine Lightning-Adresse", "JPFYIM": "Keine Lightning-Adresse",
"JeoS4y": "Repost", "JeoS4y": "Repost",
@ -175,7 +175,7 @@
"LgbKvU": "Kommentar", "LgbKvU": "Kommentar",
"Lu5/Bj": "In Zapstr öffnen", "Lu5/Bj": "In Zapstr öffnen",
"Lw+I+J": "{n,plural,=0{{name} zappte} other{{name} & {n} andere zappten}}", "Lw+I+J": "{n,plural,=0{{name} zappte} other{{name} & {n} andere zappten}}",
"LwYmVi": "Zaps on this note will be split to the following users.", "LwYmVi": "Zaps auf diese Note werden an die folgenden Nutzer aufgeteilt.",
"M3Oirc": "Debug Menüs", "M3Oirc": "Debug Menüs",
"MBAYRO": "Zeigt \"ID kopieren\" und \"Event JSON kopieren\" im Kontextmenu jeder Nachricht an", "MBAYRO": "Zeigt \"ID kopieren\" und \"Event JSON kopieren\" im Kontextmenu jeder Nachricht an",
"MI2jkA": "Nicht verfügbar:", "MI2jkA": "Nicht verfügbar:",
@ -221,7 +221,7 @@
"RoOyAh": "Relais", "RoOyAh": "Relais",
"Rs4kCE": "Lesezeichen", "Rs4kCE": "Lesezeichen",
"RwFaYs": "Sortieren", "RwFaYs": "Sortieren",
"SMO+on": "Send zap to {name}", "SMO+on": "Zap an {name} senden",
"SOqbe9": "Lightning-Adresse aktualisieren", "SOqbe9": "Lightning-Adresse aktualisieren",
"SP0+yi": "Abonnement kaufen", "SP0+yi": "Abonnement kaufen",
"SX58hM": "Kopieren", "SX58hM": "Kopieren",
@ -251,10 +251,10 @@
"W2PiAr": "{n} Blockiert", "W2PiAr": "{n} Blockiert",
"W9355R": "Stummschaltung aufheben", "W9355R": "Stummschaltung aufheben",
"WONP5O": "Finden Sie Ihre Twitter Kontakte auf Nostr (Daten zur Verfügung gestellt von {provider})", "WONP5O": "Finden Sie Ihre Twitter Kontakte auf Nostr (Daten zur Verfügung gestellt von {provider})",
"WvGmZT": "npub / nprofile / nostr address", "WvGmZT": "npub / nprofile / Nostr-Adresse",
"WxthCV": "z.B. Jack", "WxthCV": "z.B. Jack",
"X7xU8J": "nsec, npub, nip-05, hex, mnemonic", "X7xU8J": "nsec, npub, nip-05, hex, mnemonic",
"XECMfW": "Send usage metrics", "XECMfW": "Nutzungsmetriken senden",
"XICsE8": "Datei-Hosts", "XICsE8": "Datei-Hosts",
"XgWvGA": "Reaktionen", "XgWvGA": "Reaktionen",
"Xopqkl": "Dein standardmäßiger Zap-Betrag ist {number} sats, Beispielwerte werden daraus berechnet.", "Xopqkl": "Dein standardmäßiger Zap-Betrag ist {number} sats, Beispielwerte werden daraus berechnet.",
@ -263,7 +263,7 @@
"Y31HTH": "Unterstütze die Entwicklung von Snort", "Y31HTH": "Unterstütze die Entwicklung von Snort",
"YDURw6": "URL des Dienstes", "YDURw6": "URL des Dienstes",
"YXA3AH": "Reaktionen aktivieren", "YXA3AH": "Reaktionen aktivieren",
"Z0FDj+": "Abonniere Snort {plan} für {price} und erhalte folgende Belohnungen", "Z0FDj+": "Abonniere Snort {plan} für {price} und erhalte folgende Prämien",
"Z4BMCZ": "Verbindungs-Passphrase eingeben", "Z4BMCZ": "Verbindungs-Passphrase eingeben",
"ZKORll": "Jetzt aktivieren", "ZKORll": "Jetzt aktivieren",
"ZLmyG9": "Mitwirkende", "ZLmyG9": "Mitwirkende",
@ -340,11 +340,11 @@
"jvo0vs": "Speichern", "jvo0vs": "Speichern",
"jzgQ2z": "{n} Reaktionen", "jzgQ2z": "{n} Reaktionen",
"k2veDA": "Schreiben", "k2veDA": "Schreiben",
"k7sKNy": "Unser eigener NIP-05-Verifizierungsdienst unterstützt die Entwicklung dieser Website. Unterstütze uns und erhalte ein Sonderabzeichen für deine Webseite!", "k7sKNy": "Unser eigener NIP-05-Verifizierungsdienst unterstützt die Entwicklung dieser Website. Unterstütze uns und erhalte ein Abzeichen auf unserer Seite!",
"kJYo0u": "{n,plural,=0{{name} hat gerepostet} other{{name} & {n} andere haben gerepostet}}", "kJYo0u": "{n,plural,=0{{name} hat gerepostet} other{{name} & {n} andere haben gerepostet}}",
"kaaf1E": "jetzt", "kaaf1E": "jetzt",
"kuPHYE": "{n,plural,=0{{name} gefällt das} other{{name} & {n} anderen gefällt das}}", "kuPHYE": "{n,plural,=0{{name} gefällt das} other{{name} & {n} anderen gefällt das}}",
"l+ikU1": "Alles im {plan}", "l+ikU1": "Alles aus {plan}",
"lBboHo": "Wenn du ein paar andere ausprobieren möchtest, besuche {link} für mehr!", "lBboHo": "Wenn du ein paar andere ausprobieren möchtest, besuche {link} für mehr!",
"lCILNz": "Jetzt kaufen", "lCILNz": "Jetzt kaufen",
"lD3+8a": "Bezahlen", "lD3+8a": "Bezahlen",
@ -380,7 +380,7 @@
"oxCa4R": "Das Erhalten eines Identifikators hilft Menschen, die Sie kennen, Ihre Identität zu bestätigen. Viele Leute können einen Benutzernamen wie @jack haben, aber es kann nur einen jack@cash.app geben.", "oxCa4R": "Das Erhalten eines Identifikators hilft Menschen, die Sie kennen, Ihre Identität zu bestätigen. Viele Leute können einen Benutzernamen wie @jack haben, aber es kann nur einen jack@cash.app geben.",
"p4N05H": "Hochladen", "p4N05H": "Hochladen",
"p85Uwy": "Aktive Abonnements", "p85Uwy": "Aktive Abonnements",
"pI+77w": "Herunterladbare Backups von Snort Relais", "pI+77w": "Herunterladbare Backups vom Snort Relais",
"puLNUJ": "Anheften", "puLNUJ": "Anheften",
"pzTOmv": "Follower", "pzTOmv": "Follower",
"qD9EUF": "E-Mail <> DM Brücke für deine Snort Nostr-Adresse", "qD9EUF": "E-Mail <> DM Brücke für deine Snort Nostr-Adresse",
@ -401,19 +401,19 @@
"rudscU": "Abonnements konnten nicht geladen werden, bitte versuchen Sie es später erneut", "rudscU": "Abonnements konnten nicht geladen werden, bitte versuchen Sie es später erneut",
"sUNhQE": "Nutzer", "sUNhQE": "Nutzer",
"sWnYKw": "Snort wurde darauf konzipiert ein Twitter ähnliches Erlebnis zu bieten.", "sWnYKw": "Snort wurde darauf konzipiert ein Twitter ähnliches Erlebnis zu bieten.",
"sZQzjQ": "Failed to parse zap split: {input}", "sZQzjQ": "Fehler beim Parsen der Zap-Aufteilung: {input}",
"svOoEH": "Namens-Squatting und Impersonation sind nicht erlaubt. Snort und unsere Partner behalten sich das Recht vor, bei einem Verstoß gegen diese Regel dein Handle zu löschen (nicht dein Konto - das kann dir niemand wegnehmen).", "svOoEH": "Namens-Squatting und Impersonation sind nicht erlaubt. Snort und unsere Partner behalten sich das Recht vor, bei einem Verstoß gegen diese Regel dein Handle zu löschen (nicht dein Konto - das kann dir niemand wegnehmen).",
"tOdNiY": "Dunkel", "tOdNiY": "Dunkel",
"th5lxp": "Sende Note zu einer Untergruppe deiner Schreib-Relays", "th5lxp": "Sende Note zu einer Untergruppe deiner Schreib-Relays",
"thnRpU": "Eine NIP-05 Verifizierung kann helfen:", "thnRpU": "Eine NIP-05 Verifizierung kann helfen:",
"ttxS0b": "Unterstützer Abzeichen", "ttxS0b": "Unterstützer-Abzeichen",
"u/vOPu": "Bezahlt", "u/vOPu": "Bezahlt",
"u4bHcR": "Sieh dir hier den Code an: {link}", "u4bHcR": "Sieh dir hier den Code an: {link}",
"uSV4Ti": "Reposts müssen manuell bestätigt werden", "uSV4Ti": "Reposts müssen manuell bestätigt werden",
"usAvMr": "Profil anpassen", "usAvMr": "Profil anpassen",
"ut+2Cd": "Holen Sie sich einen Partner-Identifikator", "ut+2Cd": "Holen Sie sich einen Partner-Identifikator",
"v8lolG": "Chat starten", "v8lolG": "Chat starten",
"vOKedj": "{n,plural,one {}=1{& {n} other} other{& {n} andere}}", "vOKedj": "{n,plural,one {}=1{& {n} anderer} other{& {n} andere}}",
"vU71Ez": "Bezahlen mit {wallet}", "vU71Ez": "Bezahlen mit {wallet}",
"vZ4quW": "NIP-05 ist eine DNS-basierte Verifizierungsspezifikation, die dabei hilft, dich als echten Benutzer zu validieren.", "vZ4quW": "NIP-05 ist eine DNS-basierte Verifizierungsspezifikation, die dabei hilft, dich als echten Benutzer zu validieren.",
"vhlWFg": "Umfrageoptionen", "vhlWFg": "Umfrageoptionen",
@ -442,7 +442,7 @@
"y1Z3or": "Sprache", "y1Z3or": "Sprache",
"yCLnBC": "LNURL oder Lightning-Adresse", "yCLnBC": "LNURL oder Lightning-Adresse",
"yCmnnm": "Global lesen von", "yCmnnm": "Global lesen von",
"zCb8fX": "Weight", "zCb8fX": "Gewichtung",
"zFegDD": "Kontakt", "zFegDD": "Kontakt",
"zINlao": "Eigentümer", "zINlao": "Eigentümer",
"zQvVDJ": "Alle", "zQvVDJ": "Alle",

View File

@ -23,7 +23,7 @@ export function linkToEventTag(link: NostrLink) {
} }
export function tagToNostrLink(tag: Array<string>) { export function tagToNostrLink(tag: Array<string>) {
switch(tag[0]) { switch (tag[0]) {
case "e": { case "e": {
return createNostrLink(NostrPrefix.Event, tag[1], tag.slice(2)); return createNostrLink(NostrPrefix.Event, tag[1], tag.slice(2));
} }