From ef613ee76000a39c805bb6edb43ce5ef6d03c7db Mon Sep 17 00:00:00 2001 From: 6543 <6543@obermui.de> Date: Fri, 8 Aug 2025 18:18:30 +0200 Subject: [PATCH 01/97] Add `has_code` to repository REST API (#35214) similar to how we can enable/disable repos or issues on a repo add the code unit as option to it. affects ``` PATCH /repos/{owner}/{repo} ``` --- *Sponsored by Kithara Software GmbH* --- modules/structs/repo.go | 3 ++ routers/api/v1/repo/repo.go | 12 ++++++ templates/swagger/v1_json.tmpl | 9 +++++ tests/integration/api_repo_edit_test.go | 54 +++++++++++++++++++++++++ 4 files changed, 78 insertions(+) diff --git a/modules/structs/repo.go b/modules/structs/repo.go index f2e11b1542..404718def0 100644 --- a/modules/structs/repo.go +++ b/modules/structs/repo.go @@ -84,6 +84,7 @@ type Repository struct { Updated time.Time `json:"updated_at"` ArchivedAt time.Time `json:"archived_at"` Permissions *Permission `json:"permissions,omitempty"` + HasCode bool `json:"has_code"` HasIssues bool `json:"has_issues"` InternalTracker *InternalTracker `json:"internal_tracker,omitempty"` ExternalTracker *ExternalTracker `json:"external_tracker,omitempty"` @@ -170,6 +171,8 @@ type EditRepoOption struct { Private *bool `json:"private,omitempty"` // either `true` to make this repository a template or `false` to make it a normal repository Template *bool `json:"template,omitempty"` + // either `true` to enable code for this repository or `false` to disable it. + HasCode *bool `json:"has_code,omitempty"` // either `true` to enable issues for this repository or `false` to disable them. HasIssues *bool `json:"has_issues,omitempty"` // set this structure to configure internal issue tracker diff --git a/routers/api/v1/repo/repo.go b/routers/api/v1/repo/repo.go index 7b3858ccb1..e69b7729a0 100644 --- a/routers/api/v1/repo/repo.go +++ b/routers/api/v1/repo/repo.go @@ -869,6 +869,18 @@ func updateRepoUnits(ctx *context.APIContext, opts api.EditRepoOption) error { } } + if opts.HasCode != nil && !unit_model.TypeCode.UnitGlobalDisabled() { + if *opts.HasCode { + units = append(units, repo_model.RepoUnit{ + RepoID: repo.ID, + Type: unit_model.TypeCode, + Config: &repo_model.UnitConfig{}, + }) + } else { + deleteUnitTypes = append(deleteUnitTypes, unit_model.TypeCode) + } + } + if opts.HasPullRequests != nil && !unit_model.TypePullRequests.UnitGlobalDisabled() { if *opts.HasPullRequests { // We do allow setting individual PR settings through the API, so diff --git a/templates/swagger/v1_json.tmpl b/templates/swagger/v1_json.tmpl index 35c743dcd4..749d86901d 100644 --- a/templates/swagger/v1_json.tmpl +++ b/templates/swagger/v1_json.tmpl @@ -24333,6 +24333,11 @@ "type": "boolean", "x-go-name": "HasActions" }, + "has_code": { + "description": "either `true` to enable code for this repository or `false` to disable it.", + "type": "boolean", + "x-go-name": "HasCode" + }, "has_issues": { "description": "either `true` to enable issues for this repository or `false` to disable them.", "type": "boolean", @@ -27375,6 +27380,10 @@ "type": "boolean", "x-go-name": "HasActions" }, + "has_code": { + "type": "boolean", + "x-go-name": "HasCode" + }, "has_issues": { "type": "boolean", "x-go-name": "HasIssues" diff --git a/tests/integration/api_repo_edit_test.go b/tests/integration/api_repo_edit_test.go index e228da26e9..7fe59c0d09 100644 --- a/tests/integration/api_repo_edit_test.go +++ b/tests/integration/api_repo_edit_test.go @@ -76,12 +76,36 @@ func getRepoEditOptionFromRepo(repo *repo_model.Repository) *api.EditRepoOption allowFastForwardOnly = config.AllowFastForwardOnly } archived := repo.IsArchived + hasProjects := false + var projectsMode *string + if unit, err := repo.GetUnit(db.DefaultContext, unit_model.TypeProjects); err == nil && unit != nil { + hasProjects = true + pm := string(unit.ProjectsConfig().ProjectsMode) + projectsMode = &pm + } + hasCode := repo.UnitEnabled(db.DefaultContext, unit_model.TypeCode) + hasPackages := repo.UnitEnabled(db.DefaultContext, unit_model.TypePackages) + hasReleases := repo.UnitEnabled(db.DefaultContext, unit_model.TypeReleases) + hasActions := false + if unit, err := repo.GetUnit(db.DefaultContext, unit_model.TypeActions); err == nil && unit != nil { + hasActions = true + // TODO: expose action config of repo to api + // actionsConfig = &api.RepoActionsConfig{ + // DisabledWorkflows: unit.ActionsConfig().DisabledWorkflows, + // } + } return &api.EditRepoOption{ Name: &name, Description: &description, Website: &website, Private: &private, HasIssues: &hasIssues, + HasProjects: &hasProjects, + ProjectsMode: projectsMode, + HasCode: &hasCode, + HasPackages: &hasPackages, + HasReleases: &hasReleases, + HasActions: &hasActions, ExternalTracker: externalTracker, InternalTracker: internalTracker, HasWiki: &hasWiki, @@ -108,6 +132,11 @@ func getNewRepoEditOption(opts *api.EditRepoOption) *api.EditRepoOption { private := !*opts.Private hasIssues := !*opts.HasIssues hasWiki := !*opts.HasWiki + hasProjects := !*opts.HasProjects + hasCode := !*opts.HasCode + hasPackages := !*opts.HasPackages + hasReleases := !*opts.HasReleases + hasActions := !*opts.HasActions defaultBranch := "master" hasPullRequests := !*opts.HasPullRequests ignoreWhitespaceConflicts := !*opts.IgnoreWhitespaceConflicts @@ -125,6 +154,11 @@ func getNewRepoEditOption(opts *api.EditRepoOption) *api.EditRepoOption { DefaultBranch: &defaultBranch, HasIssues: &hasIssues, HasWiki: &hasWiki, + HasProjects: &hasProjects, + HasCode: &hasCode, + HasPackages: &hasPackages, + HasReleases: &hasReleases, + HasActions: &hasActions, HasPullRequests: &hasPullRequests, IgnoreWhitespaceConflicts: &ignoreWhitespaceConflicts, AllowMerge: &allowMerge, @@ -156,6 +190,11 @@ func TestAPIRepoEdit(t *testing.T) { // Test editing a repo1 which user2 owns, changing name and many properties origRepoEditOption := getRepoEditOptionFromRepo(repo1) + assert.True(t, *origRepoEditOption.HasCode) + assert.True(t, *origRepoEditOption.HasPackages) + assert.True(t, *origRepoEditOption.HasProjects) + assert.True(t, *origRepoEditOption.HasReleases) + assert.True(t, *origRepoEditOption.HasActions) repoEditOption := getNewRepoEditOption(origRepoEditOption) req := NewRequestWithJSON(t, "PATCH", fmt.Sprintf("/api/v1/repos/%s/%s", user2.Name, repo1.Name), &repoEditOption). AddTokenAuth(token2) @@ -177,6 +216,11 @@ func TestAPIRepoEdit(t *testing.T) { assert.Equal(t, *repoEditOption.Archived, *repo1editedOption.Archived) assert.Equal(t, *repoEditOption.Private, *repo1editedOption.Private) assert.Equal(t, *repoEditOption.HasWiki, *repo1editedOption.HasWiki) + assert.Equal(t, *repoEditOption.HasCode, *repo1editedOption.HasCode) + assert.Equal(t, *repoEditOption.HasPackages, *repo1editedOption.HasPackages) + assert.Equal(t, *repoEditOption.HasProjects, *repo1editedOption.HasProjects) + assert.Equal(t, *repoEditOption.HasReleases, *repo1editedOption.HasReleases) + assert.Equal(t, *repoEditOption.HasActions, *repo1editedOption.HasActions) // Test editing repo1 to use internal issue and wiki (default) *repoEditOption.HasIssues = true @@ -224,6 +268,11 @@ func TestAPIRepoEdit(t *testing.T) { assert.Equal(t, *repo1editedOption.ExternalTracker, *repoEditOption.ExternalTracker) assert.True(t, *repo1editedOption.HasWiki) assert.Equal(t, *repo1editedOption.ExternalWiki, *repoEditOption.ExternalWiki) + assert.False(t, *repo1editedOption.HasCode) + assert.False(t, *repo1editedOption.HasPackages) + assert.False(t, *repo1editedOption.HasProjects) + assert.False(t, *repo1editedOption.HasReleases) + assert.False(t, *repo1editedOption.HasActions) repoEditOption.ExternalTracker.ExternalTrackerStyle = "regexp" repoEditOption.ExternalTracker.ExternalTrackerRegexpPattern = `(\d+)` @@ -272,6 +321,11 @@ func TestAPIRepoEdit(t *testing.T) { assert.NotNil(t, *repo1editedOption.ExternalTracker) assert.True(t, *repo1editedOption.HasWiki) assert.NotNil(t, *repo1editedOption.ExternalWiki) + assert.False(t, *repo1editedOption.HasCode) + assert.False(t, *repo1editedOption.HasPackages) + assert.False(t, *repo1editedOption.HasProjects) + assert.False(t, *repo1editedOption.HasReleases) + assert.False(t, *repo1editedOption.HasActions) // reset repo in db req = NewRequestWithJSON(t, "PATCH", fmt.Sprintf("/api/v1/repos/%s/%s", user2.Name, *repoEditOption.Name), &origRepoEditOption). From c4c1a4bd18a6b38aa7ae3f3763258a728fbe1806 Mon Sep 17 00:00:00 2001 From: silverwind Date: Fri, 8 Aug 2025 18:52:49 +0200 Subject: [PATCH 02/97] Update stylelint, enable `report*` options (#35236) - Update stylelint - Enable three [`report*` directives](https://stylelint.io/user-guide/configure/#report) - Fix discovered issues --- package-lock.json | 8 ++++---- package.json | 2 +- stylelint.config.js | 3 +++ web_src/css/features/colorpicker.css | 2 +- web_src/css/repo.css | 2 +- 5 files changed, 10 insertions(+), 7 deletions(-) diff --git a/package-lock.json b/package-lock.json index 0cee3699a8..7d67cfa83a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -103,7 +103,7 @@ "material-icon-theme": "5.24.0", "nolyfill": "1.0.44", "postcss-html": "1.8.0", - "stylelint": "16.23.0", + "stylelint": "16.23.1", "stylelint-config-recommended": "17.0.0", "stylelint-declaration-block-no-ignored-properties": "2.8.0", "stylelint-declaration-strict-value": "1.10.11", @@ -12263,9 +12263,9 @@ "license": "ISC" }, "node_modules/stylelint": { - "version": "16.23.0", - "resolved": "https://registry.npmjs.org/stylelint/-/stylelint-16.23.0.tgz", - "integrity": "sha512-69T5aS2LUY306ekt1Q1oaSPwz/jaG9HjyMix3UMrai1iEbuOafBe2Dh8xlyczrxFAy89qcKyZWWtc42XLx3Bbw==", + "version": "16.23.1", + "resolved": "https://registry.npmjs.org/stylelint/-/stylelint-16.23.1.tgz", + "integrity": "sha512-dNvDTsKV1U2YtiUDfe9d2gp902veFeo3ecCWdGlmLm2WFrAV0+L5LoOj/qHSBABQwMsZPJwfC4bf39mQm1S5zw==", "dev": true, "funding": [ { diff --git a/package.json b/package.json index 8d12276d27..8109c40eb0 100644 --- a/package.json +++ b/package.json @@ -102,7 +102,7 @@ "material-icon-theme": "5.24.0", "nolyfill": "1.0.44", "postcss-html": "1.8.0", - "stylelint": "16.23.0", + "stylelint": "16.23.1", "stylelint-config-recommended": "17.0.0", "stylelint-declaration-block-no-ignored-properties": "2.8.0", "stylelint-declaration-strict-value": "1.10.11", diff --git a/stylelint.config.js b/stylelint.config.js index c57c1fd3a3..bd11307b53 100644 --- a/stylelint.config.js +++ b/stylelint.config.js @@ -10,6 +10,9 @@ const cssVarFiles = [ export default defineConfig({ extends: 'stylelint-config-recommended', + reportUnscopedDisables: true, + reportNeedlessDisables: true, + reportInvalidScopeDisables: true, plugins: [ 'stylelint-declaration-strict-value', 'stylelint-declaration-block-no-ignored-properties', diff --git a/web_src/css/features/colorpicker.css b/web_src/css/features/colorpicker.css index 4c517e6348..a353532f4e 100644 --- a/web_src/css/features/colorpicker.css +++ b/web_src/css/features/colorpicker.css @@ -15,7 +15,7 @@ top: 50%; transform: translateY(-50%); border-radius: 2px; - background: repeating-linear-gradient(45deg, #aaa 25%, transparent 25%, transparent 75%, #aaa 75%, #aaa), repeating-linear-gradient(45deg, #aaa 25%, #fff 25%, #fff 75%, #aaa 75%, #aaa); /* stylelint-disable-line scale-unlimited/declaration-strict-value */ + background: repeating-linear-gradient(45deg, #aaa 25%, transparent 25%, transparent 75%, #aaa 75%, #aaa), repeating-linear-gradient(45deg, #aaa 25%, #fff 25%, #fff 75%, #aaa 75%, #aaa); background-position: 0 0, 4px 4px; background-size: 8px 8px; } diff --git a/web_src/css/repo.css b/web_src/css/repo.css index 14db7d07e6..5238e3a2e5 100644 --- a/web_src/css/repo.css +++ b/web_src/css/repo.css @@ -1672,7 +1672,7 @@ tbody.commit-list { .diff-file-header .file-link { max-width: fit-content; display: -webkit-box; - -webkit-box-orient: vertical; /* stylelint-disable property-no-deprecated -- https://github.com/stylelint/stylelint/issues/8698 */ + -webkit-box-orient: vertical; -webkit-line-clamp: 2; overflow: hidden; overflow-wrap: anywhere; From a8349c4dc3c85de111824f6b6753d91a6b64cae4 Mon Sep 17 00:00:00 2001 From: GiteaBot Date: Sun, 10 Aug 2025 00:43:29 +0000 Subject: [PATCH 03/97] [skip ci] Updated translations via Crowdin --- options/locale/locale_zh-CN.ini | 101 ++++++++++++++++++++++++++++++++ 1 file changed, 101 insertions(+) diff --git a/options/locale/locale_zh-CN.ini b/options/locale/locale_zh-CN.ini index 01e35820a1..bad5af1dbe 100644 --- a/options/locale/locale_zh-CN.ini +++ b/options/locale/locale_zh-CN.ini @@ -44,6 +44,7 @@ webauthn_use_twofa=使用来自手机中的两步验证码 webauthn_error=无法读取安全密钥。 webauthn_unsupported_browser=您的浏览器目前不支持 WebAuthn。 webauthn_error_unknown=发生未知错误。请重试。 +webauthn_error_insecure=WebAuthn 仅支持安全连接。如果要在 HTTP 协议上进行测试,请使用 "localhost" 或 "127.0.0.1" 作为访问来源 webauthn_error_unable_to_process=服务器无法处理您的请求。 webauthn_error_duplicated=此安全密钥未被许可用于这个请求。请确保该密钥尚未注册。 webauthn_error_empty=您必须为此密钥设置一个名称。 @@ -116,6 +117,7 @@ files=文件 error=错误 error404=您正尝试访问的页面 不存在您尚未被授权 查看该页面。 +error503=服务器无法完成您的请求,请稍后重试。 go_back=返回 invalid_data=无效数据: %v @@ -166,18 +168,33 @@ no_results_found=未找到结果 internal_error_skipped=发生内部错误,但已跳过: %s [search] +search=搜索... type_tooltip=搜索类型 fuzzy=模糊 +fuzzy_tooltip=包含近似匹配搜索词的结果 words=词 words_tooltip=仅包含匹配搜索词的结果 regexp=正则表达式 regexp_tooltip=仅包含匹配正则表达式搜索词的结果 exact=精确 exact_tooltip=仅包含精确匹配搜索词的结果 +repo_kind=搜索仓库... +user_kind=搜索用户... +org_kind=搜索组织... +team_kind=搜索团队... +code_kind=搜索代码... code_search_unavailable=代码搜索当前不可用。请与网站管理员联系。 code_search_by_git_grep=当前代码搜索结果由「git grep」提供。如果站点管理员启用仓库索引器,可能会有更好的结果。 +package_kind=搜索软件包... +project_kind=搜索项目... +branch_kind=搜索分支... +tag_kind=搜索Git标签... tag_tooltip=搜索匹配的标签。使用「%」来匹配任何序列的数字。 +commit_kind=搜索提交记录... +runner_kind=搜索运行器... no_results=未找到匹配结果 +issue_kind=搜索工单... +pull_kind=搜索合并请求... keyword_search_unavailable=按关键字搜索当前不可用。请联系站点管理员。 [aria] @@ -213,6 +230,8 @@ buttons.enable_monospace_font=启用等宽字体 buttons.disable_monospace_font=禁用等宽字体 [filter] +string.asc=A - Z +string.desc=Z - A [error] occurred=发生了一个错误 @@ -233,6 +252,7 @@ license_desc=所有的代码都开源在 官方文档 后再对本页面进行填写。 require_db_desc=Gitea 需要使用 MySQL、PostgreSQL、MSSQL、SQLite3 或 TiDB (MySQL协议) 等数据库 @@ -249,10 +269,16 @@ path=数据库文件路径 sqlite_helper=SQLite3 数据库的文件路径。
如果以服务的方式运行 Gitea,请输入绝对路径。 reinstall_error=您正在尝试安装到一个已经有 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 位置上运行,而且您确定您必须重新安装。您确认您知晓上述风险。 err_empty_db_path=SQLite 数据库文件路径不能为空。 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=管理员用户名无效 general_title=一般设置 app_name=站点名称 @@ -268,6 +294,7 @@ domain_helper=服务器的域名或主机地址。 ssh_port=SSH 服务端口 ssh_port_helper=SSH 服务器的端口号,为空则禁用它。 http_port=HTTP 服务端口 +http_port_helper=Gitea Web 服务器将侦听的端口号。 app_url=基础URL app_url_helper=用于 HTTP (S) 克隆和邮件通知的基本地址。 log_root_path=日志路径 @@ -331,6 +358,7 @@ 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 算法相当安全,但使用大量内存,因此可能不适合小型系统。 enable_update_checker=启用更新检查 enable_update_checker_helper=通过连接到 gitea.io 定期检查新版本发布。 env_config_keys=环境配置 @@ -402,6 +430,8 @@ allow_password_change=要求用户更改密码(推荐) reset_password_mail_sent_prompt=确认邮件已被发送到 %s。请您在 %s 内检查您的收件箱 ,完成密码重置流程。 active_your_account=激活您的帐户 account_activated=帐户已激活 +prohibit_login=禁止登录 +prohibit_login_desc=您的帐户被禁止登录,请与网站管理员联系。 resent_limit_prompt=您请求发送激活邮件过于频繁,请等待 3 分钟后再试! has_unconfirmed_mail=%s 您好,系统检测到您有一封发送至 %s 但未被确认的邮件。如果您未收到激活邮件,或需要重新发送,请单击下方的按钮。 change_unconfirmed_mail_address=如果您的注册邮箱地址不正确,您可以在此更改并重新发送新的确认邮件。 @@ -422,6 +452,7 @@ use_scratch_code=使用验证口令 twofa_scratch_used=您已经使用了您的验证口令。您将会转到两步验证设置页面以便移除您的注册设备或者重新生成新的验证口令。 twofa_passcode_incorrect=您的验证码不正确。如果您丢失了您的设备,请使用您的验证口令。 twofa_scratch_token_incorrect=您的验证口令不正确。 +twofa_required=您必须设置两步验证来访问仓库,或者尝试重新登录。 login_userpass=登录 login_openid=OpenID oauth_signup_tab=注册帐号 @@ -440,13 +471,17 @@ 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=您不能使用您的邮箱地址注册。 authorize_application=应用授权 authorize_redirect_notice=如果您授权此应用,您将会被重定向到 %s。 authorize_application_created_by=此应用由 %s 创建。 +authorize_application_description=如果您允许,它将能够读取和修改您的所有帐户信息,包括私人仓库和组织。 authorize_application_with_scopes=范围:%s authorize_title=授权 %s 访问您的帐户? authorization_failed=授权失败 +authorization_failed_desc=因为检测到无效请求,授权失败。请尝试联系您授权应用的管理员。 sspi_auth_failed=SSPI 认证失败 password_pwned=此密码出现在 被盗密码 列表上并且曾经被公开。 请使用另一个密码再试一次。 password_pwned_err=无法完成对 HaveIBeenPwned 的请求 @@ -472,6 +507,7 @@ activate_email.text=请在 %s 时间内,点击以下链接,以验证 register_notify=欢迎来到 %s register_notify.title=%[1]s,欢迎来到 %[2]s register_notify.text_1=这是您的 %s 注册确认邮件 ! +register_notify.text_2=您现在可以以用户名 %s 登录。 register_notify.text_3=如果此账户已为您创建,请先 设置您的密码。 reset_password=恢复您的账户 @@ -509,6 +545,7 @@ 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.body=访问 %s 以接受或拒绝转移,亦可忽略此邮件。 repo.collaborator.added.subject=%s 把您添加到了 %s repo.collaborator.added.text=您已被添加为仓库的协作者: @@ -560,6 +597,7 @@ 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` unknown_error=未知错误: captcha_incorrect=验证码不正确。 @@ -574,14 +612,17 @@ username_has_not_been_changed=用户名未更改 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=团队名称已使用。 team_no_units_error=至少选择一项仓库单元。 email_been_used=该邮箱地址已在使用中。 email_invalid=此邮箱地址无效。 +email_domain_is_not_allowed=用户 %s 与EMAIL_DOMAIN_ALLOWLIT 或 EMAIL_DOMAIN_BLOCKLIT 冲突。请确保您的操作是预期的。 openid_been_used=OpenID 地址「%s」已被使用。 username_password_incorrect=用户名或密码不正确。 password_complexity=密码未达到复杂程度要求: @@ -916,6 +957,7 @@ twofa_not_enrolled=您的账号未开启两步验证。 twofa_disable=禁用两步认证 twofa_scratch_token_regenerate=重新生成初始令牌 twofa_scratch_token_regenerated=您的初始令牌现在是 %s。将其存放在安全的地方,它将不会再次显示。 +twofa_enroll=启用两步验证 twofa_disable_note=如果需要, 可以禁用双因素身份验证。 twofa_disable_desc=关掉两步验证会使得您的账号不安全,继续执行? regenerate_scratch_token_desc=如果您丢失了您的恢复密钥或已经使用它登录, 您可以在这里重置它。 @@ -1128,6 +1170,7 @@ migrate.clone_address=从 URL 迁移/克隆 migrate.clone_address_desc=现有仓库的 HTTP(s) 或 Git "clone" URL migrate.clone_local_path=或服务器本地路径 migrate.permission_denied=您没有获得导入本地仓库的权限。 +migrate.permission_denied_blocked=您不能从不允许的主机导入,请询问管理员以检查 ALLOWED_DOMAINS/ALLOW_LOCALNETWORKS/BLOCKED_DOMAINS 设置。 migrate.invalid_local_path=本地路径无效。它不存在或不是一个目录。 migrate.invalid_lfs_endpoint=LFS 网址无效。 migrate.failed=迁移失败:%v @@ -1135,6 +1178,7 @@ migrate.migrate_items_options=需要访问令牌来迁移额外的内容 migrated_from=从 %[2]s 迁移 migrated_from_fake=从 %[1]s 迁移成功 migrate.migrate=从 %s 迁移 +migrate.migrating=正在从 %s 迁移... migrate.migrating_failed=从 %s 迁移失败。 migrate.migrating_failed.error=迁移失败:%s migrate.migrating_failed_no_addr=迁移失败。 @@ -1183,7 +1227,9 @@ clone_this_repo=克隆当前仓库 cite_this_repo=引用此仓库 create_new_repo_command=从命令行创建一个新的仓库 push_exist_repo=从命令行推送已经创建的仓库 +empty_message=这个家伙很懒,什么都没有推送。 broken_message=无法读取此仓库下的 Git 数据。 联系此实例的管理员或删除此仓库。 +no_branch=该仓库没有任何分支。 code=代码 code.desc=查看源码、文件、提交和分支。 @@ -1200,6 +1246,7 @@ projects=项目 packages=软件包 actions=工作流 labels=标签 +org_labels_desc=组织级别的标签,可以被本组织下的 所有仓库 使用 org_labels_desc_manage=管理 milestone=里程碑 @@ -1248,6 +1295,7 @@ commit_graph.color=彩色 commit.contained_in=这个提交包含在: commit.contained_in_default_branch=此提交是默认分支的一部分 commit.load_referencing_branches_and_tags=加载引用该提交的分支和标签 +commit.merged_in_pr=此提交已合并在合并请求 %s 中。 blame=Blame download_file=下载文件 normal_view=普通视图 @@ -1296,6 +1344,8 @@ editor.new_branch_name_desc=新的分支名称... editor.cancel=取消 editor.filename_cannot_be_empty=文件名不能为空。 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」已作为文件名在此仓库中存在。 @@ -1713,6 +1763,7 @@ issues.review.self.approval=您不能批准您自己的合并请求。 issues.review.self.rejection=您不能请求对您自己的合并请求进行更改。 issues.review.approve=于 %s 批准此合并请求 issues.review.comment=评审于 %s +issues.review.dismissed=于 %[2]s 取消了 %[1]s 的评审 issues.review.dismissed_label=已取消 issues.review.left_comment=留下了一条评论 issues.review.content.empty=您需要留下一个注释,表明需要的更改。 @@ -1720,6 +1771,7 @@ issues.review.reject=请求变更 %s issues.review.wait=已请求 %s 审核 issues.review.add_review_request=于 %[2]s 请求 %[1]s 评审 issues.review.remove_review_request=取消对 %s 的评审请求 %s +issues.review.remove_review_request_self=拒绝审核 %s issues.review.pending=待定 issues.review.pending.tooltip=此评论目前对其他用户不可见。 若要提交您的待定评论,请在页面顶部选择 %s -> %s/%s/%s。 issues.review.review=评审 @@ -1777,9 +1829,11 @@ pulls.show_all_commits=显示所有提交 pulls.show_changes_since_your_last_review=显示自您上次审核以来的更改 pulls.showing_only_single_commit=仅显示提交 %[1]s 的更改 pulls.showing_specified_commit_range=仅显示 %[1]s..%[2]s 之间的更改 +pulls.select_commit_hold_shift_for_range=选择提交。按住 Shift + 单击选择一个范围 pulls.review_only_possible_for_full_diff=只有在查看全部差异时才能进行审核 pulls.filter_changes_by_commit=按提交筛选 pulls.nothing_to_compare=分支内容相同,无需创建合并请求。 +pulls.nothing_to_compare_have_tag=所选分支/标签相同。 pulls.nothing_to_compare_and_allow_empty_pr=这些分支是相等的,此合并请求将为空。 pulls.has_pull_request=这些分支之间的合并请求已存在: %[2]s#%[3]d pulls.create=创建合并请求 @@ -1804,6 +1858,7 @@ pulls.add_prefix=添加 %s 前缀 pulls.remove_prefix=删除 %s 前缀 pulls.data_broken=此合并请求因为派生仓库信息缺失而中断。 pulls.files_conflicted=此合并请求有变更与目标分支冲突。 +pulls.is_checking=正在进行合并冲突检测 ... pulls.is_ancestor=此分支已经包含在目标分支中,没有什么可以合并。 pulls.is_empty=此分支上的更改已经在目标分支上。这将是一个空提交。 pulls.required_status_check_failed=一些必要的检查没有成功 @@ -1827,12 +1882,16 @@ pulls.reject_count_1=%d 变更请求 pulls.reject_count_n=%d 变更请求 pulls.waiting_count_1=%d 个正在等待审核 pulls.waiting_count_n=%d 个正在等待审核 +pulls.wrong_commit_id=提交 id 必须在目标分支上 pulls.no_merge_desc=由于未启用合并选项,此合并请求无法合并。 pulls.no_merge_helper=在仓库设置中启用合并选项或者手工合并请求。 pulls.no_merge_wip=这个合并请求无法合并,因为被标记为尚未完成的工作。 +pulls.no_merge_not_ready=此合并请求尚未准备好合并,请检查审核状态和状态检查。 pulls.no_merge_access=您无权合并此合并请求。 pulls.merge_pull_request=创建合并提交 +pulls.rebase_merge_pull_request=变基后快进 +pulls.rebase_merge_commit_pull_request=变基后创建合并提交 pulls.squash_merge_pull_request=创建压缩提交 pulls.fast_forward_only_merge_pull_request=仅快进 pulls.merge_manually=手动合并 @@ -2488,6 +2547,7 @@ settings.lfs_lock=锁定 settings.lfs_locks_no_locks=无锁定 settings.lfs_lock_file_no_exist=锁定的文件在默认分支中不存在 settings.lfs_force_unlock=强制解锁 +settings.lfs_pointers.found=找到 %d 个块指针 - %d 个关联, %d 个未关联(%d 个从仓库丢失) settings.lfs_pointers.sha=Blob SHA settings.lfs_pointers.oid=OID settings.lfs_pointers.inRepo=在仓库中 @@ -2669,6 +2729,7 @@ error.csv.invalid_field_count=无法渲染此文件,因为它在第 %d 行中 error.broken_git_hook=此仓库的 Git 钩子似乎已损坏。 请按照 文档 来修复它们,然后推送一些提交来刷新状态。 [graphs] +component_loading=正在加载 %s... component_loading_failed=无法加载 %s component_loading_info=这可能需要一点时间… component_failed_to_load=意外的错误发生了。 @@ -2707,6 +2768,7 @@ form.create_org_not_allowed=此账号禁止创建组织 settings=组织设置 settings.options=组织 settings.full_name=组织全名 +settings.email=联系邮箱 settings.website=网站 settings.location=所在地区 settings.permission=权限 @@ -2723,7 +2785,10 @@ settings.update_setting_success=组织设置已更新。 settings.rename=修改组织名称 settings.rename_desc=更改组织名称同时会更改组织的 URL 地址并释放旧的名称。 +settings.rename_success=组织 %[1]s 已成功重命名为 %[2]s。 +settings.rename_no_change=组织名称没有变更。 settings.rename_new_org_name=新组织名称 +settings.rename_failed=由于内部错误,重命名组织失败 settings.rename_notices_1=此操作 无法 被回滚。 settings.rename_notices_2=在被人使用前,旧名称将会被重定向。 @@ -2733,9 +2798,11 @@ settings.delete_account=删除当前组织 settings.delete_prompt=删除操作会永久清除该组织的信息,并且 无法 恢复! settings.name_confirm=输入组织名称以确认: settings.delete_notices_1=此操作 无法 被回滚。 +settings.delete_notices_2=此操作将永久删除 %s 的所有仓库,包括 Git 数据、 工单、评论、百科和协作者的操作权限。 settings.delete_notices_3=此操作将永久删除 %s 的所有 软件包。 settings.delete_notices_4=此操作将永久删除 %s 的所有 项目。 settings.confirm_delete_account=确认删除组织 +settings.delete_failed=由于内部错误,删除组织失败 settings.delete_successful=组织 %s 已成功删除。 settings.hooks_desc=在此处添加的 Web 钩子将会应用到该组织下的 所有仓库。 @@ -2792,6 +2859,7 @@ teams.remove_all_repos_title=移除所有团队仓库 teams.remove_all_repos_desc=这将从团队中移除所有仓库。 teams.add_all_repos_title=添加所有仓库 teams.add_all_repos_desc=这将把组织的所有仓库添加到团队。 +teams.add_nonexistent_repo=您尝试添加的仓库不存在,请先创建它。 teams.add_duplicate_users=用户已经是团队成员。 teams.repos.none=此团队无法访问任何仓库。 teams.members.none=团队中没有成员。 @@ -2832,6 +2900,7 @@ repositories=仓库管理 hooks=Web 钩子 integrations=集成 authentication=认证源 +emails=用户邮箱 config=应用配置 config_summary=摘要 config_settings=设置 @@ -2863,8 +2932,11 @@ 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.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 数据同步标签到数据库 @@ -2872,10 +2944,15 @@ dashboard.update_mirrors=更新镜像仓库 dashboard.repo_health_check=健康检查所有仓库 dashboard.check_repo_stats=检查所有仓库统计 dashboard.archive_cleanup=删除旧的仓库存档 +dashboard.deleted_branches_cleanup=清理已删除的分支 dashboard.update_migration_poster_id=更新迁移的发表者ID +dashboard.git_gc_repos=对仓库进行垃圾回收 +dashboard.resync_all_sshkeys=使用 Gitea 的 SSH 密钥更新「.ssh/authorized_keys」文件。 +dashboard.resync_all_sshprincipals=使用 Gitea 的 SSH 规则更新「.ssh/authorized_principals」文件。 dashboard.reinit_missing_repos=重新初始化所有丢失的 Git 仓库存在的记录 dashboard.sync_external_users=同步外部用户数据 dashboard.cleanup_hook_task_table=清理 hook_task 表 +dashboard.cleanup_packages=清理过期的软件包 dashboard.cleanup_actions=清理过期的工作流资源 dashboard.server_uptime=服务运行时间 dashboard.current_goroutine=当前 Goroutines 数量 @@ -2907,8 +2984,10 @@ dashboard.total_gc_pause=GC 暂停时间总量 dashboard.last_gc_pause=上次 GC 暂停时间 dashboard.gc_times=GC 执行次数 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=取消已放弃的工作流任务 @@ -2932,6 +3011,7 @@ users.2fa=两步验证 users.repos=仓库数 users.created=创建时间 users.last_login=上次登录 +users.never_login=从未登录 users.send_register_notify=发送注册通知 users.new_success=用户账户「%s」已创建。 users.edit=修改 @@ -2958,6 +3038,7 @@ users.still_own_repo=此用户仍然拥有一个或多个仓库。必须首先 users.still_has_org=此用户是组织的成员。必须先从组织中删除用户。 users.purge=清理用户 users.purge_help=强制删除用户和用户拥有的任何仓库、组织和软件包。所有评论也将删除。 +users.still_own_packages=此用户仍然拥有一个或多个软件包,请先删除这些软件包。 users.deletion_success=用户帐户已删除。 users.reset_2fa=重置两步验证 users.list_status_filter.menu_text=过滤 @@ -2977,7 +3058,11 @@ users.details=用户详细信息 emails.email_manage_panel=邮件管理 emails.primary=主要的 emails.activated=已激活 +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=更新邮箱属性 @@ -2985,6 +3070,7 @@ emails.change_email_text=您确定要更新该邮箱地址吗? emails.delete=删除邮箱 emails.delete_desc=您确定要删除该邮箱地址? emails.deletion_success=邮箱地址已删除。 +emails.delete_primary_email_error=您不能删除主邮箱。 orgs.org_manage_panel=组织管理 orgs.name=名称 @@ -3098,7 +3184,11 @@ auths.oauth2_required_claim_name_helper=设置此名称,只有具有此名称 auths.oauth2_required_claim_value=必须填写 Claim 声明的值 auths.oauth2_required_claim_value_helper=设置此值,只有拥有对应的声明(Claim)的名称和值的用户才被允许从此源登录 auths.oauth2_group_claim_name=用于提供用户组名称的 Claim 声明名称。(可选) +auths.oauth2_full_name_claim_name=全名声明名称。(可选,如果设置,用户的全名将始终与此声明同步) auths.oauth2_ssh_public_key_claim_name=SSH 公钥声明名称 +auths.oauth2_admin_group=管理员用户组的 Claim 声明值。(可选 - 需要上面的声明名称) +auths.oauth2_restricted_group=受限用户组的 Claim 声明值。(可选 - 需要上面的声明名称) +auths.oauth2_map_group_to_team=映射声明的组到组织团队。(可选 - 要求在上面填写声明的名字) auths.oauth2_map_group_to_team_removal=如果用户不属于相应的组,从已同步团队中移除用户 auths.enable_auto_register=允许用户自动注册 auths.sspi_auto_create_users=自动创建用户 @@ -3112,6 +3202,7 @@ 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=使用下面的菜单「设置 -> 安全 -> OAuth 2.0 客户端」在您的实例上注册一个新的 OAuth 客户端 auths.tip.dropbox=在 %s 上创建一个新的应用程序 auths.tip.facebook=在 %s 注册一个新的应用,并添加产品「Facebook 登录」 auths.tip.github=在 %s 注册一个 OAuth 应用程序 @@ -3221,6 +3312,7 @@ config.mailer_sendmail_path=Sendmail 路径 config.mailer_sendmail_args=Sendmail 的额外参数 config.mailer_sendmail_timeout=Sendmail 超时 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 @@ -3294,6 +3386,7 @@ monitor.start=开始时间 monitor.execute_time=执行时长 monitor.last_execution_result=结果 monitor.process.cancel=中止进程 +monitor.process.cancel_desc=中止一个进程可能导致数据丢失 monitor.process.children=子进程 monitor.queues=队列 @@ -3308,6 +3401,7 @@ monitor.queue.numberinqueue=队列中的数量 monitor.queue.review_add=查看 / 添加工作者 monitor.queue.settings.title=池设置 monitor.queue.settings.desc=因为工作者队列阻塞,池正在动态扩展。 +monitor.queue.settings.maxnumberworkers=最大工作者数量 monitor.queue.settings.maxnumberworkers.placeholder=当前 %[1]d monitor.queue.settings.maxnumberworkers.error=最大工作者数必须是数字 monitor.queue.settings.submit=更新设置 @@ -3333,6 +3427,10 @@ 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 ...」SQL 手动解决这个问题。 self_check.location_origin_mismatch=当前 URL(%[1]s)与 Gitea 的 URL(%[2]s)不匹配 。 如果您正在使用反向代理,请确保设置正确的「Host」和「X-Forwarded-Proto」标头。 [action] @@ -3485,6 +3583,7 @@ container.labels=标签 container.labels.key=键 container.labels.value=值 cran.install=要安装软件包,请运行以下命令: +debian.registry=从命令行设置此注册中心: debian.registry.info=从下面的列表中选择 $distribution 和 $component。 debian.install=要安装软件包,请运行以下命令: debian.repository=仓库信息 @@ -3493,6 +3592,7 @@ debian.repository.components=组件 debian.repository.architectures=架构 generic.download=从命令行下载软件包: go.install=通过命令行安装软件包: +helm.registry=从命令行设置此注册中心: helm.install=要安装包,请运行以下命令: maven.install2=通过命令行运行: maven.download=要下载依赖项,请通过命令行运行: @@ -3631,6 +3731,7 @@ runners.delete_runner=删除此运行器 runners.delete_runner_success=运行器删除成功 runners.delete_runner_failed=运行器删除失败 runners.delete_runner_header=确认要删除此运行器 +runners.delete_runner_notice=如果一个任务正在运行在此运行器上,它将被终止并标记为失败。它可能会打断正在构建的工作流。 runners.none=无可用运行器 runners.status.unspecified=未知 runners.status.idle=空闲 From d328e007753bd9f28ff609d6dbc34a54358299e5 Mon Sep 17 00:00:00 2001 From: GiteaBot Date: Mon, 11 Aug 2025 00:41:48 +0000 Subject: [PATCH 04/97] [skip ci] Updated translations via Crowdin --- options/locale/locale_zh-CN.ini | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/options/locale/locale_zh-CN.ini b/options/locale/locale_zh-CN.ini index bad5af1dbe..fd2ecedbda 100644 --- a/options/locale/locale_zh-CN.ini +++ b/options/locale/locale_zh-CN.ini @@ -647,8 +647,14 @@ 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 +still_own_repo=此帐户仍拥有至少一个仓库,您需要先删除或转移它们。 +still_has_org=此帐户隶属于一个或多个组织,请先退出这些组织。 +still_own_packages=您的账户拥有一个或多个软件包,请先删除它们。 +org_still_own_repo=该组织仍然是某些仓库的拥有者,请先删除或转移它们! +org_still_own_packages=该组织仍然是一个或多个软件包的拥有者,请先删除它们。 target_branch_not_exist=目标分支不存在。 target_ref_not_exist=目标引用 %s 不存在 @@ -679,9 +685,11 @@ settings=用户设置 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.unblock=取消屏蔽 block.unblock.failure=取消屏蔽用户失败:%s @@ -791,6 +799,7 @@ manage_themes=选择默认主题 manage_openid=管理 OpenID 地址 email_desc=您的主邮箱地址将用于通知、密码恢复以及基于网页的 Git 操作(如果它未设为隐藏)。 theme_desc=这将是您在整个网站上的默认主题。 +theme_colorblindness_help=颜色障碍主题支持 primary=主要 activated=已激活 requires_activation=需要激活 @@ -1550,6 +1559,7 @@ issues.filter_type.reviewed_by_you=您评审过的 issues.filter_sort=排序 issues.filter_sort.latest=最新创建 issues.filter_sort.oldest=最早创建 +issues.filter_sort.recentupdate=最近更新 issues.filter_sort.leastupdate=最早更新 issues.filter_sort.mostcomment=最多评论 issues.filter_sort.leastcomment=最少评论 From 9b5a3e9c9cb109768a76ff60e71573754bac1486 Mon Sep 17 00:00:00 2001 From: Sebastian Ertz Date: Mon, 11 Aug 2025 13:00:20 +0200 Subject: [PATCH 05/97] Update chroma to v2.20.0 (#35220) https://github.com/alecthomas/chroma/releases/tag/v2.20.0 --------- Signed-off-by: wxiaoguang Co-authored-by: wxiaoguang --- go.mod | 2 +- go.sum | 8 ++++---- modules/markup/orgmode/orgmode_test.go | 14 ++++---------- 3 files changed, 9 insertions(+), 15 deletions(-) diff --git a/go.mod b/go.mod index 5fc7473df7..03fc2ae4bf 100644 --- a/go.mod +++ b/go.mod @@ -27,7 +27,7 @@ require ( github.com/ProtonMail/go-crypto v1.2.0 github.com/PuerkitoBio/goquery v1.10.3 github.com/SaveTheRbtz/zstd-seekable-format-go/pkg v0.7.3 - github.com/alecthomas/chroma/v2 v2.17.0 + github.com/alecthomas/chroma/v2 v2.20.0 github.com/aws/aws-sdk-go-v2/credentials v1.17.67 github.com/aws/aws-sdk-go-v2/service/codecommit v1.28.2 github.com/blakesmith/ar v0.0.0-20190502131153-809d4375e1fb diff --git a/go.sum b/go.sum index 2ccdc64d77..b912466eb0 100644 --- a/go.sum +++ b/go.sum @@ -78,11 +78,11 @@ github.com/SaveTheRbtz/zstd-seekable-format-go/pkg v0.7.3/go.mod h1:hMNtySovKkn2 github.com/alecthomas/assert/v2 v2.11.0 h1:2Q9r3ki8+JYXvGsDyBXwH3LcJ+WK5D0gc5E8vS6K3D0= github.com/alecthomas/assert/v2 v2.11.0/go.mod h1:Bze95FyfUr7x34QZrjL+XP+0qgp/zg8yS+TtBj1WA3k= github.com/alecthomas/chroma/v2 v2.2.0/go.mod h1:vf4zrexSH54oEjJ7EdB65tGNHmH3pGZmVkgTP5RHvAs= -github.com/alecthomas/chroma/v2 v2.17.0 h1:3r2Cgk+nXNICMBxIFGnTRTbQFUwMiLisW+9uos0TtUI= -github.com/alecthomas/chroma/v2 v2.17.0/go.mod h1:RVX6AvYm4VfYe/zsk7mjHueLDZor3aWCNE14TFlepBk= +github.com/alecthomas/chroma/v2 v2.20.0 h1:sfIHpxPyR07/Oylvmcai3X/exDlE8+FA820NTz+9sGw= +github.com/alecthomas/chroma/v2 v2.20.0/go.mod h1:e7tViK0xh/Nf4BYHl00ycY6rV7b8iXBksI9E359yNmA= github.com/alecthomas/repr v0.0.0-20220113201626-b1b626ac65ae/go.mod h1:2kn6fqh/zIyPLmm3ugklbEi5hg5wS435eygvNfaDQL8= -github.com/alecthomas/repr v0.4.0 h1:GhI2A8MACjfegCPVq9f1FLvIBS+DrQ2KQBFZP1iFzXc= -github.com/alecthomas/repr v0.4.0/go.mod h1:Fr0507jx4eOXV7AlPV6AVZLYrLIuIeSOWtW57eE/O/4= +github.com/alecthomas/repr v0.5.1 h1:E3G4t2QbHTSNpPKBgMTln5KLkZHLOcU7r37J4pXBuIg= +github.com/alecthomas/repr v0.5.1/go.mod h1:Fr0507jx4eOXV7AlPV6AVZLYrLIuIeSOWtW57eE/O/4= github.com/alexbrainman/sspi v0.0.0-20231016080023-1a75b4708caa h1:LHTHcTQiSGT7VVbI0o4wBRNQIgn917usHWOd6VAffYI= github.com/alexbrainman/sspi v0.0.0-20231016080023-1a75b4708caa/go.mod h1:cEWa1LVoE5KvSD9ONXsZrj0z6KqySlCCNKHlLzbqAt4= github.com/anchore/archiver/v3 v3.5.2 h1:Bjemm2NzuRhmHy3m0lRe5tNoClB9A4zYyDV58PaB6aA= diff --git a/modules/markup/orgmode/orgmode_test.go b/modules/markup/orgmode/orgmode_test.go index df4bb38ad1..ebda2271f2 100644 --- a/modules/markup/orgmode/orgmode_test.go +++ b/modules/markup/orgmode/orgmode_test.go @@ -97,16 +97,10 @@ func TestRender_Source(t *testing.T) { assert.Equal(t, strings.TrimSpace(expected), strings.TrimSpace(buffer)) } - test(`#+begin_src go -// HelloWorld prints "Hello World" -func HelloWorld() { - fmt.Println("Hello World") -} + test(`#+begin_src c +int a; #+end_src -`, `
-
// HelloWorld prints "Hello World"
-func HelloWorld() {
-	fmt.Println("Hello World")
-}
+`, `
+
int a;
`) } From 87b28b3e83f515e67c999b62e93ff14a0b5f1b70 Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Mon, 11 Aug 2025 04:27:22 -0700 Subject: [PATCH 06/97] Reload issue when sending webhook to make num comments is right. (#35243) Fix #35229 --------- Co-authored-by: Giteabot --- services/actions/notifier.go | 11 +---------- services/issue/comments.go | 6 ++++++ services/webhook/notifier.go | 1 + 3 files changed, 8 insertions(+), 10 deletions(-) diff --git a/services/actions/notifier.go b/services/actions/notifier.go index d10cc0ab34..110e330f68 100644 --- a/services/actions/notifier.go +++ b/services/actions/notifier.go @@ -263,11 +263,6 @@ func (n *actionsNotifier) CreateIssueComment(ctx context.Context, doer *user_mod func (n *actionsNotifier) UpdateComment(ctx context.Context, doer *user_model.User, c *issues_model.Comment, oldContent string) { ctx = withMethod(ctx, "UpdateComment") - if err := c.LoadIssue(ctx); err != nil { - log.Error("LoadIssue: %v", err) - return - } - if c.Issue.IsPull { notifyIssueCommentChange(ctx, doer, c, oldContent, webhook_module.HookEventPullRequestComment, api.HookIssueCommentEdited) return @@ -278,11 +273,6 @@ func (n *actionsNotifier) UpdateComment(ctx context.Context, doer *user_model.Us func (n *actionsNotifier) DeleteComment(ctx context.Context, doer *user_model.User, comment *issues_model.Comment) { ctx = withMethod(ctx, "DeleteComment") - if err := comment.LoadIssue(ctx); err != nil { - log.Error("LoadIssue: %v", err) - return - } - if comment.Issue.IsPull { notifyIssueCommentChange(ctx, doer, comment, "", webhook_module.HookEventPullRequestComment, api.HookIssueCommentDeleted) return @@ -291,6 +281,7 @@ func (n *actionsNotifier) DeleteComment(ctx context.Context, doer *user_model.Us } func notifyIssueCommentChange(ctx context.Context, doer *user_model.User, comment *issues_model.Comment, oldContent string, event webhook_module.HookEventType, action api.HookIssueCommentAction) { + comment.Issue = nil // force issue to be loaded if err := comment.LoadIssue(ctx); err != nil { log.Error("LoadIssue: %v", err) return diff --git a/services/issue/comments.go b/services/issue/comments.go index 10c81198d5..9442701029 100644 --- a/services/issue/comments.go +++ b/services/issue/comments.go @@ -80,6 +80,12 @@ func CreateIssueComment(ctx context.Context, doer *user_model.User, repo *repo_m return nil, err } + // reload issue to ensure it has the latest data, especially the number of comments + issue, err = issues_model.GetIssueByID(ctx, issue.ID) + if err != nil { + return nil, err + } + notify_service.CreateIssueComment(ctx, doer, repo, issue, comment, mentions) return comment, nil diff --git a/services/webhook/notifier.go b/services/webhook/notifier.go index 672abd5c95..80de6b00fd 100644 --- a/services/webhook/notifier.go +++ b/services/webhook/notifier.go @@ -481,6 +481,7 @@ func (m *webhookNotifier) DeleteComment(ctx context.Context, doer *user_model.Us log.Error("LoadPoster: %v", err) return } + comment.Issue = nil // reload issue to ensure it has the latest data, especially the number of comments if err = comment.LoadIssue(ctx); err != nil { log.Error("LoadIssue: %v", err) return From 345045888dbeb7dfa3a83bcf78e4ae3cc0c7be5a Mon Sep 17 00:00:00 2001 From: Tim Biermann Date: Tue, 12 Aug 2025 04:57:44 +0200 Subject: [PATCH 07/97] =?UTF-8?q?modules/setting/actions.go:=20fixed=20typ?= =?UTF-8?q?o:=20=C3=AC->i=20(#35253)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- modules/setting/actions.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/setting/actions.go b/modules/setting/actions.go index 8bace1f750..34346b62cf 100644 --- a/modules/setting/actions.go +++ b/modules/setting/actions.go @@ -24,7 +24,7 @@ var ( ZombieTaskTimeout time.Duration `ini:"ZOMBIE_TASK_TIMEOUT"` EndlessTaskTimeout time.Duration `ini:"ENDLESS_TASK_TIMEOUT"` AbandonedJobTimeout time.Duration `ini:"ABANDONED_JOB_TIMEOUT"` - SkipWorkflowStrings []string `ìni:"SKIP_WORKFLOW_STRINGS"` + SkipWorkflowStrings []string `ini:"SKIP_WORKFLOW_STRINGS"` }{ Enabled: true, DefaultActionsURL: defaultActionsURLGitHub, From 90a48e96c7ab18689fba0a4a7c29dfb44b63d96d Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Mon, 11 Aug 2025 22:38:17 -0700 Subject: [PATCH 08/97] Fix a bug where lfs gc never worked. (#35198) Fix #31113 After #22385 introduced LFS GC, it never worked due to a bug in the INI library: fields in structs embedded more than one level deep are not populated from the INI file. This PR fixes the issue by replacing the multi-level embedded struct with a single-level struct for parsing the cron.gc_lfs configuration. Added a new test for retrieving cron settings to demonstrate the bug in the INI package. --- modules/setting/cron_test.go | 53 ++++++++++++++++++++++++++++ services/cron/tasks_extended.go | 43 +++++++++++----------- services/cron/tasks_extended_test.go | 51 ++++++++++++++++++++++++++ 3 files changed, 126 insertions(+), 21 deletions(-) create mode 100644 services/cron/tasks_extended_test.go diff --git a/modules/setting/cron_test.go b/modules/setting/cron_test.go index 39a228068a..53996b5de9 100644 --- a/modules/setting/cron_test.go +++ b/modules/setting/cron_test.go @@ -41,3 +41,56 @@ EXTEND = true assert.Equal(t, "white rabbit", extended.Second) assert.True(t, extended.Extend) } + +// Test_getCronSettings2 tests that getCronSettings can not handle two levels of embedding +func Test_getCronSettings2(t *testing.T) { + type BaseStruct struct { + Enabled bool + RunAtStart bool + Schedule string + } + + type Extended struct { + BaseStruct + Extend bool + } + type Extended2 struct { + Extended + Third string + } + + iniStr := ` +[cron.test] +ENABLED = TRUE +RUN_AT_START = TRUE +SCHEDULE = @every 1h +EXTEND = true +THIRD = white rabbit +` + cfg, err := NewConfigProviderFromData(iniStr) + assert.NoError(t, err) + + extended := &Extended2{ + Extended: Extended{ + BaseStruct: BaseStruct{ + Enabled: false, + RunAtStart: false, + Schedule: "@every 72h", + }, + Extend: false, + }, + Third: "black rabbit", + } + + _, err = getCronSettings(cfg, "test", extended) + assert.NoError(t, err) + + // This confirms the first level of embedding works + assert.Equal(t, "white rabbit", extended.Third) + assert.True(t, extended.Extend) + + // This confirms 2 levels of embedding doesn't work + assert.False(t, extended.Enabled) + assert.False(t, extended.RunAtStart) + assert.Equal(t, "@every 72h", extended.Schedule) +} diff --git a/services/cron/tasks_extended.go b/services/cron/tasks_extended.go index 0018c5facc..3747111984 100644 --- a/services/cron/tasks_extended.go +++ b/services/cron/tasks_extended.go @@ -171,34 +171,35 @@ func registerDeleteOldSystemNotices() { }) } +type GCLFSConfig struct { + BaseConfig + OlderThan time.Duration + LastUpdatedMoreThanAgo time.Duration + NumberToCheckPerRepo int64 + ProportionToCheckPerRepo float64 +} + func registerGCLFS() { if !setting.LFS.StartServer { return } - type GCLFSConfig struct { - OlderThanConfig - LastUpdatedMoreThanAgo time.Duration - NumberToCheckPerRepo int64 - ProportionToCheckPerRepo float64 - } RegisterTaskFatal("gc_lfs", &GCLFSConfig{ - OlderThanConfig: OlderThanConfig{ - BaseConfig: BaseConfig{ - Enabled: false, - RunAtStart: false, - Schedule: "@every 24h", - }, - // Only attempt to garbage collect lfs meta objects older than a week as the order of git lfs upload - // and git object upload is not necessarily guaranteed. It's possible to imagine a situation whereby - // an LFS object is uploaded but the git branch is not uploaded immediately, or there are some rapid - // changes in new branches that might lead to lfs objects becoming temporarily unassociated with git - // objects. - // - // It is likely that a week is potentially excessive but it should definitely be enough that any - // unassociated LFS object is genuinely unassociated. - OlderThan: 24 * time.Hour * 7, + BaseConfig: BaseConfig{ + Enabled: false, + RunAtStart: false, + Schedule: "@every 24h", }, + // Only attempt to garbage collect lfs meta objects older than a week as the order of git lfs upload + // and git object upload is not necessarily guaranteed. It's possible to imagine a situation whereby + // an LFS object is uploaded but the git branch is not uploaded immediately, or there are some rapid + // changes in new branches that might lead to lfs objects becoming temporarily unassociated with git + // objects. + // + // It is likely that a week is potentially excessive but it should definitely be enough that any + // unassociated LFS object is genuinely unassociated. + OlderThan: 24 * time.Hour * 7, + // Only GC things that haven't been looked at in the past 3 days LastUpdatedMoreThanAgo: 24 * time.Hour * 3, NumberToCheckPerRepo: 100, diff --git a/services/cron/tasks_extended_test.go b/services/cron/tasks_extended_test.go new file mode 100644 index 0000000000..a3d40630a3 --- /dev/null +++ b/services/cron/tasks_extended_test.go @@ -0,0 +1,51 @@ +// Copyright 2025 The Gitea Authors. All rights reserved. +// SPDX-License-Identifier: MIT + +package cron + +import ( + "testing" + "time" + + "code.gitea.io/gitea/modules/setting" + "code.gitea.io/gitea/modules/test" + + "github.com/stretchr/testify/assert" +) + +func Test_GCLFSConfig(t *testing.T) { + cfg, err := setting.NewConfigProviderFromData(` +[cron.gc_lfs] +ENABLED = true +RUN_AT_START = true +SCHEDULE = "@every 2h" +OLDER_THAN = "1h" +LAST_UPDATED_MORE_THAN_AGO = "7h" +NUMBER_TO_CHECK_PER_REPO = 10 +PROPORTION_TO_CHECK_PER_REPO = 0.1 +`) + assert.NoError(t, err) + defer test.MockVariableValue(&setting.CfgProvider, cfg)() + + config := &GCLFSConfig{ + BaseConfig: BaseConfig{ + Enabled: false, + RunAtStart: false, + Schedule: "@every 24h", + }, + OlderThan: 24 * time.Hour * 7, + LastUpdatedMoreThanAgo: 24 * time.Hour * 3, + NumberToCheckPerRepo: 100, + ProportionToCheckPerRepo: 0.6, + } + + _, err = setting.GetCronSettings("gc_lfs", config) + assert.NoError(t, err) + assert.True(t, config.Enabled) + assert.True(t, config.RunAtStart) + assert.Equal(t, "@every 2h", config.Schedule) + assert.Equal(t, 1*time.Hour, config.OlderThan) + assert.Equal(t, 7*time.Hour, config.LastUpdatedMoreThanAgo) + assert.Equal(t, int64(10), config.NumberToCheckPerRepo) + assert.InDelta(t, 0.1, config.ProportionToCheckPerRepo, 0.001) +} From e02b47d2f32736d8c032e9daa602a143ee8a2548 Mon Sep 17 00:00:00 2001 From: silverwind Date: Tue, 12 Aug 2025 10:06:45 +0200 Subject: [PATCH 09/97] Fix font-size in inline code comment preview (#35209) Previously, when writing a inline code comment, the markup preview would have incorrect font size of 16px. This fixes it to 14px and also combines similar CSS rules into one. I'm not a fan of this selector complexity, but it seems like a necessity because standalone markup files render at 16px while comments render at 14px. --------- Signed-off-by: silverwind --- web_src/css/markup/content.css | 3 ++- web_src/css/repo.css | 12 ------------ 2 files changed, 2 insertions(+), 13 deletions(-) diff --git a/web_src/css/markup/content.css b/web_src/css/markup/content.css index c6a89edf25..14d95ca726 100644 --- a/web_src/css/markup/content.css +++ b/web_src/css/markup/content.css @@ -1,6 +1,6 @@ .markup { overflow: hidden; - font-size: 16px; + font-size: 14px; /* 14px for comments, overridden to 16px for .file-view below. */ line-height: 1.5 !important; overflow-wrap: break-word; } @@ -318,6 +318,7 @@ In markup content, we always use bottom margin for all elements */ .file-view.markup { padding: 1em 2em; + font-size: 16px; } .file-view.markup:has(.file-not-rendered-prompt) { diff --git a/web_src/css/repo.css b/web_src/css/repo.css index 5238e3a2e5..9f4fa51881 100644 --- a/web_src/css/repo.css +++ b/web_src/css/repo.css @@ -300,10 +300,6 @@ td .commit-summary { min-width: 100px; } -.repository.new.issue .comment.form .content .markup { - font-size: 14px; -} - .repository.view.issue .instruct-toggle { display: inline-block; } @@ -630,10 +626,6 @@ td .commit-summary { background: var(--color-light); } -.repository.view.issue .comment-list .comment .markup { - font-size: 14px; -} - .repository.view.issue .comment-list .comment .no-content { color: var(--color-text-light-2); font-style: italic; @@ -723,10 +715,6 @@ td .commit-summary { text-align: center; } -.repository.compare.pull .markup { - font-size: 14px; -} - .repository.branches .commit-divergence .bar-group { position: relative; float: left; From a2e8bf526138ec74cd8946296166cec3f43f0b1d Mon Sep 17 00:00:00 2001 From: GiteaBot Date: Thu, 14 Aug 2025 00:37:39 +0000 Subject: [PATCH 10/97] [skip ci] Updated translations via Crowdin --- options/locale/locale_zh-CN.ini | 104 ++++++++++++++++++++++++++++---- 1 file changed, 92 insertions(+), 12 deletions(-) diff --git a/options/locale/locale_zh-CN.ini b/options/locale/locale_zh-CN.ini index fd2ecedbda..36b975ba36 100644 --- a/options/locale/locale_zh-CN.ini +++ b/options/locale/locale_zh-CN.ini @@ -702,6 +702,7 @@ block.info_3=通过 @ 提及您的用户名向您发送通知 block.info_4=邀请您作为协作者到他们的仓库中 block.info_5=在仓库中点赞、派生或关注 block.info_6=打开和评论工单或合并请求 +block.info_7=在问题或合并请求中对您的评论做出反应 block.user_to_block=要屏蔽的用户 block.note=备注 block.note.title=可选备注: @@ -752,6 +753,7 @@ cancel=取消操作 language=界面语言 ui=主题 hidden_comment_types=隐藏的评论类型 +hidden_comment_types_description=此处选中的注释类型不会显示在工单页面上。比如,勾选「标签」删除所有「{user} 添加/删除的 {label}」注释。 hidden_comment_types.ref_tooltip=注释此问题在何处被提及过,如另一个问题、代码提交等 hidden_comment_types.issue_ref_tooltip=注释用户在何处更改了与此问题相关联的分支/标签 comment_type_group_reference=引用 @@ -800,12 +802,14 @@ manage_openid=管理 OpenID 地址 email_desc=您的主邮箱地址将用于通知、密码恢复以及基于网页的 Git 操作(如果它未设为隐藏)。 theme_desc=这将是您在整个网站上的默认主题。 theme_colorblindness_help=颜色障碍主题支持 +theme_colorblindness_prompt=Gitea 仅有少数主题存在基本的颜色障碍支持,这些主题只定义了少数颜色。这项工作仍在进行中,可以通过在主题的 CSS 文件中定义更多颜色来实现更多改进。 primary=主要 activated=已激活 requires_activation=需要激活 primary_email=设为主邮箱 activate_email=发送激活邮件 activations_pending=等待激活 +can_not_add_email_activations_pending=有一个待处理的激活请求,请稍等几分钟后再尝试添加新的邮箱地址。 delete_email=移除 email_deletion=移除邮箱地址 email_deletion_desc=邮箱地址和相关信息将会被删除。使用此邮箱地址发送的Git提交将会保留,继续? @@ -851,6 +855,7 @@ gpg_key_matched_identities_long=此密钥中包含的身份信息与以下此用 gpg_key_verified=已验证的密钥 gpg_key_verified_long=密钥已通过令牌验证,除与此密钥匹配的任何身份外,还可用于验证与该用户任何已激活邮箱地址匹配的提交。 gpg_key_verify=验证 +gpg_invalid_token_signature=提供的 GPG 密钥、签名和令牌不匹配或过期。 gpg_token_required=您必须为下面的令牌提供签名 gpg_token=令牌 gpg_token_help=您可以使用以下方式生成签名: @@ -860,6 +865,7 @@ verify_gpg_key_success=GPG 密钥「%s」已验证。 ssh_key_verified=已验证的密钥 ssh_key_verified_long=密钥已通过令牌验证,可用于验证与该用户任何已激活邮箱地址匹配的提交。 ssh_key_verify=验证 +ssh_invalid_token_signature=提供的 SSH 密钥、签名或令牌不匹配或令牌已过期。 ssh_token_required=您必须为下面的令牌提供签名 ssh_token=令牌 ssh_token_help=您可以使用以下方式生成签名: @@ -880,6 +886,7 @@ gpg_key_deletion=删除 GPG 密钥 ssh_principal_deletion=删除 SSH 证书规则 ssh_key_deletion_desc=删除 SSH 公钥将取消对应的私钥对您的 Gitea 帐户的访问权限。继续? gpg_key_deletion_desc=删除 GPG 公钥将无法认证对应私钥签名的提交,继续? +ssh_principal_deletion_desc=删除此 SSH 证书规则将取消它对您的账户的访问权限。继续? ssh_key_deletion_success=SSH 密钥已删除。 gpg_key_deletion_success=GPG 密钥已删除。 ssh_principal_deletion_success=此规则删除成功。 @@ -941,6 +948,7 @@ create_oauth2_application_button=创建应用 create_oauth2_application_success=您已成功创建了一个新的 OAuth2 应用。 update_oauth2_application_success=您已成功更新了此 OAuth2 应用。 oauth2_application_name=应用名称 +oauth2_confidential_client=机密客户端。对于需要保密的应用(例如 Web 应用),请选择此选项。对于包括桌面和移动应用在内的本机应用,请勿选择此选项。 oauth2_skip_secondary_authorization=首次授权后允许公共客户端跳过授权步骤。 可能会带来安全风险。 oauth2_redirect_uris=重定向 URI。每行一个 URI。 save_application=保存 @@ -955,8 +963,10 @@ oauth2_application_remove_description=移除一个OAuth2应用将会阻止它访 oauth2_application_locked=如果配置启用,Gitea 将在启动时预注册一些 OAuth2 应用程序。 为了防止意外的行为, 这些应用既不能编辑也不能删除。请参阅 OAuth2 文档以获取更多信息。 authorized_oauth2_applications=已授权的 OAuth2 应用 +authorized_oauth2_applications_description=您已授予这些第三方应用程序访问您的个人 Gitea 账户的权限。请撤销那些您不再需要的应用程序的访问权限。 revoke_key=撤销 revoke_oauth2_grant=撤回权限 +revoke_oauth2_grant_description=确定撤销此三方应用程序的授权,并阻止此应用程序访问您的数据? revoke_oauth2_grant_success=成功撤销了访问权限。 twofa_desc=为保护您的账号密码安全,您可以使用智能手机或其它设备来接收时间强相关的一次性密码(TOTP)。 @@ -982,6 +992,7 @@ webauthn_desc=安全密钥是包含加密密钥的硬件设备。它们可以用 webauthn_register_key=添加安全密钥 webauthn_nickname=昵称 webauthn_delete_key=移除安全密钥 +webauthn_delete_key_desc=如果删除了安全密钥,则不能再使用它登录。继续? webauthn_key_loss_warning=如果您丢失了您的安全密钥,您将无法访问您的帐户。 webauthn_alternative_tip=您可能想要配置额外的身份验证方法。 @@ -1049,6 +1060,7 @@ fork_branch=要克隆为派生的分支 all_branches=所有分支 view_all_branches=查看所有分支 view_all_tags=查看所有标签 +fork_no_valid_owners=这个代码仓库无法被派生,因为没有有效的所有者。 fork.blocked_user=无法克隆仓库,因为您被仓库所有者屏蔽。 use_template=使用此模板 open_with_editor=用 %s 打开 @@ -1093,10 +1105,12 @@ mirror_sync=已同步 mirror_sync_on_commit=推送提交时同步 mirror_address=从 URL 克隆 mirror_address_desc=在授权框中输入必要的凭据。 +mirror_address_url_invalid=提供的 URL 无效。请确保 URL 的所有组成部分均已正确转义。 mirror_address_protocol_invalid=提供的URL无效。只能使用http(s)://或git://地址进行镜像操作。 mirror_lfs=大文件存储 (LFS) mirror_lfs_desc=镜像 LFS 数据。 mirror_lfs_endpoint=LFS 网址 +mirror_lfs_endpoint_desc=同步将尝试使用克隆 URL 来 确定 LFS 服务器。如果仓库 LFS 数据存储在其他位置,您还可以指定自定义网址。 mirror_last_synced=上次同步 mirror_password_placeholder=(未更改) mirror_password_blank_placeholder=(未设置) @@ -1109,6 +1123,7 @@ stars=点赞数 reactions_more=再加载 %d unit_disabled=站点管理员已禁用此仓库单元。 language_other=其它 +adopt_search=输入用户名以搜索未被收录的仓库…(留空以查找全部) adopt_preexisting_label=收录仓库 adopt_preexisting=收录已存在的仓库 adopt_preexisting_content=从 %s 创建仓库 @@ -1150,6 +1165,8 @@ template.issue_labels=工单标签 template.one_item=必须至少选择一个模板项 template.invalid=必须选择一个模板仓库 +archive.title=该仓库已被归档。您可以查看文件和克隆它,但不能创建工单、合并请求或推送提交。 +archive.title_date=该仓库已于 %s 归档。您可以查看文件和克隆它,但不能创建工单、合并请求或推送提交。 archive.issue.nocomment=此仓库已存档,您不能在此工单添加评论。 archive.pull.nocomment=此仓库已存档,您不能在此合并请求添加评论。 @@ -1166,6 +1183,7 @@ migrate_options_lfs=迁移 LFS 文件 migrate_options_lfs_endpoint.label=LFS 网址 migrate_options_lfs_endpoint.description=迁移将尝试使用您的 Git remote 来 确定 LFS 服务器。如果仓库 LFS 数据存储在其他位置,您还可以指定自定义网址。 migrate_options_lfs_endpoint.description.local=支持本地服务器路径。 +migrate_options_lfs_endpoint.placeholder=如果留空,网址将从克隆 URL 中得到 migrate_items=迁移项目 migrate_items_wiki=百科 migrate_items_milestones=里程碑 @@ -1177,6 +1195,7 @@ migrate_items_releases=发布 migrate_repo=迁移仓库 migrate.clone_address=从 URL 迁移/克隆 migrate.clone_address_desc=现有仓库的 HTTP(s) 或 Git "clone" URL +migrate.github_token_desc=您可以在此处输入一个或多个令牌(以逗号分隔),以绕过 GitHub API 速率限制来加快迁移速度。警告:滥用此功能可能会违反服务提供商的政策并导致帐户被封禁。 migrate.clone_local_path=或服务器本地路径 migrate.permission_denied=您没有获得导入本地仓库的权限。 migrate.permission_denied_blocked=您不能从不允许的主机导入,请询问管理员以检查 ALLOWED_DOMAINS/ALLOW_LOCALNETWORKS/BLOCKED_DOMAINS 设置。 @@ -1358,10 +1377,12 @@ 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_modifying_no_longer_exists=正在修改的文件「%s」已不存在于此仓库。 editor.file_changed_while_editing=文件内容在您进行编辑时已经发生变动。单击此处 查看变动的具体内容,或者 再次提交 覆盖已发生的变动。 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=您要提交的文件是空的,继续吗? @@ -1387,6 +1408,7 @@ editor.fork_create_description=您不能直接编辑此仓库。您可以派生 editor.fork_edit_description=您不能直接编辑此仓库。 更改将写入您的派生仓库 %s,以便您可以创建一个合并请求。 editor.fork_not_editable=您已经派生了此仓库,但您的派生是不可编辑的。 editor.fork_failed_to_push_branch=推送分支 %s 到仓库失败。 +editor.fork_branch_exists=分支「%s」已存在于您的派生仓库中,请选择一个新的分支名称。 commits.desc=浏览代码修改历史 commits.commits=次代码提交 @@ -1466,7 +1488,7 @@ issues.filter_assignees=筛选指派人 issues.filter_milestones=筛选里程碑 issues.filter_projects=筛选项目 issues.filter_labels=筛选标签 -issues.filter_reviewers=筛选审核者 +issues.filter_reviewers=筛选评审人 issues.filter_no_results=没有结果 issues.filter_no_results_placeholder=请尝试调整您的搜索过滤器。 issues.new=创建工单 @@ -1486,8 +1508,9 @@ issues.new.clear_milestone=取消选中里程碑 issues.new.assignees=指派成员 issues.new.clear_assignees=取消指派成员 issues.new.no_assignees=未指派成员 -issues.new.no_reviewers=无审核者 +issues.new.no_reviewers=无评审人 issues.new.blocked_user=无法创建工单,因为您已被仓库所有者屏蔽。 +issues.edit.already_changed=无法保存对工单的更改。其内容似乎已被其他用户更改。 请刷新页面并重新编辑以避免覆盖他们的更改。 issues.edit.blocked_user=无法编辑内容,因为您已被仓库所有者或工单创建者屏蔽。 issues.choose.get_started=开始 issues.choose.open_external_link=开启 @@ -1652,7 +1675,7 @@ issues.label_exclusive_warning=在编辑工单或合并请求的标签时,任 issues.label_exclusive_order=排序顺序 issues.label_exclusive_order_tooltip=在同一个范围内的互斥标签将按照这个数字进行排序 issues.label_count=%d 个标签 -issues.label_open_issues=%d 个已打开工单/合并请求 +issues.label_open_issues=%d 个开启的工单/合并请求 issues.label_edit=编辑 issues.label_delete=删除 issues.label_modify=编辑标签 @@ -1681,6 +1704,7 @@ issues.lock_no_reason=锁定并限制仅协作者 %s issues.unlock_comment=解锁此对话 %s issues.lock_confirm=锁定 issues.unlock_confirm=解锁​​​​ +issues.lock.notice_1=- 其他用户不能对这个工单添加新的评论。 issues.lock.notice_2=- 您和仓库其他协作者仍可评论并可见。 issues.lock.notice_3=- 您可以在未来再次解锁这个工单。 issues.unlock.notice_1=- 每个人都可以再次就这一工单发表评论。 @@ -1735,6 +1759,7 @@ issues.due_date_form=yyyy年mm月dd日 issues.due_date_form_add=设置到期时间 issues.due_date_form_edit=编辑 issues.due_date_form_remove=删除 +issues.due_date_not_writer=您需要该仓库的写权限以更新工单的到期日期。 issues.due_date_not_set=未设置到期时间。 issues.due_date_added=于 %[2]s 设置到期时间为 %[1]s issues.due_date_modified=将到期日从 %[2]s 修改为 %[1]s %[3]s @@ -1742,8 +1767,8 @@ issues.due_date_remove=于 %[2]s 删除了到期时间 %[1]s issues.due_date_overdue=过期 issues.due_date_invalid=到期日期无效或超出范围。请使用 'yyyy-mm-dd' 格式。 issues.dependency.title=依赖工单 -issues.dependency.issue_no_dependencies=没有设置依赖项。 -issues.dependency.pr_no_dependencies=没有设置依赖项。 +issues.dependency.issue_no_dependencies=未设置依赖工单。 +issues.dependency.pr_no_dependencies=未设置依赖工单。 issues.dependency.no_permission_1=您没有读取 %d 依赖关系的权限 issues.dependency.no_permission_n=您没有读取 %d 依赖关系的权限 issues.dependency.no_permission.can_remove=您没有读取此依赖关系的权限,但可以删除此依赖关系 @@ -1757,7 +1782,9 @@ issues.dependency.pr_closing_blockedby=以下工单阻止了关闭此合并请 issues.dependency.issue_closing_blockedby=关闭此工单被以下工单阻止 issues.dependency.issue_close_blocks=此工单阻止了以下工单的关闭 issues.dependency.pr_close_blocks=此合并请求阻止以下工单的关闭 +issues.dependency.issue_close_blocked=您需要关闭所有阻止此工单的工单后才能关闭它。 issues.dependency.issue_batch_close_blocked=无法批量关闭您所选择的工单,因为 #%d 工单仍然有处于打开状态的依赖工单 +issues.dependency.pr_close_blocked=您需要关闭所有阻止此合并请求的工单后才能合并它。 issues.dependency.blocks_short=阻止 issues.dependency.blocked_by_short=依赖于 issues.dependency.remove_header=删除依赖项 @@ -1768,6 +1795,7 @@ 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=依赖项已存在。 +issues.dependency.add_error_cannot_create_circular=您无法在相互阻塞的问题之间建立依赖关系。 issues.dependency.add_error_dep_not_same_repo=这两个工单必须在同一仓库。 issues.review.self.approval=您不能批准您自己的合并请求。 issues.review.self.rejection=您不能请求对您自己的合并请求进行更改。 @@ -1803,6 +1831,7 @@ issues.review.requested=等待审核 issues.review.rejected=请求变更 issues.review.stale=批准后已更新 issues.review.unofficial=非官方审批数 +issues.assignee.error=因为未知原因,并非所有的指派都成功。 issues.reference_issue.body=内容 issues.content_history.deleted=已删除 issues.content_history.edited=已编辑 @@ -1819,6 +1848,7 @@ pulls.desc=启用合并请求和代码评审。 pulls.new=创建合并请求 pulls.new.blocked_user=无法创建合并请求,因为您已被仓库所有者屏蔽。 pulls.new.must_collaborator=您必须是仓库的协作者才能创建合并请求。 +pulls.edit.already_changed=无法保存对合并请求的更改。其内容似乎已被其他用户更改。 请刷新页面并重新编辑以避免覆盖他们的更改。 pulls.view=查看合并请求 pulls.compare_changes=创建合并请求 pulls.allow_edits_from_maintainers=允许维护者编辑 @@ -1909,10 +1939,17 @@ pulls.merge_commit_id=合并提交 ID pulls.require_signed_wont_sign=分支需要签名的提交,但这个合并将不会被签名 pulls.invalid_merge_option=您可以在此合并请求中使用合并选项。 +pulls.merge_conflict=合并失败:合并时有冲突发生。提示:采用其它合并策略。 pulls.merge_conflict_summary=错误信息 +pulls.rebase_conflict=合并失败:变基提交有冲突:%[1]s。提示:采用其它合并策略。 pulls.rebase_conflict_summary=错误信息 +pulls.unrelated_histories=合并失败:两个分支没有共同历史。提示:尝试不同的策略。 +pulls.merge_out_of_date=合并失败:在生成合并时,主分支已更新。提示:再试一次。 +pulls.head_out_of_date=合并失败:在生成合并时,head 已更新。提示:再试一次。 +pulls.has_merged=失败:合并请求已经合并。您不能再次合并或更改目标分支。 pulls.push_rejected=推送失败:推送被拒绝。审查此仓库的 Git 钩子。 pulls.push_rejected_summary=详细拒绝信息 +pulls.push_rejected_no_message=推送失败:此推送被拒绝但未提供其他信息。请检查此仓库的 Git 钩子。 pulls.open_unmerged_pull_exists=`您不能执行重新打开操作, 因为已经存在相同的合并请求 (#%d)。` pulls.status_checking=一些检测仍在等待运行 pulls.status_checks_success=所有检测均成功 @@ -1938,6 +1975,7 @@ pulls.cmd_instruction_merge_title=合并 pulls.cmd_instruction_merge_desc=合并变更并更新到 Gitea 上 pulls.cmd_instruction_merge_warning=警告:此操作不能合并该合并请求,因为「自动检测手动合并」未启用 pulls.clear_merge_message=清除合并信息 +pulls.clear_merge_message_hint=清除合并消息只会删除提交消息内容,并保留生成的 Git 附加内容,如「Co-Authored-By…」。 pulls.auto_merge_button_when_succeed=(当检查成功时) pulls.auto_merge_when_succeed=在所有检查成功后自动合并 @@ -1998,10 +2036,12 @@ milestones.filter_sort.most_issues=工单从多到少 milestones.filter_sort.least_issues=工单从少到多 signing.will_sign=这个提交将用密钥「%s」签名。 +signing.wont_sign.error=在检查提交是否可以被签名时出错。 signing.wont_sign.nokey=没有可用的密钥来签署这个提交。 signing.wont_sign.never=提交从未签名。 signing.wont_sign.always=提交总是签名。 signing.wont_sign.pubkey=由于您没有公钥关联到您的账户,提交将不会被签名。 +signing.wont_sign.twofa=您必须启用两步验证才能签名提交。 signing.wont_sign.parentsigned=提交将不会被签名,因为父提交没有签名。 signing.wont_sign.basesigned=合并将不会被签名,因为父提交没有签名。 signing.wont_sign.headsigned=合并将不会被签名,因为最新提交没有签名。 @@ -2076,7 +2116,7 @@ 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=已打开的工单 +activity.new_issues_count_1=开启的工单 activity.new_issues_count_n=已打开的工单 activity.new_issue_label=打开的 activity.title.unresolved_conv_1=%d 未解决的会话 @@ -2087,6 +2127,7 @@ 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 位作者 @@ -2114,11 +2155,13 @@ contributors.contribution_type.additions=新增 contributors.contribution_type.deletions=删除 settings=设置 +settings.desc=设置是您可以管理仓库设置的地方。 settings.options=仓库 settings.public_access=公开访问 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=所有人可写:所有登录用户都有写入权限。只有百科支持此权限。 settings.collaboration=协作者 settings.collaboration.admin=管理员 @@ -2136,6 +2179,7 @@ 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.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=您可以在这里找到更多关于推送和拉取镜像的信息: @@ -2210,6 +2254,7 @@ settings.admin_indexer_commit_sha=上次索引的 SHA settings.admin_indexer_unindexed=未索引 settings.reindex_button=添加到重新索引队列 settings.reindex_requested=已请求重新索引 +settings.admin_enable_close_issues_via_commit_in_any_branch=通过在非默认分支中提交来关闭工单 settings.danger_zone=危险操作区 settings.new_owner_has_same_repo=新的仓库拥有者已经存在同名仓库! settings.convert=转换为普通仓库 @@ -2231,6 +2276,7 @@ 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=- 如果仓库是私有的并且被转移给某个用户,那么此操作可以确保该用户至少具有读权限(以及必要时的更改权限)。 @@ -2245,9 +2291,13 @@ settings.trust_model.default=默认信任模型 settings.trust_model.default.desc=为此安装使用默认仓库信任模型。 settings.trust_model.collaborator=协作者 settings.trust_model.collaborator.long=协作者:信任协作者的签名 +settings.trust_model.collaborator.desc=此仓库中协作者的有效签名将被标记为「可信」(无论它们是否是提交者),签名只符合提交者时将标记为「不可信」,都不匹配时标记为「不匹配」。 settings.trust_model.committer=提交者 +settings.trust_model.committer.long=提交者: 信任与提交者相符的签名(这符合 GitHub 的行为并将强制 Gitea 签名的提交以 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 签名密钥必须匹配数据库中的一个用户密钥。 settings.wiki_delete=删除百科数据 settings.wiki_delete_desc=删除仓库百科数据是永久性的,无法撤消。 settings.wiki_delete_notices_1=- 这将永久删除和禁用 %s 的百科。 @@ -2256,6 +2306,7 @@ settings.wiki_deletion_success=仓库百科数据删除成功! settings.delete=删除本仓库 settings.delete_desc=删除仓库是永久性的, 无法撤消。 settings.delete_notices_1=- 此操作 无法 被回滚。 +settings.delete_notices_2=- 此操作将永久删除仓库 %s,包括代码、 工单、评论、百科数据和协作者设置。 settings.delete_notices_fork_1=- 在此仓库删除后,它的派生仓库将变成独立仓库。 settings.deletion_success=仓库已删除。 settings.update_settings_success=仓库设置已更新。 @@ -2277,6 +2328,8 @@ settings.team_not_in_organization=团队不在与仓库相同的组织中 settings.teams=团队 settings.add_team=添加团队 settings.add_team_duplicate=团队已经拥有仓库 +settings.add_team_success=团队现在可以访问仓库。 +settings.change_team_permission_tip=团队权限设置于团队设置页面,不能根据仓库更改 settings.delete_team_tip=该团队仍有仓库, 无法删除 settings.remove_team_success=团队访问仓库的权限已删除。 settings.add_webhook=添加 Web 钩子 @@ -2492,6 +2545,7 @@ settings.block_on_official_review_requests_desc=处于评审状态时,即使 settings.block_outdated_branch=如果合并请求已经过时,阻止合并 settings.block_outdated_branch_desc=当头部分支落后基础分支时,不能合并。 settings.block_admin_merge_override=管理员须遵守分支保护规则 +settings.block_admin_merge_override_desc=管理员须遵守分支保护规则,不能规避该规则。 settings.default_branch_desc=请选择一个默认的分支用于合并请求和提交: settings.merge_style_desc=合并方式 settings.default_merge_style_desc=默认合并风格 @@ -2518,7 +2572,10 @@ settings.matrix.homeserver_url=主服务器网址 settings.matrix.room_id=房间ID settings.matrix.message_type=消息类型 settings.visibility.private.button=设为私有 +settings.visibility.private.text=将可见性更改为私有会使仓库仅对允许的成员可见,而且可能会消除它与派生仓库、关注者和点赞之间的关系。 settings.visibility.private.bullet_title=将可见性改为私有将会: +settings.visibility.private.bullet_one=使仓库只对允许的成员可见。 +settings.visibility.private.bullet_two=可能会删除它与 派生仓库关注者点赞 之间的关系。 settings.visibility.public.button=设为公开 settings.visibility.public.text=将可见性更改为公开会使任何人都可见。 settings.visibility.public.bullet_title=将可见性改为公开将会: @@ -2528,7 +2585,7 @@ 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=请不要对镜像仓库归档,谢谢! @@ -2537,6 +2594,7 @@ settings.archive.tagsettings_unavailable=已归档仓库的标签设置不可用 settings.archive.mirrors_unavailable=如果仓库已归档,镜像将不可用。 settings.unarchive.button=撤销仓库归档 settings.unarchive.header=撤销此仓库归档 +settings.unarchive.text=撤销归档将恢复仓库接收提交、推送,以及新工单和合并请求的能力。 settings.unarchive.success=仓库已成功撤销归档。 settings.unarchive.error=仓库在取消归档时出现异常。请通过日志获取详细信息。 settings.update_avatar_success=仓库头像已经更新。 @@ -2554,6 +2612,7 @@ settings.lfs_invalid_locking_path=无效路径:%s settings.lfs_invalid_lock_directory=无法锁定目录:%s settings.lfs_lock_already_exists=锁已经存在:%s settings.lfs_lock=锁定 +settings.lfs_lock_path=要锁定的文件路径… settings.lfs_locks_no_locks=无锁定 settings.lfs_lock_file_no_exist=锁定的文件在默认分支中不存在 settings.lfs_force_unlock=强制解锁 @@ -2715,6 +2774,7 @@ branch.new_branch_from=基于「%s」创建新分支 branch.renamed=分支 %s 已重命名为 %s。 branch.rename_default_or_protected_branch_error=只有管理员能重命名默认分支和受保护的分支。 branch.rename_protected_branch_failed=此分支受到 glob 语法规则的保护。 +branch.commits_divergence_from=提交分歧:落后 %[3]s %[1]d 个提交,领先 %[2]d 个提交 branch.commits_no_divergence=与分支 %[1]s 相同 tag.create_tag=创建标签 %s @@ -2959,6 +3019,7 @@ dashboard.update_migration_poster_id=更新迁移的发表者ID dashboard.git_gc_repos=对仓库进行垃圾回收 dashboard.resync_all_sshkeys=使用 Gitea 的 SSH 密钥更新「.ssh/authorized_keys」文件。 dashboard.resync_all_sshprincipals=使用 Gitea 的 SSH 规则更新「.ssh/authorized_principals」文件。 +dashboard.resync_all_hooks=重新同步所有仓库的 pre-receive、update 和 post-receive 钩子 dashboard.reinit_missing_repos=重新初始化所有丢失的 Git 仓库存在的记录 dashboard.sync_external_users=同步外部用户数据 dashboard.cleanup_hook_task_table=清理 hook_task 表 @@ -3202,11 +3263,15 @@ auths.oauth2_map_group_to_team=映射声明的组到组织团队。(可选 - auths.oauth2_map_group_to_team_removal=如果用户不属于相应的组,从已同步团队中移除用户 auths.enable_auto_register=允许用户自动注册 auths.sspi_auto_create_users=自动创建用户 +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_separator_replacement=要使用的分隔符代替\, / 和 @ +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 应该是: @@ -3331,10 +3396,10 @@ config.test_mail_sent=测试邮件已经发送至「%s」。 config.oauth_config=OAuth 配置 config.oauth_enabled=启用 -config.cache_config=Cache 配置 -config.cache_adapter=Cache 适配器 -config.cache_interval=Cache 周期 -config.cache_conn=Cache 连接字符串 +config.cache_config=缓存配置 +config.cache_adapter=缓存适配器 +config.cache_interval=缓存周期 +config.cache_conn=缓存连接字符串 config.cache_item_ttl=缓存项目 TTL config.cache_test=测试缓存 config.cache_test_failed=缓存测试失败: %v。 @@ -3373,7 +3438,7 @@ config.logger_name_fmt=日志:%s config.disabled_logger=禁用 config.access_log_mode=访问日志模式 config.access_log_template=访问日志模板 -config.xorm_log_sql=日志 SQL +config.xorm_log_sql=SQL 日志 config.set_setting_failed=设置 %s 失败 @@ -3524,6 +3589,8 @@ error.no_committer_account=没有帐户链接到提交者的邮箱 error.no_gpg_keys_found=找不到此签名对应的密钥 error.not_signed_commit=未签名的提交 error.failed_retrieval_gpg_keys=找不到任何与该提交者账号相关的密钥 +error.probable_bad_signature=警告!虽然数据库中有一个此 ID 的密钥,但它没有验证此提交!此提交是可疑的。 +error.probable_bad_default_signature=警告!虽然默认密钥拥有此 ID,但它没有验证此提交!此提交是可疑的。 [units] unit=单元 @@ -3562,6 +3629,7 @@ versions.view_all=查看全部 dependency.id=ID dependency.version=版本 search_in_external_registry=在 %s 中搜索 +alpine.registry=通过在您的 /etc/apk/repositories 文件中添加 URL 来设置此注册中心: alpine.registry.key=下载注册中心公开的 RSA 密钥到 /etc/apk/keys/ 文件夹来验证索引签名: alpine.registry.info=从下面的列表中选择 $branch 和 $repository。 alpine.install=要安装软件包,请运行以下命令: @@ -3574,13 +3642,18 @@ arch.install=使用 pacman 同步软件包: arch.repository=仓库信息 arch.repository.repositories=仓库 arch.repository.architectures=架构 +cargo.registry=在 Cargo 配置文件中设置此注册中心(例如:~/.cargo/config.toml): cargo.install=要使用 Cargo 安装软件包,请运行以下命令: +chef.registry=在您的 ~/.chef/config.rb 文件中设置此注册中心: chef.install=要安装软件包,请运行以下命令: +composer.registry=在您的 ~/.composer/config.json 文件中设置此注册中心: composer.install=要使用 Composer 安装软件包,请运行以下命令: composer.dependencies=依赖 composer.dependencies.development=开发依赖 conan.details.repository=仓库 +conan.registry=从命令行设置此注册中心: conan.install=要使用 Conan 安装软件包,请运行以下命令: +conda.registry=在您的 .condarc 文件中将此注册中心设置为 Conda 仓库: conda.install=要使用 Conda 安装软件包,请运行以下命令: container.details.type=镜像类型 container.details.platform=平台 @@ -3592,6 +3665,7 @@ container.layers=镜像层 container.labels=标签 container.labels.key=键 container.labels.value=值 +cran.registry=在您的 Rprofile.site 文件中设置此注册中心: cran.install=要安装软件包,请运行以下命令: debian.registry=从命令行设置此注册中心: debian.registry.info=从下面的列表中选择 $distribution 和 $component。 @@ -3604,10 +3678,14 @@ generic.download=从命令行下载软件包: go.install=通过命令行安装软件包: helm.registry=从命令行设置此注册中心: helm.install=要安装包,请运行以下命令: +maven.registry=在您项目的 pom.xml 文件中设置此注册中心: +maven.install=要使用这个软件包,在 pom.xml 文件中的 依赖项 块中包含以下内容: maven.install2=通过命令行运行: maven.download=要下载依赖项,请通过命令行运行: +nuget.registry=从命令行设置此注册中心: nuget.install=要使用 Nuget 安装软件包,请运行以下命令: nuget.dependency.framework=目标框架 +npm.registry=在您项目的 .npmrc 文件中设置此注册中心: npm.install=要使用 npm 安装软件包,请运行以下命令: npm.install2=或将其添加到 package.json 文件: npm.dependencies=依赖项 @@ -3619,6 +3697,7 @@ npm.details.tag=标签 pub.install=要使用 Dart 安装软件包,请运行以下命令: pypi.requires=需要 Python pypi.install=要使用 pip 安装软件包,请运行以下命令: +rpm.registry=从命令行设置此仓库: rpm.distros.redhat=在基于 RedHat 的发行版 rpm.distros.suse=在基于 SUSE 的发行版 rpm.install=要安装软件包,请运行以下命令: @@ -3631,6 +3710,7 @@ rubygems.dependencies.runtime=运行时依赖 rubygems.dependencies.development=开发依赖 rubygems.required.ruby=需要 Ruby 版本 rubygems.required.rubygems=需要 RubyGem 版本 +swift.registry=从命令行设置此仓库: swift.install=在您的 Package.swift文件中添加该包: swift.install2=并运行以下命令: vagrant.install=若要添加一个 Vagrant box,请运行以下命令: From ee4459488a83211bd33a8e04c2991c415cdba89b Mon Sep 17 00:00:00 2001 From: Karl T Date: Thu, 14 Aug 2025 08:30:35 +0200 Subject: [PATCH 11/97] OneDev migration: fix broken migration caused by various REST API changes in OneDev 7.8.0 and later (#35216) OneDev migration: fix broken migration caused by various REST API changes in OneDev 7.8.0 and later - in REST urls use `~api` instead of `api` - check minimum required OneDev version before starting migration - required OneDev version is now 12.0.1 (older versions do not offer necessary API: https://code.onedev.io/onedev/server/~issues/2491) - support migrating OneDev subprojects (e.g. http:/onedev.host/projectA/subProjectB) - set milestone closed state if milestone is closed in OneDev - moved memory allocation for milestone JSON decoding into for loop (which gets 100 milestones per iteration) to fix wrong due dates when having more than 100 milestones --- services/migrations/onedev.go | 273 ++++++++++++++++++++-------------- 1 file changed, 162 insertions(+), 111 deletions(-) diff --git a/services/migrations/onedev.go b/services/migrations/onedev.go index e052cba0cc..9917bdae3c 100644 --- a/services/migrations/onedev.go +++ b/services/migrations/onedev.go @@ -6,6 +6,7 @@ package migrations import ( "context" "fmt" + "io" "net/http" "net/url" "strconv" @@ -16,8 +17,12 @@ import ( "code.gitea.io/gitea/modules/log" base "code.gitea.io/gitea/modules/migration" "code.gitea.io/gitea/modules/structs" + + "github.com/hashicorp/go-version" ) +const OneDevRequiredVersion = "12.0.1" + var ( _ base.Downloader = &OneDevDownloader{} _ base.DownloaderFactory = &OneDevDownloaderFactory{} @@ -37,23 +42,14 @@ func (f *OneDevDownloaderFactory) New(ctx context.Context, opts base.MigrateOpti return nil, err } - var repoName string - - fields := strings.Split(strings.Trim(u.Path, "/"), "/") - if len(fields) == 2 && fields[0] == "projects" { - repoName = fields[1] - } else if len(fields) == 1 { - repoName = fields[0] - } else { - return nil, fmt.Errorf("invalid path: %s", u.Path) - } + repoPath := strings.Trim(u.Path, "/") u.Path = "" u.Fragment = "" - log.Trace("Create onedev downloader. BaseURL: %v RepoName: %s", u, repoName) + log.Trace("Create onedev downloader. BaseURL: %v RepoPath: %s", u, repoPath) - return NewOneDevDownloader(ctx, u, opts.AuthUsername, opts.AuthPassword, repoName), nil + return NewOneDevDownloader(ctx, u, opts.AuthUsername, opts.AuthPassword, repoPath), nil } // GitServiceType returns the type of git service @@ -62,9 +58,9 @@ func (f *OneDevDownloaderFactory) GitServiceType() structs.GitServiceType { } type onedevUser struct { - ID int64 `json:"id"` - Name string `json:"name"` - Email string `json:"email"` + ID int64 + Name string + Email string } // OneDevDownloader implements a Downloader interface to get repository information @@ -73,7 +69,7 @@ type OneDevDownloader struct { base.NullDownloader client *http.Client baseURL *url.URL - repoName string + repoPath string repoID int64 maxIssueIndex int64 userMap map[int64]*onedevUser @@ -81,10 +77,10 @@ type OneDevDownloader struct { } // NewOneDevDownloader creates a new downloader -func NewOneDevDownloader(_ context.Context, baseURL *url.URL, username, password, repoName string) *OneDevDownloader { +func NewOneDevDownloader(_ context.Context, baseURL *url.URL, username, password, repoPath string) *OneDevDownloader { downloader := &OneDevDownloader{ baseURL: baseURL, - repoName: repoName, + repoPath: repoPath, client: &http.Client{ Transport: &http.Transport{ Proxy: func(req *http.Request) (*url.URL, error) { @@ -104,14 +100,14 @@ func NewOneDevDownloader(_ context.Context, baseURL *url.URL, username, password // String implements Stringer func (d *OneDevDownloader) String() string { - return fmt.Sprintf("migration from oneDev server %s [%d]/%s", d.baseURL, d.repoID, d.repoName) + return fmt.Sprintf("migration from oneDev server %s [%d]/%s", d.baseURL, d.repoID, d.repoPath) } func (d *OneDevDownloader) LogString() string { if d == nil { return "" } - return fmt.Sprintf("", d.baseURL, d.repoID, d.repoName) + return fmt.Sprintf("", d.baseURL, d.repoID, d.repoPath) } func (d *OneDevDownloader) callAPI(ctx context.Context, endpoint string, parameter map[string]string, result any) error { @@ -139,23 +135,54 @@ func (d *OneDevDownloader) callAPI(ctx context.Context, endpoint string, paramet } defer resp.Body.Close() + // special case to read OneDev server version, which is not valid JSON + if presult, ok := result.(**version.Version); ok { + bytes, err := io.ReadAll(resp.Body) + if err != nil { + return err + } + vers, err := version.NewVersion(string(bytes)) + if err != nil { + return err + } + *presult = vers + return nil + } + decoder := json.NewDecoder(resp.Body) return decoder.Decode(&result) } // GetRepoInfo returns repository information func (d *OneDevDownloader) GetRepoInfo(ctx context.Context) (*base.Repository, error) { + // check OneDev server version + var serverVersion *version.Version + err := d.callAPI( + ctx, + "/~api/version/server", + nil, + &serverVersion, + ) + if err != nil { + return nil, fmt.Errorf("failed to get OneDev server version; OneDev %s or newer required", OneDevRequiredVersion) + } + requiredVersion, _ := version.NewVersion(OneDevRequiredVersion) + if serverVersion.LessThan(requiredVersion) { + return nil, fmt.Errorf("OneDev %s or newer required; currently running OneDev %s", OneDevRequiredVersion, serverVersion) + } + info := make([]struct { ID int64 `json:"id"` Name string `json:"name"` + Path string `json:"path"` Description string `json:"description"` }, 0, 1) - err := d.callAPI( + err = d.callAPI( ctx, - "/api/projects", + "/~api/projects", map[string]string{ - "query": `"Name" is "` + d.repoName + `"`, + "query": `"Path" is "` + d.repoPath + `"`, "offset": "0", "count": "1", }, @@ -165,16 +192,12 @@ func (d *OneDevDownloader) GetRepoInfo(ctx context.Context) (*base.Repository, e return nil, err } if len(info) != 1 { - return nil, fmt.Errorf("Project %s not found", d.repoName) + return nil, fmt.Errorf("Project %s not found", d.repoPath) } d.repoID = info[0].ID - cloneURL, err := d.baseURL.Parse(info[0].Name) - if err != nil { - return nil, err - } - originalURL, err := d.baseURL.Parse("/projects/" + info[0].Name) + cloneURL, err := d.baseURL.Parse(info[0].Path) if err != nil { return nil, err } @@ -183,25 +206,25 @@ func (d *OneDevDownloader) GetRepoInfo(ctx context.Context) (*base.Repository, e Name: info[0].Name, Description: info[0].Description, CloneURL: cloneURL.String(), - OriginalURL: originalURL.String(), + OriginalURL: cloneURL.String(), }, nil } // GetMilestones returns milestones func (d *OneDevDownloader) GetMilestones(ctx context.Context) ([]*base.Milestone, error) { - rawMilestones := make([]struct { - ID int64 `json:"id"` - Name string `json:"name"` - Description string `json:"description"` - DueDate *time.Time `json:"dueDate"` - Closed bool `json:"closed"` - }, 0, 100) - - endpoint := fmt.Sprintf("/api/projects/%d/milestones", d.repoID) + endpoint := fmt.Sprintf("/~api/projects/%d/iterations", d.repoID) milestones := make([]*base.Milestone, 0, 100) offset := 0 for { + rawMilestones := make([]struct { + ID int64 `json:"id"` + Name string `json:"name"` + Description string `json:"description"` + DueDay int64 `json:"dueDay"` + Closed bool `json:"closed"` + }, 0, 100) + err := d.callAPI( ctx, endpoint, @@ -221,16 +244,26 @@ func (d *OneDevDownloader) GetMilestones(ctx context.Context) ([]*base.Milestone for _, milestone := range rawMilestones { d.milestoneMap[milestone.ID] = milestone.Name - closed := milestone.DueDate - if !milestone.Closed { - closed = nil + + var dueDate *time.Time + if milestone.DueDay != 0 { + d := time.Unix(milestone.DueDay*24*60*60, 0) + dueDate = &d + } + + var closedDate *time.Time + state := "open" + if milestone.Closed { + closedDate = dueDate + state = "closed" } milestones = append(milestones, &base.Milestone{ Title: milestone.Name, Description: milestone.Description, - Deadline: milestone.DueDate, - Closed: closed, + Deadline: dueDate, + Closed: closedDate, + State: state, }) } } @@ -273,6 +306,10 @@ type onedevIssueContext struct { // GetIssues returns issues func (d *OneDevDownloader) GetIssues(ctx context.Context, page, perPage int) ([]*base.Issue, bool, error) { + type Field struct { + Name string `json:"name"` + Value string `json:"value"` + } rawIssues := make([]struct { ID int64 `json:"id"` Number int64 `json:"number"` @@ -281,15 +318,17 @@ func (d *OneDevDownloader) GetIssues(ctx context.Context, page, perPage int) ([] Description string `json:"description"` SubmitterID int64 `json:"submitterId"` SubmitDate time.Time `json:"submitDate"` + Fields []Field `json:"fields"` }, 0, perPage) err := d.callAPI( ctx, - "/api/issues", + "/~api/issues", map[string]string{ - "query": `"Project" is "` + d.repoName + `"`, - "offset": strconv.Itoa((page - 1) * perPage), - "count": strconv.Itoa(perPage), + "query": `"Project" is "` + d.repoPath + `"`, + "offset": strconv.Itoa((page - 1) * perPage), + "count": strconv.Itoa(perPage), + "withFields": "true", }, &rawIssues, ) @@ -299,22 +338,8 @@ func (d *OneDevDownloader) GetIssues(ctx context.Context, page, perPage int) ([] issues := make([]*base.Issue, 0, len(rawIssues)) for _, issue := range rawIssues { - fields := make([]struct { - Name string `json:"name"` - Value string `json:"value"` - }, 0, 10) - err := d.callAPI( - ctx, - fmt.Sprintf("/api/issues/%d/fields", issue.ID), - nil, - &fields, - ) - if err != nil { - return nil, false, err - } - var label *base.Label - for _, field := range fields { + for _, field := range issue.Fields { if field.Name == "Type" { label = &base.Label{Name: field.Value} break @@ -327,7 +352,7 @@ func (d *OneDevDownloader) GetIssues(ctx context.Context, page, perPage int) ([] }, 0, 10) err = d.callAPI( ctx, - fmt.Sprintf("/api/issues/%d/milestones", issue.ID), + fmt.Sprintf("/~api/issues/%d/iterations", issue.ID), nil, &milestones, ) @@ -383,9 +408,9 @@ func (d *OneDevDownloader) GetComments(ctx context.Context, commentable base.Com var endpoint string if context.IsPullRequest { - endpoint = fmt.Sprintf("/api/pull-requests/%d/comments", commentable.GetForeignIndex()) + endpoint = fmt.Sprintf("/~api/pulls/%d/comments", commentable.GetForeignIndex()) } else { - endpoint = fmt.Sprintf("/api/issues/%d/comments", commentable.GetForeignIndex()) + endpoint = fmt.Sprintf("/~api/issues/%d/comments", commentable.GetForeignIndex()) } err := d.callAPI( @@ -405,9 +430,9 @@ func (d *OneDevDownloader) GetComments(ctx context.Context, commentable base.Com }, 0, 100) if context.IsPullRequest { - endpoint = fmt.Sprintf("/api/pull-requests/%d/changes", commentable.GetForeignIndex()) + endpoint = fmt.Sprintf("/~api/pulls/%d/changes", commentable.GetForeignIndex()) } else { - endpoint = fmt.Sprintf("/api/issues/%d/changes", commentable.GetForeignIndex()) + endpoint = fmt.Sprintf("/~api/issues/%d/changes", commentable.GetForeignIndex()) } err = d.callAPI( @@ -468,26 +493,24 @@ func (d *OneDevDownloader) GetComments(ctx context.Context, commentable base.Com // GetPullRequests returns pull requests func (d *OneDevDownloader) GetPullRequests(ctx context.Context, page, perPage int) ([]*base.PullRequest, bool, error) { rawPullRequests := make([]struct { - ID int64 `json:"id"` - Number int64 `json:"number"` - Title string `json:"title"` - SubmitterID int64 `json:"submitterId"` - SubmitDate time.Time `json:"submitDate"` - Description string `json:"description"` - TargetBranch string `json:"targetBranch"` - SourceBranch string `json:"sourceBranch"` - BaseCommitHash string `json:"baseCommitHash"` - CloseInfo *struct { - Date *time.Time `json:"date"` - Status string `json:"status"` - } + ID int64 `json:"id"` + Number int64 `json:"number"` + Title string `json:"title"` + SubmitterID int64 `json:"submitterId"` + SubmitDate time.Time `json:"submitDate"` + Description string `json:"description"` + TargetBranch string `json:"targetBranch"` + SourceBranch string `json:"sourceBranch"` + BaseCommitHash string `json:"baseCommitHash"` + CloseDate *time.Time `json:"closeDate"` + Status string `json:"status"` // Possible values: OPEN, MERGED, DISCARDED }, 0, perPage) err := d.callAPI( ctx, - "/api/pull-requests", + "/~api/pulls", map[string]string{ - "query": `"Target Project" is "` + d.repoName + `"`, + "query": `"Target Project" is "` + d.repoPath + `"`, "offset": strconv.Itoa((page - 1) * perPage), "count": strconv.Itoa(perPage), }, @@ -507,7 +530,7 @@ func (d *OneDevDownloader) GetPullRequests(ctx context.Context, page, perPage in } err := d.callAPI( ctx, - fmt.Sprintf("/api/pull-requests/%d/merge-preview", pr.ID), + fmt.Sprintf("/~api/pulls/%d/merge-preview", pr.ID), nil, &mergePreview, ) @@ -519,12 +542,12 @@ func (d *OneDevDownloader) GetPullRequests(ctx context.Context, page, perPage in merged := false var closeTime *time.Time var mergedTime *time.Time - if pr.CloseInfo != nil { + if pr.Status != "OPEN" { state = "closed" - closeTime = pr.CloseInfo.Date - if pr.CloseInfo.Status == "MERGED" { // "DISCARDED" + closeTime = pr.CloseDate + if pr.Status == "MERGED" { // "DISCARDED" merged = true - mergedTime = pr.CloseInfo.Date + mergedTime = pr.CloseDate } } poster := d.tryGetUser(ctx, pr.SubmitterID) @@ -545,12 +568,12 @@ func (d *OneDevDownloader) GetPullRequests(ctx context.Context, page, perPage in Head: base.PullRequestBranch{ Ref: pr.SourceBranch, SHA: mergePreview.HeadCommitHash, - RepoName: d.repoName, + RepoName: d.repoPath, }, Base: base.PullRequestBranch{ Ref: pr.TargetBranch, SHA: mergePreview.TargetHeadCommitHash, - RepoName: d.repoName, + RepoName: d.repoPath, }, ForeignIndex: pr.ID, Context: onedevIssueContext{IsPullRequest: true}, @@ -566,18 +589,14 @@ func (d *OneDevDownloader) GetPullRequests(ctx context.Context, page, perPage in // GetReviews returns pull requests reviews func (d *OneDevDownloader) GetReviews(ctx context.Context, reviewable base.Reviewable) ([]*base.Review, error) { rawReviews := make([]struct { - ID int64 `json:"id"` - UserID int64 `json:"userId"` - Result *struct { - Commit string `json:"commit"` - Approved bool `json:"approved"` - Comment string `json:"comment"` - } + ID int64 `json:"id"` + UserID int64 `json:"userId"` + Status string `json:"status"` // Possible values: PENDING, APPROVED, REQUESTED_FOR_CHANGES, EXCLUDED }, 0, 100) err := d.callAPI( ctx, - fmt.Sprintf("/api/pull-requests/%d/reviews", reviewable.GetForeignIndex()), + fmt.Sprintf("/~api/pulls/%d/reviews", reviewable.GetForeignIndex()), nil, &rawReviews, ) @@ -589,14 +608,11 @@ func (d *OneDevDownloader) GetReviews(ctx context.Context, reviewable base.Revie for _, review := range rawReviews { state := base.ReviewStatePending content := "" - if review.Result != nil { - if len(review.Result.Comment) > 0 { - state = base.ReviewStateCommented - content = review.Result.Comment - } - if review.Result.Approved { - state = base.ReviewStateApproved - } + switch review.Status { + case "APPROVED": + state = base.ReviewStateApproved + case "REQUESTED_FOR_CHANGES": + state = base.ReviewStateChangesRequested } poster := d.tryGetUser(ctx, review.UserID) @@ -620,17 +636,52 @@ func (d *OneDevDownloader) GetTopics(_ context.Context) ([]string, error) { func (d *OneDevDownloader) tryGetUser(ctx context.Context, userID int64) *onedevUser { user, ok := d.userMap[userID] if !ok { + // get user name + type RawUser struct { + Name string `json:"name"` + } + var rawUser RawUser err := d.callAPI( ctx, - fmt.Sprintf("/api/users/%d", userID), + fmt.Sprintf("/~api/users/%d", userID), nil, - &user, + &rawUser, ) - if err != nil { - user = &onedevUser{ - Name: fmt.Sprintf("User %d", userID), + var userName string + if err == nil { + userName = rawUser.Name + } else { + userName = fmt.Sprintf("User %d", userID) + } + + // get (primary) user Email address + rawEmailAddresses := make([]struct { + Value string `json:"value"` + Primary bool `json:"primary"` + }, 0, 10) + err = d.callAPI( + ctx, + fmt.Sprintf("/~api/users/%d/email-addresses", userID), + nil, + &rawEmailAddresses, + ) + var userEmail string + if err == nil { + for _, email := range rawEmailAddresses { + if userEmail == "" || email.Primary { + userEmail = email.Value + } + if email.Primary { + break + } } } + + user = &onedevUser{ + ID: userID, + Name: userName, + Email: userEmail, + } d.userMap[userID] = user } From 4ff8cdf8264271a91352170bdfb804c8c7a9f9cc Mon Sep 17 00:00:00 2001 From: Tim Biermann Date: Thu, 14 Aug 2025 08:57:05 +0200 Subject: [PATCH 12/97] Fix token lifetime, closes #35230 (#35271) This is an attempt to fix #35230 as discussed in the ticket. --- services/actions/auth.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/services/actions/auth.go b/services/actions/auth.go index 12a8fba53f..c742e19c60 100644 --- a/services/actions/auth.go +++ b/services/actions/auth.go @@ -53,7 +53,7 @@ func CreateAuthorizationToken(taskID, runID, jobID int64) (string, error) { claims := actionsClaims{ RegisteredClaims: jwt.RegisteredClaims{ - ExpiresAt: jwt.NewNumericDate(now.Add(24 * time.Hour)), + ExpiresAt: jwt.NewNumericDate(now.Add(1*time.Hour + setting.Actions.EndlessTaskTimeout)), NotBefore: jwt.NewNumericDate(now), }, Scp: fmt.Sprintf("Actions.Results:%d:%d", runID, jobID), From d9a2dfd95e4f73f62c6dd0772ab3776defc097fd Mon Sep 17 00:00:00 2001 From: techknowlogick Date: Thu, 14 Aug 2025 14:39:38 -0400 Subject: [PATCH 13/97] fix nix dev shell on darwin (#35278) --- flake.lock | 6 ++--- flake.nix | 68 ++++++++++++++++++++++++++++++++---------------------- 2 files changed, 43 insertions(+), 31 deletions(-) diff --git a/flake.lock b/flake.lock index 67f87dfaf6..1aa393f27b 100644 --- a/flake.lock +++ b/flake.lock @@ -20,11 +20,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1752480373, - "narHash": "sha256-JHQbm+OcGp32wAsXTE/FLYGNpb+4GLi5oTvCxwSoBOA=", + "lastModified": 1755027561, + "narHash": "sha256-IVft239Bc8p8Dtvf7UAACMG5P3ZV+3/aO28gXpGtMXI=", "owner": "nixos", "repo": "nixpkgs", - "rev": "62e0f05ede1da0d54515d4ea8ce9c733f12d9f08", + "rev": "005433b926e16227259a1843015b5b2b7f7d1fc3", "type": "github" }, "original": { diff --git a/flake.nix b/flake.nix index 13aa5008e6..29730e8c16 100644 --- a/flake.nix +++ b/flake.nix @@ -18,38 +18,50 @@ go = go_1_24; nodejs = nodejs_24; python3 = python312; - in - pkgs.mkShell { - buildInputs = [ - # generic - git - git-lfs - gnumake - gnused - gnutar - gzip - # frontend - nodejs - - # linting - python3 - uv - - # backend - go + # Platform-specific dependencies + linuxOnlyInputs = lib.optionals pkgs.stdenv.isLinux [ glibc.static - gofumpt - sqlite ]; - CFLAGS = "-I${glibc.static.dev}/include"; - LDFLAGS = "-L ${glibc.static}/lib"; - GO = "${go}/bin/go"; - GOROOT = "${go}/share/go"; - TAGS = "sqlite sqlite_unlock_notify"; - STATIC = "true"; - }; + linuxOnlyEnv = lib.optionalAttrs pkgs.stdenv.isLinux { + CFLAGS = "-I${glibc.static.dev}/include"; + LDFLAGS = "-L ${glibc.static}/lib"; + }; + in + pkgs.mkShell ( + { + buildInputs = [ + # generic + git + git-lfs + gnumake + gnused + gnutar + gzip + + # frontend + nodejs + + # linting + python3 + uv + + # backend + go + gofumpt + sqlite + ] + ++ linuxOnlyInputs; + + GO = "${go}/bin/go"; + GOROOT = "${go}/share/go"; + + TAGS = "sqlite sqlite_unlock_notify"; + STATIC = "true"; + } + // linuxOnlyEnv + ); } ); } From 1740d36581dd62f01830dc5d1ac40a2126519009 Mon Sep 17 00:00:00 2001 From: techknowlogick Date: Fri, 15 Aug 2025 06:13:24 -0400 Subject: [PATCH 14/97] go1.25.0 (#35262) --- Dockerfile | 2 +- Dockerfile.rootless | 2 +- Makefile | 2 +- snap/snapcraft.yaml | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Dockerfile b/Dockerfile index f852cf4235..014eed9d46 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,5 +1,5 @@ # Build stage -FROM docker.io/library/golang:1.24-alpine3.22 AS build-env +FROM docker.io/library/golang:1.25-alpine3.22 AS build-env ARG GOPROXY ENV GOPROXY=${GOPROXY:-direct} diff --git a/Dockerfile.rootless b/Dockerfile.rootless index f955edc667..677d36bbcc 100644 --- a/Dockerfile.rootless +++ b/Dockerfile.rootless @@ -1,5 +1,5 @@ # Build stage -FROM docker.io/library/golang:1.24-alpine3.22 AS build-env +FROM docker.io/library/golang:1.25-alpine3.22 AS build-env ARG GOPROXY ENV GOPROXY=${GOPROXY:-direct} diff --git a/Makefile b/Makefile index 53671e9927..77ea40f203 100644 --- a/Makefile +++ b/Makefile @@ -23,7 +23,7 @@ SHASUM ?= shasum -a 256 HAS_GO := $(shell hash $(GO) > /dev/null 2>&1 && echo yes) COMMA := , -XGO_VERSION := go-1.24.x +XGO_VERSION := go-1.25.x AIR_PACKAGE ?= github.com/air-verse/air@v1 EDITORCONFIG_CHECKER_PACKAGE ?= github.com/editorconfig-checker/editorconfig-checker/v3/cmd/editorconfig-checker@v3 diff --git a/snap/snapcraft.yaml b/snap/snapcraft.yaml index 596f703131..46900f7b85 100644 --- a/snap/snapcraft.yaml +++ b/snap/snapcraft.yaml @@ -44,7 +44,7 @@ parts: source: . stage-packages: [ git, sqlite3, openssh-client ] build-packages: [ git, libpam0g-dev, libsqlite3-dev, build-essential] - build-snaps: [ go/1.24/stable, node/22/stable ] + build-snaps: [ go/1.25/stable, node/22/stable ] build-environment: - LDFLAGS: "" override-pull: | From 5cca69517dfcb8160fd9d92608604516fb501675 Mon Sep 17 00:00:00 2001 From: techknowlogick Date: Fri, 15 Aug 2025 14:47:39 -0400 Subject: [PATCH 15/97] nix flake use go1.25 (#35288) --- flake.lock | 6 +++--- flake.nix | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/flake.lock b/flake.lock index 1aa393f27b..16a487ba13 100644 --- a/flake.lock +++ b/flake.lock @@ -20,11 +20,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1755027561, - "narHash": "sha256-IVft239Bc8p8Dtvf7UAACMG5P3ZV+3/aO28gXpGtMXI=", + "lastModified": 1755186698, + "narHash": "sha256-wNO3+Ks2jZJ4nTHMuks+cxAiVBGNuEBXsT29Bz6HASo=", "owner": "nixos", "repo": "nixpkgs", - "rev": "005433b926e16227259a1843015b5b2b7f7d1fc3", + "rev": "fbcf476f790d8a217c3eab4e12033dc4a0f6d23c", "type": "github" }, "original": { diff --git a/flake.nix b/flake.nix index 29730e8c16..33f9449675 100644 --- a/flake.nix +++ b/flake.nix @@ -15,7 +15,7 @@ with pkgs; let # only bump toolchain versions here - go = go_1_24; + go = go_1_25; nodejs = nodejs_24; python3 = python312; From 9549c6641a75852b809fc720b268698091d60d2a Mon Sep 17 00:00:00 2001 From: Alex Blackie Date: Fri, 15 Aug 2025 17:50:05 -0400 Subject: [PATCH 16/97] Fix GitHub release assets URL validation (#35287) GitHub changed where the attachments on releases are stored, which means repo migrations with releases now fail because the redirect URLs don't match the base URL validation. We need to update the base URL check to check for the `release-assets` subdomain as well. --- services/migrations/github.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/services/migrations/github.go b/services/migrations/github.go index c6cd6ea173..a8a89dce0b 100644 --- a/services/migrations/github.go +++ b/services/migrations/github.go @@ -354,7 +354,8 @@ func (g *GithubDownloaderV3) convertGithubRelease(ctx context.Context, rel *gith // Prevent open redirect if !hasBaseURL(redirectURL, g.baseURL) && - !hasBaseURL(redirectURL, "https://objects.githubusercontent.com/") { + !hasBaseURL(redirectURL, "https://objects.githubusercontent.com/") && + !hasBaseURL(redirectURL, "https://release-assets.githubusercontent.com/") { WarnAndNotice("Unexpected AssetURL for assetID[%d] in %s: %s", asset.GetID(), g, redirectURL) return io.NopCloser(strings.NewReader(redirectURL)), nil From 04017f259bb22dd2b7de8348618580c5c5ccbb15 Mon Sep 17 00:00:00 2001 From: GiteaBot Date: Sat, 16 Aug 2025 00:35:49 +0000 Subject: [PATCH 17/97] [skip ci] Updated translations via Crowdin --- options/locale/locale_zh-CN.ini | 446 ++++++++++++++++---------------- 1 file changed, 223 insertions(+), 223 deletions(-) diff --git a/options/locale/locale_zh-CN.ini b/options/locale/locale_zh-CN.ini index 36b975ba36..bb67c763cb 100644 --- a/options/locale/locale_zh-CN.ini +++ b/options/locale/locale_zh-CN.ini @@ -112,7 +112,7 @@ copy_type_unsupported=无法复制此类型的文件内容 write=撰写 preview=预览 -loading=正在加载... +loading=正在加载… files=文件 error=错误 @@ -126,7 +126,7 @@ unknown=未知 rss_feed=RSS 订阅源 -pin=固定 +pin=置顶 unpin=取消置顶 artifacts=产物 @@ -168,7 +168,7 @@ no_results_found=未找到结果 internal_error_skipped=发生内部错误,但已跳过: %s [search] -search=搜索... +search=搜索… type_tooltip=搜索类型 fuzzy=模糊 fuzzy_tooltip=包含近似匹配搜索词的结果 @@ -178,23 +178,23 @@ regexp=正则表达式 regexp_tooltip=仅包含匹配正则表达式搜索词的结果 exact=精确 exact_tooltip=仅包含精确匹配搜索词的结果 -repo_kind=搜索仓库... -user_kind=搜索用户... -org_kind=搜索组织... -team_kind=搜索团队... -code_kind=搜索代码... +repo_kind=搜索仓库… +user_kind=搜索用户… +org_kind=搜索组织… +team_kind=搜索团队… +code_kind=搜索代码… code_search_unavailable=代码搜索当前不可用。请与网站管理员联系。 code_search_by_git_grep=当前代码搜索结果由「git grep」提供。如果站点管理员启用仓库索引器,可能会有更好的结果。 -package_kind=搜索软件包... -project_kind=搜索项目... -branch_kind=搜索分支... -tag_kind=搜索Git标签... -tag_tooltip=搜索匹配的标签。使用「%」来匹配任何序列的数字。 -commit_kind=搜索提交记录... -runner_kind=搜索运行器... +package_kind=搜索软件包… +project_kind=搜索项目… +branch_kind=搜索分支… +tag_kind=搜索 Git 标签… +tag_tooltip=搜索匹配的 Git 标签。使用「%」来匹配任何序列的数字。 +commit_kind=搜索提交记录… +runner_kind=搜索运行器… no_results=未找到匹配结果 -issue_kind=搜索工单... -pull_kind=搜索合并请求... +issue_kind=搜索工单… +pull_kind=搜索合并请求… keyword_search_unavailable=按关键字搜索当前不可用。请联系站点管理员。 [aria] @@ -252,7 +252,7 @@ license_desc=所有的代码都开源在 官方文档 后再对本页面进行填写。 require_db_desc=Gitea 需要使用 MySQL、PostgreSQL、MSSQL、SQLite3 或 TiDB (MySQL协议) 等数据库 @@ -315,9 +315,9 @@ server_service_title=服务器和第三方服务设置 offline_mode=启用本地模式 offline_mode_popup=禁用第三方 CDN 并在本地服务所有资源。 disable_gravatar=禁用 Gravatar 头像 -disable_gravatar_popup=禁用 Gravatar 和第三方头像源。除非用户在本地上传头像, 否则将使用默认的头像。 +disable_gravatar_popup=禁用 Gravatar 和第三方头像源。除非用户在本地上传头像,否则将使用默认头像。 federated_avatar_lookup=启用 Federated 头像 -federated_avatar_lookup_popup=启用 Federated Avatars 查找以使用开源的 Libravatar 服务。 +federated_avatar_lookup_popup=启用 Federated 头像查找以使用开源的 Libravatar 服务。 disable_registration=禁止用户自助注册 disable_registration_popup=禁用用户自助注册。只有管理员才能创建新的用户帐户。 allow_only_external_registration_popup=仅允许通过外部服务注册 @@ -343,15 +343,15 @@ 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 +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_allow_create_organization_popup=默认情况下,允许新用户帐户创建组织。 default_enable_timetracking=默认情况下启用时间跟踪 default_enable_timetracking_popup=默认情况下启用新仓库的时间跟踪。 no_reply_address=隐藏邮件域 @@ -547,7 +547,7 @@ repo.transfer.subject_to_you=%s 想要将「%s」转移给您 repo.transfer.to_you=您 repo.transfer.body=访问 %s 以接受或拒绝转移,亦可忽略此邮件。 -repo.collaborator.added.subject=%s 把您添加到了 %s +repo.collaborator.added.subject=%s 把您添加到 %s repo.collaborator.added.text=您已被添加为仓库的协作者: team_invite.subject=%[1]s 邀请您加入组织 %[2]s @@ -586,8 +586,8 @@ SSPISeparatorReplacement=分隔符 SSPIDefaultLanguage=默认语言 require_error=不能为空。 -alpha_dash_error=应该只包含字母数字、破折号 ('-') 和下划线 ('_') 字符。 -alpha_dash_dot_error=` 应该只包含字母数字, 破折号 ('-'), 下划线 ('_') 和点 ('. ') 。` +alpha_dash_error=`应该只包含字母数字、破折号('-')和下划线('_')。` +alpha_dash_dot_error=`应该只包含字母数字、破折号('-')、下划线('_')和点('.')。` git_ref_name_error=` 必须是格式良好的 git 引用名称。` size_error=长度必须为 %s。 min_size_error=长度最小为 %s 个字符。 @@ -597,7 +597,7 @@ url_error=`「%s」不是一个有效的 URL。` include_error=`必须包含子字符串「%s」。` glob_pattern_error=`匹配表达式无效:%s.` regex_pattern_error=`正则表达式无效:%s.` -username_error=`只能包含字母数字字符('0-9'、'a-z'、'A-Z')破折号('-')下划线('_')和点('.')。不能以非字母数字字符开头和结尾且不允许连续的非字母数字字符。` +username_error=`只能包含字母数字('0-9'、'a-z'、'A-Z')破折号('-')下划线('_')和点('.')。不能以非字母数字字符开头和结尾且不允许连续的非字母数字字符。` invalid_group_team_map_error=`映射无效: %s` unknown_error=未知错误: captcha_incorrect=验证码不正确。 @@ -754,8 +754,8 @@ language=界面语言 ui=主题 hidden_comment_types=隐藏的评论类型 hidden_comment_types_description=此处选中的注释类型不会显示在工单页面上。比如,勾选「标签」删除所有「{user} 添加/删除的 {label}」注释。 -hidden_comment_types.ref_tooltip=注释此问题在何处被提及过,如另一个问题、代码提交等 -hidden_comment_types.issue_ref_tooltip=注释用户在何处更改了与此问题相关联的分支/标签 +hidden_comment_types.ref_tooltip=注释此工单在何处被提及过,如另一个工单、提交… +hidden_comment_types.issue_ref_tooltip=注释用户在何处更改了与此工单相关联的分支 / Git 标签 comment_type_group_reference=引用 comment_type_group_label=标签 comment_type_group_milestone=里程碑 @@ -776,13 +776,13 @@ keep_activity_private=隐藏个人资料页面中的活动 keep_activity_private_popup=使活动仅对您和管理员可见 lookup_avatar_by_mail=从邮箱地址查找头像 -federated_avatar_lookup=Federated Avatar 查找 -enable_custom_avatar=启动自定义头像 +federated_avatar_lookup=查找 Federated 头像 +enable_custom_avatar=使用自定义头像 choose_new_avatar=选择新的头像 update_avatar=更新头像 delete_current_avatar=删除当前头像 uploaded_avatar_not_a_image=上传的文件不是一张图片。 -uploaded_avatar_is_too_big=上传的文件大小(%d KiB) 超过最大限制(%d KiB)。 +uploaded_avatar_is_too_big=上传的文件大小(%d KiB)超过最大限制(%d KiB)。 update_avatar_success=您的头像已更新。 update_user_avatar_success=用户头像已更新。 cropper_prompt=您可以在保存前编辑图像。编辑的图像将被保存为 PNG 格式。 @@ -803,7 +803,7 @@ email_desc=您的主邮箱地址将用于通知、密码恢复以及基于网页 theme_desc=这将是您在整个网站上的默认主题。 theme_colorblindness_help=颜色障碍主题支持 theme_colorblindness_prompt=Gitea 仅有少数主题存在基本的颜色障碍支持,这些主题只定义了少数颜色。这项工作仍在进行中,可以通过在主题的 CSS 文件中定义更多颜色来实现更多改进。 -primary=主要 +primary=主 activated=已激活 requires_activation=需要激活 primary_email=设为主邮箱 @@ -812,7 +812,7 @@ activations_pending=等待激活 can_not_add_email_activations_pending=有一个待处理的激活请求,请稍等几分钟后再尝试添加新的邮箱地址。 delete_email=移除 email_deletion=移除邮箱地址 -email_deletion_desc=邮箱地址和相关信息将会被删除。使用此邮箱地址发送的Git提交将会保留,继续? +email_deletion_desc=邮箱地址和相关信息将会被删除。使用此邮箱地址发送的 Git 提交将会保留,继续? email_deletion_success=您的邮箱地址已移除。 theme_update_success=您的主题已更新。 theme_update_error=所选主题不存在。 @@ -847,7 +847,7 @@ key_content_gpg_placeholder=以 '-----BEGIN PGP PUBLIC KEY BLOCK-----' 开头 add_new_principal=添加规则 ssh_key_been_used=此 SSH 密钥已添加到服务器。 ssh_key_name_used=使用相同名称的 SSH 公钥已经存在。 -ssh_principal_been_used=此规则已经加入到了服务器。 +ssh_principal_been_used=此规则已经加入到服务器。 gpg_key_id_used=使用相同名称的 GPG 公钥已经存在。 gpg_no_key_email_found=此 GPG 密钥与您帐户关联的任何已激活邮箱地址均不匹配。如果您已对提供的令牌进行签名,仍可添加该密钥。 gpg_key_matched_identities=匹配的身份: @@ -945,8 +945,8 @@ remove_oauth2_application_desc=删除 OAuth2 应用将撤销所有签名的访 remove_oauth2_application_success=该应用已删除。 create_oauth2_application=创建新的 OAuth2 应用程序 create_oauth2_application_button=创建应用 -create_oauth2_application_success=您已成功创建了一个新的 OAuth2 应用。 -update_oauth2_application_success=您已成功更新了此 OAuth2 应用。 +create_oauth2_application_success=您已成功创建一个新的 OAuth2 应用。 +update_oauth2_application_success=您已成功更新此 OAuth2 应用。 oauth2_application_name=应用名称 oauth2_confidential_client=机密客户端。对于需要保密的应用(例如 Web 应用),请选择此选项。对于包括桌面和移动应用在内的本机应用,请勿选择此选项。 oauth2_skip_secondary_authorization=首次授权后允许公共客户端跳过授权步骤。 可能会带来安全风险。 @@ -967,7 +967,7 @@ authorized_oauth2_applications_description=您已授予这些第三方应用程 revoke_key=撤销 revoke_oauth2_grant=撤回权限 revoke_oauth2_grant_description=确定撤销此三方应用程序的授权,并阻止此应用程序访问您的数据? -revoke_oauth2_grant_success=成功撤销了访问权限。 +revoke_oauth2_grant_success=成功撤销访问权限。 twofa_desc=为保护您的账号密码安全,您可以使用智能手机或其它设备来接收时间强相关的一次性密码(TOTP)。 twofa_recovery_tip=如果您丢失了您的设备,您将能够使用一次性恢复密钥来重新获得对您账户的访问。 @@ -977,15 +977,15 @@ twofa_disable=禁用两步认证 twofa_scratch_token_regenerate=重新生成初始令牌 twofa_scratch_token_regenerated=您的初始令牌现在是 %s。将其存放在安全的地方,它将不会再次显示。 twofa_enroll=启用两步验证 -twofa_disable_note=如果需要, 可以禁用双因素身份验证。 +twofa_disable_note=如果需要,您可以禁用两步验证。 twofa_disable_desc=关掉两步验证会使得您的账号不安全,继续执行? -regenerate_scratch_token_desc=如果您丢失了您的恢复密钥或已经使用它登录, 您可以在这里重置它。 +regenerate_scratch_token_desc=如果您丢失了您的恢复密钥或已经使用它登录,您可以在这里重置它。 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=安全密钥是包含加密密钥的硬件设备。它们可以用于双因素身份验证。安全密钥必须支持 WebAuthn 身份验证器 标准。 @@ -1011,7 +1011,7 @@ repos_none=您并不拥有任何仓库。 delete_account=删除当前帐户 delete_prompt=此操作将永久删除您的用户帐户。它 无法 被撤消。 -delete_with_all_comments=您的帐户年龄小于 %s。为了避免幽灵评论,所有工单/合并请求的评论都将与它一起被删除。 +delete_with_all_comments=您的帐户年龄小于 %s。为了避免幽灵评论,所有工单 / 合并请求的评论都将与它一起被删除。 confirm_delete_account=确认删除帐户 delete_account_title=删除当前帐户 delete_account_desc=确实要永久删除此用户帐户吗? @@ -1021,7 +1021,7 @@ email_notifications.onmention=仅被提及时通知 email_notifications.disable=停用邮件通知 email_notifications.submit=设置邮件通知 email_notifications.andyourown=仅与您相关的通知 -email_notifications.actions.desc=设置了 Gitea 工作流 的仓库中工作流运行的通知。 +email_notifications.actions.desc=已设置 Gitea 工作流 的仓库中工作流运行的通知。 email_notifications.actions.failure_only=仅在工作流运行失败时通知 visibility=用户可见性 @@ -1059,7 +1059,7 @@ fork_visibility_helper=无法更改派生仓库的可见性。 fork_branch=要克隆为派生的分支 all_branches=所有分支 view_all_branches=查看所有分支 -view_all_tags=查看所有标签 +view_all_tags=查看所有 Git 标签 fork_no_valid_owners=这个代码仓库无法被派生,因为没有有效的所有者。 fork.blocked_user=无法克隆仓库,因为您被仓库所有者屏蔽。 use_template=使用此模板 @@ -1099,7 +1099,7 @@ default_branch_label=默认 default_branch_helper=默认分支是用于合并请求和代码提交的基础分支。 mirror_prune=修剪 mirror_prune_desc=删除过时的远程跟踪引用 -mirror_interval=镜像间隔 (有效的时间单位是 'h', 'm', 's')。0 禁用自动定期同步 (最短间隔: %s) +mirror_interval=镜像间隔(有效的时间单位是 'h'、'm'、's')。0 禁用自动定期同步(最短间隔: %s) mirror_interval_invalid=镜像间隔无效。 mirror_sync=已同步 mirror_sync_on_commit=推送提交时同步 @@ -1206,7 +1206,7 @@ migrate.migrate_items_options=需要访问令牌来迁移额外的内容 migrated_from=从 %[2]s 迁移 migrated_from_fake=从 %[1]s 迁移成功 migrate.migrate=从 %s 迁移 -migrate.migrating=正在从 %s 迁移... +migrate.migrating=正在从 %s 迁移… migrate.migrating_failed=从 %s 迁移失败。 migrate.migrating_failed.error=迁移失败:%s migrate.migrating_failed_no_addr=迁移失败。 @@ -1264,10 +1264,10 @@ code.desc=查看源码、文件、提交和分支。 branch=分支 tree=目录树 clear_ref=`清除当前引用` -filter_branch_and_tag=过滤分支或标签 -find_tag=查找标签 +filter_branch_and_tag=过滤分支或 Git 标签 +find_tag=查找 Git 标签 branches=分支列表 -tags=标签列表 +tags=Git 标签列表 issues=工单 pulls=合并请求 projects=项目 @@ -1283,8 +1283,8 @@ commits=提交 commit=提交 release=发布 releases=发布 -tag=标签 -released_this=发布 +tag=Git 标签 +released_this=发布于 tagged_this=已标记 file.title=%s 位于 %s file_raw=原始文件 @@ -1322,7 +1322,7 @@ commit_graph.monochrome=黑白 commit_graph.color=彩色 commit.contained_in=这个提交包含在: commit.contained_in_default_branch=此提交是默认分支的一部分 -commit.load_referencing_branches_and_tags=加载引用该提交的分支和标签 +commit.load_referencing_branches_and_tags=加载引用该提交的分支和 Git 标签 commit.merged_in_pr=此提交已合并在合并请求 %s 中。 blame=Blame download_file=下载文件 @@ -1347,7 +1347,7 @@ editor.fork_before_edit=您必须派生这个仓库才能对此文件进行修 editor.delete_this_file=删除文件 editor.must_have_write_access=您必须具有写权限才能对此文件进行修改操作。 editor.file_delete_success=文件「%s」已删除。 -editor.name_your_file=命名文件... +editor.name_your_file=命名文件… editor.filename_help=通过键入名称后跟斜线 ("/") 来添加目录。通过在输入框的开头键入「退格」来删除目录。 editor.or=或 editor.cancel_lower=取消 @@ -1361,14 +1361,14 @@ editor.patch=应用补丁 editor.patching=打补丁: editor.fail_to_apply_patch=无法应用补丁 editor.new_patch=新补丁 -editor.commit_message_desc=添加一个可选的扩展描述... +editor.commit_message_desc=添加一个可选的扩展描述… editor.signoff_desc=在提交日志消息末尾添加签署人信息。 editor.commit_directly_to_this_branch=直接提交至 %s 分支。 editor.create_new_branch=为此提交创建一个 新的分支 并发起合并请求。 editor.create_new_branch_np=为此提交创建 新分支。 editor.propose_file_change=建议文件更改 editor.new_branch_name=为这次提交的新分支命名 -editor.new_branch_name_desc=新的分支名称... +editor.new_branch_name_desc=新的分支名称… editor.cancel=取消 editor.filename_cannot_be_empty=文件名不能为空。 editor.filename_is_invalid=文件名无效:「%s」。 @@ -1390,7 +1390,7 @@ editor.no_changes_to_show=没有可以显示的变更。 editor.push_rejected_no_message=此修改被服务器拒绝并且没有反馈消息。请检查 Git 钩子。 editor.push_rejected=此修改被服务器拒绝。请检查 Git 钩子。 editor.push_rejected_summary=详细拒绝信息: -editor.add_subdir=添加目录 +editor.add_subdir=添加目录… editor.unable_to_upload_files=上传文件至「%s」失败:%v editor.upload_file_is_locked=文件「%s」被 %s 锁定。 editor.upload_files_to_dir=上传文件至「%s」 @@ -1414,7 +1414,7 @@ commits.desc=浏览代码修改历史 commits.commits=次代码提交 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.tooltip=您可以在关键词前加上前缀,如「author:」、「committer:」、「after:」或「before:」,例如「retrin author:Alice before:2019-01-13」。 commits.search_branch=此分支 commits.search_all=所有分支 commits.author=作者 @@ -1510,7 +1510,7 @@ issues.new.clear_assignees=取消指派成员 issues.new.no_assignees=未指派成员 issues.new.no_reviewers=无评审人 issues.new.blocked_user=无法创建工单,因为您已被仓库所有者屏蔽。 -issues.edit.already_changed=无法保存对工单的更改。其内容似乎已被其他用户更改。 请刷新页面并重新编辑以避免覆盖他们的更改。 +issues.edit.already_changed=无法保存对工单的更改。其内容似乎已被其他用户更改。请刷新页面并重新编辑以避免覆盖他们的更改。 issues.edit.blocked_user=无法编辑内容,因为您已被仓库所有者或工单创建者屏蔽。 issues.choose.get_started=开始 issues.choose.open_external_link=开启 @@ -1519,7 +1519,7 @@ issues.choose.blank_about=从默认模板创建一个工单。 issues.choose.ignore_invalid_templates=已忽略无效模板 issues.choose.invalid_templates=发现了 %v 个无效模板 issues.choose.invalid_config=问题配置包含错误: -issues.no_ref=分支/Git标签未指定 +issues.no_ref=分支 / Git 标签未指定 issues.create=创建工单 issues.new_label=创建标签 issues.new_label_placeholder=标签名称 @@ -1530,29 +1530,29 @@ issues.label_templates.info=还没有任何标签。您可以使用「创建标 issues.label_templates.helper=选择标签模板 issues.label_templates.use=使用标签集 issues.label_templates.fail_to_load_file=加载标签模板文件「%s」时发生错误:%v -issues.add_label=于 %[2]s 添加了标签 %[1]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 -issues.add_milestone_at=`于 %[2]s 添加了里程碑 %[1]s` -issues.add_project_at=`于 %[2]s 将此添加到 %[1]s 项目` -issues.move_to_column_of_project=`将此对象移至 %s 的 %s 中在 %s 上` -issues.change_milestone_at=`%[3]s 修改了里程碑从 %[1]s%[2]s` -issues.change_project_at=于 %[3]s 将此从项目 %[1]s 移到 %[2]s -issues.remove_milestone_at=`%[2]s 删除了里程碑 %[1]s` -issues.remove_project_at=`于 %[2]s 将此工单从项目 %[1]s 中删除` +issues.add_label=于 %[2]s 添加标签 %[1]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 +issues.add_milestone_at=`于 %[2]s 添加里程碑 %[1]s` +issues.add_project_at=`于 %[2]s 将此工单添加到 %[1]s 项目` +issues.move_to_column_of_project=`将 %[3]s 上的 %[2]s 移至 %[1]s` +issues.change_milestone_at=`于 %[3]s 修改里程碑从 %[1]s%[2]s` +issues.change_project_at=于 %[3]s 将项目从 %[1]s 移至 %[2]s +issues.remove_milestone_at=`于 %[2]s 删除里程碑 %[1]s` +issues.remove_project_at=`于 %[2]s 将此工单从项目 %[1]s 中移除` issues.deleted_milestone=(已删除) issues.deleted_project=`(已删除)` issues.self_assign_at=`于 %s 指派给自己` issues.add_assignee_at=`于 %[2]s 由 %[1]s 指派` -issues.remove_assignee_at=`%s 取消了指派在 %s` -issues.remove_self_assignment=`于 %s 取消了指派` +issues.remove_assignee_at=`于 %[2]s 由 %[1]s 取消指派` +issues.remove_self_assignment=`于 %s 取消指派` issues.change_title_at=`于 %[3]s 修改标题 %[1]s%[2]s` -issues.change_ref_at=`将引用从 %s 更改为了 %s %s` -issues.remove_ref_at=`删除了引用 %s %s` -issues.add_ref_at=`添加了引用 %s %s` -issues.delete_branch_at=`于 %[2]s 删除了分支 %[1]s` +issues.change_ref_at=`于 %[3]s 修改引用 %[1]s%[2]s` +issues.remove_ref_at=`于 %[2]s 删除引用 %[1]s` +issues.add_ref_at=`于 %[2]s 添加引用 %[1]s` +issues.delete_branch_at=`于 %[2]s 删除分支 %[1]s` issues.filter_label=标签筛选 issues.filter_label_exclude=`使用 alt + 鼠标左键 / 回车 排除标签` issues.filter_label_no_select=所有标签 @@ -1578,7 +1578,7 @@ issues.filter_type.assigned_to_you=指派给您的 issues.filter_type.created_by_you=由您创建的 issues.filter_type.mentioning_you=提及您的 issues.filter_type.review_requested=已请求评审 -issues.filter_type.reviewed_by_you=您评审过的 +issues.filter_type.reviewed_by_you=您已评审的 issues.filter_sort=排序 issues.filter_sort.latest=最新创建 issues.filter_sort.oldest=最早创建 @@ -1623,29 +1623,29 @@ issues.context.edit=编辑 issues.context.delete=刪除 issues.no_content=没有提供说明。 issues.close=关闭工单 -issues.comment_pull_merged_at=已合并提交 %[1]s 到 %[2]s %[3]s -issues.comment_manually_pull_merged_at=手动合并提交 %[1]s 到 %[2]s %[3]s +issues.comment_pull_merged_at=于 %[3]s 合并提交 %[1]s 到 %[2]s +issues.comment_manually_pull_merged_at=于 %[3]s 手动合并提交 %[1]s 到 %[2]s issues.close_comment_issue=评论并关闭 issues.reopen_issue=重新打开 issues.reopen_comment_issue=评论并重新打开 issues.create_comment=评论 issues.comment.blocked_user=无法创建或编辑评论,因为您已被仓库所有者或工单创建者屏蔽。 issues.closed_at=`于 %[2]s 关闭此工单` -issues.reopened_at=`重新打开此问题 %[2]s` -issues.commit_ref_at=`于 %[2]s 在代码提交中引用了该工单` -issues.ref_issue_from=`于 %[2]s 引用了工单 %[4]s ` -issues.ref_pull_from=`于 %[2]s 引用了合并请求 %[4]s ` -issues.ref_closing_from=`于 %[2]s 引用了合并请求 %[4]s 将关闭此工单` -issues.ref_reopening_from=`于 %[2]s 引用了合并请求 %[4]s 将重新讨论此工单 ` -issues.ref_closed_from=`关闭了这个工单 %[4]s %[2]s` -issues.ref_reopened_from=`重新打开这个工单 %[4]s %[2]s` +issues.reopened_at=`于 %[2]s 重新打开此工单` +issues.commit_ref_at=`于 %[2]s 在代码提交中引用该工单` +issues.ref_issue_from=`于 %[2]s 引用工单 %[4]s ` +issues.ref_pull_from=`于 %[2]s 引用合并请求 %[4]s ` +issues.ref_closing_from=`于 %[2]s 引用合并请求 %[4]s 将关闭此工单` +issues.ref_reopening_from=`于 %[2]s 引用合并请求 %[4]s 将重新打开此工单 ` +issues.ref_closed_from=`关闭此工单 %[4]s %[2]s` +issues.ref_reopened_from=`重新打开此工单 %[4]s %[2]s` issues.ref_from=`来自 %[1]s` issues.author=作者 issues.author_helper=此用户是作者。 issues.role.owner=所有者 -issues.role.owner_helper=该用户是该仓库的所有者。 +issues.role.owner_helper=该用户是此仓库的所有者。 issues.role.member=成员 -issues.role.member_helper=该用户是拥有该仓库的组织成员。 +issues.role.member_helper=该用户是拥有此仓库的组织的成员。 issues.role.collaborator=协作者 issues.role.collaborator_helper=该用户已被邀请在仓库上进行协作。 issues.role.first_time_contributor=首次贡献者 @@ -1675,7 +1675,7 @@ issues.label_exclusive_warning=在编辑工单或合并请求的标签时,任 issues.label_exclusive_order=排序顺序 issues.label_exclusive_order_tooltip=在同一个范围内的互斥标签将按照这个数字进行排序 issues.label_count=%d 个标签 -issues.label_open_issues=%d 个开启的工单/合并请求 +issues.label_open_issues=%d 个开启中工单 / 合并请求 issues.label_edit=编辑 issues.label_delete=删除 issues.label_modify=编辑标签 @@ -1699,7 +1699,7 @@ issues.lock=锁定对话 issues.unlock=解锁对话 issues.lock_duplicate=一个工单不能锁定两次。 issues.unlock_error=无法解锁一个未锁定的工单。 -issues.lock_with_reason=因为 %s 而锁定,并将对话限制为协作者 %s +issues.lock_with_reason=于 %s 锁定为 %s,并将对话限制为协作者 issues.lock_no_reason=锁定并限制仅协作者 %s issues.unlock_comment=解锁此对话 %s issues.lock_confirm=锁定 @@ -1708,10 +1708,10 @@ issues.lock.notice_1=- 其他用户不能对这个工单添加新的评论。 issues.lock.notice_2=- 您和仓库其他协作者仍可评论并可见。 issues.lock.notice_3=- 您可以在未来再次解锁这个工单。 issues.unlock.notice_1=- 每个人都可以再次就这一工单发表评论。 -issues.unlock.notice_2=- 您可以在未来再次解锁这个工单。 +issues.unlock.notice_2=- 您可以在未来再次锁定这个工单。 issues.lock.reason=锁定原因 -issues.lock.title=锁定有关此问题的对话。 -issues.unlock.title=解锁有关此问题的对话。 +issues.lock.title=锁定有关此工单的对话。 +issues.unlock.title=解锁有关此工单的对话。 issues.comment_on_locked=您不能对锁定的问题发表评论。 issues.delete=删除 issues.delete.title=是否删除工单? @@ -1738,49 +1738,49 @@ issues.stop_tracking_history=工作 %[1]s 于 %[2]s 停止 issues.cancel_tracking=取消 issues.cancel_tracking_history=`取消时间跟踪 %s` issues.del_time=删除此时间跟踪日志 -issues.add_time_history=已于 %[2]s 添加计时 %[1] +issues.add_time_history=于 %[2]s 添加计时 %[1] issues.del_time_history=`已删除时间 %s` issues.add_time_manually=手动添加时间 issues.add_time_hours=小时 issues.add_time_minutes=分钟 issues.add_time_sum_to_small=没有输入时间。 issues.time_spent_total=总用时 -issues.time_spent_from_all_authors=`总花费时间:%s` +issues.time_spent_from_all_authors=`总用时:%s` -issues.due_date=到期时间 -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 个提交 -issues.push_commits_n=于 %[2]s 推送了 %[1]d 个提交 -issues.force_push_codes=`于 %[6]s 强制推送 %[1]s,从 %[2]s,至 %[4]s` +issues.due_date=截止日期 +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 个提交 +issues.push_commits_n=于 %[2]s 推送 %[1]d 个提交 +issues.force_push_codes=`于 %[6]s 强制推送 %[1]s,从 %[2]s%[4]s` issues.force_push_compare=比较 issues.due_date_form=yyyy年mm月dd日 -issues.due_date_form_add=设置到期时间 +issues.due_date_form_add=设置截止日期 issues.due_date_form_edit=编辑 issues.due_date_form_remove=删除 -issues.due_date_not_writer=您需要该仓库的写权限以更新工单的到期日期。 -issues.due_date_not_set=未设置到期时间。 -issues.due_date_added=于 %[2]s 设置到期时间为 %[1]s -issues.due_date_modified=将到期日从 %[2]s 修改为 %[1]s %[3]s -issues.due_date_remove=于 %[2]s 删除了到期时间 %[1]s +issues.due_date_not_writer=您需要该仓库的写权限以更新工单的截止日期。 +issues.due_date_not_set=未设置截止日期。 +issues.due_date_added=于 %[2]s 设置截止日期为 %[1]s +issues.due_date_modified=于 %[3]s 将截止日期从 %[2]s 修改为 %[1]s +issues.due_date_remove=于 %[2]s 删除截止日期 %[1]s issues.due_date_overdue=过期 -issues.due_date_invalid=到期日期无效或超出范围。请使用 'yyyy-mm-dd' 格式。 +issues.due_date_invalid=截止日期无效或超出范围。请使用「yyyy-mm-dd」格式。 issues.dependency.title=依赖工单 issues.dependency.issue_no_dependencies=未设置依赖工单。 issues.dependency.pr_no_dependencies=未设置依赖工单。 issues.dependency.no_permission_1=您没有读取 %d 依赖关系的权限 issues.dependency.no_permission_n=您没有读取 %d 依赖关系的权限 issues.dependency.no_permission.can_remove=您没有读取此依赖关系的权限,但可以删除此依赖关系 -issues.dependency.add=添加依赖工单... +issues.dependency.add=添加依赖工单… issues.dependency.cancel=取消 issues.dependency.remove=删除 issues.dependency.remove_info=删除此依赖项 -issues.dependency.added_dependency=`添加了一个新的依赖项 %s` +issues.dependency.added_dependency=`添加了一个新依赖项 %s` issues.dependency.removed_dependency=`移除了一个依赖项 %s` -issues.dependency.pr_closing_blockedby=以下工单阻止了关闭此合并请求 +issues.dependency.pr_closing_blockedby=以下工单阻止关闭此合并请求 issues.dependency.issue_closing_blockedby=关闭此工单被以下工单阻止 -issues.dependency.issue_close_blocks=此工单阻止了以下工单的关闭 +issues.dependency.issue_close_blocks=此工单阻止以下工单的关闭 issues.dependency.pr_close_blocks=此合并请求阻止以下工单的关闭 issues.dependency.issue_close_blocked=您需要关闭所有阻止此工单的工单后才能关闭它。 issues.dependency.issue_batch_close_blocked=无法批量关闭您所选择的工单,因为 #%d 工单仍然有处于打开状态的依赖工单 @@ -1788,28 +1788,28 @@ issues.dependency.pr_close_blocked=您需要关闭所有阻止此合并请求的 issues.dependency.blocks_short=阻止 issues.dependency.blocked_by_short=依赖于 issues.dependency.remove_header=删除依赖项 -issues.dependency.issue_remove_text=此操作将从工单中删除依赖。是否要继续? -issues.dependency.pr_remove_text=此操作将从合并请求中删除依赖。是否要继续? +issues.dependency.issue_remove_text=此操作将从工单中删除依赖。是否要继续? +issues.dependency.pr_remove_text=此操作将从合并请求中删除依赖。是否要继续? issues.dependency.setting=为工单和合并请求启用依赖 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=依赖项已存在。 -issues.dependency.add_error_cannot_create_circular=您无法在相互阻塞的问题之间建立依赖关系。 +issues.dependency.add_error_cannot_create_circular=您无法在相互阻塞的工单之间建立依赖关系。 issues.dependency.add_error_dep_not_same_repo=这两个工单必须在同一仓库。 issues.review.self.approval=您不能批准您自己的合并请求。 issues.review.self.rejection=您不能请求对您自己的合并请求进行更改。 issues.review.approve=于 %s 批准此合并请求 -issues.review.comment=评审于 %s -issues.review.dismissed=于 %[2]s 取消了 %[1]s 的评审 +issues.review.comment=于 %s 评审 +issues.review.dismissed=于 %[2]s 取消 %[1]s 的评审 issues.review.dismissed_label=已取消 issues.review.left_comment=留下了一条评论 issues.review.content.empty=您需要留下一个注释,表明需要的更改。 issues.review.reject=请求变更 %s -issues.review.wait=已请求 %s 审核 +issues.review.wait=已请求 %s 评审 issues.review.add_review_request=于 %[2]s 请求 %[1]s 评审 issues.review.remove_review_request=取消对 %s 的评审请求 %s -issues.review.remove_review_request_self=拒绝审核 %s +issues.review.remove_review_request_self=拒绝评审 %s issues.review.pending=待定 issues.review.pending.tooltip=此评论目前对其他用户不可见。 若要提交您的待定评论,请在页面顶部选择 %s -> %s/%s/%s。 issues.review.review=评审 @@ -1839,7 +1839,7 @@ issues.content_history.created=已创建 issues.content_history.delete_from_history=从历史记录中删除 issues.content_history.delete_from_history_confirm=从历史记录中删除吗? issues.content_history.options=选项 -issues.reference_link=参考:%s +issues.reference_link=引用:%s compare.compare_base=基准分支 compare.compare_head=比较 @@ -1848,7 +1848,7 @@ pulls.desc=启用合并请求和代码评审。 pulls.new=创建合并请求 pulls.new.blocked_user=无法创建合并请求,因为您已被仓库所有者屏蔽。 pulls.new.must_collaborator=您必须是仓库的协作者才能创建合并请求。 -pulls.edit.already_changed=无法保存对合并请求的更改。其内容似乎已被其他用户更改。 请刷新页面并重新编辑以避免覆盖他们的更改。 +pulls.edit.already_changed=无法保存对合并请求的更改。其内容似乎已被其他用户更改。请刷新页面并重新编辑以避免覆盖他们的更改。 pulls.view=查看合并请求 pulls.compare_changes=创建合并请求 pulls.allow_edits_from_maintainers=允许维护者编辑 @@ -1873,9 +1873,9 @@ pulls.select_commit_hold_shift_for_range=选择提交。按住 Shift + 单击选 pulls.review_only_possible_for_full_diff=只有在查看全部差异时才能进行审核 pulls.filter_changes_by_commit=按提交筛选 pulls.nothing_to_compare=分支内容相同,无需创建合并请求。 -pulls.nothing_to_compare_have_tag=所选分支/标签相同。 +pulls.nothing_to_compare_have_tag=所选分支 / Git 标签相同。 pulls.nothing_to_compare_and_allow_empty_pr=这些分支是相等的,此合并请求将为空。 -pulls.has_pull_request=这些分支之间的合并请求已存在: %[2]s#%[3]d +pulls.has_pull_request=这些分支之间的合并请求已存在:%[2]s#%[3]d pulls.create=创建合并请求 pulls.title_desc=请求将 %[1]d 次代码提交从 %[2]s 合并至 %[3]s pulls.merged_title_desc=于 %[4]s 将 %[1]d 次代码提交从 %[2]s合并至 %[3]s @@ -1886,11 +1886,11 @@ pulls.tab_files=文件变动 pulls.reopen_to_merge=请重新创建此合并请求。 pulls.cant_reopen_deleted_branch=无法重新打开此合并请求,因为分支已删除。 pulls.merged=已合并 -pulls.merged_success=合并请求已成功合并和关闭 +pulls.merged_success=合并请求已成功合并并关闭 pulls.closed=合并请求已关闭 pulls.manually_merged=已手动合并 pulls.merged_info_text=分支 %s 现在可以删除了。 -pulls.is_closed=合并请求已经关闭。 +pulls.is_closed=合并请求已关闭。 pulls.title_wip_desc=`标题以 %s 开头以免合并请求意外合并。` pulls.cannot_merge_work_in_progress=此合并请求被标记为正在进行的工作。 pulls.still_in_progress=仍在进行中? @@ -1898,7 +1898,7 @@ pulls.add_prefix=添加 %s 前缀 pulls.remove_prefix=删除 %s 前缀 pulls.data_broken=此合并请求因为派生仓库信息缺失而中断。 pulls.files_conflicted=此合并请求有变更与目标分支冲突。 -pulls.is_checking=正在进行合并冲突检测 ... +pulls.is_checking=正在进行合并冲突检查… pulls.is_ancestor=此分支已经包含在目标分支中,没有什么可以合并。 pulls.is_empty=此分支上的更改已经在目标分支上。这将是一个空提交。 pulls.required_status_check_failed=一些必要的检查没有成功 @@ -1950,9 +1950,9 @@ pulls.has_merged=失败:合并请求已经合并。您不能再次合并或更 pulls.push_rejected=推送失败:推送被拒绝。审查此仓库的 Git 钩子。 pulls.push_rejected_summary=详细拒绝信息 pulls.push_rejected_no_message=推送失败:此推送被拒绝但未提供其他信息。请检查此仓库的 Git 钩子。 -pulls.open_unmerged_pull_exists=`您不能执行重新打开操作, 因为已经存在相同的合并请求 (#%d)。` -pulls.status_checking=一些检测仍在等待运行 -pulls.status_checks_success=所有检测均成功 +pulls.open_unmerged_pull_exists=`您不能执行重新打开操作,因为已经存在相同的合并请求 (#%d)。` +pulls.status_checking=一些检查仍在等待运行 +pulls.status_checks_success=所有检查均成功 pulls.status_checks_warning=一些检查报告了警告 pulls.status_checks_failure=一些检查失败了 pulls.status_checks_error=一些检查报告了错误 @@ -1967,13 +1967,13 @@ pulls.update_not_allowed=您无权更新分支 pulls.outdated_with_base_branch=此分支相比基础分支已过期 pulls.close=关闭合并请求 pulls.closed_at=`于 %[2]s 关闭此合并请求 ` -pulls.reopened_at=`重新打开此合并请求 %[2]s` +pulls.reopened_at=`于 %[2]s 重新打开此合并请求` pulls.cmd_instruction_hint=查看命令行提示 pulls.cmd_instruction_checkout_title=检出 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…」。 @@ -1987,12 +1987,12 @@ pulls.auto_merge_not_scheduled=此合并请求没有计划自动合并。 pulls.auto_merge_canceled_schedule=此合并请求的自动合并已取消。 pulls.auto_merge_newly_scheduled_comment=`已于 %[1]s 设置此合并请求在所有检查成功后自动合并` -pulls.auto_merge_canceled_schedule_comment=`已于 %[1]s 取消了自动合并设置 ` +pulls.auto_merge_canceled_schedule_comment=`已于 %[1]s 取消自动合并设置 ` pulls.delete.title=删除此合并请求? pulls.delete.text=您真的要删除这个合并请求吗?(这将永久删除所有内容。如果您打算将内容存档,请考虑关闭它) -pulls.recently_pushed_new_branches=您已经于%[2]s推送了分支 %[1]s +pulls.recently_pushed_new_branches=您已经于 %[2]s 推送分支 %[1]s pulls.upstream_diverging_prompt_behind_1=该分支落后于 %[2]s %[1]d 个提交 pulls.upstream_diverging_prompt_behind_n=该分支落后于 %[2]s %[1]d 个提交 pulls.upstream_diverging_prompt_base_newer=基础分支 %s 有新的更改 @@ -2017,7 +2017,7 @@ milestones.title=标题 milestones.desc=描述 milestones.due_date=截止日期(可选) milestones.clear=清除 -milestones.invalid_due_date_format=到期时间的格式必须是「yyyy-mm-dd」的形式。 +milestones.invalid_due_date_format=截止日期的格式必须是「yyyy-mm-dd」的形式。 milestones.create_success=里程碑「%s」创建成功。 milestones.edit=编辑里程碑 milestones.edit_subheader=里程碑组织工单,合并请求和跟踪进度。 @@ -2054,7 +2054,7 @@ ext_wiki.desc=链接到外部百科。 wiki=百科 wiki.welcome=欢迎来到百科。 -wiki.welcome_desc=百科允许您撰写和与协作者分享文档。 +wiki.welcome_desc=百科允许您撰写并与协作者分享文档。 wiki.desc=撰写和与协作者分享文档 wiki.create_first_page=创建第一个页面 wiki.page=页面 @@ -2072,11 +2072,11 @@ wiki.wiki_page_revisions=页面历史 wiki.back_to_wiki=返回百科 wiki.delete_page_button=删除页面 wiki.delete_page_notice_1=百科页面「%s」删除后无法恢复,是否继续? -wiki.page_already_exists=相同名称的 Wiki 页面已经存在。 +wiki.page_already_exists=相同名称的百科页面已经存在。 wiki.reserved_page=百科页面名称「%s」是保留的。 wiki.pages=所有页面 wiki.last_updated=最后更新于 %s -wiki.page_name_desc=输入此百科页面的名称。特殊名称有:「Home」,「_Sidebar」和「_Footer」。 +wiki.page_name_desc=输入此百科页面的名称。特殊名称有:「Home」、「_Sidebar」和「_Footer」。 wiki.original_git_entry_tooltip=查看原始的 Git 文件而不是使用友好链接。 activity=活动 @@ -2097,13 +2097,13 @@ activity.active_prs_count_1=%d 个合并请求 activity.active_prs_count_n=%d 个合并请求 activity.merged_prs_count_1=已合并的合并请求 activity.merged_prs_count_n=已合并的合并请求 -activity.opened_prs_count_1=创建的合并请求 -activity.opened_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.prs_merged_by=%[2]s 由 %[1]s 合并 +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=已创建 @@ -2113,7 +2113,7 @@ 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_closed_from=%[2]s 关闭了 %[1]s activity.title.issues_created_by=%[2]s 创建了 %[1]s activity.closed_issue_label=已关闭 activity.new_issues_count_1=开启的工单 @@ -2123,8 +2123,8 @@ 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=在此期间没有任何提交活动。 @@ -2174,9 +2174,9 @@ settings.hooks=Web 钩子 settings.githooks=管理 Git 钩子 settings.basic_settings=基本设置 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=将您的仓库设置为自动同步另一个仓库的提交、Git 标签和分支。 +settings.mirror_settings.docs.disabled_pull_mirror.instructions=将您的项目设置为自动将提交、Git 标签和分支推送到另一个仓库。您的站点管理员已禁用了拉取镜像。 +settings.mirror_settings.docs.disabled_push_mirror.instructions=将您的项目设置为自动从一个仓库拉取提交、Git 标签和分支。 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=您的仓库将镜像同步另一个仓库的更改。请注意,您目前无法创建任何新的镜像。 @@ -2229,12 +2229,12 @@ settings.tracker_issue_style.alphanumeric=英文字母数字组合形式 settings.tracker_issue_style.regexp=正则表达式 settings.tracker_issue_style.regexp_pattern=正则表达式 settings.tracker_issue_style.regexp_pattern_desc=第一个被捕获的组将取代 {index}。 -settings.tracker_url_format_desc=使用占位符 {user}, {repo}{index} 作为用户名、仓库名和工单索引。 +settings.tracker_url_format_desc=使用占位符 {user}{repo}{index} 作为用户名、仓库名和工单索引。 settings.enable_timetracker=启用时间跟踪 settings.allow_only_contributors_to_track_time=仅允许成员跟踪时间 settings.pulls_desc=启用合并请求 settings.pulls.ignore_whitespace=忽略空白冲突 -settings.pulls.enable_autodetect_manual_merge=启用自动检测手动合并 (注意:在某些特殊情况下可能发生错误判断) +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=默认允许维护者编辑 @@ -2304,7 +2304,7 @@ settings.wiki_delete_notices_1=- 这将永久删除和禁用 %s 的百科。 settings.confirm_wiki_delete=删除百科数据 settings.wiki_deletion_success=仓库百科数据删除成功! settings.delete=删除本仓库 -settings.delete_desc=删除仓库是永久性的, 无法撤消。 +settings.delete_desc=删除仓库是永久性的,无法撤消。 settings.delete_notices_1=- 此操作 无法 被回滚。 settings.delete_notices_2=- 此操作将永久删除仓库 %s,包括代码、 工单、评论、百科数据和协作者设置。 settings.delete_notices_fork_1=- 在此仓库删除后,它的派生仓库将变成独立仓库。 @@ -2330,7 +2330,7 @@ settings.add_team=添加团队 settings.add_team_duplicate=团队已经拥有仓库 settings.add_team_success=团队现在可以访问仓库。 settings.change_team_permission_tip=团队权限设置于团队设置页面,不能根据仓库更改 -settings.delete_team_tip=该团队仍有仓库, 无法删除 +settings.delete_team_tip=该团队仍有仓库,无法删除 settings.remove_team_success=团队访问仓库的权限已删除。 settings.add_webhook=添加 Web 钩子 settings.add_webhook.invalid_channel_name=Web 钩子通道名称不能为空且不能仅包含一个 # 字符。 @@ -2368,12 +2368,12 @@ settings.discord_icon_url=图标 URL settings.event_desc=触发条件: settings.event_push_only=推送事件 settings.event_send_everything=所有事件 -settings.event_choose=自定义事件... +settings.event_choose=自定义事件… settings.event_header_repository=仓库事件 settings.event_create=创建 -settings.event_create_desc=创建分支或标签 +settings.event_create_desc=分支或 Git 标签已创建。 settings.event_delete=刪除 -settings.event_delete_desc=分支或标签已删除。 +settings.event_delete_desc=分支或 Git 标签已删除。 settings.event_fork=派生 settings.event_fork_desc=仓库已派生。 settings.event_wiki=百科 @@ -2425,7 +2425,7 @@ settings.event_workflow_job_desc=Gitea 工作流队列中、等待中、正在 settings.event_package=软件包 settings.event_package_desc=软件包在仓库中已创建或删除。 settings.branch_filter=分支过滤 -settings.branch_filter_desc=推送、创建,删除分支事件的分支白名单,使用 glob 表达式匹配指定。若为空或 *,则会报告所有分支的事件。语法文档见 %[2]s。示例:master,{master,release*}。 +settings.branch_filter_desc=推送、创建,删除分支事件的分支白名单,使用 glob 表达式匹配指定。若为空或 *,则会报告所有分支的事件。语法文档见 %[2]s。示例:master{master,release*}。 settings.authorization_header=授权标头 settings.authorization_header_desc=当存在时将被作为授权标头包含在内。例如: %s。 settings.active=激活 @@ -2528,9 +2528,9 @@ settings.protect_branch_name_pattern=受保护的分支名称表达式 settings.protect_branch_name_pattern_desc=分支保护的名称匹配表达式。语法请参阅 文档 。如:main, release/** settings.protect_patterns=表达式 settings.protect_protected_file_patterns=受保护的文件表达式(使用分号「;」分隔): -settings.protect_protected_file_patterns_desc=即使用户有权添加、编辑或删除此分支中的文件,也不允许直接更改受保护的文件。 可以使用分号「;」分隔多个表达式。 见%[2]s文档了解表达式语法。例如: .drone.yml, /docs/**/*.txt。 +settings.protect_protected_file_patterns_desc=即使用户有权添加、编辑或删除此分支中的文件,也不允许直接更改受保护的文件。可以使用分号(';')分隔多个表达式。见 %[2]s 文档了解表达式语法。例如:.drone.yml/docs/**/*.txt。 settings.protect_unprotected_file_patterns=不受保护的文件表达式(使用分号「;」分隔): -settings.protect_unprotected_file_patterns_desc=如果用户有写权限,则允许直接更改的不受保护的文件,以绕过推送限制。可以使用分号分隔多个表达式「;」。 见 %[2]s 文档了解表达式语法。例如: .drone.yml, /docs/**/*.txt。 +settings.protect_unprotected_file_patterns_desc=如果用户具有写权限则允许直接更改的不受保护文件,可绕过推送限制。可使用分号(';')分隔多个表达式。见 %[2]s 文档了解表达式语法。例如:.drone.yml/docs/**/*.txt。 settings.add_protected_branch=启用保护 settings.delete_protected_branch=禁用保护 settings.update_protect_branch_success=分支保护规则「%s」更新成功。 @@ -2549,22 +2549,22 @@ settings.block_admin_merge_override_desc=管理员须遵守分支保护规则, settings.default_branch_desc=请选择一个默认的分支用于合并请求和提交: settings.merge_style_desc=合并方式 settings.default_merge_style_desc=默认合并风格 -settings.choose_branch=选择一个分支... +settings.choose_branch=选择一个分支… settings.no_protected_branch=没有受保护的分支 settings.edit_protected_branch=编辑 settings.protected_branch_required_rule_name=必须填写规则名称 settings.protected_branch_duplicate_rule_name=规则名称已存在 settings.protected_branch_required_approvals_min=所需的审批数不能为负数。 -settings.tags=标签 -settings.tags.protection=标签保护 -settings.tags.protection.pattern=标签表达式 +settings.tags=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=保护标签 -settings.tags.protection.none=没有受保护的标签。 -settings.tags.protection.pattern.description=您可以使用单个名称或 glob 表达式匹配或正则表达式来匹配多个标签。了解详情请访问 保护标签指南。 +settings.tags.protection.create=保护 Git 标签 +settings.tags.protection.none=没有受保护的 Git 标签。 +settings.tags.protection.pattern.description=您可以使用单个名称或 glob 表达式匹配或正则表达式来匹配多个 Git 标签。了解详情请访问 保护标签指南。 settings.bot_token=Bot 令牌 settings.chat_id=聊天 ID settings.thread_id=线程 ID @@ -2590,7 +2590,7 @@ settings.archive.success=仓库已成功归档。 settings.archive.error=仓库在归档时出现异常。请通过日志获取详细信息。 settings.archive.error_ismirror=请不要对镜像仓库归档,谢谢! settings.archive.branchsettings_unavailable=已归档仓库无法进行分支设置。 -settings.archive.tagsettings_unavailable=已归档仓库的标签设置不可用。 +settings.archive.tagsettings_unavailable=已归档仓库的 Git 标签设置不可用。 settings.archive.mirrors_unavailable=如果仓库已归档,镜像将不可用。 settings.unarchive.button=撤销仓库归档 settings.unarchive.header=撤销此仓库归档 @@ -2616,7 +2616,7 @@ settings.lfs_lock_path=要锁定的文件路径… settings.lfs_locks_no_locks=无锁定 settings.lfs_lock_file_no_exist=锁定的文件在默认分支中不存在 settings.lfs_force_unlock=强制解锁 -settings.lfs_pointers.found=找到 %d 个块指针 - %d 个关联, %d 个未关联(%d 个从仓库丢失) +settings.lfs_pointers.found=找到 %d 个块指针 — %d 个关联, %d 个未关联(%d 个从仓库丢失) settings.lfs_pointers.sha=Blob SHA settings.lfs_pointers.oid=OID settings.lfs_pointers.inRepo=在仓库中 @@ -2689,9 +2689,9 @@ diff.submodule_deleted=子模块 %[1]s 已从 %[2]s 中删除 diff.submodule_updated=子模块 %[1]s 已更新:%[2]s releases.desc=跟踪项目版本和下载。 -release.releases=发布 +release.releases=版本发布 release.detail=发布详情 -release.tags=标签 +release.tags=Git 标签 release.new_release=发布新版 release.draft=草稿 release.prerelease=预发布 @@ -2700,16 +2700,16 @@ release.latest=最新 release.compare=比较 release.edit=编辑 release.ahead.commits=%d 次提交 -release.ahead.target=在此版本发布后已加入到 %s -tag.ahead.target=自此标签到 %s +release.ahead.target=在此版本后已推送到 %s +tag.ahead.target=自此 Git 标签到 %s release.source_code=源代码 release.new_subheader=发布组织项目的版本。 release.edit_subheader=发布组织项目的版本。 -release.tag_name=标签名称 +release.tag_name=Git 标签名称 release.target=目标分支 -release.tag_helper=选择一个存在的标签或者创建新标签。 -release.tag_helper_new=新标签。此标签将从目标创建。 -release.tag_helper_existing=现有标签。 +release.tag_helper=选择一个存在的 Git 标签或者创建新 Git 标签。 +release.tag_helper_new=新 Git 标签。此 Git 标签将从目标创建。 +release.tag_helper_existing=现有 Git 标签。 release.title=发布标题 release.title_empty=标题不能为空。 release.message=描述这个版本 @@ -2720,22 +2720,22 @@ release.publish=发布版本 release.save_draft=保存草稿 release.edit_release=保存此次发布 release.delete_release=删除发布 -release.delete_tag=删除标签 +release.delete_tag=删除 Git 标签 release.deletion=删除发布 release.deletion_desc=删除发布只会从 Gitea 中移除发布。这不会影响 Git 的标签以及您仓库的内容和历史。是否继续? release.deletion_success=该发布已删除。 -release.deletion_tag_desc=将从仓库中删除此标签。仓库内容和历史记录保持不变。继续吗? -release.deletion_tag_success=该标签已删除。 -release.tag_name_already_exist=使用此标签名称的发布已经存在。 -release.tag_name_invalid=标签名称无效。 -release.tag_name_protected=标签名已受保护。 -release.tag_already_exist=此标签名已存在。 +release.deletion_tag_desc=将从仓库中删除此 Git 标签。仓库内容和历史记录保持不变。继续吗? +release.deletion_tag_success=该 Git 标签已删除。 +release.tag_name_already_exist=使用此 Git 标签名称的发布已经存在。 +release.tag_name_invalid=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.add_tag_msg=使用发布的标题和内容作为 Git 标签消息。 +release.add_tag=仅创建 Git 标签 release.releases_for=%s 的发布 -release.tags_for=%s 的标签 +release.tags_for=%s 的 Git 标签 branch.name=分支名称 branch.already_exists=名为「%s」的分支已存在。 @@ -2751,7 +2751,7 @@ branch.create_from=从「%s」 branch.create_success=分支「%s」已创建。 branch.branch_already_exists=此仓库已存在名为「%s」的分支。 branch.branch_name_conflict=分支名称「%s」与已存在的分支「%s」冲突。 -branch.tag_collision=分支「%s」无法创建,因为同名的标签已经存在。 +branch.tag_collision=分支「%s」无法创建,因为同名的 Git 标签已经存在。 branch.deleted_by=删除人:%s branch.restore_success=分支「%s」已还原。 branch.restore_failed=分支「%s」还原失败。 @@ -2777,12 +2777,12 @@ branch.rename_protected_branch_failed=此分支受到 glob 语法规则的保护 branch.commits_divergence_from=提交分歧:落后 %[3]s %[1]d 个提交,领先 %[2]d 个提交 branch.commits_no_divergence=与分支 %[1]s 相同 -tag.create_tag=创建标签 %s -tag.create_tag_operation=创建标签 -tag.confirm_create_tag=创建标签 -tag.create_tag_from=基于「%s」创建新标签 +tag.create_tag=创建 Git 标签 %s +tag.create_tag_operation=创建 Git 标签 +tag.confirm_create_tag=创建 Git 标签 +tag.create_tag_from=基于「%s」创建新 Git 标签 -tag.create_success=标签「%s」已存在。 +tag.create_success=Git 标签「%s」已存在。 topic.manage_topics=管理主题 topic.done=保存 @@ -2799,7 +2799,7 @@ error.csv.invalid_field_count=无法渲染此文件,因为它在第 %d 行中 error.broken_git_hook=此仓库的 Git 钩子似乎已损坏。 请按照 文档 来修复它们,然后推送一些提交来刷新状态。 [graphs] -component_loading=正在加载 %s... +component_loading=正在加载 %s… component_loading_failed=无法加载 %s component_loading_info=这可能需要一点时间… component_failed_to_load=意外的错误发生了。 @@ -3009,7 +3009,7 @@ 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_tags=从 Git 数据同步 Git 标签到数据库 dashboard.update_mirrors=更新镜像仓库 dashboard.repo_health_check=健康检查所有仓库 dashboard.check_repo_stats=检查所有仓库统计 @@ -3064,7 +3064,7 @@ dashboard.stop_endless_tasks=停止无限循环的工作流任务 dashboard.cancel_abandoned_jobs=取消已放弃的工作流任务 dashboard.start_schedule_tasks=启动工作流计划任务 dashboard.sync_branch.started=分支同步已开始 -dashboard.sync_tag.started=标签同步已开始 +dashboard.sync_tag.started=Git 标签同步已开始 dashboard.rebuild_issue_indexer=重建工单索引 dashboard.sync_repo_licenses=重新探测仓库许可证 @@ -3094,7 +3094,7 @@ 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=受限 @@ -3127,7 +3127,7 @@ users.list_status_filter.not_2fa_enabled=未启用 2FA users.details=用户详细信息 emails.email_manage_panel=邮件管理 -emails.primary=主要的 +emails.primary=主 emails.activated=已激活 emails.filter_sort.email=邮箱 emails.filter_sort.email_reverse=邮箱(倒序) @@ -3257,9 +3257,9 @@ auths.oauth2_required_claim_value_helper=设置此值,只有拥有对应的声 auths.oauth2_group_claim_name=用于提供用户组名称的 Claim 声明名称。(可选) auths.oauth2_full_name_claim_name=全名声明名称。(可选,如果设置,用户的全名将始终与此声明同步) auths.oauth2_ssh_public_key_claim_name=SSH 公钥声明名称 -auths.oauth2_admin_group=管理员用户组的 Claim 声明值。(可选 - 需要上面的声明名称) -auths.oauth2_restricted_group=受限用户组的 Claim 声明值。(可选 - 需要上面的声明名称) -auths.oauth2_map_group_to_team=映射声明的组到组织团队。(可选 - 要求在上面填写声明的名字) +auths.oauth2_admin_group=管理员用户组的 Claim 声明值。(可选 — 需要上面的声明名称) +auths.oauth2_restricted_group=受限用户组的 Claim 声明值。(可选 — 需要上面的声明名称) +auths.oauth2_map_group_to_team=映射声明的组到组织团队。(可选 — 要求在上面填写声明的名字) auths.oauth2_map_group_to_team_removal=如果用户不属于相应的组,从已同步团队中移除用户 auths.enable_auto_register=允许用户自动注册 auths.sspi_auto_create_users=自动创建用户 @@ -3271,7 +3271,7 @@ auths.sspi_strip_domain_names_helper=如果选中此项,域名将从登录名 auths.sspi_separator_replacement=要使用的分隔符代替\, / 和 @ auths.sspi_separator_replacement_helper=用于替换下级登录名称分隔符的字符(例如「DOMAIN\user」)中的 \ 和用户主名字(如「user@example.org」中的 @)。 auths.sspi_default_language=默认语言 -auths.sspi_default_language_helper=SSPI 认证方法为用户自动创建的默认语言。如果您想要自动检测到语言,请留空。 +auths.sspi_default_language_helper=通过 SSPI 身份验证方式自动创建的用户的默认语言。如果您希望自动检测语言,请留空。 auths.tips=帮助提示 auths.tips.oauth2.general=OAuth2 认证 auths.tips.oauth2.general.tip=当注册新的 OAuth2 身份验证时,回调/重定向 URL 应该是: @@ -3283,11 +3283,11 @@ 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.openid_connect=使用 OpenID 连接发现 URL「{server}/.well-known/openid-configuration」来指定终点 auths.tip.twitter=访问 %s,创建应用并确保启用了「允许此应用程序使用 Twitter 登录」的选项 auths.tip.discord=在 %s 上注册新应用程序 auths.tip.gitea=注册一个新的 OAuth2 应用程序。可以访问 %s 查看帮助 -auths.tip.yandex=在 %s 上创建一个新的应用。在「Yandex.Passport API」这部分中选择以下权限:「访问邮箱地址」,「访问用户头像」和「访问用户名,名字和姓氏,性别」 +auths.tip.yandex=在 %s 上创建一个新的应用。在「Yandex.Passport API」这部分中选择以下权限:「访问邮箱地址」、「访问用户头像」和「访问用户名,名字和姓氏,性别」 auths.tip.mastodon=输入您想要认证的 mastodon 实例的自定义 URL (或使用默认值) auths.edit=修改认证源 auths.activated=该认证源已经启用 @@ -3306,7 +3306,7 @@ auths.invalid_openIdConnectAutoDiscoveryURL=无效的自动发现 URL(这必 config.server_config=服务器配置 config.app_name=站点名称 -config.app_ver=Gitea版本 +config.app_ver=Gitea 版本 config.app_url=Gitea 基本 URL config.custom_conf=配置文件路径 config.custom_file_root_path=自定义文件根路径 @@ -3402,23 +3402,23 @@ config.cache_interval=缓存周期 config.cache_conn=缓存连接字符串 config.cache_item_ttl=缓存项目 TTL config.cache_test=测试缓存 -config.cache_test_failed=缓存测试失败: %v。 +config.cache_test_failed=缓存测试失败:%v。 config.cache_test_slow=缓存测试成功,但响应缓慢:%s。 config.cache_test_succeeded=缓存测试成功,在 %s 时间内得到响应。 -config.session_config=Session 配置 -config.session_provider=Session 提供者 +config.session_config=会话配置 +config.session_provider=会话提供者 config.provider_config=提供者配置 config.cookie_name=Cookie 名称 config.gc_interval_time=GC 周期 -config.session_life_time=Session 生命周期 +config.session_life_time=会话生命周期 config.https_only=仅限 HTTPS config.cookie_life_time=Cookie 生命周期 config.picture_config=图片和头像配置 config.picture_service=图片服务 config.disable_gravatar=禁用 Gravatar 头像 -config.enable_federated_avatar=启用 Federated Avatars +config.enable_federated_avatar=启用 Federated 头像 config.open_with_editor_app_help=用于克隆菜单的编辑器。如果为空将使用默认值。展开可以查看默认值。 config.git_config=Git 配置 @@ -3434,7 +3434,7 @@ config.git_pull_timeout=拉取操作超时 config.git_gc_timeout=GC 操作超时 config.log_config=日志配置 -config.logger_name_fmt=日志:%s +config.logger_name_fmt=%s 日志 config.disabled_logger=禁用 config.access_log_mode=访问日志模式 config.access_log_template=访问日志模板 @@ -3502,16 +3502,16 @@ 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_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」标头。 +self_check.location_origin_mismatch=当前 URL(%[1]s)与 Gitea 的 URL(%[2]s)不匹配。如果您正在使用反向代理,请确保设置正确的「Host」和「X-Forwarded-Proto」标头。 [action] create_repo=创建了仓库 %s -rename_repo=重命名仓库 %[1]s%[3]s -commit_repo=推送到了仓库 %[4]s%[3]s 分支 +rename_repo=重命名了仓库 %[1]s%[3]s +commit_repo=推送了仓库 %[4]s%[3]s 分支 create_issue=`创建了工单 %[3]s#%[2]s` close_issue=`关闭了工单 %[3]s#%[2]s` reopen_issue=`重新打开了工单 %[3]s#%[2]s` @@ -3523,9 +3523,9 @@ comment_pull=`评论了合并请求 %[3]s#%[2]s` merge_pull_request=`合并了合并请求 %[3]s#%[2]s` auto_merge_pull_request=`自动合并了合并请求 %[3]s#%[2]s` transfer_repo=将仓库 %s 转移至 %s -push_tag=推送了标签 %[3]s 至仓库 %[4]s -delete_tag=从%[3]s 删除了标签 %[2]s -delete_branch=从 %[3]s 删除分支 %[2]s +push_tag=推送了 Git 标签 %[3]s 至仓库 %[4]s +delete_tag=从 %[3]s 删除了 Git 标签 %[2]s +delete_branch=从 %[3]s 删除了分支 %[2]s compare_branch=比较 compare_commits=比较 %d 提交 compare_commits_general=比较提交 @@ -3533,13 +3533,13 @@ mirror_sync_push=从镜像同步了提交至仓库 %[4]s 的 mirror_sync_create=从镜像同步了引用 %[3]s 至仓库 %[4]s mirror_sync_delete=从镜像同步并从 %[3]s 删除了引用 %[2]s approve_pull_request=`批准了 %[3]s#%[2]s` -reject_pull_request=`建议变更 %[3]s#%[2]s` +reject_pull_request=`建议了变更 %[3]s#%[2]s` publish_release=`在 %[3]s 发布了 %[4]s ` -review_dismissed=`取消了 %[4]s%[3]s#%[2]s 的变更请求` +review_dismissed=`取消了 %[4]s%[3]s#%[2]s 的评审` review_dismissed_reason=原因: create_branch=于 %[4]s 创建了分支 %[3]s starred_repo=点赞了 %[2]s -watched_repo=开始关注 %[2]s +watched_repo=关注了 %[2]s [tool] now=现在 @@ -3711,7 +3711,7 @@ rubygems.dependencies.development=开发依赖 rubygems.required.ruby=需要 Ruby 版本 rubygems.required.rubygems=需要 RubyGem 版本 swift.registry=从命令行设置此仓库: -swift.install=在您的 Package.swift文件中添加该包: +swift.install=在您的 Package.swift 文件中添加该包: swift.install2=并运行以下命令: vagrant.install=若要添加一个 Vagrant box,请运行以下命令: settings.link=将此软件包链接到仓库 @@ -3728,7 +3728,7 @@ 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.error=初始化 Cargo 索引失败:%v owner.settings.cargo.initialize.success=Cargo 索引已经成功创建。 owner.settings.cargo.rebuild=重建索引 owner.settings.cargo.rebuild.description=如果索引与存储的 Cargo 包不同步,重建可能会有用。 From 621f2fcadb0ed2b3a97dfc28d8cba7190f6b7914 Mon Sep 17 00:00:00 2001 From: wxiaoguang Date: Sun, 17 Aug 2025 00:24:30 +0800 Subject: [PATCH 18/97] Skip "parentsigned" check when the repo is empty (#35292) Fix #35280 --- services/asymkey/sign.go | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/services/asymkey/sign.go b/services/asymkey/sign.go index f94462ea46..2b77fb92dc 100644 --- a/services/asymkey/sign.go +++ b/services/asymkey/sign.go @@ -290,16 +290,22 @@ Loop: return false, nil, nil, err } defer gitRepo.Close() - commit, err := gitRepo.GetCommit(parentCommit) + isEmpty, err := gitRepo.IsEmpty() if err != nil { return false, nil, nil, err } - if commit.Signature == nil { - return false, nil, nil, &ErrWontSign{parentSigned} - } - verification := ParseCommitWithSignature(ctx, commit) - if !verification.Verified { - return false, nil, nil, &ErrWontSign{parentSigned} + if !isEmpty { + commit, err := gitRepo.GetCommit(parentCommit) + if err != nil { + return false, nil, nil, err + } + if commit.Signature == nil { + return false, nil, nil, &ErrWontSign{parentSigned} + } + verification := ParseCommitWithSignature(ctx, commit) + if !verification.Verified { + return false, nil, nil, &ErrWontSign{parentSigned} + } } } } From 08a7e65c84d6612b73b3c930fdeaa31a43b685e0 Mon Sep 17 00:00:00 2001 From: LePau <101608950+LePau@users.noreply.github.com> Date: Sat, 16 Aug 2025 10:51:45 -0600 Subject: [PATCH 19/97] Fix LFS range size header response (#35277) Fix #35276 Signed-off-by: LePau <101608950+LePau@users.noreply.github.com> --- services/lfs/server.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/services/lfs/server.go b/services/lfs/server.go index c9d9f164bf..9f2e532f23 100644 --- a/services/lfs/server.go +++ b/services/lfs/server.go @@ -114,7 +114,7 @@ func DownloadHandler(ctx *context.Context) { } } - ctx.Resp.Header().Set("Content-Range", fmt.Sprintf("bytes %d-%d/%d", fromByte, toByte, meta.Size-fromByte)) + ctx.Resp.Header().Set("Content-Range", fmt.Sprintf("bytes %d-%d/%d", fromByte, toByte, meta.Size)) ctx.Resp.Header().Set("Access-Control-Expose-Headers", "Content-Range") } } From 6619b1ed2badb2e3a01710cc4235c06c75d9474d Mon Sep 17 00:00:00 2001 From: GiteaBot Date: Mon, 18 Aug 2025 00:40:58 +0000 Subject: [PATCH 20/97] [skip ci] Updated translations via Crowdin --- options/locale/locale_zh-CN.ini | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/options/locale/locale_zh-CN.ini b/options/locale/locale_zh-CN.ini index bb67c763cb..f834d92b26 100644 --- a/options/locale/locale_zh-CN.ini +++ b/options/locale/locale_zh-CN.ini @@ -1649,7 +1649,7 @@ issues.role.member_helper=该用户是拥有此仓库的组织的成员。 issues.role.collaborator=协作者 issues.role.collaborator_helper=该用户已被邀请在仓库上进行协作。 issues.role.first_time_contributor=首次贡献者 -issues.role.first_time_contributor_helper=这是该用户对仓库的第一次贡献。 +issues.role.first_time_contributor_helper=这是该用户对此仓库的第一次贡献。 issues.role.contributor=贡献者 issues.role.contributor_helper=该用户之前提交过该仓库。 issues.re_request_review=再次请求审核 @@ -1905,7 +1905,7 @@ pulls.required_status_check_failed=一些必要的检查没有成功 pulls.required_status_check_missing=缺少一些必要的检查。 pulls.required_status_check_administrator=作为管理员,您仍可合并此合并请求 pulls.blocked_by_approvals=此合并请求还没有足够的批准。已获批准数 %d 个,需获批准数 %d 个。 -pulls.blocked_by_approvals_whitelisted=此合并请求还没有足够的批准。%[2]d 中的 %[1]d 个已由允许名单中的用户或团队批准。 +pulls.blocked_by_approvals_whitelisted=此合并请求尚未获得足够的批准。已获得 %d/%d 个来自允许列表中用户或团队的批准。 pulls.blocked_by_rejection=此合并请求有官方审核员请求的更改。 pulls.blocked_by_official_review_requests=此合并请求需要官方评审。 pulls.blocked_by_outdated_branch=此合并请求因过期而被阻止。 @@ -2828,7 +2828,7 @@ team_desc_helper=描述团队的目的或作用。 team_access_desc=仓库权限 team_permission_desc=权限 team_unit_desc=允许访问仓库单元 -team_unit_disabled=(已禁用) +team_unit_disabled=(已禁用) form.name_been_taken=组织名称「%s」已经被占用。 form.name_reserved=组织名称「%s」是保留的。 @@ -3562,7 +3562,7 @@ raw_seconds=秒 raw_minutes=分钟 [dropzone] -default_message=拖动文件或者点击此处上传。 +default_message=拖曳文件或点击此处上传。 invalid_input_type=您不能上传该类型的文件 file_too_big=文件体积({{filesize}} MB)超过了最大允许体积({{maxFilesize}} MB) remove_file=移除文件 From 28729849195564f3aec3db658b2393a17009c953 Mon Sep 17 00:00:00 2001 From: 6543 <6543@obermui.de> Date: Mon, 18 Aug 2025 16:51:16 +0200 Subject: [PATCH 21/97] nix dev shell add zip (#35300) as zip is needed in our makefile and not installed on nixos by default --- flake.nix | 1 + 1 file changed, 1 insertion(+) diff --git a/flake.nix b/flake.nix index 33f9449675..9008e1f839 100644 --- a/flake.nix +++ b/flake.nix @@ -39,6 +39,7 @@ gnused gnutar gzip + zip # frontend nodejs From d782cad7f8be7df76d89ad69d50c4b17c1e604f9 Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Mon, 18 Aug 2025 08:17:19 -0700 Subject: [PATCH 22/97] Add start time on perf trace because it seems some steps haven't been recorded. (#35282) The new trace log looks like ``` http start=2025-08-14 15:03:04 duration=0.6978s http.route=/ http.func start=2025-08-14 15:03:04 duration=0.6978s func=common.ForwardedHeadersHandler.ForwardedHeaders http.func start=2025-08-14 15:03:04 duration=0.6978s func=routing.(*requestRecordsManager).handler-fm http.func start=2025-08-14 15:03:04 duration=0.6978s func=gzhttp.NewWrapper http.func start=2025-08-14 15:03:04 duration=0.6975s func=session.Sessioner http.func start=2025-08-14 15:03:04 duration=0.6973s func=context.Contexter ``` --- modules/gtprof/trace_builtin.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/gtprof/trace_builtin.go b/modules/gtprof/trace_builtin.go index 2590ed3a13..7b4e3b8b4f 100644 --- a/modules/gtprof/trace_builtin.go +++ b/modules/gtprof/trace_builtin.go @@ -40,7 +40,7 @@ func (t *traceBuiltinSpan) toString(out *strings.Builder, indent int) { if t.ts.endTime.IsZero() { out.WriteString(" duration: (not ended)") } else { - fmt.Fprintf(out, " duration=%.4fs", t.ts.endTime.Sub(t.ts.startTime).Seconds()) + fmt.Fprintf(out, " start=%s duration=%.4fs", t.ts.startTime.Format("2006-01-02 15:04:05"), t.ts.endTime.Sub(t.ts.startTime).Seconds()) } for _, a := range t.ts.attributes { out.WriteString(" ") From 4ea8f33ae623e6c276c690e9d28c779316a65e65 Mon Sep 17 00:00:00 2001 From: Kerwin Bryant Date: Tue, 19 Aug 2025 04:45:15 +0800 Subject: [PATCH 23/97] fix: remove duplicate IDs (#35210) Signed-off-by: Kerwin Bryant Co-authored-by: silverwind Co-authored-by: Giteabot --- templates/repo/view_file.tmpl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/templates/repo/view_file.tmpl b/templates/repo/view_file.tmpl index 1486d7181d..d022af38fd 100644 --- a/templates/repo/view_file.tmpl +++ b/templates/repo/view_file.tmpl @@ -108,7 +108,7 @@ {{range $idx, $code := .FileContent}} {{$line := Eval $idx "+" 1}} - + {{if $.EscapeStatus.Escaped}} {{if (index $.LineEscapeStatus $idx).Escaped}}{{end}} {{end}} From 57b84417450fc9c2c87d3cac174ef10766881da3 Mon Sep 17 00:00:00 2001 From: 6543 <6543@obermui.de> Date: Mon, 18 Aug 2025 23:23:40 +0200 Subject: [PATCH 24/97] Refactor smal code snippeds in models/issues/pull.go (#35301) just code refactor nits --- models/issues/pull.go | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/models/issues/pull.go b/models/issues/pull.go index 00d7bfe1ca..7a37b627e1 100644 --- a/models/issues/pull.go +++ b/models/issues/pull.go @@ -29,6 +29,8 @@ import ( var ErrMustCollaborator = util.NewPermissionDeniedErrorf("user must be a collaborator") +const reviewedBy = "Reviewed-by: " + // ErrPullRequestNotExist represents a "PullRequestNotExist" kind of error. type ErrPullRequestNotExist struct { ID int64 @@ -348,7 +350,11 @@ type ReviewCount struct { func (pr *PullRequest) GetApprovalCounts(ctx context.Context) ([]*ReviewCount, error) { rCounts := make([]*ReviewCount, 0, 6) sess := db.GetEngine(ctx).Where("issue_id = ?", pr.IssueID) - return rCounts, sess.Select("issue_id, type, count(id) as `count`").Where("official = ? AND dismissed = ?", true, false).GroupBy("issue_id, type").Table("review").Find(&rCounts) + return rCounts, sess.Select("issue_id, type, count(id) as `count`"). + Where(builder.Eq{"official": true, "dismissed": false}). + GroupBy("issue_id, type"). + Table("review"). + Find(&rCounts) } // GetApprovers returns the approvers of the pull request @@ -392,7 +398,7 @@ func (pr *PullRequest) getReviewedByLines(ctx context.Context, writer io.Writer) } else if review.Reviewer == nil { continue } - if _, err := writer.Write([]byte("Reviewed-by: ")); err != nil { + if _, err := writer.Write([]byte(reviewedBy)); err != nil { return err } if _, err := writer.Write([]byte(review.Reviewer.NewGitSig().String())); err != nil { From 463016b31774cacf83df44d0bb580621d2af4020 Mon Sep 17 00:00:00 2001 From: Jackson Stewart Date: Tue, 19 Aug 2025 05:38:12 -0600 Subject: [PATCH 25/97] Upgrade devcontainer go version to 1.24.6 (#35298) Addresses go version mismatch when using the devcontainer as a result of [this commit](https://github.com/go-gitea/gitea/commit/793815adf7a694fa04c12bd3df3262e591f127ab) (bumps Go version from 1.24.5 to 1.24.6) The current official devcontainer Go image used in this repository (`1.24-bookworm`) uses 1.24.5 and sets GOTOOLCHAIN to local. This PR overrides it to auto so that build commands automatically update to the correct version. --------- Signed-off-by: Jackson Stewart Co-authored-by: techknowlogick --- .devcontainer/devcontainer.json | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index 95d673cd30..0bf0edc45e 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -1,6 +1,10 @@ { "name": "Gitea DevContainer", "image": "mcr.microsoft.com/devcontainers/go:1.24-bookworm", + "containerEnv": { + // override "local" from packaged version + "GOTOOLCHAIN": "auto" + }, "features": { // installs nodejs into container "ghcr.io/devcontainers/features/node:1": { From 9790f128cc858f1f420fef1631ef52e9261e073e Mon Sep 17 00:00:00 2001 From: silverwind Date: Tue, 19 Aug 2025 19:23:47 +0200 Subject: [PATCH 26/97] Update to golangci-lint@v2.4.0 (#35310) Adds go 1.25 support. No new issues discovered. https://github.com/golangci/golangci-lint/releases --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 77ea40f203..9cd32e4c33 100644 --- a/Makefile +++ b/Makefile @@ -28,7 +28,7 @@ XGO_VERSION := go-1.25.x AIR_PACKAGE ?= github.com/air-verse/air@v1 EDITORCONFIG_CHECKER_PACKAGE ?= github.com/editorconfig-checker/editorconfig-checker/v3/cmd/editorconfig-checker@v3 GOFUMPT_PACKAGE ?= mvdan.cc/gofumpt@v0.8.0 -GOLANGCI_LINT_PACKAGE ?= github.com/golangci/golangci-lint/v2/cmd/golangci-lint@v2.1.6 +GOLANGCI_LINT_PACKAGE ?= github.com/golangci/golangci-lint/v2/cmd/golangci-lint@v2.4.0 GXZ_PACKAGE ?= github.com/ulikunitz/xz/cmd/gxz@v0.5.12 MISSPELL_PACKAGE ?= github.com/golangci/misspell/cmd/misspell@v0.7.0 SWAGGER_PACKAGE ?= github.com/go-swagger/go-swagger/cmd/swagger@v0.32.3 From c4b70c57bca1063337ce2bbacbae181b5246ae23 Mon Sep 17 00:00:00 2001 From: eric-j-ason <75301977+eric-j-ason@users.noreply.github.com> Date: Tue, 19 Aug 2025 20:49:01 +0200 Subject: [PATCH 27/97] exit with success when already up to date (#35312) Exit `upgrade.sh` with status 0 (instead of status 1) when the installed Gitea is already on the latest version and nothing needs to be done. Fixes #35309 --- contrib/upgrade.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contrib/upgrade.sh b/contrib/upgrade.sh index 4b166a02a0..e5e296ea8b 100755 --- a/contrib/upgrade.sh +++ b/contrib/upgrade.sh @@ -85,7 +85,7 @@ fi # confirm update echo "Checking currently installed version..." current=$(giteacmd --version | cut -d ' ' -f 3) -[[ "$current" == "$giteaversion" ]] && echo "$current is already installed, stopping." && exit 1 +[[ "$current" == "$giteaversion" ]] && echo "$current is already installed, stopping." && exit 0 if [[ -z "${no_confirm:-}" ]]; then echo "Make sure to read the changelog first: https://github.com/go-gitea/gitea/blob/main/CHANGELOG.md" echo "Are you ready to update Gitea from ${current} to ${giteaversion}? (y/N)" From 709535c506b7baca67fabcd21f7df3b0bcc7c1c1 Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Wed, 20 Aug 2025 08:20:22 -0700 Subject: [PATCH 28/97] Fix some overflows in test (#35315) Fix #35311 --- models/repo/collaboration_test.go | 4 ++-- modules/templates/util_format_test.go | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/models/repo/collaboration_test.go b/models/repo/collaboration_test.go index 7b07dbffdf..1e0c84092b 100644 --- a/models/repo/collaboration_test.go +++ b/models/repo/collaboration_test.go @@ -85,8 +85,8 @@ func TestRepository_ChangeCollaborationAccessMode(t *testing.T) { assert.NoError(t, repo_model.ChangeCollaborationAccessMode(db.DefaultContext, repo, unittest.NonexistentID, perm.AccessModeAdmin)) - // Disvard invalid input. - assert.NoError(t, repo_model.ChangeCollaborationAccessMode(db.DefaultContext, repo, 4, perm.AccessMode(unittest.NonexistentID))) + // Discard invalid input. + assert.NoError(t, repo_model.ChangeCollaborationAccessMode(db.DefaultContext, repo, 4, perm.AccessMode(-1))) unittest.CheckConsistencyFor(t, &repo_model.Repository{ID: repo.ID}) } diff --git a/modules/templates/util_format_test.go b/modules/templates/util_format_test.go index 13a57c24e2..89e42532f9 100644 --- a/modules/templates/util_format_test.go +++ b/modules/templates/util_format_test.go @@ -13,6 +13,6 @@ func TestCountFmt(t *testing.T) { assert.Equal(t, "125", countFmt(125)) assert.Equal(t, "1.3k", countFmt(int64(1317))) assert.Equal(t, "21.3M", countFmt(21317675)) - assert.Equal(t, "45.7G", countFmt(45721317675)) + assert.Equal(t, "45.7G", countFmt(int64(45721317675))) assert.Empty(t, countFmt("test")) } From c0f24bd8035df8e995950c01e25ccb0af1601b1d Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Wed, 20 Aug 2025 20:57:42 -0700 Subject: [PATCH 29/97] Move organization's visibility change to danger zone. (#34814) image image --------- Co-authored-by: wxiaoguang --- models/user/user.go | 10 +++ modules/indexer/issues/util.go | 6 +- options/locale/locale_en-US.ini | 6 ++ routers/web/org/setting.go | 48 +++++++------ routers/web/web.go | 1 + services/forms/org.go | 1 - services/org/org.go | 71 ++++++++++++++++++ services/repository/create.go | 2 +- services/repository/repository.go | 10 +-- templates/org/settings/options.tmpl | 23 ------ .../org/settings/options_dangerzone.tmpl | 72 ++++++++++++++++--- web_src/css/base.css | 6 +- 12 files changed, 189 insertions(+), 67 deletions(-) diff --git a/models/user/user.go b/models/user/user.go index c362cbc6d2..9cad1cc7c9 100644 --- a/models/user/user.go +++ b/models/user/user.go @@ -955,6 +955,16 @@ func UpdateUserCols(ctx context.Context, u *User, cols ...string) error { return err } +// UpdateUserColsNoAutoTime update user according special columns +func UpdateUserColsNoAutoTime(ctx context.Context, u *User, cols ...string) error { + if err := ValidateUser(u, cols...); err != nil { + return err + } + + _, err := db.GetEngine(ctx).ID(u.ID).Cols(cols...).NoAutoTime().Update(u) + return err +} + // GetInactiveUsers gets all inactive users func GetInactiveUsers(ctx context.Context, olderThan time.Duration) ([]*User, error) { cond := builder.And( diff --git a/modules/indexer/issues/util.go b/modules/indexer/issues/util.go index 19d835a1d8..7647be58e8 100644 --- a/modules/indexer/issues/util.go +++ b/modules/indexer/issues/util.go @@ -97,10 +97,14 @@ func getIssueIndexerData(ctx context.Context, issueID int64) (*internal.IndexerD return nil, false, err } + if err := issue.Repo.LoadOwner(ctx); err != nil { + return nil, false, fmt.Errorf("issue.Repo.LoadOwner: %w", err) + } + return &internal.IndexerData{ ID: issue.ID, RepoID: issue.RepoID, - IsPublic: !issue.Repo.IsPrivate, + IsPublic: !issue.Repo.IsPrivate && issue.Repo.Owner.Visibility.IsPublic(), Title: issue.Title, Content: issue.Content, Comments: comments, diff --git a/options/locale/locale_en-US.ini b/options/locale/locale_en-US.ini index d7e73a0cfb..ba4664964e 100644 --- a/options/locale/locale_en-US.ini +++ b/options/locale/locale_en-US.ini @@ -120,6 +120,7 @@ error404 = The page you are trying to reach either does not exist
-
-
- -
-
- - -
-
-
-
- - -
-
-
-
- - -
-
-
-
diff --git a/templates/org/settings/options_dangerzone.tmpl b/templates/org/settings/options_dangerzone.tmpl index 01cf3fd405..d01252e3e1 100644 --- a/templates/org/settings/options_dangerzone.tmpl +++ b/templates/org/settings/options_dangerzone.tmpl @@ -3,6 +3,16 @@
+
+
+
{{ctx.Locale.Tr "org.settings.visibility"}}
+
{{ctx.Locale.Tr "org.settings.visibility_desc"}}
+
+
+ +
+
+
{{ctx.Locale.Tr "org.settings.rename"}}
@@ -25,15 +35,55 @@
+ +