diff --git a/NOTICE b/NOTICE index 21d77cd9..d30d3b3a 100644 --- a/NOTICE +++ b/NOTICE @@ -12,3 +12,4 @@ This product depends on third-party software, including: - Monaco Editor (MIT), Microsoft Corporation - vscode-diff (MIT) - DOMPurify (Apache-2.0 / MPL-2.0) +- @vscode/l10n (MIT), Microsoft Corporation diff --git a/apps/extension/l10n/bundle.l10n.json b/apps/extension/l10n/bundle.l10n.json new file mode 100644 index 00000000..1134accc --- /dev/null +++ b/apps/extension/l10n/bundle.l10n.json @@ -0,0 +1,3217 @@ +{ + "\n\n$(cloud) tracking {0}": "\n\n$(cloud) tracking {0}", + "\n\nNothing on disk changes, and their branches stay.": "\n\nNothing on disk changes, and their branches stay.", + "\n and {0} more": "\n and {0} more", + " …and {0} more": " …and {0} more", + " You, now • Uncommitted changes": " You, now • Uncommitted changes", + " (Added the remote {0} for {1}.)": " (Added the remote {0} for {1}.)", + " (GitHub shows no diff for it)": " (GitHub shows no diff for it)", + " (by {0})": " (by {0})", + " (folder gone)": " (folder gone)", + " (from {0})": " (from {0})", + " (not a worktree any more)": " (not a worktree any more)", + " (removed lines)": " (removed lines)", + " (renamed from {0})": " (renamed from {0})", + " (was {0})": " (was {0})", + " ({0} in Yours, {1} in Theirs)": " ({0} in Yours, {1} in Theirs)", + " ({0} of {1})": " ({0} of {1})", + " HEAD is on no branch, so the merge is on no branch either: create a branch from it to keep it.": " HEAD is on no branch, so the merge is on no branch either: create a branch from it to keep it.", + " It can't bring back the overwritten untracked {0}.": " It can't bring back the overwritten untracked {0}.", + " It is checked out in the worktree at {0}.": " It is checked out in the worktree at {0}.", + " It was staged and then changed again, so its staged version is not kept.": " It was staged and then changed again, so its staged version is not kept.", + " Its author doesn't let maintainers edit it, so a push to it will be refused.": " Its author doesn't let maintainers edit it, so a push to it will be refused.", + " Some stashes may need putting back: {0}.": " Some stashes may need putting back: {0}.", + " and deleted the branch {0}": " and deleted the branch {0}", + " and {0} more": " and {0} more", + " as it was stashed": " as it was stashed", + " as they were stashed": " as they were stashed", + " behind — pull first": " behind — pull first", + " from ": " from ", + " from {0}": " from {0}", + " from “{0}”": " from “{0}”", + " in this workspace)": " in this workspace)", + " matching the filters": " matching the filters", + " the stash list. Undo (Ctrl/Cmd+Alt+G Z) puts it back.": " the stash list. Undo (Ctrl/Cmd+Alt+G Z) puts it back.", + " {0} {1} locked, so prune keeps {2} though {3} — forget {4} in Worktrees.": " {0} {1} locked, so prune keeps {2} though {3} — forget {4} in Worktrees.", + " {0} {1}into ": " {0} {1}into ", + " · $(check) current": " · $(check) current", + " · $(git-merge) merge": " · $(git-merge) merge", + " · also on {0}": " · also on {0}", + " · undoes 1 newer operation first": " · undoes 1 newer operation first", + " · undoes {0} newer operations first": " · undoes {0} newer operations first", + " · {0} more queued": " · {0} more queued", + " · {0} {1} of {2}": " · {0} {1} of {2}", + " — GitHub lists at most 3,000": " — GitHub lists at most 3,000", + " — commits here belong to no branch": " — commits here belong to no branch", + " — drops this message": " — drops this message", + " — its changes are in the stash “{0}”": " — its changes are in the stash “{0}”", + " — keeps both messages": " — keeps both messages", + " — {0} {1} to resolve": " — {0} {1} to resolve", + "\"{0}\" changed {1} in a way Undo can't put back. Nothing was changed.": "\"{0}\" changed {1} in a way Undo can't put back. Nothing was changed.", + "\"{0}\" has already been pushed{1}": "\"{0}\" has already been pushed{1}", + "\"{0}\" isn't a branch name git takes.": "\"{0}\" isn't a branch name git takes.", + "\"{0}\" isn't a ref git can fetch.": "\"{0}\" isn't a ref git can fetch.", + "\"{0}\" isn't a remote URL.": "\"{0}\" isn't a remote URL.", + "\"{0}\" isn't a remote name.": "\"{0}\" isn't a remote name.", + "\"{0}\" isn't a repository GitStudio can add as a remote.": "\"{0}\" isn't a repository GitStudio can add as a remote.", + "\"{0}\" isn't in the undo history any more": "\"{0}\" isn't in the undo history any more", + "\"{0}\" no longer tracks a remote branch": "\"{0}\" no longer tracks a remote branch", + "\"{0}\" tracks {1}, which no longer exists": "\"{0}\" tracks {1}, which no longer exists", + "\"{0}/{1}\" isn't a GitHub repository name.": "\"{0}/{1}\" isn't a GitHub repository name.", + "\"{0}: Restore VS Code's Merge Editor\".": "\"{0}: Restore VS Code's Merge Editor\".", + "#{0} isn't a pull request number.": "#{0} isn't a pull request number.", + "#{0}'s changed files couldn't be read, so its review can't start yet. Refresh and try again.": "#{0}'s changed files couldn't be read, so its review can't start yet. Refresh and try again.", + "$(calendar) {0}\n": "$(calendar) {0}\n", + "$(calendar) {0} ({1})\n\n": "$(calendar) {0} ({1})\n\n", + "$(check) Commit message copied": "$(check) Commit message copied", + "$(check) Committed": "$(check) Committed", + "$(check) Copied {0}": "$(check) Copied {0}", + "$(check) Created & switched to {0}": "$(check) Created & switched to {0}", + "$(check) GitStudio: AI features disabled": "$(check) GitStudio: AI features disabled", + "$(check) Nothing to push from {0} — up to date": "$(check) Nothing to push from {0} — up to date", + "$(check) Nothing to push — up to date": "$(check) Nothing to push — up to date", + "$(check) Pushed": "$(check) Pushed", + "$(check) Rebase complete": "$(check) Rebase complete", + "$(check) Renamed {0} to {1}": "$(check) Renamed {0} to {1}", + "$(check) Reordered": "$(check) Reordered", + "$(check) Undid {0} local {1}": "$(check) Undid {0} local {1}", + "$(check) {0}": "$(check) {0}", + "$(check) {0} {1} to {2}": "$(check) {0} {1} to {2}", + "$(comment-discussion) Reviewing #{0} · {1} pending": "$(comment-discussion) Reviewing #{0} · {1} pending", + "$(comment-discussion) {0} reviews · {1} pending": "$(comment-discussion) {0} reviews · {1} pending", + "$(copy) Copy Message": "$(copy) Copy Message", + "$(copy) Copy SHA": "$(copy) Copy SHA", + "$(debug-continue) {0}": "$(debug-continue) {0}", + "$(debug-pause) Rebase paused": "$(debug-pause) Rebase paused", + "$(discard) Reset Current Branch to Here…": "$(discard) Reset Current Branch to Here…", + "$(discard) {0}": "$(discard) {0}", + "$(git-branch) Create Branch Here…": "$(git-branch) Create Branch Here…", + "$(git-branch) tracking `{0}` · {1} in, {2} out\n\n": "$(git-branch) tracking `{0}` · {1} in, {2} out\n\n", + "$(git-branch) {0}": "$(git-branch) {0}", + "$(git-commit) **Uncommitted changes**\n\n": "$(git-commit) **Uncommitted changes**\n\n", + "$(git-commit) Checkout Commit": "$(git-commit) Checkout Commit", + "$(git-commit) Detach HEAD Here…": "$(git-commit) Detach HEAD Here…", + "$(git-commit) HEAD\n\n": "$(git-commit) HEAD\n\n", + "$(git-commit) Uncommitted changes": "$(git-commit) Uncommitted changes", + "$(git-commit) `{0}`": "$(git-commit) `{0}`", + "$(git-commit) `{0}` ": "$(git-commit) `{0}` ", + "$(git-commit) {0}, {1}": "$(git-commit) {0}, {1}", + "$(git-merge) Start Interactive Rebase Here…": "$(git-merge) Start Interactive Rebase Here…", + "$(git-pull-request) Cherry-Pick Commit": "$(git-pull-request) Cherry-Pick Commit", + "$(history) Revert Commit": "$(history) Revert Commit", + "$(info) GitStudio: no change on this line to stage": "$(info) GitStudio: no change on this line to stage", + "$(info) GitStudio: no change under the cursor to stage": "$(info) GitStudio: no change under the cursor to stage", + "$(info) GitStudio: no staged change selected to unstage": "$(info) GitStudio: no staged change selected to unstage", + "$(info) GitStudio: nothing staged to unstage here": "$(info) GitStudio: nothing staged to unstage here", + "$(info) GitStudio: nothing to stage in the selection": "$(info) GitStudio: nothing to stage in the selection", + "$(info) GitStudio: {0}": "$(info) GitStudio: {0}", + "$(info) No local commits to undo": "$(info) No local commits to undo", + "$(info) {0}: {1}": "$(info) {0}: {1}", + "$(sparkle) Drafted from unstaged changes (nothing was staged)": "$(sparkle) Drafted from unstaged changes (nothing was staged)", + "$(sparkle) Nothing to draft (stage changes first)": "$(sparkle) Nothing to draft (stage changes first)", + "$(sync~spin) Fetching {0}…": "$(sync~spin) Fetching {0}…", + "$(tag) Create Tag Here…": "$(tag) Create Tag Here…", + "$(warning) Resolve Conflicts": "$(warning) Resolve Conflicts", + "' exactly. Asks first, and says what would be lost.": "' exactly. Asks first, and says what would be lost.", + "' match '": "' match '", + "'{0}' and {1} have diverged": "'{0}' and {1} have diverged", + "'{0}' can't be switched to safely — git would read its name as an option. Rename it, then undo.": "'{0}' can't be switched to safely — git would read its name as an option. Rename it, then undo.", + "'{0}' doesn't track a remote branch, so there is nothing to reset it to. Set its tracked branch first.": "'{0}' doesn't track a remote branch, so there is nothing to reset it to. Set its tracked branch first.", + "'{0}' goes back to {1}.": "'{0}' goes back to {1}.", + "'{0}' has been deleted since \"{1}\", so there is nothing to put back.": "'{0}' has been deleted since \"{1}\", so there is nothing to put back.", + "'{0}' has been pushed since, so putting it back would rewrite published history. Nothing was changed.": "'{0}' has been pushed since, so putting it back would rewrite published history. Nothing was changed.", + "'{0}' has moved since (it is at {1} now), and putting it back would throw that away.": "'{0}' has moved since (it is at {1} now), and putting it back would throw that away.", + "'{0}' has moved since the rebase (it is at {1} now), and putting it back would throw that away.": "'{0}' has moved since the rebase (it is at {1} now), and putting it back would throw that away.", + "'{0}' has no upstream to pull from": "'{0}' has no upstream to pull from", + "'{0}' has no upstream to pull from.": "'{0}' has no upstream to pull from.", + "'{0}' has the only copy of its commits, so Undo won't delete it. Nothing was changed.": "'{0}' has the only copy of its commits, so Undo won't delete it. Nothing was changed.", + "'{0}' is": "'{0}' is", + "'{0}' is checked out in another worktree, at {1}, so this one can't switch back to it.": "'{0}' is checked out in another worktree, at {1}, so this one can't switch back to it.", + "'{0}' is checked out in another worktree, at {1}. Reset it there, or check out another branch in that worktree first.": "'{0}' is checked out in another worktree, at {1}. Reset it there, or check out another branch in that worktree first.", + "'{0}' is checked out in another worktree, at {1}. Undo it there.": "'{0}' is checked out in another worktree, at {1}. Undo it there.", + "'{0}' is checked out. Switch to another branch, then undo.": "'{0}' is checked out. Switch to another branch, then undo.", + "'{0}' is not a revision: it starts with '-'.": "'{0}' is not a revision: it starts with '-'.", + "'{0}' is not in this repository any more — refresh and try again.": "'{0}' is not in this repository any more — refresh and try again.", + "'{0}' is not in this repository any more, so there is nothing to switch back to.": "'{0}' is not in this repository any more, so there is nothing to switch back to.", + "'{0}' is not in this repository any more. Nothing was reset.": "'{0}' is not in this repository any more. Nothing was reset.", + "'{0}' moved while you were being asked (it is at {1} now, not {2}). Nothing was reset — try again.": "'{0}' moved while you were being asked (it is at {1} now, not {2}). Nothing was reset — try again.", + "'{0}' tracks '{1}', a branch in this repository, not on a remote — there is nothing to fetch and reset it to.": "'{0}' tracks '{1}', a branch in this repository, not on a remote — there is nothing to fetch and reset it to.", + "'{0}' tracks {1}, which no longer exists on the remote": "'{0}' tracks {1}, which no longer exists on the remote", + "'{0}' tracks {1}. Choose another branch to track.": "'{0}' tracks {1}. Choose another branch to track.", + "'{0}' was checked out here when \"{1}\" ran, and it isn't now. Check it out again, then undo.": "'{0}' was checked out here when \"{1}\" ran, and it isn't now. Check it out again, then undo.", + "'{0}', which '{1}' tracked, no longer exists on the remote. Choose the branch it tracks now.": "'{0}', which '{1}' tracked, no longer exists on the remote. Choose the branch it tracks now.", + "(new file)": "(new file)", + "(no branch)": "(no branch)", + "(no commit message)": "(no commit message)", + "(no message)": "(no message)", + "(whitespace only)": "(whitespace only)", + ", and ": ", and ", + ", and {0} has {1} it doesn't.": ", and {0} has {1} it doesn't.", + ", but not your uncommitted changes — git can't keep a copy of them {0}": ", but not your uncommitted changes — git can't keep a copy of them {0}", + ", current branch": ", current branch", + ", folder": ", folder", + ", folder, ": ", folder, ", + ", in {0}": ", in {0}", + ", partly staged": ", partly staged", + ", remote branch": ", remote branch", + ", required": ", required", + ", staged": ", staged", + ", tag": ", tag", + ", tracking '{0}'": ", tracking '{0}'", + ", tracks ": ", tracks ", + ", was {0}": ", was {0}", + ", which no longer exists on the remote": ", which no longer exists on the remote", + ", with your uncommitted changes": ", with your uncommitted changes", + ", with {0}": ", with {0}", + ", {0} to pull": ", {0} to pull", + ", {0} to push": ", {0} to push", + ". {0}. Go to the next one.": ". {0}. Go to the next one.", + "1 File": "1 File", + "1 change in this file was": "1 change in this file was", + "1 changed file": "1 changed file", + "1 commit": "1 commit", + "1 commit isn't": "1 commit isn't", + "1 commit to pull": "1 commit to pull", + "1 commit to push": "1 commit to push", + "1 conflicted file": "1 conflicted file", + "1 file": "1 file", + "1 file has conflicts to resolve.": "1 file has conflicts to resolve.", + "1 file selected": "1 file selected", + "1 file still contains": "1 file still contains", + "1 incoming commit to pull": "1 incoming commit to pull", + "1 more is": "1 more is", + "1 pending comment": "1 pending comment", + "1 selected file": "1 selected file", + "1 terminal": "1 terminal", + ": yours at {0}, theirs at {1}": ": yours at {0}, theirs at {1}", + "; it now tracks {0}": "; it now tracks {0}", + "; the branch {0} was kept — a commit was made on it while you were asked, and {1} doesn't have it": "; the branch {0} was kept — a commit was made on it while you were asked, and {1} doesn't have it", + "; the branch {0} was kept — git couldn't tell whether it is still merged into {1}": "; the branch {0} was kept — git couldn't tell whether it is still merged into {1}", + "; {0} can be resolved automatically (Resolve simple conflicts)": "; {0} can be resolved automatically (Resolve simple conflicts)", + "A Comment review needs something to say: write a summary, or add a comment on a changed line.": "A Comment review needs something to say: write a summary, or add a comment on a changed line.", + "A band that meets a line between two rows on the other side: lines added there, or removed.": "A band that meets a line between two rows on the other side: lines added there, or removed.", + "A branch named '{0}' exists again, so Undo won't bring back the one \"{1}\" deleted. Nothing was changed.": "A branch named '{0}' exists again, so Undo won't bring back the one \"{1}\" deleted. Nothing was changed.", + "A branch named {0} already exists — choose another name. {1}": "A branch named {0} already exists — choose another name. {1}", + "A branch named “{0}” already exists.": "A branch named “{0}” already exists.", + "A broad catalog of open models.": "A broad catalog of open models.", + "A change still to decide: its line numbers and its link to the Result in the full colour, its lines lighter with the words that changed in the full colour.": "A change still to decide: its line numbers and its link to the Result in the full colour, its lines lighter with the words that changed in the full colour.", + "A cherry-pick": "A cherry-pick", + "A cherry-pick is in progress in it. Removing the worktree abandons the cherry-pick.": "A cherry-pick is in progress in it. Removing the worktree abandons the cherry-pick.", + "A cherry-pick is stopped in it": "A cherry-pick is stopped in it", + "A command in the plan failed. Fix what it needs, then continue.": "A command in the plan failed. Fix what it needs, then continue.", + "A commit message is required.": "A commit message is required.", + "A draft can't be merged until it's marked ready.": "A draft can't be merged until it's marked ready.", + "A draft: not ready for review, and GitHub won't merge it yet": "A draft: not ready for review, and GitHub won't merge it yet", + "A file is left unmerged in it, which git can't stash.": "A file is left unmerged in it, which git can't stash.", + "A git am session": "A git am session", + "A high-level summary of your current changes": "A high-level summary of your current changes", + "A label to recognise it by later.": "A label to recognise it by later.", + "A lighter band in the Result, line numbers too: a conflict with one side in, the other still to decide.": "A lighter band in the Result, line numbers too: a conflict with one side in, the other still to decide.", + "A lighter band, line numbers too, linked to the Result: the side you took. A settled Result keeps it too.": "A lighter band, line numbers too, linked to the Result: the side you took. A settled Result keeps it too.", + "A local {0} already exists, with {1} that {2} doesn't have": "A local {0} already exists, with {1} that {2} doesn't have", + "A merge": "A merge", + "A merge has two sides, so git needs to know which one to keep.": "A merge has two sides, so git needs to know which one to keep.", + "A merge is in progress in it": "A merge is in progress in it", + "A merge is in progress in it. Removing the worktree abandons the merge.": "A merge is in progress in it. Removing the worktree abandons the merge.", + "A name that does not start with \"-\" — git can check that out like any other branch.": "A name that does not start with \"-\" — git can check that out like any other branch.", + "A new branch, {0}. {1}": "A new branch, {0}. {1}", + "A new local branch is created from {0} and checked out in the new worktree.": "A new local branch is created from {0} and checked out in the new worktree.", + "A normal push. Refused if the remote has commits you don't have.": "A normal push. Refused if the remote has commits you don't have.", + "A one-off tip": "A one-off tip", + "A patch series (git am) is in progress": "A patch series (git am) is in progress", + "A push to a named destination needs its remote and branch, and is never forced.": "A push to a named destination needs its remote and branch, and is never forced.", + "A rebase": "A rebase", + "A rebase is already in progress — continue or abort it before starting another.": "A rebase is already in progress — continue or abort it before starting another.", + "A rebase is in progress in it. Removing the worktree abandons the rebase; the branch being rebased stays as it was before the rebase began.": "A rebase is in progress in it. Removing the worktree abandons the rebase; the branch being rebased stays as it was before the rebase began.", + "A rebase is in progress that \"{0}\" didn't start. Finish or abort it first, then undo.": "A rebase is in progress that \"{0}\" didn't start. Finish or abort it first, then undo.", + "A rebase is stopped in it": "A rebase is stopped in it", + "A rebase of {0} is in progress, so there is no branch to push until it finishes. ": "A rebase of {0} is in progress, so there is no branch to push until it finishes. ", + "A remote URL cannot contain spaces.": "A remote URL cannot contain spaces.", + "A revert": "A revert", + "A revert is in progress in it. Removing the worktree abandons the revert.": "A revert is in progress in it. Removing the worktree abandons the revert.", + "A revert is stopped in it": "A revert is stopped in it", + "A revision can't start with '-'.": "A revision can't start with '-'.", + "A squash or fixup has nothing above it to fold into — git can't run this plan.": "A squash or fixup has nothing above it to fold into — git can't run this plan.", + "A squash or fixup has nothing below it to fold into — git can't run this plan.": "A squash or fixup has nothing below it to fold into — git can't run this plan.", + "A stronger tint on some words: exactly what changed within the line. A change of whitespace only has none; its tooltip says so.": "A stronger tint on some words: exactly what changed within the line. A change of whitespace only has none; its tooltip says so.", + "A tag is a fixed point, so you'll be on a detached HEAD — not on any branch. Commits made here belong to nothing until you create a branch for them.": "A tag is a fixed point, so you'll be on a detached HEAD — not on any branch. Commits made here belong to nothing until you create a branch for them.", + "A thin outline with no link: the side you discarded.": "A thin outline with no link: the side you discarded.", + "A title is required.": "A title is required.", + "A worktree is a second folder of this repository with its own branch checked out — no stashing, no switching.": "A worktree is a second folder of this repository with its own branch checked out — no stashing, no switching.", + "A {0} is in progress": "A {0} is in progress", + "AI review of your current changes": "AI review of your current changes", + "Abandon the rebase in progress: '{0}' stays at {1}, as it was.": "Abandon the rebase in progress: '{0}' stays at {1}, as it was.", + "Abandon the rebase in progress: HEAD goes back to {0}.": "Abandon the rebase in progress: HEAD goes back to {0}.", + "Abandon this patch series?": "Abandon this patch series?", + "Abort": "Abort", + "Abort (git am)": "Abort (git am)", + "Abort Cherry-pick": "Abort Cherry-pick", + "Abort Merge": "Abort Merge", + "Abort Rebase": "Abort Rebase", + "Abort Revert": "Abort Revert", + "Abort rebase": "Abort rebase", + "Abort the {0}?": "Abort the {0}?", + "Abort this interactive rebase?": "Abort this interactive rebase?", + "About this pull request": "About this pull request", + "Accept": "Accept", + "Accept Theirs": "Accept Theirs", + "Accept Yours": "Accept Yours", + "Accept theirs everywhere": "Accept theirs everywhere", + "Accept yours everywhere": "Accept yours everywhere", + "Accept {0}": "Accept {0}", + "Accept {0} for {1}": "Accept {0} for {1}", + "Accept {0}: {1}": "Accept {0}: {1}", + "Action for {0}": "Action for {0}", + "Action history": "Action history", + "Actions for ": "Actions for ", + "Actions for {0}": "Actions for {0}", + "Actions for {0} commits": "Actions for {0} commits", + "Add Remote": "Add Remote", + "Add Remote…": "Add Remote…", + "Add a comment to the conversation": "Add a comment to the conversation", + "Add a message…": "Add a message…", + "Add remote": "Add remote", + "Add remote {0}": "Add remote {0}", + "Add remote…": "Add remote…", + "Add the commits to the description, as a list": "Add the commits to the description, as a list", + "Add to Favorites": "Add to Favorites", + "Add to favorites": "Add to favorites", + "Add to filter": "Add to filter", + "Add {0} after {1}": "Add {0} after {1}", + "Add {0} to the filter": "Add {0} to the filter", + "Added": "Added", + "Added on both sides, with no earlier version: every line is compared against an empty file.": "Added on both sides, with no earlier version: every line is compared against an empty file.", + "Added on one side only": "Added on one side only", + "Added remote {0}": "Added remote {0}", + "After your resolution, {0} “{1}” has no changes left, so git leaves it out of {2}.": "After your resolution, {0} “{1}” has no changes left, so git leaves it out of {2}.", + "All": "All", + "All 1 check passed": "All 1 check passed", + "All branches": "All branches", + "All changes have been processed": "All changes have been processed", + "All conflicts": "All conflicts", + "All conflicts are resolved. Open the Conflicts view to continue.": "All conflicts are resolved. Open the Conflicts view to continue.", + "All conflicts resolved": "All conflicts resolved", + "All differences": "All differences", + "All filters": "All filters", + "All patches applied": "All patches applied", + "All patches applied.": "All patches applied.", + "All {0} changed files go back to their committed version.": "All {0} changed files go back to their committed version.", + "All {0} checks passed": "All {0} checks passed", + "All {0} commits are": "All {0} commits are", + "All {0} {1} are": "All {0} {1} are", + "Already at the newest revision": "Already at the newest revision", + "Already at the oldest revision": "Already at the oldest revision", + "Already merged in the file, outside the conflict markers (by git, or by hand): check it": "Already merged in the file, outside the conflict markers (by git, or by hand): check it", + "Already on {0}": "Already on {0}", + "Already pushed. {0} it would rewrite history other people have.": "Already pushed. {0} it would rewrite history other people have.", + "Already rebased commits": "Already rebased commits", + "Already rebased commits and commits from main": "Already rebased commits and commits from main", + "Already rebased commits and commits from {0}": "Already rebased commits and commits from {0}", + "Also delete the branch {0}": "Also delete the branch {0}", + "Alt": "Alt", + "Amend": "Amend", + "Amend commit": "Amend commit", + "An https:// URL, an ssh URL, git@host:owner/repo.git, or a local path.": "An https:// URL, an ssh URL, git@host:owner/repo.git, or a local path.", + "Another file…": "Another file…", + "Answer the question above first: the file changed outside the merge editor": "Answer the question above first: the file changed outside the merge editor", + "Anthropic (Claude)": "Anthropic (Claude)", + "Anthropic is temporarily overloaded — try again shortly.": "Anthropic is temporarily overloaded — try again shortly.", + "Anthropic rate limit hit — try again in a moment.": "Anthropic rate limit hit — try again in a moment.", + "Anthropic rejected the API key. Check it in Settings ▸ AI.": "Anthropic rejected the API key. Check it in Settings ▸ AI.", + "Anthropic request failed (HTTP {0}).": "Anthropic request failed (HTTP {0}).", + "Any": "Any", + "Any label": "Any label", + "Any server that speaks /chat/completions.": "Any server that speaks /chat/completions.", + "Anyone": "Anyone", + "Anything you changed while its question was open is discarded too.": "Anything you changed while its question was open is discarded too.", + "Append": "Append", + "Applied stash": "Applied stash", + "Apply": "Apply", + "Apply all non-conflicting changes": "Apply all non-conflicting changes", + "Apply both sides, change {0}": "Apply both sides, change {0}", + "Apply merge resolution": "Apply merge resolution", + "Apply non-conflicting changes from theirs": "Apply non-conflicting changes from theirs", + "Apply non-conflicting changes from yours": "Apply non-conflicting changes from yours", + "Apply non-conflicting changes from {0}": "Apply non-conflicting changes from {0}", + "Apply non-conflicting changes:": "Apply non-conflicting changes:", + "Apply non-conflicting changes: all": "Apply non-conflicting changes: all", + "Apply non-conflicting changes: {0}": "Apply non-conflicting changes: {0}", + "Apply stash": "Apply stash", + "Apply with {0} unresolved": "Apply with {0} unresolved", + "Apply: put these changes back and keep the stash": "Apply: put these changes back and keep the stash", + "Applying": "Applying", + "Applying a stash": "Applying a stash", + "Applying patches": "Applying patches", + "Applying patches (git am)": "Applying patches (git am)", + "Applying stashed changes on {0}": "Applying stashed changes on {0}", + "Applying the stash": "Applying the stash", + "Applying {0}{1}": "Applying {0}{1}", + "Approve": "Approve", + "Approve this pull request — opens the review box": "Approve this pull request — opens the review box", + "Approved": "Approved", + "Argument rejected for safety (starts with '-' or contains a control character).": "Argument rejected for safety (starts with '-' or contains a control character).", + "Ask GitHub again": "Ask GitHub again", + "Ask for a review from": "Ask for a review from", + "Asked again": "Asked again", + "Assign it to": "Assign it to", + "Assign it to {0}": "Assign it to {0}", + "Assign yourself": "Assign yourself", + "Assignees": "Assignees", + "At least one approving review is required to merge.": "At least one approving review is required to merge.", + "Audit is OFF. Enable \"{0}\" in Settings, then reproduce the problem.": "Audit is OFF. Enable \"{0}\" in Settings, then reproduce the problem.", + "Author": "Author", + "Author override": "Author override", + "Author override — Name ": "Author override — Name ", + "Authorize on GitHub": "Authorize on GitHub", + "Awaiting review": "Awaiting review", + "Azure OpenAI": "Azure OpenAI", + "Back to the branches": "Back to the branches", + "Back to the branches (Left or Escape)": "Back to the branches (Left or Escape)", + "Back to {0}": "Back to {0}", + "Bare repository": "Bare repository", + "Baseline": "Baseline", + "Before this version the two sides were swapped.": "Before this version the two sides were swapped.", + "Binary": "Binary", + "Binary file ({0}) at {1} — its content isn't shown.": "Binary file ({0}) at {1} — its content isn't shown.", + "Binary file — not shown.": "Binary file — not shown.", + "Bind sessions to the device": "Bind sessions to the device", + "Both sides added or changed these lines the same way: nothing to choose": "Both sides added or changed these lines the same way: nothing to choose", + "Both sides changed these lines, differently": "Both sides changed these lines, differently", + "Both sides deleted {0}. There is no side to take — delete the file to settle it.": "Both sides deleted {0}. There is no side to take — delete the file to settle it.", + "Both sides deleted {0}. There is nothing to merge — delete the file to settle it.": "Both sides deleted {0}. There is nothing to merge — delete the file to settle it.", + "Branch": "Branch", + "Branch & actions": "Branch & actions", + "Branch / Tag": "Branch / Tag", + "Branch {0}": "Branch {0}", + "Branch+Tag": "Branch+Tag", + "Branches": "Branches", + "Branches and actions": "Branches and actions", + "Branches: {0}": "Branches: {0}", + "Bring back branch '{0}' at {1}{2}.": "Bring back branch '{0}' at {1}{2}.", + "Bring their commits in and record a merge commit. Yours keep their shas.": "Bring their commits in and record a merge commit. Yours keep their shas.", + "Brings in the pull request's {0} (a fast-forward). It will track {1}.": "Brings in the pull request's {0} (a fast-forward). It will track {1}.", + "Bulk accept": "Bulk accept", + "Buy me a coffee": "Buy me a coffee", + "By {0}.": "By {0}.", + "CLI connections must be built by the host, not makeProvider().": "CLI connections must be built by the host, not makeProvider().", + "Can't undo \"{0}\"": "Can't undo \"{0}\"", + "Can't undo \"{0}\": {1}": "Can't undo \"{0}\": {1}", + "Cancel": "Cancel", + "Cancel applying the stash?": "Cancel applying the stash?", + "Cancel the merge": "Cancel the merge", + "Cancel the stash apply": "Cancel the stash apply", + "Cancelled": "Cancelled", + "Cancelled after {0}": "Cancelled after {0}", + "Cancelled. The conflicted files are back to their last commit.": "Cancelled. The conflicted files are back to their last commit.", + "Cancelled. Your stashed changes are still in the stash.": "Cancelled. Your stashed changes are still in the stash.", + "Cannot contain spaces.": "Cannot contain spaces.", + "Cannot push": "Cannot push", + "Change anyway": "Change anyway", + "Change base ref": "Change base ref", + "Change compare ref": "Change compare ref", + "Change made the same on both sides": "Change made the same on both sides", + "Change on one side only": "Change on one side only", + "Changed Files": "Changed Files", + "Changed files": "Changed files", + "Changed on one side, deleted on the other": "Changed on one side, deleted on the other", + "Changes": "Changes", + "Changes from cherry-pick {0}": "Changes from cherry-pick {0}", + "Changes from worktree {0} ({1}), stashed before removing it": "Changes from worktree {0} ({1}), stashed before removing it", + "Changes from {0}": "Changes from {0}", + "Changes from {0} (rewritten)": "Changes from {0} (rewritten)", + "Changes requested": "Changes requested", + "Changes — Ctrl/Cmd-click to select every file, ": "Changes — Ctrl/Cmd-click to select every file, ", + "Changes, the commit graph, worktrees and sync status follow the file you are editing. Pick a repository to keep them on it.": "Changes, the commit graph, worktrees and sync status follow the file you are editing. Pick a repository to keep them on it.", + "Changes, the commit graph, worktrees and sync status stay on {0} until you pick again.": "Changes, the commit graph, worktrees and sync status stay on {0} until you pick again.", + "Changes, {0}": "Changes, {0}", + "Changing whitespace handling compares the files again, and the changes you have resolved so far ": "Changing whitespace handling compares the files again, and the changes you have resolved so far ", + "Check Out a Branch…": "Check Out a Branch…", + "Check all": "Check all", + "Check it out directly, or as a new named branch?": "Check it out directly, or as a new named branch?", + "Check out its branch here, to merge the base into it and resolve the conflicts": "Check out its branch here, to merge the base into it and resolve the conflicts", + "Check out its branch here, tracking it on GitHub, so a push reaches the pull request": "Check out its branch here, tracking it on GitHub, so a push reaches the pull request", + "Check out tag {0}?": "Check out tag {0}?", + "Check out the existing local branch {0}.": "Check out the existing local branch {0}.", + "Check out which remote branch?": "Check out which remote branch?", + "Check out {0}": "Check out {0}", + "Check out {0} as a detached HEAD.": "Check out {0} as a detached HEAD.", + "Check out {0}?": "Check out {0}?", + "Check your network connection.": "Check your network connection.", + "Checked out": "Checked out", + "Checked out PR #{0} as {1}, updated to its latest and {2}.{3}": "Checked out PR #{0} as {1}, updated to its latest and {2}.{3}", + "Checked out PR #{0} as {1}, updated to its latest.": "Checked out PR #{0} as {1}, updated to its latest.", + "Checked out PR #{0} as {1}, {2}.": "Checked out PR #{0} as {1}, {2}.", + "Checked out PR #{0} as {1}, {2}.{3}": "Checked out PR #{0} as {1}, {2}.{3}", + "Checked out PR #{0} as {1}, {2}: {3}.{4}": "Checked out PR #{0} as {1}, {2}: {3}.{4}", + "Checked out PR #{0} as {1}.": "Checked out PR #{0} as {1}.", + "Checked out {0}": "Checked out {0}", + "Checked out {0} (tracking {1})": "Checked out {0} (tracking {1})", + "Checked out {0} as it was (not updated to PR #{1}).": "Checked out {0} as it was (not updated to PR #{1}).", + "Checked out {0}, but couldn't make it track {1}: {2}": "Checked out {0}, but couldn't make it track {1}: {2}", + "Checking out PR #{0}…": "Checking out PR #{0}…", + "Checking out…": "Checking out…", + "Checkout": "Checkout", + "Checkout '{0}'": "Checkout '{0}'", + "Checkout Commit": "Checkout Commit", + "Checkout Revision '": "Checkout Revision '", + "Checkout Tag (detached)": "Checkout Tag (detached)", + "Checkout Tag or Revision": "Checkout Tag or Revision", + "Checkout Tag or Revision…": "Checkout Tag or Revision…", + "Checkout as {0}": "Checkout as {0}", + "Checkout pull request #{0}": "Checkout pull request #{0}", + "Checkout to resolve": "Checkout to resolve", + "Checkout {0}": "Checkout {0}", + "Checkout {0} as it is": "Checkout {0} as it is", + "Checkout {0}…": "Checkout {0}…", + "Checks": "Checks", + "Checks failed": "Checks failed", + "Checks passed": "Checks passed", + "Checks running": "Checks running", + "Cherry-Pick Commit": "Cherry-Pick Commit", + "Cherry-Pick {0} Commits": "Cherry-Pick {0} Commits", + "Cherry-pick": "Cherry-pick", + "Cherry-pick conflicts": "Cherry-pick conflicts", + "Cherry-pick in progress": "Cherry-pick in progress", + "Cherry-pick of {0} needs a decision — resolve any ": "Cherry-pick of {0} needs a decision — resolve any ", + "Cherry-pick stopped": "Cherry-pick stopped", + "Cherry-pick {0}": "Cherry-pick {0}", + "Cherry-pick {0} commits": "Cherry-pick {0} commits", + "Cherry-picked {0}": "Cherry-picked {0}", + "Cherry-picked {0} commits.": "Cherry-picked {0} commits.", + "Cherry-picking {0} commits": "Cherry-picking {0} commits", + "Cherry-picking {0} commits stopped on a commit that needs you — resolve any conflicts and continue, skip that commit, or abort to put the branch back as it was.": "Cherry-picking {0} commits stopped on a commit that needs you — resolve any conflicts and continue, skip that commit, or abort to put the branch back as it was.", + "Cherry-picking {0} onto {1}{2}": "Cherry-picking {0} onto {1}{2}", + "Choose the branch it comes from": "Choose the branch it comes from", + "Choose the branch it goes into": "Choose the branch it goes into", + "Choose the remote branch '{0}' pulls from and pushes to.": "Choose the remote branch '{0}' pulls from and pushes to.", + "Choose where to push it": "Choose where to push it", + "Choose {0}": "Choose {0}", + "Claude (Anthropic)": "Claude (Anthropic)", + "Claude Code (local)": "Claude Code (local)", + "Claude Opus, Sonnet & Haiku — strongest for code & agentic work.": "Claude Opus, Sonnet & Haiku — strongest for code & agentic work.", + "Clear": "Clear", + "Clear (Esc)": "Clear (Esc)", + "Clear Selection": "Clear Selection", + "Clear filters": "Clear filters", + "Clear search (Esc)": "Clear search (Esc)", + "Clear the search": "Clear the search", + "Click to copy {0}": "Click to copy {0}", + "Click to undo back to before this action": "Click to undo back to before this action", + "Close": "Close", + "Close details": "Close details", + "Close details (Esc)": "Close details (Esc)", + "Close it without merging (you can reopen it)": "Close it without merging (you can reopen it)", + "Close pull request": "Close pull request", + "Close sample": "Close sample", + "Close the merge editor (Escape). Nothing is written.": "Close the merge editor (Escape). Nothing is written.", + "Close the merge editor (Escape). Nothing is written: the {0} stays paused and {1} keeps its conflict markers.": "Close the merge editor (Escape). Nothing is written: the {0} stays paused and {1} keeps its conflict markers.", + "Close this box": "Close this box", + "Close this box — your pending comments are kept": "Close this box — your pending comments are kept", + "Close this dashboard": "Close this dashboard", + "Close this form — nothing is created": "Close this form — nothing is created", + "Close without applying": "Close without applying", + "Close without applying? {0}{1} keeps its conflict markers; ": "Close without applying? {0}{1} keeps its conflict markers; ", + "Close without merging": "Close without merging", + "Closed without merging ": "Closed without merging ", + "Closing…": "Closing…", + "Code Review": "Code Review", + "Codex (local)": "Codex (local)", + "Collapse All Folders": "Collapse All Folders", + "Collapse all files": "Collapse all files", + "Columns": "Columns", + "Comment": "Comment", + "Comment posted": "Comment posted", + "Comment posted to GitHub.": "Comment posted to GitHub.", + "Comment, approve or request changes": "Comment, approve or request changes", + "Commented": "Commented", + "Commenting…": "Commenting…", + "Commit": "Commit", + "Commit & Push": "Commit & Push", + "Commit Graph": "Commit Graph", + "Commit actions": "Commit actions", + "Commit all 1 changed file?": "Commit all 1 changed file?", + "Commit all {0}": "Commit all {0}", + "Commit all {0} changed files?": "Commit all {0} changed files?", + "Commit and Push": "Commit and Push", + "Commit graph": "Commit graph", + "Commit list": "Commit list", + "Commit message": "Commit message", + "Commit or stash {0}, then pull again.": "Commit or stash {0}, then pull again.", + "Commit something first, then open a pull request from its branch.": "Commit something first, then open a pull request from its branch.", + "Commit title": "Commit title", + "Commit {0}": "Commit {0}", + "Commit {0}, {1}, action {2}": "Commit {0}, {1}, action {2}", + "Commit {0}: {1}, by {2}, {3}{4}": "Commit {0}: {1}, by {2}, {3}{4}", + "Commit-message drafting, diff explanation, summaries and AI review stop being offered. Git operations are unaffected. Re-enable with GitStudio: Connect AI Provider, or by setting gitstudio.ai.provider.": "Commit-message drafting, diff explanation, summaries and AI review stop being offered. Git operations are unaffected. Re-enable with GitStudio: Connect AI Provider, or by setting gitstudio.ai.provider.", + "Commits": "Commits", + "Commits to push": "Commits to push", + "Commits to rebase, newest first": "Commits to rebase, newest first", + "Committed on {0}": "Committed on {0}", + "Committing…": "Committing…", + "Commit…": "Commit…", + "Compare": "Compare", + "Compare These Two Commits": "Compare These Two Commits", + "Compare from (base)…": "Compare from (base)…", + "Compare to (head)…": "Compare to (head)…", + "Compare with {0}": "Compare with {0}", + "Compare {0} with…": "Compare {0} with…", + "Compare: {0} ↔ {1}": "Compare: {0} ↔ {1}", + "Compared with {0} as last fetched: GitHub couldn't be reached.": "Compared with {0} as last fetched: GitHub couldn't be reached.", + "Comparing…": "Comparing…", + "Comparison mode": "Comparison mode", + "Confirm merge": "Confirm merge", + "Confirm push": "Confirm push", + "Confirm push from the worktree ": "Confirm push from the worktree ", + "Confirm rebase and merge": "Confirm rebase and merge", + "Confirm squash and merge": "Confirm squash and merge", + "Conflict": "Conflict", + "Conflict — you choose (orange): both sides changed these lines, differently — even when one of them removed lines. Accept one side, both, or edit the result.": "Conflict — you choose (orange): both sides changed these lines, differently — even when one of them removed lines. Accept one side, both, or edit the result.", + "Conflicted binary file": "Conflicted binary file", + "Conflicted submodule": "Conflicted submodule", + "Conflicted symbolic link": "Conflicted symbolic link", + "Conflicts": "Conflicts", + "Conflicts ({0})": "Conflicts ({0})", + "Conflicts dashboard. {0}'s own commands still work.": "Conflicts dashboard. {0}'s own commands still work.", + "Connect AI": "Connect AI", + "Connect GitHub to use pull requests.": "Connect GitHub to use pull requests.", + "Connect a model to write commit messages and review your changes. Bring your own API key, run a model locally (fully private), or use your editor's built-in AI. It's optional and never blocks Git.": "Connect a model to write commit messages and review your changes. Bring your own API key, run a model locally (fully private), or use your editor's built-in AI. It's optional and never blocks Git.", + "Connect an AI provider — powers commit messages & code review": "Connect an AI provider — powers commit messages & code review", + "Contents are identical": "Contents are identical", + "Continue": "Continue", + "Continue (git am)": "Continue (git am)", + "Continue Anyway": "Continue Anyway", + "Continue Cherry-pick": "Continue Cherry-pick", + "Continue Merge": "Continue Merge", + "Continue Rebase": "Continue Rebase", + "Continue Revert": "Continue Revert", + "Continue failed.": "Continue failed.", + "Continue isn't possible yet.": "Continue isn't possible yet.", + "Continuing drops {0} {1} — confirm to go ahead.": "Continuing drops {0} {1} — confirm to go ahead.", + "Continuing will drop {0} “{1}” from {2}: ": "Continuing will drop {0} “{1}” from {2}: ", + "Continuing would drop an emptied commit — confirm to go ahead.": "Continuing would drop an emptied commit — confirm to go ahead.", + "Convert this draft to ready for review": "Convert this draft to ready for review", + "Copied": "Copied", + "Copied commit message": "Copied commit message", + "Copied {0}": "Copied {0}", + "Copied {0} SHAs": "Copied {0} SHAs", + "Copied {0} to Changes": "Copied {0} to Changes", + "Copy": "Copy", + "Copy Branch Name": "Copy Branch Name", + "Copy Message": "Copy Message", + "Copy Path": "Copy Path", + "Copy SHA": "Copy SHA", + "Copy SHA {0}": "Copy SHA {0}", + "Copy SHAs": "Copy SHAs", + "Copy Tag Name": "Copy Tag Name", + "Copy a worktree's path": "Copy a worktree's path", + "Copy failed": "Copy failed", + "Copy finding": "Copy finding", + "Copy full review": "Copy full review", + "Copy it to edit somewhere else": "Copy it to edit somewhere else", + "Copy link": "Copy link", + "Copy report": "Copy report", + "Copy the full 40-character SHA": "Copy the full 40-character SHA", + "Copy the pull request's link": "Copy the pull request's link", + "Copy to Changes": "Copy to Changes", + "Copy {0} to Changes": "Copy {0} to Changes", + "Copy: bring {0} back {1}, and keep {2} in the stash": "Copy: bring {0} back {1}, and keep {2} in the stash", + "Could not finish loading — see the GitStudio Output channel for the error": "Could not finish loading — see the GitStudio Output channel for the error", + "Could not write the rebase plan": "Could not write the rebase plan", + "Couldn't abort the rebase.": "Couldn't abort the rebase.", + "Couldn't bring the conflict in {0} back.": "Couldn't bring the conflict in {0} back.", + "Couldn't check out PR #{0}: {1}": "Couldn't check out PR #{0}: {1}", + "Couldn't compare the branches": "Couldn't compare the branches", + "Couldn't compare {0} with {1}.": "Couldn't compare {0} with {1}.", + "Couldn't connect.": "Couldn't connect.", + "Couldn't create the pull request: {0}": "Couldn't create the pull request: {0}", + "Couldn't delete {0}.": "Couldn't delete {0}.", + "Couldn't draft the description: {0}": "Couldn't draft the description: {0}", + "Couldn't drop {0}.": "Couldn't drop {0}.", + "Couldn't drop {0}: {1}": "Couldn't drop {0}: {1}", + "Couldn't fetch PR #{0}'s branch from {1}: {2}": "Couldn't fetch PR #{0}'s branch from {1}: {2}", + "Couldn't find the pull request's head in what was fetched.": "Couldn't find the pull request's head in what was fetched.", + "Couldn't find what was fetched (FETCH_HEAD).": "Couldn't find what was fetched (FETCH_HEAD).", + "Couldn't find {0} in what was fetched.": "Couldn't find {0} in what was fetched.", + "Couldn't list pull requests.": "Couldn't list pull requests.", + "Couldn't load history": "Couldn't load history", + "Couldn't load its files. {0} ": "Couldn't load its files. {0} ", + "Couldn't load more: {0}": "Couldn't load more: {0}", + "Couldn't load pull requests": "Couldn't load pull requests", + "Couldn't load the changed files. {0}": "Couldn't load the changed files. {0}", + "Couldn't load the history": "Couldn't load the history", + "Couldn't load {0}#{1}": "Couldn't load {0}#{1}", + "Couldn't move {0}: {1}": "Couldn't move {0}: {1}", + "Couldn't post the comment.": "Couldn't post the comment.", + "Couldn't post the reply.": "Couldn't post the reply.", + "Couldn't push {0} to {1}": "Couldn't push {0} to {1}", + "Couldn't put the branch back.": "Couldn't put the branch back.", + "Couldn't put the stash back. `git stash store {0}` brings it back by hand.": "Couldn't put the stash back. `git stash store {0}` brings it back by hand.", + "Couldn't reach Anthropic (network error).": "Couldn't reach Anthropic (network error).", + "Couldn't reach GitHub": "Couldn't reach GitHub", + "Couldn't reach GitHub. Check your network connection.": "Couldn't reach GitHub. Check your network connection.", + "Couldn't reach {0} — is the endpoint reachable?": "Couldn't reach {0} — is the endpoint reachable?", + "Couldn't reach {0} — is the model server running?": "Couldn't reach {0} — is the model server running?", + "Couldn't read its uncommitted changes.": "Couldn't read its uncommitted changes.", + "Couldn't read the conflict state for {0}. Nothing was changed.": "Couldn't read the conflict state for {0}. Nothing was changed.", + "Couldn't read the conflicted files: {0}": "Couldn't read the conflicted files: {0}", + "Couldn't read the worktrees": "Couldn't read the worktrees", + "Couldn't read this commit's files.": "Couldn't read this commit's files.", + "Couldn't read what was fetched (FETCH_HEAD).": "Couldn't read what was fetched (FETCH_HEAD).", + "Couldn't read {0}": "Couldn't read {0}", + "Couldn't read {0}/{1} after fetching it.": "Couldn't read {0}/{1} after fetching it.", + "Couldn't refresh: {0}": "Couldn't refresh: {0}", + "Couldn't resolve the conversation.": "Couldn't resolve the conversation.", + "Couldn't stage {0}.": "Couldn't stage {0}.", + "Couldn't submit the review.": "Couldn't submit the review.", + "Couldn't submit your review": "Couldn't submit your review", + "Couldn't take that version of {0}. Nothing was changed.": "Couldn't take that version of {0}. Nothing was changed.", + "Couldn't take those files out of the stash ({0}): {1}": "Couldn't take those files out of the stash ({0}): {1}", + "Couldn't tell whether {0} has changed since it was resolved. Nothing was changed.": "Couldn't tell whether {0} has changed since it was resolved. Nothing was changed.", + "Couldn't unresolve the conversation.": "Couldn't unresolve the conversation.", + "Couldn't update {0}: {1}": "Couldn't update {0}: {1}", + "Couldn't {0} {1}.": "Couldn't {0} {1}.", + "Couldn't {0} {1}: {2}": "Couldn't {0} {1}: {2}", + "Couldn't {0}: {1}": "Couldn't {0}: {1}", + "Create Branch": "Create Branch", + "Create Branch Here": "Create Branch Here", + "Create Branch Here…": "Create Branch Here…", + "Create Branch…": "Create Branch…", + "Create Only": "Create Only", + "Create Tag": "Create Tag", + "Create Tag Here…": "Create Tag Here…", + "Create Worktree": "Create Worktree", + "Create a branch from": "Create a branch from", + "Create a branch from it under another name instead.": "Create a branch from it under another name instead.", + "Create a merge commit": "Create a merge commit", + "Create a new branch from the current HEAD.": "Create a new branch from the current HEAD.", + "Create a new branch from these commits (and switch to it)": "Create a new branch from these commits (and switch to it)", + "Create a new local branch starting from {0}.": "Create a new local branch starting from {0}.", + "Create and Switch": "Create and Switch", + "Create as draft": "Create as draft", + "Create branch": "Create branch", + "Create branch at {0}": "Create branch at {0}", + "Create branch from stash": "Create branch from stash", + "Create branch from “{0}”": "Create branch from “{0}”", + "Create pull request": "Create pull request", + "Create tag": "Create tag", + "Create tag at {0}": "Create tag at {0}", + "Create the branch and check it out.": "Create the branch and check it out.", + "Create the branch and stay on the current one.": "Create the branch and stay on the current one.", + "Create the pull request on {0}": "Create the pull request on {0}", + "Create {0}": "Create {0}", + "Created branch {0}": "Created branch {0}", + "Created tag {0}": "Created tag {0}", + "Created the worktree {0} at {1}": "Created the worktree {0} at {1}", + "Created {0}": "Created {0}", + "Created {0}pull request #{1}.": "Created {0}pull request #{1}.", + "Creates the branch at HEAD and switches to it.": "Creates the branch at HEAD and switches to it.", + "Creates the branch at the current commit and switches to it.": "Creates the branch at the current commit and switches to it.", + "Creating…": "Creating…", + "Ctrl+Enter to send": "Ctrl+Enter to send", + "Ctrl/Cmd-click to select every file in it, right-click for its actions": "Ctrl/Cmd-click to select every file in it, right-click for its actions", + "Current ({0})": "Current ({0})", + "Current + upstream": "Current + upstream", + "Current branch": "Current branch", + "Current — open in this window.": "Current — open in this window.", + "Custom (OpenAI-compatible)": "Custom (OpenAI-compatible)", + "Date": "Date", + "DeepSeek-V3 chat & R1 reasoning.": "DeepSeek-V3 chat & R1 reasoning.", + "Delete": "Delete", + "Delete Remote Branch": "Delete Remote Branch", + "Delete Tag": "Delete Tag", + "Delete branch": "Delete branch", + "Delete branch '{0}', which \"{1}\" created.": "Delete branch '{0}', which \"{1}\" created.", + "Delete branch {0}": "Delete branch {0}", + "Delete branch {0}?": "Delete branch {0}?", + "Delete remote branch": "Delete remote branch", + "Delete tag": "Delete tag", + "Delete tag {0}?": "Delete tag {0}?", + "Delete the conflicted file": "Delete the conflicted file", + "Delete the file": "Delete the file", + "Delete them — nothing is sent": "Delete them — nothing is sent", + "Delete which remote branch?": "Delete which remote branch?", + "Delete {0} on GitHub after merging": "Delete {0} on GitHub after merging", + "Delete {0} on {1}?": "Delete {0} on {1}?", + "Deleted": "Deleted", + "Deleted on both sides": "Deleted on both sides", + "Deleted tag {0}": "Deleted tag {0}", + "Deleted the file and staged the deletion.": "Deleted the file and staged the deletion.", + "Deleted {0}": "Deleted {0}", + "Deleted {0}/{1}": "Deleted {0}/{1}", + "Deletes its folder, {0}.": "Deletes its folder, {0}.", + "Deletes its folder.": "Deletes its folder.", + "Describe the change. Markdown is fine.": "Describe the change. Markdown is fine.", + "Description": "Description", + "Detach HEAD Here…": "Detach HEAD Here…", + "Detach HEAD here": "Detach HEAD here", + "Detached HEAD": "Detached HEAD", + "Detached HEAD at ": "Detached HEAD at ", + "Detached HEAD at {0}": "Detached HEAD at {0}", + "Detached HEAD at {0} — commits here belong to no branch": "Detached HEAD at {0} — commits here belong to no branch", + "Detached HEAD: commits made here are on no branch\n\n": "Detached HEAD: commits made here are on no branch\n\n", + "Detached at {0} — check out a branch to pull or push": "Detached at {0} — check out a branch to pull or push", + "Details": "Details", + "Details of {0}": "Details of {0}", + "Diff": "Diff", + "Diff style": "Diff style", + "Diff: {0}": "Diff: {0}", + "Disable AI": "Disable AI", + "Disable all GitStudio AI features?": "Disable all GitStudio AI features?", + "Discard": "Discard", + "Discard 1 pending comment on #{0}?": "Discard 1 pending comment on #{0}?", + "Discard All": "Discard All", + "Discard Changes": "Discard Changes", + "Discard Changes and Remove": "Discard Changes and Remove", + "Discard Folder": "Discard Folder", + "Discard all": "Discard all", + "Discard all 1 working-tree change?": "Discard all 1 working-tree change?", + "Discard all uncommitted changes?": "Discard all uncommitted changes?", + "Discard all {0} working-tree changes?": "Discard all {0} working-tree changes?", + "Discard changes": "Discard changes", + "Discard changes in 1 file?": "Discard changes in 1 file?", + "Discard changes in {0} files?": "Discard changes in {0} files?", + "Discard changes in {0}?": "Discard changes in {0}?", + "Discard folder": "Discard folder", + "Discard pending comments…": "Discard pending comments…", + "Discard this change on both sides": "Discard this change on both sides", + "Discard your pending comments?": "Discard your pending comments?", + "Discard {0}": "Discard {0}", + "Discard {0} Files": "Discard {0} Files", + "Discard {0} pending comments on #{1}?": "Discard {0} pending comments on #{1}?", + "Discard {0} too: the result keeps what it has": "Discard {0} too: the result keeps what it has", + "Discard {0}: keep {1} as the result": "Discard {0}: keep {1} as the result", + "Discard {0}? They haven't been sent to GitHub, and this can't be undone.": "Discard {0}? They haven't been sent to GitHub, and this can't be undone.", + "Discarded": "Discarded", + "Discarded both: the Result keeps the original": "Discarded both: the Result keeps the original", + "Discarded the change (the same on both sides)": "Discarded the change (the same on both sides)", + "Discarded the change (the same on both sides): the Result keeps the original": "Discarded the change (the same on both sides): the Result keeps the original", + "Discarded {0}: the Result keeps the original": "Discarded {0}: the Result keeps the original", + "Dismiss": "Dismiss", + "Dismissed": "Dismissed", + "Do not ignore": "Do not ignore", + "Don't ask again": "Don't ask again", + "Don't show this again": "Don't show this again", + "Down arrow": "Down arrow", + "Draft": "Draft", + "Draft with AI": "Draft with AI", + "Drafting a commit message with AI…": "Drafting a commit message with AI…", + "Drafting…": "Drafting…", + "Drag rows or press": "Drag rows or press", + "Drag to reorder": "Drag to reorder", + "Drag to reorder — the selected commits move together (or press Alt+↑ / Alt+↓)": "Drag to reorder — the selected commits move together (or press Alt+↑ / Alt+↓)", + "Drag to resize": "Drag to resize", + "Drag to resize Commit message / Changes": "Drag to resize Commit message / Changes", + "Drag to resize {0} · double-click to reset": "Drag to resize {0} · double-click to reset", + "Drag to resize · double-click to reset": "Drag to resize · double-click to reset", + "Drive your installed `claude` CLI with its own login — no API key.": "Drive your installed `claude` CLI with its own login — no API key.", + "Drive your installed `codex` CLI with its ChatGPT/OpenAI login — no API key.": "Drive your installed `codex` CLI with its ChatGPT/OpenAI login — no API key.", + "Drive your installed `gemini` CLI with its Google login — no API key.": "Drive your installed `gemini` CLI with its Google login — no API key.", + "Drop": "Drop", + "Drop Commit": "Drop Commit", + "Drop Commits": "Drop Commits", + "Drop Commit…": "Drop Commit…", + "Drop and move those branches": "Drop and move those branches", + "Drop from this branch only": "Drop from this branch only", + "Drop it and continue": "Drop it and continue", + "Drop remote-tracking branches that no longer exist on the server.": "Drop remote-tracking branches that no longer exist on the server.", + "Drop stash": "Drop stash", + "Drop the emptied commit?": "Drop the emptied commit?", + "Drop the empty commit?": "Drop the empty commit?", + "Drop to apply": "Drop to apply", + "Drop to copy {0}": "Drop to copy {0}", + "Drop to move {0}": "Drop to move {0}", + "Drop to pop": "Drop to pop", + "Drop to stash {0}": "Drop to stash {0}", + "Drop {0}": "Drop {0}", + "Drop {0} Commits…": "Drop {0} Commits…", + "Drop {0} commits?": "Drop {0} commits?", + "Drop {0}?": "Drop {0}?", + "Drop “{0}”": "Drop “{0}”", + "Drop “{0}”?": "Drop “{0}”?", + "Dropped stash": "Dropped stash", + "Dropped {0}.": "Dropped {0}.", + "Dropping": "Dropping", + "Dropping every commit would erase the whole range.": "Dropping every commit would erase the whole range.", + "Dropping {0} hit a conflict while replaying a later commit. Resolve it and continue the rebase — or skip that commit, or abort to put the branch back as it was.": "Dropping {0} hit a conflict while replaying a later commit. Resolve it and continue the rebase — or skip that commit, or abort to put the branch back as it was.", + "Dropping {0} stopped and needs you — continue the rebase, or abort it to put the branch back as it was.": "Dropping {0} stopped and needs you — continue the rebase, or abort it to put the branch back as it was.", + "Drop…": "Drop…", + "Edit": "Edit", + "Edit URL": "Edit URL", + "Edit URL of {0}": "Edit URL of {0}", + "Edit result": "Edit result", + "Enable LM Studio's local server (Developer ▸ Start Server), then load a model.": "Enable LM Studio's local server (Developer ▸ Start Server), then load a model.", + "Encrypted at rest in GitStudio's own store — not your OS keychain, so it never raises a password prompt. The key stays host-side and is never sent to a webview.": "Encrypted at rest in GitStudio's own store — not your OS keychain, so it never raises a password prompt. The key stays host-side and is never sent to a webview.", + "Errored": "Errored", + "Every check on its latest commit": "Every check on its latest commit", + "Every conflict is resolved, and your stashed changes are in your files. git keeps the stash entry when applying it stops on conflicts, so it is still in your stash list — drop it once you are happy with the result.": "Every conflict is resolved, and your stashed changes are in your files. git keeps the stash entry when applying it stops on conflicts, so it is still in your stash list — drop it once you are happy with the result.", + "Every conflict is resolved.": "Every conflict is resolved.", + "Every difference between the two refs": "Every difference between the two refs", + "Every position HEAD has held, including ones no branch points at any more.": "Every position HEAD has held, including ones no branch points at any more.", + "Every unmerged file goes back to its last committed version, and so does everything that is staged — including changes you staged before the conflict. Conflicts you have resolved are discarded too; none of it was committed, so nothing can bring it back. Changes you never staged are kept.": "Every unmerged file goes back to its last committed version, and so does everything that is staged — including changes you staged before the conflict. Conflicts you have resolved are discarded too; none of it was committed, so nothing can bring it back. Changes you never staged are kept.", + "Everything here is going. Untick anything you want to keep.": "Everything here is going. Untick anything you want to keep.", + "Everything you wrote is still here.": "Everything you wrote is still here.", + "Expand all files": "Expand all files", + "Expected — waiting for it to report": "Expected — waiting for it to report", + "Explain Diff": "Explain Diff", + "Failed": "Failed", + "Failed to start": "Failed to start", + "Fast-forward {0} to {1}?": "Fast-forward {0} to {1}?", + "Fast-forwarded": "Fast-forwarded", + "Fast-forwarded {0}": "Fast-forwarded {0}", + "Fast-forwards '{0}' from {1} — no checkout": "Fast-forwards '{0}' from {1} — no checkout", + "Favorites": "Favorites", + "Feedback without an explicit approval": "Feedback without an explicit approval", + "Fetch": "Fetch", + "Fetched": "Fetched", + "Fetched all remotes": "Fetched all remotes", + "Fetched {0}": "Fetched {0}", + "Fetches, then makes '": "Fetches, then makes '", + "Fetching…": "Fetching…", + "File history": "File history", + "File too large to show ({0}) at {1}.": "File too large to show ({0}) at {1}.", + "Files": "Files", + "Files changed": "Files changed", + "Files resolved": "Files resolved", + "Filter": "Filter", + "Filter branches: {0}": "Filter branches: {0}", + "Filter branches…": "Filter branches…", + "Filter by author, review requested, assignee or label": "Filter by author, review requested, assignee or label", + "Filter by author, review requested, assignee or label ({0} on)": "Filter by author, review requested, assignee or label ({0} on)", + "Filter by {0}": "Filter by {0}", + "Filter changed files": "Filter changed files", + "Filter changed files…": "Filter changed files…", + "Filter pull requests": "Filter pull requests", + "Filter the branch list": "Filter the branch list", + "Filter worktrees": "Filter worktrees", + "Filter {0}": "Filter {0}", + "Filter {0} worktrees": "Filter {0} worktrees", + "Filter, {0} on": "Filter, {0} on", + "Filters on": "Filters on", + "Find a branch": "Find a branch", + "Find a branch, or type one": "Find a branch, or type one", + "Find a label": "Find a label", + "Find a remote": "Find a remote", + "Find a repository": "Find a repository", + "Find a template": "Find a template", + "Find someone, or type a login": "Find someone, or type a login", + "Finding copied": "Finding copied", + "Finish it with {0}": "Finish it with {0}", + "Fixup": "Fixup", + "Folder missing": "Folder missing", + "Follow the active editor": "Follow the active editor", + "Follows the branch you are on · All for every branch": "Follows the branch you are on · All for every branch", + "Follows your local branches · All for every branch": "Follows your local branches · All for every branch", + "For OpenAI / Codex / OpenRouter. Leave blank for a local, keyless server (Ollama / LM Studio). Encrypted at rest in GitStudio's own store and never sent to a webview.": "For OpenAI / Codex / OpenRouter. Leave blank for a local, keyless server (Ollama / LM Studio). Encrypted at rest in GitStudio's own store and never sent to a webview.", + "Force Delete": "Force Delete", + "Force push": "Force push", + "Forget": "Forget", + "Forget It": "Forget It", + "Forget It and Continue": "Forget It and Continue", + "Forget Worktree…": "Forget Worktree…", + "Forget a worktree": "Forget a worktree", + "Forget the {0} git can prune: {1}": "Forget the {0} git can prune: {1}", + "Forget the {0} whose folder is gone": "Forget the {0} whose folder is gone", + "Forget worktree {0}?": "Forget worktree {0}?", + "Forgetting…": "Forgetting…", + "Forgot": "Forgot", + "From the worktree ": "From the worktree ", + "From {0}": "From {0}", + "From {0} — choose the branch it comes from": "From {0} — choose the branch it comes from", + "GPT-4o / o-series via the OpenAI API.": "GPT-4o / o-series via the OpenAI API.", + "Gemini 2.5 Pro & Flash via the OpenAI-compatible endpoint.": "Gemini 2.5 Pro & Flash via the OpenAI-compatible endpoint.", + "Gemini CLI (local)": "Gemini CLI (local)", + "Generate commit message": "Generate commit message", + "Generate commit message with AI": "Generate commit message with AI", + "Generating commit message…": "Generating commit message…", + "Git can't continue yet.": "Git can't continue yet.", + "Git can't safely check out a branch whose name starts with \"-\": \"{0}\"{1} would be read as an option. ": "Git can't safely check out a branch whose name starts with \"-\": \"{0}\"{1} would be read as an option. ", + "Git can't safely move '{0}': a branch name that starts with \"-\" reads as an option. Rename it, then reset it.": "Git can't safely move '{0}': a branch name that starts with \"-\" reads as an option. Rename it, then reset it.", + "Git forgets {0}:\n": "Git forgets {0}:\n", + "Git needs to know how to combine them — this applies to this pull only.": "Git needs to know how to combine them — this applies to this pull only.", + "Git refused to skip.": "Git refused to skip.", + "Git refused to {0}.": "Git refused to {0}.", + "Git won't prune, move or remove it until it is unlocked. Say why, so whoever sees the lock knows — or leave it empty.": "Git won't prune, move or remove it until it is unlocked. Say why, so whoever sees the lock knows — or leave it empty.", + "Git's default. The new name stays local-only.": "Git's default. The new name stays local-only.", + "GitHub couldn't answer the query.": "GitHub couldn't answer the query.", + "GitHub couldn't find what to {0}.": "GitHub couldn't find what to {0}.", + "GitHub couldn't {0}.": "GitHub couldn't {0}.", + "GitHub deletes {0} after it is merged.": "GitHub deletes {0} after it is merged.", + "GitHub denied the request (insufficient permissions).": "GitHub denied the request (insufficient permissions).", + "GitHub didn't answer.": "GitHub didn't answer.", + "GitHub has no pull request {0}#{1}": "GitHub has no pull request {0}#{1}", + "GitHub has no repository {0}": "GitHub has no repository {0}", + "GitHub has no repository {0} — or this sign-in can't see it.": "GitHub has no repository {0} — or this sign-in can't see it.", + "GitHub has no repository {0}/{1}.": "GitHub has no repository {0}/{1}.", + "GitHub is checking whether it can be merged": "GitHub is checking whether it can be merged", + "GitHub is merging {0} into {1}": "GitHub is merging {0} into {1}", + "GitHub no longer accepts this sign-in. Sign in again to see pull requests.": "GitHub no longer accepts this sign-in. Sign in again to see pull requests.", + "GitHub rate limit reached. Try again after {0}.": "GitHub rate limit reached. Try again after {0}.", + "GitHub refused to list {0}'s pull requests": "GitHub refused to list {0}'s pull requests", + "GitHub refused to list {0}'s pull requests.": "GitHub refused to list {0}'s pull requests.", + "GitHub refused to search {0}.": "GitHub refused to search {0}.", + "GitHub refused to show {0}": "GitHub refused to show {0}", + "GitHub refused to show {0}#{1}": "GitHub refused to show {0}#{1}", + "GitHub refused to show {0}.": "GitHub refused to show {0}.", + "GitHub refused to {0}.": "GitHub refused to {0}.", + "GitHub rejected the request": "GitHub rejected the request", + "GitHub request failed (HTTP {0}).": "GitHub request failed (HTTP {0}).", + "GitHub takes no approval of your own pull request": "GitHub takes no approval of your own pull request", + "GitHub takes no change request on your own pull request": "GitHub takes no change request on your own pull request", + "GitHub takes review comments only on lines that are part of the diff, and {0} {1}. Delete {2} or move {3} onto a changed line.": "GitHub takes review comments only on lines that are part of the diff, and {0} {1}. Delete {2} or move {3} onto a changed line.", + "GitHub's rate limit was reached": "GitHub's rate limit was reached", + "GitHub's rate limit was reached.": "GitHub's rate limit was reached.", + "GitHub's rate limit was reached. Try again in a few minutes.": "GitHub's rate limit was reached. Try again in a few minutes.", + "GitStudio AI": "GitStudio AI", + "GitStudio Blame": "GitStudio Blame", + "GitStudio Branch Sync": "GitStudio Branch Sync", + "GitStudio Commit Graph": "GitStudio Commit Graph", + "GitStudio File History": "GitStudio File History", + "GitStudio Pull Request Review": "GitStudio Pull Request Review", + "GitStudio Terminal": "GitStudio Terminal", + "GitStudio can't tell what moved '{0}' since \"{1}\" (it keeps no reflog), so it won't guess. Nothing was changed.": "GitStudio can't tell what moved '{0}' since \"{1}\" (it keeps no reflog), so it won't guess. Nothing was changed.", + "GitStudio can't tell what moved HEAD since \"{0}\" (it keeps no reflog), so it won't guess. Nothing was changed.": "GitStudio can't tell what moved HEAD since \"{0}\" (it keeps no reflog), so it won't guess. Nothing was changed.", + "GitStudio is free and open source. If it saves you time, you can support it.": "GitStudio is free and open source. If it saves you time, you can support it.", + "GitStudio uses VS Code's GitHub account — no token to paste.": "GitStudio uses VS Code's GitHub account — no token to paste.", + "GitStudio uses VS Code's GitHub account — no token to paste. Then list, check out, review, merge and create pull requests here.": "GitStudio uses VS Code's GitHub account — no token to paste. Then list, check out, review, merge and create pull requests here.", + "GitStudio · AI": "GitStudio · AI", + "GitStudio — {0}": "GitStudio — {0}", + "GitStudio's Push reaches the pull request; from a terminal, git push {0} HEAD:{1}.": "GitStudio's Push reaches the pull request; from a terminal, git push {0} HEAD:{1}.", + "GitStudio's Undo can put the branch back{0}.": "GitStudio's Undo can put the branch back{0}.", + "GitStudio: AI features are already disabled.": "GitStudio: AI features are already disabled.", + "GitStudio: Anthropic API key cleared.": "GitStudio: Anthropic API key cleared.", + "GitStudio: Anthropic API key saved. AI features are now available.": "GitStudio: Anthropic API key saved. AI features are now available.", + "GitStudio: Commit Graph": "GitStudio: Commit Graph", + "GitStudio: Interactive Rebase": "GitStudio: Interactive Rebase", + "GitStudio: Nothing to prune: {0}{1}": "GitStudio: Nothing to prune: {0}{1}", + "GitStudio: OpenAI API key cleared (keyless / local mode).": "GitStudio: OpenAI API key cleared (keyless / local mode).", + "GitStudio: OpenAI API key cleared.": "GitStudio: OpenAI API key cleared.", + "GitStudio: OpenAI API key saved.": "GitStudio: OpenAI API key saved.", + "GitStudio: Process Audit": "GitStudio: Process Audit", + "GitStudio: That stash is no longer in the list.": "GitStudio: That stash is no longer in the list.", + "GitStudio: a rebase is already in progress — finish or abort it first.": "GitStudio: a rebase is already in progress — finish or abort it first.", + "GitStudio: can't undo the repository's initial commit this way.": "GitStudio: can't undo the repository's initial commit this way.", + "GitStudio: cannot publish a detached HEAD — check out a branch first.": "GitStudio: cannot publish a detached HEAD — check out a branch first.", + "GitStudio: commit or stash your changes before reordering — a rebase needs a clean working tree.": "GitStudio: commit or stash your changes before reordering — a rebase needs a clean working tree.", + "GitStudio: couldn't create branch{0}": "GitStudio: couldn't create branch{0}", + "GitStudio: couldn't create the worktree — {0}": "GitStudio: couldn't create the worktree — {0}", + "GitStudio: couldn't find {0} in this repository's refs — refresh and try again.": "GitStudio: couldn't find {0} in this repository's refs — refresh and try again.", + "GitStudio: couldn't lock the worktree {0} — {1}": "GitStudio: couldn't lock the worktree {0} — {1}", + "GitStudio: couldn't match this Source Control repository.": "GitStudio: couldn't match this Source Control repository.", + "GitStudio: couldn't prepare the push — {0}": "GitStudio: couldn't prepare the push — {0}", + "GitStudio: couldn't prune — {0}": "GitStudio: couldn't prune — {0}", + "GitStudio: couldn't reset {0} to {1}{2}": "GitStudio: couldn't reset {0} to {1}{2}", + "GitStudio: couldn't stage that change — {0}": "GitStudio: couldn't stage that change — {0}", + "GitStudio: couldn't stage the changes — {0}": "GitStudio: couldn't stage the changes — {0}", + "GitStudio: couldn't stash your changes, so nothing ran — {0}": "GitStudio: couldn't stash your changes, so nothing ran — {0}", + "GitStudio: couldn't unlock the worktree {0} — {1}": "GitStudio: couldn't unlock the worktree {0} — {1}", + "GitStudio: couldn't {0} the worktree {1} — its changes were stashed first, and are in the stash list — {2}": "GitStudio: couldn't {0} the worktree {1} — its changes were stashed first, and are in the stash list — {2}", + "GitStudio: couldn't {0} the worktree {1} — {2}": "GitStudio: couldn't {0} the worktree {1} — {2}", + "GitStudio: couldn't {0} {1} — {2}": "GitStudio: couldn't {0} {1} — {2}", + "GitStudio: enter a commit message.": "GitStudio: enter a commit message.", + "GitStudio: its changes are back, but “{0}” couldn't be dropped — {1}": "GitStudio: its changes are back, but “{0}” couldn't be dropped — {1}", + "GitStudio: keep at least one blame column (Revision, Date, Author, or Commit number).": "GitStudio: keep at least one blame column (Revision, Date, Author, or Commit number).", + "GitStudio: no changes to review — stage or edit some files first.": "GitStudio: no changes to review — stage or edit some files first.", + "GitStudio: no changes to summarize.": "GitStudio: no changes to summarize.", + "GitStudio: no diff to explain.": "GitStudio: no diff to explain.", + "GitStudio: no key entered.": "GitStudio: no key entered.", + "GitStudio: no remotes configured.": "GitStudio: no remotes configured.", + "GitStudio: no worktree this can be done to.": "GitStudio: no worktree this can be done to.", + "GitStudio: nothing staged, or AI is unavailable.": "GitStudio: nothing staged, or AI is unavailable.", + "GitStudio: nothing stashed — every file was unticked.": "GitStudio: nothing stashed — every file was unticked.", + "GitStudio: nothing to draft (stage changes first), or AI is unavailable.": "GitStudio: nothing to draft (stage changes first), or AI is unavailable.", + "GitStudio: nothing to stash — the working tree is clean.": "GitStudio: nothing to stash — the working tree is clean.", + "GitStudio: open a file in a Git repository to stage lines.": "GitStudio: open a file in a Git repository to stage lines.", + "GitStudio: renamed locally, but publishing {0} failed{1}. It still tracks {2}/{3}.": "GitStudio: renamed locally, but publishing {0} failed{1}. It still tracks {2}/{3}.", + "GitStudio: reorder failed{0}": "GitStudio: reorder failed{0}", + "GitStudio: reordering hit a conflict — resolve it, then continue or abort the rebase.": "GitStudio: reordering hit a conflict — resolve it, then continue or abort the rebase.", + "GitStudio: select exactly two commits to compare them.": "GitStudio: select exactly two commits to compare them.", + "GitStudio: the Changes view didn't open, so this action can't ask its question. Open the GitStudio sidebar and try again.": "GitStudio: the Changes view didn't open, so this action can't ask its question. Open the GitStudio sidebar and try again.", + "GitStudio: the Changes view isn't available, so this action can't ask for input. Open the GitStudio sidebar and try again.": "GitStudio: the Changes view isn't available, so this action can't ask for input. Open the GitStudio sidebar and try again.", + "GitStudio: the history changed while you were dragging — nothing was reordered.": "GitStudio: the history changed while you were dragging — nothing was reordered.", + "GitStudio: the rebase stopped and needs you — continue or abort it.": "GitStudio: the rebase stopped and needs you — continue or abort it.", + "GitStudio: there are no stashes.": "GitStudio: there are no stashes.", + "GitStudio: this file is not inside an open Git repository.": "GitStudio: this file is not inside an open Git repository.", + "GitStudio: this file isn't in an open Git repository.": "GitStudio: this file isn't in an open Git repository.", + "GitStudio: this line has uncommitted changes — there's no revision yet.": "GitStudio: this line has uncommitted changes — there's no revision yet.", + "GitStudio: this repository has no {0} to choose from.": "GitStudio: this repository has no {0} to choose from.", + "GitStudio: those files are no longer in the stash.": "GitStudio: those files are no longer in the stash.", + "GitStudio: undo failed{0}": "GitStudio: undo failed{0}", + "GitStudio: using Claude (Anthropic).": "GitStudio: using Claude (Anthropic).", + "GitStudio: using {0}.": "GitStudio: using {0}.", + "GitStudio: {0}": "GitStudio: {0}", + "GitStudio: {0} conflicts. ": "GitStudio: {0} conflicts. ", + "GitStudio: {0} failed{1}": "GitStudio: {0} failed{1}", + "GitStudio: {0} is a merge commit — {1} it on its own, where you can choose which side to keep.": "GitStudio: {0} is a merge commit — {1} it on its own, where you can choose which side to keep.", + "GitStudio: {0} is hidden by the branch filter.": "GitStudio: {0} is hidden by the branch filter.", + "GitStudio: {0} is no longer open, so it can't be shown.": "GitStudio: {0} is no longer open, so it can't be shown.", + "GitStudio: {0} is not a branch on this commit any more — refresh and try again.": "GitStudio: {0} is not a branch on this commit any more — refresh and try again.", + "GitStudio: {0} is not a local branch.": "GitStudio: {0} is not a local branch.", + "GitStudio: {0} is not in this repository any more — refresh and try again.": "GitStudio: {0} is not in this repository any more — refresh and try again.", + "GitStudio: {0} is published and tracked, but {1}/{2} could not be deleted{3}.": "GitStudio: {0} is published and tracked, but {1}/{2} could not be deleted{3}.", + "GitStudio: {0} is the main worktree, which git can't lock.": "GitStudio: {0} is the main worktree, which git can't lock.", + "GitStudio: {0} was added by {1}, so there is no earlier revision of it.": "GitStudio: {0} was added by {1}, so there is no earlier revision of it.", + "GitStudio: {0}'s folder is gone — {1}. Forget the worktree in Worktrees to clear it from the list.": "GitStudio: {0}'s folder is gone — {1}. Forget the worktree in Worktrees to clear it from the list.", + "GitStudio: {0}'s folder is there, so there's nothing to forget. Remove Worktree… removes it, folder and all.": "GitStudio: {0}'s folder is there, so there's nothing to forget. Remove Worktree… removes it, folder and all.", + "GitStudio: {0}'s folder isn't a worktree any more — {1}. Forget the worktree in Worktrees to clear it from the list.": "GitStudio: {0}'s folder isn't a worktree any more — {1}. Forget the worktree in Worktrees to clear it from the list.", + "GitStudio: {0}.": "GitStudio: {0}.", + "GitStudio: “{0}” is a binary file, so there is no text to compare. Copy it to Changes to open it.": "GitStudio: “{0}” is a binary file, so there is no text to compare. Copy it to Changes to open it.", + "GitStudio: “{0}” is no longer in that stash.": "GitStudio: “{0}” is no longer in that stash.", + "Give this commit a name so it stops being unreachable.": "Give this commit a name so it stops being unreachable.", + "Go back to the detached HEAD at {0}.": "Go back to the detached HEAD at {0}.", + "Go here on a detached HEAD to look around.": "Go here on a detached HEAD to look around.", + "Google Gemini": "Google Gemini", + "Got it": "Got it", + "Graph": "Graph", + "Graph & message are always shown": "Graph & message are always shown", + "Grok models from xAI.": "Grok models from xAI.", + "HEAD": "HEAD", + "HEAD has moved since \"{0}\" (it is at {1} now), so the changes it made to your working tree can't be taken back safely.": "HEAD has moved since \"{0}\" (it is at {1} now), so the changes it made to your working tree can't be taken back safely.", + "HEAD is detached — there is no current branch": "HEAD is detached — there is no current branch", + "HEAD is detached, so there is no branch to pull into. Check out a branch first.": "HEAD is detached, so there is no branch to pull into. Check out a branch first.", + "HEAD is detached, so these commits are on no branch and there is nothing to push them to. Create a branch here to push them.": "HEAD is detached, so these commits are on no branch and there is nothing to push them to. Create a branch here to push them.", + "HEAD was detached when \"{0}\" ran, and it isn't now. Detach it at {1} again, then undo.": "HEAD was detached when \"{0}\" ran, and it isn't now. Detach it at {1} again, then undo.", + "HEAD was detached when the commit was dropped, and it's on a branch now. Detach it again, then undo.": "HEAD was detached when the commit was dropped, and it's on a branch now. Detach it again, then undo.", + "HEAD was detached when the {0} ran, and it's on a branch now. Detach it again, then undo.": "HEAD was detached when the {0} ran, and it's on a branch now. Detach it again, then undo.", + "HEAD was {0}{1}": "HEAD was {0}{1}", + "HEAD ↔ Index": "HEAD ↔ Index", + "HEAD~5 main origin/main": "HEAD~5 main origin/main", + "Hard": "Hard", + "Hard-resetting to {0} throws away every uncommitted edit in the working tree and the index.": "Hard-resetting to {0} throws away every uncommitted edit in the working tree and the index.", + "Hide": "Hide", + "Hide individual changes": "Hide individual changes", + "Hide the terminal": "Hide the terminal", + "Highlight granularity": "Highlight granularity", + "Highlight lines": "Highlight lines", + "Highlight words": "Highlight words", + "Hold Undo on a file to bring its conflict back.": "Hold Undo on a file to bring its conflict back.", + "Hold to bring the conflict back (hold Enter or Space from the keyboard)": "Hold to bring the conflict back (hold Enter or Space from the keyboard)", + "Hold to undo": "Hold to undo", + "Hold to undo the resolution of {0}": "Hold to undo the resolution of {0}", + "Hold {0} to copy": "Hold {0} to copy", + "Hold {0} to pop": "Hold {0} to pop", + "How to merge": "How to merge", + "Ignore whitespaces": "Ignore whitespaces", + "Ignore {0} for {1}": "Ignore {0} for {1}", + "Ignore {0}, change {1}": "Ignore {0}, change {1}", + "Ignored": "Ignored", + "Imported 1 key into GitStudio's own encrypted store. Your editor's keychain entry has been cleared.": "Imported 1 key into GitStudio's own encrypted store. Your editor's keychain entry has been cleared.", + "Imported {0} keys into GitStudio's own encrypted store. Your editor's keychain entry has been cleared.": "Imported {0} keys into GitStudio's own encrypted store. Your editor's keychain entry has been cleared.", + "Include this change in the commit": "Include this change in the commit", + "Include {0} in the commit": "Include {0} in the commit", + "Included in the commit — click to remove it": "Included in the commit — click to remove it", + "Index ↔ Working Tree": "Index ↔ Working Tree", + "Inline blame is on, so the editor's built-in blame is turned off — ": "Inline blame is on, so the editor's built-in blame is turned off — ", + "Install Claude Code and run `claude login` (docs.anthropic.com/claude-code).": "Install Claude Code and run `claude login` (docs.anthropic.com/claude-code).", + "Install the Codex CLI and sign in (github.com/openai/codex).": "Install the Codex CLI and sign in (github.com/openai/codex).", + "Install the Gemini CLI and sign in (github.com/google-gemini/gemini-cli).": "Install the Gemini CLI and sign in (github.com/google-gemini/gemini-cli).", + "Interactive Rebase": "Interactive Rebase", + "Interactive rebase": "Interactive rebase", + "Interactive rebase onto {0}": "Interactive rebase onto {0}", + "Interactive rebase over a range this long is slow, and a conflict in the middle leaves you resolving one commit at a time. A nearer base is usually what you want.": "Interactive rebase over a range this long is slow, and a conflict in the middle leaves you resolving one commit at a time. A nearer base is usually what you want.", + "Interactive rebase plan refused": "Interactive rebase plan refused", + "Interactive rebase works best on a clean tree — commit or stash first. GitStudio snapshots your work so Undo can recover it, but git may simply refuse to start.": "Interactive rebase works best on a clean tree — commit or stash first. GitStudio snapshots your work so Undo can recover it, but git may simply refuse to start.", + "Into": "Into", + "Into {0}": "Into {0}", + "Into {0} — choose the branch it goes into": "Into {0} — choose the branch it goes into", + "It and {0} have diverged: {1} to push, {2} to pull.": "It and {0} have diverged: {1} to push, {2} to pull.", + "It can't be merged into {0} until they are resolved: check it out, merge {1} into it and push.": "It can't be merged into {0} until they are resolved: check it out, merge {1} into it and push.", + "It has 1 uncommitted change:\n": "It has 1 uncommitted change:\n", + "It has been pushed since, so putting it back would rewrite published history — it can only be reverted.": "It has been pushed since, so putting it back would rewrite published history — it can only be reverted.", + "It has no branch checked out (detached at {0}).": "It has no branch checked out (detached at {0}).", + "It has {0} the pull request doesn't. It will track {1}, so a push adds them to it.": "It has {0} the pull request doesn't. It will track {1}, so a push adds them to it.", + "It has {0} uncommitted changes:\n": "It has {0} uncommitted changes:\n", + "It is at the pull request's latest. It will track {0}.": "It is at the pull request's latest. It will track {0}.", + "It is fully merged into {0}, so no commit is lost.": "It is fully merged into {0}, so no commit is lost.", + "It is locked already.": "It is locked already.", + "It is locked, with no reason given.": "It is locked, with no reason given.", + "It is locked: “{0}”.": "It is locked: “{0}”.", + "It is still a draft.": "It is still a draft.", + "It is still open.": "It is still open.", + "It is still {0}.": "It is still {0}.", + "It is the bare repository itself, not a working tree.": "It is the bare repository itself, not a working tree.", + "It isn't a worktree any more — {0}.": "It isn't a worktree any more — {0}.", + "It isn't locked.": "It isn't locked.", + "It stays": "It stays", + "It was recorded by an older version of GitStudio, which can't say exactly what it changed. Nothing was changed.": "It was recorded by an older version of GitStudio, which can't say exactly what it changed. Nothing was changed.", + "It's": "It's", + "It's the newest commit, so nothing else changes.": "It's the newest commit, so nothing else changes.", + "Its 1 uncommitted change": "Its 1 uncommitted change", + "Its 1 uncommitted change goes with it, and nothing can bring it back:\n": "Its 1 uncommitted change goes with it, and nothing can bring it back:\n", + "Its author marks it ready for review before it can be merged.": "Its author marks it ready for review before it can be merged.", + "Its branch": "Its branch", + "Its branch has no upstream to pull from.": "Its branch has no upstream to pull from.", + "Its branch has no upstream: Push publishes it.": "Its branch has no upstream: Push publishes it.", + "Its branch — the one checked out here": "Its branch — the one checked out here", + "Its changes come": "Its changes come", + "Its changes come back {0} and the stash is dropped.{1}": "Its changes come back {0} and the stash is dropped.{1}", + "Its changes come back {0}. The stash is kept, staging and all.": "Its changes come back {0}. The stash is kept, staging and all.", + "Its commits join your history. If the two sides touched the same lines you'll get conflicts to resolve, and Undo can take you back either way.": "Its commits join your history. If the two sides touched the same lines you'll get conflicts to resolve, and Undo can take you back either way.", + "Its files couldn't be read.": "Its files couldn't be read.", + "Its folder is gone: {0}. Forgetting it removes git's record of the worktree; nothing on disk changes.": "Its folder is gone: {0}. Forgetting it removes git's record of the worktree; nothing on disk changes.", + "Its folder is missing.": "Its folder is missing.", + "Its folder is there, but it isn't a worktree any more: {0}. Forget it to clear it from the list — the folder and its files stay.": "Its folder is there, but it isn't a worktree any more: {0}. Forget it to clear it from the list — the folder and its files stay.", + "Its folder isn't there. Forget it to clear it from the list — if it is on a drive that isn't connected, connect it instead.": "Its folder isn't there. Forget it to clear it from the list — if it is on a drive that isn't connected, connect it instead.", + "Its folder isn't there. Forget it to clear it from the list.": "Its folder isn't there. Forget it to clear it from the list.", + "Its folder isn't there: {0}. Forgetting it removes git's record of the worktree. If the folder is on a drive that isn't connected, it is no longer a worktree when the drive comes back.": "Its folder isn't there: {0}. Forgetting it removes git's record of the worktree. If the folder is on a drive that isn't connected, it is no longer a worktree when the drive comes back.", + "Its folder, {0}, isn't a worktree any more: {1}. Forgetting it removes git's record of the worktree; the folder and everything in it stay.": "Its folder, {0}, isn't a worktree any more: {1}. Forgetting it removes git's record of the worktree; the folder and everything in it stay.", + "Its remote-tracking branches are renamed to match.": "Its remote-tracking branches are renamed to match.", + "Its remote-tracking branches go with it. Nothing on the server changes.": "Its remote-tracking branches go with it. Nothing on the server changes.", + "Its uncommitted changes": "Its uncommitted changes", + "Its uncommitted changes couldn't be read.": "Its uncommitted changes couldn't be read.", + "Its uncommitted changes couldn't be read; any it has are deleted with it.": "Its uncommitted changes couldn't be read; any it has are deleted with it.", + "Its unstaged edits are lost; the part you staged stays staged. {0}": "Its unstaged edits are lost; the part you staged stays staged. {0}", + "Its upstream, {0}, is gone from the remote.": "Its upstream, {0}, is gone from the remote.", + "Its upstream, {0}, was deleted from the remote.": "Its upstream, {0}, was deleted from the remote.", + "Its {0} are still marked so you can check each; Apply saves the Result as shown.": "Its {0} are still marked so you can check each; Apply saves the Result as shown.", + "Its {0} is still marked so you can check each; Apply saves the Result as shown.": "Its {0} is still marked so you can check each; Apply saves the Result as shown.", + "Its {0} uncommitted changes": "Its {0} uncommitted changes", + "Its {0} uncommitted changes go with it, and nothing can bring them back:\n": "Its {0} uncommitted changes go with it, and nothing can bring them back:\n", + "Its {0} {1}": "Its {0} {1}", + "Jump to HEAD": "Jump to HEAD", + "Keep Staged": "Keep Staged", + "Keep editing": "Keep editing", + "Keep going": "Keep going", + "Keep my changes": "Keep my changes", + "Keep parent {0}": "Keep parent {0}", + "Keep staged changes staged": "Keep staged changes staged", + "Keep the branch that was merged in": "Keep the branch that was merged in", + "Keep the branch this was merged into": "Keep the branch this was merged into", + "Keep them": "Keep them", + "Keep tracking {0}/{1}": "Keep tracking {0}/{1}", + "Keep what's here": "Keep what's here", + "Keep your pending comments": "Keep your pending comments", + "Keep {0} and stage it": "Keep {0} and stage it", + "Keeps its {0}. Nothing is reset.": "Keeps its {0}. Nothing is reset.", + "Kept {0}{1} and staged it.": "Kept {0}{1} and staged it.", + "LM Studio (local)": "LM Studio (local)", + "Label it": "Label it", + "Label: {0}": "Label: {0}", + "Labels": "Labels", + "Language Model": "Language Model", + "Large file: word-level highlights disabled": "Large file: word-level highlights disabled", + "Last commit resolved": "Last commit resolved", + "Last commit skipped. {0} complete, without it": "Last commit skipped. {0} complete, without it", + "Last patch resolved": "Last patch resolved", + "Last patch skipped. The series is finished, without it": "Last patch skipped. The series is finished, without it", + "Last {0} resolved": "Last {0} resolved", + "Leave a comment — Markdown works": "Leave a comment — Markdown works", + "Leave a summary (optional)": "Leave a summary (optional)", + "Leave everything as it is": "Leave everything as it is", + "Leave it alone": "Leave it alone", + "Leave that edit in {0}, and keep working here. Apply replaces it with the Result.": "Leave that edit in {0}, and keep working here. Apply replaces it with the Result.", + "Leave the branch local-only; set a new upstream later.": "Leave the branch local-only; set a new upstream later.", + "Left or Escape goes back to the branches": "Left or Escape goes back to the branches", + "Let {0} open conflicts": "Let {0} open conflicts", + "Line History — {0}": "Line History — {0}", + "Line history": "Line history", + "Line {0}": "Line {0}", + "Lines removed on one side only, or the same lines removed on both: no conflict, safe to take": "Lines removed on one side only, or the same lines removed on both: no conflict, safe to take", + "Lines {0} to {1}": "Lines {0} to {1}", + "Load more": "Load more", + "Loading editor…": "Loading editor…", + "Loading files…": "Loading files…", + "Loading history…": "Loading history…", + "Loading its files…": "Loading its files…", + "Loading line history ({0}–{1})…": "Loading line history ({0}–{1})…", + "Loading pull requests": "Loading pull requests", + "Loading rebase plan…": "Loading rebase plan…", + "Loading the changed files…": "Loading the changed files…", + "Loading the commits": "Loading the commits", + "Loading the files": "Loading the files", + "Loading the form": "Loading the form", + "Loading the pull request": "Loading the pull request", + "Loading…": "Loading…", + "Local": "Local", + "Local branches": "Local branches", + "Local models via LM Studio's server — private, no key.": "Local models via LM Studio's server — private, no key.", + "Local only": "Local only", + "Lock": "Lock", + "Lock a worktree": "Lock a worktree", + "Lock worktree {0}": "Lock worktree {0}", + "Locked": "Locked", + "Locked the worktree {0}": "Locked the worktree {0}", + "Locked, with no reason given. Git won't prune, move or remove it until it is unlocked.": "Locked, with no reason given. Git won't prune, move or remove it until it is unlocked.", + "Locked: {0}": "Locked: {0}", + "Locked: “{0}”. Git won't prune, move or remove it until it is unlocked.": "Locked: “{0}”. Git won't prune, move or remove it until it is unlocked.", + "Lock…": "Lock…", + "Looking for a repository…": "Looking for a repository…", + "L{0}": "L{0}", + "L{0}–{1}": "L{0}–{1}", + "Main worktree": "Main worktree", + "Main worktree — the repository's own folder.": "Main worktree — the repository's own folder.", + "Make your first commit and the history will appear here.": "Make your first commit and the history will appear here.", + "Makes {0} match {1}, then switches to it. Asks first, and says what would be lost.": "Makes {0} match {1}, then switches to it. Asks first, and says what would be lost.", + "Manage remotes": "Manage remotes", + "Mark it ready for review to merge it.": "Mark it ready for review to merge it.", + "Mark ready": "Mark ready", + "Mark this conversation resolved": "Mark this conversation resolved", + "Marking ready…": "Marking ready…", + "Merge": "Merge", + "Merge #{0} into {1}": "Merge #{0} into {1}", + "Merge '{0}' into {1}": "Merge '{0}' into {1}", + "Merge Conflicts": "Merge Conflicts", + "Merge Studio": "Merge Studio", + "Merge applied": "Merge applied", + "Merge applied and staged": "Merge applied and staged", + "Merge conflicts": "Merge conflicts", + "Merge in progress": "Merge in progress", + "Merge pull request #{0} from {1}/{2}": "Merge pull request #{0} from {1}/{2}", + "Merge the base branch into this one, on GitHub": "Merge the base branch into this one, on GitHub", + "Merge this pull request": "Merge this pull request", + "Merge this pull request — choose how": "Merge this pull request — choose how", + "Merge {0}": "Merge {0}", + "Merge {0} into the current branch?": "Merge {0} into the current branch?", + "Merge {0} into this branch on GitHub": "Merge {0} into this branch on GitHub", + "Merge {0} into {1}?": "Merge {0} into {1}?", + "Merged by {0} into {1} ": "Merged by {0} into {1} ", + "Merged into {0} ": "Merged into {0} ", + "Merged pull requests show here once some land.": "Merged pull requests show here once some land.", + "Merged {0}": "Merged {0}", + "Merges {0} from {1} into {2}": "Merges {0} from {1} into {2}", + "Merges {0} into {1}": "Merges {0} into {1}", + "Merge…": "Merge…", + "Merging is blocked": "Merging is blocked", + "Merging {0} into {1}": "Merging {0} into {1}", + "Merging…": "Merging…", + "Message": "Message", + "Message (what & why)…": "Message (what & why)…", + "Mistral & Codestral models.": "Mistral & Codestral models.", + "Mixed": "Mixed", + "Model ID for commit messages and explain — gpt-4o-mini, llama3.1, qwen2.5-coder.": "Model ID for commit messages and explain — gpt-4o-mini, llama3.1, qwen2.5-coder.", + "Modified": "Modified", + "Monaco worker URI was not provided by the host.": "Monaco worker URI was not provided by the host.", + "More Actions…": "More Actions…", + "More actions": "More actions", + "More actions for pull request #{0}": "More actions for pull request #{0}", + "More actions for {0}": "More actions for {0}", + "Move": "Move", + "Move down": "Move down", + "Move down (Alt+Down)": "Move down (Alt+Down)", + "Move the branch and DISCARD every working-tree and staged change.": "Move the branch and DISCARD every working-tree and staged change.", + "Move the branch, keep the working tree, unstage everything. Git's default.": "Move the branch, keep the working tree, unstage everything. Git's default.", + "Move the branch. Keep your working tree AND everything staged.": "Move the branch. Keep your working tree AND everything staged.", + "Move the current branch back to this commit.": "Move the current branch back to this commit.", + "Move the selected commits down": "Move the selected commits down", + "Move the selected commits down (Alt+Down)": "Move the selected commits down (Alt+Down)", + "Move the selected commits up": "Move the selected commits up", + "Move the selected commits up (Alt+Up)": "Move the selected commits up (Alt+Up)", + "Move to Changes": "Move to Changes", + "Move up": "Move up", + "Move up (Alt+Up)": "Move up (Alt+Up)", + "Move {0} out of “{1}”": "Move {0} out of “{1}”", + "Move {0} to Changes": "Move {0} to Changes", + "Move: take {0} out of the stash, back {1}": "Move: take {0} out of the stash, back {1}", + "Moved {0} to Changes": "Moved {0} to Changes", + "Must be addressed before merging": "Must be addressed before merging", + "Name this stash": "Name this stash", + "Needs action": "Needs action", + "Needs the `claude` CLI on your PATH and signed in. Model names map to `claude --model`.": "Needs the `claude` CLI on your PATH and signed in. Model names map to `claude --model`.", + "Needs the `codex` CLI on your PATH and signed in.": "Needs the `codex` CLI on your PATH and signed in.", + "Needs the `gemini` CLI on your PATH and signed in.": "Needs the `gemini` CLI on your PATH and signed in.", + "Neither side has this file — delete it and stage the deletion": "Neither side has this file — delete it and stage the deletion", + "Neutral": "Neutral", + "Neutral, in {0}": "Neutral, in {0}", + "New Branch": "New Branch", + "New Branch '": "New Branch '", + "New Branch '{0}'": "New Branch '{0}'", + "New Branch from '": "New Branch from '", + "New Branch from These Commits": "New Branch from These Commits", + "New Branch…": "New Branch…", + "New Worktree from '": "New Worktree from '", + "New Worktree…": "New Worktree…", + "New branch": "New branch", + "New branch from {0}": "New branch from {0}", + "New branch…": "New branch…", + "New commit message…": "New commit message…", + "New in {0} {1}:": "New in {0} {1}:", + "New pull request": "New pull request", + "New pull request · {0}": "New pull request · {0}", + "New worktree branch": "New worktree branch", + "New worktree for {0}": "New worktree for {0}", + "New worktree — pick a ref": "New worktree — pick a ref", + "Next change (F7)": "Next change (F7)", + "Next match (Enter)": "Next match (Enter)", + "No AI model is connected. Connect one from the ✨ button in the Changes view, then run the review again.": "No AI model is connected. Connect one from the ✨ button in the Changes view, then run the review again.", + "No AI model is connected. Connect one from the ✨ button in the Changes view, then try again.": "No AI model is connected. Connect one from the ✨ button in the Changes view, then try again.", + "No Anthropic API key set. Add it in Settings ▸ AI.": "No Anthropic API key set. Add it in Settings ▸ AI.", + "No GitStudio keys were found in the editor's secret storage.": "No GitStudio keys were found in the editor's secret storage.", + "No actions yet": "No actions yet", + "No active repository.": "No active repository.", + "No branch is checked out in it, so there is nothing to pull into.": "No branch is checked out in it, so there is nothing to pull into.", + "No branch is checked out in it, so there is nothing to push.": "No branch is checked out in it, so there is nothing to push.", + "No branch matches": "No branch matches", + "No branch or tag matches '": "No branch or tag matches '", + "No branches match": "No branches match", + "No branches or tags": "No branches or tags", + "No changed files.": "No changed files.", + "No changes": "No changes", + "No changes to commit.": "No changes to commit.", + "No checks": "No checks", + "No checks run on this pull request's latest commit.": "No checks run on this pull request's latest commit.", + "No closed pull requests": "No closed pull requests", + "No commits to rebase from that point.": "No commits to rebase from that point.", + "No commits to rebase.": "No commits to rebase.", + "No commits yet": "No commits yet", + "No commits —": "No commits —", + "No commits.": "No commits.", + "No common version was found, so both sides are compared against an empty file.": "No common version was found, so both sides are compared against an empty file.", + "No conflicted files at this step.": "No conflicted files at this step.", + "No conflicted files.": "No conflicted files.", + "No content changes.": "No content changes.", + "No description provided.": "No description provided.", + "No file changes between these refs.": "No file changes between these refs.", + "No file changes in these commits.": "No file changes in these commits.", + "No file changes in this commit.": "No file changes in this commit.", + "No file changes.": "No file changes.", + "No files change.": "No files change.", + "No files match the filter.": "No files match the filter.", + "No history for lines {0}–{1} of {2}.": "No history for lines {0}–{1} of {2}.", + "No history for {0}.": "No history for {0}.", + "No issues": "No issues", + "No label matches": "No label matches", + "No labels match": "No labels match", + "No line comments yet. In Files, open a file and click + beside a changed line to add one.": "No line comments yet. In Files, open a file and click + beside a changed line to add one.", + "No local branches": "No local branches", + "No match — Enter uses what you typed": "No match — Enter uses what you typed", + "No matches": "No matches", + "No merge method is allowed": "No merge method is allowed", + "No merged pull requests": "No merged pull requests", + "No model configured for this connection.": "No model configured for this connection.", + "No model is connected yet — pick one below.": "No model is connected yet — pick one below.", + "No one": "No one", + "No one matches": "No one matches", + "No one yet": "No one yet", + "No open pull requests": "No open pull requests", + "No open pull requests.": "No open pull requests.", + "No pull requests yet": "No pull requests yet", + "No rebase in progress — a {0} is. Abort it from the Conflicts dashboard.": "No rebase in progress — a {0} is. Abort it from the Conflicts dashboard.", + "No rebase in progress.": "No rebase in progress.", + "No remote is configured for this repository.": "No remote is configured for this repository.", + "No remote matches": "No remote matches", + "No remotes configured": "No remotes configured", + "No repository is open": "No repository is open", + "No repository matches": "No repository matches", + "No repository open": "No repository open", + "No response from the model — check the server, base URL and model ID.": "No response from the model — check the server, base URL and model ID.", + "No results": "No results", + "No results in {0} loaded": "No results in {0} loaded", + "No review is under way. Start one from a pull request's page.": "No review is under way. Start one from a pull request's page.", + "No reviews yet": "No reviews yet", + "No separate changes to pick from.": "No separate changes to pick from.", + "No template": "No template", + "No template matches": "No template matches", + "No textual diff (binary, empty, or rename with no content change).": "No textual diff (binary, empty, or rename with no content change).", + "No undo history yet": "No undo history yet", + "No upstream": "No upstream", + "No upstream set\n\n": "No upstream set\n\n", + "No upstream: {0} no remote has yet. Push publishes the branch.": "No upstream: {0} no remote has yet. Push publishes the branch.", + "No worktree matches “{0}”.": "No worktree matches “{0}”.", + "No {0}pull requests match": "No {0}pull requests match", + "None": "None", + "None of them is required: merging is still allowed.": "None of them is required: merging is still allowed.", + "None of these can be {0} — nothing {1} them is kept to fold into.": "None of these can be {0} — nothing {1} them is kept to fold into.", + "None of this repository's remotes is on github.com: {0}. Pull requests are available for github.com repositories.": "None of this repository's remotes is on github.com: {0}. Pull requests are available for github.com repositories.", + "None of those files are in the stash.": "None of those files are in the stash.", + "None selected": "None selected", + "None yet": "None yet", + "Not a valid git ref name.": "Not a valid git ref name.", + "Not a worktree": "Not a worktree", + "Not all of those commits are on the current branch, so they can't be {0} from it.": "Not all of those commits are on the current branch, so they can't be {0} from it.", + "Not assigned": "Not assigned", + "Not found on GitHub.": "Not found on GitHub.", + "Not in the branch list yet — refresh": "Not in the branch list yet — refresh", + "Not in the branch list yet — refresh the graph": "Not in the branch list yet — refresh the graph", + "Not included — click to include it": "Not included — click to include it", + "Not now": "Not now", + "Not on any branch": "Not on any branch", + "Not on any remote": "Not on any remote", + "Not on {0}": "Not on {0}", + "Not pushed to {0}": "Not pushed to {0}", + "Not ready to continue yet": "Not ready to continue yet", + "Not staged — click to stage this change": "Not staged — click to stage this change", + "Nothing above it is kept to fold into — git can't run this": "Nothing above it is kept to fold into — git can't run this", + "Nothing changes until you press “Start Rebase,”": "Nothing changes until you press “Start Rebase,”", + "Nothing changes.": "Nothing changes.", + "Nothing could be stashed.": "Nothing could be stashed.", + "Nothing else changes.": "Nothing else changes.", + "Nothing here": "Nothing here", + "Nothing is blocking it.": "Nothing is blocking it.", + "Nothing is in progress.": "Nothing is in progress.", + "Nothing is left to commit at this step: it is already on the branch. Skip it, or abort.": "Nothing is left to commit at this step: it is already on the branch. Skip it, or abort.", + "Nothing is pushed and nothing is pulled.": "Nothing is pushed and nothing is pulled.", + "Nothing is pushed.": "Nothing is pushed.", + "Nothing is staged for this patch. Apply it by hand and stage the result, or skip the patch.": "Nothing is staged for this patch. Apply it by hand and stage the result, or skip the patch.", + "Nothing is staged — stage the changes you want to include, then commit.": "Nothing is staged — stage the changes you want to include, then commit.", + "Nothing is staged — the only changes are new files git isn't tracking yet. Stage them to include them in a commit.": "Nothing is staged — the only changes are new files git isn't tracking yet. Stage them to include them in a commit.", + "Nothing is staged, so everything currently changed will be included — new files too. ": "Nothing is staged, so everything currently changed will be included — new files too. ", + "Nothing is waiting to be reviewed or merged.": "Nothing is waiting to be reviewed or merged.", + "Nothing is written to it until you choose.": "Nothing is written to it until you choose.", + "Nothing matches these filters.": "Nothing matches these filters.", + "Nothing matches “{0}” with these filters.": "Nothing matches “{0}” with these filters.", + "Nothing runs on this branch's commits.": "Nothing runs on this branch's commits.", + "Nothing runs.": "Nothing runs.", + "Nothing runs. Apply keeps the stash, so its staged versions stay in it.": "Nothing runs. Apply keeps the stash, so its staged versions stay in it.", + "Nothing runs. Commit or stash them yourself first.": "Nothing runs. Commit or stash them yourself first.", + "Nothing runs. {0} in the stash, staging and all.": "Nothing runs. {0} in the stash, staging and all.", + "Nothing to commit or push.": "Nothing to commit or push.", + "Nothing to commit — the working tree is clean.": "Nothing to commit — the working tree is clean.", + "Nothing to compare: {0} has no commits that {1} doesn't.": "Nothing to compare: {0} has no commits that {1} doesn't.", + "Nothing to merge line by line": "Nothing to merge line by line", + "Nothing to push — it is up to date with {0}.": "Nothing to push — it is up to date with {0}.", + "Nothing to rebase — all 1 commit here are either merges or changes already on the base, which a rebase would skip.": "Nothing to rebase — all 1 commit here are either merges or changes already on the base, which a rebase would skip.", + "Nothing to rebase — all {0} commits here are either merges or changes already on the base, which a rebase would skip.": "Nothing to rebase — all {0} commits here are either merges or changes already on the base, which a rebase would skip.", + "Nothing to rebase.": "Nothing to rebase.", + "Nothing to resolve here. Continue when you are ready.": "Nothing to resolve here. Continue when you are ready.", + "Nothing to revert — \"{0}\" is already undone.": "Nothing to revert — \"{0}\" is already undone.", + "Nothing to revert — {0} is already undone on this branch.": "Nothing to revert — {0} is already undone on this branch.", + "Nothing to stash — nothing is staged.": "Nothing to stash — nothing is staged.", + "Nothing to stash — the files you selected have no changes.": "Nothing to stash — the files you selected have no changes.", + "Nothing to stash — the working tree is clean.": "Nothing to stash — the working tree is clean.", + "Nothing to undo": "Nothing to undo", + "Nothing to undo for \"{0}\" — {1}": "Nothing to undo for \"{0}\" — {1}", + "Nothing was pruned": "Nothing was pruned", + "Nothing was stashed — the files you selected are new ones git isn't tracking yet. Stash again with \"Include untracked files\" to put those away too.": "Nothing was stashed — the files you selected are new ones git isn't tracking yet. Stash again with \"Include untracked files\" to put those away too.", + "Nothing was stashed — the only changes are new files git isn't tracking yet. Stash again with \"Include untracked files\" to put those away too.": "Nothing was stashed — the only changes are new files git isn't tracking yet. Stash again with \"Include untracked files\" to put those away too.", + "Nothing was written. {0} changed outside the merge editor: reload the merge, or keep that edit, first.": "Nothing was written. {0} changed outside the merge editor: reload the merge, or keep that edit, first.", + "Nothing was written. {0} keeps the resolution it had.": "Nothing was written. {0} keeps the resolution it had.", + "OK": "OK", + "Ollama (local)": "Ollama (local)", + "One key, hundreds of models (Claude, GPT, Llama, Gemini, …).": "One key, hundreds of models (Claude, GPT, Llama, Gemini, …).", + "One later commit will be replayed on top, with a new SHA.": "One later commit will be replayed on top, with a new SHA.", + "One of those commits is a merge — {0} it would flatten the history it joined.": "One of those commits is a merge — {0} it would flatten the history it joined.", + "One side only": "One side only", + "One side only — safe to take (blue): only one side added or changed these lines.": "One side only — safe to take (blue): only one side added or changed these lines.", + "Only commits next to each other on the branch can be squashed — there are other commits between the ones you selected.": "Only commits next to each other on the branch can be squashed — there are other commits between the ones you selected.", + "Only one side added or changed these lines": "Only one side added or changed these lines", + "Only the first 100 are listed; type to find others.": "Only the first 100 are listed; type to find others.", + "Only the local name changes — the commits and the remote branch stay where they are.": "Only the local name changes — the commits and the remote branch stay where they are.", + "Only whitespace changed here": "Only whitespace changed here", + "Open": "Open", + "Open #{0}": "Open #{0}", + "Open All Changes": "Open All Changes", + "Open Changes": "Open Changes", + "Open Changes (vs HEAD)": "Open Changes (vs HEAD)", + "Open Containing Folder": "Open Containing Folder", + "Open File": "Open File", + "Open Folder…": "Open Folder…", + "Open GitHub's page that authorizes this sign-in for the organization": "Open GitHub's page that authorizes this sign-in for the organization", + "Open Pull Request": "Open Pull Request", + "Open Sample Diff": "Open Sample Diff", + "Open Sample Merge": "Open Sample Merge", + "Open Staged Changes": "Open Staged Changes", + "Open Workspace": "Open Workspace", + "Open Worktree in New Window": "Open Worktree in New Window", + "Open a Git repository to open a pull request from it.": "Open a Git repository to open a pull request from it.", + "Open a Git repository to see its pull requests.": "Open a Git repository to see its pull requests.", + "Open a file in a Git repository first": "Open a file in a Git repository first", + "Open a file, then click + beside a changed line to comment": "Open a file, then click + beside a changed line to comment", + "Open a folder that is a git repository to see its worktrees.": "Open a folder that is a git repository to see its worktrees.", + "Open a folder that's under Git and its history will appear here.": "Open a folder that's under Git and its history will appear here.", + "Open a folder that's under Git to see your changes, branches, and history.": "Open a folder that's under Git to see your changes, branches, and history.", + "Open a new pull request": "Open a new pull request", + "Open a pull request — from the branch checked out, or any other": "Open a pull request — from the branch checked out, or any other", + "Open a terminal at the repository root": "Open a terminal at the repository root", + "Open a terminal in a worktree": "Open a terminal in a worktree", + "Open a worktree in a new window": "Open a worktree in a new window", + "Open a worktree in this window": "Open a worktree in this window", + "Open changes — {0}{1}": "Open changes — {0}{1}", + "Open in Commit Graph": "Open in Commit Graph", + "Open in Embedded Diff": "Open in Embedded Diff", + "Open in New Window": "Open in New Window", + "Open in Terminal": "Open in Terminal", + "Open in This Window": "Open in This Window", + "Open in diff editor": "Open in diff editor", + "Open models at very low latency.": "Open models at very low latency.", + "Open on GitHub": "Open on GitHub", + "Open on GitHub for the rest": "Open on GitHub for the rest", + "Open on remote": "Open on remote", + "Open pull request #{0}": "Open pull request #{0}", + "Open pull request #{0} on GitHub": "Open pull request #{0} on GitHub", + "Open pull requests": "Open pull requests", + "Open the first file, ready for your comments": "Open the first file, ready for your comments", + "Open the first one to propose a change.": "Open the first one to propose a change.", + "Open the pull request's page": "Open the pull request's page", + "Open this change in the diff": "Open this change in the diff", + "Open this conversation again": "Open this conversation again", + "Open this pull request on GitHub": "Open this pull request on GitHub", + "Open {0} at Revision": "Open {0} at Revision", + "Open {0} at line {1}": "Open {0} at line {1}", + "Open {0} — the lines this was written on have changed since": "Open {0} — the lines this was written on have changed since", + "Open {0}'s details": "Open {0}'s details", + "OpenAI / local (OpenAI-compatible)": "OpenAI / local (OpenAI-compatible)", + "OpenAI models hosted in your Azure tenant.": "OpenAI models hosted in your Azure tenant.", + "OpenAI rate limit hit — try again in a moment.": "OpenAI rate limit hit — try again in a moment.", + "OpenAI, Codex, OpenRouter, or a local server (Ollama / LM Studio). Base URL / model / key.": "OpenAI, Codex, OpenRouter, or a local server (Ollama / LM Studio). Base URL / model / key.", + "OpenAI-compatible Base URL": "OpenAI-compatible Base URL", + "OpenAI-compatible Model": "OpenAI-compatible Model", + "OpenAI-compatible request failed (HTTP {0}).": "OpenAI-compatible request failed (HTTP {0}).", + "Opens on {0} — choose another repository": "Opens on {0} — choose another repository", + "Operation failed.": "Operation failed.", + "Operation in progress": "Operation in progress", + "Or this GitHub sign-in can't see it.": "Or this GitHub sign-in can't see it.", + "Or this GitHub sign-in can't see it: a private repository needs an account with access to it.": "Or this GitHub sign-in can't see it: a private repository needs an account with access to it.", + "Otherwise git labels it with the branch and its last commit.": "Otherwise git labels it with the branch and its last commit.", + "Outdated": "Outdated", + "Overview of the changes still to resolve — press to go there": "Overview of the changes still to resolve — press to go there", + "Partly included — click to include the rest": "Partly included — click to include the rest", + "Partly staged — click to stage the rest": "Partly staged — click to stage the rest", + "Partly staged — click to stage the rest of this change": "Partly staged — click to stage the rest of this change", + "Passed": "Passed", + "Passed in {0}": "Passed in {0}", + "Patch conflicts": "Patch conflicts", + "Patch series": "Patch series", + "Patch series abandoned": "Patch series abandoned", + "Patch series abandoned — the branch is back where it was before it started.": "Patch series abandoned — the branch is back where it was before it started.", + "Patch {0}": "Patch {0}", + "Patch {0} of {1}": "Patch {0} of {1}", + "Paused": "Paused", + "Paused at a break in the rebase plan": "Paused at a break in the rebase plan", + "Paused because a command in the rebase plan failed": "Paused because a command in the rebase plan failed", + "Paused because the command “{0}” failed": "Paused because the command “{0}” failed", + "Paused to edit a commit": "Paused to edit a commit", + "Paused to edit {0} {1}": "Paused to edit {0} {1}", + "Paused: {0}": "Paused: {0}", + "Pending": "Pending", + "Pending for {0}": "Pending for {0}", + "Pending review comment": "Pending review comment", + "Pick": "Pick", + "Pick a base": "Pick a base", + "Pick a branch": "Pick a branch", + "Pick a commit to diff it against its parent.": "Pick a commit to diff it against its parent.", + "Pick a revision to diff against your working tree.": "Pick a revision to diff against your working tree.", + "Pick a tag or branch, or type any revision (a sha, origin/main~3). Checks out as a detached HEAD.": "Pick a tag or branch, or type any revision (a sha, origin/main~3). Checks out as a detached HEAD.", + "Pick any file on disk to diff against.": "Pick any file on disk to diff against.", + "Pick both branches to see what it will have.": "Pick both branches to see what it will have.", + "Pick one of the listed entries.": "Pick one of the listed entries.", + "Pick the branch it goes into.": "Pick the branch it goes into.", + "Pick the branch to open it from.": "Pick the branch to open it from.", + "Picking": "Picking", + "Point the submodule at {0}'s commit{1} and stage it": "Point the submodule at {0}'s commit{1} and stage it", + "Point the submodule at {0}'s commit{1}{2} and stage it": "Point the submodule at {0}'s commit{1}{2} and stage it", + "Pop": "Pop", + "Pop stash": "Pop stash", + "Pop “{0}”": "Pop “{0}”", + "Pop: put these changes back and delete the stash": "Pop: put these changes back and delete the stash", + "Popped stash": "Popped stash", + "Post your comment on GitHub": "Post your comment on GitHub", + "Post your reply on GitHub": "Post your reply on GitHub", + "Previous change (Shift+F7)": "Previous change (Shift+F7)", + "Previous match (Shift+Enter)": "Previous match (Shift+Enter)", + "Prune": "Prune", + "Prune 1 missing worktree?": "Prune 1 missing worktree?", + "Prune 1 missing worktree…": "Prune 1 missing worktree…", + "Prune Stale Branches": "Prune Stale Branches", + "Prune {0}": "Prune {0}", + "Prune {0} missing worktrees?": "Prune {0} missing worktrees?", + "Prune {0} missing worktrees…": "Prune {0} missing worktrees…", + "Pruned 1 worktree whose folder was gone: {0}": "Pruned 1 worktree whose folder was gone: {0}", + "Pruned 1 worktree: {0}": "Pruned 1 worktree: {0}", + "Pruned {0}": "Pruned {0}", + "Pruned {0} worktrees whose folder was gone: {1}": "Pruned {0} worktrees whose folder was gone: {1}", + "Pruned {0} worktrees: {1}": "Pruned {0} worktrees: {1}", + "Publish": "Publish", + "Publish this branch to which remote?": "Publish this branch to which remote?", + "Publish to which remote?": "Publish to which remote?", + "Publish {0}": "Publish {0}", + "Publish {0}, keep {1}": "Publish {0}, keep {1}", + "Published {0}": "Published {0}", + "Published {0} to {1}": "Published {0} to {1}", + "Pull": "Pull", + "Pull 1 Commit into '{0}'": "Pull 1 Commit into '{0}'", + "Pull 1 commit": "Pull 1 commit", + "Pull 1 commit into {0}, in its own folder": "Pull 1 commit into {0}, in its own folder", + "Pull Requests": "Pull Requests", + "Pull commits": "Pull commits", + "Pull hit conflicts. Resolve them, then continue or abort.": "Pull hit conflicts. Resolve them, then continue or abort.", + "Pull into '{0}'": "Pull into '{0}'", + "Pull into a worktree": "Pull into a worktree", + "Pull request": "Pull request", + "Pull request #{0}": "Pull request #{0}", + "Pull request #{0}: {1}": "Pull request #{0}: {1}", + "Pull request actions": "Pull request actions", + "Pull requests": "Pull requests", + "Pull requests are opened on github.com repositories. Add a remote that points at one.": "Pull requests are opened on github.com repositories. Add a remote that points at one.", + "Pull requests closed without merging show here.": "Pull requests closed without merging show here.", + "Pull requests show here once a remote points at github.com.": "Pull requests show here once a remote points at github.com.", + "Pull them in first, then push.": "Pull them in first, then push.", + "Pull these commits from the upstream": "Pull these commits from the upstream", + "Pull using Merge": "Pull using Merge", + "Pull using Rebase": "Pull using Rebase", + "Pull {0} Commits into '{1}'": "Pull {0} Commits into '{1}'", + "Pull {0} commits": "Pull {0} commits", + "Pull {0} commits into {1}, in its own folder": "Pull {0} commits into {1}, in its own folder", + "Pull {0} didn't run: {1}": "Pull {0} didn't run: {1}", + "Pull {0} failed — {1}": "Pull {0} failed — {1}", + "Pull {0}: {1}": "Pull {0}: {1}", + "Pulled": "Pulled", + "Pulled the worktree {0}": "Pulled the worktree {0}", + "Pulling with rebase": "Pulling with rebase", + "Pulling with rebase needs a clean working tree, and you have uncommitted changes to {0}. ": "Pulling with rebase needs a clean working tree, and you have uncommitted changes to {0}. ", + "Pulling…": "Pulling…", + "Push": "Push", + "Push 1 commit": "Push 1 commit", + "Push Tag to Remote…": "Push Tag to Remote…", + "Push and create pull request": "Push and create pull request", + "Push commits": "Push commits", + "Push from a worktree": "Push from a worktree", + "Push it to": "Push it to", + "Push tag": "Push tag", + "Push these commits to the upstream": "Push these commits to the upstream", + "Push to": "Push to", + "Push to another remote": "Push to another remote", + "Push to the upstream branch?": "Push to the upstream branch?", + "Push {0}": "Push {0}", + "Push {0} and track it, but leave {1}/{2} in place.": "Push {0} and track it, but leave {1}/{2} in place.", + "Push {0} commits": "Push {0} commits", + "Push {0} to which remote?": "Push {0} to which remote?", + "Push {0}, then create the pull request on {1}": "Push {0}, then create the pull request on {1}", + "Push {0}, track it, and delete {1}/{2}.": "Push {0}, track it, and delete {1}/{2}.", + "Pushed": "Pushed", + "Pushed tag {0} to {1}": "Pushed tag {0} to {1}", + "Pushed to {0} — choose another of this clone's GitHub remotes": "Pushed to {0} — choose another of this clone's GitHub remotes", + "Pushed {0}": "Pushed {0}", + "Pushing and creating…": "Pushing and creating…", + "Pushing…": "Pushing…", + "Push…": "Push…", + "Put the stash “{0}” back {1}.": "Put the stash “{0}” back {1}.", + "Putting {0} back would overwrite uncommitted changes, and some of them you had before \"{1}\" — ": "Putting {0} back would overwrite uncommitted changes, and some of them you had before \"{1}\" — ", + "Queued": "Queued", + "Re-creating merge of {0} into {1}{2}": "Re-creating merge of {0} into {1}{2}", + "Reached the step limit before finishing.": "Reached the step limit before finishing.", + "Reached the step limit.": "Reached the step limit.", + "Read its files again": "Read its files again", + "Read the pull request again": "Read the pull request again", + "Read-only": "Read-only", + "Reading changes…": "Reading changes…", + "Reading its files…": "Reading its files…", + "Reading the diff…": "Reading the diff…", + "Ready to merge": "Ready to merge", + "Reason (optional)": "Reason (optional)", + "Rebase": "Rebase", + "Rebase aborted": "Rebase aborted", + "Rebase and merge": "Rebase and merge", + "Rebase commits, oldest first": "Rebase commits, oldest first", + "Rebase conflicts": "Rebase conflicts", + "Rebase failed.": "Rebase failed.", + "Rebase in progress": "Rebase in progress", + "Rebase onto which commit or branch? The base itself is excluded — everything after it becomes the todo.": "Rebase onto which commit or branch? The base itself is excluded — everything after it becomes the todo.", + "Rebase onto which commit or branch? The base itself is excluded — everything after it lands in the workspace.": "Rebase onto which commit or branch? The base itself is excluded — everything after it lands in the workspace.", + "Rebase onto {0}": "Rebase onto {0}", + "Rebase paused": "Rebase paused", + "Rebase paused for editing.": "Rebase paused for editing.", + "Rebase paused on a conflict — resolve the files, then Continue. ": "Rebase paused on a conflict — resolve the files, then Continue. ", + "Rebase paused on a conflict.": "Rebase paused on a conflict.", + "Rebase paused to edit a commit — amend in your working tree, then Continue. ": "Rebase paused to edit a commit — amend in your working tree, then Continue. ", + "Rebase paused.": "Rebase paused.", + "Rebase paused. ": "Rebase paused. ", + "Rebase plan applied": "Rebase plan applied", + "Rebase stopped": "Rebase stopped", + "Rebase the current branch onto {0}?": "Rebase the current branch onto {0}?", + "Rebase {0} commits?": "Rebase {0} commits?", + "Rebase {0} onto '{1}'": "Rebase {0} onto '{1}'", + "Rebase {0} onto {1}?": "Rebase {0} onto {1}?", + "Rebased onto {0}": "Rebased onto {0}", + "Rebasing": "Rebasing", + "Rebasing a1b2c3d from feature/session-hardening": "Rebasing a1b2c3d from feature/session-hardening", + "Rebasing {0}": "Rebasing {0}", + "Rebasing {0} from {1}": "Rebasing {0} from {1}", + "Rebasing {0} onto {1}{2}{3}": "Rebasing {0} onto {1}{2}{3}", + "Recents": "Recents", + "Recover — {0} ({1})": "Recover — {0} ({1})", + "Recreate the remote branch from your local commits.": "Recreate the remote branch from your local commits.", + "Recurring support": "Recurring support", + "Redo ({0})": "Redo ({0})", + "Reflog": "Reflog", + "Reflog — Time Machine": "Reflog — Time Machine", + "Refresh": "Refresh", + "Refresh the pull request": "Refresh the pull request", + "Refresh — read the branches and GitHub again": "Refresh — read the branches and GitHub again", + "Refresh — read the pull request again": "Refresh — read the pull request again", + "Refresh: read the branches and GitHub again": "Refresh: read the branches and GitHub again", + "Refreshing…": "Refreshing…", + "Refusing to rebase: unrecognised plan entry {0}.": "Refusing to rebase: unrecognised plan entry {0}.", + "Release {0} to apply": "Release {0} to apply", + "Release {0} to move": "Release {0} to move", + "Reload the merge": "Reload the merge", + "Remote": "Remote", + "Remote: {0}": "Remote: {0}", + "Remotes": "Remotes", + "Remove": "Remove", + "Remove Worktree…": "Remove Worktree…", + "Remove a worktree": "Remove a worktree", + "Remove every filter": "Remove every filter", + "Remove from Favorites": "Remove from Favorites", + "Remove from favorites": "Remove from favorites", + "Remove from filter": "Remove from filter", + "Remove remote": "Remove remote", + "Remove remote {0}?": "Remove remote {0}?", + "Remove the label {0}": "Remove the label {0}", + "Remove the search and every filter": "Remove the search and every filter", + "Remove the {0} filter": "Remove the {0} filter", + "Remove the {0} filter ({1})": "Remove the {0} filter ({1})", + "Remove worktree {0}?": "Remove worktree {0}?", + "Remove {0}": "Remove {0}", + "Removed": "Removed", + "Removed lines": "Removed lines", + "Removed lines (grey): lines removed on one side only, or the same lines removed on both. No conflict: safe to take.": "Removed lines (grey): lines removed on one side only, or the same lines removed on both. No conflict: safe to take.", + "Removed remote {0}": "Removed remote {0}", + "Removes git's record of the worktree.": "Removes git's record of the worktree.", + "Removes git's record of the worktree; the folder stays.": "Removes git's record of the worktree; the folder stays.", + "Removing…": "Removing…", + "Rename": "Rename", + "Rename branch": "Rename branch", + "Rename branch {0}": "Rename branch {0}", + "Rename it, then check it out.": "Rename it, then check it out.", + "Rename of '{0}'": "Rename of '{0}'", + "Rename on {0}": "Rename on {0}", + "Rename remote": "Rename remote", + "Rename {0}": "Rename {0}", + "Rename {0} on {1} too?": "Rename {0} on {1} too?", + "Renamed": "Renamed", + "Renamed on {0}: {1} → {2}": "Renamed on {0}: {1} → {2}", + "Renamed remote to {0}": "Renamed remote to {0}", + "Renamed to {0}": "Renamed to {0}", + "Rename…": "Rename…", + "Reopen pull request": "Reopen pull request", + "Reopen this pull request": "Reopen this pull request", + "Reopening…": "Reopening…", + "Reorder": "Reorder", + "Reorder 1 commit?": "Reorder 1 commit?", + "Reorder and move those branches": "Reorder and move those branches", + "Reorder plan refused": "Reorder plan refused", + "Reorder this branch only": "Reorder this branch only", + "Reorder {0} commits": "Reorder {0} commits", + "Reorder {0} commits?": "Reorder {0} commits?", + "Reordering stops at a merge — moving a commit past one would flatten it.": "Reordering stops at a merge — moving a commit past one would flatten it.", + "Replace and stage": "Replace and stage", + "Replace the file with {0} and stage it": "Replace the file with {0} and stage it", + "Replace the resolution already in {0}?": "Replace the resolution already in {0}?", + "Replace what you typed with this": "Replace what you typed with this", + "Replace with the left side's text": "Replace with the left side's text", + "Replaces only the versions you rewrote — nobody else's commits are on the remote branch.": "Replaces only the versions you rewrote — nobody else's commits are on the remote branch.", + "Replay your commits on top of theirs. Linear history, new shas.": "Replay your commits on top of theirs. Linear history, new shas.", + "Replaying": "Replaying", + "Reply": "Reply", + "Reply to the conversation on {0}": "Reply to the conversation on {0}", + "Replying…": "Replying…", + "Reply…": "Reply…", + "RepoManager ready — repos={0}, active={1}": "RepoManager ready — repos={0}, active={1}", + "Repository {0}. {1}": "Repository {0}. {1}", + "Repository: {0}. Choose another": "Repository: {0}. Choose another", + "Republish Branch": "Republish Branch", + "Request cancelled.": "Request cancelled.", + "Request changes": "Request changes", + "Required": "Required", + "Required to pass before merging": "Required to pass before merging", + "Required.": "Required.", + "Reset": "Reset", + "Reset --hard": "Reset --hard", + "Reset Branch to Here": "Reset Branch to Here", + "Reset Current Branch to Here…": "Reset Current Branch to Here…", + "Reset column widths": "Reset column widths", + "Reset current branch to {0}": "Reset current branch to {0}", + "Reset merge": "Reset merge", + "Reset plan": "Reset plan", + "Reset the conflicted files?": "Reset the conflicted files?", + "Reset the merge to where it started": "Reset the merge to where it started", + "Reset to '": "Reset to '", + "Reset to {0}": "Reset to {0}", + "Reset to {0} ({1})": "Reset to {0} ({1})", + "Reset {0} to the pull request's version": "Reset {0} to the pull request's version", + "Reset {0} to {1}": "Reset {0} to {1}", + "Reset {0} to {1}?": "Reset {0} to {1}?", + "Reset {0} to {1}…": "Reset {0} to {1}…", + "Resize Commit message / Changes divider": "Resize Commit message / Changes divider", + "Resize the details column": "Resize the details column", + "Resize {0} column": "Resize {0} column", + "Resolve Conflicts…": "Resolve Conflicts…", + "Resolve and stage them first — git can't commit while files are unmerged.": "Resolve and stage them first — git can't commit while files are unmerged.", + "Resolve conversation": "Resolve conversation", + "Resolve every change with theirs — {0}": "Resolve every change with theirs — {0}", + "Resolve every change with yours — {0}": "Resolve every change with yours — {0}", + "Resolve every change with {0}": "Resolve every change with {0}", + "Resolve in Merge Editor": "Resolve in Merge Editor", + "Resolve it change by change in the merge editor": "Resolve it change by change in the merge editor", + "Resolve simple": "Resolve simple", + "Resolve simple conflicts": "Resolve simple conflicts", + "Resolve simple conflicts (apply both sides where their edits don't overlap)": "Resolve simple conflicts (apply both sides where their edits don't overlap)", + "Resolve the last conflicted file first.": "Resolve the last conflicted file first.", + "Resolve the whole file with {0}{1}": "Resolve the whole file with {0}{1}", + "Resolve the {0} conflicted files first.": "Resolve the {0} conflicted files first.", + "Resolve {0} and {1} — or abort it — before {2}.": "Resolve {0} and {1} — or abort it — before {2}.", + "Resolved": "Resolved", + "Resolved (in an editor, or outside this app)": "Resolved (in an editor, or outside this app)", + "Resolved by deleting the file — both sides had deleted it": "Resolved by deleting the file — both sides had deleted it", + "Resolved by deleting the file, as {0}{1} did": "Resolved by deleting the file, as {0}{1} did", + "Resolved by {0}": "Resolved by {0}", + "Resolved in the merge editor": "Resolved in the merge editor", + "Resolved with {0}{1}": "Resolved with {0}{1}", + "Resolved.": "Resolved.", + "Resolving…": "Resolving…", + "Restore": "Restore", + "Restore VS Code's Merge Editor": "Restore VS Code's Merge Editor", + "Restore every column to its default width": "Restore every column to its default width", + "Result": "Result", + "Retry": "Retry", + "Reveal a worktree": "Reveal a worktree", + "Reveal in File Explorer": "Reveal in File Explorer", + "Reveal in File Manager": "Reveal in File Manager", + "Reveal in Finder": "Reveal in Finder", + "Reveal {0} in the graph": "Reveal {0} in the graph", + "Revert": "Revert", + "Revert Commit": "Revert Commit", + "Revert conflicts": "Revert conflicts", + "Revert in progress": "Revert in progress", + "Revert of \"{0}\" needs a decision — resolve any conflicts ": "Revert of \"{0}\" needs a decision — resolve any conflicts ", + "Revert of {0} needs a decision — resolve any ": "Revert of {0} needs a decision — resolve any ", + "Revert stopped": "Revert stopped", + "Revert the merge {0}": "Revert the merge {0}", + "Revert {0}": "Revert {0}", + "Revert {0} Commits": "Revert {0} Commits", + "Revert {0} commits": "Revert {0} commits", + "Reverted {0}": "Reverted {0}", + "Reverted {0} commits.": "Reverted {0} commits.", + "Reverting": "Reverting", + "Reverting {0} commits": "Reverting {0} commits", + "Reverting {0} commits stopped on a commit that needs you — resolve any conflicts and continue, skip that commit, or abort to put the branch back as it was.": "Reverting {0} commits stopped on a commit that needs you — resolve any conflicts and continue, skip that commit, or abort to put the branch back as it was.", + "Reverting {0} on {1}{2}": "Reverting {0} on {1}{2}", + "Review #{0}": "Review #{0}", + "Review ({0} pending)": "Review ({0} pending)", + "Review below, then {0} to commit it.": "Review below, then {0} to commit it.", + "Review below.": "Review below.", + "Review changes with AI": "Review changes with AI", + "Review copied": "Review copied", + "Review requested": "Review requested", + "Review required": "Review required", + "Review submitted on #{0}: {1}.": "Review submitted on #{0}: {1}.", + "Review summary": "Review summary", + "Review threads": "Review threads", + "Review what {0} would push": "Review what {0} would push", + "Reviewers": "Reviewers", + "Reviewers, assignees and labels": "Reviewers, assignees and labels", + "Reviewers, labels and assignees take triage access to {0}. Its maintainers can add them.": "Reviewers, labels and assignees take triage access to {0}. Its maintainers can add them.", + "Reviewing your changes…": "Reviewing your changes…", + "Reviews: {0}": "Reviews: {0}", + "Reword": "Reword", + "Rewrites the remote branch": "Rewrites the remote branch", + "Rewriting published history would break everyone who has already pulled it. GitStudio will Revert instead — a new commit that undoes the change, leaving the original in place.": "Rewriting published history would break everyone who has already pulled it. GitStudio will Revert instead — a new commit that undoes the change, leaving the original in place.", + "Rewriting published history would break everyone who has already pulled it. GitStudio will add a new commit instead that puts the files back as they were before \"{0}\", leaving the pushed commit in place.": "Rewriting published history would break everyone who has already pulled it. GitStudio will add a new commit instead that puts the files back as they were before \"{0}\", leaving the pushed commit in place.", + "Run models on your own machine — fully private, no key.": "Run models on your own machine — fully private, no key.", + "Running": "Running", + "Running for {0}": "Running for {0}", + "SHA": "SHA", + "Same on both sides": "Same on both sides", + "Same on both sides — either arrow takes it": "Same on both sides — either arrow takes it", + "Same on both sides — either arrow takes it (green): both sides added or changed these lines the same way. Nothing to choose.": "Same on both sides — either arrow takes it (green): both sides added or changed these lines the same way. Nothing to choose.", + "Sample": "Sample", + "Sample resolved. In a real conflict, Apply saves and stages the file, then Continue Rebase appears.": "Sample resolved. In a real conflict, Apply saves and stages the file, then Continue Rebase appears.", + "Sample · after": "Sample · after", + "Sample · before": "Sample · before", + "Sample · rebasing feature/session-hardening onto main · commit 2 of 3": "Sample · rebasing feature/session-hardening onto main · commit 2 of 3", + "Sample: authorizeRequest.ts": "Sample: authorizeRequest.ts", + "Save Key": "Save Key", + "Save the result and mark the conflict resolved": "Save the result and mark the conflict resolved", + "Saved {0}, but couldn't stage it.": "Saved {0}, but couldn't stage it.", + "Saved. This file is not in a Git repository, so there is nothing to stage.": "Saved. This file is not in a Git repository, so there is nothing to stage.", + "Search": "Search", + "Search SHA…": "Search SHA…", + "Search authors…": "Search authors…", + "Search branches & tags…": "Search branches & tags…", + "Search branches and actions": "Search branches and actions", + "Search commits": "Search commits", + "Search commits ({0})": "Search commits ({0})", + "Search commits, authors, refs…": "Search commits, authors, refs…", + "Search for branches and actions": "Search for branches and actions", + "Search in": "Search in", + "Search in: {0}": "Search in: {0}", + "Search messages…": "Search messages…", + "Search pull requests": "Search pull requests", + "Search scope": "Search scope", + "Search scope: {0}": "Search scope: {0}", + "Select AI Model": "Select AI Model", + "Select AI Model…": "Select AI Model…", + "Select All (": "Select All (", + "Select Checked (": "Select Checked (", + "Select Unchecked (": "Select Unchecked (", + "Select a commit to see its details": "Select a commit to see its details", + "Select a tag to check out": "Select a tag to check out", + "Select a tag to delete": "Select a tag to delete", + "Select a tag to push": "Select a tag to push", + "Select at least two commits to squash them.": "Select at least two commits to squash them.", + "Select only this commit": "Select only this commit", + "Select only {0}: {1}": "Select only {0}: {1}", + "Selected commits": "Selected commits", + "Send your review as {0}{1}": "Send your review as {0}{1}", + "Sending…": "Sending…", + "Set Anthropic API Key": "Set Anthropic API Key", + "Set OpenAI API Key": "Set OpenAI API Key", + "Set Tracked Branch…": "Set Tracked Branch…", + "Set action": "Set action", + "Set the action of the selected commits": "Set the action of the selected commits", + "Set the base URL to your deployment and append `?api-version=…` if required.": "Set the base URL to your deployment and append `?api-version=…` if required.", + "Set the upstream for which branch?": "Set the upstream for which branch?", + "Set up AI to draft commit messages": "Set up AI to draft commit messages", + "Set upstream": "Set upstream", + "Set upstream for {0}": "Set upstream for {0}", + "Set upstream of {0} → {1}": "Set upstream of {0} → {1}", + "Shift- or ": "Shift- or ", + "Shift- or {0}-click selects several;": "Shift- or {0}-click selects several;", + "Show Commit Graph": "Show Commit Graph", + "Show all branches": "Show all branches", + "Show branches": "Show branches", + "Show checks": "Show checks", + "Show individual changes": "Show individual changes", + "Show it": "Show it", + "Show only this branch": "Show only this branch", + "Show only this tag": "Show only this tag", + "Show or hide columns": "Show or hide columns", + "Show the first": "Show the first", + "Show the next pull requests ({0} of {1} shown)": "Show the next pull requests ({0} of {1} shown)", + "Show the pull requests of": "Show the pull requests of", + "Show the repository of whichever file you are editing.": "Show the repository of whichever file you are editing.", + "Show the terminal": "Show the terminal", + "Show {0}": "Show {0}", + "Show {0} more": "Show {0} more", + "Show {0} more of {1}": "Show {0} more of {1}", + "Showing every branch and tag · tick one to narrow": "Showing every branch and tag · tick one to narrow", + "Showing the latest {0} of {1} commits. Open on GitHub for the rest.": "Showing the latest {0} of {1} commits. Open on GitHub for the rest.", + "Showing the latest {0} of {1} events. ": "Showing the latest {0} of {1} events. ", + "Showing the list as it was {0}.": "Showing the list as it was {0}.", + "Showing the pull request as it was.": "Showing the pull request as it was.", + "Showing the pull requests of {0}. Choose another repository": "Showing the pull requests of {0}. Choose another repository", + "Showing {0} ({1}). Choose another repository": "Showing {0} ({1}). Choose another repository", + "Showing {0} of {1} checks.": "Showing {0} of {1} checks.", + "Showing {0} of {1} files{2}. Open on GitHub for the rest.": "Showing {0} of {1} files{2}. Open on GitHub for the rest.", + "Showing {0} of {1} review threads. Open on GitHub for the rest.": "Showing {0} of {1} review threads. Open on GitHub for the rest.", + "Sign in again": "Sign in again", + "Sign in again to see {0}#{1}.": "Sign in again to see {0}#{1}.", + "Sign in again to see {0}'s pull requests.": "Sign in again to see {0}'s pull requests.", + "Sign in to GitHub": "Sign in to GitHub", + "Sign in to GitHub to open a pull request": "Sign in to GitHub to open a pull request", + "Sign in to GitHub to see pull requests": "Sign in to GitHub to see pull requests", + "Sign in to GitHub, with another account if need be": "Sign in to GitHub, with another account if need be", + "Sign-off": "Sign-off", + "Skip": "Skip", + "Skip This Commit": "Skip This Commit", + "Skip failed.": "Skip failed.", + "Skip isn't offered here.": "Skip isn't offered here.", + "Skip patch": "Skip patch", + "Skip this commit": "Skip this commit", + "Skipped": "Skipped", + "Soft": "Soft", + "Some checks didn't pass": "Some checks didn't pass", + "Some of its commits are not on any other branch, so deleting it may leave them unreachable. Undo can still recover them.": "Some of its commits are not on any other branch, so deleting it may leave them unreachable. Undo can still recover them.", + "Some of these commits are already pushed. {0} them would rewrite history other people have.": "Some of these commits are already pushed. {0} them would rewrite history other people have.", + "Someone deleted or renamed that remote branch.": "Someone deleted or renamed that remote branch.", + "Someone not listed": "Someone not listed", + "Something interrupted reading them — they refresh on their own.": "Something interrupted reading them — they refresh on their own.", + "Split diff": "Split diff", + "Sponsor on GitHub": "Sponsor on GitHub", + "Squash": "Squash", + "Squash Commits": "Squash Commits", + "Squash and merge": "Squash and merge", + "Squash {0} Commits…": "Squash {0} Commits…", + "Squash {0} commits": "Squash {0} commits", + "Squash {0} commits — move the branches too?": "Squash {0} commits — move the branches too?", + "Squashed {0} into one.": "Squashed {0} into one.", + "Squashing": "Squashing", + "Stage": "Stage", + "Stage All": "Stage All", + "Stage All Changes": "Stage All Changes", + "Stage Changes with Ticks": "Stage Changes with Ticks", + "Stage Folder": "Stage Folder", + "Stage all": "Stage all", + "Stage file": "Stage file", + "Stage folder": "Stage folder", + "Stage individually first if you only want some of it.": "Stage individually first if you only want some of it.", + "Stage {0}": "Stage {0}", + "Stage, commit, stash, or discard below": "Stage, commit, stash, or discard below", + "Staged": "Staged", + "Staged 1 change": "Staged 1 change", + "Staged changes": "Staged changes", + "Staged everything else. ": "Staged everything else. ", + "Staged when it was stashed: it comes back staged": "Staged when it was stashed: it comes back staged", + "Staged {0} changes": "Staged {0} changes", + "Staged — click to unstage this change": "Staged — click to unstage this change", + "Staged, then changed again, when it was stashed: both versions come back": "Staged, then changed again, when it was stashed: both versions come back", + "Staging": "Staging", + "Start Interactive Rebase Here…": "Start Interactive Rebase Here…", + "Start Ollama, then `ollama pull qwen2.5-coder`. Nothing leaves your machine.": "Start Ollama, then `ollama pull qwen2.5-coder`. Nothing leaves your machine.", + "Start Rebase": "Start Rebase", + "Start rebase": "Start rebase", + "Start review": "Start review", + "Start the description from": "Start the description from", + "Start the description from one of the repository's templates": "Start the description from one of the repository's templates", + "Start the merge over from {0} as it is now. The work in this editor is not kept.": "Start the merge over from {0} as it is now. The work in this editor is not kept.", + "Start your review": "Start your review", + "Stash": "Stash", + "Stash & Remove": "Stash & Remove", + "Stash & Retry": "Stash & Retry", + "Stash 1 selected file…": "Stash 1 selected file…", + "Stash All Changes": "Stash All Changes", + "Stash Everything Staged": "Stash Everything Staged", + "Stash This File": "Stash This File", + "Stash This Folder": "Stash This Folder", + "Stash all changes…": "Stash all changes…", + "Stash applied": "Stash applied", + "Stash apply cancelled — the files are back as they were, and the stash is still in your list.": "Stash apply cancelled — the files are back as they were, and the stash is still in your list.", + "Stash conflicts": "Stash conflicts", + "Stash everything staged ({0} {1})": "Stash everything staged ({0} {1})", + "Stash {0}": "Stash {0}", + "Stash {0} and try again, or commit {1} first.": "Stash {0} and try again, or commit {1} first.", + "Stash {0} selected files…": "Stash {0} selected files…", + "Stash {0} {1}": "Stash {0} {1}", + "Stash {0}, run it again, and put {1} back.": "Stash {0}, run it again, and put {1} back.", + "Stash “{0}”": "Stash “{0}”", + "Stashed by GitHub Desktop": "Stashed by GitHub Desktop", + "Stashed {0}": "Stashed {0}", + "Stashes": "Stashes", + "Stashes — click to hide them": "Stashes — click to hide them", + "Stashes — click to show them": "Stashes — click to show them", + "Stashes, {0}": "Stashes, {0}", + "Stashing the staged changes of specific files is not supported by git — ": "Stashing the staged changes of specific files is not supported by git — ", + "Status": "Status", + "Stay on {0} as it is": "Stay on {0} as it is", + "Stop Tracking": "Stop Tracking", + "Stopped again — there are conflicts to resolve.": "Stopped again — there are conflicts to resolve.", + "Stopped at {0} {1} of {2}": "Stopped at {0} {1} of {2}", + "Stopped at {0} {1} of {2} — it has conflicts to resolve.": "Stopped at {0} {1} of {2} — it has conflicts to resolve.", + "Stream from Anthropic failed.": "Stream from Anthropic failed.", + "Stream from {0} failed.": "Stream from {0} failed.", + "Subject line: 1 character. Keep it to 50.": "Subject line: 1 character. Keep it to 50.", + "Subject line: {0} characters, over 50. Aim for 50; 72 at most.": "Subject line: {0} characters, over 50. Aim for 50; 72 at most.", + "Subject line: {0} characters, over 72. GitHub cuts a longer subject short.": "Subject line: {0} characters, over 72. GitHub cuts a longer subject short.", + "Subject line: {0} characters. Keep it to 50.": "Subject line: {0} characters. Keep it to 50.", + "Submit": "Submit", + "Submit review": "Submit review", + "Submit your review — {0} will be sent with it": "Submit your review — {0} will be sent with it", + "Submitting…": "Submitting…", + "Success — the model replied. You're all set.": "Success — the model replied. You're all set.", + "Summarize Changes": "Summarize Changes", + "Summarizing with AI…": "Summarizing with AI…", + "Summarizing your changes…": "Summarizing your changes…", + "Summary": "Summary", + "Support GitStudio": "Support GitStudio", + "Swap base and compare": "Swap base and compare", + "Switch Repository": "Switch Repository", + "Switch back to '{0}'.": "Switch back to '{0}'.", + "Switch repository (": "Switch repository (", + "Switch to checkboxes": "Switch to checkboxes", + "Switch to local {0}": "Switch to local {0}", + "Switch to staged / unstaged": "Switch to staged / unstaged", + "Switch to the new branch after creating it?": "Switch to the new branch after creating it?", + "Switch to {0}": "Switch to {0}", + "Switched to {0}": "Switched to {0}", + "Synced": "Synced", + "Synchronized scrolling": "Synchronized scrolling", + "Tag": "Tag", + "Tags": "Tags", + "Template": "Template", + "Template: {0}": "Template: {0}", + "Test failed.": "Test failed.", + "That change is no longer there — the file moved underneath. Refresh and try again.": "That change is no longer there — the file moved underneath. Refresh and try again.", + "That commit is too far down the branch to drop from here. Start an interactive rebase from it instead.": "That commit is too far down the branch to drop from here. Start an interactive rebase from it instead.", + "That commit isn't on the current branch, so there's nothing to drop it from.": "That commit isn't on the current branch, so there's nothing to drop it from.", + "That isn't a drop this app made.": "That isn't a drop this app made.", + "That isn't a stash this app recorded.": "That isn't a stash this app recorded.", + "That isn't a usable file path.": "That isn't a usable file path.", + "That isn't a {0} this app made.": "That isn't a {0} this app made.", + "That path escapes the repository — nothing was changed.": "That path escapes the repository — nothing was changed.", + "That puts back only what it changed, and only where nothing has moved since.": "That puts back only what it changed, and only where nothing has moved since.", + "That stash is no longer in the list, so nothing was changed.": "That stash is no longer in the list, so nothing was changed.", + "That stash is no longer in the list.": "That stash is no longer in the list.", + "That stash is no longer in the repository.": "That stash is no longer in the repository.", + "That stash no longer exists.": "That stash no longer exists.", + "That's a merge commit — dropping it would flatten the history it joined. Revert it instead.": "That's a merge commit — dropping it would flatten the history it joined. Revert it instead.", + "That's the only commit on the branch — dropping it would leave nothing.": "That's the only commit on the branch — dropping it would leave nothing.", + "The AI had nothing to say about this change": "The AI had nothing to say about this change", + "The Anthropic API key is missing or invalid. Run “GitStudio: Set Anthropic API Key…”.": "The Anthropic API key is missing or invalid. Run “GitStudio: Set Anthropic API Key…”.", + "The OpenAI-compatible endpoint rejected the API key (401). Run “GitStudio: Set OpenAI API Key”, or clear it for a local server.": "The OpenAI-compatible endpoint rejected the API key (401). Run “GitStudio: Set OpenAI API Key”, or clear it for a local server.", + "The OpenAI-compatible endpoint returned 404 — check the base URL and model ID in settings.": "The OpenAI-compatible endpoint returned 404 — check the base URL and model ID in settings.", + "The branch action": "The branch action", + "The branch goes back to where it was before the rebase started. No commits are changed.": "The branch goes back to where it was before the rebase started. No commits are changed.", + "The branch goes back to where it was before the series started. Patches already applied are ": "The branch goes back to where it was before the series started. Patches already applied are ", + "The branch has moved since the {0}, so undoing it now would throw that away too. Nothing was changed.": "The branch has moved since the {0}, so undoing it now would throw that away too. Nothing was changed.", + "The branch has moved since you chose Drop, so nothing was dropped. Look at the history again and retry.": "The branch has moved since you chose Drop, so nothing was dropped. Look at the history again and retry.", + "The branch has moved since you chose these commits, so nothing was changed. Look at the history again and retry.": "The branch has moved since you chose these commits, so nothing was changed. Look at the history again and retry.", + "The branch is back": "The branch is back", + "The branch is created at the current HEAD and checked out in the new worktree.": "The branch is created at the current HEAD and checked out in the new worktree.", + "The branch it comes from": "The branch it comes from", + "The branch it goes into": "The branch it goes into", + "The branch it {0} into": "The branch it {0} into", + "The branch label is removed. Its commits stay reachable from anywhere else that points at them, and GitStudio's Undo can put the branch back.": "The branch label is removed. Its commits stay reachable from anywhere else that points at them, and GitStudio's Undo can put the branch back.", + "The branch moved on since this page read it. Refresh, look at what changed, and merge again.": "The branch moved on since this page read it. Refresh, look at what changed, and merge again.", + "The branch starts at HEAD.": "The branch starts at HEAD.", + "The branch starts at {0}.": "The branch starts at {0}.", + "The branch {0} and its commits stay.": "The branch {0} and its commits stay.", + "The change is good to merge": "The change is good to merge", + "The changed file goes back to its committed version.": "The changed file goes back to its committed version.", + "The changes it made to your working tree are taken back.": "The changes it made to your working tree are taken back.", + "The changes you stashed, being put back": "The changes you stashed, being put back", + "The code it was written on has changed since": "The code it was written on has changed since", + "The commit after it will be replayed on top, with a new SHA.": "The commit after it will be replayed on top, with a new SHA.", + "The commit being cherry-picked": "The commit being cherry-picked", + "The commit being cherry-picked: {0} “{1}”": "The commit being cherry-picked: {0} “{1}”", + "The commit is": "The commit is", + "The commit is added to {0} as one new commit.": "The commit is added to {0} as one new commit.", + "The commits HEAD has that {0} does not are rewritten on top of it, so they get new shas. HEAD is on no branch, so they are on no branch either: create a branch from them to keep them. Undo can take you back.": "The commits HEAD has that {0} does not are rewritten on top of it, so they get new shas. HEAD is on no branch, so they are on no branch either: create a branch from them to keep them. Undo can take you back.", + "The conflict is back, but {0} couldn't be restored on disk.": "The conflict is back, but {0} couldn't be restored on disk.", + "The conflicted files are back to their last committed versions.": "The conflicted files are back to their last committed versions.", + "The conflicts list: every conflicted file of this {0}, and {1}{2}": "The conflicts list: every conflicted file of this {0}, and {1}{2}", + "The current commit": "The current commit", + "The dropped commit is back": "The dropped commit is back", + "The file goes back to its committed version. {0}": "The file goes back to its committed version. {0}", + "The file is deleted. Git has never tracked it, so nothing — not even Undo — can bring it back.": "The file is deleted. Git has never tracked it, so nothing — not even Undo — can bring it back.", + "The file is saved, but git could not stage it ({0}). Stage it with git add before you continue.": "The file is saved, but git could not stage it ({0}). Stage it with git add before you continue.", + "The file was saved but could not be staged.": "The file was saved but could not be staged.", + "The files go back to how they were before the stash was applied. The stash itself stays in ": "The files go back to how they were before the stash was applied. The stash itself stays in ", + "The first commit — there is nothing below it to reorder past.": "The first commit — there is nothing below it to reorder past.", + "The first parent — usually what you want.": "The first parent — usually what you want.", + "The first {0} of {1} commits.": "The first {0} of {1} commits.", + "The index survives, so a partly staged commit stays ready.": "The index survives, so a partly staged commit stays ready.", + "The last committed version of this file.": "The last committed version of this file.", + "The main worktree holds the repository itself, so git can't lock it.": "The main worktree holds the repository itself, so git can't lock it.", + "The main worktree holds the repository itself, so git never removes it.": "The main worktree holds the repository itself, so git never removes it.", + "The model declined this request.": "The model declined this request.", + "The model request failed.": "The model request failed.", + "The new worktree's folder. Suggested {0}, as {1}; change it if you like — it must not exist yet, or be empty.": "The new worktree's folder. Suggested {0}, as {1}; change it if you like — it must not exist yet, or be empty.", + "The oldest commit can't be \"{0}\" — there's nothing older for it to fold into.": "The oldest commit can't be \"{0}\" — there's nothing older for it to fold into.", + "The operation": "The operation", + "The operation was aborted": "The operation was aborted", + "The operation {0} was resolved in has finished — its conflict can't be brought back.": "The operation {0} was resolved in has finished — its conflict can't be brought back.", + "The other side of the conflict": "The other side of the conflict", + "The page follows as it happens.": "The page follows as it happens.", + "The patch being applied": "The patch being applied", + "The patch git is stuck on": "The patch git is stuck on", + "The patch series was abandoned, but HEAD had moved since it started, so git left it ": "The patch series was abandoned, but HEAD had moved since it started, so git left it ", + "The pull request isn't loaded yet.": "The pull request isn't loaded yet.", + "The pull request's page": "The pull request's page", + "The pull stopped on conflicts in {0}. Resolve {1}, ": "The pull stopped on conflicts in {0}. Resolve {1}, ", + "The pull would overwrite your uncommitted changes to {0}. Commit or stash {1}, then pull again.": "The pull would overwrite your uncommitted changes to {0}. Commit or stash {1}, then pull again.", + "The rebase is still stopped.": "The rebase is still stopped.", + "The reflog is empty": "The reflog is empty", + "The remote branch has commits this branch has never had — fetched in the background, ": "The remote branch has commits this branch has never had — fetched in the background, ", + "The remote refused a normal push. This uses --force-with-lease, ": "The remote refused a normal push. This uses --force-with-lease, ", + "The remote still has the commits you replaced — amending a pushed ": "The remote still has the commits you replaced — amending a pushed ", + "The remote-tracking branch this branch pushes to and compares against.": "The remote-tracking branch this branch pushes to and compares against.", + "The repository PR #{0}'s branch came from is gone": "The repository PR #{0}'s branch came from is gone", + "The repository changed while you were being asked, so \"{0}\" wasn't undone. Try Undo again.": "The repository changed while you were being asked, so \"{0}\" wasn't undone. Try Undo again.", + "The repository goes back to how it was before the {0} started. Conflicts you have already ": "The repository goes back to how it was before the {0} started. Conflicts you have already ", + "The repository has no remote to pull from.": "The repository has no remote to pull from.", + "The repository has no remote to push to.": "The repository has no remote to push to.", + "The repository it opens on": "The repository it opens on", + "The repository's hooks run as it merges.": "The repository's hooks run as it merges.", + "The resolution leaves nothing to commit for this commit. Skip it instead.": "The resolution leaves nothing to commit for this commit. Skip it instead.", + "The reverse of commit {0} “{1}”": "The reverse of commit {0} “{1}”", + "The reverse of the commit being reverted": "The reverse of the commit being reverted", + "The rules that protect {0} aren't met yet.": "The rules that protect {0} aren't met yet.", + "The short name you'll refer to it by — origin, upstream, fork.": "The short name you'll refer to it by — origin, upstream, fork.", + "The squashed commit needs a message.": "The squashed commit needs a message.", + "The staged deletions could not be stashed.": "The staged deletions could not be stashed.", + "The stash hit conflicts. Resolve them, or cancel to put the files back — the stash is kept.": "The stash hit conflicts. Resolve them, or cancel to put the files back — the stash is kept.", + "The stash is applied on the new branch and dropped once it applies cleanly.": "The stash is applied on the new branch and dropped once it applies cleanly.", + "The stash is back, but the ones that were above it couldn't all be put back on top: ": "The stash is back, but the ones that were above it couldn't all be put back on top: ", + "The stash leaves": "The stash leaves", + "The stash “{0}” it made is kept: it holds more than Undo puts back.": "The stash “{0}” it made is kept: it holds more than Undo puts back.", + "The uncommitted changes you had before it can't come back — git couldn't keep a copy of them {0}.": "The uncommitted changes you had before it can't come back — git couldn't keep a copy of them {0}.", + "The uncommitted changes you had then come back too.": "The uncommitted changes you had then come back too.", + "The untracked file is deleted.": "The untracked file is deleted.", + "The version on {0}": "The version on {0}", + "The worktree at {0} is locked.": "The worktree at {0} is locked.", + "The {0} commit you keep can't be {1} — there's nothing {2} it to fold into.": "The {0} commit you keep can't be {1} — there's nothing {2} it to fold into.", + "The {0} commits after it will be replayed on top, with new SHAs.": "The {0} commits after it will be replayed on top, with new SHAs.", + "The {0} commits are": "The {0} commits are", + "The {0} commits become one commit on {1}.": "The {0} commits become one commit on {1}.", + "The {0} in progress is abandoned.": "The {0} in progress is abandoned.", + "The {0} is": "The {0} is", + "The {0} later commits will be replayed on top, with new SHAs.": "The {0} later commits will be replayed on top, with new SHAs.", + "The {0} stays paused, and ": "The {0} stays paused, and ", + "The {0} untracked files are deleted.": "The {0} untracked files are deleted.", + "The {0} was stopped, but HEAD had moved since its ": "The {0} was stopped, but HEAD had moved since its ", + "Their changes come": "Their changes come", + "Their changes return as unstaged edits.": "Their changes return as unstaged edits.", + "Their changes return to the Staged group, ready to re-commit.": "Their changes return to the Staged group, ready to re-commit.", + "Theirs": "Theirs", + "There are unresolved conflicts — resolve them or cancel first.": "There are unresolved conflicts — resolve them or cancel first.", + "There is no '{0}' to reset to — it is not on {1} any more.": "There is no '{0}' to reset to — it is not on {1} any more.", + "There is no '{0}' to reset to, and {1} couldn't be reached to fetch it.": "There is no '{0}' to reset to, and {1} couldn't be reached to fetch it.", + "There is no Apply to undo here any more.": "There is no Apply to undo here any more.", + "There is no earlier conflict to bring back for {0}.": "There is no earlier conflict to bring back for {0}.", + "There is nothing git can skip here.": "There is nothing git can skip here.", + "There is nothing to abort.": "There is nothing to abort.", + "There is nothing to continue in the {0}.": "There is nothing to continue in the {0}.", + "There is nothing to continue.": "There is nothing to continue.", + "There's a merge between that commit and the tip of the branch — replaying the commits after it would flatten the merge.": "There's a merge between that commit and the tip of the branch — replaying the commits after it would flatten the merge.", + "There's a merge between those commits and the tip of the branch — replaying the commits after them would flatten the merge.": "There's a merge between those commits and the tip of the branch — replaying the commits after them would flatten the merge.", + "There's already a branch named {0}": "There's already a branch named {0}", + "These edits were never committed, so nothing — not even Undo — can bring them back.": "These edits were never committed, so nothing — not even Undo — can bring them back.", + "These {0} files": "These {0} files", + "They are rewritten, so they get new identities. Undo is available afterwards.": "They are rewritten, so they get new identities. Undo is available afterwards.", + "They can't be stashed without knowing what they are.": "They can't be stashed without knowing what they are.", + "They follow onto the replayed commits.": "They follow onto the replayed commits.", + "They follow onto the rewritten commits.": "They follow onto the rewritten commits.", + "They haven't been sent to GitHub, and discarding them can't be undone.": "They haven't been sent to GitHub, and discarding them can't be undone.", + "They keep pointing at the commits as they are now.": "They keep pointing at the commits as they are now.", + "They stay": "They stay", + "They're": "They're", + "This branch": "This branch", + "This branch has conflicts": "This branch has conflicts", + "This branch is out of date with {0}, and the repository requires it to be up to date. Update the branch to merge it.": "This branch is out of date with {0}, and the repository requires it to be up to date. Update the branch to merge it.", + "This branch still tracks {0}/{1} — renaming locally doesn't rename it on the remote.": "This branch still tracks {0}/{1} — renaming locally doesn't rename it on the remote.", + "This branch was rewritten": "This branch was rewritten", + "This commit": "This commit", + "This commit exists only in your local repository.": "This commit exists only in your local repository.", + "This commit resolved": "This commit resolved", + "This conversation is resolved": "This conversation is resolved", + "This deletes the tag locally. If it was already pushed, it stays on the remote until you delete it there too.": "This deletes the tag locally. If it was already pushed, it stays on the remote until you delete it there too.", + "This file can only be staged whole — it is binary or too large to stage change by change.": "This file can only be staged whole — it is binary or too large to stage change by change.", + "This file is done. {0} still {1} conflicts.": "This file is done. {0} still {1} conflicts.", + "This file is not in a Git repository, so there is no conflict to resolve.": "This file is not in a Git repository, so there is no conflict to resolve.", + "This file is not in a Git repository.": "This file is not in a Git repository.", + "This file is not inside an open Git repository": "This file is not inside an open Git repository", + "This file was already resolved outside the merge editor (by hand, or by git rerere): the Result starts from it. ": "This file was already resolved outside the merge editor (by hand, or by git rerere): the Result starts from it. ", + "This line has local, not-yet-committed edits.": "This line has local, not-yet-committed edits.", + "This merge has {0} parents. Which one should be kept as the mainline?": "This merge has {0} parents. Which one should be kept as the mainline?", + "This pull request is still a draft": "This pull request is still a draft", + "This pull request is {0}": "This pull request is {0}", + "This pull request's branch is the one checked out here. Updated {0}": "This pull request's branch is the one checked out here. Updated {0}", + "This removes the branch from the remote for everyone, not just from your copy. Your local {0} (if you have one) is untouched.": "This removes the branch from the remote for everyone, not just from your copy. Your local {0} (if you have one) is untouched.", + "This replaces only the versions you rewrote — nobody else's commits are on the remote branch.": "This replaces only the versions you rewrote — nobody else's commits are on the remote branch.", + "This repository has no GitHub remote": "This repository has no GitHub remote", + "This repository has no branches yet": "This repository has no branches yet", + "This repository has no remote for {0}, so its pull requests can't be checked out here.": "This repository has no remote for {0}, so its pull requests can't be checked out here.", + "This repository has no remotes": "This repository has no remotes", + "This repository has no remotes, so there is nothing to fetch from or push to.": "This repository has no remotes, so there is nothing to fetch from or push to.", + "This repository has no remotes. Pull requests show here once a remote points at github.com.": "This repository has no remotes. Pull requests show here once a remote points at github.com.", + "This repository isn't connected to GitHub.": "This repository isn't connected to GitHub.", + "This repository isn't on GitHub": "This repository isn't on GitHub", + "This tab has {0} open, so it can't be removed from here — its folder would be deleted from under the tab. Close this tab, then remove it from another worktree of the repository.": "This tab has {0} open, so it can't be removed from here — its folder would be deleted from under the tab. Close this tab, then remove it from another worktree of the repository.", + "This takes a moment after a push. Refresh to see.": "This takes a moment after a push. Refresh to see.", + "This window": "This window", + "This window has it open — its folder would be deleted from under the window.": "This window has it open — its folder would be deleted from under the window.", + "This window has it open.": "This window has it open.", + "This window has {0} open, so it can't be removed from here — its folder would be deleted from under the window. Remove it from another window, or open something else in this one first.": "This window has {0} open, so it can't be removed from here — its folder would be deleted from under the window. Remove it from another window, or open something else in this one first.", + "Those are all the commits on the branch — dropping them would leave nothing.": "Those are all the commits on the branch — dropping them would leave nothing.", + "Those changes are no longer there — refresh and try again.": "Those changes are no longer there — refresh and try again.", + "Those commits are too far down the branch to {0} from here. Start an interactive rebase instead.": "Those commits are too far down the branch to {0} from here. Start an interactive rebase instead.", + "Throw your pending comments away without sending them": "Throw your pending comments away without sending them", + "Tidy up your recent commits before you push.": "Tidy up your recent commits before you push.", + "Timed out": "Timed out", + "Timed out after 15s — is the server running and the model loaded?": "Timed out after 15s — is the server running and the model loaded?", + "Title": "Title", + "To pull from {0}": "To pull from {0}", + "Together AI": "Together AI", + "Toggle columns": "Toggle columns", + "Toggle file tree": "Toggle file tree", + "Too large to merge here": "Too large to merge here", + "Took": "Took", + "Took both": "Took both", + "Took the change (the same on both sides)": "Took the change (the same on both sides)", + "Took {0}": "Took {0}", + "Tracked Branch: {0}…": "Tracked Branch: {0}…", + "Trim whitespaces": "Trim whitespaces", + "Turn them off": "Turn them off", + "Type changed": "Type changed", + "Uncheck all": "Uncheck all", + "Uncommitted": "Uncommitted", + "Uncommitted changes": "Uncommitted changes", + "Uncommitted changes to {0} will be discarded.": "Uncommitted changes to {0} will be discarded.", + "Uncommitted changes you have made since are discarded.": "Uncommitted changes you have made since are discarded.", + "Uncommitted changes — open in the Commit Graph for details": "Uncommitted changes — open in the Commit Graph for details", + "Undid {0}": "Undid {0}", + "Undo": "Undo", + "Undo \"{0}\"?{1}": "Undo \"{0}\"?{1}", + "Undo ({0}Z)": "Undo ({0}Z)", + "Undo History": "Undo History", + "Undo commits…": "Undo commits…", + "Undo couldn't abandon the rebase: {0}": "Undo couldn't abandon the rebase: {0}", + "Undo couldn't go back to {0} without overwriting your uncommitted changes: {1}": "Undo couldn't go back to {0} without overwriting your uncommitted changes: {1}", + "Undo couldn't put your working tree back: {0}": "Undo couldn't put your working tree back: {0}", + "Undo couldn't switch back to {0}: {1}": "Undo couldn't switch back to {0}: {1}", + "Undo couldn't {0}: {1}": "Undo couldn't {0}: {1}", + "Undo failed: could not reset to {0}: {1}": "Undo failed: could not reset to {0}: {1}", + "Undo is available afterwards.": "Undo is available afterwards.", + "Undo of the reverted commit": "Undo of the reverted commit", + "Undo of {0}": "Undo of {0}", + "Undo put things back, but couldn't end the {0} in progress: {1}": "Undo put things back, but couldn't end the {0} in progress: {1}", + "Undo put your changes back, but couldn't drop the stash “{0}”: {1}": "Undo put your changes back, but couldn't drop the stash “{0}”: {1}", + "Undo restored the commit but re-applying your uncommitted changes hit a conflict: {0} ": "Undo restored the commit but re-applying your uncommitted changes hit a conflict: {0} ", + "Undo the Apply: bring the conflict back into the file": "Undo the Apply: bring the conflict back into the file", + "Undo these local commits — reset them back to staged / unstaged changes": "Undo these local commits — reset them back to staged / unstaged changes", + "Undo this operation — and, newest first, every one after it.": "Undo this operation — and, newest first, every one after it.", + "Undo {0} local {1}": "Undo {0} local {1}", + "Undone — click to re-apply up to here": "Undone — click to re-apply up to here", + "Unified diff": "Unified diff", + "Unknown ref: {0}": "Unknown ref: {0}", + "Unlock": "Unlock", + "Unlock a worktree": "Unlock a worktree", + "Unlock and Forget": "Unlock and Forget", + "Unlock and Remove": "Unlock and Remove", + "Unlock, Discard Changes and Remove": "Unlock, Discard Changes and Remove", + "Unlock, Stash & Remove": "Unlock, Stash & Remove", + "Unlocked the worktree {0}": "Unlocked the worktree {0}", + "Unmerged files": "Unmerged files", + "Unmerged files on {0}": "Unmerged files on {0}", + "Unresolve": "Unresolve", + "Unresolving…": "Unresolving…", + "Unset upstream": "Unset upstream", + "Unstage": "Unstage", + "Unstage All": "Unstage All", + "Unstage Folder": "Unstage Folder", + "Unstage all": "Unstage all", + "Unstage file": "Unstage file", + "Unstage folder": "Unstage folder", + "Unstage {0}": "Unstage {0}", + "Unstaged": "Unstaged", + "Unstaged edits are lost; {0}.": "Unstaged edits are lost; {0}.", + "Unstaged selection": "Unstaged selection", + "Untracked": "Untracked", + "Up arrow": "Up arrow", + "Up to date with upstream": "Up to date with upstream", + "Up to date with {0}.": "Up to date with {0}.", + "Update URL": "Update URL", + "Update branch": "Update branch", + "Update it to the latest": "Update it to the latest", + "Update this remote's branches.": "Update this remote's branches.", + "Updated {0}": "Updated {0}", + "Updated {0} URL": "Updated {0} URL", + "Updated {0} to the latest of PR #{1} ({2} brought in).{3}": "Updated {0} to the latest of PR #{1} ({2} brought in).{3}", + "Updated {0} to the latest of PR #{1}.": "Updated {0} to the latest of PR #{1}.", + "Updating…": "Updating…", + "Upstream gone": "Upstream gone", + "Use": "Use", + "Use Anthropic directly with your API key.": "Use Anthropic directly with your API key.", + "Use instead": "Use instead", + "Use letters, digits, dot, dash or underscore.": "Use letters, digits, dot, dash or underscore.", + "Use {0}": "Use {0}", + "Uses --force-with-lease, which still refuses to overwrite remote work you haven't seen.": "Uses --force-with-lease, which still refuses to overwrite remote work you haven't seen.", + "VS Code Language Model (zero-key) — Copilot / Cursor": "VS Code Language Model (zero-key) — Copilot / Cursor", + "VS Code's own merge editor and conflict highlights are as they were.": "VS Code's own merge editor and conflict highlights are as they were.", + "VS Code's own merge editor and conflict highlights are off.": "VS Code's own merge editor and conflict highlights are off.", + "View as List": "View as List", + "View as Tree": "View as Tree", + "WIP: …": "WIP: …", + "Waiting": "Waiting", + "Waiting for the model…": "Waiting for the model…", + "Waiting on {0}.": "Waiting on {0}.", + "What is being merged in: {0}": "What is being merged in: {0}", + "What is committed on {0} now": "What is committed on {0} now", + "What should the new worktree be based on?": "What should the new worktree be based on?", + "What the colours and lines mean": "What the colours and lines mean", + "What the colours mean": "What the colours mean", + "What the merge colours and lines mean": "What the merge colours and lines mean", + "What the pull request does": "What the pull request does", + "What the pull request will have": "What the pull request will have", + "What this change does, in plain language": "What this change does, in plain language", + "When \"{0}\" ran, git couldn't keep a copy of your uncommitted changes {1}, ": "When \"{0}\" ran, git couldn't keep a copy of your uncommitted changes {1}, ", + "Where a file was staged and then changed again, its staged version is not kept.": "Where a file was staged and then changed again, its staged version is not kept.", + "Where should the committed changes go? Your work is kept either way.": "Where should the committed changes go? Your work is kept either way.", + "Where this remote fetches from and pushes to.": "Where this remote fetches from and pushes to.", + "Which branch is checked out changed while you were being asked. Nothing was reset — try again.": "Which branch is checked out changed while you were being asked. Nothing was reset — try again.", + "Which model should the AI features use?": "Which model should the AI features use?", + "Which pull requests": "Which pull requests", + "Whitespace handling": "Whitespace handling", + "Why?": "Why?", + "Work on another branch, side by side": "Work on another branch, side by side", + "Working": "Working", + "Working Tree": "Working Tree", + "Working Tree vs HEAD": "Working Tree vs HEAD", + "Working tree clean": "Working tree clean", + "Working…": "Working…", + "Worktree from '{0}'": "Worktree from '{0}'", + "Worktrees": "Worktrees", + "Write a comment (a Comment review needs one)": "Write a comment (a Comment review needs one)", + "Write the description from the commits and the diff with AI (replaces what is there)": "Write the description from the commits and the diff with AI (replaces what is there)", + "Written on {0} — the pull request has moved on to {1}. They are sent on the commit they were written on.": "Written on {0} — the pull request has moved on to {1}. They are sent on the commit they were written on.", + "You": "You", + "You (@{0})": "You (@{0})", + "You have uncommitted changes": "You have uncommitted changes", + "You have uncommitted changes. Commit or stash them, then drop the commit.": "You have uncommitted changes. Commit or stash them, then drop the commit.", + "You have uncommitted changes. Commit or stash them, then drop the commits.": "You have uncommitted changes. Commit or stash them, then drop the commits.", + "You have uncommitted changes. Commit or stash them, then squash the commits.": "You have uncommitted changes. Commit or stash them, then squash the commits.", + "You have uncommitted changes. Commit or stash them, then start the rebase.": "You have uncommitted changes. Commit or stash them, then start the rebase.", + "You have {0} {1} doesn't, and it has {2} you don't. ": "You have {0} {1} doesn't, and it has {2} you don't. ", + "You rewrote a commit the remote already has, so a normal push is refused. ": "You rewrote a commit the remote already has, so a normal push is refused. ", + "You'll be on a detached HEAD — commits made here belong to no branch until you create one.": "You'll be on a detached HEAD — commits made here belong to no branch until you create one.", + "You'll be on a detached HEAD — not on any branch. Commits made here belong to nothing until you create a branch for them.": "You'll be on a detached HEAD — not on any branch. Commits made here belong to nothing until you create a branch for them.", + "You're already on {0}, the branch of PR #{1}{2}.{3}": "You're already on {0}, the branch of PR #{1}{2}.{3}", + "You're on {0}, the branch of PR #{1}: {2}.{3}": "You're on {0}, the branch of PR #{1}: {2}.{3}", + "You've made commits on the detached HEAD since (it is at {0} now), and switching back would leave them on no branch. Create a branch for them first, then undo.": "You've made commits on the detached HEAD since (it is at {0} now), and switching back would leave them on no branch. Create a branch for them first, then undo.", + "Your GitHub session expired": "Your GitHub session expired", + "Your GitHub session expired. Sign in again to continue.": "Your GitHub session expired. Sign in again to continue.", + "Your branch {0}": "Your branch {0}", + "Your branch {0}, as it was before the merge": "Your branch {0}, as it was before the merge", + "Your changes to {0} are kept in the stash {1} — git won't put them back ": "Your changes to {0} are kept in the stash {1} — git won't put them back ", + "Your changes to {0} are waiting in the stash {1} — ": "Your changes to {0} are waiting in the stash {1} — ", + "Your changes to {0} were put back, but they conflict with what came in — ": "Your changes to {0} were put back, but they conflict with what came in — ", + "Your comment is back in its box.": "Your comment is back in its box.", + "Your commit a1b2c3d “{0}” from feature/session-hardening": "Your commit a1b2c3d “{0}” from feature/session-hardening", + "Your commit {0} “{1}” from {2}": "Your commit {0} “{1}” from {2}", + "Your commits stay. The PR's newer commits aren't brought in.": "Your commits stay. The PR's newer commits aren't brought in.", + "Your commits stay. The pull request's newer commits aren't brought in: pull to merge them.": "Your commits stay. The pull request's newer commits aren't brought in: pull to merge them.", + "Your history will appear here after the first commit.": "Your history will appear here after the first commit.", + "Your local commits are rewritten on top of {0}, so they get new shas. If you have already pushed them, the next push needs a force. Undo can take you back.": "Your local commits are rewritten on top of {0}, so they get new shas. If you have already pushed them, the next push needs a force. Undo can take you back.", + "Your reply is back in its box.": "Your reply is back in its box.", + "Your resolution leaves {0} “{1}” with no changes, so continuing drops it ": "Your resolution leaves {0} “{1}” with no changes, so continuing drops it ", + "Your review": "Your review", + "Your review of {0}/{1}#{2}{3}: {4}. Click to submit it.": "Your review of {0}/{1}#{2}{3}: {4}. Click to submit it.", + "Your reviews of {0}: {1}. Click to submit one.": "Your reviews of {0}: {1}. Click to submit one.", + "Your stashed changes": "Your stashed changes", + "Your uncommitted changes are in the way": "Your uncommitted changes are in the way", + "Your uncommitted changes are kept.": "Your uncommitted changes are kept.", + "Your uncommitted changes come along.": "Your uncommitted changes come along.", + "Your uncommitted changes come back as they were before it.": "Your uncommitted changes come back as they were before it.", + "Your uncommitted changes go back to how they were before it.": "Your uncommitted changes go back to how they were before it.", + "Your uncommitted changes to {0} are in the way of creating the branch “{1}” ": "Your uncommitted changes to {0} are in the way of creating the branch “{1}” ", + "Your uncommitted changes to {0} are in the way of {1} — ": "Your uncommitted changes to {0} are in the way of {1} — ", + "Your uncommitted changes touch files the {0} changed. Commit or stash them, then undo.": "Your uncommitted changes touch files the {0} changed. Commit or stash them, then undo.", + "Your verdict": "Your verdict", + "Your {0} replaced the {1} the remote still has — amending a pushed commit does this. Pulling would bring the old one back.": "Your {0} replaced the {1} the remote still has — amending a pushed commit does this. Pulling would bring the old one back.", + "Yours": "Yours", + "Yours {0}, theirs {1}: the result keeps {2}.": "Yours {0}, theirs {1}: the result keeps {2}.", + "[$(arrow-up) Push](command:gitstudio.sync.push)": "[$(arrow-up) Push](command:gitstudio.sync.push)", + "[$(repo-fetch) Fetch](command:gitstudio.sync.fetch)": "[$(repo-fetch) Fetch](command:gitstudio.sync.fetch)", + "`git stash apply {0}` brings them back.": "`git stash apply {0}` brings them back.", + "a branch not listed": "a branch not listed", + "a cherry-pick": "a cherry-pick", + "a commit": "a commit", + "a deleted account": "a deleted account", + "a few minutes": "a few minutes", + "a fork that was deleted": "a fork that was deleted", + "a merge": "a merge", + "a new file": "a new file", + "a new or renamed file": "a new or renamed file", + "a new root": "a new root", + "a patch": "a patch", + "a rebase": "a rebase", + "a renamed file": "a renamed file", + "a revert": "a revert", + "a signal": "a signal", + "a {0}": "a {0}", + "above": "above", + "add its assignees": "add its assignees", + "add its labels": "add its labels", + "added on both sides": "added on both sides", + "added on one side": "added on one side", + "all": "all", + "all changes": "all changes", + "already made are still there. Check the log before carrying on.": "already made are still there. Check the log before carrying on.", + "an operation": "an operation", + "an unknown revision": "an unknown revision", + "an {0}": "an {0}", + "and Undo (⌘⌥G Z) reverses it.": "and Undo (⌘⌥G Z) reverses it.", + "and continue, or abort the revert.": "and continue, or abort the revert.", + "and more — the Commit Graph shows them all": "and more — the Commit Graph shows them all", + "anything settled here and not saved is not kept.": "anything settled here and not saved is not kept.", + "apply the next patch": "apply the next patch", + "applying": "applying", + "applying a stash": "applying a stash", + "applying patches (git am)": "applying patches (git am)", + "applying the stash": "applying the stash", + "approved": "approved", + "approved these changes": "approved these changes", + "are": "are", + "aren't": "aren't", + "as it was": "as it was", + "asked for a review": "asked for a review", + "asked to review": "asked to review", + "asked to review again": "asked to review again", + "asked {0} for a review": "asked {0} for a review", + "automatic opening is off. Turn VS Code's own merge editor and conflict highlights back on?": "automatic opening is off. Turn VS Code's own merge editor and conflict highlights back on?", + "before ↔ {0} “{1}”": "before ↔ {0} “{1}”", + "below": "below", + "beside the main worktree": "beside the main worktree", + "binary": "binary", + "blame failed for {0}: {1}": "blame failed for {0}: {1}", + "branch": "branch", + "branches": "branches", + "bring back '{0}'": "bring back '{0}'", + "by {0}": "by {0}", + "change": "change", + "changed": "changed", + "changed file": "changed file", + "changed files": "changed files", + "changes": "changes", + "changes requested": "changes requested", + "changes were requested": "changes were requested", + "checked out": "checked out", + "checked out here": "checked out here", + "checking out": "checking out", + "checking…": "checking…", + "cherry-pick": "cherry-pick", + "cherry-picking": "cherry-picking", + "choose between — the file is going either way. Delete it to accept the deletion and settle ": "choose between — the file is going either way. Delete it to accept the deletion and settle ", + "closed": "closed", + "closed this": "closed this", + "comment": "comment", + "commented": "commented", + "comments": "comments", + "commit": "commit", + "commit does this. A normal push will be refused.": "commit does this. A normal push will be refused.", + "commit the merge": "commit the merge", + "commits": "commits", + "commits{0}. Accept one side to record its commit. The submodule's own checkout is left as it is: run ": "commits{0}. Accept one side to record its commit. The submodule's own checkout is left as it is: run ", + "committed by {0}": "committed by {0}", + "compared with": "compared with", + "conflict": "conflict", + "conflicted files now open in its merge editor. Turn off VS Code's own merge editor and conflict ": "conflicted files now open in its merge editor. Turn off VS Code's own merge editor and conflict ", + "conflicting file": "conflicting file", + "conflicting files": "conflicting files", + "conflicts": "conflicts", + "conflicts and continue, or abort the revert.": "conflicts and continue, or abort the revert.", + "conflicts and continue, skip this commit, or abort.": "conflicts and continue, skip this commit, or abort.", + "continue": "continue", + "continue the cherry-pick": "continue the cherry-pick", + "continue the rebase": "continue the rebase", + "continue the revert": "continue the revert", + "conversation": "conversation", + "conversations": "conversations", + "couldn't load the diff — {0}": "couldn't load the diff — {0}", + "couldn't read the conflict versions — {0}": "couldn't read the conflict versions — {0}", + "couldn't restore the conflict.": "couldn't restore the conflict.", + "couldn't save the resolved file — {0}": "couldn't save the resolved file — {0}", + "couldn't stage that change — {0}": "couldn't stage that change — {0}", + "couldn't {0} ({1})": "couldn't {0} ({1})", + "current": "current", + "current HEAD": "current HEAD", + "day": "day", + "days": "days", + "default": "default", + "delete '{0}'": "delete '{0}'", + "delete the commit": "delete the commit", + "delete the selected commits": "delete the selected commits", + "deleted on both sides": "deleted on both sides", + "deleted on one side": "deleted on one side", + "detached HEAD": "detached HEAD", + "detached at {0}": "detached at {0}", + "dismissed a review": "dismissed a review", + "diverged": "diverged", + "doesn't.": "doesn't.", + "draft ": "draft ", + "drop": "drop", + "dropped": "dropped", + "dropping": "dropping", + "dropping a commit": "dropping a commit", + "dropping commits": "dropping commits", + "each line is not annotated twice. You can turn it back on in Settings.": "each line is not annotated twice. You can turn it back on in Settings.", + "edit": "edit", + "either arrow takes it": "either arrow takes it", + "every worktree's folder is still there.": "every worktree's folder is still there.", + "everything staged": "everything staged", + "file": "file", + "files": "files", + "first": "first", + "fixup": "fixup", + "fold each into the commit before it, dropping its message": "fold each into the commit before it, dropping its message", + "fold each into the commit before it, keeping both messages": "fold each into the commit before it, keeping both messages", + "fold up, discard message": "fold up, discard message", + "fold up, keep both messages": "fold up, keep both messages", + "folder missing": "folder missing", + "force-pushed the branch": "force-pushed the branch", + "force-pushed the branch from {0} to {1}": "force-pushed the branch from {0} to {1}", + "forget": "forget", + "from a deleted fork": "from a deleted fork", + "from another machine or someone else — and a force push would delete them. ": "from another machine or someone else — and a force push would delete them. ", + "from the fork {0}": "from the fork {0}", + "from the stash, which first switches to where the stash was made. ": "from the stash, which first switches to where the stash was made. ", + "from {0}. Keep editing if you meant to keep it.": "from {0}. Keep editing if you meant to keep it.", + "git am is applying patches in it": "git am is applying patches in it", + "git am is applying patches in it. Removing the worktree abandons the patches not yet applied.": "git am is applying patches in it. Removing the worktree abandons the patches not yet applied.", + "git blame failed for {0} (exit {1}): {2}": "git blame failed for {0} (exit {1}): {2}", + "git can't continue the {0} yet.": "git can't continue the {0} yet.", + "git can't keep both at one path, and taking the file would delete the folder — nothing was changed. ": "git can't keep both at one path, and taking the file would delete the folder — nothing was changed. ", + "git couldn't add the remote {0}: {1}": "git couldn't add the remote {0}: {1}", + "git couldn't apply this patch. Skip it, or abort.": "git couldn't apply this patch. Skip it, or abort.", + "git couldn't delete it": "git couldn't delete it", + "git couldn't keep a copy of those {0}. Commit or stash them, then undo.": "git couldn't keep a copy of those {0}. Commit or stash them, then undo.", + "git diff --cached --check failed ({0}).": "git diff --cached --check failed ({0}).", + "git diff --name-only failed ({0}).": "git diff --name-only failed ({0}).", + "git exited with code {0}.": "git exited with code {0}.", + "git fetch exited with {0}": "git fetch exited with {0}", + "git gave no reason.": "git gave no reason.", + "git has moved on since that Apply, so there is no conflict to bring back. Nothing was changed.": "git has moved on since that Apply, so there is no conflict to bring back. Nothing was changed.", + "git log --follow failed for {0} (exit {1}): ": "git log --follow failed for {0} (exit {1}): ", + "git log -L failed for {0} (exit {1}): ": "git log -L failed for {0} (exit {1}): ", + "git ls-files --resolve-undo failed ({0}).": "git ls-files --resolve-undo failed ({0}).", + "git ls-files -u failed ({0})": "git ls-files -u failed ({0})", + "git ls-files -u failed ({0}), so the unmerged files are unknown.": "git ls-files -u failed ({0}), so the unmerged files are unknown.", + "git reflog exited {0}": "git reflog exited {0}", + "git refused": "git refused", + "git refused the commit without saying why. If this repository has a pre-commit hook, check its output.": "git refused the commit without saying why. If this repository has a pre-commit hook, check its output.", + "git refused the push.": "git refused the push.", + "git rev-parse --git-path failed ({0}).": "git rev-parse --git-path failed ({0}).", + "git rev-parse --git-path {0} failed ({1}).": "git rev-parse --git-path {0} failed ({1}).", + "git says: “{0}”": "git says: “{0}”", + "git still has a worktree at {0} ({1}) — {2} that worktree in Worktrees, or choose another folder. {3}": "git still has a worktree at {0} ({1}) — {2} that worktree in Worktrees, or choose another folder. {3}", + "git still has a worktree at {0} ({1}), though its folder is gone — {2} that worktree in Worktrees, or choose another folder. {3}": "git still has a worktree at {0} ({1}), though its folder is gone — {2} that worktree in Worktrees, or choose another folder. {3}", + "git submodule update afterwards.": "git submodule update afterwards.", + "git was stopped by {0} before it finished.": "git was stopped by {0} before it finished.", + "git won't overwrite them. Stash {0} and try again, or commit {1} first.": "git won't overwrite them. Stash {0} and try again, or commit {1} first.", + "git worktree add failed.": "git worktree add failed.", + "git {0} exited with code {1}": "git {0} exited with code {1}", + "git {0} failed: {1}": "git {0} failed: {1}", + "git {0}: {1}": "git {0}: {1}", + "git's record of the worktree at {0} wasn't found.": "git's record of the worktree at {0} wasn't found.", + "go on to the next step": "go on to the next step", + "goes": "goes", + "has": "has", + "has no line breaks": "has no line breaks", + "has none": "has none", + "has nothing that": "has nothing that", + "have": "have", + "highlights so they don't open alongside it? You can switch back any time with ": "highlights so they don't open alongside it? You can switch back any time with ", + "hour": "hour", + "hours": "hours", + "ignored": "ignored", + "in": "in", + "in the project's folder": "in the project's folder", + "in the worktree {0}": "in the worktree {0}", + "in your working tree": "in your working tree", + "into Changes": "into Changes", + "into Staged": "into Staged", + "into Staged and Unstaged": "into Staged and Unstaged", + "into Unstaged": "into Unstaged", + "is": "is", + "is no earlier version behind either. Keep the new file, or leave it out.": "is no earlier version behind either. Keep the new file, or leave it out.", + "isn't": "isn't", + "it": "it", + "it in an editor and stage it.": "it in an editor and stage it.", + "it is": "it is", + "it isn't a worktree any more": "it isn't a worktree any more", + "it needs an approving review": "it needs an approving review", + "its .git file is gone": "its .git file is gone", + "its folder is gone, or isn't a worktree any more": "its folder is gone, or isn't a worktree any more", + "its staged version no longer applies": "its staged version no longer applies", + "its upstream": "its upstream", + "just now": "just now", + "keep it, but rewrite the message": "keep it, but rewrite the message", + "keep the commit as it is": "keep the commit as it is", + "keep the selected commits as they are": "keep the selected commits as they are", + "keep them, and rewrite their messages": "keep them, and rewrite their messages", + "keep, change message": "keep, change message", + "kept theirs": "kept theirs", + "kept yours": "kept yours", + "kept {0} · {1}": "kept {0} · {1}", + "labels {0}": "labels {0}", + "last commit, so git left the branch where it is rather than rewinding — the commits it had ": "last commit, so git left the branch where it is rather than rewinding — the commits it had ", + "leave": "leave", + "leaves": "leaves", + "lines {0}–{1}": "lines {0}–{1}", + "loading older commits…": "loading older commits…", + "local branch": "local branch", + "local branches": "local branches", + "locked": "locked", + "made here, or from before the pull request was force-pushed.": "made here, or from before the pull request was force-pushed.", + "main, plus the commits already rebased onto it": "main, plus the commits already rebased onto it", + "mark #{0} ready for review": "mark #{0} ready for review", + "mark it ready for review": "mark it ready for review", + "marked this as a draft": "marked this as a draft", + "marked this ready for review": "marked this ready for review", + "meld into the commit above (the older one)": "meld into the commit above (the older one)", + "meld into the commit above, drop this message": "meld into the commit above, drop this message", + "merge": "merge", + "merge #{0}": "merge #{0}", + "merge into the commit below it — drop this message": "merge into the commit below it — drop this message", + "merge into the commit below it — keep both messages": "merge into the commit below it — keep both messages", + "merged": "merged", + "merged commit {0} into {1}": "merged commit {0} into {1}", + "merged this into {0}": "merged this into {0}", + "merging": "merging", + "minute": "minute", + "minutes": "minutes", + "missing": "missing", + "month": "month", + "months": "months", + "move '{0}' back to {1}": "move '{0}' back to {1}", + "new base": "new base", + "new root": "new root", + "no branch (detached HEAD)": "no branch (detached HEAD)", + "no branches": "no branches", + "no commits yet": "no commits yet", + "no email recorded": "no email recorded", + "no one": "no one", + "no remote of this repository ({0}) is a GitHub, GitLab or Bitbucket address.": "no remote of this repository ({0}) is a GitHub, GitLab or Bitbucket address.", + "not a pull request number: {0}": "not a pull request number: {0}", + "not a worktree": "not a worktree", + "not published": "not published", + "not pushed": "not pushed", + "not the op's": "not the op's", + "nothing": "nothing", + "nothing to merge line by line: keep the edited file, or accept the deletion.": "nothing to merge line by line: keep the edited file, or accept the deletion.", + "nothing to pull or push": "nothing to pull or push", + "of": "of", + "oldest": "oldest", + "on top of the stash list": "on top of the stash list", + "one side only — safe to take": "one side only — safe to take", + "onto": "onto", + "open": "open", + "open a file in a Git repository to stage its changes.": "open a file in a Git repository to stage its changes.", + "open a file to compare it against HEAD.": "open a file to compare it against HEAD.", + "opened this": "opened this", + "operation": "operation", + "or by git rerere. Apply replaces that with the Result shown here, and stages it.": "or by git rerere. Apply replaces that with the Result shown here, and stages it.", + "over the changes that just came in. Apply it when you're ready.": "over the changes that just came in. Apply it when you're ready.", + "parent": "parent", + "parents": "parents", + "partly staged": "partly staged", + "patch": "patch", + "patch series": "patch series", + "patch {0} of {1}": "patch {0} of {1}", + "pause at each so you can amend it": "pause at each so you can amend it", + "pause here so you can amend the commit": "pause here so you can amend the commit", + "pending comment": "pending comment", + "pending comments": "pending comments", + "pick": "pick", + "picked commit": "picked commit", + "point": "point", + "points": "points", + "post the reply": "post the reply", + "post your comment": "post your comment", + "post your reply": "post your reply", + "pulling again": "pulling again", + "pushed to": "pushed to", + "rebase": "rebase", + "rebasing": "rebasing", + "remote branch": "remote branch", + "remote branches": "remote branches", + "remote {0} — a fork of {1}/{2}": "remote {0} — a fork of {1}/{2}", + "remote {0} — {1} was forked from it": "remote {0} — {1} was forked from it", + "remote-tracking branch": "remote-tracking branch", + "remote-tracking branches": "remote-tracking branches", + "remove": "remove", + "remove the commit": "remove the commit", + "reopened this": "reopened this", + "replay the next commit": "replay the next commit", + "request its reviewers": "request its reviewers", + "requested changes": "requested changes", + "required checks failed": "required checks failed", + "required checks haven't finished": "required checks haven't finished", + "reset {0} to pull request #{1}": "reset {0} to pull request #{1}", + "resetting": "resetting", + "resolve the conversation": "resolve the conversation", + "resolve them in Changes. They are also kept in the stash {0}.": "resolve them in Changes. They are also kept in the stash {0}.", + "resolved": "resolved", + "resolved and commit the markers — resolve them first.": "resolved and commit the markers — resolve them first.", + "resolved are discarded — they were never committed, so nothing can bring them back.": "resolved are discarded — they were never committed, so nothing can bring them back.", + "revert": "revert", + "reverting": "reverting", + "reviewed": "reviewed", + "reviewed (dismissed)": "reviewed (dismissed)", + "reword": "reword", + "safe to take": "safe to take", + "saving a merge built from part of a file would delete the rest. Accept one side, or resolve ": "saving a merge built from part of a file would delete the rest. Accept one side, or resolve ", + "set their action.": "set their action.", + "sk-… (blank for a local, keyless server)": "sk-… (blank for a local, keyless server)", + "so Undo can't put them back. Nothing was changed.": "so Undo can't put them back. Nothing was changed.", + "someone not listed": "someone not listed", + "squash": "squash", + "squashed": "squashed", + "squashing": "squashing", + "squashing commits": "squashing commits", + "staged": "staged", + "staged in": "staged in", + "started a review": "started a review", + "stash": "stash", + "stash apply": "stash apply", + "stash the whole staged section, or stash those files entirely.": "stash the whole staged section, or stash those files entirely.", + "stashed in": "stashed in", + "stashes": "stashes", + "step": "step", + "still shows a rebase's sides the old way round. Update {0} to use one Conflicts view, ": "still shows a rebase's sides the old way round. Update {0} to use one Conflicts view, ", + "stop to amend the commit": "stop to amend the commit", + "submodule": "submodule", + "switching to it": "switching to it", + "symbolic link": "symbolic link", + "tag": "tag", + "tag: {0}": "tag: {0}", + "tagged": "tagged", + "tags": "tags", + "taken": "taken", + "that comment": "that comment", + "the PR was force-pushed.": "the PR was force-pushed.", + "the changes": "the changes", + "the cherry-pick": "the cherry-pick", + "the conflict is settled. Resolve them first.": "the conflict is settled. Resolve them first.", + "the conflict.": "the conflict.", + "the detached HEAD": "the detached HEAD", + "the file that has staged changes keeps them": "the file that has staged changes keeps them", + "the file yourself and stage it.": "the file yourself and stage it.", + "the files are in Changes, but the stash couldn't be updated — {0}": "the files are in Changes, but the stash couldn't be updated — {0}", + "the files are in Changes, but “{0}” had left the stash list meanwhile, so nothing more was changed.": "the files are in Changes, but “{0}” had left the stash list meanwhile, so nothing more was changed.", + "the folder is gone": "the folder is gone", + "the link to pull request #{0}": "the link to pull request #{0}", + "the local branch {0}": "the local branch {0}", + "the merge": "the merge", + "the merged branch": "the merged branch", + "the new base": "the new base", + "the only worktrees git could prune are locked.": "the only worktrees git could prune are locked.", + "the other branch": "the other branch", + "the pull": "the pull", + "the rebase": "the rebase", + "the rebase didn't change any branch.": "the rebase didn't change any branch.", + "the rebase didn't change anything.": "the rebase didn't change anything.", + "the rebase was abandoned, so it changed nothing.": "the rebase was abandoned, so it changed nothing.", + "the revert": "the revert", + "the root commit": "the root commit", + "the worktree whose folder is gone": "the worktree whose folder is gone", + "the worktree whose folder is gone or isn't a worktree any more": "the worktree whose folder is gone or isn't a worktree any more", + "the {0} files that have staged changes keep them": "the {0} files that have staged changes keep them", + "the {0} worktrees whose folders are gone": "the {0} worktrees whose folders are gone", + "the {0} worktrees whose folders are gone or aren't worktrees any more": "the {0} worktrees whose folders are gone or aren't worktrees any more", + "their folders are gone, or aren't worktrees any more": "their folders are gone, or aren't worktrees any more", + "their staged versions no longer apply": "their staged versions no longer apply", + "them": "them", + "then {0} — or abort to go back to where you were.": "then {0} — or abort to go back to where you were.", + "there is no {0} '{1}' any more.": "there is no {0} '{1}' any more.", + "these {0} files": "these {0} files", + "they are": "they are", + "they aren't worktrees any more": "they aren't worktrees any more", + "this change, made the same on both sides": "this change, made the same on both sides", + "this file": "this file", + "this repository has no remote to open the commit on.": "this repository has no remote to open the commit on.", + "those comments": "those comments", + "those commits could not be read any more — refresh the graph and try again.": "those commits could not be read any more — refresh the graph and try again.", + "tip of": "tip of", + "to reorder. Topmost runs first — this is git's todo file, oldest at the top.": "to reorder. Topmost runs first — this is git's todo file, oldest at the top.", + "too large to merge here": "too large to merge here", + "tracking {0}": "tracking {0}", + "uncommitted change": "uncommitted change", + "uncommitted changes": "uncommitted changes", + "uncommitted changes to {0} are in the way. Stash {1} and try again, or commit {2} first.": "uncommitted changes to {0} are in the way. Stash {1} and try again, or commit {2} first.", + "undone, and conflicts you have resolved are discarded.": "undone, and conflicts you have resolved are discarded.", + "unknown": "unknown", + "unlinked": "unlinked", + "unresolve the conversation": "unresolve the conversation", + "unresolved change": "unresolved change", + "unresolved changes": "unresolved changes", + "unstaged, but for {0}, which git adds back staged,": "unstaged, but for {0}, which git adds back staged,", + "untracked here, and going back to {0} would overwrite {1}. Move {2} aside, then undo.": "untracked here, and going back to {0} would overwrite {1}. Move {2} aside, then undo.", + "up to date": "up to date", + "update the branch": "update the branch", + "update {0} to pull request #{1}": "update {0} to pull request #{1}", + "updated {0}": "updated {0}", + "upstream gone": "upstream gone", + "use commit, edit its message": "use commit, edit its message", + "use the commit as-is": "use the commit as-is", + "uses {0}": "uses {0}", + "v1.2.0 a1b2c3d origin/main~3": "v1.2.0 a1b2c3d origin/main~3", + "version": "version", + "versions": "versions", + "wants to merge": "wants to merge", + "week": "week", + "weeks": "weeks", + "went": "went", + "where it is rather than rewinding. Check the log before carrying on.": "where it is rather than rewinding. Check the log before carrying on.", + "where it opens": "where it opens", + "where it was in the stash list": "where it was in the stash list", + "while a file is only marked to be added (git add -N)": "while a file is only marked to be added (git add -N)", + "while a file was only marked to be added (git add -N)": "while a file was only marked to be added (git add -N)", + "whitespace only": "whitespace only", + "will be saved as the Result shows {0}": "will be saved as the Result shows {0}", + "worktree": "worktree", + "xAI (Grok)": "xAI (Grok)", + "year": "year", + "years": "years", + "you": "you", + "you choose": "you choose", + "your fork": "your fork", + "your stash list, so nothing in it is lost — but conflicts you have resolved here are.": "your stash list, so nothing in it is lost — but conflicts you have resolved here are.", + "{0}\nCtrl/⌘-click: add it after what the result has": "{0}\nCtrl/⌘-click: add it after what the result has", + "{0}\nThe result keeps what it has": "{0}\nThe result keeps what it has", + "{0} (before {1} ↔ after HEAD)": "{0} (before {1} ↔ after HEAD)", + "{0} & Push": "{0} & Push", + "{0} (HEAD ↔ Working Tree)": "{0} (HEAD ↔ Working Tree)", + "{0} (Staged)": "{0} (Staged)", + "{0} (Working Tree)": "{0} (Working Tree)", + "{0} (bare)": "{0} (bare)", + "{0} (current branch)": "{0} (current branch)", + "{0} (current)": "{0} (current)", + "{0} (detached)": "{0} (detached)", + "{0} (from {1})": "{0} (from {1})", + "{0} (rebasing)": "{0} (rebasing)", + "{0} (was {1})": "{0} (was {1})", + "{0} + upstream": "{0} + upstream", + "{0} A private repository needs a sign-in with access to it.": "{0} A private repository needs a sign-in with access to it.", + "{0} But GitStudio {1}.": "{0} But GitStudio {1}.", + "{0} Click Apply again to save anyway.": "{0} Click Apply again to save anyway.", + "{0} Files": "{0} Files", + "{0} Forgetting it unlocks it.": "{0} Forgetting it unlocks it.", + "{0} GitStudio's Undo can put the branch back and bring those edits back with it — git itself keeps no copy of them.": "{0} GitStudio's Undo can put the branch back and bring those edits back with it — git itself keeps no copy of them.", + "{0} Only people with write access to {1} can merge it.": "{0} Only people with write access to {1} can merge it.", + "{0} Resolve {1} and {2}, or abort it, then try again.": "{0} Resolve {1} and {2}, or abort it, then try again.", + "{0} Resolve {1}, finish or abort what git is in the middle of, then try again.": "{0} Resolve {1}, finish or abort what git is in the middle of, then try again.", + "{0} Resolve {1}, then try again.": "{0} Resolve {1}, then try again.", + "{0} Take it off the undo history and go on to undo \"{1}\"? ": "{0} Take it off the undo history and go on to undo \"{1}\"? ", + "{0} The files left in the stash are in commit {1}: `git stash store {2}` brings them back.": "{0} The files left in the stash are in commit {1}: `git stash store {2}` brings them back.", + "{0} The next push will need to be a force push.": "{0} The next push will need to be a force push.", + "{0} The {1} one stays {2} — there's nothing {3} it to fold into.": "{0} The {1} one stays {2} — there's nothing {3} it to fold into.", + "{0} The {1} {2} stay as they were — nothing {3} them is kept to fold into.": "{0} The {1} {2} stay as they were — nothing {3} them is kept to fold into.", + "{0} This cannot be undone from here.": "{0} This cannot be undone from here.", + "{0} Unstaged": "{0} Unstaged", + "{0} Use git_stage first.": "{0} Use git_stage first.", + "{0} Your comments are kept.": "{0} Your comments are kept.", + "{0} added to {1}, joined by a merge commit.": "{0} added to {1}, joined by a merge commit.", + "{0} after {1}": "{0} after {1}", + "{0} ago": "{0} ago", + "{0} all {1}": "{0} all {1}", + "{0} already exists and isn't empty — choose another folder. {1}": "{0} already exists and isn't empty — choose another folder. {1}", + "{0} already has an open pull request, #{1}.": "{0} already has an open pull request, #{1}.", + "{0} already has an open pull request: #{1}.": "{0} already has an open pull request: #{1}.", + "{0} already matches {1}. Nothing to reset.": "{0} already matches {1}. Nothing to reset.", + "{0} already merged, outside the conflict markers. ": "{0} already merged, outside the conflict markers. ", + "{0} and move those branches": "{0} and move those branches", + "{0} and these commits land on {1}.": "{0} and these commits land on {1}.", + "{0} and {1}": "{0} and {1}", + "{0} and {1} more": "{0} and {1} more", + "{0} and {1}/{2} have both moved on: pull, then create it.": "{0} and {1}/{2} have both moved on: pull, then create it.", + "{0} are deleted with its folder, and nothing can bring them back.": "{0} are deleted with its folder, and nothing can bring them back.", + "{0} are still conflicted. Resolve {1} before {2}.": "{0} are still conflicted. Resolve {1} before {2}.", + "{0} as the rebase has rewritten it so far": "{0} as the rebase has rewritten it so far", + "{0} audit started — every process GitStudio spawns is logged below.": "{0} audit started — every process GitStudio spawns is logged below.", + "{0} back {1}. The stash keeps {2}, staging and all.": "{0} back {1}. The stash keeps {2}, staging and all.", + "{0} behind": "{0} behind", + "{0} brings them back.": "{0} brings them back.", + "{0} can't go into itself: pick another base.": "{0} can't go into itself: pick another base.", + "{0} cancelled — the repository is back where it was before.": "{0} cancelled — the repository is back where it was before.", + "{0} changed": "{0} changed", + "{0} changed after the Apply — undoing it now would throw those edits away. Nothing was changed.": "{0} changed after the Apply — undoing it now would throw those edits away. Nothing was changed.", + "{0} changed files": "{0} changed files", + "{0} changed outside the merge editor (in another editor, by a formatter, or on disk). ": "{0} changed outside the merge editor (in another editor, by a formatter, or on disk). ", + "{0} commit": "{0} commit", + "{0} commits": "{0} commits", + "{0} commits aren't": "{0} commits aren't", + "{0} commits to pull": "{0} commits to pull", + "{0} commits to push": "{0} commits to push", + "{0} commits will be removed from {1}: {2}.": "{0} commits will be removed from {1}: {2}.", + "{0} complete.": "{0} complete.", + "{0} conflict markers ({1}) — staging a file with markers in it tells git ": "{0} conflict markers ({1}) — staging a file with markers in it tells git ", + "{0} conflicted": "{0} conflicted", + "{0} conflicted files": "{0} conflicted files", + "{0} couldn't be fetched from {1}: {2}": "{0} couldn't be fetched from {1}: {2}", + "{0} couldn't be reached, so this uses {1} as it was when last fetched.": "{0} couldn't be reached, so this uses {1} as it was when last fetched.", + "{0} couldn't be read.": "{0} couldn't be read.", + "{0} did not finish.": "{0} did not finish.", + "{0} doesn't exist yet.": "{0} doesn't exist yet.", + "{0} done": "{0} done", + "{0} during a rebase, Yours is your commit{1}, on the left. {2}": "{0} during a rebase, Yours is your commit{1}, on the left. {2}", + "{0} failed": "{0} failed", + "{0} failed — {1}": "{0} failed — {1}", + "{0} files": "{0} files", + "{0} files ({1}{2}) are": "{0} files ({1}{2}) are", + "{0} files are left unmerged in it, which git can't stash.": "{0} files are left unmerged in it, which git can't stash.", + "{0} files have conflicts to resolve.": "{0} files have conflicts to resolve.", + "{0} files selected": "{0} files selected", + "{0} files still contain": "{0} files still contain", + "{0} files still have": "{0} files still have", + "{0} files still have conflicts": "{0} files still have conflicts", + "{0} from “{1}”": "{0} from “{1}”", + "{0} git can't keep a copy of them {1}, so GitStudio's Undo can put the branch back, but not those edits.": "{0} git can't keep a copy of them {1}, so GitStudio's Undo can put the branch back, but not those edits.", + "{0} git keeps no copy of them, so nothing can bring them back.": "{0} git keeps no copy of them, so nothing can bring them back.", + "{0} go into a stash you can apply from any worktree of this repository; then its folder is deleted.": "{0} go into a stash you can apply from any worktree of this repository; then its folder is deleted.", + "{0} goes into a stash you can apply from any worktree of this repository; then its folder is deleted.": "{0} goes into a stash you can apply from any worktree of this repository; then its folder is deleted.", + "{0} had no conflict markers left when the merge editor opened: it was already resolved, by hand ": "{0} had no conflict markers left when the merge editor opened: it was already resolved, by hand ", + "{0} has been pushed since, so Undo would have to revert it — and it can't put the rest of what \"{1}\" changed back that way. Nothing was changed.": "{0} has been pushed since, so Undo would have to revert it — and it can't put the rest of what \"{1}\" changed back that way. Nothing was changed.", + "{0} has changes since it was resolved, and bringing the conflict back would overwrite them. Nothing was changed.": "{0} has changes since it was resolved, and bringing the conflict back would overwrite them. Nothing was changed.", + "{0} has changes that aren't staged. Stage or stash them first — git won't continue a rebase with unstaged changes.": "{0} has changes that aren't staged. Stage or stash them first — git won't continue a rebase with unstaged changes.", + "{0} has commits that PR #{1} doesn't": "{0} has commits that PR #{1} doesn't", + "{0} has commits {1} doesn't": "{0} has commits {1} doesn't", + "{0} has moved on": "{0} has moved on", + "{0} has moved since (it is at {1} now), and putting it back would throw that away.": "{0} has moved since (it is at {1} now), and putting it back would throw that away.", + "{0} has no GitHub remote to be pushed to.": "{0} has no GitHub remote to be pushed to.", + "{0} has no commits that {1} doesn't.": "{0} has no commits that {1} doesn't.", + "{0} has no pull request #{1}.": "{0} has no pull request #{1}.", + "{0} has no text to merge here.": "{0} has no text to merge here.", + "{0} has uncommitted changes it didn't have when you were asked, so nothing was removed. Remove it again to see what it holds now.": "{0} has uncommitted changes it didn't have when you were asked, so nothing was removed. Remove it again to see what it holds now.", + "{0} has {1} that pull request #{2} doesn't — made here, or from before ": "{0} has {1} that pull request #{2} doesn't — made here, or from before ", + "{0} has {1} that {2} doesn't, and {3} has {4} that {5} doesn't — ": "{0} has {1} that {2} doesn't, and {3} has {4} that {5} doesn't — ", + "{0} have changes that aren't staged. Stage or stash them first — git won't continue a rebase with unstaged changes.": "{0} have changes that aren't staged. Stage or stash them first — git won't continue a rebase with unstaged changes.", + "{0} hidden · drag header edges to resize": "{0} hidden · drag header edges to resize", + "{0} hit conflicts. Resolve them, then continue or abort.": "{0} hit conflicts. Resolve them, then continue or abort.", + "{0} in Theirs": "{0} in Theirs", + "{0} in Yours": "{0} in Yours", + "{0} in the Result, marked so you can check {1}.": "{0} in the Result, marked so you can check {1}.", + "{0} in this file were": "{0} in this file were", + "{0} incoming commits to pull": "{0} incoming commits to pull", + "{0} into {1}": "{0} into {1}", + "{0} is a file on one side and a folder on the other ({1} is in the folder). ": "{0} is a file on one side and a folder on the other ({1} is in the folder). ", + "{0} is a submodule (a gitlink), and {1} and {2} point it at different ": "{0} is a submodule (a gitlink), and {1} and {2} point it at different ", + "{0} is a symbolic link, so there is no line-by-line merge: {1} and ": "{0} is a symbolic link, so there is no line-by-line merge: {1} and ", + "{0} is a symbolic link. Saving text here would overwrite whatever it points at, not the link — {1}.": "{0} is a symbolic link. Saving text here would overwrite whatever it points at, not the link — {1}.", + "{0} is a worktree again — its .git is back.": "{0} is a worktree again — its .git is back.", + "{0} is already in progress — continue or abort it first.": "{0} is already in progress — continue or abort it first.", + "{0} is binary, so there is no line-by-line merge to make. Accept one side, or replace ": "{0} is binary, so there is no line-by-line merge to make. Accept one side, or replace ", + "{0} is checked out and already matches PR #{1}.": "{0} is checked out and already matches PR #{1}.", + "{0} is checked out in another worktree ({1}).": "{0} is checked out in another worktree ({1}).", + "{0} is checked out in another worktree ({1}). Switch to it there, or check out a different branch in that worktree first.": "{0} is checked out in another worktree ({1}). Switch to it there, or check out a different branch in that worktree first.", + "{0} is checked out in the worktree at {1}, and a branch can be checked out in only one worktree at a time. {2}": "{0} is checked out in the worktree at {1}, and a branch can be checked out in only one worktree at a time. {2}", + "{0} is deleted with its folder, and nothing can bring it back.": "{0} is deleted with its folder, and nothing can bring it back.", + "{0} is in progress on a detached HEAD, so these commits are on no branch. ": "{0} is in progress on a detached HEAD, so these commits are on no branch. ", + "{0} is installed, so {1} opens your conflicts, with the same merge editor and ": "{0} is installed, so {1} opens your conflicts, with the same merge editor and ", + "{0} is larger than can be read in one go, so only part of it is available — and ": "{0} is larger than can be read in one go, so only part of it is available — and ", + "{0} is left out and the rest carries on.": "{0} is left out and the rest carries on.", + "{0} is left out and the rest of the series carries on.": "{0} is left out and the rest of the series carries on.", + "{0} is left out, and that ends the series.": "{0} is left out, and that ends the series.", + "{0} is left out, and that ends the {1}.": "{0} is left out, and that ends the {1}.", + "{0} is left out, and the {1} finishes without it.": "{0} is left out, and the {1} finishes without it.", + "{0} is new in {1} and does not exist in {2} — there ": "{0} is new in {1} and does not exist in {2} — there ", + "{0} is no longer a worktree of this repository.": "{0} is no longer a worktree of this repository.", + "{0} is no longer conflicted — nothing was changed.": "{0} is no longer conflicted — nothing was changed.", + "{0} is no longer conflicted — nothing was written, so a resolution made elsewhere stays as it is.": "{0} is no longer conflicted — nothing was written, so a resolution made elsewhere stays as it is.", + "{0} is not in an open Git repository, so it has no HEAD version.": "{0} is not in an open Git repository, so it has no HEAD version.", + "{0} is open in another tab of this window, so it can't be removed — its folder would be deleted from under that tab. Close that tab first.": "{0} is open in another tab of this window, so it can't be removed — its folder would be deleted from under that tab. Close that tab first.", + "{0} is still conflicted — there is nothing to undo.": "{0} is still conflicted — there is nothing to undo.", + "{0} is still conflicted. Resolve {1} before {2}.": "{0} is still conflicted. Resolve {1} before {2}.", + "{0} is still in progress, with {1} still conflicted. ": "{0} is still in progress, with {1} still conflicted. ", + "{0} is still in progress. Commit it — or abort it — before {1}.": "{0} is still in progress. Commit it — or abort it — before {1}.", + "{0} is still in progress. Continue it — or abort it — before {1}.": "{0} is still in progress. Continue it — or abort it — before {1}.", + "{0} is the main worktree — it holds the repository itself, so git never removes it.": "{0} is the main worktree — it holds the repository itself, so git never removes it.", + "{0} is {1} behind {2} and has no commits of its own, so nothing will be lost: it will move forward to match.": "{0} is {1} behind {2} and has no commits of its own, so nothing will be lost: it will move forward to match.", + "{0} isn't UTF-8 text. Saving it as text would rewrite the bytes it can't represent — {1}.": "{0} isn't UTF-8 text. Saving it as text would rewrite the bytes it can't represent — {1}.", + "{0} isn't among #{1}'s changed files any more.": "{0} isn't among #{1}'s changed files any more.", + "{0} isn't on {1} yet: it is pushed there first.": "{0} isn't on {1} yet: it is pushed there first.", + "{0} keeps the edit made outside the merge editor until you Apply. Apply replaces it with the Result.": "{0} keeps the edit made outside the merge editor until you Apply. Apply replaces it with the Result.", + "{0} left unmerged in it. Open the worktree to resolve it.": "{0} left unmerged in it. Open the worktree to resolve it.", + "{0} left unmerged in it. Open the worktree to resolve them.": "{0} left unmerged in it. Open the worktree to resolve them.", + "{0} match": "{0} match", + "{0} matches": "{0} matches", + "{0} more are": "{0} more are", + "{0} more on GitHub.": "{0} more on GitHub.", + "{0} more — type to narrow": "{0} more — type to narrow", + "{0} more: {1}": "{0} more: {1}", + "{0} moved while you were being asked ({1}), so nothing was reverted. Try Undo again.": "{0} moved while you were being asked ({1}), so nothing was reverted. Try Undo again.", + "{0} needs a clean working tree, and your ": "{0} needs a clean working tree, and your ", + "{0} not on {1}": "{0} not on {1}", + "{0} not pushed to {1}.": "{0} not pushed to {1}.", + "{0} of yours on this file": "{0} of yours on this file", + "{0} of yours {1} pushed to it yet": "{0} of yours {1} pushed to it yet", + "{0} of {1} ticked · untick the last for all": "{0} of {1} ticked · untick the last for all", + "{0} on this branch only": "{0} on this branch only", + "{0} on this file": "{0} on this file", + "{0} on {1}": "{0} on {1}", + "{0} on {1} not pulled yet.": "{0} on {1} not pulled yet.", + "{0} on {1}/{2} yet: {3} pushed first.": "{0} on {1}/{2} yet: {3} pushed first.", + "{0} or ": "{0} or ", + "{0} pending": "{0} pending", + "{0} pending comments": "{0} pending comments", + "{0} point it at different targets. Accept the side whose target you want.": "{0} point it at different targets. Accept the side whose target you want.", + "{0} pull requests": "{0} pull requests", + "{0} rate limit hit — try again in a moment.": "{0} rate limit hit — try again in a moment.", + "{0} rejected the API key (HTTP {1}). Check the key in Settings ▸ AI.": "{0} rejected the API key (HTTP {1}). Check the key in Settings ▸ AI.", + "{0} replayed onto {1} one by one, with no merge commit.": "{0} replayed onto {1} one by one, with no merge commit.", + "{0} request failed (HTTP {1}).": "{0} request failed (HTTP {1}).", + "{0} resolves outside the repository — nothing was changed.": "{0} resolves outside the repository — nothing was changed.", + "{0} returned 404 — check the base URL and model id.": "{0} returned 404 — check the base URL and model id.", + "{0} selected files": "{0} selected files", + "{0} set on 1 commit.": "{0} set on 1 commit.", + "{0} set on {1} commits.": "{0} set on {1} commits.", + "{0} skipped. The {1} is over": "{0} skipped. The {1} is over", + "{0} skipped; the rest applied — the series is finished": "{0} skipped; the rest applied — the series is finished", + "{0} skipped; the rest applied — {1} complete": "{0} skipped; the rest applied — {1} complete", + "{0} staged": "{0} staged", + "{0} still contains conflict markers. Staging it would mark the conflict ": "{0} still contains conflict markers. Staging it would mark the conflict ", + "{0} still exists on one side. Accept Yours or Accept Theirs instead.": "{0} still exists on one side. Accept Yours or Accept Theirs instead.", + "{0} still has": "{0} still has", + "{0} still has conflict markers staged": "{0} still has conflict markers staged", + "{0} still has conflicts": "{0} still has conflicts", + "{0} still has unresolved conflicts.": "{0} still has unresolved conflicts.", + "{0} still have conflict markers staged": "{0} still have conflict markers staged", + "{0} still have unresolved conflicts.": "{0} still have unresolved conflicts.", + "{0} stopped — finish it, or Undo.": "{0} stopped — finish it, or Undo.", + "{0} terminals": "{0} terminals", + "{0} the file without its staging?": "{0} the file without its staging?", + "{0} the files without their staging?": "{0} the files without their staging?", + "{0} the stash without its staging?": "{0} the stash without its staging?", + "{0} the worktree {1}": "{0} the worktree {1}", + "{0} to commit it and go on to the next {1} ({2} queued). It stops again if one conflicts.": "{0} to commit it and go on to the next {1} ({2} queued). It stops again if one conflicts.", + "{0} to finish.": "{0} to finish.", + "{0} to pull": "{0} to pull", + "{0} to push": "{0} to push", + "{0} to {1}. It stops again if that one conflicts.": "{0} to {1}. It stops again if that one conflicts.", + "{0} tracks {1} — it isn't {2}, the branch of PR #{3}.": "{0} tracks {1} — it isn't {2}, the branch of PR #{3}.", + "{0} turns off every merge method GitHub has. Merge it on GitHub.": "{0} turns off every merge method GitHub has. Merge it on GitHub.", + "{0} unpublished": "{0} unpublished", + "{0} unstaged": "{0} unstaged", + "{0} untracked": "{0} untracked", + "{0} was deleted in {1} and in {2}. There is nothing to ": "{0} was deleted in {1} and in {2}. There is nothing to ", + "{0} was edited in {1} and deleted in {2}. There is ": "{0} was edited in {1} and deleted in {2}. There is ", + "{0} when a stash is applied, Yours is your stashed changes, on the left. {1}": "{0} when a stash is applied, Yours is your stashed changes, on the left. {1}", + "{0} which review?": "{0} which review?", + "{0} which stash?": "{0} which stash?", + "{0} will also get the {1} on {2} it doesn't have yet.": "{0} will also get the {1} on {2} it doesn't have yet.", + "{0} will be removed from {1}.": "{0} will be removed from {1}.", + "{0} will be sent with this review": "{0} will be sent with this review", + "{0} will become one commit with the message below.": "{0} will become one commit with the message below.", + "{0} will become one commit.": "{0} will become one commit.", + "{0} will keep the original text.": "{0} will keep the original text.", + "{0} will lose {1} that {2} on {3}:\n": "{0} will lose {1} that {2} on {3}:\n", + "{0} with one side in, the other to decide": "{0} with one side in, the other to decide", + "{0} worktrees": "{0} worktrees", + "{0} {1}": "{0} {1}", + "{0} {1} ago": "{0} {1} ago", + "{0} {1} at a commit that will be replayed.": "{0} {1} at a commit that will be replayed.", + "{0} {1} at a commit that will be rewritten.": "{0} {1} at a commit that will be rewritten.", + "{0} {1} doesn't have. The repository has no remote.": "{0} {1} doesn't have. The repository has no remote.", + "{0} {1} hit a conflict while replaying a later commit. Resolve it and continue the rebase — or skip that commit, or abort to put the branch back as it was.": "{0} {1} hit a conflict while replaying a later commit. Resolve it and continue the rebase — or skip that commit, or abort to put the branch back as it was.", + "{0} {1} of {2}": "{0} {1} of {2}", + "{0} {1} of {2} resolved": "{0} {1} of {2} resolved", + "{0} {1} pull requests{2}": "{0} {1} pull requests{2}", + "{0} {1} pull request{2}": "{0} {1} pull request{2}", + "{0} {1} staged in “{2}”, and git can only stage {3} again when nothing else is staged — your own staged changes are in the way. Nothing has changed yet.": "{0} {1} staged in “{2}”, and git can only stage {3} again when nothing else is staged — your own staged changes are in the way. Nothing has changed yet.", + "{0} {1} staged in “{2}”, and {3} to what HEAD has now. Nothing has changed yet.": "{0} {1} staged in “{2}”, and {3} to what HEAD has now. Nothing has changed yet.", + "{0} {1} stopped and needs you — continue the rebase, or abort it to put the branch back as it was.": "{0} {1} stopped and needs you — continue the rebase, or abort it to put the branch back as it was.", + "{0} {1}, change {2}": "{0} {1}, change {2}", + "{0} {1}, {2} to decide": "{0} {1}, {2} to decide", + "{0} {1}.": "{0} {1}.", + "{0} · {1} can be merged automatically": "{0} · {1} can be merged automatically", + "{0} — click to collapse, ": "{0} — click to collapse, ", + "{0} — continue or abort it first.": "{0} — continue or abort it first.", + "{0} — done.": "{0} — done.", + "{0} — filter the graph by it, or check it out": "{0} — filter the graph by it, or check it out", + "{0} — open the Conflicts view": "{0} — open the Conflicts view", + "{0} — the branch starts here. You stay on the current branch.": "{0} — the branch starts here. You stay on the current branch.", + "{0} — the index is stashed whole; the working tree is left alone.": "{0} — the index is stashed whole; the working tree is left alone.", + "{0} — the tag stays local until you push it.": "{0} — the tag stays local until you push it.", + "{0} — update it to the pull request's latest": "{0} — update it to the pull request's latest", + "{0} — {1} by {2}, {3}. Show its files": "{0} — {1} by {2}, {3}. Show its files", + "{0}'s own commits stay only in the reflog.": "{0}'s own commits stay only in the reflog.", + "{0}+Enter creates it": "{0}+Enter creates it", + "{0}, and PR #{1}'s last commit couldn't be fetched: {2}": "{0}, and PR #{1}'s last commit couldn't be fetched: {2}", + "{0}, but {1} isn't: {2}": "{0}, but {1} isn't: {2}", + "{0}, plus the commits of {1} already rebased onto it": "{0}, plus the commits of {1} already rebased onto it", + "{0}, so it was checked out as {1} at its last commit — a push from there can't reach the pull request. {2}": "{0}, so it was checked out as {1} at its last commit — a push from there can't reach the pull request. {2}", + "{0}, then create a branch to push them.": "{0}, then create a branch to push them.", + "{0}, with {1} left to resolve. Open the worktree to continue or abort it.": "{0}, with {1} left to resolve. Open the worktree to continue or abort it.", + "{0}, {1}": "{0}, {1}", + "{0}, {1} and 1 other file": "{0}, {1} and 1 other file", + "{0}, {1} and {2} other files": "{0}, {1} and {2} other files", + "{0}, {1}{2}, {3} added, {4} removed": "{0}, {1}{2}, {3} added, {4} removed", + "{0}, {1}{2}{3}. Open changes": "{0}, {1}{2}{3}. Open changes", + "{0}.": "{0}.", + "{0}. Finish or abort it first, then undo.": "{0}. Finish or abort it first, then undo.", + "{0}. Open the Conflicts view to continue.": "{0}. Open the Conflicts view to continue.", + "{0}. Open the worktree to continue or abort it.": "{0}. Open the worktree to continue or abort it.", + "{0}. Then: {1}": "{0}. Then: {1}", + "{0}: Conflicts": "{0}: Conflicts", + "{0}: {1} will keep the original text, {2} {3}.": "{0}: {1} will keep the original text, {2} {3}.", + "{0}: {1}.": "{0}: {1}.", + "{0}: {1}{2}. Open its diff": "{0}: {1}{2}. Open its diff", + "{0}h": "{0}h", + "{0}h {1}m": "{0}h {1}m", + "{0}m": "{0}m", + "{0}m {1}s": "{0}m {1}s", + "{0}s": "{0}s", + "{0}{1} has no version of this file — accepting ": "{0}{1} has no version of this file — accepting ", + "{0}{1} has no version of this file — accepting it deletes the file": "{0}{1} has no version of this file — accepting it deletes the file", + "{0}{1} is installed too. It also opens your conflicts, and it ": "{0}{1} is installed too. It also opens your conflicts, and it ", + "{0}{1} — {2}. Open its diff": "{0}{1} — {2}. Open its diff", + "{0}{1}. Opens the branch menu.": "{0}{1}. Opens the branch menu.", + "· also on {0}": "· also on {0}", + "· start of history ·": "· start of history ·", + "“{0}” has staged changes that no longer apply to what HEAD has now. Nothing has changed yet.": "“{0}” has staged changes that no longer apply to what HEAD has now. Nothing has changed yet.", + "“{0}” has staged changes, and git can only stage them again when nothing else is staged — your own staged changes are in the way. Nothing has changed yet.": "“{0}” has staged changes, and git can only stage them again when nothing else is staged — your own staged changes are in the way. Nothing has changed yet.", + "“{0}” is not a branch name git can use.": "“{0}” is not a branch name git can use.", + "“{0}” is not a stash git can read.": "“{0}” is not a stash git can read.", + "“{0}” is not a stash.": "“{0}” is not a stash.", + "✓ deleted": "✓ deleted", + "✓ resolved": "✓ resolved" +} diff --git a/apps/extension/l10n/bundle.l10n.zh-cn.json b/apps/extension/l10n/bundle.l10n.zh-cn.json new file mode 100644 index 00000000..50f80c89 --- /dev/null +++ b/apps/extension/l10n/bundle.l10n.zh-cn.json @@ -0,0 +1,3217 @@ +{ + "\n\n$(cloud) tracking {0}": "\n\n$(cloud) 正在跟踪 {0}", + "\n\nNothing on disk changes, and their branches stay.": "\n\n磁盘上不会有任何改动,它们的分支也保持不变。", + "\n and {0} more": "\n 以及另外 {0} 个", + " …and {0} more": " …还有 {0} 个", + " You, now • Uncommitted changes": " 你,现在 • 未提交的更改", + " (Added the remote {0} for {1}.)": " (已为 {1} 添加远程 {0}。)", + " (GitHub shows no diff for it)": " (GitHub 未显示它的差异)", + " (by {0})": " (由 {0})", + " (folder gone)": " (文件夹已不存在)", + " (from {0})": " (来自 {0})", + " (not a worktree any more)": " (已不再是工作树)", + " (removed lines)": " (删除的行)", + " (renamed from {0})": " (由 {0} 重命名)", + " (was {0})": " (原为 {0})", + " ({0} in Yours, {1} in Theirs)": " ({0} 处属于我方,{1} 处属于对方)", + " ({0} of {1})": " ({1} 中的 {0})", + " HEAD is on no branch, so the merge is on no branch either: create a branch from it to keep it.": " HEAD 不在任何分支上,因此合并结果也不在任何分支上:请从它创建一个分支来保留它。", + " It can't bring back the overwritten untracked {0}.": " 它无法恢复被覆盖的未跟踪 {0}。", + " It is checked out in the worktree at {0}.": " 它已在工作树 {0} 中检出。", + " It was staged and then changed again, so its staged version is not kept.": " 它曾暂存,之后又被修改,因此不保留其暂存版本。", + " Its author doesn't let maintainers edit it, so a push to it will be refused.": " 其作者不允许维护者编辑,因此推送到它会被拒绝。", + " Some stashes may need putting back: {0}.": " 有些贮藏可能还需要放回:{0}。", + " and deleted the branch {0}": ",并已删除分支 {0}", + " and {0} more": " 以及另外 {0} 个", + " as it was stashed": "(按贮藏时的样子)", + " as they were stashed": "(按贮藏时的样子)", + " behind — pull first": " 落后 — 请先拉取", + " from ": " 来自 ", + " from {0}": " 来自 {0}", + " from “{0}”": "(来自“{0}”)", + " in this workspace)": " 在此工作区中)", + " matching the filters": " 符合筛选条件", + " the stash list. Undo (Ctrl/Cmd+Alt+G Z) puts it back.": " 贮藏列表。撤销(Ctrl/Cmd+Alt+G Z)可将其放回。", + " {0} {1} locked, so prune keeps {2} though {3} — forget {4} in Worktrees.": " {0} {1}锁定,因此清理会保留{2},尽管{3} — 请在“工作树”中忘记{4}。", + " {0} {1}into ": " {0} {1}合入 ", + " · $(check) current": " · $(check) 当前", + " · $(git-merge) merge": " · $(git-merge) 合并", + " · also on {0}": " · 也在 {0} 上", + " · undoes 1 newer operation first": " · 会先撤销 1 个较新的操作", + " · undoes {0} newer operations first": " · 会先撤销 {0} 个较新的操作", + " · {0} more queued": " · 另有 {0} 个排队", + " · {0} {1} of {2}": " · {0} {1}/{2}", + " — GitHub lists at most 3,000": " — GitHub 最多列出 3,000 条", + " — commits here belong to no branch": " — 此处的提交不属于任何分支", + " — drops this message": " — 丢弃这条提交信息", + " — its changes are in the stash “{0}”": " — 其更改在贮藏“{0}”中", + " — keeps both messages": " — 保留两条提交信息", + " — {0} {1} to resolve": " — {0} 个{1}待解决", + "\"{0}\" changed {1} in a way Undo can't put back. Nothing was changed.": "\"{0}\" 以撤销无法放回的方式更改了 {1}。未做任何更改。", + "\"{0}\" has already been pushed{1}": "\"{0}\" 已被推送{1}", + "\"{0}\" isn't a branch name git takes.": "\"{0}\" 不是 git 能接受的分支名。", + "\"{0}\" isn't a ref git can fetch.": "\"{0}\" 不是 git 能获取的引用。", + "\"{0}\" isn't a remote URL.": "\"{0}\" 不是远程 URL。", + "\"{0}\" isn't a remote name.": "\"{0}\" 不是远程名称。", + "\"{0}\" isn't a repository GitStudio can add as a remote.": "\"{0}\" 不是 GitStudio 可作为远程添加的仓库。", + "\"{0}\" isn't in the undo history any more": "\"{0}\" 已不在撤销历史中", + "\"{0}\" no longer tracks a remote branch": "\"{0}\" 不再跟踪任何远程分支", + "\"{0}\" tracks {1}, which no longer exists": "\"{0}\" 跟踪 {1},但后者已不存在", + "\"{0}/{1}\" isn't a GitHub repository name.": "\"{0}/{1}\" 不是 GitHub 仓库名。", + "\"{0}: Restore VS Code's Merge Editor\".": "\"{0}:恢复 VS Code 的合并编辑器\"。", + "#{0} isn't a pull request number.": "#{0} 不是拉取请求编号。", + "#{0}'s changed files couldn't be read, so its review can't start yet. Refresh and try again.": "无法读取 #{0} 的更改文件,因此其审查尚无法开始。请刷新后重试。", + "$(calendar) {0}\n": "$(calendar) {0}\n", + "$(calendar) {0} ({1})\n\n": "$(calendar) {0}({1})\n\n", + "$(check) Commit message copied": "$(check) 已复制提交信息", + "$(check) Committed": "$(check) 已提交", + "$(check) Copied {0}": "$(check) 已复制 {0}", + "$(check) Created & switched to {0}": "$(check) 已创建并切换到 {0}", + "$(check) GitStudio: AI features disabled": "$(check) GitStudio:AI 功能已禁用", + "$(check) Nothing to push from {0} — up to date": "$(check) {0} 没有需要推送的内容 — 已是最新", + "$(check) Nothing to push — up to date": "$(check) 没有需要推送的内容 — 已是最新", + "$(check) Pushed": "$(check) 已推送", + "$(check) Rebase complete": "$(check) 变基完成", + "$(check) Renamed {0} to {1}": "$(check) 已将 {0} 重命名为 {1}", + "$(check) Reordered": "$(check) 已重新排序", + "$(check) Undid {0} local {1}": "$(check) 已撤销 {0} 个本地 {1}", + "$(check) {0}": "$(check) {0}", + "$(check) {0} {1} to {2}": "$(check) 已将 {0} {1} 到 {2}", + "$(comment-discussion) Reviewing #{0} · {1} pending": "$(comment-discussion) 正在审查 #{0} · {1} 项待处理", + "$(comment-discussion) {0} reviews · {1} pending": "$(comment-discussion) {0} 条审查 · {1} 项待处理", + "$(copy) Copy Message": "$(copy) 复制提交信息", + "$(copy) Copy SHA": "$(copy) 复制 SHA", + "$(debug-continue) {0}": "$(debug-continue) {0}", + "$(debug-pause) Rebase paused": "$(debug-pause) 变基已暂停", + "$(discard) Reset Current Branch to Here…": "$(discard) 将当前分支重置到此处…", + "$(discard) {0}": "$(discard) {0}", + "$(git-branch) Create Branch Here…": "$(git-branch) 在此创建分支…", + "$(git-branch) tracking `{0}` · {1} in, {2} out\n\n": "$(git-branch) 跟踪 `{0}` · 待拉取 {1},待推送 {2}\n\n", + "$(git-branch) {0}": "$(git-branch) {0}", + "$(git-commit) **Uncommitted changes**\n\n": "$(git-commit) **未提交的更改**\n\n", + "$(git-commit) Checkout Commit": "$(git-commit) 检出提交", + "$(git-commit) Detach HEAD Here…": "$(git-commit) 在此分离 HEAD…", + "$(git-commit) HEAD\n\n": "$(git-commit) HEAD\n\n", + "$(git-commit) Uncommitted changes": "$(git-commit) 未提交的更改", + "$(git-commit) `{0}`": "$(git-commit) `{0}`", + "$(git-commit) `{0}` ": "$(git-commit) `{0}` ", + "$(git-commit) {0}, {1}": "$(git-commit) {0},{1}", + "$(git-merge) Start Interactive Rebase Here…": "$(git-merge) 从此处开始交互式变基…", + "$(git-pull-request) Cherry-Pick Commit": "$(git-pull-request) 拣选提交", + "$(history) Revert Commit": "$(history) 还原提交", + "$(info) GitStudio: no change on this line to stage": "$(info) GitStudio:此行没有可暂存的更改", + "$(info) GitStudio: no change under the cursor to stage": "$(info) GitStudio:光标处没有可暂存的更改", + "$(info) GitStudio: no staged change selected to unstage": "$(info) GitStudio:未选择要取消暂存的已暂存更改", + "$(info) GitStudio: nothing staged to unstage here": "$(info) GitStudio:此处没有可取消暂存的已暂存更改", + "$(info) GitStudio: nothing to stage in the selection": "$(info) GitStudio:所选内容中没有可暂存的更改", + "$(info) GitStudio: {0}": "$(info) GitStudio:{0}", + "$(info) No local commits to undo": "$(info) 没有可撤销的本地提交", + "$(info) {0}: {1}": "$(info) {0}:{1}", + "$(sparkle) Drafted from unstaged changes (nothing was staged)": "$(sparkle) 已根据未暂存的更改起草(未暂存任何内容)", + "$(sparkle) Nothing to draft (stage changes first)": "$(sparkle) 没有可起草的内容(请先暂存更改)", + "$(sync~spin) Fetching {0}…": "$(sync~spin) 正在获取 {0}…", + "$(tag) Create Tag Here…": "$(tag) 在此创建标签…", + "$(warning) Resolve Conflicts": "$(warning) 解决冲突", + "' exactly. Asks first, and says what would be lost.": "' 完全一致。会先询问,并说明将失去什么。", + "' match '": "' 匹配 '", + "'{0}' and {1} have diverged": "'{0}' 与 {1} 已分叉", + "'{0}' can't be switched to safely — git would read its name as an option. Rename it, then undo.": "'{0}' 无法安全切换 — git 会把它的名称当作选项。请重命名,然后撤销。", + "'{0}' doesn't track a remote branch, so there is nothing to reset it to. Set its tracked branch first.": "'{0}' 未跟踪远程分支,因此没有可重置到的目标。请先设置它跟踪的分支。", + "'{0}' goes back to {1}.": "'{0}' 将回到 {1}。", + "'{0}' has been deleted since \"{1}\", so there is nothing to put back.": "'{0}' 自 \"{1}\" 起已被删除,因此没有可放回的内容。", + "'{0}' has been pushed since, so putting it back would rewrite published history. Nothing was changed.": "'{0}' 此后已被推送,放回它会改写已发布的历史。未做任何更改。", + "'{0}' has moved since (it is at {1} now), and putting it back would throw that away.": "'{0}' 此后已移动(现在位于 {1}),放回它会丢弃这些更改。", + "'{0}' has moved since the rebase (it is at {1} now), and putting it back would throw that away.": "'{0}' 在变基后已移动(现在位于 {1}),放回它会丢弃这些更改。", + "'{0}' has no upstream to pull from": "“{0}”没有可拉取的上游分支", + "'{0}' has no upstream to pull from.": "'{0}' 没有可拉取的跟踪分支。", + "'{0}' has the only copy of its commits, so Undo won't delete it. Nothing was changed.": "'{0}' 持有其提交的唯一副本,因此撤销不会删除它。未做任何更改。", + "'{0}' is": "'{0}' 是", + "'{0}' is checked out in another worktree, at {1}, so this one can't switch back to it.": "'{0}' 已在另一个工作树({1})中检出,因此这个工作树无法切回它。", + "'{0}' is checked out in another worktree, at {1}. Reset it there, or check out another branch in that worktree first.": "'{0}' 已在另一个工作树({1})中检出。请在那里重置,或先在该工作树中检出另一个分支。", + "'{0}' is checked out in another worktree, at {1}. Undo it there.": "'{0}' 已在另一个工作树({1})中检出。请在那里撤销。", + "'{0}' is checked out. Switch to another branch, then undo.": "'{0}' 已检出。请切换到另一个分支,然后撤销。", + "'{0}' is not a revision: it starts with '-'.": "'{0}' 不是有效的版本:它以 '-' 开头。", + "'{0}' is not in this repository any more — refresh and try again.": "'{0}' 已不在此仓库中 — 请刷新后重试。", + "'{0}' is not in this repository any more, so there is nothing to switch back to.": "'{0}' 已不在此仓库中,因此没有可切回的内容。", + "'{0}' is not in this repository any more. Nothing was reset.": "'{0}' 已不在此仓库中。未重置任何内容。", + "'{0}' moved while you were being asked (it is at {1} now, not {2}). Nothing was reset — try again.": "'{0}' 在询问你期间发生了移动(现在位于 {1},而不是 {2})。未重置任何内容 — 请重试。", + "'{0}' tracks '{1}', a branch in this repository, not on a remote — there is nothing to fetch and reset it to.": "'{0}' 跟踪的是 '{1}',这是本仓库中的分支,不在远程上 — 没有可获取并重置到的目标。", + "'{0}' tracks {1}, which no longer exists on the remote": "“{0}”跟踪的 {1} 在远端已不存在", + "'{0}' tracks {1}. Choose another branch to track.": "“{0}”跟踪 {1}。请选择另一个要跟踪的分支。", + "'{0}' was checked out here when \"{1}\" ran, and it isn't now. Check it out again, then undo.": "运行 \"{1}\" 时 '{0}' 在此处检出,现在已不是。请重新检出它,然后撤销。", + "'{0}', which '{1}' tracked, no longer exists on the remote. Choose the branch it tracks now.": "“{0}”(原先由“{1}”跟踪)在远端已不存在。请选择它现在跟踪的分支。", + "(new file)": "(新文件)", + "(no branch)": "(无分支)", + "(no commit message)": "(无提交信息)", + "(no message)": "(无信息)", + "(whitespace only)": "(仅空白字符)", + ", and ": ",并 ", + ", and {0} has {1} it doesn't.": ",且 {0} 有 {1} 个它没有的提交。", + ", but not your uncommitted changes — git can't keep a copy of them {0}": ",但不包括你未提交的更改 — git 无法保留它们的副本 {0}", + ", current branch": ",当前分支", + ", folder": ",文件夹", + ", folder, ": ",文件夹,", + ", in {0}": ",在 {0} 中", + ", partly staged": ",部分已暂存", + ", remote branch": ",远程分支", + ", required": ",必填", + ", staged": ",已暂存", + ", tag": ",标签", + ", tracking '{0}'": ",跟踪 '{0}'", + ", tracks ": ",跟踪 ", + ", was {0}": ",原为 {0}", + ", which no longer exists on the remote": ",它在远程已不存在", + ", with your uncommitted changes": ",并带有你未提交的更改", + ", with {0}": ",还有 {0}", + ", {0} to pull": ",可拉取 {0}", + ", {0} to push": ",可推送 {0}", + ". {0}. Go to the next one.": "。{0}。前往下一个。", + "1 File": "1 个文件", + "1 change in this file was": "此文件中的 1 处更改", + "1 changed file": "1 个已更改的文件", + "1 commit": "1 个提交", + "1 commit isn't": "1 个提交", + "1 commit to pull": "1 个提交待拉取", + "1 commit to push": "1 个提交待推送", + "1 conflicted file": "1 个有冲突的文件", + "1 file": "1 个文件", + "1 file has conflicts to resolve.": "1 个文件有冲突需要解决。", + "1 file selected": "已选择 1 个文件", + "1 file still contains": "1 个文件仍包含", + "1 incoming commit to pull": "1 个待拉取的提交", + "1 more is": "还有 1 个", + "1 pending comment": "1 条未提交的评论", + "1 selected file": "1 个选中的文件", + "1 terminal": "1 个终端", + ": yours at {0}, theirs at {1}": ":你方在 {0},他方在 {1}", + "; it now tracks {0}": ";它现在跟踪 {0}", + "; the branch {0} was kept — a commit was made on it while you were asked, and {1} doesn't have it": ";分支 {0} 已保留 — 询问期间其上产生了提交,而 {1} 没有该提交", + "; the branch {0} was kept — git couldn't tell whether it is still merged into {1}": ";分支 {0} 已保留 — git 无法判断它是否仍合并进 {1}", + "; {0} can be resolved automatically (Resolve simple conflicts)": ";{0}可自动解决(解决简单冲突)", + "A Comment review needs something to say: write a summary, or add a comment on a changed line.": "评论式审查需要写点内容:请写一段摘要,或在已更改的行上添加评论。", + "A band that meets a line between two rows on the other side: lines added there, or removed.": "色带在对侧两行之间与一条线相接:那里新增或删除了行。", + "A branch named '{0}' exists again, so Undo won't bring back the one \"{1}\" deleted. Nothing was changed.": "名为 '{0}' 的分支又出现了,因此撤销不会恢复 \"{1}\" 删除的那个分支。未做任何更改。", + "A branch named {0} already exists — choose another name. {1}": "名为 {0} 的分支已存在 — 请换一个名称。{1}", + "A branch named “{0}” already exists.": "已存在名为“{0}”的分支。", + "A broad catalog of open models.": "涵盖大量开源模型。", + "A change still to decide: its line numbers and its link to the Result in the full colour, its lines lighter with the words that changed in the full colour.": "尚未决定的更改:其行号和指向结果的链接用完整颜色,其行用较浅的颜色,其中变更的词用完整颜色。", + "A cherry-pick": "一次拣选", + "A cherry-pick is in progress in it. Removing the worktree abandons the cherry-pick.": "其中正在进行拣选。移除该工作树会放弃这次拣选。", + "A cherry-pick is stopped in it": "其中拣选已停止", + "A command in the plan failed. Fix what it needs, then continue.": "计划中的某个命令失败了。请修复它所需的条件,然后继续。", + "A commit message is required.": "必须填写提交信息。", + "A draft can't be merged until it's marked ready.": "草稿在被标记为就绪之前无法合并。", + "A draft: not ready for review, and GitHub won't merge it yet": "草稿:尚未准备好接受审查,GitHub 也还不会合并它", + "A file is left unmerged in it, which git can't stash.": "其中有 1 个文件未合并,git 无法贮藏。", + "A git am session": "一个 git am 会话", + "A high-level summary of your current changes": "你当前更改的总体摘要", + "A label to recognise it by later.": "便于日后识别的标签。", + "A lighter band in the Result, line numbers too: a conflict with one side in, the other still to decide.": "结果中较浅的色带,连同行号:一处冲突,一侧已采纳,另一侧仍待决定。", + "A lighter band, line numbers too, linked to the Result: the side you took. A settled Result keeps it too.": "较浅的色带,连同行号,并与结果关联:你采纳的那一侧。已确定的结果也会保留它。", + "A local {0} already exists, with {1} that {2} doesn't have": "本地已存在 {0},它有 {1} 个 {2} 没有的提交", + "A merge": "一次合并", + "A merge has two sides, so git needs to know which one to keep.": "合并有两个版本,因此 git 需要知道保留哪一个。", + "A merge is in progress in it": "其中正在进行合并", + "A merge is in progress in it. Removing the worktree abandons the merge.": "其中正在进行合并。移除该工作树会放弃这次合并。", + "A name that does not start with \"-\" — git can check that out like any other branch.": "不以 \"-\" 开头的名称 — git 可以像任何其他分支一样检出它。", + "A new branch, {0}. {1}": "一个新分支 {0}。{1}", + "A new local branch is created from {0} and checked out in the new worktree.": "将从 {0} 创建新的本地分支,并在新的工作树中检出。", + "A normal push. Refused if the remote has commits you don't have.": "普通推送。如果远程有你没有的提交,则会被拒绝。", + "A one-off tip": "一次性提示", + "A patch series (git am) is in progress": "正在进行补丁序列(git am)", + "A push to a named destination needs its remote and branch, and is never forced.": "推送到具名目标需要指定其远程和分支,且绝不会强制推送。", + "A rebase": "一次变基", + "A rebase is already in progress — continue or abort it before starting another.": "已有变基在进行中 — 开始另一次之前请先继续或中止它。", + "A rebase is in progress in it. Removing the worktree abandons the rebase; the branch being rebased stays as it was before the rebase began.": "其中正在进行变基。移除该工作树会放弃这次变基;被变基的分支会保持变基开始前的状态。", + "A rebase is in progress that \"{0}\" didn't start. Finish or abort it first, then undo.": "有一个不是 \"{0}\" 启动的变基正在进行。请先完成或中止它,然后撤销。", + "A rebase is stopped in it": "其中变基已停止", + "A rebase of {0} is in progress, so there is no branch to push until it finishes. ": "正在对 {0} 进行变基,因此完成前没有可推送的分支。 ", + "A remote URL cannot contain spaces.": "远程 URL 不能包含空格。", + "A revert": "一次还原", + "A revert is in progress in it. Removing the worktree abandons the revert.": "其中正在进行还原。移除该工作树会放弃这次还原。", + "A revert is stopped in it": "其中还原已停止", + "A revision can't start with '-'.": "版本不能以 '-' 开头。", + "A squash or fixup has nothing above it to fold into — git can't run this plan.": "压缩或修正的上方没有可折叠的提交 — git 无法执行此计划。", + "A squash or fixup has nothing below it to fold into — git can't run this plan.": "压缩或修正项下方没有可并入的提交 — git 无法执行此计划。", + "A stronger tint on some words: exactly what changed within the line. A change of whitespace only has none; its tooltip says so.": "部分词语颜色更深:表示行内具体改动的位置。仅空白变化不会着色,其提示会说明。", + "A tag is a fixed point, so you'll be on a detached HEAD — not on any branch. Commits made here belong to nothing until you create a branch for them.": "标签是一个固定点,因此你将处于分离的 HEAD — 不在任何分支上。在创建分支之前,这里产生的提交不属于任何分支。", + "A thin outline with no link: the side you discarded.": "细描边且无链接:你丢弃的那一侧。", + "A title is required.": "标题为必填项。", + "A worktree is a second folder of this repository with its own branch checked out — no stashing, no switching.": "工作树是本仓库的第二个文件夹,检出了自己的分支 — 无需贮藏,也无需切换。", + "A {0} is in progress": "正在进行{0}", + "AI review of your current changes": "用 AI 审查你当前的更改", + "Abandon the rebase in progress: '{0}' stays at {1}, as it was.": "放弃正在进行的变基:'{0}' 保持原样,仍在 {1}。", + "Abandon the rebase in progress: HEAD goes back to {0}.": "放弃正在进行的变基:HEAD 回到 {0}。", + "Abandon this patch series?": "放弃这个补丁系列?", + "Abort": "中止", + "Abort (git am)": "中止(git am)", + "Abort Cherry-pick": "中止拣选", + "Abort Merge": "中止合并", + "Abort Rebase": "中止变基", + "Abort Revert": "中止还原", + "Abort rebase": "中止变基", + "Abort the {0}?": "中止{0}?", + "Abort this interactive rebase?": "中止这次交互式变基?", + "About this pull request": "关于此拉取请求", + "Accept": "接受", + "Accept Theirs": "接受对方", + "Accept Yours": "接受我方", + "Accept theirs everywhere": "全部接受对方", + "Accept yours everywhere": "全部接受我方", + "Accept {0}": "接受 {0}", + "Accept {0} for {1}": "为 {1} 接受 {0}", + "Accept {0}: {1}": "接受 {0}:{1}", + "Action for {0}": "{0} 的操作", + "Action history": "操作历史", + "Actions for ": "以下对象的操作 ", + "Actions for {0}": "{0} 的操作", + "Actions for {0} commits": "{0} 个提交的操作", + "Add Remote": "添加远程", + "Add Remote…": "添加远程…", + "Add a comment to the conversation": "在对话中添加评论", + "Add a message…": "添加信息…", + "Add remote": "添加远程", + "Add remote {0}": "添加远程 {0}", + "Add remote…": "添加远程…", + "Add the commits to the description, as a list": "将这些提交以列表形式添加到描述中", + "Add to Favorites": "添加到收藏夹", + "Add to favorites": "添加到收藏夹", + "Add to filter": "添加到筛选", + "Add {0} after {1}": "在 {1} 之后添加 {0}", + "Add {0} to the filter": "将 {0} 添加到筛选器", + "Added": "新增", + "Added on both sides, with no earlier version: every line is compared against an empty file.": "两侧都新增,且没有较早的版本:每一行都与空文件比较。", + "Added on one side only": "仅在一侧新增", + "Added remote {0}": "已添加远程 {0}", + "After your resolution, {0} “{1}” has no changes left, so git leaves it out of {2}.": "在你的解决之后,{0}“{1}”已无剩余更改,因此 git 会将它排除在 {2} 之外。", + "All": "全部", + "All 1 check passed": "全部 1 项检查已通过", + "All branches": "所有分支", + "All changes have been processed": "所有更改都已处理", + "All conflicts": "所有冲突", + "All conflicts are resolved. Open the Conflicts view to continue.": "所有冲突均已解决。打开“冲突”视图以继续。", + "All conflicts resolved": "所有冲突已解决", + "All differences": "所有差异", + "All filters": "所有筛选器", + "All patches applied": "所有补丁已应用", + "All patches applied.": "所有补丁已应用。", + "All {0} changed files go back to their committed version.": "全部 {0} 个更改文件将回到其已提交的版本。", + "All {0} checks passed": "全部 {0} 项检查已通过", + "All {0} commits are": "全部 {0} 个提交", + "All {0} {1} are": "所有 {0} 个 {1} 都", + "Already at the newest revision": "已是最新的版本", + "Already at the oldest revision": "已是最旧的版本", + "Already merged in the file, outside the conflict markers (by git, or by hand): check it": "已在文件中合并,位于冲突标记之外(由 git 或手工完成):请检查", + "Already on {0}": "已在 {0} 上", + "Already pushed. {0} it would rewrite history other people have.": "已被推送。{0} 它会改写其他人已有的历史。", + "Already rebased commits": "已变基的提交", + "Already rebased commits and commits from main": "已变基的提交和来自 main 的提交", + "Already rebased commits and commits from {0}": "已变基的提交和来自 {0} 的提交", + "Also delete the branch {0}": "同时删除分支 {0}", + "Alt": "Alt", + "Amend": "修补", + "Amend commit": "修补提交", + "An https:// URL, an ssh URL, git@host:owner/repo.git, or a local path.": "可以是 https:// 链接、ssh 链接、git@host:owner/repo.git,或本地路径。", + "Another file…": "其他文件…", + "Answer the question above first: the file changed outside the merge editor": "请先回答上面的问题:该文件在合并编辑器之外被修改了", + "Anthropic (Claude)": "Anthropic (Claude)", + "Anthropic is temporarily overloaded — try again shortly.": "Anthropic 暂时过载 — 请稍后重试。", + "Anthropic rate limit hit — try again in a moment.": "已达到 Anthropic 速率限制 — 请稍后重试。", + "Anthropic rejected the API key. Check it in Settings ▸ AI.": "Anthropic 拒绝了该 API 密钥。请在“设置 ▸ AI”中检查。", + "Anthropic request failed (HTTP {0}).": "Anthropic 请求失败(HTTP {0})。", + "Any": "任意", + "Any label": "任意标签", + "Any server that speaks /chat/completions.": "任何支持 /chat/completions 的服务器。", + "Anyone": "任何人", + "Anything you changed while its question was open is discarded too.": "在其提问期间你所做的任何更改也会被丢弃。", + "Append": "追加", + "Applied stash": "已应用贮藏", + "Apply": "应用", + "Apply all non-conflicting changes": "应用所有无冲突的更改", + "Apply both sides, change {0}": "应用两侧,修改 {0}", + "Apply merge resolution": "应用合并解决方案", + "Apply non-conflicting changes from theirs": "应用来自对方的无冲突更改", + "Apply non-conflicting changes from yours": "应用来自我方的无冲突更改", + "Apply non-conflicting changes from {0}": "应用来自 {0} 的无冲突更改", + "Apply non-conflicting changes:": "应用无冲突的更改:", + "Apply non-conflicting changes: all": "应用无冲突的更改:全部", + "Apply non-conflicting changes: {0}": "应用无冲突的更改:{0}", + "Apply stash": "应用贮藏", + "Apply with {0} unresolved": "在 {0} 处未解决的情况下应用", + "Apply: put these changes back and keep the stash": "应用:将这些更改放回并保留贮藏", + "Applying": "正在应用", + "Applying a stash": "正在应用贮藏", + "Applying patches": "正在应用补丁", + "Applying patches (git am)": "正在应用补丁(git am)", + "Applying stashed changes on {0}": "正在 {0} 上应用贮藏的更改", + "Applying the stash": "正在应用贮藏", + "Applying {0}{1}": "正在应用 {0}{1}", + "Approve": "批准", + "Approve this pull request — opens the review box": "批准此拉取请求 — 打开评审框", + "Approved": "已批准", + "Argument rejected for safety (starts with '-' or contains a control character).": "为安全起见已拒绝该参数(以 '-' 开头或包含控制字符)。", + "Ask GitHub again": "再次询问 GitHub", + "Ask for a review from": "请求以下人员审查", + "Asked again": "已再次询问", + "Assign it to": "分配给它", + "Assign it to {0}": "将它分配给 {0}", + "Assign yourself": "将自己设为指派人", + "Assignees": "指派给", + "At least one approving review is required to merge.": "合并至少需要一项批准的审查。", + "Audit is OFF. Enable \"{0}\" in Settings, then reproduce the problem.": "审计已关闭。请在设置中启用 \"{0}\",然后重现该问题。", + "Author": "作者", + "Author override": "覆盖作者", + "Author override — Name ": "覆盖作者 — 姓名 ", + "Authorize on GitHub": "在 GitHub 上授权", + "Awaiting review": "等待审查", + "Azure OpenAI": "Azure OpenAI", + "Back to the branches": "返回分支列表", + "Back to the branches (Left or Escape)": "返回分支列表(左箭头或 Esc)", + "Back to {0}": "返回 {0}", + "Bare repository": "裸仓库", + "Baseline": "基线", + "Before this version the two sides were swapped.": "在此版本之前,两侧是互换的。", + "Binary": "二进制", + "Binary file ({0}) at {1} — its content isn't shown.": "二进制文件({0})位于 {1} — 不显示其内容。", + "Binary file — not shown.": "二进制文件 — 不显示。", + "Bind sessions to the device": "将会话绑定到设备", + "Both sides added or changed these lines the same way: nothing to choose": "两侧以相同方式新增或修改了这些行:无需选择", + "Both sides changed these lines, differently": "两侧以不同方式修改了这些行", + "Both sides deleted {0}. There is no side to take — delete the file to settle it.": "双方都删除了 {0}。没有可采纳的一方 — 请删除该文件以了结。", + "Both sides deleted {0}. There is nothing to merge — delete the file to settle it.": "双方都删除了 {0}。没有可合并的内容 — 请删除该文件以了结。", + "Branch": "分支", + "Branch & actions": "分支与操作", + "Branch / Tag": "分支 / 标签", + "Branch {0}": "分支 {0}", + "Branch+Tag": "分支+标签", + "Branches": "分支", + "Branches and actions": "分支与操作", + "Branches: {0}": "分支:{0}", + "Bring back branch '{0}' at {1}{2}.": "在 {1}{2} 恢复分支 '{0}'。", + "Bring their commits in and record a merge commit. Yours keep their shas.": "引入对方的提交并记录一次合并提交。你的提交保持其 sha 不变。", + "Brings in the pull request's {0} (a fast-forward). It will track {1}.": "引入拉取请求的 {0}(一次快进)。它将跟踪 {1}。", + "Bulk accept": "批量接受", + "Buy me a coffee": "请我喝杯咖啡", + "By {0}.": "由 {0}。", + "CLI connections must be built by the host, not makeProvider().": "CLI 连接必须由宿主构建,而不是 makeProvider()。", + "Can't undo \"{0}\"": "无法撤销 \"{0}\"", + "Can't undo \"{0}\": {1}": "无法撤销 \"{0}\":{1}", + "Cancel": "取消", + "Cancel applying the stash?": "取消应用贮藏?", + "Cancel the merge": "取消合并", + "Cancel the stash apply": "取消贮藏应用", + "Cancelled": "已取消", + "Cancelled after {0}": "{0} 后已取消", + "Cancelled. The conflicted files are back to their last commit.": "已取消。冲突文件已回到其最后一次提交的状态。", + "Cancelled. Your stashed changes are still in the stash.": "已取消。你贮藏的更改仍在贮藏中。", + "Cannot contain spaces.": "不能包含空格。", + "Cannot push": "无法推送", + "Change anyway": "仍然修改", + "Change base ref": "更改基准引用", + "Change compare ref": "更改比较引用", + "Change made the same on both sides": "两侧做了相同的修改", + "Change on one side only": "仅一侧有修改", + "Changed Files": "已更改的文件", + "Changed files": "已更改的文件", + "Changed on one side, deleted on the other": "一侧修改,另一侧删除", + "Changes": "更改", + "Changes from cherry-pick {0}": "来自拣选 {0} 的更改", + "Changes from worktree {0} ({1}), stashed before removing it": "来自工作树 {0}({1})的更改,在移除前已贮藏", + "Changes from {0}": "来自 {0} 的更改", + "Changes from {0} (rewritten)": "来自 {0} 的更改(已重写)", + "Changes requested": "已请求更改", + "Changes — Ctrl/Cmd-click to select every file, ": "更改 — Ctrl/Cmd 单击可选中每个文件,", + "Changes, the commit graph, worktrees and sync status follow the file you are editing. Pick a repository to keep them on it.": "更改、提交图、工作树和同步状态会跟随你正在编辑的文件。选择一个仓库即可让它们保持在该仓库上。", + "Changes, the commit graph, worktrees and sync status stay on {0} until you pick again.": "更改、提交图、工作树和同步状态会保持在 {0} 上,直到你再次选择。", + "Changes, {0}": "更改,{0}", + "Changing whitespace handling compares the files again, and the changes you have resolved so far ": "更改空白处理方式会重新比较文件,而你目前已解决的更改", + "Check Out a Branch…": "检出分支…", + "Check all": "全选", + "Check it out directly, or as a new named branch?": "直接检出,还是作为新的命名分支检出?", + "Check out its branch here, to merge the base into it and resolve the conflicts": "在此检出它的分支,以便将基准合并进去并解决冲突", + "Check out its branch here, tracking it on GitHub, so a push reaches the pull request": "在此检出它的分支,并在 GitHub 上跟踪它,这样推送就能到达该拉取请求", + "Check out tag {0}?": "检出标签 {0}?", + "Check out the existing local branch {0}.": "检出已存在的本地分支 {0}。", + "Check out which remote branch?": "检出哪个远程分支?", + "Check out {0}": "检出 {0}", + "Check out {0} as a detached HEAD.": "将 {0} 作为分离的 HEAD 检出。", + "Check out {0}?": "检出 {0}?", + "Check your network connection.": "请检查你的网络连接。", + "Checked out": "已检出", + "Checked out PR #{0} as {1}, updated to its latest and {2}.{3}": "已将 PR #{0} 检出为 {1},更新至其最新状态,并{2}。{3}", + "Checked out PR #{0} as {1}, updated to its latest.": "已将 PR #{0} 检出为 {1},并更新至其最新状态。", + "Checked out PR #{0} as {1}, {2}.": "已将 PR #{0} 检出为 {1},{2}。", + "Checked out PR #{0} as {1}, {2}.{3}": "已将 PR #{0} 检出为 {1},{2}。{3}", + "Checked out PR #{0} as {1}, {2}: {3}.{4}": "已将 PR #{0} 检出为 {1},{2}:{3}。{4}", + "Checked out PR #{0} as {1}.": "已将 PR #{0} 检出为 {1}。", + "Checked out {0}": "已检出 {0}", + "Checked out {0} (tracking {1})": "已检出 {0}(跟踪 {1})", + "Checked out {0} as it was (not updated to PR #{1}).": "已按原样检出 {0}(未更新到 PR #{1})。", + "Checked out {0}, but couldn't make it track {1}: {2}": "已检出 {0},但无法让它跟踪 {1}:{2}", + "Checking out PR #{0}…": "正在检出 PR #{0}…", + "Checking out…": "正在检出…", + "Checkout": "检出", + "Checkout '{0}'": "检出 '{0}'", + "Checkout Commit": "检出提交", + "Checkout Revision '": "检出修订 '", + "Checkout Tag (detached)": "检出标签(分离)", + "Checkout Tag or Revision": "检出标签或修订", + "Checkout Tag or Revision…": "检出标签或修订…", + "Checkout as {0}": "检出为 {0}", + "Checkout pull request #{0}": "检出拉取请求 #{0}", + "Checkout to resolve": "检出以解决", + "Checkout {0}": "检出 {0}", + "Checkout {0} as it is": "按原样检出 {0}", + "Checkout {0}…": "检出 {0}…", + "Checks": "检查", + "Checks failed": "检查未通过", + "Checks passed": "检查已通过", + "Checks running": "检查运行中", + "Cherry-Pick Commit": "拣选提交", + "Cherry-Pick {0} Commits": "拣选 {0} 个提交", + "Cherry-pick": "拣选", + "Cherry-pick conflicts": "拣选冲突", + "Cherry-pick in progress": "拣选进行中", + "Cherry-pick of {0} needs a decision — resolve any ": "对 {0} 的拣选需要做出决定 — 请解决任何", + "Cherry-pick stopped": "拣选已停止", + "Cherry-pick {0}": "拣选 {0}", + "Cherry-pick {0} commits": "拣选 {0} 个提交", + "Cherry-picked {0}": "已拣选 {0}", + "Cherry-picked {0} commits.": "已拣选 {0} 个提交。", + "Cherry-picking {0} commits": "正在拣选 {0} 个提交", + "Cherry-picking {0} commits stopped on a commit that needs you — resolve any conflicts and continue, skip that commit, or abort to put the branch back as it was.": "拣选 {0} 个提交时停在了一个需要你处理的提交上 — 请解决所有冲突并继续、跳过该提交,或中止以把分支恢复原样。", + "Cherry-picking {0} onto {1}{2}": "正在将 {0} 拣选到 {1}{2}", + "Choose the branch it comes from": "选择它来自的分支", + "Choose the branch it goes into": "选择它要进入的分支", + "Choose the remote branch '{0}' pulls from and pushes to.": "选择“{0}”拉取和推送所用的远程分支。", + "Choose where to push it": "选择推送目标", + "Choose {0}": "选择 {0}", + "Claude (Anthropic)": "Claude (Anthropic)", + "Claude Code (local)": "Claude Code (本地)", + "Claude Opus, Sonnet & Haiku — strongest for code & agentic work.": "Claude Opus、Sonnet 与 Haiku — 在代码与智能体任务上最强。", + "Clear": "清除", + "Clear (Esc)": "清除 (Esc)", + "Clear Selection": "清除选择", + "Clear filters": "清除筛选器", + "Clear search (Esc)": "清除搜索 (Esc)", + "Clear the search": "清除搜索", + "Click to copy {0}": "点击复制 {0}", + "Click to undo back to before this action": "点击可撤销回到此操作之前", + "Close": "关闭", + "Close details": "关闭详情", + "Close details (Esc)": "关闭详情(Esc)", + "Close it without merging (you can reopen it)": "不合并直接关闭(之后可以重新打开)", + "Close pull request": "关闭拉取请求", + "Close sample": "关闭示例", + "Close the merge editor (Escape). Nothing is written.": "关闭合并编辑器(Escape)。不会写入任何内容。", + "Close the merge editor (Escape). Nothing is written: the {0} stays paused and {1} keeps its conflict markers.": "关闭合并编辑器(Escape)。不会写入任何内容:{0} 保持暂停,{1} 保留其冲突标记。", + "Close this box": "关闭此框", + "Close this box — your pending comments are kept": "关闭此框 — 你未提交的评论会保留", + "Close this dashboard": "关闭此面板", + "Close this form — nothing is created": "关闭此表单 — 不会创建任何内容", + "Close without applying": "关闭而不应用", + "Close without applying? {0}{1} keeps its conflict markers; ": "不应用就关闭?{0}{1} 会保留冲突标记;", + "Close without merging": "关闭而不合并", + "Closed without merging ": "已关闭,未合并 ", + "Closing…": "正在关闭…", + "Code Review": "代码审查", + "Codex (local)": "Codex (本地)", + "Collapse All Folders": "折叠所有文件夹", + "Collapse all files": "折叠所有文件", + "Columns": "列", + "Comment": "评论", + "Comment posted": "评论已发布", + "Comment posted to GitHub.": "评论已发布到 GitHub。", + "Comment, approve or request changes": "评论、批准或请求更改", + "Commented": "已评论", + "Commenting…": "正在发表评论…", + "Commit": "提交", + "Commit & Push": "提交并推送", + "Commit Graph": "提交图", + "Commit actions": "提交操作", + "Commit all 1 changed file?": "提交全部 1 个已更改文件?", + "Commit all {0}": "提交全部 {0}", + "Commit all {0} changed files?": "提交全部 {0} 个已更改文件?", + "Commit and Push": "提交并推送", + "Commit graph": "提交图", + "Commit list": "提交列表", + "Commit message": "提交信息", + "Commit or stash {0}, then pull again.": "请先提交或贮藏 {0},然后再次拉取。", + "Commit something first, then open a pull request from its branch.": "请先提交一些内容,然后从该分支发起拉取请求。", + "Commit title": "提交标题", + "Commit {0}": "提交 {0}", + "Commit {0}, {1}, action {2}": "提交 {0},{1},操作 {2}", + "Commit {0}: {1}, by {2}, {3}{4}": "提交 {0}:{1},作者 {2},{3}{4}", + "Commit-message drafting, diff explanation, summaries and AI review stop being offered. Git operations are unaffected. Re-enable with GitStudio: Connect AI Provider, or by setting gitstudio.ai.provider.": "将不再提供提交信息起草、差异解释、摘要和 AI 审查。Git 操作不受影响。可通过 GitStudio: Connect AI Provider 或设置 gitstudio.ai.provider 重新启用。", + "Commits": "提交", + "Commits to push": "待推送的提交", + "Commits to rebase, newest first": "待变基的提交,最新的在前", + "Committed on {0}": "提交于 {0}", + "Committing…": "正在提交…", + "Commit…": "提交…", + "Compare": "比较", + "Compare These Two Commits": "比较这两个提交", + "Compare from (base)…": "比较起点(基准)…", + "Compare to (head)…": "比较终点(目标)…", + "Compare with {0}": "与 {0} 比较", + "Compare {0} with…": "将 {0} 与…比较", + "Compare: {0} ↔ {1}": "比较:{0} ↔ {1}", + "Compared with {0} as last fetched: GitHub couldn't be reached.": "与上次获取的 {0} 相比:无法访问 GitHub。", + "Comparing…": "正在比较…", + "Comparison mode": "比较模式", + "Confirm merge": "确认合并", + "Confirm push": "确认推送", + "Confirm push from the worktree ": "确认从工作树推送 ", + "Confirm rebase and merge": "确认变基并合并", + "Confirm squash and merge": "确认压缩并合并", + "Conflict": "冲突", + "Conflict — you choose (orange): both sides changed these lines, differently — even when one of them removed lines. Accept one side, both, or edit the result.": "冲突 — 由你选择(橙色):两侧以不同方式修改了这些行 — 即使其中一侧删除了行。可接受一侧、两侧,或编辑结果。", + "Conflicted binary file": "冲突的二进制文件", + "Conflicted submodule": "冲突的子模块", + "Conflicted symbolic link": "冲突的符号链接", + "Conflicts": "冲突", + "Conflicts ({0})": "冲突({0})", + "Conflicts dashboard. {0}'s own commands still work.": "冲突面板。{0} 自身的命令仍然可用。", + "Connect AI": "连接 AI", + "Connect GitHub to use pull requests.": "连接 GitHub 以使用拉取请求。", + "Connect a model to write commit messages and review your changes. Bring your own API key, run a model locally (fully private), or use your editor's built-in AI. It's optional and never blocks Git.": "连接一个模型来撰写提交信息并审查你的更改。可自带 API 密钥、在本地运行模型(完全私密),或使用编辑器内置的 AI。它是可选的,绝不阻塞 Git。", + "Connect an AI provider — powers commit messages & code review": "连接 AI 提供方 — 用于提交信息与代码审查", + "Contents are identical": "内容完全相同", + "Continue": "继续", + "Continue (git am)": "继续(git am)", + "Continue Anyway": "仍然继续", + "Continue Cherry-pick": "继续拣选", + "Continue Merge": "继续合并", + "Continue Rebase": "继续变基", + "Continue Revert": "继续还原", + "Continue failed.": "继续失败。", + "Continue isn't possible yet.": "目前还无法继续。", + "Continuing drops {0} {1} — confirm to go ahead.": "继续将丢弃 {0} {1} — 请确认以继续。", + "Continuing will drop {0} “{1}” from {2}: ": "继续将从 {2} 中丢弃 {0}“{1}”: ", + "Continuing would drop an emptied commit — confirm to go ahead.": "继续将丢弃一个已空的提交 — 请确认以继续。", + "Convert this draft to ready for review": "将此草稿转为待评审", + "Copied": "已复制", + "Copied commit message": "已复制提交信息", + "Copied {0}": "已复制 {0}", + "Copied {0} SHAs": "已复制 {0} 个 SHA", + "Copied {0} to Changes": "已将 {0} 复制到更改", + "Copy": "复制", + "Copy Branch Name": "复制分支名称", + "Copy Message": "复制提交信息", + "Copy Path": "复制路径", + "Copy SHA": "复制 SHA", + "Copy SHA {0}": "复制 SHA {0}", + "Copy SHAs": "复制 SHA", + "Copy Tag Name": "复制标签名称", + "Copy a worktree's path": "复制工作树的路径", + "Copy failed": "复制失败", + "Copy finding": "复制发现", + "Copy full review": "复制完整审查", + "Copy it to edit somewhere else": "复制它以在别处编辑", + "Copy link": "复制链接", + "Copy report": "复制报告", + "Copy the full 40-character SHA": "复制完整的 40 位 SHA", + "Copy the pull request's link": "复制该拉取请求的链接", + "Copy to Changes": "复制到更改", + "Copy {0} to Changes": "将 {0} 复制到“更改”", + "Copy: bring {0} back {1}, and keep {2} in the stash": "复制:将 {0} 取回{1},并在贮藏中保留{2}", + "Could not finish loading — see the GitStudio Output channel for the error": "无法完成加载 — 请查看 GitStudio 输出通道中的错误", + "Could not write the rebase plan": "无法写入变基计划", + "Couldn't abort the rebase.": "无法中止变基。", + "Couldn't bring the conflict in {0} back.": "无法恢复 {0} 中的冲突。", + "Couldn't check out PR #{0}: {1}": "无法检出 PR #{0}:{1}", + "Couldn't compare the branches": "无法比较这些分支", + "Couldn't compare {0} with {1}.": "无法比较 {0} 与 {1}。", + "Couldn't connect.": "无法连接。", + "Couldn't create the pull request: {0}": "无法创建拉取请求:{0}", + "Couldn't delete {0}.": "无法删除 {0}。", + "Couldn't draft the description: {0}": "无法起草描述:{0}", + "Couldn't drop {0}.": "无法丢弃 {0}。", + "Couldn't drop {0}: {1}": "无法丢弃 {0}:{1}", + "Couldn't fetch PR #{0}'s branch from {1}: {2}": "无法从 {1} 获取 PR #{0} 的分支:{2}", + "Couldn't find the pull request's head in what was fetched.": "在获取的内容中找不到该拉取请求的头部。", + "Couldn't find what was fetched (FETCH_HEAD).": "找不到获取到的内容(FETCH_HEAD)。", + "Couldn't find {0} in what was fetched.": "在获取的内容中找不到 {0}。", + "Couldn't list pull requests.": "无法列出拉取请求。", + "Couldn't load history": "无法加载历史", + "Couldn't load its files. {0} ": "无法加载它的文件。{0} ", + "Couldn't load more: {0}": "无法加载更多:{0}", + "Couldn't load pull requests": "无法加载拉取请求", + "Couldn't load the changed files. {0}": "无法加载已更改的文件。{0}", + "Couldn't load the history": "无法加载历史", + "Couldn't load {0}#{1}": "无法加载 {0}#{1}", + "Couldn't move {0}: {1}": "无法移动 {0}:{1}", + "Couldn't post the comment.": "无法发布评论。", + "Couldn't post the reply.": "无法发布回复。", + "Couldn't push {0} to {1}": "无法将 {0} 推送到 {1}", + "Couldn't put the branch back.": "无法将分支放回。", + "Couldn't put the stash back. `git stash store {0}` brings it back by hand.": "无法放回贮藏。可用 `git stash store {0}` 手动恢复。", + "Couldn't reach Anthropic (network error).": "无法连接 Anthropic(网络错误)。", + "Couldn't reach GitHub": "无法访问 GitHub", + "Couldn't reach GitHub. Check your network connection.": "无法访问 GitHub。请检查你的网络连接。", + "Couldn't reach {0} — is the endpoint reachable?": "无法连接 {0} — 该端点可访问吗?", + "Couldn't reach {0} — is the model server running?": "无法访问 {0} — 模型服务器是否在运行?", + "Couldn't read its uncommitted changes.": "无法读取其未提交的更改。", + "Couldn't read the conflict state for {0}. Nothing was changed.": "无法读取 {0} 的冲突状态。未做任何更改。", + "Couldn't read the conflicted files: {0}": "无法读取冲突文件:{0}", + "Couldn't read the worktrees": "无法读取工作树", + "Couldn't read this commit's files.": "无法读取此提交的文件。", + "Couldn't read what was fetched (FETCH_HEAD).": "无法读取获取到的内容(FETCH_HEAD)。", + "Couldn't read {0}": "无法读取 {0}", + "Couldn't read {0}/{1} after fetching it.": "获取 {0}/{1} 后无法读取它。", + "Couldn't refresh: {0}": "无法刷新:{0}", + "Couldn't resolve the conversation.": "无法解决该会话。", + "Couldn't stage {0}.": "无法暂存 {0}。", + "Couldn't submit the review.": "无法提交审查。", + "Couldn't submit your review": "无法提交你的审查", + "Couldn't take that version of {0}. Nothing was changed.": "无法采纳 {0} 的那个版本。未做任何更改。", + "Couldn't take those files out of the stash ({0}): {1}": "无法从贮藏中取出这些文件({0}):{1}", + "Couldn't tell whether {0} has changed since it was resolved. Nothing was changed.": "无法判断 {0} 自解决以来是否发生变化。未做任何更改。", + "Couldn't unresolve the conversation.": "无法取消解决该会话。", + "Couldn't update {0}: {1}": "无法更新 {0}:{1}", + "Couldn't {0} {1}.": "无法{0} {1}。", + "Couldn't {0} {1}: {2}": "无法{0} {1}:{2}", + "Couldn't {0}: {1}": "无法{0}:{1}", + "Create Branch": "创建分支", + "Create Branch Here": "在此创建分支", + "Create Branch Here…": "在此创建分支…", + "Create Branch…": "创建分支…", + "Create Only": "仅创建", + "Create Tag": "创建标签", + "Create Tag Here…": "在此创建标签…", + "Create Worktree": "创建工作树", + "Create a branch from": "从以下对象创建分支", + "Create a branch from it under another name instead.": "改为以另一个名称从它创建分支。", + "Create a merge commit": "创建合并提交", + "Create a new branch from the current HEAD.": "从当前 HEAD 创建新分支。", + "Create a new branch from these commits (and switch to it)": "从这些提交创建新分支(并切换到它)", + "Create a new local branch starting from {0}.": "从 {0} 开始创建新的本地分支。", + "Create and Switch": "创建并切换", + "Create as draft": "创建为草稿", + "Create branch": "创建分支", + "Create branch at {0}": "在 {0} 创建分支", + "Create branch from stash": "从贮藏创建分支", + "Create branch from “{0}”": "从“{0}”创建分支", + "Create pull request": "创建拉取请求", + "Create tag": "创建标签", + "Create tag at {0}": "在 {0} 创建标签", + "Create the branch and check it out.": "创建该分支并检出。", + "Create the branch and stay on the current one.": "创建该分支并留在当前分支。", + "Create the pull request on {0}": "在 {0} 上创建拉取请求", + "Create {0}": "创建 {0}", + "Created branch {0}": "已创建分支 {0}", + "Created tag {0}": "已创建标签 {0}", + "Created the worktree {0} at {1}": "已在 {1} 创建工作树 {0}", + "Created {0}": "已创建 {0}", + "Created {0}pull request #{1}.": "已创建{0}拉取请求 #{1}。", + "Creates the branch at HEAD and switches to it.": "在 HEAD 处创建该分支并切换到它。", + "Creates the branch at the current commit and switches to it.": "在当前提交处创建该分支并切换到它。", + "Creating…": "正在创建…", + "Ctrl+Enter to send": "按 Ctrl+Enter 发送", + "Ctrl/Cmd-click to select every file in it, right-click for its actions": "Ctrl/Cmd 单击可选中其中每个文件,右键可查看其操作", + "Current ({0})": "当前({0})", + "Current + upstream": "当前 + 上游", + "Current branch": "当前分支", + "Current — open in this window.": "当前 — 在此窗口中打开。", + "Custom (OpenAI-compatible)": "自定义(兼容 OpenAI)", + "Date": "日期", + "DeepSeek-V3 chat & R1 reasoning.": "DeepSeek-V3 对话与 R1 推理。", + "Delete": "删除", + "Delete Remote Branch": "删除远程分支", + "Delete Tag": "删除标签", + "Delete branch": "删除分支", + "Delete branch '{0}', which \"{1}\" created.": "删除由 \"{1}\" 创建的分支 '{0}'。", + "Delete branch {0}": "删除分支 {0}", + "Delete branch {0}?": "删除分支 {0}?", + "Delete remote branch": "删除远程分支", + "Delete tag": "删除标签", + "Delete tag {0}?": "删除标签 {0}?", + "Delete the conflicted file": "删除冲突的文件", + "Delete the file": "删除文件", + "Delete them — nothing is sent": "删除它们 — 不会发送任何内容", + "Delete which remote branch?": "删除哪个远程分支?", + "Delete {0} on GitHub after merging": "合并后在 GitHub 上删除 {0}", + "Delete {0} on {1}?": "在 {1} 上删除 {0}?", + "Deleted": "已删除", + "Deleted on both sides": "两侧都已删除", + "Deleted tag {0}": "已删除标签 {0}", + "Deleted the file and staged the deletion.": "已删除该文件并暂存了删除操作。", + "Deleted {0}": "已删除 {0}", + "Deleted {0}/{1}": "已删除 {0}/{1}", + "Deletes its folder, {0}.": "删除其文件夹,{0}。", + "Deletes its folder.": "删除其文件夹。", + "Describe the change. Markdown is fine.": "描述此次更改。可使用 Markdown。", + "Description": "描述", + "Detach HEAD Here…": "在此分离 HEAD…", + "Detach HEAD here": "在此分离 HEAD", + "Detached HEAD": "分离的 HEAD", + "Detached HEAD at ": "分离的 HEAD 位于 ", + "Detached HEAD at {0}": "分离的 HEAD 位于 {0}", + "Detached HEAD at {0} — commits here belong to no branch": "游离的 HEAD,位于 {0} — 这里的提交不属于任何分支", + "Detached HEAD: commits made here are on no branch\n\n": "分离的 HEAD:此处创建的提交不在任何分支上\n\n", + "Detached at {0} — check out a branch to pull or push": "处于分离状态:{0} — 检出分支后才能拉取或推送", + "Details": "详细信息", + "Details of {0}": "{0} 的详情", + "Diff": "差异", + "Diff style": "差异样式", + "Diff: {0}": "差异:{0}", + "Disable AI": "禁用 AI", + "Disable all GitStudio AI features?": "禁用所有 GitStudio AI 功能?", + "Discard": "丢弃", + "Discard 1 pending comment on #{0}?": "丢弃 #{0} 上的 1 条未提交评论?", + "Discard All": "全部丢弃", + "Discard Changes": "丢弃更改", + "Discard Changes and Remove": "丢弃更改并移除", + "Discard Folder": "丢弃文件夹", + "Discard all": "全部丢弃", + "Discard all 1 working-tree change?": "丢弃全部 1 处工作树更改?", + "Discard all uncommitted changes?": "丢弃所有未提交的更改?", + "Discard all {0} working-tree changes?": "丢弃全部 {0} 处工作树更改?", + "Discard changes": "丢弃更改", + "Discard changes in 1 file?": "丢弃 1 个文件中的更改?", + "Discard changes in {0} files?": "丢弃 {0} 个文件中的更改?", + "Discard changes in {0}?": "丢弃 {0} 中的更改?", + "Discard folder": "丢弃文件夹", + "Discard pending comments…": "丢弃未提交的评论…", + "Discard this change on both sides": "在两侧丢弃此更改", + "Discard your pending comments?": "丢弃你未提交的评论?", + "Discard {0}": "丢弃 {0}", + "Discard {0} Files": "丢弃 {0} 个文件", + "Discard {0} pending comments on #{1}?": "丢弃 #{1} 上的 {0} 条未提交评论?", + "Discard {0} too: the result keeps what it has": "同时丢弃 {0}:结果保留其现有内容", + "Discard {0}: keep {1} as the result": "丢弃 {0}:将 {1} 保留为结果", + "Discard {0}? They haven't been sent to GitHub, and this can't be undone.": "丢弃 {0}?它们尚未发送到 GitHub,且此操作无法撤销。", + "Discarded": "已丢弃", + "Discarded both: the Result keeps the original": "已丢弃两侧:结果保留原始内容", + "Discarded the change (the same on both sides)": "已丢弃该更改(两侧相同)", + "Discarded the change (the same on both sides): the Result keeps the original": "已丢弃该更改(两侧相同):结果保留原始内容", + "Discarded {0}: the Result keeps the original": "已丢弃 {0}:结果保留原始内容", + "Dismiss": "忽略", + "Dismissed": "已驳回", + "Do not ignore": "不忽略", + "Don't ask again": "不再询问", + "Don't show this again": "不再显示此消息", + "Down arrow": "下箭头", + "Draft": "草稿", + "Draft with AI": "用 AI 起草", + "Drafting a commit message with AI…": "正在用 AI 起草提交信息…", + "Drafting…": "正在生成草稿…", + "Drag rows or press": "拖动行或按", + "Drag to reorder": "拖动以重新排序", + "Drag to reorder — the selected commits move together (or press Alt+↑ / Alt+↓)": "拖动以重新排序 — 选中的提交会一起移动(或按 Alt+↑ / Alt+↓)", + "Drag to resize": "拖动以调整大小", + "Drag to resize Commit message / Changes": "拖动以调整提交信息 / 更改的大小", + "Drag to resize {0} · double-click to reset": "拖动以调整 {0} · 双击可重置", + "Drag to resize · double-click to reset": "拖动以调整大小 · 双击可重置", + "Drive your installed `claude` CLI with its own login — no API key.": "用你自己登录的 `claude` CLI 驱动 — 无需 API 密钥。", + "Drive your installed `codex` CLI with its ChatGPT/OpenAI login — no API key.": "用你自己 ChatGPT/OpenAI 登录的 `codex` CLI 驱动 — 无需 API 密钥。", + "Drive your installed `gemini` CLI with its Google login — no API key.": "用你自己 Google 登录的 `gemini` CLI 驱动 — 无需 API 密钥。", + "Drop": "丢弃", + "Drop Commit": "丢弃提交", + "Drop Commits": "丢弃提交", + "Drop Commit…": "丢弃提交…", + "Drop and move those branches": "丢弃并移动那些分支", + "Drop from this branch only": "仅从该分支丢弃", + "Drop it and continue": "丢弃它并继续", + "Drop remote-tracking branches that no longer exist on the server.": "丢弃服务器上已不存在的远程跟踪分支。", + "Drop stash": "丢弃贮藏", + "Drop the emptied commit?": "丢弃已清空的提交?", + "Drop the empty commit?": "丢弃空提交?", + "Drop to apply": "拖放以应用", + "Drop to copy {0}": "拖到此处以复制 {0}", + "Drop to move {0}": "拖到此处以移动 {0}", + "Drop to pop": "拖放以弹出", + "Drop to stash {0}": "拖到此处贮藏 {0}", + "Drop {0}": "丢弃 {0}", + "Drop {0} Commits…": "丢弃 {0} 个提交…", + "Drop {0} commits?": "丢弃 {0} 个提交?", + "Drop {0}?": "丢弃 {0}?", + "Drop “{0}”": "丢弃“{0}”", + "Drop “{0}”?": "丢弃“{0}”?", + "Dropped stash": "已丢弃贮藏", + "Dropped {0}.": "已丢弃 {0}。", + "Dropping": "丢弃", + "Dropping every commit would erase the whole range.": "丢弃每个提交会清空整个范围。", + "Dropping {0} hit a conflict while replaying a later commit. Resolve it and continue the rebase — or skip that commit, or abort to put the branch back as it was.": "丢弃 {0} 时在重放后续提交时遇到冲突。请解决它并继续变基 — 或跳过该提交,或中止以把分支恢复原样。", + "Dropping {0} stopped and needs you — continue the rebase, or abort it to put the branch back as it was.": "丢弃 {0} 已停止,需要你处理 — 请继续变基,或中止以把分支恢复原样。", + "Drop…": "丢弃…", + "Edit": "编辑", + "Edit URL": "编辑 URL", + "Edit URL of {0}": "编辑 {0} 的 URL", + "Edit result": "编辑结果", + "Enable LM Studio's local server (Developer ▸ Start Server), then load a model.": "请启用 LM Studio 的本地服务器(Developer ▸ Start Server),然后加载模型。", + "Encrypted at rest in GitStudio's own store — not your OS keychain, so it never raises a password prompt. The key stays host-side and is never sent to a webview.": "静态加密存储在 GitStudio 自己的存储中 — 不是你的操作系统钥匙串,因此绝不会弹出密码提示。密钥保留在宿主侧,绝不会发送到 webview。", + "Errored": "出错", + "Every check on its latest commit": "每项检查都在其最新提交上", + "Every conflict is resolved, and your stashed changes are in your files. git keeps the stash entry when applying it stops on conflicts, so it is still in your stash list — drop it once you are happy with the result.": "每个冲突都已解决,你贮藏的更改已在文件中。在应用时遇到冲突而停下,git 会保留贮藏条目,所以它仍在贮藏列表中 — 满意后即可丢弃它。", + "Every conflict is resolved.": "所有冲突都已解决。", + "Every difference between the two refs": "两个引用之间的所有差异", + "Every position HEAD has held, including ones no branch points at any more.": "HEAD 曾处的每个位置,包括已无任何分支指向的位置。", + "Every unmerged file goes back to its last committed version, and so does everything that is staged — including changes you staged before the conflict. Conflicts you have resolved are discarded too; none of it was committed, so nothing can bring it back. Changes you never staged are kept.": "所有未合并的文件都会回到上次提交的版本,已暂存的内容也一样 — 包括冲突前暂存的更改。已解决的冲突也会被丢弃;这些都没有提交过,无法恢复。你从未暂存的更改会保留。", + "Everything here is going. Untick anything you want to keep.": "这里的所有内容都将被丢弃。取消勾选你想保留的内容。", + "Everything you wrote is still here.": "你写的内容都还在。", + "Expand all files": "展开所有文件", + "Expected — waiting for it to report": "符合预期 — 正在等待其报告", + "Explain Diff": "解释差异", + "Failed": "失败", + "Failed to start": "启动失败", + "Fast-forward {0} to {1}?": "将 {0} 快进到 {1}?", + "Fast-forwarded": "已快进", + "Fast-forwarded {0}": "已快进 {0}", + "Fast-forwards '{0}' from {1} — no checkout": "快进“{0}”到 {1} — 不检出", + "Favorites": "收藏", + "Feedback without an explicit approval": "不带明确批准的反馈", + "Fetch": "获取", + "Fetched": "已获取", + "Fetched all remotes": "已获取所有远程", + "Fetched {0}": "已获取 {0}", + "Fetches, then makes '": "先获取,然后将 '", + "Fetching…": "正在获取…", + "File history": "文件历史", + "File too large to show ({0}) at {1}.": "文件过大,无法显示({0})于 {1}。", + "Files": "文件", + "Files changed": "已更改的文件", + "Files resolved": "已解决的文件", + "Filter": "筛选", + "Filter branches: {0}": "筛选分支:{0}", + "Filter branches…": "筛选分支…", + "Filter by author, review requested, assignee or label": "按作者、请求审查者、指派人或标签筛选", + "Filter by author, review requested, assignee or label ({0} on)": "按作者、请求审查者、指派人或标签筛选(已启用 {0})", + "Filter by {0}": "按 {0} 筛选", + "Filter changed files": "筛选已更改的文件", + "Filter changed files…": "筛选已更改的文件…", + "Filter pull requests": "筛选拉取请求", + "Filter the branch list": "筛选分支列表", + "Filter worktrees": "筛选工作树", + "Filter {0}": "筛选 {0}", + "Filter {0} worktrees": "筛选 {0} 个工作树", + "Filter, {0} on": "筛选,已启用 {0}", + "Filters on": "已启用的筛选", + "Find a branch": "查找分支", + "Find a branch, or type one": "查找分支,或输入一个", + "Find a label": "查找标签", + "Find a remote": "查找远程", + "Find a repository": "查找仓库", + "Find a template": "查找模板", + "Find someone, or type a login": "查找用户,或输入登录名", + "Finding copied": "查找已复制", + "Finish it with {0}": "用 {0} 完成", + "Fixup": "修复合并", + "Folder missing": "文件夹丢失", + "Follow the active editor": "跟随活动编辑器", + "Follows the branch you are on · All for every branch": "跟随你所在的分支 · 全部表示所有分支", + "Follows your local branches · All for every branch": "跟随你的本地分支 · 全部表示所有分支", + "For OpenAI / Codex / OpenRouter. Leave blank for a local, keyless server (Ollama / LM Studio). Encrypted at rest in GitStudio's own store and never sent to a webview.": "用于 OpenAI / Codex / OpenRouter。本地无密钥服务器(Ollama / LM Studio)请留空。静态加密存储在 GitStudio 自己的存储中,绝不发送到 webview。", + "Force Delete": "强制删除", + "Force push": "强制推送", + "Forget": "忘记", + "Forget It": "忽略它", + "Forget It and Continue": "忽略并继续", + "Forget Worktree…": "忽略工作树…", + "Forget a worktree": "忽略一个工作树", + "Forget the {0} git can prune: {1}": "忽略 git 可以清理的 {0}:{1}", + "Forget the {0} whose folder is gone": "忽略文件夹已消失的 {0}", + "Forget worktree {0}?": "忘记工作树 {0}?", + "Forgetting…": "正在移除记录…", + "Forgot": "已忘记", + "From the worktree ": "来自工作树 ", + "From {0}": "来自 {0}", + "From {0} — choose the branch it comes from": "来自 {0} — 选择它来自的分支", + "GPT-4o / o-series via the OpenAI API.": "通过 OpenAI API 使用 GPT-4o / o 系列。", + "Gemini 2.5 Pro & Flash via the OpenAI-compatible endpoint.": "通过兼容 OpenAI 的端点使用 Gemini 2.5 Pro 与 Flash。", + "Gemini CLI (local)": "Gemini CLI (本地)", + "Generate commit message": "生成提交信息", + "Generate commit message with AI": "用 AI 生成提交信息", + "Generating commit message…": "正在生成提交信息…", + "Git can't continue yet.": "Git 还无法继续。", + "Git can't safely check out a branch whose name starts with \"-\": \"{0}\"{1} would be read as an option. ": "git 无法安全检出名称以 \"-\" 开头的分支:\"{0}\"{1} 会被当作选项。 ", + "Git can't safely move '{0}': a branch name that starts with \"-\" reads as an option. Rename it, then reset it.": "git 无法安全移动 '{0}':以 \"-\" 开头的分支名会被当作选项。请重命名,然后重置。", + "Git forgets {0}:\n": "Git 将遗忘 {0}:\n", + "Git needs to know how to combine them — this applies to this pull only.": "Git 需要知道如何合并它们 — 这仅适用于本次拉取。", + "Git refused to skip.": "Git 拒绝跳过。", + "Git refused to {0}.": "Git 拒绝{0}。", + "Git won't prune, move or remove it until it is unlocked. Say why, so whoever sees the lock knows — or leave it empty.": "在解锁之前,Git 不会清理、移动或删除它。请说明原因,以便看到锁的人了解情况 — 或留空。", + "Git's default. The new name stays local-only.": "Git 的默认行为。新名称仅保留在本地。", + "GitHub couldn't answer the query.": "GitHub 无法回答该查询。", + "GitHub couldn't find what to {0}.": "GitHub 找不到要{0}的内容。", + "GitHub couldn't {0}.": "GitHub 无法{0}。", + "GitHub deletes {0} after it is merged.": "GitHub 会在 {0} 合并后删除它。", + "GitHub denied the request (insufficient permissions).": "GitHub 拒绝了这个请求(权限不足)。", + "GitHub didn't answer.": "GitHub 没有响应。", + "GitHub has no pull request {0}#{1}": "GitHub 上没有拉取请求 {0}#{1}", + "GitHub has no repository {0}": "GitHub 上没有仓库 {0}", + "GitHub has no repository {0} — or this sign-in can't see it.": "GitHub 上没有仓库 {0} — 或此次登录看不到它。", + "GitHub has no repository {0}/{1}.": "GitHub 上没有仓库 {0}/{1}。", + "GitHub is checking whether it can be merged": "GitHub 正在检查它是否可以合并", + "GitHub is merging {0} into {1}": "GitHub 正在将 {0} 合并到 {1}", + "GitHub no longer accepts this sign-in. Sign in again to see pull requests.": "GitHub 不再接受此登录。请重新登录以查看拉取请求。", + "GitHub rate limit reached. Try again after {0}.": "已达到 GitHub 速率限制。请在 {0} 后重试。", + "GitHub refused to list {0}'s pull requests": "GitHub 拒绝列出 {0} 的拉取请求", + "GitHub refused to list {0}'s pull requests.": "GitHub 拒绝列出 {0} 的拉取请求。", + "GitHub refused to search {0}.": "GitHub 拒绝搜索 {0}。", + "GitHub refused to show {0}": "GitHub 拒绝显示 {0}", + "GitHub refused to show {0}#{1}": "GitHub 拒绝显示 {0}#{1}", + "GitHub refused to show {0}.": "GitHub 拒绝显示 {0}。", + "GitHub refused to {0}.": "GitHub 拒绝{0}。", + "GitHub rejected the request": "GitHub 拒绝了这个请求", + "GitHub request failed (HTTP {0}).": "GitHub 请求失败(HTTP {0})。", + "GitHub takes no approval of your own pull request": "GitHub 不接受批准你自己的拉取请求", + "GitHub takes no change request on your own pull request": "GitHub 不接受对你自己的拉取请求请求更改", + "GitHub takes review comments only on lines that are part of the diff, and {0} {1}. Delete {2} or move {3} onto a changed line.": "GitHub 只接受位于差异中那些行上的审查评论,而 {0} {1}包含在差异中。请删除 {2},或将 {3} 移到已更改的行上。", + "GitHub's rate limit was reached": "已达到 GitHub 的速率限制", + "GitHub's rate limit was reached.": "已达到 GitHub 的速率限制。", + "GitHub's rate limit was reached. Try again in a few minutes.": "已达到 GitHub 的速率限制。请几分钟后重试。", + "GitStudio AI": "GitStudio AI", + "GitStudio Blame": "GitStudio Blame", + "GitStudio Branch Sync": "GitStudio Branch Sync", + "GitStudio Commit Graph": "GitStudio 提交图", + "GitStudio File History": "GitStudio File History", + "GitStudio Pull Request Review": "GitStudio Pull Request Review", + "GitStudio Terminal": "GitStudio 终端", + "GitStudio can't tell what moved '{0}' since \"{1}\" (it keeps no reflog), so it won't guess. Nothing was changed.": "GitStudio 无法判断 '{0}' 自 \"{1}\" 以来被什么移动(它不保存 reflog),因此不会猜测。未做任何更改。", + "GitStudio can't tell what moved HEAD since \"{0}\" (it keeps no reflog), so it won't guess. Nothing was changed.": "GitStudio 无法判断 HEAD 自 \"{0}\" 以来被什么移动(它不保存 reflog),因此不会猜测。未做任何更改。", + "GitStudio is free and open source. If it saves you time, you can support it.": "GitStudio 是免费开源的。如果它为你节省了时间,你可以支持它。", + "GitStudio uses VS Code's GitHub account — no token to paste.": "GitStudio 使用 VS Code 的 GitHub 账号 — 无需粘贴令牌。", + "GitStudio uses VS Code's GitHub account — no token to paste. Then list, check out, review, merge and create pull requests here.": "GitStudio 使用 VS Code 的 GitHub 账号 — 无需粘贴令牌。然后便可在此列出、检出、审查、合并和创建拉取请求。", + "GitStudio · AI": "GitStudio · AI", + "GitStudio — {0}": "GitStudio — {0}", + "GitStudio's Push reaches the pull request; from a terminal, git push {0} HEAD:{1}.": "GitStudio 的推送可直达该拉取请求;在终端中请用 git push {0} HEAD:{1}。", + "GitStudio's Undo can put the branch back{0}.": "GitStudio 的撤销可以把分支放回{0}。", + "GitStudio: AI features are already disabled.": "GitStudio: AI 功能已处于禁用状态。", + "GitStudio: Anthropic API key cleared.": "GitStudio: Anthropic API 密钥已清除。", + "GitStudio: Anthropic API key saved. AI features are now available.": "GitStudio: Anthropic API 密钥已保存。AI 功能现已可用。", + "GitStudio: Commit Graph": "GitStudio: 提交图", + "GitStudio: Interactive Rebase": "GitStudio: 交互式变基", + "GitStudio: Nothing to prune: {0}{1}": "GitStudio: 没有可清理的内容:{0}{1}", + "GitStudio: OpenAI API key cleared (keyless / local mode).": "GitStudio: OpenAI API 密钥已清除(无密钥 / 本地模式)。", + "GitStudio: OpenAI API key cleared.": "GitStudio: OpenAI API 密钥已清除。", + "GitStudio: OpenAI API key saved.": "GitStudio: OpenAI API 密钥已保存。", + "GitStudio: Process Audit": "GitStudio: 进程审计", + "GitStudio: That stash is no longer in the list.": "GitStudio: 该贮藏已不在列表中。", + "GitStudio: a rebase is already in progress — finish or abort it first.": "GitStudio: 已有一个变基在进行中 — 请先完成或中止它。", + "GitStudio: can't undo the repository's initial commit this way.": "GitStudio: 无法用这种方式撤销仓库的初始提交。", + "GitStudio: cannot publish a detached HEAD — check out a branch first.": "GitStudio: 无法发布分离的 HEAD — 请先检出一个分支。", + "GitStudio: commit or stash your changes before reordering — a rebase needs a clean working tree.": "GitStudio: 重新排序前请先提交或贮藏你的更改 — 变基需要干净的工作树。", + "GitStudio: couldn't create branch{0}": "GitStudio: 无法创建分支{0}", + "GitStudio: couldn't create the worktree — {0}": "GitStudio: 无法创建工作树 — {0}", + "GitStudio: couldn't find {0} in this repository's refs — refresh and try again.": "GitStudio: 在此仓库的引用中找不到 {0} — 请刷新后重试。", + "GitStudio: couldn't lock the worktree {0} — {1}": "GitStudio: 无法锁定工作树 {0} — {1}", + "GitStudio: couldn't match this Source Control repository.": "GitStudio: 无法匹配此源代码管理仓库。", + "GitStudio: couldn't prepare the push — {0}": "GitStudio: 无法准备推送 — {0}", + "GitStudio: couldn't prune — {0}": "GitStudio: 无法清理 — {0}", + "GitStudio: couldn't reset {0} to {1}{2}": "GitStudio: 无法将 {0} 重置为 {1}{2}", + "GitStudio: couldn't stage that change — {0}": "GitStudio: 无法暂存该更改 — {0}", + "GitStudio: couldn't stage the changes — {0}": "GitStudio: 无法暂存这些更改 — {0}", + "GitStudio: couldn't stash your changes, so nothing ran — {0}": "GitStudio: 无法贮藏你的更改,因此未执行任何操作 — {0}", + "GitStudio: couldn't unlock the worktree {0} — {1}": "GitStudio: 无法解锁工作树 {0} — {1}", + "GitStudio: couldn't {0} the worktree {1} — its changes were stashed first, and are in the stash list — {2}": "GitStudio: 无法{0}工作树 {1} — 其更改已先被贮藏,并在贮藏列表中 — {2}", + "GitStudio: couldn't {0} the worktree {1} — {2}": "GitStudio: 无法{0}工作树 {1} — {2}", + "GitStudio: couldn't {0} {1} — {2}": "GitStudio: 无法{0} {1} — {2}", + "GitStudio: enter a commit message.": "GitStudio: 请输入提交信息。", + "GitStudio: its changes are back, but “{0}” couldn't be dropped — {1}": "GitStudio: 它的更改已恢复,但无法丢弃“{0}” — {1}", + "GitStudio: keep at least one blame column (Revision, Date, Author, or Commit number).": "GitStudio: 请至少保留一列追溯信息(修订、日期、作者或提交号)。", + "GitStudio: no changes to review — stage or edit some files first.": "GitStudio: 没有可审查的更改 — 请先暂存或编辑一些文件。", + "GitStudio: no changes to summarize.": "GitStudio: 没有可生成摘要的更改。", + "GitStudio: no diff to explain.": "GitStudio: 没有可解释的差异。", + "GitStudio: no key entered.": "GitStudio: 未输入密钥。", + "GitStudio: no remotes configured.": "GitStudio: 未配置远程仓库。", + "GitStudio: no worktree this can be done to.": "GitStudio: 没有可执行此操作的工作树。", + "GitStudio: nothing staged, or AI is unavailable.": "GitStudio: 没有已暂存的内容,或 AI 不可用。", + "GitStudio: nothing stashed — every file was unticked.": "GitStudio: 没有贮藏任何内容 — 所有文件都未勾选。", + "GitStudio: nothing to draft (stage changes first), or AI is unavailable.": "GitStudio: 没有可起草的内容(请先暂存更改),或 AI 不可用。", + "GitStudio: nothing to stash — the working tree is clean.": "GitStudio: 没有可贮藏的内容 — 工作树是干净的。", + "GitStudio: open a file in a Git repository to stage lines.": "GitStudio: 请打开 Git 仓库中的文件以暂存行。", + "GitStudio: renamed locally, but publishing {0} failed{1}. It still tracks {2}/{3}.": "GitStudio: 已在本地重命名,但发布 {0} 失败{1}。它仍跟踪 {2}/{3}。", + "GitStudio: reorder failed{0}": "GitStudio: 重新排序失败{0}", + "GitStudio: reordering hit a conflict — resolve it, then continue or abort the rebase.": "GitStudio: 重新排序时遇到冲突 — 请解决它,然后继续或中止变基。", + "GitStudio: select exactly two commits to compare them.": "GitStudio: 请恰好选择两个提交以进行比较。", + "GitStudio: the Changes view didn't open, so this action can't ask its question. Open the GitStudio sidebar and try again.": "GitStudio: “更改”视图未打开,因此此操作无法提问。请打开 GitStudio 侧边栏后重试。", + "GitStudio: the Changes view isn't available, so this action can't ask for input. Open the GitStudio sidebar and try again.": "GitStudio: “更改”视图不可用,因此此操作无法请求输入。请打开 GitStudio 侧边栏后重试。", + "GitStudio: the history changed while you were dragging — nothing was reordered.": "GitStudio: 你拖动期间历史发生了变化 — 未重新排序任何内容。", + "GitStudio: the rebase stopped and needs you — continue or abort it.": "GitStudio: 变基已停止,需要你处理 — 请继续或中止它。", + "GitStudio: there are no stashes.": "GitStudio: 没有贮藏。", + "GitStudio: this file is not inside an open Git repository.": "GitStudio: 此文件不在已打开的 Git 仓库中。", + "GitStudio: this file isn't in an open Git repository.": "GitStudio: 此文件不在已打开的 Git 仓库中。", + "GitStudio: this line has uncommitted changes — there's no revision yet.": "GitStudio: 此行有未提交的更改 — 还没有修订版本。", + "GitStudio: this repository has no {0} to choose from.": "GitStudio: 此仓库没有可选择的 {0}。", + "GitStudio: those files are no longer in the stash.": "GitStudio: 那些文件已不在该贮藏中。", + "GitStudio: undo failed{0}": "GitStudio: 撤销失败{0}", + "GitStudio: using Claude (Anthropic).": "GitStudio: 正在使用 Claude (Anthropic)。", + "GitStudio: using {0}.": "GitStudio: 正在使用 {0}。", + "GitStudio: {0}": "GitStudio: {0}", + "GitStudio: {0} conflicts. ": "GitStudio: {0} 个冲突。", + "GitStudio: {0} failed{1}": "GitStudio: {0} 失败{1}", + "GitStudio: {0} is a merge commit — {1} it on its own, where you can choose which side to keep.": "GitStudio: {0} 是一个合并提交 — 请单独{1}它,在那里你可以选择保留哪一侧。", + "GitStudio: {0} is hidden by the branch filter.": "GitStudio: {0} 被分支筛选器隐藏。", + "GitStudio: {0} is no longer open, so it can't be shown.": "GitStudio: {0} 已不再打开,因此无法显示。", + "GitStudio: {0} is not a branch on this commit any more — refresh and try again.": "GitStudio: {0} 已不再是此提交上的分支 — 请刷新后重试。", + "GitStudio: {0} is not a local branch.": "GitStudio: {0} 不是本地分支。", + "GitStudio: {0} is not in this repository any more — refresh and try again.": "GitStudio: {0} 已不在此仓库中 — 请刷新后重试。", + "GitStudio: {0} is published and tracked, but {1}/{2} could not be deleted{3}.": "GitStudio: {0} 已发布并被跟踪,但无法删除 {1}/{2}{3}。", + "GitStudio: {0} is the main worktree, which git can't lock.": "GitStudio: {0} 是主工作树,git 无法锁定它。", + "GitStudio: {0} was added by {1}, so there is no earlier revision of it.": "GitStudio: {0} 是由 {1} 添加的,因此没有更早的修订版本。", + "GitStudio: {0}'s folder is gone — {1}. Forget the worktree in Worktrees to clear it from the list.": "GitStudio: {0} 的文件夹已消失 — {1}。在工作树中忽略该工作树即可将其从列表中清除。", + "GitStudio: {0}'s folder is there, so there's nothing to forget. Remove Worktree… removes it, folder and all.": "GitStudio: {0} 的文件夹还在,因此没有可忽略的内容。Remove Worktree… 会连同文件夹一起移除。", + "GitStudio: {0}'s folder isn't a worktree any more — {1}. Forget the worktree in Worktrees to clear it from the list.": "GitStudio: {0} 的文件夹已不再是工作树 — {1}。在工作树中忽略该工作树即可将其从列表中清除。", + "GitStudio: {0}.": "GitStudio: {0}。", + "GitStudio: “{0}” is a binary file, so there is no text to compare. Copy it to Changes to open it.": "GitStudio: “{0}”是二进制文件,因此没有可比较的文本。将其复制到更改即可打开。", + "GitStudio: “{0}” is no longer in that stash.": "GitStudio: “{0}”已不在该贮藏中。", + "Give this commit a name so it stops being unreachable.": "给这个提交一个名称,使其不再无法访问。", + "Go back to the detached HEAD at {0}.": "回到位于 {0} 的分离 HEAD。", + "Go here on a detached HEAD to look around.": "以分离的 HEAD 前往此处查看。", + "Google Gemini": "Google Gemini", + "Got it": "知道了", + "Graph": "图谱", + "Graph & message are always shown": "图表和提交信息始终显示", + "Grok models from xAI.": "来自 xAI 的 Grok 模型。", + "HEAD": "HEAD", + "HEAD has moved since \"{0}\" (it is at {1} now), so the changes it made to your working tree can't be taken back safely.": "HEAD 自 \"{0}\" 以来已移动(现在位于 {1}),因此无法安全撤回它对你工作树所做的更改。", + "HEAD is detached — there is no current branch": "HEAD 处于分离状态 — 没有当前分支", + "HEAD is detached, so there is no branch to pull into. Check out a branch first.": "HEAD 处于分离状态,因此没有可拉入的分支。请先检出一个分支。", + "HEAD is detached, so these commits are on no branch and there is nothing to push them to. Create a branch here to push them.": "HEAD 处于分离状态,因此这些提交不在任何分支上,也没有可推送的目标。请在此创建分支以便推送它们。", + "HEAD was detached when \"{0}\" ran, and it isn't now. Detach it at {1} again, then undo.": "运行 \"{0}\" 时 HEAD 是分离的,现在已不是。请在 {1} 再次分离它,然后撤销。", + "HEAD was detached when the commit was dropped, and it's on a branch now. Detach it again, then undo.": "丢弃该提交时 HEAD 是分离的,现在它在某个分支上。请再次分离它,然后撤销。", + "HEAD was detached when the {0} ran, and it's on a branch now. Detach it again, then undo.": "运行{0}时 HEAD 是分离的,现在它在某个分支上。请再次分离它,然后撤销。", + "HEAD was {0}{1}": "HEAD 曾为 {0}{1}", + "HEAD ↔ Index": "HEAD ↔ 索引", + "HEAD~5 main origin/main": "HEAD~5 main origin/main", + "Hard": "硬重置", + "Hard-resetting to {0} throws away every uncommitted edit in the working tree and the index.": "硬重置到 {0} 会丢弃工作树和索引中的每个未提交编辑。", + "Hide": "隐藏", + "Hide individual changes": "隐藏单个更改", + "Hide the terminal": "隐藏终端", + "Highlight granularity": "高亮粒度", + "Highlight lines": "按行高亮", + "Highlight words": "按词高亮", + "Hold Undo on a file to bring its conflict back.": "在文件上长按撤销可恢复其冲突。", + "Hold to bring the conflict back (hold Enter or Space from the keyboard)": "长按可恢复冲突(键盘上长按 Enter 或空格)", + "Hold to undo": "长按以撤销", + "Hold to undo the resolution of {0}": "长按以撤销对 {0} 的解决", + "Hold {0} to copy": "按住 {0} 复制", + "Hold {0} to pop": "按住 {0} 弹出", + "How to merge": "如何合并", + "Ignore whitespaces": "忽略空白字符", + "Ignore {0} for {1}": "对 {1} 忽略 {0}", + "Ignore {0}, change {1}": "忽略 {0},更改 {1}", + "Ignored": "已忽略", + "Imported 1 key into GitStudio's own encrypted store. Your editor's keychain entry has been cleared.": "已将 1 个密钥导入 GitStudio 自有的加密存储。编辑器钥匙串中的条目已清除。", + "Imported {0} keys into GitStudio's own encrypted store. Your editor's keychain entry has been cleared.": "已将 {0} 个密钥导入 GitStudio 自有的加密存储。编辑器钥匙串中的条目已清除。", + "Include this change in the commit": "在提交中包含此更改", + "Include {0} in the commit": "将 {0} 包含进提交", + "Included in the commit — click to remove it": "已包含在提交中 — 点击可移除", + "Index ↔ Working Tree": "索引 ↔ 工作树", + "Inline blame is on, so the editor's built-in blame is turned off — ": "行内追溯已开启,因此编辑器的内置追溯已关闭 — ", + "Install Claude Code and run `claude login` (docs.anthropic.com/claude-code).": "请安装 Claude Code 并运行 `claude login`(docs.anthropic.com/claude-code)。", + "Install the Codex CLI and sign in (github.com/openai/codex).": "请安装 Codex CLI 并登录(github.com/openai/codex)。", + "Install the Gemini CLI and sign in (github.com/google-gemini/gemini-cli).": "请安装 Gemini CLI 并登录(github.com/google-gemini/gemini-cli)。", + "Interactive Rebase": "交互式变基", + "Interactive rebase": "交互式变基", + "Interactive rebase onto {0}": "交互式变基到 {0}", + "Interactive rebase over a range this long is slow, and a conflict in the middle leaves you resolving one commit at a time. A nearer base is usually what you want.": "对这么长的范围做交互式变基会很慢,中途出现冲突还会让你逐个提交去解决。通常你需要的是更近的基点。", + "Interactive rebase plan refused": "交互式变基计划被拒绝", + "Interactive rebase works best on a clean tree — commit or stash first. GitStudio snapshots your work so Undo can recover it, but git may simply refuse to start.": "交互式变基最好在工作树干净时进行 — 请先提交或贮藏。GitStudio 会为你的工作建立快照,以便撤销能够恢复它,但 git 可能直接拒绝启动。", + "Into": "合入", + "Into {0}": "合并到 {0}", + "Into {0} — choose the branch it goes into": "合并到 {0} — 选择它进入的分支", + "It and {0} have diverged: {1} to push, {2} to pull.": "它和 {0} 已分叉:{1}待推送,{2}待拉取。", + "It can't be merged into {0} until they are resolved: check it out, merge {1} into it and push.": "在解决它们之前它无法合并到 {0}:请检出它,将 {1} 合并进去并推送。", + "It has 1 uncommitted change:\n": "它有 1 个未提交的更改:\n", + "It has been pushed since, so putting it back would rewrite published history — it can only be reverted.": "它此后已被推送,放回它会改写已发布的历史 — 只能还原它。", + "It has no branch checked out (detached at {0}).": "它没有检出任何分支(游离于 {0})。", + "It has {0} the pull request doesn't. It will track {1}, so a push adds them to it.": "它有的 {0} 在拉取请求中没有。它将跟踪 {1},因此推送会把这些提交加进去。", + "It has {0} uncommitted changes:\n": "它有 {0} 个未提交的更改:\n", + "It is at the pull request's latest. It will track {0}.": "它已在拉取请求的最新版本上。它将跟踪 {0}。", + "It is fully merged into {0}, so no commit is lost.": "它已完全合并进 {0},因此不会丢失任何提交。", + "It is locked already.": "它已被锁定。", + "It is locked, with no reason given.": "它已被锁定,未给出原因。", + "It is locked: “{0}”.": "它已被锁定:“{0}”。", + "It is still a draft.": "它仍是草稿。", + "It is still open.": "它仍是打开的。", + "It is still {0}.": "它仍然是{0}。", + "It is the bare repository itself, not a working tree.": "它就是裸仓库本身,不是工作树。", + "It isn't a worktree any more — {0}.": "它已不再是工作树 — {0}。", + "It isn't locked.": "它未被锁定。", + "It stays": "保留在原处", + "It was recorded by an older version of GitStudio, which can't say exactly what it changed. Nothing was changed.": "它由旧版 GitStudio 记录,无法准确说明它更改了什么。未做任何更改。", + "It's": "它位于", + "It's the newest commit, so nothing else changes.": "它是最新的提交,因此不会有其他变化。", + "Its 1 uncommitted change": "它的 1 个未提交的更改", + "Its 1 uncommitted change goes with it, and nothing can bring it back:\n": "它的 1 个未提交的更改会随之消失,无法恢复:\n", + "Its author marks it ready for review before it can be merged.": "需要其作者将其标记为待评审后才能合并。", + "Its branch": "它的分支", + "Its branch has no upstream to pull from.": "它的分支没有可供拉取的上游。", + "Its branch has no upstream: Push publishes it.": "它的分支没有上游:推送即可发布它。", + "Its branch — the one checked out here": "它的分支 — 即在此检出的那个", + "Its changes come": "它的更改来自", + "Its changes come back {0} and the stash is dropped.{1}": "它的更改会以{0}方式恢复,且该贮藏会被丢弃。{1}", + "Its changes come back {0}. The stash is kept, staging and all.": "它的更改会以{0}方式恢复。该贮藏会保留,包括暂存状态。", + "Its commits join your history. If the two sides touched the same lines you'll get conflicts to resolve, and Undo can take you back either way.": "它的提交会加入你的历史。如果两侧修改了相同的行,你会遇到需要解决的冲突,而无论哪种情况都可以用撤销回退。", + "Its files couldn't be read.": "无法读取它的文件。", + "Its folder is gone: {0}. Forgetting it removes git's record of the worktree; nothing on disk changes.": "它的文件夹已不在:{0}。忘记它会删除 git 对该工作树的记录;磁盘上不会有任何变化。", + "Its folder is missing.": "它的文件夹丢失了。", + "Its folder is there, but it isn't a worktree any more: {0}. Forget it to clear it from the list — the folder and its files stay.": "它的文件夹还在,但已不再是工作树:{0}。忘记它即可从列表中清除 — 文件夹及其文件会保留。", + "Its folder isn't there. Forget it to clear it from the list — if it is on a drive that isn't connected, connect it instead.": "它的文件夹不在。忘记它即可从列表中清除 — 如果它位于未连接的驱动器上,请改为连接该驱动器。", + "Its folder isn't there. Forget it to clear it from the list.": "它的文件夹不在。忘记它即可从列表中清除。", + "Its folder isn't there: {0}. Forgetting it removes git's record of the worktree. If the folder is on a drive that isn't connected, it is no longer a worktree when the drive comes back.": "它的文件夹不在:{0}。忘记它会删除 git 对该工作树的记录。如果该文件夹位于未连接的驱动器上,驱动器恢复后它就不再是工作树。", + "Its folder, {0}, isn't a worktree any more: {1}. Forgetting it removes git's record of the worktree; the folder and everything in it stay.": "它的文件夹 {0} 已不再是工作树:{1}。忘记它会删除 git 对该工作树的记录;文件夹及其中的所有内容会保留。", + "Its remote-tracking branches are renamed to match.": "它的远程跟踪分支会相应重命名。", + "Its remote-tracking branches go with it. Nothing on the server changes.": "它的远程跟踪分支会随之变化。服务器上没有任何改动。", + "Its uncommitted changes": "它的未提交更改", + "Its uncommitted changes couldn't be read.": "无法读取它的未提交更改。", + "Its uncommitted changes couldn't be read; any it has are deleted with it.": "无法读取它的未提交更改;它拥有的任何更改都会随之删除。", + "Its unstaged edits are lost; the part you staged stays staged. {0}": "它未暂存的修改会丢失;已暂存的部分仍保持暂存。{0}", + "Its upstream, {0}, is gone from the remote.": "它的上游 {0} 已从远程消失。", + "Its upstream, {0}, was deleted from the remote.": "它的上游 {0} 已从远程删除。", + "Its {0} are still marked so you can check each; Apply saves the Result as shown.": "它的 {0} 仍带有标记,便于你逐处检查;应用会按结果当前所示保存。", + "Its {0} is still marked so you can check each; Apply saves the Result as shown.": "它的 {0} 仍带有标记,便于你检查;应用会按结果当前所示保存。", + "Its {0} uncommitted changes": "它的 {0} 个未提交的更改", + "Its {0} uncommitted changes go with it, and nothing can bring them back:\n": "它的 {0} 个未提交的更改会随之消失,无法恢复:\n", + "Its {0} {1}": "它的 {0} {1}", + "Jump to HEAD": "跳到 HEAD", + "Keep Staged": "保留暂存", + "Keep editing": "继续编辑", + "Keep going": "继续", + "Keep my changes": "保留我的更改", + "Keep parent {0}": "保留父提交 {0}", + "Keep staged changes staged": "让已暂存的更改保持暂存", + "Keep the branch that was merged in": "保留被合并进来的分支", + "Keep the branch this was merged into": "保留合并到的那个分支", + "Keep them": "保留它们", + "Keep tracking {0}/{1}": "继续跟踪 {0}/{1}", + "Keep what's here": "保留此处的内容", + "Keep your pending comments": "保留你未提交的评论", + "Keep {0} and stage it": "保留 {0} 并暂存它", + "Keeps its {0}. Nothing is reset.": "保留其 {0}。不会重置任何内容。", + "Kept {0}{1} and staged it.": "已保留 {0}{1} 并暂存。", + "LM Studio (local)": "LM Studio (本地)", + "Label it": "添加标签", + "Label: {0}": "标签:{0}", + "Labels": "标签", + "Language Model": "语言模型", + "Large file: word-level highlights disabled": "文件较大:已禁用词级高亮", + "Last commit resolved": "最后一个提交已解决", + "Last commit skipped. {0} complete, without it": "已跳过最后一个提交。{0}完成,但不含该提交", + "Last patch resolved": "最后一个补丁已解决", + "Last patch skipped. The series is finished, without it": "已跳过最后一个补丁。该补丁序列已完成,不含它", + "Last {0} resolved": "最后一个 {0} 已解决", + "Leave a comment — Markdown works": "留下评论 — 支持 Markdown", + "Leave a summary (optional)": "留下摘要(可选)", + "Leave everything as it is": "保持一切原样", + "Leave it alone": "不去管它", + "Leave that edit in {0}, and keep working here. Apply replaces it with the Result.": "把该编辑留在 {0},并在此继续工作。应用会用结果替换它。", + "Leave the branch local-only; set a new upstream later.": "让分支仅保留在本地;稍后再设置新的上游。", + "Left or Escape goes back to the branches": "按左键或 Escape 返回分支列表", + "Let {0} open conflicts": "让 {0} 打开冲突", + "Line History — {0}": "行历史 — {0}", + "Line history": "行历史", + "Line {0}": "第 {0} 行", + "Lines removed on one side only, or the same lines removed on both: no conflict, safe to take": "仅一侧删除了这些行,或两侧删除了相同的行:没有冲突,可以安全采用", + "Lines {0} to {1}": "第 {0} 到 {1} 行", + "Load more": "加载更多", + "Loading editor…": "正在加载编辑器…", + "Loading files…": "正在加载文件…", + "Loading history…": "正在加载历史…", + "Loading its files…": "正在加载它的文件…", + "Loading line history ({0}–{1})…": "正在加载行历史({0}–{1})…", + "Loading pull requests": "正在加载拉取请求", + "Loading rebase plan…": "正在加载变基计划…", + "Loading the changed files…": "正在加载已更改的文件…", + "Loading the commits": "正在加载提交", + "Loading the files": "正在加载文件", + "Loading the form": "正在加载表单", + "Loading the pull request": "正在加载拉取请求", + "Loading…": "加载中…", + "Local": "本地", + "Local branches": "本地分支", + "Local models via LM Studio's server — private, no key.": "通过 LM Studio 的服务器使用本地模型 — 隐私安全,无需密钥。", + "Local only": "仅本地", + "Lock": "锁定", + "Lock a worktree": "锁定工作树", + "Lock worktree {0}": "锁定工作树 {0}", + "Locked": "已锁定", + "Locked the worktree {0}": "已锁定工作树 {0}", + "Locked, with no reason given. Git won't prune, move or remove it until it is unlocked.": "已锁定,未给出原因。在解锁之前,git 不会清理、移动或移除它。", + "Locked: {0}": "已锁定:{0}", + "Locked: “{0}”. Git won't prune, move or remove it until it is unlocked.": "已锁定:“{0}”。在解锁之前,git 不会清理、移动或移除它。", + "Lock…": "锁定…", + "Looking for a repository…": "正在查找仓库…", + "L{0}": "第{0}行", + "L{0}–{1}": "第{0}–{1}行", + "Main worktree": "主工作树", + "Main worktree — the repository's own folder.": "主工作树 — 仓库自己的文件夹。", + "Make your first commit and the history will appear here.": "完成第一次提交后,历史就会显示在这里。", + "Makes {0} match {1}, then switches to it. Asks first, and says what would be lost.": "使 {0} 与 {1} 一致,然后切换到它。会先询问,并说明将丢失什么。", + "Manage remotes": "管理远程仓库", + "Mark it ready for review to merge it.": "请将其标记为待评审以合并。", + "Mark ready": "标记为待评审", + "Mark this conversation resolved": "将此对话标记为已解决", + "Marking ready…": "正在标记为就绪…", + "Merge": "合并", + "Merge #{0} into {1}": "将 #{0} 合并到 {1}", + "Merge '{0}' into {1}": "将“{0}”合并到 {1}", + "Merge Conflicts": "合并冲突", + "Merge Studio": "Merge Studio", + "Merge applied": "已应用合并", + "Merge applied and staged": "已应用合并并暂存", + "Merge conflicts": "合并冲突", + "Merge in progress": "合并进行中", + "Merge pull request #{0} from {1}/{2}": "合并来自 {1}/{2} 的拉取请求 #{0}", + "Merge the base branch into this one, on GitHub": "在 GitHub 上将基点分支合并到这个分支", + "Merge this pull request": "合并此拉取请求", + "Merge this pull request — choose how": "合并此拉取请求 — 选择方式", + "Merge {0}": "合并 {0}", + "Merge {0} into the current branch?": "将 {0} 合并到当前分支?", + "Merge {0} into this branch on GitHub": "在 GitHub 上将 {0} 合并到此分支", + "Merge {0} into {1}?": "将 {0} 合并到 {1}?", + "Merged by {0} into {1} ": "已由 {0} 合并进 {1} ", + "Merged into {0} ": "已合并进 {0} ", + "Merged pull requests show here once some land.": "合并后的拉取请求落地后会显示在这里。", + "Merged {0}": "已合并 {0}", + "Merges {0} from {1} into {2}": "将 {0} 从 {1} 合并到 {2}", + "Merges {0} into {1}": "将 {0} 合并到 {1}", + "Merge…": "合并…", + "Merging is blocked": "合并被阻止", + "Merging {0} into {1}": "正在将 {0} 合并到 {1}", + "Merging…": "正在合并…", + "Message": "提交信息", + "Message (what & why)…": "提交信息(做了什么与为什么)…", + "Mistral & Codestral models.": "Mistral 与 Codestral 模型。", + "Mixed": "混合重置", + "Model ID for commit messages and explain — gpt-4o-mini, llama3.1, qwen2.5-coder.": "用于提交信息和解释的模型 ID — gpt-4o-mini、llama3.1、qwen2.5-coder。", + "Modified": "已修改", + "Monaco worker URI was not provided by the host.": "宿主未提供 Monaco worker 的 URI。", + "More Actions…": "更多操作…", + "More actions": "更多操作", + "More actions for pull request #{0}": "拉取请求 #{0} 的更多操作", + "More actions for {0}": "{0} 的更多操作", + "Move": "移动", + "Move down": "下移", + "Move down (Alt+Down)": "下移(Alt+Down)", + "Move the branch and DISCARD every working-tree and staged change.": "移动分支,并丢弃工作树和暂存区的所有更改。", + "Move the branch, keep the working tree, unstage everything. Git's default.": "移动分支,保留工作树,取消所有暂存。这是 Git 的默认行为。", + "Move the branch. Keep your working tree AND everything staged.": "移动分支。保留工作树以及所有已暂存的内容。", + "Move the current branch back to this commit.": "将当前分支移回此提交。", + "Move the selected commits down": "下移选中的提交", + "Move the selected commits down (Alt+Down)": "下移选中的提交(Alt+Down)", + "Move the selected commits up": "上移选中的提交", + "Move the selected commits up (Alt+Up)": "上移选中的提交(Alt+Up)", + "Move to Changes": "移到更改", + "Move up": "上移", + "Move up (Alt+Up)": "上移(Alt+Up)", + "Move {0} out of “{1}”": "将 {0} 移出“{1}”", + "Move {0} to Changes": "将 {0} 移动到“更改”", + "Move: take {0} out of the stash, back {1}": "移动:将 {0} 从贮藏中取出,放回 {1}", + "Moved {0} to Changes": "已将 {0} 移到更改", + "Must be addressed before merging": "合并前必须处理", + "Name this stash": "为此贮藏命名", + "Needs action": "需要处理", + "Needs the `claude` CLI on your PATH and signed in. Model names map to `claude --model`.": "需要在 PATH 中有 `claude` CLI 并已登录。模型名会映射到 `claude --model`。", + "Needs the `codex` CLI on your PATH and signed in.": "需要在 PATH 中有 `codex` CLI 并已登录。", + "Needs the `gemini` CLI on your PATH and signed in.": "需要在 PATH 中有 `gemini` CLI 并已登录。", + "Neither side has this file — delete it and stage the deletion": "两侧都没有此文件 — 删除它并暂存该删除", + "Neutral": "中立", + "Neutral, in {0}": "中性,在 {0} 中", + "New Branch": "新建分支", + "New Branch '": "新建分支 '", + "New Branch '{0}'": "新建分支 '{0}'", + "New Branch from '": "新建分支,起点为 '", + "New Branch from These Commits": "从这些提交新建分支", + "New Branch…": "新建分支…", + "New Worktree from '": "新建工作树,起点为 '", + "New Worktree…": "新建工作树…", + "New branch": "新建分支", + "New branch from {0}": "从 {0} 新建分支", + "New branch…": "新建分支…", + "New commit message…": "新提交信息…", + "New in {0} {1}:": "{0} 中的新增内容 {1}:", + "New pull request": "新建拉取请求", + "New pull request · {0}": "新建拉取请求 · {0}", + "New worktree branch": "新工作树分支", + "New worktree for {0}": "为 {0} 新建工作树", + "New worktree — pick a ref": "新建工作树 — 选择一个引用", + "Next change (F7)": "下一个更改(F7)", + "Next match (Enter)": "下一个匹配项 (Enter)", + "No AI model is connected. Connect one from the ✨ button in the Changes view, then run the review again.": "未连接任何 AI 模型。请在“更改”视图中通过 ✨ 按钮连接一个,然后重新运行审查。", + "No AI model is connected. Connect one from the ✨ button in the Changes view, then try again.": "未连接任何 AI 模型。请在“更改”视图中通过 ✨ 按钮连接一个,然后重试。", + "No Anthropic API key set. Add it in Settings ▸ AI.": "未设置 Anthropic API 密钥。请在“设置 ▸ AI”中添加。", + "No GitStudio keys were found in the editor's secret storage.": "在编辑器的密钥存储中未找到 GitStudio 密钥。", + "No actions yet": "暂无操作", + "No active repository.": "没有活动仓库。", + "No branch is checked out in it, so there is nothing to pull into.": "它没有检出任何分支,因此没有可拉取到的目标。", + "No branch is checked out in it, so there is nothing to push.": "它没有检出任何分支,因此没有可推送的内容。", + "No branch matches": "没有匹配的分支", + "No branch or tag matches '": "没有匹配的分支或标签 '", + "No branches match": "没有匹配的分支", + "No branches or tags": "没有分支或标签", + "No changed files.": "没有已更改的文件。", + "No changes": "没有更改", + "No changes to commit.": "没有可提交的更改。", + "No checks": "无检查", + "No checks run on this pull request's latest commit.": "此拉取请求的最新提交上没有运行任何检查。", + "No closed pull requests": "没有已关闭的拉取请求", + "No commits to rebase from that point.": "从该点起没有可变基的提交。", + "No commits to rebase.": "没有可变基的提交。", + "No commits yet": "还没有提交", + "No commits —": "没有提交 —", + "No commits.": "没有提交。", + "No common version was found, so both sides are compared against an empty file.": "未找到共同版本,因此两侧都与空文件进行比较。", + "No conflicted files at this step.": "此步骤没有冲突文件。", + "No conflicted files.": "没有冲突文件。", + "No content changes.": "没有内容更改。", + "No description provided.": "未提供描述。", + "No file changes between these refs.": "这两个引用之间没有文件更改。", + "No file changes in these commits.": "这些提交中没有文件更改。", + "No file changes in this commit.": "此提交中没有文件更改。", + "No file changes.": "没有文件更改。", + "No files change.": "没有文件变更。", + "No files match the filter.": "没有文件匹配该筛选条件。", + "No history for lines {0}–{1} of {2}.": "{2} 的第 {0}–{1} 行没有历史记录。", + "No history for {0}.": "{0} 没有历史记录。", + "No issues": "没有问题", + "No label matches": "没有匹配的标签", + "No labels match": "没有匹配的标签", + "No line comments yet. In Files, open a file and click + beside a changed line to add one.": "还没有行评论。在“文件”中打开一个文件,点击已更改行旁边的 + 即可添加。", + "No local branches": "没有本地分支", + "No match — Enter uses what you typed": "没有匹配项 — 按 Enter 使用你输入的内容", + "No matches": "没有匹配项", + "No merge method is allowed": "不允许任何合并方式", + "No merged pull requests": "没有已合并的拉取请求", + "No model configured for this connection.": "此连接未配置模型。", + "No model is connected yet — pick one below.": "尚未连接模型 — 请在下方选择一个。", + "No one": "没有人", + "No one matches": "没有人匹配", + "No one yet": "还没有人", + "No open pull requests": "没有打开的拉取请求", + "No open pull requests.": "没有打开的拉取请求。", + "No pull requests yet": "还没有拉取请求", + "No rebase in progress — a {0} is. Abort it from the Conflicts dashboard.": "没有正在进行的变基 — 正在进行的是 {0}。请从冲突面板中止它。", + "No rebase in progress.": "没有正在进行的变基。", + "No remote is configured for this repository.": "此仓库未配置远程仓库。", + "No remote matches": "没有匹配的远程仓库", + "No remotes configured": "未配置远程仓库", + "No repository is open": "没有打开的仓库", + "No repository matches": "没有匹配的仓库", + "No repository open": "没有打开的仓库", + "No response from the model — check the server, base URL and model ID.": "模型没有响应 — 请检查服务器、基础 URL 和模型 ID。", + "No results": "没有结果", + "No results in {0} loaded": "未加载 {0} 中的结果", + "No review is under way. Start one from a pull request's page.": "没有进行中的审查。请从拉取请求页面开始一个。", + "No reviews yet": "还没有审查", + "No separate changes to pick from.": "没有可挑选的独立更改。", + "No template": "没有模板", + "No template matches": "没有匹配的模板", + "No textual diff (binary, empty, or rename with no content change).": "没有文本差异(二进制、空文件,或重命名但没有内容更改)。", + "No undo history yet": "还没有撤销历史", + "No upstream": "无上游", + "No upstream set\n\n": "未设置上游\n\n", + "No upstream: {0} no remote has yet. Push publishes the branch.": "无上游:远程还没有 {0}。推送即可发布该分支。", + "No worktree matches “{0}”.": "没有工作树匹配“{0}”。", + "No {0}pull requests match": "没有匹配的 {0}拉取请求", + "None": "无", + "None of them is required: merging is still allowed.": "它们都不是必需的:仍可合并。", + "None of these can be {0} — nothing {1} them is kept to fold into.": "这些都无法{0} — 它们{1}没有任何保留下来可供折叠的提交。", + "None of this repository's remotes is on github.com: {0}. Pull requests are available for github.com repositories.": "此仓库的远程仓库都不在 github.com 上:{0}。拉取请求仅适用于 github.com 上的仓库。", + "None of those files are in the stash.": "那些文件都不在贮藏中。", + "None selected": "未选择任何内容", + "None yet": "还没有", + "Not a valid git ref name.": "不是有效的 git 引用名称。", + "Not a worktree": "不是工作树", + "Not all of those commits are on the current branch, so they can't be {0} from it.": "这些提交并非都在当前分支上,因此无法从该分支{0}它们。", + "Not assigned": "未指派", + "Not found on GitHub.": "在 GitHub 上未找到。", + "Not in the branch list yet — refresh": "还不在分支列表中 — 请刷新", + "Not in the branch list yet — refresh the graph": "还不在分支列表中 — 请刷新提交图", + "Not included — click to include it": "未包含 — 点击以包含", + "Not now": "暂不", + "Not on any branch": "不在任何分支上", + "Not on any remote": "不在任何远程上", + "Not on {0}": "不在 {0} 上", + "Not pushed to {0}": "未推送到 {0}", + "Not ready to continue yet": "还不能继续", + "Not staged — click to stage this change": "未暂存 — 点击以暂存此更改", + "Nothing above it is kept to fold into — git can't run this": "上方没有保留可供折叠的提交 — git 无法执行此操作", + "Nothing changes until you press “Start Rebase,”": "在你按下“开始变基”之前不会有任何改动,", + "Nothing changes.": "不会有任何改动。", + "Nothing could be stashed.": "没有任何内容可以贮藏。", + "Nothing else changes.": "其他都不会改变。", + "Nothing here": "这里什么都没有", + "Nothing is blocking it.": "没有任何东西阻止它。", + "Nothing is in progress.": "没有正在进行中的操作。", + "Nothing is left to commit at this step: it is already on the branch. Skip it, or abort.": "此步骤没有可提交的内容:它已经在分支上了。请跳过它,或中止。", + "Nothing is pushed and nothing is pulled.": "没有推送也没有拉取。", + "Nothing is pushed.": "没有推送任何内容。", + "Nothing is staged for this patch. Apply it by hand and stage the result, or skip the patch.": "此补丁没有已暂存的内容。请手动应用并暂存结果,或跳过该补丁。", + "Nothing is staged — stage the changes you want to include, then commit.": "没有已暂存的内容 — 请先暂存你想包含的更改,然后提交。", + "Nothing is staged — the only changes are new files git isn't tracking yet. Stage them to include them in a commit.": "没有已暂存的内容 — 唯一的更改是 git 尚未跟踪的新文件。请暂存它们以包含在提交中。", + "Nothing is staged, so everything currently changed will be included — new files too. ": "没有任何内容被暂存,因此当前所有已更改的内容都会被包含 — 新文件也一样。", + "Nothing is waiting to be reviewed or merged.": "没有等待审查或合并的内容。", + "Nothing is written to it until you choose.": "在你选择之前不会写入任何内容。", + "Nothing matches these filters.": "没有内容匹配这些筛选条件。", + "Nothing matches “{0}” with these filters.": "在这些筛选条件下没有内容匹配“{0}”。", + "Nothing runs on this branch's commits.": "此分支的提交上不会运行任何内容。", + "Nothing runs.": "不会运行任何内容。", + "Nothing runs. Apply keeps the stash, so its staged versions stay in it.": "不会运行任何内容。应用会保留该贮藏,因此其暂存版本仍留在其中。", + "Nothing runs. Commit or stash them yourself first.": "不会运行任何内容。请先自行提交或贮藏它们。", + "Nothing runs. {0} in the stash, staging and all.": "不会运行任何内容。{0} 会留在贮藏中,包括暂存状态。", + "Nothing to commit or push.": "没有可提交或推送的内容。", + "Nothing to commit — the working tree is clean.": "没有可提交的内容 — 工作树是干净的。", + "Nothing to compare: {0} has no commits that {1} doesn't.": "没有可比较的内容:{0} 没有 {1} 所没有的提交。", + "Nothing to merge line by line": "没有可逐行合并的内容", + "Nothing to push — it is up to date with {0}.": "没有可推送的内容 — 它与 {0} 已同步。", + "Nothing to rebase — all 1 commit here are either merges or changes already on the base, which a rebase would skip.": "没有可变基的提交 — 这里全部 1 个提交要么是合并,要么是已存在于基点上的更改,变基会跳过它。", + "Nothing to rebase — all {0} commits here are either merges or changes already on the base, which a rebase would skip.": "没有可变基的提交 — 这里全部 {0} 个提交要么是合并,要么是已存在于基点上的更改,变基会跳过它们。", + "Nothing to rebase.": "没有可变基的内容。", + "Nothing to resolve here. Continue when you are ready.": "这里没有需要解决的内容。准备好后即可继续。", + "Nothing to revert — \"{0}\" is already undone.": "没有可还原的内容 — “{0}”已被撤销。", + "Nothing to revert — {0} is already undone on this branch.": "没有可还原的内容 — {0} 已在此分支上被撤销。", + "Nothing to stash — nothing is staged.": "没有可贮藏的内容 — 没有任何已暂存的内容。", + "Nothing to stash — the files you selected have no changes.": "没有可贮藏的内容 — 你选择的文件没有任何更改。", + "Nothing to stash — the working tree is clean.": "没有可贮藏的内容 — 工作树是干净的。", + "Nothing to undo": "没有可撤销的内容", + "Nothing to undo for \"{0}\" — {1}": "“{0}”没有可撤销的内容 — {1}", + "Nothing was pruned": "没有清理任何内容", + "Nothing was stashed — the files you selected are new ones git isn't tracking yet. Stash again with \"Include untracked files\" to put those away too.": "未贮藏任何内容 — 你选择的文件是 git 尚未跟踪的新文件。请勾选 \"Include untracked files\" 再次贮藏,以便把这些也收起来。", + "Nothing was stashed — the only changes are new files git isn't tracking yet. Stash again with \"Include untracked files\" to put those away too.": "未贮藏任何内容 — 唯一的更改是 git 尚未跟踪的新文件。请勾选 \"Include untracked files\" 再次贮藏,以便把这些也收起来。", + "Nothing was written. {0} changed outside the merge editor: reload the merge, or keep that edit, first.": "没有写入任何内容。{0} 在合并编辑器之外被修改了:请先重新加载合并,或保留该编辑。", + "Nothing was written. {0} keeps the resolution it had.": "没有写入任何内容。{0} 保留原有的解决结果。", + "OK": "确定", + "Ollama (local)": "Ollama (本地)", + "One key, hundreds of models (Claude, GPT, Llama, Gemini, …).": "一个密钥,数百个模型(Claude、GPT、Llama、Gemini……)。", + "One later commit will be replayed on top, with a new SHA.": "稍后的一个提交会在其之上重放,并生成新的 SHA。", + "One of those commits is a merge — {0} it would flatten the history it joined.": "其中一个提交是合并提交 — {0}它会压平它并入的历史。", + "One side only": "仅一侧", + "One side only — safe to take (blue): only one side added or changed these lines.": "仅一侧 — 可以安全采用(蓝色):只有一侧新增或修改了这些行。", + "Only commits next to each other on the branch can be squashed — there are other commits between the ones you selected.": "只有分支上相邻的提交才能压缩 — 你选择的提交之间还有其他提交。", + "Only one side added or changed these lines": "只有一侧新增或修改了这些行", + "Only the first 100 are listed; type to find others.": "只列出前 100 个;输入以查找其他项。", + "Only the local name changes — the commits and the remote branch stay where they are.": "只有本地名称会变化 — 提交和远程分支都保持原样。", + "Only whitespace changed here": "此处仅空白字符有变化", + "Open": "打开", + "Open #{0}": "打开 #{0}", + "Open All Changes": "打开所有更改", + "Open Changes": "打开更改", + "Open Changes (vs HEAD)": "打开与 HEAD 的更改对比", + "Open Containing Folder": "打开所在文件夹", + "Open File": "打开文件", + "Open Folder…": "打开文件夹…", + "Open GitHub's page that authorizes this sign-in for the organization": "打开 GitHub 上为该组织授权此登录的页面", + "Open Pull Request": "打开拉取请求", + "Open Sample Diff": "打开示例差异", + "Open Sample Merge": "打开示例合并", + "Open Staged Changes": "打开已暂存的更改", + "Open Workspace": "打开工作区", + "Open Worktree in New Window": "在新窗口中打开工作树", + "Open a Git repository to open a pull request from it.": "打开一个 Git 仓库以从其中创建拉取请求。", + "Open a Git repository to see its pull requests.": "打开一个 Git 仓库以查看其拉取请求。", + "Open a file in a Git repository first": "请先在 Git 仓库中打开一个文件", + "Open a file, then click + beside a changed line to comment": "打开一个文件,然后点击已更改行旁边的 + 即可评论", + "Open a folder that is a git repository to see its worktrees.": "打开一个 git 仓库文件夹以查看其工作树。", + "Open a folder that's under Git and its history will appear here.": "打开一个处于 Git 管理下的文件夹,其历史就会显示在这里。", + "Open a folder that's under Git to see your changes, branches, and history.": "打开一个处于 Git 管理下的文件夹,即可查看你的更改、分支和历史。", + "Open a new pull request": "发起新的拉取请求", + "Open a pull request — from the branch checked out, or any other": "创建拉取请求 — 可从已检出的分支或任何其他分支", + "Open a terminal at the repository root": "在仓库根目录打开终端", + "Open a terminal in a worktree": "在工作树中打开终端", + "Open a worktree in a new window": "在新窗口中打开工作树", + "Open a worktree in this window": "在此窗口中打开工作树", + "Open changes — {0}{1}": "打开更改 — {0}{1}", + "Open in Commit Graph": "在提交图中打开", + "Open in Embedded Diff": "在内嵌差异视图中打开", + "Open in New Window": "在新窗口中打开", + "Open in Terminal": "在终端中打开", + "Open in This Window": "在此窗口中打开", + "Open in diff editor": "在差异编辑器中打开", + "Open models at very low latency.": "极低延迟的开源模型。", + "Open on GitHub": "在 GitHub 上打开", + "Open on GitHub for the rest": "将其余的都在 GitHub 上打开", + "Open on remote": "在远端打开", + "Open pull request #{0}": "打开拉取请求 #{0}", + "Open pull request #{0} on GitHub": "在 GitHub 上打开拉取请求 #{0}", + "Open pull requests": "打开的拉取请求", + "Open the first file, ready for your comments": "打开第一个文件,随时可以评论", + "Open the first one to propose a change.": "打开第一个以提出更改。", + "Open the pull request's page": "打开该拉取请求的页面", + "Open this change in the diff": "在差异中打开此更改", + "Open this conversation again": "重新打开此对话", + "Open this pull request on GitHub": "在 GitHub 上打开此拉取请求", + "Open {0} at Revision": "在修订版本处打开 {0}", + "Open {0} at line {1}": "在第 {1} 行打开 {0}", + "Open {0} — the lines this was written on have changed since": "打开 {0} — 这段内容所对应的行之后已发生变化", + "Open {0}'s details": "打开 {0} 的详情", + "OpenAI / local (OpenAI-compatible)": "OpenAI / 本地(OpenAI 兼容)", + "OpenAI models hosted in your Azure tenant.": "托管在你的 Azure 租户中的 OpenAI 模型。", + "OpenAI rate limit hit — try again in a moment.": "已达到 OpenAI 速率限制 — 请稍后重试。", + "OpenAI, Codex, OpenRouter, or a local server (Ollama / LM Studio). Base URL / model / key.": "OpenAI、Codex、OpenRouter,或本地服务器(Ollama / LM Studio)。基础 URL / 模型 / 密钥。", + "OpenAI-compatible Base URL": "OpenAI 兼容基础 URL", + "OpenAI-compatible Model": "OpenAI 兼容模型", + "OpenAI-compatible request failed (HTTP {0}).": "OpenAI 兼容请求失败(HTTP {0})。", + "Opens on {0} — choose another repository": "在 {0} 上打开 — 选择另一个仓库", + "Operation failed.": "操作失败。", + "Operation in progress": "操作进行中", + "Or this GitHub sign-in can't see it.": "或者此 GitHub 登录看不到它。", + "Or this GitHub sign-in can't see it: a private repository needs an account with access to it.": "或者此 GitHub 登录看不到它:私有仓库需要拥有访问权限的账号。", + "Otherwise git labels it with the branch and its last commit.": "否则 git 会用分支及其最后一次提交来标记它。", + "Outdated": "已过时", + "Overview of the changes still to resolve — press to go there": "尚未解决更改的概览 — 按下可前往", + "Partly included — click to include the rest": "部分已包含 — 点击以包含其余部分", + "Partly staged — click to stage the rest": "部分已暂存 — 点击以暂存其余部分", + "Partly staged — click to stage the rest of this change": "部分已暂存 — 点击以暂存此更改的其余部分", + "Passed": "已通过", + "Passed in {0}": "在 {0} 中通过", + "Patch conflicts": "补丁冲突", + "Patch series": "补丁序列", + "Patch series abandoned": "补丁系列已放弃", + "Patch series abandoned — the branch is back where it was before it started.": "补丁系列已放弃 — 分支已回到开始之前的状态。", + "Patch {0}": "补丁 {0}", + "Patch {0} of {1}": "第 {0} 个补丁,共 {1} 个", + "Paused": "已暂停", + "Paused at a break in the rebase plan": "在变基计划的断点处暂停", + "Paused because a command in the rebase plan failed": "因变基计划中的命令失败而暂停", + "Paused because the command “{0}” failed": "因命令“{0}”失败而暂停", + "Paused to edit a commit": "暂停以编辑提交", + "Paused to edit {0} {1}": "暂停以编辑 {0} {1}", + "Paused: {0}": "已暂停:{0}", + "Pending": "待处理", + "Pending for {0}": "已等待 {0}", + "Pending review comment": "待提交的审查评论", + "Pick": "保留", + "Pick a base": "选择基点", + "Pick a branch": "选择分支", + "Pick a commit to diff it against its parent.": "选择一个提交,与其父提交进行差异比较。", + "Pick a revision to diff against your working tree.": "选择一个修订版本,与你的工作树进行差异比较。", + "Pick a tag or branch, or type any revision (a sha, origin/main~3). Checks out as a detached HEAD.": "选择标签或分支,或输入任意修订版本(如 sha、origin/main~3)。将以分离的 HEAD 检出。", + "Pick any file on disk to diff against.": "选择磁盘上的任意文件进行差异比较。", + "Pick both branches to see what it will have.": "选择两个分支,看看它将拥有什么。", + "Pick one of the listed entries.": "请从列出的条目中选择一个。", + "Pick the branch it goes into.": "选择它要进入的分支。", + "Pick the branch to open it from.": "选择要从中打开它的分支。", + "Picking": "正在拣选", + "Point the submodule at {0}'s commit{1} and stage it": "将子模块指向 {0} 的提交{1}并暂存", + "Point the submodule at {0}'s commit{1}{2} and stage it": "将子模块指向 {0} 的提交{1}{2}并暂存", + "Pop": "弹出", + "Pop stash": "弹出贮藏", + "Pop “{0}”": "弹出“{0}”", + "Pop: put these changes back and delete the stash": "弹出:恢复这些更改并删除该贮藏", + "Popped stash": "已弹出贮藏", + "Post your comment on GitHub": "在 GitHub 上发布你的评论", + "Post your reply on GitHub": "在 GitHub 上发布你的回复", + "Previous change (Shift+F7)": "上一个更改(Shift+F7)", + "Previous match (Shift+Enter)": "上一个匹配项 (Shift+Enter)", + "Prune": "清理", + "Prune 1 missing worktree?": "清理 1 个缺失的工作树?", + "Prune 1 missing worktree…": "清理 1 个缺失的工作树…", + "Prune Stale Branches": "清理失效分支", + "Prune {0}": "清理 {0}", + "Prune {0} missing worktrees?": "清理 {0} 个缺失的工作树?", + "Prune {0} missing worktrees…": "清理 {0} 个缺失的工作树…", + "Pruned 1 worktree whose folder was gone: {0}": "已清理 1 个文件夹已不存在的工作树:{0}", + "Pruned 1 worktree: {0}": "已清理 1 个工作树:{0}", + "Pruned {0}": "已清理 {0}", + "Pruned {0} worktrees whose folder was gone: {1}": "已清理 {0} 个文件夹已不存在的工作树:{1}", + "Pruned {0} worktrees: {1}": "已清理 {0} 个工作树:{1}", + "Publish": "发布", + "Publish this branch to which remote?": "将此分支发布到哪个远程仓库?", + "Publish to which remote?": "发布到哪个远程仓库?", + "Publish {0}": "发布 {0}", + "Publish {0}, keep {1}": "发布 {0},保留 {1}", + "Published {0}": "已发布 {0}", + "Published {0} to {1}": "已将 {0} 发布到 {1}", + "Pull": "拉取", + "Pull 1 Commit into '{0}'": "拉取 1 个提交到“{0}”", + "Pull 1 commit": "拉取 1 个提交", + "Pull 1 commit into {0}, in its own folder": "将 1 个提交拉取到 {0},位于其独立文件夹中", + "Pull Requests": "拉取请求", + "Pull commits": "拉取提交", + "Pull hit conflicts. Resolve them, then continue or abort.": "拉取遇到冲突。请解决冲突,然后继续或中止。", + "Pull into '{0}'": "拉取到 '{0}'", + "Pull into a worktree": "拉取到工作树", + "Pull request": "拉取请求", + "Pull request #{0}": "拉取请求 #{0}", + "Pull request #{0}: {1}": "拉取请求 #{0}:{1}", + "Pull request actions": "拉取请求操作", + "Pull requests": "拉取请求", + "Pull requests are opened on github.com repositories. Add a remote that points at one.": "拉取请求只能针对 github.com 上的仓库创建。请添加一个指向它的远程仓库。", + "Pull requests closed without merging show here.": "未合并即关闭的拉取请求会显示在这里。", + "Pull requests show here once a remote points at github.com.": "当某个远程仓库指向 github.com 时,拉取请求就会显示在这里。", + "Pull them in first, then push.": "请先把它们拉取进来,然后推送。", + "Pull these commits from the upstream": "从上游拉取这些提交", + "Pull using Merge": "使用合并方式拉取", + "Pull using Rebase": "使用变基方式拉取", + "Pull {0} Commits into '{1}'": "拉取 {0} 个提交到“{1}”", + "Pull {0} commits": "拉取 {0} 个提交", + "Pull {0} commits into {1}, in its own folder": "将 {0} 个提交拉取到 {1},位于其独立文件夹中", + "Pull {0} didn't run: {1}": "拉取 {0} 未执行:{1}", + "Pull {0} failed — {1}": "拉取 {0} 失败 — {1}", + "Pull {0}: {1}": "拉取 {0}:{1}", + "Pulled": "已拉取", + "Pulled the worktree {0}": "已拉取工作树 {0}", + "Pulling with rebase": "以变基方式拉取", + "Pulling with rebase needs a clean working tree, and you have uncommitted changes to {0}. ": "使用变基拉取需要干净的工作树,而你对 {0} 有未提交的更改。 ", + "Pulling…": "正在拉取…", + "Push": "推送", + "Push 1 commit": "推送 1 个提交", + "Push Tag to Remote…": "将标签推送到远程…", + "Push and create pull request": "推送并创建拉取请求", + "Push commits": "推送提交", + "Push from a worktree": "从工作树推送", + "Push it to": "将其推送到", + "Push tag": "推送标签", + "Push these commits to the upstream": "将这些提交推送到上游", + "Push to": "推送到", + "Push to another remote": "推送到另一个远程仓库", + "Push to the upstream branch?": "推送到上游分支?", + "Push {0}": "推送 {0}", + "Push {0} and track it, but leave {1}/{2} in place.": "推送 {0} 并跟踪它,但保留 {1}/{2} 不变。", + "Push {0} commits": "推送 {0} 个提交", + "Push {0} to which remote?": "将 {0} 推送到哪个远程仓库?", + "Push {0}, then create the pull request on {1}": "推送 {0},然后在 {1} 上创建拉取请求", + "Push {0}, track it, and delete {1}/{2}.": "推送 {0},跟踪它,并删除 {1}/{2}。", + "Pushed": "已推送", + "Pushed tag {0} to {1}": "已将标签 {0} 推送到 {1}", + "Pushed to {0} — choose another of this clone's GitHub remotes": "已推送到 {0} — 选择此克隆的另一个 GitHub 远程仓库", + "Pushed {0}": "已推送 {0}", + "Pushing and creating…": "正在推送并创建…", + "Pushing…": "正在推送…", + "Push…": "推送…", + "Put the stash “{0}” back {1}.": "将贮藏“{0}”放回{1}。", + "Putting {0} back would overwrite uncommitted changes, and some of them you had before \"{1}\" — ": "放回 {0} 会覆盖未提交的更改,其中一些是你在 \"{1}\" 之前就有的 — ", + "Queued": "已排队", + "Re-creating merge of {0} into {1}{2}": "正在重新创建将 {0} 合并到 {1}{2}", + "Reached the step limit before finishing.": "未完成就达到了步数上限。", + "Reached the step limit.": "已达到步数上限。", + "Read its files again": "重新读取它的文件", + "Read the pull request again": "重新读取拉取请求", + "Read-only": "只读", + "Reading changes…": "正在读取更改…", + "Reading its files…": "正在读取它的文件…", + "Reading the diff…": "正在读取差异…", + "Ready to merge": "可以合并", + "Reason (optional)": "原因(可选)", + "Rebase": "变基", + "Rebase aborted": "变基已中止", + "Rebase and merge": "变基并合并", + "Rebase commits, oldest first": "变基提交,最旧的在前", + "Rebase conflicts": "变基冲突", + "Rebase failed.": "变基失败。", + "Rebase in progress": "变基进行中", + "Rebase onto which commit or branch? The base itself is excluded — everything after it becomes the todo.": "变基到哪个提交或分支?基点本身被排除 — 它之后的所有内容都会成为待办清单。", + "Rebase onto which commit or branch? The base itself is excluded — everything after it lands in the workspace.": "变基到哪个提交或分支?基点本身被排除 — 它之后的所有内容都会进入工作区。", + "Rebase onto {0}": "变基到 {0}", + "Rebase paused": "变基已暂停", + "Rebase paused for editing.": "变基因编辑而暂停。", + "Rebase paused on a conflict — resolve the files, then Continue. ": "变基因冲突而暂停 — 请解决这些文件,然后继续。", + "Rebase paused on a conflict.": "变基因冲突而暂停。", + "Rebase paused to edit a commit — amend in your working tree, then Continue. ": "变基已暂停以编辑提交 — 请在工作树中修正,然后继续。", + "Rebase paused.": "变基已暂停。", + "Rebase paused. ": "变基已暂停。", + "Rebase plan applied": "已应用变基计划", + "Rebase stopped": "变基已停止", + "Rebase the current branch onto {0}?": "将当前分支变基到 {0}?", + "Rebase {0} commits?": "变基 {0} 个提交?", + "Rebase {0} onto '{1}'": "将 {0} 变基到“{1}”", + "Rebase {0} onto {1}?": "将 {0} 变基到 {1}?", + "Rebased onto {0}": "已变基到 {0}", + "Rebasing": "正在变基", + "Rebasing a1b2c3d from feature/session-hardening": "正在将 a1b2c3d(来自 feature/session-hardening)变基", + "Rebasing {0}": "正在变基 {0}", + "Rebasing {0} from {1}": "正在从 {1} 变基 {0}", + "Rebasing {0} onto {1}{2}{3}": "正在将 {0} 变基到 {1}{2}{3}", + "Recents": "最近使用", + "Recover — {0} ({1})": "恢复 — {0}({1})", + "Recreate the remote branch from your local commits.": "从你的本地提交重新创建远程分支。", + "Recurring support": "定期支持", + "Redo ({0})": "重做({0})", + "Reflog": "引用日志", + "Reflog — Time Machine": "Reflog — 时间机器", + "Refresh": "刷新", + "Refresh the pull request": "刷新拉取请求", + "Refresh — read the branches and GitHub again": "刷新 — 重新读取分支和 GitHub", + "Refresh — read the pull request again": "刷新 — 重新读取拉取请求", + "Refresh: read the branches and GitHub again": "刷新:重新读取分支和 GitHub", + "Refreshing…": "正在刷新…", + "Refusing to rebase: unrecognised plan entry {0}.": "拒绝变基:无法识别的计划条目 {0}。", + "Release {0} to apply": "松开 {0} 以应用", + "Release {0} to move": "松开 {0} 以移动", + "Reload the merge": "重新加载合并", + "Remote": "远程", + "Remote: {0}": "远程:{0}", + "Remotes": "远程仓库", + "Remove": "移除", + "Remove Worktree…": "移除工作树…", + "Remove a worktree": "移除工作树", + "Remove every filter": "移除所有筛选条件", + "Remove from Favorites": "从收藏中移除", + "Remove from favorites": "从收藏中移除", + "Remove from filter": "从筛选中移除", + "Remove remote": "移除远程仓库", + "Remove remote {0}?": "移除远程仓库 {0}?", + "Remove the label {0}": "移除标签 {0}", + "Remove the search and every filter": "移除搜索和所有筛选条件", + "Remove the {0} filter": "移除 {0} 筛选条件", + "Remove the {0} filter ({1})": "移除 {0} 筛选条件({1})", + "Remove worktree {0}?": "移除工作树 {0}?", + "Remove {0}": "移除 {0}", + "Removed": "已移除", + "Removed lines": "已删除的行", + "Removed lines (grey): lines removed on one side only, or the same lines removed on both. No conflict: safe to take.": "已删除的行(灰色):仅一侧删除了这些行,或两侧删除了相同的行。没有冲突:可以安全采用。", + "Removed remote {0}": "已移除远程仓库 {0}", + "Removes git's record of the worktree.": "删除 git 对该工作树的记录。", + "Removes git's record of the worktree; the folder stays.": "删除 git 对该工作树的记录;文件夹会保留。", + "Removing…": "正在移除…", + "Rename": "重命名", + "Rename branch": "重命名分支", + "Rename branch {0}": "重命名分支 {0}", + "Rename it, then check it out.": "请重命名,然后检出。", + "Rename of '{0}'": "'{0}' 的重命名", + "Rename on {0}": "在 {0} 上重命名", + "Rename remote": "重命名远程仓库", + "Rename {0}": "重命名 {0}", + "Rename {0} on {1} too?": "是否同时重命名 {1} 上的 {0}?", + "Renamed": "已重命名", + "Renamed on {0}: {1} → {2}": "已在 {0} 上重命名:{1} → {2}", + "Renamed remote to {0}": "已将远程仓库重命名为 {0}", + "Renamed to {0}": "已重命名为 {0}", + "Rename…": "重命名…", + "Reopen pull request": "重新打开拉取请求", + "Reopen this pull request": "重新打开此拉取请求", + "Reopening…": "正在重新打开…", + "Reorder": "重新排序", + "Reorder 1 commit?": "重新排序 1 个提交?", + "Reorder and move those branches": "重新排序并移动那些分支", + "Reorder plan refused": "重新排序计划被拒绝", + "Reorder this branch only": "仅重新排序该分支", + "Reorder {0} commits": "重新排序 {0} 个提交", + "Reorder {0} commits?": "重新排序 {0} 个提交?", + "Reordering stops at a merge — moving a commit past one would flatten it.": "重新排序会在合并提交处停止 — 把提交移过合并提交会压平它。", + "Replace and stage": "替换并暂存", + "Replace the file with {0} and stage it": "用 {0} 替换该文件并暂存", + "Replace the resolution already in {0}?": "替换 {0} 中已有的解决结果?", + "Replace what you typed with this": "用此内容替换你输入的内容", + "Replace with the left side's text": "替换为左侧的文本", + "Replaces only the versions you rewrote — nobody else's commits are on the remote branch.": "只替换你改写过的版本 — 远程分支上没有其他人的提交。", + "Replay your commits on top of theirs. Linear history, new shas.": "将你的提交重放到他们的提交之上。线性历史,新的 sha。", + "Replaying": "正在重放", + "Reply": "回复", + "Reply to the conversation on {0}": "在 {0} 上回复该对话", + "Replying…": "正在回复…", + "Reply…": "回复…", + "RepoManager ready — repos={0}, active={1}": "RepoManager 已就绪 — repos={0}, active={1}", + "Repository {0}. {1}": "仓库 {0}。{1}", + "Repository: {0}. Choose another": "仓库:{0}。选择另一个", + "Republish Branch": "重新发布分支", + "Request cancelled.": "请求已取消。", + "Request changes": "请求更改", + "Required": "必需", + "Required to pass before merging": "合并前必须通过", + "Required.": "必填。", + "Reset": "重置", + "Reset --hard": "重置 --hard", + "Reset Branch to Here": "将分支重置到此处", + "Reset Current Branch to Here…": "将当前分支重置到此处…", + "Reset column widths": "重置列宽", + "Reset current branch to {0}": "将当前分支重置为 {0}", + "Reset merge": "重置合并", + "Reset plan": "重置计划", + "Reset the conflicted files?": "重置冲突文件?", + "Reset the merge to where it started": "将合并重置到起始状态", + "Reset to '": "重置到 '", + "Reset to {0}": "重置为 {0}", + "Reset to {0} ({1})": "重置为 {0}({1})", + "Reset {0} to the pull request's version": "将 {0} 重置为拉取请求的版本", + "Reset {0} to {1}": "将 {0} 重置为 {1}", + "Reset {0} to {1}?": "将 {0} 重置为 {1}?", + "Reset {0} to {1}…": "将 {0} 重置为 {1}…", + "Resize Commit message / Changes divider": "调整提交信息 / 更改分隔条的大小", + "Resize the details column": "调整详情列大小", + "Resize {0} column": "调整 {0} 列的大小", + "Resolve Conflicts…": "解决冲突…", + "Resolve and stage them first — git can't commit while files are unmerged.": "请先解决并暂存它们 — 文件未合并时 git 无法提交。", + "Resolve conversation": "解决对话", + "Resolve every change with theirs — {0}": "用他们的版本解决所有更改 — {0}", + "Resolve every change with yours — {0}": "用你的版本解决所有更改 — {0}", + "Resolve every change with {0}": "用 {0} 解决所有更改", + "Resolve in Merge Editor": "在合并编辑器中解决", + "Resolve it change by change in the merge editor": "在合并编辑器中逐个解决更改", + "Resolve simple": "解决简单冲突", + "Resolve simple conflicts": "解决简单冲突", + "Resolve simple conflicts (apply both sides where their edits don't overlap)": "解决简单冲突(在两侧编辑不重叠处同时应用)", + "Resolve the last conflicted file first.": "请先解决最后一个冲突文件。", + "Resolve the whole file with {0}{1}": "用 {0} 解决整个文件{1}", + "Resolve the {0} conflicted files first.": "请先解决 {0} 个冲突文件。", + "Resolve {0} and {1} — or abort it — before {2}.": "在{2}之前,请先解决 {0} 和 {1} — 或中止它。", + "Resolved": "已解决", + "Resolved (in an editor, or outside this app)": "已解决(在编辑器中,或在此应用之外)", + "Resolved by deleting the file — both sides had deleted it": "通过删除文件解决 — 两侧都已删除它", + "Resolved by deleting the file, as {0}{1} did": "通过删除文件解决,与 {0}{1} 的做法一致", + "Resolved by {0}": "由 {0} 解决", + "Resolved in the merge editor": "已在合并编辑器中解决", + "Resolved with {0}{1}": "已用 {0} 解决{1}", + "Resolved.": "已解决。", + "Resolving…": "正在解决…", + "Restore": "恢复", + "Restore VS Code's Merge Editor": "恢复 VS Code 的合并编辑器", + "Restore every column to its default width": "将所有列恢复为默认宽度", + "Result": "结果", + "Retry": "重试", + "Reveal a worktree": "显示工作树", + "Reveal in File Explorer": "在文件资源管理器中显示", + "Reveal in File Manager": "在文件管理器中显示", + "Reveal in Finder": "在访达中显示", + "Reveal {0} in the graph": "在提交图中定位 {0}", + "Revert": "还原", + "Revert Commit": "还原提交", + "Revert conflicts": "还原冲突", + "Revert in progress": "还原进行中", + "Revert of \"{0}\" needs a decision — resolve any conflicts ": "“{0}”的还原需要做出决定 — 请解决所有冲突", + "Revert of {0} needs a decision — resolve any ": "{0} 的还原需要做出决定 — 请解决所有", + "Revert stopped": "还原已停止", + "Revert the merge {0}": "还原合并 {0}", + "Revert {0}": "还原 {0}", + "Revert {0} Commits": "还原 {0} 个提交", + "Revert {0} commits": "还原 {0} 个提交", + "Reverted {0}": "已还原 {0}", + "Reverted {0} commits.": "已还原 {0} 个提交。", + "Reverting": "正在还原", + "Reverting {0} commits": "正在还原 {0} 个提交", + "Reverting {0} commits stopped on a commit that needs you — resolve any conflicts and continue, skip that commit, or abort to put the branch back as it was.": "还原 {0} 个提交时停在一个需要你处理的提交上 — 请解决所有冲突并继续、跳过该提交,或中止以把分支恢复原样。", + "Reverting {0} on {1}{2}": "正在 {1}{2} 上还原 {0}", + "Review #{0}": "审查 #{0}", + "Review ({0} pending)": "审查({0} 条待提交)", + "Review below, then {0} to commit it.": "在下方审查,然后按 {0} 提交。", + "Review below.": "在下方审查。", + "Review changes with AI": "用 AI 审查更改", + "Review copied": "审查内容已复制", + "Review requested": "已请求审查", + "Review required": "需要审查", + "Review submitted on #{0}: {1}.": "已在 #{0} 上提交审查:{1}。", + "Review summary": "审查摘要", + "Review threads": "审查讨论串", + "Review what {0} would push": "查看 {0} 将会推送的内容", + "Reviewers": "审查者", + "Reviewers, assignees and labels": "审查者、指派人和标签", + "Reviewers, labels and assignees take triage access to {0}. Its maintainers can add them.": "评审者、标签和负责人需要对 {0} 的分诊权限。其维护者可以添加它们。", + "Reviewing your changes…": "正在审查你的更改…", + "Reviews: {0}": "审查:{0}", + "Reword": "改写信息", + "Rewrites the remote branch": "重写远程分支", + "Rewriting published history would break everyone who has already pulled it. GitStudio will Revert instead — a new commit that undoes the change, leaving the original in place.": "重写已发布的历史会影响所有已经拉取过它的人。GitStudio 将改为还原 — 用一个新提交撤销该更改,保留原始提交。", + "Rewriting published history would break everyone who has already pulled it. GitStudio will add a new commit instead that puts the files back as they were before \"{0}\", leaving the pushed commit in place.": "重写已发布的历史会影响所有已经拉取过它的人。GitStudio 将改为添加一个新提交,把文件恢复到“{0}”之前的状态,保留已推送的提交。", + "Run models on your own machine — fully private, no key.": "在你自己的机器上运行模型 — 完全私密,无需密钥。", + "Running": "运行中", + "Running for {0}": "已运行 {0}", + "SHA": "SHA", + "Same on both sides": "两侧相同", + "Same on both sides — either arrow takes it": "两侧相同 — 任一箭头都可采用", + "Same on both sides — either arrow takes it (green): both sides added or changed these lines the same way. Nothing to choose.": "两侧相同 — 任一箭头都可采用(绿色):两侧以相同方式新增或修改了这些行。无需选择。", + "Sample": "示例", + "Sample resolved. In a real conflict, Apply saves and stages the file, then Continue Rebase appears.": "示例已解决。在真实的冲突中,应用会保存并暂存该文件,然后就会出现“继续变基”。", + "Sample · after": "示例 · 之后", + "Sample · before": "示例 · 之前", + "Sample · rebasing feature/session-hardening onto main · commit 2 of 3": "示例 · 正在将 feature/session-hardening 变基到 main · 第 2/3 个提交", + "Sample: authorizeRequest.ts": "示例:authorizeRequest.ts", + "Save Key": "保存密钥", + "Save the result and mark the conflict resolved": "保存结果并将冲突标记为已解决", + "Saved {0}, but couldn't stage it.": "已保存 {0},但无法暂存它。", + "Saved. This file is not in a Git repository, so there is nothing to stage.": "已保存。此文件不在 Git 仓库中,因此没有可暂存的内容。", + "Search": "搜索", + "Search SHA…": "搜索 SHA…", + "Search authors…": "搜索作者…", + "Search branches & tags…": "搜索分支和标签…", + "Search branches and actions": "搜索分支和操作", + "Search commits": "搜索提交", + "Search commits ({0})": "搜索提交({0})", + "Search commits, authors, refs…": "搜索提交、作者、引用…", + "Search for branches and actions": "搜索分支和操作", + "Search in": "搜索范围", + "Search in: {0}": "搜索范围:{0}", + "Search messages…": "搜索提交信息…", + "Search pull requests": "搜索拉取请求", + "Search scope": "搜索范围", + "Search scope: {0}": "搜索范围:{0}", + "Select AI Model": "选择 AI 模型", + "Select AI Model…": "选择 AI 模型…", + "Select All (": "全选(", + "Select Checked (": "选择已勾选(", + "Select Unchecked (": "选择未勾选(", + "Select a commit to see its details": "选择一个提交以查看其详情", + "Select a tag to check out": "选择要检出的标签", + "Select a tag to delete": "选择要删除的标签", + "Select a tag to push": "选择要推送的标签", + "Select at least two commits to squash them.": "请至少选择两个提交才能压缩。", + "Select only this commit": "只选中此提交", + "Select only {0}: {1}": "只选中 {0}:{1}", + "Selected commits": "已选中的提交", + "Send your review as {0}{1}": "将你的审查以 {0}{1} 的方式发送", + "Sending…": "正在发送…", + "Set Anthropic API Key": "设置 Anthropic API 密钥", + "Set OpenAI API Key": "设置 OpenAI API 密钥", + "Set Tracked Branch…": "设置跟踪分支…", + "Set action": "设置操作", + "Set the action of the selected commits": "设置所选提交的操作", + "Set the base URL to your deployment and append `?api-version=…` if required.": "请将基础 URL 设置为你的部署地址,如有需要可追加 `?api-version=…`。", + "Set the upstream for which branch?": "为哪个分支设置上游?", + "Set up AI to draft commit messages": "设置 AI 来起草提交信息", + "Set upstream": "设置上游", + "Set upstream for {0}": "为 {0} 设置上游", + "Set upstream of {0} → {1}": "将 {0} 的上游设为 → {1}", + "Shift- or ": "Shift- 或 ", + "Shift- or {0}-click selects several;": "按 Shift 或 {0} 点击可多选;", + "Show Commit Graph": "显示提交图", + "Show all branches": "显示所有分支", + "Show branches": "显示分支", + "Show checks": "显示检查", + "Show individual changes": "显示各个更改", + "Show it": "显示它", + "Show only this branch": "只显示此分支", + "Show only this tag": "只显示此标签", + "Show or hide columns": "显示或隐藏列", + "Show the first": "显示前", + "Show the next pull requests ({0} of {1} shown)": "显示下一批拉取请求(已显示 {1} 个中的 {0} 个)", + "Show the pull requests of": "显示以下位置的拉取请求", + "Show the repository of whichever file you are editing.": "显示你正在编辑的文件所属的仓库。", + "Show the terminal": "显示终端", + "Show {0}": "显示 {0}", + "Show {0} more": "再显示 {0} 项", + "Show {0} more of {1}": "再显示 {1} 中的 {0} 项", + "Showing every branch and tag · tick one to narrow": "正在显示所有分支和标签 · 勾选一个以缩小范围", + "Showing the latest {0} of {1} commits. Open on GitHub for the rest.": "正在显示 {1} 个提交中最新的 {0} 个。其余请在 GitHub 上查看。", + "Showing the latest {0} of {1} events. ": "正在显示 {1} 个事件中最新的 {0} 个。 ", + "Showing the list as it was {0}.": "显示列表在 {0} 时的状态。", + "Showing the pull request as it was.": "显示拉取请求当时的状态。", + "Showing the pull requests of {0}. Choose another repository": "正在显示 {0} 的拉取请求。选择另一个仓库", + "Showing {0} ({1}). Choose another repository": "正在显示 {0}({1})。选择另一个仓库", + "Showing {0} of {1} checks.": "正在显示 {1} 项检查中的 {0} 项。", + "Showing {0} of {1} files{2}. Open on GitHub for the rest.": "正在显示 {1} 个文件中的 {0} 个{2}。其余请在 GitHub 上查看。", + "Showing {0} of {1} review threads. Open on GitHub for the rest.": "正在显示 {1} 个审查讨论串中的 {0} 个。其余请在 GitHub 上查看。", + "Sign in again": "重新登录", + "Sign in again to see {0}#{1}.": "重新登录以查看 {0}#{1}。", + "Sign in again to see {0}'s pull requests.": "重新登录以查看 {0} 的拉取请求。", + "Sign in to GitHub": "登录 GitHub", + "Sign in to GitHub to open a pull request": "登录 GitHub 以创建拉取请求", + "Sign in to GitHub to see pull requests": "登录 GitHub 以查看拉取请求", + "Sign in to GitHub, with another account if need be": "登录 GitHub,必要时可使用其他账号", + "Sign-off": "签名", + "Skip": "跳过", + "Skip This Commit": "跳过此提交", + "Skip failed.": "跳过失败。", + "Skip isn't offered here.": "此处不提供跳过。", + "Skip patch": "跳过补丁", + "Skip this commit": "跳过此提交", + "Skipped": "已跳过", + "Soft": "软重置", + "Some checks didn't pass": "部分检查未通过", + "Some of its commits are not on any other branch, so deleting it may leave them unreachable. Undo can still recover them.": "它的一些提交不在任何其他分支上,因此删除它可能会让这些提交无法访问。撤销仍能恢复它们。", + "Some of these commits are already pushed. {0} them would rewrite history other people have.": "其中一些提交已被推送。{0}它们会改写其他人已有的历史。", + "Someone deleted or renamed that remote branch.": "有人删除或重命名了该远程分支。", + "Someone not listed": "其他未列出的人", + "Something interrupted reading them — they refresh on their own.": "读取它们时被中断 — 它们会自动刷新。", + "Split diff": "分栏差异", + "Sponsor on GitHub": "在 GitHub 上赞助", + "Squash": "压缩合并", + "Squash Commits": "压缩提交", + "Squash and merge": "压缩并合并", + "Squash {0} Commits…": "压缩 {0} 个提交…", + "Squash {0} commits": "压缩 {0} 个提交", + "Squash {0} commits — move the branches too?": "压缩 {0} 个提交 — 同时移动分支吗?", + "Squashed {0} into one.": "已将 {0} 个提交压缩为一个。", + "Squashing": "压缩", + "Stage": "暂存", + "Stage All": "全部暂存", + "Stage All Changes": "暂存所有更改", + "Stage Changes with Ticks": "用勾选标记暂存更改", + "Stage Folder": "暂存文件夹", + "Stage all": "全部暂存", + "Stage file": "暂存文件", + "Stage folder": "暂存文件夹", + "Stage individually first if you only want some of it.": "如果只想要其中一部分,请先逐个暂存。", + "Stage {0}": "暂存 {0}", + "Stage, commit, stash, or discard below": "在下方暂存、提交、贮藏或丢弃", + "Staged": "已暂存", + "Staged 1 change": "已暂存 1 处更改", + "Staged changes": "已暂存的更改", + "Staged everything else. ": "已暂存其余所有内容。 ", + "Staged when it was stashed: it comes back staged": "贮藏时已暂存:恢复时也会是已暂存状态", + "Staged {0} changes": "已暂存 {0} 处更改", + "Staged — click to unstage this change": "已暂存 — 点击以取消暂存此更改", + "Staged, then changed again, when it was stashed: both versions come back": "贮藏时已暂存、之后又发生更改:两个版本都会恢复", + "Staging": "暂存", + "Start Interactive Rebase Here…": "从此处开始交互式变基…", + "Start Ollama, then `ollama pull qwen2.5-coder`. Nothing leaves your machine.": "启动 Ollama,然后执行 `ollama pull qwen2.5-coder`。数据不会离开你的机器。", + "Start Rebase": "开始变基", + "Start rebase": "开始变基", + "Start review": "开始审查", + "Start the description from": "描述从以下内容开始", + "Start the description from one of the repository's templates": "以仓库的某个模板作为描述的开头", + "Start the merge over from {0} as it is now. The work in this editor is not kept.": "从 {0} 当前的状态重新开始合并。此编辑器中的工作不会被保留。", + "Start your review": "开始你的审查", + "Stash": "贮藏", + "Stash & Remove": "贮藏并移除", + "Stash & Retry": "贮藏并重试", + "Stash 1 selected file…": "贮藏 1 个所选文件…", + "Stash All Changes": "贮藏所有更改", + "Stash Everything Staged": "贮藏所有已暂存内容", + "Stash This File": "贮藏此文件", + "Stash This Folder": "贮藏此文件夹", + "Stash all changes…": "贮藏所有更改…", + "Stash applied": "已应用贮藏", + "Stash apply cancelled — the files are back as they were, and the stash is still in your list.": "已取消应用贮藏 — 文件已恢复原状,该贮藏仍在你的列表中。", + "Stash conflicts": "贮藏冲突", + "Stash everything staged ({0} {1})": "贮藏所有已暂存内容({0} {1})", + "Stash {0}": "贮藏 {0}", + "Stash {0} and try again, or commit {1} first.": "请贮藏 {0} 后重试,或先提交 {1}。", + "Stash {0} selected files…": "贮藏所选的 {0} 个文件…", + "Stash {0} {1}": "贮藏 {0} {1}", + "Stash {0}, run it again, and put {1} back.": "贮藏 {0},再次运行它,然后恢复 {1}。", + "Stash “{0}”": "贮藏“{0}”", + "Stashed by GitHub Desktop": "由 GitHub Desktop 贮藏", + "Stashed {0}": "已贮藏 {0}", + "Stashes": "贮藏", + "Stashes — click to hide them": "贮藏 — 点击隐藏", + "Stashes — click to show them": "贮藏 — 点击显示", + "Stashes, {0}": "贮藏,{0}", + "Stashing the staged changes of specific files is not supported by git — ": "git 不支持只贮藏特定文件的已暂存更改 — ", + "Status": "状态", + "Stay on {0} as it is": "留在 {0} 并保持现状", + "Stop Tracking": "停止跟踪", + "Stopped again — there are conflicts to resolve.": "再次停止 — 有冲突需要解决。", + "Stopped at {0} {1} of {2}": "停止于 {0} {1}/{2}", + "Stopped at {0} {1} of {2} — it has conflicts to resolve.": "停止于 {0} {1}/{2} — 它有冲突需要解决。", + "Stream from Anthropic failed.": "来自 Anthropic 的流式响应失败。", + "Stream from {0} failed.": "来自 {0} 的流式响应失败。", + "Subject line: 1 character. Keep it to 50.": "主题行:1 个字符。请控制在 50 个以内。", + "Subject line: {0} characters, over 50. Aim for 50; 72 at most.": "主题行:{0} 个字符,超过 50。建议 50,最多 72。", + "Subject line: {0} characters, over 72. GitHub cuts a longer subject short.": "主题行:{0} 个字符,超过 72。更长的主题会被 GitHub 截断。", + "Subject line: {0} characters. Keep it to 50.": "主题行:{0} 个字符。请控制在 50 个以内。", + "Submit": "提交", + "Submit review": "提交审查", + "Submit your review — {0} will be sent with it": "提交你的审查 — 将同时发送 {0}", + "Submitting…": "正在提交…", + "Success — the model replied. You're all set.": "成功 — 模型已回复。一切就绪。", + "Summarize Changes": "总结更改", + "Summarizing with AI…": "正在用 AI 生成摘要…", + "Summarizing your changes…": "正在总结你的更改…", + "Summary": "摘要", + "Support GitStudio": "支持 GitStudio", + "Swap base and compare": "交换基准和对比", + "Switch Repository": "切换仓库", + "Switch back to '{0}'.": "切回 '{0}'。", + "Switch repository (": "切换仓库(", + "Switch to checkboxes": "切换到复选框", + "Switch to local {0}": "切换到本地 {0}", + "Switch to staged / unstaged": "切换到已暂存 / 未暂存", + "Switch to the new branch after creating it?": "创建后是否切换到新分支?", + "Switch to {0}": "切换到 {0}", + "Switched to {0}": "已切换到 {0}", + "Synced": "已同步", + "Synchronized scrolling": "同步滚动", + "Tag": "标签", + "Tags": "标签", + "Template": "模板", + "Template: {0}": "模板:{0}", + "Test failed.": "测试失败。", + "That change is no longer there — the file moved underneath. Refresh and try again.": "该更改已不存在 — 底层的文件已被移动。请刷新后重试。", + "That commit is too far down the branch to drop from here. Start an interactive rebase from it instead.": "该提交在分支中位置太靠下,无法从这里丢弃。请改为从它开始交互式变基。", + "That commit isn't on the current branch, so there's nothing to drop it from.": "该提交不在当前分支上,因此无从丢弃它。", + "That isn't a drop this app made.": "这不是本应用执行的丢弃。", + "That isn't a stash this app recorded.": "这不是本应用记录的贮藏。", + "That isn't a usable file path.": "这不是可用的文件路径。", + "That isn't a {0} this app made.": "这不是本应用执行的{0}。", + "That path escapes the repository — nothing was changed.": "该路径超出了仓库范围 — 未做任何更改。", + "That puts back only what it changed, and only where nothing has moved since.": "这样只会恢复它改动过的部分,而且仅限于之后没有变动的位置。", + "That stash is no longer in the list, so nothing was changed.": "该贮藏已不在列表中,因此未做任何更改。", + "That stash is no longer in the list.": "该贮藏已不在列表中。", + "That stash is no longer in the repository.": "该贮藏已不在仓库中。", + "That stash no longer exists.": "该贮藏已不存在。", + "That's a merge commit — dropping it would flatten the history it joined. Revert it instead.": "这是一个合并提交 — 丢弃它会压平它并入的历史。请改为还原它。", + "That's the only commit on the branch — dropping it would leave nothing.": "这是分支上唯一的提交 — 丢弃它会什么都不剩。", + "The AI had nothing to say about this change": "AI 对此更改没有意见", + "The Anthropic API key is missing or invalid. Run “GitStudio: Set Anthropic API Key…”.": "Anthropic API 密钥缺失或无效。请运行“GitStudio: Set Anthropic API Key…”。", + "The OpenAI-compatible endpoint rejected the API key (401). Run “GitStudio: Set OpenAI API Key”, or clear it for a local server.": "OpenAI 兼容端点拒绝了该 API 密钥(401)。请运行“GitStudio: Set OpenAI API Key”,或清除它以使用本地服务器。", + "The OpenAI-compatible endpoint returned 404 — check the base URL and model ID in settings.": "OpenAI 兼容端点返回 404 — 请检查设置中的基础 URL 和模型 ID。", + "The branch action": "分支操作", + "The branch goes back to where it was before the rebase started. No commits are changed.": "分支会回到变基开始之前的状态。不会改动任何提交。", + "The branch goes back to where it was before the series started. Patches already applied are ": "分支会回到补丁系列开始之前的状态。已应用的补丁 ", + "The branch has moved since the {0}, so undoing it now would throw that away too. Nothing was changed.": "自{0}以来分支已移动,因此现在撤销它会把这些也一并丢掉。未做任何更改。", + "The branch has moved since you chose Drop, so nothing was dropped. Look at the history again and retry.": "自你选择“丢弃”以来分支已移动,因此未丢弃任何内容。请再次查看历史后重试。", + "The branch has moved since you chose these commits, so nothing was changed. Look at the history again and retry.": "自你选择这些提交以来分支已移动,因此未做任何更改。请再次查看历史后重试。", + "The branch is back": "分支已恢复", + "The branch is created at the current HEAD and checked out in the new worktree.": "该分支在当前 HEAD 处创建,并在新的工作树中检出。", + "The branch it comes from": "它来自的分支", + "The branch it goes into": "它要进入的分支", + "The branch it {0} into": "它{0}并入的分支", + "The branch label is removed. Its commits stay reachable from anywhere else that points at them, and GitStudio's Undo can put the branch back.": "分支标签被移除。它的提交仍可从任何其他指向它们的地方访问,而且 GitStudio 的撤销可以恢复该分支。", + "The branch moved on since this page read it. Refresh, look at what changed, and merge again.": "自此页面读取之后分支已有更新。请刷新,查看发生了什么变化,然后重新合并。", + "The branch starts at HEAD.": "分支从 HEAD 开始。", + "The branch starts at {0}.": "分支从 {0} 开始。", + "The branch {0} and its commits stay.": "分支 {0} 及其提交会保留。", + "The change is good to merge": "此更改可以合并", + "The changed file goes back to its committed version.": "已更改的文件会恢复为其已提交的版本。", + "The changes it made to your working tree are taken back.": "它对工作树所做的更改已被撤回。", + "The changes you stashed, being put back": "你贮藏的更改,正在放回", + "The code it was written on has changed since": "它所在的代码此后已发生变化", + "The commit after it will be replayed on top, with a new SHA.": "其后的提交会在上面重放,并生成新的 SHA。", + "The commit being cherry-picked": "正在拣选的提交", + "The commit being cherry-picked: {0} “{1}”": "正在拣选的提交:{0} “{1}”", + "The commit is": "该提交", + "The commit is added to {0} as one new commit.": "该提交会作为一个新提交添加到 {0}。", + "The commits HEAD has that {0} does not are rewritten on top of it, so they get new shas. HEAD is on no branch, so they are on no branch either: create a branch from them to keep them. Undo can take you back.": "HEAD 拥有而 {0} 没有的提交会被重写到它之上,因此会获得新的 sha。HEAD 不在任何分支上,所以这些提交也不在任何分支上:请从它们创建一个分支来保留它们。撤销可以带你回到原状。", + "The conflict is back, but {0} couldn't be restored on disk.": "冲突已恢复,但 {0} 无法在磁盘上恢复。", + "The conflicted files are back to their last committed versions.": "冲突文件已恢复为它们最后一次提交的版本。", + "The conflicts list: every conflicted file of this {0}, and {1}{2}": "冲突列表:此 {0} 的每个冲突文件,以及 {1}{2}", + "The current commit": "当前提交", + "The dropped commit is back": "被丢弃的提交已恢复", + "The file goes back to its committed version. {0}": "该文件会恢复为其已提交的版本。{0}", + "The file is deleted. Git has never tracked it, so nothing — not even Undo — can bring it back.": "该文件将被删除。Git 从未跟踪过它,所以任何东西 — 甚至撤销 — 都无法把它找回来。", + "The file is saved, but git could not stage it ({0}). Stage it with git add before you continue.": "文件已保存,但 git 无法暂存它({0})。继续之前请先用 git add 暂存它。", + "The file was saved but could not be staged.": "文件已保存,但无法暂存。", + "The files go back to how they were before the stash was applied. The stash itself stays in ": "这些文件会恢复到应用贮藏之前的状态。该贮藏本身仍留在 ", + "The first commit — there is nothing below it to reorder past.": "第一个提交 — 它下面没有可越过的内容。", + "The first parent — usually what you want.": "第一个父提交 — 通常就是你要的。", + "The first {0} of {1} commits.": "{1} 个提交中的前 {0} 个。", + "The index survives, so a partly staged commit stays ready.": "索引会保留,因此部分暂存的提交仍保持就绪。", + "The last committed version of this file.": "此文件最后一次提交的版本。", + "The main worktree holds the repository itself, so git can't lock it.": "主工作树承载着仓库本身,因此 git 无法锁定它。", + "The main worktree holds the repository itself, so git never removes it.": "主工作树承载着仓库本身,因此 git 永远不会移除它。", + "The model declined this request.": "模型拒绝了这个请求。", + "The model request failed.": "模型请求失败。", + "The new worktree's folder. Suggested {0}, as {1}; change it if you like — it must not exist yet, or be empty.": "新工作树的文件夹。建议使用 {0}({1});如有需要可以修改 — 该文件夹必须尚不存在或为空。", + "The oldest commit can't be \"{0}\" — there's nothing older for it to fold into.": "最旧的提交无法“{0}” — 没有更旧的内容可供并入。", + "The operation": "该操作", + "The operation was aborted": "操作已中止", + "The operation {0} was resolved in has finished — its conflict can't be brought back.": "解决 {0} 时所处的操作已结束 — 无法恢复其冲突。", + "The other side of the conflict": "冲突的另一方", + "The page follows as it happens.": "页面会随之实时更新。", + "The patch being applied": "正在应用的补丁", + "The patch git is stuck on": "git 卡住的那个补丁", + "The patch series was abandoned, but HEAD had moved since it started, so git left it ": "该补丁序列已放弃,但自其开始以来 HEAD 已移动,因此 git 将它保留为 ", + "The pull request isn't loaded yet.": "该拉取请求尚未加载。", + "The pull request's page": "拉取请求的页面", + "The pull stopped on conflicts in {0}. Resolve {1}, ": "拉取在 {0} 中的冲突处停止。请解决 {1}, ", + "The pull would overwrite your uncommitted changes to {0}. Commit or stash {1}, then pull again.": "拉取会覆盖你对 {0} 的未提交更改。请提交或贮藏 {1},然后重新拉取。", + "The rebase is still stopped.": "变基仍处于停止状态。", + "The reflog is empty": "reflog 为空", + "The remote branch has commits this branch has never had — fetched in the background, ": "远程分支有本分支从未有过的提交 — 已在后台获取, ", + "The remote refused a normal push. This uses --force-with-lease, ": "远程仓库拒绝了普通推送。这里使用 --force-with-lease,", + "The remote still has the commits you replaced — amending a pushed ": "远程仓库仍有你替换掉的提交 — 修正一个已推送的 ", + "The remote-tracking branch this branch pushes to and compares against.": "此分支推送并与之比较的远程跟踪分支。", + "The repository PR #{0}'s branch came from is gone": "PR #{0} 的分支来源仓库已不存在", + "The repository changed while you were being asked, so \"{0}\" wasn't undone. Try Undo again.": "在询问你的过程中仓库发生了变化,因此“{0}”未被撤销。请再试一次撤销。", + "The repository goes back to how it was before the {0} started. Conflicts you have already ": "仓库会回到 {0} 开始之前的状态。你已经解决的", + "The repository has no remote to pull from.": "此仓库没有可供拉取的远程。", + "The repository has no remote to push to.": "此仓库没有可供推送的远程。", + "The repository it opens on": "它打开的仓库", + "The repository's hooks run as it merges.": "合并时会运行该仓库的钩子。", + "The resolution leaves nothing to commit for this commit. Skip it instead.": "该解决方案使此提交没有可提交的内容。请改为跳过它。", + "The reverse of commit {0} “{1}”": "提交 {0} “{1}”的逆向提交", + "The reverse of the commit being reverted": "正在还原的提交的逆向提交", + "The rules that protect {0} aren't met yet.": "保护 {0} 的规则尚未满足。", + "The short name you'll refer to it by — origin, upstream, fork.": "你用来指代它的简短名称 — origin、upstream、fork。", + "The squashed commit needs a message.": "压缩后的提交需要一条提交信息。", + "The staged deletions could not be stashed.": "已暂存的删除无法被贮藏。", + "The stash hit conflicts. Resolve them, or cancel to put the files back — the stash is kept.": "应用贮藏时遇到冲突。请解决冲突,或取消以恢复文件 — 该贮藏会被保留。", + "The stash is applied on the new branch and dropped once it applies cleanly.": "该贮藏会在新分支上应用,并在干净应用后删除。", + "The stash is back, but the ones that were above it couldn't all be put back on top: ": "贮藏已恢复,但原本位于其上的那些未能全部放回顶部: ", + "The stash leaves": "该贮藏会离开", + "The stash “{0}” it made is kept: it holds more than Undo puts back.": "它所创建的贮藏“{0}”会保留:其中内容超出撤销所放回的范围。", + "The uncommitted changes you had before it can't come back — git couldn't keep a copy of them {0}.": "你在其之前的未提交更改无法恢复 — git 无法保留它们的副本{0}。", + "The uncommitted changes you had then come back too.": "你当时的未提交更改也会恢复。", + "The untracked file is deleted.": "该未跟踪的文件将被删除。", + "The version on {0}": "{0} 上的版本", + "The worktree at {0} is locked.": "{0} 处的工作树已锁定。", + "The {0} commit you keep can't be {1} — there's nothing {2} it to fold into.": "你保留的那个{0}提交无法{1} — 它{2}没有任何可供折叠的提交。", + "The {0} commits after it will be replayed on top, with new SHAs.": "其后的 {0} 个提交会在上面重放,并生成新的 SHA。", + "The {0} commits are": "这 {0} 个提交", + "The {0} commits become one commit on {1}.": "这 {0} 个提交会成为 {1} 上的一个提交。", + "The {0} in progress is abandoned.": "进行中的{0}已被放弃。", + "The {0} is": "{0} 是", + "The {0} later commits will be replayed on top, with new SHAs.": "其后的 {0} 个提交会在上面重放,并生成新的 SHA。", + "The {0} stays paused, and ": "{0} 保持暂停,并且 ", + "The {0} untracked files are deleted.": "这 {0} 个未跟踪的文件将被删除。", + "The {0} was stopped, but HEAD had moved since its ": "{0} 操作已停止,但 HEAD 自其", + "Their changes come": "他们的更改会", + "Their changes return as unstaged edits.": "他们的更改会作为未暂存的编辑返回。", + "Their changes return to the Staged group, ready to re-commit.": "他们的更改会回到“已暂存”分组,可以重新提交。", + "Theirs": "对方的", + "There are unresolved conflicts — resolve them or cancel first.": "还有未解决的冲突 — 请先解决它们或取消。", + "There is no '{0}' to reset to — it is not on {1} any more.": "没有可重置到的 '{0}' — 它已不在 {1} 上。", + "There is no '{0}' to reset to, and {1} couldn't be reached to fetch it.": "没有可重置到的 '{0}',且无法访问 {1} 来获取它。", + "There is no Apply to undo here any more.": "这里已经没有可撤销的应用了。", + "There is no earlier conflict to bring back for {0}.": "没有可供 {0} 恢复的更早冲突。", + "There is nothing git can skip here.": "这里没有 git 可以跳过的内容。", + "There is nothing to abort.": "没有可中止的内容。", + "There is nothing to continue in the {0}.": "{0} 中没有可继续的内容。", + "There is nothing to continue.": "没有可继续的内容。", + "There's a merge between that commit and the tip of the branch — replaying the commits after it would flatten the merge.": "该提交与分支末端之间存在合并 — 重放其后的提交会压平该合并。", + "There's a merge between those commits and the tip of the branch — replaying the commits after them would flatten the merge.": "那些提交与分支末端之间存在合并 — 重放其后的提交会压平该合并。", + "There's already a branch named {0}": "已存在名为 {0} 的分支", + "These edits were never committed, so nothing — not even Undo — can bring them back.": "这些编辑从未提交过,所以任何东西 — 甚至撤销 — 都无法把它们找回来。", + "These {0} files": "这 {0} 个文件", + "They are rewritten, so they get new identities. Undo is available afterwards.": "它们会被重写,因此会获得新的身份。之后可以使用撤销。", + "They can't be stashed without knowing what they are.": "在不知道它们是什么的情况下无法贮藏。", + "They follow onto the replayed commits.": "它们会跟到重放的提交之上。", + "They follow onto the rewritten commits.": "它们会跟到重写的提交之上。", + "They haven't been sent to GitHub, and discarding them can't be undone.": "它们尚未发送到 GitHub,丢弃后将无法恢复。", + "They keep pointing at the commits as they are now.": "它们仍会指向这些提交当前的样子。", + "They stay": "它们保留在", + "They're": "它们位于", + "This branch": "此分支", + "This branch has conflicts": "此分支存在冲突", + "This branch is out of date with {0}, and the repository requires it to be up to date. Update the branch to merge it.": "此分支已落后于 {0},而该仓库要求它保持最新。请更新分支以合并。", + "This branch still tracks {0}/{1} — renaming locally doesn't rename it on the remote.": "此分支仍跟踪 {0}/{1} — 在本地重命名不会改变远程仓库上的名称。", + "This branch was rewritten": "此分支已被重写", + "This commit": "此提交", + "This commit exists only in your local repository.": "此提交只存在于你的本地仓库中。", + "This commit resolved": "此提交已解决", + "This conversation is resolved": "此对话已解决", + "This deletes the tag locally. If it was already pushed, it stays on the remote until you delete it there too.": "这会在本地删除该标签。如果它已经推送过,它会保留在远程仓库中,直到你在那里也删除它。", + "This file can only be staged whole — it is binary or too large to stage change by change.": "此文件只能整体暂存 — 它是二进制文件,或过大而无法逐块暂存。", + "This file is done. {0} still {1} conflicts.": "此文件已完成。{0} 仍{1}冲突。", + "This file is not in a Git repository, so there is no conflict to resolve.": "此文件不在 Git 仓库中,因此没有需要解决的冲突。", + "This file is not in a Git repository.": "此文件不在 Git 仓库中。", + "This file is not inside an open Git repository": "此文件不在已打开的 Git 仓库中", + "This file was already resolved outside the merge editor (by hand, or by git rerere): the Result starts from it. ": "此文件已在合并编辑器之外解决(手动完成,或由 git rerere 完成):结果将从它开始。 ", + "This line has local, not-yet-committed edits.": "此行有本地尚未提交的编辑。", + "This merge has {0} parents. Which one should be kept as the mainline?": "此合并有 {0} 个父提交。应以哪一个为主线保留?", + "This pull request is still a draft": "此拉取请求仍是草稿", + "This pull request is {0}": "此拉取请求为 {0}", + "This pull request's branch is the one checked out here. Updated {0}": "此拉取请求的分支就是这里检出的分支。已更新 {0}", + "This removes the branch from the remote for everyone, not just from your copy. Your local {0} (if you have one) is untouched.": "这会将分支从远程仓库中移除,对所有人生效,而不只是你的副本。你的本地 {0}(如果有)不受影响。", + "This replaces only the versions you rewrote — nobody else's commits are on the remote branch.": "这只替换你改写过的版本 — 远程分支上没有其他人的提交。", + "This repository has no GitHub remote": "此仓库没有 GitHub 远程仓库", + "This repository has no branches yet": "此仓库还没有分支", + "This repository has no remote for {0}, so its pull requests can't be checked out here.": "此仓库没有 {0} 的远程仓库,因此无法在这里检出它的拉取请求。", + "This repository has no remotes": "此仓库没有远程仓库", + "This repository has no remotes, so there is nothing to fetch from or push to.": "此仓库没有远程仓库,因此没有可获取或推送的目标。", + "This repository has no remotes. Pull requests show here once a remote points at github.com.": "此仓库没有远程仓库。当某个远程仓库指向 github.com 时,拉取请求就会显示在这里。", + "This repository isn't connected to GitHub.": "此仓库未连接到 GitHub。", + "This repository isn't on GitHub": "此仓库不在 GitHub 上", + "This tab has {0} open, so it can't be removed from here — its folder would be deleted from under the tab. Close this tab, then remove it from another worktree of the repository.": "此标签页打开了 {0},因此无法从这里移除 — 它的文件夹会从该标签页下被删除。请关闭此标签页,再从仓库的其他工作树中移除它。", + "This takes a moment after a push. Refresh to see.": "推送后这需要一点时间。请刷新查看。", + "This window": "此窗口", + "This window has it open — its folder would be deleted from under the window.": "此窗口打开着它 — 它的文件夹会从该窗口下被删除。", + "This window has it open.": "此窗口打开着它。", + "This window has {0} open, so it can't be removed from here — its folder would be deleted from under the window. Remove it from another window, or open something else in this one first.": "此窗口打开了 {0},因此无法从这里移除 — 它的文件夹会从该窗口下被删除。请从另一个窗口移除它,或先在此窗口打开别的内容。", + "Those are all the commits on the branch — dropping them would leave nothing.": "这些是分支上的全部提交 — 丢弃它们会什么都不剩。", + "Those changes are no longer there — refresh and try again.": "那些更改已不存在 — 请刷新后重试。", + "Those commits are too far down the branch to {0} from here. Start an interactive rebase instead.": "那些提交在分支中位置太靠下,无法从这里{0}。请改用交互式变基。", + "Throw your pending comments away without sending them": "丢弃你待提交的评论,不发送它们", + "Tidy up your recent commits before you push.": "推送前先整理你的近期提交。", + "Timed out": "已超时", + "Timed out after 15s — is the server running and the model loaded?": "15 秒后超时 — 服务器是否在运行、模型是否已加载?", + "Title": "标题", + "To pull from {0}": "要从 {0} 拉取", + "Together AI": "Together AI", + "Toggle columns": "切换列显示", + "Toggle file tree": "切换文件树", + "Too large to merge here": "太大,无法在此合并", + "Took": "已采用", + "Took both": "采用了双方", + "Took the change (the same on both sides)": "采用了该更改(两侧相同)", + "Took {0}": "采用了 {0}", + "Tracked Branch: {0}…": "跟踪的分支:{0}…", + "Trim whitespaces": "去除空白字符", + "Turn them off": "关闭它们", + "Type changed": "类型已更改", + "Uncheck all": "全部取消勾选", + "Uncommitted": "未提交", + "Uncommitted changes": "未提交的更改", + "Uncommitted changes to {0} will be discarded.": "对 {0} 的未提交更改将被丢弃。", + "Uncommitted changes you have made since are discarded.": "此后你所做的未提交更改会被丢弃。", + "Uncommitted changes — open in the Commit Graph for details": "未提交的更改 — 在提交图中打开以查看详情", + "Undid {0}": "已撤销 {0}", + "Undo": "撤销", + "Undo \"{0}\"?{1}": "撤销“{0}”?{1}", + "Undo ({0}Z)": "撤销({0}Z)", + "Undo History": "撤销历史", + "Undo commits…": "撤销提交…", + "Undo couldn't abandon the rebase: {0}": "撤销无法放弃变基:{0}", + "Undo couldn't go back to {0} without overwriting your uncommitted changes: {1}": "撤销无法在不覆盖你未提交更改的情况下回到 {0}:{1}", + "Undo couldn't put your working tree back: {0}": "撤销无法恢复你的工作树:{0}", + "Undo couldn't switch back to {0}: {1}": "撤销无法切回 {0}:{1}", + "Undo couldn't {0}: {1}": "撤销无法{0}:{1}", + "Undo failed: could not reset to {0}: {1}": "撤销失败:无法重置到 {0}:{1}", + "Undo is available afterwards.": "之后可以使用撤销。", + "Undo of the reverted commit": "对已还原提交的撤销", + "Undo of {0}": "对 {0} 的撤销", + "Undo put things back, but couldn't end the {0} in progress: {1}": "撤销已恢复原状,但无法结束进行中的{0}:{1}", + "Undo put your changes back, but couldn't drop the stash “{0}”: {1}": "撤销已恢复你的更改,但无法删除贮藏“{0}”:{1}", + "Undo restored the commit but re-applying your uncommitted changes hit a conflict: {0} ": "撤销恢复了该提交,但重新应用你的未提交更改时遇到冲突:{0} ", + "Undo the Apply: bring the conflict back into the file": "撤销应用:将冲突带回文件中", + "Undo these local commits — reset them back to staged / unstaged changes": "撤销这些本地提交 — 将它们重置回已暂存 / 未暂存的更改", + "Undo this operation — and, newest first, every one after it.": "撤销此操作 — 以及按从新到旧顺序的其后每一个操作。", + "Undo {0} local {1}": "撤销 {0} 个本地 {1}", + "Undone — click to re-apply up to here": "已撤销 — 点击以重新应用到此为止", + "Unified diff": "统一差异", + "Unknown ref: {0}": "未知的引用:{0}", + "Unlock": "解锁", + "Unlock a worktree": "解锁工作树", + "Unlock and Forget": "解锁并忘记", + "Unlock and Remove": "解锁并移除", + "Unlock, Discard Changes and Remove": "解锁、丢弃更改并移除", + "Unlock, Stash & Remove": "解锁、贮藏并移除", + "Unlocked the worktree {0}": "已解锁工作树 {0}", + "Unmerged files": "未合并的文件", + "Unmerged files on {0}": "{0} 上未合并的文件", + "Unresolve": "取消解决", + "Unresolving…": "正在取消解决…", + "Unset upstream": "取消设置上游", + "Unstage": "取消暂存", + "Unstage All": "全部取消暂存", + "Unstage Folder": "取消暂存文件夹", + "Unstage all": "全部取消暂存", + "Unstage file": "取消暂存文件", + "Unstage folder": "取消暂存文件夹", + "Unstage {0}": "取消暂存 {0}", + "Unstaged": "未暂存", + "Unstaged edits are lost; {0}.": "未暂存的修改会丢失;{0}。", + "Unstaged selection": "已取消暂存所选内容", + "Untracked": "未跟踪", + "Up arrow": "上箭头", + "Up to date with upstream": "与上游保持一致", + "Up to date with {0}.": "与 {0} 已同步。", + "Update URL": "更新 URL", + "Update branch": "更新分支", + "Update it to the latest": "将其更新到最新", + "Update this remote's branches.": "更新此远程仓库的分支。", + "Updated {0}": "已更新 {0}", + "Updated {0} URL": "已更新 {0} 的 URL", + "Updated {0} to the latest of PR #{1} ({2} brought in).{3}": "已将 {0} 更新到 PR #{1} 的最新版本(引入了 {2})。{3}", + "Updated {0} to the latest of PR #{1}.": "已将 {0} 更新到 PR #{1} 的最新版本。", + "Updating…": "正在更新…", + "Upstream gone": "上游已消失", + "Use": "使用", + "Use Anthropic directly with your API key.": "使用你的 API 密钥直接调用 Anthropic。", + "Use instead": "改为使用", + "Use letters, digits, dot, dash or underscore.": "请使用字母、数字、点、短横线或下划线。", + "Use {0}": "使用 {0}", + "Uses --force-with-lease, which still refuses to overwrite remote work you haven't seen.": "使用 --force-with-lease,它仍会拒绝覆盖你尚未见过的远程工作。", + "VS Code Language Model (zero-key) — Copilot / Cursor": "VS Code 语言模型(免密钥)— Copilot / Cursor", + "VS Code's own merge editor and conflict highlights are as they were.": "VS Code 自带的合并编辑器和冲突高亮保持原样。", + "VS Code's own merge editor and conflict highlights are off.": "VS Code 自带的合并编辑器和冲突高亮已关闭。", + "View as List": "以列表查看", + "View as Tree": "以树形查看", + "WIP: …": "WIP:…", + "Waiting": "等待中", + "Waiting for the model…": "正在等待模型…", + "Waiting on {0}.": "正在等待 {0}。", + "What is being merged in: {0}": "正在合并进来的内容:{0}", + "What is committed on {0} now": "{0} 上当前已提交的内容", + "What should the new worktree be based on?": "新工作树应基于什么?", + "What the colours and lines mean": "颜色和线条的含义", + "What the colours mean": "颜色的含义", + "What the merge colours and lines mean": "合并颜色和线条的含义", + "What the pull request does": "此拉取请求做了什么", + "What the pull request will have": "此拉取请求将包含什么", + "What this change does, in plain language": "用通俗的语言说明此更改做了什么", + "When \"{0}\" ran, git couldn't keep a copy of your uncommitted changes {1}, ": "运行 \"{0}\" 时,git 无法保留你未提交更改的副本{1}, ", + "Where a file was staged and then changed again, its staged version is not kept.": "如果文件先被暂存、之后又被更改,其已暂存的版本不会被保留。", + "Where should the committed changes go? Your work is kept either way.": "已提交的更改应放到哪里?无论哪种方式,你的工作都会被保留。", + "Where this remote fetches from and pushes to.": "此远程仓库的获取来源和推送目标。", + "Which branch is checked out changed while you were being asked. Nothing was reset — try again.": "在你被询问期间,检出的分支发生了改变。未重置任何内容 — 请重试。", + "Which model should the AI features use?": "AI 功能应使用哪个模型?", + "Which pull requests": "哪些拉取请求", + "Whitespace handling": "空白字符处理", + "Why?": "为什么?", + "Work on another branch, side by side": "在另一个分支上并行工作", + "Working": "进行中", + "Working Tree": "工作树", + "Working Tree vs HEAD": "工作树 vs HEAD", + "Working tree clean": "工作树干净", + "Working…": "处理中…", + "Worktree from '{0}'": "从 '{0}' 创建的工作树", + "Worktrees": "工作树", + "Write a comment (a Comment review needs one)": "写一条评论(“评论”类审查需要一条)", + "Write the description from the commits and the diff with AI (replaces what is there)": "用 AI 根据提交和差异撰写描述(替换现有内容)", + "Written on {0} — the pull request has moved on to {1}. They are sent on the commit they were written on.": "写于 {0} — 拉取请求已推进到 {1}。它们会以撰写时所在的提交发送。", + "You": "你", + "You (@{0})": "你(@{0})", + "You have uncommitted changes": "你有未提交的更改", + "You have uncommitted changes. Commit or stash them, then drop the commit.": "你有未提交的更改。请先提交或贮藏它们,然后丢弃该提交。", + "You have uncommitted changes. Commit or stash them, then drop the commits.": "你有未提交的更改。请先提交或贮藏它们,然后丢弃这些提交。", + "You have uncommitted changes. Commit or stash them, then squash the commits.": "你有未提交的更改。请先提交或贮藏它们,然后压缩这些提交。", + "You have uncommitted changes. Commit or stash them, then start the rebase.": "你有未提交的更改。请先提交或贮藏它们,然后开始变基。", + "You have {0} {1} doesn't, and it has {2} you don't. ": "你有 {0} 个提交是 {1} 没有的,而它有 {2} 个是你没有的。 ", + "You rewrote a commit the remote already has, so a normal push is refused. ": "你改写了远程仓库已有的提交,因此普通推送会被拒绝。 ", + "You'll be on a detached HEAD — commits made here belong to no branch until you create one.": "你将处于分离的 HEAD 状态 — 在这里进行的提交不属于任何分支,直到你创建一个分支。", + "You'll be on a detached HEAD — not on any branch. Commits made here belong to nothing until you create a branch for them.": "你将处于分离的 HEAD 状态 — 不在任何分支上。在这里进行的提交不属于任何东西,直到你为它们创建一个分支。", + "You're already on {0}, the branch of PR #{1}{2}.{3}": "你已经在 {0} 上,即 PR #{1} 的分支{2}。{3}", + "You're on {0}, the branch of PR #{1}: {2}.{3}": "你在 {0} 上,即 PR #{1} 的分支:{2}。{3}", + "You've made commits on the detached HEAD since (it is at {0} now), and switching back would leave them on no branch. Create a branch for them first, then undo.": "你此后在分离 HEAD 上创建了提交(现在位于 {0}),切回会让它们不属于任何分支。请先为它们创建一个分支,然后撤销。", + "Your GitHub session expired": "你的 GitHub 会话已过期", + "Your GitHub session expired. Sign in again to continue.": "你的 GitHub 会话已过期。请重新登录以继续。", + "Your branch {0}": "你的分支 {0}", + "Your branch {0}, as it was before the merge": "你的分支 {0},合并之前的样子", + "Your changes to {0} are kept in the stash {1} — git won't put them back ": "你对 {0} 的更改保存在贮藏 {1} 中 — git 不会把它们放回 ", + "Your changes to {0} are waiting in the stash {1} — ": "你对 {0} 的更改正等待在贮藏 {1} 中 — ", + "Your changes to {0} were put back, but they conflict with what came in — ": "你对 {0} 的更改已放回,但它们与进来的内容冲突 — ", + "Your comment is back in its box.": "你的评论已回到输入框中。", + "Your commit a1b2c3d “{0}” from feature/session-hardening": "你在 feature/session-hardening 上的提交 a1b2c3d“{0}”", + "Your commit {0} “{1}” from {2}": "你的提交 {0} “{1}”,来自 {2}", + "Your commits stay. The PR's newer commits aren't brought in.": "你的提交会保留。该 PR 较新的提交不会被引入。", + "Your commits stay. The pull request's newer commits aren't brought in: pull to merge them.": "你的提交会保留。该拉取请求较新的提交不会被引入:请拉取以合并它们。", + "Your history will appear here after the first commit.": "第一次提交后,你的历史将显示在这里。", + "Your local commits are rewritten on top of {0}, so they get new shas. If you have already pushed them, the next push needs a force. Undo can take you back.": "你的本地提交会被重写到 {0} 之上,因此会获得新的 sha。如果你已经推送过它们,下次推送需要强制。撤销可以带你回到原状。", + "Your reply is back in its box.": "你的回复已回到输入框中。", + "Your resolution leaves {0} “{1}” with no changes, so continuing drops it ": "你的解决方式使 {0}“{1}”没有任何更改,因此继续会把它 ", + "Your review": "你的审查", + "Your review of {0}/{1}#{2}{3}: {4}. Click to submit it.": "你对 {0}/{1}#{2}{3} 的审查:{4}。点击以提交。", + "Your reviews of {0}: {1}. Click to submit one.": "你对 {0} 的审查:{1}。点击以提交其中一条。", + "Your stashed changes": "你贮藏的更改", + "Your uncommitted changes are in the way": "你的未提交更改造成了阻碍", + "Your uncommitted changes are kept.": "你的未提交更改会被保留。", + "Your uncommitted changes come along.": "你的未提交更改会一起带上。", + "Your uncommitted changes come back as they were before it.": "你的未提交更改会恢复为它之前的样子。", + "Your uncommitted changes go back to how they were before it.": "你的未提交更改会回到它之前的状态。", + "Your uncommitted changes to {0} are in the way of creating the branch “{1}” ": "你对 {0} 的未提交更改妨碍了创建分支“{1}” ", + "Your uncommitted changes to {0} are in the way of {1} — ": "你对 {0} 的未提交更改妨碍了{1} — ", + "Your uncommitted changes touch files the {0} changed. Commit or stash them, then undo.": "你的未提交更改涉及{0}所改动的文件。请先提交或贮藏它们,然后撤销。", + "Your verdict": "你的结论", + "Your {0} replaced the {1} the remote still has — amending a pushed commit does this. Pulling would bring the old one back.": "你的{0}替换了远程仍持有的{1} — 修改已推送的提交会导致这种情况。拉取会带回旧的那个。", + "Yours": "你的", + "Yours {0}, theirs {1}: the result keeps {2}.": "你的 {0},他们的 {1}:结果保留 {2}。", + "[$(arrow-up) Push](command:gitstudio.sync.push)": "[$(arrow-up) 推送](command:gitstudio.sync.push)", + "[$(repo-fetch) Fetch](command:gitstudio.sync.fetch)": "[$(repo-fetch) 获取](command:gitstudio.sync.fetch)", + "`git stash apply {0}` brings them back.": "`git stash apply {0}` 可以把它们找回来。", + "a branch not listed": "一个未列出的分支", + "a cherry-pick": "一次拣选", + "a commit": "一个提交", + "a deleted account": "一个已删除的帐户", + "a few minutes": "几分钟", + "a fork that was deleted": "一个已删除的复刻", + "a merge": "一次合并", + "a new file": "一个新文件", + "a new or renamed file": "一个新文件或重命名的文件", + "a new root": "一个新的根", + "a patch": "一个补丁", + "a rebase": "一次变基", + "a renamed file": "一个重命名的文件", + "a revert": "一次还原", + "a signal": "信号", + "a {0}": "一个{0}", + "above": "上方", + "add its assignees": "添加其负责人", + "add its labels": "添加其标签", + "added on both sides": "两侧都已添加", + "added on one side": "一侧已添加", + "all": "全部", + "all changes": "所有更改", + "already made are still there. Check the log before carrying on.": "创建的提交仍在。继续之前请先查看日志。", + "an operation": "一个操作", + "an unknown revision": "未知版本", + "an {0}": "一个{0}", + "and Undo (⌘⌥G Z) reverses it.": "而撤销(⌘⌥G Z)会将其撤销。", + "and continue, or abort the revert.": "然后继续,或中止该还原。", + "and more — the Commit Graph shows them all": "以及更多 — 提交图会显示全部", + "anything settled here and not saved is not kept.": "在此处解决但未保存的内容不会被保留。", + "apply the next patch": "应用下一个补丁", + "applying": "正在应用", + "applying a stash": "正在应用贮藏", + "applying patches (git am)": "正在应用补丁(git am)", + "applying the stash": "正在应用该贮藏", + "approved": "已批准", + "approved these changes": "批准了这些更改", + "are": "已被", + "aren't": "未", + "as it was": "保持原样", + "asked for a review": "请求了评审", + "asked to review": "已请求审查", + "asked to review again": "已再次请求审查", + "asked {0} for a review": "请求 {0} 评审", + "automatic opening is off. Turn VS Code's own merge editor and conflict highlights back on?": "自动打开已关闭。是否重新开启 VS Code 自带的合并编辑器和冲突高亮?", + "before ↔ {0} “{1}”": "之前 ↔ {0}“{1}”", + "below": "下方", + "beside the main worktree": "位于主工作树旁边", + "binary": "二进制", + "blame failed for {0}: {1}": "对 {0} 的 blame 失败:{1}", + "branch": "分支", + "branches": "分支", + "bring back '{0}'": "恢复 '{0}'", + "by {0}": "由 {0}", + "change": "个更改", + "changed": "已更改", + "changed file": "个更改的文件", + "changed files": "个更改的文件", + "changes": "个更改", + "changes requested": "请求了更改", + "changes were requested": "有人请求了更改", + "checked out": "已检出", + "checked out here": "在此处检出", + "checking out": "正在检出", + "checking…": "正在检查…", + "cherry-pick": "拣选", + "cherry-picking": "正在拣选", + "choose between — the file is going either way. Delete it to accept the deletion and settle ": "在两者之间选择 — 该文件无论如何都会如此。删除它以接受删除并了结 ", + "closed": "已关闭", + "closed this": "关闭了此拉取请求", + "comment": "条评论", + "commented": "已评论", + "comments": "条评论", + "commit": "提交", + "commit does this. A normal push will be refused.": "提交会造成这种情况。普通推送将被拒绝。", + "commit the merge": "提交该合并", + "commits": "提交", + "commits{0}. Accept one side to record its commit. The submodule's own checkout is left as it is: run ": "个提交{0}。接受一侧以记录其提交。子模块自身的检出保持原样:请运行 ", + "committed by {0}": "提交者 {0}", + "compared with": "对比于", + "conflict": "个冲突", + "conflicted files now open in its merge editor. Turn off VS Code's own merge editor and conflict ": "个冲突文件现在会在它的合并编辑器中打开。请关闭 VS Code 自带的合并编辑器和冲突 ", + "conflicting file": "个冲突文件", + "conflicting files": "个冲突文件", + "conflicts": "个冲突", + "conflicts and continue, or abort the revert.": "冲突并继续,或中止该还原。", + "conflicts and continue, skip this commit, or abort.": "冲突并继续、跳过此提交,或中止。", + "continue": "继续", + "continue the cherry-pick": "继续拣选", + "continue the rebase": "继续变基", + "continue the revert": "继续还原", + "conversation": "个会话", + "conversations": "个会话", + "couldn't load the diff — {0}": "无法加载差异 — {0}", + "couldn't read the conflict versions — {0}": "无法读取冲突版本 — {0}", + "couldn't restore the conflict.": "无法恢复该冲突。", + "couldn't save the resolved file — {0}": "无法保存已解决的文件 — {0}", + "couldn't stage that change — {0}": "无法暂存该更改 — {0}", + "couldn't {0} ({1})": "无法{0}({1})", + "current": "当前", + "current HEAD": "当前 HEAD", + "day": "天", + "days": "天", + "default": "默认", + "delete '{0}'": "删除 '{0}'", + "delete the commit": "删除该提交", + "delete the selected commits": "删除选中的提交", + "deleted on both sides": "两侧都已删除", + "deleted on one side": "一侧已删除", + "detached HEAD": "分离的 HEAD", + "detached at {0}": "分离于 {0}", + "dismissed a review": "驳回了评审", + "diverged": "已分叉", + "doesn't.": "没有。", + "draft ": "草稿 ", + "drop": "丢弃", + "dropped": "丢弃", + "dropping": "丢弃", + "dropping a commit": "正在丢弃提交", + "dropping commits": "正在丢弃多个提交", + "each line is not annotated twice. You can turn it back on in Settings.": "每一行不会被重复标注。你可以在设置中重新开启。", + "edit": "编辑", + "either arrow takes it": "任一方向键即可采用", + "every worktree's folder is still there.": "每个工作树的文件夹仍然存在。", + "everything staged": "所有已暂存的内容", + "file": "个文件", + "files": "个文件", + "first": "第一个", + "fixup": "修正", + "fold each into the commit before it, dropping its message": "将它们各自并入前一个提交,丢弃其提交信息", + "fold each into the commit before it, keeping both messages": "将它们各自并入前一个提交,保留两条提交信息", + "fold up, discard message": "折叠合并,丢弃信息", + "fold up, keep both messages": "折叠合并,保留两条信息", + "folder missing": "文件夹丢失", + "force-pushed the branch": "强制推送了分支", + "force-pushed the branch from {0} to {1}": "强制推送了分支 {0} → {1}", + "forget": "忘记", + "from a deleted fork": "来自一个已删除的复刻", + "from another machine or someone else — and a force push would delete them. ": "来自另一台机器或他人 — 而强制推送会删除它们。 ", + "from the fork {0}": "来自复刻 {0}", + "from the stash, which first switches to where the stash was made. ": "来自贮藏,这会先切换到创建该贮藏的位置。 ", + "from {0}. Keep editing if you meant to keep it.": "从 {0} 中丢弃。如果你确实想保留它,请继续编辑。", + "git am is applying patches in it": "git am 正在其中应用补丁", + "git am is applying patches in it. Removing the worktree abandons the patches not yet applied.": "git am 正在其中应用补丁。移除该工作树会放弃尚未应用的补丁。", + "git blame failed for {0} (exit {1}): {2}": "{0} 的 git blame 失败(退出码 {1}):{2}", + "git can't continue the {0} yet.": "git 暂时无法继续该 {0}。", + "git can't keep both at one path, and taking the file would delete the folder — nothing was changed. ": "git 无法在同一路径上同时保留两者,取用该文件会删除该文件夹 — 未做任何更改。 ", + "git couldn't add the remote {0}: {1}": "git 无法添加远程仓库 {0}:{1}", + "git couldn't apply this patch. Skip it, or abort.": "git 无法应用此补丁。跳过它,或中止。", + "git couldn't delete it": "git 无法删除它", + "git couldn't keep a copy of those {0}. Commit or stash them, then undo.": "git 无法保留那些{0}的副本。请先提交或贮藏它们,然后撤销。", + "git diff --cached --check failed ({0}).": "git diff --cached --check 失败({0})。", + "git diff --name-only failed ({0}).": "git diff --name-only 失败({0})。", + "git exited with code {0}.": "git 以代码 {0} 退出。", + "git fetch exited with {0}": "git fetch 以 {0} 退出", + "git gave no reason.": "git 未给出原因。", + "git has moved on since that Apply, so there is no conflict to bring back. Nothing was changed.": "自那次应用以来 git 已发生变化,因此没有可带回的冲突。未做任何更改。", + "git log --follow failed for {0} (exit {1}): ": "{0} 的 git log --follow 失败(退出码 {1}): ", + "git log -L failed for {0} (exit {1}): ": "{0} 的 git log -L 失败(退出码 {1}): ", + "git ls-files --resolve-undo failed ({0}).": "git ls-files --resolve-undo 失败({0})。", + "git ls-files -u failed ({0})": "git ls-files -u 失败({0})", + "git ls-files -u failed ({0}), so the unmerged files are unknown.": "git ls-files -u 失败({0}),因此未合并的文件未知。", + "git reflog exited {0}": "git reflog 以 {0} 退出", + "git refused": "git 拒绝", + "git refused the commit without saying why. If this repository has a pre-commit hook, check its output.": "git 拒绝提交但没有说明原因。如果此仓库有 pre-commit 钩子,请检查它的输出。", + "git refused the push.": "git 拒绝了推送。", + "git rev-parse --git-path failed ({0}).": "git rev-parse --git-path 失败({0})。", + "git rev-parse --git-path {0} failed ({1}).": "git rev-parse --git-path {0} 失败({1})。", + "git says: “{0}”": "git 说:“{0}”", + "git still has a worktree at {0} ({1}) — {2} that worktree in Worktrees, or choose another folder. {3}": "git 在 {0}({1})仍注册着工作树 — 请在工作树中{2}该工作树,或选择其他文件夹。{3}", + "git still has a worktree at {0} ({1}), though its folder is gone — {2} that worktree in Worktrees, or choose another folder. {3}": "git 在 {0}({1})仍注册着工作树,尽管其文件夹已不存在 — 请在工作树中{2}该工作树,或选择其他文件夹。{3}", + "git submodule update afterwards.": "之后执行 git submodule update。", + "git was stopped by {0} before it finished.": "git 在完成前被{0}中止。", + "git won't overwrite them. Stash {0} and try again, or commit {1} first.": "git 不会覆盖它们。请贮藏 {0} 后重试,或先提交 {1}。", + "git worktree add failed.": "git worktree add 失败。", + "git {0} exited with code {1}": "git {0} 以代码 {1} 退出", + "git {0} failed: {1}": "git {0} 失败:{1}", + "git {0}: {1}": "git {0}:{1}", + "git's record of the worktree at {0} wasn't found.": "未找到 git 对 {0} 处工作树的记录。", + "go on to the next step": "进行下一步", + "goes": "将要", + "has": "有", + "has no line breaks": "没有换行符", + "has none": "没有", + "has nothing that": "没有任何", + "have": "有", + "highlights so they don't open alongside it? You can switch back any time with ": "高亮,以便它们不会与它同时打开?你可以随时用以下方式切回 ", + "hour": "小时", + "hours": "小时", + "ignored": "已忽略", + "in": "在", + "in the project's folder": "在项目文件夹中", + "in the worktree {0}": "在工作树 {0} 中", + "in your working tree": "在你的工作树中", + "into Changes": "移入“更改”", + "into Staged": "移入“已暂存”", + "into Staged and Unstaged": "移入“已暂存”和“未暂存”", + "into Unstaged": "移入“未暂存”", + "is": "已被", + "is no earlier version behind either. Keep the new file, or leave it out.": "背后也没有更早的版本。保留新文件,或将其排除。", + "isn't": "未", + "it": "它", + "it in an editor and stage it.": "在编辑器中处理后再暂存它。", + "it is": "它", + "it isn't a worktree any more": "它不再是工作树", + "it needs an approving review": "还需要一次批准评审", + "its .git file is gone": "它的 .git 文件已不见", + "its folder is gone, or isn't a worktree any more": "它的文件夹已不存在,或它不再是工作树", + "its staged version no longer applies": "它暂存的版本已不再适用", + "its upstream": "它的上游", + "just now": "刚刚", + "keep it, but rewrite the message": "保留它,但改写信息", + "keep the commit as it is": "保持该提交原样", + "keep the selected commits as they are": "保持选中的提交原样", + "keep them, and rewrite their messages": "保留它们,并重写其提交信息", + "keep, change message": "保留,修改信息", + "kept theirs": "保留他们的", + "kept yours": "保留你的", + "kept {0} · {1}": "保留了 {0} · {1}", + "labels {0}": "标签 {0}", + "last commit, so git left the branch where it is rather than rewinding — the commits it had ": "上一次提交以来已移动,因此 git 没有回退分支而是保持原样 — 它已经", + "leave": "会离开", + "leaves": "会离开", + "lines {0}–{1}": "第 {0}–{1} 行", + "loading older commits…": "正在加载更早的提交…", + "local branch": "本地分支", + "local branches": "本地分支", + "locked": "已锁定", + "made here, or from before the pull request was force-pushed.": "在此处进行的,或在该拉取请求被强制推送之前进行的。", + "main, plus the commits already rebased onto it": "main,以及已经变基到它上面的提交", + "mark #{0} ready for review": "将 #{0} 标记为可供审查", + "mark it ready for review": "将其标记为可供审查", + "marked this as a draft": "将其标记为草稿", + "marked this ready for review": "将其标记为可评审", + "meld into the commit above (the older one)": "合并进上面的提交(更早的那个)", + "meld into the commit above, drop this message": "合并进上面的提交,丢弃这条信息", + "merge": "合并", + "merge #{0}": "合并 #{0}", + "merge into the commit below it — drop this message": "合并进它下面的提交 — 丢弃这条信息", + "merge into the commit below it — keep both messages": "合并进它下面的提交 — 保留两条信息", + "merged": "已合并", + "merged commit {0} into {1}": "将提交 {0} 合并进 {1}", + "merged this into {0}": "将其合并进 {0}", + "merging": "正在合并", + "minute": "分钟", + "minutes": "分钟", + "missing": "丢失", + "month": "个月", + "months": "个月", + "move '{0}' back to {1}": "将 '{0}' 移回 {1}", + "new base": "新的基底", + "new root": "新的根", + "no branch (detached HEAD)": "无分支(分离的 HEAD)", + "no branches": "无分支", + "no commits yet": "尚无提交", + "no email recorded": "未记录邮箱", + "no one": "无人", + "no remote of this repository ({0}) is a GitHub, GitLab or Bitbucket address.": "此仓库的所有远程仓库({0})都不是 GitHub、GitLab 或 Bitbucket 地址。", + "not a pull request number: {0}": "不是拉取请求编号:{0}", + "not a worktree": "不是工作树", + "not published": "未发布", + "not pushed": "未推送", + "not the op's": "不属于该操作", + "nothing": "无", + "nothing to merge line by line: keep the edited file, or accept the deletion.": "没有可逐行合并的内容:保留已编辑的文件,或接受删除。", + "nothing to pull or push": "无需拉取或推送", + "of": "/", + "oldest": "最早", + "on top of the stash list": "贮藏列表顶部", + "one side only — safe to take": "仅一侧 — 可安全采用", + "onto": "变基到", + "open": "打开", + "open a file in a Git repository to stage its changes.": "打开 Git 仓库中的文件以暂存其更改。", + "open a file to compare it against HEAD.": "打开文件以将其与 HEAD 比较。", + "opened this": "打开了此拉取请求", + "operation": "操作", + "or by git rerere. Apply replaces that with the Result shown here, and stages it.": "或由 git rerere 完成。应用会用此处显示的结果替换它,并将其暂存。", + "over the changes that just came in. Apply it when you're ready.": "覆盖刚刚进来的更改。准备好后再应用它。", + "parent": "父提交", + "parents": "父提交", + "partly staged": "部分暂存", + "patch": "补丁", + "patch series": "补丁系列", + "patch {0} of {1}": "补丁 {0}/{1}", + "pause at each so you can amend it": "在每个提交处暂停,以便修改", + "pause here so you can amend the commit": "在此暂停,以便你修正该提交", + "pending comment": "条待发送评论", + "pending comments": "条待发送评论", + "pick": "拣选", + "picked commit": "被拣选的提交", + "point": "指向", + "points": "指向", + "post the reply": "发布回复", + "post your comment": "发布你的评论", + "post your reply": "发布你的回复", + "pulling again": "正在重新拉取", + "pushed to": "已推送到", + "rebase": "变基", + "rebasing": "正在变基", + "remote branch": "远程分支", + "remote branches": "远程分支", + "remote {0} — a fork of {1}/{2}": "远程 {0} — {1}/{2} 的复刻", + "remote {0} — {1} was forked from it": "远程 {0} — {1} 是从它复刻的", + "remote-tracking branch": "远程跟踪分支", + "remote-tracking branches": "远程跟踪分支", + "remove": "移除", + "remove the commit": "移除该提交", + "reopened this": "重新打开了此拉取请求", + "replay the next commit": "重放下一个提交", + "request its reviewers": "请求其审查者", + "requested changes": "请求了更改", + "required checks failed": "必需的检查未通过", + "required checks haven't finished": "必需的检查尚未完成", + "reset {0} to pull request #{1}": "将 {0} 重置为拉取请求 #{1}", + "resetting": "正在重置", + "resolve the conversation": "解决该会话", + "resolve them in Changes. They are also kept in the stash {0}.": "请到“更改”视图中解决它们。它们也保存在贮藏 {0} 中。", + "resolved": "已解决", + "resolved and commit the markers — resolve them first.": "已解决并提交这些标记 — 请先解决它们。", + "resolved are discarded — they were never committed, so nothing can bring them back.": "冲突会被丢弃 — 它们从未提交过,所以任何东西都无法把它们找回来。", + "revert": "还原", + "reverting": "正在还原", + "reviewed": "已评审", + "reviewed (dismissed)": "已评审(已驳回)", + "reword": "改写", + "safe to take": "可安全采用", + "saving a merge built from part of a file would delete the rest. Accept one side, or resolve ": "保存由文件的一部分构建的合并会删除其余部分。请接受一侧,或解决 ", + "set their action.": "设置它们的操作。", + "sk-… (blank for a local, keyless server)": "sk-… (本地免密钥服务器可留空)", + "so Undo can't put them back. Nothing was changed.": "因此撤销无法把它们放回。未做任何更改。", + "someone not listed": "一个未列出的人", + "squash": "压缩", + "squashed": "压缩", + "squashing": "压缩", + "squashing commits": "正在压缩多个提交", + "staged": "已暂存", + "staged in": "暂存于", + "started a review": "开始了评审", + "stash": "贮藏", + "stash apply": "贮藏应用", + "stash the whole staged section, or stash those files entirely.": "贮藏整个已暂存部分,或把这些文件整体贮藏。", + "stashed in": "贮藏于", + "stashes": "贮藏", + "step": "步骤", + "still shows a rebase's sides the old way round. Update {0} to use one Conflicts view, ": "仍以旧方式显示变基的两侧。请更新 {0} 以使用统一的冲突视图,", + "stop to amend the commit": "停下来修改该提交", + "submodule": "子模块", + "switching to it": "正在切换到它", + "symbolic link": "符号链接", + "tag": "标签", + "tag: {0}": "标签:{0}", + "tagged": "已打标签", + "tags": "标签", + "taken": "已采纳", + "that comment": "该评论", + "the PR was force-pushed.": "该 PR 被强制推送过。", + "the changes": "这些更改", + "the cherry-pick": "该拣选", + "the conflict is settled. Resolve them first.": "该冲突才算解决。请先解决它们。", + "the conflict.": "该冲突。", + "the detached HEAD": "分离的 HEAD", + "the file that has staged changes keeps them": "有已暂存更改的那个文件会保留这些更改", + "the file yourself and stage it.": "需要你自行处理该文件后再暂存。", + "the files are in Changes, but the stash couldn't be updated — {0}": "文件已在“更改”中,但无法更新该贮藏 — {0}", + "the files are in Changes, but “{0}” had left the stash list meanwhile, so nothing more was changed.": "文件已在“更改”中,但“{0}”在此期间已离开贮藏列表,因此没有再更改其他内容。", + "the folder is gone": "其文件夹已不存在", + "the link to pull request #{0}": "指向拉取请求 #{0} 的链接", + "the local branch {0}": "本地分支 {0}", + "the merge": "该合并", + "the merged branch": "被合并的分支", + "the new base": "新的基底", + "the only worktrees git could prune are locked.": "git 唯一能清理的工作树都已锁定。", + "the other branch": "另一个分支", + "the pull": "该拉取", + "the rebase": "该变基", + "the rebase didn't change any branch.": "该变基没有改变任何分支。", + "the rebase didn't change anything.": "该变基没有改变任何内容。", + "the rebase was abandoned, so it changed nothing.": "该变基已被放弃,因此没有改变任何内容。", + "the revert": "该还原", + "the root commit": "根提交", + "the worktree whose folder is gone": "文件夹已不存在的工作树", + "the worktree whose folder is gone or isn't a worktree any more": "文件夹已不存在或不再是工作树的那个工作树", + "the {0} files that have staged changes keep them": "有已暂存更改的 {0} 个文件会保留这些更改", + "the {0} worktrees whose folders are gone": "文件夹已不存在的 {0} 个工作树", + "the {0} worktrees whose folders are gone or aren't worktrees any more": "文件夹已不存在或已不再是工作树的 {0} 个工作树", + "their folders are gone, or aren't worktrees any more": "它们的文件夹已不存在,或它们不再是工作树", + "their staged versions no longer apply": "它们暂存的版本已不再适用", + "them": "它们", + "then {0} — or abort to go back to where you were.": "然后{0} — 或中止以回到你原来的位置。", + "there is no {0} '{1}' any more.": "已不存在 {0} '{1}'。", + "these {0} files": "这 {0} 个文件", + "they are": "它们", + "they aren't worktrees any more": "它们不再是工作树", + "this change, made the same on both sides": "此更改在两侧相同", + "this file": "此文件", + "this repository has no remote to open the commit on.": "此仓库没有可用于打开该提交的远程。", + "those comments": "那些评论", + "those commits could not be read any more — refresh the graph and try again.": "那些提交已无法读取 — 请刷新提交图并重试。", + "tip of": "指向", + "to reorder. Topmost runs first — this is git's todo file, oldest at the top.": "以重新排序。最上面的最先执行 — 这就是 git 的 todo 文件,最旧的排在最上面。", + "too large to merge here": "文件过大,无法在此合并", + "tracking {0}": "跟踪 {0}", + "uncommitted change": "个未提交的更改", + "uncommitted changes": "个未提交的更改", + "uncommitted changes to {0} are in the way. Stash {1} and try again, or commit {2} first.": "对 {0} 的未提交更改造成妨碍。请贮藏 {1} 后重试,或先提交 {2}。", + "undone, and conflicts you have resolved are discarded.": "被撤销,你已经解决的冲突会被丢弃。", + "unknown": "未知", + "unlinked": "未链接", + "unresolve the conversation": "重新打开该会话", + "unresolved change": "个未解决的更改", + "unresolved changes": "个未解决的更改", + "unstaged, but for {0}, which git adds back staged,": "未暂存,但对于 {0},git 会以已暂存状态加回,", + "untracked here, and going back to {0} would overwrite {1}. Move {2} aside, then undo.": "在此处未跟踪,而回到 {0} 会覆盖 {1}。请先把 {2} 移开,然后撤销。", + "up to date": "已是最新", + "update the branch": "更新该分支", + "update {0} to pull request #{1}": "将 {0} 更新到拉取请求 #{1}", + "updated {0}": "更新于 {0}", + "upstream gone": "上游已消失", + "use commit, edit its message": "使用提交,编辑其信息", + "use the commit as-is": "按原样使用该提交", + "uses {0}": "使用 {0}", + "v1.2.0 a1b2c3d origin/main~3": "v1.2.0 a1b2c3d origin/main~3", + "version": "版本", + "versions": "版本", + "wants to merge": "想合并", + "week": "周", + "weeks": "周", + "went": "曾", + "where it is rather than rewinding. Check the log before carrying on.": "保持原样而不是回退。继续之前请先查看日志。", + "where it opens": "打开它的位置", + "where it was in the stash list": "原在贮藏列表中的位置", + "while a file is only marked to be added (git add -N)": "因为某个文件只是被标记为待添加(git add -N)", + "while a file was only marked to be added (git add -N)": "因为某个文件当时只是被标记为待添加(git add -N)", + "whitespace only": "仅空白变化", + "will be saved as the Result shows {0}": "将按结果当前所示保存{0}", + "worktree": "工作树", + "xAI (Grok)": "xAI (Grok)", + "year": "年", + "years": "年", + "you": "你", + "you choose": "由你选择", + "your fork": "你的复刻", + "your stash list, so nothing in it is lost — but conflicts you have resolved here are.": "你的贮藏列表,因此其中的内容不会丢失 — 但你在此处解决的冲突会丢失。", + "{0}\nCtrl/⌘-click: add it after what the result has": "{0}\nCtrl/⌘-点击:将其添加到结果已有内容之后", + "{0}\nThe result keeps what it has": "{0}\n结果保留它已有的内容", + "{0} (before {1} ↔ after HEAD)": "{0} ({1} 之前 ↔ HEAD 之后)", + "{0} & Push": "{0}并推送", + "{0} (HEAD ↔ Working Tree)": "{0}(HEAD ↔ 工作树)", + "{0} (Staged)": "{0}(已暂存)", + "{0} (Working Tree)": "{0}(工作树)", + "{0} (bare)": "{0}(裸仓库)", + "{0} (current branch)": "{0}(当前分支)", + "{0} (current)": "{0}(当前)", + "{0} (detached)": "{0}(分离)", + "{0} (from {1})": "{0}(来自 {1})", + "{0} (rebasing)": "{0}(变基中)", + "{0} (was {1})": "{0}(原为 {1})", + "{0} + upstream": "{0} + 上游", + "{0} A private repository needs a sign-in with access to it.": "{0} 私有仓库需要使用有权访问它的账号登录。", + "{0} But GitStudio {1}.": "{0} 但 GitStudio {1}。", + "{0} Click Apply again to save anyway.": "{0} 再次点击“应用”以仍然保存。", + "{0} Files": "{0} 个文件", + "{0} Forgetting it unlocks it.": "{0} 忘记它会将其解锁。", + "{0} GitStudio's Undo can put the branch back and bring those edits back with it — git itself keeps no copy of them.": "{0} GitStudio 的撤销可以恢复该分支并随之找回那些编辑 — git 本身不保留它们的副本。", + "{0} Only people with write access to {1} can merge it.": "{0} 只有对 {1} 有写入权限的人才能合并它。", + "{0} Resolve {1} and {2}, or abort it, then try again.": "{0} 请解决 {1} 和 {2},或中止它,然后重试。", + "{0} Resolve {1}, finish or abort what git is in the middle of, then try again.": "{0} 请解决 {1},完成或中止 git 正在进行中的操作,然后重试。", + "{0} Resolve {1}, then try again.": "{0} 请解决 {1},然后重试。", + "{0} Take it off the undo history and go on to undo \"{1}\"? ": "{0} 将其从撤销历史中移除并继续撤销“{1}”? ", + "{0} The files left in the stash are in commit {1}: `git stash store {2}` brings them back.": "{0} 留在贮藏中的文件在提交 {1} 里:`git stash store {2}` 可以把它们找回来。", + "{0} The next push will need to be a force push.": "{0} 下一次推送需要强制推送。", + "{0} The {1} one stays {2} — there's nothing {3} it to fold into.": "{0} {1}的那个保持{2} — 其{3}没有可并入的内容。", + "{0} The {1} {2} stay as they were — nothing {3} them is kept to fold into.": "{0} {1} 个 {2} 保持原样 — 其{3}没有可并入的内容。", + "{0} This cannot be undone from here.": "{0} 这无法从此处撤销。", + "{0} Unstaged": "{0} 未暂存", + "{0} Use git_stage first.": "{0} 请先使用 git_stage。", + "{0} Your comments are kept.": "{0} 你的评论会保留。", + "{0} added to {1}, joined by a merge commit.": "{0} 已添加到 {1},通过一个合并提交连接。", + "{0} after {1}": "{1}后{0}", + "{0} ago": "{0}前", + "{0} all {1}": "{0}全部 {1}", + "{0} already exists and isn't empty — choose another folder. {1}": "{0} 已存在且不为空 — 请选择其他文件夹。{1}", + "{0} already has an open pull request, #{1}.": "{0} 已有打开的拉取请求 #{1}。", + "{0} already has an open pull request: #{1}.": "{0} 已有打开的拉取请求:#{1}。", + "{0} already matches {1}. Nothing to reset.": "{0} 已与 {1} 一致。无需重置。", + "{0} already merged, outside the conflict markers. ": "{0} 已在冲突标记之外合并。 ", + "{0} and move those branches": "{0}并移动这些分支", + "{0} and these commits land on {1}.": "{0},这些提交就会落在 {1} 上。", + "{0} and {1}": "{0} 和 {1}", + "{0} and {1} more": "{0} 以及另外 {1} 个", + "{0} and {1}/{2} have both moved on: pull, then create it.": "{0} 与 {1}/{2} 都已前进:请先拉取,然后创建。", + "{0} are deleted with its folder, and nothing can bring them back.": "{0} 会随其文件夹一起删除,无法恢复。", + "{0} are still conflicted. Resolve {1} before {2}.": "{0} 仍有冲突。请先解决{1},再{2}。", + "{0} as the rebase has rewritten it so far": "{0}(变基目前重写到的状态)", + "{0} audit started — every process GitStudio spawns is logged below.": "{0} 审核已开始 — GitStudio 启动的每个进程都会记录在下方。", + "{0} back {1}. The stash keeps {2}, staging and all.": "{0} 恢复 {1}。该贮藏会保留 {2},包括暂存状态。", + "{0} behind": "落后 {0}", + "{0} brings them back.": "{0} 可以把它们找回来。", + "{0} can't go into itself: pick another base.": "{0} 不能作为自己的目标:请选择另一个基点。", + "{0} cancelled — the repository is back where it was before.": "{0} 已取消 — 仓库已回到之前的状态。", + "{0} changed": "{0} 个已更改", + "{0} changed after the Apply — undoing it now would throw those edits away. Nothing was changed.": "{0} 在应用之后发生了更改 — 现在撤销会丢弃那些编辑。未做任何更改。", + "{0} changed files": "{0} 个已更改的文件", + "{0} changed outside the merge editor (in another editor, by a formatter, or on disk). ": "{0} 在合并编辑器之外被修改(在另一个编辑器中、被格式化工具修改,或直接在磁盘上)。 ", + "{0} commit": "{0} 个提交", + "{0} commits": "{0} 个提交", + "{0} commits aren't": "{0} 个提交", + "{0} commits to pull": "{0} 个提交待拉取", + "{0} commits to push": "{0} 个提交待推送", + "{0} commits will be removed from {1}: {2}.": "{0} 个提交将从 {1} 中移除:{2}。", + "{0} complete.": "{0}已完成。", + "{0} conflict markers ({1}) — staging a file with markers in it tells git ": "{0} 个冲突标记({1})— 暂存含有标记的文件会告诉 git ", + "{0} conflicted": "{0} 个冲突", + "{0} conflicted files": "{0} 个有冲突的文件", + "{0} couldn't be fetched from {1}: {2}": "无法从 {1} 获取 {0}:{2}", + "{0} couldn't be reached, so this uses {1} as it was when last fetched.": "无法访问 {0},因此这里使用上次获取时的 {1}。", + "{0} couldn't be read.": "无法读取 {0}。", + "{0} did not finish.": "{0}未完成。", + "{0} doesn't exist yet.": "{0} 尚不存在。", + "{0} done": "{0} 已完成", + "{0} during a rebase, Yours is your commit{1}, on the left. {2}": "{0} 在变基期间,“你的”是你的提交{1},位于左侧。{2}", + "{0} failed": "{0}失败", + "{0} failed — {1}": "{0} 失败 — {1}", + "{0} files": "{0} 个文件", + "{0} files ({1}{2}) are": "{0} 个文件({1}{2})是", + "{0} files are left unmerged in it, which git can't stash.": "其中有 {0} 个文件未合并,git 无法贮藏。", + "{0} files have conflicts to resolve.": "{0} 个文件有冲突需要解决。", + "{0} files selected": "已选择 {0} 个文件", + "{0} files still contain": "{0} 个文件仍包含", + "{0} files still have": "{0} 个文件仍有", + "{0} files still have conflicts": "{0} 个文件仍有冲突", + "{0} from “{1}”": "来自“{1}”的 {0}", + "{0} git can't keep a copy of them {1}, so GitStudio's Undo can put the branch back, but not those edits.": "{0} git 无法保留它们的副本{1},因此 GitStudio 的撤销可以恢复该分支,但无法找回那些编辑。", + "{0} git keeps no copy of them, so nothing can bring them back.": "{0} git 不保留它们的副本,所以任何东西都无法把它们找回来。", + "{0} go into a stash you can apply from any worktree of this repository; then its folder is deleted.": "{0} 会进入一个可从本仓库任何工作树应用的贮藏;随后其文件夹会被删除。", + "{0} goes into a stash you can apply from any worktree of this repository; then its folder is deleted.": "{0} 会进入一个可从本仓库任何工作树应用的贮藏;随后其文件夹会被删除。", + "{0} had no conflict markers left when the merge editor opened: it was already resolved, by hand ": "{0} 在合并编辑器打开时已没有冲突标记:它已被手动解决,", + "{0} has been pushed since, so Undo would have to revert it — and it can't put the rest of what \"{1}\" changed back that way. Nothing was changed.": "{0} 此后已被推送,因此撤销只能还原它 — 而那样无法把 \"{1}\" 改动的其余部分放回。未做任何更改。", + "{0} has changes since it was resolved, and bringing the conflict back would overwrite them. Nothing was changed.": "{0} 在解决之后又有更改,恢复该冲突会覆盖它们。未做任何更改。", + "{0} has changes that aren't staged. Stage or stash them first — git won't continue a rebase with unstaged changes.": "{0} 有未暂存的更改。请先暂存或贮藏它们 — git 不会带着未暂存的更改继续变基。", + "{0} has commits that PR #{1} doesn't": "{0} 有 PR #{1} 没有的提交", + "{0} has commits {1} doesn't": "{0} 上有 {1} 没有的提交", + "{0} has moved on": "{0} 已向前推进", + "{0} has moved since (it is at {1} now), and putting it back would throw that away.": "{0} 此后已移动(现在位于 {1}),放回它会把这些丢掉。", + "{0} has no GitHub remote to be pushed to.": "{0} 没有可推送到的 GitHub 远程。", + "{0} has no commits that {1} doesn't.": "{0} 没有 {1} 没有的提交。", + "{0} has no pull request #{1}.": "{0} 没有拉取请求 #{1}。", + "{0} has no text to merge here.": "{0} 在此没有可合并的文本。", + "{0} has uncommitted changes it didn't have when you were asked, so nothing was removed. Remove it again to see what it holds now.": "{0} 有了在你被询问时不存在的未提交更改,因此未移除任何内容。请再次移除它以查看它现在持有什么。", + "{0} has {1} that pull request #{2} doesn't — made here, or from before ": "{0} 有 {1},而拉取请求 #{2} 没有 — 在此处创建的,或来自之前 ", + "{0} has {1} that {2} doesn't, and {3} has {4} that {5} doesn't — ": "{0} 有 {1} 是 {2} 没有的,而 {3} 有 {4} 是 {5} 没有的 — ", + "{0} have changes that aren't staged. Stage or stash them first — git won't continue a rebase with unstaged changes.": "{0} 有未暂存的更改。请先暂存或贮藏它们 — git 不会带着未暂存的更改继续变基。", + "{0} hidden · drag header edges to resize": "已隐藏 {0} · 拖动表头边缘可调整大小", + "{0} hit conflicts. Resolve them, then continue or abort.": "{0} 遇到冲突。请解决它们,然后继续或中止。", + "{0} in Theirs": "{0} 在“他们的”中", + "{0} in Yours": "{0} 在“你的”中", + "{0} in the Result, marked so you can check {1}.": "{0} 在结果中,已标记,便于你检查 {1}。", + "{0} in this file were": "此文件中的 {0} 处更改", + "{0} incoming commits to pull": "{0} 个待拉取的提交", + "{0} into {1}": "{0} 到 {1}", + "{0} is a file on one side and a folder on the other ({1} is in the folder). ": "{0} 在一侧是文件,在另一侧是文件夹({1} 在该文件夹中)。 ", + "{0} is a submodule (a gitlink), and {1} and {2} point it at different ": "{0} 是一个子模块(gitlink),而 {1} 和 {2} 将它指向不同的 ", + "{0} is a symbolic link, so there is no line-by-line merge: {1} and ": "{0} 是符号链接,因此无法逐行合并:{1} 和 ", + "{0} is a symbolic link. Saving text here would overwrite whatever it points at, not the link — {1}.": "{0} 是一个符号链接。在这里保存文本会覆盖它指向的内容,而不是该链接 — {1}。", + "{0} is a worktree again — its .git is back.": "{0} 又变回工作树了 — 它的 .git 回来了。", + "{0} is already in progress — continue or abort it first.": "{0} 已在进行中 — 请先继续或中止它。", + "{0} is binary, so there is no line-by-line merge to make. Accept one side, or replace ": "{0} 是二进制文件,因此无法进行逐行合并。请接受一侧,或替换 ", + "{0} is checked out and already matches PR #{1}.": "{0} 已检出,并且已与 PR #{1} 一致。", + "{0} is checked out in another worktree ({1}).": "{0} 已在另一个工作树中检出({1})。", + "{0} is checked out in another worktree ({1}). Switch to it there, or check out a different branch in that worktree first.": "{0} 已在另一个工作树中检出({1})。请在那里切换到它,或先在该工作树中检出其他分支。", + "{0} is checked out in the worktree at {1}, and a branch can be checked out in only one worktree at a time. {2}": "{0} 已在位于 {1} 的工作树中检出,而一个分支一次只能在一个工作树中检出。{2}", + "{0} is deleted with its folder, and nothing can bring it back.": "{0} 会随其文件夹一起删除,无法恢复。", + "{0} is in progress on a detached HEAD, so these commits are on no branch. ": "{0} 正在分离的 HEAD 上进行,因此这些提交不属于任何分支。 ", + "{0} is installed, so {1} opens your conflicts, with the same merge editor and ": "已安装 {0},因此 {1} 会打开你的冲突,使用相同的合并编辑器和 ", + "{0} is larger than can be read in one go, so only part of it is available — and ": "{0} 太大,无法一次读取完,因此只有一部分可用 — 并且 ", + "{0} is left out and the rest carries on.": "将跳过{0},其余部分继续。", + "{0} is left out and the rest of the series carries on.": "将跳过{0},该系列的其余补丁继续。", + "{0} is left out, and that ends the series.": "{0} 被排除,补丁系列到此结束。", + "{0} is left out, and that ends the {1}.": "{0} 被排除,该 {1} 到此结束。", + "{0} is left out, and the {1} finishes without it.": "{0} 被排除,{1} 将在没有它的情况下结束。", + "{0} is new in {1} and does not exist in {2} — there ": "{0} 在 {1} 中是新增的,在 {2} 中不存在 — ", + "{0} is no longer a worktree of this repository.": "{0} 已不再是本仓库的工作树。", + "{0} is no longer conflicted — nothing was changed.": "{0} 已不再有冲突 — 未做任何更改。", + "{0} is no longer conflicted — nothing was written, so a resolution made elsewhere stays as it is.": "{0} 已不再有冲突 — 未写入任何内容,因此别处所做的解决保持不变。", + "{0} is not in an open Git repository, so it has no HEAD version.": "{0} 不在已打开的 Git 仓库中,因此没有 HEAD 版本。", + "{0} is open in another tab of this window, so it can't be removed — its folder would be deleted from under that tab. Close that tab first.": "{0} 在此窗口的另一个标签页中打开,因此无法移除 — 它的文件夹会从该标签页下被删除。请先关闭该标签页。", + "{0} is still conflicted — there is nothing to undo.": "{0} 仍有冲突 — 没有可撤销的内容。", + "{0} is still conflicted. Resolve {1} before {2}.": "{0} 仍有冲突。请先解决{1},再{2}。", + "{0} is still in progress, with {1} still conflicted. ": "{0} 仍在进行中,{1} 仍有冲突。 ", + "{0} is still in progress. Commit it — or abort it — before {1}.": "{0} 仍在进行中。请先提交或中止它,再{1}。", + "{0} is still in progress. Continue it — or abort it — before {1}.": "{0} 仍在进行中。请先继续或中止它,再{1}。", + "{0} is the main worktree — it holds the repository itself, so git never removes it.": "{0} 是主工作树 — 它承载着仓库本身,因此 git 永远不会移除它。", + "{0} is {1} behind {2} and has no commits of its own, so nothing will be lost: it will move forward to match.": "{0} 落后 {2} {1},且没有自己的提交,因此不会有任何损失:它会前移到一致。", + "{0} isn't UTF-8 text. Saving it as text would rewrite the bytes it can't represent — {1}.": "{0} 不是 UTF-8 文本。以文本保存会重写它无法表示的字节 — {1}。", + "{0} isn't among #{1}'s changed files any more.": "{0} 已不在 #{1} 的更改文件之中。", + "{0} isn't on {1} yet: it is pushed there first.": "{0} 还不在 {1} 上:会先把它推送到那里。", + "{0} keeps the edit made outside the merge editor until you Apply. Apply replaces it with the Result.": "在你应用之前,{0} 会保留在合并编辑器之外所做的编辑。应用会用结果替换它。", + "{0} left unmerged in it. Open the worktree to resolve it.": "其中有 {0} 个未合并。打开该工作树来解决它。", + "{0} left unmerged in it. Open the worktree to resolve them.": "其中有 {0} 个未合并。打开该工作树来解决它们。", + "{0} match": "{0} 个匹配", + "{0} matches": "{0} 个匹配", + "{0} more are": "还有 {0} 个", + "{0} more on GitHub.": "GitHub 上还有 {0} 个。", + "{0} more — type to narrow": "还有 {0} 项 — 输入以缩小范围", + "{0} more: {1}": "还有 {0} 个:{1}", + "{0} moved while you were being asked ({1}), so nothing was reverted. Try Undo again.": "在你被询问期间 {0} 发生了移动({1}),因此未还原任何内容。请再次尝试撤销。", + "{0} needs a clean working tree, and your ": "{0} 需要干净的工作树,而你的 ", + "{0} not on {1}": "{0} 不在 {1} 上", + "{0} not pushed to {1}.": "{0}未推送到 {1}。", + "{0} of yours on this file": "此文件上有你的 {0}", + "{0} of yours {1} pushed to it yet": "你的 {0} 个提交{1}推送到它", + "{0} of {1} ticked · untick the last for all": "已勾选 {1} 个中的 {0} 个 · 取消勾选最后一个即为全部", + "{0} on this branch only": "{0}(仅限此分支)", + "{0} on this file": "此文件上有 {0}", + "{0} on {1}": "{0}(在 {1} 上)", + "{0} on {1} not pulled yet.": "{1} 上的 {0}尚未拉取。", + "{0} on {1}/{2} yet: {3} pushed first.": "{0} 还不在 {1}/{2} 上:会先推送 {3}。", + "{0} or ": "{0} 或 ", + "{0} pending": "{0} 项待处理", + "{0} pending comments": "{0} 条未提交的评论", + "{0} point it at different targets. Accept the side whose target you want.": "{0} 将它指向不同的目标。请接受你想要的目标所在的那一侧。", + "{0} pull requests": "{0} 个拉取请求", + "{0} rate limit hit — try again in a moment.": "{0} 触发速率限制 — 请稍后重试。", + "{0} rejected the API key (HTTP {1}). Check the key in Settings ▸ AI.": "{0} 拒绝了该 API 密钥(HTTP {1})。请在“设置 ▸ AI”中检查该密钥。", + "{0} replayed onto {1} one by one, with no merge commit.": "{0} 逐个重放到 {1},不使用合并提交。", + "{0} request failed (HTTP {1}).": "{0} 请求失败(HTTP {1})。", + "{0} resolves outside the repository — nothing was changed.": "{0} 解析到仓库之外 — 未做任何更改。", + "{0} returned 404 — check the base URL and model id.": "{0} 返回 404 — 请检查基础 URL 和模型 id。", + "{0} selected files": "{0} 个选中的文件", + "{0} set on 1 commit.": "已对 1 个提交设置{0}。", + "{0} set on {1} commits.": "已对 {1} 个提交设置{0}。", + "{0} skipped. The {1} is over": "已跳过 {0}。{1}已结束", + "{0} skipped; the rest applied — the series is finished": "已跳过{0};其余补丁已应用 — 该系列已完成", + "{0} skipped; the rest applied — {1} complete": "已跳过{0};其余已应用 — {1}完成", + "{0} staged": "{0} 个已暂存", + "{0} still contains conflict markers. Staging it would mark the conflict ": "{0} 仍包含冲突标记。暂存它会将该冲突标记为 ", + "{0} still exists on one side. Accept Yours or Accept Theirs instead.": "{0} 仍然存在于一侧。请改用“接受我的”或“接受对方的”。", + "{0} still has": "{0} 仍有", + "{0} still has conflict markers staged": "{0} 仍暂存着冲突标记", + "{0} still has conflicts": "{0} 仍有冲突", + "{0} still has unresolved conflicts.": "{0} 仍有未解决的冲突。", + "{0} still have conflict markers staged": "{0} 仍暂存着冲突标记", + "{0} still have unresolved conflicts.": "{0} 仍有未解决的冲突。", + "{0} stopped — finish it, or Undo.": "{0} 已停止 — 请完成它,或撤销。", + "{0} terminals": "{0} 个终端", + "{0} the file without its staging?": "{0} 该文件但不要其暂存状态?", + "{0} the files without their staging?": "{0} 这些文件但不要它们的暂存状态?", + "{0} the stash without its staging?": "{0} 该贮藏但不要其暂存状态?", + "{0} the worktree {1}": "{0}工作树 {1}", + "{0} to commit it and go on to the next {1} ({2} queued). It stops again if one conflicts.": "{0} 以提交它并继续下一个 {1}(已排队 {2} 个)。如果其中一个发生冲突,它会再次停止。", + "{0} to finish.": "{0}即可完成。", + "{0} to pull": "{0} 个待拉取", + "{0} to push": "{0} 个待推送", + "{0} to {1}. It stops again if that one conflicts.": "{0} 到 {1}。如果那一个发生冲突,它会再次停止。", + "{0} tracks {1} — it isn't {2}, the branch of PR #{3}.": "{0} 跟踪 {1} — 它不是 {2},即 PR #{3} 的分支。", + "{0} turns off every merge method GitHub has. Merge it on GitHub.": "{0} 会关闭 GitHub 的所有合并方式。请在 GitHub 上合并。", + "{0} unpublished": "{0} 个未发布", + "{0} unstaged": "{0} 个未暂存", + "{0} untracked": "{0} 个未跟踪", + "{0} was deleted in {1} and in {2}. There is nothing to ": "{0} 在 {1} 和 {2} 中都被删除。没有可 ", + "{0} was edited in {1} and deleted in {2}. There is ": "{0} 在 {1} 中被编辑,在 {2} 中被删除。", + "{0} when a stash is applied, Yours is your stashed changes, on the left. {1}": "{0} 应用贮藏时,“你的”是你贮藏的更改,位于左侧。{1}", + "{0} which review?": "{0} 哪一条审查?", + "{0} which stash?": "{0} 哪一个贮藏?", + "{0} will also get the {1} on {2} it doesn't have yet.": "{0} 还会获得它在 {2} 上尚未拥有的 {1}。", + "{0} will be removed from {1}.": "{0} 将从 {1} 中移除。", + "{0} will be sent with this review": "{0} 将随本次审查发送", + "{0} will become one commit with the message below.": "{0} 将合并为一个提交,使用下方的提交信息。", + "{0} will become one commit.": "{0} 将合并为一个提交。", + "{0} will keep the original text.": "{0} 将保留原始文本。", + "{0} will lose {1} that {2} on {3}:\n": "{0} 将丢失 {1} —— {2}在 {3} 上:\n", + "{0} with one side in, the other to decide": "{0} 一侧已确定,另一侧待决定", + "{0} worktrees": "{0} 个工作树", + "{0} {1}": "{0} {1}", + "{0} {1} ago": "{0} {1}前", + "{0} {1} at a commit that will be replayed.": "{0} {1}一个将被重放的提交。", + "{0} {1} at a commit that will be rewritten.": "{0} {1}一个将被重写的提交。", + "{0} {1} doesn't have. The repository has no remote.": "{0} {1} 尚未拥有。此仓库没有远程。", + "{0} {1} hit a conflict while replaying a later commit. Resolve it and continue the rebase — or skip that commit, or abort to put the branch back as it was.": "{0} {1} 在重放后续提交时遇到冲突。请解决它并继续变基 — 或跳过该提交,或中止以把分支恢复原样。", + "{0} {1} of {2}": "{0} {1}/{2}", + "{0} {1} of {2} resolved": "{0} {1}/{2} 已解决", + "{0} {1} pull requests{2}": "{0} {1} 个拉取请求{2}", + "{0} {1} pull request{2}": "{0} {1} 个拉取请求{2}", + "{0} {1} staged in “{2}”, and git can only stage {3} again when nothing else is staged — your own staged changes are in the way. Nothing has changed yet.": "{0} {1} 已在“{2}”中暂存,而 git 只有在没有其他内容已暂存时才能再次暂存 {3} — 你自己已暂存的更改造成了阻碍。尚未做任何更改。", + "{0} {1} staged in “{2}”, and {3} to what HEAD has now. Nothing has changed yet.": "{0} {1} 已在“{2}”中暂存,而 {3} 与 HEAD 现在的内容相比。尚未做任何更改。", + "{0} {1} stopped and needs you — continue the rebase, or abort it to put the branch back as it was.": "{0} {1} 已停止,需要你处理 — 请继续变基,或中止以把分支恢复原样。", + "{0} {1}, change {2}": "{0} {1},更改 {2}", + "{0} {1}, {2} to decide": "{0} {1},{2} 待决定", + "{0} {1}.": "{0} {1}。", + "{0} · {1} can be merged automatically": "{0} · {1} 可以自动合并", + "{0} — click to collapse, ": "{0} — 点击折叠,", + "{0} — continue or abort it first.": "{0} — 请先继续或中止它。", + "{0} — done.": "{0} — 已完成。", + "{0} — filter the graph by it, or check it out": "{0} — 用它筛选提交图,或检出它", + "{0} — open the Conflicts view": "{0} — 打开冲突视图", + "{0} — the branch starts here. You stay on the current branch.": "{0} — 分支从此处开始。你仍留在当前分支。", + "{0} — the index is stashed whole; the working tree is left alone.": "{0} — 索引会整体贮藏;工作树保持不变。", + "{0} — the tag stays local until you push it.": "{0} — 在你推送之前,该标签只保留在本地。", + "{0} — update it to the pull request's latest": "{0} — 将其更新到拉取请求的最新版本", + "{0} — {1} by {2}, {3}. Show its files": "{0} — 由 {2} 于 {3} 提交的 {1}。显示其文件", + "{0}'s own commits stay only in the reflog.": "{0} 自己的提交只保留在 reflog 中。", + "{0}+Enter creates it": "{0}+Enter 创建它", + "{0}, and PR #{1}'s last commit couldn't be fetched: {2}": "{0},并且无法获取 PR #{1} 的最后一个提交:{2}", + "{0}, but {1} isn't: {2}": "{0},但 {1} 不是:{2}", + "{0}, plus the commits of {1} already rebased onto it": "{0},再加上已变基到其上的 {1} 的提交", + "{0}, so it was checked out as {1} at its last commit — a push from there can't reach the pull request. {2}": "{0},因此以 {1} 在其最后一个提交处检出 — 从那里推送无法到达该拉取请求。{2}", + "{0}, then create a branch to push them.": "{0},然后创建一个分支来推送它们。", + "{0}, with {1} left to resolve. Open the worktree to continue or abort it.": "{0},还有 {1} 待解决。打开该工作树以继续或中止它。", + "{0}, {1}": "{0},{1}", + "{0}, {1} and 1 other file": "{0}、{1} 以及另外 1 个文件", + "{0}, {1} and {2} other files": "{0}、{1} 以及另外 {2} 个文件", + "{0}, {1}{2}, {3} added, {4} removed": "{0},{1}{2},新增 {3} 行,删除 {4} 行", + "{0}, {1}{2}{3}. Open changes": "{0},{1}{2}{3}。打开更改", + "{0}.": "{0}。", + "{0}. Finish or abort it first, then undo.": "{0}。请先完成或中止它,然后撤销。", + "{0}. Open the Conflicts view to continue.": "{0}。打开冲突视图以继续。", + "{0}. Open the worktree to continue or abort it.": "{0}。打开该工作树以继续或中止它。", + "{0}. Then: {1}": "{0}。然后:{1}", + "{0}: Conflicts": "{0}:冲突", + "{0}: {1} will keep the original text, {2} {3}.": "{0}:{1} 将保留原始文本,{2} {3}。", + "{0}: {1}.": "{0}:{1}。", + "{0}: {1}{2}. Open its diff": "{0}:{1}{2}。打开其差异", + "{0}h": "{0} 小时", + "{0}h {1}m": "{0} 小时 {1} 分", + "{0}m": "{0} 分", + "{0}m {1}s": "{0} 分 {1} 秒", + "{0}s": "{0} 秒", + "{0}{1} has no version of this file — accepting ": "{0}{1} 没有此文件的任何版本 — 接受 ", + "{0}{1} has no version of this file — accepting it deletes the file": "{0}{1} 没有此文件的任何版本 — 接受它会删除该文件", + "{0}{1} is installed too. It also opens your conflicts, and it ": "也安装了 {0}{1}。它也会打开你的冲突,并且它 ", + "{0}{1} — {2}. Open its diff": "{0}{1} — {2}。打开其差异", + "{0}{1}. Opens the branch menu.": "{0}{1}。打开分支菜单。", + "· also on {0}": "· 也在 {0} 上", + "· start of history ·": "· 历史起点 ·", + "“{0}” has staged changes that no longer apply to what HEAD has now. Nothing has changed yet.": "“{0}”有已暂存的更改,但它们已不再适用于 HEAD 现在的内容。尚未做任何更改。", + "“{0}” has staged changes, and git can only stage them again when nothing else is staged — your own staged changes are in the way. Nothing has changed yet.": "“{0}”有已暂存的更改,而 git 只有在没有其他内容已暂存时才能再次暂存它们 — 你自己已暂存的更改造成了阻碍。尚未做任何更改。", + "“{0}” is not a branch name git can use.": "“{0}”不是 git 可用的分支名。", + "“{0}” is not a stash git can read.": "“{0}”不是 git 可读的贮藏。", + "“{0}” is not a stash.": "“{0}”不是贮藏。", + "✓ deleted": "✓ 已删除", + "✓ resolved": "✓ 已解决" +} diff --git a/apps/extension/package.json b/apps/extension/package.json index 442e33c3..47e9b2ca 100644 --- a/apps/extension/package.json +++ b/apps/extension/package.json @@ -1,7 +1,7 @@ { "name": "gitstudio", - "displayName": "GitStudio \u2014 JetBrains-style Git Graph, Blame & Merge", - "description": "Free, open-source Git GUI & commit graph for VS Code and Cursor. Git Studio brings a JetBrains-style Git workflow into the editor \u2014 inline blame, file history, hunk & line staging, 3-pane merge, interactive rebase with universal Undo, stash/shelf, worktrees, and in-editor GitHub PRs. A free alternative to GitLens, GitKraken & Sourcetree.", + "displayName": "%displayName%", + "description": "%description%", "version": "1.17.0", "publisher": "gitstudio", "license": "Apache-2.0", @@ -96,14 +96,14 @@ "activitybar": [ { "id": "gitstudio", - "title": "GitStudio", + "title": "%viewContainer.gitstudio.title%", "icon": "media/activitybar.svg" } ], "panel": [ { "id": "gitstudioPanel", - "title": "Commit Graph", + "title": "%viewContainer.gitstudioPanel.title%", "icon": "media/activitybar.svg" } ] @@ -112,28 +112,28 @@ "gitstudio": [ { "id": "gitstudio.commit", - "name": "Changes", + "name": "%view.gitstudio.commit.name%", "type": "webview", "initialSize": 7, "visibility": "visible" }, { "id": "gitstudio.commits", - "name": "Commits", + "name": "%view.gitstudio.commits.name%", "type": "webview", "initialSize": 3, "visibility": "visible" }, { "id": "gitstudio.worktrees", - "name": "Worktrees", + "name": "%view.gitstudio.worktrees.name%", "type": "webview", "initialSize": 1, "visibility": "collapsed" }, { "id": "gitstudio.pullRequests", - "name": "Pull Requests", + "name": "%view.gitstudio.pullRequests.name%", "type": "webview", "initialSize": 1, "visibility": "collapsed" @@ -142,7 +142,7 @@ "gitstudioPanel": [ { "id": "gitstudio.commitPanel", - "name": "Commit Graph", + "name": "%view.gitstudio.commitPanel.name%", "type": "webview", "contextualTitle": "GitStudio Commit Graph" } @@ -151,7 +151,7 @@ "customEditors": [ { "viewType": "gitstudio.mergeEditor", - "displayName": "GitStudio 3-Pane Merge", + "displayName": "%customEditor.gitstudio.mergeEditor.displayName%", "selector": [ { "filenamePattern": "*" @@ -161,7 +161,7 @@ }, { "viewType": "gitstudio.rebaseTodoEditor", - "displayName": "GitStudio Interactive Rebase", + "displayName": "%customEditor.gitstudio.rebaseTodoEditor.displayName%", "selector": [ { "filenamePattern": "**/git-rebase-todo" @@ -173,792 +173,792 @@ "commands": [ { "command": "gitstudio.debug.showProcessAudit", - "title": "Show Process Audit", + "title": "%command.gitstudio.debug.showProcessAudit.title%", "category": "GitStudio" }, { "command": "gitstudio.showWelcome", - "title": "Welcome", + "title": "%command.gitstudio.showWelcome.title%", "category": "GitStudio", "icon": "$(home)" }, { "command": "gitstudio.openWalkthrough", - "title": "Get Started", + "title": "%command.gitstudio.openWalkthrough.title%", "category": "GitStudio", "icon": "$(rocket)" }, { "command": "gitstudio.support", - "title": "Support GitStudio…", + "title": "%command.gitstudio.support.title%", "category": "GitStudio", "icon": "$(heart)" }, { "command": "gitstudio.refreshCommits", - "title": "Refresh Commits", + "title": "%command.gitstudio.refreshCommits.title%", "category": "GitStudio", "icon": "$(refresh)" }, { "command": "gitstudio.refreshBranches", - "title": "Refresh Branches", + "title": "%command.gitstudio.refreshBranches.title%", "category": "GitStudio", "icon": "$(refresh)" }, { "command": "gitstudio.copyCommitSha", - "title": "Copy Commit SHA", + "title": "%command.gitstudio.copyCommitSha.title%", "category": "GitStudio", "icon": "$(copy)" }, { "command": "gitstudio.toggleFileBlame", - "title": "Annotate with Git Blame", + "title": "%command.gitstudio.toggleFileBlame.title%", "category": "GitStudio", "icon": "$(eye)", "toggled": "gitstudio.blameAnnotated" }, { "command": "gitstudio.blame.showLineActions", - "title": "Line Blame Actions", + "title": "%command.gitstudio.blame.showLineActions.title%", "category": "GitStudio", "icon": "$(eye)" }, { "command": "gitstudio.showCommitGraph", - "title": "Show Commit Graph", + "title": "%command.gitstudio.showCommitGraph.title%", "category": "GitStudio", "icon": "$(git-commit)" }, { "command": "gitstudio.showLineHistory", - "title": "Show Line History", + "title": "%command.gitstudio.showLineHistory.title%", "category": "GitStudio", "icon": "$(history)" }, { "command": "gitstudio.openChanges", - "title": "Open Changes (vs HEAD)", + "title": "%command.gitstudio.openChanges.title%", "category": "GitStudio", "icon": "$(git-compare)" }, { "command": "gitstudio.openFileAtRevision", - "title": "Open File at Revision\u2026", + "title": "%command.gitstudio.openFileAtRevision.title%", "category": "GitStudio", "icon": "$(history)" }, { "command": "gitstudio.revisionNavigateBack", - "title": "Revision: Step to Older", + "title": "%command.gitstudio.revisionNavigateBack.title%", "category": "GitStudio", "icon": "$(arrow-left)" }, { "command": "gitstudio.revisionNavigateForward", - "title": "Revision: Step to Newer", + "title": "%command.gitstudio.revisionNavigateForward.title%", "category": "GitStudio", "icon": "$(arrow-right)" }, { "command": "gitstudio.showReflog", - "title": "Show Reflog (Time Machine)", + "title": "%command.gitstudio.showReflog.title%", "category": "GitStudio", "icon": "$(history)" }, { "command": "gitstudio.switchRepository", - "title": "Switch Repository\u2026", + "title": "%command.gitstudio.switchRepository.title%", "category": "GitStudio", "icon": "$(repo)" }, { "command": "gitstudio.branches.open", - "title": "Branches\u2026", + "title": "%command.gitstudio.branches.open.title%", "category": "GitStudio", "icon": "$(git-branch)" }, { "command": "gitstudio.resolveInMergeEditor", - "title": "Resolve in Merge Editor", + "title": "%command.gitstudio.resolveInMergeEditor.title%", "category": "GitStudio", "icon": "$(git-merge)" }, { "command": "gitstudio.compare", - "title": "Compare File\u2026", + "title": "%command.gitstudio.compare.title%", "category": "GitStudio", "icon": "$(git-compare)" }, { "command": "gitstudio.showConflicts", - "title": "Resolve Conflicts\u2026", + "title": "%command.gitstudio.showConflicts.title%", "category": "GitStudio", "icon": "$(warning)" }, { "command": "gitstudio.openDiff", - "title": "Open in Embedded Diff", + "title": "%command.gitstudio.openDiff.title%", "category": "GitStudio", "icon": "$(diff)" }, { "command": "gitstudio.merge.openDemo", - "title": "Open Sample Merge", + "title": "%command.gitstudio.merge.openDemo.title%", "category": "GitStudio" }, { "command": "gitstudio.merge.openDemoDiff", - "title": "Open Sample Diff", + "title": "%command.gitstudio.merge.openDemoDiff.title%", "category": "GitStudio" }, { "command": "gitstudio.operation.continue", - "title": "Continue Operation", + "title": "%command.gitstudio.operation.continue.title%", "category": "GitStudio", "icon": "$(debug-continue)" }, { "command": "gitstudio.operation.skip", - "title": "Skip This Commit", + "title": "%command.gitstudio.operation.skip.title%", "category": "GitStudio", "icon": "$(debug-step-over)" }, { "command": "gitstudio.operation.abort", - "title": "Abort Operation", + "title": "%command.gitstudio.operation.abort.title%", "category": "GitStudio", "icon": "$(stop)" }, { "command": "gitstudio.merge.restoreBuiltInMergeEditor", - "title": "Restore VS Code's Merge Editor", + "title": "%command.gitstudio.merge.restoreBuiltInMergeEditor.title%", "category": "GitStudio", "icon": "$(discard)" }, { "command": "gitstudio.stageSelectedLines", - "title": "Stage Selected Lines", + "title": "%command.gitstudio.stageSelectedLines.title%", "category": "GitStudio", "icon": "$(add)" }, { "command": "gitstudio.unstageSelectedLines", - "title": "Unstage Selected Lines", + "title": "%command.gitstudio.unstageSelectedLines.title%", "category": "GitStudio", "icon": "$(remove)" }, { "command": "gitstudio.stageHunk", - "title": "Stage Hunk", + "title": "%command.gitstudio.stageHunk.title%", "category": "GitStudio", "icon": "$(add)" }, { "command": "gitstudio.unstageHunk", - "title": "Unstage Hunk", + "title": "%command.gitstudio.unstageHunk.title%", "category": "GitStudio", "icon": "$(remove)" }, { "command": "gitstudio.startInteractiveRebase", - "title": "Start Interactive Rebase\u2026", + "title": "%command.gitstudio.startInteractiveRebase.title%", "category": "GitStudio", "icon": "$(git-merge)" }, { "command": "gitstudio.abortRebase", - "title": "Abort Rebase", + "title": "%command.gitstudio.abortRebase.title%", "category": "GitStudio", "icon": "$(stop)" }, { "command": "gitstudio.undo", - "title": "Undo Last Git Operation", + "title": "%command.gitstudio.undo.title%", "category": "GitStudio", "icon": "$(discard)" }, { "command": "gitstudio.showUndoHistory", - "title": "Show Undo History", + "title": "%command.gitstudio.showUndoHistory.title%", "category": "GitStudio", "icon": "$(history)" }, { "command": "gitstudio.resetToCommit", - "title": "Reset Current Branch to Here\u2026", + "title": "%command.gitstudio.resetToCommit.title%", "category": "GitStudio", "icon": "$(discard)" }, { "command": "gitstudio.stashes.refresh", - "title": "Refresh Stashes", + "title": "%command.gitstudio.stashes.refresh.title%", "category": "GitStudio", "icon": "$(refresh)" }, { "command": "gitstudio.stash.save", - "title": "Stash Changes\u2026", + "title": "%command.gitstudio.stash.save.title%", "category": "GitStudio", "icon": "$(add)" }, { "command": "gitstudio.stash.apply", - "title": "Apply Stash\u2026", + "title": "%command.gitstudio.stash.apply.title%", "category": "GitStudio", "icon": "$(git-stash-apply)" }, { "command": "gitstudio.stash.pop", - "title": "Pop Stash\u2026", + "title": "%command.gitstudio.stash.pop.title%", "category": "GitStudio", "icon": "$(git-stash-pop)" }, { "command": "gitstudio.stash.drop", - "title": "Drop Stash\u2026", + "title": "%command.gitstudio.stash.drop.title%", "category": "GitStudio", "icon": "$(trash)" }, { "command": "gitstudio.stash.branch", - "title": "Create Branch from Stash\u2026", + "title": "%command.gitstudio.stash.branch.title%", "category": "GitStudio", "icon": "$(git-branch)" }, { "command": "gitstudio.worktrees.refresh", - "title": "Refresh Worktrees", + "title": "%command.gitstudio.worktrees.refresh.title%", "category": "GitStudio", "icon": "$(refresh)" }, { "command": "gitstudio.worktree.open", - "title": "Open Worktree\u2026", + "title": "%command.gitstudio.worktree.open.title%", "category": "GitStudio", "icon": "$(empty-window)" }, { "command": "gitstudio.worktree.openInNewWindow", - "title": "Open Worktree in New Window\u2026", + "title": "%command.gitstudio.worktree.openInNewWindow.title%", "category": "GitStudio", "icon": "$(empty-window)" }, { "command": "gitstudio.worktree.openHere", - "title": "Open Worktree in This Window\u2026", + "title": "%command.gitstudio.worktree.openHere.title%", "category": "GitStudio", "icon": "$(folder-opened)" }, { "command": "gitstudio.worktree.add", - "title": "New Worktree\u2026", + "title": "%command.gitstudio.worktree.add.title%", "category": "GitStudio", "icon": "$(add)" }, { "command": "gitstudio.worktree.remove", - "title": "Remove Worktree\u2026", + "title": "%command.gitstudio.worktree.remove.title%", "category": "GitStudio", "icon": "$(trash)" }, { "command": "gitstudio.worktree.forget", - "title": "Forget Worktree\u2026", + "title": "%command.gitstudio.worktree.forget.title%", "category": "GitStudio", "icon": "$(close)" }, { "command": "gitstudio.worktree.lock", - "title": "Lock Worktree\u2026", + "title": "%command.gitstudio.worktree.lock.title%", "category": "GitStudio", "icon": "$(lock)" }, { "command": "gitstudio.worktree.unlock", - "title": "Unlock Worktree\u2026", + "title": "%command.gitstudio.worktree.unlock.title%", "category": "GitStudio", "icon": "$(unlock)" }, { "command": "gitstudio.worktree.prune", - "title": "Prune Missing Worktrees\u2026", + "title": "%command.gitstudio.worktree.prune.title%", "category": "GitStudio", "icon": "$(trash)" }, { "command": "gitstudio.compareRefs", - "title": "Compare Branches/Tags\u2026", + "title": "%command.gitstudio.compareRefs.title%", "category": "GitStudio", "icon": "$(git-compare)" }, { "command": "gitstudio.branch.checkout", - "title": "Checkout", + "title": "%command.gitstudio.branch.checkout.title%", "category": "GitStudio", "icon": "$(check)" }, { "command": "gitstudio.branch.merge", - "title": "Merge into Current", + "title": "%command.gitstudio.branch.merge.title%", "category": "GitStudio", "icon": "$(git-merge)" }, { "command": "gitstudio.branch.rebase", - "title": "Rebase Current onto This", + "title": "%command.gitstudio.branch.rebase.title%", "category": "GitStudio", "icon": "$(git-merge)" }, { "command": "gitstudio.branch.rename", - "title": "Rename Branch\u2026", + "title": "%command.gitstudio.branch.rename.title%", "category": "GitStudio", "icon": "$(edit)" }, { "command": "gitstudio.branch.delete", - "title": "Delete Branch", + "title": "%command.gitstudio.branch.delete.title%", "category": "GitStudio", "icon": "$(trash)" }, { "command": "gitstudio.branch.push", - "title": "Push / Publish Branch", + "title": "%command.gitstudio.branch.push.title%", "category": "GitStudio", "icon": "$(arrow-up)" }, { "command": "gitstudio.branch.setUpstream", - "title": "Set Upstream\u2026", + "title": "%command.gitstudio.branch.setUpstream.title%", "category": "GitStudio", "icon": "$(cloud)" }, { "command": "gitstudio.branch.resetToUpstream", - "title": "Reset Branch to Its Upstream\u2026", + "title": "%command.gitstudio.branch.resetToUpstream.title%", "category": "GitStudio", "icon": "$(discard)" }, { "command": "gitstudio.branch.new", - "title": "New Branch from Here\u2026", + "title": "%command.gitstudio.branch.new.title%", "category": "GitStudio", "icon": "$(add)" }, { "command": "gitstudio.branch.createWorktree", - "title": "New Worktree from This Branch\u2026", + "title": "%command.gitstudio.branch.createWorktree.title%", "category": "GitStudio", "icon": "$(repo-clone)" }, { "command": "gitstudio.branch.compare", - "title": "Compare with Current", + "title": "%command.gitstudio.branch.compare.title%", "category": "GitStudio", "icon": "$(git-compare)" }, { "command": "gitstudio.remoteBranch.checkout", - "title": "Checkout (Create Local Tracking)\u2026", + "title": "%command.gitstudio.remoteBranch.checkout.title%", "category": "GitStudio", "icon": "$(check)" }, { "command": "gitstudio.remoteBranch.delete", - "title": "Delete Remote Branch", + "title": "%command.gitstudio.remoteBranch.delete.title%", "category": "GitStudio", "icon": "$(trash)" }, { "command": "gitstudio.tag.checkout", - "title": "Checkout Tag", + "title": "%command.gitstudio.tag.checkout.title%", "category": "GitStudio", "icon": "$(check)" }, { "command": "gitstudio.tag.delete", - "title": "Delete Tag", + "title": "%command.gitstudio.tag.delete.title%", "category": "GitStudio", "icon": "$(trash)" }, { "command": "gitstudio.tag.push", - "title": "Push Tag\u2026", + "title": "%command.gitstudio.tag.push.title%", "category": "GitStudio", "icon": "$(arrow-up)" }, { "command": "gitstudio.fetch", - "title": "Fetch", + "title": "%command.gitstudio.fetch.title%", "category": "GitStudio", "icon": "$(sync)" }, { "command": "gitstudio.addRemote", - "title": "Add Remote\u2026", + "title": "%command.gitstudio.addRemote.title%", "category": "GitStudio", "icon": "$(add)" }, { "command": "gitstudio.manageRemotes", - "title": "Manage Remotes\u2026", + "title": "%command.gitstudio.manageRemotes.title%", "category": "GitStudio", "icon": "$(cloud)" }, { "command": "gitstudio.ai.setApiKey", - "title": "Set Anthropic API Key\u2026", + "title": "%command.gitstudio.ai.setApiKey.title%", "category": "GitStudio", "icon": "$(key)" }, { "command": "gitstudio.ai.clearApiKey", - "title": "Clear Anthropic API Key", + "title": "%command.gitstudio.ai.clearApiKey.title%", "category": "GitStudio", "icon": "$(trash)" }, { "command": "gitstudio.ai.setOpenAIKey", - "title": "Set OpenAI API Key\u2026", + "title": "%command.gitstudio.ai.setOpenAIKey.title%", "category": "GitStudio", "icon": "$(key)" }, { "command": "gitstudio.ai.clearOpenAIKey", - "title": "Clear OpenAI API Key", + "title": "%command.gitstudio.ai.clearOpenAIKey.title%", "category": "GitStudio", "icon": "$(trash)" }, { "command": "gitstudio.ai.selectModel", - "title": "Select AI Model\u2026", + "title": "%command.gitstudio.ai.selectModel.title%", "category": "GitStudio", "icon": "$(sparkle)" }, { "command": "gitstudio.ai.generateCommitMessage", - "title": "Generate Commit Message (AI)", + "title": "%command.gitstudio.ai.generateCommitMessage.title%", "category": "GitStudio", "icon": "$(sparkle)" }, { "command": "gitstudio.ai.explainDiff", - "title": "Explain Diff (AI)", + "title": "%command.gitstudio.ai.explainDiff.title%", "category": "GitStudio", "icon": "$(sparkle)" }, { "command": "gitstudio.ai.summarizeChanges", - "title": "Summarize Changes (AI)", + "title": "%command.gitstudio.ai.summarizeChanges.title%", "category": "GitStudio", "icon": "$(sparkle)" }, { "command": "gitstudio.ai.reviewChanges", - "title": "Review Changes (AI)", + "title": "%command.gitstudio.ai.reviewChanges.title%", "category": "GitStudio", "icon": "$(sparkle)" }, { "command": "gitstudio.ai.connect", - "title": "Connect AI Provider", + "title": "%command.gitstudio.ai.connect.title%", "category": "GitStudio", "icon": "$(plug)" }, { "command": "gitstudio.ai.disable", - "title": "Disable AI Features", + "title": "%command.gitstudio.ai.disable.title%", "category": "GitStudio" }, { "command": "gitstudio.pr.create", - "title": "New Pull Request", + "title": "%command.gitstudio.pr.create.title%", "category": "GitStudio", "icon": "$(git-pull-request)" }, { "command": "gitstudio.pr.refresh", - "title": "Refresh Pull Requests", + "title": "%command.gitstudio.pr.refresh.title%", "category": "GitStudio", "icon": "$(refresh)" }, { "command": "gitstudio.pr.signIn", - "title": "Sign in to GitHub", + "title": "%command.gitstudio.pr.signIn.title%", "category": "GitStudio", "icon": "$(github)" }, { "command": "gitstudio.pr.openDescription", - "title": "Open Pull Request", + "title": "%command.gitstudio.pr.openDescription.title%", "category": "GitStudio", "icon": "$(git-pull-request)" }, { "command": "gitstudio.pr.checkout", - "title": "Checkout Pull Request", + "title": "%command.gitstudio.pr.checkout.title%", "category": "GitStudio", "icon": "$(git-branch)" }, { "command": "gitstudio.pr.startReview", - "title": "Review Pull Request", + "title": "%command.gitstudio.pr.startReview.title%", "category": "GitStudio", "icon": "$(comment-discussion)" }, { "command": "gitstudio.pr.submitReview", - "title": "Submit Review", + "title": "%command.gitstudio.pr.submitReview.title%", "category": "GitStudio", "icon": "$(check-all)" }, { "command": "gitstudio.pr.cancelReview", - "title": "Discard Pending Review", + "title": "%command.gitstudio.pr.cancelReview.title%", "category": "GitStudio", "icon": "$(trash)" }, { "command": "gitstudio.pr.replyThread", - "title": "Reply", + "title": "%command.gitstudio.pr.replyThread.title%", "category": "GitStudio", "icon": "$(reply)" }, { "command": "gitstudio.pr.resolveThread", - "title": "Resolve Conversation", + "title": "%command.gitstudio.pr.resolveThread.title%", "category": "GitStudio", "icon": "$(check)" }, { "command": "gitstudio.pr.unresolveThread", - "title": "Unresolve Conversation", + "title": "%command.gitstudio.pr.unresolveThread.title%", "category": "GitStudio", "icon": "$(issue-reopened)" }, { "command": "gitstudio.pr.addReviewComment", - "title": "Add to Review", + "title": "%command.gitstudio.pr.addReviewComment.title%", "category": "GitStudio", "icon": "$(add)" }, { "command": "gitstudio.pr.addSingleComment", - "title": "Add Single Comment", + "title": "%command.gitstudio.pr.addSingleComment.title%", "category": "GitStudio", "icon": "$(comment)" }, { "command": "gitstudio.pr.deleteReviewComment", - "title": "Delete Comment", + "title": "%command.gitstudio.pr.deleteReviewComment.title%", "category": "GitStudio", "icon": "$(trash)" }, { "command": "gitstudio.pr.merge", - "title": "Merge Pull Request…", + "title": "%command.gitstudio.pr.merge.title%", "category": "GitStudio", "icon": "$(git-merge)" }, { "command": "gitstudio.pr.openOnGitHub", - "title": "Open on GitHub", + "title": "%command.gitstudio.pr.openOnGitHub.title%", "category": "GitStudio", "icon": "$(link-external)" }, { "command": "gitstudio.pr.copyUrl", - "title": "Copy Pull Request Link", + "title": "%command.gitstudio.pr.copyUrl.title%", "category": "GitStudio", "icon": "$(copy)" }, { "command": "gitstudio.blame.field.revision.on", - "title": "\u2713 Revision", + "title": "%command.gitstudio.blame.field.revision.on.title%", "category": "GitStudio Blame" }, { "command": "gitstudio.blame.field.revision.off", - "title": "Revision", + "title": "%command.gitstudio.blame.field.revision.off.title%", "category": "GitStudio Blame" }, { "command": "gitstudio.blame.field.date.on", - "title": "\u2713 Date", + "title": "%command.gitstudio.blame.field.date.on.title%", "category": "GitStudio Blame" }, { "command": "gitstudio.blame.field.date.off", - "title": "Date", + "title": "%command.gitstudio.blame.field.date.off.title%", "category": "GitStudio Blame" }, { "command": "gitstudio.blame.field.author.on", - "title": "\u2713 Author", + "title": "%command.gitstudio.blame.field.author.on.title%", "category": "GitStudio Blame" }, { "command": "gitstudio.blame.field.author.off", - "title": "Author", + "title": "%command.gitstudio.blame.field.author.off.title%", "category": "GitStudio Blame" }, { "command": "gitstudio.blame.field.commitNumber.on", - "title": "\u2713 Commit number", + "title": "%command.gitstudio.blame.field.commitNumber.on.title%", "category": "GitStudio Blame" }, { "command": "gitstudio.blame.field.commitNumber.off", - "title": "Commit number", + "title": "%command.gitstudio.blame.field.commitNumber.off.title%", "category": "GitStudio Blame" }, { "command": "gitstudio.blame.colors.author.on", - "title": "\u2713 Author", + "title": "%command.gitstudio.blame.colors.author.on.title%", "category": "GitStudio Blame" }, { "command": "gitstudio.blame.colors.author.off", - "title": "Author", + "title": "%command.gitstudio.blame.colors.author.off.title%", "category": "GitStudio Blame" }, { "command": "gitstudio.blame.colors.order.on", - "title": "\u2713 Order", + "title": "%command.gitstudio.blame.colors.order.on.title%", "category": "GitStudio Blame" }, { "command": "gitstudio.blame.colors.order.off", - "title": "Order", + "title": "%command.gitstudio.blame.colors.order.off.title%", "category": "GitStudio Blame" }, { "command": "gitstudio.blame.colors.hide.on", - "title": "\u2713 Hide", + "title": "%command.gitstudio.blame.colors.hide.on.title%", "category": "GitStudio Blame" }, { "command": "gitstudio.blame.colors.hide.off", - "title": "Hide", + "title": "%command.gitstudio.blame.colors.hide.off.title%", "category": "GitStudio Blame" }, { "command": "gitstudio.blame.names.initials.on", - "title": "\u2713 Initials", + "title": "%command.gitstudio.blame.names.initials.on.title%", "category": "GitStudio Blame" }, { "command": "gitstudio.blame.names.initials.off", - "title": "Initials", + "title": "%command.gitstudio.blame.names.initials.off.title%", "category": "GitStudio Blame" }, { "command": "gitstudio.blame.names.lastName.on", - "title": "\u2713 Last Name", + "title": "%command.gitstudio.blame.names.lastName.on.title%", "category": "GitStudio Blame" }, { "command": "gitstudio.blame.names.lastName.off", - "title": "Last Name", + "title": "%command.gitstudio.blame.names.lastName.off.title%", "category": "GitStudio Blame" }, { "command": "gitstudio.blame.names.firstName.on", - "title": "\u2713 First Name", + "title": "%command.gitstudio.blame.names.firstName.on.title%", "category": "GitStudio Blame" }, { "command": "gitstudio.blame.names.firstName.off", - "title": "First Name", + "title": "%command.gitstudio.blame.names.firstName.off.title%", "category": "GitStudio Blame" }, { "command": "gitstudio.blame.names.fullName.on", - "title": "\u2713 Full Name", + "title": "%command.gitstudio.blame.names.fullName.on.title%", "category": "GitStudio Blame" }, { "command": "gitstudio.blame.names.fullName.off", - "title": "Full Name", + "title": "%command.gitstudio.blame.names.fullName.off.title%", "category": "GitStudio Blame" }, { "command": "gitstudio.blame.names.email.on", - "title": "\u2713 Email", + "title": "%command.gitstudio.blame.names.email.on.title%", "category": "GitStudio Blame" }, { "command": "gitstudio.blame.names.email.off", - "title": "Email", + "title": "%command.gitstudio.blame.names.email.off.title%", "category": "GitStudio Blame" }, { "command": "gitstudio.blame.hover.on", - "title": "\u2713 Show Diff On Hover", + "title": "%command.gitstudio.blame.hover.on.title%", "category": "GitStudio Blame" }, { "command": "gitstudio.blame.hover.off", - "title": "Show Diff On Hover", + "title": "%command.gitstudio.blame.hover.off.title%", "category": "GitStudio Blame" }, { "command": "gitstudio.revealCommitInGraph", - "title": "Show Commit in Graph", + "title": "%command.gitstudio.revealCommitInGraph.title%", "category": "GitStudio" }, { "command": "gitstudio.blame.copyRevision", - "title": "Copy Revision Number", + "title": "%command.gitstudio.blame.copyRevision.title%", "category": "GitStudio Blame" }, { "command": "gitstudio.blame.showDiff", - "title": "Show Diff", + "title": "%command.gitstudio.blame.showDiff.title%", "category": "GitStudio Blame" }, { "command": "gitstudio.blame.showCommit", - "title": "Show Commit", + "title": "%command.gitstudio.blame.showCommit.title%", "category": "GitStudio Blame" }, { "command": "gitstudio.blame.openPreviousRevision", - "title": "Open Previous Revision", + "title": "%command.gitstudio.blame.openPreviousRevision.title%", "category": "GitStudio Blame" }, { "command": "gitstudio.blame.viewInBrowser", - "title": "View in Browser", + "title": "%command.gitstudio.blame.viewInBrowser.title%", "category": "GitStudio Blame" }, { "command": "gitstudio.blame.closeAnnotations", - "title": "Close Annotations", + "title": "%command.gitstudio.blame.closeAnnotations.title%", "category": "GitStudio Blame" }, { "command": "gitstudio.showCommitPanel", - "title": "Show Commit Graph", + "title": "%command.gitstudio.showCommitPanel.title%", "category": "GitStudio", "icon": "$(git-commit)" }, { "command": "gitstudio.stageWithTicks", - "title": "Stage Changes with Ticks", + "title": "%command.gitstudio.stageWithTicks.title%", "category": "GitStudio", "icon": "$(checklist)" }, { "command": "gitstudio.toggleStageAtLine", - "title": "Stage or Unstage the Change at This Line", + "title": "%command.gitstudio.toggleStageAtLine.title%", "category": "GitStudio" }, { "command": "gitstudio.openTerminal", - "title": "Open Terminal at Repository Root", + "title": "%command.gitstudio.openTerminal.title%", "category": "GitStudio", "icon": "$(terminal)" } @@ -1015,25 +1015,25 @@ "configuration": [ { "id": "gitstudio.general", - "title": "General", + "title": "%config.gitstudio.general.title%", "order": 1, "properties": { "gitstudio.statusBar.showGraph": { "type": "boolean", "default": true, - "description": "Show a status-bar button that opens the Commit Graph.", + "description": "%config.gitstudio.statusBar.showGraph.description%", "order": 1 }, "gitstudio.statusBar.showTerminal": { "type": "boolean", "default": true, - "description": "Show a status-bar button that opens a terminal already in the active repository's root \u2014 which is not necessarily the workspace root.", + "description": "%config.gitstudio.statusBar.showTerminal.description%", "order": 2 }, "gitstudio.worktrees.prefixWithProjectName": { "type": "boolean", "default": false, - "description": "No longer used: New Worktree now suggests the folder '-' beside the main worktree, and you can edit it before it is created.", + "description": "%config.gitstudio.worktrees.prefixWithProjectName.description%", "markdownDeprecationMessage": "No longer used: **New Worktree** now suggests the folder `-` beside the main worktree, and you can edit it before it is created.", "order": 3 }, @@ -1045,25 +1045,25 @@ "rebase" ], "enumDescriptions": [ - "Create a merge commit.", - "Squash the PR's commits into one and merge.", - "Rebase the PR's commits onto the base and merge." + "%config.gitstudio.pr.defaultMergeMethod.enumDescriptions.0%", + "%config.gitstudio.pr.defaultMergeMethod.enumDescriptions.1%", + "%config.gitstudio.pr.defaultMergeMethod.enumDescriptions.2%" ], "default": "squash", - "description": "Default method offered first when merging a pull request.", + "description": "%config.gitstudio.pr.defaultMergeMethod.description%", "order": 4 }, "gitstudio.avatars.gravatar": { "type": "boolean", "default": true, - "markdownDescription": "Show commit authors' pictures in the Commit Graph, the Commits view and commit details. To find one, GitStudio sends an MD5 hash of each author's email address to Gravatar (`www.gravatar.com`, run by Automattic); for a GitHub noreply address (`…@users.noreply.github.com`) it asks GitHub (`avatars.githubusercontent.com`) for that account's picture instead. Turn this off to show every author as coloured initials and send neither request. While you are signed in to GitHub, the pictures GitHub itself returns (on pull requests, and for the authors of a GitHub repository's recent commits) still show. See [PRIVACY.md](https://github.com/GitStudioHQ/gitstudio/blob/main/apps/extension/PRIVACY.md).", + "markdownDescription": "%config.gitstudio.avatars.gravatar.markdownDescription%", "order": 5 } } }, { "id": "gitstudio.changes", - "title": "Changes & Staging", + "title": "%config.gitstudio.changes.title%", "order": 2, "properties": { "gitstudio.changes.stagingModel": { @@ -1073,91 +1073,91 @@ "checkboxes" ], "enumDescriptions": [ - "Separate Staged and Unstaged groups \u2014 the clearest view of what is going into this commit.", - "One list with a tick per file, JetBrains-style. Ticking a file stages it, so both models are the same underlying Git state." + "%config.gitstudio.changes.stagingModel.enumDescriptions.0%", + "%config.gitstudio.changes.stagingModel.enumDescriptions.1%" ], "default": "split", - "description": "How the Changes view presents your work. Either way, committing with nothing ticked or staged offers to commit everything after asking.", + "description": "%config.gitstudio.changes.stagingModel.description%", "order": 1 }, "gitstudio.changes.autoRefresh": { "type": "boolean", "default": true, - "description": "Keep the Changes list up to date on its own \u2014 after you save a file, and when the window regains focus so edits made by other tools show up too. Turn this off on a very large repository to refresh only on demand.", + "description": "%config.gitstudio.changes.autoRefresh.description%", "order": 2 }, "gitstudio.changesBadge": { "type": "boolean", "default": true, - "description": "Show a count badge on the GitStudio activity-bar icon for changed files in the working tree (like the built-in Source Control badge). The tooltip also reports commits waiting to be pulled.", + "description": "%config.gitstudio.changesBadge.description%", "order": 3 }, "gitstudio.staging.showGutterState": { "type": "boolean", "default": true, - "description": "Show which changes are staged in the editor gutter. The glyph reports state only \u2014 VS Code's API does not allow an extension to make a gutter icon clickable. Toggle a change with the keybinding, by right-clicking its line number, or on GitStudio's own diff page.", + "description": "%config.gitstudio.staging.showGutterState.description%", "order": 4 }, "gitstudio.staging.clickGutterToggles": { "type": "boolean", "default": false, - "description": "Stage or unstage a change by clicking the gutter beside it. Off by default: VS Code gives decorations no click event, so this is inferred from a click landing at the start of a line \u2014 which is also how you place a caret. It never fires on a line without a change, and yields while blame annotations are shown.", + "description": "%config.gitstudio.staging.clickGutterToggles.description%", "order": 5 } } }, { "id": "gitstudio.commit", - "title": "Commit & Sync", + "title": "%config.gitstudio.commit.title%", "order": 3, "properties": { "gitstudio.commit.signoffByDefault": { "type": "boolean", "default": false, - "description": "Enable the Sign-off toggle by default in the GitStudio commit box (adds a Signed-off-by trailer).", + "description": "%config.gitstudio.commit.signoffByDefault.description%", "order": 1 }, "gitstudio.fetch.prune": { "type": "boolean", "default": true, - "description": "Pass --prune when fetching, so remote-tracking branches deleted on the remote disappear from the branch list instead of lingering as stale entries. Never touches local branches.", + "description": "%config.gitstudio.fetch.prune.description%", "order": 2 } } }, { "id": "gitstudio.blame", - "title": "Blame", + "title": "%config.gitstudio.blame.title%", "order": 4, "properties": { "gitstudio.blame.inlineEnabled": { "type": "boolean", "default": true, - "description": "Show inline blame for the current line (author, relative time, and summary) at the end of the line.", + "description": "%config.gitstudio.blame.inlineEnabled.description%", "order": 1 }, "gitstudio.blame.statusBarEnabled": { "type": "boolean", "default": true, - "description": "Show the current line's commit author and age in the status bar.", + "description": "%config.gitstudio.blame.statusBarEnabled.description%", "order": 2 }, "gitstudio.blame.showDiffOnHover": { "type": "boolean", "default": true, - "description": "Show the commit behind a line \u2014 message, author, date, and a copyable SHA \u2014 when hovering it.", + "description": "%config.gitstudio.blame.showDiffOnHover.description%", "order": 3 }, "gitstudio.blame.clickOpensCommit": { "type": "boolean", "default": true, - "description": "While blame annotations are shown, clicking one reveals that commit in the GitStudio Commit Graph, opened beside the code.", + "description": "%config.gitstudio.blame.clickOpensCommit.description%", "order": 4 }, "gitstudio.blame.heatmap": { "type": "boolean", "default": true, - "description": "Tint full-file blame annotations with a code-age heatmap (recent changes warmer, older changes cooler).", + "description": "%config.gitstudio.blame.heatmap.description%", "order": 5 }, "gitstudio.blame.gutter.fields": { @@ -1181,7 +1181,7 @@ "date", "author" ], - "description": "Which columns the blame annotation gutter shows. Configure them from the annotation right-click menu: Git Blame Annotations \u2192 Options.", + "description": "%config.gitstudio.blame.gutter.fields.description%", "order": 6 }, "gitstudio.blame.gutter.nameStyle": { @@ -1194,14 +1194,14 @@ "email" ], "enumDescriptions": [ - "AA", - "Arnaudov", - "Anton", - "Anton Arnaudov", - "anton@example.com" + "%config.gitstudio.blame.gutter.nameStyle.enumDescriptions.0%", + "%config.gitstudio.blame.gutter.nameStyle.enumDescriptions.1%", + "%config.gitstudio.blame.gutter.nameStyle.enumDescriptions.2%", + "%config.gitstudio.blame.gutter.nameStyle.enumDescriptions.3%", + "%config.gitstudio.blame.gutter.nameStyle.enumDescriptions.4%" ], "default": "fullName", - "description": "How author names are written in the blame annotation gutter.", + "description": "%config.gitstudio.blame.gutter.nameStyle.description%", "order": 7 }, "gitstudio.blame.gutter.colors": { @@ -1212,38 +1212,38 @@ "hide" ], "enumDescriptions": [ - "Tint by commit age \u2014 a code-age heatmap (recent warmer, older cooler).", - "Give every author their own stable tint.", - "No background tint." + "%config.gitstudio.blame.gutter.colors.enumDescriptions.0%", + "%config.gitstudio.blame.gutter.colors.enumDescriptions.1%", + "%config.gitstudio.blame.gutter.colors.enumDescriptions.2%" ], "default": "order", - "description": "Background tint for the blame annotation gutter.", + "description": "%config.gitstudio.blame.gutter.colors.description%", "order": 8 } } }, { "id": "gitstudio.merge", - "title": "Merge & Diff", + "title": "%config.gitstudio.merge.title%", "order": 5, "properties": { "gitstudio.merge.autoOpen": { "type": "boolean", "default": true, - "markdownDescription": "When a merge, rebase, cherry-pick, revert, git am or stash pop stops on conflicts: show the **Conflicts** dashboard, open a conflicted file in the GitStudio merge editor as soon as you switch to it, and take over VS Code's built-in merge editor tab. Off: nothing opens by itself \u2014 use **GitStudio: Resolve Conflicts\u2026**. (This used to open every conflicted file as its own tab.) If Merge Studio is also installed, it leaves this to GitStudio; turn this off to let Merge Studio open conflicts instead.", + "markdownDescription": "%config.gitstudio.merge.autoOpen.markdownDescription%", "order": 1 }, "gitstudio.merge.autoApplyNonConflicting": { "type": "boolean", "default": false, - "description": "Open the merge editor with every non-conflicting change already applied (JetBrains' \"apply non-conflicting changes\" on open). Off: they wait for you, one click each or all at once from the toolbar.", + "description": "%config.gitstudio.merge.autoApplyNonConflicting.description%", "order": 4 } } }, { "id": "gitstudio.ai", - "title": "AI", + "title": "%config.gitstudio.ai.title%", "order": 6, "properties": { "gitstudio.ai.provider": { @@ -1257,15 +1257,15 @@ "off" ], "enumDescriptions": [ - "Prefer the zero-key VS Code Language Model (GitHub Copilot / Cursor) when available; otherwise Anthropic (if a key is set), then an OpenAI-compatible endpoint (if a model is configured).", - "Use the VS Code Language Model API \u2014 GitHub Copilot or Cursor's models, with no key. Pick a specific model via \u201cGitStudio: Select AI Model\u2026\u201d.", - "Use Anthropic directly (requires an API key, set with \u201cGitStudio: Connect AI Provider\u201d).", - "Use any OpenAI-compatible endpoint \u2014 OpenAI, Codex, OpenRouter, or a local server (Ollama / LM Studio). Configure the base URL and model below; a key is optional for local servers.", - "Use a local agent CLI \u2014 Claude Code, Codex or Gemini CLI \u2014 with its own login and no API key. Which one is gitstudio.ai.cliAgent; pick it with \u201cGitStudio: Connect AI Provider\u201d.", - "Disable all AI features." + "%config.gitstudio.ai.provider.enumDescriptions.0%", + "%config.gitstudio.ai.provider.enumDescriptions.1%", + "%config.gitstudio.ai.provider.enumDescriptions.2%", + "%config.gitstudio.ai.provider.enumDescriptions.3%", + "%config.gitstudio.ai.provider.enumDescriptions.4%", + "%config.gitstudio.ai.provider.enumDescriptions.5%" ], "default": "auto", - "markdownDescription": "Which provider GitStudio uses for its optional AI features. AI is off until a provider is available; it never gates or breaks Git operations. Use **GitStudio: Select AI Model\u2026** for a guided picker.", + "markdownDescription": "%config.gitstudio.ai.provider.markdownDescription%", "order": 1 }, "gitstudio.ai.commitStyle": { @@ -1276,19 +1276,19 @@ "descriptive" ], "enumDescriptions": [ - "Conventional Commits (type(scope): summary), optional body.", - "A single concise subject line, no body.", - "Imperative subject plus a short explanatory body." + "%config.gitstudio.ai.commitStyle.enumDescriptions.0%", + "%config.gitstudio.ai.commitStyle.enumDescriptions.1%", + "%config.gitstudio.ai.commitStyle.enumDescriptions.2%" ], "default": "conventional", - "description": "How AI-generated commit messages are styled.", + "description": "%config.gitstudio.ai.commitStyle.description%", "order": 2 }, "gitstudio.ai.reviewPrompt": { "type": "string", "editPresentation": "multilineText", "default": "", - "markdownDescription": "Custom system prompt for **Review Changes (AI)**. Leave empty to use GitStudio's built-in code-review prompt. Set your own to steer the review (e.g. focus areas, house style, output format).", + "markdownDescription": "%config.gitstudio.ai.reviewPrompt.markdownDescription%", "order": 3 }, "gitstudio.ai.cliAgent": { @@ -1300,86 +1300,86 @@ "gemini-cli" ], "enumDescriptions": [ - "No local agent.", - "Claude Code CLI (`claude`).", - "OpenAI Codex CLI (`codex`).", - "Gemini CLI (`gemini`)." + "%config.gitstudio.ai.cliAgent.enumDescriptions.0%", + "%config.gitstudio.ai.cliAgent.enumDescriptions.1%", + "%config.gitstudio.ai.cliAgent.enumDescriptions.2%", + "%config.gitstudio.ai.cliAgent.enumDescriptions.3%" ], "default": "", - "description": "The local agent CLI to drive (uses its own login, no API key). Set via the GitStudio \u00b7 AI panel; used when the provider is a local agent.", + "description": "%config.gitstudio.ai.cliAgent.description%", "order": 4 }, "gitstudio.ai.cliModel": { "type": "string", "default": "", - "description": "Optional model override passed to the local agent CLI (blank = the CLI's default).", + "description": "%config.gitstudio.ai.cliModel.description%", "order": 5 }, "gitstudio.ai.anthropicModelFast": { "type": "string", "default": "claude-haiku-4-5", - "description": "Anthropic model ID for fast/cheap tasks (commit messages).", + "description": "%config.gitstudio.ai.anthropicModelFast.description%", "order": 6 }, "gitstudio.ai.anthropicModelMid": { "type": "string", "default": "claude-sonnet-4-6", - "description": "Anthropic model ID for mid-tier tasks (explain diff, summaries).", + "description": "%config.gitstudio.ai.anthropicModelMid.description%", "order": 7 }, "gitstudio.ai.anthropicModelDeep": { "type": "string", "default": "claude-opus-4-8", - "description": "Anthropic model ID for opt-in deep reasoning.", + "description": "%config.gitstudio.ai.anthropicModelDeep.description%", "order": 8 }, "gitstudio.ai.openai.baseUrl": { "type": "string", "default": "https://api.openai.com/v1", - "markdownDescription": "Base URL for the OpenAI-compatible endpoint (`/chat/completions` is appended). Examples: `https://api.openai.com/v1` (OpenAI), `https://openrouter.ai/api/v1` (OpenRouter), `http://localhost:11434/v1` (Ollama), `http://localhost:1234/v1` (LM Studio).", + "markdownDescription": "%config.gitstudio.ai.openai.baseUrl.markdownDescription%", "order": 9 }, "gitstudio.ai.openai.modelFast": { "type": "string", "default": "gpt-4o-mini", - "description": "OpenAI-compatible model ID for fast/cheap tasks (commit messages). For a local server use its model name, e.g. llama3.1 or qwen2.5-coder.", + "description": "%config.gitstudio.ai.openai.modelFast.description%", "order": 10 }, "gitstudio.ai.openai.modelMid": { "type": "string", "default": "gpt-4o-mini", - "description": "OpenAI-compatible model ID for mid-tier tasks (explain diff, summaries).", + "description": "%config.gitstudio.ai.openai.modelMid.description%", "order": 11 }, "gitstudio.ai.openai.modelDeep": { "type": "string", "default": "gpt-4o", - "description": "OpenAI-compatible model ID for opt-in deep reasoning.", + "description": "%config.gitstudio.ai.openai.modelDeep.description%", "order": 12 } } }, { "id": "gitstudio.advanced", - "title": "Advanced", + "title": "%config.gitstudio.advanced.title%", "order": 7, "properties": { "gitstudio.errorReporting.enabled": { "type": "boolean", "default": true, - "markdownDescription": "Send **anonymous, scrubbed crash reports** when a GitStudio command fails, so we can find and fix bugs during the beta without waiting for someone to file a report. Only the shape of a failure is sent (error type/message/stack or the failed operation), tagged with a random install id and your OS/editor version, and it is scrubbed first: paths, file and branch names, commit subjects, emails, tokens and remote repository names are taken out wherever the scrubber recognises them (a remote's host name, such as github.com, is kept). See [PRIVACY.md](https://github.com/GitStudioHQ/gitstudio/blob/main/apps/extension/PRIVACY.md). Reports are also gated by VS Code's global `telemetry.telemetryLevel`: set that to `off` to disable regardless of this toggle. Turn this off to opt out entirely.", + "markdownDescription": "%config.gitstudio.errorReporting.enabled.markdownDescription%", "order": 1 }, "gitstudio.errorReporting.endpoint": { "type": "string", "default": "https://gitstudio.dev/api/errors", - "markdownDescription": "Collector URL that anonymous crash reports are POSTed to as a plain JSON body. Defaults to GitStudio's collector; point it at any endpoint you control, or **leave it blank to disable sending entirely**. If unreachable, reporting silently no-ops.", + "markdownDescription": "%config.gitstudio.errorReporting.endpoint.markdownDescription%", "order": 2 }, "gitstudio.debug.logChildProcesses": { "type": "boolean", "default": false, - "description": "Log every child process GitStudio launches - the binary, its full arguments, the working directory, and the environment variables GitStudio adds - to the GitStudio: Process Audit output channel. Turn this on only while reproducing a problem you want to report: it is how an OS-level prompt raised by a child process (a credential helper, a git hook, an editor binary) is traced back to the exact command that caused it. Secret-looking values are scrubbed.", + "description": "%config.gitstudio.debug.logChildProcesses.description%", "order": 3 } } @@ -1388,14 +1388,14 @@ "walkthroughs": [ { "id": "gitstudio.gettingStarted", - "title": "Get Started with GitStudio", - "description": "A free, JetBrains-grade Git suite \u2014 commit graph, blame, history, hunk staging, 3-pane merge, interactive rebase with Undo, and optional BYO-key AI. Take the tour.", + "title": "%walkthrough.gitstudio.gettingStarted.title%", + "description": "%walkthrough.gitstudio.gettingStarted.description%", "when": "true", "steps": [ { "id": "gitstudio.walkthrough.graph", - "title": "Browse your history in the commit graph", - "description": "Your history as a commit graph: colored lanes for branches, chips for branches and tags, and who wrote each commit. It is in the **Commits** view, under Changes in the GitStudio sidebar, and in the **Commit Graph** panel beside the terminal. Right-click a commit to check it out, cherry-pick it, branch from it or reset to it; select two to compare them.\n[Show Commit Graph](command:gitstudio.showCommitGraph)", + "title": "%walkthrough.gitstudio.gettingStarted.gitstudio.walkthrough.graph.title%", + "description": "%walkthrough.gitstudio.gettingStarted.gitstudio.walkthrough.graph.description%", "media": { "image": { "light": "media/walkthrough/graph-light.png", @@ -1403,7 +1403,7 @@ "hc": "media/walkthrough/graph-hc-dark.png", "hcLight": "media/walkthrough/graph-hc-light.png" }, - "altText": "The Commit Graph: branch lanes, branch and tag chips, and the authors of the commits on main, a feature branch and a release branch" + "altText": "%walkthrough.gitstudio.gettingStarted.gitstudio.walkthrough.graph.altText%" }, "completionEvents": [ "onCommand:gitstudio.showCommitGraph" @@ -1411,8 +1411,8 @@ }, { "id": "gitstudio.walkthrough.blame", - "title": "See who changed a line, and why", - "description": "Who last changed the line you are on, and when \u2014 at the end of the line and in the status bar. **Annotate with Git Blame** adds a column beside every line, tinted by age; click an annotation and its commit opens in the graph, with its message, its author and the files it changed.\n[Annotate with Git Blame](command:gitstudio.toggleFileBlame)\nShortcut: __Ctrl/Cmd+Alt+G B__ in any editor.", + "title": "%walkthrough.gitstudio.gettingStarted.gitstudio.walkthrough.blame.title%", + "description": "%walkthrough.gitstudio.gettingStarted.gitstudio.walkthrough.blame.description%", "media": { "image": { "light": "media/walkthrough/blame-light.png", @@ -1420,7 +1420,7 @@ "hc": "media/walkthrough/blame-hc-dark.png", "hcLight": "media/walkthrough/blame-hc-light.png" }, - "altText": "A commit opened from a blamed line: its author, message, the branches it is on and the file it changed, beside the graph" + "altText": "%walkthrough.gitstudio.gettingStarted.gitstudio.walkthrough.blame.altText%" }, "completionEvents": [ "onCommand:gitstudio.toggleFileBlame" @@ -1428,8 +1428,8 @@ }, { "id": "gitstudio.walkthrough.stage", - "title": "Stage changes & commit", - "description": "Stage whole files, or tick single changes inside one, in the **Changes** view, then commit from its commit box (Amend, Sign-off, a different author, Commit & Push). With AI on, the sparkle button in the box drafts a message from what you staged. Your stashes are listed under your changes: open one to see every file it holds, and **Move to Changes** just the files you want back.\n[Open the Changes view](command:workbench.view.extension.gitstudio)\nIn the editor: select lines and press __Ctrl/Cmd+Alt+G S__ to stage the changes they touch.", + "title": "%walkthrough.gitstudio.gettingStarted.gitstudio.walkthrough.stage.title%", + "description": "%walkthrough.gitstudio.gettingStarted.gitstudio.walkthrough.stage.description%", "media": { "image": { "light": "media/walkthrough/stage-light.png", @@ -1437,7 +1437,7 @@ "hc": "media/walkthrough/stage-hc-dark.png", "hcLight": "media/walkthrough/stage-hc-light.png" }, - "altText": "The Changes view with ticks: one file's changes open, one of them ticked, and a commit message ready" + "altText": "%walkthrough.gitstudio.gettingStarted.gitstudio.walkthrough.stage.altText%" }, "completionEvents": [ "onCommand:gitstudio.stageHunk", @@ -1448,8 +1448,8 @@ }, { "id": "gitstudio.walkthrough.history", - "title": "Explore file & line history", - "description": "Every commit that changed the lines you select, newest first \u2014 pick one to see its diff. Step a whole file back and forth through its revisions, and find lost work in the reflog.\n[Show Line History](command:gitstudio.showLineHistory)\nShortcut: __Ctrl/Cmd+Alt+G H__ on the current line.", + "title": "%walkthrough.gitstudio.gettingStarted.gitstudio.walkthrough.history.title%", + "description": "%walkthrough.gitstudio.gettingStarted.gitstudio.walkthrough.history.description%", "media": { "image": { "light": "media/walkthrough/history-light.png", @@ -1457,7 +1457,7 @@ "hc": "media/walkthrough/history-hc-dark.png", "hcLight": "media/walkthrough/history-hc-light.png" }, - "altText": "Line History for two lines of a file: the three commits that changed them, with their authors and ages" + "altText": "%walkthrough.gitstudio.gettingStarted.gitstudio.walkthrough.history.altText%" }, "completionEvents": [ "onCommand:gitstudio.showLineHistory", @@ -1466,8 +1466,8 @@ }, { "id": "gitstudio.walkthrough.merge", - "title": "Resolve conflicts in the 3-pane editor", - "description": "When a merge, rebase or cherry-pick stops on a conflict, GitStudio opens a three-pane editor \u2014 your side, the result and theirs \u2014 where an arrow takes a change into the result. Interactive rebase gets the same care.\n[Start Interactive Rebase\u2026](command:gitstudio.startInteractiveRebase)\nMade a mistake? __Undo Last Git Operation__ (Ctrl/Cmd+Alt+G Z) reverses it.", + "title": "%walkthrough.gitstudio.gettingStarted.gitstudio.walkthrough.merge.title%", + "description": "%walkthrough.gitstudio.gettingStarted.gitstudio.walkthrough.merge.description%", "media": { "image": { "light": "media/walkthrough/merge-light.png", @@ -1475,7 +1475,7 @@ "hc": "media/walkthrough/merge-hc-dark.png", "hcLight": "media/walkthrough/merge-hc-light.png" }, - "altText": "The three-pane merge editor stopped on a conflict: changes from main, the result, and changes from feature" + "altText": "%walkthrough.gitstudio.gettingStarted.gitstudio.walkthrough.merge.altText%" }, "completionEvents": [ "onCommand:gitstudio.startInteractiveRebase", @@ -1484,8 +1484,8 @@ }, { "id": "gitstudio.walkthrough.connect", - "title": "Connect GitHub & set up AI (optional)", - "description": "Sign in once with VS Code's built-in GitHub account to list, check out, review, merge, and create pull requests in-editor. AI is optional: it uses Copilot's (or Cursor's) model when there is one, with nothing to set up; otherwise connect Anthropic, an OpenAI-compatible endpoint or a local agent CLI for commit messages, explain-this-diff, and summaries. It never gates a Git operation, and Disable AI Features turns it off.\n[Sign in to GitHub](command:gitstudio.pr.signIn)\n[Connect AI Provider](command:gitstudio.ai.connect)\nGitStudio is free and open source. [Support GitStudio…](command:gitstudio.support)", + "title": "%walkthrough.gitstudio.gettingStarted.gitstudio.walkthrough.connect.title%", + "description": "%walkthrough.gitstudio.gettingStarted.gitstudio.walkthrough.connect.description%", "media": { "image": { "light": "media/walkthrough/connect-light.png", @@ -1493,7 +1493,7 @@ "hc": "media/walkthrough/connect-hc-dark.png", "hcLight": "media/walkthrough/connect-hc-light.png" }, - "altText": "The AI settings: the editor's own AI connected and ready, and the other ways to connect a model" + "altText": "%walkthrough.gitstudio.gettingStarted.gitstudio.walkthrough.connect.altText%" }, "completionEvents": [ "onCommand:gitstudio.pr.signIn", @@ -2446,23 +2446,23 @@ "submenus": [ { "id": "gitstudio.editorMenu", - "label": "GitStudio" + "label": "%submenu.gitstudio.editorMenu.label%" }, { "id": "gitstudio.blame.annotationsMenu", - "label": "Git Blame Annotations" + "label": "%submenu.gitstudio.blame.annotationsMenu.label%" }, { "id": "gitstudio.blame.colorsMenu", - "label": "Colors" + "label": "%submenu.gitstudio.blame.colorsMenu.label%" }, { "id": "gitstudio.blame.namesMenu", - "label": "Names" + "label": "%submenu.gitstudio.blame.namesMenu.label%" }, { "id": "gitstudio.blame.optionsMenu", - "label": "Options" + "label": "%submenu.gitstudio.blame.optionsMenu.label%" } ] }, @@ -2488,9 +2488,11 @@ "@gitstudio/engine": "*", "@gitstudio/git-service": "*", "@gitstudio/host-bridge": "*", + "@gitstudio/l10n": "*", "@gitstudio/merge-vscode": "*", "@gitstudio/secret-store": "*", - "@gitstudio/webview-ui": "*" + "@gitstudio/webview-ui": "*", + "@vscode/l10n": "^0.0.18" }, "pricing": "Free", "extensionKind": [ @@ -2499,8 +2501,9 @@ "capabilities": { "virtualWorkspaces": { "supported": false, - "description": "GitStudio requires a local git repository on disk." + "description": "%capabilities.virtualWorkspaces.description%" } }, - "preview": false + "preview": false, + "l10n": "./l10n" } diff --git a/apps/extension/package.nls.json b/apps/extension/package.nls.json new file mode 100644 index 00000000..3c23e203 --- /dev/null +++ b/apps/extension/package.nls.json @@ -0,0 +1,247 @@ +{ + "capabilities.virtualWorkspaces.description": "GitStudio requires a local git repository on disk.", + "command.gitstudio.abortRebase.title": "Abort Rebase", + "command.gitstudio.addRemote.title": "Add Remote…", + "command.gitstudio.ai.clearApiKey.title": "Clear Anthropic API Key", + "command.gitstudio.ai.clearOpenAIKey.title": "Clear OpenAI API Key", + "command.gitstudio.ai.connect.title": "Connect AI Provider", + "command.gitstudio.ai.disable.title": "Disable AI Features", + "command.gitstudio.ai.explainDiff.title": "Explain Diff (AI)", + "command.gitstudio.ai.generateCommitMessage.title": "Generate Commit Message (AI)", + "command.gitstudio.ai.reviewChanges.title": "Review Changes (AI)", + "command.gitstudio.ai.selectModel.title": "Select AI Model…", + "command.gitstudio.ai.setApiKey.title": "Set Anthropic API Key…", + "command.gitstudio.ai.setOpenAIKey.title": "Set OpenAI API Key…", + "command.gitstudio.ai.summarizeChanges.title": "Summarize Changes (AI)", + "command.gitstudio.blame.closeAnnotations.title": "Close Annotations", + "command.gitstudio.blame.colors.author.off.title": "Author", + "command.gitstudio.blame.colors.author.on.title": "✓ Author", + "command.gitstudio.blame.colors.hide.off.title": "Hide", + "command.gitstudio.blame.colors.hide.on.title": "✓ Hide", + "command.gitstudio.blame.colors.order.off.title": "Order", + "command.gitstudio.blame.colors.order.on.title": "✓ Order", + "command.gitstudio.blame.copyRevision.title": "Copy Revision Number", + "command.gitstudio.blame.field.author.off.title": "Author", + "command.gitstudio.blame.field.author.on.title": "✓ Author", + "command.gitstudio.blame.field.commitNumber.off.title": "Commit number", + "command.gitstudio.blame.field.commitNumber.on.title": "✓ Commit number", + "command.gitstudio.blame.field.date.off.title": "Date", + "command.gitstudio.blame.field.date.on.title": "✓ Date", + "command.gitstudio.blame.field.revision.off.title": "Revision", + "command.gitstudio.blame.field.revision.on.title": "✓ Revision", + "command.gitstudio.blame.hover.off.title": "Show Diff On Hover", + "command.gitstudio.blame.hover.on.title": "✓ Show Diff On Hover", + "command.gitstudio.blame.names.email.off.title": "Email", + "command.gitstudio.blame.names.email.on.title": "✓ Email", + "command.gitstudio.blame.names.firstName.off.title": "First Name", + "command.gitstudio.blame.names.firstName.on.title": "✓ First Name", + "command.gitstudio.blame.names.fullName.off.title": "Full Name", + "command.gitstudio.blame.names.fullName.on.title": "✓ Full Name", + "command.gitstudio.blame.names.initials.off.title": "Initials", + "command.gitstudio.blame.names.initials.on.title": "✓ Initials", + "command.gitstudio.blame.names.lastName.off.title": "Last Name", + "command.gitstudio.blame.names.lastName.on.title": "✓ Last Name", + "command.gitstudio.blame.openPreviousRevision.title": "Open Previous Revision", + "command.gitstudio.blame.showCommit.title": "Show Commit", + "command.gitstudio.blame.showDiff.title": "Show Diff", + "command.gitstudio.blame.showLineActions.title": "Line Blame Actions", + "command.gitstudio.blame.viewInBrowser.title": "View in Browser", + "command.gitstudio.branch.checkout.title": "Checkout", + "command.gitstudio.branch.compare.title": "Compare with Current", + "command.gitstudio.branch.createWorktree.title": "New Worktree from This Branch…", + "command.gitstudio.branch.delete.title": "Delete Branch", + "command.gitstudio.branch.merge.title": "Merge into Current", + "command.gitstudio.branch.new.title": "New Branch from Here…", + "command.gitstudio.branch.push.title": "Push / Publish Branch", + "command.gitstudio.branch.rebase.title": "Rebase Current onto This", + "command.gitstudio.branch.rename.title": "Rename Branch…", + "command.gitstudio.branch.resetToUpstream.title": "Reset Branch to Its Upstream…", + "command.gitstudio.branch.setUpstream.title": "Set Upstream…", + "command.gitstudio.branches.open.title": "Branches…", + "command.gitstudio.compare.title": "Compare File…", + "command.gitstudio.compareRefs.title": "Compare Branches/Tags…", + "command.gitstudio.copyCommitSha.title": "Copy Commit SHA", + "command.gitstudio.debug.showProcessAudit.title": "Show Process Audit", + "command.gitstudio.fetch.title": "Fetch", + "command.gitstudio.manageRemotes.title": "Manage Remotes…", + "command.gitstudio.merge.openDemo.title": "Open Sample Merge", + "command.gitstudio.merge.openDemoDiff.title": "Open Sample Diff", + "command.gitstudio.merge.restoreBuiltInMergeEditor.title": "Restore VS Code's Merge Editor", + "command.gitstudio.openChanges.title": "Open Changes (vs HEAD)", + "command.gitstudio.openDiff.title": "Open in Embedded Diff", + "command.gitstudio.openFileAtRevision.title": "Open File at Revision…", + "command.gitstudio.openTerminal.title": "Open Terminal at Repository Root", + "command.gitstudio.openWalkthrough.title": "Get Started", + "command.gitstudio.operation.abort.title": "Abort Operation", + "command.gitstudio.operation.continue.title": "Continue Operation", + "command.gitstudio.operation.skip.title": "Skip This Commit", + "command.gitstudio.pr.addReviewComment.title": "Add to Review", + "command.gitstudio.pr.addSingleComment.title": "Add Single Comment", + "command.gitstudio.pr.cancelReview.title": "Discard Pending Review", + "command.gitstudio.pr.checkout.title": "Checkout Pull Request", + "command.gitstudio.pr.copyUrl.title": "Copy Pull Request Link", + "command.gitstudio.pr.create.title": "New Pull Request", + "command.gitstudio.pr.deleteReviewComment.title": "Delete Comment", + "command.gitstudio.pr.merge.title": "Merge Pull Request…", + "command.gitstudio.pr.openDescription.title": "Open Pull Request", + "command.gitstudio.pr.openOnGitHub.title": "Open on GitHub", + "command.gitstudio.pr.refresh.title": "Refresh Pull Requests", + "command.gitstudio.pr.replyThread.title": "Reply", + "command.gitstudio.pr.resolveThread.title": "Resolve Conversation", + "command.gitstudio.pr.signIn.title": "Sign in to GitHub", + "command.gitstudio.pr.startReview.title": "Review Pull Request", + "command.gitstudio.pr.submitReview.title": "Submit Review", + "command.gitstudio.pr.unresolveThread.title": "Unresolve Conversation", + "command.gitstudio.refreshBranches.title": "Refresh Branches", + "command.gitstudio.refreshCommits.title": "Refresh Commits", + "command.gitstudio.remoteBranch.checkout.title": "Checkout (Create Local Tracking)…", + "command.gitstudio.remoteBranch.delete.title": "Delete Remote Branch", + "command.gitstudio.resetToCommit.title": "Reset Current Branch to Here…", + "command.gitstudio.resolveInMergeEditor.title": "Resolve in Merge Editor", + "command.gitstudio.revealCommitInGraph.title": "Show Commit in Graph", + "command.gitstudio.revisionNavigateBack.title": "Revision: Step to Older", + "command.gitstudio.revisionNavigateForward.title": "Revision: Step to Newer", + "command.gitstudio.showCommitGraph.title": "Show Commit Graph", + "command.gitstudio.showCommitPanel.title": "Show Commit Graph", + "command.gitstudio.showConflicts.title": "Resolve Conflicts…", + "command.gitstudio.showLineHistory.title": "Show Line History", + "command.gitstudio.showReflog.title": "Show Reflog (Time Machine)", + "command.gitstudio.showUndoHistory.title": "Show Undo History", + "command.gitstudio.showWelcome.title": "Welcome", + "command.gitstudio.stageHunk.title": "Stage Hunk", + "command.gitstudio.stageSelectedLines.title": "Stage Selected Lines", + "command.gitstudio.stageWithTicks.title": "Stage Changes with Ticks", + "command.gitstudio.startInteractiveRebase.title": "Start Interactive Rebase…", + "command.gitstudio.stash.apply.title": "Apply Stash…", + "command.gitstudio.stash.branch.title": "Create Branch from Stash…", + "command.gitstudio.stash.drop.title": "Drop Stash…", + "command.gitstudio.stash.pop.title": "Pop Stash…", + "command.gitstudio.stash.save.title": "Stash Changes…", + "command.gitstudio.stashes.refresh.title": "Refresh Stashes", + "command.gitstudio.support.title": "Support GitStudio…", + "command.gitstudio.switchRepository.title": "Switch Repository…", + "command.gitstudio.tag.checkout.title": "Checkout Tag", + "command.gitstudio.tag.delete.title": "Delete Tag", + "command.gitstudio.tag.push.title": "Push Tag…", + "command.gitstudio.toggleFileBlame.title": "Annotate with Git Blame", + "command.gitstudio.toggleStageAtLine.title": "Stage or Unstage the Change at This Line", + "command.gitstudio.undo.title": "Undo Last Git Operation", + "command.gitstudio.unstageHunk.title": "Unstage Hunk", + "command.gitstudio.unstageSelectedLines.title": "Unstage Selected Lines", + "command.gitstudio.worktree.add.title": "New Worktree…", + "command.gitstudio.worktree.forget.title": "Forget Worktree…", + "command.gitstudio.worktree.lock.title": "Lock Worktree…", + "command.gitstudio.worktree.open.title": "Open Worktree…", + "command.gitstudio.worktree.openHere.title": "Open Worktree in This Window…", + "command.gitstudio.worktree.openInNewWindow.title": "Open Worktree in New Window…", + "command.gitstudio.worktree.prune.title": "Prune Missing Worktrees…", + "command.gitstudio.worktree.remove.title": "Remove Worktree…", + "command.gitstudio.worktree.unlock.title": "Unlock Worktree…", + "command.gitstudio.worktrees.refresh.title": "Refresh Worktrees", + "config.gitstudio.advanced.title": "Advanced", + "config.gitstudio.ai.anthropicModelDeep.description": "Anthropic model ID for opt-in deep reasoning.", + "config.gitstudio.ai.anthropicModelFast.description": "Anthropic model ID for fast/cheap tasks (commit messages).", + "config.gitstudio.ai.anthropicModelMid.description": "Anthropic model ID for mid-tier tasks (explain diff, summaries).", + "config.gitstudio.ai.cliAgent.description": "The local agent CLI to drive (uses its own login, no API key). Set via the GitStudio · AI panel; used when the provider is a local agent.", + "config.gitstudio.ai.cliAgent.enumDescriptions.0": "No local agent.", + "config.gitstudio.ai.cliAgent.enumDescriptions.1": "Claude Code CLI (`claude`).", + "config.gitstudio.ai.cliAgent.enumDescriptions.2": "OpenAI Codex CLI (`codex`).", + "config.gitstudio.ai.cliAgent.enumDescriptions.3": "Gemini CLI (`gemini`).", + "config.gitstudio.ai.cliModel.description": "Optional model override passed to the local agent CLI (blank = the CLI's default).", + "config.gitstudio.ai.commitStyle.description": "How AI-generated commit messages are styled.", + "config.gitstudio.ai.commitStyle.enumDescriptions.0": "Conventional Commits (type(scope): summary), optional body.", + "config.gitstudio.ai.commitStyle.enumDescriptions.1": "A single concise subject line, no body.", + "config.gitstudio.ai.commitStyle.enumDescriptions.2": "Imperative subject plus a short explanatory body.", + "config.gitstudio.ai.openai.baseUrl.markdownDescription": "Base URL for the OpenAI-compatible endpoint (`/chat/completions` is appended). Examples: `https://api.openai.com/v1` (OpenAI), `https://openrouter.ai/api/v1` (OpenRouter), `http://localhost:11434/v1` (Ollama), `http://localhost:1234/v1` (LM Studio).", + "config.gitstudio.ai.openai.modelDeep.description": "OpenAI-compatible model ID for opt-in deep reasoning.", + "config.gitstudio.ai.openai.modelFast.description": "OpenAI-compatible model ID for fast/cheap tasks (commit messages). For a local server use its model name, e.g. llama3.1 or qwen2.5-coder.", + "config.gitstudio.ai.openai.modelMid.description": "OpenAI-compatible model ID for mid-tier tasks (explain diff, summaries).", + "config.gitstudio.ai.provider.enumDescriptions.0": "Prefer the zero-key VS Code Language Model (GitHub Copilot / Cursor) when available; otherwise Anthropic (if a key is set), then an OpenAI-compatible endpoint (if a model is configured).", + "config.gitstudio.ai.provider.enumDescriptions.1": "Use the VS Code Language Model API — GitHub Copilot or Cursor's models, with no key. Pick a specific model via “GitStudio: Select AI Model…”.", + "config.gitstudio.ai.provider.enumDescriptions.2": "Use Anthropic directly (requires an API key, set with “GitStudio: Connect AI Provider”).", + "config.gitstudio.ai.provider.enumDescriptions.3": "Use any OpenAI-compatible endpoint — OpenAI, Codex, OpenRouter, or a local server (Ollama / LM Studio). Configure the base URL and model below; a key is optional for local servers.", + "config.gitstudio.ai.provider.enumDescriptions.4": "Use a local agent CLI — Claude Code, Codex or Gemini CLI — with its own login and no API key. Which one is gitstudio.ai.cliAgent; pick it with “GitStudio: Connect AI Provider”.", + "config.gitstudio.ai.provider.enumDescriptions.5": "Disable all AI features.", + "config.gitstudio.ai.provider.markdownDescription": "Which provider GitStudio uses for its optional AI features. AI is off until a provider is available; it never gates or breaks Git operations. Use **GitStudio: Select AI Model…** for a guided picker.", + "config.gitstudio.ai.reviewPrompt.markdownDescription": "Custom system prompt for **Review Changes (AI)**. Leave empty to use GitStudio's built-in code-review prompt. Set your own to steer the review (e.g. focus areas, house style, output format).", + "config.gitstudio.ai.title": "AI", + "config.gitstudio.avatars.gravatar.markdownDescription": "Show commit authors' pictures in the Commit Graph, the Commits view and commit details. To find one, GitStudio sends an MD5 hash of each author's email address to Gravatar (`www.gravatar.com`, run by Automattic); for a GitHub noreply address (`…@users.noreply.github.com`) it asks GitHub (`avatars.githubusercontent.com`) for that account's picture instead. Turn this off to show every author as coloured initials and send neither request. While you are signed in to GitHub, the pictures GitHub itself returns (on pull requests, and for the authors of a GitHub repository's recent commits) still show. See [PRIVACY.md](https://github.com/GitStudioHQ/gitstudio/blob/main/apps/extension/PRIVACY.md).", + "config.gitstudio.blame.clickOpensCommit.description": "While blame annotations are shown, clicking one reveals that commit in the GitStudio Commit Graph, opened beside the code.", + "config.gitstudio.blame.gutter.colors.description": "Background tint for the blame annotation gutter.", + "config.gitstudio.blame.gutter.colors.enumDescriptions.0": "Tint by commit age — a code-age heatmap (recent warmer, older cooler).", + "config.gitstudio.blame.gutter.colors.enumDescriptions.1": "Give every author their own stable tint.", + "config.gitstudio.blame.gutter.colors.enumDescriptions.2": "No background tint.", + "config.gitstudio.blame.gutter.fields.description": "Which columns the blame annotation gutter shows. Configure them from the annotation right-click menu: Git Blame Annotations → Options.", + "config.gitstudio.blame.gutter.nameStyle.description": "How author names are written in the blame annotation gutter.", + "config.gitstudio.blame.gutter.nameStyle.enumDescriptions.0": "AA", + "config.gitstudio.blame.gutter.nameStyle.enumDescriptions.1": "Arnaudov", + "config.gitstudio.blame.gutter.nameStyle.enumDescriptions.2": "Anton", + "config.gitstudio.blame.gutter.nameStyle.enumDescriptions.3": "Anton Arnaudov", + "config.gitstudio.blame.gutter.nameStyle.enumDescriptions.4": "anton@example.com", + "config.gitstudio.blame.heatmap.description": "Tint full-file blame annotations with a code-age heatmap (recent changes warmer, older changes cooler).", + "config.gitstudio.blame.inlineEnabled.description": "Show inline blame for the current line (author, relative time, and summary) at the end of the line.", + "config.gitstudio.blame.showDiffOnHover.description": "Show the commit behind a line — message, author, date, and a copyable SHA — when hovering it.", + "config.gitstudio.blame.statusBarEnabled.description": "Show the current line's commit author and age in the status bar.", + "config.gitstudio.blame.title": "Blame", + "config.gitstudio.changes.autoRefresh.description": "Keep the Changes list up to date on its own — after you save a file, and when the window regains focus so edits made by other tools show up too. Turn this off on a very large repository to refresh only on demand.", + "config.gitstudio.changes.stagingModel.description": "How the Changes view presents your work. Either way, committing with nothing ticked or staged offers to commit everything after asking.", + "config.gitstudio.changes.stagingModel.enumDescriptions.0": "Separate Staged and Unstaged groups — the clearest view of what is going into this commit.", + "config.gitstudio.changes.stagingModel.enumDescriptions.1": "One list with a tick per file, JetBrains-style. Ticking a file stages it, so both models are the same underlying Git state.", + "config.gitstudio.changes.title": "Changes & Staging", + "config.gitstudio.changesBadge.description": "Show a count badge on the GitStudio activity-bar icon for changed files in the working tree (like the built-in Source Control badge). The tooltip also reports commits waiting to be pulled.", + "config.gitstudio.commit.signoffByDefault.description": "Enable the Sign-off toggle by default in the GitStudio commit box (adds a Signed-off-by trailer).", + "config.gitstudio.commit.title": "Commit & Sync", + "config.gitstudio.debug.logChildProcesses.description": "Log every child process GitStudio launches - the binary, its full arguments, the working directory, and the environment variables GitStudio adds - to the GitStudio: Process Audit output channel. Turn this on only while reproducing a problem you want to report: it is how an OS-level prompt raised by a child process (a credential helper, a git hook, an editor binary) is traced back to the exact command that caused it. Secret-looking values are scrubbed.", + "config.gitstudio.errorReporting.enabled.markdownDescription": "Send **anonymous, scrubbed crash reports** when a GitStudio command fails, so we can find and fix bugs during the beta without waiting for someone to file a report. Only the shape of a failure is sent (error type/message/stack or the failed operation), tagged with a random install id and your OS/editor version, and it is scrubbed first: paths, file and branch names, commit subjects, emails, tokens and remote repository names are taken out wherever the scrubber recognises them (a remote's host name, such as github.com, is kept). See [PRIVACY.md](https://github.com/GitStudioHQ/gitstudio/blob/main/apps/extension/PRIVACY.md). Reports are also gated by VS Code's global `telemetry.telemetryLevel`: set that to `off` to disable regardless of this toggle. Turn this off to opt out entirely.", + "config.gitstudio.errorReporting.endpoint.markdownDescription": "Collector URL that anonymous crash reports are POSTed to as a plain JSON body. Defaults to GitStudio's collector; point it at any endpoint you control, or **leave it blank to disable sending entirely**. If unreachable, reporting silently no-ops.", + "config.gitstudio.fetch.prune.description": "Pass --prune when fetching, so remote-tracking branches deleted on the remote disappear from the branch list instead of lingering as stale entries. Never touches local branches.", + "config.gitstudio.general.title": "General", + "config.gitstudio.merge.autoApplyNonConflicting.description": "Open the merge editor with every non-conflicting change already applied (JetBrains' \"apply non-conflicting changes\" on open). Off: they wait for you, one click each or all at once from the toolbar.", + "config.gitstudio.merge.autoOpen.markdownDescription": "When a merge, rebase, cherry-pick, revert, git am or stash pop stops on conflicts: show the **Conflicts** dashboard, open a conflicted file in the GitStudio merge editor as soon as you switch to it, and take over VS Code's built-in merge editor tab. Off: nothing opens by itself — use **GitStudio: Resolve Conflicts…**. (This used to open every conflicted file as its own tab.) If Merge Studio is also installed, it leaves this to GitStudio; turn this off to let Merge Studio open conflicts instead.", + "config.gitstudio.merge.title": "Merge & Diff", + "config.gitstudio.pr.defaultMergeMethod.description": "Default method offered first when merging a pull request.", + "config.gitstudio.pr.defaultMergeMethod.enumDescriptions.0": "Create a merge commit.", + "config.gitstudio.pr.defaultMergeMethod.enumDescriptions.1": "Squash the PR's commits into one and merge.", + "config.gitstudio.pr.defaultMergeMethod.enumDescriptions.2": "Rebase the PR's commits onto the base and merge.", + "config.gitstudio.staging.clickGutterToggles.description": "Stage or unstage a change by clicking the gutter beside it. Off by default: VS Code gives decorations no click event, so this is inferred from a click landing at the start of a line — which is also how you place a caret. It never fires on a line without a change, and yields while blame annotations are shown.", + "config.gitstudio.staging.showGutterState.description": "Show which changes are staged in the editor gutter. The glyph reports state only — VS Code's API does not allow an extension to make a gutter icon clickable. Toggle a change with the keybinding, by right-clicking its line number, or on GitStudio's own diff page.", + "config.gitstudio.statusBar.showGraph.description": "Show a status-bar button that opens the Commit Graph.", + "config.gitstudio.statusBar.showTerminal.description": "Show a status-bar button that opens a terminal already in the active repository's root — which is not necessarily the workspace root.", + "config.gitstudio.worktrees.prefixWithProjectName.description": "No longer used: New Worktree now suggests the folder '-' beside the main worktree, and you can edit it before it is created.", + "customEditor.gitstudio.mergeEditor.displayName": "GitStudio 3-Pane Merge", + "customEditor.gitstudio.rebaseTodoEditor.displayName": "GitStudio Interactive Rebase", + "description": "Free, open-source Git GUI & commit graph for VS Code and Cursor. Git Studio brings a JetBrains-style Git workflow into the editor — inline blame, file history, hunk & line staging, 3-pane merge, interactive rebase with universal Undo, stash/shelf, worktrees, and in-editor GitHub PRs. A free alternative to GitLens, GitKraken & Sourcetree.", + "displayName": "GitStudio — JetBrains-style Git Graph, Blame & Merge", + "submenu.gitstudio.blame.annotationsMenu.label": "Git Blame Annotations", + "submenu.gitstudio.blame.colorsMenu.label": "Colors", + "submenu.gitstudio.blame.namesMenu.label": "Names", + "submenu.gitstudio.blame.optionsMenu.label": "Options", + "submenu.gitstudio.editorMenu.label": "GitStudio", + "view.gitstudio.commit.name": "Changes", + "view.gitstudio.commitPanel.name": "Commit Graph", + "view.gitstudio.commits.name": "Commits", + "view.gitstudio.pullRequests.name": "Pull Requests", + "view.gitstudio.worktrees.name": "Worktrees", + "viewContainer.gitstudio.title": "GitStudio", + "viewContainer.gitstudioPanel.title": "Commit Graph", + "walkthrough.gitstudio.gettingStarted.description": "A free, JetBrains-grade Git suite — commit graph, blame, history, hunk staging, 3-pane merge, interactive rebase with Undo, and optional BYO-key AI. Take the tour.", + "walkthrough.gitstudio.gettingStarted.gitstudio.walkthrough.blame.altText": "A commit opened from a blamed line: its author, message, the branches it is on and the file it changed, beside the graph", + "walkthrough.gitstudio.gettingStarted.gitstudio.walkthrough.blame.description": "Who last changed the line you are on, and when — at the end of the line and in the status bar. **Annotate with Git Blame** adds a column beside every line, tinted by age; click an annotation and its commit opens in the graph, with its message, its author and the files it changed.\n[Annotate with Git Blame](command:gitstudio.toggleFileBlame)\nShortcut: __Ctrl/Cmd+Alt+G B__ in any editor.", + "walkthrough.gitstudio.gettingStarted.gitstudio.walkthrough.blame.title": "See who changed a line, and why", + "walkthrough.gitstudio.gettingStarted.gitstudio.walkthrough.connect.altText": "The AI settings: the editor's own AI connected and ready, and the other ways to connect a model", + "walkthrough.gitstudio.gettingStarted.gitstudio.walkthrough.connect.description": "Sign in once with VS Code's built-in GitHub account to list, check out, review, merge, and create pull requests in-editor. AI is optional: it uses Copilot's (or Cursor's) model when there is one, with nothing to set up; otherwise connect Anthropic, an OpenAI-compatible endpoint or a local agent CLI for commit messages, explain-this-diff, and summaries. It never gates a Git operation, and Disable AI Features turns it off.\n[Sign in to GitHub](command:gitstudio.pr.signIn)\n[Connect AI Provider](command:gitstudio.ai.connect)\nGitStudio is free and open source. [Support GitStudio…](command:gitstudio.support)", + "walkthrough.gitstudio.gettingStarted.gitstudio.walkthrough.connect.title": "Connect GitHub & set up AI (optional)", + "walkthrough.gitstudio.gettingStarted.gitstudio.walkthrough.graph.altText": "The Commit Graph: branch lanes, branch and tag chips, and the authors of the commits on main, a feature branch and a release branch", + "walkthrough.gitstudio.gettingStarted.gitstudio.walkthrough.graph.description": "Your history as a commit graph: colored lanes for branches, chips for branches and tags, and who wrote each commit. It is in the **Commits** view, under Changes in the GitStudio sidebar, and in the **Commit Graph** panel beside the terminal. Right-click a commit to check it out, cherry-pick it, branch from it or reset to it; select two to compare them.\n[Show Commit Graph](command:gitstudio.showCommitGraph)", + "walkthrough.gitstudio.gettingStarted.gitstudio.walkthrough.graph.title": "Browse your history in the commit graph", + "walkthrough.gitstudio.gettingStarted.gitstudio.walkthrough.history.altText": "Line History for two lines of a file: the three commits that changed them, with their authors and ages", + "walkthrough.gitstudio.gettingStarted.gitstudio.walkthrough.history.description": "Every commit that changed the lines you select, newest first — pick one to see its diff. Step a whole file back and forth through its revisions, and find lost work in the reflog.\n[Show Line History](command:gitstudio.showLineHistory)\nShortcut: __Ctrl/Cmd+Alt+G H__ on the current line.", + "walkthrough.gitstudio.gettingStarted.gitstudio.walkthrough.history.title": "Explore file & line history", + "walkthrough.gitstudio.gettingStarted.gitstudio.walkthrough.merge.altText": "The three-pane merge editor stopped on a conflict: changes from main, the result, and changes from feature", + "walkthrough.gitstudio.gettingStarted.gitstudio.walkthrough.merge.description": "When a merge, rebase or cherry-pick stops on a conflict, GitStudio opens a three-pane editor — your side, the result and theirs — where an arrow takes a change into the result. Interactive rebase gets the same care.\n[Start Interactive Rebase…](command:gitstudio.startInteractiveRebase)\nMade a mistake? __Undo Last Git Operation__ (Ctrl/Cmd+Alt+G Z) reverses it.", + "walkthrough.gitstudio.gettingStarted.gitstudio.walkthrough.merge.title": "Resolve conflicts in the 3-pane editor", + "walkthrough.gitstudio.gettingStarted.gitstudio.walkthrough.stage.altText": "The Changes view with ticks: one file's changes open, one of them ticked, and a commit message ready", + "walkthrough.gitstudio.gettingStarted.gitstudio.walkthrough.stage.description": "Stage whole files, or tick single changes inside one, in the **Changes** view, then commit from its commit box (Amend, Sign-off, a different author, Commit & Push). With AI on, the sparkle button in the box drafts a message from what you staged. Your stashes are listed under your changes: open one to see every file it holds, and **Move to Changes** just the files you want back.\n[Open the Changes view](command:workbench.view.extension.gitstudio)\nIn the editor: select lines and press __Ctrl/Cmd+Alt+G S__ to stage the changes they touch.", + "walkthrough.gitstudio.gettingStarted.gitstudio.walkthrough.stage.title": "Stage changes & commit", + "walkthrough.gitstudio.gettingStarted.title": "Get Started with GitStudio" +} diff --git a/apps/extension/package.nls.zh-cn.json b/apps/extension/package.nls.zh-cn.json new file mode 100644 index 00000000..84c66680 --- /dev/null +++ b/apps/extension/package.nls.zh-cn.json @@ -0,0 +1,247 @@ +{ + "capabilities.virtualWorkspaces.description": "GitStudio 需要磁盘上的本地 git 仓库。", + "command.gitstudio.abortRebase.title": "中止变基", + "command.gitstudio.addRemote.title": "添加远程仓库…", + "command.gitstudio.ai.clearApiKey.title": "清除 Anthropic API 密钥", + "command.gitstudio.ai.clearOpenAIKey.title": "清除 OpenAI API 密钥", + "command.gitstudio.ai.connect.title": "连接 AI 提供方", + "command.gitstudio.ai.disable.title": "禁用 AI 功能", + "command.gitstudio.ai.explainDiff.title": "解释差异(AI)", + "command.gitstudio.ai.generateCommitMessage.title": "生成提交信息(AI)", + "command.gitstudio.ai.reviewChanges.title": "审查更改(AI)", + "command.gitstudio.ai.selectModel.title": "选择 AI 模型…", + "command.gitstudio.ai.setApiKey.title": "设置 Anthropic API 密钥…", + "command.gitstudio.ai.setOpenAIKey.title": "设置 OpenAI API 密钥…", + "command.gitstudio.ai.summarizeChanges.title": "总结更改(AI)", + "command.gitstudio.blame.closeAnnotations.title": "关闭注释", + "command.gitstudio.blame.colors.author.off.title": "作者", + "command.gitstudio.blame.colors.author.on.title": "✓ 作者", + "command.gitstudio.blame.colors.hide.off.title": "隐藏", + "command.gitstudio.blame.colors.hide.on.title": "✓ 隐藏", + "command.gitstudio.blame.colors.order.off.title": "顺序", + "command.gitstudio.blame.colors.order.on.title": "✓ 顺序", + "command.gitstudio.blame.copyRevision.title": "复制修订号", + "command.gitstudio.blame.field.author.off.title": "作者", + "command.gitstudio.blame.field.author.on.title": "✓ 作者", + "command.gitstudio.blame.field.commitNumber.off.title": "提交编号", + "command.gitstudio.blame.field.commitNumber.on.title": "✓ 提交编号", + "command.gitstudio.blame.field.date.off.title": "日期", + "command.gitstudio.blame.field.date.on.title": "✓ 日期", + "command.gitstudio.blame.field.revision.off.title": "修订", + "command.gitstudio.blame.field.revision.on.title": "✓ 修订", + "command.gitstudio.blame.hover.off.title": "悬停时显示差异", + "command.gitstudio.blame.hover.on.title": "✓ 悬停时显示差异", + "command.gitstudio.blame.names.email.off.title": "邮箱", + "command.gitstudio.blame.names.email.on.title": "✓ 邮箱", + "command.gitstudio.blame.names.firstName.off.title": "名字", + "command.gitstudio.blame.names.firstName.on.title": "✓ 名字", + "command.gitstudio.blame.names.fullName.off.title": "全名", + "command.gitstudio.blame.names.fullName.on.title": "✓ 全名", + "command.gitstudio.blame.names.initials.off.title": "姓名缩写", + "command.gitstudio.blame.names.initials.on.title": "✓ 姓名缩写", + "command.gitstudio.blame.names.lastName.off.title": "姓氏", + "command.gitstudio.blame.names.lastName.on.title": "✓ 姓氏", + "command.gitstudio.blame.openPreviousRevision.title": "打开上一个修订", + "command.gitstudio.blame.showCommit.title": "显示提交", + "command.gitstudio.blame.showDiff.title": "显示差异", + "command.gitstudio.blame.showLineActions.title": "行 Blame 操作", + "command.gitstudio.blame.viewInBrowser.title": "在浏览器中查看", + "command.gitstudio.branch.checkout.title": "检出", + "command.gitstudio.branch.compare.title": "与当前分支比较", + "command.gitstudio.branch.createWorktree.title": "从此分支新建工作树…", + "command.gitstudio.branch.delete.title": "删除分支", + "command.gitstudio.branch.merge.title": "合并到当前分支", + "command.gitstudio.branch.new.title": "从此处新建分支…", + "command.gitstudio.branch.push.title": "推送 / 发布分支", + "command.gitstudio.branch.rebase.title": "将当前分支变基到此分支", + "command.gitstudio.branch.rename.title": "重命名分支…", + "command.gitstudio.branch.resetToUpstream.title": "将分支重置到其上游…", + "command.gitstudio.branch.setUpstream.title": "设置上游…", + "command.gitstudio.branches.open.title": "分支…", + "command.gitstudio.compare.title": "比较文件…", + "command.gitstudio.compareRefs.title": "比较分支/标签…", + "command.gitstudio.copyCommitSha.title": "复制提交 SHA", + "command.gitstudio.debug.showProcessAudit.title": "显示进程审核", + "command.gitstudio.fetch.title": "获取", + "command.gitstudio.manageRemotes.title": "管理远程仓库…", + "command.gitstudio.merge.openDemo.title": "打开示例合并", + "command.gitstudio.merge.openDemoDiff.title": "打开示例差异", + "command.gitstudio.merge.restoreBuiltInMergeEditor.title": "恢复 VS Code 的合并编辑器", + "command.gitstudio.openChanges.title": "打开更改(相对 HEAD)", + "command.gitstudio.openDiff.title": "在内嵌差异中打开", + "command.gitstudio.openFileAtRevision.title": "在修订版本处打开文件…", + "command.gitstudio.openTerminal.title": "在仓库根目录打开终端", + "command.gitstudio.openWalkthrough.title": "开始使用", + "command.gitstudio.operation.abort.title": "中止操作", + "command.gitstudio.operation.continue.title": "继续操作", + "command.gitstudio.operation.skip.title": "跳过此提交", + "command.gitstudio.pr.addReviewComment.title": "添加到审查", + "command.gitstudio.pr.addSingleComment.title": "添加单条评论", + "command.gitstudio.pr.cancelReview.title": "丢弃待提交的审查", + "command.gitstudio.pr.checkout.title": "检出拉取请求", + "command.gitstudio.pr.copyUrl.title": "复制拉取请求链接", + "command.gitstudio.pr.create.title": "新建拉取请求", + "command.gitstudio.pr.deleteReviewComment.title": "删除评论", + "command.gitstudio.pr.merge.title": "合并拉取请求…", + "command.gitstudio.pr.openDescription.title": "打开拉取请求", + "command.gitstudio.pr.openOnGitHub.title": "在 GitHub 上打开", + "command.gitstudio.pr.refresh.title": "刷新拉取请求", + "command.gitstudio.pr.replyThread.title": "回复", + "command.gitstudio.pr.resolveThread.title": "解决对话", + "command.gitstudio.pr.signIn.title": "登录 GitHub", + "command.gitstudio.pr.startReview.title": "审查拉取请求", + "command.gitstudio.pr.submitReview.title": "提交审查", + "command.gitstudio.pr.unresolveThread.title": "取消解决对话", + "command.gitstudio.refreshBranches.title": "刷新分支", + "command.gitstudio.refreshCommits.title": "刷新提交", + "command.gitstudio.remoteBranch.checkout.title": "检出(创建本地跟踪分支)…", + "command.gitstudio.remoteBranch.delete.title": "删除远程分支", + "command.gitstudio.resetToCommit.title": "将当前分支重置到此处…", + "command.gitstudio.resolveInMergeEditor.title": "在合并编辑器中解决", + "command.gitstudio.revealCommitInGraph.title": "在图中显示提交", + "command.gitstudio.revisionNavigateBack.title": "修订:切换到更早", + "command.gitstudio.revisionNavigateForward.title": "修订:切换到更新", + "command.gitstudio.showCommitGraph.title": "显示提交图", + "command.gitstudio.showCommitPanel.title": "显示提交图", + "command.gitstudio.showConflicts.title": "解决冲突…", + "command.gitstudio.showLineHistory.title": "显示行历史", + "command.gitstudio.showReflog.title": "显示 Reflog(时间机器)", + "command.gitstudio.showUndoHistory.title": "显示撤销历史", + "command.gitstudio.showWelcome.title": "欢迎", + "command.gitstudio.stageHunk.title": "暂存区块", + "command.gitstudio.stageSelectedLines.title": "暂存所选行", + "command.gitstudio.stageWithTicks.title": "以勾选方式暂存更改", + "command.gitstudio.startInteractiveRebase.title": "开始交互式变基…", + "command.gitstudio.stash.apply.title": "应用贮藏…", + "command.gitstudio.stash.branch.title": "从贮藏创建分支…", + "command.gitstudio.stash.drop.title": "删除贮藏…", + "command.gitstudio.stash.pop.title": "弹出贮藏…", + "command.gitstudio.stash.save.title": "贮藏更改…", + "command.gitstudio.stashes.refresh.title": "刷新贮藏", + "command.gitstudio.support.title": "支持 GitStudio…", + "command.gitstudio.switchRepository.title": "切换仓库…", + "command.gitstudio.tag.checkout.title": "检出标签", + "command.gitstudio.tag.delete.title": "删除标签", + "command.gitstudio.tag.push.title": "推送标签…", + "command.gitstudio.toggleFileBlame.title": "用 Git Blame 注释", + "command.gitstudio.toggleStageAtLine.title": "暂存或取消暂存此行处的更改", + "command.gitstudio.undo.title": "撤销上一次 Git 操作", + "command.gitstudio.unstageHunk.title": "取消暂存区块", + "command.gitstudio.unstageSelectedLines.title": "取消暂存所选行", + "command.gitstudio.worktree.add.title": "新建工作树…", + "command.gitstudio.worktree.forget.title": "忘记工作树…", + "command.gitstudio.worktree.lock.title": "锁定工作树…", + "command.gitstudio.worktree.open.title": "打开工作树…", + "command.gitstudio.worktree.openHere.title": "在此窗口中打开工作树…", + "command.gitstudio.worktree.openInNewWindow.title": "在新窗口中打开工作树…", + "command.gitstudio.worktree.prune.title": "清理缺失的工作树…", + "command.gitstudio.worktree.remove.title": "移除工作树…", + "command.gitstudio.worktree.unlock.title": "解锁工作树…", + "command.gitstudio.worktrees.refresh.title": "刷新工作树", + "config.gitstudio.advanced.title": "高级", + "config.gitstudio.ai.anthropicModelDeep.description": "用于选择性深度推理的 Anthropic 模型 ID。", + "config.gitstudio.ai.anthropicModelFast.description": "用于快速/低成本任务(提交信息)的 Anthropic 模型 ID。", + "config.gitstudio.ai.anthropicModelMid.description": "用于中等复杂度任务(解释差异、总结)的 Anthropic 模型 ID。", + "config.gitstudio.ai.cliAgent.description": "要驱动的本地 agent CLI(使用它自己的登录,无需 API 密钥)。通过 GitStudio · AI 面板设置;当提供方为本地 agent 时使用。", + "config.gitstudio.ai.cliAgent.enumDescriptions.0": "不使用本地 agent。", + "config.gitstudio.ai.cliAgent.enumDescriptions.1": "Claude Code CLI(`claude`)。", + "config.gitstudio.ai.cliAgent.enumDescriptions.2": "OpenAI Codex CLI(`codex`)。", + "config.gitstudio.ai.cliAgent.enumDescriptions.3": "Gemini CLI(`gemini`)。", + "config.gitstudio.ai.cliModel.description": "传递给本地 agent CLI 的可选模型覆盖(留空 = 使用 CLI 的默认值)。", + "config.gitstudio.ai.commitStyle.description": "AI 生成的提交信息采用什么风格。", + "config.gitstudio.ai.commitStyle.enumDescriptions.0": "Conventional Commits(type(scope): 摘要),正文可选。", + "config.gitstudio.ai.commitStyle.enumDescriptions.1": "单行简洁的主题,不带正文。", + "config.gitstudio.ai.commitStyle.enumDescriptions.2": "祈使句主题,加上简短说明正文。", + "config.gitstudio.ai.openai.baseUrl.markdownDescription": "OpenAI 兼容端点的基础 URL(会追加 `/chat/completions`)。示例:`https://api.openai.com/v1`(OpenAI)、`https://openrouter.ai/api/v1`(OpenRouter)、`http://localhost:11434/v1`(Ollama)、`http://localhost:1234/v1`(LM Studio)。", + "config.gitstudio.ai.openai.modelDeep.description": "用于选择性深度推理的 OpenAI 兼容模型 ID。", + "config.gitstudio.ai.openai.modelFast.description": "用于快速/低成本任务(提交信息)的 OpenAI 兼容模型 ID。使用本地服务器时填它的模型名称,例如 llama3.1 或 qwen2.5-coder。", + "config.gitstudio.ai.openai.modelMid.description": "用于中等复杂度任务(解释差异、总结)的 OpenAI 兼容模型 ID。", + "config.gitstudio.ai.provider.enumDescriptions.0": "优先使用免密钥的 VS Code 语言模型(GitHub Copilot / Cursor)(如果可用);否则使用 Anthropic(如果已设置密钥),再否则使用 OpenAI 兼容端点(如果已配置模型)。", + "config.gitstudio.ai.provider.enumDescriptions.1": "使用 VS Code 语言模型 API — GitHub Copilot 或 Cursor 的模型,无需密钥。可通过“GitStudio:选择 AI 模型…”指定具体模型。", + "config.gitstudio.ai.provider.enumDescriptions.2": "直接使用 Anthropic(需要 API 密钥,请通过“GitStudio:连接 AI 提供方”设置)。", + "config.gitstudio.ai.provider.enumDescriptions.3": "使用任意 OpenAI 兼容端点 — OpenAI、Codex、OpenRouter,或本地服务器(Ollama / LM Studio)。在下方配置基础 URL 和模型;本地服务器可不需要密钥。", + "config.gitstudio.ai.provider.enumDescriptions.4": "使用本地 agent CLI — Claude Code、Codex 或 Gemini CLI — 用它自己的登录,无需 API 密钥。具体使用哪一个由 gitstudio.ai.cliAgent 决定;可通过“GitStudio:连接 AI 提供方”选择。", + "config.gitstudio.ai.provider.enumDescriptions.5": "禁用所有 AI 功能。", + "config.gitstudio.ai.provider.markdownDescription": "GitStudio 的可选 AI 功能使用哪个提供方。在有可用提供方之前 AI 处于关闭状态;它绝不会阻碍或破坏 Git 操作。可用 **GitStudio:选择 AI 模型…** 打开引导式选择器。", + "config.gitstudio.ai.reviewPrompt.markdownDescription": "用于 **审查更改(AI)** 的自定义系统提示。留空则使用 GitStudio 内置的代码审查提示。设置自己的提示可引导审查(例如关注点、团队风格、输出格式)。", + "config.gitstudio.ai.title": "AI", + "config.gitstudio.avatars.gravatar.markdownDescription": "在提交图、提交视图和提交详情中显示提交作者的头像。为了找到头像,GitStudio 会将每位作者邮箱地址的 MD5 哈希发送给 Gravatar(`www.gravatar.com`,由 Automattic 运营);对于 GitHub 的 noreply 地址(`…@users.noreply.github.com`),它会改为向 GitHub(`avatars.githubusercontent.com`)请求该账号的头像。关闭此项后,每位作者都会以彩色姓名缩写显示,并且不会发送任何请求。当你登录 GitHub 时,GitHub 自己返回的图片(在拉取请求上,以及 GitHub 仓库近期提交的作者)仍会显示。参见 [PRIVACY.md](https://github.com/GitStudioHQ/gitstudio/blob/main/apps/extension/PRIVACY.md)。", + "config.gitstudio.blame.clickOpensCommit.description": "显示 blame 注释时,点击某条注释会在代码旁边打开的 GitStudio 提交图中显示该提交。", + "config.gitstudio.blame.gutter.colors.description": "blame 注释栏的背景色调。", + "config.gitstudio.blame.gutter.colors.enumDescriptions.0": "按提交时间着色 — 代码年龄热力图(较新偏暖,较旧偏冷)。", + "config.gitstudio.blame.gutter.colors.enumDescriptions.1": "为每位作者指定各自稳定的色调。", + "config.gitstudio.blame.gutter.colors.enumDescriptions.2": "不使用背景色调。", + "config.gitstudio.blame.gutter.fields.description": "blame 注释栏显示哪些列。可通过注释右键菜单配置:Git Blame 注释 → 选项。", + "config.gitstudio.blame.gutter.nameStyle.description": "blame 注释栏中作者姓名的写法。", + "config.gitstudio.blame.gutter.nameStyle.enumDescriptions.0": "AA", + "config.gitstudio.blame.gutter.nameStyle.enumDescriptions.1": "Arnaudov", + "config.gitstudio.blame.gutter.nameStyle.enumDescriptions.2": "Anton", + "config.gitstudio.blame.gutter.nameStyle.enumDescriptions.3": "Anton Arnaudov", + "config.gitstudio.blame.gutter.nameStyle.enumDescriptions.4": "anton@example.com", + "config.gitstudio.blame.heatmap.description": "用代码年龄热力图给整文件的 blame 注释着色(较新的更改偏暖,较旧的偏冷)。", + "config.gitstudio.blame.inlineEnabled.description": "在行尾显示当前行的内联 blame(作者、相对时间和摘要)。", + "config.gitstudio.blame.showDiffOnHover.description": "悬停在某一行时显示它背后的提交 — 信息、作者、日期和可复制的 SHA。", + "config.gitstudio.blame.statusBarEnabled.description": "在状态栏显示当前行的提交作者和年龄。", + "config.gitstudio.blame.title": "Blame", + "config.gitstudio.changes.autoRefresh.description": "让“更改”列表自动保持最新 — 在你保存文件后,以及窗口重新获得焦点时(这样其他工具所做的编辑也会显示出来)。在非常大的仓库中可关闭此项,改为按需刷新。", + "config.gitstudio.changes.stagingModel.description": "“更改”视图如何呈现你的工作。无论哪种方式,在未勾选或未暂存任何内容时提交,都会先询问然后再提供提交全部内容。", + "config.gitstudio.changes.stagingModel.enumDescriptions.0": "分开的“已暂存”和“未暂存”分组 — 最清楚地展示本次提交包含什么。", + "config.gitstudio.changes.stagingModel.enumDescriptions.1": "单一列表,每个文件一个勾选框,JetBrains 风格。勾选文件即暂存它,因此两种模式下的底层 Git 状态相同。", + "config.gitstudio.changes.title": "更改与暂存", + "config.gitstudio.changesBadge.description": "在 GitStudio 活动栏图标上显示工作树中已更改文件的数量徽标(类似内置的源代码管理徽标)。工具提示还会报告等待拉取的提交数。", + "config.gitstudio.commit.signoffByDefault.description": "在 GitStudio 提交框中默认启用“签名”开关(添加 Signed-off-by 尾注)。", + "config.gitstudio.commit.title": "提交与同步", + "config.gitstudio.debug.logChildProcesses.description": "将 GitStudio 启动的每个子进程 - 二进制文件、完整参数、工作目录,以及 GitStudio 添加的环境变量 - 记录到“GitStudio: 进程审核”输出通道。仅在你复现想要报告的问题时开启:它是把子进程(凭据助手、git 钩子、编辑器二进制)触发的操作系统级提示追溯到确切命令的方式。看起来像密钥的值会被清除。", + "config.gitstudio.errorReporting.enabled.markdownDescription": "当 GitStudio 命令失败时发送**匿名、已清洗的崩溃报告**,以便我们在测试期间发现并修复缺陷,而不必等待有人提交报告。只发送失败的形态(错误类型/信息/堆栈,或失败的操作),并附带随机安装 ID 和你的操作系统/编辑器版本;发送前会先清洗:路径、文件和分支名、提交主题、邮箱、令牌以及远程仓库名称,只要是能识别的都会被移除(远程的主机名,例如 github.com,会保留)。参见 [PRIVACY.md](https://github.com/GitStudioHQ/gitstudio/blob/main/apps/extension/PRIVACY.md)。报告还受 VS Code 全局 `telemetry.telemetryLevel` 控制:将它设为 `off` 可在不依赖此开关的情况下禁用。关闭此项即完全退出。", + "config.gitstudio.errorReporting.endpoint.markdownDescription": "以纯 JSON 正文 POST 匿名崩溃报告的收集器 URL。默认使用 GitStudio 的收集器;可将其指向你控制的任意端点,或**留空以完全禁用发送**。如果无法访问,报告会静默地不执行任何操作。", + "config.gitstudio.fetch.prune.description": "在获取时传入 --prune,这样在远程被删除的远程跟踪分支会从分支列表中消失,而不会作为陈旧条目残留。绝不会影响本地分支。", + "config.gitstudio.general.title": "常规", + "config.gitstudio.merge.autoApplyNonConflicting.description": "打开合并编辑器时已应用所有不冲突的更改(JetBrains 的“打开时应用不冲突的更改”)。关闭:它们会等你处理,可逐个点击或从工具栏一次性全部应用。", + "config.gitstudio.merge.autoOpen.markdownDescription": "当合并、变基、拣选、还原、git am 或贮藏弹出因冲突而停止时:显示**冲突**面板,在你切换到某个冲突文件时立即在 GitStudio 合并编辑器中打开它,并接管 VS Code 内置的合并编辑器标签页。关闭:不会自动打开任何东西 — 请使用 **GitStudio:解决冲突…**。(这在过去会把每个冲突文件作为独立标签页打开。)如果同时安装了 Merge Studio,它会把这交给 GitStudio;关闭此项可让 Merge Studio 改为打开冲突。", + "config.gitstudio.merge.title": "合并与差异", + "config.gitstudio.pr.defaultMergeMethod.description": "合并拉取请求时首先提供的默认方式。", + "config.gitstudio.pr.defaultMergeMethod.enumDescriptions.0": "创建一个合并提交。", + "config.gitstudio.pr.defaultMergeMethod.enumDescriptions.1": "将 PR 的提交压缩为一个并合并。", + "config.gitstudio.pr.defaultMergeMethod.enumDescriptions.2": "将 PR 的提交变基到基点上并合并。", + "config.gitstudio.staging.clickGutterToggles.description": "通过点击更改旁边的装订线来暂存或取消暂存。默认关闭:VS Code 不给装饰提供点击事件,因此这是从点击落在行首推断出来的 — 而这同样是放置光标的方式。它绝不会在没有更改的行上触发,并且在显示 blame 注释时会让位。", + "config.gitstudio.staging.showGutterState.description": "在编辑器装订线中显示哪些更改已暂存。该图标只报告状态 — VS Code 的 API 不允许扩展让装订线图标可点击。可通过快捷键、右键点击其行号,或在 GitStudio 自己的差异页上切换更改。", + "config.gitstudio.statusBar.showGraph.description": "显示一个打开提交图的状态栏按钮。", + "config.gitstudio.statusBar.showTerminal.description": "显示一个状态栏按钮,打开一个已位于活动仓库根目录的终端 — 该目录不一定是工作区根目录。", + "config.gitstudio.worktrees.prefixWithProjectName.description": "已不再使用:新建工作树现在会在主工作树旁边建议文件夹“-”,你可以在创建前编辑它。", + "customEditor.gitstudio.mergeEditor.displayName": "GitStudio 三栏合并", + "customEditor.gitstudio.rebaseTodoEditor.displayName": "GitStudio 交互式变基", + "description": "免费、开源的 VS Code 和 Cursor Git 图形界面与提交图。Git Studio 把 JetBrains 风格的 Git 工作流带入编辑器 — 行内 blame、文件历史、区块与行暂存、三栏合并、带通用撤销的交互式变基、贮藏/搁置、工作树,以及在编辑器内的 GitHub PR。GitLens、GitKraken 与 Sourcetree 的免费替代品。", + "displayName": "GitStudio — JetBrains 风格的 Git 图、Blame 与合并", + "submenu.gitstudio.blame.annotationsMenu.label": "Git Blame 注释", + "submenu.gitstudio.blame.colorsMenu.label": "颜色", + "submenu.gitstudio.blame.namesMenu.label": "姓名", + "submenu.gitstudio.blame.optionsMenu.label": "选项", + "submenu.gitstudio.editorMenu.label": "GitStudio", + "view.gitstudio.commit.name": "更改", + "view.gitstudio.commitPanel.name": "提交图", + "view.gitstudio.commits.name": "提交", + "view.gitstudio.pullRequests.name": "拉取请求", + "view.gitstudio.worktrees.name": "工作树", + "viewContainer.gitstudio.title": "GitStudio", + "viewContainer.gitstudioPanel.title": "提交图", + "walkthrough.gitstudio.gettingStarted.description": "免费的 JetBrains 级 Git 套件 — 提交图、blame、历史、区块暂存、三栏合并、带撤销的交互式变基,以及可选的 BYO 密钥 AI。开始导览。", + "walkthrough.gitstudio.gettingStarted.gitstudio.walkthrough.blame.altText": "从一行 blame 打开的提交:它的作者、信息、所在分支以及更改过的文件,显示在图的旁边", + "walkthrough.gitstudio.gettingStarted.gitstudio.walkthrough.blame.description": "你所在的那一行最后是谁在什么时候改的 — 显示在行尾和状态栏中。**用 Git Blame 注释** 会在每一行旁添加一列,并按时间着色;点击某条注释,其提交会在图中打开,显示信息、作者以及它更改过的文件。\n[用 Git Blame 注释](command:gitstudio.toggleFileBlame)\n快捷键:在任何编辑器中的 __Ctrl/Cmd+Alt+G B__。", + "walkthrough.gitstudio.gettingStarted.gitstudio.walkthrough.blame.title": "看看谁改了这一行,以及为什么", + "walkthrough.gitstudio.gettingStarted.gitstudio.walkthrough.connect.altText": "AI 设置:编辑器自带的 AI 已连接并就绪,以及其他连接模型的方式", + "walkthrough.gitstudio.gettingStarted.gitstudio.walkthrough.connect.description": "使用 VS Code 内置的 GitHub 账号登录一次,即可在编辑器内列出、检出、审查、合并和创建拉取请求。AI 是可选的:如果有 Copilot(或 Cursor)的模型,它会直接使用,无需任何设置;否则可连接 Anthropic、OpenAI 兼容端点或本地 agent CLI,用于提交信息、解释此差异和总结。它绝不会阻碍任何 Git 操作,而“禁用 AI 功能”可以关闭它。\n[登录 GitHub](command:gitstudio.pr.signIn)\n[连接 AI 提供方](command:gitstudio.ai.connect)\nGitStudio 免费且开源。[支持 GitStudio…](command:gitstudio.support)", + "walkthrough.gitstudio.gettingStarted.gitstudio.walkthrough.connect.title": "连接 GitHub 并设置 AI(可选)", + "walkthrough.gitstudio.gettingStarted.gitstudio.walkthrough.graph.altText": "提交图:分支泳道、分支和标签的标记,以及 main、一个功能分支和一个发布分支上各提交的作者", + "walkthrough.gitstudio.gettingStarted.gitstudio.walkthrough.graph.description": "以提交图呈现你的历史:分支用彩色泳道、分支和标签用标记,并显示每个提交是谁写的。它位于 GitStudio 侧边栏“更改”下方的 **提交** 视图中,也位于终端旁的 **提交图** 面板中。右键点击提交可检出、拣选、以此创建分支或重置到它;选中两个可进行比较。\n[显示提交图](command:gitstudio.showCommitGraph)", + "walkthrough.gitstudio.gettingStarted.gitstudio.walkthrough.graph.title": "在提交图中浏览你的历史", + "walkthrough.gitstudio.gettingStarted.gitstudio.walkthrough.history.altText": "某个文件两行的行历史:更改过它们的三个提交,及其作者和时间", + "walkthrough.gitstudio.gettingStarted.gitstudio.walkthrough.history.description": "更改过你所选行的每一个提交,最新的在前 — 选一个即可查看其差异。可将整个文件在其各个修订之间前后切换,并在 reflog 中找回丢失的工作。\n[显示行历史](command:gitstudio.showLineHistory)\n快捷键:当前行上的 __Ctrl/Cmd+Alt+G H__。", + "walkthrough.gitstudio.gettingStarted.gitstudio.walkthrough.history.title": "探索文件与行历史", + "walkthrough.gitstudio.gettingStarted.gitstudio.walkthrough.merge.altText": "在某个冲突处停下的三栏合并编辑器:来自 main 的更改、结果,以及来自 feature 的更改", + "walkthrough.gitstudio.gettingStarted.gitstudio.walkthrough.merge.description": "当合并、变基或拣选因冲突而停止时,GitStudio 会打开三栏编辑器 — 你的一侧、结果和对方的一侧 — 在其中用箭头把某个更改放进结果。交互式变基也享受同样的照顾。\n[开始交互式变基…](command:gitstudio.startInteractiveRebase)\n弄错了?__撤销上一次 Git 操作__(Ctrl/Cmd+Alt+G Z)会将其撤销。", + "walkthrough.gitstudio.gettingStarted.gitstudio.walkthrough.merge.title": "在三栏编辑器中解决冲突", + "walkthrough.gitstudio.gettingStarted.gitstudio.walkthrough.stage.altText": "带勾选框的“更改”视图:某个文件的更改已展开,其中一项被勾选,提交信息已就绪", + "walkthrough.gitstudio.gettingStarted.gitstudio.walkthrough.stage.description": "在 **更改** 视图中暂存整个文件,或勾选文件中的单个更改,然后从其提交框提交(修正、签名、其他作者、提交并推送)。开启 AI 后,提交框中的闪光按钮会根据你暂存的内容起草一条信息。你的贮藏列在更改下方:打开一个即可看到它包含的每个文件,并用 **移入更改** 只取回你想要的文件。\n[打开“更改”视图](command:workbench.view.extension.gitstudio)\n在编辑器中:选中若干行并按 __Ctrl/Cmd+Alt+G S__ 可暂存它们涉及的更改。", + "walkthrough.gitstudio.gettingStarted.gitstudio.walkthrough.stage.title": "暂存更改并提交", + "walkthrough.gitstudio.gettingStarted.title": "开始使用 GitStudio" +} diff --git a/apps/extension/src/ai/aiCommands.ts b/apps/extension/src/ai/aiCommands.ts index d20b827e..245a325f 100644 --- a/apps/extension/src/ai/aiCommands.ts +++ b/apps/extension/src/ai/aiCommands.ts @@ -8,10 +8,12 @@ import { OPENAI_KEY_SECRET, } from "./aiFeatures"; import { getNonce } from "../webview/html"; +import * as l10n from "@vscode/l10n"; +import { l10nWebviewScript } from "@gitstudio/l10n/index"; /** Shown in a result panel when no model is connected / the request was declined. */ const UNAVAILABLE_MESSAGE = - "No AI model is connected. Connect one from the ✨ button in the Changes view, then try again."; + l10n.t("No AI model is connected. Connect one from the ✨ button in the Changes view, then try again."); // Command implementations for the AI layer: key management // (SecretStorage — never sent to a webview), the seamless model picker, and the @@ -26,10 +28,10 @@ export async function setApiKey( brain: AiFeatures, ): Promise { const key = await promptInput({ - title: "Set Anthropic API Key", - hint: "Encrypted at rest in GitStudio's own store — not your OS keychain, so it never raises a password prompt. The key stays host-side and is never sent to a webview.", + title: l10n.t("Set Anthropic API Key"), + hint: l10n.t("Encrypted at rest in GitStudio's own store — not your OS keychain, so it never raises a password prompt. The key stays host-side and is never sent to a webview."), placeholder: "sk-ant-…", - confirmLabel: "Save Key", + confirmLabel: l10n.t("Save Key"), secret: true, }); if (key === undefined) { @@ -37,12 +39,12 @@ export async function setApiKey( } const trimmed = key.trim(); if (trimmed.length === 0) { - void vscode.window.showWarningMessage("GitStudio: no key entered."); + void vscode.window.showWarningMessage(l10n.t("GitStudio: no key entered.")); return; } await brain.setAnthropicKey(trimmed); void vscode.window.showInformationMessage( - "GitStudio: Anthropic API key saved. AI features are now available.", + l10n.t("GitStudio: Anthropic API key saved. AI features are now available."), ); } @@ -53,7 +55,7 @@ export async function clearApiKey( ): Promise { await brain.clearAnthropicKey(); void vscode.window.showInformationMessage( - "GitStudio: Anthropic API key cleared.", + l10n.t("GitStudio: Anthropic API key cleared."), ); } @@ -66,10 +68,10 @@ export async function setOpenAIKey( brain: AiFeatures, ): Promise { const key = await promptInput({ - title: "Set OpenAI API Key", - hint: "For OpenAI / Codex / OpenRouter. Leave blank for a local, keyless server (Ollama / LM Studio). Encrypted at rest in GitStudio's own store and never sent to a webview.", - placeholder: "sk-… (blank for a local, keyless server)", - confirmLabel: "Save Key", + title: l10n.t("Set OpenAI API Key"), + hint: l10n.t("For OpenAI / Codex / OpenRouter. Leave blank for a local, keyless server (Ollama / LM Studio). Encrypted at rest in GitStudio's own store and never sent to a webview."), + placeholder: l10n.t("sk-… (blank for a local, keyless server)"), + confirmLabel: l10n.t("Save Key"), secret: true, }); if (key === undefined) { @@ -79,13 +81,13 @@ export async function setOpenAIKey( if (trimmed.length === 0) { await brain.clearOpenAiKey(); void vscode.window.showInformationMessage( - "GitStudio: OpenAI API key cleared (keyless / local mode).", + l10n.t("GitStudio: OpenAI API key cleared (keyless / local mode)."), ); return; } await brain.setOpenAiKey(trimmed); void vscode.window.showInformationMessage( - "GitStudio: OpenAI API key saved.", + l10n.t("GitStudio: OpenAI API key saved."), ); } @@ -96,7 +98,7 @@ export async function clearOpenAIKey( ): Promise { await brain.clearOpenAiKey(); void vscode.window.showInformationMessage( - "GitStudio: OpenAI API key cleared.", + l10n.t("GitStudio: OpenAI API key cleared."), ); } @@ -216,23 +218,24 @@ export async function generateCommitMessageCommand( return; } const message = await vscode.window.withProgress( - { location: vscode.ProgressLocation.Window, title: "Drafting a commit message with AI…" }, + { location: vscode.ProgressLocation.Window, title: l10n.t("Drafting a commit message with AI…") }, () => draftCommitMessage(brain, entry), ); if (!message) { void vscode.window.showInformationMessage( - "GitStudio: nothing staged, or AI is unavailable.", + l10n.t("GitStudio: nothing staged, or AI is unavailable."), ); return; } + const copy = l10n.t("Copy"); const action = await vscode.window.showInformationMessage( message, { modal: false }, - "Copy", + copy, ); - if (action === "Copy") { + if (action === copy) { await vscode.env.clipboard.writeText(message); - void vscode.window.setStatusBarMessage("$(check) Commit message copied", 2000); + void vscode.window.setStatusBarMessage(l10n.t("$(check) Commit message copied"), 2000); } } @@ -245,7 +248,7 @@ async function generateForSourceControl( const entry = resolveRepoForSourceControl(repos, sourceControl); if (!entry) { void vscode.window.showInformationMessage( - "GitStudio: couldn't match this Source Control repository.", + l10n.t("GitStudio: couldn't match this Source Control repository."), ); return; } @@ -254,12 +257,12 @@ async function generateForSourceControl( return; } const drafted = await vscode.window.withProgress( - { location: vscode.ProgressLocation.SourceControl, title: "Drafting a commit message with AI…" }, + { location: vscode.ProgressLocation.SourceControl, title: l10n.t("Drafting a commit message with AI…") }, () => draftCommitMessageWithFallback(brain, entry), ); if (!drafted) { void vscode.window.showInformationMessage( - "GitStudio: nothing to draft (stage changes first), or AI is unavailable.", + l10n.t("GitStudio: nothing to draft (stage changes first), or AI is unavailable."), ); return; } @@ -268,7 +271,7 @@ async function generateForSourceControl( } if (drafted.unstaged) { void vscode.window.setStatusBarMessage( - "$(sparkle) Drafted from unstaged changes (nothing was staged)", + l10n.t("$(sparkle) Drafted from unstaged changes (nothing was staged)"), 4000, ); } @@ -312,11 +315,12 @@ function asSourceControl(arg: unknown): SourceControlLike | undefined { /** Offer a one-click path into the model picker when no provider is set up. */ async function offerAiSetup(): Promise { + const selectLabel = l10n.t("Select AI Model…"); const choice = await vscode.window.showInformationMessage( - notice("Set up AI to draft commit messages"), - "Select AI Model…", + notice(l10n.t("Set up AI to draft commit messages")), + selectLabel, ); - if (choice === "Select AI Model…") { + if (choice === selectLabel) { await vscode.commands.executeCommand("gitstudio.ai.selectModel"); } } @@ -336,22 +340,22 @@ export async function selectModelCommand( const lmModels = await brain.listLmModels(); for (const m of lmModels) { - const vendor = m.vendor || "Language Model"; + const vendor = m.vendor || l10n.t("Language Model"); const family = m.family || m.name || m.id; choices.push({ id: `lm:${m.id}`, label: `${vendor} · ${family}`, icon: "sparkle", detail: m.name && m.name !== family ? m.name : undefined, - description: "VS Code Language Model (zero-key) — Copilot / Cursor", + description: l10n.t("VS Code Language Model (zero-key) — Copilot / Cursor"), }); } choices.push({ id: "anthropic", - label: "Claude (Anthropic)", + label: l10n.t("Claude (Anthropic)"), icon: "key", - description: "Use Anthropic directly with your API key.", + description: l10n.t("Use Anthropic directly with your API key."), }); const baseUrl = vscode.workspace @@ -359,16 +363,16 @@ export async function selectModelCommand( .get("openai.baseUrl", "https://api.openai.com/v1"); choices.push({ id: "openai", - label: "OpenAI / local (OpenAI-compatible)", + label: l10n.t("OpenAI / local (OpenAI-compatible)"), icon: "server", detail: baseUrl, description: - "OpenAI, Codex, OpenRouter, or a local server (Ollama / LM Studio). Base URL / model / key.", + l10n.t("OpenAI, Codex, OpenRouter, or a local server (Ollama / LM Studio). Base URL / model / key."), }); const pick = await promptPick({ - title: "Select AI Model", - hint: "Which model should the AI features use?", + title: l10n.t("Select AI Model"), + hint: l10n.t("Which model should the AI features use?"), choices, }); if (!pick) { @@ -382,7 +386,7 @@ export async function selectModelCommand( await cfg.update("provider", "copilot", vscode.ConfigurationTarget.Global); await brain.refreshEnabled(); const label = choices.find((c) => c.id === pick)?.label ?? modelId; - void vscode.window.showInformationMessage(`GitStudio: using ${label}.`); + void vscode.window.showInformationMessage(l10n.t("GitStudio: using {0}.", label)); return; } @@ -393,7 +397,7 @@ export async function selectModelCommand( } else { await brain.refreshEnabled(); void vscode.window.showInformationMessage( - "GitStudio: using Claude (Anthropic).", + l10n.t("GitStudio: using Claude (Anthropic)."), ); } return; @@ -411,10 +415,10 @@ async function configureOpenAi( cfg: vscode.WorkspaceConfiguration, ): Promise { const baseUrl = await promptInput({ - title: "OpenAI-compatible Base URL", + title: l10n.t("OpenAI-compatible Base URL"), hint: "https://api.openai.com/v1 · http://localhost:11434/v1 (Ollama) · http://localhost:1234/v1 (LM Studio)", value: cfg.get("openai.baseUrl", "https://api.openai.com/v1"), - confirmLabel: "Continue", + confirmLabel: l10n.t("Continue"), validate: "url", }); if (baseUrl === undefined) { @@ -429,10 +433,10 @@ async function configureOpenAi( } const model = await promptInput({ - title: "OpenAI-compatible Model", - hint: "Model ID for commit messages and explain — gpt-4o-mini, llama3.1, qwen2.5-coder.", + title: l10n.t("OpenAI-compatible Model"), + hint: l10n.t("Model ID for commit messages and explain — gpt-4o-mini, llama3.1, qwen2.5-coder."), value: cfg.get("openai.modelFast", ""), - confirmLabel: "Continue", + confirmLabel: l10n.t("Continue"), }); if (model === undefined) { return; // cancelled @@ -484,12 +488,12 @@ export async function explainDiffCommand( } const diff = await activeDiff(entry); if (diff.trim().length === 0) { - void vscode.window.showInformationMessage("GitStudio: no diff to explain."); + void vscode.window.showInformationMessage(l10n.t("GitStudio: no diff to explain.")); return; } - const panel = createResultPanel("Explain Diff", "What this change does, in plain language"); - panel.postStatus("Reading the diff…"); + const panel = createResultPanel(l10n.t("Explain Diff"), l10n.t("What this change does, in plain language")); + panel.postStatus(l10n.t("Reading the diff…")); const source = new vscode.CancellationTokenSource(); panel.onDidDispose(() => source.cancel()); const controller = new AbortController(); @@ -523,14 +527,14 @@ export async function summarizeChangesCommand( } const diff = await activeDiff(entry); if (diff.trim().length === 0) { - void vscode.window.showInformationMessage("GitStudio: no changes to summarize."); + void vscode.window.showInformationMessage(l10n.t("GitStudio: no changes to summarize.")); return; } - const panel = createResultPanel("Summarize Changes", "A high-level summary of your current changes"); - panel.postStatus("Summarizing your changes…"); + const panel = createResultPanel(l10n.t("Summarize Changes"), l10n.t("A high-level summary of your current changes")); + panel.postStatus(l10n.t("Summarizing your changes…")); const result = await vscode.window.withProgress( - { location: vscode.ProgressLocation.Window, title: "Summarizing with AI…" }, + { location: vscode.ProgressLocation.Window, title: l10n.t("Summarizing with AI…") }, () => brain.summarizeChanges(diff), ); if (result) { @@ -555,13 +559,13 @@ export async function reviewChangesCommand( const diff = await activeDiff(entry); if (diff.trim().length === 0) { void vscode.window.showInformationMessage( - "GitStudio: no changes to review — stage or edit some files first.", + l10n.t("GitStudio: no changes to review — stage or edit some files first."), ); return; } - const panel = createResultPanel("Code Review", "AI review of your current changes"); - panel.postStatus("Reviewing your changes…"); + const panel = createResultPanel(l10n.t("Code Review"), l10n.t("AI review of your current changes")); + panel.postStatus(l10n.t("Reviewing your changes…")); const source = new vscode.CancellationTokenSource(); panel.onDidDispose(() => source.cancel()); const controller = new AbortController(); @@ -578,7 +582,7 @@ export async function reviewChangesCommand( ); if (result === null && acc.trim().length === 0) { panel.postStatus( - "No AI model is connected. Connect one from the ✨ button in the Changes view, then run the review again.", + l10n.t("No AI model is connected. Connect one from the ✨ button in the Changes view, then run the review again."), "error", ); } else if (result !== null) { @@ -648,7 +652,7 @@ function createResultPanel(title: string, subtitle = ""): ResultPanel { function resultHtml(nonce: string, title: string, subtitle: string): string { const csp = [ - `default-src 'none'`, + "default-src 'none'", `style-src 'nonce-${nonce}'`, `script-src 'nonce-${nonce}'`, ].join("; "); @@ -844,9 +848,9 @@ function resultHtml(nonce: string, title: string, subtitle: string): string {
-
@@ -855,6 +859,7 @@ function resultHtml(nonce: string, title: string, subtitle: string): string {
+ ${l10nWebviewScript(nonce)} `; const changeRowsCss = readFileSync(join(ROOT, "packages", "webview-ui", "src", "changeRows", "changeRows.css"), "utf8"); - return template() - .replace("${csp}", "default-src * 'unsafe-inline' file: data:") - .replace("${codiconUri}", () => codicons) - .replace("${tokensCss}", () => tokens) - .replace("${changeRowsCss}", () => changeRowsCss) - .replace("${changeRowsUri}", () => changeRowsScript()) - .split("${nonce}").join("harness") + const holes: Record = { + csp: "default-src * 'unsafe-inline' file: data:", + codiconUri: codicons, + nonce: "harness", + tokensCss: tokens, + changeRowsCss, + changeRowsUri: changeRowsScript(), + // The words and the bundle: see pageHoles.ts. + ...l10nHoles("harness"), + }; + return filledTemplate("commitView.ts html()", SRC, "", holes, opts.messages) .replace('', () => ``) .replace("", () => `${prelude}\n`) .replace("", () => `${harness}\n`); diff --git a/apps/extension/test/commandReferences.test.ts b/apps/extension/test/commandReferences.test.ts index 059121ab..21b65ef6 100644 --- a/apps/extension/test/commandReferences.test.ts +++ b/apps/extension/test/commandReferences.test.ts @@ -14,9 +14,10 @@ import { test } from "node:test"; import assert from "node:assert/strict"; import { readdirSync, readFileSync, statSync } from "node:fs"; import { join, relative } from "node:path"; +import { readManifest } from "./manifest"; const ROOT = join(__dirname, ".."); -const pkg = JSON.parse(readFileSync(join(ROOT, "package.json"), "utf8")) as { +const pkg = readManifest() as { contributes: { commands: { command: string; title: string; category?: string }[]; walkthroughs: { steps: { id: string; description: string; completionEvents?: string[] }[] }[]; diff --git a/apps/extension/test/comparePanelRepaint.test.ts b/apps/extension/test/comparePanelRepaint.test.ts index 9cf7244c..895e9cdc 100644 --- a/apps/extension/test/comparePanelRepaint.test.ts +++ b/apps/extension/test/comparePanelRepaint.test.ts @@ -2,6 +2,7 @@ import { test } from "node:test"; import assert from "node:assert/strict"; import { readFileSync } from "node:fs"; import { join } from "node:path"; +import "./webviewL10n"; // Issue #24: "expanded file diffs collapse on their own … about every 30 // seconds to 2 minutes even when neither branch is changing." diff --git a/apps/extension/test/compareStatePersist.test.ts b/apps/extension/test/compareStatePersist.test.ts index d0251251..d22374bc 100644 --- a/apps/extension/test/compareStatePersist.test.ts +++ b/apps/extension/test/compareStatePersist.test.ts @@ -2,6 +2,7 @@ import { test } from "node:test"; import assert from "node:assert/strict"; import { readFileSync } from "node:fs"; import { join } from "node:path"; +import "./webviewL10n"; // Issue #24's second half: surviving the repaints that MUST happen. When the // comparison really changed, the webview's html is replaced and every module diff --git a/apps/extension/test/docsClaims.test.ts b/apps/extension/test/docsClaims.test.ts index 77cfbfc0..d2330a0c 100644 --- a/apps/extension/test/docsClaims.test.ts +++ b/apps/extension/test/docsClaims.test.ts @@ -15,12 +15,13 @@ import { test } from "node:test"; import assert from "node:assert/strict"; import { readdirSync, readFileSync, statSync } from "node:fs"; import { join } from "node:path"; +import { readManifest } from "./manifest"; import { configurationProperties } from "@gitstudio/merge-vscode/contract"; const ROOT = join(__dirname, ".."); const readme = readFileSync(join(ROOT, "README.md"), "utf8"); const manifestText = readFileSync(join(ROOT, "package.json"), "utf8"); -const pkg = JSON.parse(manifestText) as { +const pkg = readManifest() as { contributes: { keybindings: { command: string; key: string; mac?: string }[]; configuration: unknown; diff --git a/apps/extension/test/dropCommit.test.ts b/apps/extension/test/dropCommit.test.ts index 4de79804..12b15991 100644 --- a/apps/extension/test/dropCommit.test.ts +++ b/apps/extension/test/dropCommit.test.ts @@ -421,7 +421,7 @@ test("the reorder's carry is undone with its branches too (graphPanel cannot loa // "Reorder and move those branches" carries go back with it, as a drop's // do above. The behaviour is the Undo state table's E37 (undoStateTable). const src = readFileSync(join(__dirname, "../src/graph/graphPanel.ts"), "utf8"); - assert.match(src, /ledger\.runWithUndo\(active, `Reorder \$\{order\.length\} commits`, run\)/); + assert.match(src, /ledger\.runWithUndo\(active, l10n\.t\("Reorder \{0\} commits", order\.length\), run\)/); }); test("Undo restores the original tip after dropping a middle commit", async () => { diff --git a/apps/extension/test/editorMenus.test.ts b/apps/extension/test/editorMenus.test.ts index 5870b153..3d371833 100644 --- a/apps/extension/test/editorMenus.test.ts +++ b/apps/extension/test/editorMenus.test.ts @@ -12,6 +12,7 @@ import { test } from "node:test"; import assert from "node:assert/strict"; import { readFileSync } from "node:fs"; import { join } from "node:path"; +import { readAppManifest } from "./manifest"; type Item = { command?: string; submenu?: string; when?: string; group?: string }; interface Manifest { @@ -21,8 +22,7 @@ interface Manifest { submenus: { id: string; label: string }[]; }; } -const read = (app: string) => - JSON.parse(readFileSync(join(__dirname, "..", "..", app, "package.json"), "utf8")) as Manifest; +const read = (app: string) => readAppManifest(join(__dirname, "..", "..", app)); const gs = read("extension"); const ms = read("merge-studio"); diff --git a/apps/extension/test/errorAttribution.test.ts b/apps/extension/test/errorAttribution.test.ts index 1a010c72..cf99ac41 100644 --- a/apps/extension/test/errorAttribution.test.ts +++ b/apps/extension/test/errorAttribution.test.ts @@ -2,6 +2,7 @@ import { test } from "node:test"; import assert from "node:assert/strict"; import { readFile } from "node:fs/promises"; import { fileURLToPath } from "node:url"; +import "./webviewL10n"; // `isAttributable` decides whether a process-wide failure gets transmitted off // the user's machine, so it is the privacy boundary of the whole reporter. diff --git a/apps/extension/test/graphAvatarPrefs.test.ts b/apps/extension/test/graphAvatarPrefs.test.ts index 445acf74..88aacd1b 100644 --- a/apps/extension/test/graphAvatarPrefs.test.ts +++ b/apps/extension/test/graphAvatarPrefs.test.ts @@ -12,6 +12,7 @@ import assert from "node:assert/strict"; import Module from "node:module"; import { join } from "node:path"; import { readFileSync } from "node:fs"; +import { readManifest } from "./manifest"; type Resolver = { _resolveFilename: (request: unknown, ...rest: unknown[]) => string }; const resolver = Module as unknown as Resolver; @@ -137,7 +138,7 @@ test("changing the setting reaches an open page at once; another setting, or a p }); test("the setting is declared as it is documented: on by default, and it says what goes where", () => { - const pkg = JSON.parse(readFileSync(join(__dirname, "..", "package.json"), "utf8")) as { + const pkg = readManifest() as { contributes: { configuration: Array<{ title: string; properties: Record }> }; }; const general = pkg.contributes.configuration.find((c) => c.title === "General"); diff --git a/apps/extension/test/inTheWayCallSites.test.ts b/apps/extension/test/inTheWayCallSites.test.ts index b717a884..9066928f 100644 --- a/apps/extension/test/inTheWayCallSites.test.ts +++ b/apps/extension/test/inTheWayCallSites.test.ts @@ -170,8 +170,8 @@ test("the door asks Stash & Retry or Cancel, in the engine's words, and files no .join("\n"); assert.match(code, /runApplying\(/, "recognised by the engine, from git's state"); assert.match(code, /changesInTheWayMessage\(/, "said in the engine's words — which files, in the way of what"); - assert.match(code, /label:\s*"Stash & Retry"/); - assert.match(code, /label:\s*"Cancel"/); + assert.match(code, /label:\s*l10n\.t\("Stash & Retry"\)/); + assert.match(code, /label:\s*l10n\.t\("Cancel"\)/); assert.match(code, /stashAndRetry\(/, "and Stash & Retry does it"); assert.match(code, /stashAndRetryPull\(/, "…for a pull too"); assert.match(code, /stashRetryNote\(/, "saying where the changes are when they are not back"); diff --git a/apps/extension/test/l10nWebview.test.ts b/apps/extension/test/l10nWebview.test.ts new file mode 100644 index 00000000..c1db1909 --- /dev/null +++ b/apps/extension/test/l10nWebview.test.ts @@ -0,0 +1,108 @@ +// The bundle script every page is handed (packages/l10n, `l10nWebviewScript`). +// +// A webview page cannot fetch the bundle — the CSP forbids it — so the host +// builds the HTML with the bundle inlined as JSON and a small ES5 helper on +// `globalThis.l10nT`. Two things about that script are easy to get wrong and +// impossible to see in English: +// +// - Substitution must be ONE pass, as `@vscode/l10n`'s own `format` is: a +// value that reads `{1}` is a value, not a placeholder to look up again. +// - `<` may not reach the element literally, or a message holding `` +// — a code sample, a diff snippet — ends the script early and the page +// loses every string in it. +// +// The script is run here the way a page runs it (an empty context: it needs no +// DOM unless a language tag is emitted), against a real bundle file read +// through `configureL10n`, and its substitutions are checked against +// `@vscode/l10n.t` on the same inputs — the two halves of the seam must agree. + +import { test, after } from "node:test"; +import assert from "node:assert/strict"; +import { mkdtempSync, readFileSync, rmSync, writeFileSync } from "node:fs"; +import { tmpdir } from "node:os"; +import { join } from "node:path"; +import vm from "node:vm"; +import { config, t } from "@vscode/l10n"; + +import { configureL10n, l10nWebviewScript } from "@gitstudio/l10n/index"; + +const BUNDLE: Record = { + "A < B": "甲 < 乙", + "Closed early": "提前关闭了 ", + "Hello {0}": "你好 {0}", + "One {0} two {1}": "一 {0} 二 {1}", +}; + +const dir = mkdtempSync(join(tmpdir(), "gitstudio-l10n-")); +writeFileSync(join(dir, "bundle.l10n.zh-cn.json"), `${JSON.stringify(BUNDLE, null, 1)}\n`); +configureL10n({ fsPath: join(dir, "bundle.l10n.zh-cn.json") }); + +after(() => { + // The runtime is global to the process: leave it as unconfigured as it was. + config({ contents: "{}" }); + configureL10n(undefined); + rmSync(dir, { recursive: true, force: true }); +}); + +/** The script element for nonce `n`, split into its attributes and its body. */ +function script(nonce = "n"): { html: string; js: string } { + const html = l10nWebviewScript(nonce); + const match = /^ cannot end the script element", () => { + const { html, js } = script(); + assert.ok(html.includes("\\u003c"), "every < travels as its JSON escape"); + assert.equal(js.includes(""), false, "nothing inside the element spells a closing tag"); + assert.equal(html.split("").length, 2, "the element is closed exactly once"); + const json = /globalThis\.__gitstudioL10n=([\s\S]*?);\nglobalThis\.l10nT=/.exec(js); + assert.ok(json, "the bundle is inlined as one JSON value"); + assert.deepEqual(JSON.parse(json[1]), BUNDLE, "and reads back as the bundle we wrote"); +}); + +test("the bundle file's own bytes are the bytes the page gets", () => { + const onDisk = JSON.parse(readFileSync(join(dir, "bundle.l10n.zh-cn.json"), "utf8")) as unknown; + assert.deepEqual(plain(page().bundle), onDisk); +}); diff --git a/apps/extension/test/manifest.ts b/apps/extension/test/manifest.ts new file mode 100644 index 00000000..907a887b --- /dev/null +++ b/apps/extension/test/manifest.ts @@ -0,0 +1,54 @@ +/** + * The extension manifests the way VS Code reads them. + * + * VS Code localizes a manifest by walking it and swapping every string shaped + * `%someKey%` for the value of `someKey` in `package.nls.json` (English) or + * `package.nls..json` (the translation of the language it runs in) — + * see src/vs/platform/extensionManagement/common/extensionNls.ts. A test that + * asserts on what a user reads ("Branches…", "Commit Graph", a walkthrough + * sentence) has to go through the same walk, or it is asserting on a key. + * + * `readManifest()` is English; `readManifest("zh-cn")` is the Chinese catalog + * with anything untranslated still falling back to English, exactly as VS Code + * leaves it. + */ +import { readFileSync } from "node:fs"; +import { join } from "node:path"; + +const EXTENSION = join(__dirname, ".."); + +/** Replace `%key%` references at every depth, leaving unknown keys verbatim. */ +export function localizeManifest(value: T, translations: Record): T { + if (typeof value === "string") { + if (value.length > 2 && value.startsWith("%") && value.endsWith("%")) { + const hit = translations[value.slice(1, -1)]; + return (typeof hit === "string" ? hit : value) as T; + } + return value; + } + if (Array.isArray(value)) return value.map((entry) => localizeManifest(entry, translations)) as T; + if (value && typeof value === "object") { + const out: Record = {}; + for (const [key, entry] of Object.entries(value)) out[key] = localizeManifest(entry, translations); + return out as T; + } + return value; +} + +/** Read a manifest beside its catalogs — `apps//package.json`. */ +export function readAppManifest(directory: string, locale?: string): T { + const read = (name: string): Record | undefined => { + try { + return JSON.parse(readFileSync(join(directory, name), "utf8")) as Record; + } catch { + return undefined; + } + }; + const translations = { ...(read("package.nls.json") ?? {}), ...(locale ? read(`package.nls.${locale}.json`) ?? {} : {}) }; + return localizeManifest(read("package.json"), translations) as T; +} + +/** The GitStudio extension's own manifest. */ +export function readManifest(locale?: string): T { + return readAppManifest(EXTENSION, locale); +} diff --git a/apps/extension/test/mergeManifest.test.ts b/apps/extension/test/mergeManifest.test.ts index 94d16a6b..7f94279b 100644 --- a/apps/extension/test/mergeManifest.test.ts +++ b/apps/extension/test/mergeManifest.test.ts @@ -1,7 +1,7 @@ import { test } from "node:test"; import assert from "node:assert/strict"; import { readFileSync } from "node:fs"; -import { fileURLToPath } from "node:url"; +import { readManifest } from "./manifest"; import { checkManifest, configurationProperties, @@ -19,9 +19,7 @@ import { // manifest is checked against, so a merge capability one product contributes // and the other does not fails here. -const manifest = JSON.parse( - readFileSync(fileURLToPath(new URL("../package.json", import.meta.url)), "utf8"), -) as { +const manifest = readManifest() as { contributes: { commands: { command: string; title: string }[]; menus: Record; diff --git a/apps/extension/test/notifyStyle.test.ts b/apps/extension/test/notifyStyle.test.ts index 510b030e..c2a69804 100644 --- a/apps/extension/test/notifyStyle.test.ts +++ b/apps/extension/test/notifyStyle.test.ts @@ -36,6 +36,14 @@ test("the sentence: GitStudio once, a capital, a full stop", () => { assert.equal(notice(" spaced "), "GitStudio: Spaced."); }); +test("the sentence in Chinese: 。?! end it, so no Latin full stop follows", () => { + assert.equal(notice("已切到 main。"), "GitStudio: 已切到 main。"); + assert.equal(notice("推完了!"), "GitStudio: 推完了!"); + assert.equal(notice("没问题?"), "GitStudio: 没问题?"); + assert.equal(notice("GitStudio: 草稿已保存。"), "GitStudio: 草稿已保存。", "the prefix never twice"); + assert.equal(notice("没有句号"), "GitStudio: 没有句号.", "a sentence that ends in neither still gets one"); +}); + test("a failure: the action, then git's reason, whole, on one line", () => { assert.equal( failed("Push", "rejected: non-fast-forward\nhint: pull first"), @@ -130,8 +138,8 @@ const EXEMPT: { rel: string; args: RegExp; why: string }[] = [ }, { rel: "ai/aiCommands.ts", - args: /^message,\s*\{ modal: false \},\s*"Copy",?$/, - why: "the commit message the AI drafted, offered to copy: the user's words, not GitStudio's", + args: /^message,\s*\{ modal: false \},\s*copy,?$/, + why: "the commit message the AI drafted, offered to copy: the user's words, not GitStudio's (copy is the button's own label, read once so the choice compares it)", }, ]; @@ -140,11 +148,15 @@ test("every toast is built by notice(), failed() or NO_REPOSITORY, or is a 'GitS // one, or git's stderr passed straight through went unread, and the // graph's failures ("Cherry-pick failed: error: …"), about twenty branch // actions (git's stderr alone) and the rebase refusals were all of those. - const built = /^(notice\(|failed\(|NO_REPOSITORY\b|["'`]GitStudio: )/; + const built = /^(notice\(|failed\(|NO_REPOSITORY\b|l10n\.t\(["'`]GitStudio: )/; + // A ternary whose two branches are both "GitStudio: " messages still says + // one, whichever branch runs: the guard reads the branch sentences, not the + // choice between them. + const branchy = /\?\s*l10n\.t\(["'`]GitStudio: [\s\S]*:\s*l10n\.t\(["'`]GitStudio: /; const seen = new Set(); const hits = calls() .filter((c) => { - if (PR_SENTENCES_OWED.test(c.rel) || built.test(c.args)) return false; + if (PR_SENTENCES_OWED.test(c.rel) || built.test(c.args) || branchy.test(c.args)) return false; const i = EXEMPT.findIndex((e) => e.rel === c.rel && e.args.test(c.args.replace(/\s+/g, " ").trim())); if (i >= 0) { seen.add(i); diff --git a/apps/extension/test/pageHoles.ts b/apps/extension/test/pageHoles.ts new file mode 100644 index 00000000..bacd14fb --- /dev/null +++ b/apps/extension/test/pageHoles.ts @@ -0,0 +1,127 @@ +/** + * The two holes every webview page carries now that GitStudio is localized. + * + * A page-builder test lifts a host file's template literal and fills its holes + * by name (changesPage.ts, rebasePanelPage.ts). An unknown name throws, so the + * l10n work turned up twice per page: the words themselves arrived as + * `${l10n.t("…")}` holes, and the bundle script arrived as a + * `${l10nWebviewScript(nonce)}` one. + * + * Both are filled here, and the page the tests render is the English page — + * which is what a browser test asserts on. A test that wants the Chinese page + * passes `messages` (the zh-cn bundle) and configures `@gitstudio/l10n` with + * it, so the words and the bundle agree: + * + * - `l10n.t("…")` is the host's own call, so its value is the English source + * text (in VS Code under a Chinese display language it would be the + * translation, and the test pages would read Chinese). + * - `l10nWebviewScript(nonce)` is the real inline script, so the page's own + * program can call `l10nT(…)` exactly as it does in VS Code. + * + * Only `l10n.t("literal")` with one string argument is resolved: a call with + * placeholders or several arguments needs a value only the live page has, and + * silently guessing one would hide a page that cannot be built. + */ +import { readFileSync } from "node:fs"; + +import ts from "typescript"; + +import { l10nWebviewScript } from "@gitstudio/l10n/index"; + +/** The hole's name in a template literal: its expression, as written. */ +export const L10N_WEBVIEW_SCRIPT = "l10nWebviewScript(nonce)"; + +/** The hole that injects the bundle into a page built with nonce `nonce`. */ +export function l10nHoles(nonce: string): Record { + return { [L10N_WEBVIEW_SCRIPT]: l10nWebviewScript(nonce) }; +} + +/** + * The value of one hole of a page template. + * + * @param where - Where the template came from, for the error a test would see. + * @param messages - The bundle to read the `l10n.t("…")` holes from. Missing + * means the English source text; a bundle without the message means the same, + * which is what VS Code does for a string a translation has not reached yet. + */ +export function fillHole( + where: string, + span: ts.TemplateSpan, + sf: ts.SourceFile, + holes: Record, + messages?: Record, +): string { + const name = span.expression.getText(sf); + if (name in holes) { + return holes[name]; + } + const english = englishMessage(span.expression); + if (english !== undefined) { + return messages?.[english] ?? english; + } + throw new Error(`${where}: a hole this page cannot fill: \${${name}}`); +} + +/** `l10n.t("…")` as the English text it returns, or undefined for anything else. */ +function englishMessage(expression: ts.Expression): string | undefined { + if (!ts.isCallExpression(expression) || !ts.isPropertyAccessExpression(expression.expression)) { + return undefined; + } + const called = expression.expression; + if (called.expression.getText() !== "l10n" || called.name.text !== "t") { + return undefined; + } + const [first, ...rest] = expression.arguments; + if (rest.length > 0 || first === undefined || !ts.isStringLiteralLike(first)) { + return undefined; + } + return first.text; +} + +/** + * A host file's `String.raw` page template, with `holes` filled — the first + * tag whose head holds `marker` (``, say). + * + * The template is lifted with the TypeScript parser, never re-typed, so the + * text is exactly what the webview gets: `String.raw` hands the literal's body + * over as written, and each span is one hole between two such bodies. + * + * @param where - Where the template came from (`"commitView.ts html()"`), for + * the error a page that cannot be built would raise. + * @param messages - The bundle the `l10n.t("…")` holes are read from; English + * source text when it is left out. + */ +export function filledTemplate( + where: string, + file: string, + marker: string, + holes: Record, + messages?: Record, +): string { + const source = readFileSync(file, "utf8"); + const sf = ts.createSourceFile(file, source, ts.ScriptTarget.Latest, true); + let tpl: ts.TemplateExpression | undefined; + const visit = (node: ts.Node): void => { + if ( + !tpl && + ts.isTaggedTemplateExpression(node) && + node.tag.getText(sf) === "String.raw" && + ts.isTemplateExpression(node.template) && + node.template.head.getText(sf).includes(marker) + ) { + tpl = node.template; + } + ts.forEachChild(node, visit); + }; + visit(sf); + if (!tpl) throw new Error(`${where}: the String.raw template was not found`); + + // head "`…${", middle "}…${", tail "}…`" — the delimiters come off. + let html = tpl.head.getText(sf).slice(1, -2); + for (const span of tpl.templateSpans) { + html += fillHole(where, span, sf, holes, messages); + const lit = span.literal.getText(sf); + html += ts.isTemplateTail(span.literal) ? lit.slice(1, -1) : lit.slice(1, -2); + } + return html; +} diff --git a/apps/extension/test/rebasePanelGuard.test.ts b/apps/extension/test/rebasePanelGuard.test.ts index 0544fb09..044b2a68 100644 --- a/apps/extension/test/rebasePanelGuard.test.ts +++ b/apps/extension/test/rebasePanelGuard.test.ts @@ -3,6 +3,7 @@ import assert from "node:assert/strict"; import { readFileSync } from "node:fs"; import { join } from "node:path"; import * as plan from "@gitstudio/engine/rebase/planEdit"; +import "./webviewL10n"; // Issue #27: "Unable to fixup/squash last commit (HEAD) to previous … // It says 'The top commit has nothing above it to fold into.' which does not diff --git a/apps/extension/test/rebasePanelPage.ts b/apps/extension/test/rebasePanelPage.ts index d76deae9..b47c8f22 100644 --- a/apps/extension/test/rebasePanelPage.ts +++ b/apps/extension/test/rebasePanelPage.ts @@ -21,6 +21,8 @@ import { tmpdir } from "node:os"; import { join } from "node:path"; import { fileURLToPath, pathToFileURL } from "node:url"; import ts from "typescript"; + +import { fillHole, l10nHoles } from "./pageHoles"; import { findChrome } from "../../../packages/webview-ui/test/headless"; import { Browser, type Page } from "../../../scripts/merge-e2e/cdp"; import { BODY_CLASS, VSCODE_THEMES, type VsCodeTheme } from "../../../scripts/merge-e2e/themes"; @@ -183,6 +185,8 @@ export async function rebasePanelHtml( planUri: pathToFileURL(planFile).href, dataJson: JSON.stringify({ base: data.base, branch: data.branch, baseCommit: data.baseCommit, commits: data.commits }).replace(/ { - const name = span.expression.getText(sf); - if (!(name in holes)) throw new Error(`rebaseWorkspacePanel.ts render(): a hole this page cannot fill: \${${name}}`); - html += holes[name] + parts[i + 1]; + html += fillHole("rebaseWorkspacePanel.ts render()", span, sf, holes) + parts[i + 1]; }); return html; } diff --git a/apps/extension/test/rebaseStopBanner.test.ts b/apps/extension/test/rebaseStopBanner.test.ts index e433100f..f058ac02 100644 --- a/apps/extension/test/rebaseStopBanner.test.ts +++ b/apps/extension/test/rebaseStopBanner.test.ts @@ -3,6 +3,7 @@ import assert from "node:assert/strict"; import { readFileSync } from "node:fs"; import { join } from "node:path"; import ts from "typescript"; +import "./webviewL10n"; // The rebase workspace's stop banner offered Continue and Abort only. It now // offers Skip where git names it as the way out (OperationProvider's canSkip — diff --git a/apps/extension/test/refFilterStore.test.ts b/apps/extension/test/refFilterStore.test.ts index a1ae38e6..d35a5244 100644 --- a/apps/extension/test/refFilterStore.test.ts +++ b/apps/extension/test/refFilterStore.test.ts @@ -185,7 +185,11 @@ test("a reveal into a filtered graph asks git before paging, and says so when th // the selection AS STORED (a preset stays its symbol); "Show all branches" // second. Both go through the store's one reload path and replay the reveal. assert.match(offer, /const contains = active \? await active\.ctx\.refs\.containingBranches\(sha\) : undefined;\s*add = revealCandidate\(contains\?\.refs \?\? \[\], this\.refList\);/); - assert.match(offer, /showInformationMessage\(\s*`GitStudio: \$\{sha\.slice\(0, 7\)\} is hidden by the branch filter\.`,\s*\.\.\.\(ADD \? \[ADD\] : \[\]\),\s*ALL,\s*\)/, "add first, all second"); + assert.match( + offer, + /showInformationMessage\(\s*l10n\.t\("GitStudio: \{0\} is hidden by the branch filter\.", sha\.slice\(0, 7\)\),\s*\.\.\.\(ADD \? \[ADD\] : \[\]\),\s*ALL,\s*\)/, + "add first, all second", + ); assert.match( offer, /this\.pendingReveal = sha;\s*void this\.setRefFilter\(pick === ADD && add \? withRef\(this\.refFilter, add\.fullName\) : null\);/, @@ -209,7 +213,7 @@ test("the chip menu's checkout runs the commit menu's own ref-checkout arm, by t // …and the menu's own rows are built through it, so there is one id format. assert.equal((actions.match(/refActionId\(ref\.fullName\)/g) ?? []).length, 3); // …labelled by the full name shorn, never git's "heads/release" (#30). - assert.equal((actions.match(/label: `Checkout \$\{refLabel\(ref\.fullName\)\}…?`/g) ?? []).length, 3); + assert.equal((actions.match(/label: l10n\.t\("Checkout \{0\}…?", refLabel\(ref\.fullName\)\)/g) ?? []).length, 3); assert.doesNotMatch(actions, /label: `Checkout \$\{ref\.name\}/); // The arm itself plans from the full name, through git-service, so the // desktop's graph menu means the same thing. diff --git a/apps/extension/test/refNameSanitize.test.ts b/apps/extension/test/refNameSanitize.test.ts index 6ac2ee76..1f7c2d2b 100644 --- a/apps/extension/test/refNameSanitize.test.ts +++ b/apps/extension/test/refNameSanitize.test.ts @@ -2,6 +2,7 @@ import { test } from "node:test"; import assert from "node:assert/strict"; import { readFile } from "node:fs/promises"; import { fileURLToPath } from "node:url"; +import "./webviewL10n"; // DLG_SANITIZE turns free text into a name git will accept, and is offered in // the branch dialog as "use this instead". Like DLG_VALIDATORS it lives inside diff --git a/apps/extension/test/refNameValidator.test.ts b/apps/extension/test/refNameValidator.test.ts index 686d8d33..96b2b496 100644 --- a/apps/extension/test/refNameValidator.test.ts +++ b/apps/extension/test/refNameValidator.test.ts @@ -2,6 +2,7 @@ import { test } from "node:test"; import assert from "node:assert/strict"; import { readFile } from "node:fs/promises"; import { fileURLToPath } from "node:url"; +import "./webviewL10n"; // The dialog validators (`DLG_VALIDATORS`) live inside the Changes webview's // inline `, + }; + } + return scriptCache.html; +} + +/** + * The bundle text as it may sit inside a `` cannot end the element early. JSON + * reads `\u003c` back as `<`, so the page sees the bundle we wrote — and `\u003c` + * cannot appear in the bundle any other way, whichever language it holds. + */ +function inlineBundle(json: string): string { + return json.replace(/(); @@ -84,9 +85,9 @@ export async function maybeOfferCoexistence(host: MergeHostCore): Promise try { choice = await host.notify( "info", - "conflicted files now open in its merge editor. Turn off VS Code's own merge editor and conflict " + - "highlights so they don't open alongside it? You can switch back any time with " + - `"${product.displayName}: Restore VS Code's Merge Editor".`, + l10n.t("conflicted files now open in its merge editor. Turn off VS Code's own merge editor and conflict ") + + l10n.t("highlights so they don't open alongside it? You can switch back any time with ") + + l10n.t("\"{0}: Restore VS Code's Merge Editor\".", product.displayName), TURN_OFF, NOT_NOW, NEVER, @@ -114,8 +115,9 @@ export async function maybeOfferCoexistence(host: MergeHostCore): Promise await config.update(key, off, vscode.ConfigurationTarget.Global); } await context.globalState.update(product.coexistencePromptKey, true); - void host.notify("info", "VS Code's own merge editor and conflict highlights are off.", "Undo").then((c) => { - if (c === "Undo") { + const undo = l10n.t("Undo"); + void host.notify("info", l10n.t("VS Code's own merge editor and conflict highlights are off."), undo).then((c) => { + if (c === undo) { void restoreBuiltIns(host); } }); @@ -166,11 +168,11 @@ export async function maybeSayPeerOutdated(host: MergeHostCore): Promise { // Set before the first await (a Memento's value is visible at once), so a // second scan in the same moment finds it and says nothing. const remembered = context.globalState.update(deferral.noticeKey, true); - const takeOver = `Let ${product.displayName} open conflicts`; + const takeOver = l10n.t("Let {0} open conflicts", product.displayName); const choice = await host.notify( "info", - `${deferral.owner} is installed, so ${deferral.owner} opens your conflicts, with the same merge editor and ` + - `Conflicts dashboard. ${product.displayName}'s own commands still work.`, + l10n.t("{0} is installed, so {1} opens your conflicts, with the same merge editor and ", deferral.owner, deferral.owner) + + l10n.t("Conflicts dashboard. {0}'s own commands still work.", product.displayName), OK, takeOver, ); @@ -234,10 +236,10 @@ export async function offerRestoreAfterAutoOpenOff(host: MergeHostCore): Promise const { context, product } = host; if (host.settings().autoOpen) return; if (!context.globalState.get(previousKey(product.coexistencePromptKey))) return; - const restore = "Restore"; + const restore = l10n.t("Restore"); const choice = await host.notify( "info", - "automatic opening is off. Turn VS Code's own merge editor and conflict highlights back on?", + l10n.t("automatic opening is off. Turn VS Code's own merge editor and conflict highlights back on?"), restore, ); if (choice === restore) { @@ -259,5 +261,5 @@ export async function restoreBuiltIns(host: MergeHostCore): Promise { await config.update(key, value === null ? undefined : value, vscode.ConfigurationTarget.Global); } await context.globalState.update(previousKey(product.coexistencePromptKey), undefined); - void host.notify("info", "VS Code's own merge editor and conflict highlights are as they were."); + void host.notify("info", l10n.t("VS Code's own merge editor and conflict highlights are as they were.")); } diff --git a/packages/merge-vscode/src/conflictsPanel.ts b/packages/merge-vscode/src/conflictsPanel.ts index 51c2a3d3..a1a8f0c3 100644 --- a/packages/merge-vscode/src/conflictsPanel.ts +++ b/packages/merge-vscode/src/conflictsPanel.ts @@ -20,6 +20,7 @@ import { saveConflictedDocuments, saveDocumentAt } from "./mergeEditorProvider"; import { outcomeLine, type OperationVerb } from "./outcome"; import type { MergeRepo } from "./product"; import { conflictsWebviewHtml } from "./webviewHtml"; +import * as l10n from "@vscode/l10n"; export class ConflictsDashboard implements vscode.Disposable { private panel: vscode.WebviewPanel | undefined; @@ -124,7 +125,7 @@ export class ConflictsDashboard implements vscode.Disposable { private create(focus: boolean): void { const panel = vscode.window.createWebviewPanel( this.host.product.viewTypes.conflicts, - "Conflicts", + l10n.t("Conflicts"), { viewColumn: vscode.ViewColumn.Active, preserveFocus: !focus }, { enableScripts: true, @@ -310,7 +311,7 @@ export class ConflictsDashboard implements vscode.Disposable { await this.openConflict(fileUri(repo, action.path)); return; case "accept": - await this.fileAction(repo, action.path, action.seq, `Accept ${action.role === "yours" ? "Yours" : "Theirs"}`, () => + await this.fileAction(repo, action.path, action.seq, l10n.t("Accept {0}", action.role === "yours" ? l10n.t("Yours") : l10n.t("Theirs")), () => repo.ctx.conflictOps.takeRole(action.path, action.role), ); return; @@ -318,7 +319,7 @@ export class ConflictsDashboard implements vscode.Disposable { await this.fileAction(repo, action.path, action.seq, undefined, () => repo.ctx.conflictOps.restore(action.path)); return; case "delete": - await this.fileAction(repo, action.path, action.seq, "Delete the conflicted file", () => + await this.fileAction(repo, action.path, action.seq, l10n.t("Delete the conflicted file"), () => repo.ctx.conflictOps.deleteFile(action.path), ); return; @@ -467,7 +468,7 @@ export class ConflictsDashboard implements vscode.Disposable { void closeMergeEditorTabs(this.host.product.viewTypes.mergeEditor); } } else { - controller.setOutcome({ kind: "failed", text: failure ?? `Git refused to ${verb}.` }); + controller.setOutcome({ kind: "failed", text: failure ?? l10n.t("Git refused to {0}.", verb) }); } this.finish(seq, page); this.host.changed(repo); diff --git a/packages/merge-vscode/src/contract.ts b/packages/merge-vscode/src/contract.ts index 09e11901..0574c27e 100644 --- a/packages/merge-vscode/src/contract.ts +++ b/packages/merge-vscode/src/contract.ts @@ -7,6 +7,8 @@ // // vscode-free data + one pure checker. +import * as l10n from "@vscode/l10n"; + import type { MergeCommandIds } from "./product"; export type CommandRole = keyof MergeCommandIds; @@ -14,17 +16,17 @@ export type CommandRole = keyof MergeCommandIds; /** Canonical titles (sentence-cased verbs, the user's words). */ export const COMMAND_TITLES: Record = { showConflicts: "Resolve Conflicts…", - resolveInMergeEditor: "Resolve in Merge Editor", + resolveInMergeEditor: l10n.t("Resolve in Merge Editor"), compare: "Compare File…", - openDiff: "Open in Embedded Diff", - openChanges: "Open Changes (vs HEAD)", - stageWithTicks: "Stage Changes with Ticks", - openDemo: "Open Sample Merge", - openDemoDiff: "Open Sample Diff", + openDiff: l10n.t("Open in Embedded Diff"), + openChanges: l10n.t("Open Changes (vs HEAD)"), + stageWithTicks: l10n.t("Stage Changes with Ticks"), + openDemo: l10n.t("Open Sample Merge"), + openDemoDiff: l10n.t("Open Sample Diff"), operationContinue: "Continue Operation", - operationSkip: "Skip This Commit", + operationSkip: l10n.t("Skip This Commit"), operationAbort: "Abort Operation", - restoreBuiltInMergeEditor: "Restore VS Code's Merge Editor", + restoreBuiltInMergeEditor: l10n.t("Restore VS Code's Merge Editor"), }; /** diff --git a/packages/merge-vscode/src/dashboardController.ts b/packages/merge-vscode/src/dashboardController.ts index ad06e008..c96f7805 100644 --- a/packages/merge-vscode/src/dashboardController.ts +++ b/packages/merge-vscode/src/dashboardController.ts @@ -30,6 +30,7 @@ import type { } from "@gitstudio/host-bridge/conflictsProtocol"; import { HOLD_TO_UNDO_MS } from "@gitstudio/host-bridge/conflictsProtocol"; import { StashEndTracker, type StashEnd } from "@gitstudio/engine/conflict/stashEnd"; +import * as l10n from "@vscode/l10n"; export interface DashboardOptions { brand: ConflictsState["brand"]; @@ -260,7 +261,7 @@ export function pendingCount(files: readonly ConflictFileView[]): number { /** The dashboard's title: "Conflicts (2)" while any remain. */ export function dashboardTitle(state: Pick): string { const pending = pendingCount(state.files); - return pending > 0 ? `Conflicts (${pending})` : "Conflicts"; + return pending > 0 ? l10n.t("Conflicts ({0})", pending) : l10n.t("Conflicts"); } const NO_OP: ConflictsState["op"] = { @@ -268,7 +269,8 @@ const NO_OP: ConflictsState["op"] = { title: "", yours: { role: "yours", stage: 2, name: "", paneTitle: "", description: "" }, theirs: { role: "theirs", stage: 3, name: "", paneTitle: "", description: "" }, - verbs: { abort: "Cancel" }, + // English sentinel: abortLabel() replaces it with a specific, localized word. + verbs: { abort: l10n.t("Cancel") }, canContinue: false, canSkip: false, episode: "none", diff --git a/packages/merge-vscode/src/demoContent.ts b/packages/merge-vscode/src/demoContent.ts index 894869f2..9985c578 100644 --- a/packages/merge-vscode/src/demoContent.ts +++ b/packages/merge-vscode/src/demoContent.ts @@ -17,6 +17,7 @@ import { markUnsettled, prepareMerge } from "@gitstudio/engine/conflict/document import type { OperationView } from "@gitstudio/host-bridge/conflictsProtocol"; import type { HostMessage, MergeInitPayload, WebviewMessage } from "@gitstudio/host-bridge/protocol"; import { markerLabelsFor } from "./documentSync"; +import * as l10n from "@vscode/l10n"; /** * Sample side-by-side diff: an auth middleware before and after a change — @@ -25,8 +26,8 @@ import { markerLabelsFor } from "./documentSync"; */ export const DEMO_DIFF = { fileName: "authorizeRequest.ts", - leftLabel: "Sample · before", - rightLabel: "Sample · after", + leftLabel: l10n.t("Sample · before"), + rightLabel: l10n.t("Sample · after"), leftText: `import type { Request, Response, NextFunction } from "express"; import { verifyJwt } from "./jwt"; import { findSession } from "./store"; @@ -193,7 +194,7 @@ export async function authorizeRequest( } `; -const COMMIT = { sha: "a1b2c3d4e5f60718293a4b5c6d7e8f9012345678", subject: "Bind sessions to the device", author: "Sample" }; +const COMMIT = { sha: "a1b2c3d4e5f60718293a4b5c6d7e8f9012345678", subject: l10n.t("Bind sessions to the device"), author: l10n.t("Sample") }; /** * The stop the sample stands for: commit 2 of 3 of feature/session-hardening @@ -204,7 +205,7 @@ const COMMIT = { sha: "a1b2c3d4e5f60718293a4b5c6d7e8f9012345678", subject: "Bind */ export const SAMPLE_OP: OperationView = { kind: "none", - title: "Sample · rebasing feature/session-hardening onto main · commit 2 of 3", + title: l10n.t("Sample · rebasing feature/session-hardening onto main · commit 2 of 3"), direction: { from: "yours", verb: "onto", to: "theirs" }, step: { n: 2, m: 3, unit: "commit" }, commit: COMMIT, @@ -212,17 +213,17 @@ export const SAMPLE_OP: OperationView = { role: "yours", stage: 3, name: "feature/session-hardening", - paneTitle: "Rebasing a1b2c3d from feature/session-hardening", - description: `Your commit a1b2c3d “${COMMIT.subject}” from feature/session-hardening`, + paneTitle: l10n.t("Rebasing a1b2c3d from feature/session-hardening"), + description: l10n.t("Your commit a1b2c3d “{0}” from feature/session-hardening", COMMIT.subject), }, theirs: { role: "theirs", stage: 2, name: "main", - paneTitle: "Already rebased commits and commits from main", - description: "main, plus the commits already rebased onto it", + paneTitle: l10n.t("Already rebased commits and commits from main"), + description: l10n.t("main, plus the commits already rebased onto it"), }, - verbs: { abort: "Close sample" }, + verbs: { abort: l10n.t("Close sample") }, canContinue: false, canSkip: false, episode: "sample", @@ -231,7 +232,7 @@ export const SAMPLE_OP: OperationView = { export const DEMO_MERGE = { fileName: "authorizeRequest.ts", /** The editor tab's title. */ - title: "Sample: authorizeRequest.ts", + title: l10n.t("Sample: authorizeRequest.ts"), base: BASE, yours: YOURS, theirs: THEIRS, @@ -240,7 +241,7 @@ export const DEMO_MERGE = { /** What Apply says in the sample: nothing is written, and what a real Apply does. */ export const SAMPLE_APPLIED = - "Sample resolved. In a real conflict, Apply saves and stages the file, then Continue Rebase appears."; + l10n.t("Sample resolved. In a real conflict, Apply saves and stages the file, then Continue Rebase appears."); let body: string | undefined; diff --git a/packages/merge-vscode/src/diffPanel.ts b/packages/merge-vscode/src/diffPanel.ts index 5c41afae..13af1d8d 100644 --- a/packages/merge-vscode/src/diffPanel.ts +++ b/packages/merge-vscode/src/diffPanel.ts @@ -16,6 +16,7 @@ import { baseName, collectUris, locate, resolveUriArg } from "./args"; import { DEMO_DIFF } from "./demoContent"; import type { MergeHostCore } from "./host"; import { mergeWebviewHtml } from "./webviewHtml"; +import * as l10n from "@vscode/l10n"; /** * One side of a diff, persisted across reloads (the panel's serialized state). @@ -187,7 +188,7 @@ export class DiffPanel { }); void this.panel.webview.postMessage({ type: "persistState", state: this.state }); } catch (error) { - void this.host.notify("error", `couldn't load the diff — ${error instanceof Error ? error.message : String(error)}`); + void this.host.notify("error", l10n.t("couldn't load the diff — {0}", error instanceof Error ? error.message : String(error))); } } @@ -271,12 +272,12 @@ export class DiffPanel { staged, ); if (!result.ok) { - vscode.window.setStatusBarMessage(`$(info) ${this.host.product.displayName}: ${result.stderr}`, 4000); + vscode.window.setStatusBarMessage(l10n.t("$(info) {0}: {1}", this.host.product.displayName, result.stderr), 4000); } } catch (error) { void this.host.notify( "error", - `couldn't stage that change — ${error instanceof Error ? error.message : String(error)}`, + l10n.t("couldn't stage that change — {0}", error instanceof Error ? error.message : String(error)), ); } this.host.changed(target.repo); @@ -326,7 +327,7 @@ async function readUriText(uri: vscode.Uri): Promise { function diffTitle(state: DiffPanelState): string { const base = state.fileName.split(/[\\/]/).pop() ?? state.fileName; - return `Diff: ${base}`; + return l10n.t("Diff: {0}", base); } /** @@ -371,7 +372,7 @@ export function headState(uri: vscode.Uri, opts: { editable: boolean }): DiffPan return { fileName: uri.fsPath, leftLabel: `${name} (HEAD)`, - rightLabel: `${name} (Working Tree)`, + rightLabel: l10n.t("{0} (Working Tree)", name), // "head" is also what makes the panel stageable (ticks). leftSource: "head", leftUri: uri.toString(), @@ -430,7 +431,7 @@ export class DiffCommands { async openChanges(arg?: unknown): Promise { const uri = resolveUriArg(arg) ?? vscode.window.activeTextEditor?.document.uri; if (!uri) { - void this.host.notify("warn", "open a file to compare it against HEAD."); + void this.host.notify("warn", l10n.t("open a file to compare it against HEAD.")); return; } if (this.host.product.openChangesEmbedded) { @@ -444,7 +445,7 @@ export class DiffCommands { async stageWithTicks(arg?: unknown): Promise { const uri = resolveUriArg(arg) ?? vscode.window.activeTextEditor?.document.uri; if (!uri || uri.scheme !== "file" || !locate(this.host.product.locator, uri)) { - void this.host.notify("info", "open a file in a Git repository to stage its changes."); + void this.host.notify("info", l10n.t("open a file in a Git repository to stage its changes.")); return; } await DiffPanel.create(this.host, headState(uri, { editable: false })); @@ -460,7 +461,7 @@ export class DiffCommands { return; } if (!locate(this.host.product.locator, uri)) { - void this.host.notify("warn", `${baseName(uri)} is not in an open Git repository, so it has no HEAD version.`); + void this.host.notify("warn", l10n.t("{0} is not in an open Git repository, so it has no HEAD version.", baseName(uri))); return; } await DiffPanel.create(this.host, headState(uri, { editable: true })); diff --git a/packages/merge-vscode/src/documentSync.ts b/packages/merge-vscode/src/documentSync.ts index d78b0fe8..62917fc9 100644 --- a/packages/merge-vscode/src/documentSync.ts +++ b/packages/merge-vscode/src/documentSync.ts @@ -30,6 +30,7 @@ import { } from "@gitstudio/engine/conflict/documentText"; import { normalizeEol } from "@gitstudio/engine/lineDiff"; import type { MergeInitPayload } from "@gitstudio/host-bridge/protocol"; +import * as l10n from "@vscode/l10n"; /** * How the markers name the sides. The first section is git's stage 2 — Yours @@ -38,10 +39,10 @@ import type { MergeInitPayload } from "@gitstudio/host-bridge/protocol"; */ export function markerLabelsFor(payload: Pick): MarkerLabels { const op = payload.op; - if (!op) return { firstIsYours: true, first: "Yours", second: "Theirs" }; + if (!op) return { firstIsYours: true, first: l10n.t("Yours"), second: l10n.t("Theirs") }; const named = (word: string, name: string): string => (name ? `${word} (${name})` : word); - const yours = named("Yours", op.yours.name); - const theirs = named("Theirs", op.theirs.name); + const yours = named(l10n.t("Yours"), op.yours.name); + const theirs = named(l10n.t("Theirs"), op.theirs.name); return op.yours.stage === 2 ? { firstIsYours: true, first: yours, second: theirs } : { firstIsYours: false, first: theirs, second: yours }; diff --git a/packages/merge-vscode/src/host.ts b/packages/merge-vscode/src/host.ts index 46e747e2..50fe33b3 100644 --- a/packages/merge-vscode/src/host.ts +++ b/packages/merge-vscode/src/host.ts @@ -6,6 +6,7 @@ import * as vscode from "vscode"; import type { MergeHostSettings, MergeProduct, MergeRepo } from "./product"; import { normalizeMergeSettings, settingWithFallback, sidesTipText } from "./product"; import type { ExitGuard } from "./exitGuard"; +import * as l10n from "@vscode/l10n"; export type NoticeKind = "info" | "warn" | "error"; @@ -46,7 +47,7 @@ export function createHostCore( notify: (kind, text, ...actions) => { const line = `${product.displayName}: ${text}`; if (kind === "info" && actions.length === 0) { - vscode.window.setStatusBarMessage(`$(check) ${line}`, 3000); + vscode.window.setStatusBarMessage(l10n.t("$(check) {0}", line), 3000); return Promise.resolve(undefined); } if (kind === "error") { diff --git a/packages/merge-vscode/src/mergeEditorProvider.ts b/packages/merge-vscode/src/mergeEditorProvider.ts index 5caae58f..6dde7730 100644 --- a/packages/merge-vscode/src/mergeEditorProvider.ts +++ b/packages/merge-vscode/src/mergeEditorProvider.ts @@ -18,6 +18,7 @@ import { closeMergeEditorTabs, dismissSidesTip, fileUri, sidesTipFor, type Merge import { MergeSession } from "./mergeSession"; import type { MergeRepo } from "./product"; import { mergeWebviewHtml } from "./webviewHtml"; +import * as l10n from "@vscode/l10n"; export class MergeEditorProvider implements vscode.CustomTextEditorProvider { static register(host: MergeHostCore): vscode.Disposable { @@ -223,15 +224,15 @@ export class MergeEditorProvider implements vscode.CustomTextEditorProvider { // seeded from it); only an Apply that CHANGES it asks first. if (sync.mirror.appliedOverResolution(message.text)) { const go = await this.host.product.ask({ - title: `Replace the resolution already in ${name}?`, + title: l10n.t("Replace the resolution already in {0}?", name), message: - `${name} had no conflict markers left when the merge editor opened: it was already resolved, by hand ` + - `or by git rerere. Apply replaces that with the Result shown here, and stages it.`, - confirmLabel: "Replace and stage", + l10n.t("{0} had no conflict markers left when the merge editor opened: it was already resolved, by hand ", name) + + l10n.t("or by git rerere. Apply replaces that with the Result shown here, and stages it."), + confirmLabel: l10n.t("Replace and stage"), danger: true, }); if (!go) { - sync.post({ type: "outcome", kind: "failed", text: `Nothing was written. ${name} keeps the resolution it had.` }); + sync.post({ type: "outcome", kind: "failed", text: l10n.t("Nothing was written. {0} keeps the resolution it had.", name) }); break; } } @@ -241,7 +242,7 @@ export class MergeEditorProvider implements vscode.CustomTextEditorProvider { sync.post({ type: "outcome", kind: "failed", - text: `Nothing was written. ${name} changed outside the merge editor: reload the merge, or keep that edit, first.`, + text: l10n.t("Nothing was written. {0} changed outside the merge editor: reload the merge, or keep that edit, first.", name), }); break; } @@ -256,7 +257,7 @@ export class MergeEditorProvider implements vscode.CustomTextEditorProvider { if (undo) { await undo(); } else { - sync.post({ type: "outcome", kind: "failed", text: "There is no Apply to undo here any more." }); + sync.post({ type: "outcome", kind: "failed", text: l10n.t("There is no Apply to undo here any more.") }); } break; } diff --git a/packages/merge-vscode/src/mergeSession.ts b/packages/merge-vscode/src/mergeSession.ts index 602c6f20..edf3ba1f 100644 --- a/packages/merge-vscode/src/mergeSession.ts +++ b/packages/merge-vscode/src/mergeSession.ts @@ -36,6 +36,7 @@ import type { HostMessage, MergeInitPayload } from "@gitstudio/host-bridge/proto import { outcomeLine, type OperationVerb } from "./outcome"; import { markersOnlyPayload, readMergePayload, type SidesReader } from "./payload"; import { stageResolvedPath, type GitRunner } from "./stageResolved"; +import * as l10n from "@vscode/l10n"; /** The git surface one session needs — a GitContext satisfies it. */ export interface SessionGit { @@ -117,7 +118,7 @@ export class MergeSession { ? await readMergePayload(d.git.conflictOps, d.rel, input) : markersOnlyPayload(input); } catch (error) { - d.notify("error", `couldn't read the conflict versions — ${reason(error)}`); + d.notify("error", l10n.t("couldn't read the conflict versions — {0}", reason(error))); return; } const tip = d.tip?.(payload.op); @@ -146,7 +147,7 @@ export class MergeSession { try { await d.save(text); } catch (error) { - const message = `couldn't save the resolved file — ${reason(error)}`; + const message = l10n.t("couldn't save the resolved file — {0}", reason(error)); d.notify("error", message); d.post({ type: "applied", staged: false, message: capitalise(message) }); return; @@ -155,7 +156,7 @@ export class MergeSession { d.post({ type: "applied", staged: false, - message: "Saved. This file is not in a Git repository, so there is nothing to stage.", + message: l10n.t("Saved. This file is not in a Git repository, so there is nothing to stage."), }); return; } @@ -183,19 +184,19 @@ export class MergeSession { d.notify("info", "resolved file saved and staged."); } }; - await (d.withUndo && !resolving ? d.withUndo("Apply merge resolution", run) : run()); + await (d.withUndo && !resolving ? d.withUndo(l10n.t("Apply merge resolution"), run) : run()); } /** The no-text panel's Accept Yours / Accept Theirs (or "Delete the file" for the missing role). */ async takeRole(role: SideRole): Promise { - await this.resolveWhole(`Accept ${role === "yours" ? "Yours" : "Theirs"}`, (git, rel) => + await this.resolveWhole(l10n.t("Accept {0}", role === "yours" ? l10n.t("Yours") : l10n.t("Theirs")), (git, rel) => git.conflictOps.takeRole(rel, role), ); } /** A both-deleted file's only resolution. */ async deleteFile(): Promise { - await this.resolveWhole("Delete the conflicted file", (git, rel) => + await this.resolveWhole(l10n.t("Delete the conflicted file"), (git, rel) => git.conflictOps.deleteFile(rel), ); } @@ -242,7 +243,7 @@ export class MergeSession { } const result = await d.git.conflictOps.restore(d.rel); if (!result.ok) { - const message = result.message ?? "couldn't restore the conflict."; + const message = result.message ?? l10n.t("couldn't restore the conflict."); d.notify(result.expected ? "warn" : "error", message); d.post({ type: "outcome", kind: "failed", text: capitalise(message) }); return; @@ -289,10 +290,10 @@ export class MergeSession { d.diskText ? d.diskText().catch(() => undefined) : Promise.resolve(undefined), ]); if (!op || op.episode !== token.episode || head !== token.head) { - return "git has moved on since that Apply, so there is no conflict to bring back. Nothing was changed."; + return l10n.t("git has moved on since that Apply, so there is no conflict to bring back. Nothing was changed."); } if (text !== token.text) { - return `${baseName(d.fileName)} changed after the Apply — undoing it now would throw those edits away. Nothing was changed.`; + return l10n.t("{0} changed after the Apply — undoing it now would throw those edits away. Nothing was changed.", baseName(d.fileName)); } return undefined; } @@ -306,7 +307,7 @@ export class MergeSession { d.post({ type: "applied", staged: false, - message: "This file is not in a Git repository, so there is no conflict to resolve.", + message: l10n.t("This file is not in a Git repository, so there is no conflict to resolve."), }); return; } @@ -336,7 +337,7 @@ export class MergeSession { const d = this.deps; const git = d.git; if (!git) { - d.post({ type: "outcome", kind: "failed", text: "This file is not in a Git repository." }); + d.post({ type: "outcome", kind: "failed", text: l10n.t("This file is not in a Git repository.") }); return; } let before: OperationView; diff --git a/packages/merge-vscode/src/outcome.ts b/packages/merge-vscode/src/outcome.ts index 9f5bef86..f73cdef1 100644 --- a/packages/merge-vscode/src/outcome.ts +++ b/packages/merge-vscode/src/outcome.ts @@ -11,6 +11,7 @@ import type { } from "@gitstudio/host-bridge/conflictsProtocol"; import { skipEndedText } from "@gitstudio/engine/conflict/sides"; import { abortConfirm, opNoun, skipConfirm } from "@gitstudio/webview-ui/conflicts/opText"; +import * as l10n from "@vscode/l10n"; export type OperationVerb = "continue" | "skip" | "abort"; @@ -27,20 +28,20 @@ export interface OutcomeLine { export function operationNoun(kind: OperationKind): string { switch (kind) { case "merge": - return "Merge"; + return l10n.t("Merge"); case "rebase": case "rebase-merge-step": - return "Rebase"; + return l10n.t("Rebase"); case "cherry-pick": - return "Cherry-pick"; + return l10n.t("Cherry-pick"); case "revert": - return "Revert"; + return l10n.t("Revert"); case "am": - return "Applying patches"; + return l10n.t("Applying patches"); case "stash": - return "Applying the stash"; + return l10n.t("Applying the stash"); case "none": - return "The operation"; + return l10n.t("The operation"); } } @@ -79,9 +80,9 @@ export function verbConfirm( /** Why Continue cannot run right now, or undefined when it can. */ export function continueRefusal(view: OperationView): string | undefined { - if (view.kind === "none" || view.kind === "stash") return "Nothing is in progress."; - if (!view.verbs.continue) return `There is nothing to continue in the ${opNoun(view.kind)}.`; - if (!view.canContinue) return view.continueBlocked || `git can't continue the ${opNoun(view.kind)} yet.`; + if (view.kind === "none" || view.kind === "stash") return l10n.t("Nothing is in progress."); + if (!view.verbs.continue) return l10n.t("There is nothing to continue in the {0}.", opNoun(view.kind)); + if (!view.canContinue) return view.continueBlocked || l10n.t("git can't continue the {0} yet.", opNoun(view.kind)); return undefined; } @@ -96,40 +97,40 @@ function doneText( if (verb === "skip") return `${skipEndedText(before)}.`; if (kind === "am") { return verb === "continue" - ? "All patches applied." - : "Patch series abandoned — the branch is back where it was before it started."; + ? l10n.t("All patches applied.") + : l10n.t("Patch series abandoned — the branch is back where it was before it started."); } if (kind === "stash") { - return "Stash apply cancelled — the files are back as they were, and the stash is still in your list."; + return l10n.t("Stash apply cancelled — the files are back as they were, and the stash is still in your list."); } if (kind === "none") { - return "The conflicted files are back to their last committed versions."; + return l10n.t("The conflicted files are back to their last committed versions."); } const noun = operationNoun(kind); - return verb === "abort" ? `${noun} cancelled — the repository is back where it was before.` : `${noun} complete.`; + return verb === "abort" ? l10n.t("{0} cancelled — the repository is back where it was before.", noun) : l10n.t("{0} complete.", noun); } function stoppedText(view: OperationView): string { if (view.pause) { - return `Paused: ${view.pause.detail}`; + return l10n.t("Paused: {0}", view.pause.detail); } if (view.step) { - return `Stopped at ${view.step.unit} ${view.step.n} of ${view.step.m} — it has conflicts to resolve.`; + return l10n.t("Stopped at {0} {1} of {2} — it has conflicts to resolve.", view.step.unit, view.step.n, view.step.m); } - return "Stopped again — there are conflicts to resolve."; + return l10n.t("Stopped again — there are conflicts to resolve."); } function refusedText(outcome: OperationOutcome, verb: OperationVerb): string { switch (outcome.refused) { case "blocked": - return outcome.view.continueBlocked || "Git can't continue yet."; + return outcome.view.continueBlocked || l10n.t("Git can't continue yet."); case "confirm-drop": return outcome.view.willDrop - ? `Continuing drops ${outcome.view.willDrop.sha.slice(0, 7)} ${outcome.view.willDrop.subject} — confirm to go ahead.` - : "Continuing would drop an emptied commit — confirm to go ahead."; + ? l10n.t("Continuing drops {0} {1} — confirm to go ahead.", outcome.view.willDrop.sha.slice(0, 7), outcome.view.willDrop.subject) + : l10n.t("Continuing would drop an emptied commit — confirm to go ahead."); case "not-allowed": - return verb === "skip" ? "There is nothing git can skip here." : "Nothing is in progress."; + return verb === "skip" ? l10n.t("There is nothing git can skip here.") : l10n.t("Nothing is in progress."); default: - return `Git refused to ${verb}.`; + return l10n.t("Git refused to {0}.", verb); } } diff --git a/packages/merge-vscode/src/payload.ts b/packages/merge-vscode/src/payload.ts index 01cc3520..02205edd 100644 --- a/packages/merge-vscode/src/payload.ts +++ b/packages/merge-vscode/src/payload.ts @@ -20,6 +20,7 @@ import { parseConflictMarkers } from "@gitstudio/engine/conflict/markers"; import type { MergeSides, ReadSidesOptions } from "@gitstudio/git-service/ConflictOps"; import type { OperationView } from "@gitstudio/host-bridge/conflictsProtocol"; import type { ConflictType, MergeInitPayload } from "@gitstudio/host-bridge/protocol"; +import * as l10n from "@vscode/l10n"; /** The one read the payload is built from (ConflictOps in production, a fake in tests). */ export interface SidesReader { @@ -43,7 +44,7 @@ export interface PayloadInput { } /** Labels used when there is no operation to name the sides. */ -export const GENERIC_LABELS = { yours: "Yours", theirs: "Theirs" } as const; +export const GENERIC_LABELS = { yours: l10n.t("Yours"), theirs: l10n.t("Theirs") } as const; /** * Builds the payload from the role-mapped sides. `op` is included when an diff --git a/packages/merge-vscode/src/product.ts b/packages/merge-vscode/src/product.ts index 33cf3c1f..d5f853b5 100644 --- a/packages/merge-vscode/src/product.ts +++ b/packages/merge-vscode/src/product.ts @@ -14,6 +14,7 @@ import { type ConflictsState, type MergeSettings, } from "@gitstudio/host-bridge/conflictsProtocol"; +import * as l10n from "@vscode/l10n"; /** * The command ids a product registers, by role. GitStudio and Merge Studio use @@ -166,14 +167,14 @@ export function sidesTipText( version: string, op: { kind: string; yours: { name: string } }, ): string | undefined { - const lead = `New in ${product.displayName} ${version}:`; - const after = "Before this version the two sides were swapped."; + const lead = l10n.t("New in {0} {1}:", product.displayName, version); + const after = l10n.t("Before this version the two sides were swapped."); if (op.kind === "rebase" || op.kind === "rebase-merge-step") { const name = op.yours.name ? ` (${op.yours.name})` : ""; - return `${lead} during a rebase, Yours is your commit${name}, on the left. ${after}`; + return l10n.t("{0} during a rebase, Yours is your commit{1}, on the left. {2}", lead, name, after); } if (op.kind === "stash") { - return `${lead} when a stash is applied, Yours is your stashed changes, on the left. ${after}`; + return l10n.t("{0} when a stash is applied, Yours is your stashed changes, on the left. {1}", lead, after); } return undefined; } @@ -404,22 +405,22 @@ export function statusItemLook(s: { if (s.defers) return undefined; if (s.unmerged > 0) { return { - text: "$(warning) Resolve Conflicts", - tooltip: `${s.unmerged === 1 ? "1 conflicted file" : `${s.unmerged} conflicted files`} — open the Conflicts view`, + text: l10n.t("$(warning) Resolve Conflicts"), + tooltip: l10n.t("{0} — open the Conflicts view", s.unmerged === 1 ? l10n.t("1 conflicted file") : l10n.t("{0} conflicted files", s.unmerged)), warning: true, }; } if (s.op?.pause) { return { - text: "$(debug-pause) Rebase paused", - tooltip: `${s.op.pause.detail || "Paused"}. Open the Conflicts view to continue.`, + text: l10n.t("$(debug-pause) Rebase paused"), + tooltip: l10n.t("{0}. Open the Conflicts view to continue.", s.op.pause.detail || l10n.t("Paused")), warning: false, }; } if (s.op?.continueVerb) { return { - text: `$(debug-continue) ${s.op.continueVerb}`, - tooltip: "All conflicts are resolved. Open the Conflicts view to continue.", + text: l10n.t("$(debug-continue) {0}", s.op.continueVerb), + tooltip: l10n.t("All conflicts are resolved. Open the Conflicts view to continue."), warning: false, }; } diff --git a/packages/merge-vscode/src/register.ts b/packages/merge-vscode/src/register.ts index e338b7c4..85224bcd 100644 --- a/packages/merge-vscode/src/register.ts +++ b/packages/merge-vscode/src/register.ts @@ -34,6 +34,7 @@ import { MergeEditorProvider, saveConflictedDocuments } from "./mergeEditorProvi import { continueRefusal, outcomeLine, verbConfirm, type OperationVerb } from "./outcome"; import { statusItemLook, type MergePeerApi, type MergeProduct, type MergeRepo } from "./product"; import { ConflictStatusItem } from "./statusItem"; +import * as l10n from "@vscode/l10n"; export interface OperationVerbOptions { /** The repository to act on; default: the one with an operation in progress. */ @@ -319,8 +320,8 @@ export async function driveVerb( if (view.willDrop) { const w = view.willDrop; confirmDrop = await product.ask({ - title: "Drop the emptied commit?", - message: `After your resolution, ${w.sha.slice(0, 7)} “${w.subject}” has no changes left, so git leaves it out of ${w.branch}.`, + title: l10n.t("Drop the emptied commit?"), + message: l10n.t("After your resolution, {0} “{1}” has no changes left, so git leaves it out of {2}.", w.sha.slice(0, 7), w.subject, w.branch), confirmLabel: `${view.verbs.continue} and drop it`, danger: true, }); @@ -362,7 +363,7 @@ export async function driveVerb( } else if (line.kind === "done") { void host.notify("info", line.text); } else if (line.kind === "stopped") { - const resolve = "Resolve Conflicts…"; + const resolve = l10n.t("Resolve Conflicts…"); void host.notify("warn", line.text, resolve).then((choice) => { if (choice === resolve) { void vscode.commands.executeCommand(product.commands.showConflicts); diff --git a/packages/merge-vscode/src/stageResolved.ts b/packages/merge-vscode/src/stageResolved.ts index 7665536c..4d3e8922 100644 --- a/packages/merge-vscode/src/stageResolved.ts +++ b/packages/merge-vscode/src/stageResolved.ts @@ -1,3 +1,4 @@ +import * as l10n from "@vscode/l10n"; // Stage a resolved file, and say so only when git actually did. // // `GitProcess.run` never throws on a non-zero exit — it resolves with the code @@ -33,7 +34,7 @@ export async function stageResolvedPath(proc: GitRunner, rel: string): Promise @@ -40,7 +42,7 @@ export function mergeWebviewHtml(webview: vscode.Webview, extensionUri: vscode.U - Merge + ${l10n.t("Merge")} -
Loading editor…
+
${l10n.t("Loading editor…")}
+ ${l10nWebviewScript(nonce)} @@ -74,7 +77,7 @@ export function conflictsWebviewHtml(webview: vscode.Webview, extensionUri: vsco const dist = (...parts: string[]) => webview.asWebviewUri(vscode.Uri.joinPath(extensionUri, "dist", ...parts)); const csp = [ - `default-src 'none'`, + "default-src 'none'", `img-src ${webview.cspSource} data:`, `style-src ${webview.cspSource}`, `font-src ${webview.cspSource} data:`, @@ -88,10 +91,11 @@ export function conflictsWebviewHtml(webview: vscode.Webview, extensionUri: vsco - Conflicts + ${l10n.t("Conflicts")}
+ ${l10nWebviewScript(nonce)} `; diff --git a/packages/webview-ui/package.json b/packages/webview-ui/package.json index 43a6074b..97d2df6a 100644 --- a/packages/webview-ui/package.json +++ b/packages/webview-ui/package.json @@ -15,7 +15,9 @@ "dependencies": { "@gitstudio/engine": "*", "@gitstudio/host-bridge": "*", + "@gitstudio/l10n": "*", "@tanstack/virtual-core": "^3.13.12", + "@vscode/l10n": "^0.0.18", "lit": "^3.3.1", "monaco-editor": "^0.55.1" } diff --git a/packages/webview-ui/src/changeRows/changeRows.ts b/packages/webview-ui/src/changeRows/changeRows.ts index 0d63af4e..a5956bd7 100644 --- a/packages/webview-ui/src/changeRows/changeRows.ts +++ b/packages/webview-ui/src/changeRows/changeRows.ts @@ -14,6 +14,7 @@ import { statusWords, type ChangeCommit, type ChangeFile } from "@gitstudio/host-bridge/changeRows"; import { relTime } from "../graph/format"; +import * as l10n from "@vscode/l10n"; export type { ChangeCommit, ChangeFile }; @@ -108,15 +109,15 @@ export function fileRow(f: ChangeFile, o: FileRowOptions = {}): HTMLElement { row.appendChild(nums); } const words = statusWords(st, f.area); - const was = f.oldPath ? `, was ${f.oldPath}` : ""; + const was = f.oldPath ? l10n.t(", was {0}", f.oldPath) : ""; if (o.onOpen) { const open = o.onOpen; row.classList.add("clickable"); row.setAttribute("role", o.role ?? "button"); row.tabIndex = o.tabIndex ?? 0; - const tip = `Open changes — ${f.path}${f.oldPath ? ` (was ${f.oldPath})` : ""}`; + const tip = l10n.t("Open changes — {0}{1}", f.path, f.oldPath ? l10n.t(" (was {0})", f.oldPath) : ""); row.dataset.tip = tip; - row.setAttribute("aria-label", `${name}, ${words}${was}${dir ? `, in ${dir}` : ""}. Open changes`); + row.setAttribute("aria-label", l10n.t("{0}, {1}{2}{3}. Open changes", name, words, was, dir ? l10n.t(", in {0}", dir) : "")); row.addEventListener("click", () => open(f)); row.addEventListener("keydown", (e) => { if (e.target !== row) return; @@ -128,8 +129,8 @@ export function fileRow(f: ChangeFile, o: FileRowOptions = {}): HTMLElement { } else { if (o.role) row.setAttribute("role", o.role); if (o.tabIndex !== undefined) row.tabIndex = o.tabIndex; - row.dataset.tip = `${f.path}${f.oldPath ? ` (was ${f.oldPath})` : ""}`; - row.setAttribute("aria-label", `${name}, ${words}${was}${dir ? `, in ${dir}` : ""}`); + row.dataset.tip = `${f.path}${f.oldPath ? l10n.t(" (was {0})", f.oldPath) : ""}`; + row.setAttribute("aria-label", `${name}, ${words}${was}${dir ? l10n.t(", in {0}", dir) : ""}`); } if (o.indent) row.style.paddingLeft = `${o.indent}px`; return row; @@ -190,7 +191,7 @@ export function commitRow(c: ChangeCommit, o: CommitRowOptions = {}): HTMLElemen row.setAttribute("role", o.role ?? "button"); row.tabIndex = o.tabIndex ?? 0; row.setAttribute("aria-expanded", "false"); - row.setAttribute("aria-label", `${c.subject} — ${c.sha.slice(0, 7)} by ${c.author}, ${when}. Show its files`); + row.setAttribute("aria-label", l10n.t("{0} — {1} by {2}, {3}. Show its files", c.subject, c.sha.slice(0, 7), c.author, when)); const files = el("div", "cr-commit-files"); files.hidden = true; files.setAttribute("role", "group"); @@ -234,7 +235,7 @@ export function toggleCommit(item: HTMLElement, open?: boolean): void { files.hidden = !next; if (next && !it._asked) { it._asked = true; - files.replaceChildren(el("div", "cr-loading", "Loading files…")); + files.replaceChildren(el("div", "cr-loading", l10n.t("Loading files…"))); if (it._commit) it._opts?.loadFiles?.(it._commit); } } @@ -248,11 +249,11 @@ export function setCommitFiles(item: HTMLElement, list: ChangeFile[] | null): vo const o = it._opts ?? {}; const indent = (o.indent ?? 8) + 18; if (list === null) { - files.replaceChildren(el("div", "cr-loading", "Couldn't read this commit's files.")); + files.replaceChildren(el("div", "cr-loading", l10n.t("Couldn't read this commit's files."))); return; } if (list.length === 0) { - files.replaceChildren(el("div", "cr-loading", "No file changes in this commit.")); + files.replaceChildren(el("div", "cr-loading", l10n.t("No file changes in this commit."))); return; } files.replaceChildren( diff --git a/packages/webview-ui/src/changeRows/global.ts b/packages/webview-ui/src/changeRows/global.ts index 2112d608..477904bd 100644 --- a/packages/webview-ui/src/changeRows/global.ts +++ b/packages/webview-ui/src/changeRows/global.ts @@ -7,6 +7,8 @@ // then drift from — this bundle hands it the same functions the Worktrees page // imports, as `window.GsChangeRows` (dist/webview/change-rows.js). +import "@gitstudio/l10n/webview"; + import { installSolidAccent } from "../styles/solidAccent"; import * as rows from "./changeRows"; diff --git a/packages/webview-ui/src/commit-details.ts b/packages/webview-ui/src/commit-details.ts index 0e22b3f6..c417d6cc 100644 --- a/packages/webview-ui/src/commit-details.ts +++ b/packages/webview-ui/src/commit-details.ts @@ -22,6 +22,7 @@ import type { CommitFileChange, WireRef, } from "@gitstudio/host-bridge/commitDetailsProtocol"; +import * as l10n from "@vscode/l10n"; interface ActionDef { id: CommitDetailsActionId; @@ -46,21 +47,21 @@ const CONTAINS_AUTO_EXPAND = 8; const CONTAINS_DEBOUNCE_MS = 350; const COMMIT_ACTIONS: ActionDef[] = [ - { id: "checkout", label: "Checkout", icon: "check", primary: true }, - { id: "branch", label: "Branch", icon: "git-branch" }, - { id: "tag", label: "Tag", icon: "tag" }, - { id: "cherry-pick", label: "Cherry-pick", icon: "git-commit" }, - { id: "revert", label: "Revert", icon: "discard" }, - { id: "interactive-rebase", label: "Rebase", icon: "git-merge" }, - { id: "reset", label: "Reset", icon: "history", danger: true }, + { id: "checkout", label: l10n.t("Checkout"), icon: "check", primary: true }, + { id: "branch", label: l10n.t("Branch"), icon: "git-branch" }, + { id: "tag", label: l10n.t("Tag"), icon: "tag" }, + { id: "cherry-pick", label: l10n.t("Cherry-pick"), icon: "git-commit" }, + { id: "revert", label: l10n.t("Revert"), icon: "discard" }, + { id: "interactive-rebase", label: l10n.t("Rebase"), icon: "git-merge" }, + { id: "reset", label: l10n.t("Reset"), icon: "history", danger: true }, ]; const WIP_ACTIONS: ActionDef[] = [ - { id: "commit", label: "Commit…", icon: "git-commit", primary: true }, - { id: "stage-all", label: "Stage all", icon: "add" }, - { id: "unstage-all", label: "Unstage all", icon: "dash" }, - { id: "stash", label: "Stash", icon: "archive" }, - { id: "discard-all", label: "Discard all", icon: "discard", danger: true }, + { id: "commit", label: l10n.t("Commit…"), icon: "git-commit", primary: true }, + { id: "stage-all", label: l10n.t("Stage all"), icon: "add" }, + { id: "unstage-all", label: l10n.t("Unstage all"), icon: "dash" }, + { id: "stash", label: l10n.t("Stash"), icon: "archive" }, + { id: "discard-all", label: l10n.t("Discard all"), icon: "discard", danger: true }, ]; /** @@ -836,8 +837,8 @@ export class CommitDetails extends LitElement { /** Close (X) affordance for the docked details panel — the host collapses the * dock so the graph reclaims the space. */ private closeButton() { - return html``; } @@ -850,7 +851,7 @@ export class CommitDetails extends LitElement { if (!d) { return html`
- Select a commit to see its details + ${l10n.t("Select a commit to see its details")}
`; } const isWip = d.kind === "wip"; @@ -865,14 +866,14 @@ export class CommitDetails extends LitElement {
${d.hasRemote - ? html`` : nothing} @@ -1013,10 +1014,10 @@ export class CommitDetails extends LitElement {
-
Uncommitted changes - in your working tree +
${l10n.t("Uncommitted changes")} + ${l10n.t("in your working tree")}
-
Stage, commit, stash, or discard below
+
${l10n.t("Stage, commit, stash, or discard below")}
${this.closeButton()}
`; @@ -1077,7 +1078,7 @@ export class CommitDetails extends LitElement { role="button" tabindex="0" aria-haspopup="menu" - title=${`${label} — filter the graph by it, or check it out`} + title=${l10n.t("{0} — filter the graph by it, or check it out", label)} @click=${(e: MouseEvent) => this.onRefChipClick(r, e)} @contextmenu=${(e: MouseEvent) => { e.preventDefault(); @@ -1092,14 +1093,14 @@ export class CommitDetails extends LitElement { >${body}
`; return html`
- ${locals.length ? row("tip of", locals.map(chip)) : nothing} + ${locals.length ? row(l10n.t("tip of"), locals.map(chip)) : nothing} ${remotes.length - ? row("pushed to", remotes.map(chip)) + ? row(l10n.t("pushed to"), remotes.map(chip)) : row("", html`not pushed`)} - ${tags.length ? row("tagged", tags.map(chip)) : nothing} + >${l10n.t("not pushed")}`)} + ${tags.length ? row(l10n.t("tagged"), tags.map(chip)) : nothing} ${this.containsHtml()}
`; } @@ -1159,16 +1160,16 @@ export class CommitDetails extends LitElement { return nothing; } if (state === "loading") { - return html`
inchecking\u2026
`; + return html`
${l10n.t("in")}${l10n.t("checking…")}
`; } const list = this.containsList; if (list.length === 0) { - return html`
inno branches
`; + return html`
${l10n.t("in")}${l10n.t("no branches")}
`; } const n = `${list.length}${this.containsTruncated ? "+" : ""}`; - return html`
in${l10n.t("in")} @@ -1191,10 +1192,10 @@ export class CommitDetails extends LitElement { // labelled and shaped differently: the sha is a copy target, each parent is // a link with a "go there" arrow. return html`
- commit + ${l10n.t("commit")} ${d.parents.length ? html` - ${d.parents.length === 1 ? "parent" : "parents"} + ${d.parents.length === 1 ? l10n.t("parent") : l10n.t("parents")} ${d.parents.map( (p, i) => html`
${this.closeButton()}
-
    +
      ${s.commits.map( (c) => html`
    • `, )}
    -
    +
    ${actions.map( (a) => html`
    ` + span + `
    ` ); diff --git a/packages/webview-ui/src/graph/commit-graph.ts b/packages/webview-ui/src/graph/commit-graph.ts index 6f6b5417..bfec9352 100644 --- a/packages/webview-ui/src/graph/commit-graph.ts +++ b/packages/webview-ui/src/graph/commit-graph.ts @@ -86,6 +86,7 @@ import { sameRows, type Selection, } from "./multiSelect"; +import * as l10n from "@vscode/l10n"; // ── Layout constants (the visual contract; tuned to GitLens proportions) ───── const ROW_HEIGHT = 34; @@ -198,15 +199,15 @@ interface ColumnSpec { const COLUMN_SPECS: readonly ColumnSpec[] = [ // The graph gutter auto-sizes to the lane count; a manual resize overrides // that (dbl-click / Home on the grip restores auto). Never hideable. - { id: "graph", label: "Graph", cssVar: "--gs-gutter-w", def: MIN_GUTTER_WIDTH, min: MIN_GUTTER_WIDTH, max: 480, hideable: false }, + { id: "graph", label: l10n.t("Graph"), cssVar: "--gs-gutter-w", def: MIN_GUTTER_WIDTH, min: MIN_GUTTER_WIDTH, max: 480, hideable: false }, // Branch/Tag is a fixed, resizable track (not auto-fit) so subjects start at // the same x on every row — a real scanability win, GitLens-style. Default is // lean so empty-ref rows don't waste width; drag wider for busy ref sets. - { id: "refs", label: "Branch / Tag", cssVar: "--col-refs-w", def: 260, min: 60, max: 640 }, - { id: "changes", label: "Changes", cssVar: "--col-changes-w", def: 100, min: 76, max: 220 }, - { id: "author", label: "Author", cssVar: "--col-author-w", def: 112, min: 76, max: 240 }, - { id: "date", label: "Date", cssVar: "--col-date-w", def: 84, min: 58, max: 170 }, - { id: "sha", label: "SHA", cssVar: "--col-sha-w", def: 66, min: 58, max: 140 }, + { id: "refs", label: l10n.t("Branch / Tag"), cssVar: "--col-refs-w", def: 260, min: 60, max: 640 }, + { id: "changes", label: l10n.t("Changes"), cssVar: "--col-changes-w", def: 100, min: 76, max: 220 }, + { id: "author", label: l10n.t("Author"), cssVar: "--col-author-w", def: 112, min: 76, max: 240 }, + { id: "date", label: l10n.t("Date"), cssVar: "--col-date-w", def: 84, min: 58, max: 170 }, + { id: "sha", label: l10n.t("SHA"), cssVar: "--col-sha-w", def: 66, min: 58, max: 140 }, ]; const COLUMN_BY_ID = new Map( COLUMN_SPECS.map((c) => [c.id, c]), @@ -3118,7 +3119,7 @@ export class CommitGraph extends LitElement { }; const done = () => { cell.classList.add("copied"); - cell.replaceChildren(glyph("check"), document.createTextNode("Copied")); + cell.replaceChildren(glyph("check"), document.createTextNode(l10n.t("Copied"))); this.copiedTimer = window.setTimeout(() => { cell.classList.remove("copied"); cell.replaceChildren(document.createTextNode(label), glyph("copy")); @@ -3390,7 +3391,7 @@ export class CommitGraph extends LitElement { ); const label = esc( isWip - ? "Uncommitted changes" + ? l10n.t("Uncommitted changes") : `${row.shortSha}: ${row.subject} — ${row.author}, ${relTime(row.authorDate)}`, ); return ( @@ -3399,7 +3400,7 @@ export class CommitGraph extends LitElement { // as you arrowed through history — every row carries a good aria-label // and none of them was ever announced. `
    0 && this.isFirstInert(row.sha) ? `data-inert-why="${esc(stopReason(this.chainStop))}" ` : "") + @@ -4186,15 +4187,19 @@ export class CommitGraph extends LitElement { // Commits only: the "Uncommitted changes" row the host puts on top of a // dirty tree is not one, and counting it made 17 commits read "18". const n = this.rows.reduce((k, r) => (ZERO_SHA_RE.test(r.sha) ? k : k + 1), 0); + const countText = `${n.toLocaleString()}${this.hasMore ? "+" : ""}`; const count = n === 0 ? "" - : `${n.toLocaleString()}${this.hasMore ? "+" : ""} commit${n === 1 ? "" : "s"}`; + : n === 1 + ? l10n.t("{0} commit", countText) + : l10n.t("{0} commits", countText); const q = this.searchQuery.trim(); // The search only sees the rows that are LOADED. Saying "No results" while // more history is unread states as fact something we have not looked at — // and "3/3" implies the search is finished when it is not. The "+" is the // same honesty the commit count beside it already uses. + const matchText = `${this.searchMatches.length.toLocaleString()}${this.hasMore ? "+" : ""}`; const results = q ? this.searchMatches.length ? // Before you travel to one, `matchIdx` is -1 — there is no "current" @@ -4203,27 +4208,29 @@ export class CommitGraph extends LitElement { // that cannot exist: every other counter in the app is 1-based, so // "0 of 12" says the search found nothing while listing twelve. this.matchIdx < 0 - ? `${this.searchMatches.length.toLocaleString()}${this.hasMore ? "+" : ""} match${this.searchMatches.length === 1 ? "" : "es"}` + ? this.searchMatches.length === 1 + ? l10n.t("{0} match", matchText) + : l10n.t("{0} matches", matchText) : `${this.matchIdx + 1}/${this.searchMatches.length}${this.hasMore ? "+" : ""}` : this.hasMore - ? `No results in ${n.toLocaleString()} loaded` - : "No results" + ? l10n.t("No results in {0} loaded", n.toLocaleString()) + : l10n.t("No results") : ""; return html`
    ${branch || (this.head ? this.head.slice(0, 8) : "no commits yet")}${branch || (this.head ? this.head.slice(0, 8) : l10n.t("no commits yet"))} ${count ? html`${count}` : nothing} @@ -4236,7 +4243,7 @@ export class CommitGraph extends LitElement { class="gh-input" type="text" placeholder=${this.searchPlaceholder()} - aria-label="Search commits" + aria-label="${l10n.t("Search commits")}" .value=${this.searchQuery} @input=${this.onSearchInput} @keydown=${this.onSearchKey} @@ -4247,19 +4254,19 @@ export class CommitGraph extends LitElement { > `, )} ${g.hidden - ? html`
    ${g.hidden} more — type to narrow
    ` + ? html`
    ${l10n.t("{0} more — type to narrow", g.hidden)}
    ` : nothing}`, )} ${groups.length === 0 && refs.length - ? html`
    No branches match
    ` + ? html`
    ${l10n.t("No branches match")}
    ` : nothing}
    @@ -4464,7 +4471,7 @@ export class CommitGraph extends LitElement { class="gh-pop gh-ctx gh-chip-menu" role="menu" tabindex="-1" - aria-label=${`Filter by ${title}`} + aria-label=${l10n.t("Filter by {0}", title)} style="left:${Math.round(left)}px;top:${Math.round(top)}px" @keydown=${this.onPopoverKeyDown} > @@ -4477,7 +4484,7 @@ export class CommitGraph extends LitElement { @click=${() => pick(m.refs)} > - ${m.kind === "tag" ? "Show only this tag" : "Show only this branch"} + ${m.kind === "tag" ? l10n.t("Show only this tag") : l10n.t("Show only this branch")} ${this.refFilter ? html`
    -
    Not in the branch list yet — refresh the graph
    `} +
    ${l10n.t("Not in the branch list yet — refresh the graph")}
    `} `; } @@ -4533,8 +4540,8 @@ export class CommitGraph extends LitElement {
    ${hiddenCount === 0 - ? "Graph & message are always shown" - : `${hiddenCount} hidden · drag header edges to resize`} + ? l10n.t("Graph & message are always shown") + : l10n.t("{0} hidden · drag header edges to resize", hiddenCount)}
    ` : nothing} @@ -4588,20 +4595,20 @@ export class CommitGraph extends LitElement { if (this.status === "error") { return html`${header}
    -
    Couldn't load the history
    +
    ${l10n.t("Couldn't load the history")}
    ${this.errorMessage ? html`
    ${this.errorMessage}
    ` : nothing}
    ${nothing}`; } if (this.status === "no-repo") { return html`${header}
    -
    No repository open
    -
    Open a folder that's under Git and its history will appear here.
    +
    ${l10n.t("No repository open")}
    +
    ${l10n.t("Open a folder that's under Git and its history will appear here.")}
    ${nothing}`; } if (this.status === "discovering") { @@ -4609,27 +4616,27 @@ export class CommitGraph extends LitElement { // repository open" while one may still be found. return html`${header}
    -
    Looking for a repository…
    +
    ${l10n.t("Looking for a repository…")}
    ${nothing}`; } if (this.status === "empty") { return html`${header}
    -
    No commits yet
    -
    Make your first commit and the history will appear here.
    +
    ${l10n.t("No commits yet")}
    +
    ${l10n.t("Make your first commit and the history will appear here.")}
    ${nothing}`; } if (this.status === "loading" && this.rows.length === 0) { return html`${header}
    -
    Loading history…
    +
    ${l10n.t("Loading history…")}
    ${nothing}`; } return html`${header}${this.colHeadHtml()}
    Graph${this.resizeHandle("graph")}${l10n.t("Graph")}${this.resizeHandle("graph")} Branch / Tag${this.resizeHandle("refs")}${l10n.t("Branch / Tag")}${this.resizeHandle("refs")} Commit message${this.resizeHandle( + >${l10n.t("Commit message")}${this.resizeHandle( "changes", true, )} Changes${this.resizeHandle("changes")}${l10n.t("Changes")}${this.resizeHandle("changes")} Author${this.resizeHandle("author")}${l10n.t("Author")}${this.resizeHandle("author")} Date${this.resizeHandle("date")}${l10n.t("Date")}${this.resizeHandle("date")} - SHA + ${l10n.t("SHA")}
    `; } @@ -4747,15 +4754,15 @@ export class CommitGraph extends LitElement { role="separator" aria-orientation="vertical" aria-label=${invert - ? "Resize Commit message / Changes divider" - : `Resize ${spec.label} column`} + ? l10n.t("Resize Commit message / Changes divider") + : l10n.t("Resize {0} column", spec.label)} /* A divider resizes the column to its LEFT, which is the table convention but is not self-evident when the label you are standing next to is the one on the RIGHT ("I dragged Author and Changes moved"). Name the column out loud. */ title=${invert - ? "Drag to resize Commit message / Changes" - : `Drag to resize ${spec.label} · double-click to reset`} + ? l10n.t("Drag to resize Commit message / Changes") + : l10n.t("Drag to resize {0} · double-click to reset", spec.label)} aria-valuenow=${Math.round(w)} aria-valuemin=${spec.min} aria-valuemax=${spec.max} @@ -4828,7 +4835,7 @@ function chipHtml(entry: ChipEntry): string { const { ref, label, remotes, twins } = entry; const nm = refNameHtml(ref, label); const tail = tailHtml(remotes); - const also = remotes.length ? ` · also on ${esc(remotes.join(", "))}` : ""; + const also = remotes.length ? l10n.t(" · also on {0}", esc(remotes.join(", "))) : ""; const tip = esc(tipData([{ name: ref.name, label, fullName: ref.fullName, kind: ref.kind, remotes, twins }])); // `data-full` / `data-twins` are what the chip's filter menu (issue #30) // resolves by: the chip's own full name and the folded twins', so "main ☁" @@ -4843,13 +4850,13 @@ function chipHtml(entry: ChipEntry): string { case "currentHead": // No leading dot: the filled accent already marks the current branch, and // the dot + name + cloud tail read as clutter at chip size. - return `${BRANCH_ICON}${nm}${tail}`; + return `${BRANCH_ICON}${nm}${tail}`; case "head": - return `${BRANCH_ICON}${nm}${tail}`; + return `${BRANCH_ICON}${nm}${tail}`; case "remoteHead": - return `${REMOTE_ICON}${nm}`; + return `${REMOTE_ICON}${nm}`; case "tag": - return `${TAG_ICON}${nm}`; + return `${TAG_ICON}${nm}`; } } @@ -4866,7 +4873,7 @@ function shaCellHtml(fullSha: string, shortSha: string, isWip: boolean): string const short = esc(shortSha); return ( `
    ` + + `title="${l10n.t("Click to copy {0}", esc(fullSha))}">` + `${short}` + `
    ` ); diff --git a/packages/webview-ui/src/graph/commit-rail.ts b/packages/webview-ui/src/graph/commit-rail.ts index f15d7d5a..ab4200b6 100644 --- a/packages/webview-ui/src/graph/commit-rail.ts +++ b/packages/webview-ui/src/graph/commit-rail.ts @@ -81,6 +81,7 @@ import { reconcile, type Selection, } from "./multiSelect"; +import * as l10n from "@vscode/l10n"; // ── Layout constants (the sidebar's visual contract) ──────────────────────── const ROW_HEIGHT = 40; @@ -1432,7 +1433,7 @@ export class CommitRail extends LitElement { ); } } - const subject = esc(isWip ? row.subject || "Uncommitted changes" : row.subject); + const subject = esc(isWip ? row.subject || l10n.t("Uncommitted changes") : row.subject); const chips = row.refs.length ? this.chipsHtml(row.refs) : ""; const who = isWip ? "" : esc(shortAuthor(row.author)); const age = isWip ? "now" : esc(relTime(row.authorDate)); @@ -1441,16 +1442,16 @@ export class CommitRail extends LitElement { ? `\n${row.refs.map((r) => chipLabel(r)).join(", ")}` : ""; const tip = isWip - ? "Uncommitted changes — open in the Commit Graph for details" + ? l10n.t("Uncommitted changes — open in the Commit Graph for details") : `${row.shortSha} · ${row.subject}\n${row.author} · ${absTime(row.authorDate)}${tipRefs}`; const acts = isWip ? `` + - `` + + `` + `` : `` + - `` + - `` + + `` + + `` + ``; return ( @@ -1489,7 +1490,7 @@ export class CommitRail extends LitElement { twins: e.twins, title: e.ref.kind === "tag" - ? `tag: ${e.label}` + ? l10n.t("tag: {0}", e.label) : [e.label, ...e.twins.map((t) => refDisplayName(t))].join(", "), })); @@ -2103,8 +2104,8 @@ export class CommitRail extends LitElement { `, )} - ${g.hidden ? html`
    ${g.hidden} more — type to narrow
    ` : nothing}`, + ${g.hidden ? html`
    ${l10n.t("{0} more — type to narrow", g.hidden)}
    ` : nothing}`, )} ${groups.length === 0 && refs.length - ? html`
    No branches match
    ` + ? html`
    ${l10n.t("No branches match")}
    ` : nothing} @@ -2334,11 +2335,11 @@ export class CommitRail extends LitElement { `; } @@ -2446,7 +2447,7 @@ export class CommitRail extends LitElement {