diff options
69 files changed, 2832 insertions, 1635 deletions
diff --git a/.gitignore b/.gitignore index 272ea2b5ed..0791a17c71 100644 --- a/.gitignore +++ b/.gitignore @@ -42,14 +42,10 @@ _testmain.go coverage.all cpu.out -/modules/migration/bindata.go -/modules/migration/bindata.go.hash -/modules/options/bindata.go -/modules/options/bindata.go.hash -/modules/public/bindata.go -/modules/public/bindata.go.hash -/modules/templates/bindata.go -/modules/templates/bindata.go.hash +/modules/migration/bindata.* +/modules/options/bindata.* +/modules/public/bindata.* +/modules/templates/bindata.* *.db *.log diff --git a/CHANGELOG.md b/CHANGELOG.md index ca2e67929c..b72ac4849a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,429 @@ This changelog goes through the changes that have been made in each release without substantial changes to our git log; to see the highlights of what has been added to each release, please refer to the [blog](https://blog.gitea.com). +## [1.24.0](https://github.com/go-gitea/gitea/releases/tag/1.24.0) - 2025-05-26 + +* BREAKING + * Make Gitea always use its internal config, ignore `/etc/gitconfig` (#33076) + * Improve log format (#33814) + * Fix markdown render behaviors (#34122) + * Add package version api endpoints (#34173) + +* FEATURES + * Enforce two-factor auth (2FA: TOTP or WebAuthn) (#34187) + * Add fullscreen mode as a more efficient operation way to view projects (#34081) + * Add anonymous access support for private/unlisted repositories (#34051) + * Support public code/issue access for private repositories (#33127) + * Add middleware for request prioritization (#33951) + * Add cli flags LDAP group configuration (#33933) + * Add file tree to file view page (#32721) + * Add material icons for file list (#33837) + * Artifacts download api for artifact actions v4 (#33510) + * Support choose email when creating a commit via web UI (#33432) + * Add basic auth support to rss/atom feeds (#33371) + * Add sorting by exclusive labels (issue priority) (#33206) + * Add sub issue list support (#32940) + * Private README.md for organization (#32872) + * Email option to embed images as base64 instead of link (#32061) + * Option to delay conflict checking of old pull requests until page view (#27779) + * Worktime tracking for the organization level (#19808) + +* PERFORMANCE + * Add cache for common package queries (#22491) + * Move issue pin to an standalone table for querying performance (#33452) + * Improve commits list performance to reduce unnecessary database queries (#33528) + * Optimize total count of feed when loading activities in user dashboard. (#33841) + * Optimize heatmap query (#33853) + * Only use prev and next buttons for pagination on user dashboard (#33981) + * Improve pull request list API performance (#34052) + * Cache GPG keys, emails and users when list commits (#34086) + * Refactor Git Attribute & performance optimization (#34154) + * Performance optimization for tags synchronization (#34355) #34522 + +* ENHANCEMENTS + * Code + * Display when a release attachment was uploaded (#34261) + * Support creating relative link to raw path in markdown (#34105) + * Improve code block readability and isolate copy button (#34009) + * Improve repository commit view (#33877) + * Full-file syntax highlighting for diff pages (#33766) + * Clone repository with Tea CLI (#33725) + * Improve sync fork behavior (#33319) + * Make git clone URL could use current signed-in user (#33091) + * Add submodule diff links (#33097) + * Link to tree views of submodules if possible (#33424) + * Only keep popular licenses (#33832) + * De-emphasize signed commits (#31160) + + * Actions + * Add flat-square action badge style (#34062) + * Update action status badge layout (#34018) + * Download actions job logs from API (#33858) + * Always show the "rerun" button for action jobs (#33692) + * Add auto-expanding running actions step (#30058) + * Update status check for all supported on.pull_request.types in Gitea (#33117) + * Workflow_dispatch use workflow from trigger branch (#33098) + * Add action auto-scroll (#30057) + * Add workflow_job webhook (#33694) + * Add a button editing action secret (#34462) + + * Pull Request + * Auto expand "New PR" form (#33971) + * Mark parent directory as viewed when all files are viewed (#33958) + * Show info about maintainers are allowed to edit a PR (#33738) + * Automerge supports deleting branch automatically after merging (#32343) + * Add additional command hints for PowerShell & CMD (#33548) + + * Issues + * Allow filtering issues by any assignee (#33343) + * Show warning on navigation if currently editing comment or title (#32920) + * Make tracked time representation display as hours (#33315) + * Add No Results Prompt Message on Issue List Page (#33699) + * Add sort option recentclose for issues and pulls (#34525) #34539 + + * Packages + * Link to nuget dependencies (#26554) + * Add composor source field (#33502) + + * Administration + * Improve navbar: add "admin" tip, add "active" style (#32927) + * Add a option "--user-type bot" to admin user create, improve role display (#27885) + * Improve admin user view page (#33735) + * Support performance trace (#32973) + * Change pprof labels to be prometheus compatible (#32865) + * Allow admins and org owners to change org member public status (#28294) + * Optimize the installation page (#32994) + * Make public URL generation configurable (#34250) + * Add a --fullname arg to gitea admin user create. (#34241) + + * Others + * Improve oauth2 error handling (#33969) + * Fail mirroring more gracefully (#34002) + * Align User Details Page Header Layout with Design Specifications (#34192) + * Webhook add X-Gitea-Hook-Installation-Target-Type Header (#33752) + * Optimize the dashboard (#32990) + * Improve button layout on small screens (#33633) + * Add cropping support when modifying the user/org/repo avatar (#33498) + * Make ROOT_URL support using request Host header (#32564) + * Add `show more` organizations icon in user's profile (#32986) + * Introduce `--page-space-bottom` at 64px (#30692) + * Improve theme display (#30671) + * Add alphabetical project sorting (#33504) + * Add global lock for migrations to make upgrade more safe with multiple replications (#33706) + * Add descriptions for private repo public access settings and improve the UI (#34057) + +* API + * Actions Runner rest api (#33873) + * Inclusion of rename organization api (#33303) + * Add API to support link package to repository and unlink it (#33481) + * Add API endpoint to request contents of multiple files simultaniously (#34139) + * Actions artifacts API list/download check status upload confirmed (#34273) + * Add API routes to lock and unlock issues (#34165) + * Fix some user name usages (#33689) + * Allow filtering /repos/{owner}/{repo}/pulls by target base branch queryparam (#33684) + * Improve swagger generation (#33664) + * Support Ephemeral action runners (#33570) + * Support workflow event dispatch via API (#33545) + * Support workflow event dispatch via API (#32059) + * Added Description Field for Secrets and Variables (#33526) + * Reject star-related requests if stars are disabled (#33208) + * Let API create and edit system webhooks, attempt 2 (#33180) + * Use `Project-URL` metadata field to get a PyPI package's homepage URL (#33089) + * Add `last_committer_date` and `last_author_date` for file contents API (#32921) + +* REFACTORS + * Remove context from git struct (#33793) + * Refactor admin/common.ts (#33788) + * Refactor repo-settings.ts (#33785) + * Refactor repo-issue.ts (#33784) + * Small refactor to reduce unnecessary database queries and remove duplicated functions (#33779) + * Refactor initRepoBranchTagSelector to use new init framework (#33776) + * Refactor buttons to use new init framework (#33774) + * Refactor markup and pdf-viewer to use new init framework (#33772) + * Refactor error system (#33771) + * Refactor mail code (#33768) + * Update TypeScript types (#33799) + * Refactor older tests to use testify (#33140) + * Move notifywatch to service layer (#33825) + * Decouple context from repository related structs (#33823) + * Remove context from mail struct (#33811) + * Refactor dropdown ellipsis (#34123) + * Refactor functions to reduce repopath expose (#33892) + * Refactor repo-diff.ts (#33746) + * Refactor web route handler (#33488) + * Refactor user & avatar (#33433) + * Refactor user package (#33423) + * Refactor decouple context from migration structs (#33399) + * Refactor context flash msg and global variables (#33375) + * Refactor response writer & access logger (#33323) + * Refactor ref type (#33242) + * Refactor context repository (#33202) + * Refactor legacy JS (#33115) + * Refactor legacy line-number and scroll code (#33094) + * Refactor env var related code (#33075) + * Move SetMerged to service layer (#33045) + * Merge updatecommentattachment functions (#33044) + * Refactor pull-request compare&create page (#33071) + * Refactor repo-new.ts (#33070) + * Refactor pagination (#33037) + * Refactor tests (#33021) + * Refactor markup render to fix various path problems (#34114) + * Refactor Branch struct in package modules/git (#33980) + * Don't create duplicated functions for code repositories and wiki repositories (#33924) + * Move git references checking to gitrepo packages to reduce expose of repository path (#33891) + * Refactor cache-control (#33861) + * Decouple diff stats query from actual diffing (#33810) + * Move part of updating protected branch logic to service layer (#33742) + * Decouple Batch from git.Repository to simplify usage without requiring the creation of a Repository struct. (#34001) + * Refactor tmpl and blob_excerpt (#32967) + * Refactor template & test related code (#32938) + * Refactor db package and remove unnecessary `DumpTables` (#32930) + * Refactor pprof labels and process desc (#32909) + * Refactor repo-projects.ts (#32892) + * Refactor getpatch/getdiff functions and remove unnecessary fallback (#32817) + * Uniform all temporary directories and allow customizing temp path (#32352) + * Remove context from retry downloader (#33871) + * Refactor global init code and add more comments (#33755) + * Remove some unnecessary template helpers (#33069) + * Move and rename UpdateRepository (#34136) + * Move hooks function to gitrepo and reduce expose repopath (#33890) + * Add abstraction layer to delete repository from disk (#33879) + * Add abstraction layer to check if the repository exists on disk (#33874) + * Move ParseCommitWithSSHSignature to service layer (#34087) + * Move duplicated functions (#33977) + * Extract code to their own functions for push update (#33944) + * Move gitgraph from modules to services layer (#33527) + * Move commits signature and verify functions to service layers (#33605) + * Use `CloseIssue` and `ReopenIssue` instead of `ChangeStatus` (#32467) + * Refactor arch route handlers (#32993) + * Refactor "string truncate" (#32984) + * Refactor arch route handlers (#32972) + * Clarify path param naming (#32969) + * Refactor request context (#32956) + * Move some errors to their own sub packages (#32880) + * Move RepoTransfer from models to models/repo sub package (#32506) + * Move delete deploy keys into service layer (#32201) + * Refactor webhook events (#33337) + * Move some Actions related functions from `routers` to `services` (#33280) + * Refactor RefName (#33234) + * Refactor context RefName and RepoAssignment (#33226) + * Refactor repository transfer (#33211) + * Refactor error system (#33626) + * Refactor error system (#33610) + * Refactor package (routes and error handling, npm peer dependency) (#33111) + * Use test context in tests and new loop system in benchmarks (#33648) + * Some small refactors (#33144) + * Simplify context ref name (#33267) + +* BUGFIXES + * Fix some dropdown problems on the issue sidebar (#34308) #34327 + * Do not return archive download URLs in API if downloads are disabled (#34324) #34338 + * Fix LFS files being editable in web UI (#34356) #34362 + * Fix only text/* being viewable in web UI (#34374) #34378 + * Fix LFS file not stored in LFS when uploaded/edited via API or web UI (#34367) + * Grey out expired artifact on Artifacts list (#34314) #34404 + * Fix incorrect divergence cache after switching default branch (#34370) #34406 + * Refactor commit message rendering and fix bugs (#34412) #34414 + * Merge and tweak markup editor expander CSS (#34409) #34415 + * Fix GetUsersByEmails (#34423) #34425 + * Only git operations should update last changed of a repository (#34388) #34427 + * Fix comment textarea scroll issue in Firefox (#34438) #34446 + * Fix repo broken check (#34444) #34452 + * Fix remove org user failure on mssql (#34449) #34453 + * Fix Workflow run Not Found page (#34459) #34466 + * When updating comment, if the content is the same, just return and not update the database (#34422) #34464 + * Fix project board view (#34470) #34475 + * Fix get / delete runner to use consistent http 404 and 500 status (#34480) #34488 + * Fix url validation in webhook add/edit API (#34492) #34496 + * Fix edithook api can not update package, status and workflow_job events (#34495) #34499 + * Fix ephemeral runner deletion (#34447) #34513 + * Don't display error log when .git-blame-ignore-revs doesn't exist (#34457) + * Only allow admins to rename default/protected branches (#33276) + * Improve "lock conversation" UI (#34207) + * Fix incorrect file links (#34189) + * Optimize Overflow Menu (#34183) + * Check user/org repo limit instead of doer (#34147) + * Make markdown render match GitHub's behavior (#34129) + * Fix team permission (#34128) + * Correctly handle submodule view and avoid throwing 500 error (#34121) + * Fix users being able bypass limits with repo transfers (#34031) + * Avoid creating unnecessary temporary cat file sub process (#33942) + * Refactor organization menu (#33928) + * Fix various Fomantic UI and htmx problems (#33851) + * Fix 500 error when error occurred in migration page (#33256) + * Validate that the tag doesn't exist when creating a tag via the web (#33241) + * Add missed transaction on setmerged (#33079) + * Rework create/fork/adopt/generate repository to make sure resources will be cleanup once failed (#31035) + * Valid email address should only start with alphanumeric (#28174) + * Fix webhook url (#34186) + * Fix "toAbsoluteLocaleDate" test when system locale is not en-US (#33939) + * Fix file name could not be searched if the file was not a text file when using the Bleve indexer (#33959) + * Fix cannot delete runners via the modal dialog (#33895) + * Fix unpin hint on the pinned pull requests (#33207) + * Fix parentCommit invalid memory address or nil pointer dereference. (#33204) + * Fix comment header padding (#33377) + * Fix some migration and repo name problems (#33986) + * Fix various trivial frontend problems (#34263) + * Fix Set Email Preference dropdown and button placement (#34255) + * Fix quoted replies incorrectly render user input as part of the quote (#34216) + * Fix button alignments and remove unnecessary styles (#34206) + * Restore form inputs on organization create error (#34201) + * Try to fix ACME (3rd) (#33807) + * Fix incorrect ref "blob" (#33240) + * Fix dynamic content loading init problem (#33748) + * Fix git empty check and HEAD request (#33690) + * Fix Untranslated Text on Actions Page (#33635) + * Fix issue label delete incorrect labels webhook payload (#34575) + * Fix incorrect page navigation with up and down arrow on last item of dashboard repos (#34570) + * Fix/improve avatar sync from LDAP (#34573) + * Fix some trivial problems (#34579) + * Retain issue sort type when a keyword search is introduced (#34559) + * Always use an empty line to separate the commit message and trailer (#34512) + * Fix line-button issue after file selection in file tree (#34574) + * Fix doctor deleting orphaned issues attachments (#34142) + * Add webhook assigning test and fix possible bug (#34420) + * Fix possible nil description of pull request when migrating from CodeCommit (#34541) + * Refactor commit reader (#34542) + * Fix possible pull request broken when leave the page immediately after clicking the update button #34509 + * Ignore "Close" error when uploading container blob (#34620) + * Fix missed merge commit sha and time when migrating from codecommit (#34645) + * Fix GetUsersByEmails (#34643) + * Misc CSS fixes (#34638) + * Add codecommit to supported services in api docs (#34626) + * Validate hex colors when creating/editing labels (#34623) + * Fix possible pull request broken when leave the page immediately after clicking the update button (#34509) + * Fix margin issue in markup paragraph rendering (#34599) + * Fix migration pull request title too long (#34577) + * Fix footnote jump behavior on the issue page. (#34621) + * Fix "oras" OCI client compatibility (#34666) + * Fix last admin check when syncing users (#34649) + * Fix skip paths check on tag push events in workflows (#34602) #34670 + +* MISC + + * Bump to alpine 3.22 (#34613) + * Make pull request and issue history more compact (#34588) + * Run integration tests against postgres 14 (#34514) #34536 + * Enable addtional linters (#34085) + * Enable testifylint rules (#34075) + * Enable staticcheck QFxxxx rules (#34064) + * Improve Actions test (#32883) + * Drop fomantic build (#33845) + * Go1.24 (#33562) + * Run yamllint with strict mode, fix issue (#33551) + * Disable cron task to update license (#33486) + * Optimize makefile help information generation (#33390) + * Convert github.com/xanzy/go-gitlab into gitlab.com/gitlab-org/api/client-go (#33126) + * Add missed changelogs (#33649) + * Update .changelog file to add performance label group (#33472) + * Add missing POPULATE_SQUASH_COMMENT_WITH_COMMIT_MESSAGES in app.example.ini (#33363) + * Update README screenshots (#33347) + * Update unrs-resolver (#34279) + * Update go&js dependencies (#34262) + * Optimize the calling code of queryElems (#34235) + * Update protected_branch.tmpl (#34193) + * Feat/optimize span svg layout (#34185) + * Set MERMAID_MAX_SOURCE_CHARACTERS to 50000 (#34152) + * Update JS and PY deps (#34143) + * Add Chinese translations for README files (#34132) + * Use `overflow-wrap: anywhere` to replace `word-break: break-all` (#34126) + * Clarify ownership in password change error messages (#34092) + * Add toggleClass function in dom.ts (#34063) + * Update to golangci-lint v2 (#34054) + * Update Makefile test comments (#34013) + * Update go mod dependencies (#33988) + * Use filepath.Join instead of path.Join for file system file operations (#33978) + * Prepare common tmpl functions in a middleware (#33957) + * Remove unused or abused styles (#33918) + * Update JS and PY deps, misc tweaks (#33903) + * Try to figure out attribute checker problem (#33901) + * Add lock for a repository pull mirror (#33876) + * Fine tune push mirror UI (#33866) + * Improve issue & code search (#33860) + * Use pullrequestlist instead of []*pullrequest (#33765) + * Upgrade act to 0.261.4 and actions-proto-go to v0.4.1 (#33760) + * Align sidebar gears to the right (#33721) + * Update Go dependencies (skip blevesearch, meilisearch) (#33655) + * Add migrations and doctor fixes (#33556) + * Remove "class-name" from svg icon (#33540) + * Update MAINTAINERS (#33529) + * Add "No data available" display when list is empty (#33517) + * Use `git diff-tree` for `DiffFileTree` on diff pages (#33514) + * Give organisation members access to organisation feeds (#33508) + * Update feishu icon (#33470) + * Hide/disable unusable UI elements when a repository is archived (#33459) + * Update `@github/text-expander-element` to 2.9.0 (#33435) + * Do not access GitRepo when a repo is being created (#33380) + * Fix incorrect ref usages (#33301) + * Prepare for support performance trace (#33286) + * Enable Typescript `noImplicitThis` (#33250) + * Remove unused CSS styles and move some styles to proper files (#33217) + * Add .run to gitignore (#33175) + * Fix typo in gitea downloader test and add missing codebase in `ToGitServiceType` (#33146) + * Remove extended glob pattern from branch protection UI (#33125) + * Clean up legacy form CSS styles (#33081) + * Unset XDG_HOME_CONFIG as gitea manages configuration locations (#33067) + * Add IntelliJ Gateway's .uuid to gitignore (#33052) + * User facing messages for AGit errors (#33012) + * Always show assignees on right (#33006) + * Fix eslint (#33002) + * Update JS dependencies (#32914) + * Bump x/net (#32896) (#32900) + * Only activity tab needs heatmap data loading (#34652) + +## [1.23.8](https://github.com/go-gitea/gitea/releases/tag/1.23.8) - 2025-05-11 + +* SECURITY + * Fix a bug when uploading file via lfs ssh command (#34408) (#34411) + * Update net package (#34228) (#34232) +* BUGFIXES + * Fix releases sidebar navigation link (#34436) #34439 + * Fix bug webhook milestone is not right. (#34419) #34429 + * Fix two missed null value checks on the wiki page. (#34205) (#34215) + * Swift files can be passed either as file or as form value (#34068) (#34236) + * Fix bug when API get pull changed files for deleted head repository (#34333) (#34368) + * Upgrade github v61 -> v71 to fix migrating bug (#34389) + * Fix bug when visiting comparation page (#34334) (#34364) + * Fix wrong review requests when updating the pull request (#34286) (#34304) + * Fix github migration error when using multiple tokens (#34144) (#34302) + * Explicitly not update indexes when sync database schemas (#34281) (#34295) + * Fix panic when comment is nil (#34257) (#34277) + * Fix project board links to related Pull Requests (#34213) (#34222) + * Don't assume the default wiki branch is master in the wiki API (#34244) (#34245) +* DOCUMENTATION + * Update token creation API swagger documentation (#34288) (#34296) +* MISC + * Fix CI Build (#34315) + * Add riscv64 support (#34199) (#34204) + * Bump go version in go.mod (#34160) + * remove hardcoded 'code' string in clone_panel.tmpl (#34153) (#34158) + +## [1.23.7](https://github.com/go-gitea/gitea/releases/tag/1.23.7) - 2025-04-07 + +* Enhancements + * Add a config option to block "expensive" pages for anonymous users (#34024) (#34071) + * Also check default ssh-cert location for host (#34099) (#34100) (#34116) +* BUGFIXES + * Fix discord webhook 400 status code when description limit is exceeded (#34084) (#34124) + * Get changed files based on merge base when checking `pull_request` actions trigger (#34106) (#34120) + * Fix invalid version in RPM package path (#34112) (#34115) + * Return default avatar url when user id is zero rather than updating database (#34094) (#34095) + * Add additional ReplaceAll in pathsep to cater for different pathsep (#34061) (#34070) + * Try to fix check-attr bug (#34029) (#34033) + * Git client will follow 301 but 307 (#34005) (#34010) + * Fix block expensive for 1.23 (#34127) + * Fix markdown frontmatter rendering (#34102) (#34107) + * Add new CLI flags to set name and scopes when creating a user with access token (#34080) (#34103) + * Do not show 500 error when default branch doesn't exist (#34096) (#34097) + * Hide activity contributors, recent commits and code frequrency left tabs if there is no code permission (#34053) (#34065) + * Simplify emoji rendering (#34048) (#34049) + * Adjust the layout of the toolbar on the Issues/Projects page (#33667) (#34047) + * Pull request updates will also trigger code owners review requests (#33744) (#34045) + * Fix org repo creation being limited by user limits (#34030) (#34044) + * Fix git client accessing renamed repo (#34034) (#34043) + * Fix the issue with error message logging for the `check-attr` command on Windows OS. (#34035) (#34036) + * Polyfill WeakRef (#34025) (#34028) + ## [1.23.6](https://github.com/go-gitea/gitea/releases/tag/v1.23.6) - 2025-03-24 * SECURITY @@ -120,8 +120,7 @@ WEBPACK_CONFIGS := webpack.config.js tailwind.config.js WEBPACK_DEST := public/assets/js/index.js public/assets/css/index.css WEBPACK_DEST_ENTRIES := public/assets/js public/assets/css public/assets/fonts -BINDATA_DEST := modules/public/bindata.go modules/options/bindata.go modules/templates/bindata.go -BINDATA_HASH := $(addsuffix .hash,$(BINDATA_DEST)) +BINDATA_DEST := modules/public/bindata.dat modules/options/bindata.dat modules/templates/bindata.dat GENERATED_GO_DEST := modules/charset/invisible_gen.go modules/charset/ambiguous_gen.go @@ -149,14 +148,8 @@ SPELLCHECK_FILES := $(GO_DIRS) $(WEB_DIRS) templates options/locale/locale_en-US EDITORCONFIG_FILES := templates .github/workflows options/locale/locale_en-US.ini GO_SOURCES := $(wildcard *.go) -GO_SOURCES += $(shell find $(GO_DIRS) -type f -name "*.go" ! -path modules/options/bindata.go ! -path modules/public/bindata.go ! -path modules/templates/bindata.go) +GO_SOURCES += $(shell find $(GO_DIRS) -type f -name "*.go") GO_SOURCES += $(GENERATED_GO_DEST) -GO_SOURCES_NO_BINDATA := $(GO_SOURCES) - -ifeq ($(filter $(TAGS_SPLIT),bindata),bindata) - GO_SOURCES += $(BINDATA_DEST) - GENERATED_GO_DEST += $(BINDATA_DEST) -endif # Force installation of playwright dependencies by setting this flag ifdef DEPS_PLAYWRIGHT @@ -226,7 +219,7 @@ clean-all: clean ## delete backend, frontend and integration files .PHONY: clean clean: ## delete backend and integration files - rm -rf $(EXECUTABLE) $(DIST) $(BINDATA_DEST) $(BINDATA_HASH) \ + rm -rf $(EXECUTABLE) $(DIST) $(BINDATA_DEST) \ integrations*.test \ e2e*.test \ tests/integration/gitea-integration-* \ @@ -268,7 +261,7 @@ endif .PHONY: generate-swagger generate-swagger: $(SWAGGER_SPEC) ## generate the swagger spec from code comments -$(SWAGGER_SPEC): $(GO_SOURCES_NO_BINDATA) $(SWAGGER_SPEC_INPUT) +$(SWAGGER_SPEC): $(GO_SOURCES) $(SWAGGER_SPEC_INPUT) $(GO) run $(SWAGGER_PACKAGE) generate spec --exclude "$(SWAGGER_EXCLUDE)" --input "$(SWAGGER_SPEC_INPUT)" --output './$(SWAGGER_SPEC)' .PHONY: swagger-check @@ -373,7 +366,7 @@ lint-go-gitea-vet: ## lint go files with gitea-vet .PHONY: lint-go-gopls lint-go-gopls: ## lint go files with gopls @echo "Running gopls check..." - @GO=$(GO) GOPLS_PACKAGE=$(GOPLS_PACKAGE) tools/lint-go-gopls.sh $(GO_SOURCES_NO_BINDATA) + @GO=$(GO) GOPLS_PACKAGE=$(GOPLS_PACKAGE) tools/lint-go-gopls.sh $(GO_SOURCES) .PHONY: lint-editorconfig lint-editorconfig: @@ -5,19 +5,10 @@ package main -// Libraries that are included to vendor utilities used during build. +// Libraries that are included to vendor utilities used during Makefile build. // These libraries will not be included in a normal compilation. import ( - // for embed - _ "github.com/shurcooL/vfsgen" - - // for cover merge - _ "golang.org/x/tools/cover" - // for vet _ "code.gitea.io/gitea-vet" - - // for swagger - _ "github.com/go-swagger/go-swagger/cmd/swagger" ) diff --git a/build/generate-bindata.go b/build/generate-bindata.go index 2fcb7c2f2a..2553770762 100644 --- a/build/generate-bindata.go +++ b/build/generate-bindata.go @@ -6,87 +6,22 @@ package main import ( - "bytes" - "crypto/sha1" "fmt" - "log" - "net/http" "os" - "path/filepath" - "strconv" - "github.com/shurcooL/vfsgen" + "code.gitea.io/gitea/modules/assetfs" ) -func needsUpdate(dir, filename string) (bool, []byte) { - needRegen := false - _, err := os.Stat(filename) - if err != nil { - needRegen = true - } - - oldHash, err := os.ReadFile(filename + ".hash") - if err != nil { - oldHash = []byte{} - } - - hasher := sha1.New() - - err = filepath.WalkDir(dir, func(path string, d os.DirEntry, err error) error { - if err != nil { - return err - } - info, err := d.Info() - if err != nil { - return err - } - _, _ = hasher.Write([]byte(d.Name())) - _, _ = hasher.Write([]byte(info.ModTime().String())) - _, _ = hasher.Write([]byte(strconv.FormatInt(info.Size(), 16))) - return nil - }) - if err != nil { - return true, oldHash - } - - newHash := hasher.Sum([]byte{}) - - if bytes.Compare(oldHash, newHash) != 0 { - return true, newHash - } - - return needRegen, newHash -} - func main() { - if len(os.Args) < 4 { - log.Fatal("Insufficient number of arguments. Need: directory packageName filename") - } - - dir, packageName, filename := os.Args[1], os.Args[2], os.Args[3] - var useGlobalModTime bool - if len(os.Args) == 5 { - useGlobalModTime, _ = strconv.ParseBool(os.Args[4]) - } - - update, newHash := needsUpdate(dir, filename) - - if !update { - fmt.Printf("bindata for %s already up-to-date\n", packageName) - return + if len(os.Args) != 3 { + fmt.Println("usage: ./generate-bindata {local-directory} {bindata-filename}") + os.Exit(1) } - fmt.Printf("generating bindata for %s\n", packageName) - var fsTemplates http.FileSystem = http.Dir(dir) - err := vfsgen.Generate(fsTemplates, vfsgen.Options{ - PackageName: packageName, - BuildTags: "bindata", - VariableName: "Assets", - Filename: filename, - UseGlobalModTime: useGlobalModTime, - }) - if err != nil { - log.Fatalf("%v\n", err) + dir, filename := os.Args[1], os.Args[2] + fmt.Printf("generating bindata for %s to %s\n", dir, filename) + if err := assetfs.GenerateEmbedBindata(dir, filename); err != nil { + fmt.Printf("failed: %s\n", err.Error()) + os.Exit(1) } - _ = os.WriteFile(filename+".hash", newHash, 0o666) } diff --git a/cmd/embedded.go b/cmd/embedded.go index 086bc06863..6a2fa07a93 100644 --- a/cmd/embedded.go +++ b/cmd/embedded.go @@ -118,7 +118,7 @@ func initEmbeddedExtractor(c *cli.Command) error { func runList(_ context.Context, c *cli.Command) error { if err := runListDo(c); err != nil { - fmt.Fprintf(os.Stderr, "%v\n", err) + _, _ = fmt.Fprintf(os.Stderr, "%v\n", err) return err } return nil @@ -126,7 +126,7 @@ func runList(_ context.Context, c *cli.Command) error { func runView(_ context.Context, c *cli.Command) error { if err := runViewDo(c); err != nil { - fmt.Fprintf(os.Stderr, "%v\n", err) + _, _ = fmt.Fprintf(os.Stderr, "%v\n", err) return err } return nil @@ -134,7 +134,7 @@ func runView(_ context.Context, c *cli.Command) error { func runExtract(_ context.Context, c *cli.Command) error { if err := runExtractDo(c); err != nil { - fmt.Fprintf(os.Stderr, "%v\n", err) + _, _ = fmt.Fprintf(os.Stderr, "%v\n", err) return err } return nil @@ -217,7 +217,7 @@ func runExtractDo(c *cli.Command) error { for _, a := range matchedAssetFiles { if err := extractAsset(destdir, a, overwrite, rename); err != nil { // Non-fatal error - fmt.Fprintf(os.Stderr, "%s: %v", a.path, err) + _, _ = fmt.Fprintf(os.Stderr, "%s: %v\n", a.path, err) } } diff --git a/cmd/serv.go b/cmd/serv.go index e4434450d6..8c6001e727 100644 --- a/cmd/serv.go +++ b/cmd/serv.go @@ -212,7 +212,7 @@ func runServ(ctx context.Context, c *cli.Command) error { if git.DefaultFeatures().SupportProcReceive { // for AGit Flow if cmd == "ssh_info" { - fmt.Print(`{"type":"gitea","version":1}`) + fmt.Print(`{"type":"agit","version":1}`) return nil } } diff --git a/custom/conf/app.example.ini b/custom/conf/app.example.ini index e9a378e877..aa2fcee765 100644 --- a/custom/conf/app.example.ini +++ b/custom/conf/app.example.ini @@ -1186,17 +1186,24 @@ LEVEL = Info ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; -;; GPG key to use to sign commits, Defaults to the default - that is the value of git config --get user.signingkey +;; GPG or SSH key to use to sign commits, Defaults to the default - that is the value of git config --get user.signingkey +;; Depending on the value of SIGNING_FORMAT this is either: +;; - openpgp: the GPG key ID +;; - ssh: the path to the ssh public key "/path/to/key.pub": where "/path/to/key" is the private key, use ssh-keygen -t ed25519 to generate a new key pair without password ;; run in the context of the RUN_USER ;; Switch to none to stop signing completely ;SIGNING_KEY = default ;; -;; If a SIGNING_KEY ID is provided and is not set to default, use the provided Name and Email address as the signer. +;; If a SIGNING_KEY ID is provided and is not set to default, use the provided Name and Email address as the signer and the signing format. ;; These should match a publicized name and email address for the key. (When SIGNING_KEY is default these are set to -;; the results of git config --get user.name and git config --get user.email respectively and can only be overridden +;; the results of git config --get user.name, git config --get user.email and git config --default openpgp --get gpg.format respectively and can only be overridden ;; by setting the SIGNING_KEY ID to the correct ID.) ;SIGNING_NAME = ;SIGNING_EMAIL = +;; SIGNING_FORMAT can be one of: +;; - openpgp (default): use GPG to sign commits +;; - ssh: use SSH to sign commits +;SIGNING_FORMAT = openpgp ;; ;; Sets the default trust model for repositories. Options are: collaborator, committer, collaboratorcommitter ;DEFAULT_TRUST_MODEL = collaborator @@ -1223,6 +1230,13 @@ LEVEL = Info ;; - commitssigned: require that all the commits in the head branch are signed. ;; - approved: only sign when merging an approved pr to a protected branch ;MERGES = pubkey, twofa, basesigned, commitssigned +;; +;; Determines which additional ssh keys are trusted for all signed commits regardless of the user +;; This is useful for ssh signing key rotation. +;; Exposes the provided SIGNING_NAME and SIGNING_EMAIL as the signer, regardless of the SIGNING_FORMAT value. +;; Multiple keys should be comma separated. +;; E.g."ssh-<algorithm> <key>". or "ssh-<algorithm> <key1>, ssh-<algorithm> <key2>". +;TRUSTED_SSH_KEYS = ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; @@ -1,6 +1,6 @@ module code.gitea.io/gitea -go 1.24.2 +go 1.24.4 // rfc5280 said: "The serial number is an integer assigned by the CA to each certificate." // But some CAs use negative serial number, just relax the check. related: @@ -60,7 +60,6 @@ require ( github.com/go-ldap/ldap/v3 v3.4.11 github.com/go-redsync/redsync/v4 v4.13.0 github.com/go-sql-driver/mysql v1.9.2 - github.com/go-swagger/go-swagger v0.31.0 github.com/go-webauthn/webauthn v0.12.3 github.com/gobwas/glob v0.2.3 github.com/gogs/chardet v0.0.0-20211120154057-b7413eaefb8f @@ -105,7 +104,6 @@ require ( github.com/santhosh-tekuri/jsonschema/v5 v5.3.1 github.com/sassoftware/go-rpmutils v0.4.0 github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3 - github.com/shurcooL/vfsgen v0.0.0-20230704071429-0000e147ea92 github.com/stretchr/testify v1.10.0 github.com/syndtr/goleveldb v1.0.0 github.com/tstranex/u2f v1.0.0 @@ -126,7 +124,6 @@ require ( golang.org/x/sync v0.15.0 golang.org/x/sys v0.33.0 golang.org/x/text v0.26.0 - golang.org/x/tools v0.33.0 google.golang.org/grpc v1.72.0 google.golang.org/protobuf v1.36.6 gopkg.in/ini.v1 v1.67.0 @@ -144,15 +141,11 @@ require ( git.sr.ht/~mariusor/go-xsd-duration v0.0.0-20220703122237-02e73435a078 // indirect github.com/Azure/azure-sdk-for-go/sdk/internal v1.11.1 // indirect github.com/DataDog/zstd v1.5.7 // indirect - github.com/Masterminds/goutils v1.1.1 // indirect - github.com/Masterminds/semver/v3 v3.3.1 // indirect - github.com/Masterminds/sprig/v3 v3.3.0 // indirect github.com/Microsoft/go-winio v0.6.2 // indirect github.com/RoaringBitmap/roaring/v2 v2.4.5 // indirect github.com/andybalholm/brotli v1.1.1 // indirect github.com/andybalholm/cascadia v1.3.3 // indirect github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be // indirect - github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 // indirect github.com/aws/aws-sdk-go-v2 v1.36.3 // indirect github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.34 // indirect github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.34 // indirect @@ -195,7 +188,6 @@ require ( github.com/dlclark/regexp2 v1.11.5 // indirect github.com/emersion/go-sasl v0.0.0-20241020182733-b788ff22d5a6 // indirect github.com/fatih/color v1.18.0 // indirect - github.com/felixge/httpsnoop v1.0.4 // indirect github.com/fxamacker/cbor/v2 v2.8.0 // indirect github.com/git-lfs/pktline v0.0.0-20230103162542-ca444d533ef1 // indirect github.com/go-ap/errors v0.0.0-20250409143711-5686c11ae650 // indirect @@ -204,18 +196,6 @@ require ( github.com/go-fed/httpsig v1.1.1-0.20201223112313-55836744818e // indirect github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 // indirect github.com/go-ini/ini v1.67.0 // indirect - github.com/go-openapi/analysis v0.23.0 // indirect - github.com/go-openapi/errors v0.22.1 // indirect - github.com/go-openapi/inflect v0.21.2 // indirect - github.com/go-openapi/jsonpointer v0.21.1 // indirect - github.com/go-openapi/jsonreference v0.21.0 // indirect - github.com/go-openapi/loads v0.22.0 // indirect - github.com/go-openapi/runtime v0.28.0 // indirect - github.com/go-openapi/spec v0.21.0 // indirect - github.com/go-openapi/strfmt v0.23.0 // indirect - github.com/go-openapi/swag v0.23.1 // indirect - github.com/go-openapi/validate v0.24.0 // indirect - github.com/go-viper/mapstructure/v2 v2.2.1 // indirect github.com/go-webauthn/x v0.1.20 // indirect github.com/goccy/go-json v0.10.5 // indirect github.com/golang-jwt/jwt/v4 v4.5.2 // indirect @@ -229,7 +209,6 @@ require ( github.com/google/go-querystring v1.1.0 // indirect github.com/google/go-tpm v0.9.3 // indirect github.com/gorilla/css v1.0.1 // indirect - github.com/gorilla/handlers v1.5.2 // indirect github.com/gorilla/mux v1.8.1 // indirect github.com/gorilla/securecookie v1.1.2 // indirect github.com/hashicorp/errwrap v1.1.0 // indirect @@ -237,12 +216,9 @@ require ( github.com/hashicorp/go-multierror v1.1.1 // indirect github.com/hashicorp/go-retryablehttp v0.7.7 // indirect github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect - github.com/jessevdk/go-flags v1.6.1 // indirect github.com/josharian/intern v1.0.0 // indirect github.com/kevinburke/ssh_config v1.2.0 // indirect github.com/klauspost/pgzip v1.2.6 // indirect - github.com/kr/pretty v0.3.1 // indirect - github.com/kr/text v0.2.0 // indirect github.com/libdns/libdns v1.0.0-beta.1 // indirect github.com/mailru/easyjson v0.9.0 // indirect github.com/markbates/going v1.0.3 // indirect @@ -253,19 +229,15 @@ require ( github.com/miekg/dns v1.1.65 // indirect github.com/minio/crc64nvme v1.0.1 // indirect github.com/minio/md5-simd v1.1.2 // indirect - github.com/mitchellh/copystructure v1.2.0 // indirect github.com/mitchellh/mapstructure v1.5.0 // indirect - github.com/mitchellh/reflectwalk v1.0.2 // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.2 // indirect github.com/mrjones/oauth v0.0.0-20190623134757-126b35219450 // indirect github.com/mschoch/smat v0.2.0 // indirect github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect github.com/nwaples/rardecode v1.1.3 // indirect - github.com/oklog/ulid v1.3.1 // indirect github.com/olekukonko/tablewriter v0.0.5 // indirect github.com/onsi/ginkgo v1.16.5 // indirect - github.com/pelletier/go-toml/v2 v2.2.4 // indirect github.com/pierrec/lz4/v4 v4.1.22 // indirect github.com/pjbgf/sha1cd v0.3.2 // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect @@ -274,22 +246,11 @@ require ( github.com/prometheus/procfs v0.16.1 // indirect github.com/rhysd/actionlint v1.7.7 // indirect github.com/rivo/uniseg v0.4.7 // indirect - github.com/rogpeppe/go-internal v1.14.1 // indirect github.com/rs/xid v1.6.0 // indirect github.com/russross/blackfriday/v2 v2.1.0 // indirect - github.com/sagikazarmark/locafero v0.9.0 // indirect - github.com/shopspring/decimal v1.4.0 // indirect - github.com/shurcooL/httpfs v0.0.0-20230704072500-f1e31cf0ba5c // indirect github.com/sirupsen/logrus v1.9.3 // indirect github.com/skeema/knownhosts v1.3.1 // indirect - github.com/sourcegraph/conc v0.3.0 // indirect - github.com/spf13/afero v1.14.0 // indirect - github.com/spf13/cast v1.7.1 // indirect - github.com/spf13/pflag v1.0.6 // indirect - github.com/spf13/viper v1.20.1 // indirect github.com/ssor/bom v0.0.0-20170718123548-6386211fdfcf // indirect - github.com/subosito/gotenv v1.6.0 // indirect - github.com/toqueteos/webbrowser v1.2.0 // indirect github.com/unknwon/com v1.0.1 // indirect github.com/valyala/fastjson v1.6.4 // indirect github.com/x448/float16 v0.8.4 // indirect @@ -300,7 +261,6 @@ require ( github.com/zeebo/assert v1.3.0 // indirect github.com/zeebo/blake3 v0.2.4 // indirect go.etcd.io/bbolt v1.4.0 // indirect - go.mongodb.org/mongo-driver v1.17.3 // indirect go.uber.org/atomic v1.11.0 // indirect go.uber.org/multierr v1.11.0 // indirect go.uber.org/zap v1.27.0 // indirect @@ -308,6 +268,7 @@ require ( golang.org/x/exp v0.0.0-20250305212735-054e65f0b394 // indirect golang.org/x/mod v0.25.0 // indirect golang.org/x/time v0.11.0 // indirect + golang.org/x/tools v0.33.0 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20250422160041-2d3770c4ea7f // indirect gopkg.in/warnings.v0 v0.1.2 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect @@ -315,8 +276,6 @@ require ( replace github.com/hashicorp/go-version => github.com/6543/go-version v1.3.1 -replace github.com/shurcooL/vfsgen => github.com/lunny/vfsgen v0.0.0-20220105142115-2c99e1ffdfa0 - replace github.com/nektos/act => gitea.com/gitea/act v0.261.6 // TODO: the only difference is in `PutObject`: the fork doesn't use `NewVerifyingReader(r, sha256.New(), oid, expectedSize)`, need to figure out why @@ -62,12 +62,6 @@ github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03 github.com/DataDog/zstd v1.5.7 h1:ybO8RBeh29qrxIhCA9E8gKY6xfONU9T6G6aP9DTKfLE= github.com/DataDog/zstd v1.5.7/go.mod h1:g4AWEaM3yOg3HYfnJ3YIawPnVdXJh9QME85blwSAmyw= github.com/Julusian/godocdown v0.0.0-20170816220326-6d19f8ff2df8/go.mod h1:INZr5t32rG59/5xeltqoCJoNY7e5x/3xoY9WSWVWg74= -github.com/Masterminds/goutils v1.1.1 h1:5nUrii3FMTL5diU80unEVvNevw1nH4+ZV4DSLVJLSYI= -github.com/Masterminds/goutils v1.1.1/go.mod h1:8cTjp+g8YejhMuvIA5y2vz3BpJxksy863GQaJW2MFNU= -github.com/Masterminds/semver/v3 v3.3.1 h1:QtNSWtVZ3nBfk8mAOu/B6v7FMJ+NHTIgUPi7rj+4nv4= -github.com/Masterminds/semver/v3 v3.3.1/go.mod h1:4V+yj/TJE1HU9XfppCwVMZq3I84lprf4nC11bSS5beM= -github.com/Masterminds/sprig/v3 v3.3.0 h1:mQh0Yrg1XPo6vjYXgtf5OtijNAKJRNcTdOOGZe3tPhs= -github.com/Masterminds/sprig/v3 v3.3.0/go.mod h1:Zy1iXRYNqNLUolqCpL4uhk6SHUMAOSCzdgBfDb35Lz0= github.com/Microsoft/go-winio v0.5.2/go.mod h1:WpS1mjBmmwHBEWmogvA2mj8546UReBk4v8QkMxJ6pZY= github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY= github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU= @@ -103,8 +97,6 @@ github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be/go.mod h1:ySMOLuW github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio= github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs= -github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 h1:DklsrG3dyBCFEj5IhUbnKptjxatkF07cF2ak3yi77so= -github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2/go.mod h1:WaHUgvxTVq04UNunO+XhnAqY/wQc+bxr74GqbsZ/Jqw= github.com/aws/aws-sdk-go-v2 v1.36.3 h1:mJoei2CxPutQVxaATCzDUjcZEjVRdpsiiXi2o38yqWM= github.com/aws/aws-sdk-go-v2 v1.36.3/go.mod h1:LLXuLpgzEbD766Z5ECcRmi8AzSwfZItDtmABVkRLGzg= github.com/aws/aws-sdk-go-v2/credentials v1.17.67 h1:9KxtdcIA/5xPNQyZRgUSpYOE6j9Bc4+D7nZua0KGYOM= @@ -274,12 +266,8 @@ github.com/fatih/color v1.18.0 h1:S8gINlzdQ840/4pfAwic/ZE0djQEH3wM94VfqLTZcOM= github.com/fatih/color v1.18.0/go.mod h1:4FelSpRwEGDpQ12mAdzqdOukCy4u8WUtOY6lkT/6HfU= github.com/felixge/fgprof v0.9.5 h1:8+vR6yu2vvSKn08urWyEuxx75NWPEvybbkBirEpsbVY= github.com/felixge/fgprof v0.9.5/go.mod h1:yKl+ERSa++RYOs32d8K6WEXCB4uXdLls4ZaZPpayhMM= -github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg= -github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= github.com/fortytw2/leaktest v1.3.0 h1:u8491cBMTQ8ft8aeV+adlcytMZylmA5nnwwkRZjI8vw= github.com/fortytw2/leaktest v1.3.0/go.mod h1:jDsjWgpAGjm2CA7WthBh/CdZYEPF31XHquHwclZch5g= -github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8= -github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= github.com/fsnotify/fsnotify v1.9.0 h1:2Ml+OJNzbYCTzsxtv8vKSFD9PbJjmhYF14k/jKC7S9k= @@ -325,28 +313,6 @@ github.com/go-ini/ini v1.67.0 h1:z6ZrTEZqSWOTyH2FlglNbNgARyHG8oLW9gMELqKr06A= github.com/go-ini/ini v1.67.0/go.mod h1:ByCAeIL28uOIIG0E3PJtZPDL8WnHpFKFOtgjp+3Ies8= github.com/go-ldap/ldap/v3 v3.4.11 h1:4k0Yxweg+a3OyBLjdYn5OKglv18JNvfDykSoI8bW0gU= github.com/go-ldap/ldap/v3 v3.4.11/go.mod h1:bY7t0FLK8OAVpp/vV6sSlpz3EQDGcQwc8pF0ujLgKvM= -github.com/go-openapi/analysis v0.23.0 h1:aGday7OWupfMs+LbmLZG4k0MYXIANxcuBTYUC03zFCU= -github.com/go-openapi/analysis v0.23.0/go.mod h1:9mz9ZWaSlV8TvjQHLl2mUW2PbZtemkE8yA5v22ohupo= -github.com/go-openapi/errors v0.22.1 h1:kslMRRnK7NCb/CvR1q1VWuEQCEIsBGn5GgKD9e+HYhU= -github.com/go-openapi/errors v0.22.1/go.mod h1:+n/5UdIqdVnLIJ6Q9Se8HNGUXYaY6CN8ImWzfi/Gzp0= -github.com/go-openapi/inflect v0.21.2 h1:0gClGlGcxifcJR56zwvhaOulnNgnhc4qTAkob5ObnSM= -github.com/go-openapi/inflect v0.21.2/go.mod h1:INezMuUu7SJQc2AyR3WO0DqqYUJSj8Kb4hBd7WtjlAw= -github.com/go-openapi/jsonpointer v0.21.1 h1:whnzv/pNXtK2FbX/W9yJfRmE2gsmkfahjMKB0fZvcic= -github.com/go-openapi/jsonpointer v0.21.1/go.mod h1:50I1STOfbY1ycR8jGz8DaMeLCdXiI6aDteEdRNNzpdk= -github.com/go-openapi/jsonreference v0.21.0 h1:Rs+Y7hSXT83Jacb7kFyjn4ijOuVGSvOdF2+tg1TRrwQ= -github.com/go-openapi/jsonreference v0.21.0/go.mod h1:LmZmgsrTkVg9LG4EaHeY8cBDslNPMo06cago5JNLkm4= -github.com/go-openapi/loads v0.22.0 h1:ECPGd4jX1U6NApCGG1We+uEozOAvXvJSF4nnwHZ8Aco= -github.com/go-openapi/loads v0.22.0/go.mod h1:yLsaTCS92mnSAZX5WWoxszLj0u+Ojl+Zs5Stn1oF+rs= -github.com/go-openapi/runtime v0.28.0 h1:gpPPmWSNGo214l6n8hzdXYhPuJcGtziTOgUpvsFWGIQ= -github.com/go-openapi/runtime v0.28.0/go.mod h1:QN7OzcS+XuYmkQLw05akXk0jRH/eZ3kb18+1KwW9gyc= -github.com/go-openapi/spec v0.21.0 h1:LTVzPc3p/RzRnkQqLRndbAzjY0d0BCL72A6j3CdL9ZY= -github.com/go-openapi/spec v0.21.0/go.mod h1:78u6VdPw81XU44qEWGhtr982gJ5BWg2c0I5XwVMotYk= -github.com/go-openapi/strfmt v0.23.0 h1:nlUS6BCqcnAk0pyhi9Y+kdDVZdZMHfEKQiS4HaMgO/c= -github.com/go-openapi/strfmt v0.23.0/go.mod h1:NrtIpfKtWIygRkKVsxh7XQMDQW5HKQl6S5ik2elW+K4= -github.com/go-openapi/swag v0.23.1 h1:lpsStH0n2ittzTnbaSloVZLuB5+fvSY/+hnagBjSNZU= -github.com/go-openapi/swag v0.23.1/go.mod h1:STZs8TbRvEQQKUA+JZNAm3EWlgaOBGpyFDqQnDHMef0= -github.com/go-openapi/validate v0.24.0 h1:LdfDKwNbpB6Vn40xhTdNZAnfLECL81w+VX3BumrGD58= -github.com/go-openapi/validate v0.24.0/go.mod h1:iyeX1sEufmv3nPbBdX3ieNviWnOZaJ1+zquzJEf2BAQ= github.com/go-redis/redis v6.15.9+incompatible h1:K0pv1D7EQUjfyoMql+r/jZqCLizCGKFlFgcHWWmHQjg= github.com/go-redis/redis v6.15.9+incompatible/go.mod h1:NAIEuMOZ/fxfXJIrKDQDz8wamY7mA7PouImQ2Jvg6kA= github.com/go-redis/redis/v7 v7.4.1 h1:PASvf36gyUpr2zdOUS/9Zqc80GbM+9BDyiJSJDDOrTI= @@ -357,13 +323,9 @@ github.com/go-redsync/redsync/v4 v4.13.0 h1:49X6GJfnbLGaIpBBREM/zA4uIMDXKAh1NDkv github.com/go-redsync/redsync/v4 v4.13.0/go.mod h1:HMW4Q224GZQz6x1Xc7040Yfgacukdzu7ifTDAKiyErQ= github.com/go-sql-driver/mysql v1.9.2 h1:4cNKDYQ1I84SXslGddlsrMhc8k4LeDVj6Ad6WRjiHuU= github.com/go-sql-driver/mysql v1.9.2/go.mod h1:qn46aNg1333BRMNU69Lq93t8du/dwxI64Gl8i5p1WMU= -github.com/go-swagger/go-swagger v0.31.0 h1:H8eOYQnY2u7vNKWDNykv2xJP3pBhRG/R+SOCAmKrLlc= -github.com/go-swagger/go-swagger v0.31.0/go.mod h1:WSigRRWEig8zV6t6Sm8Y+EmUjlzA/HoaZJ5edupq7po= github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= github.com/go-test/deep v1.1.0 h1:WOcxcdHcvdgThNXjw0t76K42FXTU7HpNQWHpA2HHNlg= github.com/go-test/deep v1.1.0/go.mod h1:5C2ZWiW0ErCdrYzpqxLbTX7MG14M9iiw8DgHncVwcsE= -github.com/go-viper/mapstructure/v2 v2.2.1 h1:ZAaOCxANMuZx5RCeg0mBdEZk7DZasvvZIxtHqx8aGss= -github.com/go-viper/mapstructure/v2 v2.2.1/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM= github.com/go-webauthn/webauthn v0.12.3 h1:hHQl1xkUuabUU9uS+ISNCMLs9z50p9mDUZI/FmkayNE= github.com/go-webauthn/webauthn v0.12.3/go.mod h1:4JRe8Z3W7HIw8NGEWn2fnUwecoDzkkeach/NnvhkqGY= github.com/go-webauthn/x v0.1.20 h1:brEBDqfiPtNNCdS/peu8gARtq8fIPsHz0VzpPjGvgiw= @@ -446,8 +408,6 @@ github.com/gorilla/css v1.0.1 h1:ntNaBIghp6JmvWnxbZKANoLyuXTPZ4cAMlo6RyhlbO8= github.com/gorilla/css v1.0.1/go.mod h1:BvnYkspnSzMmwRK+b8/xgNPLiIuNZr6vbZBTPQ2A3b0= github.com/gorilla/feeds v1.2.0 h1:O6pBiXJ5JHhPvqy53NsjKOThq+dNFm8+DFrxBEdzSCc= github.com/gorilla/feeds v1.2.0/go.mod h1:WMib8uJP3BbY+X8Szd1rA5Pzhdfh+HCCAYT2z7Fza6Y= -github.com/gorilla/handlers v1.5.2 h1:cLTUSsNkgcwhgRqvCNmdbRWG0A3N4F+M2nWKdScwyEE= -github.com/gorilla/handlers v1.5.2/go.mod h1:dX+xVpaxdSw+q0Qek8SSsl3dfMk3jNddUkMzo0GtH0w= github.com/gorilla/mux v1.8.1 h1:TuBL49tXwgrFYWhqrNgrUNEY92u81SPhu7sTdzQEiWY= github.com/gorilla/mux v1.8.1/go.mod h1:AKf9I4AEqPTmMytcMc0KkNouC66V3BtZ4qD5fmWSiMQ= github.com/gorilla/pat v0.0.0-20180118222023-199c85a7f6d1 h1:LqbZZ9sNMWVjeXS4NN5oVvhMjDyLhmA1LG86oSo+IqY= @@ -497,8 +457,6 @@ github.com/jcmturner/gokrb5/v8 v8.4.4 h1:x1Sv4HaTpepFkXbt2IkL29DXRf8sOfZXo8eRKh6 github.com/jcmturner/gokrb5/v8 v8.4.4/go.mod h1:1btQEpgT6k+unzCwX1KdWMEwPPkkgBtP+F6aCACiMrs= github.com/jcmturner/rpc/v2 v2.0.3 h1:7FXXj8Ti1IaVFpSAziCZWNzbNuZmnvw/i6CqLNdWfZY= github.com/jcmturner/rpc/v2 v2.0.3/go.mod h1:VUJYCIDm3PVOEHw8sgt091/20OJjskO/YJki3ELg/Hc= -github.com/jessevdk/go-flags v1.6.1 h1:Cvu5U8UGrLay1rZfv/zP7iLpSHGUZ/Ou68T0iX1bBK4= -github.com/jessevdk/go-flags v1.6.1/go.mod h1:Mk8T1hIAWpOiJiHa9rJASDK2UGWji0EuPGBnNLMooyc= github.com/jhillyerd/enmime v1.3.0 h1:LV5kzfLidiOr8qRGIpYYmUZCnhrPbcFAnAFUnWn99rw= github.com/jhillyerd/enmime v1.3.0/go.mod h1:6c6jg5HdRRV2FtvVL69LjiX1M8oE0xDX9VEhV3oy4gs= github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= @@ -540,8 +498,6 @@ github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw= github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= github.com/libdns/libdns v1.0.0-beta.1 h1:KIf4wLfsrEpXpZ3vmc/poM8zCATXT2klbdPe6hyOBjQ= github.com/libdns/libdns v1.0.0-beta.1/go.mod h1:4Bj9+5CQiNMVGf87wjX4CY3HQJypUHRuLvlsfsZqLWQ= -github.com/lunny/vfsgen v0.0.0-20220105142115-2c99e1ffdfa0 h1:F/3FfGmKdiKFa8kL3YrpZ7pe9H4l4AzA1pbaOUnRvPI= -github.com/lunny/vfsgen v0.0.0-20220105142115-2c99e1ffdfa0/go.mod h1:JEfTc3+2DF9Z4PXhLLvXL42zexJyh8rIq3OzUj/0rAk= github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= github.com/mailru/easyjson v0.9.0 h1:PrnmzHw7262yW8sTBwxi1PdJA3Iw/EKBa8psRf7d9a4= @@ -577,14 +533,10 @@ github.com/minio/md5-simd v1.1.2 h1:Gdi1DZK69+ZVMoNHRXJyNcxrMA4dSxoYHZSQbirFg34= github.com/minio/md5-simd v1.1.2/go.mod h1:MzdKDxYpY2BT9XQFocsiZf/NKVtR7nkE4RoEpN+20RM= github.com/minio/minio-go/v7 v7.0.91 h1:tWLZnEfo3OZl5PoXQwcwTAPNNrjyWwOh6cbZitW5JQc= github.com/minio/minio-go/v7 v7.0.91/go.mod h1:uvMUcGrpgeSAAI6+sD3818508nUyMULw94j2Nxku/Go= -github.com/mitchellh/copystructure v1.2.0 h1:vpKXTN4ewci03Vljg/q9QvCGUDttBOGBIa15WveJJGw= -github.com/mitchellh/copystructure v1.2.0/go.mod h1:qLl+cE2AmVv+CoeAwDPye/v+N2HKCj9FbZEVFJRxO9s= github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= -github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zxSIeXaQ= -github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= @@ -607,8 +559,6 @@ github.com/nwaples/rardecode v1.1.3/go.mod h1:5DzqNKiOdpKKBH87u8VlvAnPZMXcGRhxWk github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= -github.com/oklog/ulid v1.3.1 h1:EGfNDEx6MqHz8B3uNV6QAib1UR2Lm97sHi3ocA6ESJ4= -github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec= github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY= github.com/olivere/elastic/v7 v7.0.32 h1:R7CXvbu8Eq+WlsLgxmKVKPox0oOwAE/2T9Si5BnvK6E= @@ -629,8 +579,6 @@ github.com/opencontainers/image-spec v1.1.1 h1:y0fUlFfIZhPF1W537XOLg0/fcx6zcHCJw github.com/opencontainers/image-spec v1.1.1/go.mod h1:qpqAh3Dmcf36wStyyWU+kCeDgrGnAve2nCC8+7h8Q0M= github.com/orisano/pixelmatch v0.0.0-20220722002657-fb0b55479cde/go.mod h1:nZgzbfBr3hhjoZnS66nKrHmduYNpc34ny7RK4z5/HM0= github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= -github.com/pelletier/go-toml/v2 v2.2.4 h1:mye9XuhQ6gvn5h28+VilKrrPoQVanw5PMw/TB0t5Ec4= -github.com/pelletier/go-toml/v2 v2.2.4/go.mod h1:2gIqNv+qfxSVS7cM2xJQKtLSTLUE9V8t9Stt+h56mCY= github.com/philhofer/fwd v1.0.0/go.mod h1:gk3iGcWd9+svBvR0sR+KPcfE+RNWozjowpeBVG3ZVNU= github.com/pierrec/lz4/v4 v4.1.2/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4= github.com/pierrec/lz4/v4 v4.1.22 h1:cKFw6uJDK+/gfw5BcDL0JL5aBsAFdsIT18eRtLj7VIU= @@ -674,7 +622,6 @@ github.com/robfig/cron/v3 v3.0.1 h1:WdRxkvbJztn8LMz/QEvLN5sBU+xKpSqwwUO1Pjr4qDs= github.com/robfig/cron/v3 v3.0.1/go.mod h1:eQICP3HwyT7UooqI/z+Ov+PtYAWygg1TEWWzGIFLtro= github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= github.com/rogpeppe/go-internal v1.8.1/go.mod h1:JeRgkft04UBgHMgCIwADu4Pn6Mtm5d4nPKWu0nJ5d+o= -github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ= github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc= github.com/rs/xid v1.6.0 h1:fV591PaemRlL6JfRxGDEPl69wICngIQ3shQtzfy2gxU= @@ -682,8 +629,6 @@ github.com/rs/xid v1.6.0/go.mod h1:7XoLgs4eV+QndskICGsho+ADou8ySMSjJKDIan90Nz0= github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= -github.com/sagikazarmark/locafero v0.9.0 h1:GbgQGNtTrEmddYDSAH9QLRyfAHY12md+8YFTqyMTC9k= -github.com/sagikazarmark/locafero v0.9.0/go.mod h1:UBUyz37V+EdMS3hDF3QWIiVr/2dPrx49OMO0Bn0hJqk= github.com/santhosh-tekuri/jsonschema/v5 v5.3.1 h1:lZUw3E0/J3roVtGQ+SCrUrg3ON6NgVqpn3+iol9aGu4= github.com/santhosh-tekuri/jsonschema/v5 v5.3.1/go.mod h1:uToXkOrWAZ6/Oc07xWQrPOhJotwFIyu2bBVN41fcDUY= github.com/sassoftware/go-rpmutils v0.4.0 h1:ojND82NYBxgwrV+mX1CWsd5QJvvEZTKddtCdFLPWhpg= @@ -692,10 +637,6 @@ github.com/serenize/snaker v0.0.0-20171204205717-a683aaf2d516/go.mod h1:Yow6lPLS github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3 h1:n661drycOFuPLCN3Uc8sB6B/s6Z4t2xvBgU1htSHuq8= github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3/go.mod h1:A0bzQcvG0E7Rwjx0REVgAGH58e96+X0MeOfepqsbeW4= -github.com/shopspring/decimal v1.4.0 h1:bxl37RwXBklmTi0C79JfXCEBD1cqqHt0bbgBAGFp81k= -github.com/shopspring/decimal v1.4.0/go.mod h1:gawqmDU56v4yIKSwfBSFip1HdCCXN8/+DMd9qYNcwME= -github.com/shurcooL/httpfs v0.0.0-20230704072500-f1e31cf0ba5c h1:aqg5Vm5dwtvL+YgDpBcK1ITf3o96N/K7/wsRXQnUTEs= -github.com/shurcooL/httpfs v0.0.0-20230704072500-f1e31cf0ba5c/go.mod h1:owqhoLW1qZoYLZzLnBw+QkPP9WZnjlSWihhxAJC1+/M= github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= @@ -707,22 +648,12 @@ github.com/smartystreets/assertions v1.1.1/go.mod h1:tcbTF8ujkAEcZ8TElKY+i30BzYl github.com/smartystreets/goconvey v0.0.0-20181108003508-044398e4856c/go.mod h1:XDJAKZRPZ1CvBcN2aX5YOUTYGHki24fSF0Iv48Ibg0s= github.com/smartystreets/goconvey v0.0.0-20190731233626-505e41936337 h1:WN9BUFbdyOsSH/XohnWpXOlq9NBD5sGAB2FciQMUEe8= github.com/smartystreets/goconvey v0.0.0-20190731233626-505e41936337/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= -github.com/sourcegraph/conc v0.3.0 h1:OQTbbt6P72L20UqAkXXuLOj79LfEanQ+YQFNpLA9ySo= -github.com/sourcegraph/conc v0.3.0/go.mod h1:Sdozi7LEKbFPqYX2/J+iBAM6HpqSLTASQIKqDmF7Mt0= github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= -github.com/spf13/afero v1.14.0 h1:9tH6MapGnn/j0eb0yIXiLjERO8RB6xIVZRDCX7PtqWA= -github.com/spf13/afero v1.14.0/go.mod h1:acJQ8t0ohCGuMN3O+Pv0V0hgMxNYDlvdk+VTfyZmbYo= github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= -github.com/spf13/cast v1.7.1 h1:cuNEagBQEHWN1FnbGEjCXL2szYEXqfJPbP2HNUaca9Y= -github.com/spf13/cast v1.7.1/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo= github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU= github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= -github.com/spf13/pflag v1.0.6 h1:jFzHGLGAlb3ruxLB8MhbI6A8+AQX/2eW4qeyNZXNp2o= -github.com/spf13/pflag v1.0.6/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s= -github.com/spf13/viper v1.20.1 h1:ZMi+z/lvLyPSCoNtFCpqjy0S4kPbirhpTMwl8BkW9X4= -github.com/spf13/viper v1.20.1/go.mod h1:P9Mdzt1zoHIG8m2eZQinpiBjo6kCmZSKBClNNqjJvu4= github.com/ssor/bom v0.0.0-20170718123548-6386211fdfcf h1:pvbZ0lM0XWPBqUKqFU8cmavspvIl9nulOYwdy6IFRRo= github.com/ssor/bom v0.0.0-20170718123548-6386211fdfcf/go.mod h1:RJID2RhlZKId02nZ62WenDCkgHFerpIOmW0iT7GKmXM= github.com/stephens2424/writerset v1.0.2/go.mod h1:aS2JhsMn6eA7e82oNmW4rfsgAOp9COBTTl8mzkwADnc= @@ -745,13 +676,9 @@ github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOf github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/stvp/tempredis v0.0.0-20181119212430-b82af8480203 h1:QVqDTf3h2WHt08YuiTGPZLls0Wq99X9bWd0Q5ZSBesM= github.com/stvp/tempredis v0.0.0-20181119212430-b82af8480203/go.mod h1:oqN97ltKNihBbwlX8dLpwxCl3+HnXKV/R0e+sRLd9C8= -github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8= -github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU= github.com/syndtr/goleveldb v1.0.0 h1:fBdIW9lB4Iz0n9khmH8w27SJ3QEJ7+IgjPEwGSZiFdE= github.com/syndtr/goleveldb v1.0.0/go.mod h1:ZVVdQEZoIme9iO1Ch2Jdy24qqXrMMOU6lpPAyBWyWuQ= github.com/tinylib/msgp v1.1.0/go.mod h1:+d+yLhGm8mzTaHzB+wgMYrodPfmZrzkirds8fDWklFE= -github.com/toqueteos/webbrowser v1.2.0 h1:tVP/gpK69Fx+qMJKsLE7TD8LuGWPnEV71wBN9rrstGQ= -github.com/toqueteos/webbrowser v1.2.0/go.mod h1:XWoZq4cyp9WeUeak7w7LXRUQf1F1ATJMir8RTqb4ayM= github.com/tstranex/u2f v1.0.0 h1:HhJkSzDDlVSVIVt7pDJwCHQj67k7A5EeBgPmeD+pVsQ= github.com/tstranex/u2f v1.0.0/go.mod h1:eahSLaqAS0zsIEv80+vXT7WanXs7MQQDg3j3wGBSayo= github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0= @@ -809,8 +736,6 @@ gitlab.com/gitlab-org/api/client-go v0.127.0/go.mod h1:bYC6fPORKSmtuPRyD9Z2rtbAj go.etcd.io/bbolt v1.3.5/go.mod h1:G5EMThwa9y8QZGBClrRx5EY+Yw9kAhnjy3bSjsnlVTQ= go.etcd.io/bbolt v1.4.0 h1:TU77id3TnN/zKr7CO/uk+fBCwF2jGcMuw2B/FMAzYIk= go.etcd.io/bbolt v1.4.0/go.mod h1:AsD+OCi/qPN1giOX1aiLAha3o1U8rAz65bvN4j0sRuk= -go.mongodb.org/mongo-driver v1.17.3 h1:TQyXhnsWfWtgAhMtOgtYHMTkZIfBTpMTsMnd9ZBeHxQ= -go.mongodb.org/mongo-driver v1.17.3/go.mod h1:Hy04i7O2kC4RS06ZrhPRqj/u4DTYkFDAAccj+rVKqgQ= go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= go.uber.org/atomic v1.11.0 h1:ZvwS0R+56ePWxUNi+Atn9dWONBPp/AUETXlHW0DxSjE= go.uber.org/atomic v1.11.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0= diff --git a/models/renderhelper/repo_comment.go b/models/renderhelper/repo_comment.go index a400f7b908..ae0fbf0abd 100644 --- a/models/renderhelper/repo_comment.go +++ b/models/renderhelper/repo_comment.go @@ -48,10 +48,7 @@ type RepoCommentOptions struct { } func NewRenderContextRepoComment(ctx context.Context, repo *repo_model.Repository, opts ...RepoCommentOptions) *markup.RenderContext { - helper := &RepoComment{ - repoLink: repo.Link(), - opts: util.OptionalArg(opts), - } + helper := &RepoComment{opts: util.OptionalArg(opts)} rctx := markup.NewRenderContext(ctx) helper.ctx = rctx var metas map[string]string @@ -60,15 +57,16 @@ func NewRenderContextRepoComment(ctx context.Context, repo *repo_model.Repositor helper.commitChecker = newCommitChecker(ctx, repo) metas = repo.ComposeCommentMetas(ctx) } else { - // this is almost dead code, only to pass the incorrect tests - helper.repoLink = fmt.Sprintf("%s/%s", helper.opts.DeprecatedOwnerName, helper.opts.DeprecatedRepoName) - rctx = rctx.WithMetas(map[string]string{ - "user": helper.opts.DeprecatedOwnerName, - "repo": helper.opts.DeprecatedRepoName, - - "markdownNewLineHardBreak": "true", - "markupAllowShortIssuePattern": "true", - }) + // repo can be nil when rendering a commit message in user's dashboard feedback whose repository has been deleted + metas = map[string]string{} + if helper.opts.DeprecatedOwnerName != "" { + // this is almost dead code, only to pass the incorrect tests + helper.repoLink = fmt.Sprintf("%s/%s", helper.opts.DeprecatedOwnerName, helper.opts.DeprecatedRepoName) + metas["user"] = helper.opts.DeprecatedOwnerName + metas["repo"] = helper.opts.DeprecatedRepoName + } + metas["markdownNewLineHardBreak"] = "true" + metas["markupAllowShortIssuePattern"] = "true" } metas["footnoteContextId"] = helper.opts.FootnoteContextID rctx = rctx.WithMetas(metas).WithHelper(helper) diff --git a/models/renderhelper/repo_comment_test.go b/models/renderhelper/repo_comment_test.go index 776152db96..3b13bff73c 100644 --- a/models/renderhelper/repo_comment_test.go +++ b/models/renderhelper/repo_comment_test.go @@ -72,4 +72,11 @@ func TestRepoComment(t *testing.T) { <a href="/user2/repo1/commit/1234/image" target="_blank" rel="nofollow noopener"><img src="/user2/repo1/commit/1234/image" alt="./image"/></a></p> `, rendered) }) + + t.Run("NoRepo", func(t *testing.T) { + rctx := NewRenderContextRepoComment(t.Context(), nil).WithMarkupType(markdown.MarkupName) + rendered, err := markup.RenderString(rctx, "any") + assert.NoError(t, err) + assert.Equal(t, "<p>any</p>\n", rendered) + }) } diff --git a/modules/assetfs/embed.go b/modules/assetfs/embed.go new file mode 100644 index 0000000000..95176372d1 --- /dev/null +++ b/modules/assetfs/embed.go @@ -0,0 +1,375 @@ +// Copyright 2025 The Gitea Authors. All rights reserved. +// SPDX-License-Identifier: MIT + +package assetfs + +import ( + "bytes" + "compress/gzip" + "io" + "io/fs" + "os" + "path" + "path/filepath" + "strings" + "sync" + "time" + + "code.gitea.io/gitea/modules/json" + "code.gitea.io/gitea/modules/util" +) + +type EmbeddedFile interface { + io.ReadSeeker + fs.ReadDirFile + ReadDir(n int) ([]fs.DirEntry, error) +} + +type EmbeddedFileInfo interface { + fs.FileInfo + fs.DirEntry + GetGzipContent() ([]byte, bool) +} + +type decompressor interface { + io.Reader + Close() error + Reset(io.Reader) error +} + +type embeddedFileInfo struct { + fs *embeddedFS + fullName string + data []byte + + BaseName string `json:"n"` + OriginSize int64 `json:"s,omitempty"` + DataBegin int64 `json:"b,omitempty"` + DataLen int64 `json:"l,omitempty"` + Children []*embeddedFileInfo `json:"c,omitempty"` +} + +func (fi *embeddedFileInfo) GetGzipContent() ([]byte, bool) { + // when generating the bindata, if the compressed data equals or is larger than the original data, we store the original data + if fi.DataLen == fi.OriginSize { + return nil, false + } + return fi.data, true +} + +type EmbeddedFileBase struct { + info *embeddedFileInfo + dataReader io.ReadSeeker + seekPos int64 +} + +func (f *EmbeddedFileBase) ReadDir(n int) ([]fs.DirEntry, error) { + // this method is used to satisfy the "func (f ioFile) ReadDir(...)" in httpfs + l, err := f.info.fs.ReadDir(f.info.fullName) + if err != nil { + return nil, err + } + if n < 0 || n > len(l) { + return l, nil + } + return l[:n], nil +} + +type EmbeddedOriginFile struct { + EmbeddedFileBase +} + +type EmbeddedCompressedFile struct { + EmbeddedFileBase + decompressor decompressor + decompressorPos int64 +} + +type embeddedFS struct { + meta func() *EmbeddedMeta + + files map[string]*embeddedFileInfo + filesMu sync.RWMutex + + data []byte +} + +type EmbeddedMeta struct { + Root *embeddedFileInfo +} + +func NewEmbeddedFS(data []byte) fs.ReadDirFS { + efs := &embeddedFS{data: data, files: make(map[string]*embeddedFileInfo)} + efs.meta = sync.OnceValue(func() *EmbeddedMeta { + var meta EmbeddedMeta + p := bytes.LastIndexByte(data, '\n') + if p < 0 { + return &meta + } + if err := json.Unmarshal(data[p+1:], &meta); err != nil { + panic("embedded file is not valid") + } + return &meta + }) + return efs +} + +var _ fs.ReadDirFS = (*embeddedFS)(nil) + +func (e *embeddedFS) ReadDir(name string) (l []fs.DirEntry, err error) { + fi, err := e.getFileInfo(name) + if err != nil { + return nil, err + } + if !fi.IsDir() { + return nil, fs.ErrNotExist + } + l = make([]fs.DirEntry, len(fi.Children)) + for i, child := range fi.Children { + l[i], err = e.getFileInfo(name + "/" + child.BaseName) + if err != nil { + return nil, err + } + } + return l, nil +} + +func (e *embeddedFS) getFileInfo(fullName string) (*embeddedFileInfo, error) { + // no need to do heavy "path.Clean()" because we don't want to support "foo/../bar" or absolute paths + fullName = strings.TrimPrefix(fullName, "./") + if fullName == "" { + fullName = "." + } + + e.filesMu.RLock() + fi := e.files[fullName] + e.filesMu.RUnlock() + if fi != nil { + return fi, nil + } + + fields := strings.Split(fullName, "/") + fi = e.meta().Root + if fullName != "." { + found := true + for _, field := range fields { + for _, child := range fi.Children { + if found = child.BaseName == field; found { + fi = child + break + } + } + if !found { + return nil, fs.ErrNotExist + } + } + } + + e.filesMu.Lock() + defer e.filesMu.Unlock() + if fi != nil { + fi.fs = e + fi.fullName = fullName + fi.data = e.data[fi.DataBegin : fi.DataBegin+fi.DataLen] + e.files[fullName] = fi // do not cache nil, otherwise keeping accessing random non-existing file will cause OOM + return fi, nil + } + return nil, fs.ErrNotExist +} + +func (e *embeddedFS) Open(name string) (fs.File, error) { + info, err := e.getFileInfo(name) + if err != nil { + return nil, err + } + base := EmbeddedFileBase{info: info} + base.dataReader = bytes.NewReader(base.info.data) + if info.DataLen != info.OriginSize { + decomp, err := gzip.NewReader(base.dataReader) + if err != nil { + return nil, err + } + return &EmbeddedCompressedFile{EmbeddedFileBase: base, decompressor: decomp}, nil + } + return &EmbeddedOriginFile{base}, nil +} + +var ( + _ EmbeddedFileInfo = (*embeddedFileInfo)(nil) + _ EmbeddedFile = (*EmbeddedOriginFile)(nil) + _ EmbeddedFile = (*EmbeddedCompressedFile)(nil) +) + +func (f *EmbeddedOriginFile) Read(p []byte) (n int, err error) { + return f.dataReader.Read(p) +} + +func (f *EmbeddedCompressedFile) Read(p []byte) (n int, err error) { + if f.decompressorPos > f.seekPos { + if err = f.decompressor.Reset(bytes.NewReader(f.info.data)); err != nil { + return 0, err + } + f.decompressorPos = 0 + } + if f.decompressorPos < f.seekPos { + if _, err = io.CopyN(io.Discard, f.decompressor, f.seekPos-f.decompressorPos); err != nil { + return 0, err + } + f.decompressorPos = f.seekPos + } + n, err = f.decompressor.Read(p) + f.decompressorPos += int64(n) + f.seekPos = f.decompressorPos + return n, err +} + +func (f *EmbeddedFileBase) Seek(offset int64, whence int) (int64, error) { + switch whence { + case io.SeekStart: + f.seekPos = offset + case io.SeekCurrent: + f.seekPos += offset + case io.SeekEnd: + f.seekPos = f.info.OriginSize + offset + } + return f.seekPos, nil +} + +func (f *EmbeddedFileBase) Stat() (fs.FileInfo, error) { + return f.info, nil +} + +func (f *EmbeddedOriginFile) Close() error { + return nil +} + +func (f *EmbeddedCompressedFile) Close() error { + return f.decompressor.Close() +} + +func (fi *embeddedFileInfo) Name() string { + return fi.BaseName +} + +func (fi *embeddedFileInfo) Size() int64 { + return fi.OriginSize +} + +func (fi *embeddedFileInfo) Mode() fs.FileMode { + return util.Iif(fi.IsDir(), fs.ModeDir|0o555, 0o444) +} + +func (fi *embeddedFileInfo) ModTime() time.Time { + return getExecutableModTime() +} + +func (fi *embeddedFileInfo) IsDir() bool { + return fi.Children != nil +} + +func (fi *embeddedFileInfo) Sys() any { + return nil +} + +func (fi *embeddedFileInfo) Type() fs.FileMode { + return util.Iif(fi.IsDir(), fs.ModeDir, 0) +} + +func (fi *embeddedFileInfo) Info() (fs.FileInfo, error) { + return fi, nil +} + +// getExecutableModTime returns the modification time of the executable file. +// In bindata, we can't use the ModTime of the files because we need to make the build reproducible +var getExecutableModTime = sync.OnceValue(func() (modTime time.Time) { + exePath, err := os.Executable() + if err != nil { + return modTime + } + exePath, err = filepath.Abs(exePath) + if err != nil { + return modTime + } + exePath, err = filepath.EvalSymlinks(exePath) + if err != nil { + return modTime + } + st, err := os.Stat(exePath) + if err != nil { + return modTime + } + return st.ModTime() +}) + +func GenerateEmbedBindata(fsRootPath, outputFile string) error { + output, err := os.OpenFile(outputFile, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, os.ModePerm) + if err != nil { + return err + } + defer output.Close() + + meta := &EmbeddedMeta{} + meta.Root = &embeddedFileInfo{} + var outputOffset int64 + var embedFiles func(parent *embeddedFileInfo, fsPath, embedPath string) error + embedFiles = func(parent *embeddedFileInfo, fsPath, embedPath string) error { + dirEntries, err := os.ReadDir(fsPath) + if err != nil { + return err + } + for _, dirEntry := range dirEntries { + if err != nil { + return err + } + if dirEntry.IsDir() { + child := &embeddedFileInfo{ + BaseName: dirEntry.Name(), + Children: []*embeddedFileInfo{}, // non-nil means it's a directory + } + parent.Children = append(parent.Children, child) + if err = embedFiles(child, filepath.Join(fsPath, dirEntry.Name()), path.Join(embedPath, dirEntry.Name())); err != nil { + return err + } + } else { + data, err := os.ReadFile(filepath.Join(fsPath, dirEntry.Name())) + if err != nil { + return err + } + var compressed bytes.Buffer + gz, _ := gzip.NewWriterLevel(&compressed, gzip.BestCompression) + if _, err = gz.Write(data); err != nil { + return err + } + if err = gz.Close(); err != nil { + return err + } + + // only use the compressed data if it is smaller than the original data + outputBytes := util.Iif(len(compressed.Bytes()) < len(data), compressed.Bytes(), data) + child := &embeddedFileInfo{ + BaseName: dirEntry.Name(), + OriginSize: int64(len(data)), + DataBegin: outputOffset, + DataLen: int64(len(outputBytes)), + } + if _, err = output.Write(outputBytes); err != nil { + return err + } + outputOffset += child.DataLen + parent.Children = append(parent.Children, child) + } + } + return nil + } + + if err = embedFiles(meta.Root, fsRootPath, ""); err != nil { + return err + } + jsonBuf, err := json.Marshal(meta) // can't use json.NewEncoder here because it writes extra EOL + if err != nil { + return err + } + _, _ = output.Write([]byte{'\n'}) + _, err = output.Write(jsonBuf) + return err +} diff --git a/modules/assetfs/embed_test.go b/modules/assetfs/embed_test.go new file mode 100644 index 0000000000..06598da4c4 --- /dev/null +++ b/modules/assetfs/embed_test.go @@ -0,0 +1,98 @@ +// Copyright 2025 The Gitea Authors. All rights reserved. +// SPDX-License-Identifier: MIT + +package assetfs + +import ( + "bytes" + "io/fs" + "net/http" + "os" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func TestEmbed(t *testing.T) { + tmpDir := t.TempDir() + tmpDataDir := tmpDir + "/data" + _ = os.MkdirAll(tmpDataDir+"/foo/bar", 0o755) + _ = os.WriteFile(tmpDataDir+"/a.txt", []byte("a"), 0o644) + _ = os.WriteFile(tmpDataDir+"/foo/bar/b.txt", bytes.Repeat([]byte("a"), 1000), 0o644) + _ = os.WriteFile(tmpDataDir+"/foo/c.txt", []byte("c"), 0o644) + require.NoError(t, GenerateEmbedBindata(tmpDataDir, tmpDir+"/out.dat")) + + data, err := os.ReadFile(tmpDir + "/out.dat") + require.NoError(t, err) + efs := NewEmbeddedFS(data) + + // test a non-existing file + _, err = fs.ReadFile(efs, "not exist") + assert.ErrorIs(t, err, fs.ErrNotExist) + + // test a normal file (no compression) + content, err := fs.ReadFile(efs, "a.txt") + require.NoError(t, err) + assert.Equal(t, "a", string(content)) + fi, err := fs.Stat(efs, "a.txt") + require.NoError(t, err) + _, ok := fi.(EmbeddedFileInfo).GetGzipContent() + assert.False(t, ok) + + // test a compressed file + content, err = fs.ReadFile(efs, "foo/bar/b.txt") + require.NoError(t, err) + assert.Equal(t, bytes.Repeat([]byte("a"), 1000), content) + fi, err = fs.Stat(efs, "foo/bar/b.txt") + require.NoError(t, err) + assert.False(t, fi.Mode().IsDir()) + assert.True(t, fi.Mode().IsRegular()) + gzipContent, ok := fi.(EmbeddedFileInfo).GetGzipContent() + assert.True(t, ok) + assert.Greater(t, len(gzipContent), 1) + assert.Less(t, len(gzipContent), 1000) + + // test list root directory + entries, err := fs.ReadDir(efs, ".") + require.NoError(t, err) + assert.Len(t, entries, 2) + assert.Equal(t, "a.txt", entries[0].Name()) + assert.False(t, entries[0].IsDir()) + + // test list subdirectory + entries, err = fs.ReadDir(efs, "foo") + require.NoError(t, err) + require.Len(t, entries, 2) + assert.Equal(t, "bar", entries[0].Name()) + assert.True(t, entries[0].IsDir()) + assert.Equal(t, "c.txt", entries[1].Name()) + assert.False(t, entries[1].IsDir()) + + // test directory mode + fi, err = fs.Stat(efs, "foo") + require.NoError(t, err) + assert.True(t, fi.IsDir()) + assert.True(t, fi.Mode().IsDir()) + assert.False(t, fi.Mode().IsRegular()) + + // test httpfs + hfs := http.FS(efs) + hf, err := hfs.Open("foo/bar/b.txt") + require.NoError(t, err) + hi, err := hf.Stat() + require.NoError(t, err) + fiEmbedded, ok := hi.(EmbeddedFileInfo) + require.True(t, ok) + gzipContent, ok = fiEmbedded.GetGzipContent() + assert.True(t, ok) + assert.Greater(t, len(gzipContent), 1) + assert.Less(t, len(gzipContent), 1000) + + // test httpfs directory listing + hf, err = hfs.Open("foo") + require.NoError(t, err) + dirs, err := hf.Readdir(1) + require.NoError(t, err) + assert.Len(t, dirs, 1) +} diff --git a/modules/assetfs/layered.go b/modules/assetfs/layered.go index 4f3811ba2b..ce55475bd9 100644 --- a/modules/assetfs/layered.go +++ b/modules/assetfs/layered.go @@ -52,8 +52,8 @@ func Local(name, base string, sub ...string) *Layer { } // Bindata returns a new Layer with the given name, it serves files from the given bindata asset. -func Bindata(name string, fs http.FileSystem) *Layer { - return &Layer{name: name, fs: fs} +func Bindata(name string, fs fs.FS) *Layer { + return &Layer{name: name, fs: http.FS(fs)} } // LayeredFS is a layered asset file-system. It works like http.FileSystem, but it can have multiple layers. diff --git a/modules/git/command.go b/modules/git/command.go index eaaa4969d0..22f1d02339 100644 --- a/modules/git/command.go +++ b/modules/git/command.go @@ -47,6 +47,7 @@ type Command struct { globalArgsLength int brokenArgs []string cmd *exec.Cmd // for debug purpose only + configArgs []string } func logArgSanitize(arg string) string { @@ -196,6 +197,16 @@ func (c *Command) AddDashesAndList(list ...string) *Command { return c } +func (c *Command) AddConfig(key, value string) *Command { + kv := key + "=" + value + if !isSafeArgumentValue(kv) { + c.brokenArgs = append(c.brokenArgs, key) + } else { + c.configArgs = append(c.configArgs, "-c", kv) + } + return c +} + // ToTrustedCmdArgs converts a list of strings (trusted as argument) to TrustedCmdArgs // In most cases, it shouldn't be used. Use NewCommand().AddXxx() function instead func ToTrustedCmdArgs(args []string) TrustedCmdArgs { @@ -321,7 +332,7 @@ func (c *Command) run(ctx context.Context, skip int, opts *RunOpts) error { startTime := time.Now() - cmd := exec.CommandContext(ctx, c.prog, c.args...) + cmd := exec.CommandContext(ctx, c.prog, append(c.configArgs, c.args...)...) c.cmd = cmd // for debug purpose only if opts.Env == nil { cmd.Env = os.Environ() diff --git a/modules/git/key.go b/modules/git/key.go new file mode 100644 index 0000000000..2513c048b7 --- /dev/null +++ b/modules/git/key.go @@ -0,0 +1,15 @@ +// Copyright 2025 The Gitea Authors. All rights reserved. +// SPDX-License-Identifier: MIT + +package git + +// Based on https://git-scm.com/docs/git-config#Documentation/git-config.txt-gpgformat +const ( + SigningKeyFormatOpenPGP = "openpgp" // for GPG keys, the expected default of git cli + SigningKeyFormatSSH = "ssh" +) + +type SigningKey struct { + KeyID string + Format string +} diff --git a/modules/git/repo.go b/modules/git/repo.go index 45937a8d5f..239866fe9d 100644 --- a/modules/git/repo.go +++ b/modules/git/repo.go @@ -28,6 +28,7 @@ type GPGSettings struct { Email string Name string PublicKeyContent string + Format string } const prettyLogFormat = `--pretty=format:%H` diff --git a/modules/git/repo_gpg.go b/modules/git/repo_gpg.go index 8f91b4dce5..0021a7bda7 100644 --- a/modules/git/repo_gpg.go +++ b/modules/git/repo_gpg.go @@ -6,6 +6,7 @@ package git import ( "fmt" + "os" "strings" "code.gitea.io/gitea/modules/process" @@ -13,6 +14,14 @@ import ( // LoadPublicKeyContent will load the key from gpg func (gpgSettings *GPGSettings) LoadPublicKeyContent() error { + if gpgSettings.Format == SigningKeyFormatSSH { + content, err := os.ReadFile(gpgSettings.KeyID) + if err != nil { + return fmt.Errorf("unable to read SSH public key file: %s, %w", gpgSettings.KeyID, err) + } + gpgSettings.PublicKeyContent = string(content) + return nil + } content, stderr, err := process.GetManager().Exec( "gpg -a --export", "gpg", "-a", "--export", gpgSettings.KeyID) @@ -44,6 +53,9 @@ func (repo *Repository) GetDefaultPublicGPGKey(forceUpdate bool) (*GPGSettings, signingKey, _, _ := NewCommand("config", "--get", "user.signingkey").RunStdString(repo.Ctx, &RunOpts{Dir: repo.Path}) gpgSettings.KeyID = strings.TrimSpace(signingKey) + format, _, _ := NewCommand("config", "--default", SigningKeyFormatOpenPGP, "--get", "gpg.format").RunStdString(repo.Ctx, &RunOpts{Dir: repo.Path}) + gpgSettings.Format = strings.TrimSpace(format) + defaultEmail, _, _ := NewCommand("config", "--get", "user.email").RunStdString(repo.Ctx, &RunOpts{Dir: repo.Path}) gpgSettings.Email = strings.TrimSpace(defaultEmail) diff --git a/modules/git/repo_tree.go b/modules/git/repo_tree.go index 70e5aee023..309a73d759 100644 --- a/modules/git/repo_tree.go +++ b/modules/git/repo_tree.go @@ -15,7 +15,7 @@ import ( type CommitTreeOpts struct { Parents []string Message string - KeyID string + Key *SigningKey NoGPGSign bool AlwaysSign bool } @@ -43,8 +43,13 @@ func (repo *Repository) CommitTree(author, committer *Signature, tree *Tree, opt _, _ = messageBytes.WriteString(opts.Message) _, _ = messageBytes.WriteString("\n") - if opts.KeyID != "" || opts.AlwaysSign { - cmd.AddOptionFormat("-S%s", opts.KeyID) + if opts.Key != nil { + if opts.Key.Format != "" { + cmd.AddConfig("gpg.format", opts.Key.Format) + } + cmd.AddOptionFormat("-S%s", opts.Key.KeyID) + } else if opts.AlwaysSign { + cmd.AddOptionFormat("-S") } if opts.NoGPGSign { diff --git a/modules/markup/html.go b/modules/markup/html.go index d45153d95b..e8391341d9 100644 --- a/modules/markup/html.go +++ b/modules/markup/html.go @@ -86,8 +86,8 @@ var globalVars = sync.OnceValue(func() *globalVarsType { // codePreviewPattern matches "http://domain/.../{owner}/{repo}/src/commit/{commit}/{filepath}#L10-L20" v.codePreviewPattern = regexp.MustCompile(`https?://\S+/([^\s/]+)/([^\s/]+)/src/commit/([0-9a-f]{7,64})(/\S+)#(L\d+(-L\d+)?)`) - // cleans: "<foo/bar", "<any words/", ("<html", "<head", "<script", "<style") - v.tagCleaner = regexp.MustCompile(`(?i)<(/?\w+/\w+|/[\w ]+/|/?(html|head|script|style\b))`) + // cleans: "<foo/bar", "<any words/", ("<html", "<head", "<script", "<style", "<?", "<%") + v.tagCleaner = regexp.MustCompile(`(?i)<(/?\w+/\w+|/[\w ]+/|/?(html|head|script|style|%|\?)\b)`) v.nulCleaner = strings.NewReplacer("\000", "") return v }) @@ -253,7 +253,7 @@ func postProcess(ctx *RenderContext, procs []processor, input io.Reader, output node, err := html.Parse(io.MultiReader( // prepend "<html><body>" strings.NewReader("<html><body>"), - // Strip out nuls - they're always invalid + // strip out NULLs (they're always invalid), and escape known tags bytes.NewReader(globalVars().tagCleaner.ReplaceAll([]byte(globalVars().nulCleaner.Replace(string(rawHTML))), []byte("<$1"))), // close the tags strings.NewReader("</body></html>"), diff --git a/modules/markup/html_test.go b/modules/markup/html_test.go index 58f71bdd7b..5fdbf43f7c 100644 --- a/modules/markup/html_test.go +++ b/modules/markup/html_test.go @@ -525,6 +525,10 @@ func TestPostProcess(t *testing.T) { test("<script>a</script>", `<script>a</script>`) test("<STYLE>a", `<STYLE>a`) test("<style>a</STYLE>", `<style>a</STYLE>`) + + // other special tags, our special behavior + test("<?php\nfoo", "<?php\nfoo") + test("<%asp\nfoo", "<%asp\nfoo") } func TestIssue16020(t *testing.T) { diff --git a/modules/migration/schemas_bindata.go b/modules/migration/schemas_bindata.go index c5db3b3461..695c2c1135 100644 --- a/modules/migration/schemas_bindata.go +++ b/modules/migration/schemas_bindata.go @@ -3,6 +3,28 @@ //go:build bindata +//go:generate go run ../../build/generate-bindata.go ../../modules/migration/schemas bindata.dat + package migration -//go:generate go run ../../build/generate-bindata.go ../../modules/migration/schemas migration bindata.go +import ( + "io" + "io/fs" + "path" + "sync" + + _ "embed" + + "code.gitea.io/gitea/modules/assetfs" +) + +//go:embed bindata.dat +var bindata []byte + +var BuiltinAssets = sync.OnceValue(func() fs.FS { + return assetfs.NewEmbeddedFS(bindata) +}) + +func openSchema(filename string) (io.ReadCloser, error) { + return BuiltinAssets().Open(path.Base(filename)) +} diff --git a/modules/migration/schemas_static.go b/modules/migration/schemas_static.go deleted file mode 100644 index 8a0c340a65..0000000000 --- a/modules/migration/schemas_static.go +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright 2022 The Gitea Authors. All rights reserved. -// SPDX-License-Identifier: MIT - -//go:build bindata - -package migration - -import ( - "io" - "path" -) - -func openSchema(filename string) (io.ReadCloser, error) { - return Assets.Open(path.Base(filename)) -} diff --git a/modules/options/options_bindata.go b/modules/options/options_bindata.go index 29151cb3cb..b2321d7eb5 100644 --- a/modules/options/options_bindata.go +++ b/modules/options/options_bindata.go @@ -3,6 +3,21 @@ //go:build bindata +//go:generate go run ../../build/generate-bindata.go ../../options bindata.dat + package options -//go:generate go run ../../build/generate-bindata.go ../../options options bindata.go +import ( + "sync" + + _ "embed" + + "code.gitea.io/gitea/modules/assetfs" +) + +//go:embed bindata.dat +var bindata []byte + +var BuiltinAssets = sync.OnceValue(func() *assetfs.Layer { + return assetfs.Bindata("builtin(bindata)", assetfs.NewEmbeddedFS(bindata)) +}) diff --git a/modules/options/dynamic.go b/modules/options/options_dynamic.go index 085492d11c..085492d11c 100644 --- a/modules/options/dynamic.go +++ b/modules/options/options_dynamic.go diff --git a/modules/options/static.go b/modules/options/static.go deleted file mode 100644 index 72b28e990e..0000000000 --- a/modules/options/static.go +++ /dev/null @@ -1,14 +0,0 @@ -// Copyright 2022 The Gitea Authors. All rights reserved. -// SPDX-License-Identifier: MIT - -//go:build bindata - -package options - -import ( - "code.gitea.io/gitea/modules/assetfs" -) - -func BuiltinAssets() *assetfs.Layer { - return assetfs.Bindata("builtin(bindata)", Assets) -} diff --git a/modules/public/public.go b/modules/public/public.go index 7f8ce29056..2bc55b7869 100644 --- a/modules/public/public.go +++ b/modules/public/public.go @@ -89,19 +89,16 @@ func handleRequest(w http.ResponseWriter, req *http.Request, fs http.FileSystem, servePublicAsset(w, req, fi, fi.ModTime(), f) } -type GzipBytesProvider interface { - GzipBytes() []byte -} - // servePublicAsset serve http content func servePublicAsset(w http.ResponseWriter, req *http.Request, fi os.FileInfo, modtime time.Time, content io.ReadSeeker) { setWellKnownContentType(w, fi.Name()) httpcache.SetCacheControlInHeader(w.Header(), httpcache.CacheControlForPublicStatic()) encodings := parseAcceptEncoding(req.Header.Get("Accept-Encoding")) - if encodings.Contains("gzip") { - // try to provide gzip content directly from bindata (provided by vfsgenÛ°CompressedFileInfo) - if compressed, ok := fi.(GzipBytesProvider); ok { - rdGzip := bytes.NewReader(compressed.GzipBytes()) + fiEmbedded, _ := fi.(assetfs.EmbeddedFileInfo) + if encodings.Contains("gzip") && fiEmbedded != nil { + // try to provide gzip content directly from bindata + if gzipBytes, ok := fiEmbedded.GetGzipContent(); ok { + rdGzip := bytes.NewReader(gzipBytes) // all gzipped static files (from bindata) are managed by Gitea, so we can make sure every file has the correct ext name // then we can get the correct Content-Type, we do not need to do http.DetectContentType on the decompressed data if w.Header().Get("Content-Type") == "" { diff --git a/modules/public/public_bindata.go b/modules/public/public_bindata.go index 4878f88ad1..2dcf3e72e4 100644 --- a/modules/public/public_bindata.go +++ b/modules/public/public_bindata.go @@ -5,4 +5,19 @@ package public -//go:generate go run ../../build/generate-bindata.go ../../public public bindata.go true +//go:generate go run ../../build/generate-bindata.go ../../public bindata.dat + +import ( + "sync" + + _ "embed" + + "code.gitea.io/gitea/modules/assetfs" +) + +//go:embed bindata.dat +var bindata []byte + +var BuiltinAssets = sync.OnceValue(func() *assetfs.Layer { + return assetfs.Bindata("builtin(bindata)", assetfs.NewEmbeddedFS(bindata)) +}) diff --git a/modules/public/serve_dynamic.go b/modules/public/public_dynamic.go index a668b17c34..a668b17c34 100644 --- a/modules/public/serve_dynamic.go +++ b/modules/public/public_dynamic.go diff --git a/modules/public/serve_static.go b/modules/public/serve_static.go deleted file mode 100644 index e79085021e..0000000000 --- a/modules/public/serve_static.go +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright 2016 The Gitea Authors. All rights reserved. -// SPDX-License-Identifier: MIT - -//go:build bindata - -package public - -import ( - "time" - - "code.gitea.io/gitea/modules/assetfs" - "code.gitea.io/gitea/modules/timeutil" -) - -var _ GzipBytesProvider = (*vfsgenÛ°CompressedFileInfo)(nil) - -// GlobalModTime provide a global mod time for embedded asset files -func GlobalModTime(filename string) time.Time { - return timeutil.GetExecutableModTime() -} - -func BuiltinAssets() *assetfs.Layer { - return assetfs.Bindata("builtin(bindata)", Assets) -} diff --git a/modules/setting/repository.go b/modules/setting/repository.go index c6bdc65b32..318cf41108 100644 --- a/modules/setting/repository.go +++ b/modules/setting/repository.go @@ -100,11 +100,13 @@ var ( SigningKey string SigningName string SigningEmail string + SigningFormat string InitialCommit []string CRUDActions []string `ini:"CRUD_ACTIONS"` Merges []string Wiki []string DefaultTrustModel string + TrustedSSHKeys []string `ini:"TRUSTED_SSH_KEYS"` } `ini:"repository.signing"` }{ DetectedCharsetsOrder: []string{ @@ -242,20 +244,24 @@ var ( SigningKey string SigningName string SigningEmail string + SigningFormat string InitialCommit []string CRUDActions []string `ini:"CRUD_ACTIONS"` Merges []string Wiki []string DefaultTrustModel string + TrustedSSHKeys []string `ini:"TRUSTED_SSH_KEYS"` }{ SigningKey: "default", SigningName: "", SigningEmail: "", + SigningFormat: "openpgp", // git.SigningKeyFormatOpenPGP InitialCommit: []string{"always"}, CRUDActions: []string{"pubkey", "twofa", "parentsigned"}, Merges: []string{"pubkey", "twofa", "basesigned", "commitssigned"}, Wiki: []string{"never"}, DefaultTrustModel: "collaborator", + TrustedSSHKeys: []string{}, }, } RepoRootPath string diff --git a/modules/templates/static.go b/modules/templates/static.go deleted file mode 100644 index b5a7e561ec..0000000000 --- a/modules/templates/static.go +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright 2016 The Gitea Authors. All rights reserved. -// SPDX-License-Identifier: MIT - -//go:build bindata - -package templates - -import ( - "time" - - "code.gitea.io/gitea/modules/assetfs" - "code.gitea.io/gitea/modules/timeutil" -) - -// GlobalModTime provide a global mod time for embedded asset files -func GlobalModTime(filename string) time.Time { - return timeutil.GetExecutableModTime() -} - -func BuiltinAssets() *assetfs.Layer { - return assetfs.Bindata("builtin(bindata)", Assets) -} diff --git a/modules/templates/templates_bindata.go b/modules/templates/templates_bindata.go index 6f1d3cf539..a919591ecf 100644 --- a/modules/templates/templates_bindata.go +++ b/modules/templates/templates_bindata.go @@ -3,6 +3,21 @@ //go:build bindata +//go:generate go run ../../build/generate-bindata.go ../../templates bindata.dat + package templates -//go:generate go run ../../build/generate-bindata.go ../../templates templates bindata.go true +import ( + "sync" + + _ "embed" + + "code.gitea.io/gitea/modules/assetfs" +) + +//go:embed bindata.dat +var bindata []byte + +var BuiltinAssets = sync.OnceValue(func() *assetfs.Layer { + return assetfs.Bindata("builtin(bindata)", assetfs.NewEmbeddedFS(bindata)) +}) diff --git a/modules/templates/dynamic.go b/modules/templates/templates_dynamic.go index e1babd83c9..e1babd83c9 100644 --- a/modules/templates/dynamic.go +++ b/modules/templates/templates_dynamic.go diff --git a/modules/templates/util_render.go b/modules/templates/util_render.go index 8d9ba1000c..14655a53c3 100644 --- a/modules/templates/util_render.go +++ b/modules/templates/util_render.go @@ -38,8 +38,8 @@ func NewRenderUtils(ctx reqctx.RequestContext) *RenderUtils { // RenderCommitMessage renders commit message with XSS-safe and special links. func (ut *RenderUtils) RenderCommitMessage(msg string, repo *repo.Repository) template.HTML { cleanMsg := template.HTMLEscapeString(msg) - // we can safely assume that it will not return any error, since there - // shouldn't be any special HTML. + // we can safely assume that it will not return any error, since there shouldn't be any special HTML. + // "repo" can be nil when rendering commit messages for deleted repositories in a user's dashboard feed. fullMessage, err := markup.PostProcessCommitMessage(renderhelper.NewRenderContextRepoComment(ut.ctx, repo), cleanMsg) if err != nil { log.Error("PostProcessCommitMessage: %v", err) @@ -47,7 +47,7 @@ func (ut *RenderUtils) RenderCommitMessage(msg string, repo *repo.Repository) te } msgLines := strings.Split(strings.TrimSpace(fullMessage), "\n") if len(msgLines) == 0 { - return template.HTML("") + return "" } return renderCodeBlock(template.HTML(msgLines[0])) } diff --git a/modules/timeutil/executable.go b/modules/timeutil/executable.go deleted file mode 100644 index 57ae8b2a9d..0000000000 --- a/modules/timeutil/executable.go +++ /dev/null @@ -1,50 +0,0 @@ -// Copyright 2022 The Gitea Authors. All rights reserved. -// SPDX-License-Identifier: MIT - -package timeutil - -import ( - "os" - "path/filepath" - "sync" - "time" - - "code.gitea.io/gitea/modules/log" -) - -var ( - executablModTime = time.Now() - executablModTimeOnce sync.Once -) - -// GetExecutableModTime get executable file modified time of current process. -func GetExecutableModTime() time.Time { - executablModTimeOnce.Do(func() { - exePath, err := os.Executable() - if err != nil { - log.Error("os.Executable: %v", err) - return - } - - exePath, err = filepath.Abs(exePath) - if err != nil { - log.Error("filepath.Abs: %v", err) - return - } - - exePath, err = filepath.EvalSymlinks(exePath) - if err != nil { - log.Error("filepath.EvalSymlinks: %v", err) - return - } - - st, err := os.Stat(exePath) - if err != nil { - log.Error("os.Stat: %v", err) - return - } - - executablModTime = st.ModTime() - }) - return executablModTime -} diff --git a/modules/zstd/zstd_test.go b/modules/zstd/zstd_test.go index c3ca8e78f7..7fd30484ca 100644 --- a/modules/zstd/zstd_test.go +++ b/modules/zstd/zstd_test.go @@ -16,7 +16,7 @@ import ( ) func TestWriterReader(t *testing.T) { - testData := prepareTestData(t, 20_000_000) + testData := prepareTestData(t, 1_000_000) result := bytes.NewBuffer(nil) @@ -64,7 +64,7 @@ func TestWriterReader(t *testing.T) { } func TestSeekableWriterReader(t *testing.T) { - testData := prepareTestData(t, 20_000_000) + testData := prepareTestData(t, 2_000_000) result := bytes.NewBuffer(nil) @@ -109,7 +109,7 @@ func TestSeekableWriterReader(t *testing.T) { reader, err := NewSeekableReader(assertReader) require.NoError(t, err) - _, err = reader.Seek(10_000_000, io.SeekStart) + _, err = reader.Seek(1_000_000, io.SeekStart) require.NoError(t, err) data := make([]byte, 1000) @@ -117,7 +117,7 @@ func TestSeekableWriterReader(t *testing.T) { require.NoError(t, err) require.NoError(t, reader.Close()) - assert.Equal(t, testData[10_000_000:10_000_000+1000], data) + assert.Equal(t, testData[1_000_000:1_000_000+1000], data) // Should seek 3 times, // the first two times are for getting the index, diff --git a/options/locale/locale_uk-UA.ini b/options/locale/locale_uk-UA.ini index 42df483d8d..6ab4d7800c 100644 --- a/options/locale/locale_uk-UA.ini +++ b/options/locale/locale_uk-UA.ini @@ -31,7 +31,7 @@ username=Ім'Ñ ÐºÑ€Ð¸Ñтувача email=ÐдреÑа електронної пошти password=Пароль access_token=Токен доÑтупу -re_type=ÐŸÑ–Ð´Ñ‚Ð²ÐµÑ€Ð´Ð¶ÐµÐ½Ð½Ñ Ð¿Ð°Ñ€Ð¾Ð»Ñ +re_type=Підтвердити пароль captcha=CAPTCHA twofa=Двофакторна Ð°Ð²Ñ‚ÐµÐ½Ñ‚Ð¸Ñ„Ñ–ÐºÐ°Ñ†Ñ–Ñ twofa_scratch=Двофакторний одноразовий пароль @@ -40,7 +40,7 @@ passcode=Код доÑтупу webauthn_insert_key=Ð’Ñтавте ключ безпеки webauthn_sign_in=ÐатиÑніть кнопку на вашому ключі безпеки. Якщо ваш ключ без фізичної кнопки, поновно вÑтавте ключ. webauthn_press_button=Будь лаÑка, натиÑніть кнопку на вашому ключі безпеки… -webauthn_use_twofa=ВикориÑтовуйте дво-факторний код із Вашого телефона +webauthn_use_twofa=ВикориÑтовуйте двофакторний код із Вашого телефона webauthn_error=Ðе вдалоÑÑ Ð¿Ñ€Ð¾Ñ‡Ð¸Ñ‚Ð°Ñ‚Ð¸ ваш ключ безпеки. webauthn_unsupported_browser=Ваш браузер наразі не підтримує WebAuthn. webauthn_error_unknown=СталаÑÑ Ð½ÐµÐ²Ñ–Ð´Ð¾Ð¼Ð° помилка. Будь лаÑка, Ñпробуйте ще раз. @@ -51,11 +51,11 @@ webauthn_error_empty=Ви повинні вÑтановити назву Ð´Ð»Ñ webauthn_error_timeout=Ð§Ð°Ñ Ð¾Ñ‡Ñ–ÐºÑƒÐ²Ð°Ð½Ð½Ñ Ð²Ð¸Ñ‡ÐµÑ€Ð¿Ð°Ð½Ð¾, перш ніж ваш ключ було прочитано. Перезавантажте Ñторінку та Ñпробуйте ще раз. webauthn_reload=Оновити -repository=Репозиторій +repository=Сховище organization=ÐžÑ€Ð³Ð°Ð½Ñ–Ð·Ð°Ñ†Ñ–Ñ mirror=Дзеркало issue_milestone=Етап -new_repo=Ðовий репозиторій +new_repo=Ðове Ñховище new_migrate=Ðова Ð¼Ñ–Ð³Ñ€Ð°Ñ†Ñ–Ñ new_mirror=Ðове дзеркало new_org=Ðова Ð¾Ñ€Ð³Ð°Ð½Ñ–Ð·Ð°Ñ†Ñ–Ñ @@ -131,9 +131,9 @@ artifacts=Ðртефакти expired=ПроÑтрочено confirm_delete_artifact=Справді видалити артефакт '%s' ? -archived=Ðрхівовані +archived=Ðрхівовано -concept_code_repository=Репозиторій +concept_code_repository=Сховище concept_user_organization=ÐžÑ€Ð³Ð°Ð½Ñ–Ð·Ð°Ñ†Ñ–Ñ show_timestamps=Показувати чаÑові мітки @@ -148,7 +148,7 @@ value=Ð—Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ filter=Фільтр filter.clear=ОчиÑтити фільтр -filter.is_archived=Ðрхівовані +filter.is_archived=Ðрхівовано filter.not_archived=Ðе архівовано filter.is_fork=Відгалужено filter.not_fork=Ðе відгалужено @@ -224,113 +224,111 @@ app_desc=Зручний влаÑний ÑÐµÑ€Ð²Ñ–Ñ Ñ…Ð¾Ñтингу репозРinstall=Легко вÑтановити platform=ПлатформонезалежніÑть lightweight=ÐевибагливіÑть -lightweight_desc=Gitea має низькі вимоги до реÑурÑів та може працювати на недорогому Raspberry Pi. Збережіть Ñвою машину енергію! license=Відкритий вихідний код [install] install=Ð’ÑÑ‚Ð°Ð½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ installing_desc=Ð’ÑтановленнÑ, будь лаÑка, зачекайте... title=Початкова ÐºÐ¾Ð½Ñ„Ñ–Ð³ÑƒÑ€Ð°Ñ†Ñ–Ñ -docker_helper=Якщо ви запуÑкаєте Gitea вÑередині Docker, будь лаÑка уважно прочитайте <a target="_blank" rel="noopener" href="%s">документацію</a> перед тим, Ñк щоÑÑŒ змінити на цій Ñторінці. -require_db_desc=Gitea вимагає MySQL, PostgreSQL, MSSQL, SQLite3 або TiDB (протокол MySQL). +docker_helper=Якщо ви запуÑкаєте Gitea у Docker, будь лаÑка, прочитайте <a target="_blank" rel="noopener noreferrer" href="%s">документацію</a> перед тим, Ñк змінювати будь-Ñкі налаштуваннÑ. +require_db_desc=Gitea потребує MySQL, PostgreSQL, MSSQL, SQLite3 або TiDB (протокол MySQL). db_title=ÐÐ°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ð±Ð°Ð·Ð¸ даних db_type=Тип бази даних host=ХоÑÑ‚ user=Ім'Ñ ÐºÑ€Ð¸Ñтувача password=Пароль -db_name=Ім'Ñ Ð±Ð°Ð·Ð¸ даних +db_name=Ðазва бази даних db_schema=Схема -db_schema_helper=Залиште пуÑтим Ð´Ð»Ñ Ð±Ð°Ð·Ð¸ даних за замовчуваннÑм ("публічна"). +db_schema_helper=Залиште пуÑтим Ð´Ð»Ñ Ñ‚Ð¸Ð¿Ð¾Ð²Ð¾Ñ— Ñхеми бази даних ("публічна"). ssl_mode=SSL path=ШлÑÑ… -sqlite_helper=ШлÑÑ… до файлу Ð´Ð»Ñ Ð±Ð°Ð·Ð¸ даних SQLite3.<br>Введіть абÑолютний шлÑÑ…, Ñкщо ви запуÑкаєте GÑ–tea Ñк ÑервіÑ. +sqlite_helper=ШлÑÑ… до файлу бази даних SQLite3.<br>Введіть абÑолютний шлÑÑ…, Ñкщо ви запуÑкаєте GÑ–tea Ñк ÑервіÑ. reinstall_error=Ви намагаєтеÑÑ Ð²Ñтановити в наÑвну базу даних Gitea reinstall_confirm_message=Повторне вÑÑ‚Ð°Ð½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ Ð² наÑвну базу даних Gitea може Ñпричинити багато проблем. Ð’ більшоÑті випадків, ви повинні викориÑтовувати Ñвій наÑвний "app.ini" Ð´Ð»Ñ Ð·Ð°Ð¿ÑƒÑку Gitea. Якщо ви знаєте, що робите, Ñпробуйте наÑтупне: -reinstall_confirm_check_1=Дані зашифровані з викориÑтаннÑм SECRET_KEY з app.ini можуть бути втрачені: кориÑтувачі не зможуть увійти з 2FA/OTP Ñ– дзеркала можуть працювати некоректно. Ð’Ñтановлюючи цей прапорець, ви підтверджуєте, що в поточному файлі app.ini вказано правильне Ð·Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ SECRET_KEY. -reinstall_confirm_check_2=Репозиторії та Ð½Ð°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ð½ÐµÐ¾Ð±Ñ…Ñ–Ð´Ð½Ð¾ повторно Ñинхронізувати. Ð’Ñтановлюючи цей прапорець, ви підтверджуєте, що ви Ñинхронізуватимете хуки репозиторіїв та authorized_keys вручну. Ви підтверджуєте, що Ð½Ð°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ñ€ÐµÐ¿Ð¾Ð·Ð¸Ñ‚Ð¾Ñ€Ñ–ÑŽ Ñ– дзеркала Ñ” правильними. -reinstall_confirm_check_3=Ви підтверджуєте, що повніÑтю впевнені в тому, що Ð´Ð»Ñ Ñ†ÑŒÐ¾Ð³Ð¾ екземплÑра Gitea вказано правильне Ñ€Ð¾Ð·Ñ‚Ð°ÑˆÑƒÐ²Ð°Ð½Ð½Ñ app.ini та екземплÑÑ€ Ñлід вÑтановити повторно. Ви підтверджуєте, що уÑвідомлюєте вищенаведені ризики. +reinstall_confirm_check_1=Дані, зашифровані за допомогою SECRET_KEY в app.ini, можуть бути втрачені: кориÑтувачі не зможуть увійти за допомогою 2FA/OTP, а дзеркала можуть працювати некоректно. Ð’Ñтановивши цей прапорець, ви підтверджуєте, що поточний файл app.ini міÑтить правильний SECRET_KEY. +reinstall_confirm_check_2=Можливо, потрібно буде повторно Ñинхронізувати Ñховища та налаштуваннÑ. Ð’Ñтановивши цей прапорець, ви підтверджуєте, що будете реÑинхронізувати хуки Ð´Ð»Ñ Ñховищ Ñ– файл authorized_keys вручну. Ви підтверджуєте, що забезпечите правильніÑть налаштувань Ñховища Ñ– дзеркала. +reinstall_confirm_check_3=Ви підтверджуєте, що абÑолютно впевнені, що Gitea працює з правильним розташуваннÑм файлу app.ini, Ñ– що вам потрібно перевÑтановити програму. Ви підтверджуєте, що уÑвідомлюєте вищевказані ризики. err_empty_db_path=ШлÑÑ… до файлу бази даних SQLite3 не може бути порожнім. -no_admin_and_disable_registration=Ви не можете вимкнути реєÑтрацію до ÑÑ‚Ð²Ð¾Ñ€ÐµÐ½Ð½Ñ Ð¾Ð±Ð»Ñ–ÐºÐ¾Ð²Ð¾Ð³Ð¾ запиÑу адмініÑтратора. +no_admin_and_disable_registration=Ви не можете вимкнути реєÑтрацію без ÑÑ‚Ð²Ð¾Ñ€ÐµÐ½Ð½Ñ Ð¾Ð±Ð»Ñ–ÐºÐ¾Ð²Ð¾Ð³Ð¾ запиÑу адмініÑтратора. err_empty_admin_password=Пароль адмініÑтратора не може бути порожнім. err_empty_admin_email=Електронна адреÑа адмініÑтратора не може бути порожньою. -err_admin_name_is_reserved=Ðеправильне ім'Ñ ÐºÐ¾Ñ€Ð¸Ñтувача-адмініÑтратора - ім'Ñ Ð·Ð°Ñ€ÐµÐ·ÐµÑ€Ð²Ð¾Ð²Ð°Ð½Ðµ -err_admin_name_pattern_not_allowed=Ім'Ñ Ð°Ð´Ð¼Ñ–Ð½Ñ–Ñтратора недійÑне, це ім'Ñ Ð¿Ñ–Ð´Ð¿Ð°Ð´Ð°Ñ” під зарезервований шаблон -err_admin_name_is_invalid=Ðеправильне ім'Ñ ÐºÐ¾Ñ€Ð¸Ñтувача-адмініÑтратора +err_admin_name_is_reserved=Ðеправильне ім'Ñ ÐºÐ¾Ñ€Ð¸Ñтувача адмініÑтратора - ім'Ñ Ð·Ð°Ñ€ÐµÐ·ÐµÑ€Ð²Ð¾Ð²Ð°Ð½Ð¾ +err_admin_name_pattern_not_allowed=Ім'Ñ ÐºÐ¾Ñ€Ð¸Ñтувача адмініÑтратора недійÑне, воно відповідає зарезервованому шаблону +err_admin_name_is_invalid=ÐедійÑне ім'Ñ ÐºÐ¾Ñ€Ð¸Ñтувача адмініÑтратора general_title=Загальні Ð½Ð°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ app_name=Ðазва Ñайту app_name_helper=Тут ви можете ввеÑти назву Ñвоєї компанії. -repo_path=Кореневий шлÑÑ… Ñ€ÐµÐ¿Ð¾Ð·Ð¸Ñ‚Ð¾Ñ€Ñ–Ñ -repo_path_helper=Ð’ÑÑ– вилучені Git репозиторії будуть збережені в цей каталог. -lfs_path=Кореневої шлÑÑ… Git LFS -lfs_path_helper=У цій папці будуть зберігатиÑÑ Ñ„Ð°Ð¹Ð»Ð¸ Git LFS. Залиште порожнім, щоб вимкнути LFS. -run_user=ЗапуÑк від імені КориÑтувача +repo_path=Кореневий шлÑÑ… Ñховища +repo_path_helper=До цього каталогу буде збережено віддалені Ñховища Git. +lfs_path=Кореневий шлÑÑ… Git LFS +lfs_path_helper=У цій теці будуть зберігатиÑÑ Ñ„Ð°Ð¹Ð»Ð¸ Git LFS. Залиште порожнім, щоб вимкнути. +run_user=Виконати Ñк domain=Домен Ñервера -domain_helper=Домен або адреÑа хоÑта Ñервера. +domain_helper=Домен або хоÑÑ‚-адреÑа Ñервера. ssh_port=Порт SSH Ñервера ssh_port_helper=Ðомер порту, Ñкий викориÑтовує SSH Ñервер. Залиште порожнім, щоб вимкнути SSH. http_port=Gitea HTTP порт -http_port_helper=Ðомер порту, Ñкий буде проÑлуховуватиÑÑ Giteas веб-Ñервером. +http_port_helper=Ðомер порту, Ñкий буде проÑлуховуватиÑÑ Ñервером Giteas. app_url=Базова URL-адреÑа Gitea -app_url_helper=Базова адреÑа Ð´Ð»Ñ HTTP(S) ÐºÐ»Ð¾Ð½ÑƒÐ²Ð°Ð½Ð½Ñ Ñ‡ÐµÑ€ÐµÐ· URL та повідомлень електронної пошти. -log_root_path=ШлÑÑ… до лог файлу -log_root_path_helper=Файли журналу будуть запиÑані в цей каталог. - -optional_title=Додаткові Ð½Ð°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ -email_title=ÐÐ°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Email -smtp_addr=SMTP хоÑÑ‚ -smtp_port=SMTP порт -smtp_from=ВідправлÑти Email від імені +app_url_helper=Базова адреÑа Ð´Ð»Ñ URL-Ð°Ð´Ñ€ÐµÑ ÐºÐ»Ð¾Ð½Ñ–Ð² HTTP(S) та Ñповіщень електронною поштою. +log_root_path=ШлÑÑ… до журналу +log_root_path_helper=Файли журналу будуть запиÑані в цю теку. + +optional_title=Ðеобов'Ñзкові Ð½Ð°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ +email_title=ÐÐ°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ ÐµÐ»ÐµÐºÑ‚Ñ€Ð¾Ð½Ð½Ð¾Ñ— пошти +smtp_addr=Сервер SMTP +smtp_port=Порт SMTP smtp_from_invalid=ÐдреÑа "ÐадіÑлати лиÑта Ñк" недійÑна -smtp_from_helper=Електронна пошта Ð´Ð»Ñ Ð²Ð¸ÐºÐ¾Ñ€Ð¸ÑÑ‚Ð°Ð½Ð½Ñ Ð² GÑ–tea. Введіть звичайну електронну адреÑу або викориÑтовуйте формат: "Ім'Ñ" <email@example.com>. -mailer_user=SMTP Ім'Ñ ÐºÑ€Ð¸Ñтувача -mailer_password=SMTP Пароль -register_confirm=Потрібно підтвердити електронну пошту Ð´Ð»Ñ Ñ€ÐµÑ”Ñтрації +smtp_from_helper=ÐдреÑа електронної пошти, Ñку буде викориÑтовувати Gitea. Введіть звичайну адреÑу електронної пошти або викориÑтовуйте формат «Ім'Ñ» <email@example.com>. +mailer_user=Ім'Ñ ÐºÐ¾Ñ€Ð¸Ñтувача SMTP +mailer_password=Пароль SMTP +register_confirm=Вимагати Ð¿Ñ–Ð´Ñ‚Ð²ÐµÑ€Ð´Ð¶ÐµÐ½Ð½Ñ ÐµÐ»ÐµÐºÑ‚Ñ€Ð¾Ð½Ð½Ð¾ÑŽ поштою Ð´Ð»Ñ Ñ€ÐµÑ”Ñтрації mail_notify=Увімкнути ÑÐ¿Ð¾Ð²Ñ–Ñ‰ÐµÐ½Ð½Ñ ÐµÐ»ÐµÐºÑ‚Ñ€Ð¾Ð½Ð½Ð¾ÑŽ поштою -server_service_title=Сервер Ñ– Ð½Ð°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ð·Ð¾Ð²Ð½Ñ–ÑˆÐ½Ñ–Ñ… Ñлужб +server_service_title=ÐÐ°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ñервера Ñ– Ñторонніх ÑервіÑів offline_mode=Увімкнути локальний режим -offline_mode_popup=Відключити Ñторонні мережі доÑтавки контенту Ñ– обÑлуговувати вÑÑ– реÑурÑи локально. +offline_mode_popup=Вимкнути Ñторонні мережі доÑтавки контенту та обÑлуговувати вÑÑ– реÑурÑи локально. disable_gravatar=Вимкнути Gravatar -disable_gravatar_popup=Відключити Gravatar Ñ– Ñторонні джерела аватарів. Якщо кориÑтувач не завантажить аватар локально то за замовчуваннÑм буде викориÑтовуватиÑÑ Ñтандартний аватар. -federated_avatar_lookup=Увімкнути федеративні аватари -federated_avatar_lookup_popup=Увімкнути зовнішний Ðватар за допомогою Libravatar. -disable_registration=Вимкнути ÑамоÑтійну реєÑтрацію -disable_registration_popup=Вимкнути ÑамоÑтійну реєÑтрацію кориÑтувачів, тільки адмініÑтратор може Ñтворювати нові облікові запиÑи. +disable_gravatar_popup=Вимкнути Gravatar та Ñторонні джерела аватарок. Якщо кориÑтувач локально не завантажить аватар, буде викориÑтовуватиÑÑ Ñ‚Ð¸Ð¿Ð¾Ð²Ð¸Ð¹ аватар. +federated_avatar_lookup=Увімкнути зовнішні аватари +federated_avatar_lookup_popup=Увімкнути пошук об'єднаних аватарів за допомогою Libravatar. +disable_registration=Вимкнути реєÑтрацію +disable_registration_popup=Вимкнути реєÑтрацію кориÑтувачів, тільки адмініÑтратор може Ñтворювати нові облікові запиÑи. allow_only_external_registration_popup=Дозволити реєÑтрацію тільки через Ñторонні ÑервіÑи -openid_signin=Увімкнути реєÑтрацію за допомогою OpenID -openid_signin_popup=Увімкнути вхід за допомогою OpenID. +openid_signin=Увімкнути вхід за допомогою OpenID +openid_signin_popup=Увімкнути вхід кориÑтувачів за допомогою OpenID. openid_signup=Увімкнути ÑамоÑтійну реєÑтрацію за допомогою OpenID openid_signup_popup=Увімкнути ÑамореєÑтрацію кориÑтувачів на оÑнові OpenID. -enable_captcha=Увімкнути CAPTCHA при реєÑтрації -enable_captcha_popup=Вимагати перевірку CAPTCHA при ÑамоÑтійній реєÑтрації кориÑтувача. +enable_captcha=Увімкнути CAPTCHA Ð´Ð»Ñ Ñ€ÐµÑ”Ñтрації +enable_captcha_popup=Вимагати CAPTCHA Ð´Ð»Ñ ÑамореєÑтрації кориÑтувачів. require_sign_in_view=Вимагати авторизації Ð´Ð»Ñ Ð¿ÐµÑ€ÐµÐ³Ð»Ñду Ñторінок admin_setting_desc=Ð¡Ñ‚Ð²Ð¾Ñ€ÐµÐ½Ð½Ñ Ð¾Ð±Ð»Ñ–ÐºÐ¾Ð²Ð¾Ð³Ð¾ запиÑу адмініÑтратора необов'Ñзково. Перший зареєÑтрований кориÑтувач автоматично Ñтає адмініÑтратором. admin_title=ÐÐ°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ð¾Ð±Ð»Ñ–ÐºÐ¾Ð²Ð¾Ð³Ð¾ запиÑу адмініÑтратора admin_name=Ім'Ñ ÐºÑ€Ð¸Ñтувача ÐдмініÑтратора admin_password=Пароль -confirm_password=ÐŸÑ–Ð´Ñ‚Ð²ÐµÑ€Ð´Ð¶ÐµÐ½Ð½Ñ Ð¿Ð°Ñ€Ð¾Ð»Ñ +confirm_password=Підтвердити пароль admin_email=ÐдреÑа електронної пошти -install_btn_confirm=Ð’ÑÑ‚Ð°Ð½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ Gitea -test_git_failed=Ðе в змозі перевірити 'git' команду: %v +install_btn_confirm=Ð’Ñтановити Gitea +test_git_failed=Ðе вдалоÑÑ Ð¿ÐµÑ€ÐµÐ²Ñ–Ñ€Ð¸Ñ‚Ð¸ команду 'git': %v sqlite3_not_available=Ð¦Ñ Ð²ÐµÑ€ÑÑ–Ñ Gitea не підтримує SQLite3. Будь лаÑка, завантажте офіційну бінарну верÑÑ–ÑŽ з %s (не верÑÑ–ÑŽ gobuild). -invalid_db_setting=ÐÐ°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ð±Ð°Ð·Ð¸ даних Ñ” некоректними: %v -invalid_db_table=Ð¢Ð°Ð±Ð»Ð¸Ñ†Ñ '%s' бази даних Ñ” недійÑною: %v -invalid_repo_path=Помилковий шлÑÑ… до ÐºÐ¾Ñ€ÐµÐ½Ñ Ñ€ÐµÐ¿Ð¾Ð·Ð¸Ñ‚Ð¾Ñ€Ñ–ÑŽ: %v -invalid_app_data_path=Ðекоректний шлÑÑ… до даних програми: %v -run_user_not_match=Ім'Ñ ÐºÐ¾Ñ€Ð¸Ñтувача 'run as' не Ñ” поточним ім'Ñм кориÑтувача: %s -> %s -internal_token_failed=Ðе вдалоÑÑ Ð·Ð³ÐµÐ½ÐµÑ€ÑƒÐ²Ð°Ñ‚Ð¸ внутрішній токен: %v -secret_key_failed=Ðе вдалоÑÑ Ð·Ð³ÐµÐ½ÐµÑ€ÑƒÐ²Ð°Ñ‚Ð¸ Ñекретний ключ: %v -save_config_failed=Ðе в змозі зберегти конфігурацію: %v -invalid_admin_setting=ÐеприпуÑтимі Ð½Ð°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ð¾Ð±Ð»Ñ–ÐºÐ¾Ð²Ð¾Ð³Ð¾ запиÑу адмініÑтратора: %v -invalid_log_root_path=ÐеприпуÑтимий шлÑÑ… Ð´Ð»Ñ Ð»Ð¾Ð³Ñ–Ð²: %v -default_keep_email_private=Приховати адреÑу електронної пошти за замовчуваннÑм -default_keep_email_private_popup=Приховати адреÑу електронної пошти нових облікових запиÑів за замовчуваннÑм. -default_allow_create_organization=Дозволити ÑÑ‚Ð²Ð¾Ñ€ÐµÐ½Ð½Ñ Ð¾Ñ€Ð³Ð°Ð½Ñ–Ð·Ð°Ñ†Ñ–Ð¹ за замовчуваннÑм -default_allow_create_organization_popup=Дозволити новим обліковим запиÑам кориÑтувачів Ñтворювати організації за замовчуваннÑм. -default_enable_timetracking=Увімкнути відÑÑ‚ÐµÐ¶ÐµÐ½Ð½Ñ Ñ‡Ð°Ñу за замовчуваннÑм -default_enable_timetracking_popup=Включити відÑÑ‚ÐµÐ¶ÐµÐ½Ð½Ñ Ñ‡Ð°Ñу Ð´Ð»Ñ Ð½Ð¾Ð²Ð¸Ñ… репозиторіїв за замовчуваннÑм. +invalid_db_setting=ÐÐ°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ð±Ð°Ð·Ð¸ даних недійÑні: %v +invalid_db_table=База даних таблиці "%s" Ñ” недійÑною: %v +invalid_repo_path=Кореневий шлÑÑ… до Ñховища невірний: %v +invalid_app_data_path=ШлÑÑ… до даних додатка невірний: %v +run_user_not_match=Ім'Ñ ÐºÐ¾Ñ€Ð¸Ñтувача “Виконати Ñк†не Ñ” поточним ім'Ñм кориÑтувача: %s -> %s +internal_token_failed=Ðе вдалоÑÑ Ñтворити внутрішній токен: %v +secret_key_failed=Ðе вдалоÑÑ Ñтворити Ñекретний ключ: %v +save_config_failed=Ðе вдалоÑÑ Ð·Ð±ÐµÑ€ÐµÐ³Ñ‚Ð¸ конфігурацію: %v +invalid_admin_setting=ÐÐ°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ð¾Ð±Ð»Ñ–ÐºÐ¾Ð²Ð¾Ð³Ð¾ запиÑу адмініÑтратора Ñ” недійÑним: %v +invalid_log_root_path=Ðеправильний шлÑÑ… до журналу: %v +default_keep_email_private=Типово приховувати адреÑи електронної пошти +default_keep_email_private_popup=Типово приховувати адреÑи електронної пошти нових облікових запиÑів. +default_allow_create_organization=За замовчуваннÑм дозволити ÑÑ‚Ð²Ð¾Ñ€ÐµÐ½Ð½Ñ Ð¾Ñ€Ð³Ð°Ð½Ñ–Ð·Ð°Ñ†Ñ–Ð¹ +default_allow_create_organization_popup=За замовчуваннÑм дозволити новим кориÑтувачам Ñтворювати організації. +default_enable_timetracking=За замовчуваннÑм увімкнути відÑÑ‚ÐµÐ¶ÐµÐ½Ð½Ñ Ñ‡Ð°Ñу +default_enable_timetracking_popup=Увімкнути відÑÑ‚ÐµÐ¶ÐµÐ½Ð½Ñ Ñ‡Ð°Ñу Ð´Ð»Ñ Ð½Ð¾Ð²Ð¸Ñ… Ñховищ за замовчуваннÑм. no_reply_address=Прихований поштовий домен -no_reply_address_helper=Доменне ім'Ñ Ð´Ð»Ñ ÐºÐ¾Ñ€Ð¸Ñтувачів із прихованою електронною адреÑою. Ðаприклад, ім'Ñ ÐºÐ¾Ñ€Ð¸Ñтувача 'joe' буде входити в Git Ñк 'joe@noreply.example.org', Ñкщо Ð´Ð»Ñ Ð¿Ñ€Ð¸Ñ…Ð¾Ð²Ð°Ð½Ð¾Ð³Ð¾ домену електронної пошти вÑтановлено 'noreply.example.org'. +no_reply_address_helper=Доменне ім'Ñ Ð´Ð»Ñ ÐºÐ¾Ñ€Ð¸Ñтувачів із прихованою електронною адреÑою. Ðаприклад, ім'Ñ ÐºÐ¾Ñ€Ð¸Ñтувача 'Joe' буде зображатиÑÑ Ð² Git Ñк 'joe@noreply.example.org', Ñкщо прихований домен електронної пошти вÑтановлено 'noreply.example.org'. password_algorithm=Ðлгоритм Ñ…ÐµÑˆÑƒÐ²Ð°Ð½Ð½Ñ Ð¿Ð°Ñ€Ð¾Ð»Ñ invalid_password_algorithm=ÐедійÑний хеш-алгоритм Ð¿Ð°Ñ€Ð¾Ð»Ñ enable_update_checker=Увімкнути перевірку оновлень @@ -340,35 +338,35 @@ config_write_file_prompt=Ці параметри будуть запиÑані Ð [home] nav_menu=Меню навігації -uname_holder=Ім'Ñ ÐºÐ¾Ñ€Ð¸Ñтувача або Ел. пошта +uname_holder=Ім'Ñ ÐºÐ¾Ñ€Ð¸Ñтувача або адреÑа електронної пошти password_holder=Пароль switch_dashboard_context=Переключити контекÑÑ‚ панелі ÑƒÐ¿Ñ€Ð°Ð²Ð»Ñ–Ð½Ð½Ñ -my_repos=Репозиторії -show_more_repos=Показати більше репозиторіїв… -collaborative_repos=Спільні репозиторії +my_repos=Сховища +show_more_repos=Показати більше Ñховищ… +collaborative_repos=Спільні Ñховища my_orgs=Мої організації my_mirrors=Мої дзеркала view_home=ПереглÑнути %s filter=Інші фільтри -filter_by_team_repositories=Фільтрувати за репозиторіÑми команд +filter_by_team_repositories=Фільтрувати за Ñховищами команд feed_of=`Стрічка "%s"` show_archived=Ðрхівовані -show_both_archived_unarchived=Показано архівовані Ñ– не архівовані +show_both_archived_unarchived=Показано архівовані Ñ– неархівовані show_only_archived=Показано тільки архівовані -show_only_unarchived=Показано тільки не архівовані +show_only_unarchived=Показано тільки неархівовані show_private=Приватні show_both_private_public=Показано публічні та приватні show_only_private=Показано тільки приватні show_only_public=Показано тільки публічні -issues.in_your_repos=Ð’ ваших репозиторіÑÑ… +issues.in_your_repos=У ваших Ñховищах guide_title=Жодної активноÑті [explore] -repos=Репозиторії +repos=Сховища users=КориÑтувачі organizations=Організації code=Код @@ -376,100 +374,100 @@ code_last_indexed_at=ОÑтанні індекÑовані %s [auth] create_new_account=РеєÑÑ‚Ñ€Ð°Ñ†Ñ–Ñ Ð¾Ð±Ð»Ñ–ÐºÐ¾Ð²Ð¾Ð³Ð¾ запиÑу -disable_register_prompt=Вибачте, можливіÑть реєÑтрації відключена. Будь лаÑка, зв'ÑжітьÑÑ Ð· адмініÑтратором Ñайту. +disable_register_prompt=РеєÑтрацію вимкнено. Будь лаÑка, зв'ÑжітьÑÑ Ð· адмініÑтратором Ñайту. disable_register_mail=ÐŸÑ–Ð´Ñ‚Ð²ÐµÑ€Ð´Ð¶ÐµÐ½Ð½Ñ Ñ€ÐµÑ”Ñтрації електронною поштою вимкнено. remember_me=Запам’Ñтати цей приÑтрій forgot_password_title=Забув пароль forgot_password=Забули пароль? -must_change_password=Оновіть Ñвій пароль -allow_password_change=Вимагати в кориÑтувача змінити пароль (рекомендуєтьÑÑ) -reset_password_mail_sent_prompt=Електронний лиÑÑ‚ із підтвердженнÑм надіÑлано <b>%s</b>. Перевірте папку 'Вхідні' в межах наÑтупних %s, щоб завершити Ð¿Ñ€Ð¾Ñ†ÐµÑ Ð²Ñ–Ð´Ð½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ Ð¾Ð±Ð»Ñ–ÐºÐ¾Ð²Ð¾Ð³Ð¾ запиÑу. +must_change_password=Оновити пароль +allow_password_change=Вимагати від кориÑтувача змінити пароль (рекомендовано) +reset_password_mail_sent_prompt=Ðа адреÑу <b>%s</b> було надіÑлано лиÑÑ‚ із підтвердженнÑм. Будь лаÑка, перевірте Ñвою поштову Ñкриньку протÑгом наÑтупних %s, щоб завершити Ð¿Ñ€Ð¾Ñ†ÐµÑ Ð²Ñ–Ð´Ð½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ Ð¾Ð±Ð»Ñ–ÐºÐ¾Ð²Ð¾Ð³Ð¾ запиÑу. active_your_account=Ðктивувати обліковий Ð·Ð°Ð¿Ð¸Ñ account_activated=Обліковий Ð·Ð°Ð¿Ð¸Ñ Ð°ÐºÑ‚Ð¸Ð²Ð¾Ð²Ð°Ð½Ð¾ -prohibit_login=Вхід заборонений -resent_limit_prompt=Вибачте, ви вже запроÑили активацію по електронній пошті нещодавно. Будь лаÑка, зачекайте 3 хвилини, а потім Ñпробуйте ще раз. -has_unconfirmed_mail=Привіт %s, у Ð²Ð°Ñ Ñ” непідтверджена електронна адреÑа (<b>%s </b>). Якщо ви не отримали електронний лиÑÑ‚ із підтвердженнÑм або вам потрібно надіÑлати новий, натиÑніть на кнопку нижче. -resend_mail=ÐатиÑніть тут, щоб виÑлати лиÑÑ‚ активації знову -email_not_associate=Ð¦Ñ ÐµÐ»ÐµÐºÑ‚Ñ€Ð¾Ð½Ð½Ð° пошта не пов'Ñзана ні з одним обліковим запиÑом. -send_reset_mail=ÐадіÑлати електронний лиÑÑ‚ Ð´Ð»Ñ Ð²Ñ–Ð´Ð½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ Ð¾Ð±Ð»Ñ–ÐºÐ¾Ð²Ð¾Ð³Ð¾ запиÑу +prohibit_login=Вхід заборонено +resent_limit_prompt=Ви вже надÑилали запит на активацію нещодавно. Зачекайте 3 хвилини Ñ– Ñпробуйте ще раз. +has_unconfirmed_mail= +Привіт %s, у Ð²Ð°Ñ Ð½ÐµÐ¿Ñ–Ð´Ñ‚Ð²ÐµÑ€Ð´Ð¶ÐµÐ½Ð° адреÑа електронної пошти (<b>%s</b>). Якщо ви не отримали лиÑта з підтвердженнÑм або вам потрібно надіÑлати новий, будь лаÑка, натиÑніть кнопку нижче. +resend_mail=ÐатиÑніть тут, щоб повторно надіÑлати лиÑÑ‚ з активацією +email_not_associate=Ð¦Ñ Ð°Ð´Ñ€ÐµÑа електронної пошти не пов'Ñзана з жодним обліковим запиÑом. +send_reset_mail=ÐадіÑлати лиÑÑ‚ Ð´Ð»Ñ Ð²Ñ–Ð´Ð½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ Ð¾Ð±Ð»Ñ–ÐºÐ¾Ð²Ð¾Ð³Ð¾ запиÑу reset_password=Ð’Ñ–Ð´Ð½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ Ð¾Ð±Ð»Ñ–ÐºÐ¾Ð²Ð¾Ð³Ð¾ запиÑу -invalid_code=Цей код Ð¿Ñ–Ð´Ñ‚Ð²ÐµÑ€Ð´Ð¶ÐµÐ½Ð½Ñ Ð½ÐµÐ´Ñ–Ð¹Ñний або закінчивÑÑ. +invalid_code=Ваш код Ð¿Ñ–Ð´Ñ‚Ð²ÐµÑ€Ð´Ð¶ÐµÐ½Ð½Ñ Ð½ÐµÐ´Ñ–Ð¹Ñний або його термін дії закінчивÑÑ. reset_password_helper=Відновити обліковий Ð·Ð°Ð¿Ð¸Ñ password_too_short=Довжина Ð¿Ð°Ñ€Ð¾Ð»Ñ Ð½Ðµ може бути меншою за %d Ñимволів. -non_local_account=Ðелокальні акаунти не можуть змінити пароль через Gitea. +non_local_account=Ðелокальні кориÑтувачі не можуть оновити Ñвій пароль через Ð²ÐµÐ±Ñ–Ð½Ñ‚ÐµÑ€Ñ„ÐµÐ¹Ñ Gitea. verify=Підтвердити scratch_code=Одноразовий пароль -use_scratch_code=ВикориÑтовувати одноразовий пароль -twofa_scratch_used=Ви викориÑтовували одноразовий пароль. Ви були перенаправлені на Ñторінку налаштувань Ð´Ð»Ñ Ð³ÐµÐ½ÐµÑ€Ð°Ñ†Ñ–Ñ— нового коду або Ð²Ñ–Ð´ÐºÐ»ÑŽÑ‡ÐµÐ½Ð½Ñ Ð´Ð²ÑƒÑ„Ð°ÐºÑ‚Ð¾Ñ€Ð½Ð¾Ñ— автентифікації. -twofa_passcode_incorrect=Ваш пароль Ñ” невірним. Якщо ви втратили приÑтрій, викориÑтовуйте ваш одноразовий пароль. +use_scratch_code=СкориÑтатиÑÑŒ одноразовим паролем +twofa_scratch_used=Ви ÑкориÑталиÑÑ Ð¾Ð´Ð½Ð¾Ñ€Ð°Ð·Ð¾Ð²Ð¸Ð¼ паролем. Ð’Ð°Ñ Ð¿ÐµÑ€ÐµÐ½Ð°Ð¿Ñ€Ð°Ð²Ð»ÐµÐ½Ð¾ на Ñторінку налаштувань двофакторної автентифікації, щоб видалити приÑтрій або згенерувати новий одноразовий пароль. +twofa_passcode_incorrect=Ваш пароль неправильний. Якщо ви загубили Ñвій приÑтрій, ÑкориÑтайтеÑÑ Ð¾Ð´Ð½Ð¾Ñ€Ð°Ð·Ð¾Ð²Ð¸Ð¼ паролем. twofa_scratch_token_incorrect=Ðевірний одноразовий пароль. login_userpass=Увійти login_openid=OpenID oauth_signup_tab=ЗареєÑтрувати обліковий Ð·Ð°Ð¿Ð¸Ñ -oauth_signup_title=Повний новий обліковий Ð·Ð°Ð¿Ð¸Ñ -oauth_signup_submit=Повний обліковий Ð·Ð°Ð¿Ð¸Ñ -oauth_signin_tab=ПоÑÐ¸Ð»Ð°Ð½Ð½Ñ Ð½Ð° Ñ–Ñнуючий обліковий Ð·Ð°Ð¿Ð¸Ñ +oauth_signup_title=Завершити реєÑтрацію облікового запиÑу +oauth_signup_submit=Поповнити обліковий Ð·Ð°Ð¿Ð¸Ñ +oauth_signin_tab=Прив'Ñзати до Ñ–Ñнуючого облікового запиÑу oauth_signin_title=Увійдіть щоб авторизувати пов'Ñзаний обліковий Ð·Ð°Ð¿Ð¸Ñ oauth_signin_submit=Прив'Ñзати обліковий Ð·Ð°Ð¿Ð¸Ñ openid_connect_submit=Під’єднатиÑÑ openid_connect_title=ПідключитиÑÑ Ð´Ð¾ Ñ–Ñнуючого облікового запиÑу -openid_connect_desc=Вибраний OpenID URI невідомий. Пов'Ñжіть його з новим обліковим запиÑом тут. +openid_connect_desc=Обраний OpenID URI невідомий. Зв'Ñжіть його тут з новим обліковим запиÑом. openid_register_title=Створити новий обліковий Ð·Ð°Ð¿Ð¸Ñ -openid_register_desc=Вибраний OpenID URI невідомий. Пов'Ñжіть йогоз новим обліковим запиÑом тут. +openid_register_desc=Обраний OpenID URI невідомий. Зв'Ñжіть його тут з новим обліковим запиÑом. disable_forgot_password_mail=Ð’Ñ–Ð´Ð½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ Ð¾Ð±Ð»Ñ–ÐºÐ¾Ð²Ð¾Ð³Ð¾ запиÑу вимкнено, оÑкільки не налаштована електронна пошта. Будь лаÑка, зв'ÑжітьÑÑ Ð· адмініÑтратором Ñайту. -disable_forgot_password_mail_admin=Ð’Ñ–Ð´Ð½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ Ð¾Ð±Ð»Ñ–ÐºÐ¾Ð²Ð¾Ð³Ð¾ запиÑу доÑтупне лише піÑÐ»Ñ Ð½Ð°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ ÐµÐ»ÐµÐºÑ‚Ñ€Ð¾Ð½Ð½Ð¾Ñ— пошти. Будь лаÑка, налаштуйте ел. пошту Ð´Ð»Ñ Ð²Ñ–Ð´Ð½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ Ð¾Ð±Ð»Ñ–ÐºÐ¾Ð²Ð¾Ð³Ð¾ запиÑу. -email_domain_blacklisted=З вказаним email реєÑÑ‚Ñ€Ð°Ñ†Ñ–Ñ Ð½ÐµÐ¼Ð¾Ð¶Ð»Ð¸Ð²Ð°. +disable_forgot_password_mail_admin=Ð’Ñ–Ð´Ð½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ Ð¾Ð±Ð»Ñ–ÐºÐ¾Ð²Ð¾Ð³Ð¾ запиÑу доÑтупне лише за наÑвноÑті електронної пошти. Будь лаÑка, налаштуйте електронну пошту, щоб увімкнути Ð²Ñ–Ð´Ð½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ Ð¾Ð±Ð»Ñ–ÐºÐ¾Ð²Ð¾Ð³Ð¾ запиÑу. +email_domain_blacklisted=Ви не можете зареєÑтруватиÑÑ Ð· адреÑою електронної пошти. authorize_application=Ðвторизувати програму authorize_redirect_notice=Ð’Ð°Ñ Ð±ÑƒÐ´Ðµ переадреÑовано до %s, Ñкщо ви авторизуєте цю програму. authorize_application_created_by=Ð¦Ñ Ð¿Ñ€Ð¾Ð³Ñ€Ð°Ð¼Ð° Ñтворена %s. -authorize_application_description=Якщо ви надаÑте цей доÑтуп, то він матиме доÑтуп до вÑÑ–Ñ… ваших даних облікового запиÑу, включаючи приватні репозиторії та організації. -authorize_title=Ðвторизуйвати "%s" Ð´Ð»Ñ Ð´Ð¾Ñтупу до вашого облікового запиÑу? +authorize_application_description=Якщо ви авторизуєте цю програму, їй буде надано дозвіл на Ñ€ÐµÐ´Ð°Ð³ÑƒÐ²Ð°Ð½Ð½Ñ Ð°Ð±Ð¾ Ñ‡Ð¸Ñ‚Ð°Ð½Ð½Ñ Ð²Ñієї інформації вашого облікового запиÑу, включно з приватними Ñховищами та організаціÑми. +authorize_title=Ðвторизувати "%s" Ð´Ð»Ñ Ð´Ð¾Ñтупу до вашого облікового запиÑу? authorization_failed=Помилка авторизації -sspi_auth_failed=Помилка SSPI-автентифікації +sspi_auth_failed=Помилка автентифікації SSPI password_pwned_err=Ðе вдалоÑÑ Ð²Ð¸ÐºÐ¾Ð½Ð°Ñ‚Ð¸ запит до HaveIBeenPwed [mail] view_it_on=ПереглÑнути на %s reply=або надішліть відповідь безпоÑередньо на цей електронний лиÑÑ‚ -link_not_working_do_paste=Ðе працює? Спробуйте Ñкопіювати та вÑтавити його в Ñвій браузер. +link_not_working_do_paste=Ðе працює? Спробуйте Ñкопіювати та вÑтавити його у браузер. hi_user_x=Привіт <b>%s</b>, activate_account=Будь лаÑка, активуйте ваш обліковий Ð·Ð°Ð¿Ð¸Ñ activate_account.title=%s, будь лаÑка, активуйте Ñвій обліковий Ð·Ð°Ð¿Ð¸Ñ activate_account.text_1=Привіт, <b>%[1]s</b>, дÑкуємо за реєÑтрацію на %[2]s! -activate_account.text_2=Перейдіть за цим поÑиланнÑм, щоб активувати ваш обліковий Ð·Ð°Ð¿Ð¸Ñ Ð² <b>%s</b>: +activate_account.text_2=Будь лаÑка, перейдіть за наÑтупним поÑиланнÑм, щоб активувати Ñвій обліковий Ð·Ð°Ð¿Ð¸Ñ Ð¿Ñ€Ð¾Ñ‚Ñгом <b>%s</b>: -activate_email=Підтвердить вашу адреÑу електронної пошти +activate_email=Підтвердіть адреÑу електронної пошти activate_email.title=%s, будь лаÑка, підтвердіть вашу адреÑу електронної пошти -activate_email.text=Перейдіть за цим поÑиланнÑм, щоб підтвердити вашу електронну адреÑу в <b>%s</b>: +activate_email.text=Будь лаÑка, перейдіть за наÑтупним поÑиланнÑм протÑгом <b>%s</b>, щоб підтвердити Ñвою електронну адреÑу: register_notify.title=%[1]s, лаÑкаво проÑимо до %[2]s -register_notify.text_1=це ваша е-пошта Ð´Ð»Ñ Ð¿Ñ–Ð´Ñ‚Ð²ÐµÑ€Ð´Ð¶ÐµÐ½Ð½Ñ Ñ€ÐµÑ”Ñтрації Ð´Ð»Ñ %s! +register_notify.text_1=це лиÑÑ‚ з підтвердженнÑм реєÑтрації на %s! register_notify.text_2=Тепер ви можете увійти Ñк: %s. -register_notify.text_3=Якщо цей обліковий Ð·Ð°Ð¿Ð¸Ñ Ð±ÑƒÐ»Ð¾ Ñтворено Ð´Ð»Ñ Ð²Ð°Ñ, будь лаÑка, Ñпочатку <a href="%s">вÑтановіть Ñвій пароль</a>. +register_notify.text_3=Якщо цей обліковий Ð·Ð°Ð¿Ð¸Ñ Ñтворено Ð´Ð»Ñ Ð²Ð°Ñ, будь лаÑка, Ñпершу <a href="%s">вÑтановіть пароль</a>. -reset_password=Ð’Ñ–Ð´Ð½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ Ð²Ð°ÑˆÐ¾Ð³Ð¾ облікового запиÑу -reset_password.title=%s, ви відправили запит на Ð²Ñ–Ð´Ð½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ Ð¾Ð±Ð»Ñ–ÐºÐ¾Ð²Ð¾Ð³Ð¾ запиÑу -reset_password.text=Перейдіть за цим поÑиланнÑм, щоб відновити ваш обліковий Ð·Ð°Ð¿Ð¸Ñ Ð² <b>%s</b>: +reset_password=Відновити обліковий Ð·Ð°Ð¿Ð¸Ñ +reset_password.title=%s, ви надіÑлали запит на Ð²Ñ–Ð´Ð½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ Ð¾Ð±Ð»Ñ–ÐºÐ¾Ð²Ð¾Ð³Ð¾ запиÑу +reset_password.text=Щоб відновити обліковий запиÑ, перейдіть за наÑтупним поÑиланнÑм протÑгом <b>%s</b>: register_success=РеєÑÑ‚Ñ€Ð°Ñ†Ñ–Ñ ÑƒÑпішна -issue_assigned.pull=@%[1]s призначив вам запит Ð·Ð»Ð¸Ñ‚Ñ‚Ñ %[2]s в репозиторії %[3]s. -issue_assigned.issue=@%[1]s призначив вам задачу %[2]s у репозиторії %[3]s. +issue_assigned.pull=@%[1]s призначив вам запит на Ð·Ð»Ð¸Ñ‚Ñ‚Ñ %[2]s в Ñховищі %[3]s. +issue_assigned.issue=@%[1]s призначив вам задачу %[2]s в Ñховищі %[3]s. issue.x_mentioned_you=<b>@%s</b> згадав ваÑ: -issue.action.force_push=<b>%[1]s</b> force-pushed <b>%[2]s</b> з %[3]s в %[4]s. -issue.action.push_1=<b>@%[1]s</b> надіÑлав %[3]d коміти %[2]s -issue.action.push_n=<b>@%[1]s</b> відправив %[3]d коміти до %[2]s -issue.action.close=<b>@%[1]s</b> закрито #%[2]d. +issue.action.push_1=<b>@%[1]s</b> надіÑлав %[3]d коміт в %[2]s +issue.action.push_n=<b>@%[1]s</b> надіÑлав %[3]d коміти до %[2]s +issue.action.close=<b>@%[1]s</b> закрив #%[2]d. issue.action.reopen=<b>@%[1]s</b> заново відкрив #%[2]d. issue.action.merge=<b>@%[1]s</b> об'єднав #%[2]d до %[3]s. -issue.action.approve=<b>@%[1]s</b> затвердили цей запит на злиттÑ. -issue.action.reject=<b>@%[1]s</b> запитують зміни на цей запит на злиттÑ. -issue.action.review=<b>@%[1]s</b> прокоментували цей запит на злиттÑ. -issue.action.review_dismissed=<b>@%[1]s</b> відхилено оÑтанній відгук від %[2]s Ð´Ð»Ñ Ñ†ÑŒÐ¾Ð³Ð¾ запиту на злиттÑ. -issue.action.ready_for_review=<b>@%[1]s</b> позначили цей запит на Ð·Ð»Ð¸Ñ‚Ñ‚Ñ Ñк готовий до розглÑду. -issue.action.new=<b>@%[1]s</b> Ñтворили #%[2]d. +issue.action.approve=<b>@%[1]s</b> затвердив цей запит на злиттÑ. +issue.action.reject=<b>@%[1]s</b> запроÑив зміни у цьому запиті на злиттÑ. +issue.action.review=<b>@%[1]s</b> прокоментував цей запит на злиттÑ. +issue.action.review_dismissed=<b>@%[1]s</b> відхилив оÑтанній відгук від %[2]s на цей запит на злиттÑ. +issue.action.ready_for_review=<b>@%[1]s</b> позначив цей запит на Ð·Ð»Ð¸Ñ‚Ñ‚Ñ Ñк готовий до розглÑду. +issue.action.new=<b>@%[1]s</b> Ñтворив #%[2]d. issue.in_tree_path=Ð’ %s: release.new.subject=%s в %s випущено @@ -480,13 +478,13 @@ release.downloads=ЗвантаженнÑ: release.download.zip=Вихідний код (ZIP) release.download.targz=Вихідний код (TAR.GZ) -repo.transfer.subject_to=%s бажає передати"%s" в %s -repo.transfer.subject_to_you=%s бажає передати"%s" вам +repo.transfer.subject_to=%s хоче перенеÑти "%s" в %s +repo.transfer.subject_to_you=%s хоче передати"%s" вам repo.transfer.to_you=вам repo.transfer.body=Щоб прийнÑти або відхилити перейдіть до %s або проÑто ігноруйте. repo.collaborator.added.subject=%s додав Ð²Ð°Ñ Ð´Ð¾ %s -repo.collaborator.added.text=Ви були додані в ÑкоÑті Ñпівавтора репозиторію: +repo.collaborator.added.text=Ð’Ð°Ñ Ð´Ð¾Ð´Ð°Ð»Ð¸ Ñк Ñпівавтора до Ñховища: team_invite.subject=%[1]s запрошує Ð²Ð°Ñ Ð¿Ñ€Ð¸Ñ”Ð´Ð½Ð°Ñ‚Ð¸ÑÑ Ð´Ð¾ організації %[2]s team_invite.text_1=%[1]s запрошує Ð²Ð°Ñ Ð´Ð¾ команди %[2]s в організації %[3]s. @@ -497,22 +495,22 @@ yes=Так no=ÐÑ– confirm=Підтвердити cancel=Відмінити -modify=ÐžÐ½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ +modify=Оновити [form] UserName=Ð†Ð¼â€™Ñ ÐºÐ¾Ñ€Ð¸Ñтувача -RepoName=Ðазва репозиторію +RepoName=Ðазва Ñховища Email=ÐдреÑа електронної пошти Password=Пароль -Retype=ÐŸÑ–Ð´Ñ‚Ð²ÐµÑ€Ð´Ð¶ÐµÐ½Ð½Ñ Ð¿Ð°Ñ€Ð¾Ð»Ñ -SSHTitle=Iм'Ñ SSH ключа +Retype=Підтвердити пароль +SSHTitle=Ðазва ключа SSH HttpsUrl=ÐдреÑа HTTPS PayloadUrl=URL обробника TeamName=Ðазва команди AuthName=Ðазва авторизації -AdminEmail=Email адмініÑтратора +AdminEmail=ÐдреÑа електронної пошти адмініÑтратора -NewBranchName=Ім'Ñ Ð½Ð¾Ð²Ð¾Ñ— гілки +NewBranchName=Ðазва нової гілки CommitSummary=Резюме коміту CommitMessage=ÐŸÐ¾Ð²Ñ–Ð´Ð¾Ð¼Ð»ÐµÐ½Ð½Ñ ÐºÐ¾Ð¼Ñ–Ñ‚Ñƒ CommitChoice=Вибір коміта diff --git a/options/locale/locale_zh-CN.ini b/options/locale/locale_zh-CN.ini index 285ce7666f..1a07c2f4c0 100644 --- a/options/locale/locale_zh-CN.ini +++ b/options/locale/locale_zh-CN.ini @@ -4,14 +4,14 @@ explore=探索 help=帮助 logo=å¾½æ ‡ sign_in=登录 -sign_in_with_provider=使用 %s 登录 +sign_in_with_provider=使用「%sã€ç™»å½• sign_in_or=或 sign_out=退出 sign_up=注册 link_account=链接账户 register=注册 -version=当å‰ç‰ˆæœ¬ -powered_by=Powered by %s +version=版本 +powered_by=ç”± %s 强力驱动 page=é¡µé¢ template=æ¨¡æ¿ language=è¯è¨€é€‰é¡¹ @@ -28,7 +28,7 @@ return_to_gitea=返回 Gitea more_items=更多选项 username=用户å -email=电åé‚®ä»¶åœ°å€ +email=é‚®ç®±åœ°å€ password=密ç access_token=访问令牌(Access Token) re_type=确认密ç @@ -42,7 +42,7 @@ webauthn_sign_in=按下安全密钥上的按钮。如果安全密钥没有按钮 webauthn_press_button=请按下安全密钥上的按钮… webauthn_use_twofa=使用æ¥è‡ªæ‰‹æœºä¸çš„两æ¥éªŒè¯ç webauthn_error=æ— æ³•è¯»å–安全密钥。 -webauthn_unsupported_browser=ä½ çš„æµè§ˆå™¨ç›®å‰ä¸æ”¯æŒ WebAuthn。 +webauthn_unsupported_browser=您的æµè§ˆå™¨ç›®å‰ä¸æ”¯æŒ WebAuthn。 webauthn_error_unknown=å‘生未知错误。请é‡è¯•。 webauthn_error_insecure=WebAuthn 仅支æŒå®‰å…¨è¿žæŽ¥ã€‚如果è¦åœ¨ HTTP å议上进行测试,请使用 "localhost" 或 "127.0.0.1" ä½œä¸ºè®¿é—®æ¥æº webauthn_error_unable_to_process=æœåŠ¡å™¨æ— æ³•å¤„ç†æ‚¨çš„请求。 @@ -58,11 +58,11 @@ issue_milestone=里程碑 new_repo=创建仓库 new_migrate=è¿ç§»å¤–部仓库 new_mirror=åˆ›å»ºæ–°çš„é•œåƒ -new_fork=新的仓库Fork +new_fork=派生新仓库 new_org=创建组织 new_project=创建项目 new_project_column=创建列 -manage_org=ç®¡ç†æˆ‘的组织 +manage_org=管ç†ç»„织 admin_panel=管ç†åŽå° account_settings=叿ˆ·è®¾ç½® settings=设置 @@ -78,7 +78,7 @@ forks=派生 activities=最近活动 pull_requests=åˆå¹¶è¯·æ±‚ -issues=å·¥å•ç®¡ç† +issues=å·¥å• milestones=里程碑 ok=确定 @@ -91,7 +91,7 @@ add=æ·»åŠ add_all=æ·»åŠ æ‰€æœ‰ remove=移除 remove_all=移除所有 -remove_label_str=`åˆ é™¤æ ‡ç¾ "%s"` +remove_label_str=åˆ é™¤æ ‡ç¾ã€Œ%s〠edit=编辑 view=查看 test=测试 @@ -129,9 +129,9 @@ rss_feed=RSS è®¢é˜…æº pin=固定 unpin=å–æ¶ˆç½®é¡¶ -artifacts=åˆ¶å“ +artifacts=产物 expired=已过期 -confirm_delete_artifact=您确定è¦åˆ 除制å“'%s'å—? +confirm_delete_artifact=您确定è¦åˆ 除产物「%sã€å—? archived=已归档 @@ -165,7 +165,7 @@ filter.public=公开 filter.private=ç§æœ‰ no_results_found=未找到结果 -internal_error_skipped=å‘生内部错误,但已被跳过: %s +internal_error_skipped=å‘生内部错误,但已跳过: %s [search] search=æœç´¢... @@ -184,14 +184,14 @@ org_kind=æœç´¢ç»„织... team_kind=æœç´¢å›¢é˜Ÿ... code_kind=æœç´¢ä»£ç ... code_search_unavailable=ä»£ç æœç´¢å½“å‰ä¸å¯ç”¨ã€‚请与网站管ç†å‘˜è”系。 -code_search_by_git_grep=当å‰ä»£ç æœç´¢ç»“果由“git grepâ€æä¾›ã€‚å¦‚æžœç«™ç‚¹ç®¡ç†å‘˜å¯ç”¨ä»“库索引器,å¯èƒ½ä¼šæœ‰æ›´å¥½çš„结果。 +code_search_by_git_grep=当å‰ä»£ç æœç´¢ç»“果由「git grepã€æä¾›ã€‚å¦‚æžœç«™ç‚¹ç®¡ç†å‘˜å¯ç”¨ä»“库索引器,å¯èƒ½ä¼šæœ‰æ›´å¥½çš„结果。 package_kind=æœç´¢è½¯ä»¶åŒ…... project_kind=æœç´¢é¡¹ç›®... branch_kind=æœç´¢åˆ†æ”¯... tag_kind=æœç´¢æ ‡ç¾... -tag_tooltip=æœç´¢åŒ¹é…çš„æ ‡ç¾ã€‚使用“%â€æ¥åŒ¹é…任何åºåˆ—çš„æ•°å— +tag_tooltip=æœç´¢åŒ¹é…çš„æ ‡ç¾ã€‚使用「%ã€æ¥åŒ¹é…任何åºåˆ—的数å—。 commit_kind=æœç´¢æäº¤è®°å½•... -runner_kind=æœç´¢runners... +runner_kind=æœç´¢è¿è¡Œå™¨... no_results=未找到匹é…结果 issue_kind=æœç´¢å·¥å•... pull_kind=æœç´¢åˆå¹¶è¯·æ±‚... @@ -268,14 +268,14 @@ ssl_mode=SSL path=æ•°æ®åº“文件路径 sqlite_helper=SQLite3 æ•°æ®åº“的文件路径。<br>如果以æœåŠ¡çš„æ–¹å¼è¿è¡Œ Gitea,请输入ç»å¯¹è·¯å¾„。 reinstall_error=您æ£åœ¨å°è¯•å®‰è£…åˆ°ä¸€ä¸ªå·²ç»æœ‰ Gitea æ•°æ®çš„æ•°æ®åº“ä¸ -reinstall_confirm_message=使用现有的 Gitea æ•°æ®åº“釿–°å®‰è£…å¯èƒ½ä¼šå¯¼è‡´å¤šä¸ªé—®é¢˜ã€‚åœ¨å¤§å¤šæ•°æƒ…å†µä¸‹ï¼Œä½ åº”è¯¥ä½¿ç”¨ä½ çŽ°æœ‰çš„ “app.ini†æ¥è¿è¡Œ Giteaã€‚å¦‚æžœä½ çŸ¥é“自己在åšä»€ä¹ˆï¼Œè¯·ç¡®è®¤ä»¥ä¸‹å†…容: +reinstall_confirm_message=使用现有的 Gitea æ•°æ®åº“釿–°å®‰è£…å¯èƒ½ä¼šå¯¼è‡´å¤šä¸ªé—®é¢˜ã€‚在大多数情况下,您应该使用您现有的「app.iniã€æ¥è¿è¡Œ Gitea。如果您知é“自己在åšä»€ä¹ˆï¼Œè¯·ç¡®è®¤ä»¥ä¸‹å†…容: reinstall_confirm_check_1=使用 app.ini ä¸ SECRET KEY åŠ å¯†çš„æ•°æ®å¯èƒ½ä¼šä¸¢å¤±ï¼šç”¨æˆ·å¯èƒ½æ— 法使用 2FA/OTP 登录,仓库镜åƒå¯èƒ½æ— 法æ£å¸¸å·¥ä½œã€‚å‹¾é€‰æ¤æ¡†ï¼Œè¡¨ç¤ºæ‚¨ç¡®è®¤å½“å‰ app.ini æ–‡ä»¶åŒ…å«æ£ç¡®çš„ SECRET KEY。 reinstall_confirm_check_2=代ç 仓库和设置å¯èƒ½éœ€è¦é‡æ–°åŒæ¥ã€‚å‹¾é€‰æ¤æ¡†ï¼Œè¡¨ç¤ºæ‚¨ç¡®è®¤å°†æ‰‹åЍ釿–°åŒæ¥ä»“库和 SSH authorized_keys 的钩å。您确认您将确ä¿ä»£ç 仓库和镜åƒè®¾ç½®æ˜¯æ£ç¡®çš„。 -reinstall_confirm_check_3=ä½ ç¡®è®¤ä½ ç»å¯¹è‚¯å®šè¿™ä¸ª Gitea 在æ£ç¡®çš„ app.ini ä½ç½®ä¸Šè¿è¡Œï¼Œè€Œä¸”ä½ ç¡®å®šä½ å¿…é¡»é‡æ–°å®‰è£…ã€‚ä½ ç¡®è®¤ä½ çŸ¥æ™“ä¸Šè¿°é£Žé™©ã€‚ +reinstall_confirm_check_3=您确认您ç»å¯¹è‚¯å®šè¿™ä¸ª Gitea 在æ£ç¡®çš„ app.ini ä½ç½®ä¸Šè¿è¡Œï¼Œè€Œä¸”æ‚¨ç¡®å®šæ‚¨å¿…é¡»é‡æ–°å®‰è£…。您确认您知晓上述风险。 err_empty_db_path=SQLite æ•°æ®åº“文件路径ä¸èƒ½ä¸ºç©ºã€‚ no_admin_and_disable_registration=您ä¸èƒ½å¤Ÿåœ¨æœªåˆ›å»ºç®¡ç†å‘˜ç”¨æˆ·çš„æƒ…å†µä¸‹ç¦æ¢æ³¨å†Œã€‚ err_empty_admin_password=管ç†å‘˜å¯†ç ä¸èƒ½ä¸ºç©ºã€‚ -err_empty_admin_email=管ç†å‘˜ç”µå邮件ä¸èƒ½ä¸ºç©ºã€‚ +err_empty_admin_email=管ç†å‘˜é‚®ç®±ä¸èƒ½ä¸ºç©ºã€‚ err_admin_name_is_reserved=管ç†å‘˜ç”¨æˆ·åæ— æ•ˆï¼Œç”¨æˆ·åæ˜¯ä¿ç•™çš„ err_admin_name_pattern_not_allowed=管ç†å‘˜ç”¨æˆ·åæ— æ•ˆï¼Œç”¨æˆ·åæ˜¯ä¿ç•™å— err_admin_name_is_invalid=管ç†å‘˜ç”¨æˆ·åæ— æ•ˆ @@ -296,7 +296,7 @@ ssh_port_helper=SSH æœåŠ¡å™¨çš„ç«¯å£å·ï¼Œä¸ºç©ºåˆ™ç¦ç”¨å®ƒã€‚ http_port=HTTP æœåŠ¡ç«¯å£ http_port_helper=Giteas web æœåС噍将侦å¬çš„端å£å·ã€‚ app_url=基础URL -app_url_helper=用于 HTTP (S) 克隆和电å邮件通知的基本地å€ã€‚ +app_url_helper=用于 HTTP (S) 克隆和邮件通知的基本地å€ã€‚ log_root_path=日志路径 log_root_path_helper=日志文件将写入æ¤ç›®å½•。 @@ -304,12 +304,12 @@ optional_title=å¯é€‰è®¾ç½® email_title=电å邮箱设置 smtp_addr=SMTP ä¸»æœºåœ°å€ smtp_port=SMTP ç«¯å£ -smtp_from=电å邮件å‘件人 -smtp_from_invalid=`"å‘é€ç”µå邮件为"åœ°å€æ— 效` -smtp_from_helper=请输入一个用于 Gitea 的电å邮件地å€ï¼Œæˆ–è€…ä½¿ç”¨å®Œæ•´æ ¼å¼ï¼š"åç§°" <email@example.com> +smtp_from=邮件å‘件人 +smtp_from_invalid=「邮件å‘件人ã€åœ°å€æ— 效 +smtp_from_helper=请输入一个用于 Gitea 的邮箱地å€ï¼Œæˆ–è€…ä½¿ç”¨å®Œæ•´æ ¼å¼ï¼šã€Œåç§°ã€<email@example.com>。 mailer_user=SMTP 用户å mailer_password=SMTP 密ç -register_confirm=需è¦å‘电å邮件确认注册 +register_confirm=需è¦é‚®ä»¶ç¡®è®¤æ³¨å†Œ mail_notify=å¯ç”¨é‚®ä»¶é€šçŸ¥æé†’ server_service_title=æœåŠ¡å™¨å’Œç¬¬ä¸‰æ–¹æœåŠ¡è®¾ç½® offline_mode=å¯ç”¨æœ¬åœ°æ¨¡å¼ @@ -334,12 +334,12 @@ admin_title=管ç†å‘˜å¸å·è®¾ç½® admin_name=管ç†å‘˜ç”¨æˆ·å admin_password=管ç†å‘˜å¯†ç confirm_password=确认密ç -admin_email=电åé‚®ä»¶åœ°å€ +admin_email=é‚®ç®±åœ°å€ install_btn_confirm=ç«‹å³å®‰è£… test_git_failed=æ— æ³•è¯†åˆ« 'git' 命令:%v sqlite3_not_available=您所使用的å‘è¡Œç‰ˆä¸æ”¯æŒ SQLite3,请从 %s ä¸‹è½½å®˜æ–¹æž„å»ºç‰ˆï¼Œè€Œä¸æ˜¯ gobuild 版本。 invalid_db_setting=æ•°æ®åº“è®¾ç½®æ— æ•ˆ: %v -invalid_db_table=æ•°æ®åº“表 '%s' æ— æ•ˆï¼š %v +invalid_db_table=æ•°æ®åº“表「%sã€æ— 效:%v invalid_repo_path=ä»“åº“æ ¹ç›®å½•è®¾ç½®æ— æ•ˆï¼š%v invalid_app_data_path=应用数æ®è·¯å¾„æ— æ•ˆï¼š %v run_user_not_match=è¿è¡Œç”¨æˆ·å䏿˜¯å½“å‰çš„用户å:%s -> %s @@ -348,14 +348,14 @@ secret_key_failed=生æˆå¯†é’¥å¤±è´¥ï¼š %v save_config_failed=应用é…ç½®ä¿å˜å¤±è´¥ï¼š%v invalid_admin_setting=管ç†å‘˜å¸æˆ·è®¾ç½®æ— 效: %v invalid_log_root_path=æ—¥å¿—è·¯å¾„æ— æ•ˆ: %v -default_keep_email_private=默认情况下éšè—电åé‚®ä»¶åœ°å€ -default_keep_email_private_popup=默认情况下, éšè—æ–°ç”¨æˆ·å¸æˆ·çš„电å邮件地å€ã€‚ +default_keep_email_private=默认情况下éšè—é‚®ç®±åœ°å€ +default_keep_email_private_popup=默认情况下,éšè—æ–°ç”¨æˆ·å¸æˆ·çš„邮箱地å€ã€‚ default_allow_create_organization=默认情况下å…许创建组织 default_allow_create_organization_popup=默认情况下, å…è®¸æ–°ç”¨æˆ·å¸æˆ·åˆ›å»ºç»„织。 default_enable_timetracking=默认情况下å¯ç”¨æ—¶é—´è·Ÿè¸ª default_enable_timetracking_popup=默认情况下å¯ç”¨æ–°ä»“库的时间跟踪。 -no_reply_address=éšè—电å邮件 -no_reply_address_helper=具有éšè—电å邮件地å€çš„用户的域å。例如, 用户å "joe" 将以 "joe@noreply.example.org" 的身份登录到 Git ä¸. 如果éšè—的电å邮件域设置为 "noreply.example.org"。 +no_reply_address=éšè—邮件域 +no_reply_address_helper=具有éšè—邮箱地å€çš„用户的域å。例如,如果éšè—邮箱域å设置为「noreply.example.orgã€ï¼Œé‚£ä¹ˆç”¨æˆ·å「joeã€åœ¨ Git ä¸å°†æ˜¾ç¤ºä¸ºã€Œjoe@noreply.example.orgã€ã€‚ password_algorithm=密ç 哈希算法 invalid_password_algorithm=æ— æ•ˆçš„å¯†ç 哈希算法 password_algorithm_helper=è®¾ç½®å¯†ç æ•£åˆ—算法。算法有ä¸åŒçš„è¦æ±‚和强度。 argon2 算法相当安全,但使用大é‡å†…å˜ï¼Œå› æ¤å¯èƒ½ä¸é€‚åˆå°åž‹ç³»ç»Ÿã€‚ @@ -378,7 +378,7 @@ my_mirrors=æˆ‘çš„é•œåƒ view_home=访问 %s filter=其他过滤器 filter_by_team_repositories=按团队仓库ç›é€‰ -feed_of=`"%s"çš„æº` +feed_of=「%sã€çš„æº show_archived=已归档 show_both_archived_unarchived=显示已归档和未归档的 @@ -414,7 +414,7 @@ create_new_account=注册å¸å· already_have_account=已有账å·ï¼Ÿ sign_in_now=ç«‹å³ç™»å½• disable_register_prompt=对ä¸èµ·ï¼Œæ³¨å†ŒåŠŸèƒ½å·²è¢«å…³é—。请è”系网站管ç†å‘˜ã€‚ -disable_register_mail=å·²ç¦ç”¨æ³¨å†Œçš„电å邮件确认。 +disable_register_mail=å·²ç¦ç”¨æ³¨å†Œé‚®ä»¶ç¡®è®¤ã€‚ manual_activation_only=请è”系您的站点管ç†å‘˜æ¥å®Œæˆæ¿€æ´»ã€‚ remember_me=è®°ä½æ¤è®¾å¤‡ remember_me.compromised=登录令牌ä¸å†æœ‰æ•ˆï¼Œå› 为它å¯èƒ½è¡¨æ˜Žå¸æˆ·å·²è¢«ç ´åã€‚è¯·æ£€æŸ¥æ‚¨çš„å¸æˆ·æ˜¯å¦æœ‰å¼‚常活动。 @@ -423,34 +423,34 @@ forgot_password=忘记密ç ? need_account=需è¦ä¸€ä¸ªå¸æˆ·? sign_up_now=还没账å·ï¼Ÿé©¬ä¸Šæ³¨å†Œã€‚ sign_up_successful=叿ˆ·åˆ›å»ºæˆåŠŸã€‚æ¬¢è¿Žï¼ -confirmation_mail_sent_prompt_ex=䏀尿–°çš„确认邮件已ç»å‘é€åˆ° <b>%s</b>请在下一个 %s 䏿£€æŸ¥æ‚¨çš„æ”¶ä»¶ç®±ä»¥å®Œæˆæ³¨å†Œè¿‡ç¨‹ã€‚ 如果您的注册电å邮件地å€ä¸æ£ç¡®ï¼Œæ‚¨å¯ä»¥é‡æ–°ç™»å½•并更改它。 +confirmation_mail_sent_prompt_ex=䏀尿–°çš„确认邮件已ç»å‘é€åˆ° <b>%s</b>。请在下一个 %s 䏿£€æŸ¥æ‚¨çš„æ”¶ä»¶ç®±ä»¥å®Œæˆæ³¨å†Œæµç¨‹ã€‚ 如果您的注册邮箱地å€ä¸æ£ç¡®ï¼Œæ‚¨å¯ä»¥é‡æ–°ç™»å½•并更改它。 must_change_password=更新您的密ç allow_password_change=è¦æ±‚用户更改密ç (推è) -reset_password_mail_sent_prompt=确认电å邮件已被å‘é€åˆ° <b>%s</b>。请您在 %s 内检查您的收件箱 ,完æˆå¯†ç é‡ç½®è¿‡ç¨‹ã€‚ +reset_password_mail_sent_prompt=确认邮件已被å‘é€åˆ° <b>%s</b>。请您在 %s 内检查您的收件箱 ,完æˆå¯†ç é‡ç½®æµç¨‹ã€‚ active_your_account=æ¿€æ´»æ‚¨çš„å¸æˆ· account_activated=叿ˆ·å·²æ¿€æ´» prohibit_login=ç¦æ¢ç™»å½• prohibit_login_desc=æ‚¨çš„å¸æˆ·è¢«ç¦æ¢ç™»å½•,请与网站管ç†å‘˜è”系。 resent_limit_prompt=您请求å‘逿¿€æ´»é‚®ä»¶è¿‡äºŽé¢‘ç¹ï¼Œè¯·ç‰å¾… 3 分钟åŽå†è¯•ï¼ has_unconfirmed_mail=%s 您好,系统检测到您有一å°å‘é€è‡³ <b>%s</b> 但未被确认的邮件。如果您未收到激活邮件,或需è¦é‡æ–°å‘é€ï¼Œè¯·å•击下方的按钮。 -change_unconfirmed_mail_address=如果您的注册电å邮件地å€ä¸æ£ç¡®ï¼Œæ‚¨å¯ä»¥åœ¨æ¤æ›´æ”¹å¹¶é‡æ–°å‘逿–°çš„确认电å邮件。 +change_unconfirmed_mail_address=如果您的注册邮箱地å€ä¸æ£ç¡®ï¼Œæ‚¨å¯ä»¥åœ¨æ¤æ›´æ”¹å¹¶é‡æ–°å‘逿–°çš„确认邮件。 resend_mail=å•击æ¤å¤„釿–°å‘é€ç¡®è®¤é‚®ä»¶ email_not_associate=æ‚¨è¾“å…¥çš„é‚®ç®±åœ°å€æœªè¢«å…³è”到任何å¸å·ï¼ send_reset_mail=å‘é€è´¦æˆ·æ¢å¤é‚®ä»¶ reset_password=账户æ¢å¤ invalid_code=æ¤ç¡®è®¤å¯†é’¥æ— 效或已过期。 -invalid_code_forgot_password=ä½ çš„ç¡®è®¤ç æ— 效或者已过期,点击 <a href="%s">这里</a> 开始新的会è¯ã€‚ +invalid_code_forgot_password=æ‚¨çš„ç¡®è®¤ç æ— 效或已过期,点击 <a href="%s">这里</a> 开始新的会è¯ã€‚ invalid_password=您的密ç 与用于创建账户的密ç ä¸åŒ¹é…。 reset_password_helper=æ¢å¤è´¦æˆ· reset_password_wrong_user=您以 %s 登录,但æ¢å¤è´¦å·é“¾æŽ¥æ˜¯ç”¨äºŽ %s。 password_too_short=密ç 长度ä¸èƒ½å°‘于 %d ä½ã€‚ -non_local_account=éžæœ¬åœ°å¸æˆ·ä¸èƒ½é€šè¿‡ Gitea çš„ web ç•Œé¢æ›´æ”¹å¯†ç 。 +non_local_account=éžæœ¬åœ°å¸æˆ·ä¸èƒ½é€šè¿‡ Gitea çš„ Web ç•Œé¢æ›´æ”¹å¯†ç 。 verify=éªŒè¯ scratch_code=验è¯å£ä»¤ use_scratch_code=使用验è¯å£ä»¤ -twofa_scratch_used=ä½ å·²ç»ä½¿ç”¨äº†ä½ 的验è¯å£ä»¤ã€‚ä½ å°†ä¼šè½¬åˆ°ä¸¤æ¥éªŒè¯è®¾ç½®é¡µé¢ä»¥ä¾¿ç§»é™¤ä½ çš„æ³¨å†Œè®¾å¤‡æˆ–è€…é‡æ–°ç”Ÿæˆæ–°çš„验è¯å£ä»¤ã€‚ -twofa_passcode_incorrect=ä½ çš„éªŒè¯ç 䏿£ç¡®ã€‚å¦‚æžœä½ ä¸¢å¤±äº†ä½ çš„è®¾å¤‡ï¼Œè¯·ä½¿ç”¨ä½ çš„éªŒè¯å£ä»¤ã€‚ -twofa_scratch_token_incorrect=ä½ çš„éªŒè¯å£ä»¤ä¸æ£ç¡®ã€‚ +twofa_scratch_used=您已ç»ä½¿ç”¨äº†æ‚¨çš„验è¯å£ä»¤ã€‚您将会转到两æ¥éªŒè¯è®¾ç½®é¡µé¢ä»¥ä¾¿ç§»é™¤æ‚¨çš„æ³¨å†Œè®¾å¤‡æˆ–è€…é‡æ–°ç”Ÿæˆæ–°çš„验è¯å£ä»¤ã€‚ +twofa_passcode_incorrect=您的验è¯ç 䏿£ç¡®ã€‚如果您丢失了您的设备,请使用您的验è¯å£ä»¤ã€‚ +twofa_scratch_token_incorrect=您的验è¯å£ä»¤ä¸æ£ç¡®ã€‚ twofa_required=您必须设置两æ¥éªŒè¯æ¥è®¿é—®ä»“库,或者å°è¯•釿–°ç™»å½•。 login_userpass=登录 login_openid=OpenID @@ -470,14 +470,14 @@ openid_connect_desc=所选的 OpenID URI 未知。在这里关è”ä¸€ä¸ªæ–°å¸æˆ· openid_register_title=åˆ›å»ºæ–°å¸æˆ· openid_register_desc=所选的 OpenID URI 未知。在这里关è”ä¸€ä¸ªæ–°å¸æˆ·ã€‚ openid_signin_desc=输入您的OpenID地å€ã€‚例如:alice.openid.example.org 或 https://openid.example.org/alice. -disable_forgot_password_mail=由于未设置电åé‚®ä»¶ï¼Œå¸æˆ·æ¢å¤è¢«ç¦ç”¨ã€‚ 请è”系您的站点管ç†å‘˜ã€‚ -disable_forgot_password_mail_admin=叿ˆ·æ¢å¤ä»…在设置电å邮件åŽå¯ç”¨ã€‚ 请设置电å邮件以å¯ç”¨å¸æˆ·æ¢å¤ã€‚ -email_domain_blacklisted=您ä¸èƒ½ä½¿ç”¨æ‚¨çš„电åé‚®ä»¶åœ°å€æ³¨å†Œã€‚ +disable_forgot_password_mail=ç”±äºŽæœªè®¾ç½®é‚®ç®±ï¼Œå¸æˆ·æ¢å¤è¢«ç¦ç”¨ã€‚ 请è”系您的站点管ç†å‘˜ã€‚ +disable_forgot_password_mail_admin=叿ˆ·æ¢å¤ä»…在设置邮箱åŽå¯ç”¨ã€‚ 请设置邮箱以å¯ç”¨å¸æˆ·æ¢å¤ã€‚ +email_domain_blacklisted=您ä¸èƒ½ä½¿ç”¨æ‚¨çš„é‚®ç®±åœ°å€æ³¨å†Œã€‚ authorize_application=åº”ç”¨æŽˆæƒ authorize_redirect_notice=å¦‚æžœæ‚¨æŽˆæƒæ¤åº”用,您将会被é‡å®šå‘到 %s。 -authorize_application_created_by=æ¤åº”用由%s创建。 +authorize_application_created_by=æ¤åº”用由 %s 创建。 authorize_application_description=如果您å…许,它将能够读å–å’Œä¿®æ”¹æ‚¨çš„æ‰€æœ‰å¸æˆ·ä¿¡æ¯ï¼ŒåŒ…括ç§äººä»“库和组织。 -authorize_application_with_scopes=范围: %s +authorize_application_with_scopes=范围:%s authorize_title=æŽˆæƒ %s è®¿é—®æ‚¨çš„å¸æˆ·ï¼Ÿ authorization_failed=授æƒå¤±è´¥ authorization_failed_desc=å› ä¸ºæ£€æµ‹åˆ°æ— æ•ˆè¯·æ±‚ï¼ŒæŽˆæƒå¤±è´¥ã€‚请å°è¯•è”系您授æƒåº”用的管ç†å‘˜ã€‚ @@ -501,17 +501,17 @@ activate_account.text_2=请在 <b>%s</b> 时间内,点击以下链接激活您 activate_email=è¯·éªŒè¯æ‚¨çš„é‚®ç®±åœ°å€ activate_email.title=%sï¼Œè¯·éªŒè¯æ‚¨çš„邮箱 -activate_email.text=请在 <b>%s</b> 时间内,点击以下链接,以验è¯ä½ 的电å邮件地å€ï¼š +activate_email.text=请在 <b>%s</b> æ—¶é—´å†…ï¼Œç‚¹å‡»ä»¥ä¸‹é“¾æŽ¥ï¼Œä»¥éªŒè¯æ‚¨çš„邮箱地å€ï¼š register_notify=欢迎æ¥åˆ° %s register_notify.title=%[1]s,欢迎æ¥åˆ° %[2]s -register_notify.text_1=这是您的 %s 注册确认电å邮件 ï¼ +register_notify.text_1=这是您的 %s 注册确认邮件 ï¼ register_notify.text_2=您现在å¯ä»¥ä»¥ç”¨æˆ·å %s 登录。 register_notify.text_3=如果æ¤è´¦æˆ·å·²ä¸ºæ‚¨åˆ›å»ºï¼Œè¯·å…ˆ <a href="%s">设置您的密ç </a>。 reset_password=æ¢å¤æ‚¨çš„账户 reset_password.title=%s,您已请求æ¢å¤æ‚¨çš„叿ˆ· -reset_password.text=请在 <b>%s</b> 时间内,点击以下链接,æ¢å¤ä½ 的账户: +reset_password.text=请在 <b>%s</b> 时间内,点击以下链接,以æ¢å¤æ‚¨çš„账户: register_success=注册æˆåŠŸ @@ -533,26 +533,26 @@ issue.action.ready_for_review=<b>@%[1]s</b> æ ‡è®°æ¤åˆå¹¶è¯·æ±‚已评审通过 issue.action.new=<b>@%[1]s</b> 创建了 #%[2]d. issue.in_tree_path=在 %s ä¸ï¼š -release.new.subject=%[2]s ä¸çš„ %[1]s å‘布了 +release.new.subject=%[2]s ä¸çš„ %[1]s å·²å‘布 release.new.text=<b>@%[1]s</b> 于 %[3]s å‘布了 %[2]s -release.title=æ ‡é¢˜ï¼š %s +release.title=æ ‡é¢˜ï¼š%s release.note=注释: release.downloads=下载: -release.download.zip=æºä»£ç (ZIP) -release.download.targz=æºä»£ç (TAR.GZ) +release.download.zip=æºä»£ç (ZIP) +release.download.targz=æºä»£ç (TAR.GZ) -repo.transfer.subject_to=%s 想è¦å°† "%s" 转让给 %s -repo.transfer.subject_to_you=%s 想è¦å°† "%s" è½¬è®©ç»™ä½ -repo.transfer.to_you=ä½ +repo.transfer.subject_to=%s 想è¦å°†ã€Œ%sã€è½¬ç§»ç»™ %s +repo.transfer.subject_to_you=%s 想è¦å°†ã€Œ%sã€è½¬ç§»ç»™æ‚¨ +repo.transfer.to_you=您 repo.transfer.body=访问 %s ä»¥æŽ¥å—æˆ–æ‹’ç»è½¬ç§»ï¼Œäº¦å¯å¿½ç•¥æ¤é‚®ä»¶ã€‚ -repo.collaborator.added.subject=%s æŠŠä½ æ·»åŠ åˆ°äº† %s -repo.collaborator.added.text=æ‚¨å·²è¢«æ·»åŠ ä¸ºä»£ç 库的å作者: +repo.collaborator.added.subject=%s æŠŠæ‚¨æ·»åŠ åˆ°äº† %s +repo.collaborator.added.text=æ‚¨å·²è¢«æ·»åŠ ä¸ºä»“åº“çš„å作者: team_invite.subject=%[1]s é‚€è¯·æ‚¨åŠ å…¥ç»„ç»‡ %[2]s team_invite.text_1=%[1]s é‚€è¯·æ‚¨åŠ å…¥ç»„ç»‡ %[3]s ä¸çš„团队 %[2]s。 team_invite.text_2=请点击下é¢çš„é“¾æŽ¥åŠ å…¥å›¢é˜Ÿï¼š -team_invite.text_3=注æ„:这是å‘é€ç»™ %[1]s 的邀请。如果您未曾收到过æ¤ç±»é‚€è¯·ï¼Œè¯·å¿½ç•¥è¿™å°ç”µå邮件。 +team_invite.text_3=注æ„:æ¤é‚€è¯·æ˜¯å‘é€ç»™ %[1]s 的。如果您未预期收到æ¤é‚€è¯·ï¼Œè¯·å¿½ç•¥è¿™å°é‚®ä»¶ã€‚ [modal] yes=确认æ“作 @@ -592,9 +592,9 @@ size_error=长度必须为 %s。 min_size_error=长度最å°ä¸º %s 个å—符。 max_size_error=长度最大为 %s 个å—符。 email_error=䏿˜¯ä¸€ä¸ªæœ‰æ•ˆçš„邮箱地å€ã€‚ -url_error=`'%s' 䏿˜¯ä¸€ä¸ªæœ‰æ•ˆçš„ URL。` -include_error=`必须包å«åå—符串 "%s"。` -glob_pattern_error=`åŒ¹é…æ¨¡å¼æ— 效:%s.` +url_error=`「%sã€ä¸æ˜¯ä¸€ä¸ªæœ‰æ•ˆçš„ URL。` +include_error=`必须包å«åå—符串「%sã€ã€‚` +glob_pattern_error=`匹é…è¡¨è¾¾å¼æ— 效:%s.` regex_pattern_error=`æ£åˆ™è¡¨è¾¾å¼æ— 效:%s.` username_error=` åªèƒ½åŒ…å«å—æ¯æ•°å—å—符('0-9','a-z','A-Z'), ç ´æŠ˜å· ('-'), 下划线 ('_') 和点 ('.'). ä¸èƒ½ä»¥éžå—æ¯æ•°å—å—符开头或结尾,并且ä¸å…许连ç»çš„éžå—æ¯æ•°å—å—符。` invalid_group_team_map_error=`æ˜ å°„æ— æ•ˆï¼š %s` @@ -603,26 +603,26 @@ captcha_incorrect=验è¯ç 䏿£ç¡®ã€‚ password_not_match=密ç ä¸åŒ¹é…。 lang_select_error=从列表ä¸é€‰å‡ºè¯è¨€ -username_been_taken=用户å已被使用。 +username_been_taken=用户å已使用。 username_change_not_local_user=éžæœ¬åœ°ç”¨æˆ·ä¸å…许更改用户å。 -change_username_disabled=更改用户å已被ç¦ç”¨ã€‚ +change_username_disabled=更改用户åå·²ç¦ç”¨ã€‚ change_full_name_disabled=更改用户全åå·²ç¦ç”¨ username_has_not_been_changed=ç”¨æˆ·åæœªæ›´æ”¹ -repo_name_been_taken=仓库å称已被使用。 -repository_force_private=â€œå¼ºåˆ¶ç§æœ‰â€å·²å¯ç”¨ï¼šç§æœ‰ä»“库ä¸èƒ½è¢«å…¬å¼€ã€‚ +repo_name_been_taken=仓库å称已使用。 +repository_force_private=ã€Œå¼ºåˆ¶ç§æœ‰ã€å·²å¯ç”¨ï¼šç§æœ‰ä»“库ä¸èƒ½è¢«å…¬å¼€ã€‚ repository_files_already_exist=æ¤ä»“库已å˜åœ¨æ–‡ä»¶ã€‚请è”系系统管ç†å‘˜ã€‚ repository_files_already_exist.adopt=æ¤ä»“库已å˜åœ¨æ–‡ä»¶ï¼Œåªèƒ½è¢«æ”¶å½•。 repository_files_already_exist.delete=æ¤ä»“库已å˜åœ¨æ–‡ä»¶ï¼Œå¿…é¡»å…ˆåˆ é™¤ä»–ä»¬ã€‚ repository_files_already_exist.adopt_or_delete=æ¤ä»“库已å˜åœ¨æ–‡ä»¶ï¼Œè¦ä¹ˆåˆ 除他们,è¦ä¹ˆæ”¶å½•他们。 visit_rate_limit=远程访问达到速度é™åˆ¶ã€‚ 2fa_auth_required=远程访问需è¦åŒé‡éªŒè¯ã€‚ -org_name_been_taken=组织å称已被使用。 -team_name_been_taken=团队å称已被使用。 +org_name_been_taken=组织å称已使用。 +team_name_been_taken=团队å称已使用。 team_no_units_error=至少选择一项仓库å•元。 -email_been_used=该电å邮件地å€å·²åœ¨ä½¿ç”¨ä¸ã€‚ +email_been_used=该邮箱地å€å·²åœ¨ä½¿ç”¨ä¸ã€‚ email_invalid=æ¤é‚®ç®±åœ°å€æ— 效。 email_domain_is_not_allowed=用户 <b>%s</b> 与EMAIL_DOMAIN_ALLOWLIT 或 EMAIL_DOMAIN_BLOCKLIT 冲çªã€‚è¯·ç¡®ä¿æ‚¨çš„æ“ä½œæ˜¯é¢„æœŸçš„ã€‚ -openid_been_used=OpenID åœ°å€ "%s" 已被使用。 +openid_been_used=OpenID 地å€ã€Œ%sã€å·²è¢«ä½¿ç”¨ã€‚ username_password_incorrect=ç”¨æˆ·åæˆ–密ç 䏿£ç¡®ã€‚ password_complexity=å¯†ç æœªè¾¾åˆ°å¤æ‚ç¨‹åº¦è¦æ±‚: password_lowercase_one=至少一个å°å†™å—符 @@ -637,14 +637,14 @@ unset_password=登录用户没有设置密ç 。 unsupported_login_type=æ¤ç™»å½•ç±»åž‹ä¸æ”¯æŒæ‰‹åŠ¨åˆ é™¤å¸æˆ·ã€‚ user_not_exist=该用户ä¸å˜åœ¨ team_not_exist=团队ä¸å˜åœ¨ -last_org_owner=您ä¸èƒ½ä»Ž "所有者" 团队ä¸åˆ 除最åŽä¸€ä¸ªç”¨æˆ·ã€‚组织ä¸å¿…须至少有一个所有者。 -cannot_add_org_to_team=组织ä¸èƒ½è¢«åŠ å…¥åˆ°å›¢é˜Ÿä¸ã€‚ +last_org_owner=您ä¸èƒ½ä»Žã€Œæ‰€æœ‰è€…ã€å›¢é˜Ÿä¸åˆ 除最åŽä¸€ä¸ªç”¨æˆ·ã€‚组织ä¸å¿…须至少有一个所有者。 +cannot_add_org_to_team=组织ä¸èƒ½åŠ å…¥åˆ°å›¢é˜Ÿä¸ã€‚ duplicate_invite_to_team=æ¤ç”¨æˆ·å·²è¢«é‚€è¯·ä¸ºå›¢é˜Ÿæˆå‘˜ã€‚ organization_leave_success=您已æˆåŠŸç¦»å¼€ç»„ç»‡ %s。 -invalid_ssh_key=æ— æ³•éªŒè¯æ‚¨çš„ SSH 密钥: %s -invalid_gpg_key=æ— æ³•éªŒè¯æ‚¨çš„ GPG 密钥: %s -invalid_ssh_principal=æ— æ•ˆçš„è§„åˆ™ï¼š %s +invalid_ssh_key=æ— æ³•éªŒè¯æ‚¨çš„ SSH 密钥:%s +invalid_gpg_key=æ— æ³•éªŒè¯æ‚¨çš„ GPG 密钥:%s +invalid_ssh_principal=æ— æ•ˆçš„è§„åˆ™ï¼š%s must_use_public_key=您æä¾›çš„密钥是ç§é’¥ã€‚ä¸è¦åœ¨ä»»ä½•åœ°æ–¹ä¸Šä¼ æ‚¨çš„ç§é’¥ï¼Œè¯·æ”¹ç”¨æ‚¨çš„公钥。 unable_verify_ssh_key=æ— æ³•éªŒè¯ SSH å¯†é’¥ï¼Œè¯·ä»”ç»†æ£€æŸ¥æ˜¯å¦æœ‰é”™è¯¯ã€‚ auth_failed=授æƒéªŒè¯å¤±è´¥ï¼š%v @@ -677,27 +677,27 @@ follow=关注 unfollow=å–æ¶ˆå…³æ³¨ user_bio=简历 disabled_public_activity=该用户已éšè—活动记录。 -email_visibility.limited=所有已认è¯ç”¨æˆ·å‡å¯çœ‹åˆ°æ‚¨çš„电åé‚®ä»¶åœ°å€ -email_visibility.private=åªæœ‰ä½ 本人和管ç†å‘˜å¯ä»¥çœ‹åˆ°ä½ 的电åé‚®ä»¶åœ°å€ +email_visibility.limited=所有已认è¯ç”¨æˆ·å‡å¯çœ‹åˆ°æ‚¨çš„é‚®ç®±åœ°å€ +email_visibility.private=åªæœ‰æ‚¨æœ¬äººå’Œç®¡ç†å‘˜å¯ä»¥çœ‹åˆ°æ‚¨çš„é‚®ç®±åœ°å€ show_on_map=在地图上显示这个ä½ç½® settings=用户设置 -form.name_reserved=用户å "%s" 被ä¿ç•™ã€‚ -form.name_pattern_not_allowed=用户åä¸ä¸å…许使用 "%s" æ ¼å¼ã€‚ -form.name_chars_not_allowed=用户å "%s" åŒ…å«æ— 效å—符。 +form.name_reserved=用户å「%sã€è¢«ä¿ç•™ã€‚ +form.name_pattern_not_allowed=用户åä¸ä¸å…许使用「%sã€æ ¼å¼ã€‚ +form.name_chars_not_allowed=用户å「%sã€åŒ…嫿— 效å—符。 block.block=å±è”½ block.block.user=å±è”½ç”¨æˆ· block.block.org=å±è”½ç”¨æˆ·è®¿é—®ç»„织 -block.block.failure=å±è”½ç”¨æˆ·å¤±è´¥: %s +block.block.failure=å±è”½ç”¨æˆ·å¤±è´¥ï¼š%s block.unblock=å–æ¶ˆå±è”½ -block.unblock.failure=å±è”½ç”¨æˆ·å¤±è´¥: %s +block.unblock.failure=å–æ¶ˆå±è”½ç”¨æˆ·å¤±è´¥ï¼š%s block.blocked=您已å±è”½æ¤ç”¨æˆ·ã€‚ block.title=å±è”½ä¸€ä¸ªç”¨æˆ· block.info=å±è”½ç”¨æˆ·ä¼šé˜»æ¢ä»–们与仓库进行交互,例如打开或评论åˆå¹¶è¯·æ±‚或出现问题。了解更多关于å±è”½ç”¨æˆ·çš„ä¿¡æ¯ã€‚ block.info_1=阻æ¢ç”¨æˆ·åœ¨æ‚¨çš„叿ˆ·å’Œä»“库ä¸è¿›è¡Œä»¥ä¸‹æ“作: -block.info_2=å…³æ³¨ä½ çš„è´¦å· -block.info_3=通过@æåŠæ‚¨çš„用户å呿‚¨å‘é€é€šçŸ¥ +block.info_2=å…³æ³¨æ‚¨çš„è´¦å· +block.info_3=通过 @ æåŠæ‚¨çš„用户å呿‚¨å‘é€é€šçŸ¥ block.info_4=邀请您作为åä½œè€…åˆ°ä»–ä»¬çš„ä»“åº“ä¸ block.info_5=在仓库ä¸ç‚¹èµžã€æ´¾ç”Ÿæˆ–关注 block.info_6=æ‰“å¼€å’Œè¯„è®ºå·¥å•æˆ–åˆå¹¶è¯·æ±‚ @@ -730,18 +730,18 @@ uid=UID webauthn=两æ¥éªŒè¯ï¼ˆå®‰å…¨å¯†é’¥ï¼‰ public_profile=å…¬å¼€ä¿¡æ¯ -biography_placeholder=å‘Šè¯‰æˆ‘ä»¬ä¸€ç‚¹æ‚¨è‡ªå·±ï¼ (您å¯ä»¥ä½¿ç”¨Markdown) -location_placeholder=ä¸Žä»–äººåˆ†äº«ä½ çš„å¤§æ¦‚ä½ç½® -profile_desc=控制您的个人资料对其他用户的显示方å¼ã€‚您的主è¦ç”µå邮件地å€å°†ç”¨äºŽé€šçŸ¥ã€å¯†ç æ¢å¤å’ŒåŸºäºŽç½‘页界é¢çš„ Git æ“作 -password_username_disabled=您ä¸è¢«å…è®¸æ›´æ”¹ä½ çš„ç”¨æˆ·å。更多详情请è”系您的系统管ç†å‘˜ã€‚ -password_full_name_disabled=您ä¸è¢«å…è®¸æ›´æ”¹ä½ çš„å…¨å。请è”系您的站点管ç†å‘˜äº†è§£æ›´å¤šè¯¦æƒ…。 +biography_placeholder=å‘Šè¯‰æˆ‘ä»¬ä¸€ç‚¹æ‚¨è‡ªå·±ï¼ (您å¯ä»¥ä½¿ç”¨ Markdown) +location_placeholder=与他人分享您的大概ä½ç½® +profile_desc=控制您的个人资料对其他用户的显示方å¼ã€‚您的主邮箱地å€å°†ç”¨äºŽé€šçŸ¥ã€å¯†ç æ¢å¤å’ŒåŸºäºŽç½‘页的 Git æ“作。 +password_username_disabled=您ä¸è¢«å…许更改您的用户å。更多详情请è”系您的系统管ç†å‘˜ã€‚ +password_full_name_disabled=您ä¸è¢«å…许更改您的全å。请è”系您的站点管ç†å‘˜äº†è§£æ›´å¤šè¯¦æƒ…。 full_name=自定义åç§° website=个人网站 location=所在地区 update_theme=更新主题 update_profile=æ›´æ–°ä¿¡æ¯ update_language=æ›´æ–°è¯è¨€ -update_language_not_found=è¯è¨€ %s ä¸å¯ç”¨ã€‚ +update_language_not_found=è¯è¨€ã€Œ%sã€ä¸å¯ç”¨ã€‚ update_language_success=è¯è¨€å·²æ›´æ–°ã€‚ update_profile_success=您的资料信æ¯å·²ç»æ›´æ–° change_username=您的用户å已更改。 @@ -752,7 +752,7 @@ cancel=å–æ¶ˆæ“作 language=界é¢è¯è¨€ ui=主题 hidden_comment_types=éšè—的评论类型 -hidden_comment_types_description=æ¤å¤„选ä¸çš„æ³¨é‡Šç±»åž‹ä¸ä¼šæ˜¾ç¤ºåœ¨é—®é¢˜é¡µé¢ä¸ã€‚æ¯”å¦‚ï¼Œå‹¾é€‰â€æ ‡ç¾â€œåˆ 除所有 "<user> æ·»åŠ /åˆ é™¤çš„ <label>" 注释。 +hidden_comment_types_description=æ¤å¤„选ä¸çš„æ³¨é‡Šç±»åž‹ä¸ä¼šæ˜¾ç¤ºåœ¨å·¥å•页é¢ä¸ã€‚æ¯”å¦‚ï¼Œå‹¾é€‰ã€Œæ ‡ç¾ã€åˆ 除所有「{user} æ·»åŠ /åˆ é™¤çš„ {label}ã€æ³¨é‡Šã€‚ hidden_comment_types.ref_tooltip=注释æ¤é—®é¢˜åœ¨ä½•处被æåŠè¿‡ï¼Œå¦‚å¦ä¸€ä¸ªé—®é¢˜ã€ä»£ç æäº¤ç‰ hidden_comment_types.issue_ref_tooltip=注释用户在何处更改了与æ¤é—®é¢˜ç›¸å…³è”的分支/æ ‡ç¾ comment_type_group_reference=引用 @@ -774,7 +774,7 @@ privacy=éšç§è®¾ç½® keep_activity_private=éšè—个人资料页é¢ä¸çš„æ´»åЍ keep_activity_private_popup=使活动仅对您和管ç†å‘˜å¯è§ -lookup_avatar_by_mail=从电åé‚®ç®±åœ°å€æŸ¥æ‰¾å¤´åƒ +lookup_avatar_by_mail=ä»Žé‚®ç®±åœ°å€æŸ¥æ‰¾å¤´åƒ federated_avatar_lookup=Federated Avatar 查找 enable_custom_avatar=å¯åŠ¨è‡ªå®šä¹‰å¤´åƒ choose_new_avatar=é€‰æ‹©æ–°çš„å¤´åƒ @@ -798,61 +798,61 @@ emails=é‚®ç®±åœ°å€ manage_emails=管ç†é‚®ç®±åœ°å€ manage_themes=选择默认主题 manage_openid=ç®¡ç† OpenID åœ°å€ -email_desc=您的主è¦ç”µå邮件地å€å°†ç”¨äºŽé€šçŸ¥ã€å¯†ç æ¢å¤ï¼ŒåŸºäºŽç½‘页界é¢çš„Gitæ“作(åªè¦å®ƒä¸æ˜¯è®¾ç½®ä¸ºéšè—çš„)。 +email_desc=您的主邮箱地å€å°†ç”¨äºŽé€šçŸ¥ã€å¯†ç æ¢å¤ä»¥åŠåŸºäºŽç½‘页的 Git æ“作(如果它未设为éšè—)。 theme_desc=这将是您在整个网站上的默认主题。 theme_colorblindness_help=颜色障ç¢ä¸»é¢˜æ”¯æŒ -theme_colorblindness_prompt=Gitea åªèƒ½èŽ·å¾—ä¸€äº›åŸºæœ¬çš„é¢œè‰²éšœç¢æ”¯æŒï¼Œè¿™äº›ä¸»é¢˜åªå®šä¹‰äº†å°‘数颜色。 这项工作ä»åœ¨è¿›è¡Œä¸ï¼Œå¯ä»¥é€šè¿‡åœ¨ä¸»é¢˜çš„ CSS 文件ä¸å®šä¹‰æ›´å¤šé¢œè‰²æ¥åšæ›´å¤šçš„æ”¹è¿›ã€‚ +theme_colorblindness_prompt=Gitea åªèƒ½èŽ·å¾—ä¸€äº›åŸºæœ¬çš„é¢œè‰²éšœç¢æ”¯æŒï¼Œè¿™äº›ä¸»é¢˜åªå®šä¹‰äº†å°‘数颜色。这项工作ä»åœ¨è¿›è¡Œä¸ï¼Œå¯ä»¥é€šè¿‡åœ¨ä¸»é¢˜çš„ CSS 文件ä¸å®šä¹‰æ›´å¤šé¢œè‰²æ¥åšæ›´å¤šçš„æ”¹è¿›ã€‚ primary=ä¸»è¦ activated=已激活 requires_activation=éœ€è¦æ¿€æ´» -primary_email=设为主è¦é‚®ä»¶åœ°å€ +primary_email=设为主邮箱 activate_email=å‘逿¿€æ´»é‚®ä»¶ activations_pending=ç‰å¾…激活 -can_not_add_email_activations_pending=有一个待处ç†çš„æ¿€æ´»è¯·æ±‚,请ç¨ç‰å‡ 分钟åŽå†å°è¯•æ·»åŠ æ–°çš„ç”µå邮件地å€ã€‚ +can_not_add_email_activations_pending=有一个待处ç†çš„æ¿€æ´»è¯·æ±‚,请ç¨ç‰å‡ 分钟åŽå†å°è¯•æ·»åŠ æ–°çš„é‚®ç®±åœ°å€ã€‚ delete_email=移除 -email_deletion=移除电åé‚®ä»¶åœ°å€ -email_deletion_desc=电å邮箱地å€å’Œç›¸å…³ä¿¡æ¯å°†ä¼šè¢«åˆ 除。使用æ¤ç”µå邮箱地å€å‘é€çš„Gitæäº¤å°†ä¼šä¿ç•™ï¼Œç»§ç»ï¼Ÿ -email_deletion_success=您的电å邮箱地å€å·²è¢«ç§»é™¤ã€‚ +email_deletion=ç§»é™¤é‚®ç®±åœ°å€ +email_deletion_desc=邮箱地å€å’Œç›¸å…³ä¿¡æ¯å°†ä¼šè¢«åˆ 除。使用æ¤é‚®ç®±åœ°å€å‘é€çš„Gitæäº¤å°†ä¼šä¿ç•™ï¼Œç»§ç»ï¼Ÿ +email_deletion_success=您的邮箱地å€å·²ç§»é™¤ã€‚ theme_update_success=您的主题已更新。 theme_update_error=所选主题ä¸å˜åœ¨ã€‚ openid_deletion=移除 OpenID åœ°å€ -openid_deletion_desc=åˆ é™¤æ¤ OpenID 地å€å°†ä¼šé˜»æ¢ä½ ä½¿ç”¨å®ƒè¿›è¡Œç™»å½•ã€‚ä½ ç¡®å®šè¦ç»§ç»å—? -openid_deletion_success=OpenID地å€å·²è¢«ç§»é™¤ã€‚ +openid_deletion_desc=åˆ é™¤æ¤ OpenID 地å€å°†ä¼šé˜»æ¢æ‚¨ä½¿ç”¨å®ƒè¿›è¡Œç™»å½•。您确定è¦ç»§ç»å—? +openid_deletion_success=OpenID 地å€å·²ç§»é™¤ã€‚ add_new_email=æ·»åŠ æ–°çš„é‚®ç®±åœ°å€ add_new_openid=æ·»åŠ æ–°çš„ OpenID URI -add_email=å¢žåŠ ç”µåé‚®ä»¶åœ°å€ +add_email=æ–°å¢žé‚®ç®±åœ°å€ add_openid=æ·»åŠ OpenID URI -add_email_confirmation_sent=一å°ç¡®è®¤é‚®ä»¶å·²ç»è¢«å‘é€è‡³ %s,请检查您的收件箱并在 %s 内完æˆç¡®è®¤æ³¨å†Œæ“作。 -add_email_success=新的电å邮件地å€å·²æ·»åŠ ã€‚ -email_preference_set_success=电å邮件首选项已æˆåŠŸè®¾ç½®ã€‚ +add_email_confirmation_sent=一å°ç¡®è®¤é‚®ä»¶å·²ç»å‘é€è‡³ã€Œ%sã€ï¼Œè¯·æ£€æŸ¥æ‚¨çš„æ”¶ä»¶ç®±å¹¶åœ¨ %s 内完æˆç¡®è®¤æ³¨å†Œæ“作。 +add_email_success=新邮箱地å€å·²æ·»åŠ ã€‚ +email_preference_set_success=邮件首选项已æˆåŠŸè®¾ç½®ã€‚ add_openid_success=æ–°çš„ OpenID 地å€å·²æ·»åŠ ã€‚ -keep_email_private=éšè—电åé‚®ä»¶åœ°å€ -keep_email_private_popup=这将会éšè—您的电å邮件地å€ï¼Œä¸ä»…在您的个人资料ä¸ï¼Œè¿˜åœ¨æ‚¨ä½¿ç”¨Web界é¢åˆ›å»ºåˆå¹¶è¯·æ±‚或编辑文件时。已推é€çš„æäº¤å°†ä¸ä¼šè¢«ä¿®æ”¹ã€‚在æäº¤ä¸ä½¿ç”¨ %s 以和您的账å·å…³è”。 -openid_desc=OpenID è®©ä½ å¯ä»¥å°†è®¤è¯è½¬å‘到外部æœåŠ¡ã€‚ +keep_email_private=éšè—é‚®ç®±åœ°å€ +keep_email_private_popup=这将会éšè—您的邮箱地å€ï¼Œä¸ä»…在您的个人资料ä¸ï¼Œè¿˜åœ¨æ‚¨ä½¿ç”¨ Web 界é¢åˆ›å»ºåˆå¹¶è¯·æ±‚或编辑文件时。已推é€çš„æäº¤å°†ä¸ä¼šè¢«ä¿®æ”¹ã€‚在æäº¤ä¸ä½¿ç”¨ %s 以和您的账å·å…³è”。 +openid_desc=OpenID 让您å¯ä»¥å°†è®¤è¯è½¬å‘到外部æœåŠ¡ã€‚ manage_ssh_keys=ç®¡ç† SSH 密钥 -manage_ssh_principals=管ç†SSHè¯ä¹¦è§„则 +manage_ssh_principals=ç®¡ç† SSH è¯ä¹¦è§„则 manage_gpg_keys=ç®¡ç† GPG 密钥 add_key=å¢žåŠ å¯†é’¥ -ssh_desc=这些 SSH 公钥已ç»å…³è”åˆ°ä½ çš„è´¦å·ã€‚相应的ç§é’¥æ‹¥æœ‰å®Œå…¨æ“ä½œä½ çš„ä»“åº“çš„æƒé™ã€‚ -principal_desc=这些SSHè¯ä¹¦è§„则已关è”åˆ°ä½ çš„è´¦å·å°†å…è®¸å®Œå…¨è®¿é—®ä½ çš„æ‰€æœ‰ä»“åº“ã€‚ -gpg_desc=这些 GPG 公钥已ç»å…³è”åˆ°ä½ çš„è´¦å·ã€‚请妥善ä¿ç®¡ä½ çš„ç§é’¥å› ä¸ºä»–ä»¬å°†è¢«ç”¨äºŽè®¤è¯æäº¤ã€‚ +ssh_desc=这些 SSH 公钥已ç»å…³è”到您的账å·ã€‚相应的ç§é’¥æ‹¥æœ‰å®Œå…¨æ“作您仓库的æƒé™ã€‚ +principal_desc=这些 SSH è¯ä¹¦è§„则已关è”到您的账å·å°†å…许完全访问您所有仓库。 +gpg_desc=这些 GPG 公钥已ç»å…³è”到您的账å·ã€‚请妥善ä¿ç®¡æ‚¨çš„ç§é’¥å› ä¸ºä»–ä»¬å°†è¢«ç”¨äºŽè®¤è¯æäº¤ã€‚ ssh_helper=<strong>需è¦å¸®åŠ©ï¼Ÿ</strong> 请查看有关 <a href="%s">å¦‚ä½•ç”Ÿæˆ SSH 密钥</a> 或 <a href="%s">å¸¸è§ SSH 问题</a> å¯»æ‰¾ç”æ¡ˆã€‚ -gpg_helper=<strong>需è¦å¸®åŠ©å—?</strong>看一看 GitHub <a href="%s">关于GPG</a> 的指导。 +gpg_helper=<strong>需è¦å¸®åŠ©å—?</strong>看一看 GitHub <a href="%s">关于 GPG</a> 的指导。 add_new_key=å¢žåŠ SSH 密钥 add_new_gpg_key=æ·»åŠ çš„ GPG 密钥 key_content_ssh_placeholder=以 'ssh-ed25519'〠'ssh-rsa'〠'ecdsa-sha2-nistp256'ã€'ecdsa-sha2-nistp384'ã€'ecdsa-sha2-nistp521'〠'sk-ecdsa-sha2-nistp256@openssh.com' 或 'sk-ssh-ed25519@openssh.com' 开头 key_content_gpg_placeholder=以 '-----BEGIN PGP PUBLIC KEY BLOCK-----' 开头 add_new_principal=æ·»åŠ è§„åˆ™ ssh_key_been_used=æ¤ SSH å¯†é’¥å·²æ·»åŠ åˆ°æœåŠ¡å™¨ã€‚ -ssh_key_name_used=使用相åŒåç§°çš„SSH公钥已ç»å˜åœ¨ï¼ +ssh_key_name_used=使用相åŒåç§°çš„ SSH 公钥已ç»å˜åœ¨ã€‚ ssh_principal_been_used=æ¤è§„则已ç»åŠ å…¥åˆ°äº†æœåŠ¡å™¨ã€‚ -gpg_key_id_used=使用相åŒåç§°çš„GPG公钥已ç»å˜åœ¨ï¼ -gpg_no_key_email_found=æ¤ GPG å¯†é’¥ä¸Žæ‚¨å¸æˆ·å…³è”的任何已激活电å邮件地å€å‡ä¸åŒ¹é…。如果您在æä¾›çš„令牌上ç¾å,它ä»ç„¶å¯ä»¥è¢«æ·»åŠ ã€‚ +gpg_key_id_used=使用相åŒåç§°çš„ GPG 公钥已ç»å˜åœ¨ã€‚ +gpg_no_key_email_found=æ¤ GPG å¯†é’¥ä¸Žæ‚¨å¸æˆ·å…³è”的任何已激活邮箱地å€å‡ä¸åŒ¹é…。如果您已对æä¾›çš„令牌进行ç¾å,ä»å¯æ·»åŠ è¯¥å¯†é’¥ã€‚ gpg_key_matched_identities=匹é…的身份: -gpg_key_matched_identities_long=æ¤å¯†é’¥ä¸åŒ…å«çš„身份信æ¯ä¸Žä¸‹é¢è¿™ä¸ªè¯¥ç”¨æˆ·å·²æ¿€æ´»ç”µåé‚®ä»¶åœ°å€æ˜¯ç›¸åŒ¹é…çš„ã€‚å› æ¤ï¼Œèƒ½ä¸Žè¿™äº›ç”µå邮件地å€ç›¸åŒ¹é…çš„æäº¤å¯ä»¥é€šè¿‡æ¤å¯†é’¥è¿›è¡ŒéªŒè¯ã€‚ +gpg_key_matched_identities_long=æ¤å¯†é’¥ä¸åŒ…å«çš„身份信æ¯ä¸Žä»¥ä¸‹æ¤ç”¨æˆ·å·²æ¿€æ´»é‚®ç®±åœ°å€åŒ¹é…。与这些邮箱地å€ç›¸åŒ¹é…çš„æäº¤å¯é€šè¿‡æ¤å¯†é’¥è¿›è¡ŒéªŒè¯ã€‚ gpg_key_verified=已验è¯çš„密钥 -gpg_key_verified_long=密钥已ç»ç”¨ä»¤ç‰Œè¿›è¡Œäº†éªŒè¯ï¼Œå¹¶ä¸”å¯ä»¥ç”¨æ¥éªŒè¯åŒ¹é…æ¤ç”¨æˆ·ä»»ä½•已激活电å邮件地å€çš„æäº¤ï¼Œä»¥åŠåŒ¹é…æ¤å¯†é’¥çš„任何身份。 +gpg_key_verified_long=密钥已通过令牌验è¯ï¼Œé™¤ä¸Žæ¤å¯†é’¥åŒ¹é…的任何身份外,还å¯ç”¨äºŽéªŒè¯ä¸Žè¯¥ç”¨æˆ·ä»»ä½•已激活邮箱地å€åŒ¹é…çš„æäº¤ã€‚ gpg_key_verify=éªŒè¯ gpg_invalid_token_signature=æä¾›çš„ GPG 密钥ã€ç¾å和令牌ä¸åŒ¹é…或过期。 gpg_token_required=您必须为下é¢çš„令牌æä¾›ç¾å @@ -860,9 +860,9 @@ gpg_token=令牌 gpg_token_help=您å¯ä»¥ä½¿ç”¨ä»¥ä¸‹æ–¹å¼ç”Ÿæˆç¾å: gpg_token_signature=GPG 增强ç¾å key_signature_gpg_placeholder=以 '-----BEGIN PGP PUBLIC KEY BLOCK-----' 开头 -verify_gpg_key_success=GPG 密钥 %s 已被验è¯ã€‚ +verify_gpg_key_success=GPG 密钥「%sã€å·²éªŒè¯ã€‚ ssh_key_verified=已验è¯çš„密钥 -ssh_key_verified_long=密钥已ç»ç”¨ä»¤ç‰Œè¿›è¡Œäº†éªŒè¯ï¼Œå¹¶ä¸”å¯ä»¥ç”¨æ¥éªŒè¯åŒ¹é…æ¤ç”¨æˆ·ä»»ä½•已激活电å邮件地å€çš„æäº¤ã€‚ +ssh_key_verified_long=密钥已通过令牌验è¯ï¼Œå¯ç”¨äºŽéªŒè¯ä¸Žè¯¥ç”¨æˆ·ä»»ä½•已激活邮箱地å€åŒ¹é…çš„æäº¤ã€‚ ssh_key_verify=éªŒè¯ ssh_invalid_token_signature=æä¾›çš„ SSH 密钥ã€ç¾å或令牌ä¸åŒ¹é…或令牌已过期。 ssh_token_required=您必须为下é¢çš„令牌æä¾›ç¾å @@ -870,24 +870,24 @@ ssh_token=令牌 ssh_token_help=您å¯ä»¥ä½¿ç”¨ä»¥ä¸‹æ–¹å¼ç”Ÿæˆç¾å: ssh_token_signature=增强 SSH ç¾å key_signature_ssh_placeholder=以 '-----BEGIN SSH SIGNATURE -----' 开头 -verify_ssh_key_success=SSH 密钥 %s 已被验è¯ã€‚ +verify_ssh_key_success=SSH 密钥「%sã€å·²éªŒè¯ã€‚ subkeys=å项 -key_id=é”®ID +key_id=密钥 ID key_name=密钥åç§° key_content=密钥内容 principal_content=内容 -add_key_success=SSH 密钥 %s æ·»åŠ æˆåŠŸã€‚ -add_gpg_key_success=GPG 密钥 %s æ·»åŠ æˆåŠŸã€‚ -add_principal_success=SSHè¯ä¹¦è§„则 %s æ·»åŠ æˆåŠŸã€‚ +add_key_success=SSH 密钥「%sã€æ·»åŠ æˆåŠŸã€‚ +add_gpg_key_success=GPG 密钥「%sã€æ·»åŠ æˆåŠŸã€‚ +add_principal_success=SSH è¯ä¹¦è§„则「%sã€æ·»åŠ æˆåŠŸã€‚ delete_key=åˆ é™¤ ssh_key_deletion=åˆ é™¤ SSH 密钥 gpg_key_deletion=åˆ é™¤ GPG 密钥 ssh_principal_deletion=åˆ é™¤ SSH è¯ä¹¦è§„则 ssh_key_deletion_desc=åˆ é™¤ SSH 公钥将喿¶ˆå¯¹åº”çš„ç§é’¥å¯¹æ‚¨çš„ Gitea 叿ˆ·çš„访问æƒé™ã€‚ç»§ç»ï¼Ÿ -gpg_key_deletion_desc=åˆ é™¤ GPG å…¬é’¥å°†æ— æ³•è®¤çŸ¥ä½¿ç”¨å¯¹åº”ç§é’¥ç¾åçš„æäº¤ï¼Œç»§ç»ï¼Ÿ +gpg_key_deletion_desc=åˆ é™¤ GPG å…¬é’¥å°†æ— æ³•è®¤è¯å¯¹åº”ç§é’¥ç¾åçš„æäº¤ï¼Œç»§ç»ï¼Ÿ ssh_principal_deletion_desc=åˆ é™¤æ¤ SSH è¯ä¹¦è§„åˆ™å°†å–æ¶ˆå®ƒå¯¹æ‚¨çš„账户的访问æƒé™ã€‚ç»§ç»ï¼Ÿ -ssh_key_deletion_success=GPG å¯†é’¥å·²è¢«åˆ é™¤ã€‚ -gpg_key_deletion_success=GPG å¯†é’¥å·²è¢«åˆ é™¤ã€‚ +ssh_key_deletion_success=SSH å¯†é’¥å·²åˆ é™¤ã€‚ +gpg_key_deletion_success=GPG å¯†é’¥å·²åˆ é™¤ã€‚ ssh_principal_deletion_success=æ¤è§„åˆ™åˆ é™¤æˆåŠŸã€‚ added_on=æ·»åŠ äºŽ %s valid_until_date=有效期至 %s @@ -901,7 +901,7 @@ token_state_desc=7 天内使用过该密钥 principal_state_desc=7 天内使用过该规则 show_openid=在个人信æ¯ä¸Šæ˜¾ç¤º hide_openid=在个人信æ¯ä¸Šéšè— -ssh_disabled=SSH 被ç¦ç”¨ +ssh_disabled=SSH å·²ç¦ç”¨ ssh_signonly=SSH ç›®å‰å·²ç¦ç”¨ï¼Œå› æ¤è¿™äº›å¯†é’¥ä»…用于æäº¤ç¾å验è¯ã€‚ ssh_externally_managed=æ¤ SSH 密钥是由外部管ç†çš„ manage_social=管ç†å…³è”ç¤¾äº¤å¸æˆ· @@ -921,10 +921,10 @@ access_token_deletion=åˆ é™¤ Access Token access_token_deletion_cancel_action=å–æ¶ˆ access_token_deletion_confirm_action=刪除 access_token_deletion_desc=åˆ é™¤ä»¤ç‰Œå°†æ’¤é”€ç¨‹åºå¯¹æ‚¨è´¦æˆ·çš„访问æƒé™ã€‚æ¤æ“ä½œæ— æ³•æ’¤æ¶ˆã€‚æ˜¯å¦ç»§ç»ï¼Ÿ -delete_token_success=令牌已ç»è¢«åˆ 除。使用该令牌的应用将ä¸å†èƒ½å¤Ÿè®¿é—®ä½ 的账å·ã€‚ +delete_token_success=令牌已ç»è¢«åˆ 除。使用该令牌的应用将ä¸å†èƒ½å¤Ÿè®¿é—®æ‚¨çš„è´¦å·ã€‚ repo_and_org_access=仓库和组织访问æƒé™ permissions_public_only=仅公开 -permissions_access_all=全部(公开ã€ç§æœ‰å’Œå—é™) +permissions_access_all=全部(公开ã€ç§æœ‰å’Œå—é™ï¼‰ permission_not_set=未设置 permission_no_access=æ— è®¿é—®æƒé™ permission_read=å¯è¯» @@ -933,7 +933,7 @@ permission_anonymous_read=匿å读 permission_everyone_read=所有人å¯è¯» permission_everyone_write=所有人å¯å†™ access_token_desc=所选令牌æƒé™ä»…é™äºŽå¯¹åº”çš„ <a %s>API</a> 路由的授æƒã€‚阅读 <a %s>文档</a> ä»¥èŽ·å–æ›´å¤šä¿¡æ¯ã€‚ -at_least_one_permission=ä½ éœ€è¦é€‰æ‹©è‡³å°‘一个æƒé™æ‰èƒ½åˆ›å»ºä»¤ç‰Œ +at_least_one_permission=您需è¦é€‰æ‹©è‡³å°‘一个æƒé™æ‰èƒ½åˆ›å»ºä»¤ç‰Œ permissions_list=æƒé™ï¼š manage_oauth2_applications=ç®¡ç† OAuth2 åº”ç”¨ç¨‹åº @@ -941,13 +941,13 @@ edit_oauth2_application=编辑 OAuth2 åº”ç”¨ç¨‹åº oauth2_applications_desc=OAuth2 应用å…许第三方应用程åºåœ¨æ¤ Gitea 实例ä¸å®‰å…¨éªŒè¯ç”¨æˆ·ã€‚ remove_oauth2_application=åˆ é™¤ OAuth2 åº”ç”¨ç¨‹åº remove_oauth2_application_desc=åˆ é™¤ OAuth2 应用将撤销所有ç¾å的访问令牌。继ç»å—? -remove_oauth2_application_success=è¯¥åº”ç”¨å·²è¢«åˆ é™¤ã€‚ +remove_oauth2_application_success=è¯¥åº”ç”¨å·²åˆ é™¤ã€‚ create_oauth2_application=创建新的 OAuth2 åº”ç”¨ç¨‹åº create_oauth2_application_button=创建应用 create_oauth2_application_success=您已æˆåŠŸåˆ›å»ºäº†ä¸€ä¸ªæ–°çš„ OAuth2 应用。 update_oauth2_application_success=您已æˆåŠŸæ›´æ–°äº†æ¤ OAuth2 应用。 oauth2_application_name=应用åç§° -oauth2_confidential_client=æœºå¯†å®¢æˆ·ç«¯ã€‚æ˜¯å¦æ˜¯èƒ½å¤Ÿç»´æŒå‡æ®æœºå¯†æ€§çš„应用,比如网页应用程åºã€‚如果是本地应用程åºè¯·ä¸è¦å‹¾é€‰ï¼ŒåŒ…括桌é¢å’Œç§»åŠ¨ç«¯åº”ç”¨ã€‚ +oauth2_confidential_client=机密客户端。对于需è¦ä¿å¯†çš„应用(例如 Web 应用),请选择æ¤é€‰é¡¹ã€‚对于包括桌é¢å’Œç§»åŠ¨åº”ç”¨åœ¨å†…çš„æœ¬æœºåº”ç”¨ï¼Œè¯·å‹¿é€‰æ‹©æ¤é€‰é¡¹ã€‚ oauth2_skip_secondary_authorization=首次授æƒåŽå…è®¸å…¬å…±å®¢æˆ·ç«¯è·³è¿‡æŽˆæƒæ¥éª¤ã€‚ <strong>å¯èƒ½ä¼šå¸¦æ¥å®‰å…¨é£Žé™©ã€‚</strong> oauth2_redirect_uris=é‡å®šå‘ URI。æ¯è¡Œä¸€ä¸ª URI。 save_application=ä¿å˜ @@ -959,7 +959,7 @@ oauth2_client_secret_hint=您离开或刷新æ¤é¡µé¢åŽå°†ä¸ä¼šå†æ˜¾ç¤ºæ¤å¯† oauth2_application_edit=编辑 oauth2_application_create_description=OAuth2 应用å…许您的第三方应用程åºè®¿é—®æ¤å®žä¾‹çš„ç”¨æˆ·å¸æˆ·ã€‚ oauth2_application_remove_description=移除一个OAuth2应用将会阻æ¢å®ƒè®¿é—®æ¤å®žä¾‹ä¸Šçš„已授æƒç”¨æˆ·è´¦æˆ·ã€‚是å¦ç»§ç»ï¼Ÿ -oauth2_application_locked=如果é…ç½®å¯ç”¨ï¼ŒGitea预注册一些OAuth2应用程åºã€‚ ä¸ºäº†é˜²æ¢æ„外的行为, 这些应用既ä¸èƒ½ç¼–辑也ä¸èƒ½åˆ 除。请å‚阅OAuth2æ–‡æ¡£ä»¥èŽ·å–æ›´å¤šä¿¡æ¯ã€‚ +oauth2_application_locked=如果é…ç½®å¯ç”¨ï¼ŒGitea 将在å¯åŠ¨æ—¶é¢„æ³¨å†Œä¸€äº› OAuth2 应用程åºã€‚ ä¸ºäº†é˜²æ¢æ„外的行为, 这些应用既ä¸èƒ½ç¼–辑也ä¸èƒ½åˆ 除。请å‚阅 OAuth2 æ–‡æ¡£ä»¥èŽ·å–æ›´å¤šä¿¡æ¯ã€‚ authorized_oauth2_applications=已授æƒçš„ OAuth2 应用 authorized_oauth2_applications_description=您已授予这些第三方应用程åºè®¿é—®æ‚¨çš„个人 Gitea 账户的æƒé™ã€‚请撤销那些您ä¸å†éœ€è¦çš„应用程åºçš„访问æƒé™ã€‚ @@ -968,10 +968,10 @@ revoke_oauth2_grant=撤回æƒé™ revoke_oauth2_grant_description=确定撤销æ¤ä¸‰æ–¹åº”用程åºçš„æŽˆæƒï¼Œå¹¶é˜»æ¢æ¤åº”用程åºè®¿é—®æ‚¨çš„æ•°æ®ï¼Ÿ revoke_oauth2_grant_success=æˆåŠŸæ’¤é”€äº†è®¿é—®æƒé™ã€‚ -twofa_desc=ä¸ºä¿æŠ¤ä½ çš„è´¦å·å¯†ç å®‰å…¨ï¼Œä½ å¯ä»¥ä½¿ç”¨æ™ºèƒ½æ‰‹æœºæˆ–å…¶å®ƒè®¾å¤‡æ¥æŽ¥æ”¶æ—¶é—´å¼ºç›¸å…³çš„ä¸€æ¬¡æ€§å¯†ç (TOTP)。 +twofa_desc=ä¸ºä¿æŠ¤æ‚¨çš„è´¦å·å¯†ç 安全,您å¯ä»¥ä½¿ç”¨æ™ºèƒ½æ‰‹æœºæˆ–å…¶å®ƒè®¾å¤‡æ¥æŽ¥æ”¶æ—¶é—´å¼ºç›¸å…³çš„ä¸€æ¬¡æ€§å¯†ç (TOTP)。 twofa_recovery_tip=如果您丢失了您的设备,您将能够使用一次性æ¢å¤å¯†é’¥æ¥é‡æ–°èŽ·å¾—å¯¹æ‚¨è´¦æˆ·çš„è®¿é—®ã€‚ -twofa_is_enrolled=ä½ çš„è´¦å·<strong>å·²å¯ç”¨</strong>了两æ¥éªŒè¯ã€‚ -twofa_not_enrolled=ä½ çš„è´¦å·æœªå¼€å¯ä¸¤æ¥éªŒè¯ã€‚ +twofa_is_enrolled=您的账å·<strong>å·²å¯ç”¨</strong>了两æ¥éªŒè¯ã€‚ +twofa_not_enrolled=æ‚¨çš„è´¦å·æœªå¼€å¯ä¸¤æ¥éªŒè¯ã€‚ twofa_disable=ç¦ç”¨ä¸¤æ¥è®¤è¯ twofa_scratch_token_regenerate=釿–°ç”Ÿæˆåˆå§‹ä»¤ç‰Œ twofa_scratch_token_regenerated=您的åˆå§‹ä»¤ç‰ŒçŽ°åœ¨æ˜¯ %sã€‚å°†å…¶å˜æ”¾åœ¨å®‰å…¨çš„地方,它将ä¸ä¼šå†æ¬¡æ˜¾ç¤ºã€‚ @@ -979,12 +979,12 @@ twofa_enroll=å¯ç”¨ä¸¤æ¥éªŒè¯ twofa_disable_note=如果需è¦, å¯ä»¥ç¦ç”¨åŒå› ç´ èº«ä»½éªŒè¯ã€‚ twofa_disable_desc=关掉两æ¥éªŒè¯ä¼šä½¿å¾—您的账å·ä¸å®‰å…¨ï¼Œç»§ç»æ‰§è¡Œï¼Ÿ regenerate_scratch_token_desc=如果您丢失了您的æ¢å¤å¯†é’¥æˆ–å·²ç»ä½¿ç”¨å®ƒç™»å½•, 您å¯ä»¥åœ¨è¿™é‡Œé‡ç½®å®ƒã€‚ -twofa_disabled=两æ¥éªŒè¯å·²è¢«ç¦ç”¨ã€‚ +twofa_disabled=两æ¥éªŒè¯å·²ç¦ç”¨ã€‚ scan_this_image=使用您的授æƒåº”用扫æè¿™å¼ 图片: or_enter_secret=或者输入密钥:%s then_enter_passcode=并输入应用程åºä¸æ˜¾ç¤ºçš„密ç : passcode_invalid=密ç 䏿£ç¡®ã€‚å†è¯•一次。 -twofa_enrolled=ä½ çš„è´¦å·å·²ç»å¯ç”¨äº†ä¸¤æ¥éªŒè¯ã€‚请ä¿å˜åˆå§‹ä»¤ç‰Œï¼ˆ%s)到一个安全的地方,æ¤ä»¤ç‰Œä»…显示一次。 +twofa_enrolled=您的账å·å·²ç»å¯ç”¨äº†ä¸¤æ¥éªŒè¯ã€‚请ä¿å˜åˆå§‹ä»¤ç‰Œï¼ˆ%s)到一个安全的地方,æ¤ä»¤ç‰Œä»…显示一次。 twofa_failed_get_secret=èŽ·å– secret 失败。 webauthn_desc=安全密钥是包å«åŠ å¯†å¯†é’¥çš„ç¡¬ä»¶è®¾å¤‡ã€‚å®ƒä»¬å¯ä»¥ç”¨äºŽåŒå› ç´ èº«ä»½éªŒè¯ã€‚å®‰å…¨å¯†é’¥å¿…é¡»æ”¯æŒ <a rel="noreferrer" target="_blank" href="%s">WebAuthn 身份验è¯å™¨</a> æ ‡å‡†ã€‚ @@ -1003,14 +1003,14 @@ remove_account_link=åˆ é™¤å·²ç»‘å®šçš„è´¦å· remove_account_link_desc=åˆ é™¤å·²ç»‘å®šå¸æˆ·å°†åŠé”€å…¶å¯¹æ‚¨çš„ Gitea 叿ˆ·çš„访问æƒé™ã€‚ç»§ç»ï¼Ÿ remove_account_link_success=已喿¶ˆç»‘å®šå¸æˆ·ã€‚ -hooks.desc=æ·»åŠ Webhooks,它们将会在您拥有的<strong>所有仓库</strong>ä¸Šè§¦å‘ +hooks.desc=æ·»åŠ Web é’©å,它们将会在您拥有的<strong>所有仓库</strong>上触å‘。 orgs_none=æ‚¨çŽ°åœ¨è¿˜ä¸æ˜¯ä»»ä½•组织的æˆå‘˜ã€‚ -repos_none=ä½ å¹¶ä¸æ‹¥æœ‰ä»»ä½•仓库。 +repos_none=æ‚¨å¹¶ä¸æ‹¥æœ‰ä»»ä½•仓库。 delete_account=åˆ é™¤å½“å‰å¸æˆ· delete_prompt=æ¤æ“ä½œå°†æ°¸ä¹…åˆ é™¤æ‚¨çš„ç”¨æˆ·å¸æˆ·ã€‚它 <strong>ä¸èƒ½</strong> 被撤消。 -delete_with_all_comments=ä½ çš„å¸æˆ·å¹´é¾„å°äºŽ %s。为了é¿å…å¹½çµè¯„论,所有工å•/åˆå¹¶è¯·æ±‚çš„è¯„è®ºéƒ½å°†ä¸Žå®ƒä¸€èµ·è¢«åˆ é™¤ã€‚ +delete_with_all_comments=æ‚¨çš„å¸æˆ·å¹´é¾„å°äºŽ %s。为了é¿å…å¹½çµè¯„论,所有工å•/åˆå¹¶è¯·æ±‚çš„è¯„è®ºéƒ½å°†ä¸Žå®ƒä¸€èµ·è¢«åˆ é™¤ã€‚ confirm_delete_account=ç¡®è®¤åˆ é™¤å¸æˆ· delete_account_title=åˆ é™¤å½“å‰å¸æˆ· delete_account_desc=ç¡®å®žè¦æ°¸ä¹…åˆ é™¤æ¤ç”¨æˆ·å¸æˆ·å—? @@ -1034,9 +1034,9 @@ new_repo_helper=代ç 仓库包å«äº†æ‰€æœ‰çš„项目文件,包括版本历å²è owner=拥有者 owner_helper=由于最大仓库数é‡é™åˆ¶ï¼Œä¸€äº›ç»„织å¯èƒ½ä¸ä¼šæ˜¾ç¤ºåœ¨ä¸‹æ‹‰åˆ—表ä¸ã€‚ repo_name=仓库åç§° -repo_name_profile_public_hint=.profile 是一个特殊的å˜å‚¨åº“,您å¯ä»¥ä½¿ç”¨å®ƒå°† README.md æ·»åŠ åˆ°æ‚¨çš„å…¬å…±ç»„ç»‡èµ„æ–™ä¸ï¼Œä»»ä½•人都å¯ä»¥çœ‹åˆ°ã€‚请确ä¿å®ƒæ˜¯å…¬å¼€çš„,并使用个人资料目录ä¸çš„ README 对其进行åˆå§‹åŒ–以开始使用。 -repo_name_profile_private_hint=.profile-private 是一个特殊的å˜å‚¨åº“,您å¯ä»¥ä½¿ç”¨å®ƒå‘您的组织æˆå‘˜ä¸ªäººèµ„æ–™æ·»åŠ README.md,仅对组织æˆå‘˜å¯è§ã€‚请确ä¿å®ƒæ˜¯ç§æœ‰çš„,并使用个人资料目录ä¸çš„ README 对其进行åˆå§‹åŒ–以开始使用。 -repo_name_helper=ç†æƒ³çš„仓库å称应由简çŸã€æœ‰æ„义和独特的关键è¯ç»„æˆã€‚".profile" å’Œ ".profile-private" å¯ç”¨äºŽä¸ºç”¨æˆ·/ç»„ç»‡æ·»åŠ README.md。 +repo_name_profile_public_hint=.profile 是一个特殊的仓库,您å¯ä»¥ä½¿ç”¨å®ƒå°† README.md æ·»åŠ åˆ°æ‚¨çš„å…¬å…±ç»„ç»‡èµ„æ–™ä¸ï¼Œä»»ä½•人都å¯ä»¥çœ‹åˆ°ã€‚请确ä¿å®ƒæ˜¯å…¬å¼€çš„,并使用个人资料目录ä¸çš„ README 对其进行åˆå§‹åŒ–以开始使用。 +repo_name_profile_private_hint=.profile-private 是一个特殊的仓库,您å¯ä»¥ä½¿ç”¨å®ƒå‘您的组织æˆå‘˜ä¸ªäººèµ„æ–™æ·»åŠ README.md,仅对组织æˆå‘˜å¯è§ã€‚请确ä¿å®ƒæ˜¯ç§æœ‰çš„,并使用个人资料目录ä¸çš„ README 对其进行åˆå§‹åŒ–以开始使用。 +repo_name_helper=ç†æƒ³çš„仓库å称应由简çŸã€æœ‰æ„义和独特的关键è¯ç»„æˆã€‚「.profileã€å’Œã€Œ.profile-privateã€å¯ç”¨äºŽä¸ºç”¨æˆ·/ç»„ç»‡æ·»åŠ README.md。 repo_size=ä»“åº“å¤§å° template=æ¨¡æ¿ template_select=é€‰æ‹©æ¨¡æ¿ @@ -1050,10 +1050,10 @@ visibility_fork_helper=(修改该值将会影å“到所有派生仓库) clone_helper=ä¸çŸ¥é“如何克隆?查看<a target="_blank" rel="noopener noreferrer" href="%s">帮助</a> 。 fork_repo=派生仓库 fork_from=派生自 -already_forked=ä½ å·²ç»æ´¾ç”Ÿè¿‡ %s +already_forked=æ‚¨å·²ç»æ´¾ç”Ÿè¿‡ %s fork_to_different_account=æ´¾ç”Ÿåˆ°å…¶ä»–è´¦å· fork_visibility_helper=æ— æ³•æ›´æ”¹æ´¾ç”Ÿä»“åº“çš„å¯è§æ€§ã€‚ -fork_branch=è¦å…‹éš†åˆ° Fork 的分支 +fork_branch=è¦å…‹éš†ä¸ºæ´¾ç”Ÿçš„分支 all_branches=所有分支 view_all_branches=查看所有分支 view_all_tags=æŸ¥çœ‹æ‰€æœ‰æ ‡ç¾ @@ -1076,15 +1076,15 @@ issue_labels=工啿 ‡ç¾ issue_labels_helper=é€‰æ‹©ä¸€ä¸ªå·¥å•æ ‡ç¾é›† license=授æƒè®¸å¯ license_helper=选择授æƒè®¸å¯æ–‡ä»¶ã€‚ -license_helper_desc=许å¯è¯è¯´æ˜Žäº†å…¶ä»–人å¯ä»¥å’Œä¸å¯ä»¥ç”¨æ‚¨çš„代ç åšä»€ä¹ˆã€‚ä¸ç¡®å®šå“ªä¸€ä¸ªé€‚åˆä½ çš„é¡¹ç›®ï¼Ÿè§ <a target="_blank" rel="noopener noreferrer" href="%s">选择一个许å¯è¯</a> +license_helper_desc=许å¯è¯è¯´æ˜Žäº†å…¶ä»–人å¯ä»¥å’Œä¸å¯ä»¥ç”¨æ‚¨çš„代ç åšä»€ä¹ˆã€‚ä¸ç¡®å®šå“ªä¸€ä¸ªé€‚åˆæ‚¨çš„é¡¹ç›®ï¼Ÿè§ <a target="_blank" rel="noopener noreferrer" href="%s">选择一个许å¯è¯</a> multiple_licenses=多许å¯è¯ object_format=å¯¹è±¡æ ¼å¼ object_format_helper=ä»“åº“çš„å¯¹è±¡æ ¼å¼ã€‚ä¹‹åŽæ— 法更改。SHA1 是最兼容的。 readme=自述 readme_helper=选择自述文件模æ¿ã€‚ readme_helper_desc=这是您å¯ä»¥ä¸ºæ‚¨çš„项目撰写完整æè¿°çš„地方。 -auto_init=åˆå§‹åŒ–仓库(æ·»åŠ . gitignoreã€è®¸å¯è¯å’Œè‡ªè¿°æ–‡ä»¶) -trust_model_helper=选择ç¾å验è¯çš„“信任模型â€ã€‚å¯èƒ½çš„选项是: +auto_init=åˆå§‹åŒ–ä»“åº“ï¼ˆæ·»åŠ .gitignoreã€è®¸å¯è¯å’Œè‡ªè¿°æ–‡ä»¶ï¼‰ +trust_model_helper=选择ç¾å验è¯çš„信任模型。å¯èƒ½çš„选项是: trust_model_helper_collaborator=å作者:信任å作者的ç¾å trust_model_helper_committer=æäº¤è€…:信任与æäº¤è€…相符的ç¾å trust_model_helper_collaborator_committer=å作者+æäº¤è€…:信任åä½œè€…åŒæ—¶æ˜¯æäº¤è€…çš„ç¾å @@ -1106,13 +1106,13 @@ mirror_address_protocol_invalid=æä¾›çš„URLæ— æ•ˆã€‚åªèƒ½ä½¿ç”¨http(s)://或gi mirror_lfs=大文件å˜å‚¨ (LFS) mirror_lfs_desc=é•œåƒ LFS æ•°æ®ã€‚ mirror_lfs_endpoint=LFS ç½‘å€ -mirror_lfs_endpoint_desc=åŒæ¥å°†å°è¯•ä½¿ç”¨å…‹éš†ç½‘å€æ¥ <a target="_blank" rel="noopener noreferrer" href="%s">确定 LFS æœåС噍</a>。如果仓库 LFS æ•°æ®å˜å‚¨åœ¨å…¶ä»–ä½ç½®ï¼Œä½ 还å¯ä»¥æŒ‡å®šè‡ªå®šä¹‰ç½‘å€ã€‚ +mirror_lfs_endpoint_desc=åŒæ¥å°†å°è¯•ä½¿ç”¨å…‹éš†ç½‘å€æ¥ <a target="_blank" rel="noopener noreferrer" href="%s">确定 LFS æœåС噍</a>。如果仓库 LFS æ•°æ®å˜å‚¨åœ¨å…¶ä»–ä½ç½®ï¼Œæ‚¨è¿˜å¯ä»¥æŒ‡å®šè‡ªå®šä¹‰ç½‘å€ã€‚ mirror_last_synced=ä¸Šæ¬¡åŒæ¥ mirror_password_placeholder=(未更改) mirror_password_blank_placeholder=(未设置) mirror_password_help=更改用户åä»¥åˆ é™¤å·²å‚¨å˜çš„密ç 。 watchers=关注者 -stargazers=称赞者 +stargazers=已赞者 stars_remove_warning=这将清除æ¤ä»“库的所有点赞数。 forks=派生仓库 stars=点赞数 @@ -1136,11 +1136,11 @@ user_search_tooltip=最多显示30å用户 tree_path_not_found=%[2]s ä¸ä¸å˜åœ¨è·¯å¾„ %[1]s transfer.accept=接å—转移 -transfer.accept_desc=`转移到 "%s"` +transfer.accept_desc=转移到「%s〠transfer.reject=æ‹’ç»è½¬ç§» -transfer.reject_desc=`å–æ¶ˆè½¬ç§»åˆ° "%s"` -transfer.no_permission_to_accept=您没有æƒé™æŽ¥å—æ¤è½¬è®©ã€‚ -transfer.no_permission_to_reject=您没有æƒé™æ‹’ç»æ¤è½¬è®©ã€‚ +transfer.reject_desc=å–æ¶ˆè½¬ç§»åˆ°ã€Œ%s〠+transfer.no_permission_to_accept=您没有æƒé™æŽ¥å—æ¤è½¬ç§»ã€‚ +transfer.no_permission_to_reject=您没有æƒé™æ‹’ç»æ¤è½¬ç§»ã€‚ desc.private=ç§æœ‰åº“ desc.public=公开 @@ -1151,9 +1151,9 @@ desc.archived=å·²å˜æ¡£ desc.sha256=SHA256 template.items=模æ¿é€‰é¡¹ -template.git_content=Gitæ•°æ®(默认分支) +template.git_content=Git æ•°æ®ï¼ˆé»˜è®¤åˆ†æ”¯ï¼‰ template.git_hooks=Git é’©å -template.git_hooks_tooltip=ä½ ç›®å‰æ— æ³•ä¿®æ”¹æˆ–åˆ é™¤è¢«æ·»åŠ è¿‡çš„ Git Hookã€‚ä»…å½“ä½ ä¿¡ä»»æ¨¡æ¿ä»“库时æ‰å¯ä»¥é€‰æ‹©æ¤é¡¹ã€‚ +template.git_hooks_tooltip=æ‚¨ç›®å‰æ— æ³•ä¿®æ”¹æˆ–åˆ é™¤è¢«æ·»åŠ è¿‡çš„ Git é’©å。仅当您信任模æ¿ä»“库时æ‰å¯ä»¥é€‰æ‹©æ¤é¡¹ã€‚ template.webhooks=Web é’©å template.topics=主题 template.avatar=å¤´åƒ @@ -1166,9 +1166,9 @@ archive.title_date=该仓库已于 %s 归档。您å¯ä»¥æŸ¥çœ‹æ–‡ä»¶æˆ–克隆它 archive.issue.nocomment=æ¤ä»“åº“å·²å˜æ¡£ï¼Œæ‚¨ä¸èƒ½åœ¨æ¤å·¥å•æ·»åŠ è¯„è®ºã€‚ archive.pull.nocomment=æ¤ä»“åº“å·²å˜æ¡£ï¼Œæ‚¨ä¸èƒ½åœ¨æ¤åˆå¹¶è¯·æ±‚æ·»åŠ è¯„è®ºã€‚ -form.reach_limit_of_creation_1=ä½ å·²ç»è¾¾åˆ°äº† %d 仓库的上é™ã€‚ -form.reach_limit_of_creation_n=ä½ å·²ç»è¾¾åˆ°äº† %d 个仓库的上é™ã€‚ -form.name_reserved=仓库åç§° %s 是被ä¿ç•™çš„。 +form.reach_limit_of_creation_1=您已ç»è¾¾åˆ°äº† %d 仓库的上é™ã€‚ +form.reach_limit_of_creation_n=您已ç»è¾¾åˆ°äº† %d 个仓库的上é™ã€‚ +form.name_reserved=仓库åç§° %s 是ä¿ç•™çš„。 form.name_pattern_not_allowed=仓库åç§°ä¸ä¸å…许使用 %s æ ¼å¼ã€‚ need_auth=æŽˆæƒ @@ -1177,7 +1177,7 @@ migrate_service=è¿ç§»æœåŠ¡ migrate_options_mirror_helper=è¯¥ä»“åº“å°†æ˜¯ä¸€ä¸ªé•œåƒ migrate_options_lfs=è¿ç§» LFS 文件 migrate_options_lfs_endpoint.label=LFS ç½‘å€ -migrate_options_lfs_endpoint.description=è¿ç§»å°†å°è¯•ä½¿ç”¨ä½ çš„ Git remote æ¥ <a target="_blank" rel="noopener noreferrer" href="%s">确定 LFS æœåС噍</a>。如果仓库 LFS æ•°æ®å˜å‚¨åœ¨å…¶ä»–ä½ç½®ï¼Œä½ 还å¯ä»¥æŒ‡å®šè‡ªå®šä¹‰ç½‘å€ã€‚ +migrate_options_lfs_endpoint.description=è¿ç§»å°†å°è¯•使用您的 Git remote æ¥ <a target="_blank" rel="noopener noreferrer" href="%s">确定 LFS æœåС噍</a>。如果仓库 LFS æ•°æ®å˜å‚¨åœ¨å…¶ä»–ä½ç½®ï¼Œæ‚¨è¿˜å¯ä»¥æŒ‡å®šè‡ªå®šä¹‰ç½‘å€ã€‚ migrate_options_lfs_endpoint.description.local=æ”¯æŒæœ¬åœ°æœåŠ¡å™¨è·¯å¾„ã€‚ migrate_options_lfs_endpoint.placeholder=如果留空,网å€å°†ä»Žå…‹éš† URL ä¸å¾—到 migrate_items=è¿ç§»é¡¹ç›® @@ -1187,7 +1187,7 @@ migrate_items_labels=æ ‡ç¾ migrate_items_issues=å·¥å• migrate_items_pullrequests=åˆå¹¶è¯·æ±‚ migrate_items_merge_requests=åˆå¹¶è¯·æ±‚ -migrate_items_releases=版本å‘布 +migrate_items_releases=å‘布 migrate_repo=è¿ç§»ä»“库 migrate.clone_address=从 URL è¿ç§»/克隆 migrate.clone_address_desc=现有仓库的 HTTP(s) 或 Git "clone" URL @@ -1261,14 +1261,14 @@ branch=分支 tree=ç›®å½•æ ‘ clear_ref=`清除当å‰å¼•用` filter_branch_and_tag=è¿‡æ»¤åˆ†æ”¯æˆ–æ ‡ç¾ -find_tag=查找Gitæ ‡ç¾ +find_tag=查找 Git æ ‡ç¾ branches=分支列表 tags=æ ‡ç¾åˆ—表 issues=å·¥å• pulls=åˆå¹¶è¯·æ±‚ projects=项目 packages=软件包 -actions=Actions +actions=å·¥ä½œæµ labels=æ ‡ç¾ org_labels_desc=ç»„ç»‡çº§åˆ«çš„æ ‡ç¾ï¼Œå¯ä»¥è¢«æœ¬ç»„织下的 <strong>所有仓库</strong> 使用 org_labels_desc_manage=ç®¡ç† @@ -1277,9 +1277,9 @@ milestone=里程碑 milestones=里程碑 commits=æäº¤ commit=æäº¤ -release=版本å‘布 -releases=版本å‘布 -tag=Gitæ ‡ç¾ +release=å‘布 +releases=å‘布 +tag=Git æ ‡ç¾ released_this=å‘布 tagged_this=å·²æ ‡è®° file.title=%s ä½äºŽ %s @@ -1339,9 +1339,9 @@ editor.must_be_on_a_branch=您必须在æŸä¸ªåˆ†æ”¯ä¸Šæ‰èƒ½å¯¹æ¤æ–‡ä»¶è¿›è¡Œä¿ editor.fork_before_edit=您必须在派生这个仓库æ‰èƒ½å¯¹æ¤æ–‡ä»¶è¿›è¡Œä¿®æ”¹æ“作 editor.delete_this_file=åˆ é™¤æ–‡ä»¶ editor.must_have_write_access=您必须具有写æƒé™æ‰èƒ½å¯¹æ¤æ–‡ä»¶è¿›è¡Œä¿®æ”¹æ“作。 -editor.file_delete_success=文件 %s å·²è¢«åˆ é™¤ã€‚ +editor.file_delete_success=文件「%sã€å·²åˆ 除。 editor.name_your_file=命忖‡ä»¶... -editor.filename_help=通过键入åç§°åŽè·Ÿæ–œçº¿ ("/") æ¥æ·»åŠ ç›®å½•ã€‚é€šè¿‡åœ¨è¾“å…¥æ¡†çš„å¼€å¤´é”®å…¥ "é€€æ ¼" æ¥åˆ 除目录。 +editor.filename_help=通过键入åç§°åŽè·Ÿæ–œçº¿ ("/") æ¥æ·»åŠ ç›®å½•ã€‚é€šè¿‡åœ¨è¾“å…¥æ¡†çš„å¼€å¤´é”®å…¥ã€Œé€€æ ¼ã€æ¥åˆ 除目录。 editor.or=或 editor.cancel_lower=å–æ¶ˆ editor.commit_signed_changes=æäº¤å·²ç¾å的更改 @@ -1352,7 +1352,7 @@ editor.update=æ›´æ–° %s editor.delete=åˆ é™¤ %s editor.patch=åº”ç”¨è¡¥ä¸ editor.patching=打补ä¸ï¼š -editor.fail_to_apply_patch=æ— æ³•åº”ç”¨è¡¥ä¸ %s +editor.fail_to_apply_patch=æ— æ³•åº”ç”¨è¡¥ä¸ã€Œ%s〠editor.new_patch=æ–°è¡¥ä¸ editor.commit_message_desc=æ·»åŠ ä¸€ä¸ªå¯é€‰çš„æ‰©å±•æè¿°... editor.signoff_desc=在æäº¤æ—¥å¿—æ¶ˆæ¯æœ«å°¾æ·»åŠ ç¾ç½²äººä¿¡æ¯ã€‚ @@ -1364,42 +1364,42 @@ editor.new_branch_name=为这次æäº¤çš„æ–°åˆ†æ”¯å‘½å editor.new_branch_name_desc=新的分支åç§°... editor.cancel=å–æ¶ˆ editor.filename_cannot_be_empty=文件åä¸èƒ½ä¸ºç©ºã€‚ -editor.filename_is_invalid=文件å %s æ— æ•ˆ +editor.filename_is_invalid=æ–‡ä»¶åæ— 效:「%sã€ã€‚ editor.commit_email=æäº¤é‚®ç®±åœ°å€ editor.invalid_commit_email=æäº¤çš„é‚®ç®±åœ°å€æ— 效。 -editor.branch_does_not_exist=æ¤ä»“库ä¸ä¸å˜åœ¨å为 %s 的分支。 -editor.branch_already_exists=æ¤ä»“库已å˜åœ¨å为 %s 的分支。 -editor.directory_is_a_file=%s å·²ç»ä½œä¸ºæ–‡ä»¶å在æ¤ä»“库ä¸å˜åœ¨ã€‚ -editor.file_is_a_symlink=`"%s" 是一个符å·é“¾æŽ¥ï¼Œæ— 法在 web 编辑器ä¸ç¼–辑` -editor.filename_is_a_directory=æ¤ä»“库ä¸å·²å˜åœ¨å为“%s†的目录。 -editor.file_editing_no_longer_exists=æ£åœ¨ç¼–辑的文件 %s å·²ä¸å˜åœ¨ã€‚ -editor.file_deleting_no_longer_exists=æ£åœ¨åˆ 除的文件 %s å·²ä¸å˜åœ¨ã€‚ +editor.branch_does_not_exist=æ¤ä»“库ä¸ä¸å˜åœ¨å为「%sã€çš„分支。 +editor.branch_already_exists=æ¤ä»“库已å˜åœ¨å为「%sã€çš„分支。 +editor.directory_is_a_file=目录å「%sã€å·²ä½œä¸ºæ–‡ä»¶å在æ¤ä»“库ä¸å˜åœ¨ã€‚ +editor.file_is_a_symlink=`「%sã€æ˜¯ä¸€ä¸ªç¬¦å·é“¾æŽ¥ï¼Œæ— 法在 Web 编辑器ä¸ç¼–辑` +editor.filename_is_a_directory=文件å「%sã€å·²ä½œä¸ºç›®å½•å在æ¤ä»“库ä¸å˜åœ¨ã€‚ +editor.file_editing_no_longer_exists=æ£åœ¨ç¼–辑的文件「%sã€å·²ä¸å˜åœ¨äºŽæ¤ä»“库。 +editor.file_deleting_no_longer_exists=æ£åœ¨åˆ 除的文件「%sã€å·²ä¸å˜åœ¨äºŽæ¤ä»“库。 editor.file_changed_while_editing=文件内容在您进行编辑时已ç»å‘生å˜åŠ¨ã€‚<a target="_blank" rel="noopener noreferrer" href="%s">å•击æ¤å¤„</a> 查看å˜åŠ¨çš„å…·ä½“å†…å®¹ï¼Œæˆ–è€… <strong>冿¬¡æäº¤</strong> 覆盖已å‘生的å˜åŠ¨ã€‚ -editor.file_already_exists=æ¤ä»“库已ç»å˜åœ¨å为 %s 的文件。 -editor.commit_id_not_matching=æäº¤ID与您开始编辑时的IDä¸åŒ¹é…。请æäº¤åˆ°è¡¥ä¸åˆ†æ”¯ç„¶åŽåˆå¹¶ã€‚ +editor.file_already_exists=æ¤ä»“库已ç»å˜åœ¨å为「%sã€çš„æ–‡ä»¶ã€‚ +editor.commit_id_not_matching=æäº¤ ID 与您开始编辑时的 ID ä¸åŒ¹é…。请æäº¤åˆ°è¡¥ä¸åˆ†æ”¯ç„¶åŽåˆå¹¶ã€‚ editor.push_out_of_date=推é€ä¼¼ä¹Žå·²ç»è¿‡æ—¶ã€‚ editor.commit_empty_file_header=æäº¤ä¸€ä¸ªç©ºæ–‡ä»¶ editor.commit_empty_file_text=æ‚¨è¦æäº¤çš„æ–‡ä»¶æ˜¯ç©ºçš„ï¼Œç»§ç»å—? editor.no_changes_to_show=没有å¯ä»¥æ˜¾ç¤ºçš„å˜æ›´ã€‚ -editor.fail_to_update_file=æ›´æ–°/创建文件 %s 失败。 +editor.fail_to_update_file=æ›´æ–°/创建文件「%sã€å¤±è´¥ã€‚ editor.fail_to_update_file_summary=错误信æ¯ï¼š -editor.push_rejected_no_message=æ¤ä¿®æ”¹è¢«æœåŠ¡å™¨æ‹’ç»å¹¶ä¸”没有å馈消æ¯ã€‚请检查 Git Hook。 -editor.push_rejected=æ¤ä¿®æ”¹è¢«æœåŠ¡å™¨æ‹’ç»ã€‚请检查 Git Hook。 +editor.push_rejected_no_message=æ¤ä¿®æ”¹è¢«æœåŠ¡å™¨æ‹’ç»å¹¶ä¸”没有å馈消æ¯ã€‚请检查 Git é’©å。 +editor.push_rejected=æ¤ä¿®æ”¹è¢«æœåŠ¡å™¨æ‹’ç»ã€‚请检查 Git é’©å。 editor.push_rejected_summary=详细拒ç»ä¿¡æ¯ï¼š editor.add_subdir=æ·»åŠ ç›®å½• -editor.unable_to_upload_files=ä¸Šä¼ æ–‡ä»¶è‡³ %s æ—¶å‘生错误:%v -editor.upload_file_is_locked=文件 %s 被 %s é”定。 -editor.upload_files_to_dir=ä¸Šä¼ æ–‡ä»¶è‡³ %s -editor.cannot_commit_to_protected_branch=ä¸å¯ä»¥æäº¤åˆ°å—ä¿æŠ¤çš„åˆ†æ”¯ %s。 +editor.unable_to_upload_files=ä¸Šä¼ æ–‡ä»¶è‡³ã€Œ%sã€å¤±è´¥ï¼š%v +editor.upload_file_is_locked=文件「%sã€è¢« %s é”定。 +editor.upload_files_to_dir=ä¸Šä¼ æ–‡ä»¶è‡³ã€Œ%s〠+editor.cannot_commit_to_protected_branch=ä¸å¯ä»¥æäº¤åˆ°å—ä¿æŠ¤çš„åˆ†æ”¯ã€Œ%sã€ã€‚ editor.no_commit_to_branch=æ— æ³•ç›´æŽ¥æäº¤åˆ†æ”¯ï¼Œå› 为: editor.user_no_push_to_branch=用户ä¸èƒ½æŽ¨é€åˆ°åˆ†æ”¯ editor.require_signed_commit=分支需è¦ç¾åæäº¤ -editor.cherry_pick=Cherry-pick %s 到: +editor.cherry_pick=拣选æäº¤ %s 到: editor.revert=å°† %s 还原到: commits.desc=æµè§ˆä»£ç ä¿®æ”¹åŽ†å² commits.commits=æ¬¡ä»£ç æäº¤ -commits.no_commits=没有共åŒçš„æäº¤ã€‚%s å’Œ %s 的历å²å®Œå…¨ä¸åŒã€‚ +commits.no_commits=没有共åŒçš„æäº¤ã€‚「%sã€å’Œã€Œ%sã€çš„历å²å®Œå…¨ä¸åŒã€‚ commits.nothing_to_compare=这些分支是相åŒçš„。 commits.search.tooltip=`您å¯ä»¥åœ¨å…³é”®è¯å‰åŠ ä¸Šå‰ç¼€ï¼Œå¦‚"author:", "committer:", "after:", 或"before:", 例如 "retrin author:Alice before:2019-01-13"` commits.search_branch=æ¤åˆ†æ”¯ @@ -1419,11 +1419,11 @@ commits.view_file_diff=查看æäº¤ä¸çš„æ–‡ä»¶æ›´æ”¹ commit.operations=æ“作 commit.revert=还原 -commit.revert-header=还原: %s +commit.revert-header=还原:%s commit.revert-content=选择è¦è¿˜åŽŸçš„åˆ†æ”¯ï¼š -commit.cherry-pick=Cherry-pick -commit.cherry-pick-header=Cherry-pick: %s -commit.cherry-pick-content=选择 cherry-pick çš„ç›®æ ‡åˆ†æ”¯ï¼š +commit.cherry-pick=拣选æäº¤ +commit.cherry-pick-header=拣选æäº¤ï¼š%s +commit.cherry-pick-content=é€‰æ‹©è¦æ‹£é€‰æäº¤çš„ç›®æ ‡åˆ†æ”¯ï¼š commitstatus.error=错误 commitstatus.failure=失败 @@ -1440,14 +1440,14 @@ projects.create=创建项目 projects.title=æ ‡é¢˜ projects.new=创建项目 projects.new_subheader=在一个地方åè°ƒã€è·Ÿè¸ªå’Œæ›´æ–°æ‚¨çš„å·¥ä½œï¼Œè®©é¡¹ç›®ä¿æŒé€æ˜Žå¹¶æŒ‰è®¡åˆ’进行。 -projects.create_success=项目 %s 创建æˆåŠŸã€‚ +projects.create_success=项目「%sã€åˆ›å»ºæˆåŠŸã€‚ projects.deletion=åˆ é™¤é¡¹ç›® projects.deletion_desc=åˆ é™¤é¡¹ç›®ä¼šä»Žæ‰€æœ‰ç›¸å…³çš„å·¥å•ä¸ç§»é™¤å®ƒã€‚是å¦ç»§ç»ï¼Ÿ -projects.deletion_success=è¯¥é¡¹ç›®å·²è¢«åˆ é™¤ã€‚ +projects.deletion_success=è¯¥é¡¹ç›®å·²åˆ é™¤ã€‚ projects.edit=编辑项目 projects.edit_subheader=项目用于组织工å•和跟踪进展情况。 projects.modify=更新项目 -projects.edit_success=项目 %s æ›´æ–°æˆåŠŸã€‚ +projects.edit_success=项目「%sã€æ›´æ–°æˆåŠŸã€‚ projects.type.none=æ— projects.type.basic_kanban=åŸºç¡€çœ‹æ¿ projects.type.bug_triage=Bugåˆ†ç±»çœ‹æ¿ @@ -1461,7 +1461,7 @@ projects.column.new=创建列 projects.column.set_default=设为默认 projects.column.set_default_desc=设置æ¤åˆ—为未分类问题和åˆå¹¶è¯·æ±‚的默认值 projects.column.delete=åˆ é™¤åˆ— -projects.column.deletion_desc=åˆ é™¤é¡¹ç›®åˆ—ä¼šå°†æ‰€æœ‰ç›¸å…³é—®é¢˜ç§»åˆ°â€œæœªåˆ†ç±»â€ã€‚是å¦ç»§ç»ï¼Ÿ +projects.column.deletion_desc=åˆ é™¤é¡¹ç›®åˆ—ä¼šå°†æ‰€æœ‰ç›¸å…³é—®é¢˜ç§»è‡³é»˜è®¤åˆ—ã€‚æ˜¯å¦ç»§ç»ï¼Ÿ projects.column.color=颜色 projects.open=å¼€å¯ projects.close=å…³é— @@ -1513,12 +1513,12 @@ issues.new_label_placeholder=æ ‡ç¾åç§° issues.new_label_desc_placeholder=æè¿° issues.create_label=åˆ›å»ºæ ‡ç¾ issues.label_templates.title=åŠ è½½é¢„å®šä¹‰çš„æ ‡ç¾æ¨¡æ¿ -issues.label_templates.info=è¿˜æ²¡æœ‰ä»»ä½•æ ‡ç¾ã€‚您å¯ä»¥ä½¿ç”¨'åˆ›å»ºæ ‡ç¾'æŒ‰é’®æˆ–è€…åŠ è½½é¢„å®šä¹‰çš„æ ‡ç¾é›†åˆ›å»ºæ ‡ç¾ +issues.label_templates.info=è¿˜æ²¡æœ‰ä»»ä½•æ ‡ç¾ã€‚您å¯ä»¥ä½¿ç”¨ã€Œåˆ›å»ºæ ‡ç¾ã€æŒ‰é’®æˆ–è€…åŠ è½½é¢„å®šä¹‰çš„æ ‡ç¾é›†åˆ›å»ºæ ‡ç¾ï¼š issues.label_templates.helper=é€‰æ‹©æ ‡ç¾æ¨¡æ¿ issues.label_templates.use=ä½¿ç”¨æ ‡ç¾é›† -issues.label_templates.fail_to_load_file=åŠ è½½æ ‡ç¾æ¨¡æ¿æ–‡ä»¶ %s æ—¶å‘生错误:%v +issues.label_templates.fail_to_load_file=åŠ è½½æ ‡ç¾æ¨¡æ¿æ–‡ä»¶ã€Œ%sã€æ—¶å‘生错误:%v issues.add_label=于 %[2]s æ·»åŠ äº†æ ‡ç¾ %[1]s -issues.add_labels=于 %s æ·»åŠ %s æ ‡ç¾ +issues.add_labels=于 %[2]s æ·»åŠ äº†æ ‡ç¾ %[1]s issues.remove_label=于 %[2]s åˆ é™¤äº†æ ‡ç¾ %[1]s issues.remove_labels=于 %[2]s åˆ é™¤äº†æ ‡ç¾ %[1]s issues.add_remove_labels=于 %[3]s æ·»åŠ äº†æ ‡ç¾ %[1]s ï¼Œåˆ é™¤äº†æ ‡ç¾ %[2]s @@ -1532,7 +1532,7 @@ issues.remove_project_at=`于 %[2]s å°†æ¤å·¥å•从项目 <b>%[1]s</b> ä¸åˆ é™ issues.deleted_milestone=ï¼ˆå·²åˆ é™¤ï¼‰ issues.deleted_project=`(å·²åˆ é™¤)` issues.self_assign_at=`于 %s 指派给自己` -issues.add_assignee_at=`于 %[2]s 被 <b>%[1]s</b> 指派` +issues.add_assignee_at=`于 %[2]s ç”± <b>%[1]s</b> 指派` issues.remove_assignee_at=`<b>%s</b> å–æ¶ˆäº†æŒ‡æ´¾åœ¨ %s` issues.remove_self_assignment=`于 %s å–æ¶ˆäº†æŒ‡æ´¾` issues.change_title_at=`于 %[3]s ä¿®æ”¹æ ‡é¢˜ <b><strike>%[1]s</strike></b> 为 <b>%[2]s</b>` @@ -1589,11 +1589,11 @@ issues.action_assignee_no_select=未指派 issues.action_check=选ä¸/å–æ¶ˆé€‰ä¸ issues.action_check_all=选ä¸/å–æ¶ˆé€‰ä¸æ‰€æœ‰é¡¹ç›® issues.opened_by=ç”± <a href="%[2]s">%[3]s</a> 于 %[1]s创建 -pulls.merged_by=ç”± <a href="%[2]s">%[3]s</a> 创建,被åˆå¹¶äºŽ %[1]s -pulls.merged_by_fake=ç”± %[2]s 创建,被åˆå¹¶äºŽ %[1]s -issues.closed_by=ç”± <a href="%[2]s">%[3]s</a> 创建,被关é—于 %[1]s +pulls.merged_by=ç”± <a href="%[2]s">%[3]s</a> 创建,åˆå¹¶äºŽ %[1]s +pulls.merged_by_fake=ç”± %[2]s 创建,åˆå¹¶äºŽ %[1]s +issues.closed_by=ç”± <a href="%[2]s">%[3]s</a> 创建,关é—于 %[1]s issues.opened_by_fake=ç”± %[2]s 于 %[1]s 打开 -issues.closed_by_fake=ç”± %[2]s 创建,被关é—于 %[1]s +issues.closed_by_fake=ç”± %[2]s 创建,关é—于 %[1]s issues.previous=上一页 issues.next=下一页 issues.open_title=å¼€å¯ä¸ @@ -1668,23 +1668,23 @@ issues.label_delete=åˆ é™¤ issues.label_modify=ç¼–è¾‘æ ‡ç¾ issues.label_deletion=åˆ é™¤æ ‡ç¾ issues.label_deletion_desc=åˆ é™¤æ ‡ç¾ä¼šå°†å…¶ä»Žæ‰€æœ‰é—®é¢˜ä¸åˆ 除。继ç»ï¼Ÿ -issues.label_deletion_success=è¯¥æ ‡ç¾å·²è¢«åˆ 除。 +issues.label_deletion_success=è¯¥æ ‡ç¾å·²åˆ 除。 issues.label.filter_sort.alphabetically=æŒ‰å—æ¯é¡ºåºæŽ’åº issues.label.filter_sort.reverse_alphabetically=æŒ‰å—æ¯é€†åºæŽ’åº issues.label.filter_sort.by_size=最å°å°ºå¯¸ issues.label.filter_sort.reverse_by_size=最大尺寸 issues.num_participants=%d åå‚与者 -issues.attachment.open_tab=`åœ¨æ–°çš„æ ‡ç¾é¡µä¸æŸ¥çœ‹ '%s'` -issues.attachment.download=`点击下载 '%s'` +issues.attachment.open_tab=`åœ¨æ–°çš„æ ‡ç¾é¡µä¸æŸ¥çœ‹ã€Œ%sã€` +issues.attachment.download=`点击下载「%sã€` issues.subscribe=订阅 issues.unsubscribe=å–æ¶ˆè®¢é˜… issues.unpin=å–æ¶ˆç½®é¡¶ issues.max_pinned=您ä¸èƒ½ç½®é¡¶æ›´å¤šå·¥å• -issues.pin_comment=于 %s 被置顶 +issues.pin_comment=于 %s 置顶 issues.unpin_comment=于 %s å–æ¶ˆç½®é¡¶ issues.lock=é”å®šå¯¹è¯ issues.unlock=è§£é”å¯¹è¯ -issues.lock_duplicate=一个工å•ä¸èƒ½è¢«é”定两次。 +issues.lock_duplicate=一个工å•ä¸èƒ½é”定两次。 issues.unlock_error=æ— æ³•è§£é”一个未é”定的工å•。 issues.lock_with_reason=å› ä¸º <strong>%s</strong> 而é”定,并将对è¯é™åˆ¶ä¸ºå作者 %s issues.lock_no_reason=é”定并é™åˆ¶ä»…å作者 %s @@ -1711,13 +1711,13 @@ issues.timetracker_timer_discard=åˆ é™¤è®¡æ—¶å™¨ issues.timetracker_timer_manually_add=æ·»åŠ æ—¶é—´ issues.time_estimate_set=设置预计时间 -issues.time_estimate_display=预计: %s +issues.time_estimate_display=预估:%s issues.change_time_estimate_at=预估时间已修改为 <b>%[1]s</b> %[2]s -issues.remove_time_estimate_at=åˆ é™¤é¢„è®¡æ—¶é—´ %s +issues.remove_time_estimate_at=åˆ é™¤é¢„ä¼°æ—¶é—´ %s issues.time_estimate_invalid=é¢„è®¡æ—¶é—´æ ¼å¼æ— 效 issues.start_tracking_history=`开始工作 %s` issues.tracker_auto_close=当æ¤å·¥å•关闿—¶ï¼Œè‡ªåŠ¨åœæ¢è®¡æ—¶å™¨ -issues.tracking_already_started=`ä½ å·²ç»å¼€å§‹å¯¹ <a href="%s">å¦ä¸€ä¸ªå·¥å•</a> 进行时间跟踪ï¼` +issues.tracking_already_started=`您已ç»å¼€å§‹å¯¹ <a href="%s">å¦ä¸€ä¸ªå·¥å•</a> 进行时间跟踪ï¼` issues.stop_tracking=åœæ¢è®¡æ—¶å™¨ issues.stop_tracking_history=工作 <b>%[1]s</b> 于 %[2]s åœæ¢ issues.cancel_tracking=å–æ¶ˆ @@ -1733,7 +1733,7 @@ issues.time_spent_total=总用时 issues.time_spent_from_all_authors=`总花费时间:%s` issues.due_date=到期时间 -issues.invalid_due_date_format=åˆ°æœŸæ—¶é—´çš„æ ¼å¼å¿…须是 'yyyy-mm-dd' 的形å¼ã€‚ +issues.invalid_due_date_format=åˆ°æœŸæ—¶é—´çš„æ ¼å¼å¿…须是「yyyy-mm-ddã€çš„å½¢å¼ã€‚ issues.error_modifying_due_date=修改到期时间失败。 issues.error_removing_due_date=åˆ é™¤åˆ°æœŸæ—¶é—´å¤±è´¥ã€‚ issues.push_commit_1=于 %[2]s 推é€äº† %[1]d 个æäº¤ @@ -1776,7 +1776,7 @@ issues.dependency.remove_header=åˆ é™¤ä¾èµ–项 issues.dependency.issue_remove_text=æ¤æ“作将从工å•ä¸åˆ 除ä¾èµ–。是å¦è¦ç»§ç»? issues.dependency.pr_remove_text=æ¤æ“作将从åˆå¹¶è¯·æ±‚ä¸åˆ 除ä¾èµ–。是å¦è¦ç»§ç»? issues.dependency.setting=为工å•å’Œåˆå¹¶è¯·æ±‚å¯ç”¨ä¾èµ– -issues.dependency.add_error_same_issue=ä½ ä¸èƒ½è®©ä¸€ä¸ªå·¥å•ä¾èµ–于自己。 +issues.dependency.add_error_same_issue=您ä¸èƒ½è®©ä¸€ä¸ªå·¥å•ä¾èµ–于自身。 issues.dependency.add_error_dep_issue_not_exist=ä¾èµ–项ä¸å˜åœ¨ã€‚ issues.dependency.add_error_dep_not_exist=ä¾èµ–项ä¸å˜åœ¨ã€‚ issues.dependency.add_error_dep_exists=ä¾èµ–项已å˜åœ¨ã€‚ @@ -1818,9 +1818,9 @@ issues.review.stale=批准åŽå·²æ›´æ–° issues.review.unofficial=éžå®˜æ–¹å®¡æ‰¹æ•° issues.assignee.error=å› ä¸ºæœªçŸ¥åŽŸå› ï¼Œå¹¶éžæ‰€æœ‰çš„æŒ‡æ´¾éƒ½æˆåŠŸã€‚ issues.reference_issue.body=内容 -issues.content_history.deleted=åˆ é™¤äºŽ -issues.content_history.edited=最åŽç¼–辑于 -issues.content_history.created=创建于 +issues.content_history.deleted=å·²åˆ é™¤ +issues.content_history.edited=已编辑 +issues.content_history.created=已创建 issues.content_history.delete_from_history=从历å²è®°å½•ä¸åˆ 除 issues.content_history.delete_from_history_confirm=从历å²è®°å½•ä¸åˆ 除å—? issues.content_history.options=选项 @@ -1874,7 +1874,7 @@ pulls.merged=å·²åˆå¹¶ pulls.merged_success=åˆå¹¶è¯·æ±‚å·²æˆåŠŸåˆå¹¶å’Œå…³é— pulls.closed=åˆå¹¶è¯·æ±‚å·²å…³é— pulls.manually_merged=已手动åˆå¹¶ -pulls.merged_info_text=分支 %s 现在å¯ä»¥è¢«åˆ 除了。 +pulls.merged_info_text=分支 %s 现在å¯ä»¥åˆ 除了。 pulls.is_closed=åˆå¹¶è¯·æ±‚å·²ç»å…³é—。 pulls.title_wip_desc=`<a href="#">æ ‡é¢˜ä»¥ <strong>%s</strong> 开头</a>以å…åˆå¹¶è¯·æ±‚æ„外åˆå¹¶ã€‚` pulls.cannot_merge_work_in_progress=æ¤åˆå¹¶è¯·æ±‚è¢«æ ‡è®°ä¸ºæ£åœ¨è¿›è¡Œçš„工作。 @@ -1909,7 +1909,7 @@ pulls.waiting_count_1=%d 个æ£åœ¨ç‰å¾…å®¡æ ¸ pulls.waiting_count_n=%d 个æ£åœ¨ç‰å¾…å®¡æ ¸ pulls.wrong_commit_id=æäº¤ id å¿…é¡»åœ¨ç›®æ ‡åˆ†æ”¯ 上 -pulls.no_merge_desc=由于未å¯ç”¨åˆå¹¶é€‰é¡¹ï¼Œæ¤åˆå¹¶è¯·æ±‚æ— æ³•è¢«åˆå¹¶ã€‚ +pulls.no_merge_desc=由于未å¯ç”¨åˆå¹¶é€‰é¡¹ï¼Œæ¤åˆå¹¶è¯·æ±‚æ— æ³•åˆå¹¶ã€‚ pulls.no_merge_helper=在仓库设置ä¸å¯ç”¨åˆå¹¶é€‰é¡¹æˆ–者手工åˆå¹¶è¯·æ±‚。 pulls.no_merge_wip=这个åˆå¹¶è¯·æ±‚æ— æ³•åˆå¹¶ï¼Œå› ä¸ºè¢«æ ‡è®°ä¸ºå°šæœªå®Œæˆçš„工作。 pulls.no_merge_not_ready=æ¤åˆå¹¶è¯·æ±‚尚未准备好åˆå¹¶ï¼Œè¯·æ£€æŸ¥å®¡æ ¸çжæ€å’ŒçŠ¶æ€æ£€æŸ¥ã€‚ @@ -1923,7 +1923,7 @@ pulls.merge_manually=手动åˆå¹¶ pulls.merge_commit_id=åˆå¹¶æäº¤ ID pulls.require_signed_wont_sign=分支需è¦ç¾åçš„æäº¤ï¼Œä½†è¿™ä¸ªåˆå¹¶å°†ä¸ä¼šè¢«ç¾å -pulls.invalid_merge_option=ä½ å¯ä»¥åœ¨æ¤åˆå¹¶è¯·æ±‚ä¸ä½¿ç”¨åˆå¹¶é€‰é¡¹ã€‚ +pulls.invalid_merge_option=您å¯ä»¥åœ¨æ¤åˆå¹¶è¯·æ±‚ä¸ä½¿ç”¨åˆå¹¶é€‰é¡¹ã€‚ pulls.merge_conflict=åˆå¹¶å¤±è´¥ï¼šåˆå¹¶æ—¶æœ‰å†²çªå‘生。æç¤ºï¼šé‡‡ç”¨å…¶å®ƒåˆå¹¶ç–ç•¥ pulls.merge_conflict_summary=é”™è¯¯ä¿¡æ¯ pulls.rebase_conflict=åˆå¹¶å¤±è´¥ï¼šå˜åŸºæäº¤æœ‰å†²çªï¼š%[1]s。æç¤ºï¼šé‡‡ç”¨å…¶å®ƒåˆå¹¶ç–ç•¥ @@ -1931,7 +1931,7 @@ pulls.rebase_conflict_summary=é”™è¯¯ä¿¡æ¯ pulls.unrelated_histories=åˆå¹¶å¤±è´¥ï¼šä¸¤ä¸ªåˆ†æ”¯æ²¡æœ‰å…±åŒåކå²ã€‚æç¤ºï¼šå°è¯•ä¸åŒçš„ç–ç•¥ pulls.merge_out_of_date=åˆå¹¶å¤±è´¥ï¼šåœ¨ç”Ÿæˆåˆå¹¶æ—¶ï¼Œä¸»åˆ†æ”¯å·²æ›´æ–°ã€‚æç¤ºï¼šå†è¯•一次。 pulls.head_out_of_date=åˆå¹¶å¤±è´¥ï¼šåœ¨ç”Ÿæˆåˆå¹¶æ—¶ï¼Œhead 已更新。æç¤ºï¼šå†è¯•一次。 -pulls.has_merged=失败:åˆå¹¶è¯·æ±‚å·²ç»è¢«åˆå¹¶ï¼Œæ‚¨ä¸èƒ½å†æ¬¡åˆå¹¶æˆ–æ›´æ”¹ç›®æ ‡åˆ†æ”¯ã€‚ +pulls.has_merged=失败:åˆå¹¶è¯·æ±‚å·²ç»åˆå¹¶ï¼Œæ‚¨ä¸èƒ½å†æ¬¡åˆå¹¶æˆ–æ›´æ”¹ç›®æ ‡åˆ†æ”¯ã€‚ pulls.push_rejected=推é€å¤±è´¥ï¼šæŽ¨é€è¢«æ‹’ç»ã€‚审查æ¤ä»“库的 Git é’©å。 pulls.push_rejected_summary=详细拒ç»ä¿¡æ¯ pulls.push_rejected_no_message=推é€å¤±è´¥ï¼šæ¤æŽ¨é€è¢«æ‹’ç»ä½†æœªæä¾›å…¶ä»–ä¿¡æ¯ã€‚请检查æ¤ä»“库的 Git é’©å。 @@ -1955,12 +1955,12 @@ pulls.closed_at=`于 <a id="%[1]s" href="#%[1]s">%[2]s</a> 关闿¤åˆå¹¶è¯·æ±‚ pulls.reopened_at=`釿–°æ‰“å¼€æ¤åˆå¹¶è¯·æ±‚ <a id="%[1]s" href="#%[1]s">%[2]s</a>` pulls.cmd_instruction_hint=查看命令行æç¤º pulls.cmd_instruction_checkout_title=检出 -pulls.cmd_instruction_checkout_desc=ä»Žä½ çš„ä»“åº“ä¸æ£€å‡ºä¸€ä¸ªæ–°çš„åˆ†æ”¯å¹¶æµ‹è¯•å˜æ›´ã€‚ +pulls.cmd_instruction_checkout_desc=ä»Žæ‚¨çš„ä»“åº“ä¸æ£€å‡ºä¸€ä¸ªæ–°çš„åˆ†æ”¯å¹¶æµ‹è¯•å˜æ›´ã€‚ pulls.cmd_instruction_merge_title=åˆå¹¶ pulls.cmd_instruction_merge_desc=åˆå¹¶å˜æ›´å¹¶æ›´æ–°åˆ° Gitea 上 -pulls.cmd_instruction_merge_warning=è¦å‘Šï¼šæ¤æ“作ä¸èƒ½åˆå¹¶è¯¥åˆå¹¶è¯·æ±‚ï¼Œå› ä¸ºâ€œè‡ªåŠ¨æ£€æµ‹æ‰‹åŠ¨åˆå¹¶â€æœªå¯ç”¨ +pulls.cmd_instruction_merge_warning=è¦å‘Šï¼šæ¤æ“作ä¸èƒ½åˆå¹¶è¯¥åˆå¹¶è¯·æ±‚ï¼Œå› ä¸ºã€Œè‡ªåŠ¨æ£€æµ‹æ‰‹åŠ¨åˆå¹¶ã€æœªå¯ç”¨ pulls.clear_merge_message=清除åˆå¹¶ä¿¡æ¯ -pulls.clear_merge_message_hint=清除åˆå¹¶æ¶ˆæ¯åªä¼šåˆ 除æäº¤æ¶ˆæ¯å†…容,并ä¿ç•™ç”Ÿæˆçš„ git é™„åŠ å†…å®¹ï¼Œå¦‚â€œCo-Authored-By …â€ã€‚ +pulls.clear_merge_message_hint=清除åˆå¹¶æ¶ˆæ¯åªä¼šåˆ 除æäº¤æ¶ˆæ¯å†…容,并ä¿ç•™ç”Ÿæˆçš„ Git é™„åŠ å†…å®¹ï¼Œå¦‚ã€ŒCo-Authored-By…ã€ã€‚ pulls.auto_merge_button_when_succeed=(当检查æˆåŠŸæ—¶) pulls.auto_merge_when_succeed=在所有检查æˆåŠŸåŽè‡ªåЍåˆå¹¶ @@ -1975,7 +1975,7 @@ pulls.auto_merge_newly_scheduled_comment=`已于 %[1]s 设置æ¤åˆå¹¶è¯·æ±‚在æ pulls.auto_merge_canceled_schedule_comment=`已于 %[1]s å–æ¶ˆäº†è‡ªåЍåˆå¹¶è®¾ç½® ` pulls.delete.title=åˆ é™¤æ¤åˆå¹¶è¯·æ±‚? -pulls.delete.text=ä½ çœŸçš„è¦åˆ 除这个åˆå¹¶è¯·æ±‚å—? (è¿™å°†æ°¸ä¹…åˆ é™¤æ‰€æœ‰å†…å®¹ã€‚å¦‚æžœä½ æ‰“ç®—å°†å†…å®¹å˜æ¡£ï¼Œè¯·è€ƒè™‘å…³é—它) +pulls.delete.text=您真的è¦åˆ 除这个åˆå¹¶è¯·æ±‚å—ï¼Ÿï¼ˆè¿™å°†æ°¸ä¹…åˆ é™¤æ‰€æœ‰å†…å®¹ã€‚å¦‚æžœæ‚¨æ‰“ç®—å°†å†…å®¹å˜æ¡£ï¼Œè¯·è€ƒè™‘å…³é—它) pulls.recently_pushed_new_branches=您已ç»äºŽ%[2]s推é€äº†åˆ†æ”¯ <strong>%[1]s</strong> pulls.upstream_diverging_prompt_behind_1=该分支è½åŽäºŽ %[2]s %[1]d 个æäº¤ @@ -1984,7 +1984,7 @@ pulls.upstream_diverging_prompt_base_newer=基础分支 %s 有新的更改 pulls.upstream_diverging_merge=åŒæ¥æ´¾ç”Ÿ pulls.upstream_diverging_merge_confirm=è¦å°† %[1]s åˆå¹¶åˆ° %[2]s å—? -pull.deleted_branch=(å·²åˆ é™¤): %s +pull.deleted_branch=(å·²åˆ é™¤):%s pull.agit_documentation=查看有关 AGit 的文档 comments.edit.already_changed=æ— æ³•ä¿å˜å¯¹è¯„论的更改。其内容似乎已被其他用户更改。 请刷新页é¢å¹¶é‡æ–°ç¼–辑以é¿å…覆盖他们的更改 @@ -2002,16 +2002,16 @@ milestones.title=æ ‡é¢˜ milestones.desc=æè¿° milestones.due_date=æˆªæ¢æ—¥æœŸï¼ˆå¯é€‰ï¼‰ milestones.clear=清除 -milestones.invalid_due_date_format=åˆ°æœŸæ—¶é—´çš„æ ¼å¼å¿…须是 'yyyy-mm-dd' 的形å¼ã€‚ -milestones.create_success=里程碑 %s 创建æˆåŠŸã€‚ +milestones.invalid_due_date_format=åˆ°æœŸæ—¶é—´çš„æ ¼å¼å¿…须是「yyyy-mm-ddã€çš„å½¢å¼ã€‚ +milestones.create_success=里程碑「%sã€åˆ›å»ºæˆåŠŸã€‚ milestones.edit=编辑里程碑 milestones.edit_subheader=里程碑组织工å•,åˆå¹¶è¯·æ±‚和跟踪进度。 milestones.cancel=å–æ¶ˆ milestones.modify=更新里程碑 -milestones.edit_success=里程碑 %s å·²ç»æ›´æ–°ã€‚ +milestones.edit_success=里程碑「%sã€æ›´æ–°æˆåŠŸã€‚ milestones.deletion=åˆ é™¤é‡Œç¨‹ç¢‘ milestones.deletion_desc=åˆ é™¤è¯¥é‡Œç¨‹ç¢‘å°†ä¼šç§»é™¤æ‰€æœ‰å·¥å•ä¸ç›¸å…³çš„ä¿¡æ¯ã€‚是å¦ç»§ç»ï¼Ÿ -milestones.deletion_success=é‡Œç¨‹ç¢‘å·²è¢«åˆ é™¤ã€‚ +milestones.deletion_success=é‡Œç¨‹ç¢‘å·²åˆ é™¤ã€‚ milestones.filter_sort.name=åç§° milestones.filter_sort.earliest_due_data=到期日从远到近 milestones.filter_sort.latest_due_date=到期日从近到远 @@ -2020,7 +2020,7 @@ milestones.filter_sort.most_complete=完æˆåº¦ä»Žé«˜åˆ°ä½Ž milestones.filter_sort.most_issues=å·¥å•从多到少 milestones.filter_sort.least_issues=å·¥å•从少到多 -signing.will_sign=这个æäº¤å°†ç”¨å¯†é’¥ "%s" ç¾å。 +signing.will_sign=这个æäº¤å°†ç”¨å¯†é’¥ã€Œ%sã€ç¾å。 signing.wont_sign.error=在检查æäº¤æ˜¯å¦å¯ä»¥è¢«ç¾å时出错。 signing.wont_sign.nokey=没有å¯ç”¨çš„密钥æ¥ç¾ç½²è¿™ä¸ªæäº¤ã€‚ signing.wont_sign.never=æäº¤ä»Žæœªç¾å。 @@ -2035,11 +2035,11 @@ signing.wont_sign.approved=åˆå¹¶å°†ä¸ä¼šè¢«ç¾åï¼Œå› ä¸ºåˆå¹¶è¯·æ±‚æœªè¢«æ‰ signing.wont_sign.not_signed_in=您还没有登录。 ext_wiki=访问外部百科 -ext_wiki.desc=链接到外部 wiki。 +ext_wiki.desc=链接到外部百科。 wiki=百科 -wiki.welcome=欢迎æ¥åˆ°ç™¾ç§‘! -wiki.welcome_desc=百科å…è®¸ä½ æ’°å†™å’Œä¸Žå作者分享文档 +wiki.welcome=欢迎æ¥åˆ°ç™¾ç§‘。 +wiki.welcome_desc=百科å…许您撰写和与å作者分享文档。 wiki.desc=撰写和与å作者分享文档 wiki.create_first_page=åˆ›å»ºç¬¬ä¸€ä¸ªé¡µé¢ wiki.page=é¡µé¢ @@ -2056,15 +2056,15 @@ wiki.file_revision=页é¢åŽ†å² wiki.wiki_page_revisions=页é¢åŽ†å² wiki.back_to_wiki=返回百科 wiki.delete_page_button=åˆ é™¤é¡µé¢ -wiki.delete_page_notice_1=ç™¾ç§‘é¡µé¢ %s åˆ é™¤åŽæ— 法æ¢å¤ï¼Œæ˜¯å¦ç»§ç»ï¼Ÿ +wiki.delete_page_notice_1=百科页é¢ã€Œ%sã€åˆ é™¤åŽæ— 法æ¢å¤ï¼Œæ˜¯å¦ç»§ç»ï¼Ÿ wiki.page_already_exists=相åŒåç§°çš„ Wiki 页é¢å·²ç»å˜åœ¨ã€‚ -wiki.reserved_page=百科页é¢åç§° %s 是被ä¿ç•™çš„。 +wiki.reserved_page=百科页é¢å称「%sã€æ˜¯ä¿ç•™çš„。 wiki.pages=æ‰€æœ‰é¡µé¢ wiki.last_updated=æœ€åŽæ›´æ–°äºŽ %s -wiki.page_name_desc=è¾“å…¥æ¤ Wiki 页é¢çš„å称。特殊å称有:'Home', '_Sidebar' å’Œ '_Footer'。 +wiki.page_name_desc=输入æ¤ç™¾ç§‘页é¢çš„å称。特殊å称有:「Homeã€ï¼Œã€Œ_Sidebarã€å’Œã€Œ_Footerã€ã€‚ wiki.original_git_entry_tooltip=查看原始的 Git æ–‡ä»¶è€Œä¸æ˜¯ä½¿ç”¨å‹å¥½é“¾æŽ¥ã€‚ -activity=åŠ¨æ€ +activity=活动 activity.navbar.pulse=活动 activity.navbar.code_frequency=代ç 频率 activity.navbar.contributors=贡献者 @@ -2078,27 +2078,27 @@ activity.period.quarterly=3个月 activity.period.semiyearly=6 个月 activity.period.yearly=1å¹´ activity.overview=概览 -activity.active_prs_count_1=<strong>%d</strong> åˆå¹¶è¯·æ±‚ -activity.active_prs_count_n=<strong>%d</strong> åˆå¹¶è¯·æ±‚ +activity.active_prs_count_1=<strong>%d</strong> 个åˆå¹¶è¯·æ±‚ +activity.active_prs_count_n=<strong>%d</strong> 个åˆå¹¶è¯·æ±‚ activity.merged_prs_count_1=åˆå¹¶è¯·æ±‚ activity.merged_prs_count_n=åˆå¹¶è¯·æ±‚ activity.opened_prs_count_1=æ–°åˆå¹¶è¯·æ±‚ activity.opened_prs_count_n=æ–°åˆå¹¶è¯·æ±‚ -activity.title.user_1=%d 用户 -activity.title.user_n=%d 用户 -activity.title.prs_1=%d åˆå¹¶è¯·æ±‚ -activity.title.prs_n=%d åˆå¹¶è¯·æ±‚ +activity.title.user_1=%d ä½ç”¨æˆ· +activity.title.user_n=%d ä½ç”¨æˆ· +activity.title.prs_1=%d 个åˆå¹¶è¯·æ±‚ +activity.title.prs_n=%d 个åˆå¹¶è¯·æ±‚ activity.title.prs_merged_by=%[2]s ç”± %[1]s åˆå¹¶ activity.title.prs_opened_by=%[2]s 创建了 %[1]s activity.merged_prs_label=å·²åˆå¹¶ activity.opened_prs_label=已创建 -activity.active_issues_count_1=<strong>%d</strong> å·¥å• -activity.active_issues_count_n=<strong>%d</strong> å·¥å• +activity.active_issues_count_1=<strong>%d</strong> å¼ å·¥å• +activity.active_issues_count_n=<strong>%d</strong> å¼ å·¥å• activity.closed_issues_count_1=已关é—çš„å·¥å• activity.closed_issues_count_n=已关é—çš„å·¥å• -activity.title.issues_1=%d å·¥å• -activity.title.issues_n=%d å·¥å• -activity.title.issues_closed_from=%s 从 %s è¢«å…³é— +activity.title.issues_1=%d å¼ å·¥å• +activity.title.issues_n=%d å¼ å·¥å• +activity.title.issues_closed_from=%s 从 %s å…³é— activity.title.issues_created_by=%[2]s 创建了 %[1]s activity.closed_issue_label=å·²å…³é— activity.new_issues_count_1=åˆ›å»ºå·¥å• @@ -2108,23 +2108,23 @@ activity.title.unresolved_conv_1=%d æœªè§£å†³çš„ä¼šè¯ activity.title.unresolved_conv_n=%d æœªè§£å†³çš„ä¼šè¯ activity.unresolved_conv_desc=这些最近更新的工å•å’Œåˆå¹¶è¯·æ±‚还没有解决。 activity.unresolved_conv_label=打开 -activity.title.releases_1=%d 版本å‘布 -activity.title.releases_n=%d 版本å‘布 +activity.title.releases_1=%d 个å‘布 +activity.title.releases_n=%d 个å‘布 activity.title.releases_published_by=%[2]s å‘布了 %[1]s activity.published_release_label=å·²å‘布 activity.no_git_activity=åœ¨æ¤æœŸé—´æ²¡æœ‰ä»»ä½•æäº¤æ´»åŠ¨ã€‚ activity.git_stats_exclude_merges=排除åˆå¹¶ï¼Œ -activity.git_stats_author_1=%d 作者 -activity.git_stats_author_n=%d 作者 +activity.git_stats_author_1=%d ä½ä½œè€… +activity.git_stats_author_n=%d ä½ä½œè€… activity.git_stats_pushed_1=å·²ç»æŽ¨é€ activity.git_stats_pushed_n=å·²ç»æŽ¨é€ -activity.git_stats_commit_1=%d æäº¤ -activity.git_stats_commit_n=%d æäº¤ +activity.git_stats_commit_1=%d 次æäº¤ +activity.git_stats_commit_n=%d 次æäº¤ activity.git_stats_push_to_branch=到 %s å’Œ activity.git_stats_push_to_all_branches=到所有分支。 activity.git_stats_on_default_branch=在 %s 上, -activity.git_stats_file_1=%d 文件 -activity.git_stats_file_n=%d 文件 +activity.git_stats_file_1=%d 个文件 +activity.git_stats_file_n=%d 个文件 activity.git_stats_files_changed_1=å·²ç»æ”¹å˜ activity.git_stats_files_changed_n=å·²ç»æ”¹å˜ activity.git_stats_additions=而且 @@ -2136,15 +2136,15 @@ activity.git_stats_deletion_n=åˆ é™¤ %d 行 contributors.contribution_type.filter_label=贡献类型: contributors.contribution_type.commits=æäº¤ -contributors.contribution_type.additions=更多 +contributors.contribution_type.additions=新增 contributors.contribution_type.deletions=åˆ é™¤ settings=设置 -settings.desc=è®¾ç½®æ˜¯ä½ å¯ä»¥ç®¡ç†ä»“库设置的地方 +settings.desc=设置是您å¯ä»¥ç®¡ç†ä»“库设置的地方 settings.options=仓库 settings.public_access=公开访问 -settings.public_access_desc=é…置公共访客访问æƒé™ä»¥è¦†ç›–æ¤å˜å‚¨åº“的默认值。 -settings.public_access.docs.not_set=未设置:没有é¢å¤–的公共访问æƒé™ã€‚访客æƒé™éµå¾ªå˜å‚¨åº“çš„å¯è§æ€§å’Œæˆå‘˜æƒé™ã€‚ +settings.public_access_desc=é…置公共访客访问æƒé™ä»¥è¦†ç›–æ¤ä»“库的默认值。 +settings.public_access.docs.not_set=未设置:没有é¢å¤–的公共访问æƒé™ã€‚访客æƒé™éµå¾ªä»“库的å¯è§æ€§å’Œæˆå‘˜æƒé™ã€‚ settings.public_access.docs.anonymous_read=匿åå¯è¯»ï¼šæœªç™»å½•的用户å¯ä»¥é€šè¿‡è¯»å–æƒé™è®¿é—®å•元。 settings.public_access.docs.everyone_read=所有人å¯è¯»ï¼šæ‰€æœ‰ç™»å½•用户都å¯ä»¥é€šè¿‡è¯»å–æƒé™è®¿é—®å•元。读å–问题/拉å–请求å•元的æƒé™ä¹Ÿæ„味ç€ç”¨æˆ·å¯ä»¥åˆ›å»ºæ–°çš„问题/拉å–请求。 settings.public_access.docs.everyone_write=所有人å¯å†™ï¼šæ‰€æœ‰ç™»å½•用户都有写入æƒé™ã€‚åªæœ‰ç™¾ç§‘æ”¯æŒæ¤æƒé™ã€‚ @@ -2161,14 +2161,14 @@ settings.mirror_settings=镜åƒè®¾ç½® settings.mirror_settings.docs=è®¾ç½®æ‚¨çš„ä»“åº“ä»¥è‡ªåŠ¨åŒæ¥å¦ä¸€ä¸ªä»“库的æäº¤ã€æ ‡ç¾å’Œåˆ†æ”¯ã€‚ settings.mirror_settings.docs.disabled_pull_mirror.instructions=设置您的项目以自动将æäº¤ã€æ ‡ç¾å’Œåˆ†æ”¯æŽ¨é€åˆ°å¦ä¸€ä¸ªä»“库。您的站点管ç†å‘˜å·²ç¦ç”¨äº†æ‹‰å–镜åƒã€‚ settings.mirror_settings.docs.disabled_push_mirror.instructions=å°†æ‚¨çš„é¡¹ç›®è®¾ç½®ä¸ºè‡ªåŠ¨ä»Žä¸€ä¸ªä»“åº“æ‹‰å–æäº¤ã€æ ‡ç¾å’Œåˆ†æ”¯ã€‚ -settings.mirror_settings.docs.disabled_push_mirror.pull_mirror_warning=现在,这åªèƒ½åœ¨â€œè¿ç§»å¤–部仓库â€èœå•ä¸å®Œæˆã€‚欲了解更多信æ¯ï¼Œè¯·å’¨è¯¢ï¼š +settings.mirror_settings.docs.disabled_push_mirror.pull_mirror_warning=现在,这åªèƒ½åœ¨ã€Œè¿ç§»å¤–部仓库ã€èœå•ä¸å®Œæˆã€‚欲了解更多信æ¯ï¼Œè¯·å‚考: settings.mirror_settings.docs.disabled_push_mirror.info=您的站点管ç†å‘˜å·²ç¦ç”¨æŽ¨é€é•œåƒã€‚ settings.mirror_settings.docs.no_new_mirrors=您的仓库将镜åƒåŒæ¥å¦ä¸€ä¸ªä»“库的更改。请注æ„,您现在ä¸èƒ½åˆ›å»ºä»»ä½•新的镜åƒã€‚ settings.mirror_settings.docs.can_still_use=虽然您ä¸èƒ½ä¿®æ”¹çŽ°æœ‰é•œåƒæˆ–创建新镜åƒï¼Œä½†æ‚¨ä»ç„¶å¯ä»¥ä½¿ç”¨å·²å˜åœ¨çš„镜åƒã€‚ settings.mirror_settings.docs.pull_mirror_instructions=è¦åˆ›å»ºä¸€ä¸ªæ‹‰å–镜åƒï¼Œè¯·å‚阅: settings.mirror_settings.docs.more_information_if_disabled=您å¯ä»¥åœ¨è¿™é‡Œæ‰¾åˆ°æ›´å¤šå…³äºŽæŽ¨é€å’Œæ‹‰å–镜åƒçš„ä¿¡æ¯ï¼š settings.mirror_settings.docs.doc_link_title=如何镜åƒä»“库? -settings.mirror_settings.docs.doc_link_pull_section=文档ä¸çš„ “从远程仓库拉å–†部分。 +settings.mirror_settings.docs.doc_link_pull_section=文档ä¸çš„「从远程仓库拉å–ã€éƒ¨åˆ†ã€‚ settings.mirror_settings.docs.pulling_remote_title=从远程仓库拉å–代ç settings.mirror_settings.mirrored_repository=镜åƒåº“ settings.mirror_settings.pushed_repository=推é€ä»“库 @@ -2196,15 +2196,15 @@ settings.use_internal_wiki=使用内置百科 settings.default_wiki_branch_name=默认百科分支åç§° settings.failed_to_change_default_wiki_branch=更改百科默认分支失败。 settings.use_external_wiki=使用外部百科 -settings.external_wiki_url=外部 Wiki 链接 +settings.external_wiki_url=外部百科链接 settings.external_wiki_url_error=å¤–éƒ¨ç™¾ç§‘é“¾æŽ¥æ— æ•ˆ -settings.external_wiki_url_desc=å½“ç‚¹å‡»ç™¾ç§‘æ ‡ç¾æ—¶ï¼Œè®¿é—®è€…将被é‡å®šå‘到外部百科系统的URL。 +settings.external_wiki_url_desc=å½“ç‚¹å‡»ç™¾ç§‘æ ‡ç¾æ—¶ï¼Œè®¿é—®è€…将被é‡å®šå‘到外部百科系统的 URL。 settings.issues_desc=å¯ç”¨å·¥å•系统 -settings.use_internal_issue_tracker=使用内置的轻é‡çº§å·¥å•管ç†ç³»ç»Ÿ -settings.use_external_issue_tracker=使用外部的工å•管ç†ç³»ç»Ÿ +settings.use_internal_issue_tracker=使用内置工å•系统 +settings.use_external_issue_tracker=使用外部工å•系统 settings.external_tracker_url=外部工å•系统 URL settings.external_tracker_url_error=å¤–éƒ¨ç™¾ç§‘é“¾æŽ¥æ— æ•ˆ -settings.external_tracker_url_desc=å½“ç‚¹å‡»å·¥å•æ ‡ç¾æ—¶ï¼Œè®¿é—®è€…将被é‡å®šå‘到外部工å•系统的URL。 +settings.external_tracker_url_desc=å½“ç‚¹å‡»å·¥å•æ ‡ç¾æ—¶ï¼Œè®¿é—®è€…将被é‡å®šå‘到外部工å•系统的 URL。 settings.tracker_url_format=外部工å•管ç†ç³»ç»Ÿçš„ URL æ ¼å¼ settings.tracker_url_format_error=外部工å•é“¾æŽ¥æ— æ•ˆ settings.tracker_issue_style=外部工å•管ç†ç³»ç»Ÿçš„ç¼–å·æ ¼å¼ @@ -2222,14 +2222,14 @@ settings.pulls.enable_autodetect_manual_merge=å¯ç”¨è‡ªåŠ¨æ£€æµ‹æ‰‹åŠ¨åˆå¹¶ (æ³ settings.pulls.allow_rebase_update=å…许通过å˜åŸºæ›´æ–°åˆå¹¶è¯·æ±‚分支 settings.pulls.default_delete_branch_after_merge=默认åˆå¹¶åŽåˆ 除åˆå¹¶è¯·æ±‚分支 settings.pulls.default_allow_edits_from_maintainers=默认开å¯å…许维护者编辑 -settings.releases_desc=å¯ç”¨å‘布 +settings.releases_desc=å¯ç”¨ä»“库å‘布 settings.packages_desc=å¯ç”¨ä»“库软件包注册ä¸å¿ƒ settings.projects_desc=å¯ç”¨é¡¹ç›® settings.projects_mode_desc=é¡¹ç›®æ¨¡å¼ (è¦æ˜¾ç¤ºçš„项目类型) settings.projects_mode_repo=仅仓库项目 settings.projects_mode_owner=ä»…é™ç”¨æˆ·æˆ–组织项目 settings.projects_mode_all=所有项目 -settings.actions_desc=å¯ç”¨ Actions +settings.actions_desc=å¯ç”¨ä»“åº“å·¥ä½œæµ settings.admin_settings=管ç†å‘˜è®¾ç½® settings.admin_enable_health_check=å¯ç”¨ä»“库å¥åº·æ£€æŸ¥ (git fsck) settings.admin_code_indexer=代ç 索引器 @@ -2252,23 +2252,23 @@ settings.convert_fork_notices_1=该æ“作会将派生仓库转æ¢ä¸ºæ™®é€šä»“库 settings.convert_fork_confirm=转æ¢ä»“库 settings.convert_fork_succeed=æ¤æ´¾ç”Ÿä»“库已ç»è½¬æ¢ä¸ºæ™®é€šä»“库。 settings.transfer=è½¬ç§»ä»“åº“æ‰€æœ‰æƒ -settings.transfer.rejected=代ç 库转移被拒ç»ã€‚ -settings.transfer.success=代ç 库转移æˆåŠŸã€‚ -settings.transfer.blocked_user=æ— æ³•ä¼ è¾“ä»“åº“ï¼Œå› ä¸ºæ‚¨è¢«æ–°çš„æ‰€æœ‰è€…å±è”½ã€‚ +settings.transfer.rejected=仓库转移被拒ç»ã€‚ +settings.transfer.success=仓库转移æˆåŠŸã€‚ +settings.transfer.blocked_user=æ— æ³•è½¬ç§»ä»“åº“ï¼Œå› ä¸ºæ‚¨å·²è¢«æ–°æ‰€æœ‰è€…å±è”½ã€‚ settings.transfer_abort=å–æ¶ˆè½¬ç§» -settings.transfer_abort_invalid=ä½ ä¸èƒ½å–消ä¸å˜åœ¨çš„代ç 库转移。 -settings.transfer_abort_success=æˆåŠŸå–æ¶ˆäº†å°†ä»£ç 库转让给 %s。 +settings.transfer_abort_invalid=您ä¸èƒ½å–消ä¸å˜åœ¨çš„仓库转移。 +settings.transfer_abort_success=æˆåŠŸå–æ¶ˆå°†ä»“库转移给 %s。 settings.transfer_desc=您å¯ä»¥å°†ä»“库转移至您拥有管ç†å‘˜æƒé™çš„叿ˆ·æˆ–组织。 settings.transfer_form_title=输入仓库å称以åšç¡®è®¤: -settings.transfer_in_progress=当剿£åœ¨è¿›è¡Œè½¬è®©ã€‚ å¦‚æžœä½ æƒ³å°†æ¤ä»£ç 库转让给å¦ä¸€ä¸ªç”¨æˆ·ï¼Œè¯·å–消它。 -settings.transfer_notices_1=- 如果将æ¤ä»“库转移给其他用户, 您将失去对æ¤ä»“库的访问æƒé™ã€‚ -settings.transfer_notices_2=-如果将其转移到您 (å…±åŒ) 拥有的组织,您å¯ä»¥ç»§ç»è®¿é—®è¯¥ä»“库。 -settings.transfer_notices_3=- å¦‚æžœä»“åº“æ˜¯ç§æœ‰çš„并且被转移给æŸä¸ªç”¨æˆ·ï¼Œé‚£ä¹ˆæ¤æ“作å¯ä»¥ç¡®ä¿è¯¥ç”¨æˆ·è‡³å°‘具有读æƒé™(以åŠå¿…è¦æ—¶çš„æ›´æ”¹æƒé™)。 -settings.transfer_notices_4=- 如果å˜å‚¨åº“属于æŸä¸ªç»„织,而您将其转移给å¦ä¸€ä¸ªç»„织或个人,那么您将失去å˜å‚¨åº“å·¥å•与其组织项目系统之间的链接。 +settings.transfer_in_progress=当剿£åœ¨è¿›è¡Œè½¬ç§»ã€‚ 如果您想将æ¤ä»“库转移给å¦ä¸€ä¸ªç”¨æˆ·ï¼Œè¯·å–消它。 +settings.transfer_notices_1=- 如果将æ¤ä»“库转移给其他用户,您将失去对æ¤ä»“库的访问æƒé™ã€‚ +settings.transfer_notices_2=- 如果将其转移到您(共åŒï¼‰æ‹¥æœ‰çš„组织,您å¯ä»¥ç»§ç»è®¿é—®è¯¥ä»“库。 +settings.transfer_notices_3=- å¦‚æžœä»“åº“æ˜¯ç§æœ‰çš„并且被转移给æŸä¸ªç”¨æˆ·ï¼Œé‚£ä¹ˆæ¤æ“作å¯ä»¥ç¡®ä¿è¯¥ç”¨æˆ·è‡³å°‘具有读æƒé™ï¼ˆä»¥åŠå¿…è¦æ—¶çš„æ›´æ”¹æƒé™ï¼‰ã€‚ +settings.transfer_notices_4=- 如果仓库属于æŸä¸ªç»„织,而您将其转移给å¦ä¸€ä¸ªç»„织或个人,那么您将失去仓库工å•与其组织项目系统之间的链接。 settings.transfer_owner=新拥有者 -settings.transfer_perform=执行转让 -settings.transfer_started=该代ç åº“å·²è¢«æ ‡è®°ä¸ºè½¬è®©å¹¶ç‰å¾…æ¥è‡ª %s 的确认 -settings.transfer_succeed=仓库已被转移。 +settings.transfer_perform=执行转移 +settings.transfer_started=è¯¥ä»“åº“å·²æ ‡è®°ä¸ºè½¬ç§»å¹¶ç‰å¾…æ¥è‡ª %s 的确认 +settings.transfer_succeed=仓库已转移。 settings.signing_settings=ç¾å验è¯è®¾ç½® settings.trust_model=ç¾å信任模型 settings.trust_model.default=默认信任模型 @@ -2278,7 +2278,7 @@ settings.trust_model.collaborator.long=å作者:信任å作者的ç¾å settings.trust_model.collaborator.desc=æ¤ä»“库ä¸å作者的有效ç¾åå°†è¢«æ ‡è®°ä¸ºã€Œå¯ä¿¡ã€(æ— è®ºå®ƒä»¬æ˜¯å¦æ˜¯æäº¤è€…),ç¾ååªç¬¦åˆæäº¤è€…æ—¶å°†æ ‡è®°ä¸ºã€Œä¸å¯ä¿¡ã€ï¼Œéƒ½ä¸åŒ¹é…æ—¶æ ‡è®°ä¸ºã€Œä¸åŒ¹é…ã€ã€‚ settings.trust_model.committer=æäº¤è€… settings.trust_model.committer.long=æäº¤è€…: 信任与æäº¤è€…相符的ç¾å (æ¤ç‰¹æ€§ç±»ä¼¼ GitHub,这会强制采用 Gitea 作为æäº¤è€…å’Œç¾å者) -settings.trust_model.committer.desc=有效ç¾ååªæœ‰å’Œæäº¤è€…ç›¸åŒ¹é…æ‰ä¼šè¢«æ ‡è®°ä¸ºâ€œå—ä¿¡ä»»â€ï¼Œå¦åˆ™å®ƒä»¬å°†è¢«æ ‡è®°ä¸ºâ€œä¸åŒ¹é…â€ã€‚这强制 Gitea æˆä¸ºç¾åæäº¤çš„æäº¤è€…,而实际æäº¤è€…è¢«åŠ ä¸Š Co-authored-by: å’Œ Co-committed-by: çš„æ ‡è®°ã€‚ 默认的 Gitea å¯†é’¥å¿…é¡»åŒ¹é…æ•°æ®åº“ä¸çš„一å用户。 +settings.trust_model.committer.desc=有效ç¾ååªæœ‰å’Œæäº¤è€…ç›¸åŒ¹é…æ‰ä¼šè¢«æ ‡è®°ä¸ºã€Œå—ä¿¡ä»»ã€ï¼Œå¦åˆ™å®ƒä»¬å°†è¢«æ ‡è®°ä¸ºã€Œä¸åŒ¹é…ã€ã€‚这强制 Gitea æˆä¸ºç¾åæäº¤çš„æäº¤è€…,而实际æäº¤è€…è¢«åŠ ä¸Š Co-authored-by: å’Œ Co-committed-by: çš„æ ‡è®°ã€‚ 默认的 Gitea å¯†é’¥å¿…é¡»åŒ¹é…æ•°æ®åº“ä¸çš„一å用户。 settings.trust_model.collaboratorcommitter=å作者+æäº¤è€… settings.trust_model.collaboratorcommitter.long=å作者+æäº¤è€…:信任åä½œè€…åŒæ—¶æ˜¯æäº¤è€…çš„ç¾å settings.trust_model.collaboratorcommitter.desc=æ¤ä»“库ä¸å作者的有效ç¾ååœ¨ä»–åŒæ—¶æ˜¯æäº¤è€…æ—¶å°†è¢«æ ‡è®°ä¸ºã€Œå¯ä¿¡ã€ï¼Œç¾ååªåŒ¹é…了æäº¤è€…æ—¶å°†æ ‡è®°ä¸ºã€Œä¸å¯ä¿¡ã€ï¼Œéƒ½ä¸åŒ¹é…æ—¶æ ‡è®°ä¸ºã€Œä¸åŒ¹é…ã€ã€‚这会强制 Gitea æˆä¸ºç¾å者和æäº¤è€…,实际的æäº¤è€…å°†è¢«æ ‡è®°äºŽæäº¤æ¶ˆæ¯ç»“尾处的「Co-Authored-By:ã€å’Œã€ŒCo-Committed-By:ã€ã€‚默认的 Gitea ç¾åå¯†é’¥å¿…é¡»åŒ¹é…æ•°æ®åº“ä¸çš„一个用户密钥。 @@ -2292,16 +2292,16 @@ settings.delete_desc=åˆ é™¤ä»“åº“æ˜¯æ°¸ä¹…æ€§çš„, æ— æ³•æ’¤æ¶ˆã€‚ settings.delete_notices_1=- æ¤æ“作 <strong>ä¸å¯ä»¥</strong> 被回滚。 settings.delete_notices_2=- æ¤æ“ä½œå°†æ°¸ä¹…åˆ é™¤ä»“åº“ <strong>%s</strong>,包括 Git æ•°æ®ã€ å·¥å•ã€è¯„论ã€ç™¾ç§‘å’Œå作者的æ“作æƒé™ã€‚ settings.delete_notices_fork_1=- 在æ¤ä»“åº“åˆ é™¤åŽï¼Œå®ƒçš„æ´¾ç”Ÿä»“åº“å°†å˜æˆç‹¬ç«‹ä»“库。 -settings.deletion_success=ä»“åº“å·²è¢«åˆ é™¤ã€‚ +settings.deletion_success=ä»“åº“å·²åˆ é™¤ã€‚ settings.update_settings_success=仓库设置已更新。 -settings.update_settings_no_unit=该代ç 库应该至少å…许æŸç§å½¢å¼çš„交互。 +settings.update_settings_no_unit=该仓库应至少å…许æŸç§å½¢å¼çš„交互。 settings.confirm_delete=åˆ é™¤æœ¬ä»“åº“ settings.add_collaborator=å¢žåŠ å作者 settings.add_collaborator_success=åä½œè€…æ·»åŠ æˆåŠŸï¼ settings.add_collaborator_inactive_user=æ— æ³•æ·»åŠ æœªæ¿€æ´»çš„ç”¨æˆ·ä½œä¸ºåˆä½œè€…。 settings.add_collaborator_owner=ä¸èƒ½å°†æ‰€æœ‰è€…æ·»åŠ ä¸ºå作者。 -settings.add_collaborator_duplicate=åˆä½œè€…å·²ç»è¢«æ·»åŠ åˆ°æœ¬ä»“åº“ã€‚ -settings.add_collaborator.blocked_user=æ¤å†™ä½œè€…被仓库所有者å±è”½ï¼Œå之亦然。 +settings.add_collaborator_duplicate=åä½œè€…å·²ç»æ·»åŠ åˆ°æœ¬ä»“åº“ã€‚ +settings.add_collaborator.blocked_user=æ¤å作者被仓库所有者å±è”½ï¼Œå之亦然。 settings.delete_collaborator=åˆ é™¤ settings.collaborator_deletion=åˆ é™¤å作者 settings.collaborator_deletion_desc=åˆ é™¤å作者åŽä»–å°†æ— æ³•å†å¯¹æ¤ä»“库的访问。继ç»ï¼Ÿ @@ -2315,25 +2315,25 @@ settings.add_team_duplicate=å›¢é˜Ÿå·²ç»æ‹¥æœ‰ä»“库 settings.add_team_success=团队现在å¯ä»¥è®¿é—®ä»“库。 settings.change_team_permission_tip=团队æƒé™è®¾ç½®äºŽå›¢é˜Ÿè®¾ç½®é¡µé¢ï¼Œä¸èƒ½æ ¹æ®ä»“库更改 settings.delete_team_tip=è¯¥å›¢é˜Ÿä»æœ‰ä»“库, æ— æ³•åˆ é™¤ -settings.remove_team_success=团队访问仓库的æƒé™å·²è¢«åˆ 除。 +settings.remove_team_success=团队访问仓库的æƒé™å·²åˆ 除。 settings.add_webhook=æ·»åŠ Web é’©å -settings.add_webhook.invalid_channel_name=Webhook 通é“åç§°ä¸èƒ½ä¸ºç©ºä¸”ä¸èƒ½ä»…包å«ä¸€ä¸ª # å—符。 -settings.hooks_desc=当Gitea事件å‘生时,Webé’©å自动å‘出HTTP POST请求。在 <a target="_blank" rel="noopener noreferrer" href="%s"> 指å—</a> ä¸é˜…读更多内容。 +settings.add_webhook.invalid_channel_name=Web é’©å通é“åç§°ä¸èƒ½ä¸ºç©ºä¸”ä¸èƒ½ä»…包å«ä¸€ä¸ª # å—符。 +settings.hooks_desc=当 Gitea 事件å‘生时,Web é’©å自动å‘出 HTTP POST 请求。在 <a target="_blank" rel="noopener noreferrer" href="%s"> 指å—</a> ä¸é˜…读更多内容。 settings.webhook_deletion=åˆ é™¤ Web é’©å -settings.webhook_deletion_desc=åˆ é™¤ webé’©å å°†åˆ é™¤å…¶è®¾ç½®å’ŒåŽ†å²è®°å½•。继ç»ï¼Ÿ +settings.webhook_deletion_desc=åˆ é™¤ Web é’©åå°†åˆ é™¤å…¶è®¾ç½®å’ŒåŽ†å²è®°å½•。继ç»ï¼Ÿ settings.webhook_deletion_success=Web é’©ååˆ é™¤æˆåŠŸï¼ settings.webhook.test_delivery=æµ‹è¯•æŽ¨é€ -settings.webhook.test_delivery_desc=用å‡äº‹ä»¶æµ‹è¯•这个 webé’©å。 -settings.webhook.test_delivery_desc_disabled=è¦ç”¨ 虚å‡äº‹ä»¶ 测试这个Webhook,请激活它。 +settings.webhook.test_delivery_desc=用å‡äº‹ä»¶æµ‹è¯•这个 Web é’©å。 +settings.webhook.test_delivery_desc_disabled=è¦ç”¨å‡äº‹ä»¶æµ‹è¯•这个 Webé’©å,请激活它。 settings.webhook.request=请求内容 settings.webhook.response=å“应内容 settings.webhook.headers=å¤´ä¿¡æ¯ settings.webhook.payload=内容 settings.webhook.body=å“应体 -settings.webhook.replay.description=釿”¾æ¤ webhook。 -settings.webhook.replay.description_disabled=è‹¥è¦é‡æ’æ¤ WebHook,请激活它。 -settings.webhook.delivery.success=ä¸€ä¸ªäº‹ä»¶å·²è¢«æ·»åŠ åˆ°æŽ¨é€é˜Ÿåˆ—。å¯èƒ½éœ€è¦è¿‡å‡ ç§’é’Ÿæ‰ä¼šæ˜¾ç¤ºåœ¨æŽ¨é€è®°å½•ä¸ã€‚ -settings.githooks_desc=Git Hook 是 Git 本身æä¾›çš„功能。您å¯ä»¥åœ¨ä¸‹æ–¹ç¼–辑 hook 文件以设置自定义æ“作。 +settings.webhook.replay.description=釿”¾æ¤ Web é’©å。 +settings.webhook.replay.description_disabled=è‹¥è¦é‡æ–°è¿è¡Œæ¤ Web é’©å,请激活它。 +settings.webhook.delivery.success=ä¸€ä¸ªäº‹ä»¶å·²æ·»åŠ åˆ°æŽ¨é€é˜Ÿåˆ—。å¯èƒ½éœ€è¦è¿‡å‡ ç§’é’Ÿæ‰ä¼šæ˜¾ç¤ºåœ¨æŽ¨é€è®°å½•ä¸ã€‚ +settings.githooks_desc=Git é’©åæ˜¯ Git 本身æä¾›çš„功能。您å¯ä»¥åœ¨ä¸‹æ–¹ç¼–辑 hook 文件以设置自定义æ“作。 settings.githook_edit_desc=å¦‚æžœé’©åæœªå¯åŠ¨ï¼Œåˆ™ä¼šæ˜¾ç¤ºæ ·ä¾‹æ–‡ä»¶ä¸çš„内容。如果想è¦åˆ 除æŸä¸ªé’©å,则æäº¤ç©ºç™½æ–‡æœ¬å³å¯ã€‚ settings.githook_name=é’©ååç§° settings.githook_content=é’©åæ–‡æœ¬ @@ -2341,8 +2341,8 @@ settings.update_githook=æ›´æ–°é’©å设置 settings.add_webhook_desc=Gitea å°†å‘ç›®æ ‡ URL å‘é€å…·æœ‰æŒ‡å®šå†…容类型的 <code>POST</code> 请求。在 <a target="_blank" rel="noopener noreferrer" href="%s">webhooks 指å—</a> ä¸é˜…读更多内容。 settings.payload_url=ç›®æ ‡ URL settings.http_method=HTTP 方法 -settings.content_type=POST Content Type -settings.secret=密钥文本 +settings.content_type=POST 内容类型 +settings.secret=密钥 settings.slack_username=æœåŠ¡åç§° settings.slack_icon_url=å›¾æ ‡ URL settings.slack_color=颜色 @@ -2358,12 +2358,12 @@ settings.event_create_desc=åˆ›å»ºåˆ†æ”¯æˆ–æ ‡ç¾ settings.event_delete=刪除 settings.event_delete_desc=åˆ†æ”¯æˆ–æ ‡ç¾å·²åˆ 除。 settings.event_fork=派生 -settings.event_fork_desc=仓库被派生。 +settings.event_fork_desc=仓库已派生。 settings.event_wiki=百科 settings.event_wiki_desc=创建ã€é‡å‘½åã€ç¼–è¾‘æˆ–åˆ é™¤äº†ç™¾ç§‘é¡µé¢ã€‚ settings.event_statuses=çŠ¶æ€ settings.event_statuses_desc=已从 API æ›´æ–°æäº¤çжæ€ã€‚ -settings.event_release=版本å‘布 +settings.event_release=å‘布 settings.event_release_desc=å‘å¸ƒã€æ›´æ–°æˆ–åˆ é™¤ç‰ˆæœ¬æ—¶ã€‚ settings.event_push=æŽ¨é€ settings.event_force_push=å¼ºåˆ¶æŽ¨é€ @@ -2374,43 +2374,43 @@ settings.event_header_issue=å·¥å•事件 settings.event_issues=å·¥å• settings.event_issues_desc=å·¥å•已打开ã€å·²å…³é—ã€å·²é‡æ–°æ‰“开或已编辑。 settings.event_issue_assign=å·¥å•已指派 -settings.event_issue_assign_desc=å·¥å•å·²è¢«æŒ‡æ´¾æˆ–å–æ¶ˆæŒ‡æ´¾ã€‚ +settings.event_issue_assign_desc=å·¥å•å·²æŒ‡æ´¾æˆ–å–æ¶ˆæŒ‡æ´¾ã€‚ settings.event_issue_label=å·²æ ‡è®°å·¥å• -settings.event_issue_label_desc=工啿 ‡ç¾è¢«æ›´æ–°æˆ–清除。 -settings.event_issue_milestone=å·¥å•è¢«æ”¶å…¥é‡Œç¨‹ç¢‘ä¸ -settings.event_issue_milestone_desc=å·¥å•è¢«æ”¶å…¥æˆ–å–æ¶ˆæ”¶å…¥é‡Œç¨‹ç¢‘ä¸ã€‚ +settings.event_issue_label_desc=工啿 ‡ç¾å·²æ›´æ–°æˆ–清除。 +settings.event_issue_milestone=å·¥å•å·²æ”¶å…¥é‡Œç¨‹ç¢‘ä¸ +settings.event_issue_milestone_desc=å·¥å•å·²æ”¶å…¥æˆ–å–æ¶ˆæ”¶å…¥é‡Œç¨‹ç¢‘ä¸ã€‚ settings.event_issue_comment=å·¥å•评论 -settings.event_issue_comment_desc=å·¥å•评论被创建ã€ç¼–è¾‘æˆ–åˆ é™¤ +settings.event_issue_comment_desc=å·¥å•评论已创建ã€ç¼–è¾‘æˆ–åˆ é™¤ã€‚ settings.event_header_pull_request=åˆå¹¶è¯·æ±‚事件 settings.event_pull_request=åˆå¹¶è¯·æ±‚ -settings.event_pull_request_desc=åˆå¹¶è¯·æ±‚被打开ã€è¢«å…³é—ã€è¢«é‡æ–°æ‰“开或被编辑。 -settings.event_pull_request_assign=åˆå¹¶è¯·æ±‚被指派 -settings.event_pull_request_assign_desc=åˆå¹¶è¯·æ±‚è¢«æŒ‡æ´¾æˆ–å–æ¶ˆæŒ‡æ´¾ã€‚ -settings.event_pull_request_label=åˆå¹¶è¯·æ±‚è¢«è´´ä¸Šæ ‡ç¾ -settings.event_pull_request_label_desc=åˆå¹¶è¯·æ±‚çš„æ ‡ç¾è¢«æ›´æ–°æˆ–清除。 -settings.event_pull_request_milestone=åˆå¹¶è¯·æ±‚è¢«è®°å½•äºŽé‡Œç¨‹ç¢‘ä¸ -settings.event_pull_request_milestone_desc=åˆå¹¶è¯·æ±‚è¢«è®°å½•æˆ–å–æ¶ˆè®°å½•于里程碑ä¸ã€‚ -settings.event_pull_request_comment=åˆå¹¶è¯·æ±‚被评论 -settings.event_pull_request_comment_desc=åˆå¹¶è¯·æ±‚评论被创建ã€ç¼–è¾‘æˆ–åˆ é™¤ã€‚ +settings.event_pull_request_desc=åˆå¹¶è¯·æ±‚已打开ã€å…³é—ã€é‡æ–°æ‰“开或编辑。 +settings.event_pull_request_assign=åˆå¹¶è¯·æ±‚已指派 +settings.event_pull_request_assign_desc=åˆå¹¶è¯·æ±‚å·²æŒ‡æ´¾æˆ–å–æ¶ˆæŒ‡æ´¾ã€‚ +settings.event_pull_request_label=åˆå¹¶è¯·æ±‚å·²è´´ä¸Šæ ‡ç¾ +settings.event_pull_request_label_desc=åˆå¹¶è¯·æ±‚çš„æ ‡ç¾å·²æ›´æ–°æˆ–清除。 +settings.event_pull_request_milestone=åˆå¹¶è¯·æ±‚å·²è®°å½•äºŽé‡Œç¨‹ç¢‘ä¸ +settings.event_pull_request_milestone_desc=åˆå¹¶è¯·æ±‚å·²è®°å½•æˆ–å–æ¶ˆè®°å½•于里程碑ä¸ã€‚ +settings.event_pull_request_comment=åˆå¹¶è¯·æ±‚已评论 +settings.event_pull_request_comment_desc=åˆå¹¶è¯·æ±‚评论已创建ã€ç¼–è¾‘æˆ–åˆ é™¤ã€‚ settings.event_pull_request_review=å·²å®¡æ ¸çš„åˆå¹¶è¯·æ±‚ -settings.event_pull_request_review_desc=åˆå¹¶è¯·æ±‚è¢«æ‰¹å‡†ã€æ‹’ç»æˆ–æå‡ºå®¡æŸ¥æ„è§ -settings.event_pull_request_sync=åˆå¹¶è¯·æ±‚è¢«åŒæ¥ -settings.event_pull_request_sync_desc=åˆå¹¶è¯·æ±‚è¢«åŒæ¥ã€‚ +settings.event_pull_request_review_desc=åˆå¹¶è¯·æ±‚å·²æ‰¹å‡†ã€æ‹’ç»æˆ–æå‡ºå®¡æŸ¥æ„è§ã€‚ +settings.event_pull_request_sync=åˆå¹¶è¯·æ±‚å·²åŒæ¥ +settings.event_pull_request_sync_desc=åˆå¹¶è¯·æ±‚å·²åŒæ¥ã€‚ settings.event_pull_request_review_request=å‘èµ·åˆå¹¶è¯·æ±‚评审 settings.event_pull_request_review_request_desc=åˆå¹¶è¯·æ±‚è¯„å®¡å·²è¯·æ±‚æˆ–å·²å–æ¶ˆ settings.event_pull_request_approvals=åˆå¹¶è¯·æ±‚批准 settings.event_pull_request_merge=åˆå¹¶è¯·æ±‚åˆå¹¶ settings.event_header_workflow=工作æµç¨‹äº‹ä»¶ settings.event_workflow_job=工作æµä»»åŠ¡ -settings.event_workflow_job_desc=Gitea Actions 工作æµé˜Ÿåˆ—ä¸ã€ç‰å¾…ä¸ã€æ£åœ¨è¿›è¡Œæˆ–已完æˆä»»åŠ¡ã€‚ +settings.event_workflow_job_desc=Gitea 工作æµé˜Ÿåˆ—ä¸ã€ç‰å¾…ä¸ã€æ£åœ¨è¿›è¡Œæˆ–已完æˆçš„任务。 settings.event_package=软件包 -settings.event_package_desc=软件包已在仓库ä¸è¢«åˆ›å»ºæˆ–åˆ é™¤ã€‚ +settings.event_package_desc=软件包在仓库ä¸å·²åˆ›å»ºæˆ–åˆ é™¤ã€‚ settings.branch_filter=分支过滤 settings.branch_filter_desc=推é€ã€åˆ›å»ºï¼Œåˆ 除分支事件的分支白åå•,使用 glob 模å¼åŒ¹é…指定。若为空或 <code>*</code>ï¼Œåˆ™å°†æŠ¥å‘Šæ‰€æœ‰åˆ†æ”¯çš„äº‹ä»¶ã€‚è¯æ³•æ–‡æ¡£è§ <a href="%[1]s">%[2]s</a>。示例:<code>master</code>,<code>{master,release*}</code>。 settings.authorization_header=æŽˆæƒæ ‡å¤´ settings.authorization_header_desc=当å˜åœ¨æ—¶å°†è¢«ä½œä¸ºæŽˆæƒæ ‡å¤´åŒ…å«åœ¨å†…。例如: %s。 settings.active=激活 -settings.active_helper=触å‘事件的信æ¯å°†å‘é€åˆ°æ¤ webhook 网å€ã€‚ +settings.active_helper=触å‘事件的信æ¯å°†å‘é€åˆ°æ¤ Web é’©å URL。 settings.add_hook_success=Web é’©åæ·»åŠ æˆåŠŸï¼ settings.update_webhook=æ›´æ–° Web é’©å settings.update_hook_success=Web é’©åæ›´æ–°æˆåŠŸï¼ @@ -2420,7 +2420,7 @@ settings.hook_type=é’©å类型 settings.slack_token=令牌 settings.slack_domain=域å settings.slack_channel=é¢‘é“ -settings.add_web_hook_desc=å°† <a target="_blank" rel="noreferrer" href="%s">%s</a>集æˆåˆ°æ‚¨çš„代ç 库。 +settings.add_web_hook_desc=å°† <a target="_blank" rel="noreferrer" href="%s">%s</a> 集æˆåˆ°æ‚¨çš„仓库。 settings.web_hook_name_gitea=Gitea settings.web_hook_name_gogs=Gogs settings.web_hook_name_slack=Slack @@ -2447,7 +2447,7 @@ settings.title=æ ‡é¢˜ settings.deploy_key_content=密钥文本 settings.key_been_used=具有相åŒå†…容的部署密钥已在使用ä¸ã€‚ settings.key_name_used=使用相åŒå称的部署密钥已ç»å˜åœ¨ï¼ -settings.add_key_success=部署密钥 %s æ·»åŠ æˆåŠŸã€‚ +settings.add_key_success=部署密钥「%sã€æ·»åŠ æˆåŠŸã€‚ settings.deploy_key_deletion=åˆ é™¤éƒ¨ç½²å¯†é’¥ settings.deploy_key_deletion_desc=åˆ é™¤éƒ¨ç½²å¯†é’¥å°†å–æ¶ˆæ¤å¯†é’¥å¯¹æ¤ä»“库的访问æƒé™ã€‚ç»§ç»ï¼Ÿ settings.deploy_key_deletion_success=éƒ¨ç½²å¯†é’¥å·²åˆ é™¤ã€‚ @@ -2456,11 +2456,11 @@ settings.protected_branch=åˆ†æ”¯ä¿æŠ¤ settings.protected_branch.save_rule=ä¿å˜è§„则 settings.protected_branch.delete_rule=åˆ é™¤è§„åˆ™ settings.protected_branch_can_push=是å¦å…许推é€ï¼Ÿ -settings.protected_branch_can_push_yes=ä½ å¯ä»¥æŽ¨ -settings.protected_branch_can_push_no=ä½ ä¸èƒ½æŽ¨é€ -settings.branch_protection=分支 '<b>%s</b>' çš„ä¿æŠ¤è§„åˆ™ +settings.protected_branch_can_push_yes=您å¯ä»¥æŽ¨é€ +settings.protected_branch_can_push_no=您ä¸èƒ½æŽ¨é€ +settings.branch_protection=分支「<b>%s</b>ã€çš„ä¿æŠ¤è§„åˆ™ settings.protect_this_branch=å¯ç”¨åˆ†æ”¯ä¿æŠ¤ -settings.protect_this_branch_desc=阻æ¢åˆ 除并é™åˆ¶Git推é€å’Œåˆå¹¶åˆ°åˆ†æ”¯ã€‚ +settings.protect_this_branch_desc=阻æ¢åˆ 除并é™åˆ¶ Git 推é€å’Œåˆå¹¶åˆ°åˆ†æ”¯ã€‚ settings.protect_disable_push=ç¦ç”¨æŽ¨é€ settings.protect_disable_push_desc=æ¤åˆ†æ”¯ä¸å…许推é€ã€‚ settings.protect_disable_force_push=ç¦ç”¨å¼ºåˆ¶æŽ¨é€ @@ -2491,7 +2491,7 @@ settings.protect_status_check_patterns_desc=输入模å¼ï¼ŒæŒ‡å®šå“ªäº›çŠ¶æ€æ£€ settings.protect_check_status_contexts_desc=è¦æ±‚çŠ¶æ€æ£€æŸ¥é€šè¿‡æ‰èƒ½åˆå¹¶ã€‚如果å¯ç”¨ï¼Œæäº¤å¿…须先推é€åˆ°å¦ä¸€ä¸ªåˆ†æ”¯ï¼Œç„¶åŽå†åˆå¹¶æˆ–推é€åˆ°åŒ¹é…è¿™äº›ä¿æŠ¤è§„åˆ™çš„åˆ†æ”¯ã€‚å¦‚æžœæ²¡æœ‰é€‰æ‹©å…·ä½“çš„çŠ¶æ€æ£€æŸ¥ä¸Šä¸‹æ–‡ï¼Œåˆ™æ‰€æœ‰çš„çŠ¶æ€æ£€æŸ¥éƒ½é€šè¿‡æ‰èƒ½åˆå¹¶ã€‚ settings.protect_check_status_contexts_list=æ¤ä»“åº“ä¸Šå‘¨è¿›è¡Œè¿‡çš„çŠ¶æ€æ£€æŸ¥ settings.protect_status_check_matched=åŒ¹é… -settings.protect_invalid_status_check_pattern=æ— æ•ˆçš„çŠ¶æ€æ£€æŸ¥è§„则:“%sâ€ã€‚ +settings.protect_invalid_status_check_pattern=æ— æ•ˆçš„çŠ¶æ€æ£€æŸ¥è§„则:「%sã€ã€‚ settings.protect_no_valid_status_check_patterns=æ²¡æœ‰æœ‰æ•ˆçš„çŠ¶æ€æ£€æŸ¥è§„则。 settings.protect_required_approvals=所需的批准: settings.protect_required_approvals_desc=åªå…许åˆå¹¶æœ‰è¶³å¤Ÿå®¡æ ¸çš„åˆå¹¶è¯·æ±‚ã€‚è¦æ±‚çš„å®¡æ ¸å¿…é¡»æ¥è‡ªç™½å啿ˆ–者有æƒé™çš„用户或团队。 @@ -2514,9 +2514,9 @@ settings.protect_unprotected_file_patterns=ä¸å—ä¿æŠ¤çš„æ–‡ä»¶æ¨¡å¼(使用分 settings.protect_unprotected_file_patterns_desc=如果用户有写æƒé™ï¼Œåˆ™å…许直接更改的ä¸å—ä¿æŠ¤çš„æ–‡ä»¶ï¼Œä»¥ç»•è¿‡æŽ¨é€é™åˆ¶ã€‚å¯ä»¥ä½¿ç”¨åˆ†å·åˆ†éš”å¤šä¸ªæ¨¡å¼ (';')。 è§ <a href='%[1]s'>%[2]s</a> 文档了解模å¼è¯æ³•。例如: <code>.drone.yml</code>, <code>/docs/**/*.txt</code> settings.add_protected_branch=å¯ç”¨ä¿æŠ¤ settings.delete_protected_branch=ç¦ç”¨ä¿æŠ¤ -settings.update_protect_branch_success=åˆ†æ”¯ä¿æŠ¤è§„åˆ™ %s æ›´æ–°æˆåŠŸã€‚ -settings.remove_protected_branch_success=ç§»é™¤åˆ†æ”¯ä¿æŠ¤è§„åˆ™"%s"æˆåŠŸã€‚ -settings.remove_protected_branch_failed=ç§»é™¤åˆ†æ”¯ä¿æŠ¤è§„åˆ™"%s"失败。 +settings.update_protect_branch_success=åˆ†æ”¯ä¿æŠ¤è§„åˆ™ã€Œ%sã€æ›´æ–°æˆåŠŸã€‚ +settings.remove_protected_branch_success=åˆ†æ”¯ä¿æŠ¤è§„åˆ™ã€Œ%sã€ç§»é™¤æˆåŠŸã€‚ +settings.remove_protected_branch_failed=åˆ†æ”¯ä¿æŠ¤è§„åˆ™ã€Œ%sã€ç§»é™¤å¤±è´¥ã€‚ settings.protected_branch_deletion=åˆ é™¤åˆ†æ”¯ä¿æŠ¤ settings.protected_branch_deletion_desc=ç¦ç”¨åˆ†æ”¯ä¿æŠ¤å…许具有写入æƒé™çš„ç”¨æˆ·æŽ¨é€æäº¤åˆ°æ¤åˆ†æ”¯ã€‚ç»§ç»ï¼Ÿ settings.block_rejected_reviews=æ‹’ç»å®¡æ ¸é˜»æ¢äº†æ¤åˆå¹¶ @@ -2537,15 +2537,15 @@ settings.protected_branch_required_rule_name=必须填写规则åç§° settings.protected_branch_duplicate_rule_name=规则åç§°å·²å˜åœ¨ settings.protected_branch_required_approvals_min=所需的审批数ä¸èƒ½ä¸ºè´Ÿæ•°ã€‚ settings.tags=æ ‡ç¾ -settings.tags.protection=Gitæ ‡ç¾ä¿æŠ¤ -settings.tags.protection.pattern=Gitæ ‡ç¾æ¨¡å¼ +settings.tags.protection=Git æ ‡ç¾ä¿æŠ¤ +settings.tags.protection.pattern=Git æ ‡ç¾è¡¨è¾¾å¼ settings.tags.protection.allowed=å…许列表 settings.tags.protection.allowed.users=å…è®¸çš„è´¦å· settings.tags.protection.allowed.teams=å…许的团队 settings.tags.protection.allowed.noone=æ— -settings.tags.protection.create=ä¿æŠ¤Gitæ ‡ç¾ -settings.tags.protection.none=没有å—ä¿æŠ¤çš„Gitæ ‡ç¾ -settings.tags.protection.pattern.description=ä½ å¯ä»¥ä½¿ç”¨å•个å称或 glob 模å¼åŒ¹é…或æ£åˆ™è¡¨è¾¾å¼æ¥åŒ¹é…å¤šä¸ªæ ‡ç¾ã€‚了解详情请访问 <a target="_blank" rel="noopener" href="%s">ä¿æŠ¤Gitæ ‡ç¾æŒ‡å—</a>。 +settings.tags.protection.create=ä¿æŠ¤ Git æ ‡ç¾ +settings.tags.protection.none=没有å—ä¿æŠ¤çš„ Git æ ‡ç¾ã€‚ +settings.tags.protection.pattern.description=您å¯ä»¥ä½¿ç”¨å•个å称或 glob 模å¼åŒ¹é…或æ£åˆ™è¡¨è¾¾å¼æ¥åŒ¹é…å¤šä¸ªæ ‡ç¾ã€‚了解详情请访问 <a target="_blank" rel="noopener" href="%s">ä¿æŠ¤ Git æ ‡ç¾æŒ‡å—</a>。 settings.bot_token=Bot 令牌 settings.chat_id=èŠå¤© ID settings.thread_id=线程 ID @@ -2566,13 +2566,13 @@ settings.visibility.error=试图更改仓库å¯è§æ€§æ—¶å‡ºé”™ã€‚ settings.visibility.fork_error=æ— æ³•æ›´æ”¹æ´¾ç”Ÿä»“åº“çš„å¯è§æ€§ã€‚ settings.archive.button=归档仓库 settings.archive.header=å½’æ¡£æ¤ä»“库 -settings.archive.text=归档仓库将使其完全åªè¯»ã€‚它将在首页éšè—ã€‚æ²¡æœ‰äººï¼ˆç”šè‡³ä½ ï¼ï¼‰èƒ½å¤Ÿè¿›è¡Œæ–°çš„æäº¤ï¼Œæˆ–打开工å•åŠåˆå¹¶è¯·æ±‚。 +settings.archive.text=归档仓库将使其完全åªè¯»ã€‚它将在首页éšè—。没有人(包括您)能够进行新的æäº¤ï¼Œæˆ–打开工å•åŠåˆå¹¶è¯·æ±‚。 settings.archive.success=仓库已æˆåŠŸå½’æ¡£ã€‚ settings.archive.error=仓库在归档时出现异常。请通过日志获å–详细信æ¯ã€‚ settings.archive.error_ismirror=请ä¸è¦å¯¹é•œåƒä»“åº“å½’æ¡£ï¼Œè°¢è°¢ï¼ settings.archive.branchsettings_unavailable=å·²å½’æ¡£ä»“åº“æ— æ³•è¿›è¡Œåˆ†æ”¯è®¾ç½®ã€‚ -settings.archive.tagsettings_unavailable=已归档仓库的Gitæ ‡ç¾è®¾ç½®ä¸å¯ç”¨ã€‚ -settings.archive.mirrors_unavailable=如果仓库已被归档,镜åƒå°†ä¸å¯ç”¨ã€‚ +settings.archive.tagsettings_unavailable=已归档仓库的 Git æ ‡ç¾è®¾ç½®ä¸å¯ç”¨ã€‚ +settings.archive.mirrors_unavailable=如果仓库已归档,镜åƒå°†ä¸å¯ç”¨ã€‚ settings.unarchive.button=撤销仓库归档 settings.unarchive.header=撤销æ¤ä»“库归档 settings.unarchive.text=撤销归档将æ¢å¤ä»“库接收æäº¤ã€æŽ¨é€ï¼Œä»¥åŠæ–°å·¥å•å’Œåˆå¹¶è¯·æ±‚的能力。 @@ -2626,7 +2626,7 @@ diff.whitespace_show_everything=显示所有更改 diff.whitespace_ignore_all_whitespace=æ¯”è¾ƒè¡Œæ—¶å¿½ç•¥ç©ºç™½ç¬¦å· diff.whitespace_ignore_amount_changes=å¿½ç•¥ç©ºç™½ç¬¦å·æ•°é‡çš„å˜åŒ– diff.whitespace_ignore_at_eol=忽略行末空白符å·çš„æ›´æ”¹ -diff.stats_desc=共有 <strong> %d 个文件被更改</strong>,包括 <strong>%d 次æ’å…¥</strong> å’Œ <strong>%d æ¬¡åˆ é™¤</strong> +diff.stats_desc=å…±<strong>修改 %d 个文件</strong>ï¼ŒåŒ…å« <strong>%d 行新增</strong>å’Œ <strong>%d è¡Œåˆ é™¤</strong> diff.stats_desc_file=å˜æ›´ %d 行:新增 %d è¡Œï¼Œåˆ é™¤ %d 行 diff.bin=二进制 diff.bin_not_shown=二进制文件未显示。 @@ -2670,22 +2670,22 @@ diff.submodule_deleted=忍¡å— %[1]s 已从 %[2]s ä¸åˆ 除 diff.submodule_updated=忍¡å— %[1]s 已更新:%[2]s releases.desc=跟踪项目版本和下载。 -release.releases=版本å‘布 +release.releases=å‘布 release.detail=å‘布详情 -release.tags=Gitæ ‡ç¾ +release.tags=Git æ ‡ç¾ release.new_release=å‘布新版 release.draft=è‰ç¨¿ -release.prerelease=预å‘行 +release.prerelease=预å‘布 release.stable=稳定 -release.latest=最新版本 +release.latest=最新 release.compare=比较 release.edit=编辑 release.ahead.commits=<strong>%d</strong> 次æäº¤ -release.ahead.target=在æ¤ç‰ˆæœ¬å‘布åŽè¢«åŠ å…¥åˆ° %s +release.ahead.target=在æ¤ç‰ˆæœ¬å‘布åŽå·²åŠ å…¥åˆ° %s tag.ahead.target=è‡ªæ¤æ ‡ç¾åˆ° %s release.source_code=æºä»£ç -release.new_subheader=版本å‘布组织项目的版本。 -release.edit_subheader=版本å‘布组织项目的版本。 +release.new_subheader=å‘布组织项目的版本。 +release.edit_subheader=å‘布组织项目的版本。 release.tag_name=æ ‡ç¾åç§° release.target=ç›®æ ‡åˆ†æ”¯ release.tag_helper=选择一个å˜åœ¨çš„æ ‡ç¾æˆ–è€…åˆ›å»ºæ–°æ ‡ç¾ã€‚ @@ -2694,74 +2694,74 @@ release.tag_helper_existing=çŽ°æœ‰æ ‡ç¾ã€‚ release.title=å‘å¸ƒæ ‡é¢˜ release.title_empty=æ ‡é¢˜ä¸èƒ½ä¸ºç©ºã€‚ release.message=æè¿°è¿™ä¸ªç‰ˆæœ¬ -release.prerelease_desc=æ ‡è®°ä¸ºé¢„å‘行 +release.prerelease_desc=æ ‡è®°ä¸ºé¢„å‘布 release.prerelease_helper=æ ‡è®°æ¤ç‰ˆæœ¬ä¸é€‚åˆç”Ÿäº§ä½¿ç”¨ã€‚ release.cancel=å–æ¶ˆ release.publish=å‘布版本 release.save_draft=ä¿å˜è‰ç¨¿ release.edit_release=ä¿å˜æ¤æ¬¡å‘布 release.delete_release=åˆ é™¤å‘布 -release.delete_tag=åˆ é™¤ Gitæ ‡ç¾ +release.delete_tag=åˆ é™¤ Git æ ‡ç¾ release.deletion=åˆ é™¤å‘布 release.deletion_desc=åˆ é™¤ç‰ˆæœ¬å‘布åªä¼šä»Ž Gitea ä¸ç§»é™¤ã€‚è¿™ä¸ä¼šå½±å“ Git çš„æ ‡ç¾ä»¥åŠæ‚¨ä»“库的内容和历å²ã€‚是å¦ç»§ç»ï¼Ÿ -release.deletion_success=Releaseå·²è¢«åˆ é™¤ã€‚ -release.deletion_tag_desc=将从仓库ä¸åˆ é™¤æ¤ Gitæ ‡ç¾ã€‚仓库内容和历å²è®°å½•ä¿æŒä¸å˜ã€‚ç»§ç»å—? -release.deletion_tag_success=该 Gitæ ‡ç¾ å·²ç»è¢«åˆ 除 -release.tag_name_already_exist=ä½¿ç”¨æ¤æ ‡ç¾åç§°çš„å‘布版本已ç»å˜åœ¨ã€‚ +release.deletion_success=该å‘å¸ƒå·²åˆ é™¤ã€‚ +release.deletion_tag_desc=将从仓库ä¸åˆ é™¤æ¤ Git æ ‡ç¾ã€‚仓库内容和历å²è®°å½•ä¿æŒä¸å˜ã€‚ç»§ç»å—? +release.deletion_tag_success=该 Git æ ‡ç¾å·²åˆ 除。 +release.tag_name_already_exist=ä½¿ç”¨æ¤æ ‡ç¾åç§°çš„å‘布已ç»å˜åœ¨ã€‚ release.tag_name_invalid=æ ‡ç¾åç§°æ— æ•ˆã€‚ -release.tag_name_protected=Gitæ ‡ç¾åç§°å·²å—ä¿æŠ¤ã€‚ -release.tag_already_exist=æ¤ Gitæ ‡ç¾ åç§°å·²å˜åœ¨ +release.tag_name_protected=Git æ ‡ç¾åç§°å·²å—ä¿æŠ¤ã€‚ +release.tag_already_exist=æ¤ Git æ ‡ç¾åç§°å·²å˜åœ¨ã€‚ release.downloads=下载附件 release.download_count=下载:%s release.add_tag_msg=使用å‘å¸ƒçš„æ ‡é¢˜å’Œå†…å®¹ä½œä¸ºæ ‡ç¾æ¶ˆæ¯ã€‚ release.add_tag=ä»…åˆ›å»ºæ ‡ç¾ -release.releases_for=%s 的版本å‘布 +release.releases_for=%s çš„å‘布 release.tags_for=%s çš„æ ‡ç¾ branch.name=分支åç§° -branch.already_exists=å为 %s 的分支已å˜åœ¨ã€‚ +branch.already_exists=å为「%sã€çš„分支已å˜åœ¨ã€‚ branch.delete_head=刪除 -branch.delete=åˆ é™¤åˆ†æ”¯ %s +branch.delete=åˆ é™¤åˆ†æ”¯ã€Œ%s〠branch.delete_html=åˆ é™¤åˆ†æ”¯ branch.delete_desc=åˆ é™¤åˆ†æ”¯æ˜¯æ°¸ä¹…çš„ã€‚è™½ç„¶å·²åˆ é™¤çš„åˆ†æ”¯åœ¨å®žé™…è¢«åˆ é™¤å‰æœ‰å¯èƒ½ä¼šçŸæ—¶é—´å˜åœ¨ï¼Œä½†è¿™åœ¨å¤§å¤šæ•°æƒ…å†µä¸‹æ— æ³•æ’¤é”€ã€‚æ˜¯å¦ç»§ç»ï¼Ÿ -branch.deletion_success=分支 %s å·²è¢«åˆ é™¤ã€‚ -branch.deletion_failed=åˆ é™¤åˆ†æ”¯ %s 失败。 -branch.delete_branch_has_new_commits=å› ä¸ºåˆå¹¶ä¹‹åŽæœ‰æ–°çš„æäº¤ï¼Œåˆ†æ”¯ %s æ— æ³•è¢«åˆ é™¤ã€‚ +branch.deletion_success=分支「%sã€åˆ 除æˆåŠŸã€‚ +branch.deletion_failed=分支「%sã€åˆ 除失败。 +branch.delete_branch_has_new_commits=å› ä¸ºåˆå¹¶ä¹‹åŽæœ‰æ–°çš„æäº¤ï¼Œåˆ†æ”¯ã€Œ%sã€æ— æ³•åˆ é™¤ã€‚ branch.create_branch=创建分支 %s -branch.create_from=从 %s -branch.create_success=分支 '%s' 已创建。 -branch.branch_already_exists=æ¤ä»“库已å˜åœ¨å为 %s 的分支。 -branch.branch_name_conflict=分支åç§°"%s"与已å˜åœ¨çš„分支"%s"冲çªã€‚ -branch.tag_collision=分支 %s ä¸èƒ½è¢«åˆ›å»ºå› 为åŒåçš„æ ‡ç¾å·²ç»å˜åœ¨ã€‚ +branch.create_from=从「%s〠+branch.create_success=分支「%sã€å·²åˆ›å»ºã€‚ +branch.branch_already_exists=æ¤ä»“库已å˜åœ¨å为「%sã€çš„分支。 +branch.branch_name_conflict=分支å称「%sã€ä¸Žå·²å˜åœ¨çš„分支「%sã€å†²çªã€‚ +branch.tag_collision=分支「%sã€æ— æ³•åˆ›å»ºï¼Œå› ä¸ºåŒåçš„æ ‡ç¾å·²ç»å˜åœ¨ã€‚ branch.deleted_by=åˆ é™¤äººï¼š%s -branch.restore_success=分支 "%s"已还原。 -branch.restore_failed=还原分支 "%s"失败。 -branch.protected_deletion_failed=ä¸èƒ½åˆ 除å—ä¿æŠ¤çš„åˆ†æ”¯ "%s"。 -branch.default_deletion_failed=ä¸èƒ½åˆ 除默认分支"%s"。 -branch.default_branch_not_exist=默认分支 %s ä¸å˜åœ¨ã€‚ -branch.restore=`还原分支 "%s"` -branch.download=`下载分支 "%s"` -branch.rename=`é‡å‘½å分支 "%s"` +branch.restore_success=分支「%sã€å·²è¿˜åŽŸã€‚ +branch.restore_failed=分支「%sã€è¿˜åŽŸå¤±è´¥ã€‚ +branch.protected_deletion_failed=ä¸èƒ½åˆ 除å—ä¿æŠ¤çš„åˆ†æ”¯ã€Œ%sã€ã€‚ +branch.default_deletion_failed=ä¸èƒ½åˆ 除默认分支「%sã€ã€‚ +branch.default_branch_not_exist=默认分支「%sã€ä¸å˜åœ¨ã€‚ +branch.restore=还原分支「%s〠+branch.download=下载分支「%s〠+branch.rename=é‡å‘½å分支「%s〠branch.included_desc=æ¤åˆ†æ”¯æ˜¯é»˜è®¤åˆ†æ”¯çš„一部分 branch.included=å·²åŒ…å« branch.create_new_branch=从下列分支创建分支: branch.confirm_create_branch=创建分支 branch.warning_rename_default_branch=您æ£åœ¨é‡å‘½å默认分支。 -branch.rename_branch_to=é‡å‘½å %s 为: +branch.rename_branch_to=é‡å‘½å「%sã€ä¸ºï¼š branch.confirm_rename_branch=é‡å‘½å分支 branch.create_branch_operation=创建分支 branch.new_branch=创建新分支 -branch.new_branch_from=基于"%s"创建新分支 -branch.renamed=分支 %s 被é‡å‘½å为 %s。 +branch.new_branch_from=基于「%sã€åˆ›å»ºæ–°åˆ†æ”¯ +branch.renamed=分支 %s å·²é‡å‘½å为 %s。 branch.rename_default_or_protected_branch_error=åªæœ‰ç®¡ç†å‘˜èƒ½é‡å‘½å默认分支和å—ä¿æŠ¤çš„åˆ†æ”¯ã€‚ branch.rename_protected_branch_failed=æ¤åˆ†æ”¯å—到 glob è¯æ³•è§„åˆ™çš„ä¿æŠ¤ã€‚ tag.create_tag=åˆ›å»ºæ ‡ç¾ %s tag.create_tag_operation=åˆ›å»ºæ ‡ç¾ tag.confirm_create_tag=åˆ›å»ºæ ‡ç¾ -tag.create_tag_from=基于"%s"åˆ›å»ºæ–°æ ‡ç¾ +tag.create_tag_from=基于「%sã€åˆ›å»ºæ–°æ ‡ç¾ -tag.create_success=æ ‡ç¾"%s"å·²å˜åœ¨ +tag.create_success=æ ‡ç¾ã€Œ%sã€å·²å˜åœ¨ã€‚ topic.manage_topics=管ç†ä¸»é¢˜ topic.done=ä¿å˜ @@ -2808,14 +2808,14 @@ team_permission_desc=æƒé™ team_unit_desc=å…许访问仓库å•å…ƒ team_unit_disabled=(å·²ç¦ç”¨) -form.name_reserved=组织åç§° '%s' 是被ä¿ç•™çš„。 -form.name_pattern_not_allowed=仓库åç§°ä¸ä¸å…许使用 "%s"。 +form.name_reserved=组织å称「%sã€æ˜¯ä¿ç•™çš„。 +form.name_pattern_not_allowed=仓库åç§°ä¸ä¸å…许使用「%sã€ã€‚ form.create_org_not_allowed=æ¤è´¦å·ç¦æ¢åˆ›å»ºç»„织 settings=组织设置 settings.options=组织 settings.full_name=组织全å -settings.email=è”系电å邮件 +settings.email=è”系邮箱 settings.website=网站 settings.location=所在地区 settings.permission=æƒé™ @@ -2837,7 +2837,7 @@ settings.delete_account=åˆ é™¤å½“å‰ç»„织 settings.delete_prompt=åˆ é™¤æ“作会永久清除该组织的信æ¯ï¼Œå¹¶ä¸” <strong>ä¸å¯æ¢å¤</strong>ï¼ settings.confirm_delete_account=ç¡®è®¤åˆ é™¤ç»„ç»‡ settings.delete_org_title=åˆ é™¤ç»„ç»‡ -settings.delete_org_desc=æ¤ç»„ç»‡å°†ä¼šè¢«æ°¸ä¹…åˆ é™¤ï¼Œç¡®è®¤ç»§ç»å—? +settings.delete_org_desc=æ¤ç»„ç»‡å°†ä¼šæ°¸ä¹…åˆ é™¤ï¼Œç¡®è®¤ç»§ç»å—? settings.hooks_desc=在æ¤å¤„æ·»åŠ çš„ Web é’©å将会应用到该组织下的 <strong>所有仓库</strong>。 settings.labels_desc=æ·»åŠ èƒ½å¤Ÿè¢«è¯¥ç»„ç»‡ä¸‹çš„ <strong>所有仓库</strong> 的工å•ä½¿ç”¨çš„æ ‡ç¾ã€‚ @@ -2883,7 +2883,7 @@ teams.invite_team_member=é‚€è¯·åŠ å…¥ %s teams.invite_team_member.list=待处ç†çš„邀请 teams.delete_team_title=åˆ é™¤å›¢é˜Ÿ teams.delete_team_desc=åˆ é™¤ä¸€ä¸ªå›¢é˜Ÿå°†åˆ é™¤å›¢é˜Ÿæˆå‘˜çš„访问æƒé™ï¼Œç»§ç»ï¼Ÿ -teams.delete_team_success=è¯¥å›¢é˜Ÿå·²è¢«åˆ é™¤ã€‚ +teams.delete_team_success=è¯¥å›¢é˜Ÿå·²åˆ é™¤ã€‚ teams.read_permission_desc=该团队拥有对所属仓库的 <strong>读å–</strong> æƒé™ï¼Œå›¢é˜Ÿæˆå‘˜å¯ä»¥è¿›è¡ŒæŸ¥çœ‹å’Œå…‹éš†ç‰åªè¯»æ“作。 teams.write_permission_desc=该团队拥有对所属仓库的 <strong>读å–</strong> å’Œ <strong>写入</strong> çš„æƒé™ã€‚ teams.admin_permission_desc=该团队拥有一定的 <strong>管ç†</strong> æƒé™ï¼Œå›¢é˜Ÿæˆå‘˜å¯ä»¥è¯»å–ã€å…‹éš†ã€æŽ¨é€ä»¥åŠæ·»åŠ å…¶å®ƒä»“åº“å作者。 @@ -2934,7 +2934,7 @@ repositories=ä»“åº“ç®¡ç† hooks=Web é’©å integrations=é›†æˆ authentication=è®¤è¯æº -emails=用户邮件 +emails=用户邮箱 config=应用é…ç½® config_summary=æ‘˜è¦ config_settings=设置 @@ -2953,27 +2953,27 @@ dashboard.operation_name=æ“作åç§° dashboard.operation_switch=开关 dashboard.operation_run=执行 dashboard.clean_unbind_oauth=æ¸…ç†æœªç»‘定的 OAuth 连接 -dashboard.clean_unbind_oauth_success=所有未绑定的 OAuth è¿žæŽ¥å·²è¢«åˆ é™¤ã€‚ +dashboard.clean_unbind_oauth_success=所有未绑定的 OAuth è¿žæŽ¥å·²åˆ é™¤ã€‚ dashboard.task.started=已开始任务:%[1]s dashboard.task.process=任务: %[1]s dashboard.task.cancelled=任务: %[1]s 已喿¶ˆ: %[3]s dashboard.task.error=任务ä¸çš„错误: %[1]s: %[3]s dashboard.task.finished=任务: %[2]s å¯åŠ¨çš„ %[1]s å·²å®Œæˆ dashboard.task.unknown=未知任务: %[1]s -dashboard.cron.started=已开始计划任务:%[1]s +dashboard.cron.started=计划任务:%[1]s å·²å¯åЍ dashboard.cron.process=计划任务:%[1]s -dashboard.cron.cancelled=定时任务: %[1]s 已喿¶ˆ: %[3]s -dashboard.cron.error=任务ä¸çš„错误: %s: %[3]s -dashboard.cron.finished=任务:%[1]s å·²ç»å®Œæˆ +dashboard.cron.cancelled=计划任务:%[1]s 已喿¶ˆï¼š%[3]s +dashboard.cron.error=计划任务错误: %s: %[3]s +dashboard.cron.finished=计划任务:%[1]s å·²å®Œæˆ dashboard.delete_inactive_accounts=åˆ é™¤æ‰€æœ‰æœªæ¿€æ´»çš„å¸æˆ· dashboard.delete_inactive_accounts.started=åˆ é™¤æ‰€æœ‰æœªæ¿€æ´»çš„è´¦æˆ·ä»»åŠ¡å·²å¯åŠ¨ã€‚ -dashboard.delete_repo_archives=åˆ é™¤æ‰€æœ‰ä»£ç åº“çš„å˜æ¡£ (ZIP〠TARã€GZ, ç‰...) +dashboard.delete_repo_archives=åˆ é™¤æ‰€æœ‰ä»“åº“çš„å˜æ¡£ï¼ˆZIPã€TARã€GZç‰ï¼‰ dashboard.delete_repo_archives.started=åˆ é™¤æ‰€æœ‰ä»“åº“å˜æ¡£ä»»åС已å¯åŠ¨ã€‚ dashboard.delete_missing_repos=åˆ é™¤æ‰€æœ‰ä¸¢å¤± Git 文件的仓库 dashboard.delete_missing_repos.started=åˆ é™¤æ‰€æœ‰ä¸¢å¤± Git 文件的仓库任务已å¯åŠ¨ã€‚ dashboard.delete_generated_repository_avatars=åˆ é™¤ç”Ÿæˆçš„ä»“åº“å¤´åƒ -dashboard.sync_repo_branches=将缺少的分支从 git æ•°æ®åŒæ¥åˆ°æ•°æ®åº“ -dashboard.sync_repo_tags=从 git æ•°æ®åŒæ¥æ ‡ç¾åˆ°æ•°æ®åº“ +dashboard.sync_repo_branches=将缺少的分支从 Git æ•°æ®åŒæ¥åˆ°æ•°æ®åº“ +dashboard.sync_repo_tags=从 Git æ•°æ®åŒæ¥æ ‡ç¾åˆ°æ•°æ®åº“ dashboard.update_mirrors=更新镜åƒä»“库 dashboard.repo_health_check=å¥åº·æ£€æŸ¥æ‰€æœ‰ä»“库 dashboard.check_repo_stats=检查所有仓库统计 @@ -2988,11 +2988,11 @@ dashboard.reinit_missing_repos=釿–°åˆå§‹åŒ–所有丢失的 Git 仓库å˜åœ¨çš dashboard.sync_external_users=åŒæ¥å¤–éƒ¨ç”¨æˆ·æ•°æ® dashboard.cleanup_hook_task_table=æ¸…ç† hook_task 表 dashboard.cleanup_packages=清ç†è¿‡æœŸçš„软件包 -dashboard.cleanup_actions=清ç†è¿‡æœŸçš„ Actions èµ„æº +dashboard.cleanup_actions=清ç†è¿‡æœŸçš„工作æµèµ„æº dashboard.server_uptime=æœåŠ¡è¿è¡Œæ—¶é—´ dashboard.current_goroutine=å½“å‰ Goroutines æ•°é‡ dashboard.current_memory_usage=当å‰å†…å˜ä½¿ç”¨é‡ -dashboard.total_memory_allocated=所有被分é…çš„å†…å˜ +dashboard.total_memory_allocated=所有已分é…çš„å†…å˜ dashboard.memory_obtained=内å˜å ç”¨é‡ dashboard.pointer_lookup_times=指针查找次数 dashboard.memory_allocate_times=内å˜åˆ†é…次数 @@ -3001,36 +3001,36 @@ dashboard.current_heap_usage=å½“å‰ Heap 内å˜ä½¿ç”¨é‡ dashboard.heap_memory_obtained=Heap 内å˜å ç”¨é‡ dashboard.heap_memory_idle=Heap 内å˜ç©ºé—²é‡ dashboard.heap_memory_in_use=æ£åœ¨ä½¿ç”¨çš„ Heap å†…å˜ -dashboard.heap_memory_released=被释放的 Heap å†…å˜ +dashboard.heap_memory_released=已释放的 Heap å†…å˜ dashboard.heap_objects=Heap å¯¹è±¡æ•°é‡ dashboard.bootstrap_stack_usage=å¯åЍ Stack ä½¿ç”¨é‡ -dashboard.stack_memory_obtained=被分é…çš„ Stack å†…å˜ +dashboard.stack_memory_obtained=已分é…çš„ Stack å†…å˜ dashboard.mspan_structures_usage=MSpan 结构内å˜ä½¿ç”¨é‡ -dashboard.mspan_structures_obtained=被分é…çš„ MSpan ç»“æž„å†…å˜ +dashboard.mspan_structures_obtained=已分é…çš„ MSpan ç»“æž„å†…å˜ dashboard.mcache_structures_usage=MCache 结构内å˜ä½¿ç”¨é‡ -dashboard.mcache_structures_obtained=被分é…çš„ MCache ç»“æž„å†…å˜ -dashboard.profiling_bucket_hash_table_obtained=被分é…的剖æžå“ˆå¸Œè¡¨å†…å˜ -dashboard.gc_metadata_obtained=被分é…çš„ GC 元数æ®å†…å˜ -dashboard.other_system_allocation_obtained=其它被分é…çš„ç³»ç»Ÿå†…å˜ +dashboard.mcache_structures_obtained=已分é…çš„ MCache ç»“æž„å†…å˜ +dashboard.profiling_bucket_hash_table_obtained=已分é…的剖æžå“ˆå¸Œè¡¨å†…å˜ +dashboard.gc_metadata_obtained=已分é…çš„ GC 元数æ®å†…å˜ +dashboard.other_system_allocation_obtained=其它已分é…çš„ç³»ç»Ÿå†…å˜ dashboard.next_gc_recycle=下次 GC 内å˜å›žæ”¶é‡ dashboard.last_gc_time=è·ç¦»ä¸Šæ¬¡ GC æ—¶é—´ dashboard.total_gc_time=GC æš‚åœæ—¶é—´æ€»é‡ dashboard.total_gc_pause=GC æš‚åœæ—¶é—´æ€»é‡ dashboard.last_gc_pause=上次 GC æš‚åœæ—¶é—´ dashboard.gc_times=GC 执行次数 -dashboard.delete_old_actions=从数æ®åº“ä¸åˆ 除所有旧æ“作记录 -dashboard.delete_old_actions.started=已开始从数æ®åº“ä¸åˆ 除所有旧æ“作记录。 +dashboard.delete_old_actions=从数æ®åº“ä¸åˆ 除所有旧工作æµè®°å½• +dashboard.delete_old_actions.started=已开始从数æ®åº“ä¸åˆ 除所有旧工作æµè®°å½•。 dashboard.update_checker=更新检查器 dashboard.delete_old_system_notices=从数æ®åº“ä¸åˆ 除所有旧系统通知 dashboard.gc_lfs=垃圾回收 LFS å…ƒæ•°æ® -dashboard.stop_zombie_tasks=åœæ¢åƒµå°¸ä»»åŠ¡ -dashboard.stop_endless_tasks=åœæ¢æ— æ³•åœæ¢çš„任务 -dashboard.cancel_abandoned_jobs=å–æ¶ˆä¸¢å¼ƒçš„任务 -dashboard.start_schedule_tasks=开始Actions调度任务 +dashboard.stop_zombie_tasks=åœæ¢åƒµå°¸å·¥ä½œæµä»»åŠ¡ +dashboard.stop_endless_tasks=åœæ¢æ— é™å¾ªçŽ¯çš„å·¥ä½œæµä»»åŠ¡ +dashboard.cancel_abandoned_jobs=å–æ¶ˆå·²æ”¾å¼ƒçš„工作æµä»»åŠ¡ +dashboard.start_schedule_tasks=å¯åŠ¨å·¥ä½œæµè®¡åˆ’任务 dashboard.sync_branch.started=åˆ†æ”¯åŒæ¥å·²å¼€å§‹ dashboard.sync_tag.started=æ ‡ç¾åŒæ¥å·²å¼€å§‹ dashboard.rebuild_issue_indexer=é‡å»ºå·¥å•索引 -dashboard.sync_repo_licenses=釿–°ä»“库许å¯è¯æŽ¢æµ‹ +dashboard.sync_repo_licenses=釿–°æŽ¢æµ‹ä»“库许å¯è¯ users.user_manage_panel=ç”¨æˆ·å¸æˆ·ç®¡ç† users.new_account=åˆ›å»ºæ–°å¸æˆ· @@ -3048,33 +3048,33 @@ users.created=创建时间 users.last_login=上次登录 users.never_login=从未登录 users.send_register_notify=å‘逿³¨å†Œé€šçŸ¥ -users.new_success=用户账户 '%s' 已被创建。 +users.new_success=用户账户「%sã€å·²åˆ›å»ºã€‚ users.edit=修改 users.auth_source=è®¤è¯æº users.local=本地 users.auth_login_name=认è¯ç™»å½•åç§° users.password_helper=ä¿æŒå¯†ç ä¸ºç©ºå°†ä¸æ›´æ”¹å¯†ç 。 -users.update_profile_success=è¯¥å¸æˆ·å·²è¢«æ›´æ–°ã€‚ +users.update_profile_success=è¯¥å¸æˆ·å·²æ›´æ–°ã€‚ users.edit_account=编辑å¸å· users.max_repo_creation=最大仓库数 users.max_repo_creation_desc=(设置为 -1 表示使用全局默认值) -users.is_activated=该用户已被激活 +users.is_activated=该用户已激活 users.prohibit_login=ç¦ç”¨ç™»å½• users.is_admin=是管ç†å‘˜ users.is_restricted=å—é™ users.allow_git_hook=å…许创建 Git é’©å -users.allow_git_hook_tooltip=Git é’©å将会被以æ“作系统用户è¿è¡Œï¼Œå°†ä¼šæ‹¥æœ‰åŒæ ·çš„主机访问æƒé™ã€‚å› æ¤ï¼Œæ‹¥æœ‰æ¤ç‰¹æ®Šçš„Git é’©åæƒé™å°†èƒ½å¤Ÿè®¿é—®åˆä¿®æ”¹æ‰€æœ‰çš„ Gitea 仓库或者Gitea的数æ®åº“ã€‚åŒæ—¶ä¹Ÿèƒ½èŽ·å¾—Gitea的管ç†å‘˜æƒé™ã€‚ +users.allow_git_hook_tooltip=Git é’©å将会以æ“作系统用户è¿è¡Œï¼Œæ‹¥æœ‰åŒæ ·çš„主机访问æƒé™ã€‚å› æ¤ï¼Œæ‹¥æœ‰æ¤ç‰¹æ®Šçš„ Git é’©åæƒé™å°†èƒ½å¤Ÿè®¿é—®åˆä¿®æ”¹æ‰€æœ‰çš„ Gitea 仓库或者 Gitea 的数æ®åº“ã€‚åŒæ—¶ä¹Ÿèƒ½èŽ·å¾— Gitea 的管ç†å‘˜æƒé™ã€‚ users.allow_import_local=å…许导入本地仓库 users.allow_create_organization=å…许创建组织 users.update_profile=æ›´æ–°å¸æˆ· users.delete_account=åˆ é™¤å¸æˆ· -users.cannot_delete_self=ä½ ä¸èƒ½åˆ 除自己 -users.still_own_repo=æ¤ç”¨æˆ·ä»ç„¶æ‹¥æœ‰ä¸€ä¸ªæˆ–å¤šä¸ªä»“åº“ã€‚å¿…é¡»é¦–å…ˆåˆ é™¤æˆ–è½¬è®©è¿™äº›ä»“åº“ã€‚ +users.cannot_delete_self=您ä¸èƒ½åˆ 除自己 +users.still_own_repo=æ¤ç”¨æˆ·ä»ç„¶æ‹¥æœ‰ä¸€ä¸ªæˆ–å¤šä¸ªä»“åº“ã€‚å¿…é¡»é¦–å…ˆåˆ é™¤æˆ–è½¬ç§»è¿™äº›ä»“åº“ã€‚ users.still_has_org=æ¤ç”¨æˆ·æ˜¯ç»„织的æˆå‘˜ã€‚必须先从组织ä¸åˆ 除用户。 users.purge=清ç†ç”¨æˆ· -users.purge_help=å¼ºåˆ¶åˆ é™¤ç”¨æˆ·å’Œç”¨æˆ·æ‹¥æœ‰çš„ä»»ä½•ä»“åº“ã€ç»„ç»‡å’Œè½¯ä»¶åŒ…ã€‚æ‰€æœ‰è¯„è®ºä¹Ÿå°†è¢«åˆ é™¤ã€‚ +users.purge_help=å¼ºåˆ¶åˆ é™¤ç”¨æˆ·å’Œç”¨æˆ·æ‹¥æœ‰çš„ä»»ä½•ä»“åº“ã€ç»„ç»‡å’Œè½¯ä»¶åŒ…ã€‚æ‰€æœ‰è¯„è®ºä¹Ÿå°†åˆ é™¤ã€‚ users.still_own_packages=æ¤ç”¨æˆ·ä»ç„¶æ‹¥æœ‰ä¸€ä¸ªæˆ–å¤šä¸ªè½¯ä»¶åŒ…ï¼Œè¯·å…ˆåˆ é™¤è¿™äº›è½¯ä»¶åŒ…ã€‚ -users.deletion_success=ç”¨æˆ·å¸æˆ·å·²è¢«åˆ 除。 +users.deletion_success=ç”¨æˆ·å¸æˆ·å·²åˆ 除。 users.reset_2fa=é‡ç½®ä¸¤æ¥éªŒè¯ users.list_status_filter.menu_text=过滤 users.list_status_filter.reset=é‡ç½® @@ -3093,19 +3093,19 @@ users.details=ç”¨æˆ·è¯¦ç»†ä¿¡æ¯ emails.email_manage_panel=é‚®ä»¶ç®¡ç† emails.primary=主è¦çš„ emails.activated=已激活 -emails.filter_sort.email=电å邮件 -emails.filter_sort.email_reverse=电å邮件(逆åº) +emails.filter_sort.email=邮箱 +emails.filter_sort.email_reverse=邮箱(倒åºï¼‰ emails.filter_sort.name=用户å emails.filter_sort.name_reverse=用户å(倒åº) -emails.updated=电å邮件已更新 -emails.not_updated=æ— æ³•æ›´æ–°è¯·æ±‚çš„ç”µå邮件地å€ï¼š %v -emails.duplicate_active=æ¤ç”µå邮件地å€å·²è¢«å¦ä¸€ä¸ªç”¨æˆ·æ¿€æ´»ä½¿ç”¨ã€‚ -emails.change_email_header=更新电å邮件属性 -emails.change_email_text=æ‚¨ç¡®å®šè¦æ›´æ–°è¯¥ç”µå邮件地å€å—? -emails.delete=åˆ é™¤ç”µå邮件 -emails.delete_desc=您确定è¦åˆ 除该电å邮件地å€ï¼Ÿ -emails.deletion_success=电å邮件地å€å·²è¢«åˆ 除。 -emails.delete_primary_email_error=您ä¸èƒ½åˆ 除主电å邮件。 +emails.updated=邮箱已更新 +emails.not_updated=æ— æ³•æ›´æ–°è¯·æ±‚çš„é‚®ç®±åœ°å€ï¼š%v +emails.duplicate_active=æ¤é‚®ç®±åœ°å€å·²è¢«å¦ä¸€ä¸ªç”¨æˆ·æ¿€æ´»ä½¿ç”¨ã€‚ +emails.change_email_header=更新邮箱属性 +emails.change_email_text=æ‚¨ç¡®å®šè¦æ›´æ–°è¯¥é‚®ç®±åœ°å€å—? +emails.delete=åˆ é™¤é‚®ç®± +emails.delete_desc=您确定è¦åˆ 除该邮箱地å€ï¼Ÿ +emails.deletion_success=邮箱地å€å·²åˆ 除。 +emails.delete_primary_email_error=您ä¸èƒ½åˆ 除主邮箱。 orgs.org_manage_panel=ç»„ç»‡ç®¡ç† orgs.name=åç§° @@ -3125,7 +3125,7 @@ repos.lfs_size=LFS å¤§å° packages.package_manage_panel=è½¯ä»¶åŒ…ç®¡ç† packages.total_size=总大å°ï¼š%s -packages.unreferenced_size=未引用大å°ï¼š %s +packages.unreferenced_size=未引用大å°ï¼š%s packages.cleanup=清ç†è¿‡æœŸæ•°æ® packages.cleanup.success=清ç†è¿‡æœŸæ•°æ®æˆåŠŸ packages.owner=所有者 @@ -3137,13 +3137,13 @@ packages.repository=仓库 packages.size=å¤§å° packages.published=å·²å‘布 -defaulthooks=默认Webé’©å +defaulthooks=默认 Web é’©å defaulthooks.desc=当æŸäº› Gitea äº‹ä»¶è§¦å‘æ—¶ï¼ŒWeb é’©åè‡ªåŠ¨å‘æœåС噍å‘出 HTTP POST 请求。这里定义的 Web é’©åæ˜¯é»˜è®¤é…置,将被å¤åˆ¶åˆ°æ‰€æœ‰æ–°çš„仓库ä¸ã€‚详情请访问 <a target="_blank" rel="noopener" href="%s">Web é’©åæŒ‡å—</a>。 -defaulthooks.add_webhook=æ·»åŠ é»˜è®¤Web é’©å +defaulthooks.add_webhook=æ·»åŠ é»˜è®¤ Web é’©å defaulthooks.update_webhook=更新默认 Web 钩å systemhooks=系统 Web é’©å -systemhooks.desc=当æŸäº› Gitea äº‹ä»¶è§¦å‘æ—¶ï¼ŒWeb é’©åè‡ªåŠ¨å‘æœåС噍å‘出HTTP POST请求。这里定义的 Web é’©å将作用于系统上的所有仓库,所以请考虑这å¯èƒ½å¸¦æ¥çš„任何性能影å“。了解详情请访问 <a target="_blank" rel="noopener" href="%s">Web é’©åæŒ‡å—</a>。 +systemhooks.desc=当æŸäº› Gitea äº‹ä»¶è§¦å‘æ—¶ï¼ŒWeb é’©åè‡ªåŠ¨å‘æœåС噍å‘出 HTTP POST 请求。这里定义的 Web é’©å将作用于系统上的所有仓库,所以请考虑这å¯èƒ½å¸¦æ¥çš„任何性能影å“。了解详情请访问 <a target="_blank" rel="noopener" href="%s">Web é’©åæŒ‡å—</a>。 systemhooks.add_webhook=æ·»åŠ ç³»ç»Ÿ Web é’©å systemhooks.update_webhook=更新系统 Web é’©å @@ -3165,7 +3165,7 @@ auths.bind_password=绑定密ç auths.user_base=用户æœç´¢åŸºå‡† auths.user_dn=用户 DN auths.attribute_username=用户å属性 -auths.attribute_username_placeholder=置空将使用Gitea的用户å。 +auths.attribute_username_placeholder=置空将使用 Gitea 的用户å。 auths.attribute_name=åå—属性 auths.attribute_surname=å§“æ°å±žæ€§ auths.attribute_mail=电å邮箱属性 @@ -3199,7 +3199,7 @@ auths.helo_hostname=HELO 主机å auths.helo_hostname_helper=用 HELO å‘é€çš„主机å。 留空å‘é€å½“å‰ä¸»æœºå。 auths.disable_helo=ç¦ç”¨ HELO auths.pam_service_name=PAM æœåŠ¡åç§° -auths.pam_email_domain=PAM 电å邮件域(å¯é€‰) +auths.pam_email_domain=PAM 邮件域(å¯é€‰ï¼‰ auths.oauth2_provider=OAuth2 æä¾›ç¨‹åº auths.oauth2_icon_url=å›¾æ ‡ URL auths.oauth2_clientID=客户端 ID (键) @@ -3208,8 +3208,8 @@ auths.openIdConnectAutoDiscoveryURL=OpenID 连接自动å‘现 URL auths.oauth2_use_custom_url=使用自定义的 URL è€Œä¸æ˜¯é»˜è®¤çš„ URL auths.oauth2_tokenURL=令牌 URL auths.oauth2_authURL=æŽˆæƒ URL -auths.oauth2_profileURL=Profile URL -auths.oauth2_emailURL=电å邮件 URL +auths.oauth2_profileURL=个人资料 URL +auths.oauth2_emailURL=邮箱 URL auths.skip_local_two_fa=跳过本地两æ¥éªŒè¯ auths.skip_local_two_fa_helper=ä¸è®¾ç½®æ„味ç€è®¾ç½®äº†ä¸¤æ¥éªŒè¯çš„æœ¬åœ°ç”¨æˆ·ä»ç„¶éœ€è¦é€šè¿‡ä¸¤æ¥éªŒè¯æ‰èƒ½ç™»å½• auths.oauth2_tenant=租户 @@ -3229,31 +3229,31 @@ auths.sspi_auto_create_users_helper=å…许 SSPI 认è¯åœ¨ç”¨æˆ·ç¬¬ä¸€æ¬¡ç™»å½•æ— auths.sspi_auto_activate_users=自动激活用户 auths.sspi_auto_activate_users_helper=å…许 SSPI 认è¯è‡ªåŠ¨æ¿€æ´»æ–°ç”¨æˆ· auths.sspi_strip_domain_names=从用户åä¸åˆ 除域å部分 -auths.sspi_strip_domain_names_helper=å¦‚æžœé€‰ä¸æ¤é¡¹ï¼ŒåŸŸå将从登录åä¸åˆ 除(例如,"DOMAIN\user"å’Œ"user@example.org"ï¼Œä¸¤è€…éƒ½å°†å˜æˆåªæ˜¯â€œç”¨æˆ·â€)。 +auths.sspi_strip_domain_names_helper=å¦‚æžœé€‰ä¸æ¤é¡¹ï¼ŒåŸŸå将从登录åä¸åˆ 除(例如,「DOMAIN\userã€å’Œã€Œuser@example.orgã€ï¼Œä¸¤è€…éƒ½å°†å˜æˆåªæ˜¯ã€Œç”¨æˆ·ã€ï¼‰ã€‚ auths.sspi_separator_replacement=è¦ä½¿ç”¨çš„分隔符代替\, / å’Œ @ -auths.sspi_separator_replacement_helper=用于替æ¢ä¸‹çº§ç™»å½•å称分隔符的å—符 (例如 "DOMAIN\user") ä¸çš„ \ 和用户主åå—(如"user@example.org"ä¸çš„ @)。 +auths.sspi_separator_replacement_helper=用于替æ¢ä¸‹çº§ç™»å½•å称分隔符的å—符(例如「DOMAIN\userã€ï¼‰ä¸çš„ \ 和用户主åå—(如「user@example.orgã€ä¸çš„ @)。 auths.sspi_default_language=默认è¯è¨€ auths.sspi_default_language_helper=SSPI è®¤è¯æ–¹æ³•为用户自动创建的默认è¯è¨€ã€‚如果您想è¦è‡ªåŠ¨æ£€æµ‹åˆ°è¯è¨€ï¼Œè¯·ç•™ç©ºã€‚ auths.tips=帮助æç¤º auths.tips.oauth2.general=OAuth2 è®¤è¯ auths.tips.oauth2.general.tip=当注册新的 OAuth2 èº«ä»½éªŒè¯æ—¶ï¼Œå›žè°ƒ/é‡å®šå‘ URL 应该是: auths.tip.oauth2_provider=OAuth2 æä¾›ç¨‹åº -auths.tip.bitbucket=在 %s 注册新的 OAuth ä½¿ç”¨è€…åŒæ—¶æ·»åŠ æƒé™â€œè´¦å·â€-“读å–†-auths.tip.nextcloud=使用下é¢çš„èœå•“设置(Settings) -> 安全(Security) -> OAuth 2.0 clientâ€åœ¨æ‚¨çš„实例上注册一个新的 OAuth 客户端。 +auths.tip.bitbucket=在 %s 注册新的 OAuth ä½¿ç”¨è€…åŒæ—¶æ·»åŠ æƒé™ã€Œè´¦å·ã€-「读å–〠+auths.tip.nextcloud=使用下é¢çš„èœå•「设置 -> 安全 -> OAuth 2.0 客户端ã€åœ¨æ‚¨çš„实例上注册一个新的 OAuth 客户端 auths.tip.dropbox=在 %s ä¸Šåˆ›å»ºä¸€ä¸ªæ–°çš„åº”ç”¨ç¨‹åº -auths.tip.facebook=`在 %s æ³¨å†Œä¸€ä¸ªæ–°çš„åº”ç”¨ï¼Œå¹¶æ·»åŠ äº§å“"Facebook 登录"` +auths.tip.facebook=在 %s æ³¨å†Œä¸€ä¸ªæ–°çš„åº”ç”¨ï¼Œå¹¶æ·»åŠ äº§å“「Facebook 登录〠auths.tip.github=在 %s 注册一个 OAuth åº”ç”¨ç¨‹åº auths.tip.gitlab_new=在 %s 注册一个新的应用 auths.tip.google_plus=ä»Žè°·æŒ API æŽ§åˆ¶å° %s 获得 OAuth2 å®¢æˆ·ç«¯å‡æ® auths.tip.openid_connect=使用 OpenID 连接å‘现 URL ({server}/.well-known/openid-configuration) æ¥æŒ‡å®šç»ˆç‚¹ -auths.tip.twitter=访问 %s,创建应用并确ä¿å¯ç”¨äº†"å…许æ¤åº”用程åºç”¨äºŽç™»å½• Twitter"的选项。 +auths.tip.twitter=访问 %s,创建应用并确ä¿å¯ç”¨äº†ã€Œå…许æ¤åº”用程åºä½¿ç”¨ Twitter 登录ã€çš„选项 auths.tip.discord=在 %s ä¸Šæ³¨å†Œæ–°åº”ç”¨ç¨‹åº auths.tip.gitea=注册一个新的 OAuth2 应用程åºã€‚å¯ä»¥è®¿é—® %s 查看帮助 -auths.tip.yandex=在 %s 上创建一个新的应用程åºã€‚在“ Yandex.Passport APIâ€è¿™éƒ¨åˆ†ä¸é€‰æ‹©ä»¥ä¸‹æƒé™ï¼šâ€œè®¿é—®ç”µå邮件地å€ï¼ˆAccess to email address)â€ï¼Œâ€œè®¿é—®ç”¨æˆ·å¤´åƒï¼ˆAccess to user avatar)â€å’Œâ€œè®¿é—®ç”¨æˆ·å,åå—和姓æ°ï¼Œæ€§åˆ«ï¼ˆAccess to username, first name and surname, genderAccess to username, first name and surname, gender)†+auths.tip.yandex=在 %s 上创建一个新的应用。在「Yandex.Passport APIã€è¿™éƒ¨åˆ†ä¸é€‰æ‹©ä»¥ä¸‹æƒé™ï¼šã€Œè®¿é—®é‚®ç®±åœ°å€ã€ï¼Œã€Œè®¿é—®ç”¨æˆ·å¤´åƒã€å’Œã€Œè®¿é—®ç”¨æˆ·å,åå—和姓æ°ï¼Œæ€§åˆ«ã€ auths.tip.mastodon=输入您想è¦è®¤è¯çš„ mastodon 实例的自定义 URL (或使用默认值) auths.edit=ä¿®æ”¹è®¤è¯æº auths.activated=è¯¥è®¤è¯æºå·²ç»å¯ç”¨ -auths.new_success=å·²æ·»åŠ èº«ä»½éªŒè¯ '%s'。 +auths.new_success=å·²æ·»åŠ èº«ä»½éªŒè¯ã€Œ%sã€ã€‚ auths.update_success=è®¤è¯æºå·²ç»æ›´æ–°ã€‚ auths.update=æ›´æ–°è®¤è¯æº auths.delete=åˆ é™¤è®¤è¯æº @@ -3261,10 +3261,10 @@ auths.delete_auth_title=åˆ é™¤èº«ä»½éªŒè¯æº auths.delete_auth_desc=åˆ é™¤ä¸€ä¸ªè®¤è¯æºå°†é˜»æ¢ä½¿ç”¨å®ƒè¿›è¡Œç™»å½•。确认? auths.still_in_used=è®¤è¯æºä»åœ¨ä½¿ç”¨ã€‚è¯·å…ˆè§£é™¤æˆ–è€…åˆ é™¤ä½¿ç”¨æ¤è®¤è¯æºçš„用户。 auths.deletion_success=è®¤è¯æºå·²ç»æ›´æ–°ã€‚ -auths.login_source_exist=è®¤è¯æº '%s' å·²ç»å˜åœ¨ã€‚ +auths.login_source_exist=è®¤è¯æºã€Œ%sã€å·²ç»å˜åœ¨ã€‚ auths.login_source_of_type_exist=æ¤ç±»åž‹çš„è®¤è¯æºå·²å˜åœ¨ã€‚ -auths.unable_to_initialize_openid=æ— æ³•åˆå§‹åŒ– OpenID Connect æä¾›å•†ï¼š %s -auths.invalid_openIdConnectAutoDiscoveryURL=æ— æ•ˆçš„ Auto Discovery URL (这必须是一个以 http:// 或 https://开头的有效的 URL) +auths.unable_to_initialize_openid=æ— æ³•åˆå§‹åŒ– OpenID Connect æä¾›å•†ï¼š%s +auths.invalid_openIdConnectAutoDiscoveryURL=æ— æ•ˆçš„è‡ªåŠ¨å‘现 URL(这必须是一个以 http:// 或 https:// 开头的有效的 URL) config.server_config=æœåС噍é…ç½® config.app_name=站点åç§° @@ -3310,11 +3310,11 @@ config.db_ssl_mode=SSL config.db_path=æ•°æ®åº“路径 config.service_config=æœåŠ¡é…ç½® -config.register_email_confirm=需è¦ç”µå邮件确认注册 +config.register_email_confirm=需è¦é‚®ä»¶ç¡®è®¤æ³¨å†Œ config.disable_register=ç¦æ¢ç”¨æˆ·æ³¨å†Œ -config.allow_only_internal_registration=åªå…许通过 Gitea 进行注册 +config.allow_only_internal_registration=ä»…å…许通过 Gitea 进行注册 config.allow_only_external_registration=ä»…å…许通过外部æœåŠ¡æ³¨å†Œ -config.enable_openid_signup=å¯ç”¨ OpenID 自注册 +config.enable_openid_signup=å¯ç”¨ OpenID 自助注册 config.enable_openid_signin=å¯ç”¨ OpenID 登录 config.show_registration_button=显示注册按钮 config.require_sign_in_view=å¯ç”¨ç™»å½•访问é™åˆ¶ @@ -3322,12 +3322,12 @@ config.mail_notify=å¯ç”¨é‚®ä»¶é€šçŸ¥ config.enable_captcha=å¯ç”¨ç™»å½•验è¯ç config.active_code_lives=激活用户链接有效期 config.reset_password_code_lives=æ¢å¤è´¦æˆ·éªŒè¯ç 过期时间 -config.default_keep_email_private=默认情况下éšè—电åé‚®ä»¶åœ°å€ +config.default_keep_email_private=默认éšè—é‚®ç®±åœ°å€ config.default_allow_create_organization=默认情况下å…许创建组织 config.enable_timetracking=å¯ç”¨æ—¶é—´è·Ÿè¸ª config.default_enable_timetracking=默认情况下å¯ç”¨æ—¶é—´è·Ÿè¸ª config.default_allow_only_contributors_to_track_time=ä»…å…许æˆå‘˜è·Ÿè¸ªæ—¶é—´ -config.no_reply_address=éšè—电å邮件域 +config.no_reply_address=éšè—邮件域 config.default_visibility_organization=新组织的默认å¯è§æ€§ config.default_enable_dependencies=默认情况下å¯ç”¨å·¥å•ä¾èµ– @@ -3338,7 +3338,7 @@ config.skip_tls_verify=跳过 TLS éªŒè¯ config.mailer_config=Mailer é…ç½® config.mailer_enabled=å¯ç”¨æœåŠ¡ -config.mailer_enable_helo=å¯ç”¨HELO +config.mailer_enable_helo=å¯ç”¨ HELO config.mailer_name=任务åç§° config.mailer_protocol=åè®® config.mailer_smtp_addr=SMTP åœ°å€ @@ -3352,8 +3352,8 @@ config.mailer_use_dummy=Dummy config.test_email_placeholder=电åé‚®å€ (例如,test@example.com) config.send_test_mail=å‘逿µ‹è¯•邮件 config.send_test_mail_submit=å‘é€ -config.test_mail_failed=å‘逿µ‹è¯•邮件至 '%s' 时失败:%v -config.test_mail_sent=测试邮件已ç»å‘é€è‡³ '%s'。 +config.test_mail_failed=å‘逿µ‹è¯•邮件至「%sã€å¤±è´¥ï¼š%v +config.test_mail_sent=测试邮件已ç»å‘é€è‡³ã€Œ%sã€ã€‚ config.oauth_config=OAuth é…ç½® config.oauth_enabled=å¯ç”¨ @@ -3365,7 +3365,7 @@ config.cache_conn=Cache 连接å—符串 config.cache_item_ttl=缓å˜é¡¹ç›® TTL config.cache_test=æµ‹è¯•ç¼“å˜ config.cache_test_failed=ç¼“å˜æµ‹è¯•失败: %v。 -config.cache_test_slow=ç¼“å˜æµ‹è¯•æˆåŠŸï¼Œä½†å“应缓慢: %s。 +config.cache_test_slow=ç¼“å˜æµ‹è¯•æˆåŠŸï¼Œä½†å“应缓慢:%s。 config.cache_test_succeeded=ç¼“å˜æµ‹è¯•æˆåŠŸï¼Œåœ¨ %s 时间内得到å“应。 config.session_config=Session é…ç½® @@ -3406,7 +3406,7 @@ config.set_setting_failed=设置 %s 失败 monitor.stats=统计 -monitor.cron=Cron 任务 +monitor.cron=计划任务 monitor.name=任务åç§° monitor.schedule=任务安排 monitor.next=下次执行时间 @@ -3427,7 +3427,7 @@ monitor.process.cancel_desc=䏿¢ä¸€ä¸ªè¿›ç¨‹å¯èƒ½å¯¼è‡´æ•°æ®ä¸¢å¤± monitor.process.children=å进程 monitor.queues=队列 -monitor.queue=队列: %s +monitor.queue=队列:%s monitor.queue.name=åç§° monitor.queue.type=类型 monitor.queue.exemplar=æ•°æ®ç±»åž‹ @@ -3444,7 +3444,7 @@ monitor.queue.settings.maxnumberworkers.error=æœ€å¤§å·¥ä½œè€…æ•°å¿…é¡»æ˜¯æ•°å— monitor.queue.settings.submit=更新设置 monitor.queue.settings.changed=设置已更新 monitor.queue.settings.remove_all_items=移除全部 -monitor.queue.settings.remove_all_items_done=队列ä¸çš„æ‰€æœ‰é¡¹ç›®å·²è¢«ç§»é™¤ã€‚ +monitor.queue.settings.remove_all_items_done=队列ä¸çš„æ‰€æœ‰é¡¹ç›®å·²ç§»é™¤ã€‚ notices.system_notice_list=系统æç¤ºç®¡ç† notices.view_detail_header=查看æç¤ºè¯¦æƒ… @@ -3459,16 +3459,16 @@ notices.type_1=仓库 notices.type_2=任务 notices.desc=æç¤ºæè¿° notices.op=æ“作 -notices.delete_success=ç³»ç»Ÿé€šçŸ¥å·²è¢«åˆ é™¤ã€‚ +notices.delete_success=ç³»ç»Ÿé€šçŸ¥å·²åˆ é™¤ã€‚ self_check.no_problem_found=尚未å‘现问题。 self_check.startup_warnings=å¯åЍè¦å‘Šï¼š self_check.database_collation_mismatch=期望数æ®åº“ä½¿ç”¨çš„æ ¡éªŒæ–¹å¼ï¼š%s -self_check.database_collation_case_insensitive=æ•°æ®åº“æ£åœ¨ä½¿ç”¨ä¸€ä¸ªæ ¡éªŒ %s, è¿™æ˜¯ä¸€ä¸ªä¸æ•æ„Ÿçš„æ ¡éªŒ. 虽然Giteaå¯ä»¥ä¸Žå®ƒåˆä½œï¼Œä½†å¯èƒ½æœ‰ä¸€äº›ç½•è§çš„æƒ…况ä¸å¦‚é¢„æœŸçš„é‚£æ ·èµ·ä½œç”¨ã€‚ -self_check.database_inconsistent_collation_columns=æ•°æ®åº“æ£åœ¨ä½¿ç”¨%s的排åºè§„则,但是这些列使用了ä¸åŒ¹é…的排åºè§„则。这å¯èƒ½ä¼šé€ æˆä¸€äº›æ„外问题。 -self_check.database_fix_mysql=对于MySQL/MariaDB用户,您å¯ä»¥ä½¿ç”¨â€œgitea doctor convertâ€å‘½ä»¤æ¥è§£å†³æ ¡éªŒé—®é¢˜ã€‚ 或者您也å¯ä»¥é€šè¿‡ "ALTER ... COLLATE ..." è¿™æ ·çš„SQL æ¥æ‰‹åŠ¨è§£å†³è¿™ä¸ªé—®é¢˜ã€‚ -self_check.database_fix_mssql=对于MSSQL用户,您现在åªèƒ½é€šè¿‡"ALTER ... COLLATE ..."SQLs手动解决这个问题。 -self_check.location_origin_mismatch=å½“å‰ URL (%[1]s) 与 Gitea çš„ URL (%[2]s) ä¸åŒ¹é… 。 如果您æ£åœ¨ä½¿ç”¨åå‘代ç†ï¼Œè¯·ç¡®ä¿è®¾ç½®æ£ç¡®çš„“主机â€å’Œâ€œX-转å‘-åŽŸå§‹â€æ ‡é¢˜ã€‚ +self_check.database_collation_case_insensitive=æ•°æ®åº“æ£åœ¨ä½¿ç”¨ä¸€ä¸ªæ ¡éªŒ %sï¼Œè¿™æ˜¯ä¸€ä¸ªä¸æ•æ„Ÿçš„æ ¡éªŒã€‚è™½ç„¶ Gitea å¯ä»¥ä¸Žå®ƒåˆä½œï¼Œä½†å¯èƒ½æœ‰ä¸€äº›ç½•è§çš„æƒ…况ä¸å¦‚é¢„æœŸçš„é‚£æ ·èµ·ä½œç”¨ã€‚ +self_check.database_inconsistent_collation_columns=æ•°æ®åº“æ£åœ¨ä½¿ç”¨ %s 的排åºè§„则,但是这些列使用了ä¸åŒ¹é…的排åºè§„则。这å¯èƒ½ä¼šé€ æˆä¸€äº›æ„外问题。 +self_check.database_fix_mysql=对于 MySQL/MariaDB 用户,您å¯ä»¥ä½¿ç”¨ã€Œgitea doctor convertã€å‘½ä»¤æ¥è§£å†³æ ¡éªŒé—®é¢˜ã€‚ 或者您也å¯ä»¥é€šè¿‡ã€ŒALTER ... COLLATE ...ã€è¿™æ ·çš„ SQL æ¥æ‰‹åŠ¨è§£å†³è¿™ä¸ªé—®é¢˜ã€‚ +self_check.database_fix_mssql=对于 MSSQL 用户,您现在åªèƒ½é€šè¿‡ã€ŒALTER ... COLLATE ...ã€SQL 手动解决这个问题。 +self_check.location_origin_mismatch=å½“å‰ URL(%[1]s)与 Gitea çš„ URL(%[2]s)ä¸åŒ¹é… 。 如果您æ£åœ¨ä½¿ç”¨åå‘代ç†ï¼Œè¯·ç¡®ä¿è®¾ç½®æ£ç¡®çš„「Hostã€å’Œã€ŒX-Forwarded-Protoã€æ ‡å¤´ã€‚ [action] create_repo=创建了仓库 <a href="%s">%s</a> @@ -3547,7 +3547,7 @@ no_subscriptions=æ— è®¢é˜… default_key=使用默认密钥ç¾å error.extract_sign=æ— æ³•æå–ç¾å error.generate_hash=æ— æ³•ç”Ÿæˆæäº¤çš„å“ˆå¸Œ -error.no_committer_account=æ²¡æœ‰å¸æˆ·é“¾æŽ¥åˆ°æäº¤è€…的电å邮件 +error.no_committer_account=æ²¡æœ‰å¸æˆ·é“¾æŽ¥åˆ°æäº¤è€…的邮箱 error.no_gpg_keys_found=找ä¸åˆ°æ¤ç¾å对应的密钥 error.not_signed_commit=未ç¾åçš„æäº¤ error.failed_retrieval_gpg_keys=找ä¸åˆ°ä»»ä½•与该æäº¤è€…è´¦å·ç›¸å…³çš„密钥 @@ -3673,11 +3673,11 @@ rubygems.dependencies.development=å¼€å‘ä¾èµ– rubygems.required.ruby=éœ€è¦ Ruby 版本 rubygems.required.rubygems=éœ€è¦ RubyGem 版本 swift.registry=ä»Žå‘½ä»¤è¡Œè®¾ç½®æ¤æ³¨å†Œä¸å¿ƒï¼š -swift.install=åœ¨ä½ çš„ <code>Package.swift</code>æ–‡ä»¶ä¸æ·»åŠ è¯¥åŒ…ï¼š +swift.install=在您的 <code>Package.swift</code>æ–‡ä»¶ä¸æ·»åŠ è¯¥åŒ…ï¼š swift.install2=å¹¶è¿è¡Œä»¥ä¸‹å‘½ä»¤ï¼š vagrant.install=è‹¥è¦æ·»åŠ ä¸€ä¸ª Vagrant box,请è¿è¡Œä»¥ä¸‹å‘½ä»¤ï¼š settings.link=å°†æ¤è½¯ä»¶åŒ…链接到仓库 -settings.link.description=如果您将一个软件包与一个代ç 库链接起æ¥ï¼Œè½¯ä»¶åŒ…将显示在代ç 库的软件包列表ä¸ã€‚ +settings.link.description=如果您将一个软件包与一个仓库链接起æ¥ï¼Œè½¯ä»¶åŒ…将显示在仓库的软件包列表ä¸ã€‚ settings.link.select=选择仓库 settings.link.button=更新仓库链接 settings.link.success=仓库链接已æˆåŠŸæ›´æ–°ã€‚ @@ -3685,13 +3685,13 @@ settings.link.error=更新仓库链接失败。 settings.delete=åˆ é™¤è½¯ä»¶åŒ… settings.delete.description=åˆ é™¤è½¯ä»¶åŒ…æ˜¯æ°¸ä¹…æ€§çš„ï¼Œæ— æ³•æ’¤æ¶ˆã€‚ settings.delete.notice=您将è¦åˆ 除 %s (%s)ã€‚æ¤æ“作是ä¸å¯é€†çš„,您确定å—? -settings.delete.success=è½¯ä»¶åŒ…å·²è¢«åˆ é™¤ã€‚ +settings.delete.success=è½¯ä»¶åŒ…å·²åˆ é™¤ã€‚ settings.delete.error=åˆ é™¤è½¯ä»¶åŒ…å¤±è´¥ã€‚ owner.settings.cargo.title=Cargo 注册ä¸å¿ƒç´¢å¼• owner.settings.cargo.initialize=åˆå§‹åŒ–索引 -owner.settings.cargo.initialize.description=使用 Cargo 注册ä¸å¿ƒæ—¶éœ€è¦ä¸€ä¸ªç‰¹æ®Šç´¢å¼•çš„ Git 仓库。使用æ¤é€‰é¡¹å°†ï¼ˆé‡æ–°ï¼‰åˆ›å»ºå˜å‚¨åº“并自动é…置它。 -owner.settings.cargo.initialize.error=åˆå§‹åŒ–Cargo索引失败: %v -owner.settings.cargo.initialize.success=Cargoç´¢å¼•å·²ç»æˆåŠŸåˆ›å»ºã€‚ +owner.settings.cargo.initialize.description=使用 Cargo 注册ä¸å¿ƒæ—¶éœ€è¦ä¸€ä¸ªç‰¹æ®Šç´¢å¼•çš„ Git 仓库。使用æ¤é€‰é¡¹å°†ï¼ˆé‡æ–°ï¼‰åˆ›å»ºä»“库并自动é…置它。 +owner.settings.cargo.initialize.error=åˆå§‹åŒ– Cargo 索引失败: %v +owner.settings.cargo.initialize.success=Cargo ç´¢å¼•å·²ç»æˆåŠŸåˆ›å»ºã€‚ owner.settings.cargo.rebuild=é‡å»ºç´¢å¼• owner.settings.cargo.rebuild.description=如果索引与å˜å‚¨çš„ Cargo 包ä¸åŒæ¥ï¼Œé‡å»ºå¯èƒ½ä¼šæœ‰ç”¨ã€‚ owner.settings.cargo.rebuild.error=æ— æ³•é‡å»º Cargo 索引: %v @@ -3722,30 +3722,30 @@ owner.settings.chef.keypair.description=需è¦å¯†é’¥å¯¹æ‰èƒ½å‘ Chef 注册ä¸å [secrets] secrets=密钥 -description=Secrets å°†è¢«ä¼ ç»™ç‰¹å®šçš„ Actions,其它情况将ä¸èƒ½è¯»å– +description=å¯†é’¥å°†è¢«ä¼ ç»™ç‰¹å®šçš„å·¥ä½œæµï¼Œå…¶å®ƒæƒ…å†µæ— æ³•è¯»å–。 none=还没有密钥。 ; These keys are also for "edit secret", the keys are kept as-is to avoid unnecessary re-translation creation.description=组织æè¿° -creation.name_placeholder=ä¸åŒºåˆ†å¤§å°å†™ï¼Œå—æ¯æ•°å—或下划线ä¸èƒ½ä»¥GITEA_ 或 GITHUB_ 开头。 -creation.value_placeholder=输入任何内容,开头和结尾的空白都会被çœç•¥ -creation.description_placeholder=è¾“å…¥ç®€çŸæè¿°(å¯é€‰)。 +creation.name_placeholder=ä¸åŒºåˆ†å¤§å°å†™ï¼Œä»…é™å—æ¯æ•°å—或下划线且ä¸èƒ½ä»¥ GITEA_ 或 GITHUB_ 开头 +creation.value_placeholder=输入任何内容,开头和结尾的空白将会被忽略。 +creation.description_placeholder=è¾“å…¥ç®€çŸæè¿°ï¼ˆå¯é€‰ï¼‰ã€‚ -save_success=密钥 '%s' ä¿å˜æˆåŠŸã€‚ +save_success=密钥「%sã€ä¿å˜æˆåŠŸã€‚ save_failed=密钥ä¿å˜å¤±è´¥ã€‚ add_secret=æ·»åŠ å¯†é’¥ edit_secret=编辑密钥 deletion=åˆ é™¤å¯†é’¥ -deletion.description=åˆ é™¤å¯†é’¥æ˜¯æ°¸ä¹…æ€§çš„ï¼Œæ— æ³•æ’¤æ¶ˆã€‚ç»§ç»å—? -deletion.success=æ¤Secretå·²è¢«åˆ é™¤ã€‚ +deletion.description=åˆ é™¤å¯†é’¥æ˜¯æ°¸ä¹…æ€§çš„ä¸”æ— æ³•æ’¤æ¶ˆã€‚ç»§ç»ï¼Ÿ +deletion.success=æ¤å¯†é’¥å·²åˆ 除。 deletion.failed=åˆ é™¤å¯†é’¥å¤±è´¥ã€‚ management=å¯†é’¥ç®¡ç† [actions] -actions=Actions +actions=å·¥ä½œæµ -unit.desc=管ç†Actions +unit.desc=管ç†å·¥ä½œæµ status.unknown=未知 status.waiting=ç‰å¾…ä¸ @@ -3756,9 +3756,9 @@ status.cancelled=已喿¶ˆ status.skipped=已忽略 status.blocked=é˜»å¡žä¸ -runners=Runners -runners.runner_manage_panel=Runnersç®¡ç† -runners.new=创建 Runner +runners=è¿è¡Œå™¨ +runners.runner_manage_panel=è¿è¡Œå™¨ç®¡ç† +runners.new=创建新è¿è¡Œå™¨ runners.new_notice=如何å¯åŠ¨ä¸€ä¸ªè¿è¡Œå™¨ runners.status=çŠ¶æ€ runners.id=ID @@ -3767,9 +3767,9 @@ runners.owner_type=类型 runners.description=æè¿° runners.labels=æ ‡ç¾ runners.last_online=上次在线时间 -runners.runner_title=Runner -runners.task_list=最近在æ¤runner上的任务 -runners.task_list.no_tasks=还没有任务。 +runners.runner_title=è¿è¡Œå™¨ +runners.task_list=最近在æ¤è¿è¡Œå™¨ä¸Šçš„任务 +runners.task_list.no_tasks=ç›®å‰è¿˜æ²¡æœ‰ä»»åŠ¡ã€‚ runners.task_list.run=执行 runners.task_list.status=çŠ¶æ€ runners.task_list.repository=仓库 @@ -3778,13 +3778,13 @@ runners.task_list.done_at=完æˆäºŽ runners.edit_runner=编辑è¿è¡Œå™¨ runners.update_runner=更新更改 runners.update_runner_success=è¿è¡Œå™¨æ›´æ–°æˆåŠŸ -runners.update_runner_failed=æ›´æ–°è¿è¡Œå™¨å¤±è´¥ -runners.delete_runner=åˆ é™¤è¿è¡Œå™¨ +runners.update_runner_failed=è¿è¡Œå™¨æ›´æ–°å¤±è´¥ +runners.delete_runner=åˆ é™¤æ¤è¿è¡Œå™¨ runners.delete_runner_success=è¿è¡Œå™¨åˆ 除æˆåŠŸ -runners.delete_runner_failed=åˆ é™¤è¿è¡Œå™¨å¤±è´¥ +runners.delete_runner_failed=è¿è¡Œå™¨åˆ 除失败 runners.delete_runner_header=确认è¦åˆ 除æ¤è¿è¡Œå™¨ runners.delete_runner_notice=如果一个任务æ£åœ¨è¿è¡Œåœ¨æ¤è¿è¡Œå™¨ä¸Šï¼Œå®ƒå°†è¢«ç»ˆæ¢å¹¶æ ‡è®°ä¸ºå¤±è´¥ã€‚它å¯èƒ½ä¼šæ‰“æ–æ£åœ¨æž„建的工作æµã€‚ -runners.none=æ— å¯ç”¨çš„ Runner +runners.none=æ— å¯ç”¨è¿è¡Œå™¨ runners.status.unspecified=未知 runners.status.idle=空闲 runners.status.active=å¯ç”¨ @@ -3798,8 +3798,8 @@ runs.all_workflows=æ‰€æœ‰å·¥ä½œæµ runs.commit=æäº¤ runs.scheduled=已计划的 runs.pushed_by=推é€è€… -runs.invalid_workflow_helper=工作æµé…ç½®æ–‡ä»¶æ— æ•ˆã€‚è¯·æ£€æŸ¥æ‚¨çš„é…置文件: %s -runs.no_matching_online_runner_helper=æ²¡æœ‰åŒ¹é…æ ‡ç¾çš„在线 runner: %s +runs.invalid_workflow_helper=工作æµé…ç½®æ–‡ä»¶æ— æ•ˆã€‚è¯·æ£€æŸ¥æ‚¨çš„é…置文件:%s +runs.no_matching_online_runner_helper=æ²¡æœ‰åŒ¹é… %s æ ‡ç¾çš„在线è¿è¡Œå™¨ runs.no_job_without_needs=工作æµå¿…须包å«è‡³å°‘一个没有ä¾èµ–关系的作业。 runs.no_job=工作æµå¿…须包å«è‡³å°‘一个作业 runs.actor=æ“作者 @@ -3808,27 +3808,27 @@ runs.actors_no_select=所有æ“作者 runs.status_no_select=æ‰€æœ‰çŠ¶æ€ runs.no_results=没有匹é…的结果。 runs.no_workflows=ç›®å‰è¿˜æ²¡æœ‰å·¥ä½œæµã€‚ -runs.no_workflows.quick_start=ä¸çŸ¥é“如何使用 Gitea Actionså—?请查看 <a target="_blank" rel="noopener noreferrer" href="%s">快速å¯åŠ¨æŒ‡å—</a>。 -runs.no_workflows.documentation=关于Gitea Actions的更多信æ¯ï¼Œè¯·å‚阅 <a target="_blank" rel="noopener noreferrer" href="%s">文档</a>。 +runs.no_workflows.quick_start=ä¸çŸ¥é“如何使用 Gitea 工作æµå—?请查看<a target="_blank" rel="noopener noreferrer" href="%s">快速开始指å—</a>。 +runs.no_workflows.documentation=关于 Gitea 工作æµçš„æ›´å¤šä¿¡æ¯ï¼Œè¯·å‚阅<a target="_blank" rel="noopener noreferrer" href="%s">文档</a>。 runs.no_runs=工作æµå°šæœªè¿è¡Œè¿‡ã€‚ -runs.empty_commit_message=(空白的æäº¤æ¶ˆæ¯) -runs.expire_log_message=旧的日志已被清除 +runs.empty_commit_message=(空白的æäº¤æ¶ˆæ¯ï¼‰ +runs.expire_log_message=旧的日志已清除。 runs.delete=åˆ é™¤å·¥ä½œæµè¿è¡Œ runs.delete.description=æ‚¨ç¡®å®šè¦æ°¸ä¹…åˆ é™¤æ¤å·¥ä½œæµè¿è¡Œå—ï¼Ÿæ¤æ“ä½œæ— æ³•æ’¤æ¶ˆã€‚ -runs.not_done=æ¤å·¥ä½œæµè¿è¡Œæœªå®Œæˆã€‚ +runs.not_done=æ¤å·¥ä½œæµè¿è¡Œå°šæœªå®Œæˆã€‚ runs.view_workflow_file=æŸ¥çœ‹å·¥ä½œæµæ–‡ä»¶ workflow.disable=ç¦ç”¨å·¥ä½œæµ -workflow.disable_success=å·¥ä½œæµ '%s' å·²æˆåŠŸç¦ç”¨ã€‚ +workflow.disable_success=工作æµã€Œ%sã€å·²æˆåŠŸç¦ç”¨ã€‚ workflow.enable=å¯ç”¨å·¥ä½œæµ -workflow.enable_success=å·¥ä½œæµ '%s' å·²æˆåŠŸå¯ç”¨ã€‚ +workflow.enable_success=工作æµã€Œ%sã€å·²æˆåŠŸå¯ç”¨ã€‚ workflow.disabled=工作æµå·²ç¦ç”¨ã€‚ workflow.run=è¿è¡Œå·¥ä½œæµ -workflow.not_found=å·¥ä½œæµ %s 未找到。 -workflow.run_success=å·¥ä½œæµ %s å·²æˆåŠŸè¿è¡Œã€‚ +workflow.not_found=工作æµã€Œ%sã€æœªæ‰¾åˆ°ã€‚ +workflow.run_success=工作æµã€Œ%sã€å·²æˆåŠŸè¿è¡Œã€‚ workflow.from_ref=使用工作æµä»Ž -workflow.has_workflow_dispatch=æ¤ Workflow 有一个 Workflow_dispatch 事件触å‘器。 -workflow.has_no_workflow_dispatch=å·¥ä½œæµ %s 没有 workflow_dispatch 事件的触å‘器。 +workflow.has_workflow_dispatch=æ¤å·¥ä½œæµæœ‰ä¸€ä¸ª workflow_dispatch 事件触å‘器。 +workflow.has_no_workflow_dispatch=工作æµã€Œ%sã€æ²¡æœ‰ workflow_dispatch 事件触å‘器。 need_approval_desc=该工作æµç”±æ´¾ç”Ÿä»“库的åˆå¹¶è¯·æ±‚所触å‘ï¼Œéœ€è¦æ‰¹å‡†æ–¹å¯è¿è¡Œã€‚ @@ -3838,15 +3838,15 @@ variables.creation=æ·»åŠ å˜é‡ variables.none=ç›®å‰è¿˜æ²¡æœ‰å˜é‡ã€‚ variables.deletion=åˆ é™¤å˜é‡ variables.deletion.description=åˆ é™¤å˜é‡æ˜¯æ°¸ä¹…æ€§çš„ï¼Œæ— æ³•æ’¤æ¶ˆã€‚ç»§ç»å—? -variables.description=å˜é‡å°†è¢«ä¼ 给特定的 Actions,其它情况将ä¸èƒ½è¯»å– +variables.description=å˜é‡å°†è¢«ä¼ 给特定的工作æµï¼Œå…¶å®ƒæƒ…å†µä¸‹æ— æ³•è¯»å–。 variables.id_not_exist=ID为 %d çš„å˜é‡ä¸å˜åœ¨ã€‚ variables.edit=编辑å˜é‡ -variables.deletion.failed=åˆ é™¤å˜é‡å¤±è´¥ã€‚ -variables.deletion.success=å˜é‡å·²è¢«åˆ 除。 -variables.creation.failed=æ·»åŠ å˜é‡å¤±è´¥ã€‚ -variables.creation.success=å˜é‡ “%sâ€ æ·»åŠ æˆåŠŸã€‚ -variables.update.failed=编辑å˜é‡å¤±è´¥ã€‚ -variables.update.success=该å˜é‡å·²è¢«ç¼–辑。 +variables.deletion.failed=å˜é‡åˆ 除失败。 +variables.deletion.success=å˜é‡å·²åˆ 除。 +variables.creation.failed=å˜é‡æ·»åŠ å¤±è´¥ã€‚ +variables.creation.success=å˜é‡ã€Œ%sã€æ·»åŠ æˆåŠŸã€‚ +variables.update.failed=å˜é‡ç¼–辑失败。 +variables.update.success=å˜é‡å·²ç¼–辑。 logs.always_auto_scroll=总是自动滚动日志 logs.always_expand_running=总是展开è¿è¡Œæ—¥å¿— diff --git a/package-lock.json b/package-lock.json index 780b95d592..8a2f3e0db7 100644 --- a/package-lock.json +++ b/package-lock.json @@ -37,16 +37,16 @@ "license-checker-webpack-plugin": "0.2.1", "mermaid": "11.6.0", "mini-css-extract-plugin": "2.9.2", - "minimatch": "10.0.1", + "minimatch": "10.0.2", "monaco-editor": "0.52.2", "monaco-editor-webpack-plugin": "7.1.0", "pdfobject": "2.3.1", "perfect-debounce": "1.0.0", - "postcss": "8.5.4", + "postcss": "8.5.5", "postcss-loader": "8.1.1", - "postcss-nesting": "13.0.1", + "postcss-nesting": "13.0.2", "sortablejs": "1.15.6", - "swagger-ui-dist": "5.24.0", + "swagger-ui-dist": "5.24.1", "tailwindcss": "3.4.17", "throttle-debounce": "5.0.2", "tinycolor2": "1.6.0", @@ -66,7 +66,7 @@ }, "devDependencies": { "@eslint-community/eslint-plugin-eslint-comments": "4.5.0", - "@playwright/test": "1.52.0", + "@playwright/test": "1.53.0", "@stoplight/spectral-cli": "6.15.0", "@stylistic/eslint-plugin-js": "3.1.0", "@stylistic/stylelint-plugin": "3.1.2", @@ -80,25 +80,25 @@ "@types/throttle-debounce": "5.0.2", "@types/tinycolor2": "1.4.6", "@types/toastify-js": "1.12.4", - "@typescript-eslint/eslint-plugin": "8.33.1", - "@typescript-eslint/parser": "8.33.1", + "@typescript-eslint/eslint-plugin": "8.34.0", + "@typescript-eslint/parser": "8.34.0", "@vitejs/plugin-vue": "5.2.4", - "@vitest/eslint-plugin": "1.2.1", + "@vitest/eslint-plugin": "1.2.2", "eslint": "8.57.0", "eslint-import-resolver-typescript": "4.4.3", "eslint-plugin-array-func": "4.0.0", "eslint-plugin-github": "5.0.2", - "eslint-plugin-import-x": "4.15.1", + "eslint-plugin-import-x": "4.15.2", "eslint-plugin-no-jquery": "3.1.1", "eslint-plugin-no-use-extend-native": "0.5.0", "eslint-plugin-playwright": "2.2.0", - "eslint-plugin-regexp": "2.8.0", + "eslint-plugin-regexp": "2.9.0", "eslint-plugin-sonarjs": "3.0.2", "eslint-plugin-unicorn": "56.0.1", "eslint-plugin-vue": "10.2.0", "eslint-plugin-vue-scoped-css": "2.10.0", "eslint-plugin-wc": "3.0.1", - "happy-dom": "17.6.3", + "happy-dom": "18.0.1", "markdownlint-cli": "0.45.0", "material-icon-theme": "5.23.0", "nolyfill": "1.0.44", @@ -113,7 +113,7 @@ "type-fest": "4.41.0", "updates": "16.4.2", "vite-string-plugin": "1.4.4", - "vitest": "3.2.2", + "vitest": "3.2.3", "vue-tsc": "2.2.10" }, "engines": { @@ -1054,10 +1054,17 @@ "url": "https://github.com/sponsors/epoberezkin" } }, + "node_modules/@eslint/eslintrc/node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true, + "license": "MIT" + }, "node_modules/@eslint/eslintrc/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", "dev": true, "license": "MIT", "dependencies": { @@ -1177,10 +1184,17 @@ "node": ">=10.10.0" } }, + "node_modules/@humanwhocodes/config-array/node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true, + "license": "MIT" + }, "node_modules/@humanwhocodes/config-array/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", "dev": true, "license": "MIT", "dependencies": { @@ -1546,9 +1560,9 @@ } }, "node_modules/@napi-rs/wasm-runtime": { - "version": "0.2.10", - "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-0.2.10.tgz", - "integrity": "sha512-bCsCyeZEwVErsGmyPNSzwfwFn4OdxBj0mmv6hOFucB/k81Ojdu68RbZdxYsRQUPc9l6SU5F/cG+bXgWs3oUgsQ==", + "version": "0.2.11", + "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-0.2.11.tgz", + "integrity": "sha512-9DPkXtvHydrcOsopiYpUgPHpmj0HWZKMUnL2dZqpvC42lsratuBG06V5ipyno0fUek5VlFsNQ+AcFATSrJXgMA==", "dev": true, "license": "MIT", "optional": true, @@ -1624,13 +1638,13 @@ } }, "node_modules/@playwright/test": { - "version": "1.52.0", - "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.52.0.tgz", - "integrity": "sha512-uh6W7sb55hl7D6vsAeA+V2p5JnlAqzhqFyF0VcJkKZXkgnFcVG9PziERRHQfPLfNGx1C292a4JqbWzhR8L4R1g==", + "version": "1.53.0", + "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.53.0.tgz", + "integrity": "sha512-15hjKreZDcp7t6TL/7jkAo6Df5STZN09jGiv5dbP9A6vMVncXRqE7/B2SncsyOwrkZRBH2i6/TPOL8BVmm3c7w==", "dev": true, "license": "Apache-2.0", "dependencies": { - "playwright": "1.52.0" + "playwright": "1.53.0" }, "bin": { "playwright": "cli.js" @@ -1706,9 +1720,9 @@ "license": "MIT" }, "node_modules/@rollup/rollup-android-arm-eabi": { - "version": "4.42.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.42.0.tgz", - "integrity": "sha512-gldmAyS9hpj+H6LpRNlcjQWbuKUtb94lodB9uCz71Jm+7BxK1VIOo7y62tZZwxhA7j1ylv/yQz080L5WkS+LoQ==", + "version": "4.43.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.43.0.tgz", + "integrity": "sha512-Krjy9awJl6rKbruhQDgivNbD1WuLb8xAclM4IR4cN5pHGAs2oIMMQJEiC3IC/9TZJ+QZkmZhlMO/6MBGxPidpw==", "cpu": [ "arm" ], @@ -1720,9 +1734,9 @@ ] }, "node_modules/@rollup/rollup-android-arm64": { - "version": "4.42.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.42.0.tgz", - "integrity": "sha512-bpRipfTgmGFdCZDFLRvIkSNO1/3RGS74aWkJJTFJBH7h3MRV4UijkaEUeOMbi9wxtxYmtAbVcnMtHTPBhLEkaw==", + "version": "4.43.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.43.0.tgz", + "integrity": "sha512-ss4YJwRt5I63454Rpj+mXCXicakdFmKnUNxr1dLK+5rv5FJgAxnN7s31a5VchRYxCFWdmnDWKd0wbAdTr0J5EA==", "cpu": [ "arm64" ], @@ -1734,9 +1748,9 @@ ] }, "node_modules/@rollup/rollup-darwin-arm64": { - "version": "4.42.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.42.0.tgz", - "integrity": "sha512-JxHtA081izPBVCHLKnl6GEA0w3920mlJPLh89NojpU2GsBSB6ypu4erFg/Wx1qbpUbepn0jY4dVWMGZM8gplgA==", + "version": "4.43.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.43.0.tgz", + "integrity": "sha512-eKoL8ykZ7zz8MjgBenEF2OoTNFAPFz1/lyJ5UmmFSz5jW+7XbH1+MAgCVHy72aG59rbuQLcJeiMrP8qP5d/N0A==", "cpu": [ "arm64" ], @@ -1748,9 +1762,9 @@ ] }, "node_modules/@rollup/rollup-darwin-x64": { - "version": "4.42.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.42.0.tgz", - "integrity": "sha512-rv5UZaWVIJTDMyQ3dCEK+m0SAn6G7H3PRc2AZmExvbDvtaDc+qXkei0knQWcI3+c9tEs7iL/4I4pTQoPbNL2SA==", + "version": "4.43.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.43.0.tgz", + "integrity": "sha512-SYwXJgaBYW33Wi/q4ubN+ldWC4DzQY62S4Ll2dgfr/dbPoF50dlQwEaEHSKrQdSjC6oIe1WgzosoaNoHCdNuMg==", "cpu": [ "x64" ], @@ -1762,9 +1776,9 @@ ] }, "node_modules/@rollup/rollup-freebsd-arm64": { - "version": "4.42.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.42.0.tgz", - "integrity": "sha512-fJcN4uSGPWdpVmvLuMtALUFwCHgb2XiQjuECkHT3lWLZhSQ3MBQ9pq+WoWeJq2PrNxr9rPM1Qx+IjyGj8/c6zQ==", + "version": "4.43.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.43.0.tgz", + "integrity": "sha512-SV+U5sSo0yujrjzBF7/YidieK2iF6E7MdF6EbYxNz94lA+R0wKl3SiixGyG/9Klab6uNBIqsN7j4Y/Fya7wAjQ==", "cpu": [ "arm64" ], @@ -1776,9 +1790,9 @@ ] }, "node_modules/@rollup/rollup-freebsd-x64": { - "version": "4.42.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.42.0.tgz", - "integrity": "sha512-CziHfyzpp8hJpCVE/ZdTizw58gr+m7Y2Xq5VOuCSrZR++th2xWAz4Nqk52MoIIrV3JHtVBhbBsJcAxs6NammOQ==", + "version": "4.43.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.43.0.tgz", + "integrity": "sha512-J7uCsiV13L/VOeHJBo5SjasKiGxJ0g+nQTrBkAsmQBIdil3KhPnSE9GnRon4ejX1XDdsmK/l30IYLiAaQEO0Cg==", "cpu": [ "x64" ], @@ -1790,9 +1804,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm-gnueabihf": { - "version": "4.42.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.42.0.tgz", - "integrity": "sha512-UsQD5fyLWm2Fe5CDM7VPYAo+UC7+2Px4Y+N3AcPh/LdZu23YcuGPegQly++XEVaC8XUTFVPscl5y5Cl1twEI4A==", + "version": "4.43.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.43.0.tgz", + "integrity": "sha512-gTJ/JnnjCMc15uwB10TTATBEhK9meBIY+gXP4s0sHD1zHOaIh4Dmy1X9wup18IiY9tTNk5gJc4yx9ctj/fjrIw==", "cpu": [ "arm" ], @@ -1804,9 +1818,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm-musleabihf": { - "version": "4.42.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.42.0.tgz", - "integrity": "sha512-/i8NIrlgc/+4n1lnoWl1zgH7Uo0XK5xK3EDqVTf38KvyYgCU/Rm04+o1VvvzJZnVS5/cWSd07owkzcVasgfIkQ==", + "version": "4.43.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.43.0.tgz", + "integrity": "sha512-ZJ3gZynL1LDSIvRfz0qXtTNs56n5DI2Mq+WACWZ7yGHFUEirHBRt7fyIk0NsCKhmRhn7WAcjgSkSVVxKlPNFFw==", "cpu": [ "arm" ], @@ -1818,9 +1832,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-gnu": { - "version": "4.42.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.42.0.tgz", - "integrity": "sha512-eoujJFOvoIBjZEi9hJnXAbWg+Vo1Ov8n/0IKZZcPZ7JhBzxh2A+2NFyeMZIRkY9iwBvSjloKgcvnjTbGKHE44Q==", + "version": "4.43.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.43.0.tgz", + "integrity": "sha512-8FnkipasmOOSSlfucGYEu58U8cxEdhziKjPD2FIa0ONVMxvl/hmONtX/7y4vGjdUhjcTHlKlDhw3H9t98fPvyA==", "cpu": [ "arm64" ], @@ -1832,9 +1846,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-musl": { - "version": "4.42.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.42.0.tgz", - "integrity": "sha512-/3NrcOWFSR7RQUQIuZQChLND36aTU9IYE4j+TB40VU78S+RA0IiqHR30oSh6P1S9f9/wVOenHQnacs/Byb824g==", + "version": "4.43.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.43.0.tgz", + "integrity": "sha512-KPPyAdlcIZ6S9C3S2cndXDkV0Bb1OSMsX0Eelr2Bay4EsF9yi9u9uzc9RniK3mcUGCLhWY9oLr6er80P5DE6XA==", "cpu": [ "arm64" ], @@ -1846,9 +1860,9 @@ ] }, "node_modules/@rollup/rollup-linux-loongarch64-gnu": { - "version": "4.42.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.42.0.tgz", - "integrity": "sha512-O8AplvIeavK5ABmZlKBq9/STdZlnQo7Sle0LLhVA7QT+CiGpNVe197/t8Aph9bhJqbDVGCHpY2i7QyfEDDStDg==", + "version": "4.43.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.43.0.tgz", + "integrity": "sha512-HPGDIH0/ZzAZjvtlXj6g+KDQ9ZMHfSP553za7o2Odegb/BEfwJcR0Sw0RLNpQ9nC6Gy8s+3mSS9xjZ0n3rhcYg==", "cpu": [ "loong64" ], @@ -1860,9 +1874,9 @@ ] }, "node_modules/@rollup/rollup-linux-powerpc64le-gnu": { - "version": "4.42.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.42.0.tgz", - "integrity": "sha512-6Qb66tbKVN7VyQrekhEzbHRxXXFFD8QKiFAwX5v9Xt6FiJ3BnCVBuyBxa2fkFGqxOCSGGYNejxd8ht+q5SnmtA==", + "version": "4.43.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.43.0.tgz", + "integrity": "sha512-gEmwbOws4U4GLAJDhhtSPWPXUzDfMRedT3hFMyRAvM9Mrnj+dJIFIeL7otsv2WF3D7GrV0GIewW0y28dOYWkmw==", "cpu": [ "ppc64" ], @@ -1874,9 +1888,9 @@ ] }, "node_modules/@rollup/rollup-linux-riscv64-gnu": { - "version": "4.42.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.42.0.tgz", - "integrity": "sha512-KQETDSEBamQFvg/d8jajtRwLNBlGc3aKpaGiP/LvEbnmVUKlFta1vqJqTrvPtsYsfbE/DLg5CC9zyXRX3fnBiA==", + "version": "4.43.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.43.0.tgz", + "integrity": "sha512-XXKvo2e+wFtXZF/9xoWohHg+MuRnvO29TI5Hqe9xwN5uN8NKUYy7tXUG3EZAlfchufNCTHNGjEx7uN78KsBo0g==", "cpu": [ "riscv64" ], @@ -1888,9 +1902,9 @@ ] }, "node_modules/@rollup/rollup-linux-riscv64-musl": { - "version": "4.42.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.42.0.tgz", - "integrity": "sha512-qMvnyjcU37sCo/tuC+JqeDKSuukGAd+pVlRl/oyDbkvPJ3awk6G6ua7tyum02O3lI+fio+eM5wsVd66X0jQtxw==", + "version": "4.43.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.43.0.tgz", + "integrity": "sha512-ruf3hPWhjw6uDFsOAzmbNIvlXFXlBQ4nk57Sec8E8rUxs/AI4HD6xmiiasOOx/3QxS2f5eQMKTAwk7KHwpzr/Q==", "cpu": [ "riscv64" ], @@ -1902,9 +1916,9 @@ ] }, "node_modules/@rollup/rollup-linux-s390x-gnu": { - "version": "4.42.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.42.0.tgz", - "integrity": "sha512-I2Y1ZUgTgU2RLddUHXTIgyrdOwljjkmcZ/VilvaEumtS3Fkuhbw4p4hgHc39Ypwvo2o7sBFNl2MquNvGCa55Iw==", + "version": "4.43.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.43.0.tgz", + "integrity": "sha512-QmNIAqDiEMEvFV15rsSnjoSmO0+eJLoKRD9EAa9rrYNwO/XRCtOGM3A5A0X+wmG+XRrw9Fxdsw+LnyYiZWWcVw==", "cpu": [ "s390x" ], @@ -1916,9 +1930,9 @@ ] }, "node_modules/@rollup/rollup-linux-x64-gnu": { - "version": "4.42.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.42.0.tgz", - "integrity": "sha512-Gfm6cV6mj3hCUY8TqWa63DB8Mx3NADoFwiJrMpoZ1uESbK8FQV3LXkhfry+8bOniq9pqY1OdsjFWNsSbfjPugw==", + "version": "4.43.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.43.0.tgz", + "integrity": "sha512-jAHr/S0iiBtFyzjhOkAics/2SrXE092qyqEg96e90L3t9Op8OTzS6+IX0Fy5wCt2+KqeHAkti+eitV0wvblEoQ==", "cpu": [ "x64" ], @@ -1930,9 +1944,9 @@ ] }, "node_modules/@rollup/rollup-linux-x64-musl": { - "version": "4.42.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.42.0.tgz", - "integrity": "sha512-g86PF8YZ9GRqkdi0VoGlcDUb4rYtQKyTD1IVtxxN4Hpe7YqLBShA7oHMKU6oKTCi3uxwW4VkIGnOaH/El8de3w==", + "version": "4.43.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.43.0.tgz", + "integrity": "sha512-3yATWgdeXyuHtBhrLt98w+5fKurdqvs8B53LaoKD7P7H7FKOONLsBVMNl9ghPQZQuYcceV5CDyPfyfGpMWD9mQ==", "cpu": [ "x64" ], @@ -1944,9 +1958,9 @@ ] }, "node_modules/@rollup/rollup-win32-arm64-msvc": { - "version": "4.42.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.42.0.tgz", - "integrity": "sha512-+axkdyDGSp6hjyzQ5m1pgcvQScfHnMCcsXkx8pTgy/6qBmWVhtRVlgxjWwDp67wEXXUr0x+vD6tp5W4x6V7u1A==", + "version": "4.43.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.43.0.tgz", + "integrity": "sha512-wVzXp2qDSCOpcBCT5WRWLmpJRIzv23valvcTwMHEobkjippNf+C3ys/+wf07poPkeNix0paTNemB2XrHr2TnGw==", "cpu": [ "arm64" ], @@ -1958,9 +1972,9 @@ ] }, "node_modules/@rollup/rollup-win32-ia32-msvc": { - "version": "4.42.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.42.0.tgz", - "integrity": "sha512-F+5J9pelstXKwRSDq92J0TEBXn2nfUrQGg+HK1+Tk7VOL09e0gBqUHugZv7SW4MGrYj41oNCUe3IKCDGVlis2g==", + "version": "4.43.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.43.0.tgz", + "integrity": "sha512-fYCTEyzf8d+7diCw8b+asvWDCLMjsCEA8alvtAutqJOJp/wL5hs1rWSqJ1vkjgW0L2NB4bsYJrpKkiIPRR9dvw==", "cpu": [ "ia32" ], @@ -1972,9 +1986,9 @@ ] }, "node_modules/@rollup/rollup-win32-x64-msvc": { - "version": "4.42.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.42.0.tgz", - "integrity": "sha512-LpHiJRwkaVz/LqjHjK8LCi8osq7elmpwujwbXKNW88bM8eeGxavJIKKjkjpMHAh/2xfnrt1ZSnhTv41WYUHYmA==", + "version": "4.43.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.43.0.tgz", + "integrity": "sha512-SnGhLiE5rlK0ofq8kzuDkM0g7FN1s5VYY+YSMTibP7CqShxCQvqtNxTARS4xX4PFJfHjG0ZQYX9iGzI3FQh5Aw==", "cpu": [ "x64" ], @@ -2221,10 +2235,17 @@ "node": "^12.20 || >=14.13" } }, + "node_modules/@stoplight/spectral-core/node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true, + "license": "MIT" + }, "node_modules/@stoplight/spectral-core/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", "dev": true, "license": "MIT", "dependencies": { @@ -3005,12 +3026,12 @@ "license": "MIT" }, "node_modules/@types/node": { - "version": "22.15.30", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.15.30.tgz", - "integrity": "sha512-6Q7lr06bEHdlfplU6YRbgG1SFBdlsfNC4/lX+SkhiTs0cpJkOElmWls8PxDFv4yY/xKb8Y6SO0OmSX4wgqTZbA==", + "version": "24.0.1", + "resolved": "https://registry.npmjs.org/@types/node/-/node-24.0.1.tgz", + "integrity": "sha512-MX4Zioh39chHlDJbKmEgydJDS3tspMP/lnQC67G3SWsTnb9NeYVWOjkxpOSy4oMfPs4StcWHwBrvUb4ybfnuaw==", "license": "MIT", "dependencies": { - "undici-types": "~6.21.0" + "undici-types": "~7.8.0" } }, "node_modules/@types/normalize-package-data": { @@ -3167,18 +3188,25 @@ "node": ">= 8" } }, + "node_modules/@types/whatwg-mimetype": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@types/whatwg-mimetype/-/whatwg-mimetype-3.0.2.tgz", + "integrity": "sha512-c2AKvDT8ToxLIOUlN51gTiHXflsfIFisS4pO7pDPoKouJCESkhZnEy623gwP9laCy5lnLDAw1vAzu2vM2YLOrA==", + "dev": true, + "license": "MIT" + }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "8.33.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.33.1.tgz", - "integrity": "sha512-TDCXj+YxLgtvxvFlAvpoRv9MAncDLBV2oT9Bd7YBGC/b/sEURoOYuIwLI99rjWOfY3QtDzO+mk0n4AmdFExW8A==", + "version": "8.34.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.34.0.tgz", + "integrity": "sha512-QXwAlHlbcAwNlEEMKQS2RCgJsgXrTJdjXT08xEgbPFa2yYQgVjBymxP5DrfrE7X7iodSzd9qBUHUycdyVJTW1w==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/regexpp": "^4.10.0", - "@typescript-eslint/scope-manager": "8.33.1", - "@typescript-eslint/type-utils": "8.33.1", - "@typescript-eslint/utils": "8.33.1", - "@typescript-eslint/visitor-keys": "8.33.1", + "@typescript-eslint/scope-manager": "8.34.0", + "@typescript-eslint/type-utils": "8.34.0", + "@typescript-eslint/utils": "8.34.0", + "@typescript-eslint/visitor-keys": "8.34.0", "graphemer": "^1.4.0", "ignore": "^7.0.0", "natural-compare": "^1.4.0", @@ -3192,7 +3220,7 @@ "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "@typescript-eslint/parser": "^8.33.1", + "@typescript-eslint/parser": "^8.34.0", "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <5.9.0" } @@ -3208,16 +3236,16 @@ } }, "node_modules/@typescript-eslint/parser": { - "version": "8.33.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.33.1.tgz", - "integrity": "sha512-qwxv6dq682yVvgKKp2qWwLgRbscDAYktPptK4JPojCwwi3R9cwrvIxS4lvBpzmcqzR4bdn54Z0IG1uHFskW4dA==", + "version": "8.34.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.34.0.tgz", + "integrity": "sha512-vxXJV1hVFx3IXz/oy2sICsJukaBrtDEQSBiV48/YIV5KWjX1dO+bcIr/kCPrW6weKXvsaGKFNlwH0v2eYdRRbA==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/scope-manager": "8.33.1", - "@typescript-eslint/types": "8.33.1", - "@typescript-eslint/typescript-estree": "8.33.1", - "@typescript-eslint/visitor-keys": "8.33.1", + "@typescript-eslint/scope-manager": "8.34.0", + "@typescript-eslint/types": "8.34.0", + "@typescript-eslint/typescript-estree": "8.34.0", + "@typescript-eslint/visitor-keys": "8.34.0", "debug": "^4.3.4" }, "engines": { @@ -3233,14 +3261,14 @@ } }, "node_modules/@typescript-eslint/project-service": { - "version": "8.33.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.33.1.tgz", - "integrity": "sha512-DZR0efeNklDIHHGRpMpR5gJITQpu6tLr9lDJnKdONTC7vvzOlLAG/wcfxcdxEWrbiZApcoBCzXqU/Z458Za5Iw==", + "version": "8.34.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.34.0.tgz", + "integrity": "sha512-iEgDALRf970/B2YExmtPMPF54NenZUf4xpL3wsCRx/lgjz6ul/l13R81ozP/ZNuXfnLCS+oPmG7JIxfdNYKELw==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/tsconfig-utils": "^8.33.1", - "@typescript-eslint/types": "^8.33.1", + "@typescript-eslint/tsconfig-utils": "^8.34.0", + "@typescript-eslint/types": "^8.34.0", "debug": "^4.3.4" }, "engines": { @@ -3255,14 +3283,14 @@ } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "8.33.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.33.1.tgz", - "integrity": "sha512-dM4UBtgmzHR9bS0Rv09JST0RcHYearoEoo3pG5B6GoTR9XcyeqX87FEhPo+5kTvVfKCvfHaHrcgeJQc6mrDKrA==", + "version": "8.34.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.34.0.tgz", + "integrity": "sha512-9Ac0X8WiLykl0aj1oYQNcLZjHgBojT6cW68yAgZ19letYu+Hxd0rE0veI1XznSSst1X5lwnxhPbVdwjDRIomRw==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.33.1", - "@typescript-eslint/visitor-keys": "8.33.1" + "@typescript-eslint/types": "8.34.0", + "@typescript-eslint/visitor-keys": "8.34.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -3273,9 +3301,9 @@ } }, "node_modules/@typescript-eslint/tsconfig-utils": { - "version": "8.33.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.33.1.tgz", - "integrity": "sha512-STAQsGYbHCF0/e+ShUQ4EatXQ7ceh3fBCXkNU7/MZVKulrlq1usH7t2FhxvCpuCi5O5oi1vmVaAjrGeL71OK1g==", + "version": "8.34.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.34.0.tgz", + "integrity": "sha512-+W9VYHKFIzA5cBeooqQxqNriAP0QeQ7xTiDuIOr71hzgffm3EL2hxwWBIIj4GuofIbKxGNarpKqIq6Q6YrShOA==", "dev": true, "license": "MIT", "engines": { @@ -3290,14 +3318,14 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "8.33.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.33.1.tgz", - "integrity": "sha512-1cG37d9xOkhlykom55WVwG2QRNC7YXlxMaMzqw2uPeJixBFfKWZgaP/hjAObqMN/u3fr5BrTwTnc31/L9jQ2ww==", + "version": "8.34.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.34.0.tgz", + "integrity": "sha512-n7zSmOcUVhcRYC75W2pnPpbO1iwhJY3NLoHEtbJwJSNlVAZuwqu05zY3f3s2SDWWDSo9FdN5szqc73DCtDObAg==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/typescript-estree": "8.33.1", - "@typescript-eslint/utils": "8.33.1", + "@typescript-eslint/typescript-estree": "8.34.0", + "@typescript-eslint/utils": "8.34.0", "debug": "^4.3.4", "ts-api-utils": "^2.1.0" }, @@ -3314,9 +3342,9 @@ } }, "node_modules/@typescript-eslint/types": { - "version": "8.33.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.33.1.tgz", - "integrity": "sha512-xid1WfizGhy/TKMTwhtVOgalHwPtV8T32MS9MaH50Cwvz6x6YqRIPdD2WvW0XaqOzTV9p5xdLY0h/ZusU5Lokg==", + "version": "8.34.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.34.0.tgz", + "integrity": "sha512-9V24k/paICYPniajHfJ4cuAWETnt7Ssy+R0Rbcqo5sSFr3QEZ/8TSoUi9XeXVBGXCaLtwTOKSLGcInCAvyZeMA==", "dev": true, "license": "MIT", "engines": { @@ -3328,16 +3356,16 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "8.33.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.33.1.tgz", - "integrity": "sha512-+s9LYcT8LWjdYWu7IWs7FvUxpQ/DGkdjZeE/GGulHvv8rvYwQvVaUZ6DE+j5x/prADUgSbbCWZ2nPI3usuVeOA==", + "version": "8.34.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.34.0.tgz", + "integrity": "sha512-rOi4KZxI7E0+BMqG7emPSK1bB4RICCpF7QD3KCLXn9ZvWoESsOMlHyZPAHyG04ujVplPaHbmEvs34m+wjgtVtg==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/project-service": "8.33.1", - "@typescript-eslint/tsconfig-utils": "8.33.1", - "@typescript-eslint/types": "8.33.1", - "@typescript-eslint/visitor-keys": "8.33.1", + "@typescript-eslint/project-service": "8.34.0", + "@typescript-eslint/tsconfig-utils": "8.34.0", + "@typescript-eslint/types": "8.34.0", + "@typescript-eslint/visitor-keys": "8.34.0", "debug": "^4.3.4", "fast-glob": "^3.3.2", "is-glob": "^4.0.3", @@ -3356,6 +3384,23 @@ "typescript": ">=4.8.4 <5.9.0" } }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/brace-expansion": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", + "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, "node_modules/@typescript-eslint/typescript-estree/node_modules/minimatch": { "version": "9.0.5", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", @@ -3373,16 +3418,16 @@ } }, "node_modules/@typescript-eslint/utils": { - "version": "8.33.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.33.1.tgz", - "integrity": "sha512-52HaBiEQUaRYqAXpfzWSR2U3gxk92Kw006+xZpElaPMg3C4PgM+A5LqwoQI1f9E5aZ/qlxAZxzm42WX+vn92SQ==", + "version": "8.34.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.34.0.tgz", + "integrity": "sha512-8L4tWatGchV9A1cKbjaavS6mwYwp39jql8xUmIIKJdm+qiaeHy5KMKlBrf30akXAWBzn2SqKsNOtSENWUwg7XQ==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.7.0", - "@typescript-eslint/scope-manager": "8.33.1", - "@typescript-eslint/types": "8.33.1", - "@typescript-eslint/typescript-estree": "8.33.1" + "@typescript-eslint/scope-manager": "8.34.0", + "@typescript-eslint/types": "8.34.0", + "@typescript-eslint/typescript-estree": "8.34.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -3397,13 +3442,13 @@ } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "8.33.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.33.1.tgz", - "integrity": "sha512-3i8NrFcZeeDHJ+7ZUuDkGT+UHq+XoFGsymNK2jZCOHcfEzRQ0BdpRtdpSx/Iyf3MHLWIcLS0COuOPibKQboIiQ==", + "version": "8.34.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.34.0.tgz", + "integrity": "sha512-qHV7pW7E85A0x6qyrFn+O+q1k1p3tQCsqIZ1KZ5ESLXY57aTvUd3/a4rdPTeXisvhXn2VQG0VSKUqs8KHF2zcA==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.33.1", + "@typescript-eslint/types": "8.34.0", "eslint-visitor-keys": "^4.2.0" }, "engines": { @@ -3421,10 +3466,38 @@ "dev": true, "license": "ISC" }, + "node_modules/@unrs/resolver-binding-android-arm-eabi": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-android-arm-eabi/-/resolver-binding-android-arm-eabi-1.9.0.tgz", + "integrity": "sha512-h1T2c2Di49ekF2TE8ZCoJkb+jwETKUIPDJ/nO3tJBKlLFPu+fyd93f0rGP/BvArKx2k2HlRM4kqkNarj3dvZlg==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@unrs/resolver-binding-android-arm64": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-android-arm64/-/resolver-binding-android-arm64-1.9.0.tgz", + "integrity": "sha512-sG1NHtgXtX8owEkJ11yn34vt0Xqzi3k9TJ8zppDmyG8GZV4kVWw44FHwKwHeEFl07uKPeC4ZoyuQaGh5ruJYPA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, "node_modules/@unrs/resolver-binding-darwin-arm64": { - "version": "1.7.11", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-darwin-arm64/-/resolver-binding-darwin-arm64-1.7.11.tgz", - "integrity": "sha512-i3/wlWjQJXMh1uiGtiv7k1EYvrrS3L1hdwmWJJiz1D8jWy726YFYPIxQWbEIVPVAgrfRR0XNlLrTQwq17cuCGw==", + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-darwin-arm64/-/resolver-binding-darwin-arm64-1.9.0.tgz", + "integrity": "sha512-nJ9z47kfFnCxN1z/oYZS7HSNsFh43y2asePzTEZpEvK7kGyuShSl3RRXnm/1QaqFL+iP+BjMwuB+DYUymOkA5A==", "cpu": [ "arm64" ], @@ -3436,9 +3509,9 @@ ] }, "node_modules/@unrs/resolver-binding-darwin-x64": { - "version": "1.7.11", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-darwin-x64/-/resolver-binding-darwin-x64-1.7.11.tgz", - "integrity": "sha512-8XXyFvc6w6kmMmi6VYchZhjd5CDcp+Lv6Cn1YmUme0ypsZ/0Kzd+9ESrWtDrWibKPTgSteDTxp75cvBOY64FQQ==", + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-darwin-x64/-/resolver-binding-darwin-x64-1.9.0.tgz", + "integrity": "sha512-TK+UA1TTa0qS53rjWn7cVlEKVGz2B6JYe0C++TdQjvWYIyx83ruwh0wd4LRxYBM5HeuAzXcylA9BH2trARXJTw==", "cpu": [ "x64" ], @@ -3450,9 +3523,9 @@ ] }, "node_modules/@unrs/resolver-binding-freebsd-x64": { - "version": "1.7.11", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-freebsd-x64/-/resolver-binding-freebsd-x64-1.7.11.tgz", - "integrity": "sha512-0qJBYzP8Qk24CZ05RSWDQUjdiQUeIJGfqMMzbtXgCKl/a5xa6thfC0MQkGIr55LCLd6YmMyO640ifYUa53lybQ==", + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-freebsd-x64/-/resolver-binding-freebsd-x64-1.9.0.tgz", + "integrity": "sha512-6uZwzMRFcD7CcCd0vz3Hp+9qIL2jseE/bx3ZjaLwn8t714nYGwiE84WpaMCYjU+IQET8Vu/+BNAGtYD7BG/0yA==", "cpu": [ "x64" ], @@ -3464,9 +3537,9 @@ ] }, "node_modules/@unrs/resolver-binding-linux-arm-gnueabihf": { - "version": "1.7.11", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm-gnueabihf/-/resolver-binding-linux-arm-gnueabihf-1.7.11.tgz", - "integrity": "sha512-1sGwpgvx+WZf0GFT6vkkOm6UJ+mlsVnjw+Yv9esK71idWeRAG3bbpkf3AoY8KIqKqmnzJExi0uKxXpakQ5Pcbg==", + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm-gnueabihf/-/resolver-binding-linux-arm-gnueabihf-1.9.0.tgz", + "integrity": "sha512-bPUBksQfrgcfv2+mm+AZinaKq8LCFvt5PThYqRotqSuuZK1TVKkhbVMS/jvSRfYl7jr3AoZLYbDkItxgqMKRkg==", "cpu": [ "arm" ], @@ -3478,9 +3551,9 @@ ] }, "node_modules/@unrs/resolver-binding-linux-arm-musleabihf": { - "version": "1.7.11", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm-musleabihf/-/resolver-binding-linux-arm-musleabihf-1.7.11.tgz", - "integrity": "sha512-D/1F/2lTe+XAl3ohkYj51NjniVly8sIqkA/n1aOND3ZMO418nl2JNU95iVa1/RtpzaKcWEsNTtHRogykrUflJg==", + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm-musleabihf/-/resolver-binding-linux-arm-musleabihf-1.9.0.tgz", + "integrity": "sha512-uT6E7UBIrTdCsFQ+y0tQd3g5oudmrS/hds5pbU3h4s2t/1vsGWbbSKhBSCD9mcqaqkBwoqlECpUrRJCmldl8PA==", "cpu": [ "arm" ], @@ -3492,9 +3565,9 @@ ] }, "node_modules/@unrs/resolver-binding-linux-arm64-gnu": { - "version": "1.7.11", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm64-gnu/-/resolver-binding-linux-arm64-gnu-1.7.11.tgz", - "integrity": "sha512-7vFWHLCCNFLEQlmwKQfVy066ohLLArZl+AV/AdmrD1/pD1FlmqM+FKbtnONnIwbHtgetFUCV/SRi1q4D49aTlw==", + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm64-gnu/-/resolver-binding-linux-arm64-gnu-1.9.0.tgz", + "integrity": "sha512-vdqBh911wc5awE2bX2zx3eflbyv8U9xbE/jVKAm425eRoOVv/VseGZsqi3A3SykckSpF4wSROkbQPvbQFn8EsA==", "cpu": [ "arm64" ], @@ -3506,9 +3579,9 @@ ] }, "node_modules/@unrs/resolver-binding-linux-arm64-musl": { - "version": "1.7.11", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm64-musl/-/resolver-binding-linux-arm64-musl-1.7.11.tgz", - "integrity": "sha512-tYkGIx8hjWPh4zcn17jLEHU8YMmdP2obRTGkdaB3BguGHh31VCS3ywqC4QjTODjmhhNyZYkj/1Dz/+0kKvg9YA==", + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm64-musl/-/resolver-binding-linux-arm64-musl-1.9.0.tgz", + "integrity": "sha512-/8JFZ/SnuDr1lLEVsxsuVwrsGquTvT51RZGvyDB/dOK3oYK2UqeXzgeyq6Otp8FZXQcEYqJwxb9v+gtdXn03eQ==", "cpu": [ "arm64" ], @@ -3520,9 +3593,9 @@ ] }, "node_modules/@unrs/resolver-binding-linux-ppc64-gnu": { - "version": "1.7.11", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-ppc64-gnu/-/resolver-binding-linux-ppc64-gnu-1.7.11.tgz", - "integrity": "sha512-6F328QIUev29vcZeRX6v6oqKxfUoGwIIAhWGD8wSysnBYFY0nivp25jdWmAb1GildbCCaQvOKEhCok7YfWkj4Q==", + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-ppc64-gnu/-/resolver-binding-linux-ppc64-gnu-1.9.0.tgz", + "integrity": "sha512-FkJjybtrl+rajTw4loI3L6YqSOpeZfDls4SstL/5lsP2bka9TiHUjgMBjygeZEis1oC8LfJTS8FSgpKPaQx2tQ==", "cpu": [ "ppc64" ], @@ -3534,9 +3607,9 @@ ] }, "node_modules/@unrs/resolver-binding-linux-riscv64-gnu": { - "version": "1.7.11", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-riscv64-gnu/-/resolver-binding-linux-riscv64-gnu-1.7.11.tgz", - "integrity": "sha512-NqhWmiGJGdzbZbeucPZIG9Iav4lyYLCarEnxAceguMx9qlpeEF7ENqYKOwB8Zqk7/CeuYMEcLYMaW2li6HyDzQ==", + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-riscv64-gnu/-/resolver-binding-linux-riscv64-gnu-1.9.0.tgz", + "integrity": "sha512-w/NZfHNeDusbqSZ8r/hp8iL4S39h4+vQMc9/vvzuIKMWKppyUGKm3IST0Qv0aOZ1rzIbl9SrDeIqK86ZpUK37w==", "cpu": [ "riscv64" ], @@ -3548,9 +3621,9 @@ ] }, "node_modules/@unrs/resolver-binding-linux-riscv64-musl": { - "version": "1.7.11", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-riscv64-musl/-/resolver-binding-linux-riscv64-musl-1.7.11.tgz", - "integrity": "sha512-J2RPIFKMdTrLtBdfR1cUMKl8Gcy05nlQ+bEs/6al7EdWLk9cs3tnDREHZ7mV9uGbeghpjo4i8neNZNx3PYUY9w==", + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-riscv64-musl/-/resolver-binding-linux-riscv64-musl-1.9.0.tgz", + "integrity": "sha512-bEPBosut8/8KQbUixPry8zg/fOzVOWyvwzOfz0C0Rw6dp+wIBseyiHKjkcSyZKv/98edrbMknBaMNJfA/UEdqw==", "cpu": [ "riscv64" ], @@ -3562,9 +3635,9 @@ ] }, "node_modules/@unrs/resolver-binding-linux-s390x-gnu": { - "version": "1.7.11", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-s390x-gnu/-/resolver-binding-linux-s390x-gnu-1.7.11.tgz", - "integrity": "sha512-bDpGRerHvvHdhun7MmFUNDpMiYcJSqWckwAVVRTJf8F+RyqYJOp/mx04PDc7DhpNPeWdnTMu91oZRMV+gGaVcQ==", + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-s390x-gnu/-/resolver-binding-linux-s390x-gnu-1.9.0.tgz", + "integrity": "sha512-LDtMT7moE3gK753gG4pc31AAqGUC86j3AplaFusc717EUGF9ZFJ356sdQzzZzkBk1XzMdxFyZ4f/i35NKM/lFA==", "cpu": [ "s390x" ], @@ -3576,9 +3649,9 @@ ] }, "node_modules/@unrs/resolver-binding-linux-x64-gnu": { - "version": "1.7.11", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-x64-gnu/-/resolver-binding-linux-x64-gnu-1.7.11.tgz", - "integrity": "sha512-G9U7bVmylzRLma3cK39RBm3guoD1HOvY4o0NS4JNm37AD0lS7/xyMt7kn0JejYyc0Im8J+rH69/dXGM9DAJcSQ==", + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-x64-gnu/-/resolver-binding-linux-x64-gnu-1.9.0.tgz", + "integrity": "sha512-WmFd5KINHIXj8o1mPaT8QRjA9HgSXhN1gl9Da4IZihARihEnOylu4co7i/yeaIpcfsI6sYs33cNZKyHYDh0lrA==", "cpu": [ "x64" ], @@ -3590,9 +3663,9 @@ ] }, "node_modules/@unrs/resolver-binding-linux-x64-musl": { - "version": "1.7.11", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-x64-musl/-/resolver-binding-linux-x64-musl-1.7.11.tgz", - "integrity": "sha512-7qL20SBKomekSunm7M9Fe5L93bFbn+FbHiGJbfTlp0RKhPVoJDP73vOxf1QrmJHyDPECsGWPFnKa/f8fO2FsHw==", + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-x64-musl/-/resolver-binding-linux-x64-musl-1.9.0.tgz", + "integrity": "sha512-CYuXbANW+WgzVRIl8/QvZmDaZxrqvOldOwlbUjIM4pQ46FJ0W5cinJ/Ghwa/Ng1ZPMJMk1VFdsD/XwmCGIXBWg==", "cpu": [ "x64" ], @@ -3604,9 +3677,9 @@ ] }, "node_modules/@unrs/resolver-binding-wasm32-wasi": { - "version": "1.7.11", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-wasm32-wasi/-/resolver-binding-wasm32-wasi-1.7.11.tgz", - "integrity": "sha512-jisvIva8MidjI+B1lFRZZMfCPaCISePgTyR60wNT1MeQvIh5Ksa0G3gvI+Iqyj3jqYbvOHByenpa5eDGcSdoSg==", + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-wasm32-wasi/-/resolver-binding-wasm32-wasi-1.9.0.tgz", + "integrity": "sha512-6Rp2WH0OoitMYR57Z6VE8Y6corX8C6QEMWLgOV6qXiJIeZ1F9WGXY/yQ8yDC4iTraotyLOeJ2Asea0urWj2fKQ==", "cpu": [ "wasm32" ], @@ -3614,16 +3687,16 @@ "license": "MIT", "optional": true, "dependencies": { - "@napi-rs/wasm-runtime": "^0.2.10" + "@napi-rs/wasm-runtime": "^0.2.11" }, "engines": { "node": ">=14.0.0" } }, "node_modules/@unrs/resolver-binding-win32-arm64-msvc": { - "version": "1.7.11", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-arm64-msvc/-/resolver-binding-win32-arm64-msvc-1.7.11.tgz", - "integrity": "sha512-G+H5nQZ8sRZ8ebMY6mRGBBvTEzMYEcgVauLsNHpvTUavZoCCRVP1zWkCZgOju2dW3O22+8seTHniTdl1/uLz3g==", + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-arm64-msvc/-/resolver-binding-win32-arm64-msvc-1.9.0.tgz", + "integrity": "sha512-rknkrTRuvujprrbPmGeHi8wYWxmNVlBoNW8+4XF2hXUnASOjmuC9FNF1tGbDiRQWn264q9U/oGtixyO3BT8adQ==", "cpu": [ "arm64" ], @@ -3635,9 +3708,9 @@ ] }, "node_modules/@unrs/resolver-binding-win32-ia32-msvc": { - "version": "1.7.11", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-ia32-msvc/-/resolver-binding-win32-ia32-msvc-1.7.11.tgz", - "integrity": "sha512-Hfy46DBfFzyv0wgR0MMOwFFib2W2+Btc8oE5h4XlPhpelnSyA6nFxkVIyTgIXYGTdFaLoZFNn62fmqx3rjEg3A==", + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-ia32-msvc/-/resolver-binding-win32-ia32-msvc-1.9.0.tgz", + "integrity": "sha512-Ceymm+iBl+bgAICtgiHyMLz6hjxmLJKqBim8tDzpX61wpZOx2bPK6Gjuor7I2RiUynVjvvkoRIkrPyMwzBzF3A==", "cpu": [ "ia32" ], @@ -3649,9 +3722,9 @@ ] }, "node_modules/@unrs/resolver-binding-win32-x64-msvc": { - "version": "1.7.11", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-x64-msvc/-/resolver-binding-win32-x64-msvc-1.7.11.tgz", - "integrity": "sha512-7L8NdsQlCJ8T106Gbz/AjzM4QKWVsoQbKpB9bMBGcIZswUuAnJMHpvbqGW3RBqLHCIwX4XZ5fxSBHEFcK2h9wA==", + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-x64-msvc/-/resolver-binding-win32-x64-msvc-1.9.0.tgz", + "integrity": "sha512-k59o9ZyeyS0hAlcaKFezYSH2agQeRFEB7KoQLXl3Nb3rgkqT1NY9Vwy+SqODiLmYnEjxWJVRE/yq2jFVqdIxZw==", "cpu": [ "x64" ], @@ -3677,9 +3750,9 @@ } }, "node_modules/@vitest/eslint-plugin": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@vitest/eslint-plugin/-/eslint-plugin-1.2.1.tgz", - "integrity": "sha512-JQr1jdVcrsoS7Sdzn83h9sq4DvREf9Q/onTZbJCqTVlv/76qb+TZrLv/9VhjnjSMHweQH5FdpMDeCR6aDe2fgw==", + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/@vitest/eslint-plugin/-/eslint-plugin-1.2.2.tgz", + "integrity": "sha512-R8NwW+VxyKqVGcMfYsUbdThQyMbtNcoeg+jJeTgMHqWdFdcS0nrODAQXhkplvWzgd7jIJ+GQeydGqFLibsxMxg==", "dev": true, "license": "MIT", "dependencies": { @@ -3700,15 +3773,15 @@ } }, "node_modules/@vitest/expect": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-3.2.2.tgz", - "integrity": "sha512-ipHw0z669vEMjzz3xQE8nJX1s0rQIb7oEl4jjl35qWTwm/KIHERIg/p/zORrjAaZKXfsv7IybcNGHwhOOAPMwQ==", + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-3.2.3.tgz", + "integrity": "sha512-W2RH2TPWVHA1o7UmaFKISPvdicFJH+mjykctJFoAkUw+SPTJTGjUNdKscFBrqM7IPnCVu6zihtKYa7TkZS1dkQ==", "dev": true, "license": "MIT", "dependencies": { "@types/chai": "^5.2.2", - "@vitest/spy": "3.2.2", - "@vitest/utils": "3.2.2", + "@vitest/spy": "3.2.3", + "@vitest/utils": "3.2.3", "chai": "^5.2.0", "tinyrainbow": "^2.0.0" }, @@ -3717,13 +3790,13 @@ } }, "node_modules/@vitest/mocker": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-3.2.2.tgz", - "integrity": "sha512-jKojcaRyIYpDEf+s7/dD3LJt53c0dPfp5zCPXz9H/kcGrSlovU/t1yEaNzM9oFME3dcd4ULwRI/x0Po1Zf+LTw==", + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-3.2.3.tgz", + "integrity": "sha512-cP6fIun+Zx8he4rbWvi+Oya6goKQDZK+Yq4hhlggwQBbrlOQ4qtZ+G4nxB6ZnzI9lyIb+JnvyiJnPC2AGbKSPA==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/spy": "3.2.2", + "@vitest/spy": "3.2.3", "estree-walker": "^3.0.3", "magic-string": "^0.30.17" }, @@ -3771,9 +3844,9 @@ } }, "node_modules/@vitest/pretty-format": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-3.2.2.tgz", - "integrity": "sha512-FY4o4U1UDhO9KMd2Wee5vumwcaHw7Vg4V7yR4Oq6uK34nhEJOmdRYrk3ClburPRUA09lXD/oXWZ8y/Sdma0aUQ==", + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-3.2.3.tgz", + "integrity": "sha512-yFglXGkr9hW/yEXngO+IKMhP0jxyFw2/qys/CK4fFUZnSltD+MU7dVYGrH8rvPcK/O6feXQA+EU33gjaBBbAng==", "dev": true, "license": "MIT", "dependencies": { @@ -3784,27 +3857,28 @@ } }, "node_modules/@vitest/runner": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-3.2.2.tgz", - "integrity": "sha512-GYcHcaS3ejGRZYed2GAkvsjBeXIEerDKdX3orQrBJqLRiea4NSS9qvn9Nxmuy1IwIB+EjFOaxXnX79l8HFaBwg==", + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-3.2.3.tgz", + "integrity": "sha512-83HWYisT3IpMaU9LN+VN+/nLHVBCSIUKJzGxC5RWUOsK1h3USg7ojL+UXQR3b4o4UBIWCYdD2fxuzM7PQQ1u8w==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/utils": "3.2.2", - "pathe": "^2.0.3" + "@vitest/utils": "3.2.3", + "pathe": "^2.0.3", + "strip-literal": "^3.0.0" }, "funding": { "url": "https://opencollective.com/vitest" } }, "node_modules/@vitest/snapshot": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-3.2.2.tgz", - "integrity": "sha512-aMEI2XFlR1aNECbBs5C5IZopfi5Lb8QJZGGpzS8ZUHML5La5wCbrbhLOVSME68qwpT05ROEEOAZPRXFpxZV2wA==", + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-3.2.3.tgz", + "integrity": "sha512-9gIVWx2+tysDqUmmM1L0hwadyumqssOL1r8KJipwLx5JVYyxvVRfxvMq7DaWbZZsCqZnu/dZedaZQh4iYTtneA==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/pretty-format": "3.2.2", + "@vitest/pretty-format": "3.2.3", "magic-string": "^0.30.17", "pathe": "^2.0.3" }, @@ -3823,9 +3897,9 @@ } }, "node_modules/@vitest/spy": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-3.2.2.tgz", - "integrity": "sha512-6Utxlx3o7pcTxvp0u8kUiXtRFScMrUg28KjB3R2hon7w4YqOFAEA9QwzPVVS1QNL3smo4xRNOpNZClRVfpMcYg==", + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-3.2.3.tgz", + "integrity": "sha512-JHu9Wl+7bf6FEejTCREy+DmgWe+rQKbK+y32C/k5f4TBIAlijhJbRBIRIOCEpVevgRsCQR2iHRUH2/qKVM/plw==", "dev": true, "license": "MIT", "dependencies": { @@ -3836,13 +3910,13 @@ } }, "node_modules/@vitest/utils": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-3.2.2.tgz", - "integrity": "sha512-qJYMllrWpF/OYfWHP32T31QCaLa3BAzT/n/8mNGhPdVcjY+JYazQFO1nsJvXU12Kp1xMpNY4AGuljPTNjQve6A==", + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-3.2.3.tgz", + "integrity": "sha512-4zFBCU5Pf+4Z6v+rwnZ1HU1yzOKKvDkMXZrymE2PBlbjKJRlrOxbvpfPSvJTGRIwGoahaOGvp+kbCoxifhzJ1Q==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/pretty-format": "3.2.2", + "@vitest/pretty-format": "3.2.3", "loupe": "^3.1.3", "tinyrainbow": "^2.0.0" }, @@ -3974,6 +4048,23 @@ } } }, + "node_modules/@vue/language-core/node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@vue/language-core/node_modules/brace-expansion": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", + "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, "node_modules/@vue/language-core/node_modules/minimatch": { "version": "9.0.5", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", @@ -4256,9 +4347,9 @@ } }, "node_modules/acorn": { - "version": "8.14.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.1.tgz", - "integrity": "sha512-OvQ/2pUDKmgfCg++xsTX1wGxfTaszcHVcTctW4UJB4hibJx2HXxxO5UmVgyjMa+ZDsiaf5wWLXYpRWMmBI0QHg==", + "version": "8.15.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", + "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", "license": "MIT", "bin": { "acorn": "bin/acorn" @@ -4622,10 +4713,13 @@ } }, "node_modules/balanced-match": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", - "license": "MIT" + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-3.0.1.tgz", + "integrity": "sha512-vjtV3hiLqYDNRoiAv0zC4QaGAMPomEoq83PRmYIofPswwZurCeWR5LByXm7SyoL0Zh5+2z0+HC7jG8gSZJUh0w==", + "license": "MIT", + "engines": { + "node": ">= 16" + } }, "node_modules/base64-js": { "version": "1.5.1", @@ -4676,12 +4770,15 @@ "license": "ISC" }, "node_modules/brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-4.0.1.tgz", + "integrity": "sha512-YClrbvTCXGe70pU2JiEiPLYXO9gQkyxYeKpJIQHVS/gOs6EWMQP2RYBwjFLNT322Ji8TOC3IMPfsYCedNpzKfA==", "license": "MIT", "dependencies": { - "balanced-match": "^1.0.0" + "balanced-match": "^3.0.0" + }, + "engines": { + "node": ">= 18" } }, "node_modules/braces": { @@ -4799,9 +4896,9 @@ } }, "node_modules/cacheable": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/cacheable/-/cacheable-1.9.0.tgz", - "integrity": "sha512-8D5htMCxPDUULux9gFzv30f04Xo3wCnik0oOxKoRTPIBoqA7HtOcJ87uBhQTs3jCfZZTrUBGsYIZOgE0ZRgMAg==", + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/cacheable/-/cacheable-1.10.0.tgz", + "integrity": "sha512-SSgQTAnhd7WlJXnGlIi4jJJOiHzgnM5wRMEPaXAU4kECTAMpBoYKoZ9i5zHmclIEZbxcu3j7yY/CF8DTmwIsHg==", "dev": true, "license": "MIT", "dependencies": { @@ -4810,9 +4907,9 @@ } }, "node_modules/cacheable/node_modules/keyv": { - "version": "5.3.3", - "resolved": "https://registry.npmjs.org/keyv/-/keyv-5.3.3.tgz", - "integrity": "sha512-Rwu4+nXI9fqcxiEHtbkvoes2X+QfkTRo1TMkPfwzipGsJlJO/z69vqB4FNl9xJ3xCpAcbkvmEabZfPzrwN3+gQ==", + "version": "5.3.4", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-5.3.4.tgz", + "integrity": "sha512-ypEvQvInNpUe+u+w8BIcPkQvEqXquyyibWE/1NB5T2BTzIpS5cGEV1LZskDzPSTvNAaT4+5FutvzlvnkxOSKlw==", "dev": true, "license": "MIT", "dependencies": { @@ -4838,9 +4935,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001721", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001721.tgz", - "integrity": "sha512-cOuvmUVtKrtEaoKiO0rSc29jcjwMwX5tOHDy4MgVFEWiUXj4uBMJkwI8MDySkgXidpMiHUcviogAvFi4pA2hDQ==", + "version": "1.0.30001722", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001722.tgz", + "integrity": "sha512-DCQHBBZtiK6JVkAGw7drvAMK0Q0POD/xZvEmDp6baiMMP6QXXk9HpD6mNYBZWhOPG6LvIDb82ITqtWjhDckHCA==", "funding": [ { "type": "opencollective", @@ -5241,13 +5338,13 @@ "license": "MIT" }, "node_modules/core-js-compat": { - "version": "3.42.0", - "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.42.0.tgz", - "integrity": "sha512-bQasjMfyDGyaeWKBIu33lHh9qlSR0MFE/Nmc6nMjf/iU9b3rSMdAYz1Baxrv4lPdGUsTqZudHA4jIGSJy0SWZQ==", + "version": "3.43.0", + "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.43.0.tgz", + "integrity": "sha512-2GML2ZsCc5LR7hZYz4AXmjQw8zuy2T//2QntwdnpuYI7jteT6GVYJL7F6C2C57R7gSYrcqVW3lAALefdbhBLDA==", "dev": true, "license": "MIT", "dependencies": { - "browserslist": "^4.24.4" + "browserslist": "^4.25.0" }, "funding": { "type": "opencollective", @@ -6282,9 +6379,9 @@ } }, "node_modules/electron-to-chromium": { - "version": "1.5.165", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.165.tgz", - "integrity": "sha512-naiMx1Z6Nb2TxPU6fiFrUrDTjyPMLdTtaOd2oLmG8zVSg2hCWGkhPyxwk+qRmZ1ytwVqUv0u7ZcDA5+ALhaUtw==", + "version": "1.5.166", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.166.tgz", + "integrity": "sha512-QPWqHL0BglzPYyJJ1zSSmwFFL6MFXhbACOCcsCdUMCkzPdS9/OIBVxg516X/Ado2qwAq8k0nJJ7phQPCqiaFAw==", "license": "ISC" }, "node_modules/emoji-regex": { @@ -6817,21 +6914,21 @@ } }, "node_modules/eslint-plugin-import-x": { - "version": "4.15.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-import-x/-/eslint-plugin-import-x-4.15.1.tgz", - "integrity": "sha512-JfVpNg1qMkPD66iaSgmMoSYeUCGS8UFSm3GwHV0IbuV3Knar/SyK5qqCct9+AxoMIzaM+KSO7KK5pOeOkC/3GQ==", + "version": "4.15.2", + "resolved": "https://registry.npmjs.org/eslint-plugin-import-x/-/eslint-plugin-import-x-4.15.2.tgz", + "integrity": "sha512-J5gx7sN6DTm0LRT//eP3rVVQ2Yi4hrX0B+DbWxa5er8PZ6JjLo9GUBwogIFvEDdwJaSqZplpQT+haK/cXhb7VQ==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "^8.33.1", + "@typescript-eslint/types": "^8.34.0", "comment-parser": "^1.4.1", "debug": "^4.4.1", - "eslint-import-context": "^0.1.7", + "eslint-import-context": "^0.1.8", "is-glob": "^4.0.3", "minimatch": "^9.0.3 || ^10.0.1", "semver": "^7.7.2", "stable-hash-x": "^0.1.1", - "unrs-resolver": "^1.7.10" + "unrs-resolver": "^1.9.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -6853,10 +6950,17 @@ } } }, + "node_modules/eslint-plugin-import/node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true, + "license": "MIT" + }, "node_modules/eslint-plugin-import/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", "dev": true, "license": "MIT", "dependencies": { @@ -6940,10 +7044,17 @@ "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9" } }, + "node_modules/eslint-plugin-jsx-a11y/node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true, + "license": "MIT" + }, "node_modules/eslint-plugin-jsx-a11y/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", "dev": true, "license": "MIT", "dependencies": { @@ -7051,9 +7162,9 @@ } }, "node_modules/eslint-plugin-regexp": { - "version": "2.8.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-regexp/-/eslint-plugin-regexp-2.8.0.tgz", - "integrity": "sha512-xme90IvkMgdyS+NJC21FM0H6ek4urGsdlIFTXpZRqH2BKJKVSd8hRbyrCpbcqfGBi2jth3eQoLiO3RC1gxZHiw==", + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-regexp/-/eslint-plugin-regexp-2.9.0.tgz", + "integrity": "sha512-9WqJMnOq8VlE/cK+YAo9C9YHhkOtcEtEk9d12a+H7OSZFwlpI6stiHmYPGa2VE0QhTzodJyhlyprUaXDZLgHBw==", "dev": true, "license": "MIT", "dependencies": { @@ -7093,6 +7204,23 @@ "eslint": "^8.0.0 || ^9.0.0" } }, + "node_modules/eslint-plugin-sonarjs/node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true, + "license": "MIT" + }, + "node_modules/eslint-plugin-sonarjs/node_modules/brace-expansion": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", + "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, "node_modules/eslint-plugin-sonarjs/node_modules/minimatch": { "version": "9.0.5", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", @@ -7260,9 +7388,9 @@ } }, "node_modules/eslint-visitor-keys": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.0.tgz", - "integrity": "sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw==", + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz", + "integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==", "dev": true, "license": "Apache-2.0", "engines": { @@ -7289,10 +7417,17 @@ "url": "https://github.com/sponsors/epoberezkin" } }, + "node_modules/eslint/node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true, + "license": "MIT" + }, "node_modules/eslint/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", "dev": true, "license": "MIT", "dependencies": { @@ -7352,15 +7487,15 @@ } }, "node_modules/espree": { - "version": "10.3.0", - "resolved": "https://registry.npmjs.org/espree/-/espree-10.3.0.tgz", - "integrity": "sha512-0QYC8b24HWY8zjRnDTL6RiHfDbAWn63qb4LMj1Z4b076A4une81+z03Kg7l7mn/48PUTqoLptSXez8oknU8Clg==", + "version": "10.4.0", + "resolved": "https://registry.npmjs.org/espree/-/espree-10.4.0.tgz", + "integrity": "sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ==", "dev": true, "license": "BSD-2-Clause", "dependencies": { - "acorn": "^8.14.0", + "acorn": "^8.15.0", "acorn-jsx": "^5.3.2", - "eslint-visitor-keys": "^4.2.0" + "eslint-visitor-keys": "^4.2.1" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -7811,10 +7946,16 @@ "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==", "license": "BSD-2-Clause" }, + "node_modules/glob/node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "license": "MIT" + }, "node_modules/glob/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", "license": "MIT", "dependencies": { "balanced-match": "^1.0.0", @@ -7967,19 +8108,37 @@ } }, "node_modules/happy-dom": { - "version": "17.6.3", - "resolved": "https://registry.npmjs.org/happy-dom/-/happy-dom-17.6.3.tgz", - "integrity": "sha512-UVIHeVhxmxedbWPCfgS55Jg2rDfwf2BCKeylcPSqazLz5w3Kri7Q4xdBJubsr/+VUzFLh0VjIvh13RaDA2/Xug==", + "version": "18.0.1", + "resolved": "https://registry.npmjs.org/happy-dom/-/happy-dom-18.0.1.tgz", + "integrity": "sha512-qn+rKOW7KWpVTtgIUi6RVmTBZJSe2k0Db0vh1f7CWrWclkkc7/Q+FrOfkZIb2eiErLyqu5AXEzE7XthO9JVxRA==", "dev": true, "license": "MIT", "dependencies": { - "webidl-conversions": "^7.0.0", + "@types/node": "^20.0.0", + "@types/whatwg-mimetype": "^3.0.2", "whatwg-mimetype": "^3.0.0" }, "engines": { "node": ">=20.0.0" } }, + "node_modules/happy-dom/node_modules/@types/node": { + "version": "20.19.0", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.19.0.tgz", + "integrity": "sha512-hfrc+1tud1xcdVTABC2JiomZJEklMcXYNTVtZLAeqTVWD+qL5jkHKT+1lOtqDdGxt+mB53DTtiz673vfjU8D1Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "undici-types": "~6.21.0" + } + }, + "node_modules/happy-dom/node_modules/undici-types": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz", + "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==", + "dev": true, + "license": "MIT" + }, "node_modules/has-flag": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", @@ -8880,10 +9039,16 @@ "webpack": "^4.4.0 || ^5.4.0" } }, + "node_modules/license-checker-webpack-plugin/node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "license": "MIT" + }, "node_modules/license-checker-webpack-plugin/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", "license": "MIT", "dependencies": { "balanced-match": "^1.0.0", @@ -9991,12 +10156,12 @@ } }, "node_modules/minimatch": { - "version": "10.0.1", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.0.1.tgz", - "integrity": "sha512-ethXTt3SGGR+95gudmqJ1eNhRO7eGEGIgYA9vnPatK4/etz2MEVDno5GMCibdMTuBMyElzIlgxMna3K94XDIDQ==", + "version": "10.0.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.0.2.tgz", + "integrity": "sha512-+9TJCIYXgZ2Dm5LxVCFsa8jOm+evMwXHFI0JM1XROmkfkpz8/iLLDh+TwSmyIBrs6C6Xu9294/fq8cBA+P6AqA==", "license": "ISC", "dependencies": { - "brace-expansion": "^2.0.1" + "brace-expansion": "^4.0.1" }, "engines": { "node": "20 || >=22" @@ -10694,13 +10859,13 @@ } }, "node_modules/playwright": { - "version": "1.52.0", - "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.52.0.tgz", - "integrity": "sha512-JAwMNMBlxJ2oD1kce4KPtMkDeKGHQstdpFPcPH3maElAXon/QZeTvtsfXmTMRyO9TslfoYOXkSsvao2nE1ilTw==", + "version": "1.53.0", + "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.53.0.tgz", + "integrity": "sha512-ghGNnIEYZC4E+YtclRn4/p6oYbdPiASELBIYkBXfaTVKreQUYbMUYQDwS12a8F0/HtIjr/CkGjtwABeFPGcS4Q==", "dev": true, "license": "Apache-2.0", "dependencies": { - "playwright-core": "1.52.0" + "playwright-core": "1.53.0" }, "bin": { "playwright": "cli.js" @@ -10713,9 +10878,9 @@ } }, "node_modules/playwright-core": { - "version": "1.52.0", - "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.52.0.tgz", - "integrity": "sha512-l2osTgLXSMeuLZOML9qYODUQoPPnUsKsb5/P6LJ2e6uPKXUdPK5WYhN4z03G+YNbWmGDY4YENauNu4ZKczreHg==", + "version": "1.53.0", + "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.53.0.tgz", + "integrity": "sha512-mGLg8m0pm4+mmtB7M89Xw/GSqoNC+twivl8ITteqvAndachozYe2ZA7srU6uleV1vEdAHYqjq+SV8SNxRRFYBw==", "dev": true, "license": "Apache-2.0", "bin": { @@ -10762,9 +10927,9 @@ } }, "node_modules/postcss": { - "version": "8.5.4", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.4.tgz", - "integrity": "sha512-QSa9EBe+uwlGTFmHsPKokv3B/oEMQZxfqW0QqNCyhpa6mB1afzulwn8hihglqAb2pOw+BJgNlmXQ8la2VeHB7w==", + "version": "8.5.5", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.5.tgz", + "integrity": "sha512-d/jtm+rdNT8tpXuHY5MMtcbJFBkhXE6593XVR9UoGCH8jSFGci7jGvMGH5RYd5PBJW+00NZQt6gf7CbagJCrhg==", "funding": [ { "type": "opencollective", @@ -10983,9 +11148,9 @@ } }, "node_modules/postcss-nesting": { - "version": "13.0.1", - "resolved": "https://registry.npmjs.org/postcss-nesting/-/postcss-nesting-13.0.1.tgz", - "integrity": "sha512-VbqqHkOBOt4Uu3G8Dm8n6lU5+9cJFxiuty9+4rcoyRPO9zZS1JIs6td49VIoix3qYqELHlJIn46Oih9SAKo+yQ==", + "version": "13.0.2", + "resolved": "https://registry.npmjs.org/postcss-nesting/-/postcss-nesting-13.0.2.tgz", + "integrity": "sha512-1YCI290TX+VP0U/K/aFxzHzQWHWURL+CtHMSbex1lCdpXD1SoR2sYuxDu5aNI9lPoXpKTCggFZiDJbwylU0LEQ==", "funding": [ { "type": "github", @@ -10998,7 +11163,7 @@ ], "license": "MIT-0", "dependencies": { - "@csstools/selector-resolve-nested": "^3.0.0", + "@csstools/selector-resolve-nested": "^3.1.0", "@csstools/selector-specificity": "^5.0.0", "postcss-selector-parser": "^7.0.0" }, @@ -12215,6 +12380,19 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/strip-literal": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-literal/-/strip-literal-3.0.0.tgz", + "integrity": "sha512-TcccoMhJOM3OebGhSBEmp3UZ2SfDMZUEBdRA/9ynfLi8yYajyWX3JiXArcJt4Umh4vISpspkQIY8ZZoCqjbviA==", + "dev": true, + "license": "MIT", + "dependencies": { + "js-tokens": "^9.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, "node_modules/style-search": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/style-search/-/style-search-0.1.0.tgz", @@ -12424,25 +12602,25 @@ "license": "MIT" }, "node_modules/stylelint/node_modules/file-entry-cache": { - "version": "10.1.0", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-10.1.0.tgz", - "integrity": "sha512-Et/ex6smi3wOOB+n5mek+Grf7P2AxZR5ueqRUvAAn4qkyatXi3cUC1cuQXVkX0VlzBVsN4BkWJFmY/fYiRTdww==", + "version": "10.1.1", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-10.1.1.tgz", + "integrity": "sha512-zcmsHjg2B2zjuBgjdnB+9q0+cWcgWfykIcsDkWDB4GTPtl1eXUA+gTI6sO0u01AqK3cliHryTU55/b2Ow1hfZg==", "dev": true, "license": "MIT", "dependencies": { - "flat-cache": "^6.1.9" + "flat-cache": "^6.1.10" } }, "node_modules/stylelint/node_modules/flat-cache": { - "version": "6.1.9", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-6.1.9.tgz", - "integrity": "sha512-DUqiKkTlAfhtl7g78IuwqYM+YqvT+as0mY+EVk6mfimy19U79pJCzDZQsnqk3Ou/T6hFXWLGbwbADzD/c8Tydg==", + "version": "6.1.10", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-6.1.10.tgz", + "integrity": "sha512-B6/v1f0NwjxzmeOhzfXPGWpKBVA207LS7lehaVKQnFrVktcFRfkzjZZ2gwj2i1TkEUMQht7ZMJbABUT5N+V1Nw==", "dev": true, "license": "MIT", "dependencies": { - "cacheable": "^1.9.0", + "cacheable": "^1.10.0", "flatted": "^3.3.3", - "hookified": "^1.8.2" + "hookified": "^1.9.1" } }, "node_modules/stylelint/node_modules/ignore": { @@ -12565,6 +12743,21 @@ "node": ">=16 || 14 >=14.17" } }, + "node_modules/sucrase/node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "license": "MIT" + }, + "node_modules/sucrase/node_modules/brace-expansion": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", + "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, "node_modules/sucrase/node_modules/commander": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz", @@ -12779,9 +12972,9 @@ } }, "node_modules/swagger-ui-dist": { - "version": "5.24.0", - "resolved": "https://registry.npmjs.org/swagger-ui-dist/-/swagger-ui-dist-5.24.0.tgz", - "integrity": "sha512-okwN8vf14TOgBTUyGgCXEAoHnrwwp/042dC00B3kPu2OAe9zD75BtSbLlgAK1Y5e3csJhs+AdnIxJYZN9uvptg==", + "version": "5.24.1", + "resolved": "https://registry.npmjs.org/swagger-ui-dist/-/swagger-ui-dist-5.24.1.tgz", + "integrity": "sha512-ITeWc7CCAfK53u8jnV39UNqStQZjSt+bVYtJHsOEL3vVj/WV9/8HmsF8Ej4oD8r+Xk1HpWyeW/t59r1QNeAcUQ==", "license": "Apache-2.0", "dependencies": { "@scarf/scarf": "=1.4.0" @@ -12915,9 +13108,9 @@ } }, "node_modules/terser": { - "version": "5.41.0", - "resolved": "https://registry.npmjs.org/terser/-/terser-5.41.0.tgz", - "integrity": "sha512-H406eLPXpZbAX14+B8psIuvIr8+3c+2hkuYzpMkoE0ij+NdsVATbA78vb8neA/eqrj7rywa2pIkdmWRsXW6wmw==", + "version": "5.42.0", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.42.0.tgz", + "integrity": "sha512-UYCvU9YQW2f/Vwl+P0GfhxJxbUGLwd+5QrrGgLajzWAtC/23AX0vcise32kkP7Eu0Wu9VlzzHAXkLObgjQfFlQ==", "license": "BSD-2-Clause", "dependencies": { "@jridgewell/source-map": "^0.3.3", @@ -13046,9 +13239,9 @@ } }, "node_modules/tinyglobby/node_modules/fdir": { - "version": "6.4.5", - "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.4.5.tgz", - "integrity": "sha512-4BG7puHpVsIYxZUbiUE3RqGloLaSSwzYie5jvasC4LWuBWzZawynvYouhjbQKw2JuIGYdm0DzIxl8iVidKlUEw==", + "version": "6.4.6", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.4.6.tgz", + "integrity": "sha512-hiFoqpyZcfNm1yc4u8oWCf9A2c4D3QjCrks3zmoVKVxpQRzmPNar1hUJcBG2RQHvEVGDN+Jm81ZheVLAQMK6+w==", "dev": true, "license": "MIT", "peerDependencies": { @@ -13268,9 +13461,9 @@ "license": "ISC" }, "node_modules/undici-types": { - "version": "6.21.0", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz", - "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==", + "version": "7.8.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.8.0.tgz", + "integrity": "sha512-9UJ2xGDvQ43tYyVMpuHlsgApydB8ZKfVYTsLDhXkFL/6gfkp+U8xTGdh8pMJv1SpZna0zxG1DwsKZsreLbXBxw==", "license": "MIT" }, "node_modules/universalify": { @@ -13284,9 +13477,9 @@ } }, "node_modules/unrs-resolver": { - "version": "1.7.11", - "resolved": "https://registry.npmjs.org/unrs-resolver/-/unrs-resolver-1.7.11.tgz", - "integrity": "sha512-OhuAzBImFPjKNgZ2JwHMfGFUA6NSbRegd1+BPjC1Y0E6X9Y/vJ4zKeGmIMqmlYboj6cMNEwKI+xQisrg4J0HaQ==", + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/unrs-resolver/-/unrs-resolver-1.9.0.tgz", + "integrity": "sha512-wqaRu4UnzBD2ABTC1kLfBjAqIDZ5YUTr/MLGa7By47JV1bJDSW7jq/ZSLigB7enLe7ubNaJhtnBXgrc/50cEhg==", "dev": true, "hasInstallScript": true, "license": "MIT", @@ -13297,23 +13490,25 @@ "url": "https://opencollective.com/unrs-resolver" }, "optionalDependencies": { - "@unrs/resolver-binding-darwin-arm64": "1.7.11", - "@unrs/resolver-binding-darwin-x64": "1.7.11", - "@unrs/resolver-binding-freebsd-x64": "1.7.11", - "@unrs/resolver-binding-linux-arm-gnueabihf": "1.7.11", - "@unrs/resolver-binding-linux-arm-musleabihf": "1.7.11", - "@unrs/resolver-binding-linux-arm64-gnu": "1.7.11", - "@unrs/resolver-binding-linux-arm64-musl": "1.7.11", - "@unrs/resolver-binding-linux-ppc64-gnu": "1.7.11", - "@unrs/resolver-binding-linux-riscv64-gnu": "1.7.11", - "@unrs/resolver-binding-linux-riscv64-musl": "1.7.11", - "@unrs/resolver-binding-linux-s390x-gnu": "1.7.11", - "@unrs/resolver-binding-linux-x64-gnu": "1.7.11", - "@unrs/resolver-binding-linux-x64-musl": "1.7.11", - "@unrs/resolver-binding-wasm32-wasi": "1.7.11", - "@unrs/resolver-binding-win32-arm64-msvc": "1.7.11", - "@unrs/resolver-binding-win32-ia32-msvc": "1.7.11", - "@unrs/resolver-binding-win32-x64-msvc": "1.7.11" + "@unrs/resolver-binding-android-arm-eabi": "1.9.0", + "@unrs/resolver-binding-android-arm64": "1.9.0", + "@unrs/resolver-binding-darwin-arm64": "1.9.0", + "@unrs/resolver-binding-darwin-x64": "1.9.0", + "@unrs/resolver-binding-freebsd-x64": "1.9.0", + "@unrs/resolver-binding-linux-arm-gnueabihf": "1.9.0", + "@unrs/resolver-binding-linux-arm-musleabihf": "1.9.0", + "@unrs/resolver-binding-linux-arm64-gnu": "1.9.0", + "@unrs/resolver-binding-linux-arm64-musl": "1.9.0", + "@unrs/resolver-binding-linux-ppc64-gnu": "1.9.0", + "@unrs/resolver-binding-linux-riscv64-gnu": "1.9.0", + "@unrs/resolver-binding-linux-riscv64-musl": "1.9.0", + "@unrs/resolver-binding-linux-s390x-gnu": "1.9.0", + "@unrs/resolver-binding-linux-x64-gnu": "1.9.0", + "@unrs/resolver-binding-linux-x64-musl": "1.9.0", + "@unrs/resolver-binding-wasm32-wasi": "1.9.0", + "@unrs/resolver-binding-win32-arm64-msvc": "1.9.0", + "@unrs/resolver-binding-win32-ia32-msvc": "1.9.0", + "@unrs/resolver-binding-win32-x64-msvc": "1.9.0" } }, "node_modules/update-browserslist-db": { @@ -13508,9 +13703,9 @@ } }, "node_modules/vite-node": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/vite-node/-/vite-node-3.2.2.tgz", - "integrity": "sha512-Xj/jovjZvDXOq2FgLXu8NsY4uHUMWtzVmMC2LkCu9HWdr9Qu1Is5sanX3Z4jOFKdohfaWDnEJWp9pRP0vVpAcA==", + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/vite-node/-/vite-node-3.2.3.tgz", + "integrity": "sha512-gc8aAifGuDIpZHrPjuHyP4dpQmYXqWw7D1GmDnWeNWP654UEXzVfQ5IHPSK5HaHkwB/+p1atpYpSdw/2kOv8iQ==", "dev": true, "license": "MIT", "dependencies": { @@ -13545,9 +13740,9 @@ "license": "MIT" }, "node_modules/vite/node_modules/fdir": { - "version": "6.4.5", - "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.4.5.tgz", - "integrity": "sha512-4BG7puHpVsIYxZUbiUE3RqGloLaSSwzYie5jvasC4LWuBWzZawynvYouhjbQKw2JuIGYdm0DzIxl8iVidKlUEw==", + "version": "6.4.6", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.4.6.tgz", + "integrity": "sha512-hiFoqpyZcfNm1yc4u8oWCf9A2c4D3QjCrks3zmoVKVxpQRzmPNar1hUJcBG2RQHvEVGDN+Jm81ZheVLAQMK6+w==", "dev": true, "license": "MIT", "peerDependencies": { @@ -13588,9 +13783,9 @@ } }, "node_modules/vite/node_modules/rollup": { - "version": "4.42.0", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.42.0.tgz", - "integrity": "sha512-LW+Vse3BJPyGJGAJt1j8pWDKPd73QM8cRXYK1IxOBgL2AGLu7Xd2YOW0M2sLUBCkF5MshXXtMApyEAEzMVMsnw==", + "version": "4.43.0", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.43.0.tgz", + "integrity": "sha512-wdN2Kd3Twh8MAEOEJZsuxuLKCsBEo4PVNLK6tQWAn10VhsVewQLzcucMgLolRlhFybGxfclbPeEYBaP6RvUFGg==", "dev": true, "license": "MIT", "dependencies": { @@ -13604,44 +13799,44 @@ "npm": ">=8.0.0" }, "optionalDependencies": { - "@rollup/rollup-android-arm-eabi": "4.42.0", - "@rollup/rollup-android-arm64": "4.42.0", - "@rollup/rollup-darwin-arm64": "4.42.0", - "@rollup/rollup-darwin-x64": "4.42.0", - "@rollup/rollup-freebsd-arm64": "4.42.0", - "@rollup/rollup-freebsd-x64": "4.42.0", - "@rollup/rollup-linux-arm-gnueabihf": "4.42.0", - "@rollup/rollup-linux-arm-musleabihf": "4.42.0", - "@rollup/rollup-linux-arm64-gnu": "4.42.0", - "@rollup/rollup-linux-arm64-musl": "4.42.0", - "@rollup/rollup-linux-loongarch64-gnu": "4.42.0", - "@rollup/rollup-linux-powerpc64le-gnu": "4.42.0", - "@rollup/rollup-linux-riscv64-gnu": "4.42.0", - "@rollup/rollup-linux-riscv64-musl": "4.42.0", - "@rollup/rollup-linux-s390x-gnu": "4.42.0", - "@rollup/rollup-linux-x64-gnu": "4.42.0", - "@rollup/rollup-linux-x64-musl": "4.42.0", - "@rollup/rollup-win32-arm64-msvc": "4.42.0", - "@rollup/rollup-win32-ia32-msvc": "4.42.0", - "@rollup/rollup-win32-x64-msvc": "4.42.0", + "@rollup/rollup-android-arm-eabi": "4.43.0", + "@rollup/rollup-android-arm64": "4.43.0", + "@rollup/rollup-darwin-arm64": "4.43.0", + "@rollup/rollup-darwin-x64": "4.43.0", + "@rollup/rollup-freebsd-arm64": "4.43.0", + "@rollup/rollup-freebsd-x64": "4.43.0", + "@rollup/rollup-linux-arm-gnueabihf": "4.43.0", + "@rollup/rollup-linux-arm-musleabihf": "4.43.0", + "@rollup/rollup-linux-arm64-gnu": "4.43.0", + "@rollup/rollup-linux-arm64-musl": "4.43.0", + "@rollup/rollup-linux-loongarch64-gnu": "4.43.0", + "@rollup/rollup-linux-powerpc64le-gnu": "4.43.0", + "@rollup/rollup-linux-riscv64-gnu": "4.43.0", + "@rollup/rollup-linux-riscv64-musl": "4.43.0", + "@rollup/rollup-linux-s390x-gnu": "4.43.0", + "@rollup/rollup-linux-x64-gnu": "4.43.0", + "@rollup/rollup-linux-x64-musl": "4.43.0", + "@rollup/rollup-win32-arm64-msvc": "4.43.0", + "@rollup/rollup-win32-ia32-msvc": "4.43.0", + "@rollup/rollup-win32-x64-msvc": "4.43.0", "fsevents": "~2.3.2" } }, "node_modules/vitest": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/vitest/-/vitest-3.2.2.tgz", - "integrity": "sha512-fyNn/Rp016Bt5qvY0OQvIUCwW2vnaEBLxP42PmKbNIoasSYjML+8xyeADOPvBe+Xfl/ubIw4og7Lt9jflRsCNw==", + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/vitest/-/vitest-3.2.3.tgz", + "integrity": "sha512-E6U2ZFXe3N/t4f5BwUaVCKRLHqUpk1CBWeMh78UT4VaTPH/2dyvH6ALl29JTovEPu9dVKr/K/J4PkXgrMbw4Ww==", "dev": true, "license": "MIT", "dependencies": { "@types/chai": "^5.2.2", - "@vitest/expect": "3.2.2", - "@vitest/mocker": "3.2.2", - "@vitest/pretty-format": "^3.2.2", - "@vitest/runner": "3.2.2", - "@vitest/snapshot": "3.2.2", - "@vitest/spy": "3.2.2", - "@vitest/utils": "3.2.2", + "@vitest/expect": "3.2.3", + "@vitest/mocker": "3.2.3", + "@vitest/pretty-format": "^3.2.3", + "@vitest/runner": "3.2.3", + "@vitest/snapshot": "3.2.3", + "@vitest/spy": "3.2.3", + "@vitest/utils": "3.2.3", "chai": "^5.2.0", "debug": "^4.4.1", "expect-type": "^1.2.1", @@ -13655,7 +13850,7 @@ "tinypool": "^1.1.0", "tinyrainbow": "^2.0.0", "vite": "^5.0.0 || ^6.0.0 || ^7.0.0-0", - "vite-node": "3.2.2", + "vite-node": "3.2.3", "why-is-node-running": "^2.3.0" }, "bin": { @@ -13671,8 +13866,8 @@ "@edge-runtime/vm": "*", "@types/debug": "^4.1.12", "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0", - "@vitest/browser": "3.2.2", - "@vitest/ui": "3.2.2", + "@vitest/browser": "3.2.3", + "@vitest/ui": "3.2.3", "happy-dom": "*", "jsdom": "*" }, @@ -13846,9 +14041,9 @@ } }, "node_modules/vue-eslint-parser/node_modules/eslint-scope": { - "version": "8.3.0", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.3.0.tgz", - "integrity": "sha512-pUNxi75F8MJ/GdeKtVLSbYg4ZI34J6C0C7sbL4YOp2exGwen7ZsuBqKzUhXd0qMQ362yET3z+uPwKeg/0C2XCQ==", + "version": "8.4.0", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.4.0.tgz", + "integrity": "sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg==", "dev": true, "license": "BSD-2-Clause", "peer": true, @@ -13916,14 +14111,10 @@ } }, "node_modules/webidl-conversions": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz", - "integrity": "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==", - "dev": true, - "license": "BSD-2-Clause", - "engines": { - "node": ">=12" - } + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==", + "license": "BSD-2-Clause" }, "node_modules/webpack": { "version": "5.99.9", @@ -14104,12 +14295,6 @@ "webidl-conversions": "^3.0.0" } }, - "node_modules/whatwg-url/node_modules/webidl-conversions": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", - "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==", - "license": "BSD-2-Clause" - }, "node_modules/which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", diff --git a/package.json b/package.json index 0f12b831fa..96ade30f37 100644 --- a/package.json +++ b/package.json @@ -36,16 +36,16 @@ "license-checker-webpack-plugin": "0.2.1", "mermaid": "11.6.0", "mini-css-extract-plugin": "2.9.2", - "minimatch": "10.0.1", + "minimatch": "10.0.2", "monaco-editor": "0.52.2", "monaco-editor-webpack-plugin": "7.1.0", "pdfobject": "2.3.1", "perfect-debounce": "1.0.0", - "postcss": "8.5.4", + "postcss": "8.5.5", "postcss-loader": "8.1.1", - "postcss-nesting": "13.0.1", + "postcss-nesting": "13.0.2", "sortablejs": "1.15.6", - "swagger-ui-dist": "5.24.0", + "swagger-ui-dist": "5.24.1", "tailwindcss": "3.4.17", "throttle-debounce": "5.0.2", "tinycolor2": "1.6.0", @@ -65,7 +65,7 @@ }, "devDependencies": { "@eslint-community/eslint-plugin-eslint-comments": "4.5.0", - "@playwright/test": "1.52.0", + "@playwright/test": "1.53.0", "@stoplight/spectral-cli": "6.15.0", "@stylistic/eslint-plugin-js": "3.1.0", "@stylistic/stylelint-plugin": "3.1.2", @@ -79,25 +79,25 @@ "@types/throttle-debounce": "5.0.2", "@types/tinycolor2": "1.4.6", "@types/toastify-js": "1.12.4", - "@typescript-eslint/eslint-plugin": "8.33.1", - "@typescript-eslint/parser": "8.33.1", + "@typescript-eslint/eslint-plugin": "8.34.0", + "@typescript-eslint/parser": "8.34.0", "@vitejs/plugin-vue": "5.2.4", - "@vitest/eslint-plugin": "1.2.1", + "@vitest/eslint-plugin": "1.2.2", "eslint": "8.57.0", "eslint-import-resolver-typescript": "4.4.3", "eslint-plugin-array-func": "4.0.0", "eslint-plugin-github": "5.0.2", - "eslint-plugin-import-x": "4.15.1", + "eslint-plugin-import-x": "4.15.2", "eslint-plugin-no-jquery": "3.1.1", "eslint-plugin-no-use-extend-native": "0.5.0", "eslint-plugin-playwright": "2.2.0", - "eslint-plugin-regexp": "2.8.0", + "eslint-plugin-regexp": "2.9.0", "eslint-plugin-sonarjs": "3.0.2", "eslint-plugin-unicorn": "56.0.1", "eslint-plugin-vue": "10.2.0", "eslint-plugin-vue-scoped-css": "2.10.0", "eslint-plugin-wc": "3.0.1", - "happy-dom": "17.6.3", + "happy-dom": "18.0.1", "markdownlint-cli": "0.45.0", "material-icon-theme": "5.23.0", "nolyfill": "1.0.44", @@ -112,7 +112,7 @@ "type-fest": "4.41.0", "updates": "16.4.2", "vite-string-plugin": "1.4.4", - "vitest": "3.2.2", + "vitest": "3.2.3", "vue-tsc": "2.2.10" }, "browserslist": [ diff --git a/routers/api/v1/api.go b/routers/api/v1/api.go index 95512cb9b6..2c138ad61a 100644 --- a/routers/api/v1/api.go +++ b/routers/api/v1/api.go @@ -971,7 +971,8 @@ func Routes() *web.Router { // Misc (public accessible) m.Group("", func() { m.Get("/version", misc.Version) - m.Get("/signing-key.gpg", misc.SigningKey) + m.Get("/signing-key.gpg", misc.SigningKeyGPG) + m.Get("/signing-key.pub", misc.SigningKeySSH) m.Post("/markup", reqToken(), bind(api.MarkupOption{}), misc.Markup) m.Post("/markdown", reqToken(), bind(api.MarkdownOption{}), misc.Markdown) m.Post("/markdown/raw", reqToken(), misc.MarkdownRaw) @@ -1427,7 +1428,8 @@ func Routes() *web.Router { m.Combo("/file-contents", reqRepoReader(unit.TypeCode), context.ReferencesGitRepo()). Get(repo.GetFileContentsGet). Post(bind(api.GetFilesOptions{}), repo.GetFileContentsPost) // POST method requires "write" permission, so we also support "GET" method above - m.Get("/signing-key.gpg", misc.SigningKey) + m.Get("/signing-key.gpg", misc.SigningKeyGPG) + m.Get("/signing-key.pub", misc.SigningKeySSH) m.Group("/topics", func() { m.Combo("").Get(repo.ListTopics). Put(reqToken(), reqAdmin(), bind(api.RepoTopicOptions{}), repo.UpdateTopics) diff --git a/routers/api/v1/misc/signing.go b/routers/api/v1/misc/signing.go index 667396e39c..db70e04b8f 100644 --- a/routers/api/v1/misc/signing.go +++ b/routers/api/v1/misc/signing.go @@ -4,14 +4,35 @@ package misc import ( - "fmt" - + "code.gitea.io/gitea/modules/git" asymkey_service "code.gitea.io/gitea/services/asymkey" "code.gitea.io/gitea/services/context" ) -// SigningKey returns the public key of the default signing key if it exists -func SigningKey(ctx *context.APIContext) { +func getSigningKey(ctx *context.APIContext, expectedFormat string) { + // if the handler is in the repo's route group, get the repo's signing key + // otherwise, get the global signing key + path := "" + if ctx.Repo != nil && ctx.Repo.Repository != nil { + path = ctx.Repo.Repository.RepoPath() + } + content, format, err := asymkey_service.PublicSigningKey(ctx, path) + if err != nil { + ctx.APIErrorInternal(err) + return + } + if format == "" { + ctx.APIErrorNotFound("no signing key") + return + } else if format != expectedFormat { + ctx.APIErrorNotFound("signing key format is " + format) + return + } + _, _ = ctx.Write([]byte(content)) +} + +// SigningKeyGPG returns the public key of the default signing key if it exists +func SigningKeyGPG(ctx *context.APIContext) { // swagger:operation GET /signing-key.gpg miscellaneous getSigningKey // --- // summary: Get default signing-key.gpg @@ -44,19 +65,42 @@ func SigningKey(ctx *context.APIContext) { // description: "GPG armored public key" // schema: // type: string + getSigningKey(ctx, git.SigningKeyFormatOpenPGP) +} - path := "" - if ctx.Repo != nil && ctx.Repo.Repository != nil { - path = ctx.Repo.Repository.RepoPath() - } +// SigningKeySSH returns the public key of the default signing key if it exists +func SigningKeySSH(ctx *context.APIContext) { + // swagger:operation GET /signing-key.pub miscellaneous getSigningKeySSH + // --- + // summary: Get default signing-key.pub + // produces: + // - text/plain + // responses: + // "200": + // description: "ssh public key" + // schema: + // type: string - content, err := asymkey_service.PublicSigningKey(ctx, path) - if err != nil { - ctx.APIErrorInternal(err) - return - } - _, err = ctx.Write([]byte(content)) - if err != nil { - ctx.APIErrorInternal(fmt.Errorf("Error writing key content %w", err)) - } + // swagger:operation GET /repos/{owner}/{repo}/signing-key.pub repository repoSigningKeySSH + // --- + // summary: Get signing-key.pub for given repository + // produces: + // - text/plain + // parameters: + // - name: owner + // in: path + // description: owner of the repo + // type: string + // required: true + // - name: repo + // in: path + // description: name of the repo + // type: string + // required: true + // responses: + // "200": + // description: "ssh public key" + // schema: + // type: string + getSigningKey(ctx, git.SigningKeyFormatSSH) } diff --git a/routers/web/misc/misc.go b/routers/web/misc/misc.go index d42afafe9e..59b97c1717 100644 --- a/routers/web/misc/misc.go +++ b/routers/web/misc/misc.go @@ -20,7 +20,7 @@ func SSHInfo(rw http.ResponseWriter, req *http.Request) { return } rw.Header().Set("content-type", "text/json;charset=UTF-8") - _, err := rw.Write([]byte(`{"type":"gitea","version":1}`)) + _, err := rw.Write([]byte(`{"type":"agit","version":1}`)) if err != nil { log.Error("fail to write result: err: %v", err) rw.WriteHeader(http.StatusInternalServerError) diff --git a/routers/web/repo/setting/setting.go b/routers/web/repo/setting/setting.go index 5552a8726c..6602685e94 100644 --- a/routers/web/repo/setting/setting.go +++ b/routers/web/repo/setting/setting.go @@ -62,7 +62,7 @@ func SettingsCtxData(ctx *context.Context) { ctx.Data["CanConvertFork"] = ctx.Repo.Repository.IsFork && ctx.Doer.CanCreateRepoIn(ctx.Repo.Repository.Owner) signing, _ := asymkey_service.SigningKey(ctx, ctx.Repo.Repository.RepoPath()) - ctx.Data["SigningKeyAvailable"] = len(signing) > 0 + ctx.Data["SigningKeyAvailable"] = signing != nil ctx.Data["SigningSettings"] = setting.Repository.Signing ctx.Data["IsRepoIndexerEnabled"] = setting.Indexer.RepoIndexerEnabled @@ -105,7 +105,7 @@ func SettingsPost(ctx *context.Context) { ctx.Data["MinimumMirrorInterval"] = setting.Mirror.MinInterval signing, _ := asymkey_service.SigningKey(ctx, ctx.Repo.Repository.RepoPath()) - ctx.Data["SigningKeyAvailable"] = len(signing) > 0 + ctx.Data["SigningKeyAvailable"] = signing != nil ctx.Data["SigningSettings"] = setting.Repository.Signing ctx.Data["IsRepoIndexerEnabled"] = setting.Indexer.RepoIndexerEnabled diff --git a/routers/web/repo/view_file.go b/routers/web/repo/view_file.go index 3df6051975..f43433fb0d 100644 --- a/routers/web/repo/view_file.go +++ b/routers/web/repo/view_file.go @@ -140,13 +140,6 @@ func prepareToRenderFile(ctx *context.Context, entry *git.TreeEntry) { ctx.Data["LFSLockHint"] = ctx.Tr("repo.editor.this_file_locked") } - // Assume file is not editable first. - if fInfo.isLFSFile { - ctx.Data["EditFileTooltip"] = ctx.Tr("repo.editor.cannot_edit_lfs_files") - } else if !isRepresentableAsText { - ctx.Data["EditFileTooltip"] = ctx.Tr("repo.editor.cannot_edit_non_text_files") - } - // read all needed attributes which will be used later // there should be no performance different between reading 2 or 4 here attrsMap, err := attribute.CheckAttributes(ctx, ctx.Repo.GitRepo, ctx.Repo.CommitID, attribute.CheckAttributeOpts{ @@ -243,21 +236,6 @@ func prepareToRenderFile(ctx *context.Context, entry *git.TreeEntry) { ctx.Data["FileContent"] = fileContent ctx.Data["LineEscapeStatus"] = statuses } - if !fInfo.isLFSFile { - if ctx.Repo.CanEnableEditor(ctx, ctx.Doer) { - if lfsLock != nil && lfsLock.OwnerID != ctx.Doer.ID { - ctx.Data["CanEditFile"] = false - ctx.Data["EditFileTooltip"] = ctx.Tr("repo.editor.this_file_locked") - } else { - ctx.Data["CanEditFile"] = true - ctx.Data["EditFileTooltip"] = ctx.Tr("repo.editor.edit_this_file") - } - } else if !ctx.Repo.RefFullName.IsBranch() { - ctx.Data["EditFileTooltip"] = ctx.Tr("repo.editor.must_be_on_a_branch") - } else if !ctx.Repo.CanWriteToBranch(ctx, ctx.Doer, ctx.Repo.BranchName) { - ctx.Data["EditFileTooltip"] = ctx.Tr("repo.editor.fork_before_edit") - } - } case fInfo.st.IsPDF(): ctx.Data["IsPDFFile"] = true @@ -307,17 +285,49 @@ func prepareToRenderFile(ctx *context.Context, entry *git.TreeEntry) { } } - if ctx.Repo.CanEnableEditor(ctx, ctx.Doer) { - if lfsLock != nil && lfsLock.OwnerID != ctx.Doer.ID { - ctx.Data["CanDeleteFile"] = false - ctx.Data["DeleteFileTooltip"] = ctx.Tr("repo.editor.this_file_locked") - } else { - ctx.Data["CanDeleteFile"] = true - ctx.Data["DeleteFileTooltip"] = ctx.Tr("repo.editor.delete_this_file") - } - } else if !ctx.Repo.RefFullName.IsBranch() { + prepareToRenderButtons(ctx, fInfo.isLFSFile, isRepresentableAsText, lfsLock) +} + +func prepareToRenderButtons(ctx *context.Context, isLFSFile, isRepresentableAsText bool, lfsLock *git_model.LFSLock) { + // archived or mirror repository, the buttons should not be shown + if ctx.Repo.Repository.IsArchived || !ctx.Repo.Repository.CanEnableEditor() { + return + } + + // The buttons should not be shown if it's not a branch + if !ctx.Repo.RefFullName.IsBranch() { + ctx.Data["EditFileTooltip"] = ctx.Tr("repo.editor.must_be_on_a_branch") ctx.Data["DeleteFileTooltip"] = ctx.Tr("repo.editor.must_be_on_a_branch") - } else if !ctx.Repo.CanWriteToBranch(ctx, ctx.Doer, ctx.Repo.BranchName) { + return + } + + if isLFSFile { + ctx.Data["EditFileTooltip"] = ctx.Tr("repo.editor.cannot_edit_lfs_files") + } else if !isRepresentableAsText { + ctx.Data["EditFileTooltip"] = ctx.Tr("repo.editor.cannot_edit_non_text_files") + } + + if !ctx.Repo.CanWriteToBranch(ctx, ctx.Doer, ctx.Repo.BranchName) { + if !isLFSFile { // lfs file cannot be edited after fork + ctx.Data["EditFileTooltip"] = ctx.Tr("repo.editor.fork_before_edit") + } ctx.Data["DeleteFileTooltip"] = ctx.Tr("repo.editor.must_have_write_access") + return + } + + // it's a lfs file and the user is not the owner of the lock + if lfsLock != nil && lfsLock.OwnerID != ctx.Doer.ID { + ctx.Data["CanEditFile"] = false + ctx.Data["EditFileTooltip"] = ctx.Tr("repo.editor.this_file_locked") + ctx.Data["CanDeleteFile"] = false + ctx.Data["DeleteFileTooltip"] = ctx.Tr("repo.editor.this_file_locked") + return + } + + if !isLFSFile { // lfs file cannot be edited + ctx.Data["CanEditFile"] = true + ctx.Data["EditFileTooltip"] = ctx.Tr("repo.editor.edit_this_file") } + ctx.Data["CanDeleteFile"] = true + ctx.Data["DeleteFileTooltip"] = ctx.Tr("repo.editor.delete_this_file") } diff --git a/services/asymkey/commit.go b/services/asymkey/commit.go index 105782a93a..148f51fd10 100644 --- a/services/asymkey/commit.go +++ b/services/asymkey/commit.go @@ -6,6 +6,7 @@ package asymkey import ( "context" "fmt" + "slices" "strings" asymkey_model "code.gitea.io/gitea/models/asymkey" @@ -359,24 +360,39 @@ func VerifyWithGPGSettings(ctx context.Context, gpgSettings *git.GPGSettings, si return nil } +func verifySSHCommitVerificationByInstanceKey(c *git.Commit, committerUser, signerUser *user_model.User, committerGitEmail, publicKeyContent string) *asymkey_model.CommitVerification { + fingerprint, err := asymkey_model.CalcFingerprint(publicKeyContent) + if err != nil { + log.Error("Error calculating the fingerprint public key %q, err: %v", publicKeyContent, err) + return nil + } + sshPubKey := &asymkey_model.PublicKey{ + Verified: true, + Content: publicKeyContent, + Fingerprint: fingerprint, + HasUsed: true, + } + return verifySSHCommitVerification(c.Signature.Signature, c.Signature.Payload, sshPubKey, committerUser, signerUser, committerGitEmail) +} + // ParseCommitWithSSHSignature check if signature is good against keystore. -func ParseCommitWithSSHSignature(ctx context.Context, c *git.Commit, committer *user_model.User) *asymkey_model.CommitVerification { +func ParseCommitWithSSHSignature(ctx context.Context, c *git.Commit, committerUser *user_model.User) *asymkey_model.CommitVerification { // Now try to associate the signature with the committer, if present - if committer.ID != 0 { + if committerUser.ID != 0 { keys, err := db.Find[asymkey_model.PublicKey](ctx, asymkey_model.FindPublicKeyOptions{ - OwnerID: committer.ID, + OwnerID: committerUser.ID, NotKeytype: asymkey_model.KeyTypePrincipal, }) if err != nil { // Skipping failed to get ssh keys of user log.Error("ListPublicKeys: %v", err) return &asymkey_model.CommitVerification{ - CommittingUser: committer, + CommittingUser: committerUser, Verified: false, Reason: "gpg.error.failed_retrieval_gpg_keys", } } - committerEmailAddresses, err := cache.GetWithContextCache(ctx, cachegroup.UserEmailAddresses, committer.ID, user_model.GetEmailAddresses) + committerEmailAddresses, err := cache.GetWithContextCache(ctx, cachegroup.UserEmailAddresses, committerUser.ID, user_model.GetEmailAddresses) if err != nil { log.Error("GetEmailAddresses: %v", err) } @@ -391,7 +407,7 @@ func ParseCommitWithSSHSignature(ctx context.Context, c *git.Commit, committer * for _, k := range keys { if k.Verified && activated { - commitVerification := verifySSHCommitVerification(c.Signature.Signature, c.Signature.Payload, k, committer, committer, c.Committer.Email) + commitVerification := verifySSHCommitVerification(c.Signature.Signature, c.Signature.Payload, k, committerUser, committerUser, c.Committer.Email) if commitVerification != nil { return commitVerification } @@ -399,8 +415,45 @@ func ParseCommitWithSSHSignature(ctx context.Context, c *git.Commit, committer * } } + // Try the pre-set trusted keys (for key-rotation purpose) + // At the moment, we still use the SigningName&SigningEmail for the rotated keys. + // Maybe in the future we can extend the key format to "ssh-xxx .... old-user@example.com" to support different signer emails. + for _, k := range setting.Repository.Signing.TrustedSSHKeys { + signerUser := &user_model.User{ + Name: setting.Repository.Signing.SigningName, + Email: setting.Repository.Signing.SigningEmail, + } + commitVerification := verifySSHCommitVerificationByInstanceKey(c, committerUser, signerUser, c.Committer.Email, k) + if commitVerification != nil && commitVerification.Verified { + return commitVerification + } + } + + // Try the configured instance-wide SSH public key + if setting.Repository.Signing.SigningFormat == git.SigningKeyFormatSSH && !slices.Contains([]string{"", "default", "none"}, setting.Repository.Signing.SigningKey) { + gpgSettings := git.GPGSettings{ + Sign: true, + KeyID: setting.Repository.Signing.SigningKey, + Name: setting.Repository.Signing.SigningName, + Email: setting.Repository.Signing.SigningEmail, + Format: setting.Repository.Signing.SigningFormat, + } + signerUser := &user_model.User{ + Name: gpgSettings.Name, + Email: gpgSettings.Email, + } + if err := gpgSettings.LoadPublicKeyContent(); err != nil { + log.Error("Error getting instance-wide SSH signing key %q, err: %v", gpgSettings.KeyID, err) + } else { + commitVerification := verifySSHCommitVerificationByInstanceKey(c, committerUser, signerUser, gpgSettings.Email, gpgSettings.PublicKeyContent) + if commitVerification != nil && commitVerification.Verified { + return commitVerification + } + } + } + return &asymkey_model.CommitVerification{ - CommittingUser: committer, + CommittingUser: committerUser, Verified: false, Reason: asymkey_model.NoKeyFound, } diff --git a/services/asymkey/commit_test.go b/services/asymkey/commit_test.go new file mode 100644 index 0000000000..0438209a61 --- /dev/null +++ b/services/asymkey/commit_test.go @@ -0,0 +1,54 @@ +// Copyright 2025 The Gitea Authors. All rights reserved. +// SPDX-License-Identifier: MIT + +package asymkey + +import ( + "strings" + "testing" + + user_model "code.gitea.io/gitea/models/user" + "code.gitea.io/gitea/modules/git" + "code.gitea.io/gitea/modules/setting" + "code.gitea.io/gitea/modules/test" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func TestParseCommitWithSSHSignature(t *testing.T) { + // Here we only test the TrustedSSHKeys. The complete signing test is in tests/integration/gpg_ssh_git_test.go + t.Run("TrustedSSHKey", func(t *testing.T) { + defer test.MockVariableValue(&setting.Repository.Signing.SigningName, "gitea")() + defer test.MockVariableValue(&setting.Repository.Signing.SigningEmail, "gitea@fake.local")() + defer test.MockVariableValue(&setting.Repository.Signing.TrustedSSHKeys, []string{"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIH6Y4idVaW3E+bLw1uqoAfJD7o5Siu+HqS51E9oQLPE9"})() + + commit, err := git.CommitFromReader(nil, git.Sha1ObjectFormat.EmptyObjectID(), strings.NewReader(`tree 9a93ffa76e8b72bdb6431910b3a506fa2b39f42e +author User Two <user2@example.com> 1749230009 +0200 +committer User Two <user2@example.com> 1749230009 +0200 +gpgsig -----BEGIN SSH SIGNATURE----- + U1NIU0lHAAAAAQAAADMAAAALc3NoLWVkMjU1MTkAAAAgfpjiJ1VpbcT5svDW6qgB8kPujl + KK74epLnUT2hAs8T0AAAADZ2l0AAAAAAAAAAZzaGE1MTIAAABTAAAAC3NzaC1lZDI1NTE5 + AAAAQDX2t2iHuuLxEWHLJetYXKsgayv3c43r0pJNfAzdLN55Q65pC5M7rG6++gT2bxcpOu + Y6EXbpLqia9sunEF3+LQY= + -----END SSH SIGNATURE----- + +Initial commit with signed file +`)) + require.NoError(t, err) + committingUser := &user_model.User{ + ID: 2, + Name: "User Two", + Email: "user2@example.com", + } + ret := ParseCommitWithSSHSignature(t.Context(), commit, committingUser) + require.NotNil(t, ret) + assert.True(t, ret.Verified) + assert.False(t, ret.Warning) + assert.Equal(t, committingUser, ret.CommittingUser) + if assert.NotNil(t, ret.SigningUser) { + assert.Equal(t, "gitea", ret.SigningUser.Name) + assert.Equal(t, "gitea@fake.local", ret.SigningUser.Email) + } + }) +} diff --git a/services/asymkey/sign.go b/services/asymkey/sign.go index 2216bca54a..f94462ea46 100644 --- a/services/asymkey/sign.go +++ b/services/asymkey/sign.go @@ -6,6 +6,7 @@ package asymkey import ( "context" "fmt" + "os" "strings" asymkey_model "code.gitea.io/gitea/models/asymkey" @@ -85,9 +86,9 @@ func IsErrWontSign(err error) bool { } // SigningKey returns the KeyID and git Signature for the repo -func SigningKey(ctx context.Context, repoPath string) (string, *git.Signature) { +func SigningKey(ctx context.Context, repoPath string) (*git.SigningKey, *git.Signature) { if setting.Repository.Signing.SigningKey == "none" { - return "", nil + return nil, nil } if setting.Repository.Signing.SigningKey == "default" || setting.Repository.Signing.SigningKey == "" { @@ -95,53 +96,77 @@ func SigningKey(ctx context.Context, repoPath string) (string, *git.Signature) { value, _, _ := git.NewCommand("config", "--get", "commit.gpgsign").RunStdString(ctx, &git.RunOpts{Dir: repoPath}) sign, valid := git.ParseBool(strings.TrimSpace(value)) if !sign || !valid { - return "", nil + return nil, nil } + format, _, _ := git.NewCommand("config", "--default", git.SigningKeyFormatOpenPGP, "--get", "gpg.format").RunStdString(ctx, &git.RunOpts{Dir: repoPath}) signingKey, _, _ := git.NewCommand("config", "--get", "user.signingkey").RunStdString(ctx, &git.RunOpts{Dir: repoPath}) signingName, _, _ := git.NewCommand("config", "--get", "user.name").RunStdString(ctx, &git.RunOpts{Dir: repoPath}) signingEmail, _, _ := git.NewCommand("config", "--get", "user.email").RunStdString(ctx, &git.RunOpts{Dir: repoPath}) - return strings.TrimSpace(signingKey), &git.Signature{ - Name: strings.TrimSpace(signingName), - Email: strings.TrimSpace(signingEmail), + + if strings.TrimSpace(signingKey) == "" { + return nil, nil } + + return &git.SigningKey{ + KeyID: strings.TrimSpace(signingKey), + Format: strings.TrimSpace(format), + }, &git.Signature{ + Name: strings.TrimSpace(signingName), + Email: strings.TrimSpace(signingEmail), + } } - return setting.Repository.Signing.SigningKey, &git.Signature{ - Name: setting.Repository.Signing.SigningName, - Email: setting.Repository.Signing.SigningEmail, + if setting.Repository.Signing.SigningKey == "" { + return nil, nil } + + return &git.SigningKey{ + KeyID: setting.Repository.Signing.SigningKey, + Format: setting.Repository.Signing.SigningFormat, + }, &git.Signature{ + Name: setting.Repository.Signing.SigningName, + Email: setting.Repository.Signing.SigningEmail, + } } // PublicSigningKey gets the public signing key within a provided repository directory -func PublicSigningKey(ctx context.Context, repoPath string) (string, error) { +func PublicSigningKey(ctx context.Context, repoPath string) (content, format string, err error) { signingKey, _ := SigningKey(ctx, repoPath) - if signingKey == "" { - return "", nil + if signingKey == nil { + return "", "", nil + } + if signingKey.Format == git.SigningKeyFormatSSH { + content, err := os.ReadFile(signingKey.KeyID) + if err != nil { + log.Error("Unable to read SSH public key file in %s: %s, %v", repoPath, signingKey, err) + return "", signingKey.Format, err + } + return string(content), signingKey.Format, nil } content, stderr, err := process.GetManager().ExecDir(ctx, -1, repoPath, - "gpg --export -a", "gpg", "--export", "-a", signingKey) + "gpg --export -a", "gpg", "--export", "-a", signingKey.KeyID) if err != nil { log.Error("Unable to get default signing key in %s: %s, %s, %v", repoPath, signingKey, stderr, err) - return "", err + return "", signingKey.Format, err } - return content, nil + return content, signingKey.Format, nil } // SignInitialCommit determines if we should sign the initial commit to this repository -func SignInitialCommit(ctx context.Context, repoPath string, u *user_model.User) (bool, string, *git.Signature, error) { +func SignInitialCommit(ctx context.Context, repoPath string, u *user_model.User) (bool, *git.SigningKey, *git.Signature, error) { rules := signingModeFromStrings(setting.Repository.Signing.InitialCommit) signingKey, sig := SigningKey(ctx, repoPath) - if signingKey == "" { - return false, "", nil, &ErrWontSign{noKey} + if signingKey == nil { + return false, nil, nil, &ErrWontSign{noKey} } Loop: for _, rule := range rules { switch rule { case never: - return false, "", nil, &ErrWontSign{never} + return false, nil, nil, &ErrWontSign{never} case always: break Loop case pubkey: @@ -150,18 +175,18 @@ Loop: IncludeSubKeys: true, }) if err != nil { - return false, "", nil, err + return false, nil, nil, err } if len(keys) == 0 { - return false, "", nil, &ErrWontSign{pubkey} + return false, nil, nil, &ErrWontSign{pubkey} } case twofa: twofaModel, err := auth.GetTwoFactorByUID(ctx, u.ID) if err != nil && !auth.IsErrTwoFactorNotEnrolled(err) { - return false, "", nil, err + return false, nil, nil, err } if twofaModel == nil { - return false, "", nil, &ErrWontSign{twofa} + return false, nil, nil, &ErrWontSign{twofa} } } } @@ -169,19 +194,19 @@ Loop: } // SignWikiCommit determines if we should sign the commits to this repository wiki -func SignWikiCommit(ctx context.Context, repo *repo_model.Repository, u *user_model.User) (bool, string, *git.Signature, error) { +func SignWikiCommit(ctx context.Context, repo *repo_model.Repository, u *user_model.User) (bool, *git.SigningKey, *git.Signature, error) { repoWikiPath := repo.WikiPath() rules := signingModeFromStrings(setting.Repository.Signing.Wiki) signingKey, sig := SigningKey(ctx, repoWikiPath) - if signingKey == "" { - return false, "", nil, &ErrWontSign{noKey} + if signingKey == nil { + return false, nil, nil, &ErrWontSign{noKey} } Loop: for _, rule := range rules { switch rule { case never: - return false, "", nil, &ErrWontSign{never} + return false, nil, nil, &ErrWontSign{never} case always: break Loop case pubkey: @@ -190,35 +215,35 @@ Loop: IncludeSubKeys: true, }) if err != nil { - return false, "", nil, err + return false, nil, nil, err } if len(keys) == 0 { - return false, "", nil, &ErrWontSign{pubkey} + return false, nil, nil, &ErrWontSign{pubkey} } case twofa: twofaModel, err := auth.GetTwoFactorByUID(ctx, u.ID) if err != nil && !auth.IsErrTwoFactorNotEnrolled(err) { - return false, "", nil, err + return false, nil, nil, err } if twofaModel == nil { - return false, "", nil, &ErrWontSign{twofa} + return false, nil, nil, &ErrWontSign{twofa} } case parentSigned: gitRepo, err := gitrepo.OpenRepository(ctx, repo.WikiStorageRepo()) if err != nil { - return false, "", nil, err + return false, nil, nil, err } defer gitRepo.Close() commit, err := gitRepo.GetCommit("HEAD") if err != nil { - return false, "", nil, err + return false, nil, nil, err } if commit.Signature == nil { - return false, "", nil, &ErrWontSign{parentSigned} + return false, nil, nil, &ErrWontSign{parentSigned} } verification := ParseCommitWithSignature(ctx, commit) if !verification.Verified { - return false, "", nil, &ErrWontSign{parentSigned} + return false, nil, nil, &ErrWontSign{parentSigned} } } } @@ -226,18 +251,18 @@ Loop: } // SignCRUDAction determines if we should sign a CRUD commit to this repository -func SignCRUDAction(ctx context.Context, repoPath string, u *user_model.User, tmpBasePath, parentCommit string) (bool, string, *git.Signature, error) { +func SignCRUDAction(ctx context.Context, repoPath string, u *user_model.User, tmpBasePath, parentCommit string) (bool, *git.SigningKey, *git.Signature, error) { rules := signingModeFromStrings(setting.Repository.Signing.CRUDActions) signingKey, sig := SigningKey(ctx, repoPath) - if signingKey == "" { - return false, "", nil, &ErrWontSign{noKey} + if signingKey == nil { + return false, nil, nil, &ErrWontSign{noKey} } Loop: for _, rule := range rules { switch rule { case never: - return false, "", nil, &ErrWontSign{never} + return false, nil, nil, &ErrWontSign{never} case always: break Loop case pubkey: @@ -246,35 +271,35 @@ Loop: IncludeSubKeys: true, }) if err != nil { - return false, "", nil, err + return false, nil, nil, err } if len(keys) == 0 { - return false, "", nil, &ErrWontSign{pubkey} + return false, nil, nil, &ErrWontSign{pubkey} } case twofa: twofaModel, err := auth.GetTwoFactorByUID(ctx, u.ID) if err != nil && !auth.IsErrTwoFactorNotEnrolled(err) { - return false, "", nil, err + return false, nil, nil, err } if twofaModel == nil { - return false, "", nil, &ErrWontSign{twofa} + return false, nil, nil, &ErrWontSign{twofa} } case parentSigned: gitRepo, err := git.OpenRepository(ctx, tmpBasePath) if err != nil { - return false, "", nil, err + return false, nil, nil, err } defer gitRepo.Close() commit, err := gitRepo.GetCommit(parentCommit) if err != nil { - return false, "", nil, err + return false, nil, nil, err } if commit.Signature == nil { - return false, "", nil, &ErrWontSign{parentSigned} + return false, nil, nil, &ErrWontSign{parentSigned} } verification := ParseCommitWithSignature(ctx, commit) if !verification.Verified { - return false, "", nil, &ErrWontSign{parentSigned} + return false, nil, nil, &ErrWontSign{parentSigned} } } } @@ -282,16 +307,16 @@ Loop: } // SignMerge determines if we should sign a PR merge commit to the base repository -func SignMerge(ctx context.Context, pr *issues_model.PullRequest, u *user_model.User, tmpBasePath, baseCommit, headCommit string) (bool, string, *git.Signature, error) { +func SignMerge(ctx context.Context, pr *issues_model.PullRequest, u *user_model.User, tmpBasePath, baseCommit, headCommit string) (bool, *git.SigningKey, *git.Signature, error) { if err := pr.LoadBaseRepo(ctx); err != nil { log.Error("Unable to get Base Repo for pull request") - return false, "", nil, err + return false, nil, nil, err } repo := pr.BaseRepo signingKey, signer := SigningKey(ctx, repo.RepoPath()) - if signingKey == "" { - return false, "", nil, &ErrWontSign{noKey} + if signingKey == nil { + return false, nil, nil, &ErrWontSign{noKey} } rules := signingModeFromStrings(setting.Repository.Signing.Merges) @@ -302,7 +327,7 @@ Loop: for _, rule := range rules { switch rule { case never: - return false, "", nil, &ErrWontSign{never} + return false, nil, nil, &ErrWontSign{never} case always: break Loop case pubkey: @@ -311,91 +336,91 @@ Loop: IncludeSubKeys: true, }) if err != nil { - return false, "", nil, err + return false, nil, nil, err } if len(keys) == 0 { - return false, "", nil, &ErrWontSign{pubkey} + return false, nil, nil, &ErrWontSign{pubkey} } case twofa: twofaModel, err := auth.GetTwoFactorByUID(ctx, u.ID) if err != nil && !auth.IsErrTwoFactorNotEnrolled(err) { - return false, "", nil, err + return false, nil, nil, err } if twofaModel == nil { - return false, "", nil, &ErrWontSign{twofa} + return false, nil, nil, &ErrWontSign{twofa} } case approved: protectedBranch, err := git_model.GetFirstMatchProtectedBranchRule(ctx, repo.ID, pr.BaseBranch) if err != nil { - return false, "", nil, err + return false, nil, nil, err } if protectedBranch == nil { - return false, "", nil, &ErrWontSign{approved} + return false, nil, nil, &ErrWontSign{approved} } if issues_model.GetGrantedApprovalsCount(ctx, protectedBranch, pr) < 1 { - return false, "", nil, &ErrWontSign{approved} + return false, nil, nil, &ErrWontSign{approved} } case baseSigned: if gitRepo == nil { gitRepo, err = git.OpenRepository(ctx, tmpBasePath) if err != nil { - return false, "", nil, err + return false, nil, nil, err } defer gitRepo.Close() } commit, err := gitRepo.GetCommit(baseCommit) if err != nil { - return false, "", nil, err + return false, nil, nil, err } verification := ParseCommitWithSignature(ctx, commit) if !verification.Verified { - return false, "", nil, &ErrWontSign{baseSigned} + return false, nil, nil, &ErrWontSign{baseSigned} } case headSigned: if gitRepo == nil { gitRepo, err = git.OpenRepository(ctx, tmpBasePath) if err != nil { - return false, "", nil, err + return false, nil, nil, err } defer gitRepo.Close() } commit, err := gitRepo.GetCommit(headCommit) if err != nil { - return false, "", nil, err + return false, nil, nil, err } verification := ParseCommitWithSignature(ctx, commit) if !verification.Verified { - return false, "", nil, &ErrWontSign{headSigned} + return false, nil, nil, &ErrWontSign{headSigned} } case commitsSigned: if gitRepo == nil { gitRepo, err = git.OpenRepository(ctx, tmpBasePath) if err != nil { - return false, "", nil, err + return false, nil, nil, err } defer gitRepo.Close() } commit, err := gitRepo.GetCommit(headCommit) if err != nil { - return false, "", nil, err + return false, nil, nil, err } verification := ParseCommitWithSignature(ctx, commit) if !verification.Verified { - return false, "", nil, &ErrWontSign{commitsSigned} + return false, nil, nil, &ErrWontSign{commitsSigned} } // need to work out merge-base mergeBaseCommit, _, err := gitRepo.GetMergeBase("", baseCommit, headCommit) if err != nil { - return false, "", nil, err + return false, nil, nil, err } commitList, err := commit.CommitsBeforeUntil(mergeBaseCommit) if err != nil { - return false, "", nil, err + return false, nil, nil, err } for _, commit := range commitList { verification := ParseCommitWithSignature(ctx, commit) if !verification.Verified { - return false, "", nil, &ErrWontSign{commitsSigned} + return false, nil, nil, &ErrWontSign{commitsSigned} } } } diff --git a/services/context/repo.go b/services/context/repo.go index 61841aa90b..32d54c88ff 100644 --- a/services/context/repo.go +++ b/services/context/repo.go @@ -101,7 +101,7 @@ type CanCommitToBranchResults struct { UserCanPush bool RequireSigned bool WillSign bool - SigningKey string + SigningKey *git.SigningKey WontSignReason string } @@ -123,7 +123,8 @@ func (r *Repository) CanCommitToBranch(ctx context.Context, doer *user_model.Use sign, keyID, _, err := asymkey_service.SignCRUDAction(ctx, r.Repository.RepoPath(), doer, r.Repository.RepoPath(), git.BranchPrefix+r.BranchName) - canCommit := r.CanEnableEditor(ctx, doer) && userCanPush + canEnableEditor := r.CanEnableEditor(ctx, doer) + canCommit := canEnableEditor && userCanPush if requireSigned { canCommit = canCommit && sign } @@ -139,7 +140,7 @@ func (r *Repository) CanCommitToBranch(ctx context.Context, doer *user_model.Use return CanCommitToBranchResults{ CanCommitToBranch: canCommit, - EditorEnabled: r.CanEnableEditor(ctx, doer), + EditorEnabled: canEnableEditor, UserCanPush: userCanPush, RequireSigned: requireSigned, WillSign: sign, diff --git a/services/convert/pull.go b/services/convert/pull.go index 7798bebb08..8f9679f649 100644 --- a/services/convert/pull.go +++ b/services/convert/pull.go @@ -419,6 +419,9 @@ func ToAPIPullRequests(ctx context.Context, baseRepo *repo_model.Repository, prs if baseBranch != nil { apiPullRequest.Base.Sha = baseBranch.CommitID } + if pr.HeadRepoID == pr.BaseRepoID { + apiPullRequest.Head.Repository = apiPullRequest.Base.Repository + } // pull request head branch, both repository and branch could not exist if pr.HeadRepo != nil { @@ -431,22 +434,19 @@ func ToAPIPullRequests(ctx context.Context, baseRepo *repo_model.Repository, prs if exist { apiPullRequest.Head.Ref = pr.HeadBranch } + if pr.HeadRepoID != pr.BaseRepoID { + p, err := access_model.GetUserRepoPermission(ctx, pr.HeadRepo, doer) + if err != nil { + log.Error("GetUserRepoPermission[%d]: %v", pr.HeadRepoID, err) + p.AccessMode = perm.AccessModeNone + } + apiPullRequest.Head.Repository = ToRepo(ctx, pr.HeadRepo, p) + } } if apiPullRequest.Head.Ref == "" { apiPullRequest.Head.Ref = pr.GetGitRefName() } - if pr.HeadRepoID == pr.BaseRepoID { - apiPullRequest.Head.Repository = apiPullRequest.Base.Repository - } else { - p, err := access_model.GetUserRepoPermission(ctx, pr.HeadRepo, doer) - if err != nil { - log.Error("GetUserRepoPermission[%d]: %v", pr.HeadRepoID, err) - p.AccessMode = perm.AccessModeNone - } - apiPullRequest.Head.Repository = ToRepo(ctx, pr.HeadRepo, p) - } - if pr.Flow == issues_model.PullRequestFlowAGit { apiPullRequest.Head.Name = "" } diff --git a/services/convert/pull_test.go b/services/convert/pull_test.go index cd86283c8a..dfbe24d184 100644 --- a/services/convert/pull_test.go +++ b/services/convert/pull_test.go @@ -46,4 +46,11 @@ func TestPullRequest_APIFormat(t *testing.T) { assert.NotNil(t, apiPullRequest) assert.Nil(t, apiPullRequest.Head.Repository) assert.EqualValues(t, -1, apiPullRequest.Head.RepoID) + + apiPullRequests, err := ToAPIPullRequests(git.DefaultContext, pr.BaseRepo, []*issues_model.PullRequest{pr}, nil) + assert.NoError(t, err) + assert.Len(t, apiPullRequests, 1) + assert.NotNil(t, apiPullRequests[0]) + assert.Nil(t, apiPullRequests[0].Head.Repository) + assert.EqualValues(t, -1, apiPullRequests[0].Head.RepoID) } diff --git a/services/pull/merge.go b/services/pull/merge.go index 829d4b7ee1..2a2f47e880 100644 --- a/services/pull/merge.go +++ b/services/pull/merge.go @@ -432,10 +432,13 @@ func doMergeAndPush(ctx context.Context, pr *issues_model.PullRequest, doer *use func commitAndSignNoAuthor(ctx *mergeContext, message string) error { cmdCommit := git.NewCommand("commit").AddOptionFormat("--message=%s", message) - if ctx.signKeyID == "" { + if ctx.signKey == nil { cmdCommit.AddArguments("--no-gpg-sign") } else { - cmdCommit.AddOptionFormat("-S%s", ctx.signKeyID) + if ctx.signKey.Format != "" { + cmdCommit.AddConfig("gpg.format", ctx.signKey.Format) + } + cmdCommit.AddOptionFormat("-S%s", ctx.signKey.KeyID) } if err := cmdCommit.Run(ctx, ctx.RunOpts()); err != nil { log.Error("git commit %-v: %v\n%s\n%s", ctx.pr, err, ctx.outbuf.String(), ctx.errbuf.String()) diff --git a/services/pull/merge_prepare.go b/services/pull/merge_prepare.go index 719cc6b965..31a1e13734 100644 --- a/services/pull/merge_prepare.go +++ b/services/pull/merge_prepare.go @@ -27,7 +27,7 @@ type mergeContext struct { doer *user_model.User sig *git.Signature committer *git.Signature - signKeyID string // empty for no-sign, non-empty to sign + signKey *git.SigningKey env []string } @@ -99,9 +99,9 @@ func createTemporaryRepoForMerge(ctx context.Context, pr *issues_model.PullReque mergeCtx.committer = mergeCtx.sig // Determine if we should sign - sign, keyID, signer, _ := asymkey_service.SignMerge(ctx, mergeCtx.pr, mergeCtx.doer, mergeCtx.tmpBasePath, "HEAD", trackingBranch) + sign, key, signer, _ := asymkey_service.SignMerge(ctx, mergeCtx.pr, mergeCtx.doer, mergeCtx.tmpBasePath, "HEAD", trackingBranch) if sign { - mergeCtx.signKeyID = keyID + mergeCtx.signKey = key if pr.BaseRepo.GetTrustModel() == repo_model.CommitterTrustModel || pr.BaseRepo.GetTrustModel() == repo_model.CollaboratorCommitterTrustModel { mergeCtx.committer = signer } diff --git a/services/pull/merge_squash.go b/services/pull/merge_squash.go index 119b28736c..0049c0b117 100644 --- a/services/pull/merge_squash.go +++ b/services/pull/merge_squash.go @@ -71,10 +71,13 @@ func doMergeStyleSquash(ctx *mergeContext, message string) error { cmdCommit := git.NewCommand("commit"). AddOptionFormat("--author='%s <%s>'", sig.Name, sig.Email). AddOptionFormat("--message=%s", message) - if ctx.signKeyID == "" { + if ctx.signKey == nil { cmdCommit.AddArguments("--no-gpg-sign") } else { - cmdCommit.AddOptionFormat("-S%s", ctx.signKeyID) + if ctx.signKey.Format != "" { + cmdCommit.AddConfig("gpg.format", ctx.signKey.Format) + } + cmdCommit.AddOptionFormat("-S%s", ctx.signKey.KeyID) } if err := cmdCommit.Run(ctx, ctx.RunOpts()); err != nil { log.Error("git commit %-v: %v\n%s\n%s", ctx.pr, err, ctx.outbuf.String(), ctx.errbuf.String()) diff --git a/services/repository/files/temp_repo.go b/services/repository/files/temp_repo.go index 493ff9998d..1cf30edc7b 100644 --- a/services/repository/files/temp_repo.go +++ b/services/repository/files/temp_repo.go @@ -293,15 +293,18 @@ func (t *TemporaryUploadRepository) CommitTree(ctx context.Context, opts *Commit } var sign bool - var keyID string + var key *git.SigningKey var signer *git.Signature if opts.ParentCommitID != "" { - sign, keyID, signer, _ = asymkey_service.SignCRUDAction(ctx, t.repo.RepoPath(), opts.DoerUser, t.basePath, opts.ParentCommitID) + sign, key, signer, _ = asymkey_service.SignCRUDAction(ctx, t.repo.RepoPath(), opts.DoerUser, t.basePath, opts.ParentCommitID) } else { - sign, keyID, signer, _ = asymkey_service.SignInitialCommit(ctx, t.repo.RepoPath(), opts.DoerUser) + sign, key, signer, _ = asymkey_service.SignInitialCommit(ctx, t.repo.RepoPath(), opts.DoerUser) } if sign { - cmdCommitTree.AddOptionFormat("-S%s", keyID) + if key.Format != "" { + cmdCommitTree.AddConfig("gpg.format", key.Format) + } + cmdCommitTree.AddOptionFormat("-S%s", key.KeyID) if t.repo.GetTrustModel() == repo_model.CommitterTrustModel || t.repo.GetTrustModel() == repo_model.CollaboratorCommitterTrustModel { if committerSig.Name != authorSig.Name || committerSig.Email != authorSig.Email { // Add trailers diff --git a/services/repository/init.go b/services/repository/init.go index bd777b8a2f..1eeeb4aa4f 100644 --- a/services/repository/init.go +++ b/services/repository/init.go @@ -42,9 +42,12 @@ func initRepoCommit(ctx context.Context, tmpPath string, repo *repo_model.Reposi cmd := git.NewCommand("commit", "--message=Initial commit"). AddOptionFormat("--author='%s <%s>'", sig.Name, sig.Email) - sign, keyID, signer, _ := asymkey_service.SignInitialCommit(ctx, tmpPath, u) + sign, key, signer, _ := asymkey_service.SignInitialCommit(ctx, tmpPath, u) if sign { - cmd.AddOptionFormat("-S%s", keyID) + if key.Format != "" { + cmd.AddConfig("gpg.format", key.Format) + } + cmd.AddOptionFormat("-S%s", key.KeyID) if repo.GetTrustModel() == repo_model.CommitterTrustModel || repo.GetTrustModel() == repo_model.CollaboratorCommitterTrustModel { // need to set the committer to the KeyID owner diff --git a/services/wiki/wiki.go b/services/wiki/wiki.go index 9405f7cfc8..0a955406e2 100644 --- a/services/wiki/wiki.go +++ b/services/wiki/wiki.go @@ -194,7 +194,7 @@ func updateWikiPage(ctx context.Context, doer *user_model.User, repo *repo_model sign, signingKey, signer, _ := asymkey_service.SignWikiCommit(ctx, repo, doer) if sign { - commitTreeOpts.KeyID = signingKey + commitTreeOpts.Key = signingKey if repo.GetTrustModel() == repo_model.CommitterTrustModel || repo.GetTrustModel() == repo_model.CollaboratorCommitterTrustModel { committer = signer } @@ -316,7 +316,7 @@ func DeleteWikiPage(ctx context.Context, doer *user_model.User, repo *repo_model sign, signingKey, signer, _ := asymkey_service.SignWikiCommit(ctx, repo, doer) if sign { - commitTreeOpts.KeyID = signingKey + commitTreeOpts.Key = signingKey if repo.GetTrustModel() == repo_model.CommitterTrustModel || repo.GetTrustModel() == repo_model.CollaboratorCommitterTrustModel { committer = signer } diff --git a/templates/repo/actions/workflow_dispatch_inputs.tmpl b/templates/repo/actions/workflow_dispatch_inputs.tmpl index 8b8292af1d..37538a318f 100644 --- a/templates/repo/actions/workflow_dispatch_inputs.tmpl +++ b/templates/repo/actions/workflow_dispatch_inputs.tmpl @@ -33,7 +33,8 @@ </div> {{end}} <div class="ui field"> - <button class="ui tiny primary button" type="submit">{{ctx.Locale.Tr "actions.workflow.run"}}</button> + {{/* use autofocus here to prevent the "branch selection" dropdown from getting focus, otherwise it will auto popup */}} + <button class="ui tiny primary button" autofocus type="submit">{{ctx.Locale.Tr "actions.workflow.run"}}</button> </div> {{end}} {{range .workflows}} diff --git a/templates/swagger/v1_json.tmpl b/templates/swagger/v1_json.tmpl index 68b09c484b..cc9abd92bd 100644 --- a/templates/swagger/v1_json.tmpl +++ b/templates/swagger/v1_json.tmpl @@ -15164,6 +15164,42 @@ } } }, + "/repos/{owner}/{repo}/signing-key.pub": { + "get": { + "produces": [ + "text/plain" + ], + "tags": [ + "repository" + ], + "summary": "Get signing-key.pub for given repository", + "operationId": "repoSigningKeySSH", + "parameters": [ + { + "type": "string", + "description": "owner of the repo", + "name": "owner", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "name of the repo", + "name": "repo", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "ssh public key", + "schema": { + "type": "string" + } + } + } + } + }, "/repos/{owner}/{repo}/stargazers": { "get": { "produces": [ @@ -16997,6 +17033,26 @@ } } }, + "/signing-key.pub": { + "get": { + "produces": [ + "text/plain" + ], + "tags": [ + "miscellaneous" + ], + "summary": "Get default signing-key.pub", + "operationId": "getSigningKeySSH", + "responses": { + "200": { + "description": "ssh public key", + "schema": { + "type": "string" + } + } + } + } + }, "/teams/{id}": { "get": { "produces": [ diff --git a/tests/integration/gpg_git_test.go b/tests/integration/gpg_ssh_git_test.go index 32de200f63..56f9f87783 100644 --- a/tests/integration/gpg_git_test.go +++ b/tests/integration/gpg_ssh_git_test.go @@ -4,7 +4,10 @@ package integration import ( + "crypto/ed25519" + "crypto/rand" "encoding/base64" + "encoding/pem" "fmt" "net/url" "os" @@ -23,6 +26,7 @@ import ( "github.com/ProtonMail/go-crypto/openpgp/armor" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "golang.org/x/crypto/ssh" ) func TestGPGGit(t *testing.T) { @@ -42,6 +46,37 @@ func TestGPGGit(t *testing.T) { defer test.MockVariableValue(&setting.Repository.Signing.InitialCommit, []string{"never"})() defer test.MockVariableValue(&setting.Repository.Signing.CRUDActions, []string{"never"})() + testGitSigning(t) +} + +func TestSSHGit(t *testing.T) { + tmpDir := t.TempDir() // use a temp dir to store the SSH keys + err := os.Chmod(tmpDir, 0o700) + assert.NoError(t, err) + + pub, priv, err := ed25519.GenerateKey(rand.Reader) + require.NoError(t, err, "ed25519.GenerateKey") + sshPubKey, err := ssh.NewPublicKey(pub) + require.NoError(t, err, "ssh.NewPublicKey") + + err = os.WriteFile(tmpDir+"/id_ed25519.pub", ssh.MarshalAuthorizedKey(sshPubKey), 0o600) + require.NoError(t, err, "os.WriteFile id_ed25519.pub") + block, err := ssh.MarshalPrivateKey(priv, "") + require.NoError(t, err, "ssh.MarshalPrivateKey") + err = os.WriteFile(tmpDir+"/id_ed25519", pem.EncodeToMemory(block), 0o600) + require.NoError(t, err, "os.WriteFile id_ed25519") + + defer test.MockVariableValue(&setting.Repository.Signing.SigningKey, tmpDir+"/id_ed25519.pub")() + defer test.MockVariableValue(&setting.Repository.Signing.SigningName, "gitea")() + defer test.MockVariableValue(&setting.Repository.Signing.SigningEmail, "gitea@fake.local")() + defer test.MockVariableValue(&setting.Repository.Signing.SigningFormat, "ssh")() + defer test.MockVariableValue(&setting.Repository.Signing.InitialCommit, []string{"never"})() + defer test.MockVariableValue(&setting.Repository.Signing.CRUDActions, []string{"never"})() + + testGitSigning(t) +} + +func testGitSigning(t *testing.T) { username := "user2" user := unittest.AssertExistsAndLoadBean(t, &user_model.User{Name: username}) baseAPITestContext := NewAPITestContext(t, username, "repo1") diff --git a/web_src/css/markup/content.css b/web_src/css/markup/content.css index b983855630..8f92a51749 100644 --- a/web_src/css/markup/content.css +++ b/web_src/css/markup/content.css @@ -2,7 +2,7 @@ overflow: hidden; font-size: 16px; line-height: 1.5 !important; - overflow-wrap: anywhere; + overflow-wrap: break-word; } .markup > *:first-child { diff --git a/web_src/css/repo/home.css b/web_src/css/repo/home.css index 61b0a1f962..ee371f1b1c 100644 --- a/web_src/css/repo/home.css +++ b/web_src/css/repo/home.css @@ -67,6 +67,7 @@ .repo-view-content { flex: 1; + min-width: 0; } .language-stats { diff --git a/web_src/css/repo/issue-card.css b/web_src/css/repo/issue-card.css index fb832bd05a..27f3c2d554 100644 --- a/web_src/css/repo/issue-card.css +++ b/web_src/css/repo/issue-card.css @@ -7,6 +7,7 @@ padding: 8px 10px; border: 1px solid var(--color-secondary); background: var(--color-card); + color: var(--color-text); /* it can't inherit from parent because the card already has its own background */ } .issue-card-icon, diff --git a/web_src/fomantic/build/components/dropdown.js b/web_src/fomantic/build/components/dropdown.js index 9d0e07b33b..85530c7991 100644 --- a/web_src/fomantic/build/components/dropdown.js +++ b/web_src/fomantic/build/components/dropdown.js @@ -525,6 +525,7 @@ $.fn.dropdown = function(parameters) { return true; } if(settings.onShow.call(element) !== false) { + settings.onAfterFiltered.call(element); // GITEA-PATCH: callback to correctly handle the filtered items module.animate.show(function() { if( module.can.click() ) { module.bind.intent(); diff --git a/web_src/js/components/DashboardRepoList.vue b/web_src/js/components/DashboardRepoList.vue index 6b16ff9efb..6573633227 100644 --- a/web_src/js/components/DashboardRepoList.vue +++ b/web_src/js/components/DashboardRepoList.vue @@ -429,7 +429,7 @@ export default defineComponent({ <svg-icon name="octicon-archive" :size="16"/> </div> </a> - <a class="tw-flex tw-items-center" v-if="repo.latest_commit_status_state" :href="repo.latest_commit_status_state_link" :data-tooltip-content="repo.locale_latest_commit_status_state"> + <a class="tw-flex tw-items-center" v-if="repo.latest_commit_status_state" :href="repo.latest_commit_status_state_link || null" :data-tooltip-content="repo.locale_latest_commit_status_state"> <!-- the commit status icon logic is taken from templates/repo/commit_status.tmpl --> <svg-icon :name="statusIcon(repo.latest_commit_status_state)" :class="'tw-ml-2 commit-status icon text ' + statusColor(repo.latest_commit_status_state)" :size="16"/> </a> diff --git a/web_src/js/features/common-fetch-action.ts b/web_src/js/features/common-fetch-action.ts index 2da481e521..a4a69540a8 100644 --- a/web_src/js/features/common-fetch-action.ts +++ b/web_src/js/features/common-fetch-action.ts @@ -56,8 +56,12 @@ async function fetchActionDoRequest(actionElem: HTMLElement, url: string, opt: R actionElem.classList.remove('is-loading', 'loading-icon-2px'); } -async function formFetchAction(formEl: HTMLFormElement, e: SubmitEvent) { +async function onFormFetchActionSubmit(formEl: HTMLFormElement, e: SubmitEvent) { e.preventDefault(); + await submitFormFetchAction(formEl, submitEventSubmitter(e)); +} + +export async function submitFormFetchAction(formEl: HTMLFormElement, formSubmitter?: HTMLElement) { if (formEl.classList.contains('is-loading')) return; formEl.classList.add('is-loading'); @@ -68,7 +72,6 @@ async function formFetchAction(formEl: HTMLFormElement, e: SubmitEvent) { const formMethod = formEl.getAttribute('method') || 'get'; const formActionUrl = formEl.getAttribute('action'); const formData = new FormData(formEl); - const formSubmitter = submitEventSubmitter(e); const [submitterName, submitterValue] = [formSubmitter?.getAttribute('name'), formSubmitter?.getAttribute('value')]; if (submitterName) { formData.append(submitterName, submitterValue || ''); @@ -96,7 +99,7 @@ async function formFetchAction(formEl: HTMLFormElement, e: SubmitEvent) { await fetchActionDoRequest(formEl, reqUrl, reqOpt); } -async function linkAction(el: HTMLElement, e: Event) { +async function onLinkActionClick(el: HTMLElement, e: Event) { // A "link-action" can post AJAX request to its "data-url" // Then the browser is redirected to: the "redirect" in response, or "data-redirect" attribute, or current URL by reloading. // If the "link-action" has "data-modal-confirm" attribute, a confirm modal dialog will be shown before taking action. @@ -126,6 +129,6 @@ async function linkAction(el: HTMLElement, e: Event) { } export function initGlobalFetchAction() { - addDelegatedEventListener(document, 'submit', '.form-fetch-action', formFetchAction); - addDelegatedEventListener(document, 'click', '.link-action', linkAction); + addDelegatedEventListener(document, 'submit', '.form-fetch-action', onFormFetchActionSubmit); + addDelegatedEventListener(document, 'click', '.link-action', onLinkActionClick); } diff --git a/web_src/js/features/comp/LabelEdit.ts b/web_src/js/features/comp/LabelEdit.ts index a5bb750cdb..141c5eecfe 100644 --- a/web_src/js/features/comp/LabelEdit.ts +++ b/web_src/js/features/comp/LabelEdit.ts @@ -1,5 +1,6 @@ import {toggleElem} from '../../utils/dom.ts'; import {fomanticQuery} from '../../modules/fomantic/base.ts'; +import {submitFormFetchAction} from '../common-fetch-action.ts'; function nameHasScope(name: string): boolean { return /.*[^/]\/[^/].*/.test(name); @@ -70,7 +71,7 @@ export function initCompLabelEdit(pageSelector: string) { form.reportValidity(); return false; } - form.dispatchEvent(new Event('submit', {bubbles: true})); + submitFormFetchAction(form); }, }).modal('show'); }; |