style: soft profile dialog

This commit is contained in:
zhom committed 2026-10-14 21:23:25 +04:00
1 parent 7bef261c8b
commit d1245e2188
17 files changed
+397 -372

No files matched your search

+1 -1
View File
@@ -93,7 +93,7 @@ export function ProfileHandoffStatus({
data-profile-id={profileId}
data-handoff-state={phase}
aria-label={t("profileMotion.handoffTitle")}
className="flex flex-col gap-3 rounded-md bg-muted/40 p-3"
className="flex flex-col gap-3 rounded-lg bg-foreground/4 p-3"
>
<div className="flex items-start justify-between gap-3">
<div className="min-w-0">
+78 -69
View File
@@ -76,6 +76,7 @@ import {
DropdownMenuItem,
DropdownMenuTrigger,
} from "@/components/ui/dropdown-menu";
import { SoftFields } from "@/components/ui/field-variant";
import { Input } from "@/components/ui/input";
import {
Popover,
@@ -190,7 +191,7 @@ function ClearOnCloseToggle({
};
return (
<div className="flex items-center gap-3 rounded-md border border-border bg-muted/40 px-3 py-2">
<div className="flex items-center gap-3 rounded-lg bg-foreground/4 px-3 py-2">
<LuEraser className="size-4 shrink-0 text-muted-foreground" />
<div className="min-w-0 flex-1">
<p className="text-sm font-medium">{t("clearOnClose.label")}</p>
@@ -225,14 +226,14 @@ function InfoCard({
type="button"
disabled={disabled}
onClick={onClick}
className="min-w-0 rounded-md bg-muted/50 px-3 py-2.5 text-left transition-colors hover:bg-accent focus-visible:outline-2 focus-visible:outline-ring disabled:opacity-50"
className="min-w-0 rounded-lg bg-foreground/4 px-3 py-2.5 text-left transition-colors hover:bg-foreground/7 focus-visible:outline-2 focus-visible:outline-ring disabled:opacity-50"
>
<span className="block text-xs text-muted-foreground">{label}</span>
<span className="mt-0.5 block break-words text-sm">{value}</span>
</button>
);
return (
<div className="rounded-md border bg-muted/50 px-3 py-2.5">
<div className="rounded-lg bg-foreground/4 px-3 py-2.5">
<p className="text-xs text-muted-foreground">{label}</p>
<p className="mt-0.5 break-words text-sm">{value}</p>
</div>
@@ -1166,7 +1167,7 @@ function ProfileInfoLayout({
: "overview";
return (
<>
<SoftFields>
{/* Top bar */}
<div className="flex min-h-11 shrink-0 items-center gap-2 px-3 py-2">
<LuUsers className="size-3.5 shrink-0 text-muted-foreground" />
@@ -1181,7 +1182,7 @@ function ProfileInfoLayout({
</div>
{onCloneProfile && (
<Button
variant="ghost"
variant="subtle"
size="sm"
className="h-7 gap-1.5 px-2 text-xs"
disabled={isDisabled}
@@ -1193,7 +1194,7 @@ function ProfileInfoLayout({
)}
{saveTemplateAction && (
<Button
variant="ghost"
variant="subtle"
size="sm"
className="h-7 gap-1.5 px-2 text-xs"
data-slot="profile-info-save-template"
@@ -1203,12 +1204,26 @@ function ProfileInfoLayout({
{saveTemplateAction.label}
</Button>
)}
{deleteAction && (
<Button
variant="subtle"
size="icon"
data-slot="profile-info-delete"
aria-label={t("profileInfo.sections.delete")}
title={t("profileInfo.sections.delete")}
className="size-7 text-destructive-text hover:bg-destructive/10 hover:text-destructive-text"
onClick={deleteAction.onClick}
disabled={deleteAction.disabled}
>
<LuTrash2 className="size-3.5" />
</Button>
)}
<button
type="button"
data-slot="profile-info-close"
aria-label={t("common.buttons.close")}
onClick={onClose}
className="grid size-7 shrink-0 place-items-center rounded-md text-muted-foreground transition-colors duration-100 hover:bg-accent hover:text-accent-foreground focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-ring"
className="grid size-7 shrink-0 place-items-center rounded-md text-muted-foreground transition-colors duration-100 hover:bg-foreground/6 hover:text-foreground focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-ring"
>
<LuX className="size-3.5" />
</button>
@@ -1238,8 +1253,8 @@ function ProfileInfoLayout({
className={cn(
"flex min-h-8 max-w-full items-center gap-2 rounded-md px-2 py-1.5 text-left text-xs transition-colors duration-100 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-ring",
active
? "bg-accent text-accent-foreground"
: "text-muted-foreground hover:bg-accent hover:text-accent-foreground",
? "bg-foreground/8 text-foreground"
: "text-muted-foreground hover:bg-foreground/5 hover:text-foreground",
)}
>
<span className="shrink-0">{it.icon}</span>
@@ -1258,20 +1273,6 @@ function ProfileInfoLayout({
</button>
);
})}
{deleteAction && (
<button
type="button"
data-slot="profile-info-delete"
onClick={deleteAction.onClick}
disabled={deleteAction.disabled}
className="flex min-h-8 items-center gap-2 rounded-md px-2 py-1.5 text-xs text-destructive-text transition-colors duration-100 hover:bg-destructive/10 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-ring disabled:pointer-events-none disabled:opacity-50 @[40rem]/profile-info:mt-2"
>
<LuTrash2 className="size-3.5 shrink-0" />
<span className="flex-1 text-left">
{t("profileInfo.sections.delete")}
</span>
</button>
)}
</nav>
{/* Main */}
@@ -1314,8 +1315,8 @@ function ProfileInfoLayout({
/>
{/* ID */}
<div className="flex items-center gap-2 rounded-md border border-border bg-muted/40 px-3 py-2">
<span className="shrink-0 text-[10px] tracking-wide text-muted-foreground uppercase">
<div className="flex items-center gap-2 rounded-lg bg-foreground/4 px-3 py-2">
<span className="shrink-0 text-xs font-medium text-muted-foreground">
{t("profiles.table.profileId")}
</span>
<span
@@ -1367,7 +1368,7 @@ function ProfileInfoLayout({
{/* Activity */}
<div className="mt-1 flex flex-col gap-1.5">
<span className="text-[10px] tracking-wide text-muted-foreground uppercase">
<span className="text-xs font-medium text-muted-foreground">
{t("profileInfo.sections.activity")}
</span>
<div className="grid grid-cols-2 gap-2">
@@ -1401,8 +1402,8 @@ function ProfileInfoLayout({
)}
{profile.created_by_email && (
<div className="rounded-md border border-border bg-muted/40 px-3 py-2">
<p className="text-[10px] tracking-wide text-muted-foreground uppercase">
<div className="rounded-lg bg-foreground/4 px-3 py-2">
<p className="text-xs font-medium text-muted-foreground">
{t("sync.team.title")}
</p>
<p className="mt-0.5 text-sm">
@@ -1500,7 +1501,7 @@ function ProfileInfoLayout({
{synchronizerAction && (
<Button
data-slot="profile-start-synchronizer"
variant="secondary"
variant="soft"
size="sm"
className="h-auto min-h-8 self-start whitespace-normal"
onClick={synchronizerAction.onClick}
@@ -1513,7 +1514,15 @@ function ProfileInfoLayout({
</div>
)}
{section === "transfer" && <ExportProfileSection profile={profile} />}
{section === "transfer" && (
<div className="flex flex-col gap-3">
<div className="flex items-center gap-2 text-sm font-semibold">
<LuDownload className="size-4" />
{t("profileInfo.sections.transfer")}
</div>
<ExportProfileSection profile={profile} />
</div>
)}
{section === "security" && (
<SecuritySectionInline
@@ -1534,7 +1543,7 @@ function ProfileInfoLayout({
)}
</div>
</div>
</>
</SoftFields>
);
}
@@ -1563,7 +1572,7 @@ function _SectionPlaceholder({
</div>
<p className="text-xs text-muted-foreground">{description}</p>
{hint && (
<div className="rounded-md border border-border bg-muted/40 px-3 py-2 text-xs">
<div className="rounded-lg bg-foreground/4 px-3 py-2 text-xs">
{hint}
</div>
)}
@@ -1831,8 +1840,8 @@ function SyncSectionInline({
<p className="text-xs text-muted-foreground">
{t("profileInfo.sectionDesc.sync")}
</p>
<div className="flex items-center gap-2">
<span className="shrink-0 text-[10px] tracking-wide text-muted-foreground uppercase">
<div className="flex flex-col gap-1.5">
<span className="text-xs font-medium text-muted-foreground">
{t("profileInfo.fields.syncMode")}
</span>
<Select
@@ -1842,7 +1851,7 @@ function SyncSectionInline({
void onChangeMode(v);
}}
>
<SelectTrigger className="h-7 min-w-0 flex-1 text-xs">
<SelectTrigger className="h-8 w-full text-xs">
<SelectValue />
</SelectTrigger>
<SelectContent>
@@ -1855,8 +1864,8 @@ function SyncSectionInline({
</Select>
</div>
{syncStatus && (
<div className="rounded-md border border-border bg-muted/40 px-3 py-2">
<p className="text-[10px] tracking-wide text-muted-foreground uppercase">
<div className="rounded-lg bg-foreground/4 px-3 py-2">
<p className="text-xs font-medium text-muted-foreground">
{t("profileInfo.fields.syncStatus")}
</p>
<p className="mt-0.5 text-sm">
@@ -1991,7 +2000,7 @@ function NetworkSectionInline({
</p>
<div className="flex items-center gap-2">
<span className="w-12 shrink-0 text-[10px] tracking-wide text-muted-foreground uppercase">
<span className="w-12 shrink-0 text-xs font-medium text-muted-foreground">
{t("profileInfo.fields.proxy")}
</span>
<Select
@@ -2001,7 +2010,7 @@ function NetworkSectionInline({
void onProxyChange(v);
}}
>
<SelectTrigger className="h-7 min-w-0 flex-1 text-xs">
<SelectTrigger className="h-8 min-w-0 flex-1 text-xs">
<SelectValue />
</SelectTrigger>
<SelectContent>
@@ -2019,7 +2028,8 @@ function NetworkSectionInline({
<Button
type="button"
variant="soft"
className="shrink-0"
size="sm"
className="h-8 shrink-0 gap-1.5 px-2.5 text-xs"
data-slot="profile-proxy-rotate"
title={t("proxies.rotation.actionTooltip")}
disabled={isSaving}
@@ -2032,7 +2042,7 @@ function NetworkSectionInline({
</div>
<div className="flex items-center gap-2">
<span className="w-12 shrink-0 text-[10px] tracking-wide text-muted-foreground uppercase">
<span className="w-12 shrink-0 text-xs font-medium text-muted-foreground">
{t("profileInfo.fields.vpn")}
</span>
<Select
@@ -2042,7 +2052,7 @@ function NetworkSectionInline({
void onVpnChange(v);
}}
>
<SelectTrigger className="h-7 min-w-0 flex-1 text-xs">
<SelectTrigger className="h-8 min-w-0 flex-1 text-xs">
<SelectValue />
</SelectTrigger>
<SelectContent>
@@ -2067,7 +2077,7 @@ function NetworkSectionInline({
>
<label
htmlFor={dnsServerId}
className="w-12 shrink-0 pt-2.5 text-[10px] tracking-wide text-muted-foreground uppercase"
className="w-12 shrink-0 pt-2.5 text-xs font-medium text-muted-foreground"
>
{t("profileInfo.fields.dns")}
</label>
@@ -2110,7 +2120,7 @@ function EphemeralSectionNotice({
t: (key: string, options?: Record<string, unknown>) => string;
}) {
return (
<div className="flex flex-col items-center gap-3 rounded-lg border p-6 text-center">
<div className="flex flex-col items-center gap-3 rounded-lg bg-foreground/4 p-6 text-center">
<LuTimer className="size-4 shrink-0 text-muted-foreground" />
<h3 className="text-sm font-medium text-foreground">{title}</h3>
<p className="max-w-[48ch] text-sm text-pretty text-muted-foreground">
@@ -2196,8 +2206,8 @@ function ExtensionsSectionInline({
<p className="text-xs text-muted-foreground">
{t("profileInfo.sectionDesc.extensions")}
</p>
<div className="flex items-center gap-2">
<span className="w-16 shrink-0 text-[10px] tracking-wide text-muted-foreground uppercase">
<div className="flex flex-col gap-1.5">
<span className="text-xs font-medium text-muted-foreground">
{t("profileInfo.fields.extensionGroup")}
</span>
<Select
@@ -2207,7 +2217,7 @@ function ExtensionsSectionInline({
void onChange(v);
}}
>
<SelectTrigger className="h-7 flex-1 text-xs">
<SelectTrigger className="h-8 w-full text-xs">
<SelectValue />
</SelectTrigger>
<SelectContent>
@@ -2327,7 +2337,7 @@ function CookiesSectionInline({
<DropdownMenu>
<DropdownMenuTrigger asChild>
<Button
variant="outline"
variant="soft"
size="sm"
className="h-7 gap-1.5"
disabled={
@@ -2361,7 +2371,7 @@ function CookiesSectionInline({
</DropdownMenu>
{onImportCookies && (
<Button
variant="outline"
variant="soft"
size="sm"
className="h-7 gap-1.5"
disabled={isDisabled || isRunning}
@@ -2373,7 +2383,7 @@ function CookiesSectionInline({
)}
{onCopyCookies && (
<Button
variant="outline"
variant="soft"
size="sm"
className="h-7 gap-1.5"
disabled={isDisabled}
@@ -2389,15 +2399,15 @@ function CookiesSectionInline({
{t("profileInfo.sectionDesc.cookies")}
</p>
{isRunning ? (
<div className="rounded-md border border-border bg-muted/40 px-3 py-2">
<div className="rounded-lg bg-foreground/4 px-3 py-2">
<p className="text-xs text-muted-foreground">
{t("profileInfo.cookies.runningNotice")}
</p>
</div>
) : (
<>
<div className="rounded-md border border-border bg-muted/40 px-3 py-2">
<p className="text-[10px] tracking-wide text-muted-foreground uppercase">
<div className="rounded-lg bg-foreground/4 px-3 py-2">
<p className="text-xs font-medium text-muted-foreground">
{t("profileInfo.fields.cookieCount")}
</p>
<p className="mt-0.5 text-sm">
@@ -2416,8 +2426,8 @@ function CookiesSectionInline({
/>
)}
{domains.length > 0 && (
<div className="flex min-h-0 flex-1 flex-col overflow-hidden rounded-md border border-border bg-muted/40">
<p className="shrink-0 border-b border-border px-3 py-2 text-[10px] tracking-wide text-muted-foreground uppercase">
<div className="flex min-h-0 flex-1 flex-col overflow-hidden rounded-lg bg-foreground/4">
<p className="shrink-0 border-b border-foreground/6 px-3 py-2 text-xs font-medium text-muted-foreground">
{t("profileInfo.cookies.domainsHeader", {
count: domains.length,
})}
@@ -2542,10 +2552,10 @@ function StorageStateBlock({
return (
<div
data-slot="profile-storage-state"
className="flex items-center justify-between gap-3 rounded-md border border-border bg-muted/40 px-3 py-2"
className="flex items-center justify-between gap-3 rounded-lg bg-foreground/4 px-3 py-2"
>
<div className="min-w-0">
<p className="text-[10px] tracking-wide text-muted-foreground uppercase">
<p className="text-xs font-medium text-muted-foreground">
{t("profileInfo.localStorage.title")}
</p>
<p className="mt-0.5 text-sm" data-slot="profile-local-storage-stats">
@@ -2582,7 +2592,7 @@ function StorageStateBlock({
</div>
<div className="flex shrink-0 items-center gap-2">
<Button
variant="outline"
variant="soft"
size="sm"
className="h-7 gap-1.5"
data-slot="storage-state-export"
@@ -2593,7 +2603,7 @@ function StorageStateBlock({
{t("common.buttons.export")}
</Button>
<Button
variant="outline"
variant="soft"
size="sm"
className="h-7 gap-1.5"
data-slot="storage-state-import"
@@ -2707,7 +2717,7 @@ function FingerprintSectionInline({
/>
) : (
<>
<div className="flex flex-col items-center gap-3 rounded-lg border p-6 text-center">
<div className="flex flex-col items-center gap-3 rounded-lg bg-foreground/4 p-6 text-center">
<LuLock className="size-4 shrink-0 text-muted-foreground" />
<h3 className="text-sm font-medium text-foreground">
{t("profileInfo.fingerprint.lockedTitle")}
@@ -2729,7 +2739,7 @@ function FingerprintSectionInline({
<p className="text-xs text-success-text">{success}</p>
)}
<div className="mt-3 flex items-center gap-2 border-t border-border pt-3">
<div className="mt-3 flex items-center gap-2 border-t border-foreground/6 pt-3">
<Button
size="sm"
className="h-7 text-xs"
@@ -2898,8 +2908,7 @@ function SecuritySectionInline({
setIsVerifyOpen(true);
}}
className={cn(
"min-h-7 flex-1 rounded-md border px-2 py-1 text-xs transition-colors",
"border-border text-muted-foreground hover:bg-accent hover:text-accent-foreground",
"h-8 flex-1 rounded-lg bg-foreground/5 px-2 text-xs text-muted-foreground transition-colors hover:bg-foreground/8 hover:text-foreground",
)}
>
{t("profilePassword.modes.validate")}
@@ -2911,10 +2920,10 @@ function SecuritySectionInline({
reset();
}}
className={cn(
"min-h-7 flex-1 rounded-md border px-2 py-1 text-xs transition-colors",
"h-8 flex-1 rounded-lg px-2 text-xs transition-colors",
mode === "change"
? "border-transparent bg-accent text-accent-foreground"
: "border-border text-muted-foreground hover:bg-accent hover:text-accent-foreground",
? "bg-foreground/10 text-foreground"
: "bg-foreground/5 text-muted-foreground hover:bg-foreground/8 hover:text-foreground",
)}
>
{t("profilePassword.modes.change")}
@@ -2926,10 +2935,10 @@ function SecuritySectionInline({
reset();
}}
className={cn(
"h-7 flex-1 rounded-md border px-2 text-xs transition-colors",
"h-8 flex-1 rounded-lg px-2 text-xs transition-colors",
mode === "remove"
? "border-transparent bg-destructive/10 text-destructive-text"
: "border-border text-muted-foreground hover:bg-accent hover:text-accent-foreground",
? "bg-destructive/10 text-destructive-text"
: "bg-foreground/5 text-muted-foreground hover:bg-foreground/8 hover:text-foreground",
)}
>
{t("profilePassword.modes.remove")}
+1 -1
View File
@@ -90,7 +90,7 @@ export function ProfileMetadataCard({
type="button"
disabled={disabled}
data-slot={`profile-edit-${field}`}
className="min-w-0 rounded-md bg-muted/50 px-3 py-2.5 text-left transition-colors hover:bg-accent focus-visible:outline-2 focus-visible:outline-ring disabled:opacity-50"
className="min-w-0 rounded-lg bg-foreground/4 px-3 py-2.5 text-left transition-colors hover:bg-foreground/7 focus-visible:outline-2 focus-visible:outline-ring disabled:opacity-50"
>
<span className="block text-xs text-muted-foreground">{label}</span>
<span className="mt-0.5 block break-words text-sm">
+9 -4
View File
@@ -4,6 +4,7 @@ import { invoke } from "@tauri-apps/api/core";
import { open, save } from "@tauri-apps/plugin-dialog";
import { useState } from "react";
import { useTranslation } from "react-i18next";
import { LuDownload } from "react-icons/lu";
import { LoadingButton } from "@/components/loading-button";
import { Checkbox } from "@/components/ui/checkbox";
import { Label } from "@/components/ui/label";
@@ -80,8 +81,8 @@ export function ExportProfileSection({ profile }: { profile: BrowserProfile }) {
};
return (
<div className="space-y-3">
<p className="text-sm text-muted-foreground">
<div className="flex flex-col gap-3">
<p className="text-xs text-muted-foreground">
{t("profileTransfer.exportDescription")}
</p>
<div className="flex items-center gap-x-2">
@@ -98,22 +99,26 @@ export function ExportProfileSection({ profile }: { profile: BrowserProfile }) {
</Label>
</div>
{profile.password_protected && (
<p className="text-sm text-muted-foreground">
<p className="text-xs text-muted-foreground">
{t("profileTransfer.protectedNotice")}
</p>
)}
{isRunning && (
<p className="text-sm text-warning-text">
<p className="text-xs text-warning-text">
{t("profileTransfer.runningNotice")}
</p>
)}
<LoadingButton
variant="soft"
size="sm"
className="h-8 gap-1.5 self-start rounded-lg px-2.5 text-xs"
isLoading={isExporting}
disabled={isRunning}
onClick={() => {
void handleExport();
}}
>
<LuDownload className="size-3.5" />
{t("profileTransfer.exportButton")}
</LoadingButton>
</div>
+2 -2
View File
@@ -82,11 +82,11 @@ export function RestorePoints({
return (
<div
className="rounded-md border border-border px-3 py-2"
className="rounded-lg bg-foreground/4 px-3 py-2"
data-slot="restore-points"
>
<div className="flex items-center justify-between gap-2">
<p className="text-[10px] tracking-wide text-muted-foreground uppercase">
<p className="text-xs font-medium text-muted-foreground">
{t("restorePoints.title")}
</p>
<Button
+265 -254
View File
@@ -15,6 +15,7 @@ import {
DialogHeader,
DialogTitle,
} from "@/components/ui/dialog";
import { SoftFields } from "@/components/ui/field-variant";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import { ProBadge } from "@/components/ui/pro-badge";
@@ -510,8 +511,9 @@ export function WayfernConfigForm({
isLoading={isGeneratingFingerprint}
onClick={handleRegenerateClick}
disabled={readOnly}
variant="outline"
variant="soft"
size="sm"
className="h-8 rounded-lg px-3 text-xs"
>
{isCreating
? t("fingerprint.generateFingerprint")
@@ -641,7 +643,7 @@ export function WayfernConfigForm({
<Label>{t("fingerprint.cameraLabel")}</Label>
<div className="flex flex-wrap items-center gap-2">
<RippleButton
variant="outline"
variant="soft"
size="sm"
disabled={readOnly}
onClick={() => {
@@ -1583,271 +1585,280 @@ export function WayfernConfigForm({
);
return (
<div className={`@container space-y-6 ${className}`}>
{/* Rendered outside the tabs so the confirmation survives whichever
<SoftFields>
<div className={`@container space-y-6 ${className}`}>
{/* Rendered outside the tabs so the confirmation survives whichever
panel the button was pressed from. */}
<Dialog
open={isRegenerateConfirmOpen}
onOpenChange={setIsRegenerateConfirmOpen}
>
<DialogContent className="sm:max-w-md">
<DialogHeader>
<DialogTitle>{t("fingerprint.regenerateConfirmTitle")}</DialogTitle>
<DialogDescription>
{t("fingerprint.regenerateConfirmDescription")}
</DialogDescription>
</DialogHeader>
<DialogFooter>
<RippleButton
variant="outline"
onClick={() => {
setIsRegenerateConfirmOpen(false);
}}
>
{t("common.buttons.cancel")}
</RippleButton>
<RippleButton
variant="destructive"
onClick={handleConfirmRegenerate}
>
{t("fingerprint.regenerateFingerprint")}
</RippleButton>
</DialogFooter>
</DialogContent>
</Dialog>
{forceAdvanced ? (
renderAdvancedForm()
) : (
<Tabs
value={activeTab}
onValueChange={readOnly ? undefined : setActiveTab}
className="w-full"
<Dialog
open={isRegenerateConfirmOpen}
onOpenChange={setIsRegenerateConfirmOpen}
>
<TabsList className="grid w-full grid-cols-2">
<TabsTrigger value="automatic" disabled={readOnly}>
{t("fingerprint.automatic")}
</TabsTrigger>
<TabsTrigger value="manual" disabled={readOnly}>
{t("fingerprint.manual")}
</TabsTrigger>
</TabsList>
<TabsContent value="automatic" className="space-y-6">
{/* Operating System Selection */}
<div className="mt-4 space-y-3">
<Label>{t("fingerprint.osLabel")}</Label>
<Select
value={selectedOS}
onValueChange={(value: WayfernOS) => {
onConfigChange("os", value);
<DialogContent className="sm:max-w-md">
<DialogHeader>
<DialogTitle>
{t("fingerprint.regenerateConfirmTitle")}
</DialogTitle>
<DialogDescription>
{t("fingerprint.regenerateConfirmDescription")}
</DialogDescription>
</DialogHeader>
<DialogFooter>
<RippleButton
variant="soft"
onClick={() => {
setIsRegenerateConfirmOpen(false);
}}
disabled={readOnly}
>
<SelectTrigger>
<SelectValue
placeholder={t("fingerprint.selectOSPlaceholder")}
/>
</SelectTrigger>
<SelectContent>
{(
[
"windows",
"macos",
"linux",
"android",
"ios",
] as WayfernOS[]
).map((os) => {
const isDisabled = os !== currentOS && !crossOsUnlocked;
return (
<SelectItem key={os} value={os} disabled={isDisabled}>
<span className="flex items-center gap-2">
{osLabels[os]}
{isDisabled && <ProBadge />}
</span>
</SelectItem>
);
})}
</SelectContent>
</Select>
{selectedOS !== currentOS && crossOsUnlocked && (
<Alert className="mt-2">
<AlertDescription>
{t("fingerprint.crossOsLimitations")}
</AlertDescription>
</Alert>
)}
</div>
{t("common.buttons.cancel")}
</RippleButton>
<RippleButton
variant="destructive"
onClick={handleConfirmRegenerate}
>
{t("fingerprint.regenerateFingerprint")}
</RippleButton>
</DialogFooter>
</DialogContent>
</Dialog>
{forceAdvanced ? (
renderAdvancedForm()
) : (
<Tabs
value={activeTab}
onValueChange={readOnly ? undefined : setActiveTab}
className="w-full"
>
<TabsList className="grid w-full grid-cols-2">
<TabsTrigger value="automatic" disabled={readOnly}>
{t("fingerprint.automatic")}
</TabsTrigger>
<TabsTrigger value="manual" disabled={readOnly}>
{t("fingerprint.manual")}
</TabsTrigger>
</TabsList>
{/* Randomize Fingerprint Option */}
<div className="space-y-3 rounded-lg bg-foreground/4 p-4">
<div className="flex items-center gap-x-2">
<Checkbox
id="randomize-fingerprint-auto"
checked={config.randomize_fingerprint_on_launch ?? false}
onCheckedChange={(checked) => {
onConfigChange("randomize_fingerprint_on_launch", checked);
<TabsContent value="automatic" className="space-y-6">
{/* Operating System Selection */}
<div className="mt-4 space-y-3">
<Label>{t("fingerprint.osLabel")}</Label>
<Select
value={selectedOS}
onValueChange={(value: WayfernOS) => {
onConfigChange("os", value);
}}
disabled={readOnly}
/>
<Label
htmlFor="randomize-fingerprint-auto"
className="font-medium"
>
{t("fingerprint.generateRandomOnLaunch")}
</Label>
<SelectTrigger>
<SelectValue
placeholder={t("fingerprint.selectOSPlaceholder")}
/>
</SelectTrigger>
<SelectContent>
{(
[
"windows",
"macos",
"linux",
"android",
"ios",
] as WayfernOS[]
).map((os) => {
const isDisabled = os !== currentOS && !crossOsUnlocked;
return (
<SelectItem key={os} value={os} disabled={isDisabled}>
<span className="flex items-center gap-2">
{osLabels[os]}
{isDisabled && <ProBadge />}
</span>
</SelectItem>
);
})}
</SelectContent>
</Select>
{selectedOS !== currentOS && crossOsUnlocked && (
<Alert className="mt-2">
<AlertDescription>
{t("fingerprint.crossOsLimitations")}
</AlertDescription>
</Alert>
)}
</div>
<p className="ml-6 text-sm text-muted-foreground">
{t("fingerprint.generateRandomDescription")}
</p>
</div>
<SessionRestoreOption
checked={config.restore_session ?? true}
onChange={(checked) => {
onConfigChange("restore_session", checked);
}}
readOnly={readOnly}
/>
{/* Automatic Location Configuration */}
<div className="space-y-3">
<div className="flex items-center gap-x-2">
<Checkbox
id="auto-location"
checked={isAutoLocationEnabled}
onCheckedChange={handleAutoLocationToggle}
disabled={isEditingDisabled}
/>
<Label htmlFor="auto-location">
{t("fingerprint.autoLocationDescription")}
</Label>
</div>
</div>
{/* Screen Resolution */}
<div
className={
limitedMode ? "relative overflow-hidden rounded-lg" : undefined
}
>
<fieldset
disabled={isEditingDisabled || limitedMode}
className="space-y-3"
>
<Label>{t("fingerprint.screenResolution")}</Label>
<div className="grid grid-cols-1 gap-4 @md:grid-cols-2">
<div className="space-y-2">
<Label htmlFor="screen-max-width">
{t("fingerprint.maxWidth")}
</Label>
<Input
id="screen-max-width"
type="number"
value={config.screen_max_width ?? ""}
onChange={(e) => {
onConfigChange(
"screen_max_width",
e.target.value
? parseInt(e.target.value, 10)
: undefined,
);
}}
placeholder={t("common.placeholders.example", {
value: "1920",
})}
/>
</div>
<div className="space-y-2">
<Label htmlFor="screen-max-height">
{t("fingerprint.maxHeight")}
</Label>
<Input
id="screen-max-height"
type="number"
value={config.screen_max_height ?? ""}
onChange={(e) => {
onConfigChange(
"screen_max_height",
e.target.value
? parseInt(e.target.value, 10)
: undefined,
);
}}
placeholder={t("common.placeholders.example", {
value: "1080",
})}
/>
</div>
<div className="space-y-2">
<Label htmlFor="screen-min-width">
{t("fingerprint.minWidth")}
</Label>
<Input
id="screen-min-width"
type="number"
value={config.screen_min_width ?? ""}
onChange={(e) => {
onConfigChange(
"screen_min_width",
e.target.value
? parseInt(e.target.value, 10)
: undefined,
);
}}
placeholder={t("common.placeholders.example", {
value: "800",
})}
/>
</div>
<div className="space-y-2">
<Label htmlFor="screen-min-height">
{t("fingerprint.minHeight")}
</Label>
<Input
id="screen-min-height"
type="number"
value={config.screen_min_height ?? ""}
onChange={(e) => {
onConfigChange(
"screen_min_height",
e.target.value
? parseInt(e.target.value, 10)
: undefined,
);
}}
placeholder={t("common.placeholders.example", {
value: "600",
})}
/>
</div>
{/* Randomize Fingerprint Option */}
<div className="space-y-3 rounded-lg bg-foreground/4 p-4">
<div className="flex items-center gap-x-2">
<Checkbox
id="randomize-fingerprint-auto"
checked={config.randomize_fingerprint_on_launch ?? false}
onCheckedChange={(checked) => {
onConfigChange(
"randomize_fingerprint_on_launch",
checked,
);
}}
disabled={readOnly}
/>
<Label
htmlFor="randomize-fingerprint-auto"
className="font-medium"
>
{t("fingerprint.generateRandomOnLaunch")}
</Label>
</div>
</fieldset>
{limitedMode && (
<>
<div className="absolute inset-0 z-1 bg-background/30 backdrop-blur-[6px]" />
<div className="absolute inset-y-0 left-0 z-2 w-6 bg-linear-to-r from-background to-transparent" />
<div className="absolute inset-y-0 right-0 z-2 w-6 bg-linear-to-l from-background to-transparent" />
<div className="absolute inset-x-0 top-0 z-2 h-6 bg-linear-to-b from-background to-transparent" />
<div className="absolute inset-x-0 bottom-0 z-2 h-6 bg-linear-to-t from-background to-transparent" />
<div className="absolute inset-0 z-3 flex items-center justify-center">
<div className="flex items-center gap-2 rounded-md bg-background/80 px-3 py-1.5">
<ProBadge />
<span className="text-sm font-medium text-muted-foreground">
{t("fingerprint.proFeature")}
</span>
<p className="ml-6 text-sm text-muted-foreground">
{t("fingerprint.generateRandomDescription")}
</p>
</div>
<SessionRestoreOption
checked={config.restore_session ?? true}
onChange={(checked) => {
onConfigChange("restore_session", checked);
}}
readOnly={readOnly}
/>
{/* Automatic Location Configuration */}
<div className="space-y-3">
<div className="flex items-center gap-x-2">
<Checkbox
id="auto-location"
checked={isAutoLocationEnabled}
onCheckedChange={handleAutoLocationToggle}
disabled={isEditingDisabled}
/>
<Label htmlFor="auto-location">
{t("fingerprint.autoLocationDescription")}
</Label>
</div>
</div>
{/* Screen Resolution */}
<div
className={
limitedMode
? "relative overflow-hidden rounded-lg"
: undefined
}
>
<fieldset
disabled={isEditingDisabled || limitedMode}
className="space-y-3"
>
<Label>{t("fingerprint.screenResolution")}</Label>
<div className="grid grid-cols-1 gap-4 @md:grid-cols-2">
<div className="space-y-2">
<Label htmlFor="screen-max-width">
{t("fingerprint.maxWidth")}
</Label>
<Input
id="screen-max-width"
type="number"
value={config.screen_max_width ?? ""}
onChange={(e) => {
onConfigChange(
"screen_max_width",
e.target.value
? parseInt(e.target.value, 10)
: undefined,
);
}}
placeholder={t("common.placeholders.example", {
value: "1920",
})}
/>
</div>
<div className="space-y-2">
<Label htmlFor="screen-max-height">
{t("fingerprint.maxHeight")}
</Label>
<Input
id="screen-max-height"
type="number"
value={config.screen_max_height ?? ""}
onChange={(e) => {
onConfigChange(
"screen_max_height",
e.target.value
? parseInt(e.target.value, 10)
: undefined,
);
}}
placeholder={t("common.placeholders.example", {
value: "1080",
})}
/>
</div>
<div className="space-y-2">
<Label htmlFor="screen-min-width">
{t("fingerprint.minWidth")}
</Label>
<Input
id="screen-min-width"
type="number"
value={config.screen_min_width ?? ""}
onChange={(e) => {
onConfigChange(
"screen_min_width",
e.target.value
? parseInt(e.target.value, 10)
: undefined,
);
}}
placeholder={t("common.placeholders.example", {
value: "800",
})}
/>
</div>
<div className="space-y-2">
<Label htmlFor="screen-min-height">
{t("fingerprint.minHeight")}
</Label>
<Input
id="screen-min-height"
type="number"
value={config.screen_min_height ?? ""}
onChange={(e) => {
onConfigChange(
"screen_min_height",
e.target.value
? parseInt(e.target.value, 10)
: undefined,
);
}}
placeholder={t("common.placeholders.example", {
value: "600",
})}
/>
</div>
</div>
</>
)}
</div>
</TabsContent>
</fieldset>
{limitedMode && (
<>
<div className="absolute inset-0 z-1 bg-background/30 backdrop-blur-[6px]" />
<div className="absolute inset-y-0 left-0 z-2 w-6 bg-linear-to-r from-background to-transparent" />
<div className="absolute inset-y-0 right-0 z-2 w-6 bg-linear-to-l from-background to-transparent" />
<div className="absolute inset-x-0 top-0 z-2 h-6 bg-linear-to-b from-background to-transparent" />
<div className="absolute inset-x-0 bottom-0 z-2 h-6 bg-linear-to-t from-background to-transparent" />
<div className="absolute inset-0 z-3 flex items-center justify-center">
<div className="flex items-center gap-2 rounded-md bg-background/80 px-3 py-1.5">
<ProBadge />
<span className="text-sm font-medium text-muted-foreground">
{t("fingerprint.proFeature")}
</span>
</div>
</div>
</>
)}
</div>
</TabsContent>
<TabsContent value="manual" className="space-y-6">
{renderAdvancedForm()}
</TabsContent>
</Tabs>
)}
</div>
<TabsContent value="manual" className="space-y-6">
{renderAdvancedForm()}
</TabsContent>
</Tabs>
)}
</div>
</SoftFields>
);
}
+2 -2
View File
@@ -1508,7 +1508,7 @@
"extensionGroup": "Erweiterungsgruppe",
"totalSessions": "Sitzungen insgesamt",
"syncMode": "Sync-Modus",
"proxy": "PROXY",
"proxy": "Proxy",
"vpn": "VPN",
"cookieCount": "Gespeicherte Cookies",
"localDataTransfer": "Lokale Datenübertragung",
@@ -1576,7 +1576,7 @@
"sectionDesc": {
"fingerprint": "Legen Sie fest, wie dieses Profil für Fingerprinting-Skripte erscheint.",
"network": "Verwalten Sie den Proxy oder das VPN, über das dieses Profil ins Internet geht, und den DNS-Server, mit dem es Namen auflöst.",
"cookies": "Cookies für dieses Profil importieren, kopieren oder löschen.",
"cookies": "Cookies dieses Profils importieren, exportieren oder kopieren.",
"extensions": "Legen Sie fest, welche Erweiterungen beim Start dieses Profils geladen werden.",
"sync": "Legen Sie fest, wie dieses Profil auf Ihre anderen Geräte gespiegelt wird.",
"automation": "Bei jedem Start dieses Profils einen Befehl oder ein Skript ausführen.",
+7 -7
View File
@@ -1336,7 +1336,7 @@
"fingerprint": {
"crossOsWarning": "Spoofing fingerprint for a different operating system is less reliable because it is impossible to perfectly mimic all underlying components. Use with caution.",
"crossOsLimitations": "Cross-OS fingerprinting has limitations. System-level APIs may still reflect your actual operating system, and some features may have degraded performance.",
"osLabel": "Operating System Fingerprint",
"osLabel": "Operating system fingerprint",
"selectOSPlaceholder": "Select operating system",
"generateRandomOnLaunch": "Generate random fingerprint on every launch",
"generateRandomDescription": "When enabled, a new fingerprint will be generated each time the browser is launched.",
@@ -1450,7 +1450,7 @@
"brandVersion": "Brand Version",
"proFeature": "This is a Pro feature",
"generateFingerprint": "Generate Fingerprint",
"regenerateFingerprint": "Regenerate Fingerprint",
"regenerateFingerprint": "Regenerate fingerprint",
"regenerateConfirmTitle": "Regenerate this fingerprint?",
"regenerateConfirmDescription": "The profile keeps its cookies and logins but will present a different device. Sites that already know this profile can ask you to sign in again, challenge you, or block the account. Only regenerate a profile you have not used yet, or one you are willing to lose. This cannot be undone.",
"canvasNoiseSeedPlaceholder": "Enter a seed string for canvas fingerprint",
@@ -1501,14 +1501,14 @@
"group": "Group",
"tags": "Tags",
"note": "Note",
"syncStatus": "Sync Status",
"lastLaunched": "Last Launched",
"syncStatus": "Sync status",
"lastLaunched": "Last launched",
"hostOs": "Host OS",
"ephemeral": "Ephemeral",
"extensionGroup": "Extension Group",
"extensionGroup": "Extension group",
"totalSessions": "Total sessions",
"syncMode": "Sync mode",
"proxy": "PROXY",
"proxy": "Proxy",
"vpn": "VPN",
"cookieCount": "Cookies stored",
"localDataTransfer": "Local data transfer",
@@ -1576,7 +1576,7 @@
"sectionDesc": {
"fingerprint": "Configure how this profile appears to fingerprinting scripts.",
"network": "Manage the proxy or VPN this profile uses to reach the internet, and the DNS server it resolves names with.",
"cookies": "Import, copy, or wipe cookies for this profile.",
"cookies": "Import, export or copy this profile's cookies.",
"extensions": "Choose which extensions load when this profile launches.",
"sync": "Configure how this profile is mirrored to your other devices.",
"automation": "Run a command or script every time this profile launches.",
+6 -6
View File
@@ -1461,7 +1461,7 @@
"brandVersion": "Versión de marca",
"proFeature": "Esta es una función Pro",
"generateFingerprint": "Generar Huella Digital",
"regenerateFingerprint": "Regenerar Huella Digital",
"regenerateFingerprint": "Regenerar huella digital",
"regenerateConfirmTitle": "¿Regenerar esta huella digital?",
"regenerateConfirmDescription": "El perfil conserva sus cookies y sesiones, pero mostrará un dispositivo distinto. Los sitios que ya conocen este perfil pueden pedirte iniciar sesión de nuevo, someterte a una verificación o bloquear la cuenta. Regenera solo un perfil que aún no hayas usado o que estés dispuesto a perder. Esta acción no se puede deshacer.",
"canvasNoiseSeedPlaceholder": "Introduce una semilla para la huella digital del canvas",
@@ -1512,14 +1512,14 @@
"group": "Grupo",
"tags": "Etiquetas",
"note": "Nota",
"syncStatus": "Estado de Sincronización",
"lastLaunched": "Último Lanzamiento",
"syncStatus": "Estado de sincronización",
"lastLaunched": "Último lanzamiento",
"hostOs": "SO Host",
"ephemeral": "Efímero",
"extensionGroup": "Grupo de Extensiones",
"extensionGroup": "Grupo de extensiones",
"totalSessions": "Sesiones totales",
"syncMode": "Modo de sinc.",
"proxy": "PROXY",
"proxy": "Proxy",
"vpn": "VPN",
"cookieCount": "Cookies guardadas",
"localDataTransfer": "Transferencia de datos local",
@@ -1587,7 +1587,7 @@
"sectionDesc": {
"fingerprint": "Configura cómo aparece este perfil para los scripts de fingerprinting.",
"network": "Administra el proxy o la VPN que usa este perfil y el servidor DNS con el que resuelve los nombres.",
"cookies": "Importa, copia o borra cookies de este perfil.",
"cookies": "Importa, exporta o copia las cookies de este perfil.",
"extensions": "Elige las extensiones que se cargan con este perfil.",
"sync": "Configura cómo se replica este perfil entre tus dispositivos.",
"automation": "Ejecuta un comando o script al iniciar este perfil.",
+5 -5
View File
@@ -1512,14 +1512,14 @@
"group": "Groupe",
"tags": "Tags",
"note": "Note",
"syncStatus": "État de Synchronisation",
"lastLaunched": "Dernier Lancement",
"syncStatus": "État de synchronisation",
"lastLaunched": "Dernier lancement",
"hostOs": "OS Hôte",
"ephemeral": "Éphémère",
"extensionGroup": "Groupe d'Extensions",
"extensionGroup": "Groupe d'extensions",
"totalSessions": "Sessions totales",
"syncMode": "Mode de sync.",
"proxy": "PROXY",
"proxy": "Proxy",
"vpn": "VPN",
"cookieCount": "Cookies stockés",
"localDataTransfer": "Transfert de données local",
@@ -1587,7 +1587,7 @@
"sectionDesc": {
"fingerprint": "Configurez l’apparence de ce profil pour les scripts de fingerprinting.",
"network": "Gérez le proxy ou le VPN utilisé par ce profil, ainsi que le serveur DNS qui résout ses noms.",
"cookies": "Importer, copier ou effacer les cookies de ce profil.",
"cookies": "Importer, exporter ou copier les cookies de ce profil.",
"extensions": "Choisissez les extensions à charger avec ce profil.",
"sync": "Configurez la réplication de ce profil entre vos appareils.",
"automation": "Exécutez une commande au lancement de ce profil.",
+1 -1
View File
@@ -1576,7 +1576,7 @@
"sectionDesc": {
"fingerprint": "フィンガープリント対策スクリプトに対するこのプロファイルの表示を設定します。",
"network": "このプロファイルが使用するプロキシまたは VPN と、名前解決に使う DNS サーバーを管理します。",
"cookies": "このプロファイルの Cookie をインポート、コピー、消去します。",
"cookies": "このプロファイルの Cookie をインポート、エクスポート、コピーします。",
"extensions": "このプロファイル起動時に読み込む拡張機能を選択します。",
"sync": "他のデバイス間でのこのプロファイルの同期方法を設定します。",
"automation": "このプロファイル起動時に実行するコマンドを設定します。",
+1 -1
View File
@@ -1576,7 +1576,7 @@
"sectionDesc": {
"fingerprint": "이 프로필이 핑거프린팅 스크립트에 어떻게 표시되는지 구성합니다.",
"network": "이 프로필이 인터넷에 도달하는 데 사용하는 프록시 또는 VPN과 이름 확인에 사용하는 DNS 서버를 관리합니다.",
"cookies": "이 프로필의 쿠키를 가져오거나, 복사하거나, 지웁니다.",
"cookies": "이 프로필의 쿠키를 가져오거나, 내보내거나, 복사합니다.",
"extensions": "이 프로필이 실행될 때 어떤 확장 프로그램이 로드될지 선택합니다.",
"sync": "이 프로필이 다른 기기에 어떻게 미러링되는지 구성합니다.",
"automation": "이 프로필이 실행될 때마다 명령 또는 스크립트를 실행합니다.",
+7 -7
View File
@@ -1347,7 +1347,7 @@
"fingerprint": {
"crossOsWarning": "A falsificação de impressão digital para um sistema operacional diferente é menos confiável porque é impossível imitar perfeitamente todos os componentes subjacentes. Use com cautela.",
"crossOsLimitations": "A impressão digital entre sistemas operacionais tem limitações. APIs de nível de sistema ainda podem refletir seu sistema operacional real, e alguns recursos podem ter desempenho reduzido.",
"osLabel": "Impressão Digital do Sistema Operacional",
"osLabel": "Impressão digital do sistema operacional",
"selectOSPlaceholder": "Selecionar sistema operacional",
"generateRandomOnLaunch": "Gerar impressão digital aleatória a cada inicialização",
"generateRandomDescription": "Quando ativado, uma nova impressão digital será gerada cada vez que o navegador for iniciado.",
@@ -1461,7 +1461,7 @@
"brandVersion": "Versão da Marca",
"proFeature": "Este é um recurso Pro",
"generateFingerprint": "Gerar Impressão Digital",
"regenerateFingerprint": "Regenerar Impressão Digital",
"regenerateFingerprint": "Regenerar impressão digital",
"regenerateConfirmTitle": "Regenerar esta impressão digital?",
"regenerateConfirmDescription": "O perfil mantém os cookies e as sessões, mas passará a apresentar um dispositivo diferente. Sites que já conhecem este perfil podem pedir que você entre novamente, aplicar uma verificação ou bloquear a conta. Só regenere um perfil que ainda não usou ou que esteja disposto a perder. Esta ação não pode ser desfeita.",
"canvasNoiseSeedPlaceholder": "Insira uma string seed para a impressão digital do canvas",
@@ -1512,14 +1512,14 @@
"group": "Grupo",
"tags": "Tags",
"note": "Nota",
"syncStatus": "Status de Sincronização",
"lastLaunched": "Último Lançamento",
"syncStatus": "Status de sincronização",
"lastLaunched": "Último lançamento",
"hostOs": "SO Host",
"ephemeral": "Efêmero",
"extensionGroup": "Grupo de Extensões",
"extensionGroup": "Grupo de extensões",
"totalSessions": "Sessões totais",
"syncMode": "Modo de sinc.",
"proxy": "PROXY",
"proxy": "Proxy",
"vpn": "VPN",
"cookieCount": "Cookies armazenados",
"localDataTransfer": "Transferência de dados local",
@@ -1587,7 +1587,7 @@
"sectionDesc": {
"fingerprint": "Configure como este perfil aparece para scripts de fingerprinting.",
"network": "Gerencie o proxy ou VPN usado por este perfil e o servidor DNS com que ele resolve nomes.",
"cookies": "Importe, copie ou apague cookies deste perfil.",
"cookies": "Importe, exporte ou copie os cookies deste perfil.",
"extensions": "Escolha quais extensões carregar com este perfil.",
"sync": "Configure como este perfil é espelhado entre seus dispositivos.",
"automation": "Execute um comando ao iniciar este perfil.",
+2 -2
View File
@@ -1530,7 +1530,7 @@
"extensionGroup": "Группа расширений",
"totalSessions": "Всего сессий",
"syncMode": "Режим синх.",
"proxy": "ПРОКСИ",
"proxy": "Прокси",
"vpn": "VPN",
"cookieCount": "Хранится Cookie",
"localDataTransfer": "Локальный трафик",
@@ -1598,7 +1598,7 @@
"sectionDesc": {
"fingerprint": "Настройте, как этот профиль выглядит для скриптов отпечатков.",
"network": "Управляйте прокси или VPN, используемым этим профилем, и DNS-сервером, через который он разрешает имена.",
"cookies": "Импортируйте, копируйте или удаляйте cookie этого профиля.",
"cookies": "Импортируйте, экспортируйте или копируйте cookie этого профиля.",
"extensions": "Выберите, какие расширения загружать с этим профилем.",
"sync": "Настройте репликацию этого профиля между устройствами.",
"automation": "Запускайте команду при старте этого профиля.",
+7 -7
View File
@@ -1336,7 +1336,7 @@
"fingerprint": {
"crossOsWarning": "Farklı bir işletim sistemi için parmak izi taklidi daha az güvenilirdir; çünkü altta yatan tüm bileşenleri kusursuz biçimde taklit etmek imkânsızdır. Dikkatli kullanın.",
"crossOsLimitations": "İşletim sistemleri arası parmak izi taklidinin sınırlamaları vardır. Sistem düzeyindeki API'ler yine de gerçek işletim sisteminizi yansıtabilir ve bazı özelliklerin performansı düşebilir.",
"osLabel": "İşletim Sistemi Parmak İzi",
"osLabel": "İşletim sistemi parmak izi",
"selectOSPlaceholder": "İşletim sistemi seçin",
"generateRandomOnLaunch": "Her başlatmada rastgele parmak izi oluştur",
"generateRandomDescription": "Etkinleştirildiğinde, tarayıcı her başlatıldığında yeni bir parmak izi oluşturulur.",
@@ -1450,7 +1450,7 @@
"brandVersion": "Marka Sürümü",
"proFeature": "Bu bir Pro özelliğidir",
"generateFingerprint": "Parmak İzi Oluştur",
"regenerateFingerprint": "Parmak İzini Yeniden Oluştur",
"regenerateFingerprint": "Parmak izini yeniden oluştur",
"regenerateConfirmTitle": "Bu parmak izi yeniden oluşturulsun mu?",
"regenerateConfirmDescription": "Profil çerezlerini ve oturumlarını korur, ancak farklı bir cihaz olarak görünür. Bu profili zaten tanıyan siteler yeniden giriş yapmanızı isteyebilir, doğrulama uygulayabilir veya hesabı engelleyebilir. Yalnızca henüz kullanmadığınız ya da kaybetmeyi göze aldığınız bir profili yeniden oluşturun. Bu işlem geri alınamaz.",
"canvasNoiseSeedPlaceholder": "Canvas parmak izi için bir tohum dizesi girin",
@@ -1501,14 +1501,14 @@
"group": "Grup",
"tags": "Etiketler",
"note": "Not",
"syncStatus": "Eşitleme Durumu",
"lastLaunched": "Son Başlatma",
"syncStatus": "Eşitleme durumu",
"lastLaunched": "Son başlatma",
"hostOs": "Ana İşletim Sistemi",
"ephemeral": "Geçici",
"extensionGroup": "Uzantı Grubu",
"extensionGroup": "Uzantı grubu",
"totalSessions": "Toplam oturum",
"syncMode": "Eşitleme modu",
"proxy": "PROXY",
"proxy": "Proxy",
"vpn": "VPN",
"cookieCount": "Saklanan çerezler",
"localDataTransfer": "Yerel veri aktarımı",
@@ -1576,7 +1576,7 @@
"sectionDesc": {
"fingerprint": "Bu profilin parmak izi tarama betiklerine nasıl görüneceğini yapılandırın.",
"network": "Bu profilin internete erişmek için kullandığı proxy veya VPN'i ve adları çözümlediği DNS sunucusunu yönetin.",
"cookies": "Bu profil için çerezleri içe aktarın, kopyalayın veya silin.",
"cookies": "Bu profilin çerezlerini içe aktarın, dışa aktarın veya kopyalayın.",
"extensions": "Bu profil başlatıldığında hangi uzantıların yükleneceğini seçin.",
"sync": "Bu profilin diğer cihazlarınıza nasıl yansıtılacağını yapılandırın.",
"automation": "Bu profil her başlatıldığında bir komut veya betik çalıştırın.",
+2 -2
View File
@@ -1508,7 +1508,7 @@
"extensionGroup": "Nhóm tiện ích",
"totalSessions": "Tổng số phiên",
"syncMode": "Chế độ đồng bộ",
"proxy": "PROXY",
"proxy": "Proxy",
"vpn": "VPN",
"cookieCount": "Cookie đã lưu",
"localDataTransfer": "Truyền dữ liệu cục bộ",
@@ -1576,7 +1576,7 @@
"sectionDesc": {
"fingerprint": "Cấu hình cách profile này hiển thị với các script vân tay.",
"network": "Quản lý proxy hoặc VPN mà profile này sử dụng để truy cập internet và máy chủ DNS dùng để phân giải tên miền.",
"cookies": "Nhập, sao chép hoặc xóa cookie cho profile này.",
"cookies": "Nhập, xuất hoặc sao chép cookie của profile này.",
"extensions": "Chọn tiện ích nào được tải khi profile này khởi chạy.",
"sync": "Cấu hình cách profile này được phản chiếu sang các thiết bị khác của bạn.",
"automation": "Chạy lệnh hoặc script mỗi khi profile này khởi chạy.",
+1 -1
View File
@@ -1576,7 +1576,7 @@
"sectionDesc": {
"fingerprint": "配置此配置文件如何对指纹脚本显示。",
"network": "管理此配置文件使用的代理或 VPN,以及用于解析域名的 DNS 服务器。",
"cookies": "导入、复制或清除此配置文件的 Cookie。",
"cookies": "导入、导出或复制此配置文件的 Cookie。",
"extensions": "选择启动此配置文件时加载的扩展。",
"sync": "配置此配置文件如何在设备间同步。",
"automation": "在启动此配置文件时运行命令。",