The reunion is complete: one build contains both UIs and picks between them at bootstrap. - src/shared/types.ts regains `skin: "modern" | "win7"` on AppSettings. - SettingsService regains the skin signal, setSkin() and applySkin(), which toggles the `.win7` class on <html>. - buildPreload emits __APP_SKIN and adds `.win7` conditionally again, instead of unconditionally as it had sincefe028a9. - chromeOptions() regains its parameter: win7 gets frameless + transparent, modern gets the macOS hiddenInset fusion or the plain native frame. - core/platform.ts regains APP_SKIN / IS_WIN7_CHROME (added in stage 4). - main.ts now selects on both axes — skin picks the tree, APP_MODE picks the root within it. - Both tab-bars get a skin row, with the reopen caveat as its tooltip. DEFAULT_SETTINGS.skin is "modern", matching the original design and `main`. Worth flagging: this branch has booted win7 unconditionally sincefe028a9, so after this commit it starts in the modern UI unless the setting says otherwise. One word in types.ts flips that if the win7 look should be the default. i18n: en.ts is the source of truth and everything else falls back to it, so only en was strictly required — but es/eu/fr/de/zh/ja got real translations too, each matching the terminology that locale already uses for the Theme row. Verified both skins on live single-instance captures. Modern boots and renders fully styled, which also proves Tailwind scans skins/shadlike/** — a purge would have produced an unstyled page rather than this one. Win7, selected by setting skin in the persisted settings, is still pixel-identical to the pre-refactor baseline across all five stages. The persisted settings file was backed up and restored, so it still carries no skin key and resolves to the default through the backend's merge. Not verified: clicking the new skin row itself, which needs an interaction pass — no window automation is available here. Its bindings compile and the built bundle contains options.skin, setSkin and the translated labels. Co-Authored-By: Claude <noreply@anthropic.com>
315 lines
10 KiB
TypeScript
315 lines
10 KiB
TypeScript
// English is the source of truth. Other locales mirror this shape; missing keys
|
|
// fall back to English at lookup time. Placeholders use {name} interpolation.
|
|
// Keep Transloco-compatible (nested namespaces, {param}) so a later migration
|
|
// to a real i18n library is a drop-in of these dictionaries.
|
|
|
|
export const en = {
|
|
common: {
|
|
cancel: "Cancel",
|
|
save: "Save",
|
|
close: "Close",
|
|
delete: "Delete",
|
|
rename: "Rename",
|
|
create: "Create",
|
|
apply: "Apply",
|
|
choose: "Choose…",
|
|
connect: "Connect",
|
|
local: "Local",
|
|
},
|
|
app: {
|
|
notConnectedTitle: "Not connected to the app",
|
|
notConnectedBody: "This page is running in a plain browser. Launch the desktop app to use it.",
|
|
managerOpen: "The connection manager is open.",
|
|
showConnections: "Show Connections",
|
|
},
|
|
tabBar: {
|
|
connections: "Connections",
|
|
manageConnections: "Manage connections",
|
|
newTab: "New tab ({mod}T)",
|
|
closeTab: "Close tab ({mod}W)",
|
|
options: "Options",
|
|
update: "Update available",
|
|
updating: "Updating",
|
|
restartToUpdate: "Restart to apply",
|
|
updateTooltip: "Update available: miniSCP {version}",
|
|
},
|
|
options: {
|
|
title: "Options",
|
|
language: "Language",
|
|
system: "System",
|
|
skin: {
|
|
label: "Skin",
|
|
modern: "Modern",
|
|
win7: "Windows 7",
|
|
restartHint: "Reopen the window to change its frame",
|
|
},
|
|
theme: { label: "Theme", system: "System", light: "Light", dark: "Dark" },
|
|
tone: { label: "Tone", dark: "Dark", darker: "Darker" },
|
|
accent: { label: "Accent" },
|
|
accentNames: {
|
|
graphite: "Graphite",
|
|
blue: "Blue",
|
|
indigo: "Indigo",
|
|
purple: "Purple",
|
|
rose: "Rose",
|
|
orange: "Orange",
|
|
green: "Green",
|
|
teal: "Teal",
|
|
},
|
|
fileIcons: { label: "File icons", plain: "Plain", multi: "Multi" },
|
|
interface: { label: "Interface", compact: "Compact", default: "Default", large: "Large" },
|
|
speedUnit: { label: "Speed unit" },
|
|
transfers: { label: "Transfers", single: "Single", multi: "Multi" },
|
|
atOnce: "At once",
|
|
editor: { label: "Editor", builtin: "Built-in", custom: "Custom" },
|
|
systemDefault: "System default",
|
|
resetDefault: "Reset to system default",
|
|
finishedTransfers: { label: "Finished transfers", autoClear: "Auto-clear", keep: "Keep" },
|
|
},
|
|
kinds: {
|
|
folder: "Folder",
|
|
symlink: "Symlink",
|
|
file: "File",
|
|
image: "Image",
|
|
audio: "Audio",
|
|
video: "Video",
|
|
archive: "Archive",
|
|
code: "Code",
|
|
document: "Document",
|
|
},
|
|
columns: {
|
|
name: "Name",
|
|
size: "Size",
|
|
mtime: "Modified",
|
|
kind: "Kind",
|
|
rights: "Rights",
|
|
owner: "Owner",
|
|
group: "Group",
|
|
},
|
|
panel: {
|
|
choosePanel: "Choose what this panel shows",
|
|
copy: "Send",
|
|
copyToRight: "Send to right panel (F5)",
|
|
copyToLeft: "Send to left panel (F5)",
|
|
edit: "Edit",
|
|
editFile: "Edit file (F4)",
|
|
rename: "Rename (F2)",
|
|
newFolder: "New folder (F7)",
|
|
newFile: "New file",
|
|
permissions: "Permissions",
|
|
delete: "Delete",
|
|
deleteHint: "Delete (F8 / Del)",
|
|
parentDir: "Parent directory (Backspace)",
|
|
refresh: "Refresh",
|
|
clearFilter: "Clear filter (Esc)",
|
|
sshConfig: "~/.ssh/config",
|
|
connectingTo: "Connecting to {name}…",
|
|
emptyDir: "Empty directory",
|
|
noMatches: "No matches",
|
|
matches: { one: "{count} match · Esc", other: "{count} matches · Esc" },
|
|
},
|
|
connMgr: {
|
|
title: "Connections",
|
|
importWinscp: "Import from WinSCP…",
|
|
importWinscpHint: "Import sessions from a WinSCP.ini export",
|
|
newConnection: "Connection",
|
|
newConnectionHint: "New connection",
|
|
newStack: "Stack",
|
|
newStackHint: "New stack",
|
|
expand: "Expand",
|
|
collapse: "Collapse",
|
|
renameStack: "Rename stack",
|
|
deleteStack: "Delete stack",
|
|
openStack: "Open stack in tabs",
|
|
empty: "empty",
|
|
connectionsHeader: "Connections",
|
|
noneTitle: "No saved connections yet.",
|
|
noneBody: "Create one, or import your WinSCP sessions.",
|
|
name: "Name",
|
|
namePlaceholder: "my server",
|
|
host: "Host",
|
|
port: "Port",
|
|
stack: "Stack",
|
|
stackNone: "(none)",
|
|
username: "Username",
|
|
remotePath: "Remote path (optional)",
|
|
remotePathPlaceholder: "home directory",
|
|
auth: "Auth",
|
|
authPassword: "Password",
|
|
authKey: "Private key",
|
|
password: "Password",
|
|
privateKeyFile: "Private key file",
|
|
passphrase: "Passphrase (optional)",
|
|
localDir: "Local directory (optional)",
|
|
localDirPlaceholder: "~/projects/my-server",
|
|
localDirHint: "The other panel opens here when it's on Local and hasn't been navigated.",
|
|
more: "More…",
|
|
less: "Less…",
|
|
selectPrompt: "Select a connection or create a new one.",
|
|
newStackTitle: "New stack",
|
|
newStackPrompt: "stack name",
|
|
renameStackTitle: "Rename stack",
|
|
deleteStackTitle: "Delete stack",
|
|
deleteStackBody: 'Delete stack "{name}"? Its connections stay, ungrouped.',
|
|
deleteConnectionTitle: "Delete connection",
|
|
deleteConnectionBody: 'Delete "{name}"?',
|
|
},
|
|
editor: {
|
|
noFileTitle: "No file to edit",
|
|
noFileBody: "This window was opened without an editor context. Launch files from the app.",
|
|
wrap: "Wrap",
|
|
wrapHint: "Wrap long lines — hides line numbers ({alt}Z)",
|
|
findHint: "Find ({mod}F)",
|
|
findPlaceholder: "Find in file",
|
|
prevMatch: "Previous match (⇧↵)",
|
|
nextMatch: "Next match (↵)",
|
|
closeHint: "Close (Esc)",
|
|
disconnected: "Disconnected from {name} — saving will fail, but your text is preserved in this window.",
|
|
cantOpen: "Can't open {name}",
|
|
closeWindow: "Close Window",
|
|
shortcuts: "{mod}S save · {mod}F find · {mod}W close",
|
|
lines: { one: "{count} line", other: "{count} lines" },
|
|
close: "Close",
|
|
save: "Save",
|
|
saveChangesTitle: 'Save changes to "{name}"?',
|
|
saveChangesBody: "Your changes will be lost if you don't save them.",
|
|
dontSave: "Don't Save",
|
|
countLabel: "{current} of {total}",
|
|
noMatches: "No matches",
|
|
},
|
|
transfer: {
|
|
summary: "{active} active · {finished} finished",
|
|
clearFinished: "Clear finished",
|
|
cancel: "Cancel",
|
|
dismiss: "Dismiss",
|
|
showDetails: "Show transfer details",
|
|
copying: "Copying {name} · {percent}%{speed}",
|
|
queued: "{count} queued",
|
|
failed: { one: "{count} transfer failed", other: "{count} transfers failed" },
|
|
finished: "Transfers finished",
|
|
ready: "Ready",
|
|
items: "{count} items",
|
|
selected: "{count} selected",
|
|
queuedState: "Queued",
|
|
scanning: "Scanning…",
|
|
failedState: "Failed",
|
|
cancelled: "Cancelled",
|
|
completedFiles: { one: "{count} file · {size}", other: "{count} files · {size}" },
|
|
left: "{eta} left",
|
|
},
|
|
dialogs: {
|
|
chmodTitle: "Permissions",
|
|
chmodItems: "{count} items",
|
|
read: "Read",
|
|
write: "Write",
|
|
execute: "Execute",
|
|
roleOwner: "Owner",
|
|
roleGroup: "Group",
|
|
roleOthers: "Others",
|
|
octal: "Octal",
|
|
mergeFolder: "Merge folder",
|
|
replace: "Replace",
|
|
merge: "Merge",
|
|
mergeAll: "Merge all",
|
|
replaceAll: "Replace all",
|
|
skip: "Skip",
|
|
skipAll: "Skip all",
|
|
ofTotal: "{index} of {total}",
|
|
overwriteDirBody: "The destination already has a folder with this name. Merging may replace files inside it.",
|
|
overwriteFileBody: "The destination already has a file with this name.",
|
|
source: "Source",
|
|
destination: "Destination",
|
|
newer: "newer",
|
|
},
|
|
toasts: {
|
|
movedToTrash: 'Moved "{name}" to Trash',
|
|
editingExternal: "Editing {name} — saves upload automatically",
|
|
nothingToCopy: "Nothing to copy (symlinks are skipped)",
|
|
nothingToCopyAllSkipped: "Nothing to copy — all conflicting items were skipped",
|
|
sameFolder: "Both panels show the same folder",
|
|
sameFile: 'Skipped "{name}" — it is the same file',
|
|
typeMismatch: 'Skipped "{name}" — a different kind of item is in the way',
|
|
transferFailed: 'Transfer "{name}" failed: {error}',
|
|
unknownError: "unknown error",
|
|
saved: "Saved {name}",
|
|
disconnectedReason: "{title}: disconnected ({reason})",
|
|
imported: { one: "Imported {count} connection", other: "Imported {count} connections" },
|
|
importedIntoStacks: { one: " into {count} new stack", other: " into {count} new stacks" },
|
|
importedSkipped: " ({skipped} skipped)",
|
|
leftoverTitle: "Leftover edited files",
|
|
leftoverBody: {
|
|
one: "A previous session left {count} temporary edited file behind ({names}). Clear them?",
|
|
other: "A previous session left {count} temporary edited files behind ({names}). Clear them?",
|
|
},
|
|
leftoverMore: ", +{count} more",
|
|
leftoverClear: "Clear",
|
|
},
|
|
fileActions: {
|
|
deleteTitle: "Delete",
|
|
deleteBody: "Delete {what}? Folders are deleted recursively. This cannot be undone.",
|
|
deleteConfirm: "Delete",
|
|
renameTitle: 'Rename "{name}"',
|
|
renameConfirm: "Rename",
|
|
newFolderTitle: "New folder",
|
|
newFolderPlaceholder: "folder name",
|
|
newFileTitle: "New file",
|
|
newFilePlaceholder: "file name",
|
|
createConfirm: "Create",
|
|
itemsCount: "{count} items",
|
|
},
|
|
menu: {
|
|
about: "About {app}",
|
|
checkForUpdates: "Check for Updates…",
|
|
quit: "Quit",
|
|
file: "File",
|
|
newTab: "New Tab",
|
|
closeTab: "Close Tab",
|
|
newFolder: "New Folder",
|
|
newFile: "New File",
|
|
editFile: "Edit File",
|
|
connect: "Connect",
|
|
connectionManager: "Connection Manager…",
|
|
edit: "Edit",
|
|
view: "View",
|
|
refresh: "Refresh",
|
|
window: "Window",
|
|
},
|
|
ctx: {
|
|
size: "Size",
|
|
modified: "Modified",
|
|
kind: "Kind",
|
|
rights: "Rights",
|
|
owner: "Owner",
|
|
group: "Group",
|
|
revealFinder: "Reveal in Finder",
|
|
revealExplorer: "Show in Explorer",
|
|
revealFileManager: "Show in File Manager",
|
|
moveToTrash: "Move to Trash",
|
|
moveToRecycleBin: "Move to Recycle Bin",
|
|
newFolder: "New Folder",
|
|
newFile: "New File",
|
|
refresh: "Refresh",
|
|
open: "Open",
|
|
openDefault: "Open with the default application",
|
|
edit: "Edit",
|
|
copyToOther: "Send to Other Panel",
|
|
rename: "Rename",
|
|
permissions: "Permissions",
|
|
copyPath: "Copy Path",
|
|
delete: "Delete",
|
|
columns: "Columns",
|
|
trashTooltip: "Finder's Restore is not available for items trashed from here",
|
|
},
|
|
errors: {
|
|
sshAgentUnavailable: "ssh-agent not available (SSH_AUTH_SOCK is not set)",
|
|
identityFileNotFound: "identity file not found: {path}",
|
|
sessionNotConnected: 'Session "{id}" is not connected',
|
|
localCannotDisconnect: "The local session cannot be disconnected",
|
|
notADirectory: '"{path}" exists and is not a directory',
|
|
sameFileTransfer: '"{name}": source and destination are the same file',
|
|
sameFileNoName: "Source and destination are the same file",
|
|
folderOntoItself: "Cannot copy a folder onto itself",
|
|
folderIntoItself: "Cannot copy a folder into itself",
|
|
},
|
|
} as const;
|