refactor(i18n): normalize translation keys

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
This commit is contained in:
david_bai
2026-03-27 14:04:28 +08:00
parent 8f6f0a9266
commit 57004b3a1f
33 changed files with 1159 additions and 1162 deletions
+6 -6
View File
@@ -33,7 +33,7 @@ export default function HomeClient({ messages, lang }: PageContentProps) {
<div className="w-full max-w-none">
{/* sr-only--screen-only: visually hidden */}
<h2 className={cn("sr-only", "text-3xl font-bold mb-8 text-center")}>
{messages.text.home.h2_screenOnly}
{messages.text.home.h2ScreenOnly}
</h2>
<ClipboardApp />
</div>
@@ -48,16 +48,16 @@ export default function HomeClient({ messages, lang }: PageContentProps) {
<section className="mb-12" aria-label="Product Demo">
<LazyLoadWrapper>
<h2 className="text-3xl font-bold mb-6 text-center">
{messages.text.home.h2_demo}
{messages.text.home.h2Demo}
</h2>
<p className="text-center mb-6 text-muted-foreground">
{messages.text.home.h2P_demo}
{messages.text.home.h2DemoDescription}
</p>
<YouTubePlayer videoId={youtube_videoId} />
<div className="mt-4 text-center">
<p className="mb-3 text-foreground">
{messages.text.home.watch_tips}
{messages.text.home.watchTip}
</p>
<a
className="flex justify-center gap-4 text-blue-500 hover:underline transition-colors"
@@ -65,7 +65,7 @@ export default function HomeClient({ messages, lang }: PageContentProps) {
target="_blank"
rel="noopener noreferrer"
>
{messages.text.home.youtube_tips}
{messages.text.home.youtubeTip}
</a>
<a
className="flex justify-center gap-4 text-blue-500 hover:underline transition-colors"
@@ -73,7 +73,7 @@ export default function HomeClient({ messages, lang }: PageContentProps) {
target="_blank"
rel="noopener noreferrer"
>
{messages.text.home.bilibili_tips}
{messages.text.home.bilibiliTip}
</a>
</div>
</LazyLoadWrapper>
+3 -3
View File
@@ -22,17 +22,17 @@ export default function AboutContent({ messages, lang }: AboutContentProps) {
href={`/${lang}/privacy`}
className="text-blue-500 hover:underline"
>
{messages.text.privacy.PrivacyPolicy_dis}
{messages.text.privacy.privacyPolicyLabel}
</a>
</li>
<li>
<a href={`/${lang}/terms`} className="text-blue-500 hover:underline">
{messages.text.terms.TermsOfUse_dis}
{messages.text.terms.termsOfUseLabel}
</a>
</li>
<li>
<a href={`/${lang}/help`} className="text-blue-500 hover:underline">
{messages.text.help.Help_dis}
{messages.text.help.helpLabel}
</a>
</li>
</ul>
+1 -1
View File
@@ -19,7 +19,7 @@ export async function generateMetadata({
}
const messages = await getDictionary(params.lang);
const blogWord = messages.text.Header.Blog_dis;
const blogWord = messages.text.Header.blogLabel;
const blogCap = blogWord.charAt(0).toUpperCase() + blogWord.slice(1);
return {
+4 -4
View File
@@ -26,7 +26,7 @@ export default async function BlogPost({
const messages = await getDictionary(params.lang);
if (!post) {
return <div>{messages.text.blog.post_not_found}</div>;
return <div>{messages.text.blog.postNotFound}</div>;
}
const siteUrl = getSiteUrl();
@@ -45,8 +45,8 @@ export default async function BlogPost({
});
const breadcrumbsLd = buildBreadcrumbJsonLd({
items: [
{ name: messages.text.Header.Home_dis, item: `${siteUrl}/${params.lang}` },
{ name: messages.text.Header.Blog_dis, item: `${siteUrl}/${params.lang}/blog` },
{ name: messages.text.Header.homeLabel, item: `${siteUrl}/${params.lang}` },
{ name: messages.text.Header.blogLabel, item: `${siteUrl}/${params.lang}/blog` },
{ name: post.frontmatter.title, item: postUrl },
],
});
@@ -92,7 +92,7 @@ export default async function BlogPost({
/>
</div>
</article>
<TableOfContents content={post.content} title={messages.text.blog.toc_title} />
<TableOfContents content={post.content} title={messages.text.blog.tocTitle} />
</div>
</div>
);
+3 -3
View File
@@ -21,8 +21,8 @@ export default async function BlogPage({
{/* Main Content */}
<main className="lg:col-span-8">
<div className="mb-12">
<h1 className="text-4xl font-bold mb-4">{messages.text.blog.list_title}</h1>
<p className="text-muted-foreground text-lg">{messages.text.blog.list_subtitle}</p>
<h1 className="text-4xl font-bold mb-4">{messages.text.blog.listTitle}</h1>
<p className="text-muted-foreground text-lg">{messages.text.blog.listSubtitle}</p>
</div>
{/* Articles List */}
@@ -38,7 +38,7 @@ export default async function BlogPage({
<div className="sticky top-8">
{/* Recent Posts */}
<div className="bg-card rounded-xl shadow-lg p-8 mb-8">
<h2 className="text-xl font-bold mb-6">{messages.text.blog.recent_posts}</h2>
<h2 className="text-xl font-bold mb-6">{messages.text.blog.recentPosts}</h2>
<div className="space-y-4">
{posts.slice(0, 5).map((post) => (
<Link
+5 -5
View File
@@ -15,8 +15,8 @@ export async function generateMetadata({
// Note: metadata text kept concise and localized
return {
title: `${messages.text.blog.tag_title_prefix}: ${decodedTag} - PrivyDrop`,
description: messages.text.blog.tag_subtitle_template.replace("{tag}", decodedTag),
title: `${messages.text.blog.tagTitlePrefix}: ${decodedTag} - PrivyDrop`,
description: messages.text.blog.tagSubtitleTemplate.replace("{tag}", decodedTag),
keywords: `${decodedTag}, blog, privydrop`,
metadataBase: new URL("https://www.privydrop.app"),
alternates: {
@@ -50,9 +50,9 @@ export default async function TagPage({
{/* Main Content */}
<main className="lg:col-span-8">
<div className="mb-12">
<h1 className="text-4xl font-bold mb-4">{messages.text.blog.tag_title_prefix}: {decodedTag}</h1>
<h1 className="text-4xl font-bold mb-4">{messages.text.blog.tagTitlePrefix}: {decodedTag}</h1>
<p className="text-muted-foreground text-lg">
{messages.text.blog.tag_subtitle_template.replace("{tag}", decodedTag)}
{messages.text.blog.tagSubtitleTemplate.replace("{tag}", decodedTag)}
</p>
</div>
@@ -63,7 +63,7 @@ export default async function TagPage({
<ArticleListItem key={post.slug} post={post} lang={lang} messages={messages} />
))
) : (
<p>{messages.text.blog.tag_empty}</p>
<p>{messages.text.blog.tagEmpty}</p>
)}
</div>
</main>
+2 -2
View File
@@ -46,7 +46,7 @@ export default function HelpContent({ messages, lang }: HelpContentProps) {
</li>
<li>
<a href={`/${lang}/terms`} className="text-blue-500 hover:underline">
{messages.text.terms.TermsOfUse_dis}
{messages.text.terms.termsOfUseLabel}
</a>
</li>
<li>
@@ -54,7 +54,7 @@ export default function HelpContent({ messages, lang }: HelpContentProps) {
href={`/${lang}/privacy`}
className="text-blue-500 hover:underline"
>
{messages.text.privacy.PrivacyPolicy_dis}
{messages.text.privacy.privacyPolicyLabel}
</a>
</li>
</ul>
+3 -3
View File
@@ -218,8 +218,8 @@ const ClipboardApp = () => {
<CardHeader className="px-3 sm:px-6 py-3 sm:py-6">
<CardTitle className="text-lg sm:text-xl">
{activeTab === "send"
? messages.text.ClipboardApp.html.shareTitle_dis
: messages.text.ClipboardApp.html.retrieveTitle_dis}
? messages.text.ClipboardApp.html.shareTitleLabel
: messages.text.ClipboardApp.html.retrieveTitleLabel}
</CardTitle>
</CardHeader>
<CardContent className="px-3 sm:px-6">
@@ -261,7 +261,7 @@ const ClipboardApp = () => {
<Card className="border-2 sm:border-4 shadow-md mt-2 sm:mt-4">
<CardHeader className="pb-3 sm:pb-6">
<CardTitle className="text-base sm:text-lg">
{messages.text.ClipboardApp.html.RetrieveMethodTitle}
{messages.text.ClipboardApp.html.retrieveMethodTitle}
</CardTitle>
</CardHeader>
<CardContent className="pt-0 px-3 sm:px-6">
@@ -120,7 +120,7 @@ export default function CachedIdActionButton({
clearTimeout(saveTimerRef.current);
saveTimerRef.current = null;
}
putMessageInMs(messages.text.ClipboardApp.saveId_success, isShareEnd);
putMessageInMs(messages.text.ClipboardApp.saveIdSuccessMessage, isShareEnd);
}
return;
}
@@ -165,7 +165,7 @@ export default function CachedIdActionButton({
getInputValue,
setInputValue,
putMessageInMs,
messages.text.ClipboardApp.saveId_success,
messages.text.ClipboardApp.saveIdSuccessMessage,
isShareEnd,
dblClickWindowMs,
saveModeDurationMs,
@@ -176,8 +176,8 @@ export default function CachedIdActionButton({
<Tooltip
content={
isSaveMode
? messages.text.ClipboardApp.html.saveId_tips
: messages.text.ClipboardApp.html.useCachedId_tips
? messages.text.ClipboardApp.html.saveIdTip
: messages.text.ClipboardApp.html.useCachedIdTip
}
>
<span className="inline-block">
@@ -191,8 +191,8 @@ export default function CachedIdActionButton({
}
>
{isSaveMode
? messages.text.ClipboardApp.html.saveId_dis
: messages.text.ClipboardApp.html.useCachedId_dis}
? messages.text.ClipboardApp.html.saveIdLabel
: messages.text.ClipboardApp.html.useCachedIdLabel}
</Button>
</span>
</Tooltip>
@@ -319,15 +319,15 @@ const FileListDisplay: React.FC<FileListDisplayProps> = ({
<TransferProgress
message={
mode === "sender"
? messages.text.FileListDisplay.sending_dis
: messages.text.FileListDisplay.receiving_dis
? messages.text.FileListDisplay.sendingLabel
: messages.text.FileListDisplay.receivingLabel
}
progress={progress}
/>
</div>
) : showCompletion ? (
<span className="text-sm text-green-500 whitespace-nowrap">
{messages.text.FileListDisplay.finish_dis}
{messages.text.FileListDisplay.finishedLabel}
</span>
) : null}
@@ -351,7 +351,7 @@ const FileListDisplay: React.FC<FileListDisplayProps> = ({
{/* display download Num*/}
{mode === "sender" && (
<span className="text-xs sm:text-sm whitespace-nowrap">
{messages.text.FileListDisplay.downloadNum_dis}: {downloadCount}
{messages.text.FileListDisplay.downloadCountLabel}: {downloadCount}
</span>
)}
{mode === "sender" && onDelete && (
@@ -370,7 +370,7 @@ const FileListDisplay: React.FC<FileListDisplayProps> = ({
>
<Trash2 className="h-3 w-3 sm:h-4 sm:w-4 sm:mr-2" />
<span className="hidden sm:inline">
{messages.text.FileListDisplay.delete_dis}
{messages.text.FileListDisplay.deleteLabel}
</span>
</Button>
)}
@@ -384,7 +384,7 @@ const FileListDisplay: React.FC<FileListDisplayProps> = ({
const formatSize = formatFileSize(item.size);
const tooltipContent = isFolder
? `${formatFolderTips(
messages!.text.FileListDisplay.folder_tips_template,
messages!.text.FileListDisplay.folderSummaryTemplate,
item.name,
item.fileCount || 0,
formatSize
@@ -407,7 +407,7 @@ const FileListDisplay: React.FC<FileListDisplayProps> = ({
<span className="text-xs sm:text-sm text-muted-foreground">
{isFolder
? `${formatFolderDis(
messages!.text.FileListDisplay.folder_dis_template,
messages!.text.FileListDisplay.folderInlineTemplate,
item.fileCount || 0,
formatSize
)}`
@@ -433,16 +433,16 @@ const FileListDisplay: React.FC<FileListDisplayProps> = ({
<div className="mb-2">
<AutoPopupDialog
storageKey="Choose-location-popup-shown"
title={messages.text.FileListDisplay.PopupDialog_title}
title={messages.text.FileListDisplay.popupDialogTitle}
description={
messages.text.FileListDisplay.PopupDialog_description
messages.text.FileListDisplay.popupDialogDescription
}
condition={() => needPickLocation}
/>
{/* Regular reminder to select the save directory */}
<div className="flex items-center">
<p className="text-red-500 mb-2">
{messages.text.FileListDisplay.chooseSavePath_tips}
{messages.text.FileListDisplay.chooseSavePathTip}
</p>
{onLocationPick && (
<Button
@@ -454,7 +454,7 @@ const FileListDisplay: React.FC<FileListDisplayProps> = ({
size="sm"
className="mr-2 text-red-500"
>
{messages.text.FileListDisplay.chooseSavePath_dis}
{messages.text.FileListDisplay.chooseSavePathLabel}
</Button>
)}
</div>
@@ -44,14 +44,14 @@ const FileTransferButton = ({
// Display different tooltips based on status
const getTooltipContent = () => {
if (isSavedToDisk)
return messages!.text.FileTransferButton.SavedToDisk_tips;
return messages!.text.FileTransferButton.savedToDiskTip;
if (isCurrentFileTransferring)
return messages!.text.FileTransferButton.CurrentFileTransferring_tips;
return messages!.text.FileTransferButton.currentFileTransferringTip;
if (isPendingSave)
return messages!.text.FileTransferButton.PendingSave_tips;
return messages!.text.FileTransferButton.pendingSaveTip;
if (isOtherFileTransferring)
return messages!.text.FileTransferButton.OtherFileTransferring_tips;
return messages!.text.FileTransferButton.download_tips;
return messages!.text.FileTransferButton.otherFileTransferringTip;
return messages!.text.FileTransferButton.downloadTip;
};
// Set different button styles and class names based on status
@@ -108,12 +108,12 @@ const FileTransferButton = ({
}`}
/>
{isSavedToDisk
? messages.text.FileTransferButton.Saved_dis
? messages.text.FileTransferButton.savedLabel
: isPendingSave
? messages.text.FileTransferButton.Save_dis
? messages.text.FileTransferButton.saveLabel
: isOtherFileTransferring
? messages.text.FileTransferButton.Waiting_dis
: messages.text.FileTransferButton.Download_dis}
? messages.text.FileTransferButton.waitingLabel
: messages.text.FileTransferButton.downloadLabel}
</Button>
</span>
</TooltipTrigger>
@@ -52,7 +52,7 @@ const FileUploadHandler: React.FC<FileUploadHandlerProps> = ({
const fileInputRef = useRef<HTMLInputElement>(null);
// File selector -- message prompt
const [fileText, setFileText] = useState<string>(
en.text.fileUploadHandler.NoFileChosen_tips
en.text.fileUploadHandler.noFileChosenTip
);
const [isModalOpen, setIsModalOpen] = useState(false);
@@ -62,7 +62,7 @@ const FileUploadHandler: React.FC<FileUploadHandlerProps> = ({
getDictionary(locale)
.then((dict) => {
setMessages(dict);
setFileText(dict.text.fileUploadHandler.NoFileChosen_tips);
setFileText(dict.text.fileUploadHandler.noFileChosenTip);
})
.catch((error) => console.error("Failed to load messages:", error));
}
@@ -77,14 +77,14 @@ const FileUploadHandler: React.FC<FileUploadHandlerProps> = ({
const folderNum = newFiles.filter((file) => file.folderName).length;
const choose_dis = formatFileChosen(
messages!.text.fileUploadHandler.fileChosen_tips_template,
messages!.text.fileUploadHandler.fileChosenTemplate,
fileNum,
folderNum
);
setFileText(choose_dis);
setTimeout(
() => setFileText(messages!.text.fileUploadHandler.NoFileChosen_tips),
() => setFileText(messages!.text.fileUploadHandler.noFileChosenTip),
2000
);
// Reset the file input
@@ -164,7 +164,7 @@ const FileUploadHandler: React.FC<FileUploadHandlerProps> = ({
onClick={handleZoneClick}
>
<p className="text-sm text-muted-foreground mb-4">
{messages.text.fileUploadHandler.chooseFileTips}
{messages.text.fileUploadHandler.chooseFileTip}
</p>
<Upload className="h-12 w-12 mx-auto mb-4 text-primary" />
<p className="text-sm text-muted-foreground">{fileText}</p>
@@ -204,13 +204,13 @@ const FileUploadHandler: React.FC<FileUploadHandlerProps> = ({
onClick={handleSelectFile}
className="px-4 py-2 rounded transition-colors bg-primary text-primary-foreground hover:bg-primary/90"
>
{messages.text.fileUploadHandler.SelectFile_dis}
{messages.text.fileUploadHandler.selectFileLabel}
</button>
<button
onClick={handleSelectFolder}
className="px-4 py-2 rounded transition-colors bg-secondary text-secondary-foreground hover:bg-secondary/80"
>
{messages.text.fileUploadHandler.SelectFolder_dis}
{messages.text.fileUploadHandler.selectFolderLabel}
</button>
</div>
</DialogContent>
@@ -17,7 +17,7 @@ const FullScreenDropZone: React.FC<FullScreenDropZoneProps> = ({
<div className="fixed inset-0 z-50 flex flex-col items-center justify-center bg-black bg-opacity-70 backdrop-blur-sm">
<Upload className="h-24 w-24 text-white animate-bounce" />
<p className="mt-6 text-2xl font-bold text-white">
{messages.text.fileUploadHandler.dragTips}
{messages.text.fileUploadHandler.dragTip}
</p>
</div>
);
@@ -101,15 +101,15 @@ export function RetrieveTabPanel({
<div className="mb-3 text-sm text-muted-foreground">
{retrieveRoomStatusText ||
(isReceiverInRoom
? messages.text.ClipboardApp.roomStatus.connected_dis
: messages.text.ClipboardApp.roomStatus.receiverEmptyMsg)}
? messages.text.ClipboardApp.roomStatus.connectedLabel
: messages.text.ClipboardApp.roomStatus.receiverEmptyMessage)}
</div>
<div className="space-y-3 mb-4">
{/* Room ID input section */}
<div className="space-y-2">
<div className="flex flex-col sm:flex-row gap-2">
<ReadClipboardButton
title={messages.text.ClipboardApp.html.readClipboard_dis}
title={messages.text.ClipboardApp.html.readClipboardLabel}
onRead={setRetrieveRoomIdInput}
/>
{/* Save/Use Cached ID Button placed after Paste button */}
@@ -125,7 +125,7 @@ export function RetrieveTabPanel({
value={retrieveRoomIdInput}
onChange={(e) => setRetrieveRoomIdInput(e.target.value)}
placeholder={
messages.text.ClipboardApp.html.retrieveRoomId_placeholder
messages.text.ClipboardApp.html.retrieveRoomIdPlaceholder
}
className="flex-1 min-w-0"
/>
@@ -140,7 +140,7 @@ export function RetrieveTabPanel({
ref={retrieveJoinRoomBtnRef}
disabled={isReceiverInRoom || !retrieveRoomIdInput.trim()}
>
{messages.text.ClipboardApp.html.joinRoom_dis}
{messages.text.ClipboardApp.html.joinRoomLabel}
</Button>
<Button
variant={isAnyFileTransferring ? "destructive" : "outline"}
@@ -149,8 +149,8 @@ export function RetrieveTabPanel({
className="w-full sm:w-auto px-4 order-2"
>
{isAnyFileTransferring
? messages.text.ClipboardApp.roomStatus.leaveRoomBtn + " ⚠️"
: messages.text.ClipboardApp.roomStatus.leaveRoomBtn}
? messages.text.ClipboardApp.roomStatus.leaveRoomLabel + " ⚠️"
: messages.text.ClipboardApp.roomStatus.leaveRoomLabel}
</Button>
</div>
</div>
@@ -161,7 +161,7 @@ export function RetrieveTabPanel({
</div>
<div className="flex justify-start">
<WriteClipboardButton
title={messages.text.ClipboardApp.html.Copy_dis}
title={messages.text.ClipboardApp.html.copyLabel}
textToCopy={richTextToPlainText(retrievedContent)}
/>
</div>
@@ -139,17 +139,17 @@ export function SendTabPanel({
<div className="mb-3 text-sm text-muted-foreground">
{shareRoomStatusText ||
(isSenderInRoom
? messages.text.ClipboardApp.roomStatus.onlyOneMsg
: messages.text.ClipboardApp.roomStatus.senderEmptyMsg)}
? messages.text.ClipboardApp.roomStatus.onlyOneMessage
: messages.text.ClipboardApp.roomStatus.senderEmptyMessage)}
</div>
<RichTextEditor value={shareContent} onChange={updateShareContent} />
<div className="flex flex-col sm:flex-row gap-2 my-3">
<ReadClipboardButton
title={messages.text.ClipboardApp.html.Paste_dis}
title={messages.text.ClipboardApp.html.pasteLabel}
onRead={updateShareContent}
/>
<WriteClipboardButton
title={messages.text.ClipboardApp.html.Copy_dis}
title={messages.text.ClipboardApp.html.copyLabel}
textToCopy={richTextToPlainText(shareContent)}
/>
</div>
@@ -167,7 +167,7 @@ export function SendTabPanel({
{/* Room ID input section */}
<div className="space-y-2">
<p className="text-sm text-muted-foreground">
{messages.text.ClipboardApp.html.inputRoomId_tips}
{messages.text.ClipboardApp.html.inputRoomIdTip}
</p>
<div className="flex flex-col sm:flex-row gap-2">
<Input
@@ -177,7 +177,7 @@ export function SendTabPanel({
onPaste={handlePaste}
className="flex-1 min-w-0"
placeholder={
messages.text.ClipboardApp.html.retrieveRoomId_placeholder
messages.text.ClipboardApp.html.retrieveRoomIdPlaceholder
}
/>
<Button
@@ -187,8 +187,8 @@ export function SendTabPanel({
disabled={isSenderInRoom}
>
{isSimpleIdMode
? messages.text.ClipboardApp.html.generateRandomId_tips
: messages.text.ClipboardApp.html.generateSimpleId_tips}
? messages.text.ClipboardApp.html.generateRandomIdTip
: messages.text.ClipboardApp.html.generateSimpleIdTip}
</Button>
{/* Save/Use Cached ID Button in between */}
<CachedIdActionButton
@@ -208,7 +208,7 @@ export function SendTabPanel({
onClick={() => joinRoom(true, inputFieldValue.trim())}
disabled={isSenderInRoom || !inputFieldValue.trim()}
>
{messages.text.ClipboardApp.html.joinRoom_dis}
{messages.text.ClipboardApp.html.joinRoomLabel}
</Button>
</div>
</div>
@@ -219,7 +219,7 @@ export function SendTabPanel({
className="flex-1 order-1"
onClick={generateShareLinkAndBroadcast}
loadingText={
messages.text.ClipboardApp.html.SyncSending_loadingText
messages.text.ClipboardApp.html.syncSendingLoadingLabel
}
disabled={
!isSenderInRoom ||
@@ -228,7 +228,7 @@ export function SendTabPanel({
isAnyFileTransferring
}
>
{messages.text.ClipboardApp.html.SyncSending_dis}
{messages.text.ClipboardApp.html.syncSendingLabel}
</AnimatedButton>
<Button
variant={isAnyFileTransferring ? "destructive" : "outline"}
@@ -237,8 +237,8 @@ export function SendTabPanel({
className="w-full sm:w-auto px-4 order-2"
>
{isAnyFileTransferring
? messages.text.ClipboardApp.roomStatus.leaveRoomBtn + " ⚠️"
: messages.text.ClipboardApp.roomStatus.leaveRoomBtn}
? messages.text.ClipboardApp.roomStatus.leaveRoomLabel + " ⚠️"
: messages.text.ClipboardApp.roomStatus.leaveRoomLabel}
</Button>
</div>
</div>
@@ -122,7 +122,7 @@ const ShareCard: React.FC<ShareCardProps> = ({ RoomID, shareLink }) => {
return (
<div className="bg-primary/10 p-2 sm:p-4 rounded-lg border border-primary/20">
<p className="text-primary mb-3 sm:mb-4 text-sm sm:text-base">
{messages.text.RetrieveMethod.P}
{messages.text.RetrieveMethod.introMessage}
</p>
{/* Mobile-first responsive layout */}
@@ -131,14 +131,14 @@ const ShareCard: React.FC<ShareCardProps> = ({ RoomID, shareLink }) => {
<div className="bg-card p-2 sm:p-3 rounded-lg border border-border">
<div className="space-y-2">
<p className="text-sm font-medium text-foreground">
{messages.text.RetrieveMethod.RoomId_tips}
{messages.text.RetrieveMethod.roomIdTip}
</p>
<div className="flex flex-col sm:flex-row sm:items-center gap-2">
<code className="flex-1 bg-muted px-2 py-1 rounded text-sm font-mono break-all">
{RoomID}
</code>
<WriteClipboardButton
title={messages.text.RetrieveMethod.copyRoomId_tips}
title={messages.text.RetrieveMethod.copyRoomIdTip}
textToCopy={RoomID}
/>
</div>
@@ -149,14 +149,14 @@ const ShareCard: React.FC<ShareCardProps> = ({ RoomID, shareLink }) => {
<div className="bg-card p-2 sm:p-3 rounded-lg border border-border">
<div className="space-y-2">
<p className="text-sm font-medium text-foreground">
{messages.text.RetrieveMethod.url_tips}
{messages.text.RetrieveMethod.urlTip}
</p>
<div className="bg-muted px-2 py-2 rounded text-xs sm:text-sm break-all font-mono">
{shareLink}
</div>
<div className="flex justify-start">
<WriteClipboardButton
title={messages.text.RetrieveMethod.copyUrl_tips}
title={messages.text.RetrieveMethod.copyUrlTip}
textToCopy={shareLink}
/>
</div>
@@ -167,7 +167,7 @@ const ShareCard: React.FC<ShareCardProps> = ({ RoomID, shareLink }) => {
<div className="bg-card p-2 sm:p-3 rounded-lg border border-border">
<div className="space-y-3">
<p className="text-sm font-medium text-foreground">
{messages.text.RetrieveMethod.scanQR_tips}
{messages.text.RetrieveMethod.scanQrTip}
</p>
{/* QR Code display area - moved up for better mobile UX */}
@@ -194,12 +194,12 @@ const ShareCard: React.FC<ShareCardProps> = ({ RoomID, shareLink }) => {
{isCopied ? (
<>
<Check className="w-4 h-4 mr-2" />
{messages.text.RetrieveMethod.Copied_dis}
{messages.text.RetrieveMethod.copiedLabel}
</>
) : (
<>
<Copy className="mr-2 h-4 w-4" />
{messages.text.RetrieveMethod.Copy_QR_dis}
{messages.text.RetrieveMethod.copyQrLabel}
</>
)}
</Button>
@@ -210,7 +210,7 @@ const ShareCard: React.FC<ShareCardProps> = ({ RoomID, shareLink }) => {
className="w-full"
>
<Download className="mr-2 h-4 w-4" />
{messages.text.RetrieveMethod.download_QR_dis}
{messages.text.RetrieveMethod.downloadQrLabel}
</Button>
</div>
</div>
+1 -1
View File
@@ -59,7 +59,7 @@ export function ArticleListItem({ post, lang, messages }: ArticleListItemProps)
href={`/${lang}/blog/${post.slug}`}
className="text-primary hover:text-primary/80 font-medium inline-flex items-center text-lg"
>
{messages.text.blog.read_more}
{messages.text.blog.readMore}
<svg
className="w-5 h-5 ml-2"
viewBox="0 0 24 24"
+2 -2
View File
@@ -69,11 +69,11 @@ export default function FAQSection({
{showTitle &&
(isInToolPage ? (
<h2 className={`text-3xl ${titleClasses}`}>
{messages.text.faqs.FAQ_dis}
{messages.text.faqs.faqLabel}
</h2>
) : (
<h1 className={`text-4xl ${titleClasses}`}>
{messages.text.faqs.FAQ_dis}
{messages.text.faqs.faqLabel}
</h1>
))}
<Accordion type="single" collapsible className="w-full">
+4 -4
View File
@@ -25,7 +25,7 @@ export function Footer({ messages, lang }: FooterProps) {
/>
<p className="text-sm text-muted-foreground">
&copy; {new Date().getFullYear()}{" "}
{messages.text.Footer.CopyrightNotice}
{messages.text.Footer.copyrightNotice}
</p>
</div>
@@ -38,7 +38,7 @@ export function Footer({ messages, lang }: FooterProps) {
href={`/${lang}/terms`}
className="text-sm text-muted-foreground hover:text-foreground transition-colors"
>
{messages.text.Footer.Terms_dis}
{messages.text.Footer.termsLabel}
</Link>
</li>
<li>
@@ -46,14 +46,14 @@ export function Footer({ messages, lang }: FooterProps) {
href={`/${lang}/privacy`}
className="text-sm text-muted-foreground hover:text-foreground transition-colors"
>
{messages.text.Footer.Privacy_dis}
{messages.text.Footer.privacyLabel}
</Link>
</li>
{/* Entry for supported languages */}
<li>
<span className="text-sm text-muted-foreground font-bold">
{messages.text.Footer.SupportedLanguages}:
{messages.text.Footer.supportedLanguagesLabel}:
</span>
</li>
{Object.entries(languageDisplayNames).map(([code, name]) => (
+8 -8
View File
@@ -28,14 +28,14 @@ const Header = ({ messages, lang }: HeaderProps) => {
// Configuration for navigation items
const navItems = [
{ href: `/${lang}`, label: messages.text.Header.Home_dis },
{ href: `/${lang}/features`, label: messages.text.Header.Features_dis },
{ href: `/${lang}/blog`, label: messages.text.Header.Blog_dis },
{ href: `/${lang}/about`, label: messages.text.Header.About_dis },
{ href: `/${lang}/help`, label: messages.text.Header.Help_dis },
{ href: `/${lang}/faq`, label: messages.text.Header.FAQ_dis },
{ href: `/${lang}/terms`, label: messages.text.Header.Terms_dis },
{ href: `/${lang}/privacy`, label: messages.text.Header.Privacy_dis },
{ href: `/${lang}`, label: messages.text.Header.homeLabel },
{ href: `/${lang}/features`, label: messages.text.Header.featuresLabel },
{ href: `/${lang}/blog`, label: messages.text.Header.blogLabel },
{ href: `/${lang}/about`, label: messages.text.Header.aboutLabel },
{ href: `/${lang}/help`, label: messages.text.Header.helpLabel },
{ href: `/${lang}/faq`, label: messages.text.Header.faqLabel },
{ href: `/${lang}/terms`, label: messages.text.Header.termsLabel },
{ href: `/${lang}/privacy`, label: messages.text.Header.privacyLabel },
];
// GitHub repository URL
+8 -8
View File
@@ -11,18 +11,18 @@ export default function HowItWorks({ messages }: PageContentProps) {
const steps = [
{
number: 1,
title: messages!.text.HowItWorks.step1_title,
description: messages!.text.HowItWorks.step1_description,
title: messages!.text.HowItWorks.step1Title,
description: messages!.text.HowItWorks.step1Description,
},
{
number: 2,
title: messages!.text.HowItWorks.step2_title,
description: messages!.text.HowItWorks.step2_description,
title: messages!.text.HowItWorks.step2Title,
description: messages!.text.HowItWorks.step2Description,
},
{
number: 3,
title: messages!.text.HowItWorks.step3_title,
description: messages!.text.HowItWorks.step3_description,
title: messages!.text.HowItWorks.step3Title,
description: messages!.text.HowItWorks.step3Description,
},
];
@@ -33,9 +33,9 @@ export default function HowItWorks({ messages }: PageContentProps) {
<h2 className="text-3xl md:text-4xl font-bold mb-6">
{messages.text.HowItWorks.h2}
</h2>
<p className="text-muted-foreground mb-8">{messages.text.HowItWorks.h2_P}</p>
<p className="text-muted-foreground mb-8">{messages.text.HowItWorks.h2Description}</p>
<Button className="bg-gradient-to-r from-purple-500 to-blue-500 hover:from-purple-600 hover:to-blue-600 text-white rounded-full px-8 py-6 text-lg">
{messages.text.HowItWorks.btn_try}
{messages.text.HowItWorks.tryNowLabel}
</Button>
</div>
+1 -1
View File
@@ -20,7 +20,7 @@ export default function SystemDiagram({ messages }: PageContentProps) {
className="mx-auto mb-6"
/>
<p className="mt-8 text-center max-w-2xl mx-auto">
{messages.text.SystemDiagram.h2_P}
{messages.text.SystemDiagram.h2Description}
</p>
</div>
</section>
+126 -126
View File
@@ -56,37 +56,37 @@ export const de: Messages = {
},
text: {
Header: {
Home_dis: "Startseite",
Blog_dis: "Blog",
About_dis: "Über uns",
Help_dis: "Hilfe",
FAQ_dis: "FAQ",
Features_dis: "Kernfunktionen",
Terms_dis: "Nutzungsbedingungen",
Privacy_dis: "Datenschutz",
homeLabel: "Startseite",
blogLabel: "Blog",
aboutLabel: "Über uns",
helpLabel: "Hilfe",
faqLabel: "FAQ",
featuresLabel: "Kernfunktionen",
termsLabel: "Nutzungsbedingungen",
privacyLabel: "Datenschutz",
},
Footer: {
CopyrightNotice: "PrivyDrop. Alle Rechte vorbehalten.",
Terms_dis: "Nutzungsbedingungen",
Privacy_dis: "Datenschutzrichtlinie",
SupportedLanguages: "Unterstützte Sprachen",
copyrightNotice: "PrivyDrop. Alle Rechte vorbehalten.",
termsLabel: "Nutzungsbedingungen",
privacyLabel: "Datenschutzrichtlinie",
supportedLanguagesLabel: "Unterstützte Sprachen",
},
blog: {
list_title: "Blog",
list_subtitle: "Neueste Artikel und Updates",
recent_posts: "Neueste Beiträge",
listTitle: "Blog",
listSubtitle: "Neueste Artikel und Updates",
recentPosts: "Neueste Beiträge",
tags: "Schlagwörter",
read_more: "Weiterlesen",
readMore: "Weiterlesen",
by: "von",
post_not_found: "Beitrag nicht gefunden",
toc_title: "Inhaltsverzeichnis",
tag_title_prefix: "Schlagwort",
tag_subtitle_template: "Artikel mit dem Schlagwort {tag}",
tag_empty: "Keine Artikel für dieses Schlagwort gefunden.",
postNotFound: "Beitrag nicht gefunden",
tocTitle: "Inhaltsverzeichnis",
tagTitlePrefix: "Schlagwort",
tagSubtitleTemplate: "Artikel mit dem Schlagwort {tag}",
tagEmpty: "Keine Artikel für dieses Schlagwort gefunden.",
},
privacy: {
PrivacyPolicy_dis: "Datenschutzrichtlinie",
privacyPolicyLabel: "Datenschutzrichtlinie",
h1: "PrivyDrop Datenschutzrichtlinie",
h1_P: "Bei PrivyDrop sind wir bestrebt, Ihre Privatsphäre zu schützen und Ihre persönlichen Daten zu sichern. Diese Datenschutzrichtlinie beschreibt, wie wir die Daten, die Sie bei der Nutzung unseres Dienstes bereitstellen, sammeln, verwenden und schützen.",
h2_1: "Informationssammlung",
@@ -106,7 +106,7 @@ export const de: Messages = {
"Wenn Sie Fragen oder Bedenken zu unseren Datenschutzpraktiken haben, kontaktieren Sie uns bitte unter",
},
terms: {
TermsOfUse_dis: "Nutzungsbedingungen",
termsOfUseLabel: "Nutzungsbedingungen",
h1: "PrivyDrop Nutzungsbedingungen",
h1_P: "Durch die Nutzung des PrivyDrop-Dienstes erklären Sie sich mit diesen Nutzungsbedingungen einverstanden. Wenn Sie diesen Bedingungen nicht zustimmen, nutzen Sie den Dienst bitte nicht.",
h2_1: "Nutzung des Dienstes",
@@ -126,7 +126,7 @@ export const de: Messages = {
"Wir behalten uns das Recht vor, diese Nutzungsbedingungen jederzeit zu aktualisieren. Alle Änderungen werden wirksam, sobald die aktualisierten Bedingungen auf unserer Website veröffentlicht werden. Es liegt in Ihrer Verantwortung, die Nutzungsbedingungen regelmäßig auf Änderungen zu überprüfen.",
},
help: {
Help_dis: "Hilfe",
helpLabel: "Hilfe",
h1: "PrivyDrop Hilfe und Support",
h1_P: "Wir sind hier, um Ihnen zu helfen, das Beste aus PrivyDrop herauszuholen. Wenn Sie Fragen haben oder Unterstützung benötigen, zögern Sie bitte nicht, uns zu kontaktieren.",
h2_1: "Kontaktieren Sie uns",
@@ -148,21 +148,21 @@ export const de: Messages = {
},
HowItWorks: {
h2: "Wie es funktioniert",
h2_P: "Teilen Sie Dateien und Nachrichten sofort in drei einfachen Schritten",
btn_try: "Jetzt ausprobieren →",
step1_title: "Text eingeben oder Dateien auswählen",
step1_description:
h2Description: "Teilen Sie Dateien und Nachrichten sofort in drei einfachen Schritten",
tryNowLabel: "Jetzt ausprobieren →",
step1Title: "Text eingeben oder Dateien auswählen",
step1Description:
"Geben Sie Ihre Nachricht ein oder ziehen Sie Dateien/Ordner in den Auswahlbereich",
step2_title: "Raum beitreten",
step2_description:
step2Title: "Raum beitreten",
step2Description:
"Klicken Sie auf die Schaltfläche 'Raum beitreten', um eine Freigabesitzung zu erstellen",
step3_title: "Empfangen",
step3_description:
step3Title: "Empfangen",
step3Description:
"Geben Sie die Raum-ID auf der Empfangsseite ein und klicken Sie auf 'Raum beitreten', um die freigegebenen Inhalte zu erhalten",
},
SystemDiagram: {
h2: "Systemdiagramm",
h2_P: "PrivyDrop: Ihre Daten, Ihre Kontrolle. Einfach, schnell und privat.",
h2Description: "PrivyDrop: Ihre Daten, Ihre Kontrolle. Einfach, schnell und privat.",
},
KeyFeatures: {
h2: "Hauptmerkmale",
@@ -186,7 +186,7 @@ export const de: Messages = {
"Legen Sie ein Speicherverzeichnis fest, um fortsetzbare Übertragungen automatisch zu aktivieren. Machen Sie sich keine Sorgen mehr über Netzwerkunterbrechungen; Ihr Dateiaustausch wird genau dort fortgesetzt, wo er unterbrochen wurde.",
},
faqs: {
FAQ_dis: "Häufig gestellte Fragen",
faqLabel: "Häufig gestellte Fragen",
question_0:
"Werden die Daten wirklich lokal gespeichert und nicht auf andere Server übertragen?",
answer_0:
@@ -234,111 +234,111 @@ export const de: Messages = {
"Die anfängliche Gültigkeit einer Raum-ID beträgt 24 Stunden. Wenn ein Empfänger dem Raum beitritt, wird die Gültigkeit automatisch um 24 Stunden ab diesem Zeitpunkt verlängert.",
},
clipboard_btn: {
Pasted_dis: "Eingefügt",
Copied_dis: "Kopiert",
pastedLabel: "Eingefügt",
copiedLabel: "Kopiert",
},
fileUploadHandler: {
NoFileChosen_tips: "Keine Datei ausgewählt",
fileChosen_tips_template:
noFileChosenTip: "Keine Datei ausgewählt",
fileChosenTemplate:
"{fileNum} Datei(en) und {folderNum} Ordner ausgewählt",
chooseFileTips:
chooseFileTip:
"Ziehen Sie Dateien/Ordner an eine beliebige Stelle auf dieser Seite, oder klicken Sie hier, um auszuwählen.",
dragTips: "Ziehen Sie hierhin auf die Seite.",
dragTip: "Ziehen Sie hierhin auf die Seite.",
chosenDiagTitle: "Upload-Typ auswählen",
chosenDiagDescription:
"Wählen Sie aus, ob Sie Dateien oder einen Ordner hochladen möchten",
SelectFile_dis: "Dateien auswählen",
SelectFolder_dis: "Ordner auswählen",
selectFileLabel: "Dateien auswählen",
selectFolderLabel: "Ordner auswählen",
},
FileTransferButton: {
SavedToDisk_tips: "Datei bereits auf Festplatte gespeichert",
CurrentFileTransferring_tips: "Datei wird übertragen",
OtherFileTransferring_tips:
savedToDiskTip: "Datei bereits auf Festplatte gespeichert",
currentFileTransferringTip: "Datei wird übertragen",
otherFileTransferringTip:
"Bitte warten Sie, bis die aktuelle Übertragung abgeschlossen ist",
download_tips: "Klicken Sie, um die Datei herunterzuladen",
PendingSave_tips: "Klicken Sie, um die Datei lokal zu speichern", // 新增
Saved_dis: "Gespeichert",
Waiting_dis: "Warten",
Download_dis: "Herunterladen",
Save_dis: "Speichern", // 新增
downloadTip: "Klicken Sie, um die Datei herunterzuladen",
pendingSaveTip: "Klicken Sie, um die Datei lokal zu speichern", // 新增
savedLabel: "Gespeichert",
waitingLabel: "Warten",
downloadLabel: "Herunterladen",
saveLabel: "Speichern", // 新增
},
FileListDisplay: {
sending_dis: "Senden",
receiving_dis: "Empfangen",
finish_dis: "abgeschlossen",
delete_dis: "Löschen",
downloadNum_dis: "Anzahl der Downloads",
folder_tips_template:
sendingLabel: "Senden",
receivingLabel: "Empfangen",
finishedLabel: "abgeschlossen",
deleteLabel: "Löschen",
downloadCountLabel: "Anzahl der Downloads",
folderSummaryTemplate:
"Ordnername: {name} ({num} Dateien und {size}) insgesamt",
folder_dis_template: " ({num} Dateien, {size})",
PopupDialog_title: "Empfohlen: Speicherverzeichnis auswählen",
PopupDialog_description:
folderInlineTemplate: " ({num} Dateien, {size})",
popupDialogTitle: "Empfohlen: Speicherverzeichnis auswählen",
popupDialogDescription:
"Wir empfehlen, ein Speicherverzeichnis auszuwählen, um Dateien direkt auf Ihre Festplatte zu speichern. Dies erleichtert die Übertragung großer Dateien und die effiziente Synchronisierung von Ordnern.",
chooseSavePath_tips:
chooseSavePathTip:
"Speichern Sie große Dateien oder Ordner direkt in einem ausgewählten Verzeichnis. 👉",
chooseSavePath_dis: "Speicherort auswählen",
chooseSavePathLabel: "Speicherort auswählen",
},
RetrieveMethod: {
P: "Glückwunsch 🎉 Freigegebene Inhalte warten darauf, abgerufen zu werden:",
RoomId_tips: "Raum-ID abrufen: ",
copyRoomId_tips: "Raum-ID kopieren",
url_tips: "Abrufen über URL: ",
copyUrl_tips: "Freigabe-URL kopieren",
scanQR_tips: "Scannen Sie den QR-Code, um zu empfangen 👇",
Copied_dis: "Kopiert",
Copy_QR_dis: "QR-Code kopieren",
download_QR_dis: "QR-Code herunterladen",
introMessage: "Glückwunsch 🎉 Freigegebene Inhalte warten darauf, abgerufen zu werden:",
roomIdTip: "Raum-ID abrufen: ",
copyRoomIdTip: "Raum-ID kopieren",
urlTip: "Abrufen über URL: ",
copyUrlTip: "Freigabe-URL kopieren",
scanQrTip: "Scannen Sie den QR-Code, um zu empfangen 👇",
copiedLabel: "Kopiert",
copyQrLabel: "QR-Code kopieren",
downloadQrLabel: "QR-Code herunterladen",
},
ClipboardApp: {
fetchRoom_err:
fetchRoomError:
"Fehler beim Abrufen eines Raums. Bitte versuchen Sie es erneut.",
roomCheck: {
//handleShareRoomCheck
empty_msg: "Raum-ID darf nicht leer sein",
available_msg: "Raum ist verfügbar",
notAvailable_msg:
emptyMessage: "Raum-ID darf nicht leer sein",
availableMessage: "Raum ist verfügbar",
notAvailableMessage:
"Raum ist nicht verfügbar, bitte versuchen Sie einen anderen",
},
channelOpen_msg:
channelOpenMessage:
"'Datenkanal ist geöffnet, bereit zum Empfangen von Daten...'",
waitting_tips:
waitingTip:
"Warten auf den Empfänger, der sich verbindet. Bitte lassen Sie diese Seite geöffnet, bis die Übertragung abgeschlossen ist. Auf dem Desktop können Sie den Browser minimieren oder zwischen Tabs wechseln. Auf mobilen Geräten sollte der Browser im Vordergrund bleiben.",
joinRoom: {
EmptyMsg: "Warnung, die Raum-ID ist leer",
DuplicateMsg: "Diese Raum-ID ist bereits vergeben. Bitte wählen Sie eine andere ID.",
successMsg:
emptyMessage: "Warnung, die Raum-ID ist leer",
duplicateMessage: "Diese Raum-ID ist bereits vergeben. Bitte wählen Sie eine andere ID.",
successMessage:
"Raum erfolgreich betreten! Schließen Sie diese Seite nicht, bis die Übertragung abgeschlossen ist. (Am Desktop können Sie den Browser minimieren oder Tabs wechseln; auf mobilen Geräten bringen Sie den Browser nicht in den Hintergrund.)",
notExist:
notFoundMessage:
"Der Raum, dem Sie beitreten möchten, existiert nicht. Nur der Sender kann einen Raum erstellen.",
failMsg: "Fehler beim Beitreten zum Raum:",
failureMessage: "Fehler beim Beitreten zum Raum:",
},
// Connection feedback (weak/VPN network scenarios)
join_inProgress:
joinInProgress:
"Beitritt zum Raum… (in langsamen Netzen 530 Sekunden)",
join_slow:
joinSlow:
"Wirkt etwas langsam Netzwerk/VPN prüfen oder später erneut versuchen",
join_timeout:
joinTimeout:
"Beitritt zeitüberschritten (mögliche Netzbeschränkung). Bitte erneut versuchen",
rtc_slow:
rtcSlow:
"Netzwerk möglicherweise eingeschränkt — VPN deaktivieren oder später erneut versuchen",
rtc_negotiating: "Im Raum direkte P2PVerbindung wird aufgebaut…",
rtc_connected: "Verbunden",
rtc_reconnecting: "Wiederverbinden…",
rtc_restored: "Verbindung wiederhergestellt",
rtcNegotiating: "Im Raum direkte P2PVerbindung wird aufgebaut…",
rtcConnected: "Verbunden",
rtcReconnecting: "Wiederverbinden…",
rtcRestored: "Verbindung wiederhergestellt",
pickSaveMsg: "Direkt auf Festplatte speichern?",
pickSaveUnsupported: "Verzeichnisauswahl nicht unterstützt.",
pickSaveSuccess: "Speicherort festgelegt.",
pickSaveError: "Speicherort konnte nicht festgelegt werden.",
roomStatus: {
senderEmptyMsg: "Raum ist leer",
receiverEmptyMsg:
senderEmptyMessage: "Raum ist leer",
receiverEmptyMessage:
"Sie können eine Einladung annehmen, um dem Raum beizutreten",
onlyOneMsg: "Sie sind der Einzige hier",
peopleMsg_template: "{peerCount} Personen im Raum",
connected_dis: "Verbunden",
senderDisconnectedMsg: "Sender getrennt",
leftRoomMsg: "Sie haben den Raum verlassen.",
leaveRoomBtn: "Raum Verlassen",
onlyOneMessage: "Sie sind der Einzige hier",
peopleCountTemplate: "{peerCount} Personen im Raum",
connectedLabel: "Verbunden",
senderDisconnectedMessage: "Sender getrennt",
leftRoomMessage: "Sie haben den Raum verlassen.",
leaveRoomLabel: "Raum Verlassen",
},
fileExistMsg: "Einige Dateien wurden bereits hinzugefügt.",
noFilesForFolderMsg: "Keine Dateien im Ordner '{folderName}' gefunden.",
@@ -350,46 +350,46 @@ export const de: Messages = {
html: {
senderTab: "Senden",
retrieveTab: "Abrufen",
shareTitle_dis: "Inhalte teilen",
retrieveTitle_dis: "Inhalte abrufen",
RoomStatus_dis: "Status:",
Paste_dis: "Einfügen",
Copy_dis: "Kopieren",
inputRoomIdprompt: "Ihre Raum-ID (bearbeitbar):",
joinRoomBtn: "Raum beitreten",
generateSimpleId_tips: "Einfache ID",
generateRandomId_tips: "Zufällige ID",
shareTitleLabel: "Inhalte teilen",
retrieveTitleLabel: "Inhalte abrufen",
roomStatusLabel: "Status:",
pasteLabel: "Einfügen",
copyLabel: "Kopieren",
inputRoomIdPrompt: "Ihre Raum-ID (bearbeitbar):",
joinRoomButtonLabel: "Raum beitreten",
generateSimpleIdTip: "Einfache ID",
generateRandomIdTip: "Zufällige ID",
readClipboardToRoomId: "Raum-ID einfügen",
enterRoomID_placeholder: "Raum-ID eingeben",
enterRoomIdPlaceholder: "Raum-ID eingeben",
retrieveMethod: "Abrufmethode",
inputRoomId_tips: "Ihre Raum-ID (bearbeitbar):",
joinRoom_dis: "Raum beitreten",
SyncSending_loadingText: "Synchronisiert",
SyncSending_dis: "Synchronisieren",
readClipboard_dis: "Raum-ID einfügen",
retrieveRoomId_placeholder: "Raum-ID eingeben",
RetrieveMethodTitle: "Abrufmethode",
inputRoomIdTip: "Ihre Raum-ID (bearbeitbar):",
joinRoomLabel: "Raum beitreten",
syncSendingLoadingLabel: "Synchronisiert",
syncSendingLabel: "Synchronisieren",
readClipboardLabel: "Raum-ID einfügen",
retrieveRoomIdPlaceholder: "Raum-ID eingeben",
retrieveMethodTitle: "Abrufmethode",
// New: cached ID utils
saveId_dis: "ID speichern",
useCachedId_dis: "Gespeicherte ID verwenden",
saveId_tips: "Aktuelle ID für spätere schnelle Nutzung speichern",
useCachedId_tips: "Gespeicherte ID schnell nutzen; Doppelklick zum Speichermodus wechseln",
saveIdLabel: "ID speichern",
useCachedIdLabel: "Gespeicherte ID verwenden",
saveIdTip: "Aktuelle ID für spätere schnelle Nutzung speichern",
useCachedIdTip: "Gespeicherte ID schnell nutzen; Doppelklick zum Speichermodus wechseln",
},
// New: cache messages
saveId_success: "Erfolgreich im Cache gespeichert",
saveIdSuccessMessage: "Erfolgreich im Cache gespeichert",
},
home: {
h1: "Kostenloses sicheres Online-Clipboard & Dateiübertragungstool",
h1P: "P2P-Übertragungen werden dort fortgesetzt, wo sie unterbrochen wurden. Erleben Sie einen wirklich zuverlässigen, privaten und unaufhaltsamen Datei- und Textaustausch keine Registrierung, keine Beschränkungen bei Dateigröße oder Geschwindigkeit, völlig kostenlos.",
h2_screenOnly:
h2ScreenOnly:
"Jetzt sicheres Clipboard & Dateiübertragungstool ausprobieren",
h2_demo: "Sichere Dateifreigabe in Aktion sehen",
h2P_demo:
h2Demo: "Sichere Dateifreigabe in Aktion sehen",
h2DemoDescription:
"Sehen Sie, wie unsere lokale, Ende-zu-Ende-verschlüsselte Dateifreigabe Ihre Privatsphäre schützt",
watch_tips: "Sie können das Video auch auf diesen Plattformen ansehen:",
youtube_tips: "PrivyDrop auf YouTube ansehen",
bilibili_tips: "PrivyDrop auf Bilibili ansehen",
watchTip: "Sie können das Video auch auf diesen Plattformen ansehen:",
youtubeTip: "PrivyDrop auf YouTube ansehen",
bilibiliTip: "PrivyDrop auf Bilibili ansehen",
},
},
};
+126 -126
View File
@@ -56,37 +56,37 @@ export const en: Messages = {
},
text: {
Header: {
Home_dis: "Home",
Blog_dis: "blog",
About_dis: "About",
Help_dis: "Help",
FAQ_dis: "FAQ",
Features_dis: "Features",
Terms_dis: "Terms",
Privacy_dis: "Privacy",
homeLabel: "Home",
blogLabel: "blog",
aboutLabel: "About",
helpLabel: "Help",
faqLabel: "FAQ",
featuresLabel: "Features",
termsLabel: "Terms",
privacyLabel: "Privacy",
},
Footer: {
CopyrightNotice: "PrivyDrop. All rights reserved.",
Terms_dis: "Terms of Use",
Privacy_dis: "Privacy Policy",
SupportedLanguages: "Supported Languages",
copyrightNotice: "PrivyDrop. All rights reserved.",
termsLabel: "Terms of Use",
privacyLabel: "Privacy Policy",
supportedLanguagesLabel: "Supported Languages",
},
blog: {
list_title: "Blog",
list_subtitle: "Latest articles and updates",
recent_posts: "Recent Posts",
listTitle: "Blog",
listSubtitle: "Latest articles and updates",
recentPosts: "Recent Posts",
tags: "Tags",
read_more: "Read more",
readMore: "Read more",
by: "by",
post_not_found: "Post not found",
toc_title: "Table of contents",
tag_title_prefix: "Tag",
tag_subtitle_template: "Articles tagged with {tag}",
tag_empty: "No articles found for this tag.",
postNotFound: "Post not found",
tocTitle: "Table of contents",
tagTitlePrefix: "Tag",
tagSubtitleTemplate: "Articles tagged with {tag}",
tagEmpty: "No articles found for this tag.",
},
privacy: {
PrivacyPolicy_dis: "Privacy Policy",
privacyPolicyLabel: "Privacy Policy",
h1: "PrivyDrop Privacy Policy",
h1_P: "At PrivyDrop, we are committed to protecting your privacy and safeguarding your personal information. This privacy policy outlines how we collect, use, and protect the data you provide while using our service.",
h2_1: "Information Collection",
@@ -106,7 +106,7 @@ export const en: Messages = {
"If you have any questions or concerns about our privacy practices, please feel free to contact us at",
},
terms: {
TermsOfUse_dis: "Terms of Use",
termsOfUseLabel: "Terms of Use",
h1: "PrivyDrop Terms of Use",
h1_P: "By using the PrivyDrop service, you agree to be bound by these terms of use. If you do not agree to these terms, please do not use the service.",
h2_1: "Use of the Service",
@@ -126,7 +126,7 @@ export const en: Messages = {
"We reserve the right to update these terms of use at any time. Any changes will be effective immediately upon posting the updated terms on our website. It is your responsibility to review the terms of use periodically for any changes.",
},
help: {
Help_dis: "Help",
helpLabel: "Help",
h1: "PrivyDrop Help and Support",
h1_P: "We're here to help you make the most out of PrivyDrop. If you have any questions or need assistance, please don't hesitate to reach out to us.",
h2_1: "Contact Us",
@@ -148,21 +148,21 @@ export const en: Messages = {
},
HowItWorks: {
h2: "How it works",
h2_P: "Share files and messages instantly in three simple steps",
btn_try: "Try it now →",
step1_title: "Type or Choose Files",
step1_description:
h2Description: "Share files and messages instantly in three simple steps",
tryNowLabel: "Try it now →",
step1Title: "Type or Choose Files",
step1Description:
"Type your message or drag & drop files/folders into the selection area",
step2_title: "Join Room",
step2_description:
step2Title: "Join Room",
step2Description:
"Click the 'Join Room' button to create a sharing session",
step3_title: "Receive",
step3_description:
step3Title: "Receive",
step3Description:
"Enter the Room ID on the receive page and click 'Join Room' to get the shared content",
},
SystemDiagram: {
h2: "System diagram",
h2_P: "PrivyDrop: Your data, your control. Simple, fast, and private.",
h2Description: "PrivyDrop: Your data, your control. Simple, fast, and private.",
},
KeyFeatures: {
h2: "Key Features",
@@ -186,7 +186,7 @@ export const en: Messages = {
"Set a save directory to automatically enable resumable transfers. No more worrying about network interruptions; your file sharing will pick up right where it left off.",
},
faqs: {
FAQ_dis: "Frequently Asked Questions",
faqLabel: "Frequently Asked Questions",
question_0:
"Is the data truly stored locally and not transferred to other servers?",
answer_0:
@@ -231,106 +231,106 @@ export const en: Messages = {
"The initial validity of a RoomId is 24 hours. If a recipient joins the room, the validity is automatically extended by 24 hours from that moment.",
},
clipboard_btn: {
Pasted_dis: "Pasted",
Copied_dis: "Copied",
pastedLabel: "Pasted",
copiedLabel: "Copied",
},
fileUploadHandler: {
NoFileChosen_tips: "No file chosen",
fileChosen_tips_template:
noFileChosenTip: "No file chosen",
fileChosenTemplate:
"{fileNum} file(s) and {folderNum} folder(s) selected",
chooseFileTips:
chooseFileTip:
"Drag and drop files/folders anywhere on this page, or click here to choose.",
dragTips: "Drag to anywhere on this page.",
dragTip: "Drag to anywhere on this page.",
chosenDiagTitle: "Choose Upload Type",
chosenDiagDescription:
"Select whether you want to upload files or a folder",
SelectFile_dis: "Select Files",
SelectFolder_dis: "Select Folder",
selectFileLabel: "Select Files",
selectFolderLabel: "Select Folder",
},
FileTransferButton: {
SavedToDisk_tips: "File already saved to disk",
CurrentFileTransferring_tips: "File is being transferred",
OtherFileTransferring_tips:
savedToDiskTip: "File already saved to disk",
currentFileTransferringTip: "File is being transferred",
otherFileTransferringTip:
"Please wait for current transfer to complete",
download_tips: "Click to download file",
PendingSave_tips: "Click to save file locally",
Saved_dis: "Saved",
Waiting_dis: "Waiting",
Download_dis: "Download",
Save_dis: "Save",
downloadTip: "Click to download file",
pendingSaveTip: "Click to save file locally",
savedLabel: "Saved",
waitingLabel: "Waiting",
downloadLabel: "Download",
saveLabel: "Save",
},
FileListDisplay: {
sending_dis: "Sending",
receiving_dis: "Receiving",
finish_dis: "finished",
delete_dis: "Delete",
downloadNum_dis: "Download count",
folder_tips_template:
sendingLabel: "Sending",
receivingLabel: "Receiving",
finishedLabel: "finished",
deleteLabel: "Delete",
downloadCountLabel: "Download count",
folderSummaryTemplate:
"folder name:{name} ({num} files and {size}) in total",
folder_dis_template: " ({num} files, {size})",
PopupDialog_title: "Recommended: Choose a Save Directory",
PopupDialog_description:
folderInlineTemplate: " ({num} files, {size})",
popupDialogTitle: "Recommended: Choose a Save Directory",
popupDialogDescription:
"We recommend selecting a save directory to directly save files to your disk. This makes it easier to transfer large files and synchronize folders efficiently.",
chooseSavePath_tips:
chooseSavePathTip:
"Save large files or folders directly to a selected directory. 👉",
chooseSavePath_dis: "Choose save location",
chooseSavePathLabel: "Choose save location",
},
RetrieveMethod: {
P: "Congrats 🎉 Share content is waiting to be retrieved:",
RoomId_tips: "Retrieve RoomID: ",
copyRoomId_tips: "Copy RoomID",
url_tips: "Retrieve using URL: ",
copyUrl_tips: "Copy share url",
scanQR_tips: "Scan the QR code to receive 👇",
Copied_dis: "Copied",
Copy_QR_dis: "Copy QR code",
download_QR_dis: "Download QR code",
introMessage: "Congrats 🎉 Share content is waiting to be retrieved:",
roomIdTip: "Retrieve RoomID: ",
copyRoomIdTip: "Copy RoomID",
urlTip: "Retrieve using URL: ",
copyUrlTip: "Copy share url",
scanQrTip: "Scan the QR code to receive 👇",
copiedLabel: "Copied",
copyQrLabel: "Copy QR code",
downloadQrLabel: "Download QR code",
},
ClipboardApp: {
fetchRoom_err: "Failed to get a room. Please try again.",
fetchRoomError: "Failed to get a room. Please try again.",
roomCheck: {
//handleShareRoomCheck
empty_msg: "RoomID should not be empty",
available_msg: "Room is available",
notAvailable_msg: "Room is not available, please try another",
emptyMessage: "RoomID should not be empty",
availableMessage: "Room is available",
notAvailableMessage: "Room is not available, please try another",
},
channelOpen_msg: "'data channel is opened,ready to receive data...'",
waitting_tips:
channelOpenMessage: "'data channel is opened,ready to receive data...'",
waitingTip:
"Waiting for receiver to connect. Please keep this page open until the transfer is complete. On desktop, you can minimize the browser or switch tabs. On mobile, please keep the browser in the foreground.",
joinRoom: {
EmptyMsg: "Warning, the roomID is empty",
DuplicateMsg: "This room ID is already in use. Please choose another ID.",
successMsg:
emptyMessage: "Warning, the roomID is empty",
duplicateMessage: "This room ID is already in use. Please choose another ID.",
successMessage:
"Successfully joined the room! Do not close this page until the transfer is complete. (On desktop, you can minimize the browser or switch tabs; on mobile, do not move the browser to the background.)",
notExist:
notFoundMessage:
"The room you are trying to join does not exist. Only the sender can create a room.",
failMsg: "Failed to join room:",
failureMessage: "Failed to join room:",
},
// Connection feedback (weak/VPN network scenarios)
join_inProgress:
joinInProgress:
"Joining the room… this may take 530 seconds on slow networks",
join_slow: "Feels slow—check your network/VPN or try again shortly",
join_timeout:
joinSlow: "Feels slow—check your network/VPN or try again shortly",
joinTimeout:
"Join timed out (network may be restricted). Please try again",
rtc_slow:
rtcSlow:
"Network may be restricted — try turning off VPN or try again shortly",
rtc_negotiating: "In the room—establishing a direct P2P connection…",
rtc_connected: "Connected",
rtc_reconnecting: "Reconnecting…",
rtc_restored: "Connection restored",
rtcNegotiating: "In the room—establishing a direct P2P connection…",
rtcConnected: "Connected",
rtcReconnecting: "Reconnecting…",
rtcRestored: "Connection restored",
pickSaveMsg: "Save Directly to Disk ?",
pickSaveUnsupported: "Directory picker not supported.",
pickSaveSuccess: "Save location set.",
pickSaveError: "Could not set save location.",
roomStatus: {
senderEmptyMsg: "Room is empty",
receiverEmptyMsg: "You can accept an invitation to join the room",
onlyOneMsg: "You're the only one here",
peopleMsg_template: "{peerCount} People in the room",
connected_dis: "Connected",
senderDisconnectedMsg: "Sender disconnected",
leftRoomMsg: "You have left the room.",
leaveRoomBtn: "Leave Room",
senderEmptyMessage: "Room is empty",
receiverEmptyMessage: "You can accept an invitation to join the room",
onlyOneMessage: "You're the only one here",
peopleCountTemplate: "{peerCount} People in the room",
connectedLabel: "Connected",
senderDisconnectedMessage: "Sender disconnected",
leftRoomMessage: "You have left the room.",
leaveRoomLabel: "Leave Room",
},
fileExistMsg: "Some files were already added.",
noFilesForFolderMsg: "No files found for folder '{folderName}'.",
@@ -341,45 +341,45 @@ export const en: Messages = {
html: {
senderTab: "Send",
retrieveTab: "Retrieve",
shareTitle_dis: "Share Content",
retrieveTitle_dis: "Retrieve Content",
RoomStatus_dis: "Status:",
Paste_dis: "Paste",
Copy_dis: "Copy",
inputRoomIdprompt: "Your RoomID (Editable):",
joinRoomBtn: "Join room",
generateSimpleId_tips: "Simple ID",
generateRandomId_tips: "Random ID",
shareTitleLabel: "Share Content",
retrieveTitleLabel: "Retrieve Content",
roomStatusLabel: "Status:",
pasteLabel: "Paste",
copyLabel: "Copy",
inputRoomIdPrompt: "Your RoomID (Editable):",
joinRoomButtonLabel: "Join room",
generateSimpleIdTip: "Simple ID",
generateRandomIdTip: "Random ID",
readClipboardToRoomId: "Paste RoomID",
enterRoomID_placeholder: "enter RoomID",
enterRoomIdPlaceholder: "enter RoomID",
retrieveMethod: "Retrieve method",
inputRoomId_tips: "Your RoomID (Editable):",
joinRoom_dis: "Join room",
SyncSending_loadingText: "Synced",
SyncSending_dis: "Sync",
readClipboard_dis: "Paste RoomID",
retrieveRoomId_placeholder: "Enter RoomID",
RetrieveMethodTitle: "Retrieve method",
inputRoomIdTip: "Your RoomID (Editable):",
joinRoomLabel: "Join room",
syncSendingLoadingLabel: "Synced",
syncSendingLabel: "Sync",
readClipboardLabel: "Paste RoomID",
retrieveRoomIdPlaceholder: "Enter RoomID",
retrieveMethodTitle: "Retrieve method",
// New: cached ID utils
saveId_dis: "Save ID",
useCachedId_dis: "Use cached ID",
saveId_tips: "Save current ID for quick reuse later",
useCachedId_tips: "Quick use saved ID; double-click to switch save mode",
saveIdLabel: "Save ID",
useCachedIdLabel: "Use cached ID",
saveIdTip: "Save current ID for quick reuse later",
useCachedIdTip: "Quick use saved ID; double-click to switch save mode",
},
// New: cache messages
saveId_success: "Saved to cache",
saveIdSuccessMessage: "Saved to cache",
},
home: {
h1: "Free Secure Online Clipboard & File Transfer Tool",
h1P: "P2P transfers that pick up where you left off. Experience truly reliable, private, and unstoppable file and text sharing—no registration, no file size or speed limits, completely free.",
h2_screenOnly: "Try Secure Clipboard & File Transfer Tool Now",
h2ScreenOnly: "Try Secure Clipboard & File Transfer Tool Now",
h2_demo: "See Secure File Sharing in Action",
h2P_demo:
h2Demo: "See Secure File Sharing in Action",
h2DemoDescription:
"Watch how our local-first, end-to-end encrypted file sharing protects your privacy",
watch_tips: "You can also watch the video on these platforms:",
youtube_tips: "Watch PrivyDrop on YouTube",
bilibili_tips: "Watch PrivyDrop on Bilibili",
watchTip: "You can also watch the video on these platforms:",
youtubeTip: "Watch PrivyDrop on YouTube",
bilibiliTip: "Watch PrivyDrop on Bilibili",
},
},
};
+126 -126
View File
@@ -56,36 +56,36 @@ export const es: Messages = {
},
text: {
Header: {
Home_dis: "Inicio",
Blog_dis: "Blog",
About_dis: "Acerca de",
Help_dis: "Ayuda",
FAQ_dis: "FAQ",
Terms_dis: "Términos",
Privacy_dis: "Privacidad",
Features_dis: "Características",
homeLabel: "Inicio",
blogLabel: "Blog",
aboutLabel: "Acerca de",
helpLabel: "Ayuda",
faqLabel: "FAQ",
termsLabel: "Términos",
privacyLabel: "Privacidad",
featuresLabel: "Características",
},
Footer: {
CopyrightNotice: "PrivyDrop. Todos los derechos reservados.",
Terms_dis: "Términos de Uso",
Privacy_dis: "Política de Privacidad",
SupportedLanguages: "Idiomas soportados",
copyrightNotice: "PrivyDrop. Todos los derechos reservados.",
termsLabel: "Términos de Uso",
privacyLabel: "Política de Privacidad",
supportedLanguagesLabel: "Idiomas soportados",
},
blog: {
list_title: "Blog",
list_subtitle: "Últimos artículos y actualizaciones",
recent_posts: "Entradas recientes",
listTitle: "Blog",
listSubtitle: "Últimos artículos y actualizaciones",
recentPosts: "Entradas recientes",
tags: "Etiquetas",
read_more: "Leer más",
readMore: "Leer más",
by: "por",
post_not_found: "Artículo no encontrado",
toc_title: "Tabla de contenidos",
tag_title_prefix: "Etiqueta",
tag_subtitle_template: "Artículos etiquetados con {tag}",
tag_empty: "No se encontraron artículos para esta etiqueta.",
postNotFound: "Artículo no encontrado",
tocTitle: "Tabla de contenidos",
tagTitlePrefix: "Etiqueta",
tagSubtitleTemplate: "Artículos etiquetados con {tag}",
tagEmpty: "No se encontraron artículos para esta etiqueta.",
},
privacy: {
PrivacyPolicy_dis: "Política de Privacidad",
privacyPolicyLabel: "Política de Privacidad",
h1: "Política de Privacidad de PrivyDrop",
h1_P: "En PrivyDrop, estamos comprometidos con proteger su privacidad y salvaguardar su información personal. Esta política de privacidad describe cómo recopilamos, usamos y protegemos los datos que proporciona al usar nuestro servicio.",
h2_1: "Recopilación de Información",
@@ -105,7 +105,7 @@ export const es: Messages = {
"Si tiene alguna pregunta o inquietud sobre nuestras prácticas de privacidad, no dude en contactarnos en",
},
terms: {
TermsOfUse_dis: "Términos de Uso",
termsOfUseLabel: "Términos de Uso",
h1: "Términos de Uso de PrivyDrop",
h1_P: "Al usar el servicio PrivyDrop, acepta estar sujeto a estos términos de uso. Si no está de acuerdo con estos términos, por favor no use el servicio.",
h2_1: "Uso del Servicio",
@@ -125,7 +125,7 @@ export const es: Messages = {
"Nos reservamos el derecho de actualizar estos términos de uso en cualquier momento. Cualquier cambio será efectivo inmediatamente al publicar los términos actualizados en nuestro sitio web. Es su responsabilidad revisar los términos de uso periódicamente para cualquier cambio.",
},
help: {
Help_dis: "Ayuda",
helpLabel: "Ayuda",
h1: "Ayuda y Soporte de PrivyDrop",
h1_P: "Estamos aquí para ayudarte a aprovechar al máximo PrivyDrop. Si tienes alguna pregunta o necesitas asistencia, no dudes en contactarnos.",
h2_1: "Contáctanos",
@@ -147,21 +147,21 @@ export const es: Messages = {
},
HowItWorks: {
h2: "Cómo funciona",
h2_P: "Comparte archivos y mensajes instantáneamente en tres simples pasos",
btn_try: "Pruébalo ahora →",
step1_title: "Escribe o Elige Archivos",
step1_description:
h2Description: "Comparte archivos y mensajes instantáneamente en tres simples pasos",
tryNowLabel: "Pruébalo ahora →",
step1Title: "Escribe o Elige Archivos",
step1Description:
"Escribe tu mensaje o arrastra y suelta archivos/carpetas en el área de selección",
step2_title: "Únete a la Sala",
step2_description:
step2Title: "Únete a la Sala",
step2Description:
"Haz clic en el botón 'Unirse a Sala' para crear una sesión de compartición",
step3_title: "Recibe",
step3_description:
step3Title: "Recibe",
step3Description:
"Ingresa el ID de Sala en la página de recepción y haz clic en 'Unirse a Sala' para obtener el contenido compartido",
},
SystemDiagram: {
h2: "Diagrama del sistema",
h2_P: "PrivyDrop: Tus datos, tu control. Simple, rápido y privado.",
h2Description: "PrivyDrop: Tus datos, tu control. Simple, rápido y privado.",
},
KeyFeatures: {
h2: "Características Principales",
@@ -185,7 +185,7 @@ export const es: Messages = {
"Establece un directorio de guardado para habilitar automáticamente las transferencias reanudables. No más preocupaciones por interrupciones de red; tu intercambio de archivos continuará justo donde lo dejaste.",
},
faqs: {
FAQ_dis: "Preguntas Frecuentes",
faqLabel: "Preguntas Frecuentes",
question_0:
"¿Los datos realmente se almacenan localmente y no se transfieren a otros servidores?",
answer_0:
@@ -232,106 +232,106 @@ export const es: Messages = {
"La validez inicial de un ID de Sala es de 24 horas. Si un destinatario se une a la sala, la validez se extiende automáticamente por 24 horas desde ese momento.",
},
clipboard_btn: {
Pasted_dis: "Pegado",
Copied_dis: "Copiado",
pastedLabel: "Pegado",
copiedLabel: "Copiado",
},
fileUploadHandler: {
NoFileChosen_tips: "Ningún archivo seleccionado",
fileChosen_tips_template:
noFileChosenTip: "Ningún archivo seleccionado",
fileChosenTemplate:
"{fileNum} archivo(s) y {folderNum} carpeta(s) seleccionados",
chooseFileTips:
chooseFileTip:
"Arrastra y suelta archivos/carpetas en cualquier lugar de esta página, o haz clic aquí para seleccionar.",
dragTips: "Arrastra a cualquier parte de esta página.",
dragTip: "Arrastra a cualquier parte de esta página.",
chosenDiagTitle: "Elegir Tipo de Carga",
chosenDiagDescription:
"Selecciona si deseas cargar archivos o una carpeta",
SelectFile_dis: "Seleccionar Archivos",
SelectFolder_dis: "Seleccionar Carpeta",
selectFileLabel: "Seleccionar Archivos",
selectFolderLabel: "Seleccionar Carpeta",
},
FileTransferButton: {
SavedToDisk_tips: "Archivo ya guardado en disco",
CurrentFileTransferring_tips: "El archivo se está transfiriendo",
OtherFileTransferring_tips:
savedToDiskTip: "Archivo ya guardado en disco",
currentFileTransferringTip: "El archivo se está transfiriendo",
otherFileTransferringTip:
"Por favor espera a que se complete la transferencia actual",
download_tips: "Haz clic para descargar el archivo",
PendingSave_tips: "Haz clic para guardar el archivo localmente", // 新增
Saved_dis: "Guardado",
Waiting_dis: "Esperando",
Download_dis: "Descargar",
Save_dis: "Guardar", // 新增
downloadTip: "Haz clic para descargar el archivo",
pendingSaveTip: "Haz clic para guardar el archivo localmente", // 新增
savedLabel: "Guardado",
waitingLabel: "Esperando",
downloadLabel: "Descargar",
saveLabel: "Guardar", // 新增
},
FileListDisplay: {
sending_dis: "Enviando",
receiving_dis: "Recibiendo",
finish_dis: "terminado",
delete_dis: "Eliminar",
downloadNum_dis: "Número de descargas",
folder_tips_template:
sendingLabel: "Enviando",
receivingLabel: "Recibiendo",
finishedLabel: "terminado",
deleteLabel: "Eliminar",
downloadCountLabel: "Número de descargas",
folderSummaryTemplate:
"nombre de carpeta:{name} ({num} archivos y {size}) en total",
folder_dis_template: " ({num} archivos, {size})",
PopupDialog_title: "Recomendado: Elige un Directorio de Guardado",
PopupDialog_description:
folderInlineTemplate: " ({num} archivos, {size})",
popupDialogTitle: "Recomendado: Elige un Directorio de Guardado",
popupDialogDescription:
"Recomendamos seleccionar un directorio de guardado para guardar archivos directamente en tu disco. Esto facilita la transferencia de archivos grandes y la sincronización de carpetas de manera eficiente.",
chooseSavePath_tips:
chooseSavePathTip:
"Guarda archivos grandes o carpetas directamente en un directorio seleccionado. 👉",
chooseSavePath_dis: "Elegir ubicación de guardado",
chooseSavePathLabel: "Elegir ubicación de guardado",
},
RetrieveMethod: {
P: "¡Felicitaciones 🎉 El contenido compartido está esperando ser recuperado:",
RoomId_tips: "ID de Sala para recuperar: ",
copyRoomId_tips: "Copiar ID de Sala",
url_tips: "Recuperar usando URL: ",
copyUrl_tips: "Copiar URL de compartición",
scanQR_tips: "Escanea el código QR para recibir 👇",
Copied_dis: "Copiado",
Copy_QR_dis: "Copiar código QR",
download_QR_dis: "Descargar código QR",
introMessage: "¡Felicitaciones 🎉 El contenido compartido está esperando ser recuperado:",
roomIdTip: "ID de Sala para recuperar: ",
copyRoomIdTip: "Copiar ID de Sala",
urlTip: "Recuperar usando URL: ",
copyUrlTip: "Copiar URL de compartición",
scanQrTip: "Escanea el código QR para recibir 👇",
copiedLabel: "Copiado",
copyQrLabel: "Copiar código QR",
downloadQrLabel: "Descargar código QR",
},
ClipboardApp: {
fetchRoom_err: "Error al obtener una sala. Por favor intenta de nuevo.",
fetchRoomError: "Error al obtener una sala. Por favor intenta de nuevo.",
roomCheck: {
empty_msg: "El ID de Sala no debe estar vacío",
available_msg: "La sala está disponible",
notAvailable_msg: "La sala no está disponible, por favor intenta otra",
emptyMessage: "El ID de Sala no debe estar vacío",
availableMessage: "La sala está disponible",
notAvailableMessage: "La sala no está disponible, por favor intenta otra",
},
channelOpen_msg: "'canal de datos abierto, listo para recibir datos...'",
waitting_tips:
channelOpenMessage: "'canal de datos abierto, listo para recibir datos...'",
waitingTip:
"Esperando que el receptor se conecte. Por favor mantén esta página abierta hasta que se complete la transferencia. En escritorio, puedes minimizar el navegador o cambiar pestañas. En móvil, por favor mantén el navegador en primer plano.",
joinRoom: {
EmptyMsg: "Advertencia, el ID de sala está vacío",
DuplicateMsg: "Este ID de sala ya está en uso. Por favor, elige otro ID.",
successMsg:
emptyMessage: "Advertencia, el ID de sala está vacío",
duplicateMessage: "Este ID de sala ya está en uso. Por favor, elige otro ID.",
successMessage:
"¡Ingreso exitoso al cuarto! No cierres esta página hasta que se complete la transferencia. (En escritorio, puedes minimizar el navegador o cambiar de pestaña; en móvil, no lleves el navegador al fondo.)",
notExist:
notFoundMessage:
"La sala a la que intentas unirte no existe. Solo el remitente puede crear una sala.",
failMsg: "Error al unirse a la sala:",
failureMessage: "Error al unirse a la sala:",
},
// Connection feedback (weak/VPN network scenarios)
join_inProgress:
joinInProgress:
"Uniéndose a la sala… (en redes lentas puede tardar 530 s)",
join_slow:
joinSlow:
"Va algo lento—revisa tu red/VPN o inténtalo de nuevo en breve",
join_timeout:
joinTimeout:
"La unión ha caducado (posibles restricciones de red). Vuelve a intentarlo",
rtc_slow:
rtcSlow:
"La red puede estar restringida — prueba desactivar la VPN o inténtalo de nuevo en breve",
rtc_negotiating: "Dentro de la sala—estableciendo conexión P2P directa…",
rtc_connected: "Conectado",
rtc_reconnecting: "Reconectando…",
rtc_restored: "Conexión restaurada",
rtcNegotiating: "Dentro de la sala—estableciendo conexión P2P directa…",
rtcConnected: "Conectado",
rtcReconnecting: "Reconectando…",
rtcRestored: "Conexión restaurada",
pickSaveMsg: "¿Guardar Directamente en Disco?",
pickSaveUnsupported: "Selector de directorio no compatible.",
pickSaveSuccess: "Ubicación de guardado establecida.",
pickSaveError: "No se pudo establecer la ubicación de guardado.",
roomStatus: {
senderEmptyMsg: "La sala está vacía",
receiverEmptyMsg: "Puedes aceptar una invitación para unirte a la sala",
onlyOneMsg: "Eres el único aquí",
peopleMsg_template: "{peerCount} Personas en la sala",
connected_dis: "Conectado",
senderDisconnectedMsg: "Remitente desconectado",
leftRoomMsg: "Has salido de la sala.",
leaveRoomBtn: "Salir de la Sala",
senderEmptyMessage: "La sala está vacía",
receiverEmptyMessage: "Puedes aceptar una invitación para unirte a la sala",
onlyOneMessage: "Eres el único aquí",
peopleCountTemplate: "{peerCount} Personas en la sala",
connectedLabel: "Conectado",
senderDisconnectedMessage: "Remitente desconectado",
leftRoomMessage: "Has salido de la sala.",
leaveRoomLabel: "Salir de la Sala",
},
fileExistMsg: "Algunos archivos ya han sido añadidos.",
noFilesForFolderMsg:
@@ -345,45 +345,45 @@ export const es: Messages = {
html: {
senderTab: "Enviar",
retrieveTab: "Recuperar",
shareTitle_dis: "Compartir Contenido",
retrieveTitle_dis: "Recuperar Contenido",
RoomStatus_dis: "Estado:",
Paste_dis: "Pegar",
Copy_dis: "Copiar",
inputRoomIdprompt: "Tu ID de Sala (Editable):",
joinRoomBtn: "Unirse a sala",
generateSimpleId_tips: "ID Simple",
generateRandomId_tips: "ID Aleatorio",
shareTitleLabel: "Compartir Contenido",
retrieveTitleLabel: "Recuperar Contenido",
roomStatusLabel: "Estado:",
pasteLabel: "Pegar",
copyLabel: "Copiar",
inputRoomIdPrompt: "Tu ID de Sala (Editable):",
joinRoomButtonLabel: "Unirse a sala",
generateSimpleIdTip: "ID Simple",
generateRandomIdTip: "ID Aleatorio",
readClipboardToRoomId: "Pegar ID de Sala",
enterRoomID_placeholder: "ingresa ID de Sala",
enterRoomIdPlaceholder: "ingresa ID de Sala",
retrieveMethod: "Método de recuperación",
inputRoomId_tips: "Tu ID de Sala (Editable):",
joinRoom_dis: "Unirse a sala",
SyncSending_loadingText: "Sincronizado",
SyncSending_dis: "Sincronizar",
readClipboard_dis: "Pegar ID de Sala",
retrieveRoomId_placeholder: "Ingresa ID de Sala",
RetrieveMethodTitle: "Método de recuperación",
inputRoomIdTip: "Tu ID de Sala (Editable):",
joinRoomLabel: "Unirse a sala",
syncSendingLoadingLabel: "Sincronizado",
syncSendingLabel: "Sincronizar",
readClipboardLabel: "Pegar ID de Sala",
retrieveRoomIdPlaceholder: "Ingresa ID de Sala",
retrieveMethodTitle: "Método de recuperación",
// New: cached ID utils
saveId_dis: "Guardar ID",
useCachedId_dis: "Usar ID en caché",
saveId_tips: "Guarda el ID actual para reutilizarlo rápidamente",
useCachedId_tips: "Usar ID guardado rápido; doble clic para cambiar modo guardar",
saveIdLabel: "Guardar ID",
useCachedIdLabel: "Usar ID en caché",
saveIdTip: "Guarda el ID actual para reutilizarlo rápidamente",
useCachedIdTip: "Usar ID guardado rápido; doble clic para cambiar modo guardar",
},
// New: cache messages
saveId_success: "Guardado en caché",
saveIdSuccessMessage: "Guardado en caché",
},
home: {
h1: "Herramienta Gratuita de Portapapeles y Transferencia de Archivos en Línea Segura",
h1P: "Las transferencias P2P se reanudan desde donde se interrumpieron. Experimente un intercambio de archivos y texto verdaderamente fiable, privado e imparable: sin registro, sin límites de tamaño o velocidad de archivo, y completamente gratis.",
h2_screenOnly:
h2ScreenOnly:
"Prueba la Herramienta Segura de Portapapeles y Transferencia de Archivos Ahora",
h2_demo: "Ve la Compartición Segura de Archivos en Acción",
h2P_demo:
h2Demo: "Ve la Compartición Segura de Archivos en Acción",
h2DemoDescription:
"Mira cómo nuestra compartición de archivos local y cifrada de extremo a extremo protege tu privacidad",
watch_tips: "También puedes ver el video en estas plataformas:",
youtube_tips: "Ver PrivyDrop en YouTube",
bilibili_tips: "Ver PrivyDrop en Bilibili",
watchTip: "También puedes ver el video en estas plataformas:",
youtubeTip: "Ver PrivyDrop en YouTube",
bilibiliTip: "Ver PrivyDrop en Bilibili",
},
},
};
+126 -126
View File
@@ -56,37 +56,37 @@ export const fr: Messages = {
},
text: {
Header: {
Home_dis: "Accueil",
Blog_dis: "Blog",
About_dis: "À propos",
Help_dis: "Aide",
FAQ_dis: "FAQ",
Terms_dis: "Conditions",
Privacy_dis: "Confidentialité",
Features_dis: "Fonctionnalités",
homeLabel: "Accueil",
blogLabel: "Blog",
aboutLabel: "À propos",
helpLabel: "Aide",
faqLabel: "FAQ",
termsLabel: "Conditions",
privacyLabel: "Confidentialité",
featuresLabel: "Fonctionnalités",
},
Footer: {
CopyrightNotice: "PrivyDrop. Tous droits réservés.",
Terms_dis: "Conditions d'utilisation",
Privacy_dis: "Politique de confidentialité",
SupportedLanguages: "Langues prises en charge",
copyrightNotice: "PrivyDrop. Tous droits réservés.",
termsLabel: "Conditions d'utilisation",
privacyLabel: "Politique de confidentialité",
supportedLanguagesLabel: "Langues prises en charge",
},
blog: {
list_title: "Blog",
list_subtitle: "Derniers articles et mises à jour",
recent_posts: "Articles récents",
listTitle: "Blog",
listSubtitle: "Derniers articles et mises à jour",
recentPosts: "Articles récents",
tags: "Étiquettes",
read_more: "En savoir plus",
readMore: "En savoir plus",
by: "par",
post_not_found: "Article introuvable",
toc_title: "Table des matières",
tag_title_prefix: "Étiquette",
tag_subtitle_template: "Articles marqués avec {tag}",
tag_empty: "Aucun article trouvé pour cette étiquette.",
postNotFound: "Article introuvable",
tocTitle: "Table des matières",
tagTitlePrefix: "Étiquette",
tagSubtitleTemplate: "Articles marqués avec {tag}",
tagEmpty: "Aucun article trouvé pour cette étiquette.",
},
privacy: {
PrivacyPolicy_dis: "Politique de confidentialité",
privacyPolicyLabel: "Politique de confidentialité",
h1: "Politique de confidentialité de PrivyDrop",
h1_P: "Chez PrivyDrop, nous nous engageons à protéger votre vie privée et à sécuriser vos informations personnelles. Cette politique de confidentialité décrit comment nous collectons, utilisons et protégeons les données que vous fournissez lors de l'utilisation de notre service.",
h2_1: "Collecte d'informations",
@@ -106,7 +106,7 @@ export const fr: Messages = {
"Si vous avez des questions ou des préoccupations concernant nos pratiques de confidentialité, n'hésitez pas à nous contacter à l'adresse suivante :",
},
terms: {
TermsOfUse_dis: "Conditions d'utilisation",
termsOfUseLabel: "Conditions d'utilisation",
h1: "Conditions d'utilisation de PrivyDrop",
h1_P: "En utilisant le service PrivyDrop, vous acceptez d'être lié par ces conditions d'utilisation. Si vous n'acceptez pas ces conditions, veuillez ne pas utiliser le service.",
h2_1: "Utilisation du service",
@@ -126,7 +126,7 @@ export const fr: Messages = {
"Nous nous réservons le droit de mettre à jour ces conditions d'utilisation à tout moment. Toute modification sera effective immédiatement après la publication des conditions mises à jour sur notre site web. Il est de votre responsabilité de consulter périodiquement les conditions d'utilisation pour toute modification.",
},
help: {
Help_dis: "Aide",
helpLabel: "Aide",
h1: "Aide et support de PrivyDrop",
h1_P: "Nous sommes là pour vous aider à tirer le meilleur parti de PrivyDrop. Si vous avez des questions ou besoin d'assistance, n'hésitez pas à nous contacter.",
h2_1: "Contactez-nous",
@@ -148,21 +148,21 @@ export const fr: Messages = {
},
HowItWorks: {
h2: "Comment ça marche",
h2_P: "Partagez des fichiers et des messages instantanément en trois étapes simples",
btn_try: "Essayez maintenant →",
step1_title: "Tapez ou choisissez des fichiers",
step1_description:
h2Description: "Partagez des fichiers et des messages instantanément en trois étapes simples",
tryNowLabel: "Essayez maintenant →",
step1Title: "Tapez ou choisissez des fichiers",
step1Description:
"Tapez votre message ou glissez-déposez des fichiers/dossiers dans la zone de sélection",
step2_title: "Rejoindre une salle",
step2_description:
step2Title: "Rejoindre une salle",
step2Description:
"Cliquez sur le bouton 'Rejoindre une salle' pour créer une session de partage",
step3_title: "Recevoir",
step3_description:
step3Title: "Recevoir",
step3Description:
"Entrez l'ID de la salle sur la page de réception et cliquez sur 'Rejoindre une salle' pour obtenir le contenu partagé",
},
SystemDiagram: {
h2: "Diagramme du système",
h2_P: "PrivyDrop : Vos données, votre contrôle. Simple, rapide et privé.",
h2Description: "PrivyDrop : Vos données, votre contrôle. Simple, rapide et privé.",
},
KeyFeatures: {
h2: "Fonctionnalités clés",
@@ -186,7 +186,7 @@ export const fr: Messages = {
"Définissez un répertoire de sauvegarde pour activer automatiquement la reprise des transferts. Ne vous souciez plus des interruptions réseau ; votre partage de fichiers reprendra là où il s'est arrêté.",
},
faqs: {
FAQ_dis: "Questions fréquemment posées",
faqLabel: "Questions fréquemment posées",
question_0:
"Les données sont-elles vraiment stockées localement et non transférées vers d'autres serveurs ?",
answer_0:
@@ -235,110 +235,110 @@ export const fr: Messages = {
"La validité initiale d'un ID de salle est de 24 heures. Si un destinataire rejoint la salle, la validité est automatiquement prolongée de 24 heures à partir de ce moment.",
},
clipboard_btn: {
Pasted_dis: "Collé",
Copied_dis: "Copié",
pastedLabel: "Collé",
copiedLabel: "Copié",
},
fileUploadHandler: {
NoFileChosen_tips: "Aucun fichier sélectionné",
fileChosen_tips_template:
noFileChosenTip: "Aucun fichier sélectionné",
fileChosenTemplate:
"{fileNum} fichier(s) et {folderNum} dossier(s) sélectionné(s)",
chooseFileTips:
chooseFileTip:
"Faites glisser des fichiers/dossiers n'importe où sur cette page, ou cliquez ici pour choisir.",
dragTips: "Faites glisser ici sur la page.",
dragTip: "Faites glisser ici sur la page.",
chosenDiagTitle: "Choisir le type de téléversement",
chosenDiagDescription:
"Sélectionnez si vous souhaitez téléverser des fichiers ou un dossier",
SelectFile_dis: "Sélectionner des fichiers",
SelectFolder_dis: "Sélectionner un dossier",
selectFileLabel: "Sélectionner des fichiers",
selectFolderLabel: "Sélectionner un dossier",
},
FileTransferButton: {
SavedToDisk_tips: "Fichier déjà enregistré sur le disque",
CurrentFileTransferring_tips: "Le fichier est en cours de transfert",
OtherFileTransferring_tips:
savedToDiskTip: "Fichier déjà enregistré sur le disque",
currentFileTransferringTip: "Le fichier est en cours de transfert",
otherFileTransferringTip:
"Veuillez attendre que le transfert actuel soit terminé",
download_tips: "Cliquez pour télécharger le fichier",
PendingSave_tips: "Cliquez pour enregistrer le fichier localement", // 新增
Saved_dis: "Enregistré",
Waiting_dis: "En attente",
Download_dis: "Télécharger",
Save_dis: "Enregistrer", // 新增
downloadTip: "Cliquez pour télécharger le fichier",
pendingSaveTip: "Cliquez pour enregistrer le fichier localement", // 新增
savedLabel: "Enregistré",
waitingLabel: "En attente",
downloadLabel: "Télécharger",
saveLabel: "Enregistrer", // 新增
},
FileListDisplay: {
sending_dis: "Envoi",
receiving_dis: "Réception",
finish_dis: "terminé",
delete_dis: "Supprimer",
downloadNum_dis: "Nombre de téléchargements",
folder_tips_template:
sendingLabel: "Envoi",
receivingLabel: "Réception",
finishedLabel: "terminé",
deleteLabel: "Supprimer",
downloadCountLabel: "Nombre de téléchargements",
folderSummaryTemplate:
"Nom du dossier : {name} ({num} fichiers et {size}) au total",
folder_dis_template: " ({num} fichiers, {size})",
PopupDialog_title: "Recommandé : Choisir un répertoire de sauvegarde",
PopupDialog_description:
folderInlineTemplate: " ({num} fichiers, {size})",
popupDialogTitle: "Recommandé : Choisir un répertoire de sauvegarde",
popupDialogDescription:
"Nous recommandons de sélectionner un répertoire de sauvegarde pour enregistrer directement les fichiers sur votre disque. Cela facilite le transfert de fichiers volumineux et la synchronisation efficace des dossiers.",
chooseSavePath_tips:
chooseSavePathTip:
"Enregistrez des fichiers volumineux ou des dossiers directement dans un répertoire sélectionné. 👉",
chooseSavePath_dis: "Choisir l'emplacement de sauvegarde",
chooseSavePathLabel: "Choisir l'emplacement de sauvegarde",
},
RetrieveMethod: {
P: "Félicitations 🎉 Le contenu partagé attend d'être récupéré :",
RoomId_tips: "Récupérer l'ID de salle : ",
copyRoomId_tips: "Copier l'ID de salle",
url_tips: "Récupérer via URL : ",
copyUrl_tips: "Copier l'URL de partage",
scanQR_tips: "Scannez le code QR pour recevoir 👇",
Copied_dis: "Copié",
Copy_QR_dis: "Copier le code QR",
download_QR_dis: "Télécharger le code QR",
introMessage: "Félicitations 🎉 Le contenu partagé attend d'être récupéré :",
roomIdTip: "Récupérer l'ID de salle : ",
copyRoomIdTip: "Copier l'ID de salle",
urlTip: "Récupérer via URL : ",
copyUrlTip: "Copier l'URL de partage",
scanQrTip: "Scannez le code QR pour recevoir 👇",
copiedLabel: "Copié",
copyQrLabel: "Copier le code QR",
downloadQrLabel: "Télécharger le code QR",
},
ClipboardApp: {
fetchRoom_err: "Échec de l'obtention d'une salle. Veuillez réessayer.",
fetchRoomError: "Échec de l'obtention d'une salle. Veuillez réessayer.",
roomCheck: {
//handleShareRoomCheck
empty_msg: "L'ID de salle ne doit pas être vide",
available_msg: "La salle est disponible",
notAvailable_msg:
emptyMessage: "L'ID de salle ne doit pas être vide",
availableMessage: "La salle est disponible",
notAvailableMessage:
"La salle n'est pas disponible, veuillez en essayer une autre",
},
channelOpen_msg:
channelOpenMessage:
"'Le canal de données est ouvert, prêt à recevoir des données...'",
waitting_tips:
waitingTip:
"En attente de la connexion du destinataire. Veuillez garder cette page ouverte jusqu'à la fin du transfert. Sur ordinateur, vous pouvez minimiser le navigateur ou changer d'onglet. Sur mobile, veuillez garder le navigateur au premier plan.",
joinRoom: {
EmptyMsg: "Avertissement, l'ID de salle est vide",
DuplicateMsg: "Cet ID de salle est déjà utilisé. Veuillez choisir un autre ID.",
successMsg:
emptyMessage: "Avertissement, l'ID de salle est vide",
duplicateMessage: "Cet ID de salle est déjà utilisé. Veuillez choisir un autre ID.",
successMessage:
"Rejoignez le salon avec succès ! Ne fermez pas cette page tant que le transfert n'est pas terminé. (Sur ordinateur, vous pouvez réduire le navigateur ou changer d'onglet ; sur mobile, ne mettez pas le navigateur en arrière-plan.)",
notExist:
notFoundMessage:
"La salle que vous essayez de rejoindre n'existe pas. Seul l'expéditeur peut créer une salle.",
failMsg: "Échec de la connexion à la salle :",
failureMessage: "Échec de la connexion à la salle :",
},
// Connection feedback (weak/VPN network scenarios)
join_inProgress:
joinInProgress:
"Rejoindre la salle… (sur un réseau lent, 530 s possibles)",
join_slow:
joinSlow:
"Cest un peu lent — vérifiez votre réseau/VPN ou réessayez bientôt",
join_timeout:
joinTimeout:
"Délai dépassé pour rejoindre (réseau possiblement restreint). Réessayez",
rtc_slow:
rtcSlow:
"Réseau possiblement restreint — essayez de désactiver le VPN ou réessayez bientôt",
rtc_negotiating: "Dans la salle — établissement dun lien P2P direct…",
rtc_connected: "Connecté",
rtc_reconnecting: "Reconnexion…",
rtc_restored: "Connexion rétablie",
rtcNegotiating: "Dans la salle — établissement dun lien P2P direct…",
rtcConnected: "Connecté",
rtcReconnecting: "Reconnexion…",
rtcRestored: "Connexion rétablie",
pickSaveMsg: "Enregistrer directement sur le disque ?",
pickSaveUnsupported: "Sélecteur de répertoire non pris en charge.",
pickSaveSuccess: "Emplacement de sauvegarde défini.",
pickSaveError: "Impossible de définir l'emplacement de sauvegarde.",
roomStatus: {
senderEmptyMsg: "La salle est vide",
receiverEmptyMsg:
senderEmptyMessage: "La salle est vide",
receiverEmptyMessage:
"Vous pouvez accepter une invitation pour rejoindre la salle",
onlyOneMsg: "Vous êtes le seul ici",
peopleMsg_template: "{peerCount} personnes dans la salle",
connected_dis: "Connecté",
senderDisconnectedMsg: "Expéditeur déconnecté",
leftRoomMsg: "Vous avez quitté la salle.",
leaveRoomBtn: "Quitter la Salle",
onlyOneMessage: "Vous êtes le seul ici",
peopleCountTemplate: "{peerCount} personnes dans la salle",
connectedLabel: "Connecté",
senderDisconnectedMessage: "Expéditeur déconnecté",
leftRoomMessage: "Vous avez quitté la salle.",
leaveRoomLabel: "Quitter la Salle",
},
fileExistMsg: "Certains fichiers ont déjà été ajoutés.",
noFilesForFolderMsg:
@@ -352,48 +352,48 @@ export const fr: Messages = {
html: {
senderTab: "Envoyer",
retrieveTab: "Récupérer",
shareTitle_dis: "Contenu partagé",
retrieveTitle_dis: "Récupérer le contenu",
RoomStatus_dis: "Statut :",
Paste_dis: "Coller",
Copy_dis: "Copier",
inputRoomIdprompt: "Votre ID de salle (modifiable) :",
joinRoomBtn: "Rejoindre la salle",
generateSimpleId_tips: "ID Simple",
generateRandomId_tips: "ID Aléatoire",
shareTitleLabel: "Contenu partagé",
retrieveTitleLabel: "Récupérer le contenu",
roomStatusLabel: "Statut :",
pasteLabel: "Coller",
copyLabel: "Copier",
inputRoomIdPrompt: "Votre ID de salle (modifiable) :",
joinRoomButtonLabel: "Rejoindre la salle",
generateSimpleIdTip: "ID Simple",
generateRandomIdTip: "ID Aléatoire",
readClipboardToRoomId: "Coller l'ID de salle",
enterRoomID_placeholder: "entrez l'ID de salle",
enterRoomIdPlaceholder: "entrez l'ID de salle",
retrieveMethod: "Méthode de récupération",
inputRoomId_tips: "Votre ID de salle (modifiable) :",
joinRoom_dis: "Rejoindre la salle",
SyncSending_loadingText: "Synchronisé",
SyncSending_dis: "Synchroniser",
readClipboard_dis: "Coller l'ID de salle",
retrieveRoomId_placeholder: "Entrez l'ID de salle",
RetrieveMethodTitle: "Méthode de récupération",
inputRoomIdTip: "Votre ID de salle (modifiable) :",
joinRoomLabel: "Rejoindre la salle",
syncSendingLoadingLabel: "Synchronisé",
syncSendingLabel: "Synchroniser",
readClipboardLabel: "Coller l'ID de salle",
retrieveRoomIdPlaceholder: "Entrez l'ID de salle",
retrieveMethodTitle: "Méthode de récupération",
// New: cached ID utils
saveId_dis: "Enregistrer lID",
useCachedId_dis: "Utiliser lID en cache",
saveId_tips:
saveIdLabel: "Enregistrer lID",
useCachedIdLabel: "Utiliser lID en cache",
saveIdTip:
"Enregistrez lID actuel pour une réutilisation rapide",
useCachedId_tips: "Utiliser ID enregistré rapide; double-clic pour changer mode sauvegarde",
useCachedIdTip: "Utiliser ID enregistré rapide; double-clic pour changer mode sauvegarde",
},
// New: cache messages
saveId_success: "Enregistré dans le cache",
saveIdSuccessMessage: "Enregistré dans le cache",
},
home: {
h1: "Outil gratuit de transfert de fichiers et de presse-papiers en ligne sécurisé",
h1P: "Les transferts P2P reprennent là où ils ont été interrompus. Découvrez un partage de fichiers et de texte vraiment fiable, privé et inarrêtable — sans inscription, sans limite de taille ou de vitesse de fichier, et entièrement gratuit.",
h2_screenOnly:
h2ScreenOnly:
"Essayez maintenant l'outil de transfert de fichiers et de presse-papiers sécurisé",
h2_demo: "Voyez le partage de fichiers sécurisé en action",
h2P_demo:
h2Demo: "Voyez le partage de fichiers sécurisé en action",
h2DemoDescription:
"Découvrez comment notre partage de fichiers local et chiffré de bout en bout protège votre vie privée",
watch_tips:
watchTip:
"Vous pouvez également regarder la vidéo sur ces plateformes :",
youtube_tips: "Regarder PrivyDrop sur YouTube",
bilibili_tips: "Regarder PrivyDrop sur Bilibili",
youtubeTip: "Regarder PrivyDrop sur YouTube",
bilibiliTip: "Regarder PrivyDrop sur Bilibili",
},
},
};
+126 -126
View File
@@ -56,36 +56,36 @@ export const ja: Messages = {
},
text: {
Header: {
Home_dis: "ホーム",
Blog_dis: "ブログ",
About_dis: "について",
Help_dis: "ヘルプ",
FAQ_dis: "FAQ",
Features_dis: "機能",
Terms_dis: "利用規約",
Privacy_dis: "プライバシー",
homeLabel: "ホーム",
blogLabel: "ブログ",
aboutLabel: "について",
helpLabel: "ヘルプ",
faqLabel: "FAQ",
featuresLabel: "機能",
termsLabel: "利用規約",
privacyLabel: "プライバシー",
},
Footer: {
CopyrightNotice: "PrivyDrop. All rights reserved.",
Terms_dis: "利用規約",
Privacy_dis: "プライバシーポリシー",
SupportedLanguages: "対応言語",
copyrightNotice: "PrivyDrop. All rights reserved.",
termsLabel: "利用規約",
privacyLabel: "プライバシーポリシー",
supportedLanguagesLabel: "対応言語",
},
blog: {
list_title: "ブログ",
list_subtitle: "最新の記事と更新",
recent_posts: "最新の投稿",
listTitle: "ブログ",
listSubtitle: "最新の記事と更新",
recentPosts: "最新の投稿",
tags: "タグ",
read_more: "続きを読む",
readMore: "続きを読む",
by: "著者",
post_not_found: "記事が見つかりません",
toc_title: "目次",
tag_title_prefix: "タグ",
tag_subtitle_template: "「{tag}」のタグが付いた記事",
tag_empty: "このタグの記事は見つかりません。",
postNotFound: "記事が見つかりません",
tocTitle: "目次",
tagTitlePrefix: "タグ",
tagSubtitleTemplate: "「{tag}」のタグが付いた記事",
tagEmpty: "このタグの記事は見つかりません。",
},
privacy: {
PrivacyPolicy_dis: "プライバシーポリシー",
privacyPolicyLabel: "プライバシーポリシー",
h1: "PrivyDropプライバシーポリシー",
h1_P: "PrivyDropでは、あなたのプライバシーを保護し、個人情報を守ることに尽力しています。このプライバシーポリシーでは、私たちがサービスを利用する際に提供されるデータをどのように収集、使用、保護するかを説明します。",
h2_1: "情報収集",
@@ -105,7 +105,7 @@ export const ja: Messages = {
"私たちのプライバシー慣行について質問や懸念がある場合は、お気軽にお問い合わせください。",
},
terms: {
TermsOfUse_dis: "利用規約",
termsOfUseLabel: "利用規約",
h1: "PrivyDrop利用規約",
h1_P: "PrivyDropサービスを利用することにより、あなたはこれらの利用規約に拘束されることに同意します。これらの規約に同意しない場合は、サービスを利用しないでください。",
h2_1: "サービスの使用",
@@ -124,7 +124,7 @@ export const ja: Messages = {
"私たちは、これらの利用規約を随時更新する権利を留保します。変更は、更新された規約をウェブサイトに掲載した時点で即座に有効になります。定期的に利用規約を確認し、変更を確認するのはあなたの責任です。",
},
help: {
Help_dis: "ヘルプ",
helpLabel: "ヘルプ",
h1: "PrivyDropヘルプとサポート",
h1_P: "PrivyDropを最大限に活用するためのお手伝いをします。質問やサポートが必要な場合は、お気軽にお問い合わせください。",
h2_1: "お問い合わせ",
@@ -145,21 +145,21 @@ export const ja: Messages = {
},
HowItWorks: {
h2: "使い方",
h2_P: "3つの簡単なステップでファイルやメッセージを即座に共有",
btn_try: "今すぐ試す →",
step1_title: "入力またはファイルを選択",
step1_description:
h2Description: "3つの簡単なステップでファイルやメッセージを即座に共有",
tryNowLabel: "今すぐ試す →",
step1Title: "入力またはファイルを選択",
step1Description:
"メッセージを入力するか、ファイル/フォルダを選択エリアにドラッグ&ドロップ",
step2_title: "ルームに参加",
step2_description:
step2Title: "ルームに参加",
step2Description:
"「ルームに参加」ボタンをクリックして共有セッションを作成",
step3_title: "受信",
step3_description:
step3Title: "受信",
step3Description:
"受信ページでルームIDを入力し、「ルームに参加」をクリックして共有コンテンツを取得",
},
SystemDiagram: {
h2: "システム図",
h2_P: "PrivyDrop: あなたのデータ、あなたの管理。シンプルで高速、プライベート。",
h2Description: "PrivyDrop: あなたのデータ、あなたの管理。シンプルで高速、プライベート。",
},
KeyFeatures: {
h2: "主な特徴",
@@ -183,7 +183,7 @@ export const ja: Messages = {
"保存ディレクトリを設定すると、再開可能な転送が自動的に有効になります。ネットワークの中断を心配する必要はもうありません。ファイル共有は中断したところから再開されます。",
},
faqs: {
FAQ_dis: "よくある質問",
faqLabel: "よくある質問",
question_0:
"データは本当にローカルに保存され、他のサーバーに転送されませんか?",
answer_0:
@@ -229,105 +229,105 @@ export const ja: Messages = {
"ルームIDの初期有効期間は24時間です。受信者がルームに参加すると、その時点から24時間自動的に延長されます。",
},
clipboard_btn: {
Pasted_dis: "貼り付け済み",
Copied_dis: "コピー済み",
pastedLabel: "貼り付け済み",
copiedLabel: "コピー済み",
},
fileUploadHandler: {
NoFileChosen_tips: "ファイルが選択されていません",
fileChosen_tips_template:
noFileChosenTip: "ファイルが選択されていません",
fileChosenTemplate:
"{fileNum} ファイルと {folderNum} フォルダが選択されました",
chooseFileTips:
chooseFileTip:
"このページ上のどこかにファイル/フォルダをドラッグ&ドロップするか、ここをクリックして選択してください。",
dragTips: "このページ上のどこかにドラッグしてください。",
dragTip: "このページ上のどこかにドラッグしてください。",
chosenDiagTitle: "アップロードタイプを選択",
chosenDiagDescription:
"ファイルまたはフォルダをアップロードするか選択してください",
SelectFile_dis: "ファイルを選択",
SelectFolder_dis: "フォルダを選択",
selectFileLabel: "ファイルを選択",
selectFolderLabel: "フォルダを選択",
},
FileTransferButton: {
SavedToDisk_tips: "ファイルは既にディスクに保存されています",
CurrentFileTransferring_tips: "ファイルが転送中です",
OtherFileTransferring_tips: "現在の転送が完了するまでお待ちください",
download_tips: "クリックしてファイルをダウンロード",
PendingSave_tips: "クリックしてファイルをローカルに保存", // 新增
Saved_dis: "保存済み",
Waiting_dis: "待機中",
Download_dis: "ダウンロード",
Save_dis: "保存", // 新增
savedToDiskTip: "ファイルは既にディスクに保存されています",
currentFileTransferringTip: "ファイルが転送中です",
otherFileTransferringTip: "現在の転送が完了するまでお待ちください",
downloadTip: "クリックしてファイルをダウンロード",
pendingSaveTip: "クリックしてファイルをローカルに保存", // 新增
savedLabel: "保存済み",
waitingLabel: "待機中",
downloadLabel: "ダウンロード",
saveLabel: "保存", // 新增
},
FileListDisplay: {
sending_dis: "送信中",
receiving_dis: "受信中",
finish_dis: "完了",
delete_dis: "削除",
downloadNum_dis: "ダウンロード回数",
folder_tips_template: "フォルダ名:{name} ({num} ファイルと {size})",
folder_dis_template: " ({num} ファイル, {size})",
PopupDialog_title: "推奨: 保存ディレクトリを選択",
PopupDialog_description:
sendingLabel: "送信中",
receivingLabel: "受信中",
finishedLabel: "完了",
deleteLabel: "削除",
downloadCountLabel: "ダウンロード回数",
folderSummaryTemplate: "フォルダ名:{name} ({num} ファイルと {size})",
folderInlineTemplate: " ({num} ファイル, {size})",
popupDialogTitle: "推奨: 保存ディレクトリを選択",
popupDialogDescription:
"大きなファイルを転送し、フォルダを効率的に同期するために、保存ディレクトリを選択することをお勧めします。",
chooseSavePath_tips:
chooseSavePathTip:
"大きなファイルやフォルダを選択したディレクトリに直接保存します。👉",
chooseSavePath_dis: "保存場所を選択",
chooseSavePathLabel: "保存場所を選択",
},
RetrieveMethod: {
P: "おめでとう 🎉 共有コンテンツが取得待ちです:",
RoomId_tips: "ルームIDを取得:",
copyRoomId_tips: "ルームIDをコピー",
url_tips: "URLを使用して取得:",
copyUrl_tips: "共有URLをコピー",
scanQR_tips: "QRコードをスキャンして受信 👇",
Copied_dis: "コピー済み",
Copy_QR_dis: "QRコードをコピー",
download_QR_dis: "QRコードをダウンロード",
introMessage: "おめでとう 🎉 共有コンテンツが取得待ちです:",
roomIdTip: "ルームIDを取得:",
copyRoomIdTip: "ルームIDをコピー",
urlTip: "URLを使用して取得:",
copyUrlTip: "共有URLをコピー",
scanQrTip: "QRコードをスキャンして受信 👇",
copiedLabel: "コピー済み",
copyQrLabel: "QRコードをコピー",
downloadQrLabel: "QRコードをダウンロード",
},
ClipboardApp: {
fetchRoom_err: "ルームの取得に失敗しました。もう一度お試しください。",
fetchRoomError: "ルームの取得に失敗しました。もう一度お試しください。",
roomCheck: {
empty_msg: "ルームIDは空にできません",
available_msg: "ルームは利用可能です",
notAvailable_msg: "ルームは利用できません。別のルームをお試しください",
emptyMessage: "ルームIDは空にできません",
availableMessage: "ルームは利用可能です",
notAvailableMessage: "ルームは利用できません。別のルームをお試しください",
},
channelOpen_msg:
channelOpenMessage:
"データチャネルが開かれ、データを受信する準備ができました...",
waitting_tips:
waitingTip:
"受信者が接続するのを待っています。転送が完了するまでこのページを開いたままにしてください。デスクトップでは、ブラウザを最小化したり、タブを切り替えたりできます。モバイルでは、ブラウザをフォアグラウンドに保ってください。",
joinRoom: {
EmptyMsg: "警告、ルームIDが空です",
DuplicateMsg: "このルームIDは既に使用されています。別のIDをご利用ください。",
successMsg:
emptyMessage: "警告、ルームIDが空です",
duplicateMessage: "このルームIDは既に使用されています。別のIDをご利用ください。",
successMessage:
"ルームに成功して参加しました!転送が完了するまでこのページを閉じないでください。(PCではブラウザを最小化したりタブを切り替えたりできます。モバイルではブラウザをバックグラウンドにしないでください。)",
notExist:
notFoundMessage:
"参加しようとしているルームは存在しません。送信者のみがルームを作成できます。",
failMsg: "ルームへの参加に失敗しました:",
failureMessage: "ルームへの参加に失敗しました:",
},
// Connection feedback (weak/VPN network scenarios)
join_inProgress:
joinInProgress:
"ルームに参加中…(回線が遅い環境では 5〜30 秒かかることがあります)",
join_slow:
joinSlow:
"少し時間がかかっています—ネットワーク/VPN をご確認のうえ、しばらくしてからお試しください",
join_timeout:
joinTimeout:
"参加がタイムアウトしました(ネットワーク制限の可能性)。再試行してください",
rtc_slow:
rtcSlow:
"ネットワークが制限されている可能性があります — VPN をオフにするか、しばらくしてから再試行してください",
rtc_negotiating: "入室済み—P2P 接続を確立しています…",
rtc_connected: "接続しました",
rtc_reconnecting: "再接続中…",
rtc_restored: "接続が回復しました",
rtcNegotiating: "入室済み—P2P 接続を確立しています…",
rtcConnected: "接続しました",
rtcReconnecting: "再接続中…",
rtcRestored: "接続が回復しました",
pickSaveMsg: "ディスクに直接保存しますか?",
pickSaveUnsupported: "ディレクトリピッカーはサポートされていません。",
pickSaveSuccess: "保存場所が設定されました。",
pickSaveError: "保存場所を設定できませんでした。",
roomStatus: {
senderEmptyMsg: "ルームは空です",
receiverEmptyMsg: "招待を受けてルームに参加できます",
onlyOneMsg: "あなただけがここにいます",
peopleMsg_template: "{peerCount} 人がルームにいます",
connected_dis: "接続済み",
senderDisconnectedMsg: "送信者が切断されました",
leftRoomMsg: "ルームを離れました。",
leaveRoomBtn: "ルームを離れる",
senderEmptyMessage: "ルームは空です",
receiverEmptyMessage: "招待を受けてルームに参加できます",
onlyOneMessage: "あなただけがここにいます",
peopleCountTemplate: "{peerCount} 人がルームにいます",
connectedLabel: "接続済み",
senderDisconnectedMessage: "送信者が切断されました",
leftRoomMessage: "ルームを離れました。",
leaveRoomLabel: "ルームを離れる",
},
fileExistMsg: "一部のファイルは既に追加されています。",
noFilesForFolderMsg: "フォルダ '{folderName}' にファイルが見つかりません。",
@@ -338,44 +338,44 @@ export const ja: Messages = {
html: {
senderTab: "送信",
retrieveTab: "取得",
shareTitle_dis: "共有コンテンツ",
retrieveTitle_dis: "取得コンテンツ",
RoomStatus_dis: "ステータス:",
Paste_dis: "貼り付け",
Copy_dis: "コピー",
inputRoomIdprompt: "ルームID(編集可能):",
joinRoomBtn: "ルームに参加",
generateSimpleId_tips: "シンプルID",
generateRandomId_tips: "ランダムID",
shareTitleLabel: "共有コンテンツ",
retrieveTitleLabel: "取得コンテンツ",
roomStatusLabel: "ステータス:",
pasteLabel: "貼り付け",
copyLabel: "コピー",
inputRoomIdPrompt: "ルームID(編集可能):",
joinRoomButtonLabel: "ルームに参加",
generateSimpleIdTip: "シンプルID",
generateRandomIdTip: "ランダムID",
readClipboardToRoomId: "ルームIDを貼り付け",
enterRoomID_placeholder: "ルームIDを入力",
enterRoomIdPlaceholder: "ルームIDを入力",
retrieveMethod: "取得方法",
inputRoomId_tips: "ルームID(編集可能):",
joinRoom_dis: "ルームに参加",
SyncSending_loadingText: "同期完了",
SyncSending_dis: "同期(どうき)",
readClipboard_dis: "ルームIDを貼り付け",
retrieveRoomId_placeholder: "ルームIDを入力",
RetrieveMethodTitle: "取得方法",
inputRoomIdTip: "ルームID(編集可能):",
joinRoomLabel: "ルームに参加",
syncSendingLoadingLabel: "同期完了",
syncSendingLabel: "同期(どうき)",
readClipboardLabel: "ルームIDを貼り付け",
retrieveRoomIdPlaceholder: "ルームIDを入力",
retrieveMethodTitle: "取得方法",
// New: cached ID utils
saveId_dis: "ID を保存",
useCachedId_dis: "保存済みIDを使用",
saveId_tips: "現在のIDを保存して次回すぐに使えるようにします",
useCachedId_tips: "保存済みIDを即使用;ダブルクリックで保存モード切替",
saveIdLabel: "ID を保存",
useCachedIdLabel: "保存済みIDを使用",
saveIdTip: "現在のIDを保存して次回すぐに使えるようにします",
useCachedIdTip: "保存済みIDを即使用;ダブルクリックで保存モード切替",
},
// New: cache messages
saveId_success: "キャッシュに保存しました",
saveIdSuccessMessage: "キャッシュに保存しました",
},
home: {
h1: "無料で安全なオンラインクリップボード&ファイル転送ツール",
h1P: "P2P転送が中断した場所から再開します。真に信頼でき、プライベートで、止められないファイルとテキストの共有を体験してください—登録不要、ファイルサイズや速度の制限なし、完全無料です。",
h2_screenOnly: "今すぐ安全なクリップボード&ファイル転送ツールを試す",
h2_demo: "安全なファイル共有のデモを見る",
h2P_demo:
h2ScreenOnly: "今すぐ安全なクリップボード&ファイル転送ツールを試す",
h2Demo: "安全なファイル共有のデモを見る",
h2DemoDescription:
"ローカルファースト、エンドツーエンド暗号化されたファイル共有がどのようにプライバシーを保護するかを見てください",
watch_tips: "これらのプラットフォームでもビデオを視聴できます:",
youtube_tips: "YouTubeでPrivyDropを見る",
bilibili_tips: "BilibiliでPrivyDropを見る",
watchTip: "これらのプラットフォームでもビデオを視聴できます:",
youtubeTip: "YouTubeでPrivyDropを見る",
bilibiliTip: "BilibiliでPrivyDropを見る",
},
},
};
+126 -126
View File
@@ -56,37 +56,37 @@ export const ko: Messages = {
},
text: {
Header: {
Home_dis: "홈",
Blog_dis: "블로그",
About_dis: "소개",
Help_dis: "도움말",
FAQ_dis: "FAQ",
Terms_dis: "이용 약관",
Privacy_dis: "개인정보 보호",
Features_dis: "기능",
homeLabel: "홈",
blogLabel: "블로그",
aboutLabel: "소개",
helpLabel: "도움말",
faqLabel: "FAQ",
termsLabel: "이용 약관",
privacyLabel: "개인정보 보호",
featuresLabel: "기능",
},
Footer: {
CopyrightNotice: "PrivyDrop. 모든 권리 보유.",
Terms_dis: "이용 약관",
Privacy_dis: "개인정보 보호정책",
SupportedLanguages: "지원 언어",
copyrightNotice: "PrivyDrop. 모든 권리 보유.",
termsLabel: "이용 약관",
privacyLabel: "개인정보 보호정책",
supportedLanguagesLabel: "지원 언어",
},
blog: {
list_title: "블로그",
list_subtitle: "최신 글과 업데이트",
recent_posts: "최근 글",
listTitle: "블로그",
listSubtitle: "최신 글과 업데이트",
recentPosts: "최근 글",
tags: "태그",
read_more: "더 보기",
readMore: "더 보기",
by: "작성자",
post_not_found: "게시글을 찾을 수 없습니다",
toc_title: "목차",
tag_title_prefix: "태그",
tag_subtitle_template: "{tag} 태그가 달린 글",
tag_empty: "해당 태그의 글이 없습니다.",
postNotFound: "게시글을 찾을 수 없습니다",
tocTitle: "목차",
tagTitlePrefix: "태그",
tagSubtitleTemplate: "{tag} 태그가 달린 글",
tagEmpty: "해당 태그의 글이 없습니다.",
},
privacy: {
PrivacyPolicy_dis: "개인정보 보호정책",
privacyPolicyLabel: "개인정보 보호정책",
h1: "PrivyDrop 개인정보 보호정책",
h1_P: "PrivyDrop는 귀하의 개인 정보를 보호하고 안전하게 지키기 위해 최선을 다하고 있습니다. 이 개인정보 보호정책은 귀하가 우리 서비스를 사용하는 동안 제공하는 데이터를 어떻게 수집, 사용 및 보호하는지 설명합니다.",
h2_1: "정보 수집",
@@ -106,7 +106,7 @@ export const ko: Messages = {
"개인정보 보호 관행에 대해 궁금한 점이 있으면 언제든지 다음 주소로 문의하십시오:",
},
terms: {
TermsOfUse_dis: "이용 약관",
termsOfUseLabel: "이용 약관",
h1: "PrivyDrop 이용 약관",
h1_P: "PrivyDrop 서비스를 사용함으로써 귀하는 본 이용 약관에 동의하게 됩니다. 이 약관에 동의하지 않으면 서비스를 사용하지 마십시오.",
h2_1: "서비스 사용",
@@ -125,7 +125,7 @@ export const ko: Messages = {
"우리는 언제든지 본 이용 약관을 업데이트할 권리를 보유합니다. 모든 변경 사항은 업데이트된 약관을 웹사이트에 게시함으로써 즉시 효력이 발생합니다. 귀하는 정기적으로 이용 약관을 검토하여 변경 사항을 확인할 책임이 있습니다.",
},
help: {
Help_dis: "도움말",
helpLabel: "도움말",
h1: "PrivyDrop 도움말 및 지원",
h1_P: "PrivyDrop를 최대한 활용할 수 있도록 도와드리겠습니다. 질문이 있거나 도움이 필요하면 언제든지 문의하십시오.",
h2_1: "문의하기",
@@ -146,20 +146,20 @@ export const ko: Messages = {
},
HowItWorks: {
h2: "작동 방식",
h2_P: "세 가지 간단한 단계로 파일과 메시지를 즉시 공유하세요",
btn_try: "지금 사용해 보기 →",
step1_title: "텍스트 입력 또는 파일 선택",
step1_description:
h2Description: "세 가지 간단한 단계로 파일과 메시지를 즉시 공유하세요",
tryNowLabel: "지금 사용해 보기 →",
step1Title: "텍스트 입력 또는 파일 선택",
step1Description:
"메시지를 입력하거나 파일/폴더를 선택 영역으로 드래그 앤 드롭하세요",
step2_title: "방 참가",
step2_description: "'방 참가' 버튼을 클릭하여 공유 세션을 생성하세요",
step3_title: "받기",
step3_description:
step2Title: "방 참가",
step2Description: "'방 참가' 버튼을 클릭하여 공유 세션을 생성하세요",
step3Title: "받기",
step3Description:
"받기 페이지에서 방 ID를 입력하고 '방 참가'를 클릭하여 공유된 콘텐츠를 받으세요",
},
SystemDiagram: {
h2: "시스템 다이어그램",
h2_P: "PrivyDrop: 귀하의 데이터, 귀하의 통제. 간단하고 빠르며 개인적입니다.",
h2Description: "PrivyDrop: 귀하의 데이터, 귀하의 통제. 간단하고 빠르며 개인적입니다.",
},
KeyFeatures: {
h2: "주요 기능",
@@ -183,7 +183,7 @@ export const ko: Messages = {
"저장 디렉토리를 설정하여 이어받기 가능한 전송을 자동으로 활성화하세요. 더 이상 네트워크 중단을 걱정할 필요가 없습니다. 파일 공유는 중단된 지점에서 바로 다시 시작됩니다.",
},
faqs: {
FAQ_dis: "자주 묻는 질문",
faqLabel: "자주 묻는 질문",
question_0:
"데이터가 정말로 로컬에 저장되고 다른 서버로 전송되지 않나요?",
answer_0:
@@ -228,104 +228,104 @@ export const ko: Messages = {
"방 ID의 초기 유효 기간은 24시간입니다. 수신자가 방에 참여하면 해당 시점부터 24시간 동안 유효 기간이 자동으로 연장됩니다.",
},
clipboard_btn: {
Pasted_dis: "붙여넣기 완료",
Copied_dis: "복사 완료",
pastedLabel: "붙여넣기 완료",
copiedLabel: "복사 완료",
},
fileUploadHandler: {
NoFileChosen_tips: "선택된 파일 없음",
fileChosen_tips_template:
noFileChosenTip: "선택된 파일 없음",
fileChosenTemplate:
"{fileNum}개의 파일 및 {folderNum}개의 폴더 선택됨",
chooseFileTips:
chooseFileTip:
"파일/폴더를 이 페이지의 아무 곳이나 드래그 앤 드롭하거나, 여기서 선택하세요.",
dragTips: "이 페이지의 아무 곳이나 드래그하세요.",
dragTip: "이 페이지의 아무 곳이나 드래그하세요.",
chosenDiagTitle: "업로드 유형 선택",
chosenDiagDescription: "파일 또는 폴더 업로드를 선택하세요",
SelectFile_dis: "파일 선택",
SelectFolder_dis: "폴더 선택",
selectFileLabel: "파일 선택",
selectFolderLabel: "폴더 선택",
},
FileTransferButton: {
SavedToDisk_tips: "파일이 이미 디스크에 저장됨",
CurrentFileTransferring_tips: "파일 전송 중",
OtherFileTransferring_tips: "현재 전송이 완료될 때까지 기다려주세요",
download_tips: "파일을 다운로드하려면 클릭하세요",
PendingSave_tips: "로컬에 파일을 저장하려면 클릭하세요", // 新增
Saved_dis: "저장됨",
Waiting_dis: "대기 중",
Download_dis: "다운로드",
Save_dis: "저장", // 新增
savedToDiskTip: "파일이 이미 디스크에 저장됨",
currentFileTransferringTip: "파일 전송 중",
otherFileTransferringTip: "현재 전송이 완료될 때까지 기다려주세요",
downloadTip: "파일을 다운로드하려면 클릭하세요",
pendingSaveTip: "로컬에 파일을 저장하려면 클릭하세요", // 新增
savedLabel: "저장됨",
waitingLabel: "대기 중",
downloadLabel: "다운로드",
saveLabel: "저장", // 新增
},
FileListDisplay: {
sending_dis: "전송 중",
receiving_dis: "수신 중",
finish_dis: "완료됨",
delete_dis: "삭제",
downloadNum_dis: "다운로드 횟수",
folder_tips_template: "폴더 이름: {name} ({num}개의 파일 및 {size})",
folder_dis_template: " ({num}개의 파일, {size})",
PopupDialog_title: "권장: 저장 디렉토리 선택",
PopupDialog_description:
sendingLabel: "전송 중",
receivingLabel: "수신 중",
finishedLabel: "완료됨",
deleteLabel: "삭제",
downloadCountLabel: "다운로드 횟수",
folderSummaryTemplate: "폴더 이름: {name} ({num}개의 파일 및 {size})",
folderInlineTemplate: " ({num}개의 파일, {size})",
popupDialogTitle: "권장: 저장 디렉토리 선택",
popupDialogDescription:
"대용량 파일이나 폴더를 직접 디스크에 저장하는 것을 권장합니다. 이를 통해 대용량 파일 전송 및 폴더 동기화가 더 효율적으로 이루어집니다.",
chooseSavePath_tips:
chooseSavePathTip:
"큰 파일이나 폴더를 선택한 디렉터리에 직접 저장합니다. 👉",
chooseSavePath_dis: "저장 위치 선택",
chooseSavePathLabel: "저장 위치 선택",
},
RetrieveMethod: {
P: "축하합니다 🎉 공유된 콘텐츠가 검색을 기다리고 있습니다:",
RoomId_tips: "방 ID 검색: ",
copyRoomId_tips: "방 ID 복사",
url_tips: "URL로 검색: ",
copyUrl_tips: "공유 URL 복사",
scanQR_tips: "QR 코드를 스캔하여 받기 👇",
Copied_dis: "복사됨",
Copy_QR_dis: "QR 코드 복사",
download_QR_dis: "QR 코드 다운로드",
introMessage: "축하합니다 🎉 공유된 콘텐츠가 검색을 기다리고 있습니다:",
roomIdTip: "방 ID 검색: ",
copyRoomIdTip: "방 ID 복사",
urlTip: "URL로 검색: ",
copyUrlTip: "공유 URL 복사",
scanQrTip: "QR 코드를 스캔하여 받기 👇",
copiedLabel: "복사됨",
copyQrLabel: "QR 코드 복사",
downloadQrLabel: "QR 코드 다운로드",
},
ClipboardApp: {
fetchRoom_err: "방을 가져오지 못했습니다. 다시 시도해주세요.",
fetchRoomError: "방을 가져오지 못했습니다. 다시 시도해주세요.",
roomCheck: {
//handleShareRoomCheck
empty_msg: "방 ID는 비어 있을 수 없습니다",
available_msg: "방을 사용할 수 있습니다",
notAvailable_msg: "방을 사용할 수 없습니다. 다른 방을 시도해주세요",
emptyMessage: "방 ID는 비어 있을 수 없습니다",
availableMessage: "방을 사용할 수 있습니다",
notAvailableMessage: "방을 사용할 수 없습니다. 다른 방을 시도해주세요",
},
channelOpen_msg: "'데이터 채널이 열렸습니다. 데이터 수신 준비 중...'",
waitting_tips:
channelOpenMessage: "'데이터 채널이 열렸습니다. 데이터 수신 준비 중...'",
waitingTip:
"수신자가 연결될 때까지 기다리는 중입니다. 전송이 완료될 때까지 이 페이지를 열어 두세요. 데스크톱에서는 브라우저를 최소화하거나 탭을 전환할 수 있습니다. 모바일에서는 브라우저를 포그라운드에 유지하세요.",
joinRoom: {
EmptyMsg: "경고, 방 ID가 비어 있습니다",
DuplicateMsg: "이 방 ID는 이미 사용 중입니다. 다른 ID를 선택해주세요.",
successMsg:
emptyMessage: "경고, 방 ID가 비어 있습니다",
duplicateMessage: "이 방 ID는 이미 사용 중입니다. 다른 ID를 선택해주세요.",
successMessage:
"방에 성공적으로 입장했습니다! 전송이 완료되기 전까지 현재 페이지를 닫지 마세요. (데스크톱에서는 브라우저를 최소화하거나 탭을 전환할 수 있으며, 모바일에서는 브라우저를 백그라운드로 이동하지 마세요.)",
notExist:
notFoundMessage:
"참여하려는 방이 존재하지 않습니다. 보내는 사람만 방을 만들 수 있습니다.",
failMsg: "방 참여 실패:",
failureMessage: "방 참여 실패:",
},
// Connection feedback (weak/VPN network scenarios)
join_inProgress:
joinInProgress:
"방에 참여 중… (느린 네트워크에서는 5–30초가 걸릴 수 있어요)",
join_slow:
joinSlow:
"조금 느려 보여요 — 네트워크/VPN을 확인하거나 잠시 후 다시 시도해 주세요",
join_timeout:
joinTimeout:
"참여 시간이 초과되었습니다(네트워크가 제한될 수 있음). 다시 시도해 주세요",
rtc_slow:
rtcSlow:
"네트워크가 제한되어 있을 수 있어요 — VPN을 끄거나 잠시 후 다시 시도해 주세요",
rtc_negotiating: "입장 완료 — P2P 직접 연결을 설정하는 중…",
rtc_connected: "연결되었습니다",
rtc_reconnecting: "재연결 중…",
rtc_restored: "연결이 복구되었습니다",
rtcNegotiating: "입장 완료 — P2P 직접 연결을 설정하는 중…",
rtcConnected: "연결되었습니다",
rtcReconnecting: "재연결 중…",
rtcRestored: "연결이 복구되었습니다",
pickSaveMsg: "직접 디스크에 저장하시겠습니까?",
pickSaveUnsupported: "디렉토리 선택기가 지원되지 않습니다.",
pickSaveSuccess: "저장 위치가 설정되었습니다.",
pickSaveError: "저장 위치를 설정할 수 없습니다.",
roomStatus: {
senderEmptyMsg: "방이 비어 있습니다",
receiverEmptyMsg: "초대를 수락하여 방에 참여할 수 있습니다",
onlyOneMsg: "현재 방에 혼자 있습니다",
peopleMsg_template: "방에 {peerCount}명이 있습니다",
connected_dis: "연결됨",
senderDisconnectedMsg: "발신자가 연결 해제됨",
leftRoomMsg: "방을 나갔습니다.",
leaveRoomBtn: "방 나가기",
senderEmptyMessage: "방이 비어 있습니다",
receiverEmptyMessage: "초대를 수락하여 방에 참여할 수 있습니다",
onlyOneMessage: "현재 방에 혼자 있습니다",
peopleCountTemplate: "방에 {peerCount}명이 있습니다",
connectedLabel: "연결됨",
senderDisconnectedMessage: "발신자가 연결 해제됨",
leftRoomMessage: "방을 나갔습니다.",
leaveRoomLabel: "방 나가기",
},
fileExistMsg: "일부 파일이 이미 추가되었습니다.",
noFilesForFolderMsg: "폴더 '{folderName}'에서 파일을 찾을 수 없습니다.",
@@ -336,46 +336,46 @@ export const ko: Messages = {
html: {
senderTab: "보내기",
retrieveTab: "검색",
shareTitle_dis: "콘텐츠 공유",
retrieveTitle_dis: "콘텐츠 검색",
RoomStatus_dis: "상태:",
Paste_dis: "붙여넣기",
Copy_dis: "복사",
inputRoomIdprompt: "방 ID (편집 가능):",
joinRoomBtn: "방 참여",
generateSimpleId_tips: "간단 ID",
generateRandomId_tips: "랜덤 ID",
shareTitleLabel: "콘텐츠 공유",
retrieveTitleLabel: "콘텐츠 검색",
roomStatusLabel: "상태:",
pasteLabel: "붙여넣기",
copyLabel: "복사",
inputRoomIdPrompt: "방 ID (편집 가능):",
joinRoomButtonLabel: "방 참여",
generateSimpleIdTip: "간단 ID",
generateRandomIdTip: "랜덤 ID",
readClipboardToRoomId: "방 ID 붙여넣기",
enterRoomID_placeholder: "방 ID 입력",
enterRoomIdPlaceholder: "방 ID 입력",
retrieveMethod: "검색 방법",
inputRoomId_tips: "방 ID (편집 가능):",
joinRoom_dis: "방 참여",
SyncSending_loadingText: "동기화 완료",
SyncSending_dis: "동기화(동기화)",
readClipboard_dis: "방 ID 붙여넣기",
retrieveRoomId_placeholder: "방 ID 입력",
RetrieveMethodTitle: "검색 방법",
inputRoomIdTip: "방 ID (편집 가능):",
joinRoomLabel: "방 참여",
syncSendingLoadingLabel: "동기화 완료",
syncSendingLabel: "동기화(동기화)",
readClipboardLabel: "방 ID 붙여넣기",
retrieveRoomIdPlaceholder: "방 ID 입력",
retrieveMethodTitle: "검색 방법",
// New: cached ID utils
saveId_dis: "ID 저장",
useCachedId_dis: "저장된 ID 사용",
saveId_tips:
saveIdLabel: "ID 저장",
useCachedIdLabel: "저장된 ID 사용",
saveIdTip:
"현재 ID를 저장하여 다음에 빠르게 사용할 수 있어요",
useCachedId_tips: "저장된 ID 빠르게 사용;더블클릭으로 저장 모드 전환",
useCachedIdTip: "저장된 ID 빠르게 사용;더블클릭으로 저장 모드 전환",
},
// New: cache messages
saveId_success: "캐시에 저장되었습니다",
saveIdSuccessMessage: "캐시에 저장되었습니다",
},
home: {
h1: "무료 보안 온라인 클립보드 및 파일 전송 도구",
h1P: "P2P 전송이 중단된 지점에서 다시 시작됩니다. 진정으로 신뢰할 수 있고, 비공개이며, 멈출 수 없는 파일 및 텍스트 공유를 경험하세요 — 등록 필요 없음, 파일 크기나 속도 제한 없음, 완전 무료입니다.",
h2_screenOnly: "지금 보안 클립보드 및 파일 전송 도구를 사용해보세요",
h2ScreenOnly: "지금 보안 클립보드 및 파일 전송 도구를 사용해보세요",
h2_demo: "보안 파일 공유 작동 방식 보기",
h2P_demo:
h2Demo: "보안 파일 공유 작동 방식 보기",
h2DemoDescription:
"로컬 우선, 엔드투엔드 암호화 파일 공유가 어떻게 개인 정보를 보호하는지 확인하세요",
watch_tips: "다음 플랫폼에서도 동영상을 시청할 수 있습니다:",
youtube_tips: "YouTube에서 PrivyDrop 보기",
bilibili_tips: "Bilibili에서 PrivyDrop 보기",
watchTip: "다음 플랫폼에서도 동영상을 시청할 수 있습니다:",
youtubeTip: "YouTube에서 PrivyDrop 보기",
bilibiliTip: "Bilibili에서 PrivyDrop 보기",
},
},
};
+126 -126
View File
@@ -52,36 +52,36 @@ export const zh: Messages = {
},
text: {
Header: {
Home_dis: "首页",
Blog_dis: "博客",
About_dis: "关于",
Help_dis: "帮助",
FAQ_dis: "常见问题",
Features_dis: "核心特性",
Terms_dis: "条款",
Privacy_dis: "隐私",
homeLabel: "首页",
blogLabel: "博客",
aboutLabel: "关于",
helpLabel: "帮助",
faqLabel: "常见问题",
featuresLabel: "核心特性",
termsLabel: "条款",
privacyLabel: "隐私",
},
Footer: {
CopyrightNotice: "PrivyDrop 版权所有",
Terms_dis: "使用条款",
Privacy_dis: "隐私政策",
SupportedLanguages: "支持的语言",
copyrightNotice: "PrivyDrop 版权所有",
termsLabel: "使用条款",
privacyLabel: "隐私政策",
supportedLanguagesLabel: "支持的语言",
},
blog: {
list_title: "博客",
list_subtitle: "最新文章与更新",
recent_posts: "最新文章",
listTitle: "博客",
listSubtitle: "最新文章与更新",
recentPosts: "最新文章",
tags: "标签",
read_more: "阅读更多",
readMore: "阅读更多",
by: "作者",
post_not_found: "未找到文章",
toc_title: "目录",
tag_title_prefix: "标签",
tag_subtitle_template: "包含 {tag} 标签的文章",
tag_empty: "没有找到相关文章。",
postNotFound: "未找到文章",
tocTitle: "目录",
tagTitlePrefix: "标签",
tagSubtitleTemplate: "包含 {tag} 标签的文章",
tagEmpty: "没有找到相关文章。",
},
privacy: {
PrivacyPolicy_dis: "隐私政策",
privacyPolicyLabel: "隐私政策",
h1: "PrivyDrop隐私政策",
h1_P: "PrivyDrop致力于保护您的隐私和个人信息安全。本隐私政策说明了我们如何收集、使用和保护您在使用服务时提供的数据。",
h2_1: "信息收集",
@@ -100,7 +100,7 @@ export const zh: Messages = {
h2_5_P: "如果您对我们的隐私实践有任何问题或疑虑,请联系我们:",
},
terms: {
TermsOfUse_dis: "使用条款",
termsOfUseLabel: "使用条款",
h1: "PrivyDrop使用条款",
h1_P: "使用PrivyDrop服务即表示您同意遵守这些使用条款。如果您不同意这些条款,请不要使用本服务。",
h2_1: "服务使用",
@@ -119,7 +119,7 @@ export const zh: Messages = {
"我们保留随时更新这些使用条款的权利。更新后的条款将在网站上发布时立即生效。请定期查看使用条款以了解任何变更。",
},
help: {
Help_dis: "帮助",
helpLabel: "帮助",
h1: "PrivyDrop帮助与支持",
h1_P: "我们随时为您提供帮助,让您充分利用PrivyDrop。如果您有任何问题或需要协助,请随时联系我们。",
h2_1: "联系我们",
@@ -140,18 +140,18 @@ export const zh: Messages = {
},
HowItWorks: {
h2: "使用方法",
h2_P: "三步即可实现即时文件和消息共享",
btn_try: "立即体验 →",
step1_title: "输入或选择文件",
step1_description: "输入消息或拖放文件/文件夹到选择区域",
step2_title: "加入房间",
step2_description: '点击"加入房间"按钮创建共享会话',
step3_title: "接收",
step3_description: '在接收页面输入房间ID并点击"加入房间"获取共享内容',
h2Description: "三步即可实现即时文件和消息共享",
tryNowLabel: "立即体验 →",
step1Title: "输入或选择文件",
step1Description: "输入消息或拖放文件/文件夹到选择区域",
step2Title: "加入房间",
step2Description: '点击"加入房间"按钮创建共享会话',
step3Title: "接收",
step3Description: '在接收页面输入房间ID并点击"加入房间"获取共享内容',
},
SystemDiagram: {
h2: "系统架构",
h2_P: "PrivyDrop:您掌控数据。简单、快速、私密。",
h2Description: "PrivyDrop:您掌控数据。简单、快速、私密。",
},
KeyFeatures: {
h2: "核心特点",
@@ -175,7 +175,7 @@ export const zh: Messages = {
"设置保存目录即可自动启用断点续传。不再担心网络中断,您的文件共享将从上次离开的地方继续。",
},
faqs: {
FAQ_dis: "常见问题",
faqLabel: "常见问题",
question_0: "数据真的是本地存储,不会传输到其他服务器吗?",
answer_0:
"是的,所有数据都在本地处理。您可以查看主页上的YouTube视频 - 在建立连接后断开互联网,文件仍然可以在本地网络内传输。未来我们计划开源代码,供所有人审查。",
@@ -218,95 +218,95 @@ export const zh: Messages = {
"房间ID的初始有效期为24小时。如果有接收者加入房间,有效期会自动从那一刻起延长24小时。",
},
clipboard_btn: {
Pasted_dis: "已粘贴",
Copied_dis: "已复制",
pastedLabel: "已粘贴",
copiedLabel: "已复制",
},
fileUploadHandler: {
NoFileChosen_tips: "未选择文件",
fileChosen_tips_template: "已选择{fileNum}个文件和{folderNum}个文件夹",
chooseFileTips: "将文件/文件夹拖拽到此页面的任意位置,或点击此处选择。",
dragTips: "拖拽到此页面的任意位置",
noFileChosenTip: "未选择文件",
fileChosenTemplate: "已选择{fileNum}个文件和{folderNum}个文件夹",
chooseFileTip: "将文件/文件夹拖拽到此页面的任意位置,或点击此处选择。",
dragTip: "拖拽到此页面的任意位置",
chosenDiagTitle: "选择上传类型",
chosenDiagDescription: "选择是要上传文件还是文件夹",
SelectFile_dis: "选择文件",
SelectFolder_dis: "选择文件夹",
selectFileLabel: "选择文件",
selectFolderLabel: "选择文件夹",
},
FileTransferButton: {
SavedToDisk_tips: "文件已保存到磁盘",
CurrentFileTransferring_tips: "文件正在传输中",
OtherFileTransferring_tips: "请等待当前传输完成",
download_tips: "点击下载文件",
PendingSave_tips: "点击保存文件到本地", // 新增
Saved_dis: "已保存",
Waiting_dis: "等待中",
Download_dis: "下载",
Save_dis: "保存", // 新增
savedToDiskTip: "文件已保存到磁盘",
currentFileTransferringTip: "文件正在传输中",
otherFileTransferringTip: "请等待当前传输完成",
downloadTip: "点击下载文件",
pendingSaveTip: "点击保存文件到本地", // 新增
savedLabel: "已保存",
waitingLabel: "等待中",
downloadLabel: "下载",
saveLabel: "保存", // 新增
},
FileListDisplay: {
sending_dis: "发送中",
receiving_dis: "接收中",
finish_dis: "已完成",
delete_dis: "删除",
downloadNum_dis: "下载次数",
folder_tips_template: "文件夹名称:{name}(共{num}个文件,总大小{size}",
folder_dis_template: "{num}个文件,{size}",
PopupDialog_title: "建议:选择保存目录",
PopupDialog_description:
sendingLabel: "发送中",
receivingLabel: "接收中",
finishedLabel: "已完成",
deleteLabel: "删除",
downloadCountLabel: "下载次数",
folderSummaryTemplate: "文件夹名称:{name}(共{num}个文件,总大小{size}",
folderInlineTemplate: "{num}个文件,{size}",
popupDialogTitle: "建议:选择保存目录",
popupDialogDescription:
"我们建议选择一个保存目录来直接将文件保存到磁盘。这样可以更方便地传输大文件和同步文件夹。",
chooseSavePath_tips: "大文件或文件夹可直接保存到指定目录 👉",
chooseSavePath_dis: "选择保存位置",
chooseSavePathTip: "大文件或文件夹可直接保存到指定目录 👉",
chooseSavePathLabel: "选择保存位置",
},
RetrieveMethod: {
P: "恭喜 🎉 共享内容等待接收:",
RoomId_tips: "接收用的房间ID是:",
copyRoomId_tips: "复制房间ID",
url_tips: "分享链接:",
copyUrl_tips: "复制分享链接",
scanQR_tips: "扫描二维码接收 👇",
Copied_dis: "已复制",
Copy_QR_dis: "复制二维码",
download_QR_dis: "下载二维码",
introMessage: "恭喜 🎉 共享内容等待接收:",
roomIdTip: "接收用的房间ID是:",
copyRoomIdTip: "复制房间ID",
urlTip: "分享链接:",
copyUrlTip: "复制分享链接",
scanQrTip: "扫描二维码接收 👇",
copiedLabel: "已复制",
copyQrLabel: "复制二维码",
downloadQrLabel: "下载二维码",
},
ClipboardApp: {
fetchRoom_err: "获取房间失败,请重试。",
fetchRoomError: "获取房间失败,请重试。",
roomCheck: {
empty_msg: "房间ID不能为空",
available_msg: "房间可用",
notAvailable_msg: "房间不可用,请尝试其他房间",
emptyMessage: "房间ID不能为空",
availableMessage: "房间可用",
notAvailableMessage: "房间不可用,请尝试其他房间",
},
channelOpen_msg: "数据通道已开启,准备接收数据...",
waitting_tips:
channelOpenMessage: "数据通道已开启,准备接收数据...",
waitingTip:
"等待接收方连接。请保持此页面打开直到传输完成。在桌面端,您可以最小化浏览器或切换标签页。在移动端,请保持浏览器在前台。",
joinRoom: {
EmptyMsg: "警告,房间ID为空",
DuplicateMsg: "该房间ID已被使用,请更换其他ID。",
successMsg:
emptyMessage: "警告,房间ID为空",
duplicateMessage: "该房间ID已被使用,请更换其他ID。",
successMessage:
"成功加入房间!在被接收之前不要关闭当前页(电脑端可以最小化浏览器或切换tab页,移动端不要将浏览器切到后台)。",
notExist: "您尝试加入的房间不存在。只有发送方可以创建房间。",
failMsg: "加入房间失败:",
notFoundMessage: "您尝试加入的房间不存在。只有发送方可以创建房间。",
failureMessage: "加入房间失败:",
},
// Connection feedback (weak/VPN network scenarios)
join_inProgress: "正在加入房间…(慢网可需 5–30 秒)",
join_slow: "连接较慢,建议检查网络/VPN 或稍后重试",
join_timeout: "加入超时(网络可能受限),请重试",
rtc_slow: "网络可能受限,尝试关闭 VPN 或稍后再试",
rtc_negotiating: "已入房,正在建立 P2P 连接…",
rtc_connected: "已连接",
rtc_reconnecting: "重连中…",
rtc_restored: "已恢复连接",
joinInProgress: "正在加入房间…(慢网可需 5–30 秒)",
joinSlow: "连接较慢,建议检查网络/VPN 或稍后重试",
joinTimeout: "加入超时(网络可能受限),请重试",
rtcSlow: "网络可能受限,尝试关闭 VPN 或稍后再试",
rtcNegotiating: "已入房,正在建立 P2P 连接…",
rtcConnected: "已连接",
rtcReconnecting: "重连中…",
rtcRestored: "已恢复连接",
pickSaveMsg: "直接保存到磁盘?",
pickSaveUnsupported: "不支持目录选择器。",
pickSaveSuccess: "保存位置已设置。",
pickSaveError: "无法设置保存位置。",
roomStatus: {
senderEmptyMsg: "房间为空",
receiverEmptyMsg: "您可以接受邀请加入房间",
onlyOneMsg: "只有您一人在房间内",
peopleMsg_template: `房间内共{peerCount}人`,
connected_dis: "已连接",
senderDisconnectedMsg: "发送端已断开连接",
leftRoomMsg: "您已离开房间。",
leaveRoomBtn: "离开房间",
senderEmptyMessage: "房间为空",
receiverEmptyMessage: "您可以接受邀请加入房间",
onlyOneMessage: "只有您一人在房间内",
peopleCountTemplate: `房间内共{peerCount}人`,
connectedLabel: "已连接",
senderDisconnectedMessage: "发送端已断开连接",
leftRoomMessage: "您已离开房间。",
leaveRoomLabel: "离开房间",
},
fileExistMsg: "某些文件已添加。",
noFilesForFolderMsg: "在文件夹 '{folderName}' 中未找到文件。",
@@ -318,43 +318,43 @@ export const zh: Messages = {
html: {
senderTab: "发送",
retrieveTab: "接收",
shareTitle_dis: "分享内容",
retrieveTitle_dis: "接收内容",
RoomStatus_dis: "状态:",
Paste_dis: "粘贴",
Copy_dis: "复制",
inputRoomIdprompt: "您的房间ID(可编辑):",
joinRoomBtn: "加入房间",
generateSimpleId_tips: "简单ID",
generateRandomId_tips: "随机ID",
shareTitleLabel: "分享内容",
retrieveTitleLabel: "接收内容",
roomStatusLabel: "状态:",
pasteLabel: "粘贴",
copyLabel: "复制",
inputRoomIdPrompt: "您的房间ID(可编辑):",
joinRoomButtonLabel: "加入房间",
generateSimpleIdTip: "简单ID",
generateRandomIdTip: "随机ID",
readClipboardToRoomId: "粘贴房间ID",
enterRoomID_placeholder: "输入房间ID",
enterRoomIdPlaceholder: "输入房间ID",
retrieveMethod: "接收方式",
inputRoomId_tips: "您的房间ID(可编辑):",
joinRoom_dis: "加入房间",
SyncSending_loadingText: "已同步",
SyncSending_dis: "同步",
readClipboard_dis: "粘贴房间ID",
retrieveRoomId_placeholder: "输入房间ID",
RetrieveMethodTitle: "接收方式",
inputRoomIdTip: "您的房间ID(可编辑):",
joinRoomLabel: "加入房间",
syncSendingLoadingLabel: "已同步",
syncSendingLabel: "同步",
readClipboardLabel: "粘贴房间ID",
retrieveRoomIdPlaceholder: "输入房间ID",
retrieveMethodTitle: "接收方式",
// New: cached ID utils
saveId_dis: "保存ID",
useCachedId_dis: "使用缓存ID",
saveId_tips: "保存ID后,下次可以快捷使用该ID",
useCachedId_tips: "快捷使用已保存ID;双击可切换保存模式",
saveIdLabel: "保存ID",
useCachedIdLabel: "使用缓存ID",
saveIdTip: "保存ID后,下次可以快捷使用该ID",
useCachedIdTip: "快捷使用已保存ID;双击可切换保存模式",
},
// New: cache messages
saveId_success: "缓存成功",
saveIdSuccessMessage: "缓存成功",
},
home: {
h1: "免费安全的在线剪贴板与文件传输工具",
h1P: "P2P传输从中断处恢复。体验真正可靠、私密、不可阻挡的文件和文本共享——无需注册,无文件大小和速度限制,完全免费。",
h2_screenOnly: "立即体验安全剪贴板与文件传输工具",
h2_demo: "观看安全文件共享演示",
h2P_demo: "了解我们如何通过本地优先、端到端加密的文件共享保护您的隐私",
watch_tips: "也可以在以下平台观看视频:",
youtube_tips: "在 YouTube 观看 PrivyDrop",
bilibili_tips: "在 Bilibili 观看 PrivyDrop",
h2ScreenOnly: "立即体验安全剪贴板与文件传输工具",
h2Demo: "观看安全文件共享演示",
h2DemoDescription: "了解我们如何通过本地优先、端到端加密的文件共享保护您的隐私",
watchTip: "也可以在以下平台观看视频:",
youtubeTip: "在 YouTube 观看 PrivyDrop",
bilibiliTip: "在 Bilibili 观看 PrivyDrop",
},
},
};
+5 -8
View File
@@ -39,14 +39,11 @@ export const useClipboardActions = (): ClipboardActions => {
.then((dict) => {
setMessages(dict);
setClipboardMessages({
copiedSuccess: dict.text.clipboard_btn.Copied_dis,
pastedSuccess: dict.text.clipboard_btn.Pasted_dis,
copyError:
dict.text.clipboard_btn.Copy_failed_dis || "Failed to copy.", // Fallback
readError:
dict.text.clipboard_btn.Paste_failed_dis ||
"Failed to read clipboard.", // Fallback
loading: dict.text.Loading_dis || "Loading...", // Fallback
copiedSuccess: dict.text.clipboard_btn.copiedLabel,
pastedSuccess: dict.text.clipboard_btn.pastedLabel,
copyError: "Failed to copy.",
readError: "Failed to read clipboard.",
loading: "Loading...",
});
setIsLoadingMessages(false);
})
+11 -11
View File
@@ -39,7 +39,7 @@ export function useConnectionFeedback({
displayMs: 6000,
getMessage: () => {
if (!messages) return null;
const text = messages.text.ClipboardApp.rtc_slow;
const text = messages.text.ClipboardApp.rtcSlow;
if (!text) return null;
const isShareEnd =
rtcSlowTriggerSideRef.current === "share"
@@ -68,18 +68,18 @@ export function useConnectionFeedback({
// Sender side mapping
if (nowShare === "negotiating" && prevShare !== "negotiating") {
const msg = messages.text.ClipboardApp.rtc_negotiating;
const msg = messages.text.ClipboardApp.rtcNegotiating;
if (msg) putMessageInMs(msg, true, 4000);
if (!rtcSlowTriggerSideRef.current) rtcSlowTriggerSideRef.current = "share";
armRtcSlow("rtc-negotiating");
}
if (nowShare === "connected") {
if (!everShareRef.current) {
const msg = messages.text.ClipboardApp.rtc_connected;
const msg = messages.text.ClipboardApp.rtcConnected;
if (msg) putMessageInMs(msg, true, 4000);
}
if (wasDiscShareRef.current) {
const msg = messages.text.ClipboardApp.rtc_restored;
const msg = messages.text.ClipboardApp.rtcRestored;
if (msg) putMessageInMs(msg, true, 4000);
}
everShareRef.current = true;
@@ -90,7 +90,7 @@ export function useConnectionFeedback({
const isForeground =
typeof document !== "undefined" && document.visibilityState === "visible";
if ((everShareRef.current || wasDiscShareRef.current) && isForeground) {
const msg = messages.text.ClipboardApp.rtc_reconnecting;
const msg = messages.text.ClipboardApp.rtcReconnecting;
if (msg) putMessageInMs(msg, true, 4000);
wasDiscShareRef.current = true;
}
@@ -99,18 +99,18 @@ export function useConnectionFeedback({
// Receiver side mapping
if (nowRecv === "negotiating" && prevRecv !== "negotiating") {
const msg = messages.text.ClipboardApp.rtc_negotiating;
const msg = messages.text.ClipboardApp.rtcNegotiating;
if (msg) putMessageInMs(msg, false, 4000);
if (!rtcSlowTriggerSideRef.current) rtcSlowTriggerSideRef.current = "recv";
armRtcSlow("rtc-negotiating");
}
if (nowRecv === "connected") {
if (!everRecvRef.current) {
const msg = messages.text.ClipboardApp.rtc_connected;
const msg = messages.text.ClipboardApp.rtcConnected;
if (msg) putMessageInMs(msg, false, 4000);
}
if (wasDiscRecvRef.current) {
const msg = messages.text.ClipboardApp.rtc_restored;
const msg = messages.text.ClipboardApp.rtcRestored;
if (msg) putMessageInMs(msg, false, 4000);
}
everRecvRef.current = true;
@@ -121,7 +121,7 @@ export function useConnectionFeedback({
const isForeground =
typeof document !== "undefined" && document.visibilityState === "visible";
if ((everRecvRef.current || wasDiscRecvRef.current) && isForeground) {
const msg = messages.text.ClipboardApp.rtc_reconnecting;
const msg = messages.text.ClipboardApp.rtcReconnecting;
if (msg) putMessageInMs(msg, false, 4000);
wasDiscRecvRef.current = true;
}
@@ -153,7 +153,7 @@ export function useConnectionFeedback({
(everShareRef.current || wasDiscShareRef.current) &&
nowShare === "disconnected"
) {
const msg = messages.text.ClipboardApp.rtc_reconnecting;
const msg = messages.text.ClipboardApp.rtcReconnecting;
if (msg) putMessageInMs(msg, true, 4000);
wasDiscShareRef.current = true;
}
@@ -161,7 +161,7 @@ export function useConnectionFeedback({
(everRecvRef.current || wasDiscRecvRef.current) &&
nowRecv === "disconnected"
) {
const msg = messages.text.ClipboardApp.rtc_reconnecting;
const msg = messages.text.ClipboardApp.rtcReconnecting;
if (msg) putMessageInMs(msg, false, 4000);
wasDiscRecvRef.current = true;
}
+20 -20
View File
@@ -57,7 +57,7 @@ export function useRoomManager({
displayMs: 6000,
getMessage: () => {
if (!messages) return null;
const text = messages.text.ClipboardApp.join_slow;
const text = messages.text.ClipboardApp.joinSlow;
if (!text) return null;
return { text, isShareEnd: joinSideRef.current };
},
@@ -75,7 +75,7 @@ export function useRoomManager({
try {
// Immediate feedback on click
const joinInProgressMsg = messages.text.ClipboardApp.join_inProgress;
const joinInProgressMsg = messages.text.ClipboardApp.joinInProgress;
putMessageInMs(joinInProgressMsg, isSenderSide, 6000);
// 3s slow-network hint
@@ -91,7 +91,7 @@ export function useRoomManager({
const success = await createRoom(roomId);
if (!success) {
putMessageInMs(
messages.text.ClipboardApp.joinRoom.DuplicateMsg,
messages.text.ClipboardApp.joinRoom.duplicateMessage,
isSenderSide
);
disarmJoinSlow();
@@ -100,7 +100,7 @@ export function useRoomManager({
setShareRoomId(roomId);
} catch (error) {
putMessageInMs(
messages.text.ClipboardApp.joinRoom.failMsg +
messages.text.ClipboardApp.joinRoom.failureMessage +
` (Create room error)`,
isSenderSide
);
@@ -133,7 +133,7 @@ export function useRoomManager({
disarmJoinSlow();
putMessageInMs(
messages.text.ClipboardApp.joinRoom.successMsg,
messages.text.ClipboardApp.joinRoom.successMessage,
isSenderSide,
6000
);
@@ -148,14 +148,14 @@ export function useRoomManager({
}
} catch (error) {
console.error("[RoomManager] Failed to join room:", error);
let errorMsg = messages.text.ClipboardApp.joinRoom.failMsg;
let errorMsg = messages.text.ClipboardApp.joinRoom.failureMessage;
if (error instanceof Error) {
errorMsg =
error.message === "Room does not exist"
? messages.text.ClipboardApp.joinRoom.notExist
? messages.text.ClipboardApp.joinRoom.notFoundMessage
: error.message === "Join room timeout"
? messages.text.ClipboardApp.join_timeout
: `${messages.text.ClipboardApp.joinRoom.failMsg} ${error.message}`;
? messages.text.ClipboardApp.joinTimeout
: `${messages.text.ClipboardApp.joinRoom.failureMessage} ${error.message}`;
}
// Clear joining slow-hint on failure
disarmJoinSlow();
@@ -182,7 +182,7 @@ export function useRoomManager({
try {
if (sharePeerCount === 0) {
putMessageInMs(messages.text.ClipboardApp.waitting_tips, true);
putMessageInMs(messages.text.ClipboardApp.waitingTip, true);
} else {
// Directly call the service's broadcast method
await webrtcService.broadcastDataToAllPeers();
@@ -220,7 +220,7 @@ export function useRoomManager({
const message = isAnyFileTransferring
? messages.text.ClipboardApp.leaveWhileTransferringSuccess
: messages.text.ClipboardApp.roomStatus.leftRoomMsg;
: messages.text.ClipboardApp.roomStatus.leftRoomMessage;
putMessageInMs(message, false);
// Reset receiver state (clears all as per requirement)
@@ -276,7 +276,7 @@ export function useRoomManager({
const message = isAnyFileTransferring
? messages.text.ClipboardApp.leaveWhileTransferringSuccess
: messages.text.ClipboardApp.roomStatus.leftRoomMsg;
: messages.text.ClipboardApp.roomStatus.leftRoomMessage;
putMessageInMs(message, true);
// Reset sender state and get new room ID (keeps files as per requirement)
@@ -297,12 +297,12 @@ export function useRoomManager({
if (isValid) {
setShareRoomId(input);
putMessageInMs(
messages.text.ClipboardApp.roomCheck.available_msg,
messages.text.ClipboardApp.roomCheck.availableMessage,
true
);
} else {
putMessageInMs(
messages.text.ClipboardApp.roomCheck.notAvailable_msg,
messages.text.ClipboardApp.roomCheck.notAvailableMessage,
true
);
}
@@ -330,7 +330,7 @@ export function useRoomManager({
} catch (err) {
console.error("[RoomManager] Failed to fetch initial room:", err);
const errorMsg =
messages.text?.ClipboardApp?.fetchRoom_err ||
messages.text?.ClipboardApp?.fetchRoomError ||
"Failed to fetch room ID";
putMessageInMs(errorMsg, true);
}
@@ -362,18 +362,18 @@ export function useRoomManager({
if (!isInRoom) {
statusText =
activeTab === "retrieve"
? messages.text.ClipboardApp.roomStatus.receiverEmptyMsg
: messages.text.ClipboardApp.roomStatus.senderEmptyMsg;
? messages.text.ClipboardApp.roomStatus.receiverEmptyMessage
: messages.text.ClipboardApp.roomStatus.senderEmptyMessage;
} else if (currentPeerCount === 0) {
statusText = messages.text.ClipboardApp.roomStatus.onlyOneMsg;
statusText = messages.text.ClipboardApp.roomStatus.onlyOneMessage;
} else {
statusText =
activeTab === "send"
? format_peopleMsg(
messages.text.ClipboardApp.roomStatus.peopleMsg_template,
messages.text.ClipboardApp.roomStatus.peopleCountTemplate,
currentPeerCount + 1
)
: messages.text.ClipboardApp.roomStatus.connected_dis;
: messages.text.ClipboardApp.roomStatus.connectedLabel;
}
if (activeTab === "send") setShareRoomStatusText(statusText);
+126 -126
View File
@@ -18,25 +18,25 @@ export type Meta = {
};
export type Header = {
Home_dis: string;
Blog_dis: string;
About_dis: string;
Help_dis: string;
FAQ_dis: string;
Features_dis: string;
Terms_dis: string;
Privacy_dis: string;
homeLabel: string;
blogLabel: string;
aboutLabel: string;
helpLabel: string;
faqLabel: string;
featuresLabel: string;
termsLabel: string;
privacyLabel: string;
};
export type Footer = {
CopyrightNotice: string;
Terms_dis: string;
Privacy_dis: string;
SupportedLanguages: string;
copyrightNotice: string;
termsLabel: string;
privacyLabel: string;
supportedLanguagesLabel: string;
};
export type Privacy = {
PrivacyPolicy_dis: string;
privacyPolicyLabel: string;
h1: string;
h1_P: string;
h2_1: string;
@@ -52,7 +52,7 @@ export type Privacy = {
};
export type Terms = {
TermsOfUse_dis: string;
termsOfUseLabel: string;
h1: string;
h1_P: string;
h2_1: string;
@@ -68,7 +68,7 @@ export type Terms = {
};
export type Help = {
Help_dis: string;
helpLabel: string;
h1: string;
h1_P: string;
h2_1: string;
@@ -91,33 +91,33 @@ export type About = {
export type HowItWorks = {
h2: string;
h2_P: string;
btn_try: string;
step1_title: string;
step1_description: string;
step2_title: string;
step2_description: string;
step3_title: string;
step3_description: string;
h2Description: string;
tryNowLabel: string;
step1Title: string;
step1Description: string;
step2Title: string;
step2Description: string;
step3Title: string;
step3Description: string;
};
export type SystemDiagram = {
h2: string;
h2_P: string;
h2Description: string;
};
export type BlogTexts = {
list_title: string;
list_subtitle: string;
recent_posts: string;
listTitle: string;
listSubtitle: string;
recentPosts: string;
tags: string;
read_more: string;
readMore: string;
by: string;
post_not_found: string;
toc_title: string;
tag_title_prefix: string;
tag_subtitle_template: string; // use {tag} as placeholder
tag_empty: string;
postNotFound: string;
tocTitle: string;
tagTitlePrefix: string;
tagSubtitleTemplate: string; // use {tag} as placeholder
tagEmpty: string;
};
export type KeyFeatures = {
@@ -137,7 +137,7 @@ export type KeyFeatures = {
};
export type FAQ = {
FAQ_dis: string;
faqLabel: string;
question_0: string;
answer_0: string;
question_1: string;
@@ -169,118 +169,118 @@ export type FAQ = {
};
export type ClipboardBtn = {
Pasted_dis: string;
Copied_dis: string;
pastedLabel: string;
copiedLabel: string;
};
export type FileUploadHandler = {
NoFileChosen_tips: string;
fileChosen_tips_template: string;
chooseFileTips: string;
dragTips: string;
noFileChosenTip: string;
fileChosenTemplate: string;
chooseFileTip: string;
dragTip: string;
chosenDiagTitle: string;
chosenDiagDescription: string;
SelectFile_dis: string;
SelectFolder_dis: string;
selectFileLabel: string;
selectFolderLabel: string;
};
export type FileTransferButton = {
SavedToDisk_tips: string;
CurrentFileTransferring_tips: string;
OtherFileTransferring_tips: string;
download_tips: string;
PendingSave_tips: string;
Saved_dis: string;
Waiting_dis: string;
Download_dis: string;
Save_dis: string;
savedToDiskTip: string;
currentFileTransferringTip: string;
otherFileTransferringTip: string;
downloadTip: string;
pendingSaveTip: string;
savedLabel: string;
waitingLabel: string;
downloadLabel: string;
saveLabel: string;
};
export type FileListDisplay = {
sending_dis: string;
receiving_dis: string;
finish_dis: string;
delete_dis: string;
downloadNum_dis: string;
folder_tips_template: string;
folder_dis_template: string;
PopupDialog_title: string;
PopupDialog_description: string;
chooseSavePath_tips: string;
chooseSavePath_dis: string;
sendingLabel: string;
receivingLabel: string;
finishedLabel: string;
deleteLabel: string;
downloadCountLabel: string;
folderSummaryTemplate: string;
folderInlineTemplate: string;
popupDialogTitle: string;
popupDialogDescription: string;
chooseSavePathTip: string;
chooseSavePathLabel: string;
};
export type RetrieveMethod = {
P: string;
RoomId_tips: string;
copyRoomId_tips: string;
url_tips: string;
copyUrl_tips: string;
scanQR_tips: string;
Copied_dis: string;
Copy_QR_dis: string;
download_QR_dis: string;
introMessage: string;
roomIdTip: string;
copyRoomIdTip: string;
urlTip: string;
copyUrlTip: string;
scanQrTip: string;
copiedLabel: string;
copyQrLabel: string;
downloadQrLabel: string;
};
export type RoomCheck = {
empty_msg: string;
available_msg: string;
notAvailable_msg: string;
emptyMessage: string;
availableMessage: string;
notAvailableMessage: string;
};
export type JoinRoom = {
EmptyMsg: string;
DuplicateMsg: string;
successMsg: string;
notExist: string;
failMsg: string;
emptyMessage: string;
duplicateMessage: string;
successMessage: string;
notFoundMessage: string;
failureMessage: string;
};
export type RoomStatus = {
senderEmptyMsg: string;
receiverEmptyMsg: string;
onlyOneMsg: string;
peopleMsg_template: string;
connected_dis: string;
senderDisconnectedMsg: string;
leftRoomMsg: string;
leaveRoomBtn: string;
senderEmptyMessage: string;
receiverEmptyMessage: string;
onlyOneMessage: string;
peopleCountTemplate: string;
connectedLabel: string;
senderDisconnectedMessage: string;
leftRoomMessage: string;
leaveRoomLabel: string;
};
export type ClipboardAppHtml = {
senderTab: string;
retrieveTab: string;
shareTitle_dis: string;
retrieveTitle_dis: string;
RoomStatus_dis: string;
Paste_dis: string;
Copy_dis: string;
inputRoomIdprompt: string;
joinRoomBtn: string;
generateSimpleId_tips: string;
generateRandomId_tips: string;
shareTitleLabel: string;
retrieveTitleLabel: string;
roomStatusLabel: string;
pasteLabel: string;
copyLabel: string;
inputRoomIdPrompt: string;
joinRoomButtonLabel: string;
generateSimpleIdTip: string;
generateRandomIdTip: string;
readClipboardToRoomId: string;
enterRoomID_placeholder: string;
enterRoomIdPlaceholder: string;
retrieveMethod: string;
inputRoomId_tips: string;
joinRoom_dis: string;
SyncSending_loadingText: string;
SyncSending_dis: string;
readClipboard_dis: string;
retrieveRoomId_placeholder: string;
RetrieveMethodTitle: string;
inputRoomIdTip: string;
joinRoomLabel: string;
syncSendingLoadingLabel: string;
syncSendingLabel: string;
readClipboardLabel: string;
retrieveRoomIdPlaceholder: string;
retrieveMethodTitle: string;
// New: cached ID utilities
saveId_dis: string;
useCachedId_dis: string;
saveId_tips: string;
useCachedId_tips: string;
saveIdLabel: string;
useCachedIdLabel: string;
saveIdTip: string;
useCachedIdTip: string;
};
export type ClipboardApp = {
fetchRoom_err: string;
fetchRoomError: string;
roomCheck: RoomCheck;
channelOpen_msg: string;
waitting_tips: string;
channelOpenMessage: string;
waitingTip: string;
joinRoom: JoinRoom;
pickSaveMsg: string;
pickSaveUnsupported: string;
@@ -295,28 +295,28 @@ export type ClipboardApp = {
confirmLeaveWhileTransferring: string;
leaveWhileTransferringSuccess: string;
// New: cache messages
saveId_success: string;
saveIdSuccessMessage: string;
// UI connection feedback
join_inProgress: string;
join_slow: string;
join_timeout: string;
joinInProgress: string;
joinSlow: string;
joinTimeout: string;
// Slow P2P negotiation hint
rtc_slow: string;
rtc_negotiating: string;
rtc_connected: string;
rtc_reconnecting: string;
rtc_restored: string;
rtcSlow: string;
rtcNegotiating: string;
rtcConnected: string;
rtcReconnecting: string;
rtcRestored: string;
};
export type Home = {
h1: string;
h1P: string;
h2_screenOnly: string;
h2_demo: string;
h2P_demo: string;
watch_tips: string;
youtube_tips: string;
bilibili_tips: string;
h2ScreenOnly: string;
h2Demo: string;
h2DemoDescription: string;
watchTip: string;
youtubeTip: string;
bilibiliTip: string;
};
export type Text = {