aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAnthony Wang2023-03-12 23:17:11 +0000
committerAnthony Wang2023-03-12 23:19:57 +0000
commitdbc3eb7fa071307e623fde961bfdff0894856948 (patch)
tree8961dc6a935d9ee89f5adf680a142d36900aaebb
parentb4640101f3c8938ed689743606a79601201141ca (diff)
parente72290fd9aeb77a47311483d1d565e428ce40cd9 (diff)
Merge remote-tracking branch 'origin/main' into forgejo-federation
-rw-r--r--.drone.yml584
-rw-r--r--.gitpod.yml9
-rw-r--r--.stylelintrc.yaml6
-rw-r--r--CODE_OF_CONDUCT.md96
-rw-r--r--MAINTAINERS1
-rw-r--r--Makefile8
-rwxr-xr-xbuild/update-locales.sh44
-rw-r--r--cmd/admin.go11
-rw-r--r--cmd/convert.go2
-rw-r--r--cmd/dump.go3
-rw-r--r--cmd/serv.go25
-rw-r--r--contrib/init/ubuntu/gitea84
-rw-r--r--custom/conf/app.example.ini22
-rw-r--r--docs/content/doc/advanced/config-cheat-sheet.en-us.md12
-rw-r--r--docs/content/doc/advanced/config-cheat-sheet.zh-cn.md19
-rw-r--r--docs/content/doc/advanced/customizing-gitea.en-us.md15
-rw-r--r--docs/content/doc/developers/guidelines-frontend.en-us.md21
-rw-r--r--docs/content/doc/developers/hacking-on-gitea.zh-cn.md349
-rw-r--r--docs/content/doc/developers/oauth2-provider.en-us.md1
-rw-r--r--docs/content/doc/packages/maven.en-us.md48
-rw-r--r--docs/content/doc/usage/labels.en-us.md42
-rw-r--r--models/actions/run.go1
-rw-r--r--models/actions/task.go3
-rw-r--r--models/activities/action.go6
-rw-r--r--models/activities/action_test.go2
-rw-r--r--models/activities/user_heatmap.go4
-rw-r--r--models/auth/token_scope.go10
-rw-r--r--models/auth/token_scope_test.go4
-rw-r--r--models/db/common.go2
-rwxr-xr-xmodels/db/engine.go4
-rw-r--r--models/db/index.go2
-rw-r--r--models/db/iterate_test.go2
-rw-r--r--models/db/list_test.go4
-rw-r--r--models/db/sequence.go4
-rw-r--r--models/fixtures/repo_unit.yml6
-rw-r--r--models/fixtures/repository.yml15
-rw-r--r--models/fixtures/team.yml22
-rw-r--r--models/fixtures/user.yml6
-rw-r--r--models/fixtures/webhook.yml2
-rw-r--r--models/git/commit_status.go2
-rw-r--r--models/git/lfs_lock.go12
-rw-r--r--models/issues/label.go115
-rw-r--r--models/issues/label_test.go2
-rw-r--r--models/issues/pull_list.go16
-rw-r--r--models/issues/pull_test.go2
-rw-r--r--models/issues/stopwatch.go34
-rw-r--r--models/issues/stopwatch_test.go4
-rw-r--r--models/migrations/base/db.go28
-rw-r--r--models/migrations/migrations.go2
-rw-r--r--models/migrations/v1_12/v139.go4
-rw-r--r--models/migrations/v1_13/v140.go2
-rw-r--r--models/migrations/v1_13/v145.go8
-rw-r--r--models/migrations/v1_13/v151.go8
-rw-r--r--models/migrations/v1_14/v158.go10
-rw-r--r--models/migrations/v1_14/v175.go2
-rw-r--r--models/migrations/v1_15/v184.go4
-rw-r--r--models/migrations/v1_16/v191.go2
-rw-r--r--models/migrations/v1_17/v217.go2
-rw-r--r--models/migrations/v1_17/v218.go2
-rw-r--r--models/migrations/v1_17/v223.go4
-rw-r--r--models/migrations/v1_18/v225.go2
-rw-r--r--models/migrations/v1_19/v232.go2
-rw-r--r--models/migrations/v1_19/v242.go2
-rw-r--r--models/migrations/v1_20/v245.go74
-rw-r--r--models/organization/org.go26
-rw-r--r--models/project/project.go4
-rw-r--r--models/repo/repo_list.go2
-rw-r--r--models/unittest/testdb.go2
-rw-r--r--models/user/user.go5
-rw-r--r--models/webhook/webhook.go24
-rw-r--r--models/webhook/webhook_system.go10
-rw-r--r--models/webhook/webhook_test.go24
-rw-r--r--modules/auth/password/hash/setting.go29
-rw-r--r--modules/cache/context.go119
-rw-r--r--modules/cache/context_test.go39
-rw-r--r--modules/context/access_log.go34
-rw-r--r--modules/context/api.go2
-rw-r--r--modules/context/context.go4
-rw-r--r--modules/context/org.go78
-rw-r--r--modules/csv/csv_test.go6
-rw-r--r--modules/doctor/dbconsistency.go2
-rw-r--r--modules/git/command.go2
-rw-r--r--modules/git/commit.go13
-rw-r--r--modules/git/git.go8
-rw-r--r--modules/git/pipeline/revlist.go5
-rw-r--r--modules/git/repo_commit.go21
-rw-r--r--modules/git/repo_commit_gogit.go39
-rw-r--r--modules/git/repo_commit_nogogit.go4
-rw-r--r--modules/git/repo_commit_test.go5
-rw-r--r--modules/git/repo_compare.go11
-rw-r--r--modules/git/repo_ref_test.go12
-rw-r--r--modules/git/repo_stats_test.go4
-rw-r--r--modules/git/repo_tag_test.go9
-rw-r--r--modules/git/repo_test.go6
-rw-r--r--modules/git/tests/repos/repo1_bare/indexbin0 -> 65 bytes
-rw-r--r--modules/git/tests/repos/repo1_bare/logs/HEAD1
-rw-r--r--modules/git/tests/repos/repo1_bare/logs/refs/heads/master1
-rw-r--r--modules/git/tests/repos/repo1_bare/objects/1c/91d130dc5fb75fd2d9f586a058650889cfe7fbbin0 -> 813 bytes
-rw-r--r--modules/git/tests/repos/repo1_bare/objects/28/b55526e7100924d864dd89e35c1ea62e7a5a32bin0 -> 818 bytes
-rw-r--r--modules/git/tests/repos/repo1_bare/objects/36/f97d9a96457e2bab511db30fe2db03893ebc64bin0 -> 770 bytes
-rw-r--r--modules/git/tests/repos/repo1_bare/objects/4b/825dc642cb6eb9a060e54bf8d69288fbee4904bin0 -> 15 bytes
-rw-r--r--modules/git/tests/repos/repo1_bare/objects/93/3305878a3c9ad485c29b87fb662a73a9675c4bbin0 -> 770 bytes
-rw-r--r--modules/git/tests/repos/repo1_bare/objects/ce/064814f4a0d337b333e646ece456cd39fab612bin0 -> 815 bytes
-rw-r--r--modules/git/tests/repos/repo1_bare/objects/cf/8b0b492a950b358a7ce7f9d01b18aef48a6b2dbin0 -> 827 bytes
-rw-r--r--modules/git/tests/repos/repo1_bare/refs/heads/master2
-rw-r--r--modules/git/tests/repos/repo1_bare/refs/tags/signed-tag1
-rw-r--r--modules/httpcache/httpcache.go12
-rw-r--r--modules/label/label.go46
-rw-r--r--modules/label/parser.go126
-rw-r--r--modules/label/parser_test.go72
-rw-r--r--modules/markup/console/console_test.go4
-rw-r--r--modules/markup/csv/csv_test.go4
-rw-r--r--modules/markup/html.go3
-rw-r--r--modules/markup/html_internal_test.go43
-rw-r--r--modules/markup/html_test.go14
-rw-r--r--modules/markup/markdown/markdown_test.go23
-rw-r--r--modules/markup/orgmode/orgmode_test.go4
-rw-r--r--modules/markup/sanitizer.go2
-rw-r--r--modules/options/base.go56
-rw-r--r--modules/options/dynamic.go70
-rw-r--r--modules/options/static.go50
-rw-r--r--modules/public/public.go4
-rw-r--r--modules/queue/queue_channel.go5
-rw-r--r--modules/queue/queue_disk_channel.go29
-rw-r--r--modules/queue/queue_disk_channel_test.go8
-rw-r--r--modules/queue/unique_queue_channel.go4
-rw-r--r--modules/queue/unique_queue_channel_test.go7
-rw-r--r--modules/queue/unique_queue_disk_channel.go41
-rw-r--r--modules/queue/unique_queue_disk_channel_test.go259
-rw-r--r--modules/repository/create.go3
-rw-r--r--modules/repository/init.go134
-rw-r--r--modules/repository/push.go18
-rw-r--r--modules/setting/database.go49
-rw-r--r--modules/setting/log.go2
-rw-r--r--modules/setting/storage.go1
-rw-r--r--modules/storage/local.go3
-rw-r--r--modules/storage/minio.go25
-rw-r--r--modules/templates/helper.go21
-rw-r--r--modules/typesniffer/typesniffer.go31
-rw-r--r--modules/typesniffer/typesniffer_test.go29
-rw-r--r--modules/util/path.go8
-rw-r--r--modules/util/path_test.go12
-rw-r--r--options/label/Advanced.yaml70
-rw-r--r--options/license/AdaCore-doc1
-rw-r--r--options/license/Autoconf-exception-generic4
-rw-r--r--options/license/Autoconf-exception-macro12
-rw-r--r--options/license/BSD-4.3RENO9
-rw-r--r--options/license/BSD-4.3TAHOE11
-rw-r--r--options/license/BSD-Advertising-Acknowledgement37
-rw-r--r--options/license/BSD-Attribution-HPND-disclaimer37
-rw-r--r--options/license/Brian-Gladman-3-Clause26
-rw-r--r--options/license/CC-BY-NC-SA-2.0-DE85
-rw-r--r--options/license/CFITSIO7
-rw-r--r--options/license/CMU-Mach22
-rw-r--r--options/license/Clips15
-rw-r--r--options/license/Cornell-Lossless-JPEG20
-rw-r--r--options/license/GNAT-exception6
-rw-r--r--options/license/HP-198610
-rw-r--r--options/license/HPND-Markus-Kuhn3
-rw-r--r--options/license/HPND-sell-variant-MIT-disclaimer20
-rw-r--r--options/license/IEC-Code-Components-EULA37
-rw-r--r--options/license/JPL-image21
-rw-r--r--options/license/Kazlib4
-rw-r--r--options/license/Martin-Birgmeier5
-rw-r--r--options/license/OFFIS22
-rw-r--r--options/license/OpenPBS-2.376
-rw-r--r--options/license/QPL-1.0-INRIA-2004102
-rw-r--r--options/license/QPL-1.0-INRIA-2004-exception5
-rw-r--r--options/license/SWI-exception6
-rw-r--r--options/license/SunPro6
-rw-r--r--options/license/TPL-1.0475
-rw-r--r--options/license/UCAR32
-rw-r--r--options/license/snprintf3
-rw-r--r--options/license/w3m11
-rw-r--r--options/license/xlock14
-rw-r--r--options/locale/locale_bg-BG.ini1265
-rw-r--r--options/locale/locale_cs-CZ.ini244
-rw-r--r--options/locale/locale_de-DE.ini101
-rw-r--r--options/locale/locale_el-GR.ini203
-rw-r--r--options/locale/locale_en-US.ini9
-rw-r--r--options/locale/locale_es-ES.ini95
-rw-r--r--options/locale/locale_fa-IR.ini102
-rw-r--r--options/locale/locale_fi-FI.ini79
-rw-r--r--options/locale/locale_fr-FR.ini552
-rw-r--r--options/locale/locale_hu-HU.ini431
-rw-r--r--options/locale/locale_id-ID.ini202
-rw-r--r--options/locale/locale_is-IS.ini60
-rw-r--r--options/locale/locale_it-IT.ini94
-rw-r--r--options/locale/locale_ja-JP.ini256
-rw-r--r--options/locale/locale_ko-KR.ini89
-rw-r--r--options/locale/locale_lv-LV.ini389
-rw-r--r--options/locale/locale_ml-IN.ini804
-rw-r--r--options/locale/locale_nl-NL.ini107
-rw-r--r--options/locale/locale_pl-PL.ini94
-rw-r--r--options/locale/locale_pt-BR.ini238
-rw-r--r--options/locale/locale_pt-PT.ini261
-rw-r--r--options/locale/locale_ru-RU.ini90
-rw-r--r--options/locale/locale_si-LK.ini94
-rw-r--r--options/locale/locale_sk-SK.ini80
-rw-r--r--options/locale/locale_sv-SE.ini77
-rw-r--r--options/locale/locale_tr-TR.ini129
-rw-r--r--options/locale/locale_uk-UA.ini105
-rw-r--r--options/locale/locale_zh-CN.ini266
-rw-r--r--options/locale/locale_zh-HK.ini115
-rw-r--r--options/locale/locale_zh-TW.ini297
-rw-r--r--package-lock.json256
-rw-r--r--package.json2
-rw-r--r--routers/api/actions/runner/runner.go8
-rw-r--r--routers/api/v1/activitypub/create.go2
-rw-r--r--routers/api/v1/admin/adopt.go6
-rw-r--r--routers/api/v1/admin/hooks.go5
-rw-r--r--routers/api/v1/api.go7
-rw-r--r--routers/api/v1/org/hook.go79
-rw-r--r--routers/api/v1/org/label.go33
-rw-r--r--routers/api/v1/repo/branch.go2
-rw-r--r--routers/api/v1/repo/hook.go6
-rw-r--r--routers/api/v1/repo/issue_attachment.go2
-rw-r--r--routers/api/v1/repo/issue_comment_attachment.go2
-rw-r--r--routers/api/v1/repo/label.go52
-rw-r--r--routers/api/v1/repo/notes.go12
-rw-r--r--routers/api/v1/repo/pull.go2
-rw-r--r--routers/api/v1/repo/pull_review.go4
-rw-r--r--routers/api/v1/repo/release_attachment.go2
-rw-r--r--routers/api/v1/repo/repo.go11
-rw-r--r--routers/api/v1/user/hook.go154
-rw-r--r--routers/api/v1/utils/hook.go89
-rw-r--r--routers/common/middleware.go35
-rw-r--r--routers/common/middleware_test.go70
-rw-r--r--routers/init.go2
-rw-r--r--routers/install/install.go54
-rw-r--r--routers/install/routes.go15
-rw-r--r--routers/private/serv.go2
-rw-r--r--routers/web/admin/auths.go23
-rw-r--r--routers/web/admin/repos.go6
-rw-r--r--routers/web/base.go7
-rw-r--r--routers/web/explore/repo.go1
-rw-r--r--routers/web/healthcheck/check.go2
-rw-r--r--routers/web/org/home.go1
-rw-r--r--routers/web/org/org_labels.go5
-rw-r--r--routers/web/org/projects.go30
-rw-r--r--routers/web/org/setting.go10
-rw-r--r--routers/web/repo/actions/view.go24
-rw-r--r--routers/web/repo/attachment.go2
-rw-r--r--routers/web/repo/branch.go2
-rw-r--r--routers/web/repo/editor.go2
-rw-r--r--routers/web/repo/http.go4
-rw-r--r--routers/web/repo/issue.go40
-rw-r--r--routers/web/repo/issue_label.go5
-rw-r--r--routers/web/repo/issue_stopwatch.go14
-rw-r--r--routers/web/repo/lfs.go2
-rw-r--r--routers/web/repo/projects.go7
-rw-r--r--routers/web/repo/pull.go4
-rw-r--r--routers/web/repo/pull_review.go2
-rw-r--r--routers/web/repo/repo.go6
-rw-r--r--routers/web/repo/setting.go16
-rw-r--r--routers/web/repo/setting_protected_branch.go2
-rw-r--r--routers/web/repo/view.go2
-rw-r--r--routers/web/repo/webhook.go67
-rw-r--r--routers/web/shared/user/header.go2
-rw-r--r--routers/web/user/avatar.go2
-rw-r--r--routers/web/user/code.go1
-rw-r--r--routers/web/user/profile.go1
-rw-r--r--routers/web/user/setting/adopt.go4
-rw-r--r--routers/web/user/setting/webhooks.go48
-rw-r--r--routers/web/web.go163
-rw-r--r--services/actions/clear_tasks.go22
-rw-r--r--services/actions/commit_status.go10
-rw-r--r--services/actions/notifier_helper.go3
-rw-r--r--services/attachment/attachment.go8
-rw-r--r--services/attachment/attachment_test.go2
-rw-r--r--services/auth/source/oauth2/source_register.go4
-rw-r--r--services/context/user.go9
-rw-r--r--services/forms/repo_form.go2
-rw-r--r--services/gitdiff/gitdiff.go2
-rw-r--r--services/mailer/incoming/incoming_handler.go4
-rw-r--r--services/migrations/gitea_uploader.go23
-rw-r--r--services/mirror/mirror_pull.go7
-rw-r--r--services/packages/container/blob_uploader.go4
-rw-r--r--services/pull/comment.go90
-rw-r--r--services/pull/lfs.go2
-rw-r--r--services/pull/merge.go500
-rw-r--r--services/pull/merge_merge.go25
-rw-r--r--services/pull/merge_prepare.go288
-rw-r--r--services/pull/merge_rebase.go50
-rw-r--r--services/pull/merge_squash.go85
-rw-r--r--services/pull/patch.go17
-rw-r--r--services/pull/pull.go32
-rw-r--r--services/pull/review.go8
-rw-r--r--services/pull/temp_repo.go208
-rw-r--r--services/pull/update.go105
-rw-r--r--services/pull/update_rebase.go107
-rw-r--r--services/release/release_test.go7
-rw-r--r--services/repository/adopt.go22
-rw-r--r--services/repository/adopt_test.go10
-rw-r--r--services/repository/avatar.go10
-rw-r--r--services/repository/avatar_test.go9
-rw-r--r--services/repository/branch.go15
-rw-r--r--services/repository/files/file.go4
-rw-r--r--services/repository/fork.go4
-rw-r--r--services/repository/hooks.go2
-rw-r--r--services/repository/push.go30
-rw-r--r--services/repository/repository.go14
-rw-r--r--services/repository/review.go9
-rw-r--r--services/repository/review_test.go5
-rw-r--r--services/repository/template.go6
-rw-r--r--services/repository/transfer.go5
-rw-r--r--services/webhook/webhook.go10
-rw-r--r--templates/admin/auth/source/oauth.tmpl2
-rw-r--r--templates/admin/user/new.tmpl6
-rw-r--r--templates/base/head.tmpl2
-rw-r--r--templates/mail/issue/assigned.tmpl2
-rw-r--r--templates/mail/issue/default.tmpl6
-rw-r--r--templates/mail/release.tmpl4
-rw-r--r--templates/org/menu.tmpl10
-rw-r--r--templates/post-install.tmpl4
-rw-r--r--templates/projects/list.tmpl4
-rw-r--r--templates/projects/new.tmpl1
-rw-r--r--templates/projects/view.tmpl8
-rw-r--r--templates/repo/actions/runs_list.tmpl2
-rw-r--r--templates/repo/activity.tmpl14
-rw-r--r--templates/repo/branch_dropdown.tmpl128
-rw-r--r--templates/repo/commit_page.tmpl8
-rw-r--r--templates/repo/commits_list.tmpl2
-rw-r--r--templates/repo/diff/box.tmpl4
-rw-r--r--templates/repo/diff/comment_form.tmpl13
-rw-r--r--templates/repo/diff/comments.tmpl6
-rw-r--r--templates/repo/diff/section_unified.tmpl63
-rw-r--r--templates/repo/editor/commit_form.tmpl2
-rw-r--r--templates/repo/editor/diff_preview.tmpl2
-rw-r--r--templates/repo/home.tmpl16
-rw-r--r--templates/repo/issue/labels/label.tmpl2
-rw-r--r--templates/repo/issue/labels/label_list.tmpl8
-rw-r--r--templates/repo/issue/labels/labels_sidebar.tmpl6
-rw-r--r--templates/repo/issue/list.tmpl4
-rw-r--r--templates/repo/issue/milestone_issues.tmpl4
-rw-r--r--templates/repo/issue/new_form.tmpl22
-rw-r--r--templates/repo/issue/view_content.tmpl8
-rw-r--r--templates/repo/issue/view_content/add_reaction.tmpl4
-rw-r--r--templates/repo/issue/view_content/attachments.tmpl4
-rw-r--r--templates/repo/issue/view_content/comments.tmpl43
-rw-r--r--templates/repo/issue/view_content/comments_delete_time.tmpl14
-rw-r--r--templates/repo/issue/view_content/context_menu.tmpl20
-rw-r--r--templates/repo/issue/view_content/reactions.tmpl4
-rw-r--r--templates/repo/issue/view_content/sidebar.tmpl18
-rw-r--r--templates/repo/projects/list.tmpl2
-rw-r--r--templates/repo/projects/new.tmpl1
-rw-r--r--templates/repo/projects/view.tmpl4
-rw-r--r--templates/repo/release/new.tmpl33
-rw-r--r--templates/repo/settings/lfs_file_find.tmpl2
-rw-r--r--templates/repo/settings/webhook/history.tmpl2
-rw-r--r--templates/shared/issuelist.tmpl8
-rw-r--r--templates/swagger/v1_json.tmpl146
-rw-r--r--templates/user/dashboard/feeds.tmpl14
-rw-r--r--templates/user/dashboard/navbar.tmpl14
-rw-r--r--templates/user/dashboard/repolist.tmpl82
-rw-r--r--templates/user/overview/header.tmpl8
-rw-r--r--templates/user/profile.tmpl2
-rw-r--r--templates/user/settings/applications.tmpl6
-rw-r--r--templates/user/settings/hook_new.tmpl53
-rw-r--r--templates/user/settings/hooks.tmpl8
-rw-r--r--templates/user/settings/navbar.tmpl5
-rw-r--r--tests/gitea-repositories-meta/user2/readme-test.git/HEAD1
-rw-r--r--tests/gitea-repositories-meta/user2/readme-test.git/config4
-rw-r--r--tests/gitea-repositories-meta/user2/readme-test.git/info/exclude6
-rw-r--r--tests/gitea-repositories-meta/user2/readme-test.git/info/refs21
-rw-r--r--tests/gitea-repositories-meta/user2/readme-test.git/objects/12/11481f7314efbfe4e44703170d96c8fac8172bbin0 -> 169 bytes
-rw-r--r--tests/gitea-repositories-meta/user2/readme-test.git/objects/17/2343566bf11fc71ba4acf8d2ea70d12bc1d037bin0 -> 214 bytes
-rw-r--r--tests/gitea-repositories-meta/user2/readme-test.git/objects/1a/48cae3f18ccd9c929e6608f67087dbaac3cf9ebin0 -> 167 bytes
-rw-r--r--tests/gitea-repositories-meta/user2/readme-test.git/objects/1e/1e08102cf1b1fc01c069c88ee75445974363abbin0 -> 83 bytes
-rw-r--r--tests/gitea-repositories-meta/user2/readme-test.git/objects/21/470f9b3e8ff24e0fa083d2dbc447f4c34013552
-rw-r--r--tests/gitea-repositories-meta/user2/readme-test.git/objects/23/65bfe0c5714e2e3f2d53bb302b10d8d5b4fc7dbin0 -> 175 bytes
-rw-r--r--tests/gitea-repositories-meta/user2/readme-test.git/objects/38/9d08c6a71d024a91f14089007cd789cd977ca6bin0 -> 48 bytes
-rw-r--r--tests/gitea-repositories-meta/user2/readme-test.git/objects/3a/a8f4e0e1a535f0f9e0ae40e6ec1bce42642bc4bin0 -> 140 bytes
-rw-r--r--tests/gitea-repositories-meta/user2/readme-test.git/objects/3b/23d7f1a9cb904cb46f5f2272bfa5ed5f871fb91
-rw-r--r--tests/gitea-repositories-meta/user2/readme-test.git/objects/50/6ff7310f420e878595b4bc8f11688e3f0ae14ebin0 -> 166 bytes
-rw-r--r--tests/gitea-repositories-meta/user2/readme-test.git/objects/58/3eb775c596858380273492759d39081d65d029bin0 -> 169 bytes
-rw-r--r--tests/gitea-repositories-meta/user2/readme-test.git/objects/60/ea618ae7d4ecbe9c1962591c7da1b05bb1a5c83
-rw-r--r--tests/gitea-repositories-meta/user2/readme-test.git/objects/6a/b05db4c52530726c1856eb558228e9d1949e7fbin0 -> 169 bytes
-rw-r--r--tests/gitea-repositories-meta/user2/readme-test.git/objects/71/60a063b5544b5a78131b94f47bfd200046eda2bin0 -> 167 bytes
-rw-r--r--tests/gitea-repositories-meta/user2/readme-test.git/objects/75/6c70c97047d8aeb11ca3c71edd9fb76cefee9cbin0 -> 28 bytes
-rw-r--r--tests/gitea-repositories-meta/user2/readme-test.git/objects/7f/2b9f991d99362eb827b67f4ae2f5fbc5fa2271bin0 -> 211 bytes
-rw-r--r--tests/gitea-repositories-meta/user2/readme-test.git/objects/7f/792e709143fb0f021da2371e5f40d1bcc284fdbin0 -> 166 bytes
-rw-r--r--tests/gitea-repositories-meta/user2/readme-test.git/objects/82/817856dadc7f6b944633e1b77d5b6e302dde06bin0 -> 51 bytes
-rw-r--r--tests/gitea-repositories-meta/user2/readme-test.git/objects/8b/4149e7dede3cd53ba11c64c88b057c5fe2c200bin0 -> 169 bytes
-rw-r--r--tests/gitea-repositories-meta/user2/readme-test.git/objects/93/54813d81053c14afe878a9f056b937ec42bb48bin0 -> 28 bytes
-rw-r--r--tests/gitea-repositories-meta/user2/readme-test.git/objects/9c/72c10e55e7d6ea21f591aa424e2625e8ad8094bin0 -> 136 bytes
-rw-r--r--tests/gitea-repositories-meta/user2/readme-test.git/objects/a3/cd04bb110e17591ac04e156c7df2c2f5c96fa6bin0 -> 82 bytes
-rw-r--r--tests/gitea-repositories-meta/user2/readme-test.git/objects/b0/e851a5619e2d6cee1da25a15ab67305f0861ecbin0 -> 76 bytes
-rw-r--r--tests/gitea-repositories-meta/user2/readme-test.git/objects/b4/4c8eb00bdaf0522de61e591fee5f66851ef4b5bin0 -> 112 bytes
-rw-r--r--tests/gitea-repositories-meta/user2/readme-test.git/objects/b8/eaa80ad86072e1f23d2638842154ce9aceff8dbin0 -> 77 bytes
-rw-r--r--tests/gitea-repositories-meta/user2/readme-test.git/objects/d5/34f914944c3c943a6bdb677d869ac54934928dbin0 -> 31 bytes
-rw-r--r--tests/gitea-repositories-meta/user2/readme-test.git/objects/e2/f9904cd97b4045feecfffef5a426e9461bee70bin0 -> 117 bytes
-rw-r--r--tests/gitea-repositories-meta/user2/readme-test.git/objects/e3/a6fd8fe49e323ee10017f72b777a53fbd8076f3
-rw-r--r--tests/gitea-repositories-meta/user2/readme-test.git/objects/e7/bf02fcfa7a86f7fe9e8158b55d58ddf9d877ecbin0 -> 171 bytes
-rw-r--r--tests/gitea-repositories-meta/user2/readme-test.git/objects/ea/57c91ddb8b4ac705b5ac4c34c7a48f2d0fc180bin0 -> 77 bytes
-rw-r--r--tests/gitea-repositories-meta/user2/readme-test.git/objects/fe/495ea336f079ef2bed68648d0ba9a37cdbd4aabin0 -> 197 bytes
-rw-r--r--tests/gitea-repositories-meta/user2/readme-test.git/objects/info/commit-graphbin0 -> 2612 bytes
-rw-r--r--tests/gitea-repositories-meta/user2/readme-test.git/objects/info/packs2
-rw-r--r--tests/gitea-repositories-meta/user2/readme-test.git/objects/pack/pack-8933bd634b76f8154310cccb52537a0195e43166.bitmapbin0 -> 1642 bytes
-rw-r--r--tests/gitea-repositories-meta/user2/readme-test.git/objects/pack/pack-8933bd634b76f8154310cccb52537a0195e43166.idxbin0 -> 4012 bytes
-rw-r--r--tests/gitea-repositories-meta/user2/readme-test.git/objects/pack/pack-8933bd634b76f8154310cccb52537a0195e43166.packbin0 -> 7854 bytes
-rw-r--r--tests/gitea-repositories-meta/user2/readme-test.git/packed-refs22
-rw-r--r--tests/gitea-repositories-meta/user2/readme-test.git/refs/heads/fallbacks-broken-symlinks1
-rw-r--r--tests/gitea-repositories-meta/user2/repo1.git/objects/40/3d76c604cb569323864e06a07b85d466924802bin0 -> 68 bytes
-rw-r--r--tests/gitea-repositories-meta/user2/repo1.git/objects/78/fb907e3a3309eae4fe8fef030874cebbf1cd5ebin0 -> 158 bytes
-rw-r--r--tests/gitea-repositories-meta/user2/repo1.git/objects/f3/fa0f5cc797fc4c02a1b8bec9de4b2072fcdbdfbin0 -> 53 bytes
-rw-r--r--tests/gitea-repositories-meta/user2/repo1.git/refs/heads/home-md-img-check1
-rw-r--r--tests/integration/markup_external_test.go2
-rw-r--r--tests/integration/migration-test/migration_test.go10
-rw-r--r--tests/integration/pull_merge_test.go2
-rw-r--r--tests/integration/pull_update_test.go2
-rw-r--r--tests/integration/repo_test.go125
-rw-r--r--tests/mysql.ini.tmpl25
-rw-r--r--tests/pgsql.ini.tmpl21
-rw-r--r--tests/test_utils.go6
-rw-r--r--web_src/fomantic/build/semantic.js4
-rw-r--r--web_src/js/components/ActionRunStatus.vue30
-rw-r--r--web_src/js/components/ContextPopup.vue2
-rw-r--r--web_src/js/components/DashboardRepoList.js91
-rw-r--r--web_src/js/components/RepoActionView.vue28
-rw-r--r--web_src/js/components/RepoBranchTagDropdown.js67
-rw-r--r--web_src/js/features/aria.js5
-rw-r--r--web_src/js/features/citation.js2
-rw-r--r--web_src/js/features/comp/EasyMDE.js3
-rw-r--r--web_src/js/features/comp/LabelEdit.js2
-rw-r--r--web_src/js/features/contextpopup.js3
-rw-r--r--web_src/js/features/imagediff.js15
-rw-r--r--web_src/js/features/install.js39
-rw-r--r--web_src/js/features/repo-diff.js14
-rw-r--r--web_src/js/features/repo-editor.js66
-rw-r--r--web_src/js/features/repo-issue.js32
-rw-r--r--web_src/js/features/repo-legacy.js30
-rw-r--r--web_src/js/features/repo-projects.js48
-rw-r--r--web_src/js/features/repo-release.js39
-rw-r--r--web_src/js/index.js4
-rw-r--r--web_src/js/markup/mermaid.js41
-rw-r--r--web_src/js/svg.js3
-rw-r--r--web_src/js/webcomponents/README.md19
-rw-r--r--web_src/less/_base.less3
-rw-r--r--web_src/less/_repository.less36
-rw-r--r--web_src/less/chroma/chroma-style-diff.go79
-rw-r--r--web_src/less/chroma/dark.less14
-rw-r--r--web_src/less/chroma/light.less13
-rw-r--r--web_src/less/features/imagediff.less5
-rw-r--r--web_src/less/helpers.less21
-rw-r--r--web_src/less/themes/theme-arc-green.less1
-rw-r--r--webpack.config.js2
447 files changed, 10950 insertions, 5895 deletions
diff --git a/.drone.yml b/.drone.yml
index cf0caf761..1181b809b 100644
--- a/.drone.yml
+++ b/.drone.yml
@@ -32,6 +32,7 @@ steps:
pull: always
commands:
- make deps-backend
+ - make deps-tools
volumes:
- name: deps
path: /go
@@ -168,7 +169,7 @@ steps:
---
kind: pipeline
type: docker
-name: testing-amd64
+name: testing-pgsql
platform:
os: linux
@@ -191,51 +192,26 @@ volumes:
temp: {}
services:
- - name: mysql
- image: mysql:5.7
- pull: always
- environment:
- MYSQL_ALLOW_EMPTY_PASSWORD: yes
- MYSQL_DATABASE: test
-
- - name: mysql8
- image: mysql:8
- pull: always
- environment:
- MYSQL_ALLOW_EMPTY_PASSWORD: yes
- MYSQL_DATABASE: testgitea
-
- - name: mssql
- image: mcr.microsoft.com/mssql/server:latest
- pull: always
+ - name: pgsql
+ pull: default
+ image: postgres:15
environment:
- ACCEPT_EULA: Y
- MSSQL_PID: Standard
- SA_PASSWORD: MwantsaSecurePassword1
+ POSTGRES_DB: test
+ POSTGRES_PASSWORD: postgres
- name: ldap
image: gitea/test-openldap:latest
pull: always
- - name: elasticsearch
- image: elasticsearch:7.5.0
- pull: always
- environment:
- discovery.type: single-node
-
- name: minio
image: minio/minio:RELEASE.2021-03-12T00-00-47Z
pull: always
commands:
- - minio server /data
+ - minio server /data
environment:
MINIO_ACCESS_KEY: 123456
MINIO_SECRET_KEY: 12345678
- - name: smtpimap
- image: tabascoterrier/docker-imap-devel:latest
- pull: always
-
steps:
- name: fetch-tags
image: docker:git
@@ -257,12 +233,6 @@ steps:
- name: deps
path: /go
- - name: tag-pre-condition
- image: drone/git
- pull: always
- commands:
- - git update-ref refs/heads/tag_test ${DRONE_COMMIT_SHA}
-
- name: prepare-test-env
image: gitea/test_env:linux-amd64 # https://gitea.com/gitea/test-env
pull: always
@@ -278,88 +248,157 @@ steps:
environment:
GOPROXY: https://goproxy.io # proxy.golang.org is blocked in China, this proxy is not
GOSUMDB: sum.golang.org
- TAGS: bindata sqlite sqlite_unlock_notify
+ TAGS: bindata
depends_on: [deps-backend, prepare-test-env]
volumes:
- name: deps
path: /go
- - name: unit-test
+ - name: test-pgsql
image: gitea/test_env:linux-amd64 # https://gitea.com/gitea/test-env
user: gitea
commands:
- - make unit-test-coverage test-check
+ - timeout -s ABRT 50m make test-pgsql-migration test-pgsql
environment:
GOPROXY: https://goproxy.io
- TAGS: bindata sqlite sqlite_unlock_notify
+ TAGS: bindata gogit
RACE_ENABLED: true
- GITHUB_READ_TOKEN:
- from_secret: github_read_token
- depends_on: [deps-backend, prepare-test-env]
+ TEST_TAGS: gogit
+ TEST_LDAP: 1
+ USE_REPO_TEST_DIR: 1
+ depends_on: [build]
volumes:
- name: deps
path: /go
- - name: unit-test-gogit
+---
+kind: pipeline
+type: docker
+name: testing-mysql
+
+platform:
+ os: linux
+ arch: amd64
+
+depends_on:
+ - compliance
+
+trigger:
+ event:
+ - push
+ - tag
+ - pull_request
+ paths:
+ exclude:
+ - docs/**
+
+volumes:
+ - name: deps
+ temp: {}
+
+services:
+ - name: mysql
+ image: mysql:5.7
+ pull: always
+ environment:
+ MYSQL_ALLOW_EMPTY_PASSWORD: yes
+ MYSQL_DATABASE: test
+
+ - name: elasticsearch
+ image: elasticsearch:7.5.0
+ pull: always
+ environment:
+ discovery.type: single-node
+
+ - name: smtpimap
+ image: tabascoterrier/docker-imap-devel:latest
+ pull: always
+
+steps:
+ - name: fetch-tags
+ image: docker:git
+ pull: always
+ commands:
+ - git config --global --add safe.directory /drone/src
+ - git fetch --tags --force
+ when:
+ event:
+ exclude:
+ - pull_request
+
+ - name: deps-backend
+ image: golang:1.20
+ pull: always
+ commands:
+ - make deps-backend
+ volumes:
+ - name: deps
+ path: /go
+
+ - name: prepare-test-env
+ image: gitea/test_env:linux-amd64 # https://gitea.com/gitea/test-env
+ pull: always
+ commands:
+ - ./build/test-env-prepare.sh
+
+ - name: build
image: gitea/test_env:linux-amd64 # https://gitea.com/gitea/test-env
user: gitea
commands:
- - make unit-test-coverage test-check
+ - ./build/test-env-check.sh
+ - make backend
environment:
- GOPROXY: https://goproxy.io
- TAGS: bindata gogit sqlite sqlite_unlock_notify
- RACE_ENABLED: true
- GITHUB_READ_TOKEN:
- from_secret: github_read_token
+ GOPROXY: https://goproxy.io # proxy.golang.org is blocked in China, this proxy is not
+ GOSUMDB: sum.golang.org
+ TAGS: bindata
depends_on: [deps-backend, prepare-test-env]
volumes:
- name: deps
path: /go
- - name: test-mysql
+ - name: unit-test
image: gitea/test_env:linux-amd64 # https://gitea.com/gitea/test-env
user: gitea
commands:
- - make test-mysql-migration integration-test-coverage
+ - make unit-test-coverage test-check
environment:
GOPROXY: https://goproxy.io
TAGS: bindata
RACE_ENABLED: true
- TEST_LDAP: 1
- USE_REPO_TEST_DIR: 1
- TEST_INDEXER_CODE_ES_URL: "http://elastic:changeme@elasticsearch:9200"
- depends_on: [build]
+ GITHUB_READ_TOKEN:
+ from_secret: github_read_token
+ depends_on: [deps-backend, prepare-test-env]
volumes:
- name: deps
path: /go
- - name: test-mysql8
+ - name: unit-test-gogit
image: gitea/test_env:linux-amd64 # https://gitea.com/gitea/test-env
user: gitea
commands:
- - timeout -s ABRT 50m make test-mysql8-migration test-mysql8
+ - make unit-test-coverage test-check
environment:
GOPROXY: https://goproxy.io
- TAGS: bindata
+ TAGS: bindata gogit
RACE_ENABLED: true
- TEST_LDAP: 1
- USE_REPO_TEST_DIR: 1
- depends_on: [build]
+ GITHUB_READ_TOKEN:
+ from_secret: github_read_token
+ depends_on: [deps-backend, prepare-test-env]
volumes:
- name: deps
path: /go
- - name: test-mssql
+ - name: test-mysql
image: gitea/test_env:linux-amd64 # https://gitea.com/gitea/test-env
user: gitea
commands:
- - make test-mssql-migration test-mssql
+ - make test-mysql-migration integration-test-coverage
environment:
GOPROXY: https://goproxy.io
TAGS: bindata
RACE_ENABLED: true
- TEST_LDAP: 1
USE_REPO_TEST_DIR: 1
+ TEST_INDEXER_CODE_ES_URL: "http://elastic:changeme@elasticsearch:9200"
depends_on: [build]
volumes:
- name: deps
@@ -398,11 +437,12 @@ steps:
---
kind: pipeline
-name: testing-arm64
+type: docker
+name: testing-mysql8
platform:
os: linux
- arch: arm64
+ arch: amd64
depends_on:
- compliance
@@ -421,16 +461,102 @@ volumes:
temp: {}
services:
- - name: pgsql
- pull: default
- image: postgres:10
+ - name: mysql8
+ image: mysql:8
+ pull: always
environment:
- POSTGRES_DB: test
- POSTGRES_PASSWORD: postgres
+ MYSQL_ALLOW_EMPTY_PASSWORD: yes
+ MYSQL_DATABASE: testgitea
- - name: ldap
- pull: default
- image: gitea/test-openldap:latest
+steps:
+ - name: fetch-tags
+ image: docker:git
+ pull: always
+ commands:
+ - git config --global --add safe.directory /drone/src
+ - git fetch --tags --force
+ when:
+ event:
+ exclude:
+ - pull_request
+
+ - name: deps-backend
+ image: golang:1.20
+ pull: always
+ commands:
+ - make deps-backend
+ volumes:
+ - name: deps
+ path: /go
+
+ - name: prepare-test-env
+ image: gitea/test_env:linux-amd64 # https://gitea.com/gitea/test-env
+ pull: always
+ commands:
+ - ./build/test-env-prepare.sh
+
+ - name: build
+ image: gitea/test_env:linux-amd64 # https://gitea.com/gitea/test-env
+ user: gitea
+ commands:
+ - ./build/test-env-check.sh
+ - make backend
+ environment:
+ GOPROXY: https://goproxy.io # proxy.golang.org is blocked in China, this proxy is not
+ GOSUMDB: sum.golang.org
+ TAGS: bindata
+ depends_on: [deps-backend, prepare-test-env]
+ volumes:
+ - name: deps
+ path: /go
+
+ - name: test-mysql8
+ image: gitea/test_env:linux-amd64 # https://gitea.com/gitea/test-env
+ user: gitea
+ commands:
+ - timeout -s ABRT 50m make test-mysql8-migration test-mysql8
+ environment:
+ GOPROXY: https://goproxy.io
+ TAGS: bindata
+ USE_REPO_TEST_DIR: 1
+ depends_on: [build]
+ volumes:
+ - name: deps
+ path: /go
+
+---
+kind: pipeline
+type: docker
+name: testing-mssql
+
+platform:
+ os: linux
+ arch: amd64
+
+depends_on:
+ - compliance
+
+trigger:
+ event:
+ - push
+ - tag
+ - pull_request
+ paths:
+ exclude:
+ - docs/**
+
+volumes:
+ - name: deps
+ temp: {}
+
+services:
+ - name: mssql
+ image: mcr.microsoft.com/mssql/server:latest
+ pull: always
+ environment:
+ ACCEPT_EULA: Y
+ MSSQL_PID: Standard
+ SA_PASSWORD: MwantsaSecurePassword1
steps:
- name: fetch-tags
@@ -454,13 +580,13 @@ steps:
path: /go
- name: prepare-test-env
- image: gitea/test_env:linux-arm64 # https://gitea.com/gitea/test-env
+ image: gitea/test_env:linux-amd64 # https://gitea.com/gitea/test-env
pull: always
commands:
- ./build/test-env-prepare.sh
- name: build
- image: gitea/test_env:linux-arm64 # https://gitea.com/gitea/test-env
+ image: gitea/test_env:linux-amd64 # https://gitea.com/gitea/test-env
user: gitea
commands:
- ./build/test-env-check.sh
@@ -468,39 +594,102 @@ steps:
environment:
GOPROXY: https://goproxy.io # proxy.golang.org is blocked in China, this proxy is not
GOSUMDB: sum.golang.org
- TAGS: bindata gogit sqlite sqlite_unlock_notify
+ TAGS: bindata
depends_on: [deps-backend, prepare-test-env]
volumes:
- name: deps
path: /go
- - name: test-sqlite
- image: gitea/test_env:linux-arm64 # https://gitea.com/gitea/test-env
+ - name: test-mssql
+ image: gitea/test_env:linux-amd64 # https://gitea.com/gitea/test-env
user: gitea
commands:
- - timeout -s ABRT 50m make test-sqlite-migration test-sqlite
+ - make test-mssql-migration test-mssql
environment:
GOPROXY: https://goproxy.io
- TAGS: bindata gogit sqlite sqlite_unlock_notify
- RACE_ENABLED: true
- TEST_TAGS: gogit sqlite sqlite_unlock_notify
+ TAGS: bindata
USE_REPO_TEST_DIR: 1
depends_on: [build]
volumes:
- name: deps
path: /go
- - name: test-pgsql
+---
+kind: pipeline
+name: testing-sqlite
+
+platform:
+ os: linux
+ arch: arm64
+
+depends_on:
+ - compliance
+
+trigger:
+ event:
+ - push
+ - tag
+ - pull_request
+ paths:
+ exclude:
+ - docs/**
+
+volumes:
+ - name: deps
+ temp: {}
+
+steps:
+ - name: fetch-tags
+ image: docker:git
+ pull: always
+ commands:
+ - git config --global --add safe.directory /drone/src
+ - git fetch --tags --force
+ when:
+ event:
+ exclude:
+ - pull_request
+
+ - name: deps-backend
+ image: golang:1.20
+ pull: always
+ commands:
+ - make deps-backend
+ volumes:
+ - name: deps
+ path: /go
+
+ - name: prepare-test-env
+ image: gitea/test_env:linux-arm64 # https://gitea.com/gitea/test-env
+ pull: always
+ commands:
+ - ./build/test-env-prepare.sh
+
+ - name: build
image: gitea/test_env:linux-arm64 # https://gitea.com/gitea/test-env
user: gitea
commands:
- - timeout -s ABRT 50m make test-pgsql-migration test-pgsql
+ - ./build/test-env-check.sh
+ - make backend
+ environment:
+ GOPROXY: https://goproxy.io # proxy.golang.org is blocked in China, this proxy is not
+ GOSUMDB: sum.golang.org
+ TAGS: bindata gogit sqlite sqlite_unlock_notify
+ depends_on: [deps-backend, prepare-test-env]
+ volumes:
+ - name: deps
+ path: /go
+
+ - name: test-sqlite
+ image: gitea/test_env:linux-arm64 # https://gitea.com/gitea/test-env
+ user: gitea
+ commands:
+ - timeout -s ABRT 50m make test-sqlite-migration test-sqlite
environment:
GOPROXY: https://goproxy.io
- TAGS: bindata gogit
+ TAGS: bindata gogit sqlite sqlite_unlock_notify
RACE_ENABLED: true
- TEST_TAGS: gogit
- TEST_LDAP: 1
+ TEST_TAGS: gogit sqlite sqlite_unlock_notify
USE_REPO_TEST_DIR: 1
depends_on: [build]
volumes:
@@ -530,15 +719,6 @@ volumes:
- name: deps
temp: {}
-services:
- - name: pgsql
- pull: default
- image: postgres:10
- environment:
- POSTGRES_DB: testgitea-e2e
- POSTGRES_PASSWORD: postgres
- POSTGRES_INITDB_ARGS: --encoding=UTF8 --lc-collate='en_US.UTF-8' --lc-ctype='en_US.UTF-8'
-
steps:
- name: deps-frontend
image: node:18
@@ -568,14 +748,12 @@ steps:
- curl -sLO https://go.dev/dl/go1.20.linux-amd64.tar.gz && tar -C /usr/local -xzf go1.20.linux-amd64.tar.gz
- groupadd --gid 1001 gitea && useradd -m --gid 1001 --uid 1001 gitea
- apt-get -qq update && apt-get -qqy install build-essential
- - export TEST_PGSQL_SCHEMA=''
- ./build/test-env-prepare.sh
- - su gitea bash -c "export PATH=$PATH:/usr/local/go/bin && timeout -s ABRT 40m make test-e2e-pgsql"
+ - su gitea bash -c "export PATH=$PATH:/usr/local/go/bin && timeout -s ABRT 40m make test-e2e-sqlite"
environment:
GOPROXY: https://goproxy.io
GOSUMDB: sum.golang.org
USE_REPO_TEST_DIR: 1
- TEST_PGSQL_DBNAME: 'testgitea-e2e'
DEBIAN_FRONTEND: noninteractive
depends_on: [build-frontend, deps-backend]
volumes:
@@ -709,8 +887,11 @@ trigger:
- docs/**
depends_on:
- - testing-amd64
- - testing-arm64
+ - testing-mysql
+ - testing-mysql8
+ - testing-mssql
+ - testing-pgsql
+ - testing-sqlite
volumes:
- name: deps
@@ -842,8 +1023,11 @@ trigger:
- tag
depends_on:
- - testing-arm64
- - testing-amd64
+ - testing-mysql
+ - testing-mysql8
+ - testing-mssql
+ - testing-pgsql
+ - testing-sqlite
volumes:
- name: deps
@@ -994,8 +1178,11 @@ platform:
arch: amd64
depends_on:
- - testing-amd64
- - testing-arm64
+ - testing-mysql
+ - testing-mysql8
+ - testing-mssql
+ - testing-pgsql
+ - testing-sqlite
trigger:
ref:
@@ -1006,6 +1193,9 @@ trigger:
event:
exclude:
- cron
+ paths:
+ exclude:
+ - docs/**
steps:
- name: fetch-tags
@@ -1016,7 +1206,7 @@ steps:
- git fetch --tags --force
- name: publish
- image: techknowlogick/drone-docker:latest
+ image: plugins/docker:latest
pull: always
settings:
auto_tag: true
@@ -1028,13 +1218,17 @@ steps:
from_secret: docker_password
username:
from_secret: docker_username
+ environment:
+ PLUGIN_MIRROR:
+ from_secret: plugin_mirror
+ DOCKER_BUILDKIT: 1
when:
event:
exclude:
- pull_request
- name: publish-rootless
- image: techknowlogick/drone-docker:latest
+ image: plugins/docker:latest
settings:
dockerfile: Dockerfile.rootless
auto_tag: true
@@ -1046,6 +1240,10 @@ steps:
from_secret: docker_password
username:
from_secret: docker_username
+ environment:
+ PLUGIN_MIRROR:
+ from_secret: plugin_mirror
+ DOCKER_BUILDKIT: 1
when:
event:
exclude:
@@ -1061,8 +1259,11 @@ platform:
arch: amd64
depends_on:
- - testing-amd64
- - testing-arm64
+ - testing-mysql
+ - testing-mysql8
+ - testing-mssql
+ - testing-pgsql
+ - testing-sqlite
trigger:
ref:
@@ -1070,6 +1271,9 @@ trigger:
event:
exclude:
- cron
+ paths:
+ exclude:
+ - docs/**
steps:
- name: fetch-tags
@@ -1080,7 +1284,7 @@ steps:
- git fetch --tags --force
- name: publish
- image: techknowlogick/drone-docker:latest
+ image: plugins/docker:latest
pull: always
settings:
tags: ${DRONE_TAG##v}-linux-amd64
@@ -1091,13 +1295,17 @@ steps:
from_secret: docker_password
username:
from_secret: docker_username
+ environment:
+ PLUGIN_MIRROR:
+ from_secret: plugin_mirror
+ DOCKER_BUILDKIT: 1
when:
event:
exclude:
- pull_request
- name: publish-rootless
- image: techknowlogick/drone-docker:latest
+ image: plugins/docker:latest
settings:
dockerfile: Dockerfile.rootless
tags: ${DRONE_TAG##v}-linux-amd64-rootless
@@ -1108,6 +1316,10 @@ steps:
from_secret: docker_password
username:
from_secret: docker_username
+ environment:
+ PLUGIN_MIRROR:
+ from_secret: plugin_mirror
+ DOCKER_BUILDKIT: 1
when:
event:
exclude:
@@ -1123,8 +1335,11 @@ platform:
arch: amd64
depends_on:
- - testing-amd64
- - testing-arm64
+ - testing-mysql
+ - testing-mysql8
+ - testing-mssql
+ - testing-pgsql
+ - testing-sqlite
trigger:
ref:
@@ -1142,7 +1357,7 @@ steps:
- git fetch --tags --force
- name: publish
- image: techknowlogick/drone-docker:latest
+ image: plugins/docker:latest
pull: always
settings:
auto_tag: false
@@ -1154,13 +1369,17 @@ steps:
from_secret: docker_password
username:
from_secret: docker_username
+ environment:
+ PLUGIN_MIRROR:
+ from_secret: plugin_mirror
+ DOCKER_BUILDKIT: 1
when:
event:
exclude:
- pull_request
- name: publish-rootless
- image: techknowlogick/drone-docker:latest
+ image: plugins/docker:latest
settings:
dockerfile: Dockerfile.rootless
auto_tag: false
@@ -1172,6 +1391,10 @@ steps:
from_secret: docker_password
username:
from_secret: docker_username
+ environment:
+ PLUGIN_MIRROR:
+ from_secret: plugin_mirror
+ DOCKER_BUILDKIT: 1
when:
event:
exclude:
@@ -1186,8 +1409,11 @@ platform:
arch: amd64
depends_on:
- - testing-amd64
- - testing-arm64
+ - testing-mysql
+ - testing-mysql8
+ - testing-mssql
+ - testing-pgsql
+ - testing-sqlite
trigger:
ref:
@@ -1205,7 +1431,7 @@ steps:
- git fetch --tags --force
- name: publish
- image: techknowlogick/drone-docker:latest
+ image: plugins/docker:latest
pull: always
settings:
auto_tag: false
@@ -1217,13 +1443,17 @@ steps:
from_secret: docker_password
username:
from_secret: docker_username
+ environment:
+ PLUGIN_MIRROR:
+ from_secret: plugin_mirror
+ DOCKER_BUILDKIT: 1
when:
event:
exclude:
- pull_request
- name: publish-rootless
- image: techknowlogick/drone-docker:latest
+ image: plugins/docker:latest
settings:
dockerfile: Dockerfile.rootless
auto_tag: false
@@ -1235,6 +1465,10 @@ steps:
from_secret: docker_password
username:
from_secret: docker_username
+ environment:
+ PLUGIN_MIRROR:
+ from_secret: plugin_mirror
+ DOCKER_BUILDKIT: 1
when:
event:
exclude:
@@ -1243,7 +1477,7 @@ steps:
---
kind: pipeline
type: docker
-name: docker-linux-arm64-dry-run
+name: docker-linux-amd64-dry-run
platform:
os: linux
@@ -1261,7 +1495,7 @@ trigger:
steps:
- name: dryrun
- image: techknowlogick/drone-docker:latest
+ image: plugins/docker:latest
pull: always
settings:
dry_run: true
@@ -1272,6 +1506,7 @@ steps:
environment:
PLUGIN_MIRROR:
from_secret: plugin_mirror
+ DOCKER_BUILDKIT: 1
when:
event:
- pull_request
@@ -1286,8 +1521,11 @@ platform:
arch: arm64
depends_on:
- - testing-amd64
- - testing-arm64
+ - testing-mysql
+ - testing-mysql8
+ - testing-mssql
+ - testing-pgsql
+ - testing-sqlite
trigger:
ref:
@@ -1298,6 +1536,9 @@ trigger:
event:
exclude:
- cron
+ paths:
+ exclude:
+ - docs/**
steps:
- name: fetch-tags
@@ -1308,7 +1549,7 @@ steps:
- git fetch --tags --force
- name: publish
- image: techknowlogick/drone-docker:latest
+ image: plugins/docker:latest
pull: always
settings:
auto_tag: true
@@ -1320,13 +1561,17 @@ steps:
from_secret: docker_password
username:
from_secret: docker_username
+ environment:
+ PLUGIN_MIRROR:
+ from_secret: plugin_mirror
+ DOCKER_BUILDKIT: 1
when:
event:
exclude:
- pull_request
- name: publish-rootless
- image: techknowlogick/drone-docker:latest
+ image: plugins/docker:latest
settings:
dockerfile: Dockerfile.rootless
auto_tag: true
@@ -1338,6 +1583,10 @@ steps:
from_secret: docker_password
username:
from_secret: docker_username
+ environment:
+ PLUGIN_MIRROR:
+ from_secret: plugin_mirror
+ DOCKER_BUILDKIT: 1
when:
event:
exclude:
@@ -1353,8 +1602,11 @@ platform:
arch: arm64
depends_on:
- - testing-amd64
- - testing-arm64
+ - testing-mysql
+ - testing-mysql8
+ - testing-mssql
+ - testing-pgsql
+ - testing-sqlite
trigger:
ref:
@@ -1362,6 +1614,9 @@ trigger:
event:
exclude:
- cron
+ paths:
+ exclude:
+ - docs/**
steps:
- name: fetch-tags
@@ -1372,7 +1627,7 @@ steps:
- git fetch --tags --force
- name: publish
- image: techknowlogick/drone-docker:latest
+ image: plugins/docker:latest
pull: always
settings:
tags: ${DRONE_TAG##v}-linux-arm64
@@ -1383,13 +1638,17 @@ steps:
from_secret: docker_password
username:
from_secret: docker_username
+ environment:
+ PLUGIN_MIRROR:
+ from_secret: plugin_mirror
+ DOCKER_BUILDKIT: 1
when:
event:
exclude:
- pull_request
- name: publish-rootless
- image: techknowlogick/drone-docker:latest
+ image: plugins/docker:latest
settings:
dockerfile: Dockerfile.rootless
tags: ${DRONE_TAG##v}-linux-arm64-rootless
@@ -1400,6 +1659,10 @@ steps:
from_secret: docker_password
username:
from_secret: docker_username
+ environment:
+ PLUGIN_MIRROR:
+ from_secret: plugin_mirror
+ DOCKER_BUILDKIT: 1
when:
event:
exclude:
@@ -1415,8 +1678,11 @@ platform:
arch: arm64
depends_on:
- - testing-amd64
- - testing-arm64
+ - testing-mysql
+ - testing-mysql8
+ - testing-mssql
+ - testing-pgsql
+ - testing-sqlite
trigger:
ref:
@@ -1424,6 +1690,9 @@ trigger:
event:
exclude:
- cron
+ paths:
+ exclude:
+ - docs/**
steps:
- name: fetch-tags
@@ -1434,7 +1703,7 @@ steps:
- git fetch --tags --force
- name: publish
- image: techknowlogick/drone-docker:latest
+ image: plugins/docker:latest
pull: always
settings:
auto_tag: false
@@ -1446,13 +1715,17 @@ steps:
from_secret: docker_password
username:
from_secret: docker_username
+ environment:
+ PLUGIN_MIRROR:
+ from_secret: plugin_mirror
+ DOCKER_BUILDKIT: 1
when:
event:
exclude:
- pull_request
- name: publish-rootless
- image: techknowlogick/drone-docker:latest
+ image: plugins/docker:latest
settings:
dockerfile: Dockerfile.rootless
auto_tag: false
@@ -1464,6 +1737,10 @@ steps:
from_secret: docker_password
username:
from_secret: docker_username
+ environment:
+ PLUGIN_MIRROR:
+ from_secret: plugin_mirror
+ DOCKER_BUILDKIT: 1
when:
event:
exclude:
@@ -1478,8 +1755,11 @@ platform:
arch: arm64
depends_on:
- - testing-amd64
- - testing-arm64
+ - testing-mysql
+ - testing-mysql8
+ - testing-mssql
+ - testing-pgsql
+ - testing-sqlite
trigger:
ref:
@@ -1497,7 +1777,7 @@ steps:
- git fetch --tags --force
- name: publish
- image: techknowlogick/drone-docker:latest
+ image: plugins/docker:latest
pull: always
settings:
auto_tag: false
@@ -1509,13 +1789,17 @@ steps:
from_secret: docker_password
username:
from_secret: docker_username
+ environment:
+ PLUGIN_MIRROR:
+ from_secret: plugin_mirror
+ DOCKER_BUILDKIT: 1
when:
event:
exclude:
- pull_request
- name: publish-rootless
- image: techknowlogick/drone-docker:latest
+ image: plugins/docker:latest
settings:
dockerfile: Dockerfile.rootless
auto_tag: false
@@ -1527,6 +1811,10 @@ steps:
from_secret: docker_password
username:
from_secret: docker_username
+ environment:
+ PLUGIN_MIRROR:
+ from_secret: plugin_mirror
+ DOCKER_BUILDKIT: 1
when:
event:
exclude:
@@ -1571,6 +1859,9 @@ trigger:
event:
exclude:
- cron
+ paths:
+ exclude:
+ - docs/**
depends_on:
- docker-linux-amd64-release-version
@@ -1589,7 +1880,6 @@ platform:
steps:
- name: manifest-rootless
- pull: always
image: plugins/manifest
pull: always
settings:
@@ -1619,6 +1909,9 @@ trigger:
event:
exclude:
- cron
+ paths:
+ exclude:
+ - docs/**
depends_on:
- docker-linux-amd64-release
@@ -1650,8 +1943,11 @@ trigger:
- failure
depends_on:
- - testing-amd64
- - testing-arm64
+ - testing-mysql
+ - testing-mysql8
+ - testing-mssql
+ - testing-pgsql
+ - testing-sqlite
- release-version
- release-latest
- docker-linux-amd64-release
diff --git a/.gitpod.yml b/.gitpod.yml
index a184e6376..506c62045 100644
--- a/.gitpod.yml
+++ b/.gitpod.yml
@@ -10,9 +10,12 @@ tasks:
- name: Run backend
command: |
gp sync-await setup
- mkdir -p custom/conf/
- echo -e "[server]\nROOT_URL=$(gp url 3000)/" > custom/conf/app.ini
- echo -e "\n[database]\nDB_TYPE = sqlite3\nPATH = $GITPOD_REPO_ROOT/data/gitea.db" >> custom/conf/app.ini
+ if [ ! -f custom/conf/app.ini ]
+ then
+ mkdir -p custom/conf/
+ echo -e "[server]\nROOT_URL=$(gp url 3000)/" > custom/conf/app.ini
+ echo -e "\n[database]\nDB_TYPE = sqlite3\nPATH = $GITPOD_REPO_ROOT/data/gitea.db" >> custom/conf/app.ini
+ fi
export TAGS="sqlite sqlite_unlock_notify"
make watch-backend
- name: Run frontend
diff --git a/.stylelintrc.yaml b/.stylelintrc.yaml
index ca0f16b07..c488d0677 100644
--- a/.stylelintrc.yaml
+++ b/.stylelintrc.yaml
@@ -1,12 +1,18 @@
plugins:
- stylelint-declaration-strict-value
+ignoreFiles:
+ - "**/*.go"
+
overrides:
- files: ["**/*.less"]
customSyntax: postcss-less
- files: ["**/chroma/*", "**/codemirror/*", "**/standalone/*", "**/console/*"]
rules:
scale-unlimited/declaration-strict-value: null
+ - files: ["**/chroma/*", "**/codemirror/*"]
+ rules:
+ block-no-empty: null
rules:
alpha-value-notation: null
diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md
new file mode 100644
index 000000000..979831eb9
--- /dev/null
+++ b/CODE_OF_CONDUCT.md
@@ -0,0 +1,96 @@
+# Gitea Community Code of Conduct
+
+## About
+
+Online communities include people from many different backgrounds. The Gitea contributors are committed to providing a friendly, safe and welcoming environment for all, regardless of gender identity and expression, sexual orientation, disabilities, neurodiversity, physical appearance, body size, ethnicity, nationality, race, age, religion, or similar personal characteristics.
+
+The first goal of the Code of Conduct is to specify a baseline standard of behavior so that people with different social values and communication styles can talk about Gitea effectively, productively, and respectfully.
+
+The second goal is to provide a mechanism for resolving conflicts in the community when they arise.
+
+The third goal of the Code of Conduct is to make our community welcoming to people from different backgrounds. Diversity is critical to the project; for Gitea to be successful, it needs contributors and users from all backgrounds.
+
+We believe that healthy debate and disagreement are essential to a healthy project and community. However, it is never ok to be disrespectful. We value diverse opinions, but we value respectful behavior more.
+
+## Community values
+
+These are the values to which people in the Gitea community should aspire.
+
+- **Be friendly and welcoming.**
+- **Be patient.**
+ - Remember that people have varying communication styles and that not everyone is using their native language. (Meaning and tone can be lost in translation.)
+- **Be thoughtful.**
+ - Productive communication requires effort. Think about how your words will be interpreted.
+ - Remember that sometimes it is best to refrain entirely from commenting.
+- **Be respectful.**
+ - In particular, respect differences of opinion.
+- **Be charitable.**
+ - Interpret the arguments of others in good faith, do not seek to disagree.
+ - When we do disagree, try to understand why.
+- **Be constructive.**
+ - Avoid derailing: stay on topic; if you want to talk about something else, start a new conversation.
+ - Avoid unconstructive criticism: don't merely decry the current state of affairs; offer—or at least solicit—suggestions as to how things may be improved.
+ - Avoid snarking (pithy, unproductive, sniping comments)
+ - Avoid discussing potentially offensive or sensitive issues; this all too often leads to unnecessary conflict.
+ - Avoid microaggressions (brief and commonplace verbal, behavioral and environmental indignities that communicate hostile, derogatory or negative slights and insults to a person or group).
+- **Be responsible.**
+ - What you say and do matters. Take responsibility for your words and actions, including their consequences, whether intended or otherwise.
+
+People are complicated. You should expect to be misunderstood and to misunderstand others; when this inevitably occurs, resist the urge to be defensive or assign blame. Try not to take offense where no offense was intended. Give people the benefit of the doubt. Even if the intent was to provoke, do not rise to it. It is the responsibility of all parties to de-escalate conflict when it arises.
+
+## Code of Conduct
+
+### Our Pledge
+
+In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, education, socio-economic status, nationality, personal appearance, race, religion, or sexual identity and orientation.
+
+### Our Standards
+
+Examples of behavior that contributes to creating a positive environment include:
+
+- Using welcoming and inclusive language
+- Being respectful of differing viewpoints and experiences
+- Gracefully accepting constructive criticism
+- Focusing on what is best for the community
+- Showing empathy towards other community members
+
+Examples of unacceptable behavior by participants include:
+
+- The use of sexualized language or imagery and unwelcome sexual attention or advances
+- Trolling, insulting/derogatory comments, and personal or political attacks
+- Public or private harassment
+- Publishing others’ private information, such as a physical or electronic address, without explicit permission
+- Other conduct which could reasonably be considered inappropriate in a professional setting
+
+### Our Responsibilities
+
+Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior.
+
+Project maintainers have the right and responsibility to remove, edit, or reject: comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, as well as to ban (temporarily or permanently) any contributor for behaviors that they deem inappropriate, threatening, offensive, or harmful.
+
+### Scope
+
+This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers.
+
+This Code of Conduct also applies outside the project spaces when the Project Stewards have a reasonable belief that an individual’s behavior may have a negative impact on the project or its community.
+
+### Conflict Resolution
+
+We do not believe that all conflict is bad; healthy debate and disagreement often yield positive results. However, it is never okay to be disrespectful or to engage in behavior that violates the project’s code of conduct.
+
+If you see someone violating the code of conduct, you are encouraged to address the behavior directly with those involved. Many issues can be resolved quickly and easily, and this gives people more control over the outcome of their dispute. If you are unable to resolve the matter for any reason, or if the behavior is threatening or harassing, report it. We are dedicated to providing an environment where participants feel welcome and safe.
+
+Reports should be directed to the Gitea Project Stewards at conduct@gitea.com. It is the Project Stewards’ duty to receive and address reported violations of the code of conduct. They will then work with a committee consisting of representatives from the technical-oversight-committee.
+
+We will investigate every complaint, but you may not receive a direct response. We will use our discretion in determining when and how to follow up on reported incidents, which may range from not taking action to permanent expulsion from the project and project-sponsored spaces. Under normal circumstances, we will notify the accused of the report and provide them an opportunity to discuss it before any action is taken. If there is a consensus between maintainers that such an endeavor would be useless (i.e. in case of an obvious spammer), we reserve the right to take action without notifying the accused first. The identity of the reporter will be omitted from the details of the report supplied to the accused. In potentially harmful situations, such as ongoing harassment or threats to anyone’s safety, we may take action without notice.
+
+### Attribution
+
+This Code of Conduct is adapted from the Contributor Covenant, version 1.4, available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html
+
+## Summary
+
+- Treat everyone with respect and kindness.
+- Be thoughtful in how you communicate.
+- Don’t be destructive or inflammatory.
+- If you encounter an issue, please mail conduct@gitea.com.
diff --git a/MAINTAINERS b/MAINTAINERS
index 9464d5791..79c4ac4c3 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -44,7 +44,6 @@ Steven Kriegler <sk.bunsenbrenner@gmail.com> (@justusbunsi)
Jimmy Praet <jimmy.praet@telenet.be> (@jpraet)
Leon Hofmeister <dev.lh@web.de> (@delvh)
Wim <wim@42.be> (@42wim)
-Xinyu Zhou <i@sourcehut.net> (@xin-u)
Jason Song <i@wolfogre.com> (@wolfogre)
Yarden Shoham <hrsi88@gmail.com> (@yardenshoham)
Yu Tian <zettat123@gmail.com> (@Zettat123)
diff --git a/Makefile b/Makefile
index 3a590559d..d770ed453 100644
--- a/Makefile
+++ b/Makefile
@@ -190,6 +190,7 @@ help:
@echo " - deps install dependencies"
@echo " - deps-frontend install frontend dependencies"
@echo " - deps-backend install backend dependencies"
+ @echo " - deps-tools install tool dependencies"
@echo " - lint lint everything"
@echo " - lint-frontend lint frontend files"
@echo " - lint-backend lint backend files"
@@ -821,7 +822,7 @@ docs:
cd docs; make trans-copy clean build-offline;
.PHONY: deps
-deps: deps-frontend deps-backend
+deps: deps-frontend deps-backend deps-tools
.PHONY: deps-frontend
deps-frontend: node_modules
@@ -829,6 +830,9 @@ deps-frontend: node_modules
.PHONY: deps-backend
deps-backend:
$(GO) mod download
+
+.PHONY: deps-tools
+deps-tools:
$(GO) install $(AIR_PACKAGE)
$(GO) install $(EDITORCONFIG_CHECKER_PACKAGE)
$(GO) install $(ERRCHECK_PACKAGE)
@@ -859,6 +863,8 @@ fomantic:
cp -f $(FOMANTIC_WORK_DIR)/theme.config.less $(FOMANTIC_WORK_DIR)/node_modules/fomantic-ui/src/theme.config
cp -rf $(FOMANTIC_WORK_DIR)/_site $(FOMANTIC_WORK_DIR)/node_modules/fomantic-ui/src/
cd $(FOMANTIC_WORK_DIR) && npx gulp -f node_modules/fomantic-ui/gulpfile.js build
+ # fomantic uses "touchstart" as click event for some browsers, it's not ideal, so we force fomantic to always use "click" as click event
+ $(SED_INPLACE) -e 's/clickEvent[ \t]*=/clickEvent = "click", unstableClickEvent =/g' $(FOMANTIC_WORK_DIR)/build/semantic.js
$(SED_INPLACE) -e 's/\r//g' $(FOMANTIC_WORK_DIR)/build/semantic.css $(FOMANTIC_WORK_DIR)/build/semantic.js
rm -f $(FOMANTIC_WORK_DIR)/build/*.min.*
diff --git a/build/update-locales.sh b/build/update-locales.sh
index 046f48ee8..596ddfec0 100755
--- a/build/update-locales.sh
+++ b/build/update-locales.sh
@@ -1,14 +1,50 @@
#!/bin/sh
+# this script runs in alpine image which only has `sh` shell
+
+set +e
+if sed --version 2>/dev/null | grep -q GNU; then
+ SED_INPLACE="sed -i"
+else
+ SED_INPLACE="sed -i ''"
+fi
+set -e
+
+if [ ! -f ./options/locale/locale_en-US.ini ]; then
+ echo "please run this script in the root directory of the project"
+ exit 1
+fi
+
mv ./options/locale/locale_en-US.ini ./options/
-# Make sure to only change lines that have the translation enclosed between quotes
-sed -i -r -e '/^[a-zA-Z0-9_.-]+[ ]*=[ ]*".*"$/ {
- s/^([a-zA-Z0-9_.-]+)[ ]*="/\1=/
- s/\\"/"/g
+# the "ini" library for locale has many quirks
+# * `a="xx"` gets `xx` (no quote)
+# * `a=x\"y` gets `x\"y` (no unescaping)
+# * `a="x\"y"` gets `"x\"y"` (no unescaping, the quotes are still there)
+# * `a='x\"y'` gets `x\"y` (no unescaping, no quote)
+# * `a="foo` gets `"foo` (although the quote is not closed)
+# * 'a=`foo`' works like single-quote
+# crowdin needs the strings to be quoted correctly and doesn't like incomplete quotes
+# crowdin always outputs quoted strings if there are quotes in the strings.
+
+# this script helps to unquote the crowdin outputs for the quirky ini library
+# * find all `key="...\"..."` lines
+# * remove the leading quote
+# * remove the trailing quote
+# * unescape the quotes
+# * eg: key="...\"..." => key=..."...
+$SED_INPLACE -r -e '/^[-.A-Za-z0-9_]+[ ]*=[ ]*".*"$/ {
+ s/^([-.A-Za-z0-9_]+)[ ]*=[ ]*"/\1=/
s/"$//
+ s/\\"/"/g
}' ./options/locale/*.ini
+# * if the escaped line is incomplete like `key="...` or `key=..."`, quote it with backticks
+# * eg: key="... => key=`"...`
+# * eg: key=..." => key=`..."`
+$SED_INPLACE -r -e 's/^([-.A-Za-z0-9_]+)[ ]*=[ ]*(".*[^"])$/\1=`\2`/' ./options/locale/*.ini
+$SED_INPLACE -r -e 's/^([-.A-Za-z0-9_]+)[ ]*=[ ]*([^"].*")$/\1=`\2`/' ./options/locale/*.ini
+
# Remove translation under 25% of en_us
baselines=$(wc -l "./options/locale_en-US.ini" | cut -d" " -f1)
baselines=$((baselines / 4))
diff --git a/cmd/admin.go b/cmd/admin.go
index b913b817b..f9fb1b6c6 100644
--- a/cmd/admin.go
+++ b/cmd/admin.go
@@ -7,6 +7,7 @@ package cmd
import (
"errors"
"fmt"
+ "net/url"
"os"
"strings"
"text/tabwriter"
@@ -469,11 +470,19 @@ func runAddOauth(c *cli.Context) error {
return err
}
+ config := parseOAuth2Config(c)
+ if config.Provider == "openidConnect" {
+ discoveryURL, err := url.Parse(config.OpenIDConnectAutoDiscoveryURL)
+ if err != nil || (discoveryURL.Scheme != "http" && discoveryURL.Scheme != "https") {
+ return fmt.Errorf("invalid Auto Discovery URL: %s (this must be a valid URL starting with http:// or https://)", config.OpenIDConnectAutoDiscoveryURL)
+ }
+ }
+
return auth_model.CreateSource(&auth_model.Source{
Type: auth_model.OAuth2,
Name: c.String("name"),
IsActive: true,
- Cfg: parseOAuth2Config(c),
+ Cfg: config,
})
}
diff --git a/cmd/convert.go b/cmd/convert.go
index 30e7d01e1..d9b89495c 100644
--- a/cmd/convert.go
+++ b/cmd/convert.go
@@ -35,7 +35,7 @@ func runConvert(ctx *cli.Context) error {
log.Info("Log path: %s", setting.Log.RootPath)
log.Info("Configuration file: %s", setting.CustomConf)
- if !setting.Database.UseMySQL {
+ if !setting.Database.Type.IsMySQL() {
fmt.Println("This command can only be used with a MySQL database")
return nil
}
diff --git a/cmd/dump.go b/cmd/dump.go
index c879d2fbe..c802849f8 100644
--- a/cmd/dump.go
+++ b/cmd/dump.go
@@ -272,13 +272,14 @@ func runDump(ctx *cli.Context) error {
fatal("Failed to create tmp file: %v", err)
}
defer func() {
+ _ = dbDump.Close()
if err := util.Remove(dbDump.Name()); err != nil {
log.Warn("Unable to remove temporary file: %s: Error: %v", dbDump.Name(), err)
}
}()
targetDBType := ctx.String("database")
- if len(targetDBType) > 0 && targetDBType != setting.Database.Type {
+ if len(targetDBType) > 0 && targetDBType != setting.Database.Type.String() {
log.Info("Dumping database %s => %s...", setting.Database.Type, targetDBType)
} else {
log.Info("Dumping database...")
diff --git a/cmd/serv.go b/cmd/serv.go
index 145d1b9e9..d7510845a 100644
--- a/cmd/serv.go
+++ b/cmd/serv.go
@@ -11,6 +11,7 @@ import (
"net/url"
"os"
"os/exec"
+ "path/filepath"
"regexp"
"strconv"
"strings"
@@ -290,17 +291,21 @@ func runServ(c *cli.Context) error {
return nil
}
- // Special handle for Windows.
- if setting.IsWindows {
- verb = strings.Replace(verb, "-", " ", 1)
- }
-
var gitcmd *exec.Cmd
- verbs := strings.Split(verb, " ")
- if len(verbs) == 2 {
- gitcmd = exec.CommandContext(ctx, verbs[0], verbs[1], repoPath)
- } else {
- gitcmd = exec.CommandContext(ctx, verb, repoPath)
+ gitBinPath := filepath.Dir(git.GitExecutable) // e.g. /usr/bin
+ gitBinVerb := filepath.Join(gitBinPath, verb) // e.g. /usr/bin/git-upload-pack
+ if _, err := os.Stat(gitBinVerb); err != nil {
+ // if the command "git-upload-pack" doesn't exist, try to split "git-upload-pack" to use the sub-command with git
+ // ps: Windows only has "git.exe" in the bin path, so Windows always uses this way
+ verbFields := strings.SplitN(verb, "-", 2)
+ if len(verbFields) == 2 {
+ // use git binary with the sub-command part: "C:\...\bin\git.exe", "upload-pack", ...
+ gitcmd = exec.CommandContext(ctx, git.GitExecutable, verbFields[1], repoPath)
+ }
+ }
+ if gitcmd == nil {
+ // by default, use the verb (it has been checked above by allowedCommands)
+ gitcmd = exec.CommandContext(ctx, gitBinVerb, repoPath)
}
process.SetSysProcAttribute(gitcmd)
diff --git a/contrib/init/ubuntu/gitea b/contrib/init/ubuntu/gitea
new file mode 100644
index 000000000..da56b6e4a
--- /dev/null
+++ b/contrib/init/ubuntu/gitea
@@ -0,0 +1,84 @@
+#!/bin/sh
+### BEGIN INIT INFO
+# Provides: gitea
+# Required-Start: $syslog $network
+# Required-Stop: $syslog
+# Default-Start: 2 3 4 5
+# Default-Stop: 0 1 6
+# Short-Description: A self-hosted Git service written in Go.
+# Description: A self-hosted Git service written in Go.
+### END INIT INFO
+
+# Do NOT "set -e"
+
+# PATH should only include /usr/* if it runs after the mountnfs.sh script
+PATH=/sbin:/usr/sbin:/bin:/usr/bin:/usr/local/bin
+DESC="Gitea - Git with a cup of tea"
+NAME=gitea
+SERVICEVERBOSE=yes
+PIDFILE=/run/$NAME.pid
+SCRIPTNAME=/etc/init.d/$NAME
+WORKINGDIR=/var/lib/$NAME
+DAEMON=/usr/local/bin/$NAME
+DAEMON_ARGS="web -c /etc/$NAME/app.ini"
+USER=git
+STOP_SCHEDULE="${STOP_SCHEDULE:-QUIT/5/TERM/1/KILL/5}"
+
+# Read configuration variable file if it is present
+[ -r /etc/default/$NAME ] && . /etc/default/$NAME
+
+# Exit if the package is not installed
+[ -x "$DAEMON" ] || exit 0
+
+do_start()
+{
+ GITEA_ENVS="USER=$USER GITEA_WORK_DIR=$WORKINGDIR HOME=/home/$USER"
+ GITEA_EXEC="$DAEMON -- $DAEMON_ARGS"
+ sh -c "start-stop-daemon --start --quiet --pidfile $PIDFILE --make-pidfile \\
+ --background --chdir $WORKINGDIR --chuid $USER \\
+ --exec /bin/bash -- -c '/usr/bin/env $GITEA_ENVS $GITEA_EXEC'"
+}
+
+do_stop()
+{
+ start-stop-daemon --stop --quiet --retry=$STOP_SCHEDULE --pidfile $PIDFILE --name $NAME --oknodo
+ rm -f $PIDFILE
+}
+
+do_status()
+{
+ if [ -f $PIDFILE ]; then
+ if kill -0 $(cat "$PIDFILE"); then
+ echo "$NAME is running, PID is $(cat $PIDFILE)"
+ else
+ echo "$NAME process is dead, but pidfile exists"
+ fi
+ else
+ echo "$NAME is not running"
+ fi
+}
+
+case "$1" in
+ start)
+ echo "Starting $DESC" "$NAME"
+ do_start
+ ;;
+ stop)
+ echo "Stopping $DESC" "$NAME"
+ do_stop
+ ;;
+ status)
+ do_status
+ ;;
+ restart)
+ echo "Restarting $DESC" "$NAME"
+ do_stop
+ do_start
+ ;;
+ *)
+ echo "Usage: $SCRIPTNAME {start|stop|status|restart}" >&2
+ exit 2
+ ;;
+esac
+
+exit 0
diff --git a/custom/conf/app.example.ini b/custom/conf/app.example.ini
index 627d2cf85..a81abefef 100644
--- a/custom/conf/app.example.ini
+++ b/custom/conf/app.example.ini
@@ -576,6 +576,22 @@ ROUTER = console
;; The routing level will default to that of the system but individual router level can be set in
;; [log.<mode>.router] LEVEL
;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;
+;; Print request id which parsed from request headers in access log, when access log is enabled.
+;; * E.g:
+;; * In request Header: X-Request-ID: test-id-123
+;; * Configuration in app.ini: REQUEST_ID_HEADERS = X-Request-ID
+;; * Print in log: 127.0.0.1:58384 - - [14/Feb/2023:16:33:51 +0800] "test-id-123"
+;;
+;; If you configure more than one in the .ini file, it will match in the order of configuration,
+;; and the first match will be finally printed in the log.
+;; * E.g:
+;; * In reuqest Header: X-Trace-ID: trace-id-1q2w3e4r
+;; * Configuration in app.ini: REQUEST_ID_HEADERS = X-Request-ID, X-Trace-ID, X-Req-ID
+;; * Print in log: 127.0.0.1:58384 - - [14/Feb/2023:16:33:51 +0800] "trace-id-1q2w3e4r"
+;;
+;; REQUEST_ID_HEADERS =
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
@@ -1871,6 +1887,9 @@ ROUTER = console
;;
;; Minio enabled ssl only available when STORAGE_TYPE is `minio`
;MINIO_USE_SSL = false
+;;
+;; Minio skip SSL verification available when STORAGE_TYPE is `minio`
+;MINIO_INSECURE_SKIP_VERIFY = false
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
@@ -2552,6 +2571,9 @@ ROUTER = console
;;
;; Minio enabled ssl only available when STORAGE_TYPE is `minio`
;MINIO_USE_SSL = false
+;;
+;; Minio skip SSL verification available when STORAGE_TYPE is `minio`
+;MINIO_INSECURE_SKIP_VERIFY = false
;[proxy]
;; Enable the proxy, all requests to external via HTTP will be affected
diff --git a/docs/content/doc/advanced/config-cheat-sheet.en-us.md b/docs/content/doc/advanced/config-cheat-sheet.en-us.md
index 462556c9b..a5ef977f1 100644
--- a/docs/content/doc/advanced/config-cheat-sheet.en-us.md
+++ b/docs/content/doc/advanced/config-cheat-sheet.en-us.md
@@ -854,6 +854,7 @@ Default templates for project boards:
- `MINIO_LOCATION`: **us-east-1**: Minio location to create bucket only available when STORAGE_TYPE is `minio`
- `MINIO_BASE_PATH`: **attachments/**: Minio base path on the bucket only available when STORAGE_TYPE is `minio`
- `MINIO_USE_SSL`: **false**: Minio enabled ssl only available when STORAGE_TYPE is `minio`
+- `MINIO_INSECURE_SKIP_VERIFY`: **false**: Minio skip SSL verification available when STORAGE_TYPE is `minio`
## Log (`log`)
@@ -880,7 +881,13 @@ Default templates for project boards:
- `Identity`: the SignedUserName or `"-"` if not logged in.
- `Start`: the start time of the request.
- `ResponseWriter`: the responseWriter from the request.
+ - `RequestID`: the value matching REQUEST_ID_HEADERS(default: `-`, if not matched).
- You must be very careful to ensure that this template does not throw errors or panics as this template runs outside of the panic/recovery script.
+- `REQUEST_ID_HEADERS`: **\<empty\>**: You can configure multiple values that are splited by comma here. It will match in the order of configuration, and the first match will be finally printed in the access log.
+ - e.g.
+ - In the Request Header: X-Request-ID: **test-id-123**
+ - Configuration in app.ini: REQUEST_ID_HEADERS = X-Request-ID
+ - Print in log: 127.0.0.1:58384 - - [14/Feb/2023:16:33:51 +0800] "**test-id-123**" ...
### Log subsections (`log.name`, `log.name.*`)
@@ -1268,6 +1275,7 @@ is `data/lfs` and the default of `MINIO_BASE_PATH` is `lfs/`.
- `MINIO_LOCATION`: **us-east-1**: Minio location to create bucket only available when `STORAGE_TYPE` is `minio`
- `MINIO_BASE_PATH`: **lfs/**: Minio base path on the bucket only available when `STORAGE_TYPE` is `minio`
- `MINIO_USE_SSL`: **false**: Minio enabled ssl only available when `STORAGE_TYPE` is `minio`
+- `MINIO_INSECURE_SKIP_VERIFY`: **false**: Minio skip SSL verification available when STORAGE_TYPE is `minio`
## Storage (`storage`)
@@ -1280,6 +1288,7 @@ Default storage configuration for attachments, lfs, avatars and etc.
- `MINIO_BUCKET`: **gitea**: Minio bucket to store the data only available when `STORAGE_TYPE` is `minio`
- `MINIO_LOCATION`: **us-east-1**: Minio location to create bucket only available when `STORAGE_TYPE` is `minio`
- `MINIO_USE_SSL`: **false**: Minio enabled ssl only available when `STORAGE_TYPE` is `minio`
+- `MINIO_INSECURE_SKIP_VERIFY`: **false**: Minio skip SSL verification available when STORAGE_TYPE is `minio`
And you can also define a customize storage like below:
@@ -1298,6 +1307,8 @@ MINIO_BUCKET = gitea
MINIO_LOCATION = us-east-1
; Minio enabled ssl only available when STORAGE_TYPE is `minio`
MINIO_USE_SSL = false
+; Minio skip SSL verification available when STORAGE_TYPE is `minio`
+MINIO_INSECURE_SKIP_VERIFY = false
```
And used by `[attachment]`, `[lfs]` and etc. as `STORAGE_TYPE`.
@@ -1318,6 +1329,7 @@ is `data/repo-archive` and the default of `MINIO_BASE_PATH` is `repo-archive/`.
- `MINIO_LOCATION`: **us-east-1**: Minio location to create bucket only available when `STORAGE_TYPE` is `minio`
- `MINIO_BASE_PATH`: **repo-archive/**: Minio base path on the bucket only available when `STORAGE_TYPE` is `minio`
- `MINIO_USE_SSL`: **false**: Minio enabled ssl only available when `STORAGE_TYPE` is `minio`
+- `MINIO_INSECURE_SKIP_VERIFY`: **false**: Minio skip SSL verification available when STORAGE_TYPE is `minio`
## Proxy (`proxy`)
diff --git a/docs/content/doc/advanced/config-cheat-sheet.zh-cn.md b/docs/content/doc/advanced/config-cheat-sheet.zh-cn.md
index 2598f16a1..84186d0e9 100644
--- a/docs/content/doc/advanced/config-cheat-sheet.zh-cn.md
+++ b/docs/content/doc/advanced/config-cheat-sheet.zh-cn.md
@@ -262,7 +262,22 @@ test01.xls: application/vnd.ms-excel; charset=binary
- `ROOT_PATH`: 日志文件根目录。
- `MODE`: 日志记录模å¼ï¼Œé»˜è®¤æ˜¯ä¸º `console`。如果è¦å†™åˆ°å¤šä¸ªé€šé“,用逗å·åˆ†éš”
-- `LEVEL`: 日志级别,默认为`Trace`。
+- `LEVEL`: 日志级别,默认为 `Trace`。
+- `DISABLE_ROUTER_LOG`: 关闭日志中的路由日志。
+- `ENABLE_ACCESS_LOG`: 是å¦å¼€å¯ Access Log, 默认为 false。
+- `ACCESS_LOG_TEMPLATE`: `access.log` 输出内容的模æ¿ï¼Œé»˜è®¤æ¨¡æ¿ï¼š**`{{.Ctx.RemoteAddr}} - {{.Identity}} {{.Start.Format "[02/Jan/2006:15:04:05 -0700]" }} "{{.Ctx.Req.Method}} {{.Ctx.Req.URL.RequestURI}} {{.Ctx.Req.Proto}}" {{.ResponseWriter.Status}} {{.ResponseWriter.Size}} "{{.Ctx.Req.Referer}}\" \"{{.Ctx.Req.UserAgent}}"`**
+ 模æ¿æ”¯æŒä»¥ä¸‹å‚æ•°:
+ - `Ctx`: 请求上下文。
+ - `Identity`: 登录用户å,默认: “`-`â€ã€‚
+ - `Start`: 请求开始时间。
+ - `ResponseWriter`:
+ - `RequestID`: 从请求头中解æžå¾—到的与 `REQUEST_ID_HEADERS` 匹é…的值,默认: “`-`â€ã€‚
+ - 一定è¦è°¨æ…Žé…置该模æ¿ï¼Œå¦åˆ™å¯èƒ½ä¼šå¼•èµ·panic.
+- `REQUEST_ID_HEADERS`: 从 Request Header 中匹é…指定 Key,并将匹é…到的值输出到 `access.log` 中(需è¦åœ¨ `ACCESS_LOG_TEMPLATE` 中指定输出ä½ç½®)。如果在该å‚数中é…置多个 Key, 请用逗å·åˆ†å‰²ï¼Œç¨‹åºå°†æŒ‰ç…§é…置的顺åºè¿›è¡ŒåŒ¹é…。
+ - 示例:
+ - 请求头: X-Request-ID: **test-id-123**
+ - é…置文件: REQUEST_ID_HEADERS = X-Request-ID
+ - 日志输出: 127.0.0.1:58384 - - [14/Feb/2023:16:33:51 +0800] "**test-id-123**" ...
## Cron (`cron`)
@@ -431,6 +446,8 @@ MINIO_BUCKET = gitea
MINIO_LOCATION = us-east-1
; Minio enabled ssl only available when STORAGE_TYPE is `minio`
MINIO_USE_SSL = false
+; Minio skip SSL verification available when STORAGE_TYPE is `minio`
+MINIO_INSECURE_SKIP_VERIFY = false
```
然åŽä½ åœ¨ `[attachment]`, `[lfs]` 等中å¯ä»¥æŠŠè¿™ä¸ªå字用作 `STORAGE_TYPE` 的值。
diff --git a/docs/content/doc/advanced/customizing-gitea.en-us.md b/docs/content/doc/advanced/customizing-gitea.en-us.md
index 18fc1b3e7..bad6342aa 100644
--- a/docs/content/doc/advanced/customizing-gitea.en-us.md
+++ b/docs/content/doc/advanced/customizing-gitea.en-us.md
@@ -282,9 +282,22 @@ To add custom .gitignore, add a file with existing [.gitignore rules](https://gi
### Labels
-To add a custom label set, add a file that follows the [label format](https://github.com/go-gitea/gitea/blob/main/options/label/Default) to `$GITEA_CUSTOM/options/label`
+Starting with Gitea 1.19, you can add a file that follows the [YAML label format](https://github.com/go-gitea/gitea/blob/main/options/label/Advanced.yaml) to `$GITEA_CUSTOM/options/label`:
+
+```yaml
+labels:
+ - name: "foo/bar" # name of the label that will appear in the dropdown
+ exclusive: true # whether to use the exclusive namespace for scoped labels. scoped delimiter is /
+ color: aabbcc # hex colour coding
+ description: Some label # long description of label intent
+ ```
+
+The [legacy file format](https://github.com/go-gitea/gitea/blob/main/options/label/Default) can still be used following the format below, however we strongly recommend using the newer YAML format instead.
+
`#hex-color label name ; label description`
+For more information, see the [labels documentation]({{< relref "doc/usage/labels.en-us.md" >}}).
+
### Licenses
To add a custom license, add a file with the license text to `$GITEA_CUSTOM/options/license`
diff --git a/docs/content/doc/developers/guidelines-frontend.en-us.md b/docs/content/doc/developers/guidelines-frontend.en-us.md
index 7f4d87d90..9ac317f40 100644
--- a/docs/content/doc/developers/guidelines-frontend.en-us.md
+++ b/docs/content/doc/developers/guidelines-frontend.en-us.md
@@ -47,6 +47,8 @@ We recommend [Google HTML/CSS Style Guide](https://google.github.io/styleguide/h
7. Clarify variable types, prefer `elem.disabled = true` instead of `elem.setAttribute('disabled', 'anything')`, prefer `$el.prop('checked', var === 'yes')` instead of `$el.prop('checked', var)`.
8. Use semantic elements, prefer `<button class="ui button">` instead of `<div class="ui button">`.
9. Avoid unnecessary `!important` in CSS, add comments to explain why it's necessary if it can't be avoided.
+10. Avoid mixing different events in one event listener, prefer to use individual event listeners for every event.
+11. Custom event names are recommended to use `ce-` prefix.
### Accessibility / ARIA
@@ -83,6 +85,9 @@ It's not recommended to use `async` event listeners, which may lead to problems.
The reason is that the code after await is executed outside the event dispatch.
Reference: https://github.com/github/eslint-plugin-github/blob/main/docs/rules/async-preventdefault.md
+If an event listener must be `async`, the `e.preventDefault()` should be before any `await`,
+it's recommended to put it at the beginning of the function.
+
If we want to call an `async` function in a non-async context,
it's recommended to use `const _promise = asyncFoo()` to tell readers
that this is done by purpose, we want to call the async function and ignore the Promise.
@@ -106,6 +111,22 @@ However, there are still some special cases, so the current guideline is:
* Vue components are recommended to use `v-if` and `v-show` to show/hide elements.
* Go template code should use Gitea's `.gt-hidden` and `showElem()/hideElem()/toggleElem()`, see more details in `.gt-hidden`'s comment.
+### Styles and Attributes in Go HTML Template
+
+It's recommended to use:
+
+```html
+<div class="gt-name1 gt-name2 {{if .IsFoo}}gt-foo{{end}}" {{if .IsFoo}}data-foo{{end}}></div>
+```
+
+instead of:
+
+```html
+<div class="gt-name1 gt-name2{{if .IsFoo}} gt-foo{{end}}"{{if .IsFoo}} data-foo{{end}}></div>
+```
+
+to make the code more readable.
+
### Legacy Code
A lot of legacy code already existed before this document's written. It's recommended to refactor legacy code to follow the guidelines.
diff --git a/docs/content/doc/developers/hacking-on-gitea.zh-cn.md b/docs/content/doc/developers/hacking-on-gitea.zh-cn.md
new file mode 100644
index 000000000..9c9141bf5
--- /dev/null
+++ b/docs/content/doc/developers/hacking-on-gitea.zh-cn.md
@@ -0,0 +1,349 @@
+---
+date: "2016-12-01T16:00:00+02:00"
+title: "玩转 Gitea"
+slug: "hacking-on-gitea"
+weight: 10
+toc: false
+draft: false
+menu:
+ sidebar:
+ parent: "developers"
+ name: "玩转 Gitea"
+ weight: 10
+ identifier: "hacking-on-gitea"
+---
+
+# Hacking on Gitea
+
+**目录**
+
+{{< toc >}}
+
+## 快速入门
+
+è¦èŽ·å¾—快速工作的开å‘环境,您å¯ä»¥ä½¿ç”¨ Gitpod。
+
+[![在 Gitpod 中打开](/open-in-gitpod.svg)](https://gitpod.io/#https://github.com/go-gitea/gitea)
+
+## 安装 Golang
+
+æ‚¨éœ€è¦ [安装 go]( https://golang.org/doc/install ) 并设置您的 go 环境。
+
+接下æ¥ï¼Œ[使用 npm 安装 Node.js](https://nodejs.org/en/download/) ,这是构建
+JavaScript å’Œ CSS 文件的必è¦å·¥å…·ã€‚最低支æŒçš„ Node.js 版本是 {{< min-node-version >}}
+并且推è使用最新的 LTS 版本。
+
+**注æ„** :当执行需è¦å¤–部工具的 make 任务时,比如
+`make watch-backend`,Gitea 会自动下载并构建这些必è¦çš„组件。为了能够使用这些,你必须
+å°† `"$GOPATH"/bin` 目录加入到å¯æ‰§è¡Œè·¯å¾„上。如果你ä¸æŠŠgo bin目录添加到å¯æ‰§è¡Œè·¯å¾„你必须手动
+指定å¯æ‰§è¡Œç¨‹åºè·¯å¾„。
+
+**注æ„2** :Go版本 {{< min-go-version >}} 或更高版本是必须的。Gitea 使用 `gofmt` æ¥
+æ ¼å¼åŒ–æºä»£ç ã€‚然而,`gofmt` 的结果å¯èƒ½å›  `go` 的版本而有差异。因此推è安装我们æŒç»­é›†æˆä½¿ç”¨
+的 Go版本。截至上次更新,Go 版本应该是 {{< go-version >}}。
+
+## 安装 Make
+
+Gitea 大é‡ä½¿ç”¨ `Make` æ¥è‡ªåŠ¨åŒ–任务和改进开å‘。本指å—涵盖了如何安装 Make。
+
+### 在 Linux 上
+
+使用包管ç†å™¨å®‰è£…。
+
+在 Ubuntu/Debian 上:
+
+```bash
+sudo apt-get install make
+```
+
+在 Fedora/RHEL/CentOS 上:
+
+```bash
+sudo yum install make
+```
+
+### 在 Windows 上
+
+Make 的这三个å‘行版都å¯ä»¥åœ¨ Windows 上è¿è¡Œï¼š
+
+- [å•ä¸ªäºŒè¿›åˆ¶æž„建]( http://www.equation.com/servlet/equation.cmd?fa=make )。å¤åˆ¶åˆ°æŸå¤„并添加到 `PATH`。
+ - [32 ä½ç‰ˆæœ¬](http://www.equation.com/ftpdir/make/32/make.exe)
+ - [64 ä½ç‰ˆæœ¬](http://www.equation.com/ftpdir/make/64/make.exe)
+- [MinGW-w64](https://www.mingw-w64.org) / [MSYS2](https://www.msys2.org/)。
+ - MSYS2 是一个工具和库的集åˆï¼Œä¸ºæ‚¨æ供一个易于使用的环境æ¥æž„建ã€å®‰è£…å’Œè¿è¡Œæœ¬æœº Windows 软件,它包括 MinGW-w64。
+ - 在 MingGW-w64 中,二进制文件称为 `mingw32-make.exe` 而ä¸æ˜¯ `make.exe`。将 `bin` 文件夹添加到 `PATH`。
+ - 在 MSYS2 中,您å¯ä»¥ç›´æŽ¥ä½¿ç”¨ `make`。请å‚阅 [MSYS2 移æ¤](https://www.msys2.org/wiki/Porting/)。
+ - è¦ä½¿ç”¨ CGO_ENABLED(例如:SQLite3)编译 Gitea,您å¯èƒ½éœ€è¦ä½¿ç”¨ [tdm-gcc](https://jmeubank.github.io/tdm-gcc/) 而ä¸æ˜¯ MSYS2 gcc,因为 MSYS2 gcc 标头缺少一些 Windows -åªæœ‰ CRT å‡½æ•°åƒ _beginthread 一样。
+- [Chocolatey包管ç†å™¨]( https://chocolatey.org/packages/make )。è¿è¡Œ`choco install make`
+
+**注æ„** :如果您å°è¯•åœ¨ Windows 命令æ示符下使用 make 进行构建,您å¯èƒ½ä¼šé‡åˆ°é—®é¢˜ã€‚建议使用上述æ示(Git bash 或 MinGW),但是如果您åªæœ‰å‘½ä»¤æ示符(或å¯èƒ½æ˜¯ PowerShell),则å¯ä»¥ä½¿ç”¨ [set](https://docs.microsoft.com/en-us/windows-server/administration/windows-commands/set_1) 命令,例如 `set TAGS=bindata`。
+
+## 下载并克隆 Gitea æºä»£ç 
+
+获å–æºä»£ç çš„推è方法是使用 `git clone`。
+
+```bash
+git clone https://github.com/go-gitea/gitea
+```
+
+(自从go modules出现åŽï¼Œä¸å†éœ€è¦æž„建 go 项目从 `$GOPATH` 中获å–,因此ä¸å†æŽ¨è使用 `go get` 方法。)
+
+## 派生 Gitea
+
+如上所述下载主è¦çš„ Gitea æºä»£ç ã€‚然åŽï¼Œæ´¾ç”Ÿ [Gitea 仓库](https://github.com/go-gitea/gitea),
+å¹¶ä¸ºæ‚¨çš„æœ¬åœ°ä»“åº“åˆ‡æ¢ git 远程æºï¼Œæˆ–添加å¦ä¸€ä¸ªè¿œç¨‹æºï¼š
+
+```bash
+# 将原æ¥çš„ Gitea origin é‡å‘½å为 upstream
+git remote rename origin upstream
+git remote add origin "git@github.com:$GITHUB_USERNAME/gitea.git"
+git fetch --all --prune
+```
+
+或者:
+
+```bash
+# 为我们的 fork 添加新的远程
+git remote add "$FORK_NAME" "git@github.com:$GITHUB_USERNAME/gitea.git"
+git fetch --all --prune
+```
+
+为了能够创建åˆå¹¶è¯·æ±‚,应将分å‰å­˜å‚¨åº“添加为 Gitea 本地仓库的远程,å¦åˆ™æ— æ³•æŽ¨é€æ›´æ”¹ã€‚
+
+## 构建 Gitea(基本)
+
+看看我们的
+<a href='{{ < relref "doc/installation/from-source.en-us.md" > }}'>说明</a>
+关于如何 <a href='{{ < relref "doc/installation/from-source.en-us.md" > }}'>从æºä»£ç æž„建</a> 。
+
+从æºä»£ç æž„建的最简å•æŽ¨è方法是:
+
+```bash
+TAGS="bindata sqlite sqlite_unlock_notify" make build
+```
+
+`build` 目标将åŒæ—¶æ‰§è¡Œ `frontend` å’Œ `backend` å­ç›®æ ‡ã€‚如果存在 `bindata` 标签,资æºæ–‡ä»¶å°†è¢«ç¼–译æˆäºŒè¿›åˆ¶æ–‡ä»¶ã€‚建议在进行å‰ç«¯å¼€å‘æ—¶çœç•¥ `bindata` 标签,以便实时å映更改。
+
+有关所有å¯ç”¨çš„ `make` 目标,请å‚阅 `make help`。å¦è¯·å‚阅 [`.drone.yml`](https://github.com/go-gitea/gitea/blob/main/.drone.yml) 以了解我们的æŒç»­é›†æˆæ˜¯å¦‚何工作的。
+
+## æŒç»­æž„建
+
+è¦åœ¨æºæ–‡ä»¶æ›´æ”¹æ—¶è¿è¡Œå¹¶æŒç»­æž„建:
+
+```bash
+# 对于å‰ç«¯å’ŒåŽç«¯
+make watch
+
+# 或者:åªçœ‹å‰ç«¯æ–‡ä»¶ï¼ˆhtml/js/css)
+make watch-frontend
+
+# 或者:åªçœ‹åŽç«¯æ–‡ä»¶ (go)
+make watch-backend
+```
+
+在 macOS 上,监视所有åŽç«¯æºæ–‡ä»¶å¯èƒ½ä¼šè¾¾åˆ°é»˜è®¤çš„打开文件é™åˆ¶ï¼Œè¿™å¯ä»¥é€šè¿‡å½“å‰ shell çš„ `ulimit -n 12288` æˆ–æ‰€æœ‰æœªæ¥ shell çš„ shell å¯åŠ¨æ–‡ä»¶æ¥å¢žåŠ ã€‚
+
+### æ ¼å¼åŒ–ã€ä»£ç åˆ†æžå’Œæ‹¼å†™æ£€æŸ¥
+
+我们的æŒç»­é›†æˆå°†æ‹’ç»æœªé€šè¿‡ä»£ç æ£€æŸ¥ï¼ˆåŒ…括格å¼æ£€æŸ¥ã€ä»£ç åˆ†æžå’Œæ‹¼å†™æ£€æŸ¥ï¼‰çš„ PR。
+
+你应该格å¼åŒ–你的代ç ï¼š
+
+```bash
+make fmt
+```
+
+并检查æºä»£ç ï¼š
+
+```bash
+# lint å‰ç«¯å’ŒåŽç«¯ä»£ç 
+make lint
+# ä»… lint åŽç«¯ä»£ç 
+make lint-backend
+```
+
+**注æ„** :`gofmt` 的结果å–决于 `go` 的版本。您应该è¿è¡Œä¸ŽæŒç»­é›†æˆç›¸åŒçš„ go 版本。
+
+### å¤„ç† JS å’Œ CSS
+
+å‰ç«¯å¼€å‘应éµå¾ª [Guidelines for Frontend Development]({{ < 相关å‚考 "doc/developers/guidelines-frontend.en-us.md" > }})
+
+è¦ä½¿ç”¨å‰ç«¯èµ„æºæž„建,请使用上é¢æ到的“watch-frontendâ€ç›®æ ‡æˆ–åªæž„建一次:
+
+```bash
+make build && ./gitea
+```
+
+在æ交之å‰ï¼Œç¡®ä¿ linters 通过:
+
+```bash
+make lint-frontend
+```
+
+### é…置本地 ElasticSearch 实例
+
+使用 docker å¯åŠ¨æœ¬åœ° ElasticSearch 实例:
+
+```sh
+mkdir -p $(pwd) /data/elasticsearch
+sudo chown -R 1000:1000 $(pwd) /data/elasticsearch
+docker run --rm --memory= "4g" -p 127.0.0.1:9200:9200 -p 127.0.0.1:9300:9300 -e "discovery.type=single-node" -v "$(pwd)/data /elasticsearch:/usr/share/elasticsearch/data" docker.elastic.co/elasticsearch/elasticsearch:7.16.3
+```
+
+é…ç½®`app.ini`:
+
+```ini
+[indexer]
+ISSUE_INDEXER_TYPE = elasticsearch
+ISSUE_INDEXER_CONN_STR = http://elastic:changeme@localhost:9200
+REPO_INDEXER_ENABLED = true
+REPO_INDEXER_TYPE = elasticsearch
+REPO_INDEXER_CONN_STR = http://elastic:changeme@localhost:9200
+```
+
+### 构建和添加 SVGs
+
+SVG 图标是使用 `make svg` 目标构建的,该目标将 `build/generate-svg.js` 中定义的图标æºç¼–译到输出目录 `public/img/svg` 中。å¯ä»¥åœ¨ `web_src/svg` 目录中添加自定义图标。
+
+### 构建 Logo
+
+Gitea Logoçš„ PNG å’Œ SVG 版本是使用 `TAGS="gitea" make generate-images` 目标从å•ä¸ª SVG æºæ–‡ä»¶ assets/logo.svg 构建的。è¦è¿è¡Œå®ƒï¼ŒNode.js å’Œ npm å¿…é¡»å¯ç”¨ã€‚
+
+通过更新 `assets/logo.svg` 并è¿è¡Œ `make generate-images`,åŒæ ·çš„过程也å¯ç”¨äºŽä»Ž SVG æºæ–‡ä»¶ç”Ÿæˆè‡ªå®šä¹‰ Logo PNG。忽略 gitea 编译选项将仅更新用户指定的 LOGO 文件。
+
+### æ›´æ–° API
+
+创建新的 API 路由或修改现有的 API 路由时,您**必须**
+更新和/或创建 [Swagger](https://swagger.io/docs/specification/2-0/what-is-swagger/)
+这些使用 [go-swagger](https://goswagger.io/) 评论的文档。
+[规范]( https://goswagger.io/use/spec.html#annotation-syntax )中æ述了这些注释的结构。
+如果您想了解更多有关 Swagger 结构的信æ¯ï¼Œå¯ä»¥æŸ¥çœ‹
+[Swagger 2.0 文档](https://swagger.io/docs/specification/2-0/basic-structure/)
+或与添加新 API ç«¯ç‚¹çš„å…ˆå‰ PR 进行比较,例如 [PR #5483](https://github.com/go-gitea/gitea/pull/5843/files#diff-2e0a7b644cf31e1c8ef7d76b444fe3aaR20)
+
+您应该注æ„ä¸è¦ç ´å下游用户ä¾èµ–çš„ API。在稳定的 API 上,一般æ¥è¯´æ·»åŠ æ˜¯å¯ä»¥æŽ¥å—的,但删除
+或对 API 进行根本性更改将会被拒ç»ã€‚
+
+创建或更改 API 端点åŽï¼Œè¯·ç”¨ä»¥ä¸‹å‘½ä»¤é‡æ–°ç”Ÿæˆ Swagger 文档:
+
+```bash
+make generate-swagger
+```
+
+您应该验è¯ç”Ÿæˆçš„ Swagger 文件并使用以下命令对其进行拼写检查:
+
+```bash
+make swagger-validate misspell-check
+```
+
+您应该æ交更改åŽçš„ swagger JSON 文件。æŒç»­é›†æˆæœåŠ¡å™¨å°†ä½¿ç”¨ä»¥ä¸‹æ–¹æ³•æ£€æŸ¥æ˜¯å¦å·²å®Œæˆï¼š
+
+```bash
+make swagger-check
+```
+
+**注æ„** :请注æ„,您应该使用 Swagger 2.0 文档,而ä¸æ˜¯ OpenAPI 3 文档。
+
+### 创建新的é…置选项
+
+创建新的é…置选项时,将它们添加到 `modules/setting` 的对应文件。您应该将信æ¯æ·»åŠ åˆ° `custom/conf/app.ini`
+并到 <a href = '{{ < relref "doc/advanced/config-cheat-sheet.en-us.md" > }}'>é…置备忘å•</a>
+在 `docs/content/doc/advanced/config-cheat-sheet.en-us.md` 中找到
+
+### 更改Logo
+
+更改 Gitea Logo SVG 时,您将需è¦è¿è¡Œå¹¶æ交结果的:
+
+```bash
+make generate-images
+```
+
+这将创建必è¦çš„ Gitea 图标和其他图标。
+
+### æ•°æ®åº“è¿ç§»
+
+如果您对数æ®åº“中的任何数æ®åº“æŒä¹…结构进行é‡å¤§æ›´æ”¹
+`models/` 目录,您将需è¦è¿›è¡Œæ–°çš„è¿ç§»ã€‚å¯ä»¥æ‰¾åˆ°è¿™äº›
+在 `models/migrations/` 中。您å¯ä»¥ç¡®ä¿æ‚¨çš„è¿ç§»é€‚用于主è¦
+æ•°æ®åº“类型使用:
+
+```bash
+make test-sqlite-migration # å°† SQLite 切æ¢ä¸ºé€‚当的数æ®åº“
+```
+
+## 测试
+
+Gitea è¿è¡Œä¸¤ç§ç±»åž‹çš„测试:å•å…ƒæµ‹è¯•å’Œé›†æˆæµ‹è¯•ã€‚
+
+### å•å…ƒæµ‹è¯•
+
+`go test` 系统中的`*_test.go` 涵盖了å•å…ƒæµ‹è¯•ã€‚
+您å¯ä»¥è®¾ç½®çŽ¯å¢ƒå˜é‡ `GITEA_UNIT_TESTS_LOG_SQL=1` 以在详细模å¼ä¸‹è¿è¡Œæµ‹è¯•æ—¶æ˜¾ç¤ºæ‰€æœ‰ SQL 语å¥ï¼ˆå³è®¾ç½®`GOTESTFLAGS=-v` 时)。
+
+```bash
+TAGS="bindata sqlite sqlite_unlock_notify" make test # Runs the unit tests
+```
+
+### 集æˆæµ‹è¯•
+
+å•å…ƒæµ‹è¯•ä¸ä¼šä¹Ÿä¸èƒ½å®Œå…¨å•ç‹¬æµ‹è¯• Gitea。因此,我们编写了集æˆæµ‹è¯•ï¼›ä½†æ˜¯ï¼Œè¿™äº›ä¾èµ–于数æ®åº“。
+
+```bash
+TAGS="bindata sqlite sqlite_unlock_notify" make build test-sqlite
+```
+
+将在 SQLite 环境中è¿è¡Œé›†æˆæµ‹è¯•ã€‚集æˆæµ‹è¯•éœ€è¦å®‰è£… `git lfs`。其他数æ®åº“测试å¯ç”¨ï¼Œä½†
+å¯èƒ½éœ€è¦é€‚应当地环境。
+
+看看 [`tests/integration/README.md`](https://github.com/go-gitea/gitea/blob/main/tests/integration/README.md) 有关更多信æ¯ä»¥åŠå¦‚何è¿è¡Œå•ä¸ªæµ‹è¯•ã€‚
+
+### 测试 PR
+
+我们的æŒç»­é›†æˆå°†æµ‹è¯•ä»£ç æ˜¯å¦é€šè¿‡äº†å•å…ƒæµ‹è¯•ï¼Œå¹¶ä¸”所有支æŒçš„æ•°æ®åº“都将在 Docker 环境中通过集æˆæµ‹è¯•ã€‚
+还将测试从几个最新版本的 Gitea è¿ç§»ã€‚
+
+请在PR中附带æ交适当的å•å…ƒæµ‹è¯•å’Œé›†æˆæµ‹è¯•ã€‚
+
+## 网站文档
+
+该网站的文档ä½äºŽ `docs/` 中。如果你改å˜äº†æ–‡æ¡£å†…容,你å¯ä»¥ä½¿ç”¨ä»¥ä¸‹æµ‹è¯•æ–¹æ³•è¿›è¡ŒæŒç»­é›†æˆï¼š
+
+```bash
+# æ¥è‡ª Gitea 中的 docs 目录
+make trans-copy clean build
+```
+
+è¿è¡Œæ­¤ä»»åŠ¡ä¾èµ–于 [Hugo](https://gohugo.io/)。请注æ„:这å¯èƒ½ä¼šç”Ÿæˆä¸€äº›æœªè·Ÿè¸ªçš„ Git 对象,
+需è¦è¢«æ¸…ç†å¹²å‡€ã€‚
+
+## Visual Studio Code
+
+`contrib/ide/vscode` 中为 Visual Studio Code æ供了 `launch.json` å’Œ `tasks.json`。查看
+[`contrib/ide/README.md`](https://github.com/go-gitea/gitea/blob/main/contrib/ide/README.md) 了解更多信æ¯ã€‚
+
+## Goland
+
+å•å‡» `/main.go` 中函数 `func main()` 上的 `Run Application` 箭头
+å¯ä»¥å¿«é€Ÿå¯åŠ¨ä¸€ä¸ªå¯è°ƒè¯•çš„ Gitea 实例。
+
+`Run/Debug Configuration` 中的 `Output Directory` 必须设置为
+gitea é¡¹ç›®ç›®å½•ï¼ˆåŒ…å« `main.go` å’Œ `go.mod`),
+å¦åˆ™ï¼Œå¯åŠ¨å®žä¾‹çš„工作目录是 GoLand 的临时目录
+并防止 Gitea 在开å‘环境中加载动æ€èµ„æºï¼ˆä¾‹å¦‚:模æ¿ï¼‰ã€‚
+
+è¦åœ¨ GoLand 中使用 SQLite è¿è¡Œå•å…ƒæµ‹è¯•ï¼Œè¯·è®¾ç½® `-tags sqlite,sqlite_unlock_notify`
+在 `è¿è¡Œ/调试é…ç½®` çš„ `Go 工具å‚æ•°` 中。
+
+## æ交 PR
+
+对更改感到满æ„åŽï¼Œå°†å®ƒä»¬æŽ¨é€å¹¶æ‰“开拉å–请求。它建议您å…许 Gitea Managers å’Œ Owners 修改您的 PR
+分支,因为我们需è¦åœ¨åˆå¹¶ä¹‹å‰å°†å…¶æ›´æ–°ä¸º main å’Œ/或å¯èƒ½æ˜¯èƒ½å¤Ÿç›´æŽ¥å¸®åŠ©è§£å†³é—®é¢˜ã€‚
+
+任何 PR éƒ½éœ€è¦ Gitea 维护者的两次批准,并且需è¦é€šè¿‡æŒç»­é›†æˆã€‚看看我们的
+[CONTRIBUTING.md](https://github.com/go-gitea/gitea/blob/main/CONTRIBUTING.md)
+文档。
+
+如果您需è¦æ›´å¤šå¸®åŠ©ï¼Œè¯·è®¿é—® [Discord](https://discord.gg/gitea) #Develop 频é“
+并在那里èŠå¤©ã€‚
+
+现在,您已准备好 Hacking Gitea。
diff --git a/docs/content/doc/developers/oauth2-provider.en-us.md b/docs/content/doc/developers/oauth2-provider.en-us.md
index 17c12d22f..1ef30a7f0 100644
--- a/docs/content/doc/developers/oauth2-provider.en-us.md
+++ b/docs/content/doc/developers/oauth2-provider.en-us.md
@@ -60,6 +60,7 @@ Gitea supports the following scopes for tokens:
| &nbsp;&nbsp;&nbsp; **write:public_key** | Grant read/write access to public keys |
| &nbsp;&nbsp;&nbsp; **read:public_key** | Grant read-only access to public keys |
| **admin:org_hook** | Grants full access to organizational-level hooks |
+| **admin:user_hook** | Grants full access to user-level hooks |
| **notification** | Grants full access to notifications |
| **user** | Grants full access to user profile info |
| &nbsp;&nbsp;&nbsp; **read:user** | Grants read access to user's profile |
diff --git a/docs/content/doc/packages/maven.en-us.md b/docs/content/doc/packages/maven.en-us.md
index 22da3c16d..2ec5ca2ab 100644
--- a/docs/content/doc/packages/maven.en-us.md
+++ b/docs/content/doc/packages/maven.en-us.md
@@ -23,7 +23,7 @@ Publish [Maven](https://maven.apache.org) packages for your user or organization
## Requirements
To work with the Maven package registry, you can use [Maven](https://maven.apache.org/install.html) or [Gradle](https://gradle.org/install/).
-The following examples use `Maven`.
+The following examples use `Maven` and `Gradle Groovy`.
## Configuring the package registry
@@ -73,6 +73,40 @@ Afterwards add the following sections to your project `pom.xml` file:
| `access_token` | Your [personal access token]({{< relref "doc/developers/api-usage.en-us.md#authentication" >}}). |
| `owner` | The owner of the package. |
+### Gradle variant
+
+When you plan to add some packages from Gitea instance in your project, you should add it in repositories section:
+
+```groovy
+repositories {
+ // other repositories
+ maven { url "https://gitea.example.com/api/packages/{owner}/maven" }
+}
+```
+
+In Groovy gradle you may include next script in your publishing part:
+
+```groovy
+publishing {
+ // other settings of publication
+ repositories {
+ maven {
+ name = "Gitea"
+ url = uri("https://gitea.example.com/api/packages/{owner}/maven")
+
+ credentials(HttpHeaderCredentials) {
+ name = "Authorization"
+ value = "token {access_token}"
+ }
+
+ authentication {
+ header(HttpHeaderAuthentication)
+ }
+ }
+ }
+}
+```
+
## Publish a package
To publish a package simply run:
@@ -81,6 +115,12 @@ To publish a package simply run:
mvn deploy
```
+Or call `gradle` with task `publishAllPublicationsToGiteaRepository` in case you are using gradle:
+
+```groovy
+./gradlew publishAllPublicationsToGiteaRepository
+```
+
If you want to publish a prebuild package to the registry, you can use [`mvn deploy:deploy-file`](https://maven.apache.org/plugins/maven-deploy-plugin/deploy-file-mojo.html):
```shell
@@ -105,6 +145,12 @@ To install a Maven package from the package registry, add a new dependency to yo
</dependency>
```
+And analog in gradle groovy:
+
+```groovy
+implementation "com.test.package:test_project:1.0.0"
+```
+
Afterwards run:
```shell
diff --git a/docs/content/doc/usage/labels.en-us.md b/docs/content/doc/usage/labels.en-us.md
new file mode 100644
index 000000000..bf07c074e
--- /dev/null
+++ b/docs/content/doc/usage/labels.en-us.md
@@ -0,0 +1,42 @@
+---
+date: "2023-03-04T19:00:00+00:00"
+title: "Usage: Labels"
+slug: "labels"
+weight: 13
+toc: false
+draft: false
+menu:
+ sidebar:
+ parent: "usage"
+ name: "Labels"
+ weight: 13
+ identifier: "labels"
+---
+
+# Labels
+
+You can use labels to classify issues and pull requests and to improve your overview over them.
+
+## Creating Labels
+
+For repositories, labels can be created by going to `Issues` and clicking on `Labels`.
+
+For organizations, you can define organization-wide labels that are shared with all organization repositories, including both already-existing repositories as well as newly created ones. Organization-wide labels can be created in the organization `Settings`.
+
+Labels have a mandatory name, a mandatory color, an optional description, and must either be exclusive or not (see `Scoped labels` below).
+
+When you create a repository, you can ensure certain labels exist by using the `Issue Labels` option. This option lists a number of available label sets that are [configured globally on your instance](../customizing-gitea/#labels). Its contained labels will all be created as well while creating the repository.
+
+## Scoped Labels
+
+A scoped label is a label that contains `/` in its name (not at either end of the name). For example labels `kind/bug` and `kind/enhancement` both have scope `kind`. Such labels will display the scope with slightly darker color.
+
+The scope of a label is determined based on the **last** `/`, so for example the scope of label `scope/subscope/item` is `scope/subscope`.
+
+Scoped labels can be marked as exclusive. This ensures at most a single label with the same scope is assigned to an issue or pull request. For example, if `kind/bug` and `kind/enhancement` are marked exclusive, an issue can only be classified as a bug or an enhancement.
+
+## Filtering by Label
+
+Issue and pull request lists can be filtered by label. Selecting multiple labels shows issues and pull requests that have all selected labels assigned.
+
+By holding alt to click the label, issues and pull requests with the chosen label are excluded from the list.
diff --git a/models/actions/run.go b/models/actions/run.go
index a8d991471..d5ab45a51 100644
--- a/models/actions/run.go
+++ b/models/actions/run.go
@@ -192,6 +192,7 @@ func InsertRun(ctx context.Context, run *ActionRun, jobs []*jobparser.SingleWork
if len(needs) > 0 || run.NeedApproval {
status = StatusBlocked
}
+ job.Name, _ = util.SplitStringAtByteN(job.Name, 255)
runJobs = append(runJobs, &ActionRunJob{
RunID: run.ID,
RepoID: run.RepoID,
diff --git a/models/actions/task.go b/models/actions/task.go
index 5b6206c34..ffec4c92a 100644
--- a/models/actions/task.go
+++ b/models/actions/task.go
@@ -298,8 +298,9 @@ func CreateTaskForRunner(ctx context.Context, runner *ActionRunner) (*ActionTask
if len(workflowJob.Steps) > 0 {
steps := make([]*ActionTaskStep, len(workflowJob.Steps))
for i, v := range workflowJob.Steps {
+ name, _ := util.SplitStringAtByteN(v.String(), 255)
steps[i] = &ActionTaskStep{
- Name: v.String(),
+ Name: name,
TaskID: task.ID,
Index: int64(i),
RepoID: task.RepoID,
diff --git a/models/activities/action.go b/models/activities/action.go
index 1412d2c05..c1d17517b 100644
--- a/models/activities/action.go
+++ b/models/activities/action.go
@@ -99,7 +99,7 @@ func (a *Action) TableIndices() []*schemas.Index {
actUserIndex.AddColumn("act_user_id", "repo_id", "created_unix", "user_id", "is_deleted")
indices := []*schemas.Index{actUserIndex, repoIndex}
- if setting.Database.UsePostgreSQL {
+ if setting.Database.Type.IsPostgreSQL() {
cudIndex := schemas.NewIndex("c_u_d", schemas.IndexType)
cudIndex.AddColumn("created_unix", "user_id", "is_deleted")
indices = append(indices, cudIndex)
@@ -640,7 +640,7 @@ func DeleteIssueActions(ctx context.Context, repoID, issueID int64) error {
// CountActionCreatedUnixString count actions where created_unix is an empty string
func CountActionCreatedUnixString(ctx context.Context) (int64, error) {
- if setting.Database.UseSQLite3 {
+ if setting.Database.Type.IsSQLite3() {
return db.GetEngine(ctx).Where(`created_unix = ""`).Count(new(Action))
}
return 0, nil
@@ -648,7 +648,7 @@ func CountActionCreatedUnixString(ctx context.Context) (int64, error) {
// FixActionCreatedUnixString set created_unix to zero if it is an empty string
func FixActionCreatedUnixString(ctx context.Context) (int64, error) {
- if setting.Database.UseSQLite3 {
+ if setting.Database.Type.IsSQLite3() {
res, err := db.GetEngine(ctx).Exec(`UPDATE action SET created_unix = 0 WHERE created_unix = ""`)
if err != nil {
return 0, err
diff --git a/models/activities/action_test.go b/models/activities/action_test.go
index 2fd86bb8f..7044bcc00 100644
--- a/models/activities/action_test.go
+++ b/models/activities/action_test.go
@@ -243,7 +243,7 @@ func TestGetFeedsCorrupted(t *testing.T) {
}
func TestConsistencyUpdateAction(t *testing.T) {
- if !setting.Database.UseSQLite3 {
+ if !setting.Database.Type.IsSQLite3() {
t.Skip("Test is only for SQLite database.")
}
assert.NoError(t, unittest.PrepareTestDatabase())
diff --git a/models/activities/user_heatmap.go b/models/activities/user_heatmap.go
index 3370103a5..d3f0f0db7 100644
--- a/models/activities/user_heatmap.go
+++ b/models/activities/user_heatmap.go
@@ -39,9 +39,9 @@ func getUserHeatmapData(user *user_model.User, team *organization.Team, doer *us
groupBy := "created_unix / 900 * 900"
groupByName := "timestamp" // We need this extra case because mssql doesn't allow grouping by alias
switch {
- case setting.Database.UseMySQL:
+ case setting.Database.Type.IsMySQL():
groupBy = "created_unix DIV 900 * 900"
- case setting.Database.UseMSSQL:
+ case setting.Database.Type.IsMSSQL():
groupByName = groupBy
}
diff --git a/models/auth/token_scope.go b/models/auth/token_scope.go
index 38733a1c8..06c89fecc 100644
--- a/models/auth/token_scope.go
+++ b/models/auth/token_scope.go
@@ -32,6 +32,8 @@ const (
AccessTokenScopeAdminOrgHook AccessTokenScope = "admin:org_hook"
+ AccessTokenScopeAdminUserHook AccessTokenScope = "admin:user_hook"
+
AccessTokenScopeNotification AccessTokenScope = "notification"
AccessTokenScopeUser AccessTokenScope = "user"
@@ -64,7 +66,7 @@ type AccessTokenScopeBitmap uint64
const (
// AccessTokenScopeAllBits is the bitmap of all access token scopes, except `sudo`.
AccessTokenScopeAllBits AccessTokenScopeBitmap = AccessTokenScopeRepoBits |
- AccessTokenScopeAdminOrgBits | AccessTokenScopeAdminPublicKeyBits | AccessTokenScopeAdminOrgHookBits |
+ AccessTokenScopeAdminOrgBits | AccessTokenScopeAdminPublicKeyBits | AccessTokenScopeAdminOrgHookBits | AccessTokenScopeAdminUserHookBits |
AccessTokenScopeNotificationBits | AccessTokenScopeUserBits | AccessTokenScopeDeleteRepoBits |
AccessTokenScopePackageBits | AccessTokenScopeAdminGPGKeyBits | AccessTokenScopeAdminApplicationBits
@@ -86,6 +88,8 @@ const (
AccessTokenScopeAdminOrgHookBits AccessTokenScopeBitmap = 1 << iota
+ AccessTokenScopeAdminUserHookBits AccessTokenScopeBitmap = 1 << iota
+
AccessTokenScopeNotificationBits AccessTokenScopeBitmap = 1 << iota
AccessTokenScopeUserBits AccessTokenScopeBitmap = 1<<iota | AccessTokenScopeReadUserBits | AccessTokenScopeUserEmailBits | AccessTokenScopeUserFollowBits
@@ -123,6 +127,7 @@ var allAccessTokenScopes = []AccessTokenScope{
AccessTokenScopeAdminPublicKey, AccessTokenScopeWritePublicKey, AccessTokenScopeReadPublicKey,
AccessTokenScopeAdminRepoHook, AccessTokenScopeWriteRepoHook, AccessTokenScopeReadRepoHook,
AccessTokenScopeAdminOrgHook,
+ AccessTokenScopeAdminUserHook,
AccessTokenScopeNotification,
AccessTokenScopeUser, AccessTokenScopeReadUser, AccessTokenScopeUserEmail, AccessTokenScopeUserFollow,
AccessTokenScopeDeleteRepo,
@@ -147,6 +152,7 @@ var allAccessTokenScopeBits = map[AccessTokenScope]AccessTokenScopeBitmap{
AccessTokenScopeWriteRepoHook: AccessTokenScopeWriteRepoHookBits,
AccessTokenScopeReadRepoHook: AccessTokenScopeReadRepoHookBits,
AccessTokenScopeAdminOrgHook: AccessTokenScopeAdminOrgHookBits,
+ AccessTokenScopeAdminUserHook: AccessTokenScopeAdminUserHookBits,
AccessTokenScopeNotification: AccessTokenScopeNotificationBits,
AccessTokenScopeUser: AccessTokenScopeUserBits,
AccessTokenScopeReadUser: AccessTokenScopeReadUserBits,
@@ -263,7 +269,7 @@ func (bitmap AccessTokenScopeBitmap) ToScope() AccessTokenScope {
scope := AccessTokenScope(strings.Join(scopes, ","))
scope = AccessTokenScope(strings.ReplaceAll(
string(scope),
- "repo,admin:org,admin:public_key,admin:org_hook,notification,user,delete_repo,package,admin:gpg_key,admin:application",
+ "repo,admin:org,admin:public_key,admin:org_hook,admin:user_hook,notification,user,delete_repo,package,admin:gpg_key,admin:application",
"all",
))
return scope
diff --git a/models/auth/token_scope_test.go b/models/auth/token_scope_test.go
index 1d7f4794a..b96a5fd46 100644
--- a/models/auth/token_scope_test.go
+++ b/models/auth/token_scope_test.go
@@ -40,8 +40,8 @@ func TestAccessTokenScope_Normalize(t *testing.T) {
{"admin:gpg_key,write:gpg_key,user", "user,admin:gpg_key", nil},
{"admin:application,write:application,user", "user,admin:application", nil},
{"all", "all", nil},
- {"repo,admin:org,admin:public_key,admin:repo_hook,admin:org_hook,notification,user,delete_repo,package,admin:gpg_key,admin:application", "all", nil},
- {"repo,admin:org,admin:public_key,admin:repo_hook,admin:org_hook,notification,user,delete_repo,package,admin:gpg_key,admin:application,sudo", "all,sudo", nil},
+ {"repo,admin:org,admin:public_key,admin:repo_hook,admin:org_hook,admin:user_hook,notification,user,delete_repo,package,admin:gpg_key,admin:application", "all", nil},
+ {"repo,admin:org,admin:public_key,admin:repo_hook,admin:org_hook,admin:user_hook,notification,user,delete_repo,package,admin:gpg_key,admin:application,sudo", "all,sudo", nil},
}
for _, test := range tests {
diff --git a/models/db/common.go b/models/db/common.go
index 76c7c119f..af6130c9f 100644
--- a/models/db/common.go
+++ b/models/db/common.go
@@ -15,7 +15,7 @@ import (
// BuildCaseInsensitiveLike returns a condition to check if the given value is like the given key case-insensitively.
// Handles especially SQLite correctly as UPPER there only transforms ASCII letters.
func BuildCaseInsensitiveLike(key, value string) builder.Cond {
- if setting.Database.UseSQLite3 {
+ if setting.Database.Type.IsSQLite3() {
return builder.Like{"UPPER(" + key + ")", util.ToUpperASCII(value)}
}
return builder.Like{"UPPER(" + key + ")", strings.ToUpper(value)}
diff --git a/models/db/engine.go b/models/db/engine.go
index 5020101d4..56dd209fd 100755
--- a/models/db/engine.go
+++ b/models/db/engine.go
@@ -101,12 +101,12 @@ func newXORMEngine() (*xorm.Engine, error) {
var engine *xorm.Engine
- if setting.Database.UsePostgreSQL && len(setting.Database.Schema) > 0 {
+ if setting.Database.Type.IsPostgreSQL() && len(setting.Database.Schema) > 0 {
// OK whilst we sort out our schema issues - create a schema aware postgres
registerPostgresSchemaDriver()
engine, err = xorm.NewEngine("postgresschema", connStr)
} else {
- engine, err = xorm.NewEngine(setting.Database.Type, connStr)
+ engine, err = xorm.NewEngine(setting.Database.Type.String(), connStr)
}
if err != nil {
diff --git a/models/db/index.go b/models/db/index.go
index f840a62c8..7609d8fb6 100644
--- a/models/db/index.go
+++ b/models/db/index.go
@@ -73,7 +73,7 @@ func postgresGetNextResourceIndex(ctx context.Context, tableName string, groupID
// GetNextResourceIndex generates a resource index, it must run in the same transaction where the resource is created
func GetNextResourceIndex(ctx context.Context, tableName string, groupID int64) (int64, error) {
- if setting.Database.UsePostgreSQL {
+ if setting.Database.Type.IsPostgreSQL() {
return postgresGetNextResourceIndex(ctx, tableName, groupID)
}
diff --git a/models/db/iterate_test.go b/models/db/iterate_test.go
index a713fe0d8..6bcf740c2 100644
--- a/models/db/iterate_test.go
+++ b/models/db/iterate_test.go
@@ -25,7 +25,7 @@ func TestIterate(t *testing.T) {
return nil
})
assert.NoError(t, err)
- assert.EqualValues(t, 83, repoCnt)
+ assert.EqualValues(t, 84, repoCnt)
err = db.Iterate(db.DefaultContext, nil, func(ctx context.Context, repoUnit *repo_model.RepoUnit) error {
reopUnit2 := repo_model.RepoUnit{ID: repoUnit.ID}
diff --git a/models/db/list_test.go b/models/db/list_test.go
index ffef1e494..1295692ce 100644
--- a/models/db/list_test.go
+++ b/models/db/list_test.go
@@ -35,11 +35,11 @@ func TestFind(t *testing.T) {
var repoUnits []repo_model.RepoUnit
err := db.Find(db.DefaultContext, &opts, &repoUnits)
assert.NoError(t, err)
- assert.EqualValues(t, 83, len(repoUnits))
+ assert.EqualValues(t, 84, len(repoUnits))
cnt, err := db.Count(db.DefaultContext, &opts, new(repo_model.RepoUnit))
assert.NoError(t, err)
- assert.EqualValues(t, 83, cnt)
+ assert.EqualValues(t, 84, cnt)
repoUnits = make([]repo_model.RepoUnit, 0, 10)
newCnt, err := db.FindAndCount(db.DefaultContext, &opts, &repoUnits)
diff --git a/models/db/sequence.go b/models/db/sequence.go
index 6d801d022..f49ad935d 100644
--- a/models/db/sequence.go
+++ b/models/db/sequence.go
@@ -13,7 +13,7 @@ import (
// CountBadSequences looks for broken sequences from recreate-table mistakes
func CountBadSequences(_ context.Context) (int64, error) {
- if !setting.Database.UsePostgreSQL {
+ if !setting.Database.Type.IsPostgreSQL() {
return 0, nil
}
@@ -34,7 +34,7 @@ func CountBadSequences(_ context.Context) (int64, error) {
// FixBadSequences fixes for broken sequences from recreate-table mistakes
func FixBadSequences(_ context.Context) error {
- if !setting.Database.UsePostgreSQL {
+ if !setting.Database.Type.IsPostgreSQL() {
return nil
}
diff --git a/models/fixtures/repo_unit.yml b/models/fixtures/repo_unit.yml
index 503b8c9dd..ef0b7c1a9 100644
--- a/models/fixtures/repo_unit.yml
+++ b/models/fixtures/repo_unit.yml
@@ -569,3 +569,9 @@
type: 3
config: "{\"IgnoreWhitespaceConflicts\":false,\"AllowMerge\":true,\"AllowRebase\":true,\"AllowRebaseMerge\":true,\"AllowSquash\":true}"
created_unix: 946684810
+
+-
+ id: 84
+ repo_id: 56
+ type: 1
+ created_unix: 946684810
diff --git a/models/fixtures/repository.yml b/models/fixtures/repository.yml
index 58f9b919a..32ba8744d 100644
--- a/models/fixtures/repository.yml
+++ b/models/fixtures/repository.yml
@@ -25,7 +25,7 @@
fork_id: 0
is_template: false
template_id: 0
- size: 6708
+ size: 7028
is_fsck_enabled: true
close_issues_via_commit_in_any_branch: false
@@ -1634,3 +1634,16 @@
is_private: true
num_issues: 1
status: 0
+
+-
+ id: 56
+ owner_id: 2
+ owner_name: user2
+ lower_name: readme-test
+ name: readme-test
+ default_branch: master
+ is_empty: false
+ is_archived: false
+ is_private: true
+ status: 0
+ num_issues: 0
diff --git a/models/fixtures/team.yml b/models/fixtures/team.yml
index dd434d78a..be988b8fc 100644
--- a/models/fixtures/team.yml
+++ b/models/fixtures/team.yml
@@ -151,3 +151,25 @@
num_members: 1
includes_all_repositories: false
can_create_org_repo: true
+
+-
+ id: 15
+ org_id: 22
+ lower_name: owners
+ name: Owners
+ authorize: 4 # owner
+ num_repos: 0
+ num_members: 0
+ includes_all_repositories: false
+ can_create_org_repo: true
+
+-
+ id: 16
+ org_id: 23
+ lower_name: owners
+ name: Owners
+ authorize: 4 # owner
+ num_repos: 0
+ num_members: 0
+ includes_all_repositories: false
+ can_create_org_repo: true \ No newline at end of file
diff --git a/models/fixtures/user.yml b/models/fixtures/user.yml
index b1c7fc003..ce54defac 100644
--- a/models/fixtures/user.yml
+++ b/models/fixtures/user.yml
@@ -66,7 +66,7 @@
num_followers: 2
num_following: 1
num_stars: 2
- num_repos: 11
+ num_repos: 12
num_teams: 0
num_members: 0
visibility: 0
@@ -807,7 +807,7 @@
num_following: 0
num_stars: 0
num_repos: 2
- num_teams: 0
+ num_teams: 1
num_members: 0
visibility: 1
repo_admin_change_team_access: false
@@ -844,7 +844,7 @@
num_following: 0
num_stars: 0
num_repos: 2
- num_teams: 0
+ num_teams: 1
num_members: 0
visibility: 2
repo_admin_change_team_access: false
diff --git a/models/fixtures/webhook.yml b/models/fixtures/webhook.yml
index 5563dcada..f62bae1f3 100644
--- a/models/fixtures/webhook.yml
+++ b/models/fixtures/webhook.yml
@@ -16,7 +16,7 @@
-
id: 3
- org_id: 3
+ owner_id: 3
repo_id: 3
url: www.example.com/url3
content_type: 1 # json
diff --git a/models/git/commit_status.go b/models/git/commit_status.go
index 489507f71..82cbb2363 100644
--- a/models/git/commit_status.go
+++ b/models/git/commit_status.go
@@ -65,7 +65,7 @@ func postgresGetCommitStatusIndex(ctx context.Context, repoID int64, sha string)
// GetNextCommitStatusIndex retried 3 times to generate a resource index
func GetNextCommitStatusIndex(ctx context.Context, repoID int64, sha string) (int64, error) {
- if setting.Database.UsePostgreSQL {
+ if setting.Database.Type.IsPostgreSQL() {
return postgresGetCommitStatusIndex(ctx, repoID, sha)
}
diff --git a/models/git/lfs_lock.go b/models/git/lfs_lock.go
index 25480f3f9..178fa72f0 100644
--- a/models/git/lfs_lock.go
+++ b/models/git/lfs_lock.go
@@ -6,7 +6,6 @@ package git
import (
"context"
"fmt"
- "path"
"strings"
"time"
@@ -17,6 +16,7 @@ import (
"code.gitea.io/gitea/models/unit"
user_model "code.gitea.io/gitea/models/user"
"code.gitea.io/gitea/modules/setting"
+ "code.gitea.io/gitea/modules/util"
)
// LFSLock represents a git lfs lock of repository.
@@ -34,11 +34,7 @@ func init() {
// BeforeInsert is invoked from XORM before inserting an object of this type.
func (l *LFSLock) BeforeInsert() {
- l.Path = cleanPath(l.Path)
-}
-
-func cleanPath(p string) string {
- return path.Clean("/" + p)[1:]
+ l.Path = util.CleanPath(l.Path)
}
// CreateLFSLock creates a new lock.
@@ -53,7 +49,7 @@ func CreateLFSLock(ctx context.Context, repo *repo_model.Repository, lock *LFSLo
return nil, err
}
- lock.Path = cleanPath(lock.Path)
+ lock.Path = util.CleanPath(lock.Path)
lock.RepoID = repo.ID
l, err := GetLFSLock(dbCtx, repo, lock.Path)
@@ -73,7 +69,7 @@ func CreateLFSLock(ctx context.Context, repo *repo_model.Repository, lock *LFSLo
// GetLFSLock returns release by given path.
func GetLFSLock(ctx context.Context, repo *repo_model.Repository, path string) (*LFSLock, error) {
- path = cleanPath(path)
+ path = util.CleanPath(path)
rel := &LFSLock{RepoID: repo.ID}
has, err := db.GetEngine(ctx).Where("lower(path) = ?", strings.ToLower(path)).Get(rel)
if err != nil {
diff --git a/models/issues/label.go b/models/issues/label.go
index 90e4eb458..35c649e8f 100644
--- a/models/issues/label.go
+++ b/models/issues/label.go
@@ -7,12 +7,12 @@ package issues
import (
"context"
"fmt"
- "regexp"
"strconv"
"strings"
"code.gitea.io/gitea/models/db"
user_model "code.gitea.io/gitea/models/user"
+ "code.gitea.io/gitea/modules/label"
"code.gitea.io/gitea/modules/timeutil"
"code.gitea.io/gitea/modules/util"
@@ -78,9 +78,6 @@ func (err ErrLabelNotExist) Unwrap() error {
return util.ErrNotExist
}
-// LabelColorPattern is a regexp witch can validate LabelColor
-var LabelColorPattern = regexp.MustCompile("^#?(?:[0-9a-fA-F]{6}|[0-9a-fA-F]{3})$")
-
// Label represents a label of repository for issues.
type Label struct {
ID int64 `xorm:"pk autoincr"`
@@ -109,12 +106,12 @@ func init() {
}
// CalOpenIssues sets the number of open issues of a label based on the already stored number of closed issues.
-func (label *Label) CalOpenIssues() {
- label.NumOpenIssues = label.NumIssues - label.NumClosedIssues
+func (l *Label) CalOpenIssues() {
+ l.NumOpenIssues = l.NumIssues - l.NumClosedIssues
}
// CalOpenOrgIssues calculates the open issues of a label for a specific repo
-func (label *Label) CalOpenOrgIssues(ctx context.Context, repoID, labelID int64) {
+func (l *Label) CalOpenOrgIssues(ctx context.Context, repoID, labelID int64) {
counts, _ := CountIssuesByRepo(ctx, &IssuesOptions{
RepoID: repoID,
LabelIDs: []int64{labelID},
@@ -122,22 +119,22 @@ func (label *Label) CalOpenOrgIssues(ctx context.Context, repoID, labelID int64)
})
for _, count := range counts {
- label.NumOpenRepoIssues += count
+ l.NumOpenRepoIssues += count
}
}
// LoadSelectedLabelsAfterClick calculates the set of selected labels when a label is clicked
-func (label *Label) LoadSelectedLabelsAfterClick(currentSelectedLabels []int64, currentSelectedExclusiveScopes []string) {
+func (l *Label) LoadSelectedLabelsAfterClick(currentSelectedLabels []int64, currentSelectedExclusiveScopes []string) {
var labelQuerySlice []string
labelSelected := false
- labelID := strconv.FormatInt(label.ID, 10)
- labelScope := label.ExclusiveScope()
+ labelID := strconv.FormatInt(l.ID, 10)
+ labelScope := l.ExclusiveScope()
for i, s := range currentSelectedLabels {
- if s == label.ID {
+ if s == l.ID {
labelSelected = true
- } else if -s == label.ID {
+ } else if -s == l.ID {
labelSelected = true
- label.IsExcluded = true
+ l.IsExcluded = true
} else if s != 0 {
// Exclude other labels in the same scope from selection
if s < 0 || labelScope == "" || labelScope != currentSelectedExclusiveScopes[i] {
@@ -148,23 +145,23 @@ func (label *Label) LoadSelectedLabelsAfterClick(currentSelectedLabels []int64,
if !labelSelected {
labelQuerySlice = append(labelQuerySlice, labelID)
}
- label.IsSelected = labelSelected
- label.QueryString = strings.Join(labelQuerySlice, ",")
+ l.IsSelected = labelSelected
+ l.QueryString = strings.Join(labelQuerySlice, ",")
}
// BelongsToOrg returns true if label is an organization label
-func (label *Label) BelongsToOrg() bool {
- return label.OrgID > 0
+func (l *Label) BelongsToOrg() bool {
+ return l.OrgID > 0
}
// BelongsToRepo returns true if label is a repository label
-func (label *Label) BelongsToRepo() bool {
- return label.RepoID > 0
+func (l *Label) BelongsToRepo() bool {
+ return l.RepoID > 0
}
// Get color as RGB values in 0..255 range
-func (label *Label) ColorRGB() (float64, float64, float64, error) {
- color, err := strconv.ParseUint(label.Color[1:], 16, 64)
+func (l *Label) ColorRGB() (float64, float64, float64, error) {
+ color, err := strconv.ParseUint(l.Color[1:], 16, 64)
if err != nil {
return 0, 0, 0, err
}
@@ -176,9 +173,9 @@ func (label *Label) ColorRGB() (float64, float64, float64, error) {
}
// Determine if label text should be light or dark to be readable on background color
-func (label *Label) UseLightTextColor() bool {
- if strings.HasPrefix(label.Color, "#") {
- if r, g, b, err := label.ColorRGB(); err == nil {
+func (l *Label) UseLightTextColor() bool {
+ if strings.HasPrefix(l.Color, "#") {
+ if r, g, b, err := l.ColorRGB(); err == nil {
// Perceived brightness from: https://www.w3.org/TR/AERT/#color-contrast
// In the future WCAG 3 APCA may be a better solution
brightness := (0.299*r + 0.587*g + 0.114*b) / 255
@@ -190,40 +187,26 @@ func (label *Label) UseLightTextColor() bool {
}
// Return scope substring of label name, or empty string if none exists
-func (label *Label) ExclusiveScope() string {
- if !label.Exclusive {
+func (l *Label) ExclusiveScope() string {
+ if !l.Exclusive {
return ""
}
- lastIndex := strings.LastIndex(label.Name, "/")
- if lastIndex == -1 || lastIndex == 0 || lastIndex == len(label.Name)-1 {
+ lastIndex := strings.LastIndex(l.Name, "/")
+ if lastIndex == -1 || lastIndex == 0 || lastIndex == len(l.Name)-1 {
return ""
}
- return label.Name[:lastIndex]
+ return l.Name[:lastIndex]
}
// NewLabel creates a new label
-func NewLabel(ctx context.Context, label *Label) error {
- if !LabelColorPattern.MatchString(label.Color) {
- return fmt.Errorf("bad color code: %s", label.Color)
- }
-
- // normalize case
- label.Color = strings.ToLower(label.Color)
-
- // add leading hash
- if label.Color[0] != '#' {
- label.Color = "#" + label.Color
- }
-
- // convert 3-character shorthand into 6-character version
- if len(label.Color) == 4 {
- r := label.Color[1]
- g := label.Color[2]
- b := label.Color[3]
- label.Color = fmt.Sprintf("#%c%c%c%c%c%c", r, r, g, g, b, b)
+func NewLabel(ctx context.Context, l *Label) error {
+ color, err := label.NormalizeColor(l.Color)
+ if err != nil {
+ return err
}
+ l.Color = color
- return db.Insert(ctx, label)
+ return db.Insert(ctx, l)
}
// NewLabels creates new labels
@@ -234,11 +217,14 @@ func NewLabels(labels ...*Label) error {
}
defer committer.Close()
- for _, label := range labels {
- if !LabelColorPattern.MatchString(label.Color) {
- return fmt.Errorf("bad color code: %s", label.Color)
+ for _, l := range labels {
+ color, err := label.NormalizeColor(l.Color)
+ if err != nil {
+ return err
}
- if err := db.Insert(ctx, label); err != nil {
+ l.Color = color
+
+ if err := db.Insert(ctx, l); err != nil {
return err
}
}
@@ -247,15 +233,18 @@ func NewLabels(labels ...*Label) error {
// UpdateLabel updates label information.
func UpdateLabel(l *Label) error {
- if !LabelColorPattern.MatchString(l.Color) {
- return fmt.Errorf("bad color code: %s", l.Color)
+ color, err := label.NormalizeColor(l.Color)
+ if err != nil {
+ return err
}
+ l.Color = color
+
return updateLabelCols(db.DefaultContext, l, "name", "description", "color", "exclusive")
}
// DeleteLabel delete a label
func DeleteLabel(id, labelID int64) error {
- label, err := GetLabelByID(db.DefaultContext, labelID)
+ l, err := GetLabelByID(db.DefaultContext, labelID)
if err != nil {
if IsErrLabelNotExist(err) {
return nil
@@ -271,10 +260,10 @@ func DeleteLabel(id, labelID int64) error {
sess := db.GetEngine(ctx)
- if label.BelongsToOrg() && label.OrgID != id {
+ if l.BelongsToOrg() && l.OrgID != id {
return nil
}
- if label.BelongsToRepo() && label.RepoID != id {
+ if l.BelongsToRepo() && l.RepoID != id {
return nil
}
@@ -682,14 +671,14 @@ func newIssueLabels(ctx context.Context, issue *Issue, labels []*Label, doer *us
if err = issue.LoadRepo(ctx); err != nil {
return err
}
- for _, label := range labels {
+ for _, l := range labels {
// Don't add already present labels and invalid labels
- if HasIssueLabel(ctx, issue.ID, label.ID) ||
- (label.RepoID != issue.RepoID && label.OrgID != issue.Repo.OwnerID) {
+ if HasIssueLabel(ctx, issue.ID, l.ID) ||
+ (l.RepoID != issue.RepoID && l.OrgID != issue.Repo.OwnerID) {
continue
}
- if err = newIssueLabel(ctx, issue, label, doer); err != nil {
+ if err = newIssueLabel(ctx, issue, l, doer); err != nil {
return fmt.Errorf("newIssueLabel: %w", err)
}
}
diff --git a/models/issues/label_test.go b/models/issues/label_test.go
index 0e45e0db0..1f6ce4f42 100644
--- a/models/issues/label_test.go
+++ b/models/issues/label_test.go
@@ -15,8 +15,6 @@ import (
"github.com/stretchr/testify/assert"
)
-// TODO TestGetLabelTemplateFile
-
func TestLabel_CalOpenIssues(t *testing.T) {
assert.NoError(t, unittest.PrepareTestDatabase())
label := unittest.AssertExistsAndLoadBean(t, &issues_model.Label{ID: 1})
diff --git a/models/issues/pull_list.go b/models/issues/pull_list.go
index f4efd916c..9d361c5c5 100644
--- a/models/issues/pull_list.go
+++ b/models/issues/pull_list.go
@@ -52,13 +52,16 @@ func listPullRequestStatement(baseRepoID int64, opts *PullRequestsOptions) (*xor
// GetUnmergedPullRequestsByHeadInfo returns all pull requests that are open and has not been merged
// by given head information (repo and branch).
-func GetUnmergedPullRequestsByHeadInfo(repoID int64, branch string) ([]*PullRequest, error) {
+// arg `includeClosed` controls whether the SQL returns closed PRs
+func GetUnmergedPullRequestsByHeadInfo(repoID int64, branch string, includeClosed bool) ([]*PullRequest, error) {
prs := make([]*PullRequest, 0, 2)
- return prs, db.GetEngine(db.DefaultContext).
- Where("head_repo_id = ? AND head_branch = ? AND has_merged = ? AND issue.is_closed = ? AND flow = ?",
- repoID, branch, false, false, PullRequestFlowGithub).
+ sess := db.GetEngine(db.DefaultContext).
Join("INNER", "issue", "issue.id = pull_request.issue_id").
- Find(&prs)
+ Where("head_repo_id = ? AND head_branch = ? AND has_merged = ? AND flow = ?", repoID, branch, false, PullRequestFlowGithub)
+ if !includeClosed {
+ sess.Where("issue.is_closed = ?", false)
+ }
+ return prs, sess.Find(&prs)
}
// CanMaintainerWriteToBranch check whether user is a maintainer and could write to the branch
@@ -71,7 +74,7 @@ func CanMaintainerWriteToBranch(p access_model.Permission, branch string, user *
return false
}
- prs, err := GetUnmergedPullRequestsByHeadInfo(p.Units[0].RepoID, branch)
+ prs, err := GetUnmergedPullRequestsByHeadInfo(p.Units[0].RepoID, branch, false)
if err != nil {
return false
}
@@ -111,6 +114,7 @@ func GetUnmergedPullRequestsByBaseInfo(repoID int64, branch string) ([]*PullRequ
return prs, db.GetEngine(db.DefaultContext).
Where("base_repo_id=? AND base_branch=? AND has_merged=? AND issue.is_closed=?",
repoID, branch, false, false).
+ OrderBy("issue.updated_unix DESC").
Join("INNER", "issue", "issue.id=pull_request.issue_id").
Find(&prs)
}
diff --git a/models/issues/pull_test.go b/models/issues/pull_test.go
index 8ce8eecc4..bcd33329e 100644
--- a/models/issues/pull_test.go
+++ b/models/issues/pull_test.go
@@ -118,7 +118,7 @@ func TestHasUnmergedPullRequestsByHeadInfo(t *testing.T) {
func TestGetUnmergedPullRequestsByHeadInfo(t *testing.T) {
assert.NoError(t, unittest.PrepareTestDatabase())
- prs, err := issues_model.GetUnmergedPullRequestsByHeadInfo(1, "branch2")
+ prs, err := issues_model.GetUnmergedPullRequestsByHeadInfo(1, "branch2", false)
assert.NoError(t, err)
assert.Len(t, prs, 1)
for _, pr := range prs {
diff --git a/models/issues/stopwatch.go b/models/issues/stopwatch.go
index 6bf936c5d..c8cd5ad33 100644
--- a/models/issues/stopwatch.go
+++ b/models/issues/stopwatch.go
@@ -9,6 +9,7 @@ import (
"time"
"code.gitea.io/gitea/models/db"
+ "code.gitea.io/gitea/models/repo"
user_model "code.gitea.io/gitea/models/user"
"code.gitea.io/gitea/modules/timeutil"
"code.gitea.io/gitea/modules/util"
@@ -132,12 +133,26 @@ func StopwatchExists(userID, issueID int64) bool {
}
// HasUserStopwatch returns true if the user has a stopwatch
-func HasUserStopwatch(ctx context.Context, userID int64) (exists bool, sw *Stopwatch, err error) {
- sw = new(Stopwatch)
+func HasUserStopwatch(ctx context.Context, userID int64) (exists bool, sw *Stopwatch, issue *Issue, err error) {
+ type stopwatchIssueRepo struct {
+ Stopwatch `xorm:"extends"`
+ Issue `xorm:"extends"`
+ repo.Repository `xorm:"extends"`
+ }
+
+ swIR := new(stopwatchIssueRepo)
exists, err = db.GetEngine(ctx).
+ Table("stopwatch").
Where("user_id = ?", userID).
- Get(sw)
- return exists, sw, err
+ Join("INNER", "issue", "issue.id = stopwatch.issue_id").
+ Join("INNER", "repository", "repository.id = issue.repo_id").
+ Get(swIR)
+ if exists {
+ sw = &swIR.Stopwatch
+ issue = &swIR.Issue
+ issue.Repo = &swIR.Repository
+ }
+ return exists, sw, issue, err
}
// FinishIssueStopwatchIfPossible if stopwatch exist then finish it otherwise ignore
@@ -217,23 +232,18 @@ func CreateIssueStopwatch(ctx context.Context, user *user_model.User, issue *Iss
}
// if another stopwatch is running: stop it
- exists, sw, err := HasUserStopwatch(ctx, user.ID)
+ exists, _, otherIssue, err := HasUserStopwatch(ctx, user.ID)
if err != nil {
return err
}
if exists {
- issue, err := GetIssueByID(ctx, sw.IssueID)
- if err != nil {
- return err
- }
-
- if err := FinishIssueStopwatch(ctx, user, issue); err != nil {
+ if err := FinishIssueStopwatch(ctx, user, otherIssue); err != nil {
return err
}
}
// Create stopwatch
- sw = &Stopwatch{
+ sw := &Stopwatch{
UserID: user.ID,
IssueID: issue.ID,
}
diff --git a/models/issues/stopwatch_test.go b/models/issues/stopwatch_test.go
index ec2778aa8..ea3827a1f 100644
--- a/models/issues/stopwatch_test.go
+++ b/models/issues/stopwatch_test.go
@@ -45,12 +45,12 @@ func TestStopwatchExists(t *testing.T) {
func TestHasUserStopwatch(t *testing.T) {
assert.NoError(t, unittest.PrepareTestDatabase())
- exists, sw, err := issues_model.HasUserStopwatch(db.DefaultContext, 1)
+ exists, sw, _, err := issues_model.HasUserStopwatch(db.DefaultContext, 1)
assert.NoError(t, err)
assert.True(t, exists)
assert.Equal(t, int64(1), sw.ID)
- exists, _, err = issues_model.HasUserStopwatch(db.DefaultContext, 3)
+ exists, _, _, err = issues_model.HasUserStopwatch(db.DefaultContext, 3)
assert.NoError(t, err)
assert.False(t, exists)
}
diff --git a/models/migrations/base/db.go b/models/migrations/base/db.go
index dcf99c96a..b038ad733 100644
--- a/models/migrations/base/db.go
+++ b/models/migrations/base/db.go
@@ -89,7 +89,7 @@ func RecreateTable(sess *xorm.Session, bean interface{}) error {
hasID = hasID || (column.IsPrimaryKey && column.IsAutoIncrement)
}
- if hasID && setting.Database.UseMSSQL {
+ if hasID && setting.Database.Type.IsMSSQL() {
if _, err := sess.Exec(fmt.Sprintf("SET IDENTITY_INSERT `%s` ON", tempTableName)); err != nil {
log.Error("Unable to set identity insert for table %s. Error: %v", tempTableName, err)
return err
@@ -143,7 +143,7 @@ func RecreateTable(sess *xorm.Session, bean interface{}) error {
return err
}
- if hasID && setting.Database.UseMSSQL {
+ if hasID && setting.Database.Type.IsMSSQL() {
if _, err := sess.Exec(fmt.Sprintf("SET IDENTITY_INSERT `%s` OFF", tempTableName)); err != nil {
log.Error("Unable to switch off identity insert for table %s. Error: %v", tempTableName, err)
return err
@@ -151,7 +151,7 @@ func RecreateTable(sess *xorm.Session, bean interface{}) error {
}
switch {
- case setting.Database.UseSQLite3:
+ case setting.Database.Type.IsSQLite3():
// SQLite will drop all the constraints on the old table
if _, err := sess.Exec(fmt.Sprintf("DROP TABLE `%s`", tableName)); err != nil {
log.Error("Unable to drop old table %s. Error: %v", tableName, err)
@@ -178,7 +178,7 @@ func RecreateTable(sess *xorm.Session, bean interface{}) error {
return err
}
- case setting.Database.UseMySQL:
+ case setting.Database.Type.IsMySQL():
// MySQL will drop all the constraints on the old table
if _, err := sess.Exec(fmt.Sprintf("DROP TABLE `%s`", tableName)); err != nil {
log.Error("Unable to drop old table %s. Error: %v", tableName, err)
@@ -205,7 +205,7 @@ func RecreateTable(sess *xorm.Session, bean interface{}) error {
log.Error("Unable to recreate uniques on table %s. Error: %v", tableName, err)
return err
}
- case setting.Database.UsePostgreSQL:
+ case setting.Database.Type.IsPostgreSQL():
var originalSequences []string
type sequenceData struct {
LastValue int `xorm:"'last_value'"`
@@ -296,7 +296,7 @@ func RecreateTable(sess *xorm.Session, bean interface{}) error {
}
- case setting.Database.UseMSSQL:
+ case setting.Database.Type.IsMSSQL():
// MSSQL will drop all the constraints on the old table
if _, err := sess.Exec(fmt.Sprintf("DROP TABLE `%s`", tableName)); err != nil {
log.Error("Unable to drop old table %s. Error: %v", tableName, err)
@@ -323,7 +323,7 @@ func DropTableColumns(sess *xorm.Session, tableName string, columnNames ...strin
// TODO: This will not work if there are foreign keys
switch {
- case setting.Database.UseSQLite3:
+ case setting.Database.Type.IsSQLite3():
// First drop the indexes on the columns
res, errIndex := sess.Query(fmt.Sprintf("PRAGMA index_list(`%s`)", tableName))
if errIndex != nil {
@@ -405,7 +405,7 @@ func DropTableColumns(sess *xorm.Session, tableName string, columnNames ...strin
return err
}
- case setting.Database.UsePostgreSQL:
+ case setting.Database.Type.IsPostgreSQL():
cols := ""
for _, col := range columnNames {
if cols != "" {
@@ -416,7 +416,7 @@ func DropTableColumns(sess *xorm.Session, tableName string, columnNames ...strin
if _, err := sess.Exec(fmt.Sprintf("ALTER TABLE `%s` %s", tableName, cols)); err != nil {
return fmt.Errorf("Drop table `%s` columns %v: %v", tableName, columnNames, err)
}
- case setting.Database.UseMySQL:
+ case setting.Database.Type.IsMySQL():
// Drop indexes on columns first
sql := fmt.Sprintf("SHOW INDEX FROM %s WHERE column_name IN ('%s')", tableName, strings.Join(columnNames, "','"))
res, err := sess.Query(sql)
@@ -444,7 +444,7 @@ func DropTableColumns(sess *xorm.Session, tableName string, columnNames ...strin
if _, err := sess.Exec(fmt.Sprintf("ALTER TABLE `%s` %s", tableName, cols)); err != nil {
return fmt.Errorf("Drop table `%s` columns %v: %v", tableName, columnNames, err)
}
- case setting.Database.UseMSSQL:
+ case setting.Database.Type.IsMSSQL():
cols := ""
for _, col := range columnNames {
if cols != "" {
@@ -543,13 +543,13 @@ func newXORMEngine() (*xorm.Engine, error) {
func deleteDB() error {
switch {
- case setting.Database.UseSQLite3:
+ case setting.Database.Type.IsSQLite3():
if err := util.Remove(setting.Database.Path); err != nil {
return err
}
return os.MkdirAll(path.Dir(setting.Database.Path), os.ModePerm)
- case setting.Database.UseMySQL:
+ case setting.Database.Type.IsMySQL():
db, err := sql.Open("mysql", fmt.Sprintf("%s:%s@tcp(%s)/",
setting.Database.User, setting.Database.Passwd, setting.Database.Host))
if err != nil {
@@ -565,7 +565,7 @@ func deleteDB() error {
return err
}
return nil
- case setting.Database.UsePostgreSQL:
+ case setting.Database.Type.IsPostgreSQL():
db, err := sql.Open("postgres", fmt.Sprintf("postgres://%s:%s@%s/?sslmode=%s",
setting.Database.User, setting.Database.Passwd, setting.Database.Host, setting.Database.SSLMode))
if err != nil {
@@ -612,7 +612,7 @@ func deleteDB() error {
}
return nil
}
- case setting.Database.UseMSSQL:
+ case setting.Database.Type.IsMSSQL():
host, port := setting.ParseMSSQLHostPort(setting.Database.Host)
db, err := sql.Open("mssql", fmt.Sprintf("server=%s; port=%s; database=%s; user id=%s; password=%s;",
host, port, "master", setting.Database.User, setting.Database.Passwd))
diff --git a/models/migrations/migrations.go b/models/migrations/migrations.go
index 585457e47..4cbcd95d2 100644
--- a/models/migrations/migrations.go
+++ b/models/migrations/migrations.go
@@ -467,6 +467,8 @@ var migrations = []Migration{
// v244 -> v245
NewMigration("Add NeedApproval to actions tables", v1_20.AddNeedApprovalToActionRun),
+ // v245 -> v246
+ NewMigration("Rename Webhook org_id to owner_id", v1_20.RenameWebhookOrgToOwner),
}
// GetCurrentDBVersion returns the current db version
diff --git a/models/migrations/v1_12/v139.go b/models/migrations/v1_12/v139.go
index 725b8fa30..279aa7df8 100644
--- a/models/migrations/v1_12/v139.go
+++ b/models/migrations/v1_12/v139.go
@@ -13,9 +13,9 @@ func PrependRefsHeadsToIssueRefs(x *xorm.Engine) error {
var query string
switch {
- case setting.Database.UseMSSQL:
+ case setting.Database.Type.IsMSSQL():
query = "UPDATE `issue` SET `ref` = 'refs/heads/' + `ref` WHERE `ref` IS NOT NULL AND `ref` <> '' AND `ref` NOT LIKE 'refs/%'"
- case setting.Database.UseMySQL:
+ case setting.Database.Type.IsMySQL():
query = "UPDATE `issue` SET `ref` = CONCAT('refs/heads/', `ref`) WHERE `ref` IS NOT NULL AND `ref` <> '' AND `ref` NOT LIKE 'refs/%';"
default:
query = "UPDATE `issue` SET `ref` = 'refs/heads/' || `ref` WHERE `ref` IS NOT NULL AND `ref` <> '' AND `ref` NOT LIKE 'refs/%'"
diff --git a/models/migrations/v1_13/v140.go b/models/migrations/v1_13/v140.go
index 3de9eaaf7..4d87b955f 100644
--- a/models/migrations/v1_13/v140.go
+++ b/models/migrations/v1_13/v140.go
@@ -41,7 +41,7 @@ func FixLanguageStatsToSaveSize(x *xorm.Engine) error {
// Delete language stat statuses
truncExpr := "TRUNCATE TABLE"
- if setting.Database.UseSQLite3 {
+ if setting.Database.Type.IsSQLite3() {
truncExpr = "DELETE FROM"
}
diff --git a/models/migrations/v1_13/v145.go b/models/migrations/v1_13/v145.go
index c96e79f8a..ee40bfc77 100644
--- a/models/migrations/v1_13/v145.go
+++ b/models/migrations/v1_13/v145.go
@@ -21,7 +21,7 @@ func IncreaseLanguageField(x *xorm.Engine) error {
return err
}
- if setting.Database.UseSQLite3 {
+ if setting.Database.Type.IsSQLite3() {
// SQLite maps VARCHAR to TEXT without size so we're done
return nil
}
@@ -41,11 +41,11 @@ func IncreaseLanguageField(x *xorm.Engine) error {
}
switch {
- case setting.Database.UseMySQL:
+ case setting.Database.Type.IsMySQL():
if _, err := sess.Exec(fmt.Sprintf("ALTER TABLE language_stat MODIFY COLUMN language %s", sqlType)); err != nil {
return err
}
- case setting.Database.UseMSSQL:
+ case setting.Database.Type.IsMSSQL():
// Yet again MSSQL just has to be awkward.
// Here we have to drop the constraints first and then rebuild them
constraints := make([]string, 0)
@@ -71,7 +71,7 @@ func IncreaseLanguageField(x *xorm.Engine) error {
if err := sess.CreateUniques(new(LanguageStat)); err != nil {
return err
}
- case setting.Database.UsePostgreSQL:
+ case setting.Database.Type.IsPostgreSQL():
if _, err := sess.Exec(fmt.Sprintf("ALTER TABLE language_stat ALTER COLUMN language TYPE %s", sqlType)); err != nil {
return err
}
diff --git a/models/migrations/v1_13/v151.go b/models/migrations/v1_13/v151.go
index 9490c1778..9aa71ec29 100644
--- a/models/migrations/v1_13/v151.go
+++ b/models/migrations/v1_13/v151.go
@@ -17,13 +17,13 @@ import (
func SetDefaultPasswordToArgon2(x *xorm.Engine) error {
switch {
- case setting.Database.UseMySQL:
+ case setting.Database.Type.IsMySQL():
_, err := x.Exec("ALTER TABLE `user` ALTER passwd_hash_algo SET DEFAULT 'argon2';")
return err
- case setting.Database.UsePostgreSQL:
+ case setting.Database.Type.IsPostgreSQL():
_, err := x.Exec("ALTER TABLE `user` ALTER COLUMN passwd_hash_algo SET DEFAULT 'argon2';")
return err
- case setting.Database.UseMSSQL:
+ case setting.Database.Type.IsMSSQL():
// need to find the constraint and drop it, then recreate it.
sess := x.NewSession()
defer sess.Close()
@@ -53,7 +53,7 @@ func SetDefaultPasswordToArgon2(x *xorm.Engine) error {
}
return sess.Commit()
- case setting.Database.UseSQLite3:
+ case setting.Database.Type.IsSQLite3():
// drop through
default:
log.Fatal("Unrecognized DB")
diff --git a/models/migrations/v1_14/v158.go b/models/migrations/v1_14/v158.go
index 7ea80a659..2029829ff 100644
--- a/models/migrations/v1_14/v158.go
+++ b/models/migrations/v1_14/v158.go
@@ -62,7 +62,7 @@ func UpdateCodeCommentReplies(x *xorm.Engine) error {
return err
}
- if setting.Database.UseMSSQL {
+ if setting.Database.Type.IsMSSQL() {
if _, err := sess.Exec(sqlSelect + " INTO #temp_comments" + sqlTail); err != nil {
log.Error("unable to create temporary table")
return err
@@ -72,13 +72,13 @@ func UpdateCodeCommentReplies(x *xorm.Engine) error {
comments := make([]*Comment, 0, batchSize)
switch {
- case setting.Database.UseMySQL:
+ case setting.Database.Type.IsMySQL():
sqlCmd = sqlSelect + sqlTail + " LIMIT " + strconv.Itoa(batchSize) + ", " + strconv.Itoa(start)
- case setting.Database.UsePostgreSQL:
+ case setting.Database.Type.IsPostgreSQL():
fallthrough
- case setting.Database.UseSQLite3:
+ case setting.Database.Type.IsSQLite3():
sqlCmd = sqlSelect + sqlTail + " LIMIT " + strconv.Itoa(batchSize) + " OFFSET " + strconv.Itoa(start)
- case setting.Database.UseMSSQL:
+ case setting.Database.Type.IsMSSQL():
sqlCmd = "SELECT TOP " + strconv.Itoa(batchSize) + " * FROM #temp_comments WHERE " +
"(id NOT IN ( SELECT TOP " + strconv.Itoa(start) + " id FROM #temp_comments ORDER BY id )) ORDER BY id"
default:
diff --git a/models/migrations/v1_14/v175.go b/models/migrations/v1_14/v175.go
index f1b9b974c..70d72b260 100644
--- a/models/migrations/v1_14/v175.go
+++ b/models/migrations/v1_14/v175.go
@@ -14,7 +14,7 @@ import (
)
func FixPostgresIDSequences(x *xorm.Engine) error {
- if !setting.Database.UsePostgreSQL {
+ if !setting.Database.Type.IsPostgreSQL() {
return nil
}
diff --git a/models/migrations/v1_15/v184.go b/models/migrations/v1_15/v184.go
index 48f8b6216..caf41b604 100644
--- a/models/migrations/v1_15/v184.go
+++ b/models/migrations/v1_15/v184.go
@@ -54,11 +54,11 @@ func RenameTaskErrorsToMessage(x *xorm.Engine) error {
}
switch {
- case setting.Database.UseMySQL:
+ case setting.Database.Type.IsMySQL():
if _, err := sess.Exec("ALTER TABLE `task` CHANGE errors message text"); err != nil {
return err
}
- case setting.Database.UseMSSQL:
+ case setting.Database.Type.IsMSSQL():
if _, err := sess.Exec("sp_rename 'task.errors', 'message', 'COLUMN'"); err != nil {
return err
}
diff --git a/models/migrations/v1_16/v191.go b/models/migrations/v1_16/v191.go
index 2d2c3d1a5..c618783c0 100644
--- a/models/migrations/v1_16/v191.go
+++ b/models/migrations/v1_16/v191.go
@@ -16,7 +16,7 @@ func AlterIssueAndCommentTextFieldsToLongText(x *xorm.Engine) error {
return err
}
- if setting.Database.UseMySQL {
+ if setting.Database.Type.IsMySQL() {
if _, err := sess.Exec("ALTER TABLE `issue` CHANGE `content` `content` LONGTEXT"); err != nil {
return err
}
diff --git a/models/migrations/v1_17/v217.go b/models/migrations/v1_17/v217.go
index 3ca9215f0..3f970b68a 100644
--- a/models/migrations/v1_17/v217.go
+++ b/models/migrations/v1_17/v217.go
@@ -16,7 +16,7 @@ func AlterHookTaskTextFieldsToLongText(x *xorm.Engine) error {
return err
}
- if setting.Database.UseMySQL {
+ if setting.Database.Type.IsMySQL() {
if _, err := sess.Exec("ALTER TABLE `hook_task` CHANGE `payload_content` `payload_content` LONGTEXT, CHANGE `request_content` `request_content` LONGTEXT, change `response_content` `response_content` LONGTEXT"); err != nil {
return err
}
diff --git a/models/migrations/v1_17/v218.go b/models/migrations/v1_17/v218.go
index 675fd1df9..ae91ba0c4 100644
--- a/models/migrations/v1_17/v218.go
+++ b/models/migrations/v1_17/v218.go
@@ -38,7 +38,7 @@ func (*improveActionTableIndicesAction) TableIndices() []*schemas.Index {
actUserIndex := schemas.NewIndex("au_r_c_u_d", schemas.IndexType)
actUserIndex.AddColumn("act_user_id", "repo_id", "created_unix", "user_id", "is_deleted")
indices := []*schemas.Index{actUserIndex, repoIndex}
- if setting.Database.UsePostgreSQL {
+ if setting.Database.Type.IsPostgreSQL() {
cudIndex := schemas.NewIndex("c_u_d", schemas.IndexType)
cudIndex.AddColumn("created_unix", "user_id", "is_deleted")
indices = append(indices, cudIndex)
diff --git a/models/migrations/v1_17/v223.go b/models/migrations/v1_17/v223.go
index a23d9916b..6c61dbc53 100644
--- a/models/migrations/v1_17/v223.go
+++ b/models/migrations/v1_17/v223.go
@@ -65,11 +65,11 @@ func RenameCredentialIDBytes(x *xorm.Engine) error {
}
switch {
- case setting.Database.UseMySQL:
+ case setting.Database.Type.IsMySQL():
if _, err := sess.Exec("ALTER TABLE `webauthn_credential` CHANGE credential_id_bytes credential_id VARBINARY(1024)"); err != nil {
return err
}
- case setting.Database.UseMSSQL:
+ case setting.Database.Type.IsMSSQL():
if _, err := sess.Exec("sp_rename 'webauthn_credential.credential_id_bytes', 'credential_id', 'COLUMN'"); err != nil {
return err
}
diff --git a/models/migrations/v1_18/v225.go b/models/migrations/v1_18/v225.go
index 786772c14..b0ac3777f 100644
--- a/models/migrations/v1_18/v225.go
+++ b/models/migrations/v1_18/v225.go
@@ -16,7 +16,7 @@ func AlterPublicGPGKeyContentFieldsToMediumText(x *xorm.Engine) error {
return err
}
- if setting.Database.UseMySQL {
+ if setting.Database.Type.IsMySQL() {
if _, err := sess.Exec("ALTER TABLE `gpg_key` CHANGE `content` `content` MEDIUMTEXT"); err != nil {
return err
}
diff --git a/models/migrations/v1_19/v232.go b/models/migrations/v1_19/v232.go
index 89b595c54..9caf587c1 100644
--- a/models/migrations/v1_19/v232.go
+++ b/models/migrations/v1_19/v232.go
@@ -16,7 +16,7 @@ func AlterPackageVersionMetadataToLongText(x *xorm.Engine) error {
return err
}
- if setting.Database.UseMySQL {
+ if setting.Database.Type.IsMySQL() {
if _, err := sess.Exec("ALTER TABLE `package_version` MODIFY COLUMN `metadata_json` LONGTEXT"); err != nil {
return err
}
diff --git a/models/migrations/v1_19/v242.go b/models/migrations/v1_19/v242.go
index 517c7767b..447083521 100644
--- a/models/migrations/v1_19/v242.go
+++ b/models/migrations/v1_19/v242.go
@@ -17,7 +17,7 @@ func AlterPublicGPGKeyImportContentFieldToMediumText(x *xorm.Engine) error {
return err
}
- if setting.Database.UseMySQL {
+ if setting.Database.Type.IsMySQL() {
if _, err := sess.Exec("ALTER TABLE `gpg_key_import` CHANGE `content` `content` MEDIUMTEXT"); err != nil {
return err
}
diff --git a/models/migrations/v1_20/v245.go b/models/migrations/v1_20/v245.go
new file mode 100644
index 000000000..466f21c23
--- /dev/null
+++ b/models/migrations/v1_20/v245.go
@@ -0,0 +1,74 @@
+// Copyright 2023 The Gitea Authors. All rights reserved.
+// SPDX-License-Identifier: MIT
+
+package v1_20 //nolint
+
+import (
+ "context"
+ "fmt"
+
+ "code.gitea.io/gitea/models/migrations/base"
+ "code.gitea.io/gitea/modules/setting"
+
+ "xorm.io/xorm"
+)
+
+func RenameWebhookOrgToOwner(x *xorm.Engine) error {
+ type Webhook struct {
+ OrgID int64 `xorm:"INDEX"`
+ }
+
+ // This migration maybe rerun so that we should check if it has been run
+ ownerExist, err := x.Dialect().IsColumnExist(x.DB(), context.Background(), "webhook", "owner_id")
+ if err != nil {
+ return err
+ }
+
+ if ownerExist {
+ orgExist, err := x.Dialect().IsColumnExist(x.DB(), context.Background(), "webhook", "org_id")
+ if err != nil {
+ return err
+ }
+ if !orgExist {
+ return nil
+ }
+ }
+
+ sess := x.NewSession()
+ defer sess.Close()
+ if err := sess.Begin(); err != nil {
+ return err
+ }
+
+ if err := sess.Sync2(new(Webhook)); err != nil {
+ return err
+ }
+
+ if ownerExist {
+ if err := base.DropTableColumns(sess, "webhook", "owner_id"); err != nil {
+ return err
+ }
+ }
+
+ switch {
+ case setting.Database.Type.IsMySQL():
+ inferredTable, err := x.TableInfo(new(Webhook))
+ if err != nil {
+ return err
+ }
+ sqlType := x.Dialect().SQLType(inferredTable.GetColumn("org_id"))
+ if _, err := sess.Exec(fmt.Sprintf("ALTER TABLE `webhook` CHANGE org_id owner_id %s", sqlType)); err != nil {
+ return err
+ }
+ case setting.Database.Type.IsMSSQL():
+ if _, err := sess.Exec("sp_rename 'webhook.org_id', 'owner_id', 'COLUMN'"); err != nil {
+ return err
+ }
+ default:
+ if _, err := sess.Exec("ALTER TABLE `webhook` RENAME COLUMN org_id TO owner_id"); err != nil {
+ return err
+ }
+ }
+
+ return sess.Commit()
+}
diff --git a/models/organization/org.go b/models/organization/org.go
index f05027be7..269b3e832 100644
--- a/models/organization/org.go
+++ b/models/organization/org.go
@@ -239,6 +239,32 @@ func (org *Organization) CustomAvatarRelativePath() string {
return org.Avatar
}
+// UnitPermission returns unit permission
+func (org *Organization) UnitPermission(ctx context.Context, doer *user_model.User, unitType unit.Type) perm.AccessMode {
+ if doer != nil {
+ teams, err := GetUserOrgTeams(ctx, org.ID, doer.ID)
+ if err != nil {
+ log.Error("GetUserOrgTeams: %v", err)
+ return perm.AccessModeNone
+ }
+
+ if err := teams.LoadUnits(ctx); err != nil {
+ log.Error("LoadUnits: %v", err)
+ return perm.AccessModeNone
+ }
+
+ if len(teams) > 0 {
+ return teams.UnitMaxAccess(unitType)
+ }
+ }
+
+ if org.Visibility.IsPublic() {
+ return perm.AccessModeRead
+ }
+
+ return perm.AccessModeNone
+}
+
// CreateOrganization creates record of a new organization.
func CreateOrganization(org *Organization, owner *user_model.User) (err error) {
if !owner.CanCreateOrganization() {
diff --git a/models/project/project.go b/models/project/project.go
index 46b5c07c4..f3ed72303 100644
--- a/models/project/project.go
+++ b/models/project/project.go
@@ -409,7 +409,7 @@ func DeleteProjectByID(ctx context.Context, id int64) error {
func DeleteProjectByRepoID(ctx context.Context, repoID int64) error {
switch {
- case setting.Database.UseSQLite3:
+ case setting.Database.Type.IsSQLite3():
if _, err := db.GetEngine(ctx).Exec("DELETE FROM project_issue WHERE project_issue.id IN (SELECT project_issue.id FROM project_issue INNER JOIN project WHERE project.id = project_issue.project_id AND project.repo_id = ?)", repoID); err != nil {
return err
}
@@ -419,7 +419,7 @@ func DeleteProjectByRepoID(ctx context.Context, repoID int64) error {
if _, err := db.GetEngine(ctx).Table("project").Where("repo_id = ? ", repoID).Delete(&Project{}); err != nil {
return err
}
- case setting.Database.UsePostgreSQL:
+ case setting.Database.Type.IsPostgreSQL():
if _, err := db.GetEngine(ctx).Exec("DELETE FROM project_issue USING project WHERE project.id = project_issue.project_id AND project.repo_id = ? ", repoID); err != nil {
return err
}
diff --git a/models/repo/repo_list.go b/models/repo/repo_list.go
index d64368daa..d9cd905a1 100644
--- a/models/repo/repo_list.go
+++ b/models/repo/repo_list.go
@@ -498,7 +498,7 @@ func SearchRepositoryCondition(opts *SearchRepoOptions) builder.Cond {
subQueryCond := builder.NewCond()
// Topic checking. Topics are present.
- if setting.Database.UsePostgreSQL { // postgres stores the topics as json and not as text
+ if setting.Database.Type.IsPostgreSQL() { // postgres stores the topics as json and not as text
subQueryCond = subQueryCond.Or(builder.And(builder.NotNull{"topics"}, builder.Neq{"(topics)::text": "[]"}))
} else {
subQueryCond = subQueryCond.Or(builder.And(builder.Neq{"topics": "null"}, builder.Neq{"topics": "[]"}))
diff --git a/models/unittest/testdb.go b/models/unittest/testdb.go
index 2bc41084b..cff1489a7 100644
--- a/models/unittest/testdb.go
+++ b/models/unittest/testdb.go
@@ -76,7 +76,7 @@ func MainTest(m *testing.M, testOpts *TestOptions) {
setting.SSH.BuiltinServerUser = "builtinuser"
setting.SSH.Port = 3000
setting.SSH.Domain = "try.gitea.io"
- setting.Database.UseSQLite3 = true
+ setting.Database.Type = "sqlite3"
setting.Repository.DefaultBranch = "master" // many test code still assume that default branch is called "master"
repoRootPath, err := os.MkdirTemp(os.TempDir(), "repos")
if err != nil {
diff --git a/models/user/user.go b/models/user/user.go
index 3a2e4f19b..7bc88e773 100644
--- a/models/user/user.go
+++ b/models/user/user.go
@@ -394,6 +394,11 @@ func (u *User) IsOrganization() bool {
return u.Type == UserTypeOrganization
}
+// IsIndividual returns true if user is actually a individual user.
+func (u *User) IsIndividual() bool {
+ return u.Type == UserTypeIndividual
+}
+
// DisplayName returns full name if it's not empty,
// returns username otherwise.
func (u *User) DisplayName() string {
diff --git a/models/webhook/webhook.go b/models/webhook/webhook.go
index 64119f149..e3f6b593d 100644
--- a/models/webhook/webhook.go
+++ b/models/webhook/webhook.go
@@ -122,7 +122,7 @@ func IsValidHookContentType(name string) bool {
type Webhook struct {
ID int64 `xorm:"pk autoincr"`
RepoID int64 `xorm:"INDEX"` // An ID of 0 indicates either a default or system webhook
- OrgID int64 `xorm:"INDEX"`
+ OwnerID int64 `xorm:"INDEX"`
IsSystemWebhook bool
URL string `xorm:"url TEXT"`
HTTPMethod string `xorm:"http_method"`
@@ -412,11 +412,11 @@ func GetWebhookByRepoID(repoID, id int64) (*Webhook, error) {
})
}
-// GetWebhookByOrgID returns webhook of organization by given ID.
-func GetWebhookByOrgID(orgID, id int64) (*Webhook, error) {
+// GetWebhookByOwnerID returns webhook of a user or organization by given ID.
+func GetWebhookByOwnerID(ownerID, id int64) (*Webhook, error) {
return getWebhook(&Webhook{
- ID: id,
- OrgID: orgID,
+ ID: id,
+ OwnerID: ownerID,
})
}
@@ -424,7 +424,7 @@ func GetWebhookByOrgID(orgID, id int64) (*Webhook, error) {
type ListWebhookOptions struct {
db.ListOptions
RepoID int64
- OrgID int64
+ OwnerID int64
IsActive util.OptionalBool
}
@@ -433,8 +433,8 @@ func (opts *ListWebhookOptions) toCond() builder.Cond {
if opts.RepoID != 0 {
cond = cond.And(builder.Eq{"webhook.repo_id": opts.RepoID})
}
- if opts.OrgID != 0 {
- cond = cond.And(builder.Eq{"webhook.org_id": opts.OrgID})
+ if opts.OwnerID != 0 {
+ cond = cond.And(builder.Eq{"webhook.owner_id": opts.OwnerID})
}
if !opts.IsActive.IsNone() {
cond = cond.And(builder.Eq{"webhook.is_active": opts.IsActive.IsTrue()})
@@ -503,10 +503,10 @@ func DeleteWebhookByRepoID(repoID, id int64) error {
})
}
-// DeleteWebhookByOrgID deletes webhook of organization by given ID.
-func DeleteWebhookByOrgID(orgID, id int64) error {
+// DeleteWebhookByOwnerID deletes webhook of a user or organization by given ID.
+func DeleteWebhookByOwnerID(ownerID, id int64) error {
return deleteWebhook(&Webhook{
- ID: id,
- OrgID: orgID,
+ ID: id,
+ OwnerID: ownerID,
})
}
diff --git a/models/webhook/webhook_system.go b/models/webhook/webhook_system.go
index 21dc0406a..2e89f9547 100644
--- a/models/webhook/webhook_system.go
+++ b/models/webhook/webhook_system.go
@@ -15,7 +15,7 @@ import (
func GetDefaultWebhooks(ctx context.Context) ([]*Webhook, error) {
webhooks := make([]*Webhook, 0, 5)
return webhooks, db.GetEngine(ctx).
- Where("repo_id=? AND org_id=? AND is_system_webhook=?", 0, 0, false).
+ Where("repo_id=? AND owner_id=? AND is_system_webhook=?", 0, 0, false).
Find(&webhooks)
}
@@ -23,7 +23,7 @@ func GetDefaultWebhooks(ctx context.Context) ([]*Webhook, error) {
func GetSystemOrDefaultWebhook(ctx context.Context, id int64) (*Webhook, error) {
webhook := &Webhook{ID: id}
has, err := db.GetEngine(ctx).
- Where("repo_id=? AND org_id=?", 0, 0).
+ Where("repo_id=? AND owner_id=?", 0, 0).
Get(webhook)
if err != nil {
return nil, err
@@ -38,11 +38,11 @@ func GetSystemWebhooks(ctx context.Context, isActive util.OptionalBool) ([]*Webh
webhooks := make([]*Webhook, 0, 5)
if isActive.IsNone() {
return webhooks, db.GetEngine(ctx).
- Where("repo_id=? AND org_id=? AND is_system_webhook=?", 0, 0, true).
+ Where("repo_id=? AND owner_id=? AND is_system_webhook=?", 0, 0, true).
Find(&webhooks)
}
return webhooks, db.GetEngine(ctx).
- Where("repo_id=? AND org_id=? AND is_system_webhook=? AND is_active = ?", 0, 0, true, isActive.IsTrue()).
+ Where("repo_id=? AND owner_id=? AND is_system_webhook=? AND is_active = ?", 0, 0, true, isActive.IsTrue()).
Find(&webhooks)
}
@@ -50,7 +50,7 @@ func GetSystemWebhooks(ctx context.Context, isActive util.OptionalBool) ([]*Webh
func DeleteDefaultSystemWebhook(ctx context.Context, id int64) error {
return db.WithTx(ctx, func(ctx context.Context) error {
count, err := db.GetEngine(ctx).
- Where("repo_id=? AND org_id=?", 0, 0).
+ Where("repo_id=? AND owner_id=?", 0, 0).
Delete(&Webhook{ID: id})
if err != nil {
return err
diff --git a/models/webhook/webhook_test.go b/models/webhook/webhook_test.go
index c368fc620..74f7aeaa0 100644
--- a/models/webhook/webhook_test.go
+++ b/models/webhook/webhook_test.go
@@ -109,13 +109,13 @@ func TestGetWebhookByRepoID(t *testing.T) {
assert.True(t, IsErrWebhookNotExist(err))
}
-func TestGetWebhookByOrgID(t *testing.T) {
+func TestGetWebhookByOwnerID(t *testing.T) {
assert.NoError(t, unittest.PrepareTestDatabase())
- hook, err := GetWebhookByOrgID(3, 3)
+ hook, err := GetWebhookByOwnerID(3, 3)
assert.NoError(t, err)
assert.Equal(t, int64(3), hook.ID)
- _, err = GetWebhookByOrgID(unittest.NonexistentID, unittest.NonexistentID)
+ _, err = GetWebhookByOwnerID(unittest.NonexistentID, unittest.NonexistentID)
assert.Error(t, err)
assert.True(t, IsErrWebhookNotExist(err))
}
@@ -140,9 +140,9 @@ func TestGetWebhooksByRepoID(t *testing.T) {
}
}
-func TestGetActiveWebhooksByOrgID(t *testing.T) {
+func TestGetActiveWebhooksByOwnerID(t *testing.T) {
assert.NoError(t, unittest.PrepareTestDatabase())
- hooks, err := ListWebhooksByOpts(db.DefaultContext, &ListWebhookOptions{OrgID: 3, IsActive: util.OptionalBoolTrue})
+ hooks, err := ListWebhooksByOpts(db.DefaultContext, &ListWebhookOptions{OwnerID: 3, IsActive: util.OptionalBoolTrue})
assert.NoError(t, err)
if assert.Len(t, hooks, 1) {
assert.Equal(t, int64(3), hooks[0].ID)
@@ -150,9 +150,9 @@ func TestGetActiveWebhooksByOrgID(t *testing.T) {
}
}
-func TestGetWebhooksByOrgID(t *testing.T) {
+func TestGetWebhooksByOwnerID(t *testing.T) {
assert.NoError(t, unittest.PrepareTestDatabase())
- hooks, err := ListWebhooksByOpts(db.DefaultContext, &ListWebhookOptions{OrgID: 3})
+ hooks, err := ListWebhooksByOpts(db.DefaultContext, &ListWebhookOptions{OwnerID: 3})
assert.NoError(t, err)
if assert.Len(t, hooks, 1) {
assert.Equal(t, int64(3), hooks[0].ID)
@@ -181,13 +181,13 @@ func TestDeleteWebhookByRepoID(t *testing.T) {
assert.True(t, IsErrWebhookNotExist(err))
}
-func TestDeleteWebhookByOrgID(t *testing.T) {
+func TestDeleteWebhookByOwnerID(t *testing.T) {
assert.NoError(t, unittest.PrepareTestDatabase())
- unittest.AssertExistsAndLoadBean(t, &Webhook{ID: 3, OrgID: 3})
- assert.NoError(t, DeleteWebhookByOrgID(3, 3))
- unittest.AssertNotExistsBean(t, &Webhook{ID: 3, OrgID: 3})
+ unittest.AssertExistsAndLoadBean(t, &Webhook{ID: 3, OwnerID: 3})
+ assert.NoError(t, DeleteWebhookByOwnerID(3, 3))
+ unittest.AssertNotExistsBean(t, &Webhook{ID: 3, OwnerID: 3})
- err := DeleteWebhookByOrgID(unittest.NonexistentID, unittest.NonexistentID)
+ err := DeleteWebhookByOwnerID(unittest.NonexistentID, unittest.NonexistentID)
assert.Error(t, err)
assert.True(t, IsErrWebhookNotExist(err))
}
diff --git a/modules/auth/password/hash/setting.go b/modules/auth/password/hash/setting.go
index 701697430..f0715f31e 100644
--- a/modules/auth/password/hash/setting.go
+++ b/modules/auth/password/hash/setting.go
@@ -41,9 +41,8 @@ var RecommendedHashAlgorithms = []string{
"pbkdf2_hi",
}
-// SetDefaultPasswordHashAlgorithm will take a provided algorithmName and dealias it to
-// a complete algorithm specification.
-func SetDefaultPasswordHashAlgorithm(algorithmName string) (string, *PasswordHashAlgorithm) {
+// hashAlgorithmToSpec converts an algorithm name or a specification to a full algorithm specification
+func hashAlgorithmToSpec(algorithmName string) string {
if algorithmName == "" {
algorithmName = DefaultHashAlgorithmName
}
@@ -52,10 +51,26 @@ func SetDefaultPasswordHashAlgorithm(algorithmName string) (string, *PasswordHas
algorithmName = alias
alias, has = aliasAlgorithmNames[algorithmName]
}
+ return algorithmName
+}
- // algorithmName should now be a full algorithm specification
- // e.g. pbkdf2$50000$50 rather than pbdkf2
- DefaultHashAlgorithm = Parse(algorithmName)
+// SetDefaultPasswordHashAlgorithm will take a provided algorithmName and de-alias it to
+// a complete algorithm specification.
+func SetDefaultPasswordHashAlgorithm(algorithmName string) (string, *PasswordHashAlgorithm) {
+ algoSpec := hashAlgorithmToSpec(algorithmName)
+ // now we get a full specification, e.g. pbkdf2$50000$50 rather than pbdkf2
+ DefaultHashAlgorithm = Parse(algoSpec)
+ return algoSpec, DefaultHashAlgorithm
+}
- return algorithmName, DefaultHashAlgorithm
+// ConfigHashAlgorithm will try to find a "recommended algorithm name" defined by RecommendedHashAlgorithms for config
+// This function is not fast and is only used for the installation page
+func ConfigHashAlgorithm(algorithm string) string {
+ algorithm = hashAlgorithmToSpec(algorithm)
+ for _, recommAlgo := range RecommendedHashAlgorithms {
+ if algorithm == hashAlgorithmToSpec(recommAlgo) {
+ return recommAlgo
+ }
+ }
+ return algorithm
}
diff --git a/modules/cache/context.go b/modules/cache/context.go
index f741a8744..62bbf5dcb 100644
--- a/modules/cache/context.go
+++ b/modules/cache/context.go
@@ -6,6 +6,7 @@ package cache
import (
"context"
"sync"
+ "time"
"code.gitea.io/gitea/modules/log"
)
@@ -14,65 +15,151 @@ import (
// This is useful for caching data that is expensive to calculate and is likely to be
// used multiple times in a request.
type cacheContext struct {
- ctx context.Context
- data map[any]map[any]any
- lock sync.RWMutex
+ data map[any]map[any]any
+ lock sync.RWMutex
+ created time.Time
+ discard bool
}
func (cc *cacheContext) Get(tp, key any) any {
cc.lock.RLock()
defer cc.lock.RUnlock()
- if cc.data[tp] == nil {
- return nil
- }
return cc.data[tp][key]
}
func (cc *cacheContext) Put(tp, key, value any) {
cc.lock.Lock()
defer cc.lock.Unlock()
- if cc.data[tp] == nil {
- cc.data[tp] = make(map[any]any)
+
+ if cc.discard {
+ return
+ }
+
+ d := cc.data[tp]
+ if d == nil {
+ d = make(map[any]any)
+ cc.data[tp] = d
}
- cc.data[tp][key] = value
+ d[key] = value
}
func (cc *cacheContext) Delete(tp, key any) {
cc.lock.Lock()
defer cc.lock.Unlock()
- if cc.data[tp] == nil {
- return
- }
delete(cc.data[tp], key)
}
+func (cc *cacheContext) Discard() {
+ cc.lock.Lock()
+ defer cc.lock.Unlock()
+ cc.data = nil
+ cc.discard = true
+}
+
+func (cc *cacheContext) isDiscard() bool {
+ cc.lock.RLock()
+ defer cc.lock.RUnlock()
+ return cc.discard
+}
+
+// cacheContextLifetime is the max lifetime of cacheContext.
+// Since cacheContext is used to cache data in a request level context, 10s is enough.
+// If a cacheContext is used more than 10s, it's probably misuse.
+const cacheContextLifetime = 10 * time.Second
+
+var timeNow = time.Now
+
+func (cc *cacheContext) Expired() bool {
+ return timeNow().Sub(cc.created) > cacheContextLifetime
+}
+
var cacheContextKey = struct{}{}
+/*
+Since there are both WithCacheContext and WithNoCacheContext,
+it may be confusing when there is nesting.
+
+Some cases to explain the design:
+
+When:
+- A, B or C means a cache context.
+- A', B' or C' means a discard cache context.
+- ctx means context.Backgrand().
+- A(ctx) means a cache context with ctx as the parent context.
+- B(A(ctx)) means a cache context with A(ctx) as the parent context.
+- With is alias of WithCacheContext.
+- WithNo is alias of WithNoCacheContext.
+
+So:
+- With(ctx) -> A(ctx)
+- With(With(ctx)) -> A(ctx), not B(A(ctx)), always reuse parent cache context if possible.
+- With(With(With(ctx))) -> A(ctx), not C(B(A(ctx))), ditto.
+- WithNo(ctx) -> ctx, not A'(ctx), don't create new cache context if we don't have to.
+- WithNo(With(ctx)) -> A'(ctx)
+- WithNo(WithNo(With(ctx))) -> A'(ctx), not B'(A'(ctx)), don't create new cache context if we don't have to.
+- With(WithNo(With(ctx))) -> B(A'(ctx)), not A(ctx), never reuse a discard cache context.
+- WithNo(With(WithNo(With(ctx)))) -> B'(A'(ctx))
+- With(WithNo(With(WithNo(With(ctx))))) -> C(B'(A'(ctx))), so there's always only one not-discard cache context.
+*/
+
func WithCacheContext(ctx context.Context) context.Context {
+ if c, ok := ctx.Value(cacheContextKey).(*cacheContext); ok {
+ if !c.isDiscard() {
+ // reuse parent context
+ return ctx
+ }
+ }
return context.WithValue(ctx, cacheContextKey, &cacheContext{
- ctx: ctx,
- data: make(map[any]map[any]any),
+ data: make(map[any]map[any]any),
+ created: timeNow(),
})
}
+func WithNoCacheContext(ctx context.Context) context.Context {
+ if c, ok := ctx.Value(cacheContextKey).(*cacheContext); ok {
+ // The caller want to run long-life tasks, but the parent context is a cache context.
+ // So we should disable and clean the cache data, or it will be kept in memory for a long time.
+ c.Discard()
+ return ctx
+ }
+
+ return ctx
+}
+
func GetContextData(ctx context.Context, tp, key any) any {
if c, ok := ctx.Value(cacheContextKey).(*cacheContext); ok {
+ if c.Expired() {
+ // The warning means that the cache context is misused for long-life task,
+ // it can be resolved with WithNoCacheContext(ctx).
+ log.Warn("cache context is expired, may be misused for long-life tasks: %v", c)
+ return nil
+ }
return c.Get(tp, key)
}
- log.Warn("cannot get cache context when getting data: %v", ctx)
return nil
}
func SetContextData(ctx context.Context, tp, key, value any) {
if c, ok := ctx.Value(cacheContextKey).(*cacheContext); ok {
+ if c.Expired() {
+ // The warning means that the cache context is misused for long-life task,
+ // it can be resolved with WithNoCacheContext(ctx).
+ log.Warn("cache context is expired, may be misused for long-life tasks: %v", c)
+ return
+ }
c.Put(tp, key, value)
return
}
- log.Warn("cannot get cache context when setting data: %v", ctx)
}
func RemoveContextData(ctx context.Context, tp, key any) {
if c, ok := ctx.Value(cacheContextKey).(*cacheContext); ok {
+ if c.Expired() {
+ // The warning means that the cache context is misused for long-life task,
+ // it can be resolved with WithNoCacheContext(ctx).
+ log.Warn("cache context is expired, may be misused for long-life tasks: %v", c)
+ return
+ }
c.Delete(tp, key)
}
}
diff --git a/modules/cache/context_test.go b/modules/cache/context_test.go
index 77e3ecad2..531554786 100644
--- a/modules/cache/context_test.go
+++ b/modules/cache/context_test.go
@@ -6,6 +6,7 @@ package cache
import (
"context"
"testing"
+ "time"
"github.com/stretchr/testify/assert"
)
@@ -25,7 +26,7 @@ func TestWithCacheContext(t *testing.T) {
assert.EqualValues(t, 1, v.(int))
RemoveContextData(ctx, field, "my_config1")
- RemoveContextData(ctx, field, "my_config2") // remove an non-exist key
+ RemoveContextData(ctx, field, "my_config2") // remove a non-exist key
v = GetContextData(ctx, field, "my_config1")
assert.Nil(t, v)
@@ -38,4 +39,40 @@ func TestWithCacheContext(t *testing.T) {
v = GetContextData(ctx, field, "my_config1")
assert.EqualValues(t, 1, v)
+
+ now := timeNow
+ defer func() {
+ timeNow = now
+ }()
+ timeNow = func() time.Time {
+ return now().Add(10 * time.Second)
+ }
+ v = GetContextData(ctx, field, "my_config1")
+ assert.Nil(t, v)
+}
+
+func TestWithNoCacheContext(t *testing.T) {
+ ctx := context.Background()
+
+ const field = "system_setting"
+
+ v := GetContextData(ctx, field, "my_config1")
+ assert.Nil(t, v)
+ SetContextData(ctx, field, "my_config1", 1)
+ v = GetContextData(ctx, field, "my_config1")
+ assert.Nil(t, v) // still no cache
+
+ ctx = WithCacheContext(ctx)
+ v = GetContextData(ctx, field, "my_config1")
+ assert.Nil(t, v)
+ SetContextData(ctx, field, "my_config1", 1)
+ v = GetContextData(ctx, field, "my_config1")
+ assert.NotNil(t, v)
+
+ ctx = WithNoCacheContext(ctx)
+ v = GetContextData(ctx, field, "my_config1")
+ assert.Nil(t, v)
+ SetContextData(ctx, field, "my_config1", 1)
+ v = GetContextData(ctx, field, "my_config1")
+ assert.Nil(t, v) // still no cache
}
diff --git a/modules/context/access_log.go b/modules/context/access_log.go
index 1aaba9dc2..515682b64 100644
--- a/modules/context/access_log.go
+++ b/modules/context/access_log.go
@@ -6,7 +6,9 @@ package context
import (
"bytes"
"context"
+ "fmt"
"net/http"
+ "strings"
"text/template"
"time"
@@ -20,13 +22,39 @@ type routerLoggerOptions struct {
Start *time.Time
ResponseWriter http.ResponseWriter
Ctx map[string]interface{}
+ RequestID *string
}
var signedUserNameStringPointerKey interface{} = "signedUserNameStringPointerKey"
+const keyOfRequestIDInTemplate = ".RequestID"
+
+// According to:
+// TraceId: A valid trace identifier is a 16-byte array with at least one non-zero byte
+// MD5 output is 16 or 32 bytes: md5-bytes is 16, md5-hex is 32
+// SHA1: similar, SHA1-bytes is 20, SHA1-hex is 40.
+// UUID is 128-bit, 32 hex chars, 36 ASCII chars with 4 dashes
+// So, we accept a Request ID with a maximum character length of 40
+const maxRequestIDByteLength = 40
+
+func parseRequestIDFromRequestHeader(req *http.Request) string {
+ requestID := "-"
+ for _, key := range setting.Log.RequestIDHeaders {
+ if req.Header.Get(key) != "" {
+ requestID = req.Header.Get(key)
+ break
+ }
+ }
+ if len(requestID) > maxRequestIDByteLength {
+ requestID = fmt.Sprintf("%s...", requestID[:maxRequestIDByteLength])
+ }
+ return requestID
+}
+
// AccessLogger returns a middleware to log access logger
func AccessLogger() func(http.Handler) http.Handler {
logger := log.GetLogger("access")
+ needRequestID := len(setting.Log.RequestIDHeaders) > 0 && strings.Contains(setting.Log.AccessLogTemplate, keyOfRequestIDInTemplate)
logTemplate, _ := template.New("log").Parse(setting.Log.AccessLogTemplate)
return func(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
@@ -34,6 +62,11 @@ func AccessLogger() func(http.Handler) http.Handler {
identity := "-"
r := req.WithContext(context.WithValue(req.Context(), signedUserNameStringPointerKey, &identity))
+ var requestID string
+ if needRequestID {
+ requestID = parseRequestIDFromRequestHeader(req)
+ }
+
next.ServeHTTP(w, r)
rw := w.(ResponseWriter)
@@ -47,6 +80,7 @@ func AccessLogger() func(http.Handler) http.Handler {
"RemoteAddr": req.RemoteAddr,
"Req": req,
},
+ RequestID: &requestID,
})
if err != nil {
log.Error("Could not set up chi access logger: %v", err.Error())
diff --git a/modules/context/api.go b/modules/context/api.go
index 3f938948a..f7a338469 100644
--- a/modules/context/api.go
+++ b/modules/context/api.go
@@ -244,7 +244,7 @@ func APIContexter() func(http.Handler) http.Handler {
}
}
- httpcache.AddCacheControlToHeader(ctx.Resp.Header(), 0, "no-transform")
+ httpcache.SetCacheControlInHeader(ctx.Resp.Header(), 0, "no-transform")
ctx.Resp.Header().Set(`X-Frame-Options`, setting.CORSConfig.XFrameOptions)
ctx.Data["Context"] = &ctx
diff --git a/modules/context/context.go b/modules/context/context.go
index 0c8d7411e..50c34edae 100644
--- a/modules/context/context.go
+++ b/modules/context/context.go
@@ -388,7 +388,7 @@ func (ctx *Context) SetServeHeaders(opts *ServeHeaderOptions) {
if duration == 0 {
duration = 5 * time.Minute
}
- httpcache.AddCacheControlToHeader(header, duration)
+ httpcache.SetCacheControlInHeader(header, duration)
if !opts.LastModified.IsZero() {
header.Set("Last-Modified", opts.LastModified.UTC().Format(http.TimeFormat))
@@ -753,7 +753,7 @@ func Contexter(ctx context.Context) func(next http.Handler) http.Handler {
}
}
- httpcache.AddCacheControlToHeader(ctx.Resp.Header(), 0, "no-transform")
+ httpcache.SetCacheControlInHeader(ctx.Resp.Header(), 0, "no-transform")
ctx.Resp.Header().Set(`X-Frame-Options`, setting.CORSConfig.XFrameOptions)
ctx.Data["CsrfToken"] = ctx.csrf.GetToken()
diff --git a/modules/context/org.go b/modules/context/org.go
index 0add7f2c0..39a3038f9 100644
--- a/modules/context/org.go
+++ b/modules/context/org.go
@@ -11,7 +11,6 @@ import (
"code.gitea.io/gitea/models/perm"
"code.gitea.io/gitea/models/unit"
user_model "code.gitea.io/gitea/models/user"
- "code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/structs"
)
@@ -31,29 +30,34 @@ type Organization struct {
}
func (org *Organization) CanWriteUnit(ctx *Context, unitType unit.Type) bool {
- if ctx.Doer == nil {
- return false
- }
- return org.UnitPermission(ctx, ctx.Doer.ID, unitType) >= perm.AccessModeWrite
+ return org.Organization.UnitPermission(ctx, ctx.Doer, unitType) >= perm.AccessModeWrite
}
-func (org *Organization) UnitPermission(ctx *Context, doerID int64, unitType unit.Type) perm.AccessMode {
- if doerID > 0 {
- teams, err := organization.GetUserOrgTeams(ctx, org.Organization.ID, doerID)
- if err != nil {
- log.Error("GetUserOrgTeams: %v", err)
- return perm.AccessModeNone
- }
- if len(teams) > 0 {
- return teams.UnitMaxAccess(unitType)
- }
- }
+func (org *Organization) CanReadUnit(ctx *Context, unitType unit.Type) bool {
+ return org.Organization.UnitPermission(ctx, ctx.Doer, unitType) >= perm.AccessModeRead
+}
- if org.Organization.Visibility == structs.VisibleTypePublic {
- return perm.AccessModeRead
- }
+func GetOrganizationByParams(ctx *Context) {
+ orgName := ctx.Params(":org")
+
+ var err error
- return perm.AccessModeNone
+ ctx.Org.Organization, err = organization.GetOrgByName(ctx, orgName)
+ if err != nil {
+ if organization.IsErrOrgNotExist(err) {
+ redirectUserID, err := user_model.LookupUserRedirect(orgName)
+ if err == nil {
+ RedirectToUser(ctx, orgName, redirectUserID)
+ } else if user_model.IsErrUserRedirectNotExist(err) {
+ ctx.NotFound("GetUserByName", err)
+ } else {
+ ctx.ServerError("LookupUserRedirect", err)
+ }
+ } else {
+ ctx.ServerError("GetUserByName", err)
+ }
+ return
+ }
}
// HandleOrgAssignment handles organization assignment
@@ -77,25 +81,26 @@ func HandleOrgAssignment(ctx *Context, args ...bool) {
requireTeamAdmin = args[3]
}
- orgName := ctx.Params(":org")
-
var err error
- ctx.Org.Organization, err = organization.GetOrgByName(ctx, orgName)
- if err != nil {
- if organization.IsErrOrgNotExist(err) {
- redirectUserID, err := user_model.LookupUserRedirect(orgName)
- if err == nil {
- RedirectToUser(ctx, orgName, redirectUserID)
- } else if user_model.IsErrUserRedirectNotExist(err) {
- ctx.NotFound("GetUserByName", err)
- } else {
- ctx.ServerError("LookupUserRedirect", err)
+
+ if ctx.ContextUser == nil {
+ // if Organization is not defined, get it from params
+ if ctx.Org.Organization == nil {
+ GetOrganizationByParams(ctx)
+ if ctx.Written() {
+ return
}
- } else {
- ctx.ServerError("GetUserByName", err)
}
+ } else if ctx.ContextUser.IsOrganization() {
+ if ctx.Org == nil {
+ ctx.Org = &Organization{}
+ }
+ ctx.Org.Organization = (*organization.Organization)(ctx.ContextUser)
+ } else {
+ // ContextUser is an individual User
return
}
+
org := ctx.Org.Organization
// Handle Visibility
@@ -156,6 +161,7 @@ func HandleOrgAssignment(ctx *Context, args ...bool) {
}
ctx.Data["IsOrganizationOwner"] = ctx.Org.IsOwner
ctx.Data["IsOrganizationMember"] = ctx.Org.IsMember
+ ctx.Data["IsProjectEnabled"] = true
ctx.Data["IsPackageEnabled"] = setting.Packages.Enabled
ctx.Data["IsRepoIndexerEnabled"] = setting.Indexer.RepoIndexerEnabled
ctx.Data["IsPublicMember"] = func(uid int64) bool {
@@ -231,6 +237,10 @@ func HandleOrgAssignment(ctx *Context, args ...bool) {
return
}
}
+
+ ctx.Data["CanReadProjects"] = ctx.Org.CanReadUnit(ctx, unit.TypeProjects)
+ ctx.Data["CanReadPackages"] = ctx.Org.CanReadUnit(ctx, unit.TypePackages)
+ ctx.Data["CanReadCode"] = ctx.Org.CanReadUnit(ctx, unit.TypeCode)
}
// OrgAssignment returns a middleware to handle organization assignment
diff --git a/modules/csv/csv_test.go b/modules/csv/csv_test.go
index c627597fa..6b91a81fc 100644
--- a/modules/csv/csv_test.go
+++ b/modules/csv/csv_test.go
@@ -11,6 +11,7 @@ import (
"strings"
"testing"
+ "code.gitea.io/gitea/modules/git"
"code.gitea.io/gitea/modules/markup"
"github.com/stretchr/testify/assert"
@@ -229,7 +230,10 @@ John Doe john@doe.com This,note,had,a,lot,of,commas,to,test,delimiters`,
}
for n, c := range cases {
- delimiter := determineDelimiter(&markup.RenderContext{RelativePath: c.filename}, []byte(decodeSlashes(t, c.csv)))
+ delimiter := determineDelimiter(&markup.RenderContext{
+ Ctx: git.DefaultContext,
+ RelativePath: c.filename,
+ }, []byte(decodeSlashes(t, c.csv)))
assert.EqualValues(t, c.expectedDelimiter, delimiter, "case %d: delimiter should be equal, expected '%c' got '%c'", n, c.expectedDelimiter, delimiter)
}
}
diff --git a/modules/doctor/dbconsistency.go b/modules/doctor/dbconsistency.go
index bb560ac6a..541fc736f 100644
--- a/modules/doctor/dbconsistency.go
+++ b/modules/doctor/dbconsistency.go
@@ -155,7 +155,7 @@ func checkDBConsistency(ctx context.Context, logger log.Logger, autofix bool) er
// TODO: function to recalc all counters
- if setting.Database.UsePostgreSQL {
+ if setting.Database.Type.IsPostgreSQL() {
consistencyChecks = append(consistencyChecks, consistencyCheck{
Name: "Sequence values",
Counter: db.CountBadSequences,
diff --git a/modules/git/command.go b/modules/git/command.go
index 0bc810311..9a65279a8 100644
--- a/modules/git/command.go
+++ b/modules/git/command.go
@@ -179,7 +179,7 @@ func (c *Command) AddDashesAndList(list ...string) *Command {
}
// ToTrustedCmdArgs converts a list of strings (trusted as argument) to TrustedCmdArgs
-// In most cases, it shouldn't be used. Use AddXxx function instead
+// In most cases, it shouldn't be used. Use NewCommand().AddXxx() function instead
func ToTrustedCmdArgs(args []string) TrustedCmdArgs {
ret := make(TrustedCmdArgs, len(args))
for i, arg := range args {
diff --git a/modules/git/commit.go b/modules/git/commit.go
index 4a55645d3..6e8fcb3e0 100644
--- a/modules/git/commit.go
+++ b/modules/git/commit.go
@@ -218,6 +218,19 @@ func (c *Commit) HasPreviousCommit(commitHash SHA1) (bool, error) {
return false, err
}
+// IsForcePush returns true if a push from oldCommitHash to this is a force push
+func (c *Commit) IsForcePush(oldCommitID string) (bool, error) {
+ if oldCommitID == EmptySHA {
+ return false, nil
+ }
+ oldCommit, err := c.repo.GetCommit(oldCommitID)
+ if err != nil {
+ return false, err
+ }
+ hasPreviousCommit, err := c.HasPreviousCommit(oldCommit.ID)
+ return !hasPreviousCommit, err
+}
+
// CommitsBeforeLimit returns num commits before current revision
func (c *Commit) CommitsBeforeLimit(num int) ([]*Commit, error) {
return c.repo.getCommitsBeforeLimit(c.ID, num)
diff --git a/modules/git/git.go b/modules/git/git.go
index 2feb242ac..24cfea8c7 100644
--- a/modules/git/git.go
+++ b/modules/git/git.go
@@ -312,7 +312,7 @@ func CheckGitVersionAtLeast(atLeast string) error {
}
func configSet(key, value string) error {
- stdout, _, err := NewCommand(DefaultContext, "config", "--get").AddDynamicArguments(key).RunStdString(nil)
+ stdout, _, err := NewCommand(DefaultContext, "config", "--global", "--get").AddDynamicArguments(key).RunStdString(nil)
if err != nil && !err.IsExitCode(1) {
return fmt.Errorf("failed to get git config %s, err: %w", key, err)
}
@@ -331,7 +331,7 @@ func configSet(key, value string) error {
}
func configSetNonExist(key, value string) error {
- _, _, err := NewCommand(DefaultContext, "config", "--get").AddDynamicArguments(key).RunStdString(nil)
+ _, _, err := NewCommand(DefaultContext, "config", "--global", "--get").AddDynamicArguments(key).RunStdString(nil)
if err == nil {
// already exist
return nil
@@ -349,7 +349,7 @@ func configSetNonExist(key, value string) error {
}
func configAddNonExist(key, value string) error {
- _, _, err := NewCommand(DefaultContext, "config", "--get").AddDynamicArguments(key, regexp.QuoteMeta(value)).RunStdString(nil)
+ _, _, err := NewCommand(DefaultContext, "config", "--global", "--get").AddDynamicArguments(key, regexp.QuoteMeta(value)).RunStdString(nil)
if err == nil {
// already exist
return nil
@@ -366,7 +366,7 @@ func configAddNonExist(key, value string) error {
}
func configUnsetAll(key, value string) error {
- _, _, err := NewCommand(DefaultContext, "config", "--get").AddDynamicArguments(key).RunStdString(nil)
+ _, _, err := NewCommand(DefaultContext, "config", "--global", "--get").AddDynamicArguments(key).RunStdString(nil)
if err == nil {
// exist, need to remove
_, _, err = NewCommand(DefaultContext, "config", "--global", "--unset-all").AddDynamicArguments(key, regexp.QuoteMeta(value)).RunStdString(nil)
diff --git a/modules/git/pipeline/revlist.go b/modules/git/pipeline/revlist.go
index 09bb2c8b3..d88ebe78e 100644
--- a/modules/git/pipeline/revlist.go
+++ b/modules/git/pipeline/revlist.go
@@ -42,7 +42,10 @@ func RevListObjects(ctx context.Context, revListWriter *io.PipeWriter, wg *sync.
defer revListWriter.Close()
stderr := new(bytes.Buffer)
var errbuf strings.Builder
- cmd := git.NewCommand(ctx, "rev-list", "--objects").AddDynamicArguments(headSHA).AddArguments("--not").AddDynamicArguments(baseSHA)
+ cmd := git.NewCommand(ctx, "rev-list", "--objects").AddDynamicArguments(headSHA)
+ if baseSHA != "" {
+ cmd = cmd.AddArguments("--not").AddDynamicArguments(baseSHA)
+ }
if err := cmd.Run(&git.RunOpts{
Dir: tmpBasePath,
Stdout: revListWriter,
diff --git a/modules/git/repo_commit.go b/modules/git/repo_commit.go
index a62e0670f..0e1b00ce0 100644
--- a/modules/git/repo_commit.go
+++ b/modules/git/repo_commit.go
@@ -323,6 +323,27 @@ func (repo *Repository) CommitsBetweenLimit(last, before *Commit, limit, skip in
return repo.parsePrettyFormatLogToList(bytes.TrimSpace(stdout))
}
+// CommitsBetweenNotBase returns a list that contains commits between [before, last), excluding commits in baseBranch.
+// If before is detached (removed by reset + push) it is not included.
+func (repo *Repository) CommitsBetweenNotBase(last, before *Commit, baseBranch string) ([]*Commit, error) {
+ var stdout []byte
+ var err error
+ if before == nil {
+ stdout, _, err = NewCommand(repo.Ctx, "rev-list").AddDynamicArguments(last.ID.String()).AddOptionValues("--not", baseBranch).RunStdBytes(&RunOpts{Dir: repo.Path})
+ } else {
+ stdout, _, err = NewCommand(repo.Ctx, "rev-list").AddDynamicArguments(before.ID.String()+".."+last.ID.String()).AddOptionValues("--not", baseBranch).RunStdBytes(&RunOpts{Dir: repo.Path})
+ if err != nil && strings.Contains(err.Error(), "no merge base") {
+ // future versions of git >= 2.28 are likely to return an error if before and last have become unrelated.
+ // previously it would return the results of git rev-list before last so let's try that...
+ stdout, _, err = NewCommand(repo.Ctx, "rev-list").AddDynamicArguments(before.ID.String(), last.ID.String()).AddOptionValues("--not", baseBranch).RunStdBytes(&RunOpts{Dir: repo.Path})
+ }
+ }
+ if err != nil {
+ return nil, err
+ }
+ return repo.parsePrettyFormatLogToList(bytes.TrimSpace(stdout))
+}
+
// CommitsBetweenIDs return commits between twoe commits
func (repo *Repository) CommitsBetweenIDs(last, before string) ([]*Commit, error) {
lastCommit, err := repo.GetCommit(last)
diff --git a/modules/git/repo_commit_gogit.go b/modules/git/repo_commit_gogit.go
index 72de158e6..ce0af9361 100644
--- a/modules/git/repo_commit_gogit.go
+++ b/modules/git/repo_commit_gogit.go
@@ -7,7 +7,6 @@
package git
import (
- "fmt"
"strings"
"github.com/go-git/go-git/v5/plumbing"
@@ -67,38 +66,6 @@ func (repo *Repository) IsCommitExist(name string) bool {
return err == nil
}
-func convertPGPSignatureForTag(t *object.Tag) *CommitGPGSignature {
- if t.PGPSignature == "" {
- return nil
- }
-
- var w strings.Builder
- var err error
-
- if _, err = fmt.Fprintf(&w,
- "object %s\ntype %s\ntag %s\ntagger ",
- t.Target.String(), t.TargetType.Bytes(), t.Name); err != nil {
- return nil
- }
-
- if err = t.Tagger.Encode(&w); err != nil {
- return nil
- }
-
- if _, err = fmt.Fprintf(&w, "\n\n"); err != nil {
- return nil
- }
-
- if _, err = fmt.Fprintf(&w, t.Message); err != nil {
- return nil
- }
-
- return &CommitGPGSignature{
- Signature: t.PGPSignature,
- Payload: strings.TrimSpace(w.String()) + "\n",
- }
-}
-
func (repo *Repository) getCommit(id SHA1) (*Commit, error) {
var tagObject *object.Tag
@@ -122,12 +89,6 @@ func (repo *Repository) getCommit(id SHA1) (*Commit, error) {
commit := convertCommit(gogitCommit)
commit.repo = repo
- if tagObject != nil {
- commit.CommitMessage = strings.TrimSpace(tagObject.Message)
- commit.Author = &tagObject.Tagger
- commit.Signature = convertPGPSignatureForTag(tagObject)
- }
-
tree, err := gogitCommit.Tree()
if err != nil {
return nil, err
diff --git a/modules/git/repo_commit_nogogit.go b/modules/git/repo_commit_nogogit.go
index 7373d01c8..d5eb72310 100644
--- a/modules/git/repo_commit_nogogit.go
+++ b/modules/git/repo_commit_nogogit.go
@@ -107,10 +107,6 @@ func (repo *Repository) getCommitFromBatchReader(rd *bufio.Reader, id SHA1) (*Co
return nil, err
}
- commit.CommitMessage = strings.TrimSpace(tag.Message)
- commit.Author = tag.Tagger
- commit.Signature = tag.Signature
-
return commit, nil
case "commit":
commit, err := CommitFromReader(repo, id, io.LimitReader(rd, size))
diff --git a/modules/git/repo_commit_test.go b/modules/git/repo_commit_test.go
index af8c0592f..729fb0ba1 100644
--- a/modules/git/repo_commit_test.go
+++ b/modules/git/repo_commit_test.go
@@ -43,12 +43,13 @@ func TestGetTagCommitWithSignature(t *testing.T) {
assert.NoError(t, err)
defer bareRepo1.Close()
- commit, err := bareRepo1.GetCommit("3ad28a9149a2864384548f3d17ed7f38014c9e8a")
+ // both the tag and the commit are signed here, this validates only the commit signature
+ commit, err := bareRepo1.GetCommit("28b55526e7100924d864dd89e35c1ea62e7a5a32")
assert.NoError(t, err)
assert.NotNil(t, commit)
assert.NotNil(t, commit.Signature)
// test that signature is not in message
- assert.Equal(t, "tag", commit.CommitMessage)
+ assert.Equal(t, "signed-commit\n", commit.CommitMessage)
}
func TestGetCommitWithBadCommitID(t *testing.T) {
diff --git a/modules/git/repo_compare.go b/modules/git/repo_compare.go
index 9a4d66f2f..439455e3c 100644
--- a/modules/git/repo_compare.go
+++ b/modules/git/repo_compare.go
@@ -277,11 +277,18 @@ func (repo *Repository) GetPatch(base, head string, w io.Writer) error {
// GetFilesChangedBetween returns a list of all files that have been changed between the given commits
func (repo *Repository) GetFilesChangedBetween(base, head string) ([]string, error) {
- stdout, _, err := NewCommand(repo.Ctx, "diff", "--name-only").AddDynamicArguments(base + ".." + head).RunStdString(&RunOpts{Dir: repo.Path})
+ stdout, _, err := NewCommand(repo.Ctx, "diff", "--name-only", "-z").AddDynamicArguments(base + ".." + head).RunStdString(&RunOpts{Dir: repo.Path})
if err != nil {
return nil, err
}
- return strings.Split(stdout, "\n"), err
+ split := strings.Split(stdout, "\000")
+
+ // Because Git will always emit filenames with a terminal NUL ignore the last entry in the split - which will always be empty.
+ if len(split) > 0 {
+ split = split[:len(split)-1]
+ }
+
+ return split, err
}
// GetDiffFromMergeBase generates and return patch data from merge base to head
diff --git a/modules/git/repo_ref_test.go b/modules/git/repo_ref_test.go
index 776d7ce3e..c08ea1276 100644
--- a/modules/git/repo_ref_test.go
+++ b/modules/git/repo_ref_test.go
@@ -19,13 +19,14 @@ func TestRepository_GetRefs(t *testing.T) {
refs, err := bareRepo1.GetRefs()
assert.NoError(t, err)
- assert.Len(t, refs, 5)
+ assert.Len(t, refs, 6)
expectedRefs := []string{
BranchPrefix + "branch1",
BranchPrefix + "branch2",
BranchPrefix + "master",
TagPrefix + "test",
+ TagPrefix + "signed-tag",
NotesRef,
}
@@ -43,9 +44,12 @@ func TestRepository_GetRefsFiltered(t *testing.T) {
refs, err := bareRepo1.GetRefsFiltered(TagPrefix)
assert.NoError(t, err)
- if assert.Len(t, refs, 1) {
- assert.Equal(t, TagPrefix+"test", refs[0].Name)
+ if assert.Len(t, refs, 2) {
+ assert.Equal(t, TagPrefix+"signed-tag", refs[0].Name)
assert.Equal(t, "tag", refs[0].Type)
- assert.Equal(t, "3ad28a9149a2864384548f3d17ed7f38014c9e8a", refs[0].Object.String())
+ assert.Equal(t, "36f97d9a96457e2bab511db30fe2db03893ebc64", refs[0].Object.String())
+ assert.Equal(t, TagPrefix+"test", refs[1].Name)
+ assert.Equal(t, "tag", refs[1].Type)
+ assert.Equal(t, "3ad28a9149a2864384548f3d17ed7f38014c9e8a", refs[1].Object.String())
}
}
diff --git a/modules/git/repo_stats_test.go b/modules/git/repo_stats_test.go
index 668ed6799..3d032385e 100644
--- a/modules/git/repo_stats_test.go
+++ b/modules/git/repo_stats_test.go
@@ -24,9 +24,9 @@ func TestRepository_GetCodeActivityStats(t *testing.T) {
assert.NoError(t, err)
assert.NotNil(t, code)
- assert.EqualValues(t, 9, code.CommitCount)
+ assert.EqualValues(t, 10, code.CommitCount)
assert.EqualValues(t, 3, code.AuthorCount)
- assert.EqualValues(t, 9, code.CommitCountInAllBranches)
+ assert.EqualValues(t, 10, code.CommitCountInAllBranches)
assert.EqualValues(t, 10, code.Additions)
assert.EqualValues(t, 1, code.Deletions)
assert.Len(t, code.Authors, 3)
diff --git a/modules/git/repo_tag_test.go b/modules/git/repo_tag_test.go
index 589349a72..8ccfec3eb 100644
--- a/modules/git/repo_tag_test.go
+++ b/modules/git/repo_tag_test.go
@@ -25,11 +25,14 @@ func TestRepository_GetTags(t *testing.T) {
assert.NoError(t, err)
return
}
- assert.Len(t, tags, 1)
+ assert.Len(t, tags, 2)
assert.Equal(t, len(tags), total)
- assert.EqualValues(t, "test", tags[0].Name)
- assert.EqualValues(t, "3ad28a9149a2864384548f3d17ed7f38014c9e8a", tags[0].ID.String())
+ assert.EqualValues(t, "signed-tag", tags[0].Name)
+ assert.EqualValues(t, "36f97d9a96457e2bab511db30fe2db03893ebc64", tags[0].ID.String())
assert.EqualValues(t, "tag", tags[0].Type)
+ assert.EqualValues(t, "test", tags[1].Name)
+ assert.EqualValues(t, "3ad28a9149a2864384548f3d17ed7f38014c9e8a", tags[1].ID.String())
+ assert.EqualValues(t, "tag", tags[1].Type)
}
func TestRepository_GetTag(t *testing.T) {
diff --git a/modules/git/repo_test.go b/modules/git/repo_test.go
index 2a3914819..044b9d406 100644
--- a/modules/git/repo_test.go
+++ b/modules/git/repo_test.go
@@ -14,10 +14,10 @@ func TestGetLatestCommitTime(t *testing.T) {
bareRepo1Path := filepath.Join(testReposDir, "repo1_bare")
lct, err := GetLatestCommitTime(DefaultContext, bareRepo1Path)
assert.NoError(t, err)
- // Time is Sun Jul 21 22:43:13 2019 +0200
+ // Time is Sun Nov 13 16:40:14 2022 +0100
// which is the time of commit
- // feaf4ba6bc635fec442f46ddd4512416ec43c2c2 (refs/heads/master)
- assert.EqualValues(t, 1563741793, lct.Unix())
+ // ce064814f4a0d337b333e646ece456cd39fab612 (refs/heads/master)
+ assert.EqualValues(t, 1668354014, lct.Unix())
}
func TestRepoIsEmpty(t *testing.T) {
diff --git a/modules/git/tests/repos/repo1_bare/index b/modules/git/tests/repos/repo1_bare/index
new file mode 100644
index 000000000..65d675154
--- /dev/null
+++ b/modules/git/tests/repos/repo1_bare/index
Binary files differ
diff --git a/modules/git/tests/repos/repo1_bare/logs/HEAD b/modules/git/tests/repos/repo1_bare/logs/HEAD
index cef4ca2dc..46da5fe0b 100644
--- a/modules/git/tests/repos/repo1_bare/logs/HEAD
+++ b/modules/git/tests/repos/repo1_bare/logs/HEAD
@@ -1 +1,2 @@
37991dec2c8e592043f47155ce4808d4580f9123 feaf4ba6bc635fec442f46ddd4512416ec43c2c2 silverwind <me@silverwind.io> 1563741799 +0200 push
+feaf4ba6bc635fec442f46ddd4512416ec43c2c2 ce064814f4a0d337b333e646ece456cd39fab612 silverwind <me@silverwind.io> 1668354026 +0100 push
diff --git a/modules/git/tests/repos/repo1_bare/logs/refs/heads/master b/modules/git/tests/repos/repo1_bare/logs/refs/heads/master
index cef4ca2dc..46da5fe0b 100644
--- a/modules/git/tests/repos/repo1_bare/logs/refs/heads/master
+++ b/modules/git/tests/repos/repo1_bare/logs/refs/heads/master
@@ -1 +1,2 @@
37991dec2c8e592043f47155ce4808d4580f9123 feaf4ba6bc635fec442f46ddd4512416ec43c2c2 silverwind <me@silverwind.io> 1563741799 +0200 push
+feaf4ba6bc635fec442f46ddd4512416ec43c2c2 ce064814f4a0d337b333e646ece456cd39fab612 silverwind <me@silverwind.io> 1668354026 +0100 push
diff --git a/modules/git/tests/repos/repo1_bare/objects/1c/91d130dc5fb75fd2d9f586a058650889cfe7fb b/modules/git/tests/repos/repo1_bare/objects/1c/91d130dc5fb75fd2d9f586a058650889cfe7fb
new file mode 100644
index 000000000..fb50b65f9
--- /dev/null
+++ b/modules/git/tests/repos/repo1_bare/objects/1c/91d130dc5fb75fd2d9f586a058650889cfe7fb
Binary files differ
diff --git a/modules/git/tests/repos/repo1_bare/objects/28/b55526e7100924d864dd89e35c1ea62e7a5a32 b/modules/git/tests/repos/repo1_bare/objects/28/b55526e7100924d864dd89e35c1ea62e7a5a32
new file mode 100644
index 000000000..7779599a0
--- /dev/null
+++ b/modules/git/tests/repos/repo1_bare/objects/28/b55526e7100924d864dd89e35c1ea62e7a5a32
Binary files differ
diff --git a/modules/git/tests/repos/repo1_bare/objects/36/f97d9a96457e2bab511db30fe2db03893ebc64 b/modules/git/tests/repos/repo1_bare/objects/36/f97d9a96457e2bab511db30fe2db03893ebc64
new file mode 100644
index 000000000..c96b84390
--- /dev/null
+++ b/modules/git/tests/repos/repo1_bare/objects/36/f97d9a96457e2bab511db30fe2db03893ebc64
Binary files differ
diff --git a/modules/git/tests/repos/repo1_bare/objects/4b/825dc642cb6eb9a060e54bf8d69288fbee4904 b/modules/git/tests/repos/repo1_bare/objects/4b/825dc642cb6eb9a060e54bf8d69288fbee4904
new file mode 100644
index 000000000..adf64119a
--- /dev/null
+++ b/modules/git/tests/repos/repo1_bare/objects/4b/825dc642cb6eb9a060e54bf8d69288fbee4904
Binary files differ
diff --git a/modules/git/tests/repos/repo1_bare/objects/93/3305878a3c9ad485c29b87fb662a73a9675c4b b/modules/git/tests/repos/repo1_bare/objects/93/3305878a3c9ad485c29b87fb662a73a9675c4b
new file mode 100644
index 000000000..e198e7658
--- /dev/null
+++ b/modules/git/tests/repos/repo1_bare/objects/93/3305878a3c9ad485c29b87fb662a73a9675c4b
Binary files differ
diff --git a/modules/git/tests/repos/repo1_bare/objects/ce/064814f4a0d337b333e646ece456cd39fab612 b/modules/git/tests/repos/repo1_bare/objects/ce/064814f4a0d337b333e646ece456cd39fab612
new file mode 100644
index 000000000..93f1525e5
--- /dev/null
+++ b/modules/git/tests/repos/repo1_bare/objects/ce/064814f4a0d337b333e646ece456cd39fab612
Binary files differ
diff --git a/modules/git/tests/repos/repo1_bare/objects/cf/8b0b492a950b358a7ce7f9d01b18aef48a6b2d b/modules/git/tests/repos/repo1_bare/objects/cf/8b0b492a950b358a7ce7f9d01b18aef48a6b2d
new file mode 100644
index 000000000..1152b25bb
--- /dev/null
+++ b/modules/git/tests/repos/repo1_bare/objects/cf/8b0b492a950b358a7ce7f9d01b18aef48a6b2d
Binary files differ
diff --git a/modules/git/tests/repos/repo1_bare/refs/heads/master b/modules/git/tests/repos/repo1_bare/refs/heads/master
index c5e92eb22..9b0de2281 100644
--- a/modules/git/tests/repos/repo1_bare/refs/heads/master
+++ b/modules/git/tests/repos/repo1_bare/refs/heads/master
@@ -1 +1 @@
-feaf4ba6bc635fec442f46ddd4512416ec43c2c2
+ce064814f4a0d337b333e646ece456cd39fab612
diff --git a/modules/git/tests/repos/repo1_bare/refs/tags/signed-tag b/modules/git/tests/repos/repo1_bare/refs/tags/signed-tag
new file mode 100644
index 000000000..3998a6850
--- /dev/null
+++ b/modules/git/tests/repos/repo1_bare/refs/tags/signed-tag
@@ -0,0 +1 @@
+36f97d9a96457e2bab511db30fe2db03893ebc64
diff --git a/modules/httpcache/httpcache.go b/modules/httpcache/httpcache.go
index f0caa30eb..46e0152ef 100644
--- a/modules/httpcache/httpcache.go
+++ b/modules/httpcache/httpcache.go
@@ -15,8 +15,8 @@ import (
"code.gitea.io/gitea/modules/setting"
)
-// AddCacheControlToHeader adds suitable cache-control headers to response
-func AddCacheControlToHeader(h http.Header, maxAge time.Duration, additionalDirectives ...string) {
+// SetCacheControlInHeader sets suitable cache-control headers in the response
+func SetCacheControlInHeader(h http.Header, maxAge time.Duration, additionalDirectives ...string) {
directives := make([]string, 0, 2+len(additionalDirectives))
// "max-age=0 + must-revalidate" (aka "no-cache") is preferred instead of "no-store"
@@ -31,7 +31,7 @@ func AddCacheControlToHeader(h http.Header, maxAge time.Duration, additionalDire
directives = append(directives, "max-age=0", "private", "must-revalidate")
// to remind users they are using non-prod setting.
- h.Add("X-Gitea-Debug", "RUN_MODE="+setting.RunMode)
+ h.Set("X-Gitea-Debug", "RUN_MODE="+setting.RunMode)
}
h.Set("Cache-Control", strings.Join(append(directives, additionalDirectives...), ", "))
@@ -50,7 +50,7 @@ func HandleTimeCache(req *http.Request, w http.ResponseWriter, fi os.FileInfo) (
// HandleGenericTimeCache handles time-based caching for a HTTP request
func HandleGenericTimeCache(req *http.Request, w http.ResponseWriter, lastModified time.Time) (handled bool) {
- AddCacheControlToHeader(w.Header(), setting.StaticCacheTime)
+ SetCacheControlInHeader(w.Header(), setting.StaticCacheTime)
ifModifiedSince := req.Header.Get("If-Modified-Since")
if ifModifiedSince != "" {
@@ -81,7 +81,7 @@ func HandleGenericETagCache(req *http.Request, w http.ResponseWriter, etag strin
return true
}
}
- AddCacheControlToHeader(w.Header(), setting.StaticCacheTime)
+ SetCacheControlInHeader(w.Header(), setting.StaticCacheTime)
return false
}
@@ -125,6 +125,6 @@ func HandleGenericETagTimeCache(req *http.Request, w http.ResponseWriter, etag s
}
}
}
- AddCacheControlToHeader(w.Header(), setting.StaticCacheTime)
+ SetCacheControlInHeader(w.Header(), setting.StaticCacheTime)
return false
}
diff --git a/modules/label/label.go b/modules/label/label.go
new file mode 100644
index 000000000..d3ef0e1dc
--- /dev/null
+++ b/modules/label/label.go
@@ -0,0 +1,46 @@
+// Copyright 2023 The Gitea Authors. All rights reserved.
+// SPDX-License-Identifier: MIT
+
+package label
+
+import (
+ "fmt"
+ "regexp"
+ "strings"
+)
+
+// colorPattern is a regexp which can validate label color
+var colorPattern = regexp.MustCompile("^#?(?:[0-9a-fA-F]{6}|[0-9a-fA-F]{3})$")
+
+// Label represents label information loaded from template
+type Label struct {
+ Name string `yaml:"name"`
+ Color string `yaml:"color"`
+ Description string `yaml:"description,omitempty"`
+ Exclusive bool `yaml:"exclusive,omitempty"`
+}
+
+// NormalizeColor normalizes a color string to a 6-character hex code
+func NormalizeColor(color string) (string, error) {
+ // normalize case
+ color = strings.TrimSpace(strings.ToLower(color))
+
+ // add leading hash
+ if len(color) == 6 || len(color) == 3 {
+ color = "#" + color
+ }
+
+ if !colorPattern.MatchString(color) {
+ return "", fmt.Errorf("bad color code: %s", color)
+ }
+
+ // convert 3-character shorthand into 6-character version
+ if len(color) == 4 {
+ r := color[1]
+ g := color[2]
+ b := color[3]
+ color = fmt.Sprintf("#%c%c%c%c%c%c", r, r, g, g, b, b)
+ }
+
+ return color, nil
+}
diff --git a/modules/label/parser.go b/modules/label/parser.go
new file mode 100644
index 000000000..55bf570de
--- /dev/null
+++ b/modules/label/parser.go
@@ -0,0 +1,126 @@
+// Copyright 2023 The Gitea Authors. All rights reserved.
+// SPDX-License-Identifier: MIT
+
+package label
+
+import (
+ "errors"
+ "fmt"
+ "strings"
+
+ "code.gitea.io/gitea/modules/options"
+
+ "gopkg.in/yaml.v3"
+)
+
+type labelFile struct {
+ Labels []*Label `yaml:"labels"`
+}
+
+// ErrTemplateLoad represents a "ErrTemplateLoad" kind of error.
+type ErrTemplateLoad struct {
+ TemplateFile string
+ OriginalError error
+}
+
+// IsErrTemplateLoad checks if an error is a ErrTemplateLoad.
+func IsErrTemplateLoad(err error) bool {
+ _, ok := err.(ErrTemplateLoad)
+ return ok
+}
+
+func (err ErrTemplateLoad) Error() string {
+ return fmt.Sprintf("Failed to load label template file '%s': %v", err.TemplateFile, err.OriginalError)
+}
+
+// GetTemplateFile loads the label template file by given name,
+// then parses and returns a list of name-color pairs and optionally description.
+func GetTemplateFile(name string) ([]*Label, error) {
+ data, err := options.Labels(name + ".yaml")
+ if err == nil && len(data) > 0 {
+ return parseYamlFormat(name+".yaml", data)
+ }
+
+ data, err = options.Labels(name + ".yml")
+ if err == nil && len(data) > 0 {
+ return parseYamlFormat(name+".yml", data)
+ }
+
+ data, err = options.Labels(name)
+ if err != nil {
+ return nil, ErrTemplateLoad{name, fmt.Errorf("GetRepoInitFile: %w", err)}
+ }
+
+ return parseLegacyFormat(name, data)
+}
+
+func parseYamlFormat(name string, data []byte) ([]*Label, error) {
+ lf := &labelFile{}
+
+ if err := yaml.Unmarshal(data, lf); err != nil {
+ return nil, err
+ }
+
+ // Validate label data and fix colors
+ for _, l := range lf.Labels {
+ l.Color = strings.TrimSpace(l.Color)
+ if len(l.Name) == 0 || len(l.Color) == 0 {
+ return nil, ErrTemplateLoad{name, errors.New("label name and color are required fields")}
+ }
+ color, err := NormalizeColor(l.Color)
+ if err != nil {
+ return nil, ErrTemplateLoad{name, fmt.Errorf("bad HTML color code '%s' in label: %s", l.Color, l.Name)}
+ }
+ l.Color = color
+ }
+
+ return lf.Labels, nil
+}
+
+func parseLegacyFormat(name string, data []byte) ([]*Label, error) {
+ lines := strings.Split(string(data), "\n")
+ list := make([]*Label, 0, len(lines))
+ for i := 0; i < len(lines); i++ {
+ line := strings.TrimSpace(lines[i])
+ if len(line) == 0 {
+ continue
+ }
+
+ parts, description, _ := strings.Cut(line, ";")
+
+ color, name, ok := strings.Cut(parts, " ")
+ if !ok {
+ return nil, ErrTemplateLoad{name, fmt.Errorf("line is malformed: %s", line)}
+ }
+
+ color, err := NormalizeColor(color)
+ if err != nil {
+ return nil, ErrTemplateLoad{name, fmt.Errorf("bad HTML color code '%s' in line: %s", color, line)}
+ }
+
+ list = append(list, &Label{
+ Name: strings.TrimSpace(name),
+ Color: color,
+ Description: strings.TrimSpace(description),
+ })
+ }
+
+ return list, nil
+}
+
+// LoadFormatted loads the labels' list of a template file as a string separated by comma
+func LoadFormatted(name string) (string, error) {
+ var buf strings.Builder
+ list, err := GetTemplateFile(name)
+ if err != nil {
+ return "", err
+ }
+
+ for i := 0; i < len(list); i++ {
+ if i > 0 {
+ buf.WriteString(", ")
+ }
+ buf.WriteString(list[i].Name)
+ }
+ return buf.String(), nil
+}
diff --git a/modules/label/parser_test.go b/modules/label/parser_test.go
new file mode 100644
index 000000000..5c8042f66
--- /dev/null
+++ b/modules/label/parser_test.go
@@ -0,0 +1,72 @@
+// Copyright 2023 The Gitea Authors. All rights reserved.
+// SPDX-License-Identifier: MIT
+
+package label
+
+import (
+ "testing"
+
+ "github.com/stretchr/testify/assert"
+ "github.com/stretchr/testify/require"
+)
+
+func TestYamlParser(t *testing.T) {
+ data := []byte(`labels:
+ - name: priority/low
+ exclusive: true
+ color: "#0000ee"
+ description: "Low priority"
+ - name: priority/medium
+ exclusive: true
+ color: "0e0"
+ description: "Medium priority"
+ - name: priority/high
+ exclusive: true
+ color: "#ee0000"
+ description: "High priority"
+ - name: type/bug
+ color: "#f00"
+ description: "Bug"`)
+
+ labels, err := parseYamlFormat("test", data)
+ require.NoError(t, err)
+ require.Len(t, labels, 4)
+ assert.Equal(t, "priority/low", labels[0].Name)
+ assert.True(t, labels[0].Exclusive)
+ assert.Equal(t, "#0000ee", labels[0].Color)
+ assert.Equal(t, "Low priority", labels[0].Description)
+ assert.Equal(t, "priority/medium", labels[1].Name)
+ assert.True(t, labels[1].Exclusive)
+ assert.Equal(t, "#00ee00", labels[1].Color)
+ assert.Equal(t, "Medium priority", labels[1].Description)
+ assert.Equal(t, "priority/high", labels[2].Name)
+ assert.True(t, labels[2].Exclusive)
+ assert.Equal(t, "#ee0000", labels[2].Color)
+ assert.Equal(t, "High priority", labels[2].Description)
+ assert.Equal(t, "type/bug", labels[3].Name)
+ assert.False(t, labels[3].Exclusive)
+ assert.Equal(t, "#ff0000", labels[3].Color)
+ assert.Equal(t, "Bug", labels[3].Description)
+}
+
+func TestLegacyParser(t *testing.T) {
+ data := []byte(`#ee0701 bug ; Something is not working
+#cccccc duplicate ; This issue or pull request already exists
+#84b6eb enhancement`)
+
+ labels, err := parseLegacyFormat("test", data)
+ require.NoError(t, err)
+ require.Len(t, labels, 3)
+ assert.Equal(t, "bug", labels[0].Name)
+ assert.False(t, labels[0].Exclusive)
+ assert.Equal(t, "#ee0701", labels[0].Color)
+ assert.Equal(t, "Something is not working", labels[0].Description)
+ assert.Equal(t, "duplicate", labels[1].Name)
+ assert.False(t, labels[1].Exclusive)
+ assert.Equal(t, "#cccccc", labels[1].Color)
+ assert.Equal(t, "This issue or pull request already exists", labels[1].Description)
+ assert.Equal(t, "enhancement", labels[2].Name)
+ assert.False(t, labels[2].Exclusive)
+ assert.Equal(t, "#84b6eb", labels[2].Color)
+ assert.Empty(t, labels[2].Description)
+}
diff --git a/modules/markup/console/console_test.go b/modules/markup/console/console_test.go
index 506f86194..2337d91ac 100644
--- a/modules/markup/console/console_test.go
+++ b/modules/markup/console/console_test.go
@@ -7,6 +7,7 @@ import (
"strings"
"testing"
+ "code.gitea.io/gitea/modules/git"
"code.gitea.io/gitea/modules/markup"
"github.com/stretchr/testify/assert"
@@ -23,7 +24,8 @@ func TestRenderConsole(t *testing.T) {
canRender := render.CanRender("test", strings.NewReader(k))
assert.True(t, canRender)
- err := render.Render(&markup.RenderContext{}, strings.NewReader(k), &buf)
+ err := render.Render(&markup.RenderContext{Ctx: git.DefaultContext},
+ strings.NewReader(k), &buf)
assert.NoError(t, err)
assert.EqualValues(t, v, buf.String())
}
diff --git a/modules/markup/csv/csv_test.go b/modules/markup/csv/csv_test.go
index b9f5769be..8c07184b2 100644
--- a/modules/markup/csv/csv_test.go
+++ b/modules/markup/csv/csv_test.go
@@ -7,6 +7,7 @@ import (
"strings"
"testing"
+ "code.gitea.io/gitea/modules/git"
"code.gitea.io/gitea/modules/markup"
"github.com/stretchr/testify/assert"
@@ -23,7 +24,8 @@ func TestRenderCSV(t *testing.T) {
for k, v := range kases {
var buf strings.Builder
- err := render.Render(&markup.RenderContext{}, strings.NewReader(k), &buf)
+ err := render.Render(&markup.RenderContext{Ctx: git.DefaultContext},
+ strings.NewReader(k), &buf)
assert.NoError(t, err)
assert.EqualValues(t, v, buf.String())
}
diff --git a/modules/markup/html.go b/modules/markup/html.go
index bcb38f99e..76fc54cf4 100644
--- a/modules/markup/html.go
+++ b/modules/markup/html.go
@@ -291,9 +291,10 @@ func RenderDescriptionHTML(
// RenderEmoji for when we want to just process emoji and shortcodes
// in various places it isn't already run through the normal markdown processor
func RenderEmoji(
+ ctx *RenderContext,
content string,
) (string, error) {
- return renderProcessString(&RenderContext{}, emojiProcessors, content)
+ return renderProcessString(ctx, emojiProcessors, content)
}
var (
diff --git a/modules/markup/html_internal_test.go b/modules/markup/html_internal_test.go
index 6746c40d1..a048f1f52 100644
--- a/modules/markup/html_internal_test.go
+++ b/modules/markup/html_internal_test.go
@@ -9,6 +9,7 @@ import (
"strings"
"testing"
+ "code.gitea.io/gitea/modules/git"
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/util"
@@ -70,8 +71,13 @@ var localMetas = map[string]string{
func TestRender_IssueIndexPattern(t *testing.T) {
// numeric: render inputs without valid mentions
test := func(s string) {
- testRenderIssueIndexPattern(t, s, s, &RenderContext{})
- testRenderIssueIndexPattern(t, s, s, &RenderContext{Metas: numericMetas})
+ testRenderIssueIndexPattern(t, s, s, &RenderContext{
+ Ctx: git.DefaultContext,
+ })
+ testRenderIssueIndexPattern(t, s, s, &RenderContext{
+ Ctx: git.DefaultContext,
+ Metas: numericMetas,
+ })
}
// should not render anything when there are no mentions
@@ -119,7 +125,10 @@ func TestRender_IssueIndexPattern2(t *testing.T) {
links[i] = numericIssueLink(util.URLJoin(TestRepoURL, path), "ref-issue", index, marker)
}
expectedNil := fmt.Sprintf(expectedFmt, links...)
- testRenderIssueIndexPattern(t, s, expectedNil, &RenderContext{Metas: localMetas})
+ testRenderIssueIndexPattern(t, s, expectedNil, &RenderContext{
+ Ctx: git.DefaultContext,
+ Metas: localMetas,
+ })
class := "ref-issue"
if isExternal {
@@ -130,7 +139,10 @@ func TestRender_IssueIndexPattern2(t *testing.T) {
links[i] = numericIssueLink(prefix, class, index, marker)
}
expectedNum := fmt.Sprintf(expectedFmt, links...)
- testRenderIssueIndexPattern(t, s, expectedNum, &RenderContext{Metas: numericMetas})
+ testRenderIssueIndexPattern(t, s, expectedNum, &RenderContext{
+ Ctx: git.DefaultContext,
+ Metas: numericMetas,
+ })
}
// should render freestanding mentions
@@ -164,7 +176,10 @@ func TestRender_IssueIndexPattern3(t *testing.T) {
// alphanumeric: render inputs without valid mentions
test := func(s string) {
- testRenderIssueIndexPattern(t, s, s, &RenderContext{Metas: alphanumericMetas})
+ testRenderIssueIndexPattern(t, s, s, &RenderContext{
+ Ctx: git.DefaultContext,
+ Metas: alphanumericMetas,
+ })
}
test("")
test("this is a test")
@@ -194,7 +209,10 @@ func TestRender_IssueIndexPattern4(t *testing.T) {
links[i] = externalIssueLink("https://someurl.com/someUser/someRepo/", "ref-issue ref-external-issue", name)
}
expected := fmt.Sprintf(expectedFmt, links...)
- testRenderIssueIndexPattern(t, s, expected, &RenderContext{Metas: alphanumericMetas})
+ testRenderIssueIndexPattern(t, s, expected, &RenderContext{
+ Ctx: git.DefaultContext,
+ Metas: alphanumericMetas,
+ })
}
test("OTT-1234 test", "%s test", "OTT-1234")
test("test T-12 issue", "test %s issue", "T-12")
@@ -214,7 +232,10 @@ func TestRender_IssueIndexPattern5(t *testing.T) {
}
expected := fmt.Sprintf(expectedFmt, links...)
- testRenderIssueIndexPattern(t, s, expected, &RenderContext{Metas: metas})
+ testRenderIssueIndexPattern(t, s, expected, &RenderContext{
+ Ctx: git.DefaultContext,
+ Metas: metas,
+ })
}
test("abc ISSUE-123 def", "abc %s def",
@@ -235,7 +256,10 @@ func TestRender_IssueIndexPattern5(t *testing.T) {
[]string{"ISSUE-123"},
)
- testRenderIssueIndexPattern(t, "will not match", "will not match", &RenderContext{Metas: regexpMetas})
+ testRenderIssueIndexPattern(t, "will not match", "will not match", &RenderContext{
+ Ctx: git.DefaultContext,
+ Metas: regexpMetas,
+ })
}
func testRenderIssueIndexPattern(t *testing.T, input, expected string, ctx *RenderContext) {
@@ -255,6 +279,7 @@ func TestRender_AutoLink(t *testing.T) {
test := func(input, expected string) {
var buffer strings.Builder
err := PostProcess(&RenderContext{
+ Ctx: git.DefaultContext,
URLPrefix: TestRepoURL,
Metas: localMetas,
}, strings.NewReader(input), &buffer)
@@ -263,6 +288,7 @@ func TestRender_AutoLink(t *testing.T) {
buffer.Reset()
err = PostProcess(&RenderContext{
+ Ctx: git.DefaultContext,
URLPrefix: TestRepoURL,
Metas: localMetas,
IsWiki: true,
@@ -292,6 +318,7 @@ func TestRender_FullIssueURLs(t *testing.T) {
test := func(input, expected string) {
var result strings.Builder
err := postProcess(&RenderContext{
+ Ctx: git.DefaultContext,
URLPrefix: TestRepoURL,
Metas: localMetas,
}, []processor{fullIssuePatternProcessor}, strings.NewReader(input), &result)
diff --git a/modules/markup/html_test.go b/modules/markup/html_test.go
index aea1d9267..f8b84485c 100644
--- a/modules/markup/html_test.go
+++ b/modules/markup/html_test.go
@@ -91,6 +91,7 @@ func TestRender_CrossReferences(t *testing.T) {
test := func(input, expected string) {
buffer, err := RenderString(&RenderContext{
+ Ctx: git.DefaultContext,
RelativePath: "a.md",
URLPrefix: setting.AppSubURL,
Metas: localMetas,
@@ -135,6 +136,7 @@ func TestRender_links(t *testing.T) {
test := func(input, expected string) {
buffer, err := RenderString(&RenderContext{
+ Ctx: git.DefaultContext,
RelativePath: "a.md",
URLPrefix: TestRepoURL,
}, input)
@@ -234,6 +236,7 @@ func TestRender_email(t *testing.T) {
test := func(input, expected string) {
res, err := RenderString(&RenderContext{
+ Ctx: git.DefaultContext,
RelativePath: "a.md",
URLPrefix: TestRepoURL,
}, input)
@@ -292,6 +295,7 @@ func TestRender_emoji(t *testing.T) {
test := func(input, expected string) {
expected = strings.ReplaceAll(expected, "&", "&amp;")
buffer, err := RenderString(&RenderContext{
+ Ctx: git.DefaultContext,
RelativePath: "a.md",
URLPrefix: TestRepoURL,
}, input)
@@ -355,11 +359,13 @@ func TestRender_ShortLinks(t *testing.T) {
test := func(input, expected, expectedWiki string) {
buffer, err := markdown.RenderString(&RenderContext{
+ Ctx: git.DefaultContext,
URLPrefix: tree,
}, input)
assert.NoError(t, err)
assert.Equal(t, strings.TrimSpace(expected), strings.TrimSpace(buffer))
buffer, err = markdown.RenderString(&RenderContext{
+ Ctx: git.DefaultContext,
URLPrefix: TestRepoURL,
Metas: localMetas,
IsWiki: true,
@@ -461,12 +467,14 @@ func TestRender_RelativeImages(t *testing.T) {
test := func(input, expected, expectedWiki string) {
buffer, err := markdown.RenderString(&RenderContext{
+ Ctx: git.DefaultContext,
URLPrefix: tree,
Metas: localMetas,
}, input)
assert.NoError(t, err)
assert.Equal(t, strings.TrimSpace(expected), strings.TrimSpace(buffer))
buffer, err = markdown.RenderString(&RenderContext{
+ Ctx: git.DefaultContext,
URLPrefix: TestRepoURL,
Metas: localMetas,
IsWiki: true,
@@ -501,6 +509,7 @@ func Test_ParseClusterFuzz(t *testing.T) {
var res strings.Builder
err := PostProcess(&RenderContext{
+ Ctx: git.DefaultContext,
URLPrefix: "https://example.com",
Metas: localMetas,
}, strings.NewReader(data), &res)
@@ -511,6 +520,7 @@ func Test_ParseClusterFuzz(t *testing.T) {
res.Reset()
err = PostProcess(&RenderContext{
+ Ctx: git.DefaultContext,
URLPrefix: "https://example.com",
Metas: localMetas,
}, strings.NewReader(data), &res)
@@ -531,6 +541,7 @@ func TestIssue16020(t *testing.T) {
var res strings.Builder
err := PostProcess(&RenderContext{
+ Ctx: git.DefaultContext,
URLPrefix: "https://example.com",
Metas: localMetas,
}, strings.NewReader(data), &res)
@@ -547,6 +558,7 @@ func BenchmarkEmojiPostprocess(b *testing.B) {
for i := 0; i < b.N; i++ {
var res strings.Builder
err := PostProcess(&RenderContext{
+ Ctx: git.DefaultContext,
URLPrefix: "https://example.com",
Metas: localMetas,
}, strings.NewReader(data), &res)
@@ -557,6 +569,7 @@ func BenchmarkEmojiPostprocess(b *testing.B) {
func TestFuzz(t *testing.T) {
s := "t/l/issues/8#/../../a"
renderContext := RenderContext{
+ Ctx: git.DefaultContext,
URLPrefix: "https://example.com/go-gitea/gitea",
Metas: map[string]string{
"user": "go-gitea",
@@ -574,6 +587,7 @@ func TestIssue18471(t *testing.T) {
var res strings.Builder
err := PostProcess(&RenderContext{
+ Ctx: git.DefaultContext,
URLPrefix: "https://example.com",
Metas: localMetas,
}, strings.NewReader(data), &res)
diff --git a/modules/markup/markdown/markdown_test.go b/modules/markup/markdown/markdown_test.go
index bb458a65c..0c7650a5f 100644
--- a/modules/markup/markdown/markdown_test.go
+++ b/modules/markup/markdown/markdown_test.go
@@ -52,12 +52,14 @@ func TestRender_StandardLinks(t *testing.T) {
test := func(input, expected, expectedWiki string) {
buffer, err := RenderString(&markup.RenderContext{
+ Ctx: git.DefaultContext,
URLPrefix: setting.AppSubURL,
}, input)
assert.NoError(t, err)
assert.Equal(t, strings.TrimSpace(expected), strings.TrimSpace(buffer))
buffer, err = RenderString(&markup.RenderContext{
+ Ctx: git.DefaultContext,
URLPrefix: setting.AppSubURL,
IsWiki: true,
}, input)
@@ -81,6 +83,7 @@ func TestRender_Images(t *testing.T) {
test := func(input, expected string) {
buffer, err := RenderString(&markup.RenderContext{
+ Ctx: git.DefaultContext,
URLPrefix: setting.AppSubURL,
}, input)
assert.NoError(t, err)
@@ -311,6 +314,7 @@ func TestTotal_RenderWiki(t *testing.T) {
for i := 0; i < len(testCases); i += 2 {
line, err := RenderString(&markup.RenderContext{
+ Ctx: git.DefaultContext,
URLPrefix: AppSubURL,
IsWiki: true,
}, testCases[i])
@@ -339,6 +343,7 @@ func TestTotal_RenderString(t *testing.T) {
for i := 0; i < len(testCases); i += 2 {
line, err := RenderString(&markup.RenderContext{
+ Ctx: git.DefaultContext,
URLPrefix: AppSubURL,
}, testCases[i])
assert.NoError(t, err)
@@ -348,17 +353,17 @@ func TestTotal_RenderString(t *testing.T) {
func TestRender_RenderParagraphs(t *testing.T) {
test := func(t *testing.T, str string, cnt int) {
- res, err := RenderRawString(&markup.RenderContext{}, str)
+ res, err := RenderRawString(&markup.RenderContext{Ctx: git.DefaultContext}, str)
assert.NoError(t, err)
assert.Equal(t, cnt, strings.Count(res, "<p"), "Rendered result for unix should have %d paragraph(s) but has %d:\n%s\n", cnt, strings.Count(res, "<p"), res)
mac := strings.ReplaceAll(str, "\n", "\r")
- res, err = RenderRawString(&markup.RenderContext{}, mac)
+ res, err = RenderRawString(&markup.RenderContext{Ctx: git.DefaultContext}, mac)
assert.NoError(t, err)
assert.Equal(t, cnt, strings.Count(res, "<p"), "Rendered result for mac should have %d paragraph(s) but has %d:\n%s\n", cnt, strings.Count(res, "<p"), res)
dos := strings.ReplaceAll(str, "\n", "\r\n")
- res, err = RenderRawString(&markup.RenderContext{}, dos)
+ res, err = RenderRawString(&markup.RenderContext{Ctx: git.DefaultContext}, dos)
assert.NoError(t, err)
assert.Equal(t, cnt, strings.Count(res, "<p"), "Rendered result for windows should have %d paragraph(s) but has %d:\n%s\n", cnt, strings.Count(res, "<p"), res)
}
@@ -386,7 +391,7 @@ func TestMarkdownRenderRaw(t *testing.T) {
for _, testcase := range testcases {
log.Info("Test markdown render error with fuzzy data: %x, the following errors can be recovered", testcase)
- _, err := RenderRawString(&markup.RenderContext{}, string(testcase))
+ _, err := RenderRawString(&markup.RenderContext{Ctx: git.DefaultContext}, string(testcase))
assert.NoError(t, err)
}
}
@@ -398,7 +403,7 @@ func TestRenderSiblingImages_Issue12925(t *testing.T) {
expected := `<p><a href="/image1" target="_blank" rel="nofollow noopener"><img src="/image1" alt="image1"></a><br>
<a href="/image2" target="_blank" rel="nofollow noopener"><img src="/image2" alt="image2"></a></p>
`
- res, err := RenderRawString(&markup.RenderContext{}, testcase)
+ res, err := RenderRawString(&markup.RenderContext{Ctx: git.DefaultContext}, testcase)
assert.NoError(t, err)
assert.Equal(t, expected, res)
}
@@ -407,7 +412,7 @@ func TestRenderEmojiInLinks_Issue12331(t *testing.T) {
testcase := `[Link with emoji :moon: in text](https://gitea.io)`
expected := `<p><a href="https://gitea.io" rel="nofollow">Link with emoji <span class="emoji" aria-label="waxing gibbous moon">🌔</span> in text</a></p>
`
- res, err := RenderString(&markup.RenderContext{}, testcase)
+ res, err := RenderString(&markup.RenderContext{Ctx: git.DefaultContext}, testcase)
assert.NoError(t, err)
assert.Equal(t, expected, res)
}
@@ -441,7 +446,7 @@ func TestColorPreview(t *testing.T) {
}
for _, test := range positiveTests {
- res, err := RenderString(&markup.RenderContext{}, test.testcase)
+ res, err := RenderString(&markup.RenderContext{Ctx: git.DefaultContext}, test.testcase)
assert.NoError(t, err, "Unexpected error in testcase: %q", test.testcase)
assert.Equal(t, test.expected, res, "Unexpected result in testcase %q", test.testcase)
@@ -461,7 +466,7 @@ func TestColorPreview(t *testing.T) {
}
for _, test := range negativeTests {
- res, err := RenderString(&markup.RenderContext{}, test)
+ res, err := RenderString(&markup.RenderContext{Ctx: git.DefaultContext}, test)
assert.NoError(t, err, "Unexpected error in testcase: %q", test)
assert.NotContains(t, res, `<span class="color-preview" style="background-color: `, "Unexpected result in testcase %q", test)
}
@@ -508,7 +513,7 @@ func TestMathBlock(t *testing.T) {
}
for _, test := range testcases {
- res, err := RenderString(&markup.RenderContext{}, test.testcase)
+ res, err := RenderString(&markup.RenderContext{Ctx: git.DefaultContext}, test.testcase)
assert.NoError(t, err, "Unexpected error in testcase: %q", test.testcase)
assert.Equal(t, test.expected, res, "Unexpected result in testcase %q", test.testcase)
diff --git a/modules/markup/orgmode/orgmode_test.go b/modules/markup/orgmode/orgmode_test.go
index 4acb678cd..d6467c36f 100644
--- a/modules/markup/orgmode/orgmode_test.go
+++ b/modules/markup/orgmode/orgmode_test.go
@@ -7,6 +7,7 @@ import (
"strings"
"testing"
+ "code.gitea.io/gitea/modules/git"
"code.gitea.io/gitea/modules/markup"
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/util"
@@ -26,6 +27,7 @@ func TestRender_StandardLinks(t *testing.T) {
test := func(input, expected string) {
buffer, err := RenderString(&markup.RenderContext{
+ Ctx: git.DefaultContext,
URLPrefix: setting.AppSubURL,
}, input)
assert.NoError(t, err)
@@ -46,6 +48,7 @@ func TestRender_Images(t *testing.T) {
test := func(input, expected string) {
buffer, err := RenderString(&markup.RenderContext{
+ Ctx: git.DefaultContext,
URLPrefix: setting.AppSubURL,
}, input)
assert.NoError(t, err)
@@ -65,6 +68,7 @@ func TestRender_Source(t *testing.T) {
test := func(input, expected string) {
buffer, err := RenderString(&markup.RenderContext{
+ Ctx: git.DefaultContext,
URLPrefix: setting.AppSubURL,
}, input)
assert.NoError(t, err)
diff --git a/modules/markup/sanitizer.go b/modules/markup/sanitizer.go
index e59f6c7c8..600ccbf3c 100644
--- a/modules/markup/sanitizer.go
+++ b/modules/markup/sanitizer.go
@@ -132,6 +132,8 @@ func createDefaultPolicy() *bluemonday.Policy {
policy.AllowAttrs(generalSafeAttrs...).OnElements(generalSafeElements...)
+ policy.AllowAttrs("src", "autoplay", "controls").OnElements("video")
+
policy.AllowAttrs("itemscope", "itemtype").OnElements("div")
// FIXME: Need to handle longdesc in img but there is no easy way to do it
diff --git a/modules/options/base.go b/modules/options/base.go
index 039e934b3..e83e8df5d 100644
--- a/modules/options/base.go
+++ b/modules/options/base.go
@@ -7,11 +7,52 @@ import (
"fmt"
"io/fs"
"os"
+ "path"
"path/filepath"
+ "code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/util"
)
+// Locale reads the content of a specific locale from static/bindata or custom path.
+func Locale(name string) ([]byte, error) {
+ return fileFromDir(path.Join("locale", util.CleanPath(name)))
+}
+
+// Readme reads the content of a specific readme from static/bindata or custom path.
+func Readme(name string) ([]byte, error) {
+ return fileFromDir(path.Join("readme", util.CleanPath(name)))
+}
+
+// Gitignore reads the content of a gitignore locale from static/bindata or custom path.
+func Gitignore(name string) ([]byte, error) {
+ return fileFromDir(path.Join("gitignore", util.CleanPath(name)))
+}
+
+// License reads the content of a specific license from static/bindata or custom path.
+func License(name string) ([]byte, error) {
+ return fileFromDir(path.Join("license", util.CleanPath(name)))
+}
+
+// Labels reads the content of a specific labels from static/bindata or custom path.
+func Labels(name string) ([]byte, error) {
+ return fileFromDir(path.Join("label", util.CleanPath(name)))
+}
+
+// WalkLocales reads the content of a specific locale
+func WalkLocales(callback func(path, name string, d fs.DirEntry, err error) error) error {
+ if IsDynamic() {
+ if err := walkAssetDir(filepath.Join(setting.StaticRootPath, "options", "locale"), callback); err != nil && !os.IsNotExist(err) {
+ return fmt.Errorf("failed to walk locales. Error: %w", err)
+ }
+ }
+
+ if err := walkAssetDir(filepath.Join(setting.CustomPath, "options", "locale"), callback); err != nil && !os.IsNotExist(err) {
+ return fmt.Errorf("failed to walk locales. Error: %w", err)
+ }
+ return nil
+}
+
func walkAssetDir(root string, callback func(path, name string, d fs.DirEntry, err error) error) error {
if err := filepath.WalkDir(root, func(path string, d fs.DirEntry, err error) error {
// name is the path relative to the root
@@ -37,3 +78,18 @@ func walkAssetDir(root string, callback func(path, name string, d fs.DirEntry, e
}
return nil
}
+
+func statDirIfExist(dir string) ([]string, error) {
+ isDir, err := util.IsDir(dir)
+ if err != nil {
+ return nil, fmt.Errorf("unable to check if static directory %s is a directory. %w", dir, err)
+ }
+ if !isDir {
+ return nil, nil
+ }
+ files, err := util.StatDir(dir, true)
+ if err != nil {
+ return nil, fmt.Errorf("unable to read directory %q. %w", dir, err)
+ }
+ return files, nil
+}
diff --git a/modules/options/dynamic.go b/modules/options/dynamic.go
index a20253676..8c954492a 100644
--- a/modules/options/dynamic.go
+++ b/modules/options/dynamic.go
@@ -7,10 +7,8 @@ package options
import (
"fmt"
- "io/fs"
"os"
"path"
- "path/filepath"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/setting"
@@ -27,76 +25,20 @@ func Dir(name string) ([]string, error) {
var result []string
- customDir := path.Join(setting.CustomPath, "options", name)
-
- isDir, err := util.IsDir(customDir)
- if err != nil {
- return []string{}, fmt.Errorf("Unabe to check if custom directory %s is a directory. %w", customDir, err)
- }
- if isDir {
- files, err := util.StatDir(customDir, true)
- if err != nil {
- return []string{}, fmt.Errorf("Failed to read custom directory. %w", err)
- }
-
- result = append(result, files...)
- }
-
- staticDir := path.Join(setting.StaticRootPath, "options", name)
-
- isDir, err = util.IsDir(staticDir)
- if err != nil {
- return []string{}, fmt.Errorf("unable to check if static directory %s is a directory. %w", staticDir, err)
- }
- if isDir {
- files, err := util.StatDir(staticDir, true)
+ for _, dir := range []string{
+ path.Join(setting.CustomPath, "options", name), // custom dir
+ path.Join(setting.StaticRootPath, "options", name), // static dir
+ } {
+ files, err := statDirIfExist(dir)
if err != nil {
- return []string{}, fmt.Errorf("Failed to read static directory. %w", err)
+ return nil, err
}
-
result = append(result, files...)
}
return directories.AddAndGet(name, result), nil
}
-// Locale reads the content of a specific locale from static or custom path.
-func Locale(name string) ([]byte, error) {
- return fileFromDir(path.Join("locale", name))
-}
-
-// WalkLocales reads the content of a specific locale from static or custom path.
-func WalkLocales(callback func(path, name string, d fs.DirEntry, err error) error) error {
- if err := walkAssetDir(filepath.Join(setting.StaticRootPath, "options", "locale"), callback); err != nil && !os.IsNotExist(err) {
- return fmt.Errorf("failed to walk locales. Error: %w", err)
- }
-
- if err := walkAssetDir(filepath.Join(setting.CustomPath, "options", "locale"), callback); err != nil && !os.IsNotExist(err) {
- return fmt.Errorf("failed to walk locales. Error: %w", err)
- }
- return nil
-}
-
-// Readme reads the content of a specific readme from static or custom path.
-func Readme(name string) ([]byte, error) {
- return fileFromDir(path.Join("readme", name))
-}
-
-// Gitignore reads the content of a specific gitignore from static or custom path.
-func Gitignore(name string) ([]byte, error) {
- return fileFromDir(path.Join("gitignore", name))
-}
-
-// License reads the content of a specific license from static or custom path.
-func License(name string) ([]byte, error) {
- return fileFromDir(path.Join("license", name))
-}
-
-// Labels reads the content of a specific labels from static or custom path.
-func Labels(name string) ([]byte, error) {
- return fileFromDir(path.Join("label", name))
-}
-
// fileFromDir is a helper to read files from static or custom path.
func fileFromDir(name string) ([]byte, error) {
customPath := path.Join(setting.CustomPath, "options", name)
diff --git a/modules/options/static.go b/modules/options/static.go
index ff3c86d3f..549f4e25b 100644
--- a/modules/options/static.go
+++ b/modules/options/static.go
@@ -8,10 +8,8 @@ package options
import (
"fmt"
"io"
- "io/fs"
"os"
"path"
- "path/filepath"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/setting"
@@ -28,17 +26,14 @@ func Dir(name string) ([]string, error) {
var result []string
- customDir := path.Join(setting.CustomPath, "options", name)
- isDir, err := util.IsDir(customDir)
- if err != nil {
- return []string{}, fmt.Errorf("unable to check if custom directory %q is a directory. %w", customDir, err)
- }
- if isDir {
- files, err := util.StatDir(customDir, true)
+ for _, dir := range []string{
+ path.Join(setting.CustomPath, "options", name), // custom dir
+ // no static dir
+ } {
+ files, err := statDirIfExist(dir)
if err != nil {
- return []string{}, fmt.Errorf("unable to read custom directory %q. %w", customDir, err)
+ return nil, err
}
-
result = append(result, files...)
}
@@ -69,39 +64,6 @@ func AssetDir(dirName string) ([]string, error) {
return results, nil
}
-// Locale reads the content of a specific locale from bindata or custom path.
-func Locale(name string) ([]byte, error) {
- return fileFromDir(path.Join("locale", name))
-}
-
-// WalkLocales reads the content of a specific locale from static or custom path.
-func WalkLocales(callback func(path, name string, d fs.DirEntry, err error) error) error {
- if err := walkAssetDir(filepath.Join(setting.CustomPath, "options", "locale"), callback); err != nil && !os.IsNotExist(err) {
- return fmt.Errorf("failed to walk locales. Error: %w", err)
- }
- return nil
-}
-
-// Readme reads the content of a specific readme from bindata or custom path.
-func Readme(name string) ([]byte, error) {
- return fileFromDir(path.Join("readme", name))
-}
-
-// Gitignore reads the content of a gitignore locale from bindata or custom path.
-func Gitignore(name string) ([]byte, error) {
- return fileFromDir(path.Join("gitignore", name))
-}
-
-// License reads the content of a specific license from bindata or custom path.
-func License(name string) ([]byte, error) {
- return fileFromDir(path.Join("license", name))
-}
-
-// Labels reads the content of a specific labels from static or custom path.
-func Labels(name string) ([]byte, error) {
- return fileFromDir(path.Join("label", name))
-}
-
// fileFromDir is a helper to read files from bindata or custom path.
func fileFromDir(name string) ([]byte, error) {
customPath := path.Join(setting.CustomPath, "options", name)
diff --git a/modules/public/public.go b/modules/public/public.go
index 42026f9b1..e1d60d89e 100644
--- a/modules/public/public.go
+++ b/modules/public/public.go
@@ -6,7 +6,6 @@ package public
import (
"net/http"
"os"
- "path"
"path/filepath"
"strings"
@@ -14,6 +13,7 @@ import (
"code.gitea.io/gitea/modules/httpcache"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/setting"
+ "code.gitea.io/gitea/modules/util"
)
// Options represents the available options to configure the handler.
@@ -103,7 +103,7 @@ func setWellKnownContentType(w http.ResponseWriter, file string) {
func (opts *Options) handle(w http.ResponseWriter, req *http.Request, fs http.FileSystem, file string) bool {
// use clean to keep the file is a valid path with no . or ..
- f, err := fs.Open(path.Clean(file))
+ f, err := fs.Open(util.CleanPath(file))
if err != nil {
if os.IsNotExist(err) {
return false
diff --git a/modules/queue/queue_channel.go b/modules/queue/queue_channel.go
index 6f75b8357..baac09739 100644
--- a/modules/queue/queue_channel.go
+++ b/modules/queue/queue_channel.go
@@ -124,7 +124,10 @@ func (q *ChannelQueue) Shutdown() {
log.Trace("ChannelQueue: %s Flushing", q.name)
// We can't use Cleanup here because that will close the channel
if err := q.FlushWithContext(q.terminateCtx); err != nil {
- log.Warn("ChannelQueue: %s Terminated before completed flushing", q.name)
+ count := atomic.LoadInt64(&q.numInQueue)
+ if count > 0 {
+ log.Warn("ChannelQueue: %s Terminated before completed flushing", q.name)
+ }
return
}
log.Debug("ChannelQueue: %s Flushed", q.name)
diff --git a/modules/queue/queue_disk_channel.go b/modules/queue/queue_disk_channel.go
index c7526714c..91f91f0df 100644
--- a/modules/queue/queue_disk_channel.go
+++ b/modules/queue/queue_disk_channel.go
@@ -94,7 +94,8 @@ func NewPersistableChannelQueue(handle HandlerFunc, cfg, exemplar interface{}) (
},
Workers: 0,
},
- DataDir: config.DataDir,
+ DataDir: config.DataDir,
+ QueueName: config.Name + "-level",
}
levelQueue, err := NewLevelQueue(wrappedHandle, levelCfg, exemplar)
@@ -172,16 +173,18 @@ func (q *PersistableChannelQueue) Run(atShutdown, atTerminate func(func())) {
atShutdown(q.Shutdown)
atTerminate(q.Terminate)
- if lq, ok := q.internal.(*LevelQueue); ok && lq.byteFIFO.Len(lq.shutdownCtx) != 0 {
+ if lq, ok := q.internal.(*LevelQueue); ok && lq.byteFIFO.Len(lq.terminateCtx) != 0 {
// Just run the level queue - we shut it down once it's flushed
go q.internal.Run(func(_ func()) {}, func(_ func()) {})
go func() {
- for !q.IsEmpty() {
- _ = q.internal.Flush(0)
+ for !lq.IsEmpty() {
+ _ = lq.Flush(0)
select {
case <-time.After(100 * time.Millisecond):
- case <-q.internal.(*LevelQueue).shutdownCtx.Done():
- log.Warn("LevelQueue: %s shut down before completely flushed", q.internal.(*LevelQueue).Name())
+ case <-lq.shutdownCtx.Done():
+ if lq.byteFIFO.Len(lq.terminateCtx) > 0 {
+ log.Warn("LevelQueue: %s shut down before completely flushed", q.internal.(*LevelQueue).Name())
+ }
return
}
}
@@ -316,10 +319,22 @@ func (q *PersistableChannelQueue) Shutdown() {
// Redirect all remaining data in the chan to the internal channel
log.Trace("PersistableChannelQueue: %s Redirecting remaining data", q.delayedStarter.name)
close(q.channelQueue.dataChan)
+ countOK, countLost := 0, 0
for data := range q.channelQueue.dataChan {
- _ = q.internal.Push(data)
+ err := q.internal.Push(data)
+ if err != nil {
+ log.Error("PersistableChannelQueue: %s Unable redirect %v due to: %v", q.delayedStarter.name, data, err)
+ countLost++
+ } else {
+ countOK++
+ }
atomic.AddInt64(&q.channelQueue.numInQueue, -1)
}
+ if countLost > 0 {
+ log.Warn("PersistableChannelQueue: %s %d will be restored on restart, %d lost", q.delayedStarter.name, countOK, countLost)
+ } else if countOK > 0 {
+ log.Warn("PersistableChannelQueue: %s %d will be restored on restart", q.delayedStarter.name, countOK)
+ }
log.Trace("PersistableChannelQueue: %s Done Redirecting remaining data", q.delayedStarter.name)
log.Debug("PersistableChannelQueue: %s Shutdown", q.delayedStarter.name)
diff --git a/modules/queue/queue_disk_channel_test.go b/modules/queue/queue_disk_channel_test.go
index 318610355..4f14a5d79 100644
--- a/modules/queue/queue_disk_channel_test.go
+++ b/modules/queue/queue_disk_channel_test.go
@@ -39,7 +39,7 @@ func TestPersistableChannelQueue(t *testing.T) {
Workers: 1,
BoostWorkers: 0,
MaxWorkers: 10,
- Name: "first",
+ Name: "test-queue",
}, &testData{})
assert.NoError(t, err)
@@ -135,7 +135,7 @@ func TestPersistableChannelQueue(t *testing.T) {
Workers: 1,
BoostWorkers: 0,
MaxWorkers: 10,
- Name: "second",
+ Name: "test-queue",
}, &testData{})
assert.NoError(t, err)
@@ -227,7 +227,7 @@ func TestPersistableChannelQueue_Pause(t *testing.T) {
Workers: 1,
BoostWorkers: 0,
MaxWorkers: 10,
- Name: "first",
+ Name: "test-queue",
}, &testData{})
assert.NoError(t, err)
@@ -433,7 +433,7 @@ func TestPersistableChannelQueue_Pause(t *testing.T) {
Workers: 1,
BoostWorkers: 0,
MaxWorkers: 10,
- Name: "second",
+ Name: "test-queue",
}, &testData{})
assert.NoError(t, err)
pausable, ok = queue.(Pausable)
diff --git a/modules/queue/unique_queue_channel.go b/modules/queue/unique_queue_channel.go
index c43bd1db3..62c051aa3 100644
--- a/modules/queue/unique_queue_channel.go
+++ b/modules/queue/unique_queue_channel.go
@@ -177,7 +177,9 @@ func (q *ChannelUniqueQueue) Shutdown() {
go func() {
log.Trace("ChannelUniqueQueue: %s Flushing", q.name)
if err := q.FlushWithContext(q.terminateCtx); err != nil {
- log.Warn("ChannelUniqueQueue: %s Terminated before completed flushing", q.name)
+ if !q.IsEmpty() {
+ log.Warn("ChannelUniqueQueue: %s Terminated before completed flushing", q.name)
+ }
return
}
log.Debug("ChannelUniqueQueue: %s Flushed", q.name)
diff --git a/modules/queue/unique_queue_channel_test.go b/modules/queue/unique_queue_channel_test.go
index 9372694b8..824015b83 100644
--- a/modules/queue/unique_queue_channel_test.go
+++ b/modules/queue/unique_queue_channel_test.go
@@ -8,10 +8,13 @@ import (
"testing"
"time"
+ "code.gitea.io/gitea/modules/log"
+
"github.com/stretchr/testify/assert"
)
func TestChannelUniqueQueue(t *testing.T) {
+ _ = log.NewLogger(1000, "console", "console", `{"level":"warn","stacktracelevel":"NONE","stderr":true}`)
handleChan := make(chan *testData)
handle := func(data ...Data) []Data {
for _, datum := range data {
@@ -52,6 +55,8 @@ func TestChannelUniqueQueue(t *testing.T) {
}
func TestChannelUniqueQueue_Batch(t *testing.T) {
+ _ = log.NewLogger(1000, "console", "console", `{"level":"warn","stacktracelevel":"NONE","stderr":true}`)
+
handleChan := make(chan *testData)
handle := func(data ...Data) []Data {
for _, datum := range data {
@@ -98,6 +103,8 @@ func TestChannelUniqueQueue_Batch(t *testing.T) {
}
func TestChannelUniqueQueue_Pause(t *testing.T) {
+ _ = log.NewLogger(1000, "console", "console", `{"level":"warn","stacktracelevel":"NONE","stderr":true}`)
+
lock := sync.Mutex{}
var queue Queue
var err error
diff --git a/modules/queue/unique_queue_disk_channel.go b/modules/queue/unique_queue_disk_channel.go
index 405726182..cc8a807c6 100644
--- a/modules/queue/unique_queue_disk_channel.go
+++ b/modules/queue/unique_queue_disk_channel.go
@@ -94,7 +94,8 @@ func NewPersistableChannelUniqueQueue(handle HandlerFunc, cfg, exemplar interfac
},
Workers: 0,
},
- DataDir: config.DataDir,
+ DataDir: config.DataDir,
+ QueueName: config.Name + "-level",
}
queue.channelQueue = channelUniqueQueue.(*ChannelUniqueQueue)
@@ -209,17 +210,29 @@ func (q *PersistableChannelUniqueQueue) Run(atShutdown, atTerminate func(func())
atTerminate(q.Terminate)
_ = q.channelQueue.AddWorkers(q.channelQueue.workers, 0)
- if luq, ok := q.internal.(*LevelUniqueQueue); ok && luq.ByteFIFOUniqueQueue.byteFIFO.Len(luq.shutdownCtx) != 0 {
+ if luq, ok := q.internal.(*LevelUniqueQueue); ok && !luq.IsEmpty() {
// Just run the level queue - we shut it down once it's flushed
- go q.internal.Run(func(_ func()) {}, func(_ func()) {})
+ go luq.Run(func(_ func()) {}, func(_ func()) {})
go func() {
- _ = q.internal.Flush(0)
- log.Debug("LevelUniqueQueue: %s flushed so shutting down", q.internal.(*LevelUniqueQueue).Name())
- q.internal.(*LevelUniqueQueue).Shutdown()
- GetManager().Remove(q.internal.(*LevelUniqueQueue).qid)
+ _ = luq.Flush(0)
+ for !luq.IsEmpty() {
+ _ = luq.Flush(0)
+ select {
+ case <-time.After(100 * time.Millisecond):
+ case <-luq.shutdownCtx.Done():
+ if luq.byteFIFO.Len(luq.terminateCtx) > 0 {
+ log.Warn("LevelUniqueQueue: %s shut down before completely flushed", luq.Name())
+ }
+ return
+ }
+ }
+ log.Debug("LevelUniqueQueue: %s flushed so shutting down", luq.Name())
+ luq.Shutdown()
+ GetManager().Remove(luq.qid)
}()
} else {
log.Debug("PersistableChannelUniqueQueue: %s Skipping running the empty level queue", q.delayedStarter.name)
+ _ = q.internal.Flush(0)
q.internal.(*LevelUniqueQueue).Shutdown()
GetManager().Remove(q.internal.(*LevelUniqueQueue).qid)
}
@@ -285,8 +298,20 @@ func (q *PersistableChannelUniqueQueue) Shutdown() {
// Redirect all remaining data in the chan to the internal channel
close(q.channelQueue.dataChan)
log.Trace("PersistableChannelUniqueQueue: %s Redirecting remaining data", q.delayedStarter.name)
+ countOK, countLost := 0, 0
for data := range q.channelQueue.dataChan {
- _ = q.internal.Push(data)
+ err := q.internal.(*LevelUniqueQueue).Push(data)
+ if err != nil {
+ log.Error("PersistableChannelUniqueQueue: %s Unable redirect %v due to: %v", q.delayedStarter.name, data, err)
+ countLost++
+ } else {
+ countOK++
+ }
+ }
+ if countLost > 0 {
+ log.Warn("PersistableChannelUniqueQueue: %s %d will be restored on restart, %d lost", q.delayedStarter.name, countOK, countLost)
+ } else if countOK > 0 {
+ log.Warn("PersistableChannelUniqueQueue: %s %d will be restored on restart", q.delayedStarter.name, countOK)
}
log.Trace("PersistableChannelUniqueQueue: %s Done Redirecting remaining data", q.delayedStarter.name)
diff --git a/modules/queue/unique_queue_disk_channel_test.go b/modules/queue/unique_queue_disk_channel_test.go
new file mode 100644
index 000000000..fd76163f4
--- /dev/null
+++ b/modules/queue/unique_queue_disk_channel_test.go
@@ -0,0 +1,259 @@
+// Copyright 2023 The Gitea Authors. All rights reserved.
+// SPDX-License-Identifier: MIT
+
+package queue
+
+import (
+ "fmt"
+ "strconv"
+ "sync"
+ "testing"
+ "time"
+
+ "code.gitea.io/gitea/modules/log"
+
+ "github.com/stretchr/testify/assert"
+)
+
+func TestPersistableChannelUniqueQueue(t *testing.T) {
+ tmpDir := t.TempDir()
+ fmt.Printf("TempDir %s\n", tmpDir)
+ _ = log.NewLogger(1000, "console", "console", `{"level":"warn","stacktracelevel":"NONE","stderr":true}`)
+
+ // Common function to create the Queue
+ newQueue := func(name string, handle func(data ...Data) []Data) Queue {
+ q, err := NewPersistableChannelUniqueQueue(handle,
+ PersistableChannelUniqueQueueConfiguration{
+ Name: name,
+ DataDir: tmpDir,
+ QueueLength: 200,
+ MaxWorkers: 1,
+ BlockTimeout: 1 * time.Second,
+ BoostTimeout: 5 * time.Minute,
+ BoostWorkers: 1,
+ Workers: 0,
+ }, "task-0")
+ assert.NoError(t, err)
+ return q
+ }
+
+ // runs the provided queue and provides some timer function
+ type channels struct {
+ readyForShutdown chan struct{} // closed when shutdown functions have been assigned
+ readyForTerminate chan struct{} // closed when terminate functions have been assigned
+ signalShutdown chan struct{} // Should close to signal shutdown
+ doneShutdown chan struct{} // closed when shutdown function is done
+ queueTerminate []func() // list of atTerminate functions to call atTerminate - need to be accessed with lock
+ }
+ runQueue := func(q Queue, lock *sync.Mutex) *channels {
+ chans := &channels{
+ readyForShutdown: make(chan struct{}),
+ readyForTerminate: make(chan struct{}),
+ signalShutdown: make(chan struct{}),
+ doneShutdown: make(chan struct{}),
+ }
+ go q.Run(func(atShutdown func()) {
+ go func() {
+ lock.Lock()
+ select {
+ case <-chans.readyForShutdown:
+ default:
+ close(chans.readyForShutdown)
+ }
+ lock.Unlock()
+ <-chans.signalShutdown
+ atShutdown()
+ close(chans.doneShutdown)
+ }()
+ }, func(atTerminate func()) {
+ lock.Lock()
+ defer lock.Unlock()
+ select {
+ case <-chans.readyForTerminate:
+ default:
+ close(chans.readyForTerminate)
+ }
+ chans.queueTerminate = append(chans.queueTerminate, atTerminate)
+ })
+
+ return chans
+ }
+
+ // call to shutdown and terminate the queue associated with the channels
+ doTerminate := func(chans *channels, lock *sync.Mutex) {
+ <-chans.readyForTerminate
+
+ lock.Lock()
+ callbacks := []func(){}
+ callbacks = append(callbacks, chans.queueTerminate...)
+ lock.Unlock()
+
+ for _, callback := range callbacks {
+ callback()
+ }
+ }
+
+ mapLock := sync.Mutex{}
+ executedInitial := map[string][]string{}
+ hasInitial := map[string][]string{}
+
+ fillQueue := func(name string, done chan struct{}) {
+ t.Run("Initial Filling: "+name, func(t *testing.T) {
+ lock := sync.Mutex{}
+
+ startAt100Queued := make(chan struct{})
+ stopAt20Shutdown := make(chan struct{}) // stop and shutdown at the 20th item
+
+ handle := func(data ...Data) []Data {
+ <-startAt100Queued
+ for _, datum := range data {
+ s := datum.(string)
+ mapLock.Lock()
+ executedInitial[name] = append(executedInitial[name], s)
+ mapLock.Unlock()
+ if s == "task-20" {
+ close(stopAt20Shutdown)
+ }
+ }
+ return nil
+ }
+
+ q := newQueue(name, handle)
+
+ // add 100 tasks to the queue
+ for i := 0; i < 100; i++ {
+ _ = q.Push("task-" + strconv.Itoa(i))
+ }
+ close(startAt100Queued)
+
+ chans := runQueue(q, &lock)
+
+ <-chans.readyForShutdown
+ <-stopAt20Shutdown
+ close(chans.signalShutdown)
+ <-chans.doneShutdown
+ _ = q.Push("final")
+
+ // check which tasks are still in the queue
+ for i := 0; i < 100; i++ {
+ if has, _ := q.(UniqueQueue).Has("task-" + strconv.Itoa(i)); has {
+ mapLock.Lock()
+ hasInitial[name] = append(hasInitial[name], "task-"+strconv.Itoa(i))
+ mapLock.Unlock()
+ }
+ }
+ if has, _ := q.(UniqueQueue).Has("final"); has {
+ mapLock.Lock()
+ hasInitial[name] = append(hasInitial[name], "final")
+ mapLock.Unlock()
+ } else {
+ assert.Fail(t, "UnqueQueue %s should have \"final\"", name)
+ }
+ doTerminate(chans, &lock)
+ mapLock.Lock()
+ assert.Equal(t, 101, len(executedInitial[name])+len(hasInitial[name]))
+ mapLock.Unlock()
+ })
+ close(done)
+ }
+
+ doneA := make(chan struct{})
+ doneB := make(chan struct{})
+
+ go fillQueue("QueueA", doneA)
+ go fillQueue("QueueB", doneB)
+
+ <-doneA
+ <-doneB
+
+ executedEmpty := map[string][]string{}
+ hasEmpty := map[string][]string{}
+ emptyQueue := func(name string, done chan struct{}) {
+ t.Run("Empty Queue: "+name, func(t *testing.T) {
+ lock := sync.Mutex{}
+ stop := make(chan struct{})
+
+ // collect the tasks that have been executed
+ handle := func(data ...Data) []Data {
+ lock.Lock()
+ for _, datum := range data {
+ mapLock.Lock()
+ executedEmpty[name] = append(executedEmpty[name], datum.(string))
+ mapLock.Unlock()
+ if datum.(string) == "final" {
+ close(stop)
+ }
+ }
+ lock.Unlock()
+ return nil
+ }
+
+ q := newQueue(name, handle)
+ chans := runQueue(q, &lock)
+
+ <-chans.readyForShutdown
+ <-stop
+ close(chans.signalShutdown)
+ <-chans.doneShutdown
+
+ // check which tasks are still in the queue
+ for i := 0; i < 100; i++ {
+ if has, _ := q.(UniqueQueue).Has("task-" + strconv.Itoa(i)); has {
+ mapLock.Lock()
+ hasEmpty[name] = append(hasEmpty[name], "task-"+strconv.Itoa(i))
+ mapLock.Unlock()
+ }
+ }
+ doTerminate(chans, &lock)
+
+ mapLock.Lock()
+ assert.Equal(t, 101, len(executedInitial[name])+len(executedEmpty[name]))
+ assert.Equal(t, 0, len(hasEmpty[name]))
+ mapLock.Unlock()
+ })
+ close(done)
+ }
+
+ doneA = make(chan struct{})
+ doneB = make(chan struct{})
+
+ go emptyQueue("QueueA", doneA)
+ go emptyQueue("QueueB", doneB)
+
+ <-doneA
+ <-doneB
+
+ mapLock.Lock()
+ t.Logf("TestPersistableChannelUniqueQueue executedInitiallyA=%v, executedInitiallyB=%v, executedToEmptyA=%v, executedToEmptyB=%v",
+ len(executedInitial["QueueA"]), len(executedInitial["QueueB"]), len(executedEmpty["QueueA"]), len(executedEmpty["QueueB"]))
+
+ // reset and rerun
+ executedInitial = map[string][]string{}
+ hasInitial = map[string][]string{}
+ executedEmpty = map[string][]string{}
+ hasEmpty = map[string][]string{}
+ mapLock.Unlock()
+
+ doneA = make(chan struct{})
+ doneB = make(chan struct{})
+
+ go fillQueue("QueueA", doneA)
+ go fillQueue("QueueB", doneB)
+
+ <-doneA
+ <-doneB
+
+ doneA = make(chan struct{})
+ doneB = make(chan struct{})
+
+ go emptyQueue("QueueA", doneA)
+ go emptyQueue("QueueB", doneB)
+
+ <-doneA
+ <-doneB
+
+ mapLock.Lock()
+ t.Logf("TestPersistableChannelUniqueQueue executedInitiallyA=%v, executedInitiallyB=%v, executedToEmptyA=%v, executedToEmptyB=%v",
+ len(executedInitial["QueueA"]), len(executedInitial["QueueB"]), len(executedEmpty["QueueA"]), len(executedEmpty["QueueB"]))
+ mapLock.Unlock()
+}
diff --git a/modules/repository/create.go b/modules/repository/create.go
index 1704ea792..6a1fa41b6 100644
--- a/modules/repository/create.go
+++ b/modules/repository/create.go
@@ -23,6 +23,7 @@ import (
user_model "code.gitea.io/gitea/models/user"
"code.gitea.io/gitea/models/webhook"
"code.gitea.io/gitea/modules/git"
+ "code.gitea.io/gitea/modules/label"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/setting"
api "code.gitea.io/gitea/modules/structs"
@@ -189,7 +190,7 @@ func CreateRepository(doer, u *user_model.User, opts CreateRepoOptions) (*repo_m
// Check if label template exist
if len(opts.IssueLabels) > 0 {
- if _, err := GetLabelTemplateFile(opts.IssueLabels); err != nil {
+ if _, err := label.GetTemplateFile(opts.IssueLabels); err != nil {
return nil, err
}
}
diff --git a/modules/repository/init.go b/modules/repository/init.go
index 771b68a49..f9a33cd4f 100644
--- a/modules/repository/init.go
+++ b/modules/repository/init.go
@@ -18,6 +18,7 @@ import (
repo_model "code.gitea.io/gitea/models/repo"
user_model "code.gitea.io/gitea/models/user"
"code.gitea.io/gitea/modules/git"
+ "code.gitea.io/gitea/modules/label"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/options"
"code.gitea.io/gitea/modules/setting"
@@ -40,114 +41,6 @@ var (
LabelTemplates map[string]string
)
-// ErrIssueLabelTemplateLoad represents a "ErrIssueLabelTemplateLoad" kind of error.
-type ErrIssueLabelTemplateLoad struct {
- TemplateFile string
- OriginalError error
-}
-
-// IsErrIssueLabelTemplateLoad checks if an error is a ErrIssueLabelTemplateLoad.
-func IsErrIssueLabelTemplateLoad(err error) bool {
- _, ok := err.(ErrIssueLabelTemplateLoad)
- return ok
-}
-
-func (err ErrIssueLabelTemplateLoad) Error() string {
- return fmt.Sprintf("Failed to load label template file '%s': %v", err.TemplateFile, err.OriginalError)
-}
-
-// GetRepoInitFile returns repository init files
-func GetRepoInitFile(tp, name string) ([]byte, error) {
- cleanedName := strings.TrimLeft(path.Clean("/"+name), "/")
- relPath := path.Join("options", tp, cleanedName)
-
- // Use custom file when available.
- customPath := path.Join(setting.CustomPath, relPath)
- isFile, err := util.IsFile(customPath)
- if err != nil {
- log.Error("Unable to check if %s is a file. Error: %v", customPath, err)
- }
- if isFile {
- return os.ReadFile(customPath)
- }
-
- switch tp {
- case "readme":
- return options.Readme(cleanedName)
- case "gitignore":
- return options.Gitignore(cleanedName)
- case "license":
- return options.License(cleanedName)
- case "label":
- return options.Labels(cleanedName)
- default:
- return []byte{}, fmt.Errorf("Invalid init file type")
- }
-}
-
-// GetLabelTemplateFile loads the label template file by given name,
-// then parses and returns a list of name-color pairs and optionally description.
-func GetLabelTemplateFile(name string) ([][3]string, error) {
- data, err := GetRepoInitFile("label", name)
- if err != nil {
- return nil, ErrIssueLabelTemplateLoad{name, fmt.Errorf("GetRepoInitFile: %w", err)}
- }
-
- lines := strings.Split(string(data), "\n")
- list := make([][3]string, 0, len(lines))
- for i := 0; i < len(lines); i++ {
- line := strings.TrimSpace(lines[i])
- if len(line) == 0 {
- continue
- }
-
- parts := strings.SplitN(line, ";", 2)
-
- fields := strings.SplitN(parts[0], " ", 2)
- if len(fields) != 2 {
- return nil, ErrIssueLabelTemplateLoad{name, fmt.Errorf("line is malformed: %s", line)}
- }
-
- color := strings.Trim(fields[0], " ")
- if len(color) == 6 {
- color = "#" + color
- }
- if !issues_model.LabelColorPattern.MatchString(color) {
- return nil, ErrIssueLabelTemplateLoad{name, fmt.Errorf("bad HTML color code in line: %s", line)}
- }
-
- var description string
-
- if len(parts) > 1 {
- description = strings.TrimSpace(parts[1])
- }
-
- fields[1] = strings.TrimSpace(fields[1])
- list = append(list, [3]string{fields[1], color, description})
- }
-
- return list, nil
-}
-
-func loadLabels(labelTemplate string) ([]string, error) {
- list, err := GetLabelTemplateFile(labelTemplate)
- if err != nil {
- return nil, err
- }
-
- labels := make([]string, len(list))
- for i := 0; i < len(list); i++ {
- labels[i] = list[i][0]
- }
- return labels, nil
-}
-
-// LoadLabelsFormatted loads the labels' list of a template file as a string separated by comma
-func LoadLabelsFormatted(labelTemplate string) (string, error) {
- labels, err := loadLabels(labelTemplate)
- return strings.Join(labels, ", "), err
-}
-
// LoadRepoConfig loads the repository config
func LoadRepoConfig() {
// Load .gitignore and license files and readme templates.
@@ -158,6 +51,14 @@ func LoadRepoConfig() {
if err != nil {
log.Fatal("Failed to get %s files: %v", t, err)
}
+ if t == "label" {
+ for i, f := range files {
+ ext := strings.ToLower(filepath.Ext(f))
+ if ext == ".yaml" || ext == ".yml" {
+ files[i] = f[:len(f)-len(ext)]
+ }
+ }
+ }
customPath := path.Join(setting.CustomPath, "options", t)
isDir, err := util.IsDir(customPath)
if err != nil {
@@ -190,7 +91,7 @@ func LoadRepoConfig() {
// Load label templates
LabelTemplates = make(map[string]string)
for _, templateFile := range LabelTemplatesFiles {
- labels, err := LoadLabelsFormatted(templateFile)
+ labels, err := label.LoadFormatted(templateFile)
if err != nil {
log.Error("Failed to load labels: %v", err)
}
@@ -235,7 +136,7 @@ func prepareRepoCommit(ctx context.Context, repo *repo_model.Repository, tmpDir,
}
// README
- data, err := GetRepoInitFile("readme", opts.Readme)
+ data, err := options.Readme(opts.Readme)
if err != nil {
return fmt.Errorf("GetRepoInitFile[%s]: %w", opts.Readme, err)
}
@@ -263,7 +164,7 @@ func prepareRepoCommit(ctx context.Context, repo *repo_model.Repository, tmpDir,
var buf bytes.Buffer
names := strings.Split(opts.Gitignores, ",")
for _, name := range names {
- data, err = GetRepoInitFile("gitignore", name)
+ data, err = options.Gitignore(name)
if err != nil {
return fmt.Errorf("GetRepoInitFile[%s]: %w", name, err)
}
@@ -281,7 +182,7 @@ func prepareRepoCommit(ctx context.Context, repo *repo_model.Repository, tmpDir,
// LICENSE
if len(opts.License) > 0 {
- data, err = GetRepoInitFile("license", opts.License)
+ data, err = options.License(opts.License)
if err != nil {
return fmt.Errorf("GetRepoInitFile[%s]: %w", opts.License, err)
}
@@ -443,7 +344,7 @@ func initRepository(ctx context.Context, repoPath string, u *user_model.User, re
// InitializeLabels adds a label set to a repository using a template
func InitializeLabels(ctx context.Context, id int64, labelTemplate string, isOrg bool) error {
- list, err := GetLabelTemplateFile(labelTemplate)
+ list, err := label.GetTemplateFile(labelTemplate)
if err != nil {
return err
}
@@ -451,9 +352,10 @@ func InitializeLabels(ctx context.Context, id int64, labelTemplate string, isOrg
labels := make([]*issues_model.Label, len(list))
for i := 0; i < len(list); i++ {
labels[i] = &issues_model.Label{
- Name: list[i][0],
- Description: list[i][2],
- Color: list[i][1],
+ Name: list[i].Name,
+ Exclusive: list[i].Exclusive,
+ Description: list[i].Description,
+ Color: list[i].Color,
}
if isOrg {
labels[i].OrgID = id
diff --git a/modules/repository/push.go b/modules/repository/push.go
index 1fa711b35..aa1552351 100644
--- a/modules/repository/push.go
+++ b/modules/repository/push.go
@@ -4,10 +4,8 @@
package repository
import (
- "context"
"strings"
- repo_model "code.gitea.io/gitea/models/repo"
"code.gitea.io/gitea/modules/git"
)
@@ -96,19 +94,3 @@ func (opts *PushUpdateOptions) RefName() string {
func (opts *PushUpdateOptions) RepoFullName() string {
return opts.RepoUserName + "/" + opts.RepoName
}
-
-// IsForcePush detect if a push is a force push
-func IsForcePush(ctx context.Context, opts *PushUpdateOptions) (bool, error) {
- if !opts.IsUpdateBranch() {
- return false, nil
- }
-
- output, _, err := git.NewCommand(ctx, "rev-list", "--max-count=1").AddDynamicArguments(opts.OldCommitID, "^"+opts.NewCommitID).
- RunStdString(&git.RunOpts{Dir: repo_model.RepoPath(opts.RepoUserName, opts.RepoName)})
- if err != nil {
- return false, err
- } else if len(output) > 0 {
- return true, nil
- }
- return false, nil
-}
diff --git a/modules/setting/database.go b/modules/setting/database.go
index 49865a38a..d7a5078fe 100644
--- a/modules/setting/database.go
+++ b/modules/setting/database.go
@@ -27,7 +27,7 @@ var (
// Database holds the database settings
Database = struct {
- Type string
+ Type DatabaseType
Host string
Name string
User string
@@ -39,10 +39,6 @@ var (
Charset string
Timeout int // seconds
SQLiteJournalMode string
- UseSQLite3 bool
- UseMySQL bool
- UseMSSQL bool
- UsePostgreSQL bool
DBConnectRetries int
DBConnectBackoff time.Duration
MaxIdleConns int
@@ -59,24 +55,13 @@ var (
// LoadDBSetting loads the database settings
func LoadDBSetting() {
sec := CfgProvider.Section("database")
- Database.Type = sec.Key("DB_TYPE").String()
+ Database.Type = DatabaseType(sec.Key("DB_TYPE").String())
defaultCharset := "utf8"
- Database.UseMySQL = false
- Database.UseSQLite3 = false
- Database.UsePostgreSQL = false
- Database.UseMSSQL = false
- switch Database.Type {
- case "sqlite3":
- Database.UseSQLite3 = true
- case "mysql":
- Database.UseMySQL = true
+ if Database.Type.IsMySQL() {
defaultCharset = "utf8mb4"
- case "postgres":
- Database.UsePostgreSQL = true
- case "mssql":
- Database.UseMSSQL = true
}
+
Database.Host = sec.Key("HOST").String()
Database.Name = sec.Key("NAME").String()
Database.User = sec.Key("USER").String()
@@ -86,7 +71,7 @@ func LoadDBSetting() {
Database.Schema = sec.Key("SCHEMA").String()
Database.SSLMode = sec.Key("SSL_MODE").MustString("disable")
Database.Charset = sec.Key("CHARSET").In(defaultCharset, []string{"utf8", "utf8mb4"})
- if Database.UseMySQL && defaultCharset != "utf8mb4" {
+ if Database.Type.IsMySQL() && defaultCharset != "utf8mb4" {
log.Error("Deprecated database mysql charset utf8 support, please use utf8mb4 or convert utf8 to utf8mb4.")
}
@@ -95,7 +80,7 @@ func LoadDBSetting() {
Database.SQLiteJournalMode = sec.Key("SQLITE_JOURNAL_MODE").MustString("")
Database.MaxIdleConns = sec.Key("MAX_IDLE_CONNS").MustInt(2)
- if Database.UseMySQL {
+ if Database.Type.IsMySQL() {
Database.ConnMaxLifetime = sec.Key("CONN_MAX_LIFETIME").MustDuration(3 * time.Second)
} else {
Database.ConnMaxLifetime = sec.Key("CONN_MAX_LIFETIME").MustDuration(0)
@@ -207,3 +192,25 @@ func ParseMSSQLHostPort(info string) (string, string) {
}
return host, port
}
+
+type DatabaseType string
+
+func (t DatabaseType) String() string {
+ return string(t)
+}
+
+func (t DatabaseType) IsSQLite3() bool {
+ return t == "sqlite3"
+}
+
+func (t DatabaseType) IsMySQL() bool {
+ return t == "mysql"
+}
+
+func (t DatabaseType) IsMSSQL() bool {
+ return t == "mssql"
+}
+
+func (t DatabaseType) IsPostgreSQL() bool {
+ return t == "postgres"
+}
diff --git a/modules/setting/log.go b/modules/setting/log.go
index 5448650aa..dabdb543a 100644
--- a/modules/setting/log.go
+++ b/modules/setting/log.go
@@ -38,6 +38,7 @@ var Log struct {
EnableAccessLog bool
AccessLogTemplate string
BufferLength int64
+ RequestIDHeaders []string
}
// GetLogDescriptions returns a race safe set of descriptions
@@ -153,6 +154,7 @@ func loadLogFrom(rootCfg ConfigProvider) {
Log.AccessLogTemplate = sec.Key("ACCESS_LOG_TEMPLATE").MustString(
`{{.Ctx.RemoteAddr}} - {{.Identity}} {{.Start.Format "[02/Jan/2006:15:04:05 -0700]" }} "{{.Ctx.Req.Method}} {{.Ctx.Req.URL.RequestURI}} {{.Ctx.Req.Proto}}" {{.ResponseWriter.Status}} {{.ResponseWriter.Size}} "{{.Ctx.Req.Referer}}\" \"{{.Ctx.Req.UserAgent}}"`,
)
+ Log.RequestIDHeaders = sec.Key("REQUEST_ID_HEADERS").Strings(",")
// the `MustString` updates the default value, and `log.ACCESS` is used by `generateNamedLogger("access")` later
_ = rootCfg.Section("log").Key("ACCESS").MustString("file")
diff --git a/modules/setting/storage.go b/modules/setting/storage.go
index 9197c5f8b..4d401614e 100644
--- a/modules/setting/storage.go
+++ b/modules/setting/storage.go
@@ -41,6 +41,7 @@ func getStorage(rootCfg ConfigProvider, name, typ string, targetSec *ini.Section
sec.Key("MINIO_BUCKET").MustString("gitea")
sec.Key("MINIO_LOCATION").MustString("us-east-1")
sec.Key("MINIO_USE_SSL").MustBool(false)
+ sec.Key("MINIO_INSECURE_SKIP_VERIFY").MustBool(false)
if targetSec == nil {
targetSec, _ = rootCfg.NewSection(name)
diff --git a/modules/storage/local.go b/modules/storage/local.go
index a6a9d54a8..05bf1fb28 100644
--- a/modules/storage/local.go
+++ b/modules/storage/local.go
@@ -8,7 +8,6 @@ import (
"io"
"net/url"
"os"
- "path"
"path/filepath"
"strings"
@@ -59,7 +58,7 @@ func NewLocalStorage(ctx context.Context, cfg interface{}) (ObjectStorage, error
}
func (l *LocalStorage) buildLocalPath(p string) string {
- return filepath.Join(l.dir, path.Clean("/" + strings.ReplaceAll(p, "\\", "/"))[1:])
+ return filepath.Join(l.dir, util.CleanPath(strings.ReplaceAll(p, "\\", "/")))
}
// Open a file
diff --git a/modules/storage/minio.go b/modules/storage/minio.go
index 912f820ed..24da14b63 100644
--- a/modules/storage/minio.go
+++ b/modules/storage/minio.go
@@ -5,7 +5,9 @@ package storage
import (
"context"
+ "crypto/tls"
"io"
+ "net/http"
"net/url"
"os"
"path"
@@ -13,6 +15,7 @@ import (
"time"
"code.gitea.io/gitea/modules/log"
+ "code.gitea.io/gitea/modules/util"
"github.com/minio/minio-go/v7"
"github.com/minio/minio-go/v7/pkg/credentials"
@@ -42,13 +45,14 @@ const MinioStorageType Type = "minio"
// MinioStorageConfig represents the configuration for a minio storage
type MinioStorageConfig struct {
- Endpoint string `ini:"MINIO_ENDPOINT"`
- AccessKeyID string `ini:"MINIO_ACCESS_KEY_ID"`
- SecretAccessKey string `ini:"MINIO_SECRET_ACCESS_KEY"`
- Bucket string `ini:"MINIO_BUCKET"`
- Location string `ini:"MINIO_LOCATION"`
- BasePath string `ini:"MINIO_BASE_PATH"`
- UseSSL bool `ini:"MINIO_USE_SSL"`
+ Endpoint string `ini:"MINIO_ENDPOINT"`
+ AccessKeyID string `ini:"MINIO_ACCESS_KEY_ID"`
+ SecretAccessKey string `ini:"MINIO_SECRET_ACCESS_KEY"`
+ Bucket string `ini:"MINIO_BUCKET"`
+ Location string `ini:"MINIO_LOCATION"`
+ BasePath string `ini:"MINIO_BASE_PATH"`
+ UseSSL bool `ini:"MINIO_USE_SSL"`
+ InsecureSkipVerify bool `ini:"MINIO_INSECURE_SKIP_VERIFY"`
}
// MinioStorage returns a minio bucket storage
@@ -90,8 +94,9 @@ func NewMinioStorage(ctx context.Context, cfg interface{}) (ObjectStorage, error
log.Info("Creating Minio storage at %s:%s with base path %s", config.Endpoint, config.Bucket, config.BasePath)
minioClient, err := minio.New(config.Endpoint, &minio.Options{
- Creds: credentials.NewStaticV4(config.AccessKeyID, config.SecretAccessKey, ""),
- Secure: config.UseSSL,
+ Creds: credentials.NewStaticV4(config.AccessKeyID, config.SecretAccessKey, ""),
+ Secure: config.UseSSL,
+ Transport: &http.Transport{TLSClientConfig: &tls.Config{InsecureSkipVerify: config.InsecureSkipVerify}},
})
if err != nil {
return nil, convertMinioErr(err)
@@ -116,7 +121,7 @@ func NewMinioStorage(ctx context.Context, cfg interface{}) (ObjectStorage, error
}
func (m *MinioStorage) buildMinioPath(p string) string {
- return strings.TrimPrefix(path.Join(m.basePath, path.Clean("/" + strings.ReplaceAll(p, "\\", "/"))[1:]), "/")
+ return strings.TrimPrefix(path.Join(m.basePath, util.CleanPath(strings.ReplaceAll(p, "\\", "/"))), "/")
}
// Open open a file
diff --git a/modules/templates/helper.go b/modules/templates/helper.go
index 17ac68dc6..19893c7c9 100644
--- a/modules/templates/helper.go
+++ b/modules/templates/helper.go
@@ -385,10 +385,10 @@ func NewFuncMap() []template.FuncMap {
// the table is NOT sorted with this header
return ""
},
- "RenderLabel": func(label *issues_model.Label) template.HTML {
- return template.HTML(RenderLabel(label))
+ "RenderLabel": func(ctx context.Context, label *issues_model.Label) template.HTML {
+ return template.HTML(RenderLabel(ctx, label))
},
- "RenderLabels": func(labels []*issues_model.Label, repoLink string) template.HTML {
+ "RenderLabels": func(ctx context.Context, labels []*issues_model.Label, repoLink string) template.HTML {
htmlCode := `<span class="labels-list">`
for _, label := range labels {
// Protect against nil value in labels - shouldn't happen but would cause a panic if so
@@ -396,7 +396,7 @@ func NewFuncMap() []template.FuncMap {
continue
}
htmlCode += fmt.Sprintf("<a href='%s/issues?labels=%d'>%s</a> ",
- repoLink, label.ID, RenderLabel(label))
+ repoLink, label.ID, RenderLabel(ctx, label))
}
htmlCode += "</span>"
return template.HTML(htmlCode)
@@ -808,7 +808,7 @@ func RenderIssueTitle(ctx context.Context, text, urlPrefix string, metas map[str
}
// RenderLabel renders a label
-func RenderLabel(label *issues_model.Label) string {
+func RenderLabel(ctx context.Context, label *issues_model.Label) string {
labelScope := label.ExclusiveScope()
textColor := "#111"
@@ -821,12 +821,12 @@ func RenderLabel(label *issues_model.Label) string {
if labelScope == "" {
// Regular label
return fmt.Sprintf("<div class='ui label' style='color: %s !important; background-color: %s !important' title='%s'>%s</div>",
- textColor, label.Color, description, RenderEmoji(label.Name))
+ textColor, label.Color, description, RenderEmoji(ctx, label.Name))
}
// Scoped label
- scopeText := RenderEmoji(labelScope)
- itemText := RenderEmoji(label.Name[len(labelScope)+1:])
+ scopeText := RenderEmoji(ctx, labelScope)
+ itemText := RenderEmoji(ctx, label.Name[len(labelScope)+1:])
itemColor := label.Color
scopeColor := label.Color
@@ -869,8 +869,9 @@ func RenderLabel(label *issues_model.Label) string {
}
// RenderEmoji renders html text with emoji post processors
-func RenderEmoji(text string) template.HTML {
- renderedText, err := markup.RenderEmoji(template.HTMLEscapeString(text))
+func RenderEmoji(ctx context.Context, text string) template.HTML {
+ renderedText, err := markup.RenderEmoji(&markup.RenderContext{Ctx: ctx},
+ template.HTMLEscapeString(text))
if err != nil {
log.Error("RenderEmoji: %v", err)
return template.HTML("")
diff --git a/modules/typesniffer/typesniffer.go b/modules/typesniffer/typesniffer.go
index c9fef953c..7887fd42b 100644
--- a/modules/typesniffer/typesniffer.go
+++ b/modules/typesniffer/typesniffer.go
@@ -4,6 +4,7 @@
package typesniffer
import (
+ "bytes"
"fmt"
"io"
"net/http"
@@ -24,8 +25,9 @@ const (
)
var (
- svgTagRegex = regexp.MustCompile(`(?si)\A\s*(?:(<!--.*?-->|<!DOCTYPE\s+svg([\s:]+.*?>|>))\s*)*<svg[\s>\/]`)
- svgTagInXMLRegex = regexp.MustCompile(`(?si)\A<\?xml\b.*?\?>\s*(?:(<!--.*?-->|<!DOCTYPE\s+svg([\s:]+.*?>|>))\s*)*<svg[\s>\/]`)
+ svgComment = regexp.MustCompile(`(?s)<!--.*?-->`)
+ svgTagRegex = regexp.MustCompile(`(?si)\A\s*(?:(<!DOCTYPE\s+svg([\s:]+.*?>|>))\s*)*<svg\b`)
+ svgTagInXMLRegex = regexp.MustCompile(`(?si)\A<\?xml\b.*?\?>\s*(?:(<!DOCTYPE\s+svg([\s:]+.*?>|>))\s*)*<svg\b`)
)
// SniffedType contains information about a blobs type.
@@ -91,10 +93,27 @@ func DetectContentType(data []byte) SniffedType {
data = data[:sniffLen]
}
- if (strings.Contains(ct, "text/plain") || strings.Contains(ct, "text/html")) && svgTagRegex.Match(data) ||
- strings.Contains(ct, "text/xml") && svgTagInXMLRegex.Match(data) {
- // SVG is unsupported. https://github.com/golang/go/issues/15888
- ct = SvgMimeType
+ // SVG is unsupported by http.DetectContentType, https://github.com/golang/go/issues/15888
+
+ detectByHTML := strings.Contains(ct, "text/plain") || strings.Contains(ct, "text/html")
+ detectByXML := strings.Contains(ct, "text/xml")
+ if detectByHTML || detectByXML {
+ dataProcessed := svgComment.ReplaceAll(data, nil)
+ dataProcessed = bytes.TrimSpace(dataProcessed)
+ if detectByHTML && svgTagRegex.Match(dataProcessed) ||
+ detectByXML && svgTagInXMLRegex.Match(dataProcessed) {
+ ct = SvgMimeType
+ }
+ }
+
+ if strings.HasPrefix(ct, "audio/") && bytes.HasPrefix(data, []byte("ID3")) {
+ // The MP3 detection is quite inaccurate, any content with "ID3" prefix will result in "audio/mpeg".
+ // So remove the "ID3" prefix and detect again, if result is text, then it must be text content.
+ // This works especially because audio files contain many unprintable/invalid characters like `0x00`
+ ct2 := http.DetectContentType(data[3:])
+ if strings.HasPrefix(ct2, "text/") {
+ ct = ct2
+ }
}
return SniffedType{ct}
diff --git a/modules/typesniffer/typesniffer_test.go b/modules/typesniffer/typesniffer_test.go
index dbce94fc3..6c6da34aa 100644
--- a/modules/typesniffer/typesniffer_test.go
+++ b/modules/typesniffer/typesniffer_test.go
@@ -28,7 +28,6 @@ func TestIsSvgImage(t *testing.T) {
assert.True(t, DetectContentType([]byte("<svg></svg>")).IsSvgImage())
assert.True(t, DetectContentType([]byte(" <svg></svg>")).IsSvgImage())
assert.True(t, DetectContentType([]byte(`<svg width="100"></svg>`)).IsSvgImage())
- assert.True(t, DetectContentType([]byte("<svg/>")).IsSvgImage())
assert.True(t, DetectContentType([]byte(`<?xml version="1.0" encoding="UTF-8"?><svg></svg>`)).IsSvgImage())
assert.True(t, DetectContentType([]byte(`<!-- Comment -->
<svg></svg>`)).IsSvgImage())
@@ -57,6 +56,10 @@ func TestIsSvgImage(t *testing.T) {
<!-- Multline
Comment -->
<svg></svg>`)).IsSvgImage())
+
+ // the DetectContentType should work for incomplete data, because only beginning bytes are used for detection
+ assert.True(t, DetectContentType([]byte(`<svg>....`)).IsSvgImage())
+
assert.False(t, DetectContentType([]byte{}).IsSvgImage())
assert.False(t, DetectContentType([]byte("svg")).IsSvgImage())
assert.False(t, DetectContentType([]byte("<svgfoo></svgfoo>")).IsSvgImage())
@@ -68,6 +71,26 @@ func TestIsSvgImage(t *testing.T) {
assert.False(t, DetectContentType([]byte(`<?xml version="1.0" encoding="UTF-8"?>
<!-- <svg></svg> inside comment -->
<foo></foo>`)).IsSvgImage())
+
+ assert.False(t, DetectContentType([]byte(`
+<!-- comment1 -->
+<div>
+ <!-- comment2 -->
+ <svg></svg>
+</div>
+`)).IsSvgImage())
+
+ assert.False(t, DetectContentType([]byte(`
+<!-- comment1
+-->
+<div>
+ <!-- comment2
+-->
+ <svg></svg>
+</div>
+`)).IsSvgImage())
+ assert.False(t, DetectContentType([]byte(`<html><body><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg></svg></body></html>`)).IsSvgImage())
+ assert.False(t, DetectContentType([]byte(`<html><body><?xml version="1.0" encoding="UTF-8"?><svg></svg></body></html>`)).IsSvgImage())
}
func TestIsPDF(t *testing.T) {
@@ -86,6 +109,10 @@ func TestIsAudio(t *testing.T) {
mp3, _ := base64.StdEncoding.DecodeString("SUQzBAAAAAABAFRYWFgAAAASAAADbWFqb3JfYnJhbmQAbXA0MgBUWFhYAAAAEQAAA21pbm9yX3Zl")
assert.True(t, DetectContentType(mp3).IsAudio())
assert.False(t, DetectContentType([]byte("plain text")).IsAudio())
+
+ assert.True(t, DetectContentType([]byte("ID3Toy\000")).IsAudio())
+ assert.True(t, DetectContentType([]byte("ID3Toy\n====\t* hi 🌞, ...")).IsText()) // test ID3 tag for plain text
+ assert.True(t, DetectContentType([]byte("ID3Toy\n====\t* hi 🌞, ..."+"🌛"[0:2])).IsText()) // test ID3 tag with incomplete UTF8 char
}
func TestDetectContentTypeFromReader(t *testing.T) {
diff --git a/modules/util/path.go b/modules/util/path.go
index 74acb7a85..5aa9e15f5 100644
--- a/modules/util/path.go
+++ b/modules/util/path.go
@@ -14,6 +14,14 @@ import (
"strings"
)
+// CleanPath ensure to clean the path
+func CleanPath(p string) string {
+ if strings.HasPrefix(p, "/") {
+ return path.Clean(p)
+ }
+ return path.Clean("/" + p)[1:]
+}
+
// EnsureAbsolutePath ensure that a path is absolute, making it
// relative to absoluteBase if necessary
func EnsureAbsolutePath(path, absoluteBase string) string {
diff --git a/modules/util/path_test.go b/modules/util/path_test.go
index 93f4f67cf..2f020f924 100644
--- a/modules/util/path_test.go
+++ b/modules/util/path_test.go
@@ -136,3 +136,15 @@ func TestMisc_IsReadmeFileName(t *testing.T) {
assert.Equal(t, testCase.idx, idx)
}
}
+
+func TestCleanPath(t *testing.T) {
+ cases := map[string]string{
+ "../../test": "test",
+ "/test": "/test",
+ "/../test": "/test",
+ }
+
+ for k, v := range cases {
+ assert.Equal(t, v, CleanPath(k))
+ }
+}
diff --git a/options/label/Advanced.yaml b/options/label/Advanced.yaml
new file mode 100644
index 000000000..27b2c1463
--- /dev/null
+++ b/options/label/Advanced.yaml
@@ -0,0 +1,70 @@
+labels:
+ - name: "Kind/Bug"
+ color: ee0701
+ description: Something is not working
+ - name: "Kind/Feature"
+ color: 0288d1
+ description: New functionality
+ - name: "Kind/Enhancement"
+ color: 84b6eb
+ description: Improve existing functionality
+ - name: "Kind/Security"
+ color: 9c27b0
+ description: This is security issue
+ - name: "Kind/Testing"
+ color: 795548
+ description: Issue or pull request related to testing
+ - name: "Kind/Breaking"
+ color: c62828
+ description: Breaking change that won't be backward compatible
+ - name: "Kind/Documentation"
+ color: 37474f
+ description: Documentation changes
+ - name: "Reviewed/Duplicate"
+ exclusive: true
+ color: 616161
+ description: This issue or pull request already exists
+ - name: "Reviewed/Invalid"
+ exclusive: true
+ color: 546e7a
+ description: Invalid issue
+ - name: "Reviewed/Confirmed"
+ exclusive: true
+ color: 795548
+ description: Issue has been confirmed
+ - name: "Reviewed/Won't Fix"
+ exclusive: true
+ color: eeeeee
+ description: This issue won't be fixed
+ - name: "Status/Need More Info"
+ exclusive: true
+ color: 424242
+ description: Feedback is required to reproduce issue or to continue work
+ - name: "Status/Blocked"
+ exclusive: true
+ color: 880e4f
+ description: Something is blocking this issue or pull request
+ - name: "Status/Abandoned"
+ exclusive: true
+ color: "222222"
+ description: Somebody has started to work on this but abandoned work
+ - name: "Priority/Critical"
+ exclusive: true
+ color: b71c1c
+ description: The priority is critical
+ priority: critical
+ - name: "Priority/High"
+ exclusive: true
+ color: d32f2f
+ description: The priority is high
+ priority: high
+ - name: "Priority/Medium"
+ exclusive: true
+ color: e64a19
+ description: The priority is medium
+ priority: medium
+ - name: "Priority/Low"
+ exclusive: true
+ color: 4caf50
+ description: The priority is low
+ priority: low
diff --git a/options/license/AdaCore-doc b/options/license/AdaCore-doc
new file mode 100644
index 000000000..0a1dab1b2
--- /dev/null
+++ b/options/license/AdaCore-doc
@@ -0,0 +1 @@
+This document may be copied, in whole or in part, in any form or by any means, as is or with alterations, provided that (1) alterations are clearly marked as alterations and (2) this copyright notice is included unmodified in any copy.
diff --git a/options/license/Autoconf-exception-generic b/options/license/Autoconf-exception-generic
new file mode 100644
index 000000000..b39f82767
--- /dev/null
+++ b/options/license/Autoconf-exception-generic
@@ -0,0 +1,4 @@
+As a special exception to the GNU General Public License,
+if you distribute this file as part of a program that contains
+a configuration script generated by Autoconf, you may include
+it under the same distribution terms that you use for the rest of that program.
diff --git a/options/license/Autoconf-exception-macro b/options/license/Autoconf-exception-macro
new file mode 100644
index 000000000..8b5b4677f
--- /dev/null
+++ b/options/license/Autoconf-exception-macro
@@ -0,0 +1,12 @@
+As a special exception, the respective Autoconf Macro's copyright owner
+gives unlimited permission to copy, distribute and modify the configure
+scripts that are the output of Autoconf when processing the Macro. You
+need not follow the terms of the GNU General Public License when using
+or distributing such scripts, even though portions of the text of the
+Macro appear in them. The GNU General Public License (GPL) does govern
+all other use of the material that constitutes the Autoconf Macro.
+
+This special exception to the GPL applies to versions of the Autoconf
+Macro released by the Autoconf Archive. When you make and distribute a
+modified version of the Autoconf Macro, you may extend this special
+exception to the GPL to apply to your modified version as well.
diff --git a/options/license/BSD-4.3RENO b/options/license/BSD-4.3RENO
new file mode 100644
index 000000000..c05b03cc0
--- /dev/null
+++ b/options/license/BSD-4.3RENO
@@ -0,0 +1,9 @@
+Copyright (c) 1987 Regents of the University of California.
+All rights reserved.
+
+Redistribution and use in source and binary forms are permitted
+provided that this notice is preserved and that due credit is given
+to the University of California at Berkeley. The name of the University
+may not be used to endorse or promote products derived from this
+software without specific written prior permission. This software
+is provided ``as is'' without express or implied warranty.
diff --git a/options/license/BSD-4.3TAHOE b/options/license/BSD-4.3TAHOE
new file mode 100644
index 000000000..413098d93
--- /dev/null
+++ b/options/license/BSD-4.3TAHOE
@@ -0,0 +1,11 @@
+Copyright (c) 1987 Regents of the University of California. All rights reserved.
+
+Redistribution and use in source and binary forms are permitted provided
+that the above copyright notice and this paragraph are duplicated in all
+such forms and that any documentation, advertising materials, and other
+materials related to such distribution and use acknowledge that the software
+was developed by the University of California, Berkeley. The name of the
+University may not be used to endorse or promote products derived from this
+software without specific prior written permission. THIS SOFTWARE IS PROVIDED
+``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT
+LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
diff --git a/options/license/BSD-Advertising-Acknowledgement b/options/license/BSD-Advertising-Acknowledgement
new file mode 100644
index 000000000..cedb72e67
--- /dev/null
+++ b/options/license/BSD-Advertising-Acknowledgement
@@ -0,0 +1,37 @@
+Copyright (c) 2001 David Giffin.
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+1. Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+
+3. All advertising materials mentioning features or use of this
+software must display the following acknowledgment:
+"This product includes software developed by
+David Giffin <david@giffin.org>."
+
+4. Redistributions of any form whatsoever must retain the following
+acknowledgment:
+"This product includes software developed by
+David Giffin <david@giffin.org>."
+
+THIS SOFTWARE IS PROVIDED BY DAVID GIFFIN ``AS IS'' AND ANY
+EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL DAVID GIFFIN OR
+ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/options/license/BSD-Attribution-HPND-disclaimer b/options/license/BSD-Attribution-HPND-disclaimer
new file mode 100644
index 000000000..1272e1fe2
--- /dev/null
+++ b/options/license/BSD-Attribution-HPND-disclaimer
@@ -0,0 +1,37 @@
+Copyright (c) 1998-2003 Carnegie Mellon University. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+
+3. The name "Carnegie Mellon University" must not be used to
+ endorse or promote products derived from this software without
+ prior written permission. For permission or any other legal
+ details, please contact
+ Office of Technology Transfer
+ Carnegie Mellon University
+ 5000 Forbes Avenue
+ Pittsburgh, PA 15213-3890
+ (412) 268-4387, fax: (412) 268-7395
+ tech-transfer@andrew.cmu.edu
+
+4. Redistributions of any form whatsoever must retain the following
+ acknowledgment:
+ "This product includes software developed by Computing Services
+ at Carnegie Mellon University (http://www.cmu.edu/computing/)."
+
+CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO
+THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+AND FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE
+FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
+AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
+OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
diff --git a/options/license/Brian-Gladman-3-Clause b/options/license/Brian-Gladman-3-Clause
new file mode 100644
index 000000000..984c95e3e
--- /dev/null
+++ b/options/license/Brian-Gladman-3-Clause
@@ -0,0 +1,26 @@
+Copyright (c) 2003, Dr Brian Gladman, Worcester, UK. All rights reserved.
+
+LICENSE TERMS
+
+The free distribution and use of this software in both source and binary
+form is allowed (with or without changes) provided that:
+
+ 1. distributions of this source code include the above copyright
+ notice, this list of conditions and the following disclaimer;
+
+ 2. distributions in binary form include the above copyright
+ notice, this list of conditions and the following disclaimer
+ in the documentation and/or other associated materials;
+
+ 3. the copyright holder's name is not used to endorse products
+ built using this software without specific written permission.
+
+ALTERNATIVELY, provided that this notice is retained in full, this product
+may be distributed under the terms of the GNU General Public License (GPL),
+in which case the provisions of the GPL apply INSTEAD OF those given above.
+
+DISCLAIMER
+
+This software is provided 'as is' with no explicit or implied warranties
+in respect of its properties, including, but not limited to, correctness
+and/or fitness for purpose.
diff --git a/options/license/CC-BY-NC-SA-2.0-DE b/options/license/CC-BY-NC-SA-2.0-DE
new file mode 100644
index 000000000..ba4b72ac3
--- /dev/null
+++ b/options/license/CC-BY-NC-SA-2.0-DE
@@ -0,0 +1,85 @@
+Creative Commons Namensnennung — Nicht-kommerziell — Weitergabe unter gleichen Bedingungen 2.0
+
+CREATIVE COMMONS IST KEINE RECHTSANWALTSGESELLSCHAFT UND LEISTET KEINE RECHTSBERATUNG. DIE WEITERGABE DIESES LIZENZENTWURFES FÜHRT ZU KEINEM MANDATSVERHÄLTNIS. CREATIVE COMMONS ERBRINGT DIESE INFORMATIONEN OHNE GEWÄHR. CREATIVE COMMONS ÜBERNIMMT KEINE GEWÄHRLEISTUNG FÜR DIE GELIEFERTEN INFORMATIONEN UND SCHLIEßT DIE HAFTUNG FÜR SCHÄDEN AUS, DIE SICH AUS IHREM GEBRAUCH ERGEBEN.
+
+Lizenzvertrag
+
+DAS URHEBERRECHTLICH GESCHÜTZTE WERK ODER DER SONSTIGE SCHUTZGEGENSTAND (WIE UNTEN BESCHRIEBEN) WIRD UNTER DEN BEDINGUNGEN DIESER CREATIVE COMMONS PUBLIC LICENSE („CCPL“ ODER „LIZENZVERTRAG“) ZUR VERFÜGUNG GESTELLT. DER SCHUTZGEGENSTAND IST DURCH DAS URHEBERRECHT UND/ODER EINSCHLÄGIGE GESETZE GESCHÜTZT.
+
+DURCH DIE AUSÜBUNG EINES DURCH DIESEN LIZENZVERTRAG GEWÄHRTEN RECHTS AN DEM SCHUTZGEGENSTAND ERKLÄREN SIE SICH MIT DEN LIZENZBEDINGUNGEN RECHTSVERBINDLICH EINVERSTANDEN. DER LIZENZGEBER RÄUMT IHNEN DIE HIER BESCHRIEBENEN RECHTE UNTER DER VORAUSSETZUNGEIN, DASS SIE SICH MIT DIESEN VERTRAGSBEDINGUNGEN EINVERSTANDEN ERKLÄREN.
+
+1. Definitionen
+
+ a. Unter einer „Bearbeitung“ wird eine Übersetzung oder andere Bearbeitung des Werkes verstanden, die Ihre persönliche geistige Schöpfung ist. Eine freie Benutzung des Werkes wird nicht als Bearbeitung angesehen.
+
+ b. Unter den „Lizenzelementen“ werden die folgenden Lizenzcharakteristika verstanden, die vom Lizenzgeber ausgewählt und in der Bezeichnung der Lizenz genannt werden: „Namensnennung“, „Nicht-kommerziell“, „Weitergabe unter gleichen Bedingungen“.
+
+ c. Unter dem „Lizenzgeber“ wird die natürliche oder juristische Person verstanden, die den Schutzgegenstand unter den Bedingungen dieser Lizenz anbietet.
+
+ d. Unter einem „Sammelwerk“ wird eine Sammlung von Werken, Daten oder anderen unabhängigen Elementen verstanden, die aufgrund der Auswahl oder Anordnung der Elemente eine persönliche geistige Schöpfung ist. Darunter fallen auch solche Sammelwerke, deren Elemente systematisch oder methodisch angeordnet und einzeln mit Hilfe elektronischer Mittel oder auf andere Weise zugänglich sind (Datenbankwerke). Ein Sammelwerk wird im Zusammenhang mit dieser Lizenz nicht als Bearbeitung (wie oben beschrieben) angesehen.
+
+ e. Mit „SIE“ und „Ihnen“ ist die natürliche oder juristische Person gemeint, die die durch diese Lizenz gewährten Nutzungsrechte ausübt und die zuvor die Bedingungen dieser Lizenz im Hinblick auf das Werk nicht verletzt hat, oder die die ausdrückliche Erlaubnis des Lizenzgebers erhalten hat, die durch diese Lizenz gewährten Nutzungsrechte trotz einer vorherigen Verletzung auszuüben.
+
+ f. Unter dem „Schutzgegenstand“wird das Werk oder Sammelwerk oder das Schutzobjekt eines verwandten Schutzrechts, das Ihnen unter den Bedingungen dieser Lizenz angeboten wird, verstanden
+
+ g. Unter dem „Urheber“ wird die natürliche Person verstanden, die das Werk geschaffen hat.
+
+ h. Unter einem „verwandten Schutzrecht“ wird das Recht an einem anderen urheberrechtlichen Schutzgegenstand als einem Werk verstanden, zum Beispiel einer wissenschaftlichen Ausgabe, einem nachgelassenen Werk, einem Lichtbild, einer Datenbank, einem Tonträger, einer Funksendung, einem Laufbild oder einer Darbietung eines ausübenden Künstlers.
+
+ i. Unter dem „Werk“ wird eine persönliche geistige Schöpfung verstanden, die Ihnen unter den Bedingungen dieser Lizenz angeboten wird.
+
+2. Schranken des Urheberrechts. Diese Lizenz lässt sämtliche Befugnisse unberührt, die sich aus den Schranken des Urheberrechts,aus dem Erschöpfungsgrundsatz oder anderen Beschränkungen der Ausschließlichkeitsrechte des Rechtsinhabers ergeben.
+
+3. Lizenzierung. Unter den Bedingungen dieses Lizenzvertrages räumt Ihnen der Lizenzgeber ein lizenzgebührenfreies, räumlich und zeitlich (für die Dauer des Urheberrechts oder verwandten Schutzrechts) unbeschränktes einfaches Nutzungsrecht ein, den Schutzgegenstand in der folgenden Art und Weise zu nutzen:
+
+ a. den Schutzgegenstand in körperlicher Form zu verwerten, insbesondere zu vervielfältigen, zu verbreiten und auszustellen;
+
+ b. den Schutzgegenstand in unkörperlicher Form öffentlich wiederzugeben, insbesondere vorzutragen, aufzuführen und vorzuführen, öffentlich zugänglich zu machen, zu senden, durch Bild- und Tonträger wiederzugeben sowie Funksendungen und öffentliche Zugänglichmachungen wiederzugeben;
+
+ c. den Schutzgegenstand auf Bild- oder Tonträger aufzunehmen, Lichtbilder davon herzustellen, weiterzusenden und in dem in a. und b. genannten Umfang zu verwerten;
+
+ d. den Schutzgegenstand zu bearbeiten oder in anderer Weise umzugestalten und die Bearbeitungen zu veröffentlichen und in dem in a. bis c. genannten Umfang zu verwerten;
+
+Die genannten Nutzungsrechte können für alle bekannten Nutzungsarten ausgeübt werden. Die genannten Nutzungsrechte beinhalten das Recht, solche Veränderungen an dem Werk vorzunehmen, die technisch erforderlich sind, um die Nutzungsrechte für alle Nutzungsarten wahrzunehmen. Insbesondere sind davon die Anpassung an andere Medien und auf andere Dateiformate umfasst.
+
+4. Beschränkungen. Die Einräumung der Nutzungsrechte gemäß Ziffer 3 erfolgt ausdrücklich nur unter den folgenden Bedingungen:
+
+ a. Sie dürfen den Schutzgegenstand ausschließlich unter den Bedingungen dieser Lizenz vervielfältigen, verbreiten oder öffentlich wiedergeben, und Sie müssen stets eine Kopie oder die vollständige Internetadresse in Form des Uniform-Resource-Identifier (URI) dieser Lizenz beifügen, wenn Sie den Schutzgegenstandvervielfältigen, verbreiten oder öffentlich wiedergeben. Sie dürfen keine Vertragsbedingungen anbieten oder fordern, die die Bedingungen dieser Lizenz oder die durch sie gewährten Rechte ändern oder beschränken. Sie dürfen den Schutzgegenstand nicht unterlizenzieren. Sie müssen alle Hinweise unverändert lassen, die auf diese Lizenz und den Haftungsausschluss hinweisen. Sie dürfen den Schutzgegenstand mit keinen technischen Schutzmaßnahmen versehen, die den Zugang oder den Gebrauch des Schutzgegenstandes in einer Weise kontrollieren, die mit den Bedingungen dieser Lizenz im Widerspruch stehen. Die genannten Beschränkungen gelten auch für den Fall, dass der Schutzgegenstand einen Bestandteil eines Sammelwerkes bildet; sie verlangen aber nicht, dass das Sammelwerk insgesamt zum Gegenstand dieser Lizenz gemacht wird. Wenn Sie ein Sammelwerk erstellen, müssen Sie - soweit dies praktikabel ist - auf die Mitteilung eines Lizenzgebers oder Urhebers hin aus dem Sammelwerk jeglichen Hinweis auf diesen Lizenzgeber oder diesen Urheber entfernen. Wenn Sie den Schutzgegenstand bearbeiten, müssen Sie - soweit dies praktikabel ist- auf die Aufforderung eines Rechtsinhabers hin von der Bearbeitung jeglichen Hinweis auf diesen Rechtsinhaber entfernen.
+
+ b. Sie dürfen eine Bearbeitung ausschließlich unter den Bedingungen dieser Lizenz, einer späteren Version dieser Lizenz mit denselben Lizenzelementen wie diese Lizenz oder einer Creative Commons iCommons Lizenz, die dieselben Lizenzelemente wie diese Lizenz enthält (z.B. Namensnennung - Nicht-kommerziell - Weitergabe unter gleichen Bedingungen 2.0 Japan), vervielfältigen, verbreiten oder öffentlich wiedergeben. Sie müssen stets eine Kopie oder die Internetadresse in Form des Uniform-Resource-Identifier (URI) dieser Lizenz oder einer anderen Lizenz der im vorhergehenden Satz beschriebenen Art beifügen, wenn Sie die Bearbeitung vervielfältigen, verbreiten oder öffentlich wiedergeben. Sie dürfen keine Vertragsbedingungen anbieten oder fordern, die die Bedingungen dieser Lizenz oder die durch sie gewährten Rechte ändern oder beschränken, und Sie müssen alle Hinweise unverändert lassen, die auf diese Lizenz und den Haftungsausschluss hinweisen. Sie dürfen eine Bearbeitung nicht mit technischen Schutzmaßnahmen versehen, die den Zugang oder den Gebrauch der Bearbeitung in einer Weise kontrollieren, die mit den Bedingungen dieser Lizenz im Widerspruch stehen. Die genannten Beschränkungen gelten auch für eine Bearbeitung als Bestandteil eines Sammelwerkes; sie erfordern aber nicht, dass das Sammelwerk insgesamt zum Gegenstand dieser Lizenz gemacht wird.
+
+ c. Sie dürfen die in Ziffer 3 gewährten Nutzungsrechte in keiner Weise verwenden, die hauptsächlich auf einen geschäftlichen Vorteil oder eine vertraglich geschuldete geldwerte Vergütung abzielt oder darauf gerichtet ist. Erhalten Sie im Zusammenhang mit der Einräumung der Nutzungsrechte ebenfalls einen Schutzgegenstand, ohne dass eine vertragliche Verpflichtung hierzu besteht, so wird dies nicht als geschäftlicher Vorteil oder vertraglich geschuldete geldwerte Vergütung angesehen, wenn keine Zahlung oder geldwerte Vergütung in Verbindung mit dem Austausch der Schutzgegenstände geleistet wird (z.B. File-Sharing).
+
+ d. Wenn Sie den Schutzgegenstand oder eine Bearbeitung oder ein Sammelwerk vervielfältigen, verbreiten oder öffentlich wiedergeben, müssen Sie alle Urhebervermerke für den Schutzgegenstand unverändert lassen und die Urheberschaft oder Rechtsinhaberschaft in einer der von Ihnen vorgenommenen Nutzung angemessenen Form anerkennen, indem Sie den Namen (oder das Pseudonym, falls ein solches verwendet wird) des Urhebers oder Rechteinhabers nennen, wenn dieser angegeben ist. Dies gilt auch für den Titel des Schutzgegenstandes, wenn dieser angeben ist, sowie - in einem vernünftigerweise durchführbaren Umfang - für die mit dem Schutzgegenstand zu verbindende Internetadresse in Form des Uniform-Resource-Identifier (URI), wie sie der Lizenzgeber angegeben hat, sofern dies geschehen ist, es sei denn, diese Internetadresse verweist nicht auf den Urhebervermerk oder die Lizenzinformationen zu dem Schutzgegenstand. Bei einer Bearbeitung ist ein Hinweis darauf aufzuführen, in welcher Form der Schutzgegenstand in die Bearbeitung eingegangen ist (z.B. „Französische Übersetzung des ... (Werk) durch ... (Urheber)“ oder „Das Drehbuch beruht auf dem Werk des ... (Urheber)“). Ein solcher Hinweis kann in jeder angemessenen Weise erfolgen, wobei jedoch bei einer Bearbeitung, einer Datenbank oder einem Sammelwerk der Hinweis zumindest an gleicher Stelle und in ebenso auffälliger Weise zu erfolgen hat wie vergleichbare Hinweise auf andere Rechtsinhaber.
+
+ e. Obwohl die gemäss Ziffer 3 gewährten Nutzungsrechte in umfassender Weise ausgeübt werden dürfen, findet diese Erlaubnis ihre gesetzliche Grenze in den Persönlichkeitsrechten der Urheber und ausübenden Künstler, deren berechtigte geistige und persönliche Interessen bzw. deren Ansehen oder Ruf nicht dadurch gefährdet werden dürfen, dass ein Schutzgegenstand über das gesetzlich zulässige Maß hinaus beeinträchtigt wird.
+
+5. Gewährleistung. Sofern dies von den Vertragsparteien nicht anderweitig schriftlich vereinbart,, bietet der Lizenzgeber keine Gewährleistung für die erteilten Rechte, außer für den Fall, dass Mängel arglistig verschwiegen wurden. Für Mängel anderer Art, insbesondere bei der mangelhaften Lieferung von Verkörperungen des Schutzgegenstandes, richtet sich die Gewährleistung nach der Regelung, die die Person, die Ihnen den Schutzgegenstand zur Verfügung stellt, mit Ihnen außerhalb dieser Lizenz vereinbart, oder - wenn eine solche Regelung nicht getroffen wurde - nach den gesetzlichen Vorschriften.
+
+6. Haftung. Über die in Ziffer 5 genannte Gewährleistung hinaus haftet Ihnen der Lizenzgeber nur für Vorsatz und grobe Fahrlässigkeit.
+
+7. Vertragsende
+
+ a. Dieser Lizenzvertrag und die durch ihn eingeräumten Nutzungsrechte enden automatisch bei jeder Verletzung der Vertragsbedingungen durch Sie. Für natürliche und juristische Personen, die von Ihnen eine Bearbeitung, eine Datenbank oder ein Sammelwerk unter diesen Lizenzbedingungen erhalten haben, gilt die Lizenz jedoch weiter, vorausgesetzt, diese natürlichen oder juristischen Personen erfüllen sämtliche Vertragsbedingungen. Die Ziffern 1, 2, 5, 6, 7 und 8 gelten bei einer Vertragsbeendigung fort.
+
+ b. Unter den oben genannten Bedingungen erfolgt die Lizenz auf unbegrenzte Zeit (für die Dauer des Schutzrechts). Dennoch behält sich der Lizenzgeber das Recht vor, den Schutzgegenstand unter anderen Lizenzbedingungen zu nutzen oder die eigene Weitergabe des Schutzgegenstandes jederzeit zu beenden, vorausgesetzt, dass solche Handlungen nicht dem Widerruf dieser Lizenz dienen (oder jeder anderen Lizenzierung, die auf Grundlage dieser Lizenz erfolgt ist oder erfolgen muss) und diese Lizenz wirksam bleibt, bis Sie unter den oben genannten Voraussetzungen endet.
+
+8. Schlussbestimmungen
+
+ a. Jedes Mal, wenn Sie den Schutzgegenstand vervielfältigen, verbreiten oder öffentlich wiedergeben, bietet der Lizenzgeber dem Erwerber eine Lizenz für den Schutzgegenstand unter denselben Vertragsbedingungen an, unter denen er Ihnen die Lizenz eingeräumt hat.
+
+ b. Jedes Mal, wenn Sie eine Bearbeitung vervielfältigen, verbreiten oder öffentlich wiedergeben, bietet der Lizenzgeber dem Erwerber eine Lizenz für den ursprünglichen Schutzgegenstand unter denselben Vertragsbedingungen an, unter denen er Ihnen die Lizenz eingeräumt hat.
+
+ c. Sollte eine Bestimmung dieses Lizenzvertrages unwirksam sein, so wird die Wirksamkeit der übrigen Lizenzbestimmungen dadurch nicht berührt, und an die Stelle der unwirksamen Bestimmung tritt eine Ersatzregelung, die dem mit der unwirksamen Bestimmung angestrebten Zweck am nächsten kommt.
+
+ d. Nichts soll dahingehend ausgelegt werden, dass auf eine Bestimmung dieses Lizenzvertrages verzichtet oder einer Vertragsverletzung zugestimmt wird, so lange ein solcher Verzicht oder eine solche Zustimmung nicht schriftlich vorliegen und von der verzichtenden oder zustimmenden Vertragspartei unterschrieben sind
+
+ e. Dieser Lizenzvertrag stellt die vollständige Vereinbarung zwischen den Vertragsparteien hinsichtlich des Schutzgegenstandes dar. Es gibt keine weiteren ergänzenden Vereinbarungen oder mündlichen Abreden im Hinblick auf den Schutzgegenstand. Der Lizenzgeber ist an keine zusätzlichen Abreden gebunden, die aus irgendeiner Absprache mit Ihnen entstehen könnten. Der Lizenzvertrag kann nicht ohne eine übereinstimmende schriftliche Vereinbarung zwischen dem Lizenzgeber und Ihnen abgeändert werden.
+
+ f. Auf diesen Lizenzvertrag findet das Recht der Bundesrepublik Deutschland Anwendung.
+
+CREATIVE COMMONS IST KEINE VERTRAGSPARTEI DIESES LIZENZVERTRAGES UND ÜBERNIMMT KEINERLEI GEWÄHRLEISTUNG FÜR DAS WERK. CREATIVE COMMONS IST IHNEN ODER DRITTEN GEGENÜBER NICHT HAFTBAR FÜR SCHÄDEN JEDWEDER ART. UNGEACHTET DER VORSTEHENDEN ZWEI (2) SÄTZE HAT CREATIVE COMMONS ALL RECHTE UND PFLICHTEN EINES LIZENSGEBERS, WENN SICH CREATIVE COMMONS AUSDRÜCKLICH ALS LIZENZGEBER BEZEICHNET.
+
+AUSSER FÜR DEN BESCHRÄNKTEN ZWECK EINES HINWEISES AN DIE ÖFFENTLICHKEIT, DASS DAS WERK UNTER DER CCPL LIZENSIERT WIRD, DARF KENIE VERTRAGSPARTEI DIE MARKE “CREATIVE COMMONS†ODER EINE ÄHNLICHE MARKE ODER DAS LOGO VON CREATIVE COMMONS OHNE VORHERIGE GENEHMIGUNG VON CREATIVE COMMONS NUTZEN. JEDE GESTATTETE NUTZUNG HAT IN ÜBREEINSTIMMUNG MIT DEN JEWEILS GÜLTIGEN NUTZUNGSBEDINGUNGEN FÜR MARKEN VON CREATIVE COMMONS ZU ERFOLGEN, WIE SIE AUF DER WEBSITE ODER IN ANDERER WEISE AUF ANFRAGE VON ZEIT ZU ZEIT ZUGÄNGLICH GEMACHT WERDEN.
+
+CREATIVE COMMONS KANN UNTER https://creativecommons.org KONTAKTIERT WERDEN.
diff --git a/options/license/CFITSIO b/options/license/CFITSIO
new file mode 100644
index 000000000..f2c502057
--- /dev/null
+++ b/options/license/CFITSIO
@@ -0,0 +1,7 @@
+Copyright (Unpublished-all rights reserved under the copyright laws of the United States), U.S. Government as represented by the Administrator of the National Aeronautics and Space Administration. No copyright is claimed in the United States under Title 17, U.S. Code.
+
+Permission to freely use, copy, modify, and distribute this software and its documentation without fee is hereby granted, provided that this copyright notice and disclaimer of warranty appears in all copies.
+
+DISCLAIMER:
+
+THE SOFTWARE IS PROVIDED 'AS IS' WITHOUT ANY WARRANTY OF ANY KIND, EITHER EXPRESSED, IMPLIED, OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, ANY WARRANTY THAT THE SOFTWARE WILL CONFORM TO SPECIFICATIONS, ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND FREEDOM FROM INFRINGEMENT, AND ANY WARRANTY THAT THE DOCUMENTATION WILL CONFORM TO THE SOFTWARE, OR ANY WARRANTY THAT THE SOFTWARE WILL BE ERROR FREE. IN NO EVENT SHALL NASA BE LIABLE FOR ANY DAMAGES, INCLUDING, BUT NOT LIMITED TO, DIRECT, INDIRECT, SPECIAL OR CONSEQUENTIAL DAMAGES, ARISING OUT OF, RESULTING FROM, OR IN ANY WAY CONNECTED WITH THIS SOFTWARE, WHETHER OR NOT BASED UPON WARRANTY, CONTRACT, TORT , OR OTHERWISE, WHETHER OR NOT INJURY WAS SUSTAINED BY PERSONS OR PROPERTY OR OTHERWISE, AND WHETHER OR NOT LOSS WAS SUSTAINED FROM, OR AROSE OUT OF THE RESULTS OF, OR USE OF, THE SOFTWARE OR SERVICES PROVIDED HEREUNDER."
diff --git a/options/license/CMU-Mach b/options/license/CMU-Mach
new file mode 100644
index 000000000..1bb895d4e
--- /dev/null
+++ b/options/license/CMU-Mach
@@ -0,0 +1,22 @@
+Copyright (c) 1991,1990,1989 Carnegie Mellon University
+All Rights Reserved.
+
+Permission to use, copy, modify and distribute this software and its
+documentation is hereby granted, provided that both the copyright
+notice and this permission notice appear in all copies of the
+software, derivative works or modified versions, and any portions
+thereof, and that both notices appear in supporting documentation.
+
+CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+
+Carnegie Mellon requests users of this software to return to
+
+ Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
+ School of Computer Science
+ Carnegie Mellon University
+ Pittsburgh PA 15213-3890
+
+any improvements or extensions that they make and grant Carnegie Mellon
+the rights to redistribute these changes.
diff --git a/options/license/Clips b/options/license/Clips
new file mode 100644
index 000000000..ff5afdd29
--- /dev/null
+++ b/options/license/Clips
@@ -0,0 +1,15 @@
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, and/or sell copies of the Software, and to permit persons
+to whom the Software is furnished to do so.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
+OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
+CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
diff --git a/options/license/Cornell-Lossless-JPEG b/options/license/Cornell-Lossless-JPEG
new file mode 100644
index 000000000..7d2d44394
--- /dev/null
+++ b/options/license/Cornell-Lossless-JPEG
@@ -0,0 +1,20 @@
+Copyright (c) 1993 Cornell University, Kongji Huang
+All rights reserved.
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose, without fee, and without written
+agreement is hereby granted, provided that the above copyright notice
+and the following two paragraphs appear in all copies of this
+software.
+
+IN NO EVENT SHALL THE CORNELL UNIVERSITY BE LIABLE TO ANY PARTY FOR
+DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF CORNELL
+UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+THE CORNELL UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE
+PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND CORNELL UNIVERSITY HAS
+NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS,
+OR MODIFICATIONS.
diff --git a/options/license/GNAT-exception b/options/license/GNAT-exception
new file mode 100644
index 000000000..2b5a96a62
--- /dev/null
+++ b/options/license/GNAT-exception
@@ -0,0 +1,6 @@
+As a special exception, if other files instantiate generics from this
+unit, or you link this unit with other files to produce an executable,
+this unit does not by itself cause the resulting executable to be
+covered by the GNU General Public License. This exception does not
+however invalidate any other reasons why the executable file might be
+covered by the GNU Public License.
diff --git a/options/license/HP-1986 b/options/license/HP-1986
new file mode 100644
index 000000000..35844cb4d
--- /dev/null
+++ b/options/license/HP-1986
@@ -0,0 +1,10 @@
+(c) Copyright 1986 HEWLETT-PACKARD COMPANY
+
+To anyone who acknowledges that this file is provided "AS IS"
+without any express or implied warranty: permission to use, copy,
+modify, and distribute this file for any purpose is hereby granted
+without fee, provided that the above copyright notice and this notice
+appears in all copies, and that the name of Hewlett-Packard Company
+not be used in advertising or publicity pertaining to distribution
+of the software without specific, written prior permission. Hewlett-Packard
+Company makes no representations about the suitability of this software for any purpose.
diff --git a/options/license/HPND-Markus-Kuhn b/options/license/HPND-Markus-Kuhn
new file mode 100644
index 000000000..ca41db161
--- /dev/null
+++ b/options/license/HPND-Markus-Kuhn
@@ -0,0 +1,3 @@
+Permission to use, copy, modify, and distribute this software
+for any purpose and without fee is hereby granted. The author
+disclaims all warranties with regard to this software.
diff --git a/options/license/HPND-sell-variant-MIT-disclaimer b/options/license/HPND-sell-variant-MIT-disclaimer
new file mode 100644
index 000000000..d4464e0c3
--- /dev/null
+++ b/options/license/HPND-sell-variant-MIT-disclaimer
@@ -0,0 +1,20 @@
+by Jim Knoble <jmknoble@pobox.com>
+ Copyright (C) 1999,2000,2001 Jim Knoble
+
+ Permission to use, copy, modify, distribute, and sell this software
+ and its documentation for any purpose is hereby granted without fee,
+ provided that the above copyright notice appear in all copies and
+ that both that copyright notice and this permission notice appear in
+ supporting documentation.
+
++------------+
+| Disclaimer |
++------------+
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ express or implied, including but not limited to the warranties of
+ merchantability, fitness for a particular purpose and
+ noninfringement. In no event shall the author(s) be liable for any
+ claim, damages or other liability, whether in an action of contract,
+ tort or otherwise, arising from, out of or in connection with the
+ software or the use or other dealings in the software.
diff --git a/options/license/IEC-Code-Components-EULA b/options/license/IEC-Code-Components-EULA
new file mode 100644
index 000000000..b74269afd
--- /dev/null
+++ b/options/license/IEC-Code-Components-EULA
@@ -0,0 +1,37 @@
+IEC Code Components End-user licence agreement
+
+Code Components in IEC standards (International Standards, Technical Specifications or
+Technical Reports) which have been identified and approved for licensing, are licensed subject to
+the following conditions:
+
+- Redistributions of software must retain the Copyright Notice, this list of conditions and the
+disclaimer below (“Disclaimerâ€).
+- The software license extends to modifications permitted under the relevant IEC standard.
+- The software license extends to clarifications and corrections approved by IEC.
+- Neither the name of IEC, nor the names of specific contributors, may be used to endorse or
+promote products derived from this software without specific prior written permission. The
+relevant IEC standard may be referenced when claiming compliance with the relevant IEC
+standard.
+- The user of Code Components shall attribute each such Code Component to IEC and identify
+the IEC standard from which it is taken. Such attribution (e.g., “This code was derived from IEC
+[insert standard reference number:publication year] within modifications permitted in the
+relevant IEC standard. Please reproduce this note if possible.â€), may be placed in the code itself
+or any other reasonable location.
+
+Code Components means components included in IEC standards that are intended to be directly
+processed by a computer and also includes any text found between the markers <CODE
+BEGINS> and <CODE ENDS>, or otherwise clearly labeled in this standard as a Code
+Component.
+
+The Disclaimer is:
+EACH OF THE CODE COMPONENTS IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+CONTRIBUTORS “AS IS†AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT
+NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE CODE
+COMPONENTS, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/options/license/JPL-image b/options/license/JPL-image
new file mode 100644
index 000000000..828b1b542
--- /dev/null
+++ b/options/license/JPL-image
@@ -0,0 +1,21 @@
+JPL Image Use Policy
+
+Unless otherwise noted, images and video on JPL public web sites (public sites ending with a jpl.nasa.gov address) may be used for any purpose without prior permission, subject to the special cases noted below. Publishers who wish to have authorization may print this page and retain it for their records; JPL does not issue image permissions on an image by image basis.
+
+By electing to download the material from this web site the user agrees:
+
+1. that Caltech makes no representations or warranties with respect to ownership of copyrights in the images, and does not represent others who may claim to be authors or owners of copyright of any of the images, and makes no warranties as to the quality of the images. Caltech shall not be responsible for any loss or expenses resulting from the use of the images, and you release and hold Caltech harmless from all liability arising from such use.
+2. to use a credit line in connection with images. Unless otherwise noted in the caption information for an image, the credit line should be "Courtesy NASA/JPL-Caltech."
+3. that the endorsement of any product or service by Caltech, JPL or NASA must not be claimed or implied.
+
+Special Cases:
+
+* Prior written approval must be obtained to use the NASA insignia logo (the blue "meatball" insignia), the NASA logotype (the red "worm" logo) and the NASA seal. These images may not be used by persons who are not NASA employees or on products (including Web pages) that are not NASA sponsored. In addition, no image may be used to explicitly or implicitly suggest endorsement by NASA, JPL or Caltech of commercial goods or services. Requests to use NASA logos may be directed to Bert Ulrich, Public Services Division, NASA Headquarters, Code POS, Washington, DC 20546, telephone (202) 358-1713, fax (202) 358-4331, email bert.ulrich@hq.nasa.gov.
+
+* Prior written approval must be obtained to use the JPL logo (stylized JPL letters in red or other colors). Requests to use the JPL logo may be directed to the Institutional Communications Office, email instcomm@jpl.nasa.gov.
+
+* If an image includes an identifiable person, using the image for commercial purposes may infringe that person's right of privacy or publicity, and permission should be obtained from the person. NASA and JPL generally do not permit likenesses of current employees to appear on commercial products. For more information, consult the NASA and JPL points of contact listed above.
+
+* JPL/Caltech contractors and vendors who wish to use JPL images in advertising or public relation materials should direct requests to the Institutional Communications Office, email instcomm@jpl.nasa.gov.
+
+* Some image and video materials on JPL public web sites are owned by organizations other than JPL or NASA. These owners have agreed to make their images and video available for journalistic, educational and personal uses, but restrictions are placed on commercial uses. To obtain permission for commercial use, contact the copyright owner listed in each image caption. Ownership of images and video by parties other than JPL and NASA is noted in the caption material with each image.
diff --git a/options/license/Kazlib b/options/license/Kazlib
new file mode 100644
index 000000000..714f2eabf
--- /dev/null
+++ b/options/license/Kazlib
@@ -0,0 +1,4 @@
+Copyright (C) 1999 Kaz Kylheku
+
+Free Software License:
+All rights are reserved by the author, with the following exceptions: Permission is granted to freely reproduce and distribute this software, possibly in exchange for a fee, provided that this copyright notice appears intact. Permission is also granted to adapt this software to produce derivative works, as long as the modified versions carry this copyright notice and additional notices stating that the work has been modified. This source code may be translated into executable form and incorporated into proprietary software; there is no requirement for such software to contain a copyright notice related to this source.
diff --git a/options/license/Martin-Birgmeier b/options/license/Martin-Birgmeier
new file mode 100644
index 000000000..48d32f846
--- /dev/null
+++ b/options/license/Martin-Birgmeier
@@ -0,0 +1,5 @@
+Copyright (c) 1993 Martin Birgmeier All rights reserved.
+
+You may redistribute unmodified or modified versions of this source code provided that the above copyright notice and this and the following conditions are retained.
+
+This software is provided ``as is'', and comes with no warranties of any kind. I shall in no event be liable for anything that happens to anyone/anything when using this software.
diff --git a/options/license/OFFIS b/options/license/OFFIS
new file mode 100644
index 000000000..ad48f181c
--- /dev/null
+++ b/options/license/OFFIS
@@ -0,0 +1,22 @@
+Copyright (C) 1994-2001, OFFIS
+
+This software and supporting documentation were developed by
+
+Kuratorium OFFIS e.V.
+Healthcare Information and Communication Systems
+Escherweg 2
+D-26121 Oldenburg, Germany
+
+THIS SOFTWARE IS MADE AVAILABLE, AS IS, AND OFFIS MAKES NO WARRANTY
+REGARDING THE SOFTWARE, ITS PERFORMANCE, ITS MERCHANTABILITY OR
+FITNESS FOR ANY PARTICULAR USE, FREEDOM FROM ANY COMPUTER DISEASES OR
+ITS CONFORMITY TO ANY SPECIFICATION. THE ENTIRE RISK AS TO QUALITY AND
+PERFORMANCE OF THE SOFTWARE IS WITH THE USER.
+
+Copyright of the software and supporting documentation is, unless
+otherwise stated, owned by OFFIS, and free access is hereby granted as
+a license to use this software, copy this software and prepare
+derivative works based upon this software. However, any distribution
+of this software source code or supporting documentation or derivative
+works (source code and supporting documentation) must include the
+three paragraphs of this copyright notice.
diff --git a/options/license/OpenPBS-2.3 b/options/license/OpenPBS-2.3
new file mode 100644
index 000000000..61f52c220
--- /dev/null
+++ b/options/license/OpenPBS-2.3
@@ -0,0 +1,76 @@
+
+ OpenPBS (Portable Batch System) v2.3 Software License
+
+Copyright (c) 1999-2000 Veridian Information Solutions, Inc.
+All rights reserved.
+
+---------------------------------------------------------------------------
+For a license to use or redistribute the OpenPBS software under conditions
+other than those described below, or to purchase support for this software,
+please contact Veridian Systems, PBS Products Department ("Licensor") at:
+
+ www.OpenPBS.org +1 650 967-4675 sales@OpenPBS.org
+ 877 902-4PBS (US toll-free)
+---------------------------------------------------------------------------
+
+This license covers use of the OpenPBS v2.3 software (the "Software") at
+your site or location, and, for certain users, redistribution of the
+Software to other sites and locations. Use and redistribution of
+OpenPBS v2.3 in source and binary forms, with or without modification,
+are permitted provided that all of the following conditions are met.
+After December 31, 2001, only conditions 3-6 must be met:
+
+1. Commercial and/or non-commercial use of the Software is permitted
+ provided a current software registration is on file at www.OpenPBS.org.
+ If use of this software contributes to a publication, product, or
+ service, proper attribution must be given; see www.OpenPBS.org/credit.html
+
+2. Redistribution in any form is only permitted for non-commercial,
+ non-profit purposes. There can be no charge for the Software or any
+ software incorporating the Software. Further, there can be no
+ expectation of revenue generated as a consequence of redistributing
+ the Software.
+
+3. Any Redistribution of source code must retain the above copyright notice
+ and the acknowledgment contained in paragraph 6, this list of conditions
+ and the disclaimer contained in paragraph 7.
+
+4. Any Redistribution in binary form must reproduce the above copyright
+ notice and the acknowledgment contained in paragraph 6, this list of
+ conditions and the disclaimer contained in paragraph 7 in the
+ documentation and/or other materials provided with the distribution.
+
+5. Redistributions in any form must be accompanied by information on how to
+ obtain complete source code for the OpenPBS software and any
+ modifications and/or additions to the OpenPBS software. The source code
+ must either be included in the distribution or be available for no more
+ than the cost of distribution plus a nominal fee, and all modifications
+ and additions to the Software must be freely redistributable by any party
+ (including Licensor) without restriction.
+
+6. All advertising materials mentioning features or use of the Software must
+ display the following acknowledgment:
+
+ "This product includes software developed by NASA Ames Research Center,
+ Lawrence Livermore National Laboratory, and Veridian Information Solutions,
+ Inc. Visit www.OpenPBS.org for OpenPBS software support,
+ products, and information."
+
+7. DISCLAIMER OF WARRANTY
+
+THIS SOFTWARE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND. ANY EXPRESS
+OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT
+ARE EXPRESSLY DISCLAIMED.
+
+IN NO EVENT SHALL VERIDIAN CORPORATION, ITS AFFILIATED COMPANIES, OR THE
+U.S. GOVERNMENT OR ANY OF ITS AGENCIES BE LIABLE FOR ANY DIRECT OR INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+This license will be governed by the laws of the Commonwealth of Virginia,
+without reference to its choice of law rules.
diff --git a/options/license/QPL-1.0-INRIA-2004 b/options/license/QPL-1.0-INRIA-2004
new file mode 100644
index 000000000..45d946e2e
--- /dev/null
+++ b/options/license/QPL-1.0-INRIA-2004
@@ -0,0 +1,102 @@
+ THE Q PUBLIC LICENSE version 1.0
+
+ Copyright (C) 1999 Troll Tech AS, Norway.
+ Everyone is permitted to copy and
+ distribute this license document.
+
+The intent of this license is to establish freedom to share and change
+the software regulated by this license under the open source model.
+
+This license applies to any software containing a notice placed by the
+copyright holder saying that it may be distributed under the terms of
+the Q Public License version 1.0. Such software is herein referred to
+as the Software. This license covers modification and distribution of
+the Software, use of third-party application programs based on the
+Software, and development of free software which uses the Software.
+
+ Granted Rights
+
+1. You are granted the non-exclusive rights set forth in this license
+provided you agree to and comply with any and all conditions in this
+license. Whole or partial distribution of the Software, or software
+items that link with the Software, in any form signifies acceptance of
+this license.
+
+2. You may copy and distribute the Software in unmodified form
+provided that the entire package, including - but not restricted to -
+copyright, trademark notices and disclaimers, as released by the
+initial developer of the Software, is distributed.
+
+3. You may make modifications to the Software and distribute your
+modifications, in a form that is separate from the Software, such as
+patches. The following restrictions apply to modifications:
+
+ a. Modifications must not alter or remove any copyright notices
+ in the Software.
+
+ b. When modifications to the Software are released under this
+ license, a non-exclusive royalty-free right is granted to the
+ initial developer of the Software to distribute your
+ modification in future versions of the Software provided such
+ versions remain available under these terms in addition to any
+ other license(s) of the initial developer.
+
+4. You may distribute machine-executable forms of the Software or
+machine-executable forms of modified versions of the Software,
+provided that you meet these restrictions:
+
+ a. You must include this license document in the distribution.
+
+ b. You must ensure that all recipients of the machine-executable
+ forms are also able to receive the complete machine-readable
+ source code to the distributed Software, including all
+ modifications, without any charge beyond the costs of data
+ transfer, and place prominent notices in the distribution
+ explaining this.
+
+ c. You must ensure that all modifications included in the
+ machine-executable forms are available under the terms of this
+ license.
+
+5. You may use the original or modified versions of the Software to
+compile, link and run application programs legally developed by you or
+by others.
+
+6. You may develop application programs, reusable components and other
+software items that link with the original or modified versions of the
+Software. These items, when distributed, are subject to the following
+requirements:
+
+ a. You must ensure that all recipients of machine-executable
+ forms of these items are also able to receive and use the
+ complete machine-readable source code to the items without any
+ charge beyond the costs of data transfer.
+
+ b. You must explicitly license all recipients of your items to
+ use and re-distribute original and modified versions of the
+ items in both machine-executable and source code forms. The
+ recipients must be able to do so without any charges whatsoever,
+ and they must be able to re-distribute to anyone they choose.
+
+ c. If the items are not available to the general public, and the
+ initial developer of the Software requests a copy of the items,
+ then you must supply one.
+
+ Limitations of Liability
+
+In no event shall the initial developers or copyright holders be
+liable for any damages whatsoever, including - but not restricted to -
+lost revenue or profits or other direct, indirect, special, incidental
+or consequential damages, even if they have been advised of the
+possibility of such damages, except to the extent invariable law, if
+any, provides otherwise.
+
+ No Warranty
+
+The Software and this license document are provided AS IS with NO
+WARRANTY OF ANY KIND, INCLUDING THE WARRANTY OF DESIGN,
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+
+ Choice of Law
+
+This license is governed by the Laws of France.
diff --git a/options/license/QPL-1.0-INRIA-2004-exception b/options/license/QPL-1.0-INRIA-2004-exception
new file mode 100644
index 000000000..2418a2637
--- /dev/null
+++ b/options/license/QPL-1.0-INRIA-2004-exception
@@ -0,0 +1,5 @@
+As a special exception to the Q Public Licence, you may develop
+application programs, reusable components and other software items
+that link with the original or modified versions of the Software
+and are not made available to the general public, without any of the
+additional requirements listed in clause 6c of the Q Public licence.
diff --git a/options/license/SWI-exception b/options/license/SWI-exception
new file mode 100644
index 000000000..9ccfb9b89
--- /dev/null
+++ b/options/license/SWI-exception
@@ -0,0 +1,6 @@
+As a special exception, if you link this library with other files,
+compiled with a Free Software compiler, to produce an executable, this
+library does not by itself cause the resulting executable to be covered
+by the GNU General Public License. This exception does not however
+invalidate any other reasons why the executable file might be covered by
+the GNU General Public License.
diff --git a/options/license/SunPro b/options/license/SunPro
new file mode 100644
index 000000000..1ccb78add
--- /dev/null
+++ b/options/license/SunPro
@@ -0,0 +1,6 @@
+Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+
+Developed at SunSoft, a Sun Microsystems, Inc. business.
+Permission to use, copy, modify, and distribute this
+software is freely granted, provided that this notice
+is preserved.
diff --git a/options/license/TPL-1.0 b/options/license/TPL-1.0
new file mode 100644
index 000000000..1634db491
--- /dev/null
+++ b/options/license/TPL-1.0
@@ -0,0 +1,475 @@
+THOR Public Licence (TPL)
+
+0. Notes of Origin
+
+0.1 As required by paragraph 6.3 of the "Mozilla Public Licence",
+"MPL" in the following, it is hereby stated that this Licence
+condition ("TPL") differs in the following items from the original
+"Mozilla Public Licence" as provided by "Netscape Communications
+Corporation":
+
+a) Paragraphs 6.2 and 6.3 of the MPL has been modified to bind licence
+modifications to the Author of this Licence, Thomas Richter.
+
+b) Paragraph 11 has been modified to gover this Licence by German
+law rather than Californian Law.
+
+c) The licence has been renamed to "TPL" and "THOR Public
+Licence". All references towards "MPL" have been removed except in
+section 0 to indicate the difference from "MPL".
+
+No other modifications have been made.
+
+
+1. Definitions.
+
+1.0.1. "Commercial Use" means distribution or otherwise making the
+Covered Code available to a third party.
+
+1.1. "Contributor" means each entity that creates or contributes to
+the creation of Modifications.
+
+1.2. "Contributor Version" means the combination of the Original Code,
+prior Modifications used by a Contributor, and the Modifications made
+by that particular Contributor.
+
+1.3. "Covered Code" means the Original Code or Modifications or the
+combination of the Original Code and Modifications, in each case
+including portions thereof.
+
+1.4. "Electronic Distribution Mechanism" means a mechanism generally
+accepted in the software development community for the electronic
+transfer of data.
+
+1.5. "Executable" means Covered Code in any form other than Source
+Code.
+
+1.6. "Initial Developer" means the individual or entity identified as
+the Initial Developer in the Source Code notice required by Exhibit A.
+
+1.7. "Larger Work" means a work which combines Covered Code or
+portions thereof with code not governed by the terms of this License.
+
+1.8. "License" means this document.
+
+1.8.1. "Licensable" means having the right to grant, to the maximum
+extent possible, whether at the time of the initial grant or
+subsequently acquired, any and all of the rights conveyed herein.
+
+1.9. "Modifications" means any addition to or deletion from the
+substance or structure of either the Original Code or any previous
+Modifications. When Covered Code is released as a series of files, a
+Modification is: A. Any addition to or deletion from the contents of a
+file containing Original Code or previous Modifications.
+
+B. Any new file that contains any part of the Original Code or
+previous Modifications.
+
+1.10. "Original Code" means Source Code of computer software code
+which is described in the Source Code notice required by Exhibit A as
+Original Code, and which, at the time of its release under this
+License is not already Covered Code governed by this License.
+
+1.10.1. "Patent Claims" means any patent claim(s), now owned or
+hereafter acquired, including without limitation, method, process, and
+apparatus claims, in any patent Licensable by grantor.
+
+1.11. "Source Code" means the preferred form of the Covered Code for
+making modifications to it, including all modules it contains, plus
+any associated interface definition files, scripts used to control
+compilation and installation of an Executable, or source code
+differential comparisons against either the Original Code or another
+well known, available Covered Code of the Contributor's choice. The
+Source Code can be in a compressed or archival form, provided the
+appropriate decompression or de-archiving software is widely available
+for no charge.
+
+1.12. "You" (or "Your") means an individual or a legal entity
+exercising rights under, and complying with all of the terms of, this
+License or a future version of this License issued under Section
+6.1. For legal entities, "You" includes any entity which controls, is
+controlled by, or is under common control with You. For purposes of
+this definition, "control" means (a) the power, direct or indirect, to
+cause the direction or management of such entity, whether by contract
+or otherwise, or (b) ownership of more than fifty percent (50%) of the
+outstanding shares or beneficial ownership of such entity.
+
+2. Source Code License.
+
+2.1. The Initial Developer Grant. The Initial Developer hereby grants
+You a world-wide, royalty-free, non-exclusive license, subject to
+third party intellectual property claims: (a) under intellectual
+property rights (other than patent or trademark) Licensable by Initial
+Developer to use, reproduce, modify, display, perform, sublicense and
+distribute the Original Code (or portions thereof) with or without
+Modifications, and/or as part of a Larger Work; and
+
+(b) under Patents Claims infringed by the making, using or selling of
+Original Code, to make, have made, use, practice, sell, and offer for
+sale, and/or otherwise dispose of the Original Code (or portions
+thereof).
+
+(c) the licenses granted in this Section 2.1(a) and (b) are effective
+on the date Initial Developer first distributes Original Code under
+the terms of this License.
+
+(d) Notwithstanding Section 2.1(b) above, no patent license is
+granted: 1) for code that You delete from the Original Code; 2)
+separate from the Original Code; or 3) for infringements caused by: i)
+the modification of the Original Code or ii) the combination of the
+Original Code with other software or devices.
+
+2.2. Contributor Grant. Subject to third party intellectual property
+claims, each Contributor hereby grants You a world-wide, royalty-free,
+non-exclusive license
+
+(a) under intellectual property rights (other than patent or
+trademark) Licensable by Contributor, to use, reproduce, modify,
+display, perform, sublicense and distribute the Modifications created
+by such Contributor (or portions thereof) either on an unmodified
+basis, with other Modifications, as Covered Code and/or as part of a
+Larger Work; and
+
+(b) under Patent Claims infringed by the making, using, or selling of
+Modifications made by that Contributor either alone and/or in
+combination with its Contributor Version (or portions of such
+combination), to make, use, sell, offer for sale, have made, and/or
+otherwise dispose of: 1) Modifications made by that Contributor (or
+portions thereof); and 2) the combination of Modifications made by
+that Contributor with its Contributor Version (or portions of such
+combination).
+
+(c) the licenses granted in Sections 2.2(a) and 2.2(b) are effective
+on the date Contributor first makes Commercial Use of the Covered
+Code.
+
+(d) Notwithstanding Section 2.2(b) above, no patent license is
+granted: 1) for any code that Contributor has deleted from the
+Contributor Version; 2) separate from the Contributor Version; 3) for
+infringements caused by: i) third party modifications of Contributor
+Version or ii) the combination of Modifications made by that
+Contributor with other software (except as part of the Contributor
+Version) or other devices; or 4) under Patent Claims infringed by
+Covered Code in the absence of Modifications made by that Contributor.
+
+
+3. Distribution Obligations.
+
+3.1. Application of License. The Modifications which You create or to
+which You contribute are governed by the terms of this License,
+including without limitation Section 2.2. The Source Code version of
+Covered Code may be distributed only under the terms of this License
+or a future version of this License released under Section 6.1, and
+You must include a copy of this License with every copy of the Source
+Code You distribute. You may not offer or impose any terms on any
+Source Code version that alters or restricts the applicable version of
+this License or the recipients' rights hereunder. However, You may
+include an additional document offering the additional rights
+described in Section 3.5.
+
+3.2. Availability of Source Code. Any Modification which You create
+or to which You contribute must be made available in Source Code form
+under the terms of this License either on the same media as an
+Executable version or via an accepted Electronic Distribution
+Mechanism to anyone to whom you made an Executable version available;
+and if made available via Electronic Distribution Mechanism, must
+remain available for at least twelve (12) months after the date it
+initially became available, or at least six (6) months after a
+subsequent version of that particular Modification has been made
+available to such recipients. You are responsible for ensuring that
+the Source Code version remains available even if the Electronic
+Distribution Mechanism is maintained by a third party.
+
+3.3. Description of Modifications. You must cause all Covered Code to
+which You contribute to contain a file documenting the changes You
+made to create that Covered Code and the date of any change. You must
+include a prominent statement that the Modification is derived,
+directly or indirectly, from Original Code provided by the Initial
+Developer and including the name of the Initial Developer in (a) the
+Source Code, and (b) in any notice in an Executable version or related
+documentation in which You describe the origin or ownership of the
+Covered Code.
+
+3.4. Intellectual Property Matters (a) Third Party Claims. If
+Contributor has knowledge that a license under a third party's
+intellectual property rights is required to exercise the rights
+granted by such Contributor under Sections 2.1 or 2.2, Contributor
+must include a text file with the Source Code distribution titled
+"LEGAL" which describes the claim and the party making the claim in
+sufficient detail that a recipient will know whom to contact. If
+Contributor obtains such knowledge after the Modification is made
+available as described in Section 3.2, Contributor shall promptly
+modify the LEGAL file in all copies Contributor makes available
+thereafter and shall take other steps (such as notifying appropriate
+mailing lists or newsgroups) reasonably calculated to inform those who
+received the Covered Code that new knowledge has been obtained.
+
+(b) Contributor APIs. If Contributor's Modifications include an
+application programming interface and Contributor has knowledge of
+patent licenses which are reasonably necessary to implement that API,
+Contributor must also include this information in the LEGAL file.
+
+(c) Representations. Contributor represents that, except as disclosed
+pursuant to Section 3.4(a) above, Contributor believes that
+Contributor's Modifications are Contributor's original creation(s)
+and/or Contributor has sufficient rights to grant the rights conveyed
+by this License.
+
+
+3.5. Required Notices. You must duplicate the notice in Exhibit A in
+each file of the Source Code. If it is not possible to put such
+notice in a particular Source Code file due to its structure, then You
+must include such notice in a location (such as a relevant directory)
+where a user would be likely to look for such a notice. If You
+created one or more Modification(s) You may add your name as a
+Contributor to the notice described in Exhibit A. You must also
+duplicate this License in any documentation for the Source Code where
+You describe recipients' rights or ownership rights relating to
+Covered Code. You may choose to offer, and to charge a fee for,
+warranty, support, indemnity or liability obligations to one or more
+recipients of Covered Code. However, You may do so only on Your own
+behalf, and not on behalf of the Initial Developer or any
+Contributor. You must make it absolutely clear than any such warranty,
+support, indemnity or liability obligation is offered by You alone,
+and You hereby agree to indemnify the Initial Developer and every
+Contributor for any liability incurred by the Initial Developer or
+such Contributor as a result of warranty, support, indemnity or
+liability terms You offer.
+
+3.6. Distribution of Executable Versions. You may distribute Covered
+Code in Executable form only if the requirements of Section 3.1-3.5
+have been met for that Covered Code, and if You include a notice
+stating that the Source Code version of the Covered Code is available
+under the terms of this License, including a description of how and
+where You have fulfilled the obligations of Section 3.2. The notice
+must be conspicuously included in any notice in an Executable version,
+related documentation or collateral in which You describe recipients'
+rights relating to the Covered Code. You may distribute the Executable
+version of Covered Code or ownership rights under a license of Your
+choice, which may contain terms different from this License, provided
+that You are in compliance with the terms of this License and that the
+license for the Executable version does not attempt to limit or alter
+the recipient's rights in the Source Code version from the rights set
+forth in this License. If You distribute the Executable version under
+a different license You must make it absolutely clear that any terms
+which differ from this License are offered by You alone, not by the
+Initial Developer or any Contributor. You hereby agree to indemnify
+the Initial Developer and every Contributor for any liability incurred
+by the Initial Developer or such Contributor as a result of any such
+terms You offer.
+
+3.7. Larger Works. You may create a Larger Work by combining Covered
+Code with other code not governed by the terms of this License and
+distribute the Larger Work as a single product. In such a case, You
+must make sure the requirements of this License are fulfilled for the
+Covered Code.
+
+4. Inability to Comply Due to Statute or Regulation.
+
+If it is impossible for You to comply with any of the terms of this
+License with respect to some or all of the Covered Code due to
+statute, judicial order, or regulation then You must: (a) comply with
+the terms of this License to the maximum extent possible; and (b)
+describe the limitations and the code they affect. Such description
+must be included in the LEGAL file described in Section 3.4 and must
+be included with all distributions of the Source Code. Except to the
+extent prohibited by statute or regulation, such description must be
+sufficiently detailed for a recipient of ordinary skill to be able to
+understand it.
+
+5. Application of this License.
+
+This License applies to code to which the Initial Developer has
+attached the notice in Exhibit A and to related Covered Code.
+
+6. Versions of the License.
+
+6.1. New Versions. Thomas Richter may publish revised and/or new
+versions of the License from time to time. Each version will be given
+a distinguishing version number.
+
+6.2. Effect of New Versions. Once Covered Code has been published
+under a particular version of the License, You may always continue to
+use it under the terms of that version. You may also choose to use
+such Covered Code under the terms of any subsequent version of the
+License published by Thomas Richter. No one other than Thomas Richter
+has the right to modify the terms applicable to Covered Code created
+under this License.
+
+6.3. Derivative Works. If You create or use a modified version of
+this License (which you may only do in order to apply it to code which
+is not already Covered Code governed by this License), You must (a)
+rename Your license so that the phrases "TPL", "THOR Software",
+"Thomas Richter" or any confusingly similar phrase do not appear in
+your license (except to note that your license differs from this
+License) and (b) otherwise make it clear that Your version of the
+license contains terms which differ from the THOR Public
+License. (Filling in the name of the Initial Developer, Original Code
+or Contributor in the notice described in Exhibit A shall not of
+themselves be deemed to be modifications of this License.)
+
+7. DISCLAIMER OF WARRANTY.
+
+COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+WITHOUT LIMITATION, WARRANTIES THAT THE COVERED CODE IS FREE OF
+DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE OR
+NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF
+THE COVERED CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE
+IN ANY RESPECT, YOU (NOT THE INITIAL DEVELOPER OR ANY OTHER
+CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY SERVICING, REPAIR OR
+CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL PART
+OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER
+EXCEPT UNDER THIS DISCLAIMER.
+
+8. TERMINATION.
+
+8.1. This License and the rights granted hereunder will terminate
+automatically if You fail to comply with terms herein and fail to cure
+such breach within 30 days of becoming aware of the breach. All
+sublicenses to the Covered Code which are properly granted shall
+survive any termination of this License. Provisions which, by their
+nature, must remain in effect beyond the termination of this License
+shall survive.
+
+8.2. If You initiate litigation by asserting a patent infringement
+claim (excluding declatory judgment actions) against Initial Developer
+or a Contributor (the Initial Developer or Contributor against whom
+You file such action is referred to as "Participant") alleging that:
+
+(a) such Participant's Contributor Version directly or indirectly
+infringes any patent, then any and all rights granted by such
+Participant to You under Sections 2.1 and/or 2.2 of this License
+shall, upon 60 days notice from Participant terminate prospectively,
+unless if within 60 days after receipt of notice You either: (i) agree
+in writing to pay Participant a mutually agreeable reasonable royalty
+for Your past and future use of Modifications made by such
+Participant, or (ii) withdraw Your litigation claim with respect to
+the Contributor Version against such Participant. If within 60 days
+of notice, a reasonable royalty and payment arrangement are not
+mutually agreed upon in writing by the parties or the litigation claim
+is not withdrawn, the rights granted by Participant to You under
+Sections 2.1 and/or 2.2 automatically terminate at the expiration of
+the 60 day notice period specified above.
+
+(b) any software, hardware, or device, other than such Participant's
+Contributor Version, directly or indirectly infringes any patent, then
+any rights granted to You by such Participant under Sections 2.1(b)
+and 2.2(b) are revoked effective as of the date You first made, used,
+sold, distributed, or had made, Modifications made by that
+Participant.
+
+8.3. If You assert a patent infringement claim against Participant
+alleging that such Participant's Contributor Version directly or
+indirectly infringes any patent where such claim is resolved (such as
+by license or settlement) prior to the initiation of patent
+infringement litigation, then the reasonable value of the licenses
+granted by such Participant under Sections 2.1 or 2.2 shall be taken
+into account in determining the amount or value of any payment or
+license.
+
+8.4. In the event of termination under Sections 8.1 or 8.2 above, all
+end user license agreements (excluding distributors and resellers)
+which have been validly granted by You or any distributor hereunder
+prior to termination shall survive termination.
+
+9. LIMITATION OF LIABILITY.
+
+UNDER NO CIRCUMSTANCES AND UNDER NO LEGAL THEORY, WHETHER TORT
+(INCLUDING NEGLIGENCE), CONTRACT, OR OTHERWISE, SHALL YOU, THE INITIAL
+DEVELOPER, ANY OTHER CONTRIBUTOR, OR ANY DISTRIBUTOR OF COVERED CODE,
+OR ANY SUPPLIER OF ANY OF SUCH PARTIES, BE LIABLE TO ANY PERSON FOR
+ANY INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES OF ANY
+CHARACTER INCLUDING, WITHOUT LIMITATION, DAMAGES FOR LOSS OF GOODWILL,
+WORK STOPPAGE, COMPUTER FAILURE OR MALFUNCTION, OR ANY AND ALL OTHER
+COMMERCIAL DAMAGES OR LOSSES, EVEN IF SUCH PARTY SHALL HAVE BEEN
+INFORMED OF THE POSSIBILITY OF SUCH DAMAGES. THIS LIMITATION OF
+LIABILITY SHALL NOT APPLY TO LIABILITY FOR DEATH OR PERSONAL INJURY
+RESULTING FROM SUCH PARTY'S NEGLIGENCE TO THE EXTENT APPLICABLE LAW
+PROHIBITS SUCH LIMITATION. SOME JURISDICTIONS DO NOT ALLOW THE
+EXCLUSION OR LIMITATION OF INCIDENTAL OR CONSEQUENTIAL DAMAGES, SO
+THIS EXCLUSION AND LIMITATION MAY NOT APPLY TO YOU.
+
+10. U.S. GOVERNMENT END USERS.
+
+The Covered Code is a "commercial item," as that term is defined in 48
+C.F.R. 2.101 (Oct. 1995), consisting of "commercial computer software"
+and "commercial computer software documentation," as such terms are
+used in 48 C.F.R. 12.212 (Sept. 1995). Consistent with 48
+C.F.R. 12.212 and 48 C.F.R. 227.7202-1 through 227.7202-4 (June 1995),
+all U.S. Government End Users acquire Covered Code with only those
+rights set forth herein.
+
+11. MISCELLANEOUS.
+
+This License represents the complete agreement concerning subject
+matter hereof. If any provision of this License is held to be
+unenforceable, such provision shall be reformed only to the extent
+necessary to make it enforceable. This License shall be governed by
+German law provisions (except to the extent applicable law, if any,
+provides otherwise), excluding its conflict-of-law provisions. With
+respect to disputes in which at least one party is a citizen of, or an
+entity chartered or registered to do business in Federal Republic of
+Germany, any litigation relating to this License shall be subject to
+the jurisdiction of the Federal Courts of the Federal Republic of
+Germany, with the losing party responsible for costs, including
+without limitation, court costs and reasonable attorneys' fees and
+expenses. Any law or regulation which provides that the language of a
+contract shall be construed against the drafter shall not apply to
+this License.
+
+12. RESPONSIBILITY FOR CLAIMS.
+
+As between Initial Developer and the Contributors, each party is
+responsible for claims and damages arising, directly or indirectly,
+out of its utilization of rights under this License and You agree to
+work with Initial Developer and Contributors to distribute such
+responsibility on an equitable basis. Nothing herein is intended or
+shall be deemed to constitute any admission of liability.
+
+13. MULTIPLE-LICENSED CODE.
+
+Initial Developer may designate portions of the Covered Code as
+Multiple-Licensed. Multiple-Licensed means that the Initial Developer
+permits you to utilize portions of the Covered Code under Your choice
+of the TPL or the alternative licenses, if any, specified by the
+Initial Developer in the file described in Exhibit A.
+
+
+EXHIBIT A - THOR Public License.
+
+The contents of this file are subject to the THOR Public License
+Version 1.0 (the "License"); you may not use this file except in
+compliance with the License.
+
+Software distributed under the License is distributed on an "AS IS"
+basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+the License for the specificlanguage governing rights and limitations
+under the License.
+
+The Original Code is ______________________________________.
+
+The Initial Developer of the Original Code is _____________.
+
+Portions created by ______________________ are
+Copyright (C) ______ _______________________.
+
+All Rights Reserved.
+
+Contributor(s): ______________________________________.
+
+Alternatively, the contents of this file may be used under the terms
+of the _____ license (the [___] License), in which case the provisions
+of [______] License are applicable instead of those above. If you
+wish to allow use of your version of this file only under the terms of
+the [____] License and not to allow others to use your version of this
+file under the TPL, indicate your decision by deleting the provisions
+above and replace them with the notice and other provisions required
+by the [___] License. If you do not delete the provisions above, a
+recipient may use your version of this file under either the TPL or
+the [___] License."
+
+[NOTE: The text of this Exhibit A may differ slightly from the text of
+the notices in the Source Code files of the Original Code. You should
+use the text of this Exhibit A rather than the text found in the
+Original Code Source Code for Your Modifications.]
diff --git a/options/license/UCAR b/options/license/UCAR
new file mode 100644
index 000000000..36e181028
--- /dev/null
+++ b/options/license/UCAR
@@ -0,0 +1,32 @@
+Copyright 2014 University Corporation for Atmospheric Research and contributors.
+All rights reserved.
+
+This software was developed by the Unidata Program Center of the
+University Corporation for Atmospheric Research (UCAR)
+<http://www.unidata.ucar.edu>.
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+ 1) Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+ 2) Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+ 3) Neither the names of the development group, the copyright holders, nor the
+ names of contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+ 4) This license shall terminate automatically and you may no longer exercise
+ any of the rights granted to you by this license as of the date you
+ commence an action, including a cross-claim or counterclaim, against
+ the copyright holders or any contributor alleging that this software
+ infringes a patent. This termination provision shall not apply for an
+ action alleging patent infringement by combinations of this software with
+ other software or hardware.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE CONTRIBUTORS
+OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE SOFTWARE.
diff --git a/options/license/snprintf b/options/license/snprintf
new file mode 100644
index 000000000..9e4ae73da
--- /dev/null
+++ b/options/license/snprintf
@@ -0,0 +1,3 @@
+Copyright Patrick Powell 1995
+
+This code is based on code written by Patrick Powell (papowell@astart.com) It may be used for any purpose as long as this notice remains intact on all source code distributions
diff --git a/options/license/w3m b/options/license/w3m
new file mode 100644
index 000000000..37081007b
--- /dev/null
+++ b/options/license/w3m
@@ -0,0 +1,11 @@
+(C) Copyright 1994-2002 by Akinori Ito
+(C) Copyright 2002-2011 by Akinori Ito, Hironori Sakamoto, Fumitoshi Ukai
+
+Use, modification and redistribution of this software is hereby granted,
+provided that this entire copyright notice is included on any copies of
+this software and applications and derivations thereof.
+
+This software is provided on an "as is" basis, without warranty of any
+kind, either expressed or implied, as to any matter including, but not
+limited to warranty of fitness of purpose, or merchantability, or
+results obtained from use of this software.
diff --git a/options/license/xlock b/options/license/xlock
new file mode 100644
index 000000000..39ccda0b4
--- /dev/null
+++ b/options/license/xlock
@@ -0,0 +1,14 @@
+Copyright (c) 1990 by Sun Microsystems, Inc.
+Author: Patrick J. Naughton naughton@wind.sun.com
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted,
+provided that the above copyright notice appear in all copies and
+that both that copyright notice and this permission notice appear in
+supporting documentation.
+
+This file is provided AS IS with no warranties of any kind. The author
+shall have no liability with respect to the infringement of copyrights,
+trade secrets or any patents by this file or any part thereof. In no event
+will the author be liable for any lost revenue or profits or other special,
+indirect and consequential damages.
diff --git a/options/locale/locale_bg-BG.ini b/options/locale/locale_bg-BG.ini
deleted file mode 100644
index 61c2929ba..000000000
--- a/options/locale/locale_bg-BG.ini
+++ /dev/null
@@ -1,1265 +0,0 @@
-home=Ðачало
-dashboard=Табло
-explore=Каталог
-help=Помощ
-sign_in=Вход
-sign_in_with=Влизане Ñ
-sign_out=Изход
-sign_up=РегиÑтриране
-link_account=Свържи профил
-register=РегиÑтрациÑ
-version=ВерÑиÑ
-powered_by=С подкрепата на %s
-page=Страница
-template=Шаблон
-language=Език
-notifications=ИзвеÑтиÑ
-create_new=Създай…
-user_profile_and_more=Профил и наÑтройки…
-signed_in_as=ВпиÑан като
-enable_javascript=Този Ñайт работи по-добре Ñ JavaScript.
-
-username=Потребител
-email=Имейл адреÑ
-password=Парола
-re_type=Повторно въвеждане на парола
-captcha=CAPTCHA
-twofa=Двуфакторно удоÑтоверÑване
-twofa_scratch=Двуфакторен Ñкреч код
-passcode=Секретен код
-
-
-repository=Хранилище
-organization=ОрганизациÑ
-mirror=Огледало
-new_repo=Ðово хранилище
-new_migrate=Ðова миграциÑ
-new_mirror=Ðово огледало
-new_fork=Ðов форк на хранилище
-new_org=Ðова организациÑ
-manage_org=Управление на организации
-admin_panel=ÐдминиÑтриране на Ñайта
-account_settings=ÐаÑтройки на профила
-settings=ÐаÑтройки
-your_profile=Профил
-your_starred=ОтбелÑзани
-your_settings=ÐаÑтройки
-
-all=Ð’Ñичко
-sources=Източници
-mirrors=Огледала
-collaborative=СъвмеÑтни
-forks=РазклонениÑ
-
-activities=ÐктивноÑти
-pull_requests=ЗаÑвки за Ñливане
-issues=Задачи
-milestones=Етапи
-
-cancel=Отказ
-add=Добави
-add_all=Добави вÑички
-remove=Премахни
-remove_all=Премахни вÑички
-
-
-write=Пиши
-preview=Преглед
-loading=Зареждане…
-
-
-error404=Страницата, коÑто Ñе опитвате да доÑтъпите, <strong>не ÑъщеÑтвува</strong> или <strong>не Ñте оторизирани</strong> да Ñ Ð´Ð¾Ñтъпите.
-
-
-
-[filter]
-
-[error]
-
-[startpage]
-app_desc=Практичен ÑобÑтвен Git Ñървър
-install=ЛеÑен за инÑталиране
-platform=Платформено-незавиÑим
-platform_desc=Gitea може да работи на вÑички ÑиÑтеми, за които може да Ñе компилира Ñ <a target="_blank" rel="noopener noreferrer" href="http://golang.org/">Go</a>: Windows, macOS, Linux, ARM и Ñ‚.н. Изберете ÑиÑтемата, коÑто хареÑвате!
-lightweight=Използва малко реÑурÑи
-lightweight_desc=Gitea има ниÑки минимални хардуерни изиÑÐºÐ²Ð°Ð½Ð¸Ñ Ð¸ може да работи дори на евтино Raspberry Pi. Запазете производителноÑтта на Ð²Ð°ÑˆÐ¸Ñ ÐºÐ¾Ð¼Ð¿ÑŽÑ‚ÑŠÑ€!
-license=С отворен код
-license_desc=Изтеглете кода от <a target="_blank" rel="noopener noreferrer" href="https://code.gitea.io/gitea">code.gitea.io/gitea</a>! Станете един от Ð½Ð°Ñ ÐºÐ°Ñ‚Ð¾ <a target="_blank" rel="noopener noreferrer" href="https://github.com/go-gitea/gitea">помогнете</a> да направим проекта още по-добър. Ðе Ñе колебайте да Ñе приÑъедините към проекта!
-
-[install]
-install=ИнÑталациÑ
-title=Първоначална конфигурациÑ
-docker_helper=Ðко Ñтартирате Gitea вътре Докер, Ð¼Ð¾Ð»Ñ Ð¿Ñ€Ð¾Ñ‡ÐµÑ‚ÐµÑ‚Ðµ <a target="_blank" rel="noopener noreferrer" href="%s">документациÑ</a> преди да променÑте никакви наÑтройки.
-db_title=ÐаÑтройки на базата данни
-db_type=Тип на база данни
-host=Сървър
-user=ПотребителÑко име
-password=Парола
-db_name=Име на база данни
-db_helper=Забележка за MySQL: използвайте механизъм за Ñъхранение InnoDB и, ако използвате "utf8mb4", верÑиÑта на InnoDB Ñ‚Ñ€Ñбва да е по-голÑма от 5.6 .
-db_schema=Схема
-ssl_mode=SSL
-charset=Кодиране на знаците
-path=Път
-sqlite_helper=ПътÑÑ‚ на файла за SQLite3 база данни.<br>Въведете абÑолютен път, ако Ñтартирате Gitea като ÑервиÑ.
-err_empty_db_path=ПътÑÑ‚ за SQLite3 базата данни не може да е празен.
-no_admin_and_disable_registration=Ðе може да забраните ÑаморегиÑтрациÑта без да Ñъздадете админиÑтраторÑки акаунт.
-err_empty_admin_password=Паролата на админиÑтратора не може да е празна.
-err_empty_admin_email=E-mail адреÑÑŠÑ‚ на админиÑтратора не може да е празен.
-err_admin_name_is_reserved=Ðевалидно потребителÑко име за админиÑтраторÑÐºÐ¸Ñ Ð°ÐºÐ°ÑƒÐ½Ñ‚, името е запазено
-err_admin_name_pattern_not_allowed=ÐдминиÑтраторÑкото потребителÑко име е невалидно. ПотребителÑкото име Ñъвпада Ñ Ð·Ð°Ð¿Ð°Ð·ÐµÐ½ шаблон
-err_admin_name_is_invalid=Ðевалидно потребителÑко име за админиÑтраторÑÐºÐ¸Ñ Ð°ÐºÐ°ÑƒÐ½Ñ‚
-
-general_title=ОÑновни наÑтройки
-app_name=Заглавие на Ñайта
-app_name_helper=Можете да въведете името на вашата ÐºÐ¾Ð¼Ð¿Ð°Ð½Ð¸Ñ Ñ‚ÑƒÐº.
-repo_path=ОÑновен път към хранилищата
-repo_path_helper=Отдалечените Git хранилища ще бъде запиÑани в тази директориÑ.
-lfs_path=Git LFS оÑновна директориÑ
-lfs_path_helper=Файловете, проÑледÑвани от Git LFS ще бъдат ÑъхранÑвани в тази директориÑ. ОÑтавете празно, за да го изключите.
-run_user=Изпълни като потребителÑко име
-run_user_helper=Въведете името на акаунта, под който ще Ñе Ñтартира Gitea. Този акаунт Ñ‚Ñ€Ñбва да има доÑтъп до директориÑта Ñ Ñ…Ñ€Ð°Ð½Ð¸Ð»Ð¸Ñ‰Ð°Ñ‚Ð°.
-ssh_port=SSH Ñървър порт
-ssh_port_helper=Ðомер на порт, на който Ñлуша SSH Ñървъра. ОÑтавете празно, за да забраните.
-http_port=Gitea HTTP Listen Порт
-http_port_helper=Ðомер на порта на Gitea уеб Ñървър ще Ñлуша.
-app_url=Gitea базов URL
-app_url_helper=Базов Ð°Ð´Ñ€ÐµÑ Ð·Ð° HTTP(S) линковете за клониране и уведомÑване чрез E-mail.
-log_root_path=Път към журналите
-log_root_path_helper=ДиректориÑ, в коÑто да Ñе ÑъхранÑват лог файловете.
-
-optional_title=Опционални наÑтройки
-email_title=Имейл наÑтройки
-smtp_from=Изпрати имейл като
-smtp_from_helper=E-mail адреÑ, който да Ñе използва от Gitea. Въведете Ñамо E-mail адреÑа или име и E-mail във формат "Name <email@example.com>".
-mailer_user=SMTP потребител
-mailer_password=SMTP парола
-register_confirm=ИзиÑквай потвърждение чрез E-mail при региÑтрациÑ
-mail_notify=Включи ÑƒÐ²ÐµÐ´Ð¾Ð¼Ð»ÐµÐ½Ð¸Ñ Ð¿Ð¾ пощата
-server_service_title=ÐаÑтройки за Ñървъра и външни уÑлуги
-offline_mode=Включване на локален режим
-disable_gravatar=Изключи Gravatar
-federated_avatar_lookup_popup=ПозволÑва използване на външни аватари от уÑлуги ÑъвмеÑтими Ñ libravatar.
-disable_registration=Изключи ÑаморегиÑтрациÑта
-disable_registration_popup=Изключи потребителÑката ÑаморегиÑтрациÑ. Само админиÑтраторите могат да Ñъздават профили.
-allow_only_external_registration_popup=Позволи региÑÑ‚Ñ€Ð°Ñ†Ð¸Ñ Ñамо през външни уÑлуги
-openid_signin=Включване на OpenID вход
-openid_signin_popup=Включване на потребителÑки вход чрез OpenID.
-openid_signup=Включване на OpenID ÑаморегиÑтрациÑ
-openid_signup_popup=Включване на OpenID-базирана потребителÑка ÑаморегиÑтрациÑ.
-enable_captcha_popup=ИзиÑква валидиране Ñ captcha при ÑаморегиÑÑ‚Ñ€Ð°Ñ†Ð¸Ñ Ð½Ð° потребители.
-require_sign_in_view=ИзиÑквай впиÑване за разглеждане на Ñтраници
-require_sign_in_view_popup=Ограничаване на доÑтъпа до Ñтраницата до впиÑани потребители. ПоÑетителите ще видÑÑ‚ Ñамо Ñтраниците за впиÑване и региÑтрациÑ.
-admin_setting_desc=Създаването на админиÑтраторÑки профил не е задължително. ПървиÑÑ‚ региÑтриран потребител автоматично ще Ñтане админиÑтратор.
-admin_title=ÐаÑтройки на профил на админиÑтратора
-admin_name=ПотребителÑко име на админиÑтратора
-admin_password=Парола
-confirm_password=Потвърждение на паролата
-admin_email=Имейл адреÑ
-install_btn_confirm=ИнÑталирай Gitea
-test_git_failed=ÐеуÑпешно теÑтването на "git" команда: %v
-sqlite3_not_available=Тази верÑÐ¸Ñ Ð½Ð° Gitea не поддържа SQLite3, Ð¼Ð¾Ð»Ñ Ð¸Ð·Ñ‚ÐµÐ³Ð»ÐµÑ‚Ðµ официалната двоична верÑÐ¸Ñ Ð¾Ñ‚ %s, а не gobuild верÑиÑта.
-invalid_db_setting=ÐаÑтройките за база данни Ñа невалидни: %v
-invalid_repo_path=ОÑновниÑÑ‚ път към хранилищата е невалиден: %v
-run_user_not_match=ПотребителÑко име 'изпълни като' не Ñъвпада Ñ Ñ‚ÐµÐºÑƒÑ‰Ð¾Ñ‚Ð¾ потребителÑко име: %s -> %s
-save_config_failed=ÐеуÑпешно запазване на конфигурациÑта: %v
-invalid_admin_setting=ÐаÑтройките за профил на админиÑтратора Ñа невалидни: %v
-install_success=Добре дошли! Благодарим ви че избрахте Gitea. ЗабавлÑвайте Ñе и на добър чаÑ!
-invalid_log_root_path=ПътÑÑ‚ към журналите е невалиден: %v
-default_keep_email_private=Скриване на имейл адреÑи по подразбиране
-default_keep_email_private_popup=Скриване на имейл адреÑите на нови потребители по подразбиране.
-default_allow_create_organization=ПозволÑване на Ñъздаването на организации по подразбиране
-default_allow_create_organization_popup=ПозволÑване на нови потребители да Ñъздават организации по подразбиране.
-no_reply_address=Скрит имейл домейн
-no_reply_address_helper=Домейн за потребители ÑÑŠÑ Ñкрит имейл адреÑ. Ðапример, потребителÑкото име 'joe' ще бъде логнато в Git като 'joe@noreply.example.org' ако ÑкритиÑÑ‚ имейл домейн е 'noreply.example.org'.
-
-[home]
-uname_holder=ПотребителÑко име или имейл адреÑ
-password_holder=Парола
-switch_dashboard_context=Превключи контекÑÑ‚ на таблото
-my_repos=Хранилища
-show_more_repos=Покажи още хранилища…
-collaborative_repos=СъвмеÑтни хранилища
-my_orgs=Моите организации
-my_mirrors=Моите огледала
-view_home=Преглед на %s
-search_repos=Ðамери хранилище…
-
-
-
-issues.in_your_repos=Във Вашите хранилища
-
-[explore]
-repos=Хранилища
-users=Потребители
-organizations=Организации
-search=ТърÑене
-code=Код
-repo_no_results=Ðе Ñа открити Ñъвпадащи хранилища.
-user_no_results=Ðе Ñа открити Ñъвпадащи потребители.
-org_no_results=Ðе бÑха намерени ÑъответÑтващи организации.
-code_search_results=Резултати от Ñ‚ÑŠÑ€Ñене за '%s'
-code_last_indexed_at=ПоÑледно индекÑиран %s
-
-
-[auth]
-create_new_account=РегиÑтриране на акаунт
-register_helper_msg=Вече имате профил? Впишете Ñе Ñега!
-social_register_helper_msg=Вече имате акаунт? Свържето го Ñега!
-disable_register_prompt=РегиÑтрациите Ñа заключени. ÐœÐ¾Ð»Ñ Ð¾Ð±ÑŠÑ€Ð½ÐµÑ‚Ðµ Ñе към админиÑтратора на Ñайта.
-disable_register_mail=Потвърждението на региÑÑ‚Ñ€Ð°Ñ†Ð¸Ñ Ð¿Ñ€ÐµÐ· имейл е изключено.
-forgot_password_title=Забравена парола
-forgot_password=Забравена парола?
-sign_up_now=Ðуждаете Ñе от профил? РегиÑтрирайте Ñе Ñега.
-sign_up_successful=Профилът е Ñъздаден уÑпешно.
-must_change_password=Променете ÑвоÑта парола
-active_your_account=Ðктивиране на профил
-account_activated=Профилът беше активиран
-prohibit_login=ВпиÑването е забранено
-has_unconfirmed_mail=Здравейте %s, имате непотвърден Ð°Ð´Ñ€ÐµÑ Ð½Ð° ел. поща (<b>%s</b>). Ðко не Ñте получили пиÑмо за потвърждение или имате нужда да Ñе изпрати ново пиÑмо, Ð¼Ð¾Ð»Ñ Ñ‰Ñ€Ð°ÐºÐ½ÐµÑ‚Ðµ бутона по-долу.
-resend_mail=Щракнете тук, за да Ñе изпрати ново пиÑмо за потвърждение
-email_not_associate=Имейл адреÑÑŠÑ‚ не е Ñвързан към профил.
-send_reset_mail=Изпрати имейл за възÑтановÑване на профил
-reset_password=ВъзÑтановÑване на акаунт
-invalid_code=Кодът за потвърждение е невалиден или изтекъл.
-reset_password_helper=ВъзÑтановÑване на профил
-reset_password_wrong_user=Вие Ñте впиÑани като %s, а линкът за възÑтановÑване е за %s
-password_too_short=Дължината на паролата не може да бъде по-малко от %d Ñимвола.
-verify=Потвърждаване
-scratch_code=Код за възÑтановÑване
-use_scratch_code=Използвай код за възÑтановÑване
-twofa_scratch_token_incorrect=ВашиÑÑ‚ код за възÑтановÑване е невалиден.
-login_userpass=Вход
-login_openid=OpenID
-oauth_signup_tab=РегиÑÑ‚Ñ€Ð°Ñ†Ð¸Ñ Ð½Ð° нов профил
-oauth_signup_submit=Завършване на профил
-oauth_signin_tab=Свържи към ÑъщеÑтвуващ акаунт
-oauth_signin_submit=Свържи профил
-openid_connect_submit=Свързване
-openid_connect_title=Свързване към ÑъщеÑтвуващ профил
-openid_register_title=Създай нов акаунт
-openid_signin_desc=Въведете вашето OpenID URI. Ðапример: https://anne.me, bob.openid.org.cn или gnusocial.net/carry.
-authorize_application=Оторизиране на приложение
-authorize_redirect_notice=Ще бъдете пренаÑочени към %s ако оторизирате това приложение.
-authorize_application_created_by=Това приложение е Ñъздадено от %s.
-authorize_title=Оторизирайте "%s" доÑтъп до Ð²Ð°ÑˆÐ¸Ñ Ð°ÐºÐ°ÑƒÐ½Ñ‚?
-authorization_failed=ОторизациÑта беше неуÑпешна
-sspi_auth_failed=SSPI удоÑтоверÑването беше неуÑпешно
-
-[mail]
-
-activate_account=ÐœÐ¾Ð»Ñ Ð°ÐºÑ‚Ð¸Ð²Ð¸Ñ€Ð°Ð¹Ñ‚Ðµ Ð’Ð°ÑˆÐ¸Ñ Ð¿Ñ€Ð¾Ñ„Ð¸Ð»
-
-activate_email=Провери Ð°Ð´Ñ€ÐµÑ Ð½Ð° ел. поща
-
-register_notify=Добре дошли в Gitea
-
-reset_password=ВъзÑтановете акаунта Ñи
-
-register_success=УÑпешна региÑтрациÑ
-
-
-
-
-
-
-
-[modal]
-yes=Да
-no=Ðе
-modify=Запази
-
-[form]
-UserName=ПотребителÑко име
-RepoName=Име на хранилището
-Email=ÐÐ´Ñ€ÐµÑ Ð½Ð° ел. поща
-Password=Парола
-Retype=Въведете паролата отново
-SSHTitle=Име на SSH ключ
-HttpsUrl=HTTPS URL адреÑ
-PayloadUrl=URL Ð°Ð´Ñ€ÐµÑ Ð½Ð° изпращане
-TeamName=Име на екипа
-AuthName=Име на удоÑтоверението
-AdminEmail=Ел. поща на админиÑтратора
-
-NewBranchName=Име на нов клон
-CommitSummary=Резюме на ревизиÑ
-CommitMessage=ТекÑÑ‚ на ревизиÑ
-CommitChoice=Избор на ревизиÑ
-TreeName=Път до файл
-Content=Съдържание
-
-SSPISeparatorReplacement=Разделител
-SSPIDefaultLanguage=Език по подразбиране
-
-require_error=` не може да бъде празен.`
-size_error=` Ñ‚Ñ€Ñбва да е Ñ Ñ€Ð°Ð·Ð¼ÐµÑ€ %s.`
-min_size_error=` Ñ‚Ñ€Ñбва да Ñъдържа поне %s знака.`
-max_size_error=` Ñ‚Ñ€Ñбва да Ñъдържа най-много %s знака.`
-email_error=` не е валиден Ð°Ð´Ñ€ÐµÑ Ð½Ð° ел. поща.`
-include_error=` Ñ‚Ñ€Ñбва да Ñъдържа текÑÑ‚ '%s'.`
-glob_pattern_error=` glob шаблонът е невалиден: %s`
-unknown_error=ÐеизвеÑтна грешка:
-captcha_incorrect=ВъведениÑÑ‚ код е неправилен.
-password_not_match=Паролите не Ñъвпадат.
-lang_select_error=Изберете език от ÑпиÑъка.
-
-username_been_taken=ПотребителÑкото име вече е заето.
-repo_name_been_taken=Името на хранилището вече е заето.
-org_name_been_taken=Името на организациÑта вече е заето.
-team_name_been_taken=Името на екипа вече е заето.
-team_no_units_error=Позволете доÑтъп до поне една ÑÐµÐºÑ†Ð¸Ñ Ð½Ð° хранилището.
-email_been_used=Този имейл Ð°Ð´Ñ€ÐµÑ Ð²ÐµÑ‡Ðµ Ñе използва.
-openid_been_used=Този OpenID Ð°Ð´Ñ€ÐµÑ '%s' вече Ñе използва.
-username_password_incorrect=Ðевалиден потребител или парола.
-password_complexity=Паролата не Ð¾Ñ‚Ð³Ð¾Ð²Ð°Ñ€Ñ Ð½Ð° изиÑкваниÑта за ÑложноÑÑ‚:
-password_lowercase_one=Поне една малка буква
-password_uppercase_one=Поне една главна буква
-password_digit_one=Поне една цифра
-password_special_one=Поне един Ñпециален Ñимвол (пунктуациÑ, Ñкоби, кавички и Ñ‚.н.)
-enterred_invalid_repo_name=Въведеното име на хранилище е неправилно.
-enterred_invalid_owner_name=Името на Ð½Ð¾Ð²Ð¸Ñ ÑобÑтвеник не е валидно.
-enterred_invalid_password=Въведената парола е неправилна.
-user_not_exist=ПотребителÑÑ‚ не ÑъщеÑтвува.
-team_not_exist=Този отбор не ÑъщеÑтвува.
-cannot_add_org_to_team=ÐžÑ€Ð³Ð°Ð½Ð¸Ð·Ð°Ñ†Ð¸Ñ Ð½Ðµ може да бъде добавена като член на екип.
-
-invalid_ssh_key=ÐеуÑпешно потвърждаване на SSH ключ: %s
-invalid_gpg_key=ÐеуÑпешно потвърждаване на GPG ключ: %s
-unable_verify_ssh_key=ÐеуÑпешно потвърждаване на SSH ключ; проверете дали не Ñте допуÑнали грешка.
-auth_failed=ÐеуÑпешно удоÑтоверÑване: %v
-
-still_own_repo=ВашиÑÑ‚ профил притежава едно или повече хранилища; изтрийте ги или ги прехвърлете първо.
-still_has_org=ВашиÑÑ‚ профил е член на една или повече организации; напуÑнете ги първо.
-
-target_branch_not_exist=ЦелевиÑÑ‚ клон не ÑъщеÑтвува.
-
-[user]
-change_avatar=Промени ÑÐ²Ð¾Ñ Ð°Ð²Ð°Ñ‚Ð°Ñ€â€¦
-join_on=РегиÑтриран
-repositories=Хранилища
-activity=Публична дейноÑÑ‚
-followers=ПоÑледователи
-starred=ХареÑани хранилища
-following=Следване
-follow=Следване
-unfollow=Ðе Ñледвай
-heatmap.loading=Зареждане на топлинна карта…
-user_bio=БиографиÑ
-
-form.name_reserved=ПотребителÑкото име '%s' е запазено.
-form.name_pattern_not_allowed=Шаблонът '%s' не е позволен в потребителÑко име.
-
-[settings]
-profile=Профил
-account=Профил
-password=Парола
-security=СигурноÑÑ‚
-avatar=Ðватар
-ssh_gpg_keys=SSH / GPG ключове
-social=Социални профили
-applications=ПриложениÑ
-orgs=Управление на организации
-repos=Хранилища
-delete=Изтрий профил
-twofa=Двуфакторно удоÑтоверÑване
-account_link=Свързани акаунти
-organization=Организации
-uid=UID
-
-public_profile=Публичен профил
-profile_desc=ВашиÑÑ‚ имейл Ð°Ð´Ñ€ÐµÑ Ñ‰Ðµ Ñе използва за изпращане на ÑƒÐ²ÐµÐ´Ð¾Ð¼Ð»ÐµÐ½Ð¸Ñ Ð¸ други операции.
-full_name=Пълно име
-website=УебÑайт
-location=ЛокациÑ
-update_theme=Обнови Тема
-update_profile=Запази профила
-update_profile_success=ВашиÑÑ‚ профил беше обновен.
-change_username=Вашето потребителÑко име беше променено.
-change_username_prompt=Забележка: промÑната на потребителÑко име Ð¿Ñ€Ð¾Ð¼ÐµÐ½Ñ Ð¸ URL адреÑа на Ð²Ð°ÑˆÐ¸Ñ Ð°ÐºÐ°ÑƒÐ½Ñ‚.
-continue=Продължи
-cancel=Отказ
-language=Език
-ui=Тема
-
-federated_avatar_lookup=Външно Ñ‚ÑŠÑ€Ñене на аватари
-enable_custom_avatar=Разреши потребителÑки аватар
-choose_new_avatar=Избор на нов аватар
-update_avatar=Промени Ðватар
-delete_current_avatar=Изтрий аватар
-uploaded_avatar_not_a_image=КачениÑÑ‚ файл не е изображение.
-uploaded_avatar_is_too_big=КачениÑÑ‚ файл превишава макÑÐ¸Ð¼Ð°Ð»Ð½Ð¸Ñ Ñ€Ð°Ð·Ð¼ÐµÑ€.
-update_avatar_success=ВашиÑÑ‚ аватар беше променен.
-
-change_password=Промени парола
-old_password=Текуща парола
-new_password=Ðова парола
-retype_new_password=Повторете новата парола
-password_incorrect=Текуща парола е неправилна.
-change_password_success=Вашата парола беше променена. Влизайте Ñ Ð²Ð°ÑˆÐ°Ñ‚Ð° нова парола оттук нататък.
-
-emails=ÐдреÑи на ел. поща
-manage_emails=Управление на Имейл ÐдреÑи
-manage_themes=Изберете тема по подразбиране
-manage_openid=Управление на OpenID адреÑи
-email_desc=ВашиÑÑ‚ оÑновен Ð°Ð´Ñ€ÐµÑ Ð½Ð° ел. поща ще Ñе използва за изпращане на ÑƒÐ²ÐµÐ´Ð¾Ð¼Ð»ÐµÐ½Ð¸Ñ Ð¸ други операции.
-primary=ОÑновен
-activated=Ðктивирано
-primary_email=Ðаправи оÑновен
-delete_email=Премахване
-email_deletion=Премахни имейл адреÑ
-email_deletion_success=Имейл адреÑÑŠÑ‚ беше премахнат.
-theme_update_success=Вашата тема беше променена.
-theme_update_error=Избраната тема не ÑъщеÑтвува.
-openid_deletion=Премахни OpenID адреÑ
-openid_deletion_success=OpenID адреÑÑŠÑ‚ беше премахнат.
-add_new_email=ДобавÑне на нов имейл адреÑ
-add_new_openid=ДобавÑне на ново OpenID URI
-add_email=ДобавÑне на имейл адреÑ
-keep_email_private=Скриване на имейл адреÑа
-
-manage_ssh_keys=Управление на SSH ключове
-add_key=Добави ключ
-add_new_key=ДобавÑне на SSH ключ
-add_new_gpg_key=ДобавÑне на GPG ключ
-gpg_key_id_used=Публичен GPG ключ ÑÑŠÑ Ñъщото ID вече ÑъщеÑтвува.
-subkeys=Подключове
-key_id=ID на ключа
-key_name=Име на ключа
-key_content=Съдържание
-add_key_success=SSH ключът '%s' беше добавен.
-add_gpg_key_success=GPG ключът '%s' беше добавен.
-delete_key=Премахни
-ssh_key_deletion=Премахни SSH ключ
-gpg_key_deletion=Премахни GPG ключ
-ssh_key_deletion_success=SSH ключът беше премахнат.
-gpg_key_deletion_success=GPG ключът беше премахнат.
-add_on=Добавен на
-valid_until=Валиден до
-last_used=ПоÑледно използван на
-no_activity=ÐÑма Ñкорошна дейноÑÑ‚
-key_state_desc=Този ключ е използван през поÑледните 7 дни
-show_openid=Показване в профила
-hide_openid=Скриване от профила
-ssh_disabled=SSH Изключен
-manage_social=Управление на Ñвързани профили в Ñоциалните мрежи
-
-generate_new_token=Генериране на нов API ключ
-token_name=Име на API ключ
-generate_token=Генериране на API ключ
-delete_token=Изтрий
-
-edit_oauth2_application=Редактирай OAuth2 Приложение
-remove_oauth2_application=Премахни OAuth2 Приложение
-create_oauth2_application_button=Създаване на Приложение
-oauth2_application_name=Име на приложението
-oauth2_redirect_uri=URI за пренаÑочване
-save_application=Запазване
-oauth2_client_id=КлиентÑко ID
-oauth2_client_secret=КлиентÑка тайна
-oauth2_regenerate_secret_hint=Загубили Ñте тайната Ñи?
-oauth2_application_edit=Редактиране
-
-
-twofa_disable_note=Можете да изключите двуÑтъпкова Ð°Ð²Ñ‚ÐµÐ½Ñ‚Ð¸ÐºÐ°Ñ†Ð¸Ñ Ð¿Ð¾-къÑно.
-or_enter_secret=Или въведете този ключ: %s
-then_enter_passcode=И въведете кодът, показан в приложението:
-passcode_invalid=Този код е невалиден. Опитайте отново.
-
-
-
-
-delete_account=Изтриване на ÑобÑÑ‚Ð²ÐµÐ½Ð¸Ñ Ð¿Ñ€Ð¾Ñ„Ð¸Ð»
-confirm_delete_account=Потвърди изтриването
-delete_account_title=Изтриване на потребителÑки акаунт
-
-email_notifications.disable=Изключване на извеÑтиÑта по имейл
-
-
-[repo]
-owner=Притежател
-repo_name=Име на хранилището
-repo_size=Размер на хранилището
-template=Шаблон
-template_select=Избиране на шаблон.
-visibility=ВидимоÑÑ‚
-fork_repo=Разклони хранилището
-fork_from=Разклонение от
-use_template=Използвай този шаблон
-generate_repo=Генерирай хранилище
-generate_from=Генерирай от
-repo_desc=ОпиÑание
-repo_lang=Програмен език
-repo_gitignore_helper=Изберете .gitignore файлове.
-license=Лиценз
-create_repo=Създай хранилище
-default_branch=Клон по подразбиране
-mirror_prune=ОкаÑÑ‚Ñ€Ñне
-mirror_last_synced=ПоÑледно Ñинхронизиране
-watchers=Ðаблюдаващи
-stargazers=ХареÑващи
-forks=РазклонениÑ
-pick_reaction=Подберете реакциÑта Ñи
-language_other=Друго
-
-
-
-template.git_hooks=Git куки
-template.avatar=Ðватар
-
-
-
-migrate_items_wiki=Уики
-migrate_items_labels=Етикети
-migrate_items_issues=Проблеми
-migrate_items_pullrequests=ЗаÑвки за Ñливане
-migrate_items_releases=ВерÑии
-migrate_repo=Мигрирай хранилище
-migrate.clone_address=Мигрирай / клонирай от URL
-migrate.clone_address_desc=HTTP(S) или Git URL за клониране на ÑъщеÑтвуващо хранилище
-migrate.clone_local_path=или път към локален Ñървър
-migrate.permission_denied=ÐедоÑтатъчни права за импорт на локални хранилища.
-migrate.failed=Грешка при миграциÑ: %v
-migrated_from_fake=Мигриран от %[1]Ñ
-migrate.migrating=Мигриране от <b>%s</b>...
-migrate.migrating_failed=Мигрирането от <b>%s</b> беше неуÑпешно.
-
-mirror_from=огледало от
-forked_from=разклонено от
-fork_from_self=Ðе можете да разклоните хранилище което Ñи е Ваше.
-fork_guest_user=Влезте, за да разклоните това хранилище.
-unwatch=Ðе наблюдавам
-watch=Ðаблюдаван
-unstar=Ðе хареÑвам
-star=ХареÑван
-fork=РазклонениÑ
-download_archive=Свали хранилище
-
-no_desc=ÐÑма опиÑание
-quick_guide=Бърз Ñправочник
-clone_this_repo=Клонирай хранилището
-create_new_repo_command=Създаване на ново хранилище чрез ÐºÐ¾Ð¼Ð°Ð½Ð´Ð½Ð¸Ñ Ñ€ÐµÐ´
-empty_message=Това хранилище вÑе още не Ñъдържа нищо.
-
-code=Код
-branch=Клон
-tree=ИРна ревизиÑ
-filter_branch_and_tag=Филтър по маркер или клон
-branches=Клонове
-tags=Маркери
-issues=Задачи
-pulls=ЗаÑвки за Ñливане
-labels=Етикети
-
-milestones=Етапи
-commits=Ревизии
-releases=ВерÑии
-file_raw=Директен файл
-file_history=ИÑториÑ
-file_view_raw=Виж директен файл
-file_permalink=ПоÑтоÑнна връзка
-file_too_large=Този файл е твърде голÑм за да Ñе визуализира.
-
-video_not_supported_in_browser=ВашиÑÑ‚ браузър не поддържа HTML5 видео тагове.
-audio_not_supported_in_browser=ВашиÑÑ‚ браузър не поддържа HTML5 аудио тагове.
-symbolic_link=Символен линк
-
-editor.new_file=Ðов файл
-editor.upload_file=Качване на файл
-editor.edit_file=Редактиране на файл
-editor.preview_changes=Преглед на промени
-editor.edit_this_file=Редактиране на файл
-editor.this_file_locked=Файлът е заключен
-editor.delete_this_file=Изтриване на файл
-editor.name_your_file=Име на файла ви…
-editor.or=или
-editor.cancel_lower=Отказ
-editor.commit_changes=Промени в ревизиÑ
-editor.add=Добави '%s'
-editor.update=Модифицирай '%s'
-editor.delete=Изтрий '%s'
-editor.commit_message_desc=ДобавÑне на незадължително разширено опиÑание…
-editor.commit_directly_to_this_branch=Запази Ñ€ÐµÐ²Ð¸Ð·Ð¸Ñ Ð´Ð¸Ñ€ÐµÐºÑ‚Ð½Ð¾ в клон <strong class="branch-name">%s</strong>.
-editor.create_new_branch=Създай <strong>нов клон</strong> от тази Ñ€ÐµÐ²Ð¸Ð·Ð¸Ñ Ð¸ изпрати заÑвки за Ñливане.
-editor.create_new_branch_np=Създаване на <strong>нов клон</strong> за тази ревизиÑ.
-editor.propose_file_change=Предложи промÑна във файла
-editor.new_branch_name_desc=Име на Ð½Ð¾Ð²Ð¸Ñ ÐºÐ»Ð¾Ð½â€¦
-editor.cancel=Отказ
-editor.filename_cannot_be_empty=Името на файла не може да бъде празно.
-editor.filename_is_invalid=Името на файла е невалидно: '%s'.
-editor.branch_does_not_exist=Клон '%s' не ÑъщеÑтвува в това хранилище.
-editor.branch_already_exists=Клон '%s' вече ÑъщеÑтвува в това хранилище.
-editor.file_is_a_symlink='%s' е Ñимволен линк. Символните линкове не могат да бъдат редактирани в уеб редактора
-editor.file_editing_no_longer_exists=РедактираниÑÑ‚ файл '%s' вече не ÑъщеÑтвува в това хранилище.
-editor.file_deleting_no_longer_exists=ИзтриваниÑÑ‚ файл '%s' вече не ÑъщеÑтвува в това хранилище.
-editor.file_already_exists=Файл Ñ Ð¸Ð¼Ðµ '%s' вече ÑъщеÑтвува в това хранилище.
-editor.no_changes_to_show=ÐÑма промени.
-editor.add_subdir=ДобавÑне на директориÑ…
-editor.unable_to_upload_files=Ðевъзможно качване на файлове в '%s' заради грешка: %v
-editor.upload_file_is_locked=Файлът '%s' е заключен от %s.
-editor.upload_files_to_dir=Качи файлове в '%s'
-editor.cannot_commit_to_protected_branch=Ðе могат да бъдат направени ревизии към защитен клон '%s'.
-editor.require_signed_commit=Клонът изиÑква подпиÑана ревизиÑ
-
-commits.desc=Разгледай иÑториÑта на промените на Ð¸Ð·Ñ…Ð¾Ð´Ð½Ð¸Ñ ÐºÐ¾Ð´.
-commits.commits=Ревизии
-commits.no_commits=ÐÑма общи ревизии. '%s' и '%s' имат напълно различни иÑтории.
-commits.search=ТърÑене в ревизии…
-commits.find=ТърÑене
-commits.search_all=Ð’Ñички клонове
-commits.author=Ðвтор
-commits.message=Съобщение
-commits.date=Дата
-commits.older=По-Ñтари
-commits.newer=По-нови
-commits.signed_by=ПодпиÑан от
-commits.gpg_key_id=GPG ключ ID
-
-
-ext_issues.desc=Свързване на външна ÑиÑтема за Ñледене на задачи.
-
-
-issues.desc=Организиране на доклади за бъгове, задачи и етапи.
-issues.new=Ðова задача
-issues.new.title_empty=Заглавието не може да бъде празно
-issues.new.labels=Етикети
-issues.new.no_label=ÐÑма етикет
-issues.new.clear_labels=ИзчиÑти етикети
-issues.new.milestone=Етап
-issues.new.no_milestone=ÐÑма етап
-issues.new.clear_milestone=ИзчиÑти етап
-issues.new.open_milestone=Отворени етапи
-issues.new.closed_milestone=Затворени етапи
-issues.new.assignees=Изпълнители
-issues.new.clear_assignees=ИзчиÑти изпълнители
-issues.new.no_assignees=ÐÑма изпълнители
-issues.no_ref=ÐÑма зададен клон/таг
-issues.create=Създай задача
-issues.new_label=Ðов етикет
-issues.new_label_placeholder=Име на етикета
-issues.new_label_desc_placeholder=ОпиÑание
-issues.create_label=Създай етикет
-issues.label_templates.title=Зареждане на предварително зададен набор от етикети
-issues.label_templates.info=Ðе ÑъщеÑтвуват етикети вÑе още. Създайте етикет Ñ 'Ðов етикет' или използвайте предварително дефиниран набор етикети:
-issues.label_templates.helper=Изберете набор етикети
-issues.label_templates.use=Използвай набор етикети
-issues.label_templates.fail_to_load_file=ÐеуÑпешно зареждане на шаблон Ñ ÐµÑ‚Ð¸ÐºÐµÑ‚Ð¸ '%s': %v
-issues.deleted_milestone=`(изтрито)`
-issues.filter_label=Етикет
-issues.filter_milestone=Етап
-issues.filter_assignee=Изпълнител
-issues.filter_type=Тип
-issues.filter_type.all_issues=Ð’Ñички задачи
-issues.filter_type.assigned_to_you=Възложени на ВаÑ
-issues.filter_type.created_by_you=Създадени от ВаÑ
-issues.filter_type.mentioning_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=Ðай-малко коментирани
-issues.action_open=ОтварÑне
-issues.action_close=ЗатварÑне
-issues.action_label=Етикет
-issues.action_milestone=Етап
-issues.action_milestone_no_select=ÐÑма етап
-issues.opened_by=отворен %[1]s от <a href="%[2]s">%[3]s</a>
-issues.previous=Предишна
-issues.next=Следваща
-issues.open_title=Отворени
-issues.closed_title=Затворени
-issues.num_comments=%d коментара
-issues.commented_at=`коментира <a href="#%s">%s</a>`
-issues.delete_comment_confirm=Желаете ли да изтриете този коментар?
-issues.context.copy_link=Копиране на връзката
-issues.context.edit=Редактиране
-issues.context.delete=Изтриване
-issues.no_content=Ð’Ñе още нÑма Ñъдържание.
-issues.close_issue=Затвори
-issues.reopen_issue=Отвори повторно
-issues.create_comment=Коментирай
-issues.commit_ref_at=`поÑочи тази задача от Ñ€ÐµÐ²Ð¸Ð·Ð¸Ñ <a id="%[1]s" href="#%[1]s">%[2]s</a>`
-issues.poster=УчаÑтник
-issues.collaborator=Сътрудник
-issues.owner=Притежател
-issues.sign_in_require_desc=<a href="%s">Впишете Ñе</a> за да Ñе приÑъедините към разговора.
-issues.edit=РедакциÑ
-issues.cancel=Отказ
-issues.save=ЗапиÑ
-issues.label_title=Име на етикета
-issues.label_color=ЦвÑÑ‚ на етикет
-issues.label_count=%d етикети
-issues.label_open_issues=%d отворени задачи
-issues.label_edit=РедакциÑ
-issues.label_delete=Изтрий
-issues.label_deletion=Изтриване на етикет
-issues.label_deletion_desc=Изтриването на етикет го премахва от вÑички задачи. Продължи?
-issues.label_deletion_success=Етикетът беше изтрит.
-issues.label.filter_sort.alphabetically=По азбучен ред
-issues.label.filter_sort.by_size=Ðай-малката големина
-issues.label.filter_sort.reverse_by_size=Ðай-голÑмата големина
-issues.num_participants=%d учаÑтника
-issues.attachment.open_tab=`Щракнете за да прегледате "%s" в нов раздел`
-issues.attachment.download=`Щракнете за да изтеглите "%s"`
-issues.subscribe=Ðбониране
-issues.unsubscribe=ОтпиÑване
-issues.lock=Заключване на доÑкуÑиÑта
-issues.unlock=Отключване на диÑкуÑиÑта
-issues.lock_duplicate=Задача не може да бъде заключена два пъти.
-issues.unlock_comment=отключи този разговор %s
-issues.lock_confirm=Заключване
-issues.unlock_confirm=Отключване
-issues.lock.notice_1=-Други потребители не могат да добавÑÑ‚ нови коментари по този въпроÑ.
-issues.lock.reason=Причина за заключване
-issues.tracker=Тракер на време
-issues.tracker_auto_close=Таймерът ще бъде ÑпрÑн автоматично, когато билетът бъде затворен
-issues.add_time_short=Добави време
-issues.add_time_cancel=Отказ
-issues.add_time_history=`добави прекарано време %s`
-issues.del_time_history=`изтрий прекарано време %s`
-issues.add_time_hours=ЧаÑа
-issues.add_time_minutes=Минути
-issues.add_time_sum_to_small=ÐÑма въведено време.
-issues.due_date_form=гггг-мм-дд
-issues.due_date_form_add=Добави краен Ñрок
-issues.due_date_form_edit=РедакциÑ
-issues.due_date_form_remove=Премахни
-issues.due_date_overdue=ПроÑрочен
-issues.due_date_invalid=КрайниÑÑ‚ Ñрок е невалиден или извън обхват. ÐœÐ¾Ð»Ñ Ð¸Ð·Ð¿Ð¾Ð»Ð·Ð²Ð°Ð¹Ñ‚Ðµ форматът 'гггг-мм-дд'.
-issues.dependency.title=ЗавиÑимоÑти
-issues.dependency.add=ДобавÑне на завиÑимоÑт…
-issues.dependency.cancel=Отказ
-issues.dependency.remove=Премахване
-issues.dependency.remove_info=Премахване на тази завиÑимоÑÑ‚
-issues.dependency.blocks_short=Блокове
-issues.dependency.remove_header=Премахване на завиÑимоÑÑ‚
-issues.review.pending=Чака
-issues.review.show_outdated=Покажи оÑтарели
-issues.review.hide_outdated=Скрий оÑтарели
-issues.assignee.error=Ðе вÑички изпълнители бÑха добавени поради неочаквана грешка.
-
-
-pulls.new=Ðова заÑвка за Ñливане
-pulls.compare_base=Ñлей в
-pulls.filter_branch=Филтър по клон
-pulls.no_results=ÐÑма резултати.
-pulls.nothing_to_compare=Тези клонове Ñа еднакви. ÐÑма нужда за Ñъздаване на заÑвка за Ñливане.
-pulls.create=Създай заÑвка за Ñливане
-pulls.title_desc=заÑви обединÑване на %[1]d ревизии от <code>%[2]s</code> във <code id="branch_target">%[3]s</code>
-pulls.merged_title_desc=обедини %[1]d ревизии от <code>%[2]s</code> във <code>%[3]s</code> %[4]s
-pulls.change_target_branch_at=`промени Ñ†ÐµÐ»ÐµÐ²Ð¸Ñ ÐºÐ»Ð¾Ð½ от <b>%s</b> в <b>%s</b> %s`
-pulls.tab_conversation=Разговор
-pulls.tab_commits=Ревизии
-pulls.tab_files=Променени файлове
-pulls.reopen_to_merge=ÐœÐ¾Ð»Ñ Ð¿Ð¾Ð²Ñ‚Ð¾Ñ€Ð½Ð¾ отворете тази заÑвка за Ñливане, за да Ñе извърши обединÑване.
-pulls.cant_reopen_deleted_branch=Тази завка за Ñливане не може да бъде отворена повторно, защото клонът е бил изтрит.
-pulls.merged=Обединени
-pulls.merged_as=Тази заÑвка за Ñливане е била обединена като <a rel="nofollow" class="ui sha" href="%[1]s"><code>%[2]s</code></a>.
-pulls.is_closed=Тази заÑвка за Ñливане е затворена.
-pulls.has_merged=Тази заÑвка за Ñливане е обединена.
-pulls.title_wip_desc=`<a href="#">Започнете заглавието Ñ <strong>%s</strong></a>, за да предотвратите Ñлучайно обединÑване на заÑвката за Ñливане.`
-pulls.can_auto_merge_desc=Може да Ñе извърши обединÑване на тази заÑвка за Ñливане.
-pulls.num_conflicting_files_1=%d конфликтен файл
-pulls.num_conflicting_files_n=%d конфликтни файлове
-
-pulls.no_merge_desc=Тази заÑвка за Ñливане не може да бъде обединена, защото вÑички опции за обединÑване на хранилището Ñа изключени.
-pulls.no_merge_helper=Включете опции за Ñливане в наÑтройките на хранилището или обединете заÑвката за Ñливане ръчно.
-pulls.no_merge_wip=Тази заÑвка за Ñливане не може да бъде обединена, защото е отбелÑзана като работа в прогреÑ.
-
-; </summary><code>%[2]s<br>%[3]s</code></details>
-pulls.status_checks_success=Ð’Ñички проверÑÐ²Ð°Ð½Ð¸Ñ Ð±Ñха уÑпешни
-
-
-
-
-
-milestones.new=Ðов етап
-milestones.closed=Затворен %s
-milestones.no_due_date=ÐÑма краен Ñрок
-milestones.open=Отвори
-milestones.close=Затвори
-milestones.create=Създай етап
-milestones.title=Заглавие
-milestones.desc=ОпиÑание
-milestones.due_date=Краен Ñрок (опционален)
-milestones.clear=ИзчиÑти
-milestones.create_success=Етапът '%s' беше Ñъздаден.
-milestones.edit=Редактирай етап
-milestones.edit_subheader=Етапите организират задачи и проÑледÑват прогреÑ.
-milestones.cancel=Отказ
-milestones.modify=Промени етап
-milestones.edit_success=Етапът '%s' беше променен.
-milestones.deletion=Изтрий етап
-milestones.deletion_desc=Изтриването на етап го премахва от вÑички Ñвързани задачи. Продължаване?
-milestones.deletion_success=Този етап е изтрит.
-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=Ревизиите винаги Ñе подпиÑват
-
-ext_wiki.desc=Връзка към външното уики.
-
-wiki=Уики
-wiki.welcome=Добре дошли в Уикито.
-wiki.welcome_desc=Уикито ви позволÑва да пишете и ÑподелÑте Ð´Ð¾ÐºÑƒÐ¼ÐµÐ½Ñ‚Ð°Ñ†Ð¸Ñ ÑÑŠÑ Ñътрудници.
-wiki.desc=Пишете и ÑподелÑте Ð´Ð¾ÐºÑƒÐ¼ÐµÐ½Ñ‚Ð°Ñ†Ð¸Ñ ÑÑŠÑ Ñътрудници.
-wiki.create_first_page=Създайте първата Ñтраница
-wiki.page=Страница
-wiki.filter_page=Филтър Ñтраница
-wiki.new_page=Страница
-wiki.save_page=Ð—Ð°Ð¿Ð¸Ñ Ð½Ð° Ñтраница
-wiki.last_commit_info=%s редактира тази Ñтраница %s
-wiki.edit_page_button=РедакциÑ
-wiki.new_page_button=Ðова Ñтраница
-wiki.delete_page_button=Изтрий Ñтраница
-wiki.page_already_exists=Страница ÑÑŠÑ Ñъщото име вече ÑъщеÑтвува.
-wiki.pages=Страници
-wiki.last_updated=ПоÑледна Ð¼Ð¾Ð´Ð¸Ñ„Ð¸ÐºÐ°Ñ†Ð¸Ñ Ð½Ð° %s
-
-activity.period.filter_label=Период:
-activity.period.daily=1 ден
-activity.period.halfweekly=3 дни
-activity.period.weekly=1 Ñедмица
-activity.period.monthly=1 меÑец
-activity.title.user_1=%d потребител
-activity.title.user_n=%d потребителÑ
-activity.merged_prs_label=Слети
-activity.closed_issue_label=Затворено
-activity.new_issue_label=Отворено
-activity.unresolved_conv_label=ОтварÑне
-activity.published_release_label=Публикувано
-activity.git_stats_author_1=%d автор
-activity.git_stats_author_n=%d автори
-activity.git_stats_file_1=%d файл
-activity.git_stats_file_n=%d файла
-activity.git_stats_and_deletions=и
-
-search=ТърÑене
-
-settings=ÐаÑтройки
-settings.collaboration.write=За пиÑане
-settings.collaboration.read=За четене
-settings.collaboration.undefined=Ðедефинирано
-settings.hooks=Уеб-куки
-settings.githooks=Git куки
-settings.basic_settings=ОÑновни наÑтройки
-settings.mirror_settings=ÐаÑтройки на огледало
-settings.sync_mirror=Синхронизиране Ñега
-settings.site=УебÑайт
-settings.update_settings=Запази наÑтройките
-settings.advanced_settings=Разширени наÑтройки
-settings.external_wiki_url=URL Ð°Ð´Ñ€ÐµÑ Ð½Ð° външно уики
-settings.tracker_url_format=Формат на URL Ð°Ð´Ñ€ÐµÑ Ð½Ð° външна ÑиÑтема за проÑледÑване на задачи
-settings.tracker_issue_style.numeric=Цифров
-settings.tracker_issue_style.alphanumeric=Символен
-settings.danger_zone=ОпаÑна зона
-settings.new_owner_has_same_repo=ÐовиÑÑ‚ притежател вече има хранилище ÑÑŠÑ Ñъщото име. Изберете друго име.
-settings.transfer=Прехвърли притежание
-settings.transfer_owner=Ðов притежател
-settings.delete=Изтрий това хранилище
-settings.delete_notices_1=- Тази Ð¾Ð¿ÐµÑ€Ð°Ñ†Ð¸Ñ <strong>ÐЕ МОЖЕ</strong> да бъде отменена в поÑледÑтвие.
-settings.add_collaborator=ДобавÑне на Ñътрудник
-settings.delete_collaborator=Премахване
-settings.search_user_placeholder=ТърÑене на потребител…
-settings.add_webhook=Добави уеб-кука
-settings.webhook.test_delivery=ТеÑтово изпращане
-settings.webhook.request=ЗаÑвка
-settings.webhook.response=Отговор
-settings.webhook.headers=Заглавки
-settings.webhook.payload=Съдържание
-settings.webhook.body=ТÑло
-settings.githook_edit_desc=Ðко куката е неактивна, ще бъде предÑтавено примерно Ñъдържание. Ðко оÑтавите Ñъдържанието празно, то тази кука ще бъде изключена.
-settings.githook_name=Име на куката
-settings.githook_content=Съдържание на куката
-settings.update_githook=Запази куката
-settings.secret=Тайна
-settings.slack_username=ПотребителÑко име
-settings.slack_icon_url=URL Ð°Ð´Ñ€ÐµÑ Ð½Ð° икона
-settings.discord_username=ПотребителÑко име
-settings.discord_icon_url=URL Ð°Ð´Ñ€ÐµÑ Ð½Ð° икона
-settings.event_send_everything=Ð’Ñички ÑъбитиÑ
-settings.event_create=Създаване
-settings.event_delete=Изтриване
-settings.event_push=Предаване
-settings.event_pull_request=ЗаÑвка за Ñливане
-settings.update_webhook=Запази уеб-куката
-settings.recent_deliveries=ПоÑледни изпращаниÑ
-settings.hook_type=Тип на куката
-settings.slack_token=API ключ
-settings.slack_domain=Домейн
-settings.slack_channel=Канал
-settings.deploy_keys=Ключове за внедрÑване
-settings.add_deploy_key=Добави ключ за внедрÑване
-settings.title=Заглавие
-settings.deploy_key_content=Съдържание
-settings.branches=Клонове
-settings.protected_branch=Защита на клона
-settings.add_protected_branch=Включване на защита
-settings.delete_protected_branch=Изключване на защита
-settings.choose_branch=Изберете клон…
-settings.edit_protected_branch=Редактиране
-settings.chat_id=№ на чат
-settings.lfs_invalid_locking_path=Ðевалиден път: %s
-
-diff.browse_source=Преглед на файлове
-diff.parent=родител
-diff.commit=ревизиÑ
-diff.git-notes=Бележки
-diff.show_diff_stats=Показване на ÑтатиÑтика
-diff.show_split_view=Разделен изглед
-diff.show_unified_view=Обединен изглед
-diff.stats_desc=променени Ñа <strong>%d файла</strong>, в които Ñа <strong>добавени %d</strong> реда и Ñа <strong>изтрити %d</strong> реда
-diff.bin=Двоични данни
-diff.view_file=Ð¦ÐµÐ»Ð¸Ñ Ñ„Ð°Ð¹Ð»
-diff.file_before=Преди
-diff.file_after=След
-diff.file_image_width=Ширина
-diff.file_image_height=ВиÑочина
-diff.file_byte_size=Големина
-diff.file_suppressed=Файловите разлики Ñа ограничени, защото Ñа твърде много
-diff.comment.placeholder=ОÑтавÑне на коментар
-diff.comment.add_review_comment=ДобавÑне на коментар
-diff.comment.reply=Отговор
-diff.review.comment=Коментар
-diff.review.approve=ОдобрÑване
-
-release.releases=ВерÑии
-release.new_release=Ðова верÑиÑ
-release.draft=Чернови
-release.prerelease=Предварителни
-release.stable=Стабилни
-release.edit=редактиране
-release.source_code=Изходен код
-release.tag_name=Име на маркера
-release.target=Цел
-release.title=Заглавие
-release.content=Съдържание
-release.cancel=Отказ
-release.publish=Публикувай верÑиÑ
-release.save_draft=Ð—Ð°Ð¿Ð¸Ñ Ð½Ð° чернова
-release.downloads=ИзтеглÑниÑ
-
-branch.search=ТърÑене на клонове
-branch.delete_head=Изтриване
-branch.delete_html=Изтриване на клон
-branch.create_from=от '%s'
-branch.deleted_by=Изтрито от %s
-branch.included=Включено
-
-
-
-topic.done=Готово
-
-
-
-[org]
-org_name_holder=Име на организациÑта
-org_full_name_holder=Пълно име на организациÑта
-create_org=Създай организациÑ
-repo_updated=ПоÑледна модификациÑ
-people=УчаÑтници
-teams=Екипи
-lower_members=учаÑтници
-lower_repositories=хранилища
-create_new_team=Ðов отбор
-create_team=Създаване на отбор
-org_desc=ОпиÑание
-team_name=Име на екипа
-team_desc=ОпиÑание
-team_permission_desc=Позволение
-
-
-settings=ÐаÑтройки
-settings.options=ОрганизациÑ
-settings.full_name=Пълно име
-settings.website=УебÑайт
-settings.location=ЛокациÑ
-settings.permission=ПозволениÑ
-settings.visibility=ВидимоÑÑ‚
-
-settings.update_settings=Запази наÑтройките
-settings.delete=Изтрий организациÑта
-settings.delete_account=Изтриване на тази организациÑ
-settings.confirm_delete_account=Потвърди изтриването
-
-
-members.membership_visibility=ВидимоÑÑ‚:
-members.public=Видимо
-members.private=Скрито
-members.member_role=РолÑ:
-members.owner=Притежател
-members.member=УчаÑтник
-members.remove=Премахни
-members.leave=ÐапуÑни
-members.invite_desc=Добави нов учаÑтник в %s:
-members.invite_now=Покани
-
-teams.join=ПриÑъедини Ñе
-teams.leave=ÐапуÑни
-teams.no_desc=Този екип нÑма опиÑание
-teams.settings=ÐаÑтройки
-teams.members=УчаÑтници в екипа
-teams.update_settings=Запази наÑтройките
-teams.add_team_member=Добави учаÑтник в екипа
-teams.repositories=Хранилища на екипа
-teams.add_nonexistent_repo=Хранилището, което Ñе опитвате да добавите не ÑъщеÑтвува. ÐœÐ¾Ð»Ñ Ð¿ÑŠÑ€Ð²Ð¾ го Ñъздайте!
-
-[admin]
-dashboard=Табло
-organizations=Организации
-repositories=Хранилища
-emails=ПотребителÑки имейли
-config=КонфигурациÑ
-notices=СиÑтемни извеÑтиÑ
-monitor=Ðаблюдение
-first_page=Първа
-last_page=ПоÑледна
-total=Общо: %d
-
-dashboard.operation_name=Име на операциÑта
-dashboard.operation_switch=Превключи
-dashboard.operation_run=Изпълни
-dashboard.server_uptime=Операционно време
-dashboard.current_goroutine=Текущи Goroutines
-dashboard.current_memory_usage=Текущо използвана памет
-dashboard.total_memory_allocated=Общо заделена памет
-dashboard.memory_obtained=Получена памет
-dashboard.pointer_lookup_times=Брой Ð¾Ð±Ñ…Ð¾Ð¶Ð´Ð°Ð½Ð¸Ñ Ð½Ð° указатели
-dashboard.current_heap_usage=Текущо използвана оÑн. памет
-dashboard.heap_memory_obtained=Получена оÑн. памет
-dashboard.heap_memory_idle=Празна оÑн. памет
-dashboard.heap_memory_in_use=Използвана оÑн. памет
-dashboard.heap_memory_released=ОÑвободена оÑн. памет
-dashboard.heap_objects=Обекти в оÑн. памет
-dashboard.bootstrap_stack_usage=Използван Ñтек за bootstrap
-dashboard.stack_memory_obtained=Заделена памет в Ñтека
-dashboard.mspan_structures_usage=Използвани MSpan обекти
-dashboard.mspan_structures_obtained=Получени MSpan обекти
-dashboard.mcache_structures_usage=Използвани MCache обекти
-dashboard.mcache_structures_obtained=Получени MCache обекти
-dashboard.profiling_bucket_hash_table_obtained=Получени Profiling Bucket Hash Table
-dashboard.gc_metadata_obtained=Получени GC метаданни
-dashboard.other_system_allocation_obtained=Получена друга ÑиÑтемна памет
-dashboard.next_gc_recycle=Следващо рециклиране на GC
-dashboard.last_gc_time=Време от поÑледен GC
-dashboard.total_gc_time=Общо време за GC
-dashboard.total_gc_pause=Общо пауза за GC
-dashboard.last_gc_pause=ПоÑледна пауза за GC
-dashboard.gc_times=Брой GC
-
-users.name=ПотребителÑко име
-users.full_name=Пълно име
-users.activated=Ðктивиран
-users.admin=ÐдминиÑтратор
-users.restricted=С ограничение
-users.repos=Хранилища
-users.created=Създаване
-users.edit=РедакциÑ
-users.auth_source=Ðачин на удоÑтоверÑване
-users.local=Локално
-
-emails.filter_sort.email=Ел. поща
-emails.filter_sort.name=ПотребителÑко име
-
-orgs.org_manage_panel=Управление на организациÑта
-orgs.name=Име
-orgs.teams=Екипи
-orgs.members=УчаÑтници
-orgs.new_orga=Ðова организациÑ
-
-repos.owner=Притежател
-repos.name=Име
-repos.private=ЧаÑтно
-repos.watches=ÐаблюдаваниÑ
-repos.stars=ХареÑваниÑ
-repos.issues=Задачи
-repos.size=Големина
-
-
-
-
-auths.name=Име
-auths.type=Тип
-auths.enabled=Ðктивно
-auths.updated=ПоÑледна модификациÑ
-auths.auth_type=Тип на удоÑтоверÑване
-auths.auth_name=Име на удоÑтоверÑване
-auths.security_protocol=Протокол за защита
-auths.domain=Домейн
-auths.host=Сървър
-auths.port=Порт
-auths.bind_dn=Име (DN) за Ñвръзка
-auths.bind_password=Парола за Ñвръзка
-auths.user_base=Базов OU за Ñ‚ÑŠÑ€Ñене
-auths.user_dn=Име (DN) на потребител
-auths.search_page_size=Големина на Ñтраницата
-auths.filter=Филтър за потребител
-auths.admin_filter=Филтър за админиÑтратор
-auths.smtp_auth=SMTP удоÑтоверÑване
-auths.smtphost=SMTP Ñървър
-auths.smtpport=SMTP порт
-auths.allowed_domains=Разрешени домейни
-auths.skip_tls_verify=ПропуÑни проверка на TLS Ñертификат
-auths.pam_service_name=Име на PAM уÑлуга
-auths.oauth2_profileURL=URL Ð°Ð´Ñ€ÐµÑ Ð½Ð° профила
-auths.oauth2_emailURL=Имейл адреÑ
-auths.enable_auto_register=Включи автоматична региÑтрациÑ
-auths.tips=Съвети
-
-config.server_config=Сървърни наÑтройки
-config.disable_router_log=Изключи журнал на маршрутизатора
-config.run_mode=Режим на изпълнение
-config.git_version=ВерÑÐ¸Ñ Ð½Ð° Git
-config.repo_root_path=ОÑновен път към хранилища
-config.static_file_root_path=Път към Ñтатични файлове
-config.script_type=Тип на Ñкрипта
-config.reverse_auth_user=ПотребителÑко име при обратно удоÑтоверÑване
-
-config.ssh_config=SSH конфигурациÑ
-config.ssh_enabled=Ðктивен
-config.ssh_port=Порт
-config.ssh_listen_port=Порт за Ñлушане
-config.ssh_root_path=ОÑновен път
-config.ssh_key_test_path=Път до ключове
-config.ssh_keygen_path=Път до генератор ('ssh-keygen')
-config.ssh_minimum_key_size_check=Проверка за минимален размер на ключове
-config.ssh_minimum_key_sizes=Минимален размер на ключове
-
-config.lfs_config=Конфигуриране на LFS
-config.lfs_enabled=Включено
-
-config.db_config=ÐаÑтройки на базата данни
-config.db_type=Тип
-config.db_host=Сървър
-config.db_name=Име
-config.db_user=ПотребителÑко име
-config.db_schema=Схема
-config.db_ssl_mode=SSL
-config.db_path=Път
-
-config.service_config=ÐаÑтройка на уÑлугата
-config.show_registration_button=Покажи бутон за региÑтрациÑ
-config.disable_key_size_check=Изключи проверка минимален размер на ключ
-config.active_code_lives=Кодове за активиране
-
-config.webhook_config=ÐšÐ¾Ð½Ñ„Ð¸Ð³ÑƒÑ€Ð°Ñ†Ð¸Ñ Ð½Ð° уеб-куки
-config.queue_length=Дължина на опашка
-config.deliver_timeout=Време за отказ при изпращане
-
-config.mailer_enabled=Ðктивен
-config.mailer_name=Име
-config.mailer_user=Потребител
-
-config.oauth_config=OAuth конфигурациÑ
-config.oauth_enabled=Ðктивна
-
-config.cache_config=ÐšÐ¾Ð½Ñ„Ð¸Ð³ÑƒÑ€Ð°Ñ†Ð¸Ñ Ð½Ð° кеша
-config.cache_adapter=Кеш адаптер
-config.cache_interval=Кеш интервал
-config.cache_conn=Кеш на връзката
-
-config.session_config=ÐšÐ¾Ð½Ñ„Ð¸Ð³ÑƒÑ€Ð°Ñ†Ð¸Ñ Ð½Ð° ÑеÑии
-config.session_provider=ДоÑтавчик на ÑеÑии
-config.provider_config=ÐšÐ¾Ð½Ñ„Ð¸Ð³ÑƒÑ€Ð°Ñ†Ð¸Ñ Ð½Ð° доÑтавчик
-config.cookie_name=Име на биÑквитката
-config.gc_interval_time=GC през интервал
-config.session_life_time=Период на валидноÑÑ‚ на ÑеÑиите
-config.https_only=HTTPS Ñамо
-config.cookie_life_time=Период на валидноÑÑ‚ на биÑквитките
-
-config.picture_service=УÑлуги за Ñнимки
-config.disable_gravatar=Изключи Gravatar
-config.enable_federated_avatar=Включи външни аватари
-
-config.git_config=ÐšÐ¾Ð½Ñ„Ð¸Ð³ÑƒÑ€Ð°Ñ†Ð¸Ñ Ð½Ð° git
-config.git_disable_diff_highlight=Забрани оцветÑване на ÑинтакÑÐ¸Ñ Ð¿Ñ€Ð¸ преглед на разлики
-config.git_max_diff_lines=МакÑимален брой различни редове (за файл)
-config.git_max_diff_line_characters=МакÑимален брой различни Ñимволи (на ред)
-config.git_max_diff_files=МакÑимален брой променени файлове (при показване)
-config.git_gc_args=Ðргументи на GC
-config.git_migrate_timeout=Време за отказ при миграциÑ
-config.git_mirror_timeout=Време за отказ при Ñинхр. на огледало
-config.git_clone_timeout=Време за отказ при клониране
-config.git_pull_timeout=Време за отказ при Ñливане
-config.git_gc_timeout=Време за отказ при GC
-
-config.log_config=ÐšÐ¾Ð½Ñ„Ð¸Ð³ÑƒÑ€Ð°Ñ†Ð¸Ñ Ð½Ð° журнал
-config.log_mode=Режим на журнал
-config.disabled_logger=Изключено
-
-
-monitor.cron=Cron задачи
-monitor.name=Име
-monitor.schedule=График
-monitor.next=Следващ път
-monitor.previous=Предишен път
-monitor.process=ИзпълнÑвани процеÑи
-monitor.desc=ОпиÑание
-monitor.start=Ðачален чаÑ
-monitor.execute_time=Време за изпълнение
-monitor.queue.name=Име
-
-
-
-notices.system_notice_list=СиÑтемни извеÑтиÑ
-notices.actions=ДейÑтвиÑ
-notices.select_all=Избери вÑички
-notices.deselect_all=Без избрани
-notices.inverse_selection=Обърни избора
-notices.delete_selected=Изтрий избраните
-notices.delete_all=Изтрий вÑички ÑъобщениÑ
-notices.type=Тип
-notices.type_1=Хранилище
-notices.desc=ОпиÑание
-notices.op=Oп.
-
-[action]
-create_repo=Ñъздаде хранилище <a href="%s"> %s</a>
-rename_repo=преименува хранилище от <code>%[1]s</code> на <a href="%[2]s">%[3]s</a>
-transfer_repo=прехвърли хранилище <code>%s</code> към <a href="%s">%s</a>
-
-[tool]
-ago=преди %s
-from_now=Ñлед %s
-now=Ñега
-future=в бъдеще
-1s=1 Ñекунда
-1m=1 минута
-1h=1 чаÑ
-1d=1 ден
-1w=1 Ñедмица
-1mon=1 меÑец
-1y=1 година
-seconds=%d Ñекунди
-minutes=%d минути
-hours=%d чаÑа
-days=%d дни
-weeks=%d Ñедмици
-months=%d меÑеца
-years=%d години
-raw_seconds=Ñекунди
-raw_minutes=минути
-
-[dropzone]
-remove_file=Премахни файл
-
-[notification]
-notifications=ИзвеÑтиÑ
-unread=Ðепрочетенo
-read=За четене
-mark_as_read=Бележа като прочетено
-mark_as_unread=Бележа като непрочетено
-mark_all_as_read=Бележа вÑичко като прочетено
-
-[gpg]
-
-[units]
-
-[packages]
-
diff --git a/options/locale/locale_cs-CZ.ini b/options/locale/locale_cs-CZ.ini
index 709a71a13..543cd4404 100644
--- a/options/locale/locale_cs-CZ.ini
+++ b/options/locale/locale_cs-CZ.ini
@@ -41,7 +41,7 @@ webauthn_use_twofa=Použít dvoufaktorový kód z vašeho telefonu
webauthn_error=NepodaÅ™ilo se pÅ™eÄíst váš zabezpeÄovací klíÄ.
webauthn_unsupported_browser=Váš prohlížeÄ momentálnÄ› nepodporuje WebAuthn.
webauthn_error_unknown=Došlo k neznámé chybě. Opakujte akci.
-webauthn_error_insecure=WebAuthn podporuje pouze zabezpeÄená pÅ™ipojení. Pro testování pÅ™es HTTP můžete použít výchozí "localhost" nebo "127.0.0.1"
+webauthn_error_insecure=`WebAuthn podporuje pouze zabezpeÄená pÅ™ipojení. Pro testování pÅ™es HTTP můžete použít výchozí "localhost" nebo "127.0.0.1"`
webauthn_error_unable_to_process=Server nemohl zpracovat váš požadavek.
webauthn_error_duplicated=ZabezpeÄovací klÃ­Ä není pro tento požadavek povolen. Prosím ujistÄ›te se, zda klÃ­Ä není již registrován.
webauthn_error_empty=Musíte nastavit název tohoto klíÄe.
@@ -57,7 +57,7 @@ new_mirror=Nové zrcadlo
new_fork=Nové rozštěpení repozitáře
new_org=Nová organizace
new_project=Nový projekt
-new_project_board=Nová projektová nástěnka
+new_project_column=Nový sloupec
manage_org=Spravovat organizace
admin_panel=Administrace
account_settings=Nastavení úÄtu
@@ -86,11 +86,16 @@ remove=Odstranit
remove_all=Odstranit vše
edit=Upravit
+enabled=Povolený
+disabled=Zakázané
+
copy=Kopírovat
copy_url=Kopírovat URL
+copy_content=Kopírovat obsah
copy_branch=Kopírovat jméno větve
copy_success=Zkopírováno!
copy_error=Kopírování se nezdařilo
+copy_type_unsupported=Tento typ souboru nelze zkopírovat
write=Zapsat
preview=Náhled
@@ -106,6 +111,12 @@ never=Nikdy
rss_feed=RSS kanál
+[aria]
+navbar=NavigaÄní liÅ¡ta
+footer=PatiÄka
+footer.software=O softwaru
+footer.links=Odkazy
+
[filter]
string.asc=A – Z
string.desc=Z – A
@@ -221,7 +232,7 @@ invalid_db_setting=Nastavení databáze je neplatné: %v
invalid_db_table=Databázová tabulka „%s“ je neplatná: %v
invalid_repo_path=Kořenový adresář repozitářů není správný: %v
invalid_app_data_path=Cesta k datům aplikace je neplatná: %v
-run_user_not_match="Run as" uživatelské jméno není aktuální uživatelské jméno: %s -> %s
+run_user_not_match=`"Run as\" uživatelské jméno není aktuální uživatelské jméno: %s -> %s`
internal_token_failed=Nepodařilo se vytvořit interní token: %v
secret_key_failed=NepodaÅ™ilo se vytvoÅ™it tajný klíÄ: %v
save_config_failed=Uložení konfigurace se nezdařilo: %v
@@ -287,6 +298,71 @@ code_no_results=Nebyl nalezen žádný zdrojový kód odpovídající hledanému
code_search_results=Výsledky hledání pro „%s“
code_last_indexed_at=Naposledy indexováno %s
relevant_repositories_tooltip=Repozitáře, které jsou rozštěpení nebo nemají žádné téma, ikonu a žádný popis jsou skryty.
+relevant_repositories=`Zobrazují se pouze relevantní repositáře, <a href="`
+internal_token_failed=Nepodařilo se vytvořit interní token: %v
+secret_key_failed=NepodaÅ™ilo se vytvoÅ™it tajný klíÄ: %v
+save_config_failed=Uložení konfigurace se nezdařilo: %v
+invalid_admin_setting=Nastavení úÄtu správce není správné: %v
+invalid_log_root_path=Kořenový adresář logů není správný: %v
+default_keep_email_private=Jako poÄáteÄní nastavení skrýt e-mailové adresy
+default_keep_email_private_popup=Nastaví e-mailové adresy novým uživatelským úÄtům jako skryté.
+default_allow_create_organization=Dovolí novým uživatelům zakládat organizace
+default_allow_create_organization_popup=Povolit novým uživatelským úÄtům vytvářet organizace.
+default_enable_timetracking=Povolit sledování Äasu ve výchozím nastavení
+default_enable_timetracking_popup=Povolí sledování Äasu pro nové repozitáře.
+no_reply_address=Skrytá e-mailová doména
+no_reply_address_helper=Název domény pro uživatele se skrytou e-mailovou adresou. Příklad: Pokud je název skryté e-mailové domény nastaven na „noreply.example.org“, uživatelské jméno „joe“ bude zaznamenáno v Gitu jako „joe@noreply.example.org“.
+password_algorithm=Hash algoritmus hesla
+password_algorithm_helper=Nastavte algoritmus hashování hesla. Algoritmy mají odlišné požadavky a sílu. `argon2` používá mnoho paměti a může být nevhodný pro malé systémy.
+enable_update_checker=Povolit kontrolu aktualizací
+enable_update_checker_helper=Kontroluje vydání nových verzí pravidelně připojením ke gitea.io.
+
+[home]
+uname_holder=Uživatelské jméno nebo e-mailová adresa
+password_holder=Heslo
+switch_dashboard_context=Přepnout kontext přehledu
+my_repos=Repozitáře
+show_more_repos=Zobrazit více repozitářů…
+collaborative_repos=SpoleÄné repozitáře
+my_orgs=Mé organizace
+my_mirrors=Má zrcadla
+view_home=Zobrazit %s
+search_repos=Nalézt repozitář…
+filter=Ostatní filtry
+filter_by_team_repositories=Filtrovat podle repozitářů týmu
+feed_of=Kanál z „%s“
+
+show_archived=Archivováno
+show_both_archived_unarchived=Zobrazeny jak archivované tak nearchivované
+show_only_archived=Zobrazeny pouze archivované
+show_only_unarchived=Zobrazeny pouze nearchivované
+
+show_private=Soukromý
+show_both_private_public=Zobrazeny jak veřejné tak soukromé
+show_only_private=Zobrazeny pouze soukromé
+show_only_public=Zobrazeny pouze veřejné
+
+issues.in_your_repos=Ve vašich repozitářích
+
+[explore]
+repos=Repozitáře
+users=Uživatelé
+organizations=Organizace
+search=Vyhledat
+code=Kód
+search.type.tooltip=Druh vyhledávání
+search.fuzzy=Fuzzy
+search.fuzzy.tooltip=Zahrnout výsledky, které také úzce odpovídají hledanému výrazu
+search.match=Shoda
+search.match.tooltip=Zahrnout pouze výsledky, které odpovídají přesnému hledanému výrazu
+code_search_unavailable=V souÄasné dobÄ› není vyhledávání kódu dostupné. ObraÅ¥te se na správce webu.
+repo_no_results=Nebyly nalezeny žádné odpovídající repozitáře.
+user_no_results=Nebyly nalezeni žádní odpovídající uživatelé.
+org_no_results=Nebyly nalezeny žádné odpovídající organizace.
+code_no_results=Nebyl nalezen žádný zdrojový kód odpovídající hledanému výrazu.
+code_search_results=Výsledky hledání pro „%s“
+code_last_indexed_at=Naposledy indexováno %s
+relevant_repositories_tooltip=Repozitáře, které jsou rozštěpení nebo nemají žádné téma, ikonu a žádný popis jsou skryty.
relevant_repositories=Zobrazují se pouze relevantní repositáře, <a href="%s">zobrazit nefiltrované výsledky</a>.
@@ -317,6 +393,7 @@ email_not_associate=Tato e-mailová adresa není spojena s žádným úÄtem.
send_reset_mail=Zaslat e-mail pro obnovení úÄtu
reset_password=Obnovení úÄtu
invalid_code=Tento potvrzující kód je neplatný nebo mu vypršela platnost.
+invalid_password=VaÅ¡e heslo se neshoduje s heslem, které bylo použito k vytvoÅ™ení úÄtu.
reset_password_helper=Obnovit úÄet
reset_password_wrong_user=Jste pÅ™ihlášen/a jako %s, ale odkaz pro obnovení úÄtu je pro %s
password_too_short=Délka hesla musí být minimálně %d znaků.
@@ -360,6 +437,7 @@ password_pwned_err=Nelze dokonÄit požadavek na HaveIBeenPwned
[mail]
view_it_on=Zobrazit na %s
+reply=nebo přímo odpovědět na tento e-mail
link_not_working_do_paste=Nefunguje? Zkuste jej zkopírovat a vložit do svého prohlížeÄe.
hi_user_x=Ahoj <b>%s</b>,
@@ -463,6 +541,7 @@ url_error=`„%s“ není platná adresa URL.`
include_error=` musí obsahovat řetězec „%s“.`
glob_pattern_error=`zástupný vzor je neplatný: %s.`
regex_pattern_error=` regex vzor je neplatný: %s.`
+invalid_group_team_map_error=` mapování je neplatné: %s`
unknown_error=Neznámá chyba:
captcha_incorrect=CAPTCHA kód není správný.
password_not_match=Zadaná hesla nesouhlasí.
@@ -499,18 +578,20 @@ team_not_exist=Tento tým neexistuje.
last_org_owner=Nemůžete odstranit posledního uživatele z týmu „vlastníci“. Musí existovat alespoň jeden vlastník pro organizaci.
cannot_add_org_to_team=Organizace nemůže být pÅ™idána jako Älen týmu.
duplicate_invite_to_team=Uživatel byl již pozván jako Älen týmu.
+organization_leave_success=Úspěšně jste opustili organizaci %s.
invalid_ssh_key=Nelze ověřit váš SSH klíÄ: %s
invalid_gpg_key=Nelze ověřit váš GPG klíÄ: %s
invalid_ssh_principal=Neplatný SSH Principal certifikát: %s
-unable_verify_ssh_key=Nelze ověřit váš SSH klíÄ; znovu zkontrolujte chyby.
+must_use_public_key=Zadaný klÃ­Ä je soukromý klíÄ. Nenahrávejte svůj soukromý klÃ­Ä nikde. Místo toho použijte váš veÅ™ejný klíÄ.
+unable_verify_ssh_key=Nelze ověřit váš SSH klíÄ
auth_failed=Ověření selhalo: %v
-still_own_repo=Váš úÄet vlastní jeden nebo více repozitářů; smažte je nebo pÅ™eveÄte.
-still_has_org=Váš úÄet je Älen jedné nebo více organizací; nejdříve je opusÅ¥te.
+still_own_repo=Váš úÄet vlastní jeden nebo více repozitářů
+still_has_org=Váš úÄet je Älen jedné nebo více organizací
still_own_packages=Váš úÄet vlastní jeden nebo více balíÄků. Nejprve je musíte odstranit.
-org_still_own_repo=Organizace stále vlastní jeden nebo více repozitářů; smažte je nebo pÅ™eveÄte.
-org_still_own_packages=Organizace stále vlastní jeden nebo více balíÄků; nejprve je smažte.
+org_still_own_repo=Organizace stále vlastní jeden nebo více repozitářů
+org_still_own_packages=Organizace stále vlastní jeden nebo více balíÄků
target_branch_not_exist=Cílová větev neexistuje.
@@ -802,6 +883,7 @@ remove_account_link=Odstranit propojený úÄet
remove_account_link_desc=OdstranÄ›ním propojeného úÄtu zrušíte jeho přístup k vaÅ¡emu Gitea úÄtu. PokraÄovat?
remove_account_link_success=Propojený úÄet byl odstranÄ›n.
+
orgs_none=Nejste Älenem žádné organizace.
repos_none=Nevlastníte žádné repozitáře
@@ -1024,7 +1106,7 @@ code=Zdrojový kód
code.desc=Přístup ke zdrojovým kódům, souborům, commitům a větvím.
branch=Větev
tree=Strom
-clear_ref=`Vymazat aktuální referenci"
+clear_ref=``Vymazat aktuální referenci"`
filter_branch_and_tag=Filtr pro vÄ›tev nebo znaÄku
find_tag=Najít znaÄku
branches=Větve
@@ -1164,7 +1246,7 @@ commits.signed_by_untrusted_user_unmatched=Podepsáno nedůvěryhodným uživate
commits.gpg_key_id=ID GPG klíÄe
commits.ssh_key_fingerprint=Otisk klíÄe SSH
-commit.actions=Akce
+commit.operations=Operace
commit.revert=Vrátit
commit.revert-header=Vrátit: %s
commit.revert-content=Vyberte větev pro návrat na:
@@ -1197,19 +1279,21 @@ projects.type.bug_triage=Třídění chyb
projects.template.desc=Å ablona projektu
projects.template.desc_helper=Vyberte Å¡ablonu projektu pro zaÄátek
projects.type.uncategorized=Nezařazené
-projects.board.edit=Upravit nástěnku
-projects.board.edit_title=Název nástěnky
-projects.board.new_title=Název nové nástěnky
-projects.board.new_submit=Odeslat
-projects.board.new=Nová nástěnka
-projects.board.set_default=Nastavit jako výchozí
-projects.board.set_default_desc=Nastavit tuto nástěnku jako výchozí pro nekategorizované úkoly a požadavky na natažení
-projects.board.delete=Smazat nástěnku
-projects.board.deletion_desc=Smazáním projektové nástÄ›nky pÅ™esune vÅ¡echny související problémy do kategorie „NezaÅ™azené“. PokraÄovat?
-projects.board.color=Barva
+projects.column.edit=Upravit sloupec
+projects.column.edit_title=Název
+projects.column.new_title=Název
+projects.column.new_submit=Vytvořit sloupec
+projects.column.new=Nový sloupec
+projects.column.set_default=Nastavit jako výchozí
+projects.column.set_default_desc=Nastavit tento sloupec jako výchozí pro nekategorizované úkoly a požadavky na natažení
+projects.column.delete=Smazat sloupec
+projects.column.deletion_desc=Smazání projektového sloupce pÅ™esune vÅ¡echny související problémy do kategorie „NezaÅ™azené“. PokraÄovat?
+projects.column.color=Barva
projects.open=Otevřít
projects.close=Zavřít
-projects.board.assigned_to=Přiřazeno k
+projects.column.assigned_to=Přiřazeno k
+projects.card_type.images_and_text=Obrázky a text
+projects.card_type.text_only=Pouze text
issues.desc=Organizování hlášení chyb, úkolů a milníků.
issues.filter_assignees=Filtrovat zpracovatele
@@ -1285,6 +1369,9 @@ issues.filter_label_exclude=`Chcete-li vylouÄit Å¡títky, použijte <code>alt</
issues.filter_label_no_select=Všechny štítky
issues.filter_milestone=Milník
issues.filter_milestone_no_select=Všechny milníky
+issues.filter_project=Projekt
+issues.filter_project_all=VÅ¡echny projekty
+issues.filter_project_none=Žádný projekt
issues.filter_assignee=Zpracovatel
issues.filter_assginee_no_select=Všichni zpracovatelé
issues.filter_poster=Autor
@@ -1369,6 +1456,7 @@ issues.save=Uložit
issues.label_title=Název štítku
issues.label_description=Popis štítku
issues.label_color=Barva štítku
+issues.label_exclusive=Exkluzivní
issues.label_count=%d štítků
issues.label_open_issues=%d otevřených úkolů
issues.label_edit=Upravit
@@ -1436,6 +1524,7 @@ issues.error_removing_due_date=OdstranÄ›ní termínu dokonÄení selhalo.
issues.push_commit_1=přidal/a %d commit %s
issues.push_commits_n=přidal/a %d commity %s
issues.force_push_codes=`vynucené nahrání %[1]s od <a class="ui sha" href="%[3]s"><code>%[2]s</code></a> do <a class="ui sha" href="%[5]s"><code>%[4]s</code></a> %[6]s`
+issues.force_push_compare=Porovnat
issues.due_date_form=rrrr-mm-dd
issues.due_date_form_add=PÅ™idat termín dokonÄení
issues.due_date_form_edit=Upravit
@@ -1813,6 +1902,7 @@ settings.mirror_sync_in_progress=Právě probíhá synchronizace zrcadla. Zkuste
settings.site=Webová stránka
settings.update_settings=Aktualizovat nastavení
settings.branches.update_default_branch=Aktualizovat výchozí větev
+settings.branches.add_new_rule=Přidat nové pravidlo
settings.advanced_settings=PokroÄilá nastavení
settings.wiki_desc=Povolit Wiki repozitáře
settings.use_internal_wiki=Používat vestavěnou Wiki
@@ -1839,11 +1929,6 @@ settings.enable_timetracker=Povolit sledování Äasu
settings.allow_only_contributors_to_track_time=Povolit sledování Äasu pouze pÅ™ispÄ›vatelům
settings.pulls_desc=Povolit požadavky na natažení
settings.pulls.ignore_whitespace=Ignorovat bílé znaky při konfliktech
-settings.pulls.allow_merge_commits=Povolit sluÄování commitů
-settings.pulls.allow_rebase_merge=Povolit rebase pro sluÄovací commity
-settings.pulls.allow_rebase_merge_commit=Povolit rebase s vyžádaným sluÄovacím commitem (--no-ff)
-settings.pulls.allow_squash_commits=Povolit squash pro sluÄovací commity
-settings.pulls.allow_manual_merge=Povolit oznaÄování požadavků na natažení jako ruÄnÄ› slouÄené
settings.pulls.enable_autodetect_manual_merge=Povolit autodetekci ruÄních slouÄení (Poznámka: V nÄ›kterých zvláštních případech může dojít k nesprávnému rozhodnutí)
settings.pulls.allow_rebase_update=Povolit aktualizaci větve požadavku na natažení pomocí rebase
settings.pulls.default_delete_branch_after_merge=Ve výchozím nastavení mazat vÄ›tev požadavku na natažení po jeho slouÄení
@@ -2012,6 +2097,8 @@ settings.event_package=BalíÄek
settings.event_package_desc=BalíÄek vytvoÅ™en nebo odstranÄ›n v repozitáři.
settings.branch_filter=Filtr větví
settings.branch_filter_desc=Povolené vÄ›tve pro události nahrání, vytvoÅ™ení vÄ›tve a smazání vÄ›tve jsou urÄeny pomocí zástupného vzoru. Pokud je prázdný nebo <code>*</code>, vÅ¡echny události jsou ohlášeny. Podívejte se na dokumentaci syntaxe na <a href="https://pkg.go.dev/github.com/gobwas/glob#Compile">github.com/gobwas/glob</a>. Příklady: <code>master</code>, <code>{master,release*}</code>.
+settings.authorization_header=AutorizaÄní hlaviÄka
+settings.authorization_header_desc=Pokud vyplnÄ›no, bude pÅ™ipojeno k požadavkům jako autorizaÄní hlaviÄka. Příklady: %s.
settings.active=Aktivní
settings.active_helper=Informace o spuÅ¡tÄ›ných událostech budou odeslány na URL webového háÄku.
settings.add_hook_success=Webový háÄek byl pÅ™idán.
@@ -2056,6 +2143,8 @@ settings.deploy_key_deletion_desc=OdstranÄ›ní klíÄe pro nasazení zruší jeh
settings.deploy_key_deletion_success=KlÃ­Ä pro nasazení byl odstranÄ›n.
settings.branches=Větve
settings.protected_branch=Ochrana větví
+settings.protected_branch.save_rule=Uložit pravidlo
+settings.protected_branch.delete_rule=Odstranit pravidlo
settings.protected_branch_can_push=Povolit nahrání?
settings.protected_branch_can_push_yes=Můžete nahrávat
settings.protected_branch_can_push_no=Nemůžete nahrávat
@@ -2126,7 +2215,6 @@ settings.bot_token=Token pro robota
settings.chat_id=ID chatu
settings.matrix.homeserver_url=URL adresa Homeserveru
settings.matrix.room_id=ID místnosti
-settings.matrix.access_token=Přístupový token
settings.matrix.message_type=Typ zprávy
settings.archive.button=Archivovat repozitář
settings.archive.header=Archivovat tento repozitář
@@ -2325,7 +2413,7 @@ org_full_name_holder=Celý název organizace
org_name_helper=Jména organizací by měla být krátká a zapamatovatelná.
create_org=Vytvořit organizaci
repo_updated=Upraveno
-people=Lidé
+members=Členové
teams=Týmy
code=Kód
lower_members=Älenové
@@ -2534,6 +2622,9 @@ dashboard.delete_old_actions=Odstranit všechny staré akce z databáze
dashboard.delete_old_actions.started=ZaÄalo odstraňování vÅ¡ech starých akcí z databáze.
dashboard.update_checker=Kontrola aktualizací
dashboard.delete_old_system_notices=Odstranit všechna stará systémová upozornění z databáze
+dashboard.stop_zombie_tasks=Zastavit zombie úkoly
+dashboard.stop_endless_tasks=Zastavit nekoneÄné úkoly
+dashboard.cancel_abandoned_jobs=Zrušit opuštěné úlohy
users.user_manage_panel=Správa uživatelských úÄtů
users.new_account=VytvoÅ™it uživatelský úÄet
@@ -2715,6 +2806,7 @@ auths.oauth2_required_claim_value_helper=Nastavte tuto hodnotu pro omezení při
auths.oauth2_group_claim_name=Název tvrzení poskytující názvy skupin pro tento zdroj. (nepovinné)
auths.oauth2_admin_group=Hodnota tvrzení pro skupinu uživatelů administrátorů. (Volitelné - vyžaduje název tvrzení výše)
auths.oauth2_restricted_group=Hodnota tvrzení pro skupinu omezených uživatelů. (Volitelné - vyžaduje název tvrzení výše)
+auths.oauth2_map_group_to_team_removal=Odebrat uživatele z synchronizovaných týmů, pokud uživatel nepatří do odpovídající skupiny.
auths.enable_auto_register=Povolit zaregistrování se
auths.sspi_auto_create_users=Automaticky vytvářet uživatele
auths.sspi_auto_create_users_helper=Povolit SSPI autentizaÄní metodÄ› automaticky vytvářet nové úÄty pro uživatele, kteří se poprvé pÅ™ihlásili
@@ -2977,7 +3069,7 @@ monitor.queue.pool.cancel_desc=Opustit frontu bez skupin workerů může způsob
notices.system_notice_list=Systémová oznámení
notices.view_detail_header=Zobrazit detaily oznámení
-notices.actions=Akce
+notices.operations=Operace
notices.select_all=Vybrat vše
notices.deselect_all=Zrušit výběr všech
notices.inverse_selection=Inverzní výběr
@@ -3003,6 +3095,7 @@ reopen_pull_request=`znovuotevřel/a požadavek na natažení <a href="%[1]s">%[
comment_issue=`okomentoval/a problém <a href="%[1]s">%[3]s#%[2]s</a>`
comment_pull=`okomentoval/a požadavek na natažení <a href="%[1]s">%[3]s#%[2]s</a>`
merge_pull_request=`slouÄil/a požadavek na natažení <a href="%[1]s">%[3]s#%[2]s</a>`
+auto_merge_pull_request=`automaticky slouÄen požadavek na natažení <a href="%[1]s">%[3]s#%[2]s</a>`
transfer_repo=předal/a repozitář <code>%s</code> uživateli/organizaci <a href="%s">%s</a>
push_tag=nahrál/a znaÄku <a href="%[2]s">%[3]s</a> do <a href="%[1]s">%[4]s</a>
delete_tag=smazal/a znaÄku %[2]s z <a href="%[1]s">%[3]s</a>
@@ -3101,6 +3194,8 @@ keywords=KlíÄová slova
details=Podrobnosti
details.author=Autor
details.project_site=Stránka projektu
+details.repository_site=Stránka repositáře
+details.documentation_site=Stránka dokumentace
details.license=Licence
assets=Prostředky
versions=Verze
@@ -3108,6 +3203,13 @@ versions.on=
versions.view_all=Zobrazit všechny
dependency.id=ID
dependency.version=Verze
+cargo.install=Chcete-li nainstalovat balíÄek pomocí Cargo, spusÅ¥te následující příkaz:
+cargo.documentation=Další informace o registru Cargo naleznete v <a target="_blank" rel="noopener noreferrer" href="https://docs.gitea.io/en-us/packages/cargo/">dokumentaci</a>.
+cargo.details.repository_site=Stránka repositáře
+cargo.details.documentation_site=Stránka dokumentace
+chef.registry=Nastavit tento registr v souboru <code>~/.chef/config.rb</code>:
+chef.install=Pro instalaci balíÄku spusÅ¥te následující příkaz:
+chef.documentation=Další informace o registru Chef naleznete v <a target="_blank" rel="noopener noreferrer" href="https://docs.gitea.io/en-us/packages/chef/">dokumentaci</a>.
composer.registry=Nastavit tento registr v souboru <code>~/.composer/config.json</code>:
composer.install=Pro instalaci balíÄku pomocí Compposer spusÅ¥te následující příkaz:
composer.documentation=Další informace o registru Composer naleznete v <a target="_blank" rel="noopener noreferrer" href="https://docs.gitea.io/en-us/packages/composer/">dokumentaci</a>.
@@ -3117,10 +3219,13 @@ conan.details.repository=Repozitář
conan.registry=Nastavte tento registr z příkazového řádku:
conan.install=Pro instalaci balíÄku pomocí Conan spusÅ¥te následující příkaz:
conan.documentation=Další informace o registru Conan naleznete v <a target="_blank" rel="noopener noreferrer" href="https://docs.gitea.io/en-us/packages/conan/">dokumentaci</a>.
+conda.registry=Nastavte tento registr jako Conda repozitář ve vašem <code>.condarc</code>:
+conda.install=Pro instalaci balíÄku pomocí Conda spusÅ¥te následující příkaz:
+conda.documentation=Další informace o registru Conda naleznete v <a target="_blank" rel="noopener noreferrer" href="https://docs.gitea.io/en-us/packages/conda/">dokumentaci</a>.
+conda.details.repository_site=Stránka repositáře
+conda.details.documentation_site=Stránka dokumentace
container.details.type=Typ obrazu
container.details.platform=Platforma
-container.details.repository_site=Stránka repositáře
-container.details.documentation_site=Stránka dokumentace
container.pull=Stáhněte obraz z příkazové řádky:
container.digest=Výběr:
container.documentation=Další informace o registru Container naleznete v <a target="_blank" rel="noopener noreferrer" href="https://docs.gitea.io/en-us/packages/container/">dokumentaci</a>.
@@ -3154,8 +3259,6 @@ npm.dependencies.optional=Volitelné závislosti
npm.details.tag=ZnaÄka
pub.install=Chcete-li nainstalovat balíÄek pomocí Dart, spusÅ¥te následující příkaz:
pub.documentation=Další informace o registru Pub naleznete v <a target="_blank" rel="noopener noreferrer" href="https://docs.gitea.io/en-us/packages/pub/">dokumentaci</a>.
-pub.details.repository_site=Stránka repositáře
-pub.details.documentation_site=Stránka dokumentace
pypi.requires=Vyžaduje Python
pypi.install=Pro instalaci balíÄku pomocí pip spusÅ¥te následující příkaz:
pypi.documentation=Další informace o registru PyPI naleznete v <a target="_blank" rel="noopener noreferrer" href="https://docs.gitea.io/en-us/packages/pypi/">dokumentaci</a>.
@@ -3179,4 +3282,79 @@ settings.delete.description=Smazání balíÄku je trvalé a nelze ho vrátit zp
settings.delete.notice=Chystáte se odstranit %s (%s). Tato operace je nevratná, jste si jisti?
settings.delete.success=BalíÄek byl odstranÄ›n.
settings.delete.error=NepodaÅ™ilo se odstranit balíÄek.
+owner.settings.cargo.initialize=Inicializovat index
+owner.settings.cargo.initialize.description=K použití registru Cargo je zapotřebí speciální indexový repozitář git. Zde jej můžete (znovu) vytvořit s požadovanou konfigurací.
+owner.settings.cargo.initialize.error=Nepodařilo se inicializovat Cargo index: %v
+owner.settings.cargo.initialize.success=Index Cargo byl úspěšně vytvořen.
+owner.settings.cargo.rebuild=Znovu vytvořit Index
+owner.settings.cargo.rebuild.description=Pokud index není synchronizován s uloženými balíÄky Cargo, můžete jej zde obnovit.
+owner.settings.cargo.rebuild.error=Obnovení Cargo indexu se nezdařilo: %v
+owner.settings.cargo.rebuild.success=Cargo Index byl úspěšně obnoven.
+owner.settings.cleanuprules.title=Spravovat pravidla pro ÄiÅ¡tÄ›ní
+owner.settings.cleanuprules.add=PÅ™idat pravidlo pro ÄiÅ¡tÄ›ní
+owner.settings.cleanuprules.edit=Upravit pravidlo pro ÄiÅ¡tÄ›ní
+owner.settings.cleanuprules.none=Nejsou k dispozici žádná pravidla ÄiÅ¡tÄ›ní. PÅ™eÄtÄ›te si dokumentaci a dozvíte se více.
+owner.settings.cleanuprules.preview=Náhled pravidla pro ÄiÅ¡tÄ›ní
+owner.settings.cleanuprules.preview.overview=%d balíÄků má být odstranÄ›no.
+owner.settings.cleanuprules.preview.none=Pravidlo ÄiÅ¡tÄ›ní neodpovídá žádným balíÄkům.
+owner.settings.cleanuprules.enabled=Povolený
+owner.settings.cleanuprules.pattern_full_match=Použít vzor na úplný název balíÄku
+owner.settings.cleanuprules.keep.title=Verze, které odpovídají těmto pravidlům, jsou zachovány, i když odpovídají níže uvedenému pravidlu pro odstranění.
+owner.settings.cleanuprules.keep.count=Zachovat nejnovější
+owner.settings.cleanuprules.keep.count.1=1 verze na balíÄek
+owner.settings.cleanuprules.keep.count.n=%d verzí na balíÄek
+owner.settings.cleanuprules.keep.pattern=Ponechat odpovídající verze
+owner.settings.cleanuprules.keep.pattern.container=U balíÄků Container je vždy zachována <code>nejnovÄ›jší</code> verze.
+owner.settings.cleanuprules.remove.title=Verze, které odpovídají těmto pravidlům, jsou odstraněny, pokud výše uvedené pravidlo neukládá jejich zachování.
+owner.settings.cleanuprules.remove.days=Odstranit verze starší než
+owner.settings.cleanuprules.remove.pattern=Odstranit odpovídající verze
+owner.settings.cleanuprules.success.update=Pravidlo pro ÄiÅ¡tÄ›ní bylo aktualizováno.
+owner.settings.cleanuprules.success.delete=Pravidlo pro ÄiÅ¡tÄ›ní bylo odstranÄ›no.
+owner.settings.chef.keypair=Generovat pár klíÄů
+
+[secrets]
+secrets=Tajné klíÄe
+value=Hodnota
+name=Název
+
+[actions]
+actions=Akce
+
+unit.desc=Spravovat akce
+
+status.unknown=Neznámý
+status.waiting=Čekání
+status.running=Probíhá
+status.success=Úspěch
+status.failure=Chyba
+status.cancelled=Zrušeno
+status.skipped=PÅ™eskoÄeno
+status.blocked=Blokováno
+
+runners.status=Status
+runners.id=ID
+runners.name=Název
+runners.owner_type=Typ
+runners.description=Popis
+runners.labels=Štítky
+runners.last_online=Poslední Äas online
+runners.agent_labels=Štítky agenta
+runners.custom_labels=Vlastní štítky
+runners.custom_labels_helper=Vlastní Å¡títky jsou Å¡títky, které správce pÅ™idává ruÄnÄ›. Å títky se oddÄ›lují Äárkou, bílé znaky na zaÄátku a na konci každého Å¡títku se ignorují.
+runners.task_list.run=Spustit
+runners.task_list.status=Status
+runners.task_list.repository=Repozitář
+runners.task_list.commit=Commit
+runners.task_list.done_at=DokonÄeno v
+runners.update_runner=Aktualizovat změny
+runners.status.unspecified=Neznámý
+runners.status.idle=NeÄinný
+runners.status.active=Aktivní
+runners.status.offline=Offline
+
+runs.all_workflows=Všechny pracovní postupy
+runs.open_tab=%d otevřeno
+runs.closed_tab=%d uzavřeno
+runs.commit=Commit
+
diff --git a/options/locale/locale_de-DE.ini b/options/locale/locale_de-DE.ini
index d8874fd5f..9bee2104e 100644
--- a/options/locale/locale_de-DE.ini
+++ b/options/locale/locale_de-DE.ini
@@ -57,7 +57,6 @@ new_mirror=Neuer Mirror
new_fork=Neuer Fork
new_org=Neue Organisation
new_project=Neues Projekt
-new_project_board=Neues Projektboard
manage_org=Organisationen verwalten
admin_panel=Administration
account_settings=Kontoeinstellungen
@@ -86,6 +85,9 @@ remove=Löschen
remove_all=Alle entfernen
edit=Bearbeiten
+enabled=Aktiviert
+disabled=Deaktiviert
+
copy=Kopieren
copy_url=URL kopieren
copy_branch=Branchenname kopieren
@@ -106,6 +108,8 @@ never=Niemals
rss_feed=RSS Feed
+[aria]
+
[filter]
[error]
@@ -180,6 +184,8 @@ log_root_path_helper=Log-Dateien werden in diesem Verzeichnis gespeichert.
optional_title=Optionale Einstellungen
email_title=E-Mail-Einstellungen
+smtp_addr=SMTP-Host
+smtp_port=SMTP-Port
smtp_from=E-Mail senden als
smtp_from_helper=E-Mail-Adresse, die von Gitea genutzt werden soll. Bitte gib die E-Mail-Adresse im Format „"Name" <email@example.com>“ ein.
mailer_user=SMTP-Benutzername
@@ -222,7 +228,6 @@ internal_token_failed=Fehler beim Generieren des internen Tokens: %v
secret_key_failed=Fehler beim Generieren des geheimen Schlüssels: %v
save_config_failed=Fehler beim Speichern der Konfiguration: %v
invalid_admin_setting=Administrator-Konto Einstellungen sind ungültig: %v
-install_success=Willkommen! Danke, dass du Gitea gewählt hast. Viel Spaß!
invalid_log_root_path=Pfad zum Log-Verzeichnis ist ungültig: %v
default_keep_email_private=E-Mail-Adressen standardmäßig verbergen
default_keep_email_private_popup=E-Mail-Adressen von neuen Benutzern standardmäßig verbergen.
@@ -248,7 +253,7 @@ view_home=%s ansehen
search_repos=Finde ein Repository…
filter=Andere Filter
filter_by_team_repositories=Nach Team-Repositorys filtern
-feed_of=Feed von "%s"
+feed_of=`Feed von "%s"`
show_archived=Archiviert
show_both_archived_unarchived=Archivierte und nicht archivierte anzeigen
@@ -342,11 +347,11 @@ authorize_application=Anwendung autorisieren
authorize_redirect_notice=Du wirst zu %s weitergeleitet, wenn du diese Anwendung autorisierst.
authorize_application_created_by=Diese Anwendung wurde von %s erstellt.
authorize_application_description=Wenn du diese Anwendung autorisierst, wird sie die Berechtigung erhalten, alle Informationen zu deinem Account zu bearbeiten oder zu lesen. Dies beinhaltet auch private Repositorys und Organisationen.
-authorize_title="%s" den Zugriff auf deinen Account gestatten?
+authorize_title=`"%s\" den Zugriff auf deinen Account gestatten?`
authorization_failed=Autorisierung fehlgeschlagen
authorization_failed_desc=Die Autorisierung ist fehlgeschlagen, da wir eine ungültige Anfrage festgestellt haben. Bitte kontaktiere den Betreiber der Anwendung, die du gerade autorisieren wolltest.
sspi_auth_failed=SSPI Authentifizierung fehlgeschlagen
-password_pwned=Das von dir gewählte Passwort ist auf einer <a target="_blank" rel="noopener noreferrer" href="https://haveibeenpwned.com/Passwords">Liste von gestohlenen Passwörtern</a> die zuvor bei öffentlichen Datenschutzverletzungen aufgedeckt wurden. Bitte versuche es erneut mit einem anderen Passwort.
+password_pwned=`Das von dir gewählte Passwort ist auf einer <a target="`
password_pwned_err=Anfrage an HaveIBeenPwned konnte nicht abgeschlossen werden
[mail]
@@ -494,9 +499,9 @@ auth_failed=Authentifizierung fehlgeschlagen: %v
still_own_repo=Dein Konto besitzt ein oder mehrere Repositorys. Diese müssen zuerst gelöscht oder übertragen werden.
still_has_org=Dein Account ist Mitglied in mindestens einer Organisation. Bitte verlasse diese zuerst.
-still_own_packages=Ihr Konto besitzt ein oder mehrere Pakete; löschen Sie diese zuerst.
+still_own_packages=Ihr Konto besitzt ein oder mehrere Pakete
org_still_own_repo=Diese Organisation besitzt noch mindestens ein Repository. Bitte lösche oder übertrage diese zuerst.
-org_still_own_packages=Diese Organisation besitzt noch ein oder mehrere Pakete; lösche diese bitte zuerst.
+org_still_own_packages=Diese Organisation besitzt noch ein oder mehrere Pakete
target_branch_not_exist=Der Ziel-Branch existiert nicht.
@@ -508,6 +513,7 @@ activity=Öffentliche Aktivität
followers=Follower
starred=Favoriten
watched=Beobachtete Repositories
+code=Quelltext
projects=Projekte
following=Folge ich
follow=Folgen
@@ -786,6 +792,7 @@ remove_account_link=Verknüpften Account entfernen
remove_account_link_desc=Wenn du den verknüpften Account entfernst, wirst du darüber nicht mehr auf deinen Gitea-Account zugreifen können. Fortfahren?
remove_account_link_success=Der verknüpfte Account wurde entfernt.
+
orgs_none=Du bist kein Mitglied in einer Organisation.
repos_none=Du besitzt keine Repositories
@@ -895,7 +902,7 @@ delete_preexisting_success=Nicht übernommene Dateien in %s gelöscht
blame_prior=Blame vor dieser Änderung anzeigen
transfer.accept=Ãœbertragung Akzeptieren
-transfer.accept_desc=Ãœbertragung nach "%s"
+transfer.accept_desc=`Ãœbertragung nach "%s"`
transfer.reject=Ãœbertragung Ablehnen
transfer.reject_desc=Ãœbertragung nach "%s " abbrechen
transfer.no_permission_to_accept=Du hast nicht die Berechtigung die Ãœbertragung zu akzeptieren
@@ -1140,7 +1147,6 @@ commits.signed_by_untrusted_user_unmatched=Signiert von nicht vertrauenswürdige
commits.gpg_key_id=GPG-Schlüssel-ID
commits.ssh_key_fingerprint=SSH-Key-Fingerabdruck
-commit.actions=Aktionen
commit.revert=Zurücksetzen
commit.revert-header=Setze zurück: %s
commit.revert-content=Branch auswählen, der zurückgesetzt werden soll:
@@ -1173,19 +1179,11 @@ projects.type.bug_triage=Bug Triage
projects.template.desc=Projektvorlage
projects.template.desc_helper=Wähle eine Projektvorlage aus, um loszulegen
projects.type.uncategorized=Nicht kategorisiert
-projects.board.edit=Board bearbeiten
-projects.board.edit_title=Neuer Boardname
-projects.board.new_title=Neuer Boardname
-projects.board.new_submit=Bestätigen
-projects.board.new=Neues Board
-projects.board.set_default=Als Standard verwenden
-projects.board.set_default_desc=Dieses Board als Standard für unkategorisierte Issues und Pull Requests festlegen
-projects.board.delete=Board löschen
-projects.board.deletion_desc=Beim Löschen eines Projektboards werden alle Einträge nach 'Uncategorized' verschoben. Fortfahren?
-projects.board.color=Farbe
+projects.column.edit_title=Name
+projects.column.new_title=Name
+projects.column.color=Farbe
projects.open=Öffnen
projects.close=Schließen
-projects.board.assigned_to=Zugewiesen an
issues.desc=Verwalte Bug-Reports, Aufgaben und Meilensteine.
issues.filter_assignees=Filter
@@ -1259,6 +1257,8 @@ issues.filter_label_exclude=„<code>Alt</code> + <code>Klick/Enter</code> verwe
issues.filter_label_no_select=Alle Label
issues.filter_milestone=Meilenstein
issues.filter_milestone_no_select=Alle Meilensteine
+issues.filter_project=Projekt
+issues.filter_project_none=Kein Projekt
issues.filter_assignee=Zuständig
issues.filter_assginee_no_select=Alle Zuständigen
issues.filter_poster=Autor
@@ -1410,6 +1410,7 @@ issues.error_removing_due_date=Fehler beim Entfernen des Fälligkeitsdatums.
issues.push_commit_1=hat %d Commit %s hinzugefügt
issues.push_commits_n=hat %d Commits %s hinzugefügt
issues.force_push_codes=`hat %[6]s %[1]s von <a class="ui sha" href="%[3]s"><code>%[2]s</code></a> zu <a class="ui sha" href="%[5]s"><code>%[4]s</code></a> force-gepusht`
+issues.force_push_compare=Vergleichen
issues.due_date_form=JJJJ-MM-TT
issues.due_date_form_add=Fälligkeitsdatum hinzufügen
issues.due_date_form_edit=Bearbeiten
@@ -1809,11 +1810,6 @@ settings.enable_timetracker=Zeiterfassung aktivieren
settings.allow_only_contributors_to_track_time=Nur Mitarbeitern erlauben, die Zeiterfassung zu nutzen
settings.pulls_desc=Repository-Pull-Requests aktivieren
settings.pulls.ignore_whitespace=Bei Konflikten Leerzeichen ignorieren
-settings.pulls.allow_merge_commits=Mergecommits aktivieren
-settings.pulls.allow_rebase_merge=Mergen von Commits durch Rebasen aktivieren
-settings.pulls.allow_rebase_merge_commit=Rebasing mit expliziten merge commits aktivieren (--no-ff)
-settings.pulls.allow_squash_commits=Mergen von Commits durch Squash aktivieren
-settings.pulls.allow_manual_merge=Manuelles Mergen von Pull Requests aktivieren
settings.pulls.enable_autodetect_manual_merge=Autoerkennung von manuellen Merges aktivieren (in Ausnahmefällen können Fehleinschätzungen auftreten)
settings.pulls.allow_rebase_update=Update von Pull Request Branches per Rebase erlauben
settings.pulls.default_delete_branch_after_merge=Standardmäßig bei Pull-Requests den Branch nach dem Mergen löschen
@@ -1854,7 +1850,7 @@ settings.transfer_notices_2=– Du wirst weiterhin Zugriff haben, wenn der neue
settings.transfer_notices_3=- Wenn das Repository privat ist und an einen einzelnen Benutzer übertragen wird, wird sichergestellt, dass der Benutzer mindestens Leserechte hat (und die Berechtigungen werden gegebenenfalls ändert).
settings.transfer_owner=Neuer Besitzer
settings.transfer_perform=Übertragung durchführen
-settings.transfer_started=Für dieses Repository wurde eine Übertragung eingeleitet und wartet nun auf die Bestätigung von "%s"
+settings.transfer_started=`Für dieses Repository wurde eine Übertragung eingeleitet und wartet nun auf die Bestätigung von "%s"`
settings.transfer_succeed=Das Repository wurde transferiert.
settings.signing_settings=Signaturüberprüfungseinstellungen
settings.trust_model=Signaturvertrauensmodell
@@ -1943,6 +1939,7 @@ settings.event_delete=Löschen
settings.event_delete_desc=Branch oder Tag gelöscht.
settings.event_fork=Fork
settings.event_fork_desc=Repository geforkt.
+settings.event_wiki=Wiki
settings.event_release=Release
settings.event_release_desc=Release in einem Repository veröffentlicht, aktualisiert oder gelöscht.
settings.event_push=Push
@@ -1979,6 +1976,7 @@ settings.event_package=Paket
settings.event_package_desc=Paket wurde in einem Repository erstellt oder gelöscht.
settings.branch_filter=Branch-Filter
settings.branch_filter_desc=Whitelist für Branches für Push-, Erzeugungs- und Löschevents, als glob Pattern beschrieben. Es werden Events für alle Branches gemeldet, falls das Pattern <code>*</code> ist, oder falls es leer ist. Siehe die <a href="https://pkg.go.dev/github.com/gobwas/glob#Compile">github.com/gobwas/glob</a> Dokumentation für die Syntax (Englisch). Beispiele: <code>master</code>, <code>{master,release*}</code>.
+settings.authorization_header=Authorization-Header
settings.active=Aktiv
settings.active_helper=Informationen über ausgelöste Ereignisse werden an diese Webhook-URL gesendet.
settings.add_hook_success=Webhook wurde hinzugefügt.
@@ -2058,7 +2056,7 @@ settings.dismiss_stale_approvals_desc=Wenn neue Commits gepusht werden, die den
settings.require_signed_commits=Signierte Commits erforderlich
settings.require_signed_commits_desc=Pushes auf diesen Branch ablehnen, wenn Commits nicht signiert oder nicht überprüfbar sind.
settings.protect_protected_file_patterns=Geschützte Dateimuster (durch Semikolon getrennt '\;'):
-settings.protect_protected_file_patterns_desc=Geschützte Dateien, die nicht einmal geändert werden können, wenn der Benutzer die Rechte hat, Dateien in diesem Branch hinzuzufügen, zu bearbeiten, oder zu löschen. Verschiedene Pattern können per Semicolon (';') getrennt werden. Siehe die <a href="https://pkg.go.dev/github.com/gobwas/glob#Compile">github.com/gobwas/glob</a> Dokumentation für die Pattern Syntax (Englisch). Beispiele: <code>.drone.yml</code>, <code>/docs/**/*.txt</code>.
+settings.protect_protected_file_patterns_desc=Geschützte Dateien, die nicht einmal geändert werden können, wenn der Benutzer die Rechte hat, Dateien in diesem Branch hinzuzufügen, zu bearbeiten, oder zu löschen. Verschiedene Pattern können per Semicolon ('
settings.protect_unprotected_file_patterns=Ungeschützte Dateimuster (durch Semikolon '\;' getrennt):
settings.protect_unprotected_file_patterns_desc=Ungeschützte Dateien können ohne Push-Beschränkung geändert werden, falls der Benutzer Schreibzugriff hat. Mehrere Muster können mit Semikolon getrennt werden ('\;'). Siehe die <a href="https://pkg.go.dev/github.com/gobwas/glob#Compile">github.com/gobwas/glob</a> Dokumentation für Mustersyntax. Beispiele: <code>.drone.yml</code>, <code>/docs/**/*.txt</code>.
settings.add_protected_branch=Schutz aktivieren
@@ -2093,7 +2091,6 @@ settings.bot_token=Bot-Token
settings.chat_id=Chat-ID
settings.matrix.homeserver_url=Homeserver-URL
settings.matrix.room_id=Raum-ID
-settings.matrix.access_token=Zugangs-Token
settings.matrix.message_type=Nachrichtentyp
settings.archive.button=Repo archivieren
settings.archive.header=Dieses Repo archivieren
@@ -2292,8 +2289,9 @@ org_full_name_holder=Vollständiger Name der Organisation
org_name_helper=Organisationsnamen sollten kurz und einprägsam sein.
create_org=Organisation erstellen
repo_updated=Aktualisiert
-people=Personen
+members=Mitglieder
teams=Teams
+code=Quelltext
lower_members=Mitglieder
lower_repositories=Repositories
create_new_team=Neues Team
@@ -2378,6 +2376,8 @@ teams.members=Teammitglieder
teams.update_settings=Einstellungen aktualisieren
teams.delete_team=Team löschen
teams.add_team_member=Teammitglied hinzufügen
+teams.invite_team_member=Zu %s einladen
+teams.invite_team_member.list=Ausstehende Einladungen
teams.delete_team_title=Team löschen
teams.delete_team_desc=Das Löschen eines Teams widerruft den Repository-Zugriff für seine Mitglieder. Fortfahren?
teams.delete_team_success=Das Team wurde gelöscht.
@@ -2402,6 +2402,9 @@ teams.all_repositories_helper=Team hat Zugriff auf alle Repositorys. Wenn dies a
teams.all_repositories_read_permission_desc=Dieses Team gewährt <strong>Lese</strong>-Zugriff auf <strong>Repositories</strong>: Mitglieder können Repositories ansehen und klonen.
teams.all_repositories_write_permission_desc=Dieses Team gewährt <strong>Schreib</strong>-Zugriff auf <strong>alle Repositories</strong>: Mitglieder können Repositories lesen und auf sie pushen.
teams.all_repositories_admin_permission_desc=Dieses Team gewährt <strong>Administrator</strong>-Zugriff auf <strong> alle Repositories </strong>: Mitglieder können Repositories lesen, auf sie pushen und Mitwirkende zu Repositories hinzufügen.
+teams.invite.title=Du wurdest eingeladen, dem Team <strong>%s</strong> in der Organisation <strong>%s</strong> beizutreten.
+teams.invite.by=Von %s eingeladen
+teams.invite.description=Bitte klicke auf die folgende Schaltfläche, um dem Team beizutreten.
[admin]
dashboard=Dashboard
@@ -2532,6 +2535,7 @@ users.delete_account=Benutzerkonto löschen
users.cannot_delete_self=Du kannst dich nicht selbst löschen
users.still_own_repo=Dieser Benutzer besitzt noch mindestens ein Repository. Bitte lösche oder übertrage diese(s) zuerst.
users.still_has_org=Dieser Nutzer ist Mitglied einer Organisation. Du musst ihn zuerst aus allen Organisationen entfernen.
+users.purge=Benutzer löschen
users.purge_help=Erzwinge das Löschen des Benutzers inklusive aller seiner Repositorys, Organisationen, Pakete und Kommentare.
users.still_own_packages=Dieser Benutzer besitzt noch ein oder mehrere Pakete. Lösche diese Pakete zuerst.
users.deletion_success=Der Account wurde gelöscht.
@@ -2701,7 +2705,7 @@ auths.tip.openid_connect=Benutze die OpenID-Connect-Discovery-URL (<server>/.wel
auths.tip.twitter=Gehe auf https://dev.twitter.com/apps, erstelle eine Anwendung und stelle sicher, dass die Option „Allow this application to be used to Sign in with Twitter“ aktiviert ist
auths.tip.discord=Erstelle unter https://discordapp.com/developers/applications/me eine neue Anwendung.
auths.tip.gitea=Registriere eine neue OAuth2-Anwendung. Eine Anleitung findest du unter https://docs.gitea.io/en-us/oauth2-provider/
-auths.tip.yandex=Erstelle eine neue Anwendung auf https://oauth.yandex.com/client/new. Wähle folgende Berechtigungen aus dem "Yandex.Passport API" Bereich: "Zugriff auf E-Mail-Adresse", "Zugriff auf Benutzeravatar" und "Zugriff auf Benutzername, Vor- und Nachname, Geschlecht"
+auths.tip.yandex=`Erstelle eine neue Anwendung auf https://oauth.yandex.com/client/new. Wähle folgende Berechtigungen aus dem "Yandex.Passport API" Bereich: "Zugriff auf E-Mail-Adresse", "Zugriff auf Benutzeravatar" und "Zugriff auf Benutzername, Vor- und Nachname, Geschlecht"`
auths.tip.mastodon=Gebe eine benutzerdefinierte URL für die Mastodon-Instanz ein, mit der du dich authentifizieren möchtest (oder benutze die standardmäßige)
auths.edit=Authentifikationsquelle bearbeiten
auths.activated=Diese Authentifikationsquelle ist aktiviert
@@ -2793,6 +2797,8 @@ config.mailer_enabled=Aktiviert
config.mailer_enable_helo=HELO aktivieren
config.mailer_name=Name
config.mailer_protocol=Protokoll
+config.mailer_smtp_addr=SMTP-Adresse
+config.mailer_smtp_port=SMTP-Port
config.mailer_user=Benutzer
config.mailer_use_sendmail=Sendmail benutzen
config.mailer_sendmail_path=Sendmail-Pfad
@@ -2850,6 +2856,7 @@ config.access_log_template=Vorlage
config.xorm_log_mode=XORM Log-Modus
config.xorm_log_sql=SQL protokollieren
+config.get_setting_failed=Holen der Einstellung %s fehlgeschlagen
monitor.cron=Cron-Aufgaben
monitor.name=Name
@@ -2883,6 +2890,7 @@ monitor.queue.nopool.title=Kein Worker-Pool
monitor.queue.nopool.desc=Diese Warteschlange umgibt andere Warteschlangen und hat selbst keinen Worker-Pool.
monitor.queue.wrapped.desc=Eine Wrapped Queue umfasst eine langsame Start-Warteschlange und puffert die in der Warteschlange stehenden Aufträge in einem Kanal. Sie besitzt selbst keinen Worker-Pool.
monitor.queue.persistable-channel.desc=Ein persistierender Channel umfasst zwei Warteschlangen, eine Channel-Warteschlange mit einem eigenen Worker-Pool und eine Level-Warteschlange für persistente Anfragen aus früheren Shutdowns. Er hat selbst keinen Worker-Pool.
+monitor.queue.flush=Aufräumhelfer
monitor.queue.pool.timeout=Timeout
monitor.queue.pool.addworkers.title=Worker hinzufügen
monitor.queue.pool.addworkers.submit=Worker hinzufügen
@@ -2930,7 +2938,6 @@ monitor.queue.pool.cancel_desc=Eine Warteschlange ohne Workergruppen kann dazu f
notices.system_notice_list=Systemmitteilungen
notices.view_detail_header=Meldungsdetails ansehen
-notices.actions=Aktionen
notices.select_all=Alles auswählen
notices.deselect_all=Alles abwählen
notices.inverse_selection=Auswahl umkehren
@@ -2956,6 +2963,7 @@ reopen_pull_request=`Pull-Request <a href="%[1]s">%[3]s#%[2]s</a> wurde wiederer
comment_issue=`Ticket <a href="%[1]s">%[3]s#%[2]s</a> wurde kommentiert`
comment_pull=`Pull-Request <a href="%[1]s">%[3]s#%[2]s</a> wurde kommentiert`
merge_pull_request=`Pull-Request <a href="%[1]s">%[3]s#%[2]s</a> wurde zusammengeführt`
+auto_merge_pull_request=`Pull-Request <a href="%[1]s">%[3]s#%[2]s</a> wurde automatisch zusammengeführt`
transfer_repo=hat Repository <code>%s</code> transferiert an <a href="%s">%s</a>
push_tag=Tag <a href="%[2]s">%[3]s</a> nach <a href="%[1]s">%[4]s</a> wurde gepusht
delete_tag=hat Tag %[2]s in <a href="%[1]s">%[3]s</a> gelöscht
@@ -3013,6 +3021,8 @@ pin=Benachrichtigung pinnen
mark_as_read=Als gelesen markieren
mark_as_unread=Als ungelesen markieren
mark_all_as_read=Alle als gelesen markieren
+subscriptions=Abonnements
+no_subscriptions=Keine Abonnements
[gpg]
default_key=Mit Standardschlüssel signiert
@@ -3035,6 +3045,7 @@ title=Pakete
desc=Repository-Pakete verwalten.
empty=Noch keine Pakete vorhanden.
empty.documentation=Weitere Informationen zur Paketverwaltung findest du in der <a target="_blank" rel="noopener noreferrer" href="https://docs.gitea.io/en-us/packages/overview">Dokumentation</a>.
+empty.repo=Hast du ein Paket hochgeladen, das hier nicht angezeigt wird? Gehe zu den <a href="%[1]s">Paketeinstellungen</a> und verlinke es mit diesem Repo.
filter.type=Typ
filter.type.all=Alle
filter.no_result=Keine Ergebnisse mit diesen Kriterien gefunden.
@@ -3057,6 +3068,7 @@ versions.on=am
versions.view_all=Alle anzeigen
dependency.id=ID
dependency.version=Version
+chef.install=Nutze folgenden Befehl, um das Paket zu installieren:
composer.registry=Setze diese Paketverwaltung in deiner <code>~/.composer/config.json</code> Datei auf:
composer.install=Nutze folgenden Befehl, um das Paket mit Composer zu installieren:
composer.documentation=Weitere Informationen zur Composer-Paketverwaltung findest du in der <a target="_blank" rel="noopener noreferrer" href="https://docs.gitea.io/en-us/packages/composer/">Dokumentation</a>.
@@ -3068,8 +3080,6 @@ conan.install=Um das Paket mit Conan zu installieren, führe den folgenden Befeh
conan.documentation=Weitere Informationen zur Conan-Paketverwaltung findest du in der <a target="_blank" rel="noopener noreferrer" href="https://docs.gitea.io/en-us/packages/conan/">Dokumentation</a>.
container.details.type=Container-Image Typ
container.details.platform=Plattform
-container.details.repository_site=Repository-Seite
-container.details.documentation_site=Dokumentationsseite
container.pull=Downloade das Container-Image aus der Kommandozeile:
container.documentation=Weitere Informationen zur Container-Imageverwaltung findest du in der <a target="_blank" rel="noopener noreferrer" href="https://docs.gitea.io/en-us/packages/container/">Dokumentation</a>.
container.multi_arch=Betriebsystem / Architektur
@@ -3101,6 +3111,7 @@ npm.dependencies.peer=Peer Abhängigkeiten
npm.dependencies.optional=Optionale Abhängigkeiten
npm.details.tag=Tag
pub.install=Um das Paket mit Dart zu installieren, führe den folgenden Befehl aus:
+pub.documentation=Weitere Informationen zur pub-Paketverwaltung findest du in der <a target="_blank" rel="noopener noreferrer" href="https://docs.gitea.io/en-us/packages/pub/">Dokumentation</a>.
pypi.requires=Erfordert Python
pypi.install=Nutze folgenden Befehl, um das Paket mit pip zu installieren:
pypi.documentation=Weitere Informationen zur PyPI-Paketverwaltung findest du in der <a target="_blank" rel="noopener noreferrer" href="https://docs.gitea.io/en-us/packages/pypi/">Dokumentation</a>.
@@ -3111,6 +3122,8 @@ rubygems.dependencies.development=Entwicklungsabhängigkeiten
rubygems.required.ruby=Benötigt Ruby Version
rubygems.required.rubygems=Benötigt RubyGem Version
rubygems.documentation=Weitere Informationen zur RubyGems-Paketverwaltung findest du in der <a target="_blank" rel="noopener noreferrer" href="https://docs.gitea.io/en-us/packages/rubygems/">Dokumentation</a>.
+vagrant.install=Um eine Vagrant-Box hinzuzufügen, führen Sie folgenden Befehl aus:
+vagrant.documentation=Für weitere Informationen zur Vagrant-Registry, siehe <a target="_blank" rel="noopener noreferrer" href="https://docs.gitea.io/en-us/packages/vagrant/">Dokumentation</a>.
settings.link=Dieses Paket einem Repository zuweisen
settings.link.description=Wenn du ein Paket mit einem Repository verknüpfst, wird es in der Paketliste des Repositories angezeigt.
settings.link.select=Repository auswählen
@@ -3122,4 +3135,26 @@ settings.delete.description=Das Löschen eines Pakets ist dauerhaft und kann nic
settings.delete.notice=Du bist dabei, %s (%s) zu löschen. Dieser Vorgang ist unwiderruflich. Bist du sicher?
settings.delete.success=Das Paket wurde gelöscht.
settings.delete.error=Löschen des Pakets fehlgeschlagen.
+owner.settings.cleanuprules.enabled=Aktiviert
+
+[secrets]
+value=Wert
+name=Name
+
+[actions]
+
+
+
+runners.id=ID
+runners.name=Name
+runners.owner_type=Typ
+runners.description=Beschreibung
+runners.labels=Labels
+runners.task_list.run=Ausführen
+runners.task_list.repository=Repository
+runners.task_list.commit=Commit
+runners.status.active=Aktiv
+
+runs.commit=Commit
+
diff --git a/options/locale/locale_el-GR.ini b/options/locale/locale_el-GR.ini
index 200dabaf8..6affdf7e8 100644
--- a/options/locale/locale_el-GR.ini
+++ b/options/locale/locale_el-GR.ini
@@ -41,7 +41,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_insecure=`Το WebAuthn υποστηÏίζει μόνο ασφαλείς συνδέσεις. Για δοκιμές πάνω από HTTP, μποÏείτε να χÏησιμοποιήσετε την Ï€Ïοέλευση "localhost" ή "127.0.0.1"`
webauthn_error_unable_to_process=Ο διακομιστής δεν μπόÏεσε να επεξεÏγαστεί το αίτημά σας.
webauthn_error_duplicated=Το κλειδί ασφαλείας δεν επιτÏέπεται για αυτό το αίτημα. Βεβαιωθείτε ότι το κλειδί δεν έχει ήδη καταχωÏηθεί.
webauthn_error_empty=ΠÏέπει να οÏίσετε ένα όνομα για αυτό το κλειδί.
@@ -57,7 +57,6 @@ new_mirror=Îέο Είδωλο
new_fork=Îέο Fork ΑποθετηÏίου
new_org=Îέος ΟÏγανισμός
new_project=Îέο ΈÏγο
-new_project_board=Îέος πίνακας ΈÏγου
manage_org=ΔιαχείÏιση ΟÏγανισμών
admin_panel=ΔιαχείÏιση
account_settings=Ρυθμίσεις ΛογαÏιασμοÏ
@@ -86,6 +85,9 @@ remove=ΑφαίÏεση
remove_all=ΑφαίÏεση Όλων
edit=ΕπεξεÏγασία
+enabled=ΕνεÏγοποιημένο
+disabled=ΑπενεÏγοποιημένο
+
copy=ΑντιγÏαφή
copy_url=ΑντιγÏαφή URL
copy_branch=ΑντιγÏαφή ονόματος κλάδου
@@ -106,6 +108,8 @@ never=Ποτέ
rss_feed=Ροή RSS
+[aria]
+
[filter]
string.asc=A - Z
string.desc=Z - A
@@ -226,7 +230,6 @@ internal_token_failed=Αποτυχία δημιουÏγίας εσωτεÏικο
secret_key_failed=Αποτυχία δημιουÏγίας Î¼Ï…ÏƒÏ„Î¹ÎºÎ¿Ï ÎºÎ»ÎµÎ¹Î´Î¹Î¿Ï: %v
save_config_failed=Αποτυχία αποθήκευσης Ïυθμίσεων: %v
invalid_admin_setting=Η ÏÏθμιση λογαÏÎ¹Î±ÏƒÎ¼Î¿Ï Î´Î¹Î±Ï‡ÎµÎ¹Ïιστή δεν είναι έγκυÏη: %v
-install_success=Καλώς οÏίσατε! Σας ευχαÏιστοÏμε που επιλέξατε το Gitea. Διασκεδάστε το και να είστε καλά!
invalid_log_root_path=Η διαδÏομή της καταγÏαφής δεν είναι έγκυÏη: %v
default_keep_email_private=ΑπόκÏυψη διευθÏνσεων email από Ï€Ïοεπιλογή
default_keep_email_private_popup=ΑπόκÏυψη διευθÏνσεων email των νέων λογαÏιασμών χÏήστη σαν Ï€Ïοεπιλογή.
@@ -252,7 +255,7 @@ view_home=ΠÏοβολή %s
search_repos=Î’Ïείτε ένα αποθετήÏιο…
filter=Άλλα ΦίλτÏα
filter_by_team_repositories=ΦιλτÏάÏισμα ανά αποθετήÏια ομάδας
-feed_of=ΤÏοφοδοσία του "%s"
+feed_of=`ΤÏοφοδοσία του "%s"`
show_archived=ΑÏχειοθετήθηκε
show_both_archived_unarchived=Εμφάνιση και αÏχειοθετημένων και μη αÏχειοθετημένων
@@ -297,8 +300,8 @@ disable_register_mail=Η Επιβεβαίωση email για την εγγÏαφ
manual_activation_only=Επικοινωνήστε με το διαχειÏιστή της υπηÏεσίας για να ολοκληÏώσετε την ενεÏγοποίηση.
remember_me=Απομνημόνευση αυτής της συσκευής
forgot_password_title=Ξέχασα Τον Κωδικό ΠÏόσβασης
-forgot_password=Ξεχάσατε τον κωδικό Ï€Ïόσβασης;
-sign_up_now=ΧÏειάζεστε λογαÏιασμό; ΕγγÏαφείτε Ï„ÏŽÏα.
+forgot_password=Ξεχάσατε τον κωδικό Ï€Ïόσβασης
+sign_up_now=ΧÏειάζεστε λογαÏιασμό
sign_up_successful=Ο λογαÏιασμός δημιουÏγήθηκε με επιτυχία.
confirmation_mail_sent_prompt=Ένα νέο email επιβεβαίωσης έχει σταλεί στο <b>%s</b>. ΠαÏακαλώ ελέγξτε τα εισεÏχόμενα σας μέσα στις επόμενες %s για να ολοκληÏώσετε τη διαδικασία εγγÏαφής.
must_change_password=ΕνημεÏώστε τον κωδικό Ï€Ïόσβασης σας
@@ -349,7 +352,7 @@ authorize_application=Εξουσιοδότηση ΕφαÏμογής
authorize_redirect_notice=Θα μεταφεÏθείτε στο %s εάν εξουσιοδοτήσετε αυτήν την εφαÏμογή.
authorize_application_created_by=Αυτή η εφαÏμογή δημιουÏγήθηκε από %s.
authorize_application_description=Εάν παÏαχωÏήσετε την Ï€Ïόσβαση, θα μποÏεί να έχει Ï€Ïόσβαση και να γÏάφει σε όλες τις πληÏοφοÏίες του λογαÏÎ¹Î±ÏƒÎ¼Î¿Ï ÏƒÎ±Ï‚, συμπεÏιλαμβανομένων των ιδιωτικών αποθετηÏίων και οÏγανισμών.
-authorize_title=Εξουσιοδότηση του "%s" για έχει Ï€Ïόσβαση στο λογαÏιασμό σας;
+authorize_title=Εξουσιοδότηση του "%s" για έχει Ï€Ïόσβαση στο λογαÏιασμό σας
authorization_failed=Αποτυχία εξουσιοδότησης
authorization_failed_desc=Η εξουσιοδώτηση απέτυχε επειδή εντοπίσαμε μια μη έγκυÏη αίτηση. ΠαÏακαλοÏμε επικοινωνήστε με το συντηÏητή της εφαÏμογής που Ï€Ïοσπαθήσατε να εξουσιοδοτήσετε.
sspi_auth_failed=Αποτυχία ταυτοποίησης SSPI
@@ -358,7 +361,7 @@ password_pwned_err=Δεν ήταν δυνατή η ολοκλήÏωση του Î
[mail]
view_it_on=Δείτε το στο %s
-link_not_working_do_paste=Δεν λειτουÏγεί; Δοκιμάστε να κάνετε αντιγÏαφή και επικόλληση στο Ï€ÏόγÏαμμα πεÏιήγησης.
+link_not_working_do_paste=Δεν λειτουÏγεί
hi_user_x=Γειά σου <b>%s</b>,
activate_account=ΠαÏακαλώ ενεÏγοποιήστε το λογαÏιασμό σας
@@ -409,7 +412,7 @@ release.download.zip=Πηγαίος Κώδικας (Zip)
release.download.targz=Πηγαίος Κώδικας (TAR.GZ)
repo.transfer.subject_to=%s θα ήθελε να μεταφέÏει το "%s" σε %s
-repo.transfer.subject_to_you=%s θα ήθελε να σας μεταφέÏει το "%s"
+repo.transfer.subject_to_you=`%s θα ήθελε να σας μεταφέÏει το "%s"`
repo.transfer.to_you=εσάς
repo.transfer.body=Για να το αποδεχτείτε ή να το αποÏÏίψετε, επισκεφθείτε το %s ή απλά αγνοήστε το.
@@ -520,6 +523,7 @@ activity=Δημόσια ΔÏαστηÏιότητα
followers=Ακόλουθοι
starred=Αγαπημένα ΑποθετήÏια
watched=ΑκολουθοÏμενα ΑποθετήÏια
+code=Κώδικας
projects=ΈÏγα
following=Ακολουθεί
follow=Ακολουθήστε
@@ -624,12 +628,12 @@ activate_email=Αποστολή ΕνεÏγοποίησης
activations_pending=ΕκκÏεμοÏν ΕνεÏγοποιήσεις
delete_email=ΑφαίÏεση
email_deletion=ΑφαίÏεση ΔιεÏθυνσης Email
-email_deletion_desc=Η διεÏθυνση ηλεκτÏÎ¿Î½Î¹ÎºÎ¿Ï Ï„Î±Ï‡Ï…Î´Ïομείου και οι σχετικές πληÏοφοÏίες θα αφαιÏεθοÏν από το λογαÏιασμό σας. Οι υποβολές Git από αυτή τη διεÏθυνση email θα παÏαμείνουν αμετάβλητες. Συνέχεια;
+email_deletion_desc=Η διεÏθυνση ηλεκτÏÎ¿Î½Î¹ÎºÎ¿Ï Ï„Î±Ï‡Ï…Î´Ïομείου και οι σχετικές πληÏοφοÏίες θα αφαιÏεθοÏν από το λογαÏιασμό σας. Οι υποβολές Git από αυτή τη διεÏθυνση email θα παÏαμείνουν αμετάβλητες. Συνέχεια
email_deletion_success=Η διεÏθυνση email σας έχει καταÏγηθεί.
theme_update_success=Το θέμα διεπαφής σας ενημεÏώθηκε.
theme_update_error=Το επιλεγμένο θέμα διεπαφής δεν υπάÏχει.
openid_deletion=ΑφαίÏεση ΔιεÏθυνσης OpenID
-openid_deletion_desc=Η κατάÏγηση αυτής της διεÏθυνσης OpenID από το λογαÏιασμό σας θα σας εμποδίσει να συνδέεστε με αυτό. Συνέχεια;
+openid_deletion_desc=Η κατάÏγηση αυτής της διεÏθυνσης OpenID από το λογαÏιασμό σας θα σας εμποδίσει να συνδέεστε με αυτό. Συνέχεια
openid_deletion_success=Η διεÏθυνση OpenID αφαιÏέθηκε.
add_new_email=ΠÏοσθήκη Îέας ΔιεÏθυνσης Email
add_new_openid=ΠÏοσθήκη Îέου OpenID URI
@@ -650,8 +654,8 @@ add_key=ΠÏοσθήκη ΚλειδιοÏ
ssh_desc=Αυτά τα δημόσια SSH κλειδιά συνδέονται με το λογαÏιασμό σας. Τα αντίστοιχα ιδιωτικά κλειδιά επιτÏέπουν πλήÏη Ï€Ïόσβαση στα αποθετήÏιά σας.
principal_desc=Αυτές οι αÏχές πιστοποιητικών SSH συνδέονται με το λογαÏιασμό σας και επιτÏέπουν την πλήÏη Ï€Ïόσβαση στα αποθετήÏιά σας.
gpg_desc=Αυτά τα δημόσια κλειδιά GPG συνδέονται με το λογαÏιασμό σας. ΚÏατήστε τα ιδιωτικά κλειδιά σας ασφαλή καθώς επιτÏέπουν την επαλήθευση των υποβολών.
-ssh_helper=<strong>ΧÏειάζεστε βοήθεια;</strong> Ρίξτε μια ματιά στον οδηγό του GitHub για να <a href="%s">δημιουÏγήσετε τα δικά σας SSH κλειδιά</a> ή να λÏσετε <a href="%s">κοινά Ï€Ïοβλήματα</a> που ενδέχεται να αντιμετωπίσετε χÏησιμοποιώντας το SSH.
-gpg_helper=<strong>ΧÏειάζεστε βοήθεια;</strong> Ρίξτε μια ματιά στον οδηγό του GitHub <a href="%s">για το GPG</a>.
+ssh_helper=<strong>ΧÏειάζεστε βοήθεια
+gpg_helper=<strong>ΧÏειάζεστε βοήθεια
add_new_key=ΠÏοσθήκη SSH ΚλειδιοÏ
add_new_gpg_key=ΠÏοσθήκη GPG ΚλειδιοÏ
key_content_ssh_placeholder=Ξεκινάει με 'ssh-ed25519', 'ssh-rsa', 'ecdsa-sha2-nistp256', 'ecdsa-sha2-nistp384', 'ecdsa-sha2-nistp521', 'sk-ecdsa-sha2-nistp256@openssh.com', ή 'sk-ssh-ed25519@openssh.com'
@@ -697,9 +701,9 @@ delete_key=ΔιαγÏαφή
ssh_key_deletion=ΔιαγÏαφή ÎšÎ»ÎµÎ¹Î´Î¹Î¿Ï SSH
gpg_key_deletion=ΔιαγÏαφή ÎšÎ»ÎµÎ¹Î´Î¹Î¿Ï GPG
ssh_principal_deletion=ΔιαγÏαφή ΑÏχών Î Î¹ÏƒÏ„Î¿Ï€Î¿Î¹Î·Ï„Î¹ÎºÎ¿Ï SSH
-ssh_key_deletion_desc=Η διαγÏαφή ενός ÎºÎ»ÎµÎ¹Î´Î¹Î¿Ï SSH ανακαλεί την Ï€Ïόσβασή του στο λογαÏιασμό σας. Συνέχεια;
-gpg_key_deletion_desc=Η διαγÏαφή ενός ÎºÎ»ÎµÎ¹Î´Î¹Î¿Ï GPG απο-επαληθεÏει τις υποβολές που έχουν υπογÏαφεί από αυτό. Συνέχεια;
-ssh_principal_deletion_desc=Η διαγÏαφή μιας αÏχής Ï€Î¹ÏƒÏ„Î¿Ï€Î¿Î¹Î·Ï„Î¹ÎºÎ¿Ï SSH ανακαλεί την Ï€Ïόσβασή της στο λογαÏιασμό σας. Συνέχεια;
+ssh_key_deletion_desc=Η διαγÏαφή ενός ÎºÎ»ÎµÎ¹Î´Î¹Î¿Ï SSH ανακαλεί την Ï€Ïόσβασή του στο λογαÏιασμό σας. Συνέχεια
+gpg_key_deletion_desc=Η διαγÏαφή ενός ÎºÎ»ÎµÎ¹Î´Î¹Î¿Ï GPG απο-επαληθεÏει τις υποβολές που έχουν υπογÏαφεί από αυτό. Συνέχεια
+ssh_principal_deletion_desc=Η διαγÏαφή μιας αÏχής Ï€Î¹ÏƒÏ„Î¿Ï€Î¿Î¹Î·Ï„Î¹ÎºÎ¿Ï SSH ανακαλεί την Ï€Ïόσβασή της στο λογαÏιασμό σας. Συνέχεια
ssh_key_deletion_success=Το SSH κλειδί έχει διαγÏαφεί.
gpg_key_deletion_success=Το κλειδί GPG έχει διαγÏαφεί.
ssh_principal_deletion_success=Η αÏχή Ï€Î¹ÏƒÏ„Î¿Ï€Î¿Î¹Î·Ï„Î¹ÎºÎ¿Ï Î­Ï‡ÎµÎ¹ διαγÏαφεί.
@@ -734,14 +738,14 @@ delete_token=ΔιαγÏαφή
access_token_deletion=ΔιαγÏαφή ΔιακÏÎ¹Ï„Î¹ÎºÎ¿Ï Î Ïόσβασης
access_token_deletion_cancel_action=ΆκυÏο
access_token_deletion_confirm_action=ΔιαγÏαφή
-access_token_deletion_desc=Η διαγÏαφή ενός διακÏÎ¹Ï„Î¹ÎºÎ¿Ï Î¸Î± ανακαλέσει οÏιστικά την Ï€Ïόσβαση στο λογαÏιασμό σας για εφαÏμογές που το χÏησιμοποιοÏν. Συνέχεια;
+access_token_deletion_desc=Η διαγÏαφή ενός διακÏÎ¹Ï„Î¹ÎºÎ¿Ï Î¸Î± ανακαλέσει οÏιστικά την Ï€Ïόσβαση στο λογαÏιασμό σας για εφαÏμογές που το χÏησιμοποιοÏν. Συνέχεια
delete_token_success=Το διακÏιτικό έχει διαγÏαφεί. Οι εφαÏμογές που το χÏησιμοποιοÏν δεν έχουν πλέον Ï€Ïόσβαση στο λογαÏιασμό σας.
manage_oauth2_applications=ΔιαχείÏιση ΕφαÏμογών Oauth2
edit_oauth2_application=ΕπεξεÏγασία ΕφαÏμογής Oauth2
oauth2_applications_desc=Οι εφαÏμογές OAuth2 επιτÏέπουν στην εξωτεÏική εφαÏμογή σας την ασφαλή ταυτοποίηση των χÏηστών σε αυτό το Gitea.
remove_oauth2_application=ΑφαίÏεση ΕφαÏμογής Oauth2
-remove_oauth2_application_desc=Η αφαίÏεση μιας εφαÏμογής OAuth2 θα ανακαλέσει την Ï€Ïόσβαση σε όλα τα υπογεγÏαμμένα διακÏιτικά Ï€Ïόσβασης. Συνέχεια;
+remove_oauth2_application_desc=Η αφαίÏεση μιας εφαÏμογής OAuth2 θα ανακαλέσει την Ï€Ïόσβαση σε όλα τα υπογεγÏαμμένα διακÏιτικά Ï€Ïόσβασης. Συνέχεια
remove_oauth2_application_success=Η εφαÏμογή έχει διαγÏαφεί.
create_oauth2_application=ΔημιουÏγία νέας εφαÏμογής OAuth2
create_oauth2_application_button=ΔημιουÏγία ΕφαÏμογής
@@ -754,17 +758,17 @@ save_application=Αποθήκευση
oauth2_client_id=Ταυτότητα Πελάτη
oauth2_client_secret=Μυστικό Πελάτη
oauth2_regenerate_secret=ΑναδημιουÏγία ΜυστικοÏ
-oauth2_regenerate_secret_hint=Χάσατε το μυστικό σας;
+oauth2_regenerate_secret_hint=Χάσατε το μυστικό σας
oauth2_client_secret_hint=Το μυστικό δεν θα είναι οÏατό αν επισκεφτείτε ξανά αυτή τη σελίδα. ΠαÏακαλώ αποθηκεÏστε το μυστικό σας.
oauth2_application_edit=ΕπεξεÏγασία
oauth2_application_create_description=Οι εφαÏμογές OAuth2 δίνει Ï€Ïόσβαση στην εξωτεÏική εφαÏμογή σας σε λογαÏιασμοÏÏ‚ χÏηστών σε αυτή την υπηÏεσία.
-oauth2_application_remove_description=ΑφαιÏώντας μια εφαÏμογή OAuth2, θα αποτÏέψει την Ï€Ïόσβαση σε εξουσιοδοτημένους λογαÏιασμοÏÏ‚ χÏηστών σε αυτή την υπηÏεσία. Συνέχεια;
+oauth2_application_remove_description=ΑφαιÏώντας μια εφαÏμογή OAuth2, θα αποτÏέψει την Ï€Ïόσβαση σε εξουσιοδοτημένους λογαÏιασμοÏÏ‚ χÏηστών σε αυτή την υπηÏεσία. Συνέχεια
authorized_oauth2_applications=Εξουσιοδοτημένες ΕφαÏμογές OAuth2
authorized_oauth2_applications_description=Έχετε δώσει Ï€Ïόσβαση στον Ï€Ïοσωπικό σας λογαÏιασμό Gitea σε αυτές τις εξωτεÏικές εφαÏμογές. Ανακαλέστε την Ï€Ïόσβαση για εφαÏμογές που δεν χÏειάζονται πλέον.
revoke_key=Ανάκληση
revoke_oauth2_grant=Ανάκληση ΠÏόσβασης
-revoke_oauth2_grant_description=Η ανάκληση Ï€Ïόσβασης για αυτή την εξωτεÏική εφαÏμογή θα αποτÏέψει αυτή την εφαÏμογή από την Ï€Ïόσβαση στα δεδομένα σας. ΣίγουÏα;
+revoke_oauth2_grant_description=Η ανάκληση Ï€Ïόσβασης για αυτή την εξωτεÏική εφαÏμογή θα αποτÏέψει αυτή την εφαÏμογή από την Ï€Ïόσβαση στα δεδομένα σας. ΣίγουÏα
revoke_oauth2_grant_success=Έχετε ανακαλέσει την Ï€Ïόσβαση με επιτυχία.
twofa_desc=Ο έλεγχος ταυτότητας δÏο παÏαγόντων ενισχÏει την ασφάλεια του λογαÏÎ¹Î±ÏƒÎ¼Î¿Ï ÏƒÎ±Ï‚.
@@ -775,7 +779,7 @@ twofa_scratch_token_regenerate=ΑναδημιουÏγία ΔιακÏιτικοÏ
twofa_scratch_token_regenerated=Το διακÏιτικό μιας χÏήσης είναι Ï„ÏŽÏα %s. ΑποθηκεÏστε το σε ασφαλές μέÏος.
twofa_enroll=ΕγγÏαφή στην ταυτοποίηση δÏο παÏαγόντων
twofa_disable_note=ΜποÏείτε να απενεÏγοποιήσετε την ταυτοποίηση δÏο παÏαγόντων αν χÏειαστεί.
-twofa_disable_desc=Η απενεÏγοποίηση της ταυτοποίησης δÏο παÏαγόντων θα καταστήσει τον λογαÏιασμό σας λιγότεÏο ασφαλή. Συνέχεια;
+twofa_disable_desc=Η απενεÏγοποίηση της ταυτοποίησης δÏο παÏαγόντων θα καταστήσει τον λογαÏιασμό σας λιγότεÏο ασφαλή. Συνέχεια
regenerate_scratch_token_desc=Αν χάσατε το διακÏιτικό μίας χÏήσης σας ή το έχετε ήδη χÏησιμοποιήσει για να συνδεθείτε μποÏείτε να το επαναφέÏετε εδώ.
twofa_disabled=Η ταυτοποίηση δÏο παÏαγόντων έχει απενεÏγοποιηθεί.
scan_this_image=ΣαÏώστε αυτή την εικόνα με την εφαÏμογή ταυτοποίησης:
@@ -789,16 +793,17 @@ webauthn_desc=Τα κλειδιά ασφαλείας είναι συσκευές
webauthn_register_key=ΠÏοσθήκη ÎšÎ»ÎµÎ¹Î´Î¹Î¿Ï Î‘ÏƒÏ†Î±Î»ÎµÎ¯Î±Ï‚
webauthn_nickname=Ψευδώνυμο
webauthn_delete_key=ΑφαίÏεση ÎšÎ»ÎµÎ¹Î´Î¹Î¿Ï Î‘ÏƒÏ†Î±Î»ÎµÎ¯Î±Ï‚
-webauthn_delete_key_desc=Αν αφαιÏέσετε ένα κλειδί ασφαλείας δεν μποÏείτε πλέον να συνδεθείτε με αυτό. Συνέχεια;
+webauthn_delete_key_desc=Αν αφαιÏέσετε ένα κλειδί ασφαλείας δεν μποÏείτε πλέον να συνδεθείτε με αυτό. Συνέχεια
manage_account_links=ΔιαχείÏιση Συνδεδεμένων ΛογαÏιασμών
manage_account_links_desc=Αυτοί οι εξωτεÏικοί λογαÏιασμοί είναι συνδεδεμένοι στον Gitea λογαÏιασμό σας.
account_links_not_available=ΠÏος το παÏόν δεν υπάÏχουν εξωτεÏικοί λογαÏιασμοί συνδεδεμένοι με τον λογαÏιασμό σας στο Gitea.
link_account=ΣÏνδεση ΛογαÏιασμοÏ
remove_account_link=ΑφαίÏεση Συνδεδεμένου ΛογαÏιασμοÏ
-remove_account_link_desc=Η κατάÏγηση ενός συνδεδεμένου λογαÏÎ¹Î±ÏƒÎ¼Î¿Ï Î¸Î± ανακαλέσει την Ï€Ïόσβασή του στο λογαÏιασμό σας στο Gitea. Συνέχεια;
+remove_account_link_desc=Η κατάÏγηση ενός συνδεδεμένου λογαÏÎ¹Î±ÏƒÎ¼Î¿Ï Î¸Î± ανακαλέσει την Ï€Ïόσβασή του στο λογαÏιασμό σας στο Gitea. Συνέχεια
remove_account_link_success=Ο συνδεδεμένος λογαÏιασμός έχει αφαιÏεθεί.
+
orgs_none=Δεν είστε μέλος σε κάποιο οÏγανισμό.
repos_none=Δεν έχετε κανένα αποθετήÏιο
@@ -807,7 +812,7 @@ delete_prompt=Αυτή η ενέÏγεια θα διαγÏάψει μόνιμα
delete_with_all_comments=Ο λογαÏιασμός σας είναι νεότεÏος από %s. Για να αποφÏγετε τα σχόλια φαντάσματα, όλα τα σχόλια σε ζητήματα/PR θα διαγÏαφοÏν από αυτόν.
confirm_delete_account=Επιβεβαίωση ΔιαγÏαφής
delete_account_title=ΔιαγÏαφή ΛογαÏÎ¹Î±ÏƒÎ¼Î¿Ï Î§Ïήστη
-delete_account_desc=Είστε βέβαιοι ότι θέλετε να διαγÏάψετε μόνιμα αυτό το λογαÏιασμό χÏήστη;
+delete_account_desc=Είστε βέβαιοι ότι θέλετε να διαγÏάψετε μόνιμα αυτό το λογαÏιασμό χÏήστη
email_notifications.enable=ΕνεÏγοποίηση Ειδοποιήσεων Μέσω Email
email_notifications.onmention=Email Μόνο κατά την ΑναφοÏά
@@ -824,7 +829,7 @@ visibility.private=Ιδιωτική
visibility.private_tooltip=ΟÏατός μόνο στα μέλη της οÏγάνωσης
[repo]
-new_repo_helper=Ένα αποθετήÏιο πεÏιέχει όλα τα αÏχεία του έÏγου, συμπεÏιλαμβανομένου του ιστοÏÎ¹ÎºÎ¿Ï Ï„Î¿Ï…Ï‚. Ήδη το έχετε κάπου αλλοÏ; <a href="%s">ΜεταφοÏά αποθετηÏίου.</a>
+new_repo_helper=Ένα αποθετήÏιο πεÏιέχει όλα τα αÏχεία του έÏγου, συμπεÏιλαμβανομένου του ιστοÏÎ¹ÎºÎ¿Ï Ï„Î¿Ï…Ï‚. Ήδη το έχετε κάπου αλλοÏ
owner=Ιδιοκτήτης
owner_helper=ΟÏισμένοι οÏγανισμοί ενδέχεται να μην εμφανίζονται στο αναπτυσσόμενο Î¼ÎµÎ½Î¿Ï Î»ÏŒÎ³Ï‰ του μέγιστου αÏÎ¹Î¸Î¼Î¿Ï Î±Ï€Î¿Î¸ÎµÏ„Î·Ïίων.
repo_name=Όνομα αποθετηÏίου
@@ -839,7 +844,7 @@ visibility_description=Μόνο ο ιδιοκτήτης ή τα μέλη του
visibility_helper=Αλλαγή σε Ιδιωτικό ΑποθετήÏιο
visibility_helper_forced=Ο διαχειÏιστής σας αναγκάζει τα νέα αποθετήÏια να είναι ιδιωτικά.
visibility_fork_helper=(Αλλάζοντας αυτό θα επηÏεάσει όλα τα forks.)
-clone_helper=ΧÏειάζεστε βοήθεια για τη κλωνοποίηση; Επισκεφθείτε τη <a target="_blank" rel="noopener noreferrer" href="%s">Βοήθεια</a>.
+clone_helper=ΧÏειάζεστε βοήθεια για τη κλωνοποίηση
fork_repo=ΔημιουÏγία ενός Fork
fork_from=Fork Από Το
already_forked=Έχετε ήδη κάνει fork το %s
@@ -861,7 +866,7 @@ issue_labels=Σήματα Ζητήματος
issue_labels_helper=Επιλέξτε ένα σÏνολο σημάτων ζητημάτων.
license=Άδεια
license_helper=Επιλέξτε ένα αÏχείο άδειας.
-license_helper_desc=Μια άδεια διέπει τι άλλοι μποÏοÏν και δεν μποÏοÏν να κάνουν με τον κώδικά σας. Δεν είστε σίγουÏοι ποια είναι η σωστή για το έÏγο σας; Δείτε το <a target="_blank" rel="noopener noreferrer" href="%s">Επιλέξτε μια άδεια.</a>
+license_helper_desc=Μια άδεια διέπει τι άλλοι μποÏοÏν και δεν μποÏοÏν να κάνουν με τον κώδικά σας. Δεν είστε σίγουÏοι ποια είναι η σωστή για το έÏγο σας
readme=README
readme_helper=Επιλέξτε ένα Ï€Ïότυπο αÏχείου README.
readme_helper_desc=Αυτό είναι το μέÏος όπου μποÏείτε να γÏάψετε μια πλήÏη πεÏιγÏαφή για το έÏγο σας.
@@ -910,9 +915,9 @@ delete_preexisting_success=ΔιαγÏάφηκαν τα μη υιοθετημέν
blame_prior=ΠÏοβολή ευθÏνης Ï€Ïιν από αυτή την αλλαγή
transfer.accept=Αποδοχή ΜεταφοÏάς
-transfer.accept_desc=ΜεταφοÏά στο "%s"
+transfer.accept_desc=`ΜεταφοÏά στο "%s"`
transfer.reject=ΑπόÏÏιψη ΜεταφοÏάς
-transfer.reject_desc=ΑκÏÏωση μεταφοÏάς σε "%s"
+transfer.reject_desc=`ΑκÏÏωση μεταφοÏάς σε "%s"`
transfer.no_permission_to_accept=Δεν έχετε άδεια για να Αποδεχτείτε
transfer.no_permission_to_reject=Δεν έχετε δικαιώματα να κάνετε ΑπόÏÏιψη
@@ -1124,7 +1129,7 @@ editor.file_deleting_no_longer_exists=Το αÏχείο που διαγÏάφεÏ
editor.file_changed_while_editing=Τα πεÏιεχόμενα του αÏχείου άλλαξαν από τότε που ξεκίνησε η επεξεÏγασία. <a target="_blank" rel="noopener noreferrer" href="%s">Κάντε κλικ εδώ</a> για να τα δείτε ή <strong>Υποβολή Αλλαγών ξανά</strong> για να τα αντικαταστήσετε.
editor.file_already_exists=Ένα αÏχείο με όνομα '%s' υπάÏχει ήδη σε αυτό το αποθετήÏιο.
editor.commit_empty_file_header=Υποβολή ενός ÎºÎµÎ½Î¿Ï Î±Ïχείου
-editor.commit_empty_file_text=Το αÏχείο που Ï€Ïόκειται να υποβληθεί είναι κενό. Συνέχεια;
+editor.commit_empty_file_text=Το αÏχείο που Ï€Ïόκειται να υποβληθεί είναι κενό. Συνέχεια
editor.no_changes_to_show=Δεν υπάÏχουν αλλαγές για εμφάνιση.
editor.fail_to_update_file=Απέτυχε η ενημέÏωση/δημιουÏγία του αÏχείου '%s'.
editor.fail_to_update_file_summary=Μήνυμα Σφάλματος:
@@ -1161,7 +1166,6 @@ commits.signed_by_untrusted_user_unmatched=ΥπογÏάφηκε από ένα μ
commits.gpg_key_id=ID ÎšÎ»ÎµÎ¹Î´Î¹Î¿Ï GPG
commits.ssh_key_fingerprint=ΑποτÏπωμα ÎšÎ»ÎµÎ¹Î´Î¹Î¿Ï SSH
-commit.actions=ΔÏάσεις
commit.revert=ΑπόσυÏση
commit.revert-header=ΑπόσυÏση: %s
commit.revert-content=Επιλέξτε κλάδο για απόσυÏση σε αυτό:
@@ -1182,7 +1186,7 @@ projects.new=Îέο έÏγο
projects.new_subheader=Συντονισμός, παÏακολοÏθηση και ενημέÏωση της δουλειάς σας σε ένα μέÏος, έτσι ώστε τα έÏγα να παÏαμένουν διαφανή και μέσα στο χÏονοδιάγÏαμμα.
projects.create_success=Το έÏγο '%s' έχει δημιουÏγηθεί.
projects.deletion=ΔιαγÏαφή ΈÏγου
-projects.deletion_desc=Η διαγÏαφή ενός έÏγου το αφαιÏεί από όλα τα σχετιζόμενα ζητήματα. Συνέχεια;
+projects.deletion_desc=Η διαγÏαφή ενός έÏγου το αφαιÏεί από όλα τα σχετιζόμενα ζητήματα. Συνέχεια
projects.deletion_success=Το έÏγο έχει διαγÏαφεί.
projects.edit=ΕπεξεÏγασία ΈÏγων
projects.edit_subheader=Τα ΈÏγα οÏγανώνουν τα ζητήματα και παÏακολουθοÏν τη Ï€Ïόοδο τους.
@@ -1194,19 +1198,11 @@ projects.type.bug_triage=Διαλογή Σφαλμάτων
projects.template.desc=ΠÏότυπο έÏγου
projects.template.desc_helper=Επιλέξτε ένα Ï€Ïότυπο έÏγου για να ξεκινήσετε
projects.type.uncategorized=ΧωÏίς ΚατηγοÏία
-projects.board.edit=ΕπεξεÏγασία πίνακα
-projects.board.edit_title=Îέο Όνομα Πίνακα
-projects.board.new_title=Îέο Όνομα Πίνακα
-projects.board.new_submit=Υποβολή
-projects.board.new=Îέος Πίνακας
-projects.board.set_default=ΟÏισμός ΠÏοεπιλογής
-projects.board.set_default_desc=ΟÏίστε αυτόν τον πίνακα ως Ï€Ïοεπιλογή για μη κατηγοÏιοποιημένα ζητήματα και pull requests
-projects.board.delete=ΔιαγÏαφή Πίνακα
-projects.board.deletion_desc=Η διαγÏαφή ενός πίνακα έÏγου μετακινεί όλα τα σχετιζόμενα ζητήματα σε 'ΧωÏίς ΚατηγοÏία'. Συνέχεια;
-projects.board.color=ΧÏώμα
+projects.column.edit_title=Όνομα
+projects.column.new_title=Όνομα
+projects.column.color=ΈγχÏωμο
projects.open=Άνοιγμα
projects.close=Κλείσιμο
-projects.board.assigned_to=Ανατέθηκε σε
issues.desc=ΟÏγανώστε αναφοÏές σφαλμάτων, εÏγασίες και οÏόσημα.
issues.filter_assignees=ΦίλτÏο Αποδέκτη
@@ -1282,6 +1278,8 @@ issues.filter_label_exclude=`ΧÏησιμοποιήστε <code>alt</code> + <co
issues.filter_label_no_select=Όλα τα σήματα
issues.filter_milestone=ΟÏόσημο
issues.filter_milestone_no_select=Όλα τα οÏόσημα
+issues.filter_project=ΈÏγο
+issues.filter_project_none=ΧωÏίς έÏγα
issues.filter_assignee=Αποδέκτης
issues.filter_assginee_no_select=Όλοι οι αποδέκτες
issues.filter_poster=ΣυγγÏαφέας
@@ -1326,7 +1324,7 @@ issues.closed_title=Κλειστό
issues.draft_title=ΠÏοσχέδιο
issues.num_comments=%d σχόλια
issues.commented_at=`σχολίασε <a href="#%s">%s</a>`
-issues.delete_comment_confirm=Θέλετε σίγουÏα να διαγÏάψετε αυτό το σχόλιο;
+issues.delete_comment_confirm=Θέλετε σίγουÏα να διαγÏάψετε αυτό το σχόλιο
issues.context.copy_link=ΑντιγÏαφή Συνδέσμου
issues.context.quote_reply=ΠαÏάθεση Απάντησης
issues.context.reference_issue=ΑναφοÏά σε νέο ζήτημα
@@ -1358,7 +1356,7 @@ issues.is_stale=Έχουν υπάÏξει αλλαγές σε αυτό το PR Î
issues.remove_request_review=ΑφαίÏεση αιτήματος αναθεώÏησης
issues.remove_request_review_block=Δεν είναι δυνατή η αφαίÏεση του αιτήματος αξιολόγησης
issues.dismiss_review=ΑπόÏÏιψη Αξιολόγησης
-issues.dismiss_review_warning=Είστε βέβαιοι ότι θέλετε να αποÏÏίψετε αυτή την αξιολόγηση;
+issues.dismiss_review_warning=Είστε βέβαιοι ότι θέλετε να αποÏÏίψετε αυτή την αξιολόγηση
issues.sign_in_require_desc=<a href="%s">Συνδεθείτε</a> για να συμμετάσχετε σε αυτή τη συνομιλία.
issues.edit=ΕπεξεÏγασία
issues.cancel=ΑκÏÏωση
@@ -1372,7 +1370,7 @@ issues.label_edit=ΕπεξεÏγασία
issues.label_delete=ΔιαγÏαφή
issues.label_modify=ΕπεξεÏγασία Σήματος
issues.label_deletion=ΔιαγÏαφή Σήματος
-issues.label_deletion_desc=Η διαγÏαφή ενός σήματος την αφαιÏεί από όλα τα ζητήματα. Συνέχεια;
+issues.label_deletion_desc=Η διαγÏαφή ενός σήματος την αφαιÏεί από όλα τα ζητήματα. Συνέχεια
issues.label_deletion_success=Το σήμα έχει διαγÏαφεί.
issues.label.filter_sort.alphabetically=Αλφαβητικά
issues.label.filter_sort.reverse_alphabetically=ΑντίστÏοφα αλφαβητικά
@@ -1403,8 +1401,8 @@ issues.lock.title=Κλείδωμα συνομιλίας σε αυτό το ζήÏ
issues.unlock.title=Ξεκλείδωμα συνομιλίας σε αυτό το ζήτημα.
issues.comment_on_locked=Δεν μποÏείτε να σχολιάσετε ένα κλειδωμένο ζήτημα.
issues.delete=ΔιαγÏαφή
-issues.delete.title=ΔιαγÏαφή Î±Ï…Ï„Î¿Ï Ï„Î¿Ï… ζητήματος;
-issues.delete.text=Θέλετε Ï€Ïαγματικά να διαγÏάψετε αυτό το ζήτημα; (Αυτό θα καταÏγήσει οÏιστικά όλο το πεÏιεχόμενο. Επιλέξτε το κλείσιμο, αν σκοπεÏετε να το αÏχειοθετήσετε)
+issues.delete.title=ΔιαγÏαφή Î±Ï…Ï„Î¿Ï Ï„Î¿Ï… ζητήματος
+issues.delete.text=Θέλετε Ï€Ïαγματικά να διαγÏάψετε αυτό το ζήτημα
issues.tracker=ΚαταγÏαφή ΧÏόνου
issues.start_tracking_short=Εκκίνηση ΧÏονομέτÏου
issues.start_tracking=Εκκίνηση ΚαταγÏαφής ΧÏόνου
@@ -1433,6 +1431,7 @@ issues.error_removing_due_date=Αποτυχία κατάÏγησης της ημ
issues.push_commit_1=Ï€Ïόσθεσε %d υποβολή %s
issues.push_commits_n=Ï€Ïόσθεσε %d υποβολές %s
issues.force_push_codes=`force-pushed %[1]s από το <a class="ui sha" href="%[3]s"><code>%[2]s</code></a> στο <a class="ui sha" href="%[5]s"><code>%[4]s</code></a> %[6]s`
+issues.force_push_compare=ΣÏγκÏιση
issues.due_date_form=εεεε-μμ-ηη
issues.due_date_form_add=ΠÏοσθήκη ημεÏομηνίας παÏάδοσης
issues.due_date_form_edit=ΕπεξεÏγασία
@@ -1462,8 +1461,8 @@ 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=Αυτό θα αφαιÏέσει την εξάÏτηση από αυτό το pull request. Συνέχεια;
+issues.dependency.issue_remove_text=Αυτό θα αφαιÏέσει την εξάÏτηση από αυτό το ζήτημα. Συνέχεια
+issues.dependency.pr_remove_text=Αυτό θα αφαιÏέσει την εξάÏτηση από αυτό το pull request. Συνέχεια
issues.dependency.setting=ΕνεÏγοποίηση ΕξαÏτήσεων Για Ζητήματα και Pull Requests
issues.dependency.add_error_same_issue=Δεν μποÏείτε να εξαÏτάτε ένα ζήτημα από τον εαυτό του.
issues.dependency.add_error_dep_issue_not_exist=ΕξαÏτώμενο ζήτημα δεν υπάÏχει.
@@ -1502,7 +1501,7 @@ issues.content_history.deleted=διαγÏάφηκε
issues.content_history.edited=επεξεÏγάστηκε
issues.content_history.created=δημιουÏγήθηκε
issues.content_history.delete_from_history=ΔιαγÏαφή από το ιστοÏικό
-issues.content_history.delete_from_history_confirm=ΔιαγÏαφή από το ιστοÏικό;
+issues.content_history.delete_from_history_confirm=ΔιαγÏαφή από το ιστοÏικό
issues.content_history.options=Επιλογές
issues.reference_link=ΑναφοÏά: %s
@@ -1546,7 +1545,7 @@ pulls.is_closed=Το pull request έχει κλείσει.
pulls.has_merged=Το pull request έχει συγχωνευθεί.
pulls.title_wip_desc=`<a href="#">Ξεκινήστε τον τίτλο με <strong>%s</strong></a> για να αποτÏέψετε την τυχαία συγχώνευση του pull request.`
pulls.cannot_merge_work_in_progress=Αυτό το pull request επισημαίνεται ως μια εÏγασία σε εξέλιξη.
-pulls.still_in_progress=Ακόμα είναι σε εξέλιξη;
+pulls.still_in_progress=Ακόμα είναι σε εξέλιξη
pulls.add_prefix=ΠÏοσθήκη <strong>%s</strong> Ï€Ïοθέματος
pulls.remove_prefix=ΑφαίÏεση <strong>%s</strong> Ï€Ïοθέματος
pulls.data_broken=Αυτό το pull request είναι κατεστÏαμμένο λόγω των πληÏοφοÏιών του fork που λείπουν.
@@ -1632,8 +1631,8 @@ pulls.auto_merge_canceled_schedule=Η αυτόματη συγχώνευση ακ
pulls.auto_merge_newly_scheduled_comment=`Ï€ÏογÏαμμάτισε αυτό το PR να συγχωνευτεί αυτόματα όταν όλοι οι έλεγχοι πετÏχουν %[1]s`
pulls.auto_merge_canceled_schedule_comment=`ακÏÏωσε την αυτόματη συγχώνευση Î±Ï…Ï„Î¿Ï Ï„Î¿Ï… pull request όταν όλοι οι έλεγχοι πετÏχουν %[1]s`
-pulls.delete.title=ΔιαγÏαφή Î±Ï…Ï„Î¿Ï Ï„Î¿Ï… pull request;
-pulls.delete.text=Θέλετε Ï€Ïαγματικά να διαγÏάψετε αυτό το pull request; (Αυτό θα αφαιÏέσει μόνιμα όλο το πεÏιεχόμενο. Κλείστε το, αν σκοπεÏετε να το κÏατήσετε αÏχειοθετημένο)
+pulls.delete.title=ΔιαγÏαφή Î±Ï…Ï„Î¿Ï Ï„Î¿Ï… pull request
+pulls.delete.text=Θέλετε Ï€Ïαγματικά να διαγÏάψετε αυτό το pull request
milestones.new=Îέο ΟÏόσημο
milestones.closed=Έκλεισε %s
@@ -1656,7 +1655,7 @@ milestones.cancel=ΑκÏÏωση
milestones.modify=ΕνημέÏωση ΟÏόσημου
milestones.edit_success=Το οÏόσημο '%s' έχει ενημεÏωθεί.
milestones.deletion=ΔιαγÏαφή ΟÏόσημου
-milestones.deletion_desc=Η διαγÏαφή ενός οÏόσημου το αφαιÏεί από όλα τα συναφή ζητήματα. Συνέχεια;
+milestones.deletion_desc=Η διαγÏαφή ενός οÏόσημου το αφαιÏεί από όλα τα συναφή ζητήματα. Συνέχεια
milestones.deletion_success=Το οÏόσημο έχει διαγÏαφεί.
milestones.filter_sort.closest_due_date=ΠλησιέστεÏη παÏάδοση
milestones.filter_sort.furthest_due_date=ΑπώτεÏη παÏάδοση
@@ -1699,7 +1698,7 @@ wiki.file_revision=ΑναθεώÏηση Σελίδας
wiki.wiki_page_revisions=ΑναθεωÏήσεις Σελίδας Wiki
wiki.back_to_wiki=Πίσω στη σελίδα wiki
wiki.delete_page_button=ΔιαγÏαφή Σελίδας
-wiki.delete_page_notice_1=ΔιαγÏαφή της σελίδας wiki '%s' δεν μποÏεί να αναιÏεθεί. Συνέχεια;
+wiki.delete_page_notice_1=ΔιαγÏαφή της σελίδας wiki '%s' δεν μποÏεί να αναιÏεθεί. Συνέχεια
wiki.page_already_exists=ΥπάÏχει ήδη μια σελίδα wiki με το ίδιο όνομα.
wiki.reserved_page=Το όνομα σελίδας wiki '%s' είναι δεσμευμένο.
wiki.pages=Σελίδες
@@ -1796,7 +1795,7 @@ settings.hooks=Webhooks
settings.githooks=Git Hooks
settings.basic_settings=Βασικές Ρυθμίσεις
settings.mirror_settings=Ρυθμίσεις Ειδώλου
-settings.mirror_settings.docs=Ρυθμίστε το έÏγο σας για να ωθεί ή/και να Ï„Ïαβά αλλαγές σε/από άλλο αποθετήÏιο. Οι κλάδοι, οι ετικέτες και οι υποβολές θα συγχÏονίζονται αυτόματα. <a target="_blank" rel="noopener noreferrer" href="https://docs.gitea.io/en-us/repo-mirror/">Πώς μποÏÏŽ να καθÏεπτίσω τα αποθετήÏια;</a>
+settings.mirror_settings.docs=Ρυθμίστε το έÏγο σας για να ωθεί ή/και να Ï„Ïαβά αλλαγές σε/από άλλο αποθετήÏιο. Οι κλάδοι, οι ετικέτες και οι υποβολές θα συγχÏονίζονται αυτόματα. <a target="_blank" rel="noopener noreferrer" href="https://docs.gitea.io/en-us/repo-mirror/">Πώς μποÏÏŽ να καθÏεπτίσω τα αποθετήÏια
settings.mirror_settings.mirrored_repository=Είδωλο αποθετηÏίου
settings.mirror_settings.direction=ΚατεÏθυνση
settings.mirror_settings.direction.pull=Pull
@@ -1836,11 +1835,6 @@ settings.enable_timetracker=ΕνεÏγοποίηση ΚαταγÏαφής ΧÏÏŒ
settings.allow_only_contributors_to_track_time=Μόνο οι Συμμετέχοντες να ΚαταγÏάφουν ΧÏόνο
settings.pulls_desc=ΕνεÏγοποίηση Pull Requests στο ΑποθετήÏιο
settings.pulls.ignore_whitespace=Αγνόηση των Κενών ΧαÏακτήÏων στις ΣυγκÏοÏσεις
-settings.pulls.allow_merge_commits=ΕνεÏγοποίηση Υποβολών Συγχώνευσης
-settings.pulls.allow_rebase_merge=ΕνεÏγοποίηση Αλλαγής Βάσης για τις Υποβολές Συγχώνευσης
-settings.pulls.allow_rebase_merge_commit=ΕνεÏγοποίηση Αλλαγής Βάσης με Ïητές υποβολές συγχώνευσης (--no-ff)
-settings.pulls.allow_squash_commits=ΕνεÏγοποίηση Squashing για Υποβολές Συγχώνευσης
-settings.pulls.allow_manual_merge=ΕνεÏγοποίηση Σημείωσης του PR ως μη αυτόματα συγχωνευμένο
settings.pulls.enable_autodetect_manual_merge=ΕνεÏγοποίηση αυτόματης ανίχνευσης συγχώνευσης (Σημείωση: σε οÏισμένες ειδικές πεÏιπτώσεις, μποÏεί να Ï€ÏοκÏψουν εσφαλμένες κÏίσεις)
settings.pulls.allow_rebase_update=ΕνεÏγοποίηση της ενημέÏωσης του κλάδου του pull request μέσω rebase
settings.pulls.default_delete_branch_after_merge=ΔιαγÏαφή του κλάδου του pull request μετά τη συγχώνευση από Ï€Ïοεπιλογή
@@ -1881,7 +1875,7 @@ settings.transfer_notices_2=- Θα διατηÏήσετε την Ï€ÏόσβασÎ
settings.transfer_notices_3=- Εάν το αποθετήÏιο είναι ιδιωτικό και μεταβιβάζεται σε μεμονωμένο χÏήστη, αυτή η ενέÏγεια εξασφαλίζει ότι ο χÏήστης έχει τουλάχιστον άδεια ανάγνωσης (και αλλάζει τα δικαιώματα εάν είναι απαÏαίτητο).
settings.transfer_owner=Îέος Ιδιοκτήτης
settings.transfer_perform=Εκτέλεση ΜεταφοÏάς
-settings.transfer_started=Αυτό το αποθετήÏιο έχει επισημανθεί για μεταφοÏά και αναμένει επιβεβαίωση από το "%s"
+settings.transfer_started=`Αυτό το αποθετήÏιο έχει επισημανθεί για μεταφοÏά και αναμένει επιβεβαίωση από το "%s"`
settings.transfer_succeed=Το αποθετήÏιο έχει μεταφεÏθεί.
settings.signing_settings=Ρυθμίσεις Επαλήθευσης ΥπογÏαφής
settings.trust_model=Μοντέλο ΕμπιστοσÏνης ΥπογÏαφής
@@ -1916,7 +1910,7 @@ settings.add_collaborator_owner=Δεν είναι δυνατή η Ï€Ïοσθήκ
settings.add_collaborator_duplicate=Ο συνεÏγάτης έχει ήδη Ï€Ïοστεθεί σε αυτό το αποθετήÏιο.
settings.delete_collaborator=ΑφαίÏεση
settings.collaborator_deletion=ΑφαίÏεση ΣυνεÏγάτη
-settings.collaborator_deletion_desc=Η κατάÏγηση ενός συνεÏγάτη θα ανακαλέσει την Ï€Ïόσβασή τους σε αυτό το αποθετήÏιο. Συνέχεια;
+settings.collaborator_deletion_desc=Η κατάÏγηση ενός συνεÏγάτη θα ανακαλέσει την Ï€Ïόσβασή τους σε αυτό το αποθετήÏιο. Συνέχεια
settings.remove_collaborator_success=Ο συνεÏγάτης έχει αφαιÏεθεί.
settings.search_user_placeholder=Αναζήτηση χÏήστη…
settings.org_not_allowed_to_be_collaborator=Οι οÏγανισμοί δεν μποÏοÏν να Ï€ÏοστεθοÏν ως συνεÏγάτης.
@@ -1934,7 +1928,7 @@ settings.add_webhook=ΠÏοσθήκη Webhook
settings.add_webhook.invalid_channel_name=Το όνομα του ÎºÎ±Î½Î±Î»Î¹Î¿Ï Webhook δεν μποÏεί να είναι κενό και δεν μποÏεί να πεÏιέχει μόνο έναν χαÏακτήÏα #.
settings.hooks_desc=Τα Webhooks κάνουν αυτόματα αιτήσεις HTTP POST σε ένα διακομιστή όταν ενεÏγοποιοÏνται οÏισμένα γεγονότα στο Gitea. Διαβάστε πεÏισσότεÏα στον <a target="_blank" rel="noopener noreferrer" href="%s">οδηγό webhooks</a>.
settings.webhook_deletion=ΑφαίÏεση Webhook
-settings.webhook_deletion_desc=Η αφαίÏεση ενός webhook διαγÏάφει τις Ïυθμίσεις και το ιστοÏικό παÏαδόσεων. Συνέχεια;
+settings.webhook_deletion_desc=Η αφαίÏεση ενός webhook διαγÏάφει τις Ïυθμίσεις και το ιστοÏικό παÏαδόσεων. Συνέχεια
settings.webhook_deletion_success=Το webhook έχει αφαιÏεθεί.
settings.webhook.test_delivery=Δοκιμή ΠαÏάδοσης
settings.webhook.test_delivery_desc=Δοκιμάστε αυτό το webhook με ένα ψεÏτικο συμβάν.
@@ -2009,6 +2003,8 @@ settings.event_package=Πακέτο
settings.event_package_desc=Το πακέτο δημιουÏγήθηκε ή διαγÏάφηκε σε ένα αποθετήÏιο.
settings.branch_filter=ΦίλτÏο κλάδου
settings.branch_filter_desc=Λίστα επιτÏεπόμενων κλάδων για ωθήσεις, δημιουÏγία κλάδων και γεγονότα διαγÏαφής κλάδων, που οÏίζονται ως μοτίβο glob. Εάν είναι κενό ή <code>*</code>, αναφέÏονται συμβάντα για όλους τους κλάδους. Δείτε τη τεκμηÏίωση<a href="https://pkg.go.dev/github.com/gobwas/glob#Compile">github.com/gobwas/glob</a> για σÏνταξη. ΠαÏαδείγματα: <code>master</code>, <code>{master,release*}</code>.
+settings.authorization_header=Κεφαλίδα Authorization
+settings.authorization_header_desc=Αν υπάÏχει, θα Ï€Ïοστίθεται ως κεφαλίδα authorization στις αιτήσεις HTTP. ΠαÏαδείγματα: %s.
settings.active=ΕνεÏγό
settings.active_helper=Οι πληÏοφοÏίες σχετικά με τα γεγονότα που συμβαίνουν θα στέλνονται σε αυτό το URL webhook.
settings.add_hook_success=Έχει Ï€Ïοστεθεί το webhook.
@@ -2049,11 +2045,11 @@ settings.key_been_used=Ένα κλειδί διάθεσης με το ίδιο Ï
settings.key_name_used=Ένα κλειδί διάθεσης με το ίδιο όνομα υπάÏχει ήδη.
settings.add_key_success=Το κλειδί διάθεσης '%s' έχει Ï€Ïοστεθεί.
settings.deploy_key_deletion=ΑφαίÏεση ÎšÎ»ÎµÎ¹Î´Î¹Î¿Ï Î”Î¹Î¬Î¸ÎµÏƒÎ·Ï‚
-settings.deploy_key_deletion_desc=Η κατάÏγηση ενός κλειδί διάθεσης θα ανακαλέσει την Ï€Ïόσβασή του σε αυτό το αποθετήÏιο. Συνέχεια;
+settings.deploy_key_deletion_desc=Η κατάÏγηση ενός κλειδί διάθεσης θα ανακαλέσει την Ï€Ïόσβασή του σε αυτό το αποθετήÏιο. Συνέχεια
settings.deploy_key_deletion_success=Το κλειδί διάθεσης έχει αφαιÏεθεί.
settings.branches=Κλάδοι
settings.protected_branch=ΠÏοστασία Κλάδου
-settings.protected_branch_can_push=ΕπιτÏέψτε ώθηση;
+settings.protected_branch_can_push=ΕπιτÏέψτε ώθηση
settings.protected_branch_can_push_yes=ΜποÏείτε να ωθήσετε
settings.protected_branch_can_push_no=Δεν μποÏείτε να ωθήσετε
settings.branch_protection=ΠÏοστασία Κλάδου για το Κλάδο '<b>%s</b>'
@@ -2096,7 +2092,7 @@ settings.delete_protected_branch=ΑπενεÏγοποίηση Ï€Ïοστασία
settings.update_protect_branch_success=Η Ï€Ïοστασία κλάδου για τον κλάδο '%s' έχει ενημεÏωθεί.
settings.remove_protected_branch_success=Η Ï€Ïοστασία κλάδου για τον κλάδο '%s' έχει απενεÏγοποιηθεί.
settings.protected_branch_deletion=ΑπενεÏγοποίηση ΠÏοστασίας Κλάδου
-settings.protected_branch_deletion_desc=Η απενεÏγοποίηση της Ï€Ïοστασίας του κλάδου επιτÏέπει στους χÏήστες με άδεια εγγÏαφής να κάνουν push στον κλάδο. Συνέχεια;
+settings.protected_branch_deletion_desc=Η απενεÏγοποίηση της Ï€Ïοστασίας του κλάδου επιτÏέπει στους χÏήστες με άδεια εγγÏαφής να κάνουν push στον κλάδο. Συνέχεια
settings.block_rejected_reviews=ΦÏαγή συγχώνευσης αν υπάÏχουν αποÏÏιπτικές αξιολογήσεις
settings.block_rejected_reviews_desc=Η συγχώνευση δεν θα είναι δυνατή όταν οι αλλαγές ζητοÏνται από τους επίσημους εξεταστές, ακόμη και αν υπάÏχουν αÏκετές εγκÏίσεις.
settings.block_on_official_review_requests=ΦÏαγή συγχώνευσης σε επίσημες αιτήσεις αξιολόγησης
@@ -2123,7 +2119,6 @@ settings.bot_token=ΔιακÏιτικό Bot
settings.chat_id=ID Συνομιλίας
settings.matrix.homeserver_url=Homeserver URL
settings.matrix.room_id=ID Δωματίου
-settings.matrix.access_token=ΔιακÏιτικό ΠÏόσβασης
settings.matrix.message_type=ΤÏπος ΜηνÏματος
settings.archive.button=ΑÏχειοθέτηση ΑποθετηÏίου
settings.archive.header=ΑÏχειοθέτηση Î‘Ï…Ï„Î¿Ï Ï„Î¿Ï… ΑποθετηÏίου
@@ -2146,7 +2141,7 @@ settings.lfs_findcommits=ΕÏÏεση υποβολών
settings.lfs_lfs_file_no_commits=Δεν βÏέθηκαν υποβολές για αυτό το αÏχείο LFS
settings.lfs_noattribute=Αυτή η διαδÏομή δεν έχει λειτουÏγία κλειδώματος στον Ï€Ïοεπιλεγμένο κλάδο
settings.lfs_delete=ΔιαγÏαφή αÏχείου LFS με το OID %s
-settings.lfs_delete_warning=Η διαγÏαφή ενός αÏχείου LFS μποÏεί να Ï€Ïοκαλέσει σφάλματα 'object does not exist' κατά την ολοκλήÏωση του checkout. ΣίγουÏα;
+settings.lfs_delete_warning=Η διαγÏαφή ενός αÏχείου LFS μποÏεί να Ï€Ïοκαλέσει σφάλματα 'object does not exist' κατά την ολοκλήÏωση του checkout. ΣίγουÏα
settings.lfs_findpointerfiles=ΕÏÏεση αÏχείων δείκτη
settings.lfs_locks=Κλειδώματα
settings.lfs_invalid_locking_path=Μη έγκυÏη διαδÏομή: %s
@@ -2252,9 +2247,9 @@ release.edit_release=ΕνημέÏωση ΚυκλοφοÏίας
release.delete_release=ΔιαγÏαφή ΚυκλοφοÏίας
release.delete_tag=ΔιαγÏαφή Ετικέτας
release.deletion=ΔιαγÏαφή ΚυκλοφοÏίας
-release.deletion_desc=ΔιαγÏαφή μιας έκδοσης την αφαιÏεί μόνο από Gitea. Ετικέτες, πεÏιεχόμενα αποθετηÏίου και ιστοÏικό παÏαμένουν αμετάβλητα. Συνέχεια;
+release.deletion_desc=ΔιαγÏαφή μιας έκδοσης την αφαιÏεί μόνο από Gitea. Ετικέτες, πεÏιεχόμενα αποθετηÏίου και ιστοÏικό παÏαμένουν αμετάβλητα. Συνέχεια
release.deletion_success=Η κυκλοφοÏία έχει διαγÏαφεί.
-release.deletion_tag_desc=Θα διαγÏάψει αυτή την ετικέτα από το αποθετήÏιο. Τα πεÏιεχόμενα του αποθετηÏίου και το ιστοÏικό παÏαμένουν αμετάβλητα. Συνέχεια;
+release.deletion_tag_desc=Θα διαγÏάψει αυτή την ετικέτα από το αποθετήÏιο. Τα πεÏιεχόμενα του αποθετηÏίου και το ιστοÏικό παÏαμένουν αμετάβλητα. Συνέχεια
release.deletion_tag_success=Η ετικέτα έχει διαγÏαφεί.
release.tag_name_already_exist=ΥπάÏχει ήδη μια έκδοση με αυτό το όνομα ετικέτας.
release.tag_name_invalid=Το όνομα της ετικέτας δεν είναι έγκυÏο.
@@ -2271,7 +2266,7 @@ branch.already_exists=Ένας κλάδος με όνομα '%s' υπάÏχει
branch.delete_head=ΔιαγÏαφή
branch.delete=ΔιαγÏαφή του Κλάδου '%s'
branch.delete_html=ΔιαγÏαφή Κλάδου
-branch.delete_desc=Η διαγÏαφή του κλάδου είναι μόνιμη. <strong>ΔΕΠΜΠΟΡΕΙ</strong> να αναιÏεθεί. Συνέχεια;
+branch.delete_desc=Η διαγÏαφή του κλάδου είναι μόνιμη. <strong>ΔΕΠΜΠΟΡΕΙ</strong> να αναιÏεθεί. Συνέχεια
branch.deletion_success=Ο κλάδος '%s' έχει διαγÏαφεί.
branch.deletion_failed=Αποτυχία διαγÏαφής του κλάδου '%s'.
branch.delete_branch_has_new_commits=Ο κλάδος '%s' δεν μποÏεί να διαγÏαφεί επειδή έχουν Ï€Ïοστεθεί νέες υποβολές μετά τη συγχώνευση.
@@ -2322,8 +2317,9 @@ org_full_name_holder=ΠλήÏες Όνομα ΟÏγανισμοÏ
org_name_helper=Τα ονόματα οÏγανισμών θα Ï€Ïέπει να είναι σÏντομα και εÏκολα στην απομνημόνευση.
create_org=ΔημιουÏγία ΟÏγανισμοÏ
repo_updated=ΕνημεÏώθηκε
-people=Άτομα
+members=Μέλη
teams=Ομάδες
+code=Κώδικας
lower_members=μέλη
lower_repositories=αποθετήÏια
create_new_team=Îέα Ομάδα
@@ -2366,7 +2362,7 @@ settings.delete_account=ΔιαγÏαφή Î‘Ï…Ï„Î¿Ï Î¤Î¿Ï… ΟÏγανισμοÏ
settings.delete_prompt=Ο οÏγανισμός θα αφαιÏεθεί οÏιστικά. Αυτό το <strong>ΔΕΠΜΠΟΡΕΙ</strong> να αναιÏεθεί!
settings.confirm_delete_account=Επιβεβαίωση ΔιαγÏαφής
settings.delete_org_title=ΔιαγÏαφή ΟÏγανισμοÏ
-settings.delete_org_desc=Αυτός ο οÏγανισμός θα διαγÏαφεί οÏιστικά. Συνέχεια;
+settings.delete_org_desc=Αυτός ο οÏγανισμός θα διαγÏαφεί οÏιστικά. Συνέχεια
settings.hooks_desc=ΠÏοσθήκη webhooks που θα ενεÏγοποιοÏνται για <strong>όλα τα αποθετήÏια</strong> κάτω από αυτό τον οÏγανισμό.
settings.labels_desc=ΠÏοσθήκη σημάτων που μποÏοÏν να χÏησιμοποιηθοÏν σε ζητήματα για <strong>όλα τα αποθετήÏια</strong> κάτω από αυτό τον οÏγανισμό.
@@ -2380,15 +2376,15 @@ members.member_role=Ρόλος Μέλους:
members.owner=Ιδιοκτήτης
members.member=Μέλος
members.remove=ΑφαίÏεση
-members.remove.detail=ΑφαιÏέστε το %[1]s από %[2]s;
+members.remove.detail=ΑφαιÏέστε το %[1]s από %[2]s
members.leave=ΑποχώÏηση
-members.leave.detail=ΑποχώÏηση από %s;
+members.leave.detail=ΑποχώÏηση από %s
members.invite_desc=ΠÏοσθέστε ένα νέο μέλος στο %s:
members.invite_now=ΠÏόσκληση ΤώÏα
teams.join=Συμμετοχή
teams.leave=ΑποχώÏηση
-teams.leave.detail=ΑποχώÏηση από %s;
+teams.leave.detail=ΑποχώÏηση από %s
teams.can_create_org_repo=ΔημιουÏγία αποθετηÏίων
teams.can_create_org_repo_helper=Τα μέλη μποÏοÏν να δημιουÏγήσουν νέα αποθετήÏια στον οÏγανισμό. Ο δημιουÏγός θα αποκτήσει Ï€Ïόσβαση διαχειÏιστή στο νέο αποθετήÏιο.
teams.none_access=Καμία ΠÏόσβαση
@@ -2411,7 +2407,7 @@ teams.add_team_member=ΠÏοσθήκη Μέλους Ομάδας
teams.invite_team_member=ΠÏόσκληση στο %s
teams.invite_team_member.list=ΕκκÏεμείς ΠÏοσκλήσεις
teams.delete_team_title=ΔιαγÏαφή Ομάδας
-teams.delete_team_desc=Η διαγÏαφή μιας ομάδας ανακαλεί τη Ï€Ïόσβαση στο αποθετήÏιο από τα μέλη της. Συνέχεια;
+teams.delete_team_desc=Η διαγÏαφή μιας ομάδας ανακαλεί τη Ï€Ïόσβαση στο αποθετήÏιο από τα μέλη της. Συνέχεια
teams.delete_team_success=Η ομάδα έχει διαγÏαφεί.
teams.read_permission_desc=Αυτή η ομάδα χοÏηγεί Ï€Ïόσβαση <strong>Ανάγνωσης</strong>: τα μέλη μποÏοÏν να δουν και να κλωνοποιήσουν τα αποθετήÏια της ομάδας.
teams.write_permission_desc=Αυτή η ομάδα χοÏηγεί Ï€Ïόσβαση <strong>ΕγγÏαφής</strong>: τα μέλη μποÏοÏν να διαβάσουν και να κάνουν push στα αποθετήÏια της ομάδας.
@@ -2596,7 +2592,7 @@ emails.updated=Το email ενημεÏώθηκε
emails.not_updated=Αποτυχία ενημέÏωσης της ζητοÏμενης διεÏθυνσης email: %v
emails.duplicate_active=Αυτή η διεÏθυνση email είναι ήδη ενεÏγή σε διαφοÏετικό χÏήστη.
emails.change_email_header=ΕνημέÏωση Ιδιοτήτων Email
-emails.change_email_text=Είστε βέβαιοι ότι θέλετε να ενημεÏώσετε αυτή τη διεÏθυνση email;
+emails.change_email_text=Είστε βέβαιοι ότι θέλετε να ενημεÏώσετε αυτή τη διεÏθυνση email
orgs.org_manage_panel=ΔιαχείÏιση ΟÏγανισμοÏ
orgs.name=Όνομα
@@ -2727,9 +2723,9 @@ auths.tips.oauth2.general=Ταυτοποίηση OAuth2
auths.tips.oauth2.general.tip=Κατά την εγγÏαφή νέας ταυτοποίησης Ï„Ïπου OAuth2, το URL κλήσης/ανακατεÏθυνσης Ï€Ïέπει να είναι: <host>/user/oauth2/<Authentication Name>/callback
auths.tip.oauth2_provider=ΠάÏοχος OAuth2
auths.tip.bitbucket=ΚαταχωÏήστε ένα νέο καταναλωτή OAuth στο https://bitbucket.org/account/user/<your username>/oauth-consumers/new και Ï€Ïοσθέστε το δικαίωμα 'Account' - 'Read'
-auths.tip.nextcloud=ΚαταχωÏήστε ένα νέο καταναλωτή OAuth στην υπηÏεσία σας χÏησιμοποιώντας το παÏακάτω Î¼ÎµÎ½Î¿Ï "Settings -> Security -> OAuth 2.0 client"
+auths.tip.nextcloud=`ΚαταχωÏήστε ένα νέο καταναλωτή OAuth στην υπηÏεσία σας χÏησιμοποιώντας το παÏακάτω Î¼ÎµÎ½Î¿Ï "Settings -> Security -> OAuth 2.0 client"`
auths.tip.dropbox=ΔημιουÏγήστε μια νέα εφαÏμογή στο https://www.dropbox.com/developers/apps
-auths.tip.facebook=ΚαταχωÏήστε μια νέα εφαÏμογή στο https://developers.facebook.com/apps και Ï€Ïοσθέστε το Ï€Ïοϊόν "Facebook Login"
+auths.tip.facebook=`ΚαταχωÏήστε μια νέα εφαÏμογή στο https://developers.facebook.com/apps και Ï€Ïοσθέστε το Ï€Ïοϊόν "Facebook Login"`
auths.tip.github=ΚαταχωÏήστε μια νέα εφαÏμογή OAuth στο https://github.com/settings/applications/new
auths.tip.gitlab=ΚαταχωÏήστε μια νέα εφαÏμογή στο https://gitlab.com/profile/applications
auths.tip.google_plus=Αποκτήστε τα διαπιστευτήÏια πελάτη OAuth2 από την κονσόλα API της Google στο https://console.developers.google.com/
@@ -2737,7 +2733,7 @@ auths.tip.openid_connect=ΧÏησιμοποιήστε το OpenID Connect Discov
auths.tip.twitter=Πηγαίνετε στο https://dev.twitter.com/apps, δημιουÏγήστε μια εφαÏμογή και βεβαιωθείτε ότι η επιλογή “Allow this application to be used to Sign in with Twitter†είναι ενεÏγοποιημένη
auths.tip.discord=ΚαταχωÏήστε μια νέα εφαÏμογή στο https://discordapp.com/developers/applications/me
auths.tip.gitea=ΚαταχωÏήστε μια νέα εφαÏμογή OAuth2. Ο οδηγός μποÏεί να βÏεθεί στο https://docs.gitea.io/en-us/oauth2-provider/
-auths.tip.yandex=ΔημιουÏγήστε μια νέα εφαÏμογή στο https://oauth.yandex.com/client/new. Επιλέξτε τα ακόλουθα δικαιώματα από την ενότητα "Yandex.Passport API": "Access to email address", "Access to user avatar" και "Access to username, first name and surname, gender"
+auths.tip.yandex=`ΔημιουÏγήστε μια νέα εφαÏμογή στο https://oauth.yandex.com/client/new. Επιλέξτε τα ακόλουθα δικαιώματα από την ενότητα "Yandex.Passport API": "Access to email address", "Access to user avatar" και "Access to username, first name and surname, gender"`
auths.tip.mastodon=Εισαγάγετε ένα Ï€ÏοσαÏμομένο URL για την υπηÏεσία mastodon με την οποία θέλετε να πιστοποιήσετε (ή να χÏησιμοποιήσετε την Ï€Ïοεπιλεγμένη)
auths.edit=ΕπεξεÏγασία Πηγής Ταυτοποίησης
auths.activated=Αυτή η Πηγή Ταυτοποίησης είναι ΕνεÏγοποιημένη
@@ -2746,7 +2742,7 @@ auths.update_success=Η πηγή ταυτοποίησης έχει ενημεÏÏ
auths.update=ΕνημέÏωση Πηγής Ταυτοποίησης
auths.delete=ΔιαγÏαφή Πηγής Ταυτοποίησης
auths.delete_auth_title=ΔιαγÏαφή Πηγής Ταυτοποίησης
-auths.delete_auth_desc=Η διαγÏαφή μιας πηγής ταυτοποίησης αποτÏέπει τους χÏήστες να τη χÏησιμοποιοÏν για να συνδεθοÏν. Συνέχεια;
+auths.delete_auth_desc=Η διαγÏαφή μιας πηγής ταυτοποίησης αποτÏέπει τους χÏήστες να τη χÏησιμοποιοÏν για να συνδεθοÏν. Συνέχεια
auths.still_in_used=Η πηγή ταυτοποίησης είναι ακόμα σε χÏήση. ΜετατÏέψτε ή διαγÏάψτε χÏηστών που χÏησιμοποιοÏν αυτήν την πηγή Ï€Ïώτα.
auths.deletion_success=Η πηγή ταυτοποίησης έχει διαγÏαφεί.
auths.login_source_exist=Η πηγή ταυτοποίησης '%s' υπάÏχει ήδη.
@@ -2908,7 +2904,7 @@ monitor.execute_time=ΧÏόνος Εκτέλεσης
monitor.last_execution_result=Αποτέλεσμα
monitor.process.cancel=ΑκÏÏωση διαδικασίας
monitor.process.cancel_desc=Η ακÏÏωση μιας διαδικασίας μποÏεί να Ï€Ïοκαλέσει απώλεια δεδομένων
-monitor.process.cancel_notices=ΑκÏÏωση: <strong>%s</strong>;
+monitor.process.cancel_notices=ΑκÏÏωση: <strong>%s</strong>
monitor.process.children=ΘυγατÏικές
monitor.queues=ΟυÏές
monitor.queue=ΟυÏά: %s
@@ -2968,12 +2964,11 @@ monitor.queue.pool.workers.title=ΕνεÏγές Ομάδες ΕÏγατών
monitor.queue.pool.workers.none=Καμία ομάδα εÏγατών.
monitor.queue.pool.cancel=ΤεÏματισμός Ομάδας ΕÏγατών
monitor.queue.pool.cancelling=ΤεÏματισμός Ομάδας ΕÏγατών
-monitor.queue.pool.cancel_notices=ΤεÏματισμός αυτής της ομάδας των %s εÏγατών;
+monitor.queue.pool.cancel_notices=ΤεÏματισμός αυτής της ομάδας των %s εÏγατών
monitor.queue.pool.cancel_desc=Αφήνοντας μια ουÏά χωÏίς καμία ομάδα εÏγατών μποÏεί να Ï€Ïοκληθεί μπλοκάÏισμα των αιτημάτων επ 'αόÏιστον.
notices.system_notice_list=Ειδοποιήσεις Συστήματος
notices.view_detail_header=ΠÏοβολή ΛεπτομεÏειών Ειδοποίησης
-notices.actions=ΕνέÏγειες
notices.select_all=Επιλογή Όλων
notices.deselect_all=Αποεπιλογή Όλων
notices.inverse_selection=ΑντιστÏοφή Επιλογής
@@ -2999,6 +2994,7 @@ reopen_pull_request=`άνοιξε ξανά το pull request <a href="%[1]s">%[3
comment_issue=`σχολίασε το ζήτημα <a href="%[1]s">%[3]s#%[2]s</a>`
comment_pull=`σχολίασε στο pull request <a href="%[1]s">%[3]s#%[2]s</a>`
merge_pull_request=`συγχώνευσε το pull request <a href="%[1]s">%[3]s#%[2]s</a>`
+auto_merge_pull_request=`αυτόματη συγχώνευση του pull request <a href="%[1]s">%[3]s#%[2]s</a>`
transfer_repo=μετέφεÏε το αποθετήÏιο <code>%s</code> σε <a href="%s">%s</a>
push_tag=ώθησε την ετικέτα <a href="%[2]s">%[3]s</a> σε <a href="%[1]s">%[4]s</a>
delete_tag=διέγÏαψε την ετικέτα %[2]s από <a href="%[1]s">%[3]s</a>
@@ -3081,7 +3077,7 @@ title=Πακέτα
desc=ΔιαχείÏιση πακέτων μητÏώου.
empty=Δεν υπάÏχουν πακέτα ακόμα.
empty.documentation=Για πεÏισσότεÏες πληÏοφοÏίες σχετικά με το μητÏώο πακέτων, ανατÏέξτε <a target="_blank" rel="noopener noreferrer" href="https://docs.gitea.io/en-us/packages/overview">στην τεκμηÏίωση</a>.
-empty.repo=Μήπως ανεβάσατε ένα πακέτο, αλλά δεν εμφανίζεται εδώ; Πηγαίνετε στις <a href="%[1]s">Ïυθμίσεις πακέτων</a> και συνδέστε το σε αυτό το αποθετήÏιο.
+empty.repo=Μήπως ανεβάσατε ένα πακέτο, αλλά δεν εμφανίζεται εδώ
filter.type=ΤÏπος
filter.type.all=Όλα
filter.no_result=Το φίλτÏο δεν παÏήγαγε αποτελέσματα.
@@ -3104,6 +3100,7 @@ versions.on=τη
versions.view_all=ΠÏοβολή όλων
dependency.id=ID
dependency.version=Έκδοση
+chef.install=Για να εγκαταστήσετε το πακέτο, εκτελέστε την ακόλουθη εντολή:
composer.registry=Ρυθμίστε αυτό το μητÏώο στο αÏχείο <code>~/.composer/config.json</code>:
composer.install=Για να εγκαταστήσετε το πακέτο χÏησιμοποιώντας το Composer, εκτελέστε την ακόλουθη εντολή:
composer.documentation=Για πεÏισσότεÏες πληÏοφοÏίες σχετικά με το μητÏώο Composer, διαβάστε <a target="_blank" rel="noopener noreferrer" href="https://docs.gitea.io/en-us/packages/composer/">τη τεκμηÏίωση</a>.
@@ -3115,8 +3112,6 @@ conan.install=Για να εγκαταστήσετε το πακέτο χÏησÎ
conan.documentation=Για πεÏισσότεÏες πληÏοφοÏίες σχετικά με το μητÏώο Conan, ανατÏέξτε <a target="_blank" rel="noopener noreferrer" href="https://docs.gitea.io/en-us/packages/conan/">στην τεκμηÏίωση</a>.
container.details.type=ΤÏπος Εικόνας
container.details.platform=ΠλατφόÏμα
-container.details.repository_site=Ιστοσελίδα ΑποθετηÏίου
-container.details.documentation_site=Ιστοσελίδα ΤεκμηÏίωσης
container.pull=Κατεβάστε την εικόνα από τη γÏαμμή εντολών:
container.digest=ΣÏνοψη:
container.documentation=Για πεÏισσότεÏες πληÏοφοÏίες σχετικά με το μητÏώο για Container, ανατÏέξτε <a target="_blank" rel="noopener noreferrer" href="https://docs.gitea.io/en-us/packages/container/">στην τεκμηÏίωση</a>.
@@ -3150,8 +3145,6 @@ npm.dependencies.optional=ΠÏοαιÏετικές ΕξαÏτήσεις
npm.details.tag=Σήμανση
pub.install=Για να εγκαταστήσετε το πακέτο μέσω του Dart, εκτελέστε την ακόλουθη εντολή:
pub.documentation=Για πεÏισσότεÏες πληÏοφοÏίες σχετικά με το μητÏώο Pub, ανατÏέξτε <a target="_blank" rel="noopener noreferrer" href="https://docs.gitea.io/en-us/packages/pub/">στην τεκμηÏίωση</a>.
-pub.details.repository_site=Ιστοσελίδα ΑποθετηÏίου
-pub.details.documentation_site=Ιστοσελίδα ΤεκμηÏίωσης
pypi.requires=Απαιτεί Python
pypi.install=Για να εγκαταστήσετε το πακέτο χÏησιμοποιώντας το pip, εκτελέστε την ακόλουθη εντολή:
pypi.documentation=Για πεÏισσότεÏες πληÏοφοÏίες σχετικά με το μητÏώο PyPI, ανατÏέξτε <a target="_blank" rel="noopener noreferrer" href="https://docs.gitea.io/en-us/packages/pypi/">στην τεκμηÏίωση</a>.
@@ -3172,7 +3165,29 @@ settings.link.success=Ο σÏνδεσμος αποθετηÏίου ενημεÏÏ
settings.link.error=Αποτυχία ενημέÏωσης συνδέσμου αποθετηÏίου.
settings.delete=ΔιαγÏαφή πακέτου
settings.delete.description=Η διαγÏαφή ενός πακέτου είναι μόνιμη και δεν μποÏεί να αναιÏεθεί.
-settings.delete.notice=ΠÏόκειται να διαγÏάψετε %s (%s). Αυτή η λειτουÏγία είναι μη αναστÏέψιμη, είστε σίγουÏοι;
+settings.delete.notice=ΠÏόκειται να διαγÏάψετε %s (%s). Αυτή η λειτουÏγία είναι μη αναστÏέψιμη, είστε σίγουÏοι
settings.delete.success=Το πακέτο έχει διαγÏαφεί.
settings.delete.error=Αποτυχία διαγÏαφής του πακέτου.
+owner.settings.cleanuprules.enabled=ΕνεÏγοποιημένο
+
+[secrets]
+value=Τιμή
+name=Όνομα
+
+[actions]
+
+
+
+runners.id=ID
+runners.name=Όνομα
+runners.owner_type=ΤÏπος
+runners.description=ΠεÏιγÏαφή
+runners.labels=Ετικέτες
+runners.task_list.run=Εκτέλεση
+runners.task_list.repository=ΑποθετήÏιο
+runners.task_list.commit=Υποβολή
+runners.status.active=ΕνεÏγό
+
+runs.commit=Υποβολή
+
diff --git a/options/locale/locale_en-US.ini b/options/locale/locale_en-US.ini
index 2109950ca..dccf18433 100644
--- a/options/locale/locale_en-US.ini
+++ b/options/locale/locale_en-US.ini
@@ -237,7 +237,6 @@ internal_token_failed = Failed to generate internal token: %v
secret_key_failed = Failed to generate secret key: %v
save_config_failed = Failed to save configuration: %v
invalid_admin_setting = Administrator account setting is invalid: %v
-install_success = Welcome! Thank you for choosing Gitea. Have fun and take care!
invalid_log_root_path = The log path is invalid: %v
default_keep_email_private = Hide Email Addresses by Default
default_keep_email_private_popup = Hide email addresses of new user accounts by default.
@@ -248,6 +247,7 @@ default_enable_timetracking_popup = Enable time tracking for new repositories by
no_reply_address = Hidden Email Domain
no_reply_address_helper = Domain name for users with a hidden email address. For example, the username 'joe' will be logged in Git as 'joe@noreply.example.org' if the hidden email domain is set to 'noreply.example.org'.
password_algorithm = Password Hash Algorithm
+invalid_password_algorithm = Invalid password hash algorithm
password_algorithm_helper = Set the password hashing algorithm. Algorithms have differing requirements and strength. `argon2` whilst having good characteristics uses a lot of memory and may be inappropriate for small systems.
enable_update_checker = Enable Update Checker
enable_update_checker_helper = Checks for new version releases periodically by connecting to gitea.io.
@@ -821,6 +821,8 @@ remove_account_link = Remove Linked Account
remove_account_link_desc = Removing a linked account will revoke its access to your Gitea account. Continue?
remove_account_link_success = The linked account has been removed.
+hooks.desc = Add webhooks which will be triggered for <strong>all repositories</strong> owned by this user.
+
orgs_none = You are not a member of any organizations.
repos_none = You do not own any repositories
@@ -1470,6 +1472,7 @@ issues.error_removing_due_date = "Failed to remove the due date."
issues.push_commit_1 = "added %d commit %s"
issues.push_commits_n = "added %d commits %s"
issues.force_push_codes = `force-pushed %[1]s from <a class="ui sha" href="%[3]s"><code>%[2]s</code></a> to <a class="ui sha" href="%[5]s"><code>%[4]s</code></a> %[6]s`
+issues.force_push_compare = Compare
issues.due_date_form = "yyyy-mm-dd"
issues.due_date_form_add = "Add due date"
issues.due_date_form_edit = "Edit"
@@ -2287,6 +2290,8 @@ release.edit_subheader = Releases organize project versions.
release.tag_name = Tag name
release.target = Target
release.tag_helper = Choose an existing tag or create a new tag.
+release.tag_helper_new = New tag. This tag will be created from the target.
+release.tag_helper_existing = Existing tag.
release.title = Title
release.content = Content
release.prerelease_desc = Mark as Pre-Release
@@ -2807,6 +2812,8 @@ auths.still_in_used = The authentication source is still in use. Convert or dele
auths.deletion_success = The authentication source has been deleted.
auths.login_source_exist = The authentication source '%s' already exists.
auths.login_source_of_type_exist = An authentication source of this type already exists.
+auths.unable_to_initialize_openid = Unable to initialize OpenID Connect Provider: %s
+auths.invalid_openIdConnectAutoDiscoveryURL = Invalid Auto Discovery URL (this must be a valid URL starting with http:// or https://)
config.server_config = Server Configuration
config.app_name = Site Title
diff --git a/options/locale/locale_es-ES.ini b/options/locale/locale_es-ES.ini
index 3a16819c3..f104d3c49 100644
--- a/options/locale/locale_es-ES.ini
+++ b/options/locale/locale_es-ES.ini
@@ -41,7 +41,7 @@ webauthn_use_twofa=Utilice un código de doble factor desde su teléfono móvil
webauthn_error=No se pudo leer su llave de seguridad.
webauthn_unsupported_browser=Su navegador no soporta actualmente WebAuthn.
webauthn_error_unknown=Ha ocurrido un error desconocido. Por favor, inténtelo de nuevo.
-webauthn_error_insecure=WebAuthn sólo soporta conexiones seguras. Para probar sobre HTTP, puede utilizar el origen "localhost" o "127.0.0.1"
+webauthn_error_insecure=`WebAuthn sólo soporta conexiones seguras. Para probar sobre HTTP, puede utilizar el origen "localhost" o "127.0.0.1"`
webauthn_error_unable_to_process=El servidor no pudo procesar su solicitud.
webauthn_error_duplicated=La clave de seguridad no está permitida para esta solicitud. Por favor, asegúrese de que la clave no está ya registrada.
webauthn_error_empty=Debe establecer un nombre para esta clave.
@@ -57,7 +57,6 @@ new_mirror=Nueva réplica
new_fork=Nuevo fork de repositorio
new_org=Nueva organización
new_project=Nuevo Proyecto
-new_project_board=Nuevo tablón de proyecto
manage_org=Administrar organizaciones
admin_panel=Administración del sitio
account_settings=Configuraciones de la cuenta
@@ -86,6 +85,9 @@ remove=Eliminar
remove_all=Eliminar todos
edit=Editar
+enabled=Activo
+disabled=Desactivado
+
copy=Copiar
copy_url=Copiar URL
copy_branch=Copiar nombre de rama
@@ -106,6 +108,8 @@ never=Nunca
rss_feed=Fuentes RSS
+[aria]
+
[filter]
string.asc=A - Z
string.desc=Z - A
@@ -226,7 +230,6 @@ internal_token_failed=Fallo al generar el INTERNAL_TOKEN: %v
secret_key_failed=Fallo al generar el SECRET_KEY: %v
save_config_failed=Error al guardar la configuración: %v
invalid_admin_setting=La configuración de la cuenta de administración no es válida: %v
-install_success=¡Bienvenido! Gracias por elegir Gitea. ¡Diviértete y cuidate!
invalid_log_root_path=La ruta para los registros no es válida: %v
default_keep_email_private=Ocultar direcciones de correo electrónico por defecto
default_keep_email_private_popup=Ocultar direcciones de correo electrónico de nuevas cuentas de usuario por defecto.
@@ -252,7 +255,7 @@ view_home=Ver %s
search_repos=Buscar un repositorio…
filter=Otros filtros
filter_by_team_repositories=Filtrar por repositorios de equipo
-feed_of=Suministro de noticias de "%s"
+feed_of=`Suministro de noticias de "%s"`
show_archived=Archivado
show_both_archived_unarchived=Mostrar respositorios archivados y desarchivados
@@ -504,11 +507,11 @@ invalid_ssh_principal=Principal no válido: %s
unable_verify_ssh_key=No se puede verificar su clave SSH: compruebe si contiene errores.
auth_failed=Autenticación fallo: %v
-still_own_repo=Su cuenta posee uno o más repositorios; elimine o transfiera primero.
-still_has_org=Su cuenta es miembro de una o más organizaciones; déjalas primero.
-still_own_packages=Su cuenta posee uno o más repositorios; elimine o transfiera primero.
-org_still_own_repo=Esta organización todavía es dueña de uno o más repositorios; elimínelos o transfiéralos primero.
-org_still_own_packages=Esta organización todavía es dueña de uno o más repositorios; elimínelos o transfiéralos primero.
+still_own_repo=Su cuenta posee uno o más repositorios
+still_has_org=Su cuenta es miembro de una o más organizaciones
+still_own_packages=Su cuenta posee uno o más repositorios
+org_still_own_repo=Esta organización todavía es dueña de uno o más repositorios
+org_still_own_packages=Esta organización todavía es dueña de uno o más repositorios
target_branch_not_exist=La rama de destino no existe
@@ -799,6 +802,7 @@ remove_account_link=Eliminar cuenta vinculada
remove_account_link_desc=Eliminar una cuenta vinculada revocará su acceso a su cuenta de Gitea. ¿Continuar?
remove_account_link_success=La cuenta vinculada ha sido eliminada.
+
orgs_none=No eres miembro de ninguna organización.
repos_none=No posees ningún repositorio
@@ -910,9 +914,9 @@ delete_preexisting_success=Eliminó archivos no adoptados en %s
blame_prior=Ver la culpa antes de este cambio
transfer.accept=Aceptar transferencia
-transfer.accept_desc=Transferir a "%s"
+transfer.accept_desc=`Transferir a "%s"`
transfer.reject=Rechazar transferencia
-transfer.reject_desc=Cancelar transferencia a "%s"
+transfer.reject_desc=`Cancelar transferencia a "%s"`
transfer.no_permission_to_accept=No tiene permiso para aceptar
transfer.no_permission_to_reject=No tienes permiso para rechazar
@@ -1161,7 +1165,6 @@ commits.signed_by_untrusted_user_unmatched=Firmado por un usuario no fiable que
commits.gpg_key_id=ID de clave GPG
commits.ssh_key_fingerprint=Huella clave SSH
-commit.actions=Acciones
commit.revert=Revertir
commit.revert-header=Revertir: %s
commit.revert-content=Seleccionar rama en la que revertir:
@@ -1194,19 +1197,11 @@ projects.type.bug_triage=Prueba de error
projects.template.desc=Plantilla del proyecto
projects.template.desc_helper=Seleccione una plantilla de proyecto para empezar
projects.type.uncategorized=Sin categorizar
-projects.board.edit=Editar tablón
-projects.board.edit_title=Nuevo Nombre del Tablón
-projects.board.new_title=Nuevo Nombre del Tablón
-projects.board.new_submit=Enviar
-projects.board.new=Nuevo tablón
-projects.board.set_default=Establecer como predeterminado
-projects.board.set_default_desc=Establecer este tablero como predeterminado para incidencias no categorizadas y pulls
-projects.board.delete=Eliminar tablón
-projects.board.deletion_desc=Eliminar un tablón de proyecto mueve todas las incidencias relacionadas a 'Sin categorizar'. ¿Continuar?
-projects.board.color=Color
+projects.column.edit_title=Nombre
+projects.column.new_title=Nombre
+projects.column.color=Color
projects.open=Abrir
projects.close=Cerrar
-projects.board.assigned_to=Asignado a
issues.desc=Organizar los informes de fallos, tareas e hitos.
issues.filter_assignees=Filtrar asignado
@@ -1282,6 +1277,8 @@ issues.filter_label_exclude=`Usa <code>alt</code> + <code>clic/enter</code> para
issues.filter_label_no_select=Todas las etiquetas
issues.filter_milestone=Milestone
issues.filter_milestone_no_select=Todos los hitos
+issues.filter_project=Proyecto
+issues.filter_project_none=Ningún proyecto
issues.filter_assignee=Asignada a
issues.filter_assginee_no_select=Todos los asignados
issues.filter_poster=Autor
@@ -1433,6 +1430,7 @@ issues.error_removing_due_date=Fallo al eliminar la fecha de vencimiento.
issues.push_commit_1=añadido %d commit %s
issues.push_commits_n=añadido %d commits %s
issues.force_push_codes=`hizo push forzado %[1]s de <a class="ui sha" href="%[3]s"><code>%[2]s</code></a> a <a class="ui sha" href="%[5]s"><code>%[4]s</code></a> %[6]s`
+issues.force_push_compare=Comparar
issues.due_date_form=aaaa-mm-dd
issues.due_date_form_add=Añadir fecha de vencimiento
issues.due_date_form_edit=Editar
@@ -1836,11 +1834,6 @@ settings.enable_timetracker=Habilitar gestor de tiempo
settings.allow_only_contributors_to_track_time=Deje que solo los colaboradores hagan un seguimiento del tiempo
settings.pulls_desc=Activar Pull Requests para este repositorio
settings.pulls.ignore_whitespace=Ignorar espacios en blanco en conflictos
-settings.pulls.allow_merge_commits=Activar Commit Fusionar
-settings.pulls.allow_rebase_merge=Activar Rebase de los commits fusionados
-settings.pulls.allow_rebase_merge_commit=Activar Rebase con commits explícitos de fusión (--no-ff)
-settings.pulls.allow_squash_commits=Activar Squash en los commits fusionados
-settings.pulls.allow_manual_merge=Habilitar marcar PR como fusionado manualmente
settings.pulls.enable_autodetect_manual_merge=Habilitar la autodetección de los commits fusionado manualmente (Nota: en algunos casos especiales, pueden producirse errores de apreciación)
settings.pulls.allow_rebase_update=Habilitar la actualización de la rama de Pull Request por rebase
settings.pulls.default_delete_branch_after_merge=Eliminar por defecto la rama de pull request después de fusionar
@@ -1881,7 +1874,7 @@ settings.transfer_notices_2=- Mantendrá el acceso al repositorio si lo transfie
settings.transfer_notices_3=- Si el repositorio es privado y se transfiere a un usuario individual, esta acción se asegura de que el usuario tenga al menos permisos de lectura (y cambie los permisos si es necesario).
settings.transfer_owner=Nuevo Propietario
settings.transfer_perform=Realizar transferencia
-settings.transfer_started=Este repositorio ha sido marcado para transferencia y espera confirmación de "%s"
+settings.transfer_started=`Este repositorio ha sido marcado para transferencia y espera confirmación de "%s"`
settings.transfer_succeed=El repositorio ha sido transferido.
settings.signing_settings=Configuración de verificación de firmas
settings.trust_model=Modelo de confianza de firma
@@ -1892,7 +1885,7 @@ settings.trust_model.collaborator.long=Colaborador: Confiar en firmas de colabor
settings.trust_model.collaborator.desc=Las firmas válidas de los colaboradores de este repositorio serán marcadas como "confiables" - (coincidan o no con el committer). De lo contrario, las firmas válidas serán marcadas como "no confiables" si la firma coincide con el committer y "no coincidente" si no lo es.
settings.trust_model.committer=Committer
settings.trust_model.committer.long=Committer: Firmas de confianza que coinciden con los committers (Esto coincide con GitHub y obligará a Gitea a firmar los commits a tener a Gitea como el committer)
-settings.trust_model.committer.desc=Las firmas válidas solo se marcarán como "confiables" si coinciden con el autor de la confirmación; de lo contrario, se marcarán como "no coincidentes". Esto obligará a Gitea a ser el confirmador en los compromisos firmados con el confirmador real marcado como Co-authored-by: y Co-committed-ny: tráiler en el commit. La clave Gitea predeterminada debe coincidir con un usuario en la base de datos.
+settings.trust_model.committer.desc=Las firmas válidas solo se marcarán como "confiables" si coinciden con el autor de la confirmación
settings.trust_model.collaboratorcommitter=Colaborador+Comitter
settings.trust_model.collaboratorcommitter.long=Colaborador+Comitter: Confiar en firmas de colaboradores que coincidan con el committer
settings.trust_model.collaboratorcommitter.desc=Las firmas válidas de los colaboradores de este repositorio se marcarán como "de confianza" si coinciden con el confirmador. De lo contrario, las firmas válidas se marcarán como "no confiables" si la firma coincide con el autor de la confirmación y como "no coincidentes" en caso contrario. Esto obligará a Gitea a ser marcado como el confirmador en los compromisos firmados con el confirmador real marcado como Coautor por: y Cocommitido por: tráiler en el compromiso. La clave Gitea predeterminada debe coincidir con un usuario en la base de datos.
@@ -2009,6 +2002,8 @@ settings.event_package=Paquete
settings.event_package_desc=Paquete creado o eliminado en un repositorio.
settings.branch_filter=Filtro de rama
settings.branch_filter_desc=Lista blanca de rama para eventos de push, creación de rama y eliminación de rama, especificados como patrón globo. Si está vacío o <code>*</code>, se reportan eventos para todas las ramas. Ver <a href="https://pkg.go.dev/github.com/gobwas/glob#Compile">github.com/gobwas/glob</a> documentación para la sintaxis. Ejemplos: <code>master</code>, <code>{master,release*}</code>.
+settings.authorization_header=Encabezado de autorización
+settings.authorization_header_desc=Se incluirá como encabezado de autorización para solicitudes cuando esté presente. Ejemplo: %s.
settings.active=Activo
settings.active_helper=La información sobre los eventos desencadenados se enviará a esta URL de webhook.
settings.add_hook_success=El webhook ha sido añadido.
@@ -2123,7 +2118,6 @@ settings.bot_token=Token del Bot
settings.chat_id=ID Chat
settings.matrix.homeserver_url=URL de Homeserver
settings.matrix.room_id=ID de sala
-settings.matrix.access_token=Token de acceso
settings.matrix.message_type=Tipo de mensaje
settings.archive.button=Archivar Repositorio
settings.archive.header=Archivar este repositorio
@@ -2322,7 +2316,7 @@ org_full_name_holder=Nombre completo de la organización
org_name_helper=Los nombres de organización deben ser cortos y destacados.
create_org=Crear Organización
repo_updated=Actualizado
-people=Personas
+members=Miembros
teams=Equipos
code=Código
lower_members=miembros
@@ -2454,7 +2448,7 @@ first_page=Primera
last_page=Última
total=Total: %d
-dashboard.new_version_hint=Gitea %s ya está disponible; en este momento ejecuta la versión %s. Consulte el <a target="_blank" rel="noreferrer" href="https://blog.gitea.io">blog</a> para conocer más.
+dashboard.new_version_hint=Gitea %s ya está disponible
dashboard.statistic=Resumen
dashboard.operations=Operaciones de mantenimiento
dashboard.system_status=Estado del sistema
@@ -2728,9 +2722,9 @@ auths.tips.oauth2.general=Autenticación OAuth2
auths.tips.oauth2.general.tip=Al registrar una nueva autenticación vía OAuth2, la URL de devolución/redirección debe ser: <host>/user/oauth2/<Nombre de Autenticación>/callback
auths.tip.oauth2_provider=Proveedor OAuth2
auths.tip.bitbucket=Registrar un nuevo usuario de OAuth en https://bitbucket.org/account/user/<your username>/oauth-consumers/new y agregar el permiso 'Cuenta' - 'Lectura'
-auths.tip.nextcloud=Registre un nuevo consumidor OAuth en su instancia usando el siguiente menú "Configuración-> Seguridad-> cliente OAuth 2.0"
+auths.tip.nextcloud=`Registre un nuevo consumidor OAuth en su instancia usando el siguiente menú "Configuración-> Seguridad-> cliente OAuth 2.0"`
auths.tip.dropbox=Crear nueva aplicación en https://www.dropbox.com/developers/apps
-auths.tip.facebook=Registre una nueva aplicación en https://developers.facebook.com/apps y agregue el producto "Facebook Login"
+auths.tip.facebook=`Registre una nueva aplicación en https://developers.facebook.com/apps y agregue el producto "Facebook Login"`
auths.tip.github=Registre una nueva aplicación OAuth en https://github.com/settings/applications/new
auths.tip.gitlab=Registrar nueva solicitud en https://gitlab.com/profile/applications
auths.tip.google_plus=Obtener credenciales de cliente OAuth2 desde la consola API de Google en https://console.developers.google.com/
@@ -2738,7 +2732,7 @@ auths.tip.openid_connect=Use el OpenID Connect Discovery URL (<server>/.well-kno
auths.tip.twitter=Ir a https://dev.twitter.com/apps, crear una aplicación y asegurarse de que la opción "Permitir que esta aplicación sea usada para iniciar sesión con Twitter" está activada
auths.tip.discord=Registrar una nueva aplicación en https://discordapp.com/developers/applications/me
auths.tip.gitea=Registra una nueva aplicación OAuth2. La guía puede ser encontrada en https://docs.gitea.io/es-us/oauth2-provider/
-auths.tip.yandex=Crear una nueva aplicación en https://oauth.yandex.com/client/new. Seleccione los siguientes permisos del "Yandex.Passport API": "Access to email address", "Access to user avatar" y "Access to username, first name and surname, gender"
+auths.tip.yandex=`Crear una nueva aplicación en https://oauth.yandex.com/client/new. Seleccione los siguientes permisos del "Yandex.Passport API": "Access to email address", "Access to user avatar" y "Access to username, first name and surname, gender"`
auths.tip.mastodon=Introduzca una URL de instancia personalizada para la instancia mastodon con la que desea autenticarse (o utilice la predeterminada)
auths.edit=Editar origen de autenticación
auths.activated=Este origen de autenticación ha sido activado
@@ -2974,7 +2968,6 @@ monitor.queue.pool.cancel_desc=Dejar una cola sin ningún grupo de trabajadores
notices.system_notice_list=Notificaciones del Sistema
notices.view_detail_header=Ver detalles de notificación
-notices.actions=Acciones
notices.select_all=Sleccionar todo
notices.deselect_all=Deseleccionar todo
notices.inverse_selection=Selección inversa
@@ -3000,6 +2993,7 @@ reopen_pull_request=`reabrió el pull request <a href="%[1]s">%[3]s#%[2]s</a>`
comment_issue=`comentó en la incidencia <a href="%[1]s">%[3]s#%[2]s</a>`
comment_pull=`comentó en el pull request <a href="%[1]s">%[3]s#%[2]s</a>`
merge_pull_request=`fusionó el pull request <a href="%[1]s">%[3]s#%[2]s</a>`
+auto_merge_pull_request=`fusionado automáticamente pull request <a href="%[1]s">%[3]s#%[2]s</a>`
transfer_repo=transfirió el repositorio <code>%s</code> a <a href="%s">%s</a>
push_tag=hizó push la etiqueta <a href="%[2]s">%[3]s</a> a <a href="%[1]s">%[4]s</a>
delete_tag=etiqueta eliminada %[2]s de <a href="%[1]s">%[3]s</a>
@@ -3105,6 +3099,7 @@ versions.on=en
versions.view_all=Ver todo
dependency.id=Id.
dependency.version=Versión
+chef.install=Para instalar el paquete, ejecute el siguiente comando:
composer.registry=Configura este registro en el archivo <code>~/.composer/config.json</code>:
composer.install=Para instalar el paquete usando Composer, ejecute el siguiente comando:
composer.documentation=Para más información sobre el registro de Composer, consulte <a target="_blank" rel="noopener noreferrer" href="https://docs.gitea.io/en-us/packages/composer/">la documentación</a>.
@@ -3116,8 +3111,6 @@ conan.install=Para instalar el paquete usando Conan, ejecuta el siguiente comand
conan.documentation=Para más información sobre el registro de Conan, consulte <a target="_blank" rel="noopener noreferrer" href="https://docs.gitea.io/en-us/packages/conan/">la documentación</a>.
container.details.type=Tipo de imagen
container.details.platform=Plataforma
-container.details.repository_site=Sitio del repositorio
-container.details.documentation_site=Sitio de documentación
container.pull=Arrastra la imagen desde la línea de comandos:
container.digest=Resumen:
container.documentation=Para más información sobre el registro de Container, consulte <a target="_blank" rel="noopener noreferrer" href="https://docs.gitea.io/en-us/packages/container/">la documentación</a>.
@@ -3151,8 +3144,6 @@ npm.dependencies.optional=Dependencias opcionales
npm.details.tag=Etiqueta
pub.install=Para instalar el paquete usando Dart, ejecute el siguiente comando:
pub.documentation=Para obtener más información sobre el registro de Pub, consulte <a target="_blank" rel="noopener noreferrer" href="https://docs.gitea.io/en-us/packages/pub/">la documentación</a>.
-pub.details.repository_site=Sitio del repositorio
-pub.details.documentation_site=Sitio de documentación
pypi.requires=Requiere Python
pypi.install=Para instalar el paquete usando pip, ejecute el siguiente comando:
pypi.documentation=Para obtener más información sobre el registro PyPI, consulte <a target="_blank" rel="noopener noreferrer" href="https://docs.gitea.io/en-us/packages/pypi/">la documentación</a>.
@@ -3176,4 +3167,26 @@ settings.delete.description=La eliminación de un paquete es permanente y no se
settings.delete.notice=Está a punto de eliminar %s (%s). Esta operación es irreversible, ¿está seguro?
settings.delete.success=Se ha eliminado el paquete.
settings.delete.error=No se pudo eliminar el paquete.
+owner.settings.cleanuprules.enabled=Activo
+
+[secrets]
+value=Valor
+name=Nombre
+
+[actions]
+
+
+
+runners.id=Id.
+runners.name=Nombre
+runners.owner_type=Tipo
+runners.description=Descripción
+runners.labels=Etiquetas
+runners.task_list.run=Ejecutar
+runners.task_list.repository=Repositorio
+runners.task_list.commit=Commit
+runners.status.active=Activo
+
+runs.commit=Commit
+
diff --git a/options/locale/locale_fa-IR.ini b/options/locale/locale_fa-IR.ini
index a1e20b61d..449da63b7 100644
--- a/options/locale/locale_fa-IR.ini
+++ b/options/locale/locale_fa-IR.ini
@@ -43,7 +43,6 @@ new_mirror=قرینه ای جدید
new_fork=انشعاب مخزن جدید
new_org=سازمان جدید
new_project=پروژه جدید
-new_project_board=صÙحه پروژه جدید
manage_org=مدیریت سازمان‌ها
admin_panel=مدیریت سایت
account_settings=تنظیمات حساب
@@ -72,6 +71,9 @@ remove=حذÙ
remove_all=حذ٠همه
edit=ویرایش
+enabled=Ùعال شده
+disabled=غیرÙعال شده
+
copy=کپی
copy_url=کپی URL
copy_branch=کپی نام شاخه
@@ -91,6 +93,8 @@ error404=صÙحه موردنظر شما یا <strong>وجود ندارد</strong
never=هرگز
+[aria]
+
[filter]
[error]
@@ -159,6 +163,8 @@ log_root_path_helper=Ùایل‌های گزارش روی این مسیر ذخیØ
optional_title=تنظیمات اختیاری
email_title=تنظیمات ایمیل
+smtp_addr=میزبان SMTP
+smtp_port=گذرگاه(پورت) SMTP
smtp_from=ارسال ایمیل به عنوان
smtp_from_helper=آدرس ایمیلی Ú©Ù‡ گیتی استÙاده میکند. یک ایمیل وارد کنید یا به "Name" <email@example.com> Ø´Ú©Ù„ استÙاده کنید.
mailer_user=نام کاربری SMTP
@@ -201,7 +207,6 @@ internal_token_failed=کد داخلی ایجاد نشد: %v
secret_key_failed=کلید مخÙÛŒ ایجاد نشد: %v
save_config_failed=تنظیمات ذخیره نشد: %v
invalid_admin_setting=تنظیمات حساب مدیر نامعتبر است: %v
-install_success=خوش آمدی! از شما به خاطر انتخاب گیتی یا گیت‌گو تشکر میکنیم. لذت ببرید و مراقب باشید!
invalid_log_root_path=مسیر گزارش معتبر نیست: %v
default_keep_email_private=مخÙÛŒ کردن نشانی های ایمیل به صورت پیش Ùرض
default_keep_email_private_popup=مخÙÛŒ کردن نشانی های ایمیل از حساب های کاربر جدید به صورت پیش Ùرض.
@@ -227,7 +232,7 @@ view_home=نمایش %s
search_repos=یاÙتن مخزن…
filter=Ùیلترهای دیگر
filter_by_team_repositories=Ùیلتر کردن با مخازن تیم‌ها
-feed_of=خوراک از "%s"
+feed_of=`خوراک از "%s"`
show_archived=بایگانی شده
show_both_archived_unarchived=نمایش دادن موارد بایگانی شده و غیر بایگانی نشده
@@ -526,6 +531,7 @@ continue=ادامه
cancel=انصراÙ
language=زبان
ui=پوسته
+comment_type_group_title=عنوان
privacy=حریم خصوصی
keep_activity_private=مخÙÛŒ ساختن Ùعالیت ها از صÙحه پروÙایل
keep_activity_private_popup=نمایان ساختن Ùعالیت ها برای شما Ùˆ مدیران
@@ -589,8 +595,8 @@ add_key=اÙزودن کلید
ssh_desc=این کلیدهای عمومی SSH با حساب شما در ارتباط هستند. کلیدهای خصوصی مربوطه اجازه دسترسی کامل به مخازن شما را می دهند.
principal_desc=این گواهی‌های SSH اصلی برای حساب کاربری شما تعری٠شده و به مخزن‌های‌تان دسترسی کامل دارد.
gpg_desc=این کلید های عمومی GPG به حساب کاربری شما مرتبط مرتبط است. کلید خصوصی خود را محرمانه نگهدارید لذا با آن امکان ارسال commit تایید شده است.
-ssh_helper="<strong>آیا نمی دانید چگونه؟</strong>
- راهنمایی Github را برای <a href=\"%s\"></a>ساخت کلید SSH برای خود</a> ببینید
+ssh_helper=`"<strong>آیا نمی دانید چگونه؟</strong>`
+راهنمایی Github را برای <a href=\"%s\"></a>ساخت کلید SSH برای خود</a> ببینید
یا ممکن است با راه حل استÙاده از SSH در <a href=\"%s\">مشکلات متداول</a> مواجه شوید."
gpg_helper=<strong>به کمک نیاز دارید؟</strong> نگاهی به در GitHub را راهنمای <a href="%s">مورد GPG</a> است.
add_new_key=اضاÙÙ‡ کردن کلید SSH
@@ -615,6 +621,11 @@ gpg_token_help=با این میتوانید یک امضاء بسازید:
gpg_token_code=‪echo "%s" | gpg -a --default-key %s --detach-sig‬
gpg_token_signature=امضای GPG زره‌پوش
key_signature_gpg_placeholder=با '-----BEGIN PGP SIGNATURE-----' شروع می‌شود
+ssh_key_verified=کلید تأیید شده
+ssh_key_verify=تایید‌کنید
+ssh_token_required=باید یک امضا برای ژتون زیر ارائه کنید
+ssh_token=توکن
+ssh_token_help=با این میتوانید یک امضاء بسازید:
subkeys=کلید های زیر مجموعه
key_id=شناسه کلید
key_name=نام کلید
@@ -662,12 +673,14 @@ generate_token_success=اکنون token جدید ساخته شد. همینک Ø¢Ù
generate_token_name_duplicate=<strong>%s</strong> قبلا بعنوان نام یک برنامه استÙاده شده است. لطÙا از یک نام دیگر استÙاده کنید.
delete_token=حذÙ
access_token_deletion=حذ٠توکن
+access_token_deletion_cancel_action=انصراÙ
+access_token_deletion_confirm_action=حذÙ
delete_token_success=token مورد نظر حذ٠شد. برنامه هایی Ú©Ù‡ از آن استÙاده می‎کنند به زودی دسترسی به حساب کاربری شما را از دست می‎دهند.
-manage_oauth2_applications=مدیریت برنامه‎های OAuth2
-edit_oauth2_application=ویرایش برنامه OAuth2
+manage_oauth2_applications=مدیریت برنامه‎های OAuth2
+edit_oauth2_application=ویرایش برنامه OAuth2
oauth2_applications_desc=برنامه‎های OAuth2 احراز هویت برنامه های شخص ثالث را با بستری امن میسر می‎کند.
-remove_oauth2_application=حذ٠برنامه OAuth2
+remove_oauth2_application=حذ٠برنامه OAuth2
remove_oauth2_application_desc=حذ٠برنامه OAuth2 دسترسی تمام برنامه های متصل با آن را از بین می‎برد. آیا ادامه می‎دهید؟
remove_oauth2_application_success=برنامه حذ٠شده است.
create_oauth2_application=ساختن یک برنامه OAuth2 جدید
@@ -691,7 +704,6 @@ authorized_oauth2_applications_description=این به برنامه های شخØ
revoke_key=ابطال
revoke_oauth2_grant=ابطال دسترسی
revoke_oauth2_grant_description=لغو دسترسی برای این برنامه شخص ثالث از دسترسی این برنامه به داده های شما جلوگیری می کند. شما مطمئن هستید؟
-
revoke_oauth2_grant_success=شما اجازه دسترسی را لغو کردید.
twofa_desc=احراز هویت دو مرحله ای امنیت حساب شما را اÙزایش میدهد.
@@ -716,10 +728,12 @@ twofa_failed_get_secret=خطا در دریاÙت رمز.
manage_account_links=مدیریت حساب های مرتبط شده
manage_account_links_desc=این حساب های خارجی به حساب Gitea ارتباط دارد.
account_links_not_available=اکنون دیگر هیچ پیوند حساب‌های کاربری خارجی به حساب کاربری شما وجود ندارد.
+link_account=پیوند به حساب
remove_account_link=حذ٠حساب پیوند خرده
remove_account_link_desc=با حذ٠پیوند خارجی حساب کاربری دسترسی شما به حساب کابریتان توسط آن از بین میرود. آیا ادامه می‌دهید؟
remove_account_link_success=پیوند حساب کاربری از حذ٠شد.
+
orgs_none=شما عضو هیچ سازمانی نیستید.
repos_none=شما مالک هیچ مخزنی نیستید
@@ -882,7 +896,7 @@ 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.invalid_lfs_endpoint=نقطه پایانی LFS معتبر نیست
migrate.failed=انتقال انجام نشد: %v
migrate.migrate_items_options=نشانی دسترسی برای مهاجرت موارد اضاÙÛŒ مورد نیاز است
migrated_from=مهاجرت از <a href="%[1]s">%[2]s</a>
@@ -898,7 +912,7 @@ migrate.gitea.description=مهاجرت داده از gitea.com یا پیادهâ€
migrate.gogs.description=مهاجرت داده از notabug.com یا پیاده‌سازی‌های دیگر Gogs.
migrate.onedev.description=مهاجرت داده از code.onedev.io یا پیاده‌سازی‌های دیگر OneDev.
migrate.codebase.description=مهاجر داده ها از codebasehq.com.
-migrate.gitbucket.description=مهاجرت داده از نمونه های GitBucket
+migrate.gitbucket.description=مهاجرت داده از نمونه های GitBucket
migrate.migrating_git=انتقال داده های Git
migrate.migrating_topics=موضوعات مهاجرت
migrate.migrating_milestones=نقاط عط٠مهاجرت
@@ -951,7 +965,7 @@ release=نسخه منتشر شده
releases=انتشارها
tag=برچسب
released_this=منتشر کرده است
-file.title= %s در %s
+file.title=%s در %s
file_raw=خام
file_history=تاریخچه
file_view_source=نمایش منبع
@@ -1038,7 +1052,7 @@ commits.commits=کامیت‌ها
commits.no_commits=هیچ کامیت مشترکی وجود ندارد. '%s' Ùˆ '%s' دارای تاریجچه متÙاوت هستند.
commits.nothing_to_compare=این شاخه ها برابرند.
commits.search=جست‌وجو کامیت‌ها…
-commits.search.tooltip=شما میتوانید از کلمات کلیدی پیشوند "author:", "committer:", "after:", or "before:" Ùˆ ... استÙاده کنید به عنوان مثال: "revert author:Ali before:1397-04-01.."
+commits.search.tooltip=`شما میتوانید از کلمات کلیدی پیشوند "author:", "committer:", "after:", or "before:" Ùˆ ... استÙاده کنید به عنوان مثال: "revert author:Ali before:1397-04-01.."`
commits.find=جستجو
commits.search_all=همه شاخه ها
commits.author=مولÙ
@@ -1076,16 +1090,9 @@ projects.type.bug_triage=اشکال Triage
projects.template.desc=قالب پروژه
projects.template.desc_helper=برای شروع یک قالب پروژه را انتخاب کنید
projects.type.uncategorized=دسته‌بندی نشده
-projects.board.edit=ویرایش صÙحه
-projects.board.edit_title=نام بورد جدید
-projects.board.new_title=نام بورد جدید
-projects.board.new_submit=ثبت
-projects.board.new=بورد جدید
-projects.board.set_default=تنظیم پیش‌Ùرض
-projects.board.set_default_desc=تنظیم کردن این بورد برای مشکلات دسته‌بندی نشده
-projects.board.delete=حذ٠بورد
-projects.board.deletion_desc=حذ٠کردن تابلوی یک پروژه تمامی مشکلات مربوطه را به برد "دسته بندی نشده" منتقل می کند. ادامه می دهید؟
-projects.board.color=رنگ
+projects.column.edit_title=نام
+projects.column.new_title=نام
+projects.column.color=رنگ
projects.open=باز‌کردن
projects.close=بستن
@@ -1161,6 +1168,7 @@ issues.filter_label_exclude=`از<code>alt</code> + <code>click/enter</code> بØ
issues.filter_label_no_select=تمامی برچسب‎ها
issues.filter_milestone=نقطه عطÙ
issues.filter_milestone_no_select=تمام نقاط عطÙ
+issues.filter_project_none=هیچ پروژه ثبت نشده
issues.filter_assignee=مسئول رسیدگی
issues.filter_assginee_no_select=تمامی مسئولان رسیدگی
issues.filter_type=نوع
@@ -1195,6 +1203,7 @@ issues.previous=قبلی
issues.next=بعدی
issues.open_title=باز
issues.closed_title=بسته شده
+issues.draft_title=پیش‌نویس
issues.num_comments=%d دیدگاه
issues.commented_at=`دیدگاه ارسال شده <a href="#%s">%s</a>`
issues.delete_comment_confirm=آیا مطمئن هستید Ú©Ù‡ Ù…ÛŒ خواهید این دیدگاه را حذÙ کنید؟
@@ -1273,6 +1282,7 @@ issues.lock.reason=دلیل انسداد
issues.lock.title=انسداد مکالمه در این مسئله.
issues.unlock.title=رÙع انسداد مکالمه در این مسئله.
issues.comment_on_locked=شما نمی‌توانید در مسئله Ù‚ÙÙ„ شده اظهار نظر کنید.
+issues.delete=حذÙ
issues.tracker=پیگیری زمان
issues.start_tracking_short=تایمز شروع
issues.start_tracking=شروع به پیگیری زمان
@@ -1301,6 +1311,7 @@ issues.error_removing_due_date=حذ٠موعد مقرر با شکست مواجه
issues.push_commit_1=%d اعمال تغییر اضاÙÙ‡ شده است %s
issues.push_commits_n=%d اعمال تغییرات اضاÙÙ‡ شده است %s
issues.force_push_codes=`پوش شده اجباری %[1]s از <a class="ui sha" href="%[3]s"><code>%[2]s</code></a> به <a class="ui sha" href="%[5]s"><code>%[4]s</code></a> %[6]s`
+issues.force_push_compare=مقایسه
issues.due_date_form=yyyy-mm-dd
issues.due_date_form_add=اÙزودن موعد مقرر
issues.due_date_form_edit=ویرایش
@@ -1616,6 +1627,7 @@ search.search_repo=جستجوی مخزن
search.fuzzy=درهم
search.match=مطابق
search.results=نتیجه جستجو برای "%s" در <a href="%s">%s</a>
+search.code_no_results=کد منبعی مطابق با جستجوی شما یاÙت نشد.
settings=تنظيمات
settings.desc=تنظیمات جایی است که شما می‌توانید تنظیمات مخزن خود را مدیریت کنید
@@ -1667,11 +1679,6 @@ settings.enable_timetracker=Ùعال کردن پیگیری زمان
settings.allow_only_contributors_to_track_time=اجازه پیگیری زمان مشارکت Ùقط
settings.pulls_desc=Ùعال کردن تقاضای واکشی مخزن
settings.pulls.ignore_whitespace=نادیده گرÙتن لیست سÙید برای تداخل ها
-settings.pulls.allow_merge_commits=Ùعال کردن ادغام کامیت ها
-settings.pulls.allow_rebase_merge=Ùعال کردن احیا به ادغام کامیت ها
-settings.pulls.allow_rebase_merge_commit=Ùعال کردن «احیاء» با ادغام آشکار کامیت‌ها (--no-ff)
-settings.pulls.allow_squash_commits=Ùعال کردن خاموش کردن ادغام کامیت ها
-settings.pulls.allow_manual_merge=Mark PR بعنوان ادغام دستی Ùعال شود
settings.pulls.enable_autodetect_manual_merge=ادغام دستی تشخیص خودکار را Ùعال کنید (توجه: در برخی موارد خاص، قضاوت نادرست ممکن است رخ دهد)
settings.pulls.default_delete_branch_after_merge=پس از ادغام به طور پیش Ùرض شاخه درخواست pull را حذ٠کنید
settings.projects_desc=Ùعال کردن پروژه های انبار
@@ -1790,6 +1797,7 @@ settings.event_delete=حذÙ
settings.event_delete_desc=شاخه یا تگ حذ٠شد.
settings.event_fork=انشعاب
settings.event_fork_desc=انشعاب از مخزن ایجاد شد.
+settings.event_wiki=دانشنامه
settings.event_release=انتشار
settings.event_release_desc=منشتر شد. به روز شده یا حذ٠شده در یک مخزن.
settings.event_push=درج کردن
@@ -1921,7 +1929,6 @@ settings.bot_token=Token ربات
settings.chat_id=شناسه گپ
settings.matrix.homeserver_url=URL سرورخانه
settings.matrix.room_id=شناسه Room
-settings.matrix.access_token=نشانه دسترسی
settings.matrix.message_type=نوع پیام
settings.archive.button=بایگانی مخزن
settings.archive.header=بایگانی این مخزن
@@ -2089,6 +2096,7 @@ branch.included_desc=این شاخه بخشی از شاخه پیش Ùرض است
branch.included=مشمول شده
branch.create_new_branch=ایجاد شاخه از شاخه:
branch.confirm_create_branch=ایجاد شاخه
+branch.create_branch_operation=ایجاد شاخه
branch.new_branch=شاخه جدید ایجاد کنید
branch.new_branch_from=ایجاد شاخه جدید از '%s'
branch.renamed=شاخه %s قبلا به %s تغییر کرده است.
@@ -2113,7 +2121,7 @@ org_full_name_holder=نام کامل سازمان
org_name_helper=نام سازمان باید کوتاه Ùˆ قابل Ø­Ùظ کردن باشد.
create_org=ایجاد سازمان
repo_updated=به روز رسانی شده
-people=اÙراد
+members=اعضاء
teams=تیم‌ها
lower_members=اعضا
lower_repositories=مخازن
@@ -2182,6 +2190,7 @@ teams.leave=ترک‌کردن
teams.leave.detail=ترک %s؟
teams.can_create_org_repo=ایجاد مخزن
teams.can_create_org_repo_helper=اعضا Ù…ÛŒ توانند مخازن جدیدی را در سازمان ایجاد کنند. خالق دسترسی سرپرست به مخزن جدید را دریاÙت Ù…ÛŒ کند.
+teams.read_access=خواندن
teams.read_access_helper=اعضا می‌توانند مخازن مربوط به تیم را مشاهده و از آن همسان تهیه کنند.
teams.write_access_helper=اعضا می‌توانند مخازن مربوط به تیم را بخوانند و کامیت ها در آن درج کنند.
teams.admin_access=دسترسی مدیریت
@@ -2387,6 +2396,11 @@ repos.forks=انشعاب‌ها
repos.issues=مسائل
repos.size=اندازه
+packages.owner=مالک
+packages.name=نام
+packages.type=نوع
+packages.repository=مخزن
+packages.size=اندازه
defaulthooks=وب هوک های پیش Ùرض
defaulthooks.desc=هنگامی Ú©Ù‡ برخی رویدادهای Gitea Ùعال Ù…ÛŒ شوند، Webhook ها به طور خودکار درخواست های HTTP POST را به سرور ارسال Ù…ÛŒ کنند. هوک های تعری٠شده در اینجا پیش Ùرض هستند Ùˆ در تمام مخازن جدید Ú©Ù¾ÛŒ Ù…ÛŒ شوند. در <a target="_blank" rel="noopener" href="https://docs.gitea.io/en-us/webhooks/">راهنمای هوک‌های وب</a> بیشتر بخوانید.
@@ -2478,7 +2492,7 @@ auths.tip.oauth2_provider=تامین کننده OAuth2
auths.tip.bitbucket=ثبت یک OAuth جدید مصر٠کننده بر https://bitbucket.org/account/user/<your username>/oauth-consumers/new Ùˆ اÙزودن مجوز 'Account' - 'Read'
auths.tip.nextcloud=با استÙاده از منوی زیر "تنظیمات -> امنیت -> مشتری OAuth 2.0" مصر٠کننده OAuth جدیدی را در نمونه خود ثبت کنید
auths.tip.dropbox=یک برنامه جدید در https://www.dropbox.com/developers/apps بسازید
-auths.tip.facebook=یک برنامه جدید در https://developers.facebook.com/apps بسازید برای ورود از طریق Ùیس بوک قسمت محصولات "Facebook Login"
+auths.tip.facebook=`یک برنامه جدید در https://developers.facebook.com/apps بسازید برای ورود از طریق Ùیس بوک قسمت محصولات "Facebook Login"`
auths.tip.github=یک برنامه OAuth جدید در https://github.com/settings/applications/new ثبت کنید
auths.tip.gitlab=ثبت یک برنامه جدید در https://gitlab.com/profile/applications
auths.tip.google_plus=اطلاعات مربوط به مشتری OAuth2 را از کلاینت API Google در https://console.developers.google.com/
@@ -2486,7 +2500,7 @@ auths.tip.openid_connect=برای مشخص کردن نقاط پایانی از Ø
auths.tip.twitter=به https://dev.twitter.com/apps بروید ØŒ برنامه ای ایجاد کنید Ùˆ اطمینان حاصل کنید Ú©Ù‡ گزینه "اجازه استÙاده از این برنامه برای ورود به سیستم با Twitter" را Ùعال کنید
auths.tip.discord=یک برنامه جدید را در https://discordapp.com/developers/applications/me ثبت کنید
auths.tip.gitea=یک برنامه OAuth2 ثبت کنید. راهنمایی بیشتر https://docs.gitea.io/en-us/oauth2-provider/
-auths.tip.yandex=یک برنامه جدید در https://oauth.yandex.com/client/new ایجاد کنید. مجوزهای زیر را از بخش "Yandex.Passport API" انتخاب کنید: "دسترسی به آدرس ایمیل"، "دسترسی به آواتار کاربر" و "دسترسی به نام کاربری، نام و نام خانوادگی، جنسیت"
+auths.tip.yandex=`یک برنامه جدید در https://oauth.yandex.com/client/new ایجاد کنید. مجوزهای زیر را از بخش "Yandex.Passport API" انتخاب کنید: "دسترسی به آدرس ایمیل"، "دسترسی به آواتار کاربر" و "دسترسی به نام کاربری، نام و نام خانوادگی، جنسیت"`
auths.tip.mastodon=یک URL نمونه سÙارشی برای نمونه ماستودون Ú©Ù‡ Ù…ÛŒ خواهید با آن احراز هویت کنید وارد کنید (یا از یک پیش Ùرض استÙاده کنید)
auths.edit=ویرایش منبع احراز هویت
auths.activated=این منبع احراز هویت Ùعال شده است
@@ -2496,7 +2510,6 @@ auths.update=به‌روزکردن منبع احراز هویت
auths.delete=حذ٠منبع احراز هویت
auths.delete_auth_title=حذ٠منبع احراز هویت
auths.delete_auth_desc=حذ٠یک منبع احراز هویت، از ورود کاربران به سیستم جلوگیری می کند. آیا ادامه می‌دهید؟
-
auths.still_in_used=منبع احراز هویت همچنان در حال استÙاده است. ابتدا با استÙاده از این منبع احراز کاربرانی را تبدیل یا حذ٠کنید.
auths.deletion_success=احراز هویت منبع حذ٠شد.
auths.login_source_exist=منبع احراز هویت '%s' پیش از این وجود داشته است.
@@ -2577,6 +2590,7 @@ config.skip_tls_verify=صر٠نظر از اعتبارسنجی TLS
config.mailer_enabled=Ùعال شده
config.mailer_name=نام
+config.mailer_smtp_port=گذرگاه(پورت) SMTP
config.mailer_user=کاربر
config.mailer_use_sendmail=استÙاده از ارسال رایانامه (ایمیل) مستقیم
config.mailer_sendmail_path=مسیر ارسال ایمیل مستقیم
@@ -2704,7 +2718,6 @@ monitor.queue.pool.cancel_desc=ترک یک ص٠بدون هیچ گروه کارÚ
notices.system_notice_list=هشدارهای سامانه
notices.view_detail_header=مشاهده جزئیات اخطار
-notices.actions=اقدامات
notices.select_all=انتخاب همه
notices.deselect_all=لغو انتخاب همه
notices.inverse_selection=انتخاب معکوس
@@ -2804,4 +2817,25 @@ error.no_unit_allowed_repo=شما اجازه دسترسی به هیچ قسمت Ø
error.unit_not_allowed=شما اجازه دسترسی به این قسمت مخزن را ندارید.
[packages]
+filter.type=نوع
+conan.details.repository=مخزن
+owner.settings.cleanuprules.enabled=Ùعال شده
+
+[secrets]
+name=نام
+
+[actions]
+
+
+
+runners.name=نام
+runners.owner_type=نوع
+runners.description=شرح
+runners.task_list.run=اجرا
+runners.task_list.repository=مخزن
+runners.task_list.commit=کامیت
+runners.status.active=Ùعال
+
+runs.commit=کامیت
+
diff --git a/options/locale/locale_fi-FI.ini b/options/locale/locale_fi-FI.ini
index 3fd2f1800..a589d12c2 100644
--- a/options/locale/locale_fi-FI.ini
+++ b/options/locale/locale_fi-FI.ini
@@ -40,7 +40,7 @@ webauthn_use_twofa=Käytä kaksivaihesta vahvistusta puhelimestasi
webauthn_error=Turva-avainta ei voitu lukea.
webauthn_unsupported_browser=Selaimesi ei tällä hetkellä tue WebAuthnia.
webauthn_error_unknown=Tuntematon virhe. Yritä uudelleen.
-webauthn_error_insecure=WebAuthn tukee vain suojattuja yhteyksiä. Testaukseen HTTP:n yli, voit käyttää osoitetta "localhost" tai "127.0.0.1"
+webauthn_error_insecure=`WebAuthn tukee vain suojattuja yhteyksiä. Testaukseen HTTP:n yli, voit käyttää osoitetta "localhost" tai "127.0.0.1"`
webauthn_error_unable_to_process=Palvelin ei pystynyt toteuttamaan kutsua.
webauthn_error_duplicated=Turva-avainta ei ole sallittu tässä pyynnössä. Varmista, ettei avainta ole jo rekisteröity.
webauthn_error_empty=Sinun täytyy asettaa nimi tälle avaimelle.
@@ -84,6 +84,9 @@ remove=Poista
remove_all=Poista kaikki
edit=Muokkaa
+enabled=Käytössä
+disabled=Pois käytöstä
+
copy=Kopioi
copy_url=Kopioi osoite
copy_branch=Kopioi haaran nimi
@@ -104,6 +107,8 @@ never=Ei koskaan
rss_feed=RSS-syöte
+[aria]
+
[filter]
[error]
@@ -175,6 +180,8 @@ log_root_path_helper=Lokitiedostot kirjoitetaan tähän kansioon.
optional_title=Valinnaiset asetukset
email_title=Sähköpostiasetukset
+smtp_addr=SMTP isäntä
+smtp_port=SMTP portti
smtp_from=Lähetä sähköpostit osoitteella
smtp_from_helper=Sähköpostiosoite, jota Gitea käyttää. Kirjoita osoite â€nimi†<email@example.com> -muodossa.
mailer_user=SMTP-käyttäjätunnus
@@ -213,7 +220,6 @@ invalid_repo_path=Repojen juuri polku on virheellinen: %v
invalid_app_data_path=Sovelluksen datapolku on virheellinen: %v
internal_token_failed=Sisäisen pääsymerkin luonti epäonnistui: %v
save_config_failed=Asetusten tallentaminen epäonnistui: %v
-install_success=Tervetuloa! Kiitos kun valitsit Gitean. Pidä hauskaa!
default_keep_email_private=Piilota sähköpostiosoitteet oletuksena
default_keep_email_private_popup=Piilota oletusarvoisesti uusien käyttäjätilien sähköpostiosoitteet.
default_enable_timetracking=Ota ajan seuranta oletusarvoisesti käyttöön
@@ -236,7 +242,7 @@ view_home=Näytä %s
search_repos=Etsi repo…
filter=Muut suodattimet
filter_by_team_repositories=Suodata tiimin repojen mukaan
-feed_of=Syöte "%s"
+feed_of=`Syöte "%s"`
show_archived=Arkistoidut
show_both_archived_unarchived=Näytetään arkistoidut ja arkistoimattomat
@@ -420,7 +426,7 @@ cannot_add_org_to_team=Organisaatiota ei voida lisätä tiimin jäseneksi.
invalid_ssh_key=SSH-avaintasi ei voi vahvistaa: %s
invalid_gpg_key=GPG-avaintasi ei voi vahvistaa: %s
-unable_verify_ssh_key=SSH-avainta ei voi vahvistaa; tarkista se virheiden varalta.
+unable_verify_ssh_key=SSH-avainta ei voi vahvistaa
auth_failed=Todennus epäonnistui: %v
@@ -514,6 +520,7 @@ old_password=Nykyinen salasana
new_password=Uusi salasana
retype_new_password=Syötä uusi salasana uudelleen
password_incorrect=Nykyinen salasanasi on virheellinen.
+password_change_disabled=Ei-lokaalit käyttäjät eivät voi päivittää salasanojaan Gitean web-käyttöliittymän kautta.
emails=Sähköposti osoitteet
manage_emails=Hallitse sähköpostiosoitteita
@@ -640,10 +647,12 @@ webauthn_nickname=Nimimerkki
manage_account_links=Hallitse linkitettyjä tilejä
manage_account_links_desc=Nämä ulkoiset tilit on linkitetty Gitea tiliisi.
+link_account=Yhdistä tili
remove_account_link=Poista linkitetty tili
remove_account_link_desc=Linkitetyn tilin poistaminen peruuttaa pääsyn Gitea-tiliisi linkitetyn tili kautta. Jatketaanko?
remove_account_link_success=Linkitetty tili on poistettu.
+
orgs_none=Et ole minkään organisaation jäsen.
repos_none=Sinulla ei ole repoja
@@ -705,6 +714,7 @@ desc.public=Julkinen
desc.private_template=Yksityinen malli
desc.public_template=Malli
desc.internal=Sisäinen
+desc.archived=Arkistoidut
template.git_hooks=Git-koukut
template.webhooks=Webkoukut
@@ -753,6 +763,8 @@ branches=Branchit
tags=Tagit
issues=Ongelmat
pulls=Pull-pyynnöt
+project_board=Projektit
+packages=Paketit
labels=Tunnisteet
milestones=Merkkipaalut
@@ -832,13 +844,10 @@ projects.edit=Muokkaa projektia
projects.modify=Päivitä projekti
projects.edit_success=Projekti '%s' on päivitetty.
projects.type.basic_kanban=Yksinkertainen Kanban
+projects.template.desc=Malli
projects.type.uncategorized=Luokittelematon
-projects.board.edit=Muokkaa luetteloa
-projects.board.new_submit=Lähetä
-projects.board.new=Uusi taulu
-projects.board.set_default=Aseta oletukseksi
-projects.board.delete=Poista taulu
-projects.board.color=Väri
+projects.column.edit_title=Nimi
+projects.column.new_title=Nimi
projects.open=Avaa
projects.close=Sulje
@@ -850,6 +859,7 @@ issues.new.labels=Tunnisteet
issues.new.add_labels_title=Aseta tunniste
issues.new.no_label=Ei tunnistetta
issues.new.clear_labels=Tyhjennä tunnisteet
+issues.new.projects=Projektit
issues.new.no_items=Ei kohteita
issues.new.milestone=Merkkipaalu
issues.new.add_milestone_title=Aseta merkkipaalu
@@ -874,6 +884,7 @@ issues.change_milestone_at=`vaihtoi merkkipaalun <b>%s</b> merkkipaaluun <b>%s</
issues.remove_milestone_at=`poisti tämän <b>%s</b> merkkipaalusta %s`
issues.remove_project_at=`poisti tämän <b>%s</b> projektista %s`
issues.deleted_milestone=`(poistettu)`
+issues.deleted_project=`(poistettu)`
issues.self_assign_at=`itse otti tämän käsittelyyn %s`
issues.change_title_at=`muutti otsikon <b><strike>%s</strike></b> otsikoksi <b>%s</b> %s`
issues.delete_branch_at=`poisti haaran <b>%s</b> %s`
@@ -882,7 +893,9 @@ issues.filter_label_exclude=`Käytä <code>alt</code> + <code>klikkaus/rivinvaih
issues.filter_label_no_select=Kaikki tunnisteet
issues.filter_milestone=Merkkipaalu
issues.filter_milestone_no_select=Kaikki merkkipaalut
+issues.filter_project=Projekti
issues.filter_assignee=Osoitettu
+issues.filter_poster=Tekijä
issues.filter_type=Tyyppi
issues.filter_type.all_issues=Kaikki ongelmat
issues.filter_type.assigned_to_you=Osoitettu sinulle
@@ -907,11 +920,13 @@ issues.action_close=Sulje
issues.action_label=Tunniste
issues.action_milestone=Merkkipaalu
issues.action_milestone_no_select=Ei merkkipaalua
+issues.action_assignee=Osoitettu henkilölle
issues.opened_by=%[1]s avasi <a href="%[2]s">%[3]s</a>
issues.previous=Edellinen
issues.next=Seuraava
issues.open_title=Avoinna
issues.closed_title=Suljettu
+issues.draft_title=Työversio
issues.num_comments=%d kommenttia
issues.commented_at=`kommentoi <a href="#%s">%s</a>`
issues.delete_comment_confirm=Haluatko varmasti poistaa tämän kommentin?
@@ -936,6 +951,7 @@ issues.edit=Muokkaa
issues.cancel=Peruuta
issues.save=Tallenna
issues.label_title=Tunnisteen nimi
+issues.label_description=Kuvaus
issues.label_color=Tunnisteen väri
issues.label_count=%d tunnistetta
issues.label_open_issues=%d avointa ongelmaa
@@ -961,6 +977,7 @@ issues.unlock.notice_2=- Voit aina myöhemmin lukita tämän ongelman uudelleen.
issues.lock.reason=Lukitsemisen syy
issues.lock.title=Lukitse keskustelu tästä ongelmasta.
issues.unlock.title=Avaa keskustelu tästä ongelmasta.
+issues.delete=Poista
issues.tracker=Ajan seuranta
issues.start_tracking_short=Aloita ajanotto
issues.start_tracking=Aloita ajan seuranta
@@ -1085,6 +1102,7 @@ activity.period.yearly=1 vuosi
activity.overview=Yleiskatsaus
activity.active_prs_count_1=<strong>%d</strong> Aktiivinen vetopyyntö
activity.active_prs_count_n=<strong>%d</strong> Aktiivista vetopyyntöä
+activity.merged_prs_label=Yhdistetty
activity.active_issues_count_1=<strong>%d</strong> Aktiivinen ongelma
activity.active_issues_count_n=<strong>%d</strong> Aktiivista ongelmaa
activity.closed_issues_count_1=Suljettu ongelma
@@ -1106,6 +1124,8 @@ activity.git_stats_deletion_1=%d poisto
activity.git_stats_deletion_n=%d poistoa
search=Haku
+search.match=Osuma
+search.code_no_results=Hakuehtoasi vastaavaa lähdekoodia ei löytynyt.
settings=Asetukset
settings.options=Repo
@@ -1135,6 +1155,7 @@ settings.transfer=Siirrä omistajuus
settings.transfer_form_title=Syötä repon nimi vahvistuksena:
settings.transfer_notices_3=- Jos arkisto on yksityinen ja se siirretään yksittäiselle käyttäjälle, tämä toiminto varmistaa, että käyttäjällä on ainakin lukuoikeudet (ja muuttaa käyttöoikeuksia tarvittaessa).
settings.transfer_owner=Uusi omistaja
+settings.trust_model.collaborator=Yhteistyökumppani
settings.wiki_delete=Poista Wiki data
settings.wiki_delete_desc=Repon wikin data poistaminen on pysyvä eikä voi peruuttaa.
settings.confirm_wiki_delete=Wiki datan poistaminen
@@ -1148,6 +1169,7 @@ settings.search_user_placeholder=Etsi käyttäjä…
settings.teams=Tiimit
settings.add_team=Lisää tiimi
settings.add_webhook=Lisää webkoukku
+settings.webhook_deletion=Poista webkoukku
settings.webhook.test_delivery=Testitoimitus
settings.webhook.request=Pyyntö
settings.webhook.response=Vastaus
@@ -1172,12 +1194,14 @@ settings.event_create=Luo
settings.event_create_desc=Haara tai tagi luotu.
settings.event_delete=Poista
settings.event_delete_desc=Haara tai tagi poistettu.
+settings.event_wiki=Wiki
settings.event_release_desc=Julkaisu julkaistu, päivitetty tai poistettu varastosta.
settings.event_push=Työnnä
settings.event_push_desc=Git push repoon.
settings.event_repository=Repo
settings.event_repository_desc=Repo luotu tai poistettu.
settings.event_header_issue=Ongelmien tapahtumat
+settings.event_issues=Ongelmat
settings.event_issues_desc=Ongelma avattu, suljettu, avattu uudelleen tai muokattu.
settings.event_issue_assign=Ongelma määritetty
settings.event_issue_assign_desc=Ongelma osoitettu tai osoitus poistettu.
@@ -1251,7 +1275,6 @@ settings.tags.protection.none=Suojattuja tageja ei ole.
settings.tags.protection.pattern.description=Voit käyttää yhtä nimeä tai glob-kuviota tai säännöllistä lauseketta, joka täsmää useisiin tageihin. Lue lisää <a target="_blank" rel="noopener" href="https://docs.gitea.io/en-us/protected-tags/">suojatut tagit oppaasta</a>.
settings.bot_token=Botti pääsymerkki
settings.matrix.homeserver_url=Kotipalvelimen URL
-settings.matrix.access_token=Pääsymerkki
settings.archive.button=Arkistoi repo
settings.archive.header=Arkistoi tämä repo
settings.archive.tagsettings_unavailable=Tagien asetukset eivät ole saatavilla, jos repo on arkistoitu.
@@ -1303,6 +1326,7 @@ diff.comment.add_review_comment=Lisää kommentti
diff.comment.start_review=Aloita tarkistus
diff.comment.reply=Vastaa
diff.review.header=Lähetä arvio
+diff.review.placeholder=Tarkistuksen kommentti
diff.review.comment=Kommentoi
diff.review.approve=Hyväksy
diff.review.reject=Pyydä muutoksia
@@ -1330,6 +1354,7 @@ release.save_draft=Tallenna luonnos
release.edit_release=Päivitä julkaisu
release.delete_release=Poista julkaisu
release.delete_tag=Poista tagi
+release.deletion=Poista julkaisu
release.deletion_tag_desc=Poistetaanko tämä tagi reposta? Repon sisältö ja historia pysyvät muuttumattomina. Jatketaanko?
release.deletion_tag_success=Tagi on poistettu.
release.tag_name_invalid=Tagin nimi ei ole kelvollinen.
@@ -1353,7 +1378,7 @@ org_full_name_holder=Organisaation täydellinen nimi
org_name_helper=Organisaation nimen tulisi olla lyhyt ja mieleenpainuva.
create_org=Luo organisaatio
repo_updated=Päivitetty
-people=Ihmiset
+members=Jäsenet
teams=Tiimit
lower_members=jäsenet
lower_repositories=repot
@@ -1375,6 +1400,7 @@ settings.full_name=Kokonimi
settings.website=Nettisivu
settings.location=Sijainti
settings.permission=Käyttöoikeudet
+settings.repoadminchangeteam=Repon ylläpitäjä voi lisätä ja poistaa pääsyn tiimeihin
settings.visibility=Näkyvyys
settings.visibility.public=Julkinen
settings.visibility.limited=Rajoitettu (näkyvä vain kirjautuneille käyttäjille)
@@ -1387,6 +1413,7 @@ settings.delete=Poista organisaatio
settings.delete_account=Poista tämä organisaatio
settings.delete_prompt=Organisaatio poistetaan pysyvästi, ja tätä <strong>EI VOI</strong> peruuttaa myöhemmin!
settings.confirm_delete_account=Vahvista poisto
+settings.delete_org_title=Poista organisaatio
settings.hooks_desc=Lisää webkoukkuja, jotka suoritetaan <strong>kaikissa repoissa</strong> tässä organisaatiossa.
@@ -1405,6 +1432,7 @@ members.invite_now=Kutsu nyt
teams.join=Liity
teams.leave=Poistu
+teams.read_access=Luettu
teams.read_access_helper=Tiimin jäsenet voivat katsella ja kloonata tiimin varastoja.
teams.write_access_helper=Tiimin jäsenet voivat lukea ja työntää tiimin varastoja/varastoihin.
teams.admin_access=Ylläpito-oikeus
@@ -1543,6 +1571,10 @@ repos.issues=Ongelmat
repos.size=Koko
packages.owner=Omistaja
+packages.name=Nimi
+packages.type=Tyyppi
+packages.repository=Repo
+packages.size=Koko
@@ -1630,6 +1662,8 @@ config.deliver_timeout=Toimitus aikakatkaisu
config.mailer_enabled=Käytössä
config.mailer_name=Nimi
+config.mailer_smtp_addr=SMTP osoite
+config.mailer_smtp_port=SMTP portti
config.mailer_user=Käyttäjä
config.oauth_config=OAuth asetukset
@@ -1679,10 +1713,10 @@ monitor.queue.name=Nimi
monitor.queue.type=Tyyppi
monitor.queue.pool.addworkers.desc=Lisää käsittelijöitä tähän pooliin aikakatkaisulla tai ilman. Jos asetat aikakatkaisun, nämä käsittelijät poistetaan poolista kun aikakatkaisu on päättynyt.
+monitor.queue.settings.submit=Päivitä asetukset
notices.system_notice_list=Järjestelmän ilmoitukset
-notices.actions=Toiminnot
notices.select_all=Valitse kaikki
notices.deselect_all=Poista kaikki valinnat
notices.inverse_selection=Käänteinen valinta
@@ -1756,6 +1790,7 @@ filter.no_result=Suodattimesi ei tuottanut tuloksia.
installation=Asennus
details.author=Tekijä
composer.documentation=Lisätietoa Composer-rekisteristä löydät <a target="_blank" rel="noopener noreferrer" href="https://docs.gitea.io/en-us/packages/composer/">dokumentaatiosta</a>.
+conan.details.repository=Repo
conan.documentation=Lisätietoa Conan-rekisteristä löydät <a target="_blank" rel="noopener noreferrer" href="https://docs.gitea.io/en-us/packages/conan/">dokumentaatiosta</a>.
container.documentation=Lisätietoa Container-rekisteristä löydät<a target="_blank" rel="noopener noreferrer" href="https://docs.gitea.io/en-us/packages/container/">dokumentaatiosta</a>.
generic.documentation=Lisätietoa yleisestä pakettirekisteristä löydät <a target="_blank" rel="noopener noreferrer" href="https://docs.gitea.io/en-us/packages/generic">dokumentaatiosta</a>.
@@ -1765,4 +1800,22 @@ nuget.documentation=Lisätietoa NuGet-rekisteristä löydät <a target="_blank"
npm.documentation=Lisätietoa npm-rekisteristä löydät <a target="_blank" rel="noopener noreferrer" href="https://docs.gitea.io/en-us/packages/npm/">dokumentaatiosta</a>.
pypi.documentation=Lisätietoa PyPI-rekisteristä löydät <a target="_blank" rel="noopener noreferrer" href="https://docs.gitea.io/en-us/packages/pypi/">dokumentaatiosta</a>.
rubygems.documentation=Lisätietoa RubyGems-rekisteristä löydät <a target="_blank" rel="noopener noreferrer" href="https://docs.gitea.io/en-us/packages/rubygems/">dokumentaatiosta</a>.
+owner.settings.cleanuprules.enabled=Käytössä
+
+[secrets]
+name=Nimi
+
+[actions]
+
+
+
+runners.name=Nimi
+runners.owner_type=Tyyppi
+runners.description=Kuvaus
+runners.task_list.run=Suorita
+runners.task_list.repository=Repo
+runners.task_list.commit=Commit
+
+runs.commit=Commit
+
diff --git a/options/locale/locale_fr-FR.ini b/options/locale/locale_fr-FR.ini
index c5c140404..15d20011e 100644
--- a/options/locale/locale_fr-FR.ini
+++ b/options/locale/locale_fr-FR.ini
@@ -41,7 +41,7 @@ webauthn_use_twofa=Utilisez l'authentification à deux facteurs avec votre télÃ
webauthn_error=Impossible de lire votre clé de sécurité.
webauthn_unsupported_browser=Votre navigateur ne prend actuellement pas en charge WebAuthn.
webauthn_error_unknown=Une erreur indéterminée s'est produite. Veuillez réessayer.
-webauthn_error_insecure=WebAuthn ne prend en charge que les connexions sécurisées. Pour les tests via HTTP, vous pouvez utiliser l'origine "localhost" ou "127.0.0.1"
+webauthn_error_insecure=`WebAuthn ne prend en charge que les connexions sécurisées. Pour les tests via HTTP, vous pouvez utiliser l'origine "localhost" ou "127.0.0.1"`
webauthn_error_unable_to_process=Le serveur n'a pas pu traiter votre demande.
webauthn_error_duplicated=La clé de sécurité n'est pas autorisée pour cette demande. Veuillez vous assurer que la clé n'est pas déjà enregistrée.
webauthn_error_empty=Vous devez définir un nom pour cette clé.
@@ -57,7 +57,6 @@ new_mirror=Nouveau miroir
new_fork=Nouvelle bifurcation
new_org=Nouvelle organisation
new_project=Nouveau projet
-new_project_board=Nouveau tableau de projet
manage_org=Gérer les organisations
admin_panel=Administration du site
account_settings=Paramètres du compte
@@ -86,6 +85,9 @@ remove=Retirer
remove_all=Tout Retirer
edit=Éditer
+enabled=Activé
+disabled=Désactivé
+
copy=Copier
copy_url=Copier l'URL
copy_branch=Copier le nom de la branche
@@ -106,6 +108,8 @@ never=Jamais
rss_feed=Flux RSS
+[aria]
+
[filter]
[error]
@@ -224,7 +228,6 @@ internal_token_failed=Impossible de générer le jeton interne : %v
secret_key_failed=Impossible de générer la clé secrète : %v
save_config_failed=L'enregistrement de la configuration %v a échoué
invalid_admin_setting=Paramètres du compte administrateur invalides : %v
-install_success=Bienvenue et merci d'avoir choisi Gitea. Profitez-en bien !
invalid_log_root_path=Le répertoire des fichiers de journalisation est invalide : %v
default_keep_email_private=Masquer les adresses e-mail par défaut
default_keep_email_private_popup=Masquer les adresses e-mail des nouveaux comptes utilisateurs par défaut.
@@ -280,7 +283,7 @@ repo_no_results=Aucun dépôt correspondant n'a été trouvé.
user_no_results=Aucun utilisateur correspondant n'a été trouvé.
org_no_results=Aucune organisation correspondante n'a été trouvée.
code_no_results=Aucun code source correspondant à votre terme de recherche n'a été trouvé.
-code_search_results=Résultats de recherche pour "%s"
+code_search_results=`Résultats de recherche pour "%s"`
code_last_indexed_at=Dernière indexation %s
relevant_repositories_tooltip=Les dépôts qui sont des forks ou qui n'ont aucun sujet, aucune icône et aucune description sont cachés.
relevant_repositories=Seuls les dépôts pertinents sont affichés, <a href="%s">afficher les résultats non filtrés</a>.
@@ -407,7 +410,7 @@ release.download.zip=Code source (ZIP)
release.download.targz=Code source (TAR.GZ)
repo.transfer.subject_to=%s aimerait transférer "%s" à %s
-repo.transfer.subject_to_you=%s aimerait vous transférer "%s"
+repo.transfer.subject_to_you=`%s aimerait vous transférer "%s"`
repo.transfer.to_you=vous
repo.transfer.body=Pour l'accepter ou le rejeter, visitez %s ou ignorez-le.
@@ -494,7 +497,7 @@ cannot_add_org_to_team=Une organisation ne peut être ajoutée comme membre d'un
invalid_ssh_key=Impossible de vérifier votre clé SSH : %s
invalid_gpg_key=Impossible de vérifier votre clé GPG : %s
invalid_ssh_principal=Principal invalide : %s
-unable_verify_ssh_key=Impossible de vérifier la clé SSH ; veuillez vérifier que vous n'avez pas fait d'erreur.
+unable_verify_ssh_key=Impossible de vérifier la clé SSH 
auth_failed=Échec d'authentification : %v
still_own_repo=Ce compte possède toujours un ou plusieurs dépôts, vous devez d'abord les supprimer ou les transférer.
@@ -523,7 +526,7 @@ user_bio=Biographie
disabled_public_activity=Cet utilisateur a désactivé la visibilité publique de l'activité.
form.name_reserved=Le nom d’utilisateur "%s" est réservé.
-form.name_pattern_not_allowed="%s" n'est pas autorisé dans un nom d'utilisateur.
+form.name_pattern_not_allowed=`"%s\" n'est pas autorisé dans un nom d'utilisateur.`
form.name_chars_not_allowed=Le nom d'utilisateur '%s' contient des caractères non valides.
[settings]
@@ -644,177 +647,62 @@ add_key=Ajouter une clé
ssh_desc=Ces clefs SSH publiques sont associées à votre compte. Les clefs privées correspondantes permettent l'accès complet à vos dépôts.
principal_desc=Ces principaux certificats SSH sont associés à votre compte et permettent un accès complet à vos dépôts.
gpg_desc=Ces clefs GPG sont associées avec votre compte. Conservez-les en lieu sûr car elles permettent la vérification de vos révisions.
-ssh_helper=<strong>Besoin d'aide ?</strong> Consultez le guide Github pour <a href="%s">générer votre clé SSH</a> ou résoudre les <a href="%s">problèmes courants</a> que vous pouvez rencontrer en utilisant SSH.
-gpg_helper=<strong>Besoin d'aide ?</strong> Consultez le guide Github à propos de <a href="%s">GPG</a>.
-add_new_key=Ajouter une clé SSH
-add_new_gpg_key=Ajouter une clé GPG
-key_content_ssh_placeholder=Commence par 'ssh-ed25519', 'ssh-rsa', 'ecdsa-sha2-nistp256', 'ecdsa-sha2-nistp384', 'ecdsa-sha2-nistp521', 'sk-ecdsa-sha2-nistp256@openssh.com', ou 'sk-ssh-ed25519@openssh.com'
-key_content_gpg_placeholder=Commence par '-----BEGIN PGP PUBLIC KEY BLOCK-----'
-add_new_principal=Ajouter le principal
-ssh_key_been_used=Cette clef SSH a déjà été ajoutée au serveur.
-ssh_key_name_used=Une clé SSH avec le même nom existe déjà sur votre compte.
-ssh_principal_been_used=Ce principal a déjà été ajouté au serveur.
-gpg_key_id_used=Une clef GPG publique avec le même identifiant existe déjà.
-gpg_no_key_email_found=Cette clé GPG ne correspond à aucune adresse e-mail activée et associée avec votre compte. Elle peut toujours être ajoutée si vous signez le jeton fourni.
-gpg_key_matched_identities=Identités correspondantes :
-gpg_key_matched_identities_long=Les identités embarquées dans cette clé correspondent à l'adresse courriel activée ci-après pour cet utilisateur. Les révisions correspondantes à cette adresse courriel peuvent être vérifiés avec cette clé.
-gpg_key_verified=Clé vérifiée
-gpg_key_verified_long=La clé a été vérifiée avec un jeton et peut être utilisée pour vérifier les commits correspondant à toutes les adresses courriel pour cet utilisateur en plus de toutes les identités pour cette clé.
+ssh_helper=`<strong>Besoin d'aide ?</strong> Consultez le guide Github pour <a href="`
+
+[settings]
+profile=Profil
+password=Mot de passe
+orgs=Gérer les organisations
+repos=Dépôts
+twofa=Authentification à deux facteurs
+organization=Organisations
+
+full_name=Non Complet
+website=Site Web
+location=Localisation
+cancel=Annuler
+language=Langue
+comment_type_group_title=Titre
+
+
+password_change_disabled=Les mots de passes des comptes utilisateurs externes ne peuvent pas être modifiées depuis l'interface web Gitea.
+
+primary=Principale
+activated=Activé
+delete_email=Exclure
+
gpg_key_verify=Vérifier
-gpg_invalid_token_signature=La clé GPG fournie, la signature et le jeton ne correspondent pas ou le jeton n'est pas à jour.
-gpg_token_required=Vous devez fournir une signature pour le jeton ci-dessous
gpg_token=Jeton
-gpg_token_help=Vous pouvez générer une signature en utilisant :
-gpg_token_code=echo "%s" | gpg -a --default-key %s --detach-sig
-gpg_token_signature=Signature GPG renforcée
-key_signature_gpg_placeholder=Commence par '-----BEGIN PGP SIGNATURE-----'
-verify_gpg_key_success=La clef GPG '%s' a été vérifiée.
-ssh_key_verified=Clé vérifiée
-ssh_key_verified_long=La clé a été vérifiée avec un jeton et peut être utilisée pour vérifier les commits correspondant à toutes les adresses courriel activées pour cet utilisateur.
ssh_key_verify=Vérifier
-ssh_invalid_token_signature=La clé SSH, la signature ou le jeton fournis ne correspondent pas ou le jeton n'est pas à jour.
-ssh_token_required=Vous devez fournir une signature pour le jeton ci-dessous
ssh_token=Jeton
-ssh_token_help=Vous pouvez générer une signature en utilisant :
-ssh_token_signature=Signature SSH renforcée
-key_signature_ssh_placeholder=Commence par '-----BEGIN PGP SIGNATURE-----'
-verify_ssh_key_success=La clef SSH '%s' a été vérifiée.
-subkeys=Sous-clés
-key_id=Clé ID
-key_name=Nom de la Clé
key_content=Contenu
principal_content=Contenu
-add_key_success=La clef SSH "%s" a été ajoutée.
-add_gpg_key_success=La clef GPG "%s" a été ajoutée.
-add_principal_success=Le certificat SSH principal '%s' a été ajouté.
-delete_key=Supprimer
-ssh_key_deletion=Supprimer la clé SSH
-gpg_key_deletion=Supprimer la clé GPG
-ssh_principal_deletion=Supprimer le certificat SSH principal
-ssh_key_deletion_desc=La suppression d'une clé SSH révoque son accès à votre compte. Continuer ?
-gpg_key_deletion_desc=Retirer une clef GPG annule la vérification des révisions l'utilisant. Continuer ?
-ssh_principal_deletion_desc=La suppression d'un certificat principal SSH révoque son accès à votre compte. Continuer ?
-ssh_key_deletion_success=La clé SSH a été retirée.
-gpg_key_deletion_success=La clé GPG a été retirée.
-ssh_principal_deletion_success=Le principal a été supprimé.
-add_on=Ajouté le
-valid_until=Valide jusqu’à
-valid_forever=Valide pour toujours
-last_used=Dernière utilisation le
-no_activity=Aucune activité récente
-can_read_info=Lecture
-can_write_info=Écriture
-key_state_desc=Cette clé a été utilisée durant les 7 derniers jours
-token_state_desc=Ce jeton a été utilisé durant les 7 derniers jours
-principal_state_desc=Ce principal a été utilisé au cours des 7 derniers jours
-show_openid=Afficher sur mon profil
-hide_openid=Masquer du profil
-ssh_disabled=SSH désactivé
-ssh_externally_managed=Cette clé SSH est gérée de manière externe pour cet utilisateur
-manage_social=Gérer les réseaux sociaux associés
-social_desc=Ces réseaux sociaux sont liés à votre compte Gitea. Veuillez vous assurer que vous les reconnaissez tous car ils peuvent être utilisés pour se connecter à votre compte Gitea.
-unbind=Dissocier
-unbind_success=Le réseau social a été dissocié de votre compte Gitea.
-
-manage_access_token=Gérer les jetons d'accès
-generate_new_token=Générer le nouveau jeton
-tokens_desc=Ces jetons permettent l'accès à votre compte à travers l'API Gitea.
-new_token_desc=Les applications utilisant un jeton ont un accès total à votre compte.
-token_name=Nom du jeton
-generate_token=Générer le jeton
-generate_token_success=Votre nouveau jeton a été généré. Copiez-le maintenant car il ne sera plus jamais affiché ici.
-generate_token_name_duplicate=<strong>%s</strong> a déjà été utilisé comme nom d'application. Veuillez en utiliser un nouveau.
+delete_key=Exclure
+can_read_info=Lue(s)
+
delete_token=Supprimer
-access_token_deletion=Suppression de jetons d'accès
access_token_deletion_cancel_action=Annuler
access_token_deletion_confirm_action=Supprimer
-access_token_deletion_desc=Supprimer un jeton révoquera l'accès à votre compte pour toutes les applications l'utilisant. Cette action est irréversible. Continuer ?
-delete_token_success=Ce jeton a été supprimé. Les applications l'utilisant n'ont plus accès à votre compte.
-
-manage_oauth2_applications=Gérer les applications OAuth2
-edit_oauth2_application=Modifier l'application OAuth2
-oauth2_applications_desc=Les applications OAuth2 permettent à votre application tiers d'authentifier en toute sécurité les utilisateurs de cette instance Gitea.
-remove_oauth2_application=Supprimer l'application OAuth2
-remove_oauth2_application_desc=Supprimer une application OAuth2 révoquera l'accès à tous les jetons d'accès signés. Continuer ?
-remove_oauth2_application_success=L'application a été supprimée.
-create_oauth2_application=Créer une nouvelle application OAuth2
-create_oauth2_application_button=Créer une application
-create_oauth2_application_success=Vous avez créé avec succès une nouvelle application OAuth2.
-update_oauth2_application_success=Vous avez mis à jour l'application OAuth2 avec succès.
-oauth2_application_name=Nom de l'Application
-oauth2_redirect_uri=URL de redirection
+
save_application=Enregistrer
-oauth2_client_id=ID du client
-oauth2_client_secret=Secret du Client
-oauth2_regenerate_secret=Régénérer le Secret
-oauth2_regenerate_secret_hint=Vous avez perdu votre secret ?
-oauth2_client_secret_hint=Le secret ne sera pas visible si vous revisitez cette page. Veuillez sauvegarder votre secret.
-oauth2_application_edit=Modifier
-oauth2_application_create_description=Les applications OAuth2 donnent à votre application tierce un accès aux comptes utilisateurs sur cette instance.
-oauth2_application_remove_description=Supprimer une application OAuth2 l'empêchera d'accéder aux comptes utilisateurs autorisés dans cette instance. Continuer ?
-
-authorized_oauth2_applications=Applications OAuth2 autorisées
-authorized_oauth2_applications_description=Vous avez autorisé l'accès à votre compte Gitea à ces applications tierces. Veuillez révoquer l'accès aux applications qui ne sont plus nécessaires.
-revoke_key=Révoquer
-revoke_oauth2_grant=Révoquer l'accès
-revoke_oauth2_grant_description=Révoquer l'accès à cette application tierce empêchera cette application d'accéder à vos données. Êtes-vous sûr ?
-revoke_oauth2_grant_success=Vous avez révoqué l'accès avec succès.
-
-twofa_desc=L'authentification à deux facteurs améliore la sécurité de votre compte.
-twofa_is_enrolled=Votre compte est <strong>inscrit</strong> à l'authentification à deux facteurs.
-twofa_not_enrolled=Votre compte n'est pas inscrit à l'authentification à deux facteurs.
-twofa_disable=Désactiver l'authentification à deux facteurs
-twofa_scratch_token_regenerate=Regénérer un code de secours
-twofa_scratch_token_regenerated=Votre jeton de secours est maintenant %s. Gardez-le en lieu sûr.
-twofa_enroll=Activer l'authentification à deux facteurs
-twofa_disable_note=Vous pouvez désactiver l'authentification à deux facteurs si nécessaire.
-twofa_disable_desc=Désactiver l'authentification à deux facteurs rendra votre compte plus vulnérable. Souhaitez-vous confirmer ?
-regenerate_scratch_token_desc=Si vous avez perdu votre code de secours, ou avez dû l'utiliser pour vous authentifier, vous pouvez le réinitialiser.
-twofa_disabled=L'authentification à deux facteurs a été désactivée.
-scan_this_image=Scannez cette image avec votre application d'authentification :
-or_enter_secret=Ou saisissez le code secret: %s
-then_enter_passcode=Et entrez le mot de passe s'affichant dans l'application :
-passcode_invalid=Le mot de passe est invalide. Réessayez.
-twofa_enrolled=L'authentification à deux facteurs a été activée pour votre compte. Gardez votre jeton de secours (%s) en lieu sûr car il ne vous sera montré qu'une seule fois !
-twofa_failed_get_secret=Impossible d'obtenir le secret.
-
-webauthn_desc=Les clefs de sécurité sont des dispositifs matériels contenant des clefs cryptographiques. Elles peuvent être utilisées pour l'authentification à deux facteurs. La clef de sécurité doit supporter le standard <a rel="noreferrer" target="_blank" href="https://w3c.github.io/webauthn/#webauthn-authenticator">WebAuthn Authenticator</a>.
-webauthn_register_key=Ajouter une clé de sécurité
-webauthn_nickname=Pseudonyme
-webauthn_delete_key=Supprimer la clé de sécurité
-webauthn_delete_key_desc=Si vous retirez une clé de sécurité vous ne pourrez plus l'utiliser pour vous connecter. Continuer ?
-
-manage_account_links=Gérer les comptes liés
-manage_account_links_desc=Ces comptes externes sont liés à votre compte Gitea.
-account_links_not_available=Il n'y a pour l'instant pas de compte externe connecté à votre compte Gitea.
+oauth2_client_secret=Secret du client
+oauth2_application_edit=Éditer
+
+
+
+
link_account=Lier un Compte
-remove_account_link=Supprimer un compte lié
-remove_account_link_desc=Supprimer un compte lié révoquera son accès à votre compte Gitea. Continuer ?
-remove_account_link_success=Le compte lié a été supprimé.
-orgs_none=Vous n'êtes membre d'aucune organisation.
-repos_none=Vous ne possédez aucun dépôt
-delete_account=Supprimer votre compte
-delete_prompt=Cette opération supprimera votre compte. Ceci <strong>NE PEUT PAS</strong> être annulé.
-delete_with_all_comments=Votre compte est plus jeune que %s. Pour éviter les commentaires fantôme, tous les commentaires de ticket/PR seront supprimés avec lui.
-confirm_delete_account=Confirmer la suppression
-delete_account_title=Supprimer un compte
-delete_account_desc=Êtes-vous sûr de vouloir supprimer définitivement ce compte ?
+
+confirm_delete_account=Confirmez la suppression
+delete_account_title=Supprimer cet utilisateur
email_notifications.enable=Activer les notifications par e-mail
-email_notifications.onmention=N'envoyer un e-mail que si vous êtes mentionné
-email_notifications.disable=Désactiver les notifications par email
-email_notifications.submit=Définir la préférence e-mail
-email_notifications.andyourown=Et vos propres notifications
-
-visibility=Visibilité de l'utilisateur
-visibility.public=Publique
-visibility.public_tooltip=Visible par tous les utilisateurs
-visibility.limited=Limitée
-visibility.limited_tooltip=Visible uniquement par les utilisateurs connectés
-visibility.private=Privée
-visibility.private_tooltip=Visible uniquement par les membres de l'organisation
+
+visibility.public=Public
+visibility.limited=Limité
+visibility.private=Privé
[repo]
new_repo_helper=Un dépôt contient tous les fichiers du projet, y compris l'historique des révisions. Vous l'avez déjà ailleurs ? <a href="%s">Migrer le dépôt.</a>
@@ -903,9 +791,9 @@ delete_preexisting_success=Supprimer les fichiers non adoptés dans %s
blame_prior=Voir le blame avant cette modification
transfer.accept=Accepter le transfert
-transfer.accept_desc=Transférer à "%s"
+transfer.accept_desc=`Transférer à "%s"`
transfer.reject=Refuser le transfert
-transfer.reject_desc=Annuler le transfert à "%s"
+transfer.reject_desc=`Annuler le transfert à "%s"`
transfer.no_permission_to_accept=Vous n’avez pas la permission pour accepter
transfer.no_permission_to_reject=Vous n'avez pas la permission pour rejeter
@@ -935,7 +823,7 @@ archive.pull.nocomment=Ce dépôt est archivé. Vous ne pouvez pas commenter de
form.reach_limit_of_creation_1=Vous avez déjà atteint la limite d'%d dépôt.
form.reach_limit_of_creation_n=Vous avez déjà atteint la limite de %d dépôts.
form.name_reserved=Le dépôt "%s" a un nom réservé.
-form.name_pattern_not_allowed="%s" n'est pas autorisé dans un nom de dépôt.
+form.name_pattern_not_allowed=`"%s\" n'est pas autorisé dans un nom de dépôt.`
need_auth=Autorisation
migrate_options=Options de migration
@@ -943,7 +831,9 @@ migrate_service=Service de migration
migrate_options_mirror_helper=Ce dépôt sera un miroir
migrate_options_lfs=Migrer les fichiers LFS
migrate_options_lfs_endpoint.label=Point d'accès LFS
-migrate_options_lfs_endpoint.description=La migration va tenter d'utiliser votre dépôt Git distant pour <a target="_blank" rel="noopener noreferrer" href="%s">déterminer le serveur LFS</a>. Vous pouvez également spécifier un point d'accès personnalisé si les données LFS du dépôt sont stockées ailleurs.
+migrate_options_lfs_endpoint.description=`La migration va tenter d'utiliser votre dépôt Git distant pour <a target="`
+
+migrate_options_lfs_endpoint.label=Point d'accès LFS
migrate_options_lfs_endpoint.description.local=Un chemin de serveur local est également pris en charge.
migrate_options_lfs_endpoint.placeholder=Laisser vide pour dériver de l'URL de clonage
migrate_items=Éléments à migrer
@@ -1152,7 +1042,6 @@ commits.signed_by_untrusted_user_unmatched=Signé par un utilisateur non fiable
commits.gpg_key_id=ID de la clé GPG
commits.ssh_key_fingerprint=Empreinte numérique de la clé SSH
-commit.actions=Actions
commit.revert=Rétablir
commit.revert-header=Rétablir : %s
commit.revert-content=Sélectionnez la branche sur laquelle revenir :
@@ -1184,16 +1073,9 @@ projects.type.bug_triage=Bug à trier
projects.template.desc=Modèle de projet
projects.template.desc_helper=Sélectionnez un modèle de projet pour débuter
projects.type.uncategorized=Non catégorisé
-projects.board.edit=Modifier le tableau
-projects.board.edit_title=Nom du nouveau tableau
-projects.board.new_title=Nom du nouveau tableau
-projects.board.new_submit=Soumettre
-projects.board.new=Nouveau tableau
-projects.board.set_default=Définir par défaut
-projects.board.set_default_desc=Définir ce tableau comme valeur par défaut pour les tickets et demande d'ajouts non catégorisés
-projects.board.delete=Supprimer le tableau
-projects.board.deletion_desc=La suppression d'un tableau de projet déplace tous les tickets liés dans 'Non catégorisé'. Voulez vous continuer ?
-projects.board.color=Couleur
+projects.column.edit_title=Nom
+projects.column.new_title=Nom
+projects.column.color=Couleur
projects.open=Ouvrir
projects.close=Fermer
@@ -1266,6 +1148,7 @@ issues.filter_label_exclude=`Utiliser <code>alt</code> + <code>clic/entrée</cod
issues.filter_label_no_select=Toutes les étiquettes
issues.filter_milestone=Jalon
issues.filter_milestone_no_select=Tous les jalons
+issues.filter_project_none=Pas de projet
issues.filter_assignee=Assigné
issues.filter_assginee_no_select=Toutes les affectations
issues.filter_poster=Auteur
@@ -1302,6 +1185,7 @@ issues.previous=Page Précédente
issues.next=Page Suivante
issues.open_title=Ouvert
issues.closed_title=Fermé
+issues.draft_title=Brouillon
issues.num_comments=%d commentaires
issues.commented_at=`a commenté <a href="#%s"> %s</a>`
issues.delete_comment_confirm=Êtes-vous certain de vouloir supprimer ce commentaire?
@@ -1380,6 +1264,7 @@ issues.lock.reason=Motif de verrouillage
issues.lock.title=Verrouiller la conversation sur ce ticket.
issues.unlock.title=Déverrouiller la conversation sur ce ticket.
issues.comment_on_locked=Vous ne pouvez pas commenter un ticket verrouillé.
+issues.delete=Supprimer
issues.tracker=Suivi du temps
issues.start_tracking_short=Démarrer le suivi de temps
issues.start_tracking=Démarrer le suivi du temps
@@ -1408,6 +1293,7 @@ issues.error_removing_due_date=Impossible de supprimer l'échéance.
issues.push_commit_1=a ajouté %d révision %s
issues.push_commits_n=a ajouté %d révisions %s
issues.force_push_codes=`a forcé la poussée %[1]s de <a class="ui sha" href="%[3]s"><code>%[2]s</code></a> vers <a class="ui sha" href="%[5]s"><code>%[4]s</code></a> %[6]s`
+issues.force_push_compare=Comparer
issues.due_date_form=aaaa-mm-jj
issues.due_date_form_add=Ajouter une échéance
issues.due_date_form_edit=Éditer
@@ -1725,9 +1611,14 @@ activity.git_stats_deletion_n=%d suppressions
search=Chercher
search.search_repo=Rechercher dans le dépôt
+search.type.tooltip=Type de recherche
search.fuzzy=Approximative
+search.fuzzy.tooltip=Inclure également les résultats proches de la recherche
search.match=Exacte
+search.match.tooltip=Inclure uniquement les résultats exacts
search.results=Résultats de la recherche « %s » dans <a href="%s"> %s</a>
+search.code_no_results=Aucun code source correspondant à votre terme de recherche n'a été trouvé.
+search.code_search_unavailable=Actuellement, la recherche de code n'est pas disponible. Veuillez contacter l'administrateur de votre site.
settings=Paramètres
settings.desc=Les paramètres sont l'endroit où gérer les options du dépôt
@@ -1775,11 +1666,6 @@ settings.enable_timetracker=Activer le suivi du temps
settings.allow_only_contributors_to_track_time=Restreindre le suivi de temps aux contributeurs
settings.pulls_desc=Activer les demandes de fusion
settings.pulls.ignore_whitespace=Ignorer les espaces lors des conflits
-settings.pulls.allow_merge_commits=Activer la fusion de révisions
-settings.pulls.allow_rebase_merge=Activer le rebasage pour la fusion de révisions
-settings.pulls.allow_rebase_merge_commit=Activer le rebasage avec un commit de fusion explicite (--no-ff)
-settings.pulls.allow_squash_commits=Activer la concaténation de révisions
-settings.pulls.allow_manual_merge=Activer le marquage des demandes d'ajout comme fusionnées manuellement
settings.pulls.enable_autodetect_manual_merge=Activer la détection automatique de la fusion manuelle (Remarque : dans certains cas particuliers, des erreurs de détection peuvent se produire)
settings.pulls.allow_rebase_update=Activer la mise à jour de demande d'ajout par rebase
settings.pulls.default_delete_branch_after_merge=Supprimer la branche après la fusion par default
@@ -1813,7 +1699,7 @@ settings.transfer_notices_2=- Vous conserverez l'accès à ce dépôt si vous le
settings.transfer_notices_3=- Si le dépôt est privé et est transféré à un utilisateur individuel, cette action s'assure que l'utilisateur a au moins la permission de lire (et modifie les permissions si nécessaire).
settings.transfer_owner=Nouveau propriétaire
settings.transfer_perform=Effectuer le transfert
-settings.transfer_started=Ce dépôt a été marqué pour le transfert et attend la confirmation de "%s"
+settings.transfer_started=`Ce dépôt a été marqué pour le transfert et attend la confirmation de "%s"`
settings.transfer_succeed=Le dépôt a été transféré.
settings.signing_settings=Paramètres de vérification de la signature
settings.trust_model=Modèle de confiance de la signature
@@ -1885,6 +1771,7 @@ settings.content_type=Type de contenu POST
settings.secret=Secret
settings.slack_username=Nom d'utilisateur
settings.slack_icon_url=URL de l'icône
+settings.slack_color=Couleur
settings.discord_username=Nom d'utilisateur
settings.discord_icon_url=URL de l'icône
settings.event_desc=Événement déclencheur :
@@ -1898,6 +1785,7 @@ settings.event_delete=Suppression
settings.event_delete_desc=Branche ou étiquette supprimée.
settings.event_fork=Bifurcation
settings.event_fork_desc=Dépôt bifurqué.
+settings.event_wiki=Wiki
settings.event_release=Version
settings.event_release_desc=Version publiée, mise à jour ou supprimée dans un dépôt.
settings.event_push=Poussée
@@ -1961,7 +1849,7 @@ settings.protected_branch=Protection de branche
settings.protected_branch_can_push=Autoriser la poussée ?
settings.protected_branch_can_push_yes=Vous pouvez pousser
settings.protected_branch_can_push_no=Vous ne pouvez pas pousser
-settings.branch_protection=Protection de la branche "<b>%s</b>"
+settings.branch_protection=`Protection de la branche "<b>%s</b>"`
settings.protect_this_branch=Protection de la branche
settings.protect_this_branch_desc=Empêche les suppressions et limite les poussées et fusions sur cette branche.
settings.protect_disable_push=Désactiver le push
@@ -2011,11 +1899,11 @@ settings.choose_branch=Choisissez une branche…
settings.no_protected_branch=Il n'y a pas de branche protégée.
settings.edit_protected_branch=Éditer
settings.protected_branch_required_approvals_min=Le nombre de revues nécessaires ne peut être négatif.
+settings.tags=Tags
settings.bot_token=Jeton de Bot
settings.chat_id=ID de conversation
settings.matrix.homeserver_url=URL du serveur d'accueil
settings.matrix.room_id=ID de la salle
-settings.matrix.access_token=Jeton d'accès
settings.matrix.message_type=Type de message
settings.archive.button=Archiver ce dépôt
settings.archive.header=Archiver ce dépôt
@@ -2165,6 +2053,7 @@ branch.included_desc=Cette branche fait partie de la branche par défaut
branch.included=Incluses
branch.create_new_branch=Créer une branche à partir de la branche :
branch.confirm_create_branch=Créer une branche
+branch.create_branch_operation=Créer une branche
branch.new_branch=Créer une nouvelle branche
branch.new_branch_from=Créer une nouvelle branche à partir de '%s'
@@ -2183,7 +2072,7 @@ org_full_name_holder=Nom complet de l'organisation
org_name_helper=Le nom de l'organisation doit être court et mémorable.
create_org=Créer une organisation
repo_updated=Mis à jour
-people=Contacts
+members=Membres
teams=Équipes
lower_members=Membres
lower_repositories=dépôts
@@ -2200,7 +2089,7 @@ team_unit_desc=Permettre l’accès aux Sections du dépôt
team_unit_disabled=(Désactivé)
form.name_reserved=Le nom d'organisation "%s" est réservé.
-form.name_pattern_not_allowed="%s" n'est pas autorisé dans un nom d'organisation.
+form.name_pattern_not_allowed=`"%s\" n'est pas autorisé dans un nom d'organisation.`
form.create_org_not_allowed=Vous n'êtes pas autorisé à créer une organisation.
settings=Paramètres
@@ -2441,6 +2330,256 @@ packages.published=Publiés
systemhooks=Rappels système
+systemhooks.desc=`Les Webhooks font automatiquement des requêtes HTTP POST à un serveur lorsque certains événements Gitea se déclenchent. Les Webhooks définis ici agiront sur tous les dépots du système, donc veuillez prendre en compte les implications en termes de performances que cela peut avoir. Lire la suite dans le <a target="`
+form.create_org_not_allowed=Vous n'êtes pas autorisé à créer une organisation.
+
+settings=Paramètres
+settings.options=Organisation
+settings.full_name=Non Complet
+settings.website=Site Web
+settings.location=Localisation
+settings.permission=Autorisations
+settings.repoadminchangeteam=L'administrateur de dépôt peut ajouter et supprimer l'accès aux équipes
+settings.visibility=Visibilité
+settings.visibility.public=Public
+settings.visibility.limited=Limité (Visible uniquement aux utilisateurs connectés)
+settings.visibility.limited_shortname=Limité
+settings.visibility.private=Privé (Visible uniquement aux membres de l’organisation)
+settings.visibility.private_shortname=Privé
+
+settings.update_settings=Valider
+settings.update_setting_success=Les paramètres de l'organisation ont été mis à jour.
+settings.change_orgname_prompt=NB: changer le nom de l'organisation changera aussi son URL.
+settings.change_orgname_redirect_prompt=L'ancien nom d'utilisateur redirigera jusqu'à ce qu'il soit réclamé.
+settings.update_avatar_success=L'avatar de l'organisation a été mis à jour.
+settings.delete=Supprimer l'organisation
+settings.delete_account=Supprimer cette organisation
+settings.delete_prompt=Cette organisation sera supprimée définitivement. Cette opération est <strong>IRRÉVERSIBLE</strong> !
+settings.confirm_delete_account=Confirmez la suppression
+settings.delete_org_title=Supprimer l'organisation
+settings.delete_org_desc=Cette organisation sera supprimée définitivement. Voulez-vous continuer ?
+settings.hooks_desc=Vous pouvez ajouter des webhooks qui seront activés pour <strong>tous les dépôts</strong> de cette organisation.
+
+settings.labels_desc=Ajouter des étiquettes qui peuvent être utilisées sur les tickets pour <strong>tous les dépôts</strong> dans cette organisation.
+
+members.membership_visibility=Visibilité des membres:
+members.public=Public
+members.public_helper=rendre caché
+members.private=Caché
+members.private_helper=rendre visible
+members.member_role=Rôle du membre :
+members.owner=Propriétaire
+members.member=Membre
+members.remove=Exclure
+members.remove.detail=Supprimer %[1]s de %[2]s?
+members.leave=Quitter
+members.leave.detail=Quitter %s?
+members.invite_desc=Ajouter un nouveau membre à %s :
+members.invite_now=Envoyer une invitation
+
+teams.join=Rejoindre
+teams.leave=Quitter
+teams.leave.detail=Quitter %s?
+teams.can_create_org_repo=Créer des dépôts
+teams.can_create_org_repo_helper=Les membres peuvent créer de nouveaux dépôts dans l'organisation. Le créateur obtiendra l'accès administrateur au nouveau dépôt.
+teams.read_access=Lue(s)
+teams.read_access_helper=Les membres peuvent voir et cloner les dépôts de l'équipe.
+teams.write_access_helper=Les membres peuvent voir et pousser dans les dépôts de l'équipe.
+teams.admin_access=Accès Administrateur
+teams.admin_access_helper=Les membres peuvent tirer et pousser des modifications vers les dépôts de l'équipe, et y ajouter des collaborateurs.
+teams.no_desc=Aucune description
+teams.settings=Paramètres
+teams.owners_permission_desc=Les propriétaires ont un accès complet à <strong>tous les dépôts</strong> et disposent <strong> d'un accès administrateur</strong> de l'organisation.
+teams.members=Membres de L'Équipe
+teams.update_settings=Valider
+teams.delete_team=Supprimer l'équipe
+teams.add_team_member=Ajouter un Membre
+teams.delete_team_title=Supprimer l'équipe
+teams.delete_team_desc=Supprimer une équipe supprime l'accès aux dépôts à ses membres. Continuer ?
+teams.delete_team_success=L’équipe a été supprimée.
+teams.read_permission_desc=Cette équipe permet l'accès en <strong>lecture</strong> : les membres peuvent voir et dupliquer ses dépôts.
+teams.write_permission_desc=Cette équipe permet l'accès en <strong>écriture</strong> : les membres peuvent participer à ses dépôts.
+teams.admin_permission_desc=Cette équipe permet l'accès <strong>administrateur</strong> : les membres peuvent voir, participer et ajouter des collaborateurs à ses dépôts.
+teams.create_repo_permission_desc=De plus, cette équipe accorde la permission <strong>Créer un dépôt</strong> : les membres peuvent créer de nouveaux dépôts dans l'organisation.
+teams.repositories=Dépôts de l'Équipe
+teams.search_repo_placeholder=Rechercher dans le dépôt…
+teams.remove_all_repos_title=Supprimer tous les dépôts de l'équipe
+teams.remove_all_repos_desc=Ceci supprimera tous les dépôts de l'équipe.
+teams.add_all_repos_title=Ajouter tous les dépôts
+teams.add_all_repos_desc=Ceci ajoutera tous les dépôts de l'organisation à l'équipe.
+teams.add_nonexistent_repo=Dépôt inexistant, veuillez d'abord le créer.
+teams.add_duplicate_users=L’utilisateur est déjà un membre de l’équipe.
+teams.repos.none=Aucun dépôt n'est accessible par cette équipe.
+teams.members.none=Aucun membre dans cette équipe.
+teams.specific_repositories=Dépôts spécifiques
+teams.specific_repositories_helper=Les membres auront seulement accès aux dépôts explicitement ajoutés à l'équipe. Sélectionner ceci <strong>ne supprimera pas automatiquement</strong> les dépôts déjà ajoutés avec <i>Tous les dépôts</i>.
+teams.all_repositories=Tous les dépôts
+teams.all_repositories_helper=L'équipe a accès à tous les dépôts. Sélectionner ceci <strong>ajoutera tous les dépôts existants</strong> à l'équipe.
+teams.all_repositories_read_permission_desc=Cette équipe accorde l'accès <strong>en lecture</strong> à <strong>tous les dépôts</strong> : les membres peuvent voir et cloner les dépôts.
+teams.all_repositories_write_permission_desc=Cette équipe accorde l'accès <strong>en écriture</strong> à <strong>tous les dépôts</strong> : les membres peuvent lire et écrire dans les dépôts.
+teams.all_repositories_admin_permission_desc=Cette équipe accorde l'accès <strong>administrateur</strong> à <strong>tous les dépôts</strong> : les membres peuvent lire, écrire dans et ajouter des collaborateurs aux dépôts.
+
+[admin]
+dashboard=Tableau de bord
+users=Comptes utilisateurs
+organizations=Organisations
+repositories=Dépôts
+authentication=Sources d'authentification
+emails=Courriels de l'utilisateur
+config=Configuration
+notices=Informations
+monitor=Surveillance
+first_page=Première
+last_page=Dernière
+total=Total : %d
+
+dashboard.statistic=Résumé
+dashboard.operations=Opérations de maintenance
+dashboard.system_status=État du système
+dashboard.operation_name=Nom de l'Opération
+dashboard.operation_switch=Basculer
+dashboard.operation_run=Exécuter
+dashboard.clean_unbind_oauth=Effacer les connexions OAuth associées
+dashboard.clean_unbind_oauth_success=Toutes les connexions OAuth associées ont été supprimées.
+dashboard.task.started=Tâche démarrée: %[1]s
+dashboard.task.process=Tâche: %[1]s
+dashboard.task.cancelled=Tâche: %[1]s a annulé: %[3]s
+dashboard.task.error=Erreur dans la tâche: %[1]s: %[3]s
+dashboard.task.finished=Tâche: %[1]s démarrée par %[2]s est terminée
+dashboard.task.unknown=Tâche inconnue: %[1]s
+dashboard.cron.process=Tâche planifiée: %[1]s
+dashboard.cron.cancelled=Tâche planifiée : %s annulée : %[3]s
+dashboard.cron.error=Erreur dans la tâche planifiée : %s: %[3]s
+dashboard.cron.finished=Tâche planifiée : %[1]s a terminé
+dashboard.delete_inactive_accounts=Supprimer tous les comptes non actifs
+dashboard.delete_inactive_accounts.started=Tâche de suppression de tous les comptes inactifs démarrée.
+dashboard.delete_repo_archives=Supprimer toutes les archives des dépôts (ZIP, TAR.GZ, etc..)
+dashboard.delete_repo_archives.started=Tâche de suppression de toutes les archives de dépôts démarrée.
+dashboard.delete_missing_repos=Supprimer tous les dépôts dont les fichiers Git sont manquants
+dashboard.delete_missing_repos.started=Tâche de suppression de tous les dépôts sans fichiers Git démarrée.
+dashboard.delete_generated_repository_avatars=Supprimer les avatars de dépôt générés
+dashboard.update_mirrors=Mettre à jour les miroirs
+dashboard.repo_health_check=Vérifier l'état de santé de tous les dépôts
+dashboard.check_repo_stats=Voir les statistiques de tous les dépôts
+dashboard.archive_cleanup=Supprimer les archives des vieux dépôts
+dashboard.deleted_branches_cleanup=Nettoyer les branches supprimées
+dashboard.git_gc_repos=Collecter les déchets des dépôts
+dashboard.resync_all_sshkeys.desc=(Inutile pour le serveur SSH intégré.)
+dashboard.resync_all_sshprincipals.desc=(Inutile pour le serveur SSH intégré.)
+dashboard.resync_all_hooks=Re-synchroniser les déclencheurs Git pre-receive, update et post-receive de tous les dépôts.
+dashboard.reinit_missing_repos=Réinitialiser tous les dépôts Git manquants pour lesquels un enregistrement existe
+dashboard.sync_external_users=Synchroniser les données de l’utilisateur externe
+dashboard.cleanup_hook_task_table=Nettoyer la table hook_task
+dashboard.server_uptime=Uptime du serveur
+dashboard.current_goroutine=Goroutines actuelles
+dashboard.current_memory_usage=Utilisation Mémoire actuelle
+dashboard.total_memory_allocated=Mémoire totale allouée
+dashboard.memory_obtained=Mémoire obtenue
+dashboard.pointer_lookup_times=Nombre de Consultations Pointeur
+dashboard.memory_allocate_times=Allocations de mémoire
+dashboard.memory_free_times=Nombre de libérations de mémoire
+dashboard.current_heap_usage=Utilisation Tas (Heap)
+dashboard.heap_memory_obtained=Mémoire Tas (Heap) obtenue
+dashboard.heap_memory_idle=Mémoire Tas (Heap) au Repos
+dashboard.heap_memory_in_use=Utilisation Mémoire Tas (Heap)
+dashboard.heap_memory_released=Mémoire Tas (Heap) libérée
+dashboard.heap_objects=Objets Tas (Heap)
+dashboard.bootstrap_stack_usage=Utilisation Pile Bootstrap
+dashboard.stack_memory_obtained=Mémoire Pile obtenue
+dashboard.mspan_structures_usage=Utilisation des Structures MSpan
+dashboard.mspan_structures_obtained=Structures MSpan obtenues
+dashboard.mcache_structures_usage=Utilisation des Structures MCache
+dashboard.mcache_structures_obtained=Structures MCache obtenues
+dashboard.profiling_bucket_hash_table_obtained=Profilage de Seau de Table de Hashage obtenu
+dashboard.gc_metadata_obtained=Métadonnées GC obtenues
+dashboard.other_system_allocation_obtained=Allocation de l'autre Système obtenue
+dashboard.next_gc_recycle=Traitement GC suivant
+dashboard.last_gc_time=Depuis le dernier GC
+dashboard.total_gc_time=Pause GC
+dashboard.total_gc_pause=Pause GC
+dashboard.last_gc_pause=Dernière Pause GC
+dashboard.gc_times=Nombres de GC
+dashboard.delete_old_actions=Supprimer toutes les anciennes actions de la base de données
+
+users.user_manage_panel=Gestion du compte utilisateur
+users.new_account=Créer un compte
+users.name=Nom d'utilisateur
+users.full_name=Non Complet
+users.activated=Activé
+users.admin=Administrateur
+users.restricted=Restreint
+users.2fa=2FA
+users.repos=Dépôts
+users.created=Créés
+users.last_login=Dernière connexion
+users.never_login=Jamais connecté
+users.send_register_notify=Envoyer une notification d'inscription
+users.new_success=L'utilisateur '%s' à bien été créé.
+users.edit=Éditer
+users.auth_source=Sources d'authentification
+users.local=Locales
+users.auth_login_name=Nom d'utilisateur pour l'authentification
+users.password_helper=Laissez le mot de passe vide pour le garder inchangé.
+users.update_profile_success=Le compte a bien été mis à jour.
+users.edit_account=Modifier un compte
+users.max_repo_creation=Nombre maximal de dépôts
+users.max_repo_creation_desc=(Mettre à -1 pour utiliser la limite globale par défaut.)
+users.is_activated=Ce compte est activé
+users.prohibit_login=Désactiver la connexion
+users.is_admin=Est Administrateur
+users.is_restricted=Est restreint
+users.allow_git_hook=Autoriser la création de Git Hooks
+users.allow_import_local=Autoriser l'importation de dépôts locaux
+users.allow_create_organization=Autoriser la création d'organisations
+users.update_profile=Modifier un compte
+users.delete_account=Supprimer cet utilisateur
+users.still_own_repo=Cet utilisateur possède un ou plusieurs dépôts. Veuillez les supprimer ou les transférer à un autre utilisateur.
+users.still_has_org=Cet utilisateur est membre d'une organisation. Veuillez le retirer de toutes les organisations dont il est membre au préalable.
+users.deletion_success=Le compte a été supprimé.
+users.reset_2fa=Réinitialiser l'authentification à deux facteurs
+users.list_status_filter.is_active=Actif
+users.list_status_filter.is_admin=Administrateur
+users.list_status_filter.is_restricted=Restreint
+
+emails.email_manage_panel=Gestion des courriels des utilisateurs
+emails.primary=Principale
+emails.activated=Activée
+emails.filter_sort.email=Courriel
+emails.filter_sort.email_reverse=Courriel (inverse)
+emails.filter_sort.name=Nom d'utilisateur
+emails.filter_sort.name_reverse=Nom d'utilisateur (inverse)
+emails.updated=Courriel mis à jour
+emails.not_updated=Impossible de mettre à jour l'adresse courriel demandée : %v
+emails.duplicate_active=Cette adresse courriel est déjà active pour un autre utilisateur.
+emails.change_email_header=Mettre à jour les propriétés du courriel
+emails.change_email_text=Êtes-vous sûr de vouloir mettre à jour cette adresse courriel ?
+
+orgs.org_manage_panel=Gestion des organisations
+orgs.name=Nom
+orgs.teams=Équipes
+orgs.members=Membres
+orgs.new_orga=Nouvelle organisation
+
+repos.repo_manage_panel=Gestion des dépôts
+repos.unadopted=Dépôts non adoptés
+repos.owner=Propriétaire
+repos.name=Nom
+repos.private=Privé
+repos.watches=Suivi par
+repos.stars=Votes
+repos.forks=Bifurcations
+repos.issues=Tickets
+repos.size=Taille
+
+packages.owner=Propriétaire
+packages.name=Nom
+packages.type=Type
+packages.repository=Dépôt
+packages.size=Taille
+packages.published=Publiés
+
+
+systemhooks=Rappels système
systemhooks.desc=Les Webhooks font automatiquement des requêtes HTTP POST à un serveur lorsque certains événements Gitea se déclenchent. Les Webhooks définis ici agiront sur tous les dépots du système, donc veuillez prendre en compte les implications en termes de performances que cela peut avoir. Lire la suite dans le <a target="_blank" rel="noopener noreferrer" href="%s">guide des Webhooks</a>.
systemhooks.add_webhook=Ajouter un rappel système
systemhooks.update_webhook=Mettre à jour un rappel système
@@ -2510,10 +2649,10 @@ auths.tips=Conseils
auths.tips.oauth2.general=Authentification OAuth2
auths.tips.oauth2.general.tip=Lorsque vous enregistrez une nouvelle authentification OAuth2, l'URL de redirection doit être de la forme : <host>/user/oauth2 /<Authentication Name>/callback
auths.tip.oauth2_provider=Fournisseur OAuth2
-auths.tip.bitbucket=Créez un nouveau jeton OAuth sur https://bitbucket.org/account/user/<your username>/oauth-consumers/new et ajoutez la permission "Compte"-"Lecture"
-auths.tip.nextcloud=Enregistrez un nouveau consommateur OAuth sur votre instance en utilisant le menu "Paramètres -> Sécurité -> Client OAuth 2.0"
+auths.tip.bitbucket=`Créez un nouveau jeton OAuth sur https://bitbucket.org/account/user/<your username>/oauth-consumers/new et ajoutez la permission "Compte"-"Lecture"`
+auths.tip.nextcloud=`Enregistrez un nouveau consommateur OAuth sur votre instance en utilisant le menu "Paramètres -> Sécurité -> Client OAuth 2.0"`
auths.tip.dropbox=Créez une nouvelle application sur https://www.dropbox.com/developers/apps
-auths.tip.facebook=Enregistrez une nouvelle application sur https://developers.facebook.com/apps et ajoutez le produit "Facebook Login"
+auths.tip.facebook=`Enregistrez une nouvelle application sur https://developers.facebook.com/apps et ajoutez le produit "Facebook Login"`
auths.tip.github=Créez une nouvelle application OAuth sur https://github.com/settings/applications/new
auths.tip.gitlab=Créez une nouvelle application sur https://gitlab.com/profile/applications
auths.tip.google_plus=Obtenez des identifiants OAuth2 sur la console API de Google (https://console.developers.google.com/)
@@ -2521,7 +2660,7 @@ auths.tip.openid_connect=Utilisez l'URL de découvert OpenID (<server>/.well-kno
auths.tip.twitter=Rendez-vous sur https://dev.twitter.com/apps, créez une application et assurez-vous que l'option "Autoriser l'application à être utilisée avec Twitter Connect" est activée
auths.tip.discord=Enregistrer une nouvelle application sur https://discordapp.com/developers/applications/me
auths.tip.gitea=Enregistrez une nouvelle application OAuth2. Un guide peut être trouvé sur https://docs.gitea.io/en-us/oauth2-provider/
-auths.tip.yandex=Créez une nouvelle application sur https://oauth.yandex.com/client/new. Sélectionnez les autorisations suivantes dans la section "Yandex API passport" : "Accès à l'adresse e-mail", "Accès à l'avatar de l'utilisateur" et "Accès au nom d'utilisateur, prénom et prénom, genre"
+auths.tip.yandex=`Créez une nouvelle application sur https://oauth.yandex.com/client/new. Sélectionnez les autorisations suivantes dans la section "Yandex API passport" : "Accès à l'adresse e-mail", "Accès à l'avatar de l'utilisateur" et "Accès au nom d'utilisateur, prénom et prénom, genre"`
auths.tip.mastodon=Entrez une URL d'instance personnalisée pour l'instance mastodon avec laquelle vous voulez vous authentifier (ou utiliser celle par défaut)
auths.edit=Mettre à jour la source d'authentification
auths.activated=Cette source d'authentification est activée
@@ -2609,6 +2748,7 @@ config.skip_tls_verify=Passer la vérification TLS
config.mailer_enabled=Activé
config.mailer_name=Nom
+config.mailer_smtp_port=Port SMTP
config.mailer_user=Utilisateur
config.mailer_use_sendmail=Utiliser Sendmail
config.mailer_sendmail_path=Chemin d’accès à Sendmail
@@ -2650,9 +2790,9 @@ config.git_max_diff_files=Nombre max de fichiers de Diff (à afficher)
config.git_gc_args=Arguments de GC
config.git_migrate_timeout=Délai imparti pour une migration
config.git_mirror_timeout=Délai imparti pour mettre à jour le miroir
-config.git_clone_timeout=Délai imparti pour l'opération "Clone"
-config.git_pull_timeout=Délai imparti pour l'opération "Pull"
-config.git_gc_timeout=Délai imparti pour l'opération "GC"
+config.git_clone_timeout=`Délai imparti pour l'opération "Clone"`
+config.git_pull_timeout=`Délai imparti pour l'opération "Pull"`
+config.git_gc_timeout=`Délai imparti pour l'opération "GC"`
config.log_config=Configuration du journal
config.log_mode=Mode du journal
@@ -2735,7 +2875,6 @@ monitor.queue.pool.cancel_desc=Quitter une file d'attente sans aucun groupe de p
notices.system_notice_list=Informations
notices.view_detail_header=Voir les détails de l'information système
-notices.actions=Actions
notices.select_all=Tout Sélectionner
notices.deselect_all=Tout désélectionner
notices.inverse_selection=Inverser la sélection
@@ -2824,7 +2963,28 @@ error.unit_not_allowed=Vous n'êtes pas autorisé à accéder à cette section d
[packages]
empty.repo=Avez-vous téléchargé un paquet, mais il n'est pas affiché ici? Allez dans les <a href="%[1]s">paramètres du paquet</a> et liez le à ce dépôt.
+filter.type=Type
published_by_in=%[1]s publié par <a href="%[2]s">%[3]s</a> en <a href="%[4]s"><strong>%[5]s</strong></a>
+conan.details.repository=Dépôt
rubygems.required.ruby=Nécessite la version de Ruby
rubygems.required.rubygems=Nécessite la version de RubyGem
+owner.settings.cleanuprules.enabled=Activé
+
+[secrets]
+name=Nom
+
+[actions]
+
+
+
+runners.name=Nom
+runners.owner_type=Type
+runners.description=Description
+runners.task_list.run=Exécuter
+runners.task_list.repository=Dépôt
+runners.task_list.commit=Commit
+runners.status.active=Actif
+
+runs.commit=Commit
+
diff --git a/options/locale/locale_hu-HU.ini b/options/locale/locale_hu-HU.ini
index 1edb42932..328af14d5 100644
--- a/options/locale/locale_hu-HU.ini
+++ b/options/locale/locale_hu-HU.ini
@@ -41,7 +41,6 @@ new_mirror=Új tükör
new_fork=Új másolat
new_org=Új szervezet
new_project=Új projekt
-new_project_board=Új projekt tábla
manage_org=Szervezetek kezelése
admin_panel=Rendszergazdai felület
account_settings=Fiók beállítások
@@ -67,6 +66,10 @@ add=Hozzáadás
add_all=Összes hozzáadása
remove=Eltávolítás
remove_all=Összes eltávolítása
+edit=Szerkesztés
+
+enabled=Engedélyezett
+disabled=Letiltva
write=Ãrás
@@ -80,6 +83,8 @@ error404=Az elérni kívánt oldal vagy <strong>nem létezik</strong>, vagy <str
+[aria]
+
[filter]
[error]
@@ -136,6 +141,8 @@ log_root_path_helper=A naplófájlok ebbe a mappába fognak íródni.
optional_title=További beállítások
email_title=E-mail beállítások
+smtp_addr=SMTP kiszolgáló
+smtp_port=SMTP port
smtp_from=E-mail küldése mint
smtp_from_helper=Az E-mail cím a mit a Gitea használni fog. Megadhatja sima email címként vagy "Név<email@példa.hu>" formátumban.
mailer_user=SMTP-felhasználónév
@@ -158,7 +165,7 @@ openid_signup=Regisztráció engedélyezése OpenID alapon
openid_signup_popup=Regisztráció engedélyezése OpenID alapon.
enable_captcha_popup=CAPTCHA megkövetelése amikor egy felhasználó regisztrál.
require_sign_in_view=Bejelentkezés megkövetelése az oldalak megtekintéséhez
-require_sign_in_view_popup=Csak bejelentkezett felhasználók nézhetik meg az oldalakat; a látogatók csak a bejelentkező oldalt láthatják.
+require_sign_in_view_popup=Csak bejelentkezett felhasználók nézhetik meg az oldalakat
admin_setting_desc=Nem szükséges most beállítania rendszergazdai fiókot, mert az első felhasználó automatikusan rendszergazdai jogokat kap.
admin_title=Rendszergazda fiók beállításai
admin_name=Rendszergazda felhasználóneve
@@ -173,7 +180,6 @@ invalid_repo_path=Repository gyökérkönyvtára helytelen: %v
run_user_not_match=Futtató felhasználó más, mint az aktuális felhasználó: %s -> %s
save_config_failed=Hiba történt a konfiguráció mentése közben: %v
invalid_admin_setting=Hibás a rendszergazdai fiók beállítása: %v
-install_success=Üdvözlünk! Köszönjük, hogy a Gitea-t választottad és jó szórakozást kívánunk a használatához!
invalid_log_root_path=Naplózás gyökérmappa érvénytelen: %v
default_keep_email_private=E-mail címek elrejtése alapértelmezetten
default_keep_email_private_popup=Az új felhasználói fiókok e-mail címeinek elrejtése alapértelmezetten.
@@ -215,7 +221,7 @@ repo_no_results=Nincs ilyen tároló.
user_no_results=Nincs ilyen felhasználó.
org_no_results=Nincs ilyen szervezet.
code_no_results=Nincs találat a keresési kifejezésedre.
-code_search_results=Keresési találatok "%s"
+code_search_results=`Keresési találatok "%s"`
code_last_indexed_at=Utoljára indexelve: %s
@@ -362,7 +368,7 @@ unable_verify_ssh_key=Az ssh kulcsot nem tudtuk ellenőrizni, kérjük nézze á
auth_failed=A hitelesítés sikertelen: %v
still_own_repo=Ennek a felhasználónak egy vagy több tárolója van még, ezeket le kell törölnie, vagy át kell adnia valakinek.
-still_has_org=A fiókod takja legalább egy szervezetnek; előbb léjen ki belőlük.
+still_has_org=A fiókod takja legalább egy szervezetnek
org_still_own_repo=Ennek a szervezetnek egy vagy több tárolója van még, ezeket le kell törölnie, vagy át kell adnia valakinek.
target_branch_not_exist=Cél ág nem létezik.
@@ -417,6 +423,7 @@ continue=Folytatás
cancel=Mégsem
language=Nyelv
ui=Téma
+comment_type_group_title=Cím
privacy=Adatvédelem
lookup_avatar_by_mail=Avatar mutatása email cím alapján
@@ -476,6 +483,10 @@ add_new_key=SSH kulcs hozzáadása
add_new_gpg_key=GPG kulcs hozzáadása
ssh_key_been_used=Ezt az SSH kulcsot már hozzáadták a ehhez a szerverhez.
gpg_key_id_used=Ilyen azonosítóval már létezik nyilvános GPG kulcs.
+gpg_key_verify=Ellenőrzés
+gpg_token=Token
+ssh_key_verify=Ellenőrzés
+ssh_token=Token
subkeys=Alkulcsok
key_id=Kulcs ID
key_name=Kulcs neve
@@ -515,6 +526,8 @@ generate_token_success=Új token létrehozva. Másold le most, mivel többször
generate_token_name_duplicate=A <strong>%s</strong> nevet már használja egy alkalmazás. Válassz kérlek más nevet.
delete_token=Törlés
access_token_deletion=Hozzáférési Token Törlése
+access_token_deletion_cancel_action=Mégse
+access_token_deletion_confirm_action=Törlés
delete_token_success=A token törölve lett. Az ezt használó alkalmazásoknak többé nincs hozzáférése a fiókodhoz.
manage_oauth2_applications=OAuth2 alkalmazások kezelése
@@ -556,10 +569,12 @@ passcode_invalid=A jelszava helytelen. Próbálja újra.
manage_account_links=Kapcsolt fiókok kezelése
+link_account=Fiók kapcsolása
remove_account_link=Csatolt fiók eltávolítása
remove_account_link_desc=Egy kapcsolt fiók törlésével visszavonja a hozzáférését a fiókjához. Folytatja?
remove_account_link_success=A kapcsolt fiók törölve lett.
+
orgs_none=Nem tagja egy szervezetnek sem.
repos_none=Nincsen egyetlen saját tárolója sem
@@ -574,6 +589,8 @@ email_notifications.onmention=Email küldése csak megjelölés esetén
email_notifications.disable=Email értesítés kikapcsolása
email_notifications.submit=E-mail beállítások megadása
+visibility.public=Nyilvános
+visibility.private=Privát
[repo]
owner=Tulajdonos
@@ -617,6 +634,7 @@ forks=Másolások
pick_reaction=Válasszon reakciót
reactions_more=és további %d
language_other=Egyéb
+delete_preexisting_label=Törlés
desc.private=Privát
@@ -654,7 +672,7 @@ migrate.clone_address=Migráció / Másolás URL-ről
migrate.clone_address_desc=HTTP(S) vagy Git URL-e egy már létező tárolónak
migrate.clone_local_path=vagy a helyi szerver elérési útja
migrate.permission_denied=Nem engedélyezett számodra a helyi tárolók importálása.
-migrate.invalid_local_path=A helyi elérési út érvénytelen; nem létezik vagy nem mappára mutat.
+migrate.invalid_local_path=A helyi elérési út érvénytelen
migrate.failed=A migráció sikertelen: %v
migrated_from=Migrálva innen: <a href="%[1]s">%[2]s</a>
migrated_from_fake=Migrálva innen: %[1]s
@@ -685,6 +703,7 @@ branches=Ãgak
tags=Címkék
issues=Hibajegyek
pulls=Egyesítési kérések
+project_board=Projektek
labels=Címkék
org_labels_desc_manage=kezelés
@@ -766,6 +785,13 @@ commits.gpg_key_id=GPG kulcs azonosító
ext_issues.desc=Külső hibakövető csatlakoztatás.
+projects=Projektek
+projects.description_placeholder=Leírás
+projects.title=Cím
+projects.new=Új projekt
+projects.template.desc=Sablon
+projects.column.edit_title=Név
+projects.column.new_title=Név
issues.desc=Hibajelentések, feladatok és mérföldkövek elrendezése.
issues.filter_milestones=Mérföldkövek szűrése
@@ -776,6 +802,7 @@ issues.new.labels=Címkék
issues.new.add_labels_title=Címke alkalmazása
issues.new.no_label=Nincs címke
issues.new.clear_labels=Címkék kiürítése
+issues.new.projects=Projektek
issues.new.no_items=Nincsenek elemek
issues.new.milestone=Mérföldkő
issues.new.add_milestone_title=Mérföldkő beállítása
@@ -803,6 +830,7 @@ issues.add_milestone_at=`A hibajegy hozzá lett adva a <b>%s</b> mérföldkőhö
issues.change_milestone_at=`módosítva lett a mérföldkő <b>%s</b>-ról/ről <b>%s</b>-ra/re %s`
issues.remove_milestone_at=`eltávolítva a <b>%s</b> mérföldkőből %s`
issues.deleted_milestone=`(törölt)`
+issues.deleted_project=`(törölt)`
issues.self_assign_at=`önmagához rendelte %s`
issues.add_assignee_at=`hozzárendelve <b>%s</b> által %s`
issues.remove_assignee_at=`hozzárendelés törlése <b>%s</b> által %s`
@@ -844,6 +872,7 @@ issues.previous=Előző
issues.next=Következő
issues.open_title=Nyitott
issues.closed_title=Lezárt
+issues.draft_title=Piszkozat
issues.num_comments=%d hozzászólás
issues.commented_at=`hozzászólt <a href="#%s">%s</a>`
issues.delete_comment_confirm=Biztos vagy benne, hogy törölni akarod ezt a hozzászólást?
@@ -898,6 +927,7 @@ issues.lock.reason=Zárolás oka
issues.lock.title=Beszélgetés lezárása ezen a hibajegyen.
issues.unlock.title=Hibajegy újranyitása.
issues.comment_on_locked=Egy zárolt hibajegyhez nem lehet hozzászólni.
+issues.delete=Törlés
issues.tracker=Időzítő
issues.start_tracking=Időmérés elkezdése
issues.start_tracking_history=`elkezdett dolgozni %s`
@@ -916,6 +946,7 @@ issues.due_date=Határidő
issues.invalid_due_date_format=A határidőt 'éééé-hh-nn' formátumban kell megadni.
issues.error_modifying_due_date=Határidő módosítása sikertelen.
issues.error_removing_due_date=Határidő eltávolítása sikertelen.
+issues.force_push_compare=Összehasonlítás
issues.due_date_form=éééé-hh-nn
issues.due_date_form_add=Határidő hozzáadása
issues.due_date_form_edit=Szerkesztés
@@ -1086,7 +1117,7 @@ activity.git_stats_deletion_n=%d törlés
search=Keresés
search.search_repo=Tároló keresés
-search.results="%s" találatok keresése itt: <a href="%s">%s</a>
+search.results=`"%s\" találatok keresése itt: <a href=\"%s\">%s</a>`
settings=Beállítások
settings.desc=A beállítások menüpontban állítható a tároló paraméterei
@@ -1534,6 +1565,368 @@ auths.tips=Tippek
auths.tips.oauth2.general=OAuth2 hitelesítés
auths.tips.oauth2.general.tip=Amikor egy új OAuth2 hitelesítési módot hoz létre, a visszahívási/átirányítási URL-nek így kell kinéznie: <kiszolgáló>/user/oauth2/<hitelesítési mód neve>/callback
auths.tip.oauth2_provider=OAuth2 szolgáltató
+auths.tip.bitbucket=`Igényeljen egy új OAuth jogosultságot itt: https://bitbucket.org/account/user/<felhasználóneved>/oauth-consumers/new és adja hozzá jogosultságot a "`
+search.code_no_results=Nincs találat a keresési kifejezésedre.
+
+settings=Beállítások
+settings.options=Tároló
+settings.collaboration.read=Olvasott
+settings.collaboration.owner=Tulajdonos
+settings.githooks=Git Hook-ok
+settings.site=Webhely
+settings.update_settings=Beállítások frissítése
+settings.enable_timetracker=Időmérés bekapcsolása
+settings.trust_model.collaborator=Közreműködő
+settings.delete_collaborator=Eltávolítás
+settings.teams=Csoportok
+settings.webhook_deletion=Webhook törlése
+settings.webhook.payload=Tartalom
+settings.slack_username=Felhasználónév
+settings.discord_username=Felhasználónév
+settings.event_delete=Törlés
+settings.event_fork=Tükrözés
+settings.event_wiki=Wiki
+settings.event_release=Kiadás
+settings.event_repository=Tároló
+settings.event_issues=Hibajegyek
+settings.active=Aktív
+settings.add_hook_success=Webhook hozzáadva.
+settings.update_webhook=Webhook frissítése
+settings.update_hook_success=Webhook frissítve.
+settings.delete_webhook=Webhook törlése
+settings.recent_deliveries=Legutóbbi Küldések
+settings.hook_type=Hook típusa
+settings.slack_token=Token
+settings.slack_domain=Tartomány
+settings.slack_channel=Csatorna
+settings.deploy_keys=Telepítési kulcsok
+settings.add_deploy_key=Telepítési kulcs hozzáadása
+settings.deploy_key_desc=A Deploy kulcsoknak csak olvasó joguk van ehhez a tárolóhoz.
+settings.is_writable=Ãrási hozzáférés engedélyezése
+settings.title=Cím
+settings.deploy_key_content=Tartalom
+settings.branches=Ãgak
+settings.protected_branch=Ãg védeleme
+settings.protected_branch_can_push=Push engedélyezése?
+settings.protected_branch_can_push_yes=Most már push-olhatja
+settings.protect_whitelist_search_users=Felhasználó keresése…
+settings.protect_whitelist_search_teams=Csoportok keresése…
+settings.protect_check_status_contexts=ÃllapotellenÅ‘rzés engedélyezése
+settings.add_protected_branch=Védelem engedélyezése
+settings.delete_protected_branch=Védelem letiltása
+settings.choose_branch=Válasszon egy ágat…
+settings.edit_protected_branch=Szerkesztés
+settings.bot_token=Bot Token
+settings.update_avatar_success=A tároló avatarja frissítve.
+settings.lfs=LFS
+settings.lfs_findcommits=Commitok keresése
+settings.lfs_invalid_locking_path=Érvénytelen útvonal: %s
+settings.lfs_invalid_lock_directory=Könyvtár nem zárolható: %s
+settings.lfs_lock_already_exists=A zárolás már létezik: %s
+settings.lfs_lock=Zárolás
+settings.lfs_locks_no_locks=Nincsenek zárolások
+settings.lfs_force_unlock=Kényszerített zárolás
+settings.lfs_pointers.oid=OID
+
+diff.browse_source=Forráskód böngészése
+diff.parent=szülő
+diff.commit=commit
+diff.git-notes=Megjegyzések
+diff.data_not_available=A különbségek nem megjeleníthetőek
+diff.show_diff_stats=Statisztikák mutatása
+diff.show_split_view=Osztott nézet
+diff.show_unified_view=Egyesített nézet
+diff.stats_desc=<strong>%d fájl</strong> változott, egészen pontosan <strong>%d új sor hozzáadva</strong> és <strong>%d régi sor törölve</strong>
+diff.bin=BINáris
+diff.view_file=Fájl megtekintése
+diff.file_byte_size=Méret
+diff.file_suppressed=A különbségek nem kerülnek megjelenítésre, mivel a fájl túl nagy
+diff.comment.placeholder=Hozzászólás létrehozása
+diff.comment.markdown_info=Támogatja a markdown formázást.
+diff.comment.add_single_comment=Egyszerű hozzászólás hozzáadása
+diff.comment.reply=Válasz
+diff.review.comment=Hozzászólás
+
+release.releases=Kiadások
+release.new_release=Új kiadás
+release.draft=Piszkozat
+release.prerelease=Elő-kiadás
+release.stable=Stabil
+release.compare=Összehasonlítás
+release.edit=szerkesztés
+release.source_code=Forráskód
+release.tag_name=Címke neve
+release.target=Cél
+release.title=Cím
+release.content=Tartalom
+release.cancel=Mégse
+release.publish=Kiadás közzététele
+release.save_draft=Piszkozat mentése
+release.deletion_success=A kiadás törölve.
+release.deletion_tag_success=A cimke törölve lett.
+release.tag_name_invalid=Ez a címkenév érvénytelen.
+release.downloads=Letöltések
+release.download_count=Letöltések: %s
+
+branch.search=Ãg keresése
+branch.delete_head=Törlés
+branch.delete_html=Ãg törlése
+branch.create_branch=Ãg <strong>%s</strong> létrehozása
+branch.create_from='%s'-ból/ből
+branch.branch_already_exists=A(z) '%s' ág már létezik a tárolóban.
+branch.deleted_by=Törölve %s által
+
+
+
+topic.manage_topics=Témák kezelése
+topic.done=Kész
+
+
+
+[org]
+org_name_holder=Szervezet neve
+org_full_name_holder=Szervezet teljes neve
+org_name_helper=A szervezetek nevének rövidnek és megjegyezhetőnek kell lennie.
+create_org=Szervezet létrehozása
+repo_updated=Frissítve
+members=Tagok
+teams=Csoportok
+lower_members=tagok
+lower_repositories=tárolók
+create_new_team=Új Csapat
+create_team=Csapat létrehozása
+org_desc=Leírás
+team_name=Csoport neve
+team_desc=Leírás
+team_name_helper=A szervezetek nevének rövidnek és megjegyezhetőnek kell lennie.
+team_desc_helper=A csapat céljának vagy szerepkörének leírása.
+team_access_desc=Tároló hozzáférés
+team_permission_desc=Engedély
+team_unit_disabled=(Letiltva)
+
+form.name_reserved='%s' szervezetnév foglalt.
+form.name_pattern_not_allowed='%s' minta nem engedélyezett szervezet nevében.
+
+settings=Beállítások
+settings.options=Szervezet
+settings.full_name=Teljes név
+settings.website=Webhely
+settings.location=Tartózkodási hely
+settings.repoadminchangeteam=A tároló adminisztrátora létrehozhatja és eltávolíthatja a csapatok hozzáférését
+settings.visibility=Láthatóság
+settings.visibility.public=Nyilvános
+settings.visibility.limited=Korlátozott (csak a bejelentkezett felhasználók láthatják)
+settings.visibility.private=Privát (csak a szervezet tagjai láthatják)
+settings.visibility.private_shortname=Privát
+
+settings.update_settings=Beállítások frissítése
+settings.update_setting_success=A szervezet beállításai frissültek.
+settings.change_orgname_prompt=Megjegyzés: a szervezet nevének megváltoztatása a szervezet URL-jét is módosítja.
+settings.update_avatar_success=A szervezet avatarja frissítve.
+settings.delete=Szervezet törlése
+settings.delete_account=A szervezet törlése
+settings.delete_prompt=A szervezet véglegesen el lesz távolítva. <strong>NEM</strong> vonható vissza!
+settings.confirm_delete_account=Törlés megerősítése
+settings.delete_org_title=Szervezet törlése
+settings.delete_org_desc=Ez a szervezet véglegesen törölve lesz. Folytatható?
+settings.hooks_desc=Webhook hozzáadása a szervezet <strong>összes tárolójához</strong>.
+
+
+members.membership_visibility=Tagság láthatósága:
+members.public=Látható
+members.private=Rejtett
+members.member_role=Tag szerepkör:
+members.owner=Tulajdonos
+members.member=Tag
+members.remove=Eltávolítás
+members.leave=Távozás
+members.invite_desc=Tag hozzáadása a(z) %s szervezethez:
+members.invite_now=Meghívás most
+
+teams.join=Csatlakozás
+teams.leave=Távozás
+teams.can_create_org_repo=Tárolók létrehozása
+teams.can_create_org_repo_helper=A tagok létrehozhatnak új tárolókat a szervezetben. A létrehozó adminisztrátor hozzáférést fog kapni az új tárolóhoz.
+teams.read_access=Olvasott
+teams.read_access_helper=A tagok megtekinthetik és klónozhatják a csapat tárolóit.
+teams.admin_access=Adminisztrátori hozzáférés
+teams.no_desc=Ennek a csoportnak nincs leírása
+teams.settings=Beállítások
+teams.owners_permission_desc=A tulajdonosok a szervezet <strong>összes tárolójához adminisztrátori hozzáféréssel</strong> rendelkeznek.
+teams.members=Csoporttagok
+teams.update_settings=Beállítások frissítése
+teams.delete_team=Csapat törlése
+teams.add_team_member=Csapattag hozzáadása
+teams.delete_team_title=Csapat törlése
+teams.delete_team_desc=Egy csapat törlése visszavonja a tagjai hozzáférését a tárolókhoz. Folytatható?
+teams.delete_team_success=A csoport törölve lett.
+teams.read_permission_desc=Ez a csoport <strong>Olvasási</strong> jogosultságot biztosít: a tagok megtekinthetik és klónozhatják a csoport tárolóit.
+teams.repositories=Csoport tárolói
+teams.search_repo_placeholder=Tároló keresése…
+teams.remove_all_repos_title=Összes csapattároló eltávolítása
+teams.remove_all_repos_desc=Ez el fogja távolítani az összes tárolót a csoportból.
+teams.add_all_repos_title=Minden tároló hozzáadása
+teams.add_all_repos_desc=Ez hozzá fogja adni a szervezet összes tárolóját a csoporthoz.
+teams.add_nonexistent_repo=A tároló, melybe feltölteni szeretne, még nem létezik; először hozza létre.
+teams.add_duplicate_users=A felhasználó már csapattag.
+teams.repos.none=Ez a csapat nem férhet hozzá tárolókhoz.
+teams.members.none=Ennek a csapatnak nincsenek tagjai.
+teams.specific_repositories=Meghatározott tárolók
+teams.all_repositories=Minden tároló
+
+[admin]
+dashboard=Műszerfal
+users=Felhasználói fiókok
+organizations=Szervezetek
+repositories=Tárolók
+authentication=Hitelesítési források
+config=Konfiguráció
+notices=Rendszer-értesítések
+monitor=Figyelés
+first_page=Első
+last_page=Utolsó
+total=Összesen: %d
+
+dashboard.statistic=Összefoglaló
+dashboard.operations=Karbantartási műveletek
+dashboard.system_status=Rendszer Ãllapota
+dashboard.operation_name=Művelet Neve
+dashboard.operation_switch=Váltás
+dashboard.operation_run=Futtatás
+dashboard.clean_unbind_oauth=Megszüntetett OAuth kapcsolatok törlése
+dashboard.clean_unbind_oauth_success=Az összes megszüntetett OAuth kapcsolat törölve.
+dashboard.delete_generated_repository_avatars=Generált tároló avatarok törlése
+dashboard.reinit_missing_repos=Az összes Git tároló újra-inicializálása amihez léteznek bejegyzések
+dashboard.sync_external_users=Külső felhasználói adatok szinkronizálása
+dashboard.server_uptime=Kiszolgáló futási ideje
+dashboard.current_goroutine=Jelenlegi Goroutinok
+dashboard.current_memory_usage=Jelenlegi memória használat
+dashboard.total_memory_allocated=Összes lefoglalt memória
+dashboard.memory_obtained=Megszerzett Memória
+dashboard.pointer_lookup_times=Pointer Lookup Idők
+dashboard.memory_allocate_times=Memóriafoglalások
+dashboard.current_heap_usage=Aktuális Heap Használat
+dashboard.heap_memory_obtained=Heap Memória Megszerezve
+dashboard.heap_memory_idle=Tétlen Heap Memória
+dashboard.heap_memory_in_use=Használatban lévő Heap Memória
+dashboard.heap_memory_released=Elengedett Heap Memória
+dashboard.heap_objects=Heap Objektumok
+dashboard.bootstrap_stack_usage=Bootstrap Stack Használat
+dashboard.stack_memory_obtained=Stack Memória Megszerezve
+dashboard.mspan_structures_usage=MSpan Struktúrák Használata
+dashboard.mspan_structures_obtained=MSpan Struktúrák Megszerezve
+dashboard.mcache_structures_usage=MCache Struktúrák Használata
+dashboard.mcache_structures_obtained=MCache Struktúrák Megszerezve
+dashboard.profiling_bucket_hash_table_obtained=Profilozó Vödrös Hash Tábla Megszerezve
+dashboard.gc_metadata_obtained=GC Metaadat Megszerezve
+dashboard.other_system_allocation_obtained=Másik Rendszer Allokáció Megszerezve
+dashboard.next_gc_recycle=Következő GC Újrahasznosítás
+dashboard.last_gc_time=Utolsó GC óta eltelt idő
+dashboard.total_gc_time=Teljes GC szünet
+dashboard.total_gc_pause=Teljes GC szünet
+dashboard.last_gc_pause=Utolsó GC szünet
+dashboard.gc_times=GC Idők
+
+users.new_account=Felhasználó létrehozása
+users.name=Felhasználónév
+users.full_name=Teljes név
+users.activated=Aktivált
+users.admin=Rendszergazda
+users.restricted=Korlátozott
+users.repos=Tárolók
+users.created=Létrehozva
+users.last_login=Utolsó bejelentkezés
+users.never_login=Sosem jelentkezett be
+users.send_register_notify=Felhasználó regisztráció értesítés küldése
+users.edit=Szerkesztés
+users.auth_source=Hitelesítési forrás
+users.local=Helyi
+users.edit_account=Fiók szerkesztése
+users.is_admin=Adminisztrátor
+users.is_restricted=Korlátozott
+users.allow_create_organization=Létrehozhat szervezeteket
+users.update_profile=Fiók frissítése
+users.delete_account=Fiók törlése
+users.still_has_org=Ez a felhasználó tagja egy szervezetnek. Először el kell távolítani a felhasználót az összes szervezetből.
+users.list_status_filter.is_active=Aktív
+users.list_status_filter.is_admin=Rendszergazda
+users.list_status_filter.is_restricted=Korlátozott
+
+emails.primary=Elsődleges
+emails.activated=Aktivált
+emails.filter_sort.email=Email
+emails.filter_sort.name=Felhasználónév
+
+orgs.org_manage_panel=Szervezetek Kezelése
+orgs.name=Név
+orgs.teams=Csoportok
+orgs.members=Tagok
+orgs.new_orga=Új szervezet
+
+repos.repo_manage_panel=Tárolók Kezelése
+repos.owner=Tulajdonos
+repos.name=Név
+repos.private=Privát
+repos.watches=Figyelők
+repos.stars=Csillagok
+repos.issues=Hibajegyek
+repos.size=Méret
+
+packages.owner=Tulajdonos
+packages.name=Név
+packages.type=Típus
+packages.repository=Tároló
+packages.size=Méret
+
+
+
+auths.new=Hitelesítési forrás hozzáadása
+auths.name=Név
+auths.type=Típus
+auths.enabled=Engedélyezett
+auths.updated=Frissítve
+auths.auth_type=Hitelesítés Típusa
+auths.auth_name=Hitelesítési Forrás
+auths.security_protocol=Biztonsági Protokoll
+auths.domain=Tartomány
+auths.host=Kiszolgáló
+auths.port=Port
+auths.bind_dn=Bind DN
+auths.bind_password=Bind Jelszó
+auths.user_base=Felhasználókeresés alapja (BaseDN)
+auths.user_dn=Felhasználói DN
+auths.attribute_username=Felhasználónév attribútum
+auths.attribute_username_placeholder=Hagyja üresen, ha a Gitea-n használt felhasználónevet szeretné használni.
+auths.attribute_name=Vezetéknév attribútum
+auths.attribute_surname=Keresztnév attribútum
+auths.attribute_mail=E-mail attribútum
+auths.attribute_ssh_public_key=SSH nyilvános kulcs attribútum
+auths.attributes_in_bind=Attribútumok lekérdezése a DN környezetben
+auths.search_page_size=Oldalméret
+auths.filter=Felhasználói szűrő
+auths.admin_filter=Rendszergazdai szűrő
+auths.ms_ad_sa=MS AD Keresés attribútumok
+auths.smtp_auth=SMTP Autentikáció Típusa
+auths.smtphost=SMTP kiszolgáló
+auths.smtpport=SMTP port
+auths.allowed_domains=Engedélyezett tartományok
+auths.allowed_domains_helper=Hagyja üresen, ha minden tartományt szeretne engedélyezi. Több tartományt vesszővel(',') válasszon el.
+auths.skip_tls_verify=TLS ellenőrzés kihagyása
+auths.pam_service_name=PAM szolgáltatás neve
+auths.oauth2_provider=OAuth2 szolgáltató
+auths.oauth2_clientID=Ügyfél-azonosító (kulcs)
+auths.oauth2_clientSecret=Ügyfél-titok
+auths.openIdConnectAutoDiscoveryURL=OpenID Connect Automatikus Felfedezés URL-je
+auths.oauth2_use_custom_url=Testre szabott URL-ek használata az alapértelmezettek helyett
+auths.oauth2_tokenURL=Token URL
+auths.oauth2_authURL=Engedélyezési URL
+auths.oauth2_profileURL=Profil URL
+auths.oauth2_emailURL=E-mail URL
+auths.enable_auto_register=Automatikus regisztráció engedélyezése
+auths.tips=Tippek
+auths.tips.oauth2.general=OAuth2 hitelesítés
+auths.tips.oauth2.general.tip=Amikor egy új OAuth2 hitelesítési módot hoz létre, a visszahívási/átirányítási URL-nek így kell kinéznie: <kiszolgáló>/user/oauth2/<hitelesítési mód neve>/callback
+auths.tip.oauth2_provider=OAuth2 szolgáltató
auths.tip.bitbucket=Igényeljen egy új OAuth jogosultságot itt: https://bitbucket.org/account/user/<felhasználóneved>/oauth-consumers/new és adja hozzá jogosultságot a "Fiókok"-"Olvasás" alá
auths.tip.dropbox=Vegyen fel új alkalmazást itt: https://www.dropbox.com/developers/apps
auths.tip.facebook=Vegyen fel új alkalmazást itt: https://developers.facebook.com/apps majd adja hozzá a "Facebook Login"-t
@@ -1626,6 +2019,7 @@ config.skip_tls_verify=A TLS Hitelesítés Kihagyása
config.mailer_enabled=Engedélyezett
config.mailer_name=Név
+config.mailer_smtp_port=SMTP port
config.mailer_user=Felhasználó
config.mailer_use_sendmail=Sendmail Használata
config.mailer_sendmail_path=Sendmail Elérési Útja
@@ -1690,11 +2084,11 @@ monitor.queue.name=Név
monitor.queue.type=Típus
monitor.queue.pool.timeout=Időtúllépés
+monitor.queue.settings.submit=Beállítások frissítése
notices.system_notice_list=Rendszer Értesítések
notices.view_detail_header=Értesítés Részletei
-notices.actions=Műveletek
notices.select_all=Összes Kijelölése
notices.deselect_all=Kijelölés Megszüntetése
notices.inverse_selection=Kijelölés Megfordítása
@@ -1763,4 +2157,25 @@ error.not_signed_commit=Nem aláírt commit
[units]
[packages]
+filter.type=Típus
+conan.details.repository=Tároló
+owner.settings.cleanuprules.enabled=Engedélyezett
+
+[secrets]
+name=Név
+
+[actions]
+
+
+
+runners.name=Név
+runners.owner_type=Típus
+runners.description=Leírás
+runners.task_list.run=Futtatás
+runners.task_list.repository=Tároló
+runners.task_list.commit=Commit
+runners.status.active=Aktív
+
+runs.commit=Commit
+
diff --git a/options/locale/locale_id-ID.ini b/options/locale/locale_id-ID.ini
index e75fae5de..5b418231c 100644
--- a/options/locale/locale_id-ID.ini
+++ b/options/locale/locale_id-ID.ini
@@ -63,6 +63,10 @@ add=Tambah
add_all=Tambah Semua
remove=Buang
remove_all=Buang Semua
+edit=Edit
+
+enabled=Aktif
+disabled=Nonaktif
write=Tulis
@@ -73,6 +77,8 @@ loading=Memuat…
+[aria]
+
[filter]
[error]
@@ -85,100 +91,33 @@ platform_desc=Gitea bisa digunakan di mana <a target="_blank" rel="noopener nore
lightweight=Ringan
lightweight_desc=Gitea hanya membutuhkan persyaratan minimal dan bisa berjalan pada Raspberry Pi yang murah. Bisa menghemat listrik!
license=Sumber Terbuka
-license_desc="Go get" (Dapatkan kode sumber dari) <a target="_blank" rel="noopener noreferrer" href="https://code.gitea.io/gitea">code.gitea.io/gitea</a>! Mari bergabung dengan <a target="_blank" rel="noopener noreferrer" href="https://github.com/go-gitea/gitea">berkontribusi</a> untuk membuat proyek ini lebih baik. Jangan malu untuk menjadi kontributor!
+license_desc=`"Go get\" (Dapatkan kode sumber dari) <a target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://code.gitea.io/gitea\">code.gitea.io/gitea</a>! Mari bergabung dengan <a target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://github.com/go-gitea/gitea\">berkontribusi</a> untuk membuat proyek ini lebih baik. Jangan malu untuk menjadi kontributor!`
[install]
install=Pemasangan
title=Konfigurasi Awal
-docker_helper=Jika Anda menjalankan Gitea di dalam Docker, baca <a target="_blank" rel="noopener" href="%s">dokumentasi </a> sebelum mengubah pengaturan.
-db_title=Pengaturan Basis Data
-db_type=Tipe Basis Data
+docker_helper=`Jika Anda menjalankan Gitea di dalam Docker, baca <a target="`
+
+[install]
+title=Konfigurasi Awal
host=Host
-user=Nama Pengguna
password=Kata Sandi
-db_name=Nama Basis Data
-db_helper=Untuk pengguna MySQL: Mohon gunakan mesin penyimpanan InnoDB, dan jika Anda menggunakan enkoding "utf8mb4", versi InnoDB Anda harus diatas 5.6.
db_schema=Schema
-db_schema_helper=Biarkan kosong untuk standar database ("public").
ssl_mode=SSL
-charset=Jenis karakter
path=Jalur
-sqlite_helper=Jalur berkas untuk basis data SQLite3 atau TiDB.<br>Masukkan path absolut jika anda menjalankan Gitea sebagai layanan.
-err_empty_db_path=Jalur basis data SQLite3 tidak boleh kosong.
-no_admin_and_disable_registration=Anda tidak dapat menonaktifkan pendaftaran tanpa membuat akun admin.
-err_empty_admin_password=Sandi administrator tidak boleh kosong.
-err_empty_admin_email=Email administrator tidak boleh kosong.
-err_admin_name_is_reserved=Nama pengguna Administrator tidak valid, nama tersebut dicadangkan
-err_admin_name_pattern_not_allowed=Nama pengguna untuk Administrator tidak valid, nama tersebut sedang dicadangkan
-err_admin_name_is_invalid=Nama Administrator tidak valid.
-
-general_title=Pengaturan Umum
-app_name=Judul Situs
-app_name_helper=Anda dapat memasukkan nama perusahaan anda di sini.
-repo_path=Path Root Repositori
-repo_path_helper=Repositori Git remote akan disimpan ke direktori ini.
-lfs_path=Path Akar Git LFS
-lfs_path_helper=Berkas yang tersimpan dengan Git LFS akan disimpan ke direktori ini. Biarkan kosong untuk menonaktifkan LFS.
-run_user=Jalankan Sebagai Nama Pengguna
-run_user_helper=Masukkan nama pengguna sistem operasi yang menjalankan Gitea. Perhatikan bahwa pengguna ini harus memiliki akses ke path akar dari repositori.
-ssh_port=Port Server SSH
-ssh_port_helper=Nomor port server SSH anda. Biarkan kosong untuk menonaktifkan.
-http_port=Port HTTP Gitea
-http_port_helper=Nomor port web server dimana Gitea akan berjalan.
-app_url=URL Dasar Gitea
-app_url_helper=Alamat dasar untuk klon URL HTTP(S) dan pemberitahuan lewat surel.
-log_root_path=Path Log
-log_root_path_helper=Berkas log akan ditulis ke direktori ini.
-
-optional_title=Pengaturan Opsional
-email_title=Pengaturan Surel
-smtp_from=Kirim Surel sebagai
-smtp_from_helper=Alamat surel Gitea akan digunakan. Masukkan alamat surel atau gunakan fomat "Nama" <email@example.com>.
-mailer_user=Nama Pengguna SMTP
-mailer_password=Sandi SMTP
-register_confirm=Memerlukan Konfirmasi Surel Untuk Mendaftar
-mail_notify=Aktifkan Pemberitahuan Surel
-server_service_title=Server dan Pengaturan Layanan Pihak Ketiga
-offline_mode=Aktifkan Mode Lokal
-offline_mode_popup=Non-aktifkan jaringan pengiriman konten dari pihak ketiga dan layani semua sumber daya secara lokal.
-disable_gravatar=Non-aktifkan Gravatar
-disable_gravatar_popup=Matikan Gravatar dan sumber avatar pihak ketiga lainnya. Avatar standar akan digunakan kecuali pengguna mengunggah avatar sendiri.
-federated_avatar_lookup=Aktifkan Avatar Terfederasi
-federated_avatar_lookup_popup=Mengaktifkan pencarian avatar federasi menggunakan Libravatar.
-disable_registration=Matikan Swa-pendaftaran
-disable_registration_popup=Nonaktifkan pendaftaran oleh pengguna. Hanya admin yang dapat membuat akun pengguna baru.
-allow_only_external_registration_popup=Perbolehkan Pendaftaran Hanya Melalui Layanan External
+
+repo_path=Jalur akar repositori
+
+smtp_addr=Host SMTP
+smtp_port=Port SMTP
+register_confirm=Perlu Konfirmasi Email Saat Pendaftaran
+mail_notify=Aktifkan Notifikasi Email
+disable_gravatar=Menonaktifkan Gravatar
+federated_avatar_lookup=Aktifkan pencarian avatar
openid_signin=Aktifkan Login OpenID
-openid_signin_popup=Aktifkan masuk pengguna lewat OpenID.
-openid_signup=Aktifkan Pendaftaran OpenID
-openid_signup_popup=Aktifkan pendaftaran berdasarkan OpenID.
-enable_captcha_popup=Membutukan CAPTCHA untuk pendaftaran.
-require_sign_in_view=Anda Harus Login untuk Melihat Halaman
-require_sign_in_view_popup=Batasi akses halaman hanya pada pengguna yang masuk. Pengunjung hanya dapat melihat halaman masuk dan pendaftaran.
-admin_setting_desc=Akun administrator tidak wajib dibuat. Pengguna yang pertama kali mendaftar akan secara otomatis menjadi administrator.
-admin_title=Pengaturan Akun Admin
-admin_name=Nama Pengguna Admin
-admin_password=Kata sandi
-confirm_password=Konfirmasi Kata Sandi
-admin_email=Alamat Surel
-install_btn_confirm=Memasang Gitea
-test_git_failed=Tidak dapat menguji perintah 'git': %v
-sqlite3_not_available=Gitea versi ini tidak mendukung SQLite3, Silahkan untuh versi biner resmi dari %s (bukan versi 'gobuild').
-invalid_db_setting=Pengaturan basis data tidak valid: %v
-invalid_repo_path=Lokasi folder repositori tidak valid: %v
-run_user_not_match=Nama pengguna 'run as' bukanlah nama pengguna saat ini: %s -> %s
-save_config_failed=Gagal menyimpan konfigurasi: %v
-invalid_admin_setting=Pengaturan akun administrator tidak valid: %v
-install_success=Selamat datang! Terimakasih telah memilih Gitea. Selamat bersenang-senang dan hati-hati!
-invalid_log_root_path=Jalur folder log tidak valid: %v
-default_keep_email_private=Sembunyikan Alamat Email secara Asali
-default_keep_email_private_popup=Sembunyikan alamat email pengguna baru secara asali.
-default_allow_create_organization=Perbolehkan Pembuatan Organisasi secara Asali
-default_allow_create_organization_popup=Perbolehkan pengguna baru untuk membuat organisasi.
-default_enable_timetracking=Aktifkan Pelacakan Waktu secara Asali
-default_enable_timetracking_popup=Gunakan pelacakan waktu untuk repositori baru.
-no_reply_address=Nama Email Tersembunyi
-no_reply_address_helper=Nama domain untuk pengguna yang menyembunyikan alamat emailnya. Misal untuk pengguna dengan nama gabri, akan ditampilkan sebagai 'gabri@contoh.id' jika nama domain diisi 'contoh.id'.
+require_sign_in_view=Harus Login Untuk Melihat Halaman
+admin_password=Kata Sandi
+admin_email=Alamat Email
[home]
uname_holder=Nama Pengguna atau Alamat Surel
@@ -193,6 +132,7 @@ view_home=Lihat %s
search_repos=Cari repositori…
+show_private=Pribadi
issues.in_your_repos=Dalam repositori anda
@@ -352,12 +292,12 @@ cannot_add_org_to_team=Sebuah organisasi tidak dapat ditambahkan sebagai anggota
invalid_ssh_key=Tidak dapat memverifikasi kunci SSH Anda: %s
invalid_gpg_key=Tidak dapat memverifikasi kunci GPG Anda: %s
-unable_verify_ssh_key=Tidak dapat memverifikasi kunci SSH; periksa kembali bila ada kesalahan.
+unable_verify_ssh_key=Tidak dapat memverifikasi kunci SSH
auth_failed=Otentikasi gagal: %v
still_own_repo=Akun anda memiliki satu atau lebih repositori, pindahkan atau transfer terlebih dahulu.
still_has_org=Akun Anda adalah anggota dari satu atau lebih organisasi, tinggalkan terlebih dahulu.
-org_still_own_repo=Organisasi ini masih memiliki satu atau lebih repositori; hapus atau transfer terlebih dahulu.
+org_still_own_repo=Organisasi ini masih memiliki satu atau lebih repositori
target_branch_not_exist=Target cabang tidak ada.
@@ -409,6 +349,7 @@ continue=Lanjutkan
cancel=Batalkan
language=Bahasa
ui=Tema
+comment_type_group_title=Judul
lookup_avatar_by_mail=Cari Avatar melalui Alamat Email
federated_avatar_lookup=Aktifkan Pencarian Avatar Representasi
@@ -435,6 +376,7 @@ manage_openid=Kelola alamat OpenID
email_desc=Alamat surel utama anda akan digunakan untuk notifikasi dan operasi lainnya.
theme_desc=Ini akan menjadi tema asal Anda pada keseluruhan situs.
primary=Utama
+activated=Diaktifkan
primary_email=Buat Utama
delete_email=Hapus
email_deletion=Hapus Alamat Email
@@ -467,10 +409,15 @@ add_new_key=Tambahkan Kunci SSH
add_new_gpg_key=Tambahkan Kunci GPG
ssh_key_been_used=Kunci SSH ini telah ditambahkan ke peladen.
gpg_key_id_used=Kunci publik GPG dengan ID yang sama sudah ada.
+gpg_key_verify=Verifikasi
+gpg_token=Token
+ssh_key_verify=Verifikasi
+ssh_token=Token
subkeys=Subkunci
key_id=ID Kunci
key_name=Nama Kunci
key_content=Konten
+principal_content=Konten
add_key_success=Kunci SSH '%s' telah ditambahkan.
add_gpg_key_success=Kunci GPG '%s' telah ditambahkan.
delete_key=Hapus
@@ -506,6 +453,8 @@ generate_token=Hasilkan Token
generate_token_success=Token baru Anda telah dibuat. Salin sekarang oleh karena tidak akan ditampilkan lagi.
delete_token=Hapus
access_token_deletion=Hapus Token Akses
+access_token_deletion_cancel_action=Membatalkan
+access_token_deletion_confirm_action=Hapus
delete_token_success=Token telah dihapus. Aplikasi yang menggunakannya tidak lagi memiliki akses ke akun Anda.
manage_oauth2_applications=Kelola Aplikasi OAuth2
@@ -556,10 +505,12 @@ passcode_invalid=Kode sandi salah. Coba lagi.
manage_account_links=Kelola akun tertaut
manage_account_links_desc=Semua akun eksternal ini sementara tertaut dengan akun Gitea Anda.
account_links_not_available=Saat ini tidak ada akun eksternal yang tertaut ke akun Gitea ini.
+link_account=Tautan Akun
remove_account_link=Hapus Akun Tertaut
remove_account_link_desc=Menghapus akun tertaut akan membuat akun itu tidak bisa mengakses akun Gitea Anda. Lanjutkan?
remove_account_link_success=Akun tertaut sudah dihapus.
+
orgs_none=Anda bukan anggota dari organisasi apapun.
repos_none=Anda tidak memiliki repositori apapun
@@ -573,6 +524,7 @@ email_notifications.enable=Aktifkan Pemberitahuan Surel
email_notifications.disable=Nonaktifkan Email Notifikasi
email_notifications.submit=Pasang Pengaturan Email
+visibility.private=Pribadi
[repo]
owner=Pemilik
@@ -611,12 +563,15 @@ forks=Garpu
pick_reaction=Pilih reaksimu
reactions_more=dan %d lainnya
unit_disabled=Administrator web menonaktifkan bagian repositori ini.
+delete_preexisting_label=Hapus
+desc.private=Pribadi
template.webhooks=Webhooks
template.topics=Topik
template.avatar=Avatar
+template.issue_labels=Label Masalah
archive.title=Repositori ini diarsipkan. Anda bisa melihat berkas dan mengkloningnya, tapi tidak dapat mendorong atau membuka masalah/permintaan tarik.
archive.issue.nocomment=Repositori ini diarsipkan. Anda tidak dapat mengomentari masalah.
@@ -627,9 +582,13 @@ form.name_pattern_not_allowed=Pola '%s' tidak diperbolehkan dalam nama repositor
migrate_items=Ihwal Migrasi
migrate_items_wiki=Wiki
+migrate_items_milestones=Tonggak
+migrate_items_issues=Masalah
+migrate_items_pullrequests=Tarik Permintaan
+migrate_items_releases=Rilis
migrate_repo=Migrasi Repositori
migrate.permission_denied=Anda tidak diizinkan untuk mengimpor repositori lokal.
-migrate.invalid_local_path=Jalur lokal tidak valid; tidak ada atau bukan direktori.
+migrate.invalid_local_path=Jalur lokal tidak valid
migrate.failed=Migrasi gagal: %v
migrated_from=Termigrasi dari <a href="%[1]s">%[2]s</a>
migrated_from_fake=Termigrasi Dari %[1]s
@@ -727,6 +686,10 @@ commits.signed_by=Ditandai oleh
+projects.description_placeholder=Deskripsi
+projects.title=Judul
+projects.column.edit_title=Nama
+projects.column.new_title=Nama
issues.new=Masalah Baru
issues.new.labels=Label
@@ -740,6 +703,7 @@ issues.new.closed_milestone=Tutup Milestone
issues.no_ref=Tidak Ada Cabang/Tag Ditentukan
issues.create=Buat Masalah
issues.new_label=Label Baru
+issues.new_label_desc_placeholder=Deskripsi
issues.create_label=Buat Label
issues.label_templates.title=Muat sebuah label yang telah ditentukan
issues.label_templates.helper=Pilih set label
@@ -748,6 +712,7 @@ issues.add_milestone_at=`telah menambahkan ini ke <b>%s</b> milestone %s`
issues.change_milestone_at=`telah mengubah milestone dari <b>%s</b> ke <b>%s</b> %s`
issues.remove_milestone_at=`telah menghapus ini dari <b>%s</b> milestone %s`
issues.deleted_milestone=`(dihapus)`
+issues.deleted_project=`(dihapus)`
issues.self_assign_at=`menugaskan diri %s`
issues.add_assignee_at=`telah ditugaskan oleh <b>%s</b> %s`
issues.delete_branch_at=`telah dihapus cabang <b>%s</b> %s`
@@ -778,6 +743,7 @@ issues.previous=Sebelumnya
issues.next=Selanjutnya
issues.open_title=Buka
issues.closed_title=Tertutup
+issues.draft_title=Rancangan
issues.num_comments=%d komentar
issues.commented_at=`komentar <a href="#%s">%s</a>`
issues.delete_comment_confirm=Apakah anda yakin anda ingin menghapus komentar ini?
@@ -813,6 +779,7 @@ issues.attachment.open_tab=`Klik untuk melihat "%s" di tab baru`
issues.attachment.download=`Klik untuk mengunduh "%s"`
issues.subscribe=Berlangganan
issues.unsubscribe=Berhenti berlangganan
+issues.delete=Hapus
issues.start_tracking_history=`mulai bekerja %s`
issues.stop_tracking_history=`berhenti bekerja %s`
issues.cancel_tracking_history=`batalkan pelacakan waktu %s`
@@ -820,9 +787,14 @@ issues.add_time_cancel=Batalkan
issues.add_time_history=`tambah menghabiskan waktu %s`
issues.add_time_hours=Jam
issues.add_time_minutes=Menit
+issues.due_date_form_edit=Edit
+issues.due_date_form_remove=Menghapus
+issues.dependency.cancel=Membatalkan
+issues.dependency.remove=Menghapus
pulls.new=Permintaan Tarik Baru
+pulls.compare_changes=Permintaan Tarik Baru
pulls.filter_branch=Penyaringan cabang
pulls.no_results=Hasil tidak ditemukan.
pulls.create=Buat Permintaan Tarik
@@ -865,6 +837,7 @@ milestones.filter_sort.least_issues=Paling sedikit masalah
wiki=Wiki
wiki.page=Halaman
wiki.filter_page=Halaman Penyaring
+wiki.new_page=Halaman
wiki.default_commit_message=Tulis catatan mengenai pembaruan halaman ini (opsional).
wiki.save_page=Simpan Halaman
wiki.last_commit_info=%s halaman ini diedit %s
@@ -881,6 +854,7 @@ activity.period.daily=1 hari
activity.period.halfweekly=3 hari
activity.period.weekly=1 minggu
activity.period.monthly=1 bulan
+activity.period.yearly=1 tahun
activity.overview=Tinjauan
activity.active_prs_count_1=<strong>%d</strong> Tarik permintaan aktif
activity.active_prs_count_n=<strong>%d</strong> Tarik permintaan aktif
@@ -916,16 +890,20 @@ activity.published_release_label=Dikeluarkan
search=Cari
search.search_repo=Cari repositori
search.results=Cari hasil untuk "%s" dalam <a href="%s">%s</a>
+search.code_no_results=Tidak ada kode sumber yang cocok dengan istilah yang anda cari.
settings=Pengaturan
settings.desc=Pengaturan dimana anda dapat mengelola pengaturan untuk repositori
+settings.options=Repositori
settings.collaboration.write=Tulis
settings.collaboration.read=Baca
+settings.collaboration.owner=Pemilik
settings.collaboration.undefined=Tidak terdefinisi
settings.hooks=Webhooks
settings.githooks=Git kait
settings.basic_settings=Pengaturan Dasar
settings.mirror_settings=Pengaturan Duplikat
+settings.site=Situs web
settings.update_settings=Perbarui Pengaturan
settings.advanced_settings=Pengaturan Lanjutan
settings.external_wiki_url=URL Eksternal Wiki
@@ -937,14 +915,18 @@ settings.danger_zone=Zona Bahaya
settings.new_owner_has_same_repo=Pemilik baru sudah memiliki repositori dengan nama yang sama. Silakan pilih nama lain.
settings.transfer=Transfer Kepemilikan
settings.transfer_owner=Pemilik Baru
+settings.trust_model.collaborator=Kalaborator
settings.delete=Menghapus Repositori Ini
settings.delete_notices_1=- Operasi ini <strong>TIDAK BISA</strong> dibatalkan.
+settings.delete_collaborator=Menghapus
settings.search_user_placeholder=Cari pengguna…
+settings.teams=Tim
settings.add_webhook=Tambahkan Webhook
settings.webhook.test_delivery=Percobaan Pengiriman
settings.webhook.request=Permintaan
settings.webhook.response=Tanggapan
settings.webhook.headers=Tajuk
+settings.webhook.payload=Konten
settings.webhook.body=Tubuh
settings.githook_edit_desc=Jika hook tidak aktif, konten sampel akan dipaparkan. Meninggalkan konten dengan nilai kosong akan menonaktifkan hook ini.
settings.githook_name=Nama Hook
@@ -956,8 +938,12 @@ settings.slack_icon_url=Ikon URL
settings.discord_username=Nama pengguna
settings.discord_icon_url=URL ikon
settings.event_create=Menciptakan
+settings.event_delete=Hapus
+settings.event_fork=Garpu
+settings.event_wiki=Wiki
settings.event_push=Dorong
settings.event_repository=Repositori
+settings.event_issues=Masalah
settings.event_pull_request=Tarik permintaan
settings.update_webhook=Perbarui Webhook
settings.recent_deliveries=Pengiriman Terakhir
@@ -977,6 +963,7 @@ settings.protected_branch_can_push_no=Anda tidak dapat mendorong
settings.add_protected_branch=Aktifkan perlindungan
settings.delete_protected_branch=Nonaktifkan perlindungan
settings.choose_branch=Pilih branch…
+settings.edit_protected_branch=Edit
diff.browse_source=Telusuri Sumber
diff.parent=orang tua
@@ -987,6 +974,7 @@ diff.show_unified_view=Pandangan Terpadu
diff.stats_desc=<strong> %d mengubah file</strong> dengan <strong>%d tambahan</strong> dan <strong>%d penghapusan</strong>
diff.bin=TEMPAT SAMPAH
diff.view_file=Melihat File
+diff.file_byte_size=Ukuran
diff.file_suppressed=File diff ditekan karena terlalu besar
release.releases=Rilis
@@ -1024,7 +1012,7 @@ org_name_holder=Nama Organisasi
org_full_name_holder=Organisasi Nama Lengkap
create_org=Buat Organisasi
repo_updated=Diperbarui
-people=Orang
+members=Anggota
teams=Tim
lower_members=anggota
lower_repositories=repositori
@@ -1039,12 +1027,14 @@ settings=Pengaturan
settings.full_name=Nama Lengkap
settings.website=Situs web
settings.location=Lokasi
+settings.visibility.private_shortname=Pribadi
settings.update_settings=Perbarui Setelan
settings.update_setting_success=Pengaturan organisasi telah diperbarui.
settings.delete=Menghapus Organisasi
settings.delete_account=Menghapus Organisasi Ini
settings.confirm_delete_account=Konfirmasi Penghapusan
+settings.delete_org_title=Menghapus Organisasi
settings.hooks_desc=Tambahkan webhooks yang akan dipicu untuk <strong>semua repositori</strong> di bawah organisasi ini.
@@ -1059,6 +1049,7 @@ members.invite_now=Mengundang Sekarang
teams.join=Ikut
teams.leave=Meninggalkan
+teams.read_access=Dibaca
teams.no_desc=Tim ini tidak memiliki keterangan
teams.settings=Pengaturan
teams.members=Anggota tim
@@ -1067,7 +1058,7 @@ teams.add_team_member=Tambahkan Anggota Tim
teams.delete_team_success=Tim sudah di hapus.
teams.repositories=Tim repositori
teams.search_repo_placeholder=Cari repositori…
-teams.add_nonexistent_repo=Repositori yang ingin Anda tambahkan tidak ada; Silahkan buat terlebih dahulu.
+teams.add_nonexistent_repo=Repositori yang ingin Anda tambahkan tidak ada
[admin]
dashboard=Dasbor
@@ -1115,6 +1106,7 @@ dashboard.total_gc_pause=Total GC di jeda
dashboard.last_gc_pause=GC di jeda terakhir
dashboard.gc_times=Waktu GC
+users.full_name=Nama Lengkap
users.activated=Diaktifkan
users.admin=Pengelola
users.repos=Repo
@@ -1122,7 +1114,9 @@ users.created=Dibuat
users.edit=Edit
users.auth_source=Sumber Otentikasi
users.local=Lokal
+users.list_status_filter.is_admin=Pengelola
+emails.activated=Diaktifkan
orgs.org_manage_panel=Manajemen Organisasi
orgs.name=Nama
@@ -1138,6 +1132,11 @@ repos.stars=Bintang
repos.issues=Masalah
repos.size=Ukuran
+packages.owner=Pemilik
+packages.name=Nama
+packages.type=Jenis
+packages.repository=Repositori
+packages.size=Ukuran
@@ -1178,11 +1177,12 @@ auths.tips.oauth2.general=Otentikasi OAuth2
auths.tips.oauth2.general.tip=Saat mendaftarkan otentikasi OAuth2 yang baru, URL menelepon kembali/mengahlihkan jurusan harus menjadi: <host>/user/oauth2/<Authentication Name>/callback
auths.tip.oauth2_provider=Penyediaan OAuth2
auths.tip.dropbox=Membuat aplikasi baru di https://www.dropbox.com/developers/apps
-auths.tip.facebook=Daftarkan sebuah aplikasi baru di https://developers.facebook.com/apps dan tambakan produk "Facebook Masuk"
+auths.tip.facebook=`Daftarkan sebuah aplikasi baru di https://developers.facebook.com/apps dan tambakan produk "Facebook Masuk"`
auths.tip.github=Mendaftar aplikasi OAuth baru di https://github.com/settings/applications/new
auths.tip.gitlab=Mendaftar aplikasi baru di https://gitlab.com/profile/applications
auths.tip.openid_connect=Gunakan membuka ID yang terhubung ke jelajah URL (<server>/.well-known/openid-configuration) untuk menentukan titik akhir
auths.new_success=Otentikasi '%s' telah ditambahkan.
+auths.delete=Menghapus Otentikasi Sumber
auths.delete_auth_title=Menghapus Otentikasi Sumber
config.server_config=Pengaturan Server
@@ -1236,6 +1236,7 @@ config.skip_tls_verify=Melewatkan verifikasi TLS
config.mailer_enabled=Diaktifkan
config.mailer_name=Nama
+config.mailer_smtp_port=Port SMTP
config.mailer_user=Pengguna
config.mailer_use_sendmail=Menggunakan Sendmail
config.mailer_sendmail_path=Jalur Sendmail
@@ -1325,7 +1326,6 @@ monitor.queue.settings.changed=Pengaturan diperbarui
notices.system_notice_list=Pemberitahuan sistem
notices.view_detail_header=Lihat rincian pemberitahuan
-notices.actions=Tindakan
notices.select_all=Pilih semua
notices.deselect_all=Tidak pilih semua
notices.inverse_selection=Seleksi terbalik
@@ -1393,4 +1393,24 @@ error.no_unit_allowed_repo=Anda tidak diijinkan untuk melihat semua unit dari re
error.unit_not_allowed=Anda tidak diizinkan untuk mengunjungi unit repositori ini.
[packages]
+filter.type=Jenis
+conan.details.repository=Repositori
+owner.settings.cleanuprules.enabled=Aktif
+
+[secrets]
+name=Nama
+
+[actions]
+
+
+
+runners.name=Nama
+runners.owner_type=Jenis
+runners.description=Deskripsi
+runners.task_list.run=Lari
+runners.task_list.repository=Repositori
+runners.task_list.commit=Memperbuat
+
+runs.commit=Memperbuat
+
diff --git a/options/locale/locale_is-IS.ini b/options/locale/locale_is-IS.ini
index 3b5155840..bd596105d 100644
--- a/options/locale/locale_is-IS.ini
+++ b/options/locale/locale_is-IS.ini
@@ -56,7 +56,6 @@ new_mirror=Ný Speglun
new_fork=Ný Hugbúnaðarskipting
new_org=Ný Stofnun
new_project=Nýtt Verkefni
-new_project_board=Stjórn Nýs Verkefnis
manage_org=Stjórna Stofnunum
admin_panel=Stjórnborð
account_settings=Notandastillingar
@@ -85,6 +84,7 @@ remove=Fjarlægja
remove_all=Fjarlægja Allt
edit=Breyta
+
copy=Afrita
copy_url=Afrita vefslóð
copy_branch=Afritaðu heiti greinar
@@ -104,6 +104,8 @@ error404=Síðan sem þú ert að reyna að fá annað hvort <strong>er ekki til
never=Aldrei
+[aria]
+
[filter]
[error]
@@ -178,6 +180,8 @@ log_root_path_helper=Annálaskrár verða skrifaðar í þessa möppu.
optional_title=Valfrjálsar Stillingar
email_title=Tölvupóstsstillingar
+smtp_addr=SMTP Hýsill
+smtp_port=SMTP Gátt
smtp_from=Senda Tölvupóst Sem
smtp_from_helper=Netfang sem Gitea mun nota. Sláðu inn venjulegt netfang eða notaðu „Nafn“ <email@example.com> sniðið.
mailer_user=SMTP Notandanafn
@@ -396,7 +400,7 @@ user_not_exist=Notandinn er ekki til.
team_not_exist=Liðið er ekki til.
-org_still_own_repo=Þessi stofnun á enn eina eða fleiri hugbúnaðarsöfn; eyddu þeim eða flyttu þær fyrst.
+org_still_own_repo=Þessi stofnun á enn eina eða fleiri hugbúnaðarsöfn
[user]
@@ -549,6 +553,8 @@ token_name=Táknlykills Heiti
generate_token=Mynda Táknlykil
delete_token=Eyða
access_token_deletion=Eyða Aðgangslykli
+access_token_deletion_cancel_action=Hætta við
+access_token_deletion_confirm_action=Eyða
create_oauth2_application_button=Skapa Forrit
update_oauth2_application_success=Þú hefur uppfært OAuth2 forritið.
@@ -569,6 +575,8 @@ or_enter_secret=Eða sláðu inn leyndarmálið: %s
webauthn_nickname=Gælunafn
+link_account=Tengja Notanda
+
@@ -681,6 +689,7 @@ tags=Merki
issues=Vandamál
pulls=Sameiningarbeiðnir
project_board=Verkefni
+packages=Pakkar
labels=Skýringar
milestones=Tímamót
@@ -748,12 +757,11 @@ projects.edit=Breyta Verkefnum
projects.modify=Uppfæra Verkefni
projects.type.none=Ekkert
projects.type.uncategorized=Óflokkuð
-projects.board.new_submit=Staðfesta
-projects.board.set_default=Stilla Sjálfgildi
-projects.board.color=Litur
+projects.column.edit_title=Heiti
+projects.column.new_title=Heiti
+projects.column.color=Litað
projects.open=Opna
projects.close=Loka
-projects.board.assigned_to=Úthlutað til
issues.filter_projects=Sía Verkefni
issues.filter_labels=Sía Lýsingar
@@ -780,6 +788,10 @@ issues.filter_label=Lýsing
issues.filter_label_no_select=Allar lýsingar
issues.filter_milestone=Tímamót
issues.filter_milestone_no_select=Öll tímamót
+issues.filter_project=Verkefni
+issues.filter_project_none=Ekkert verkefni
+issues.filter_assignee=Úthlutað að
+issues.filter_poster=Höfundur
issues.filter_type=Tegund
issues.filter_type.all_issues=Öll vandamál
issues.filter_type.assigned_to_you=Úthlutuð til þín
@@ -799,12 +811,14 @@ issues.action_close=Loka
issues.action_label=Lýsing
issues.action_milestone=Tímamót
issues.action_milestone_no_select=Ekkert tímamót
+issues.action_assignee=Úthlutað að
issues.opened_by=opnað %[1]s af <a href="%[2]s">%[3]s</a>
issues.opened_by_fake=opnað %[1] af %[2]s
issues.previous=Fyrri
issues.next=Ãfram
issues.open_title=Opið
issues.closed_title=Lokað
+issues.draft_title=Uppkast
issues.num_comments=%d ummæli
issues.commented_at=`gerði ummæli <a href="#%s">%s</a>`
issues.context.edit=Breyta
@@ -1007,7 +1021,9 @@ activity.git_stats_deletion_1=%d eyðing
activity.git_stats_deletion_n=%d eyðingar
search=Leita
+search.fuzzy=Óljóst
search.code_no_results=Enginn samsvarandi frumkóði fannst eftur þínum leitarorðum.
+search.code_search_unavailable=Sem stendur er kóðaleit ekki í boði. Vinsamlegast hafðu samband við síðustjórann þinn.
settings=Stillingar
settings.options=Hugbúnaðarsafn
@@ -1045,6 +1061,7 @@ settings.teams=Lið
settings.add_webhook=Bæta við Vefkróki
settings.webhook.request=Beiðni
settings.webhook.headers=Hausar
+settings.webhook.payload=Innihald
settings.webhook.body=Meginmál
settings.update_githook=Uppfæra Krók
settings.slack_username=Notandanafn
@@ -1054,7 +1071,9 @@ settings.discord_username=Notandanafn
settings.discord_icon_url=Táknmyndarvefslóð
settings.event_delete=Eyða
settings.event_fork=Tvískipta
+settings.event_wiki=Handbók
settings.event_release=Útgáfa
+settings.event_push=Push
settings.event_repository=Hugbúnaðarsafn
settings.event_issues=Vandamál
settings.event_issues_desc=Vandamál opið, lokað, enduropnað eða breytt.
@@ -1128,7 +1147,7 @@ topic.done=Ã lagi
[org]
repo_updated=Uppfært
-people=Fólk
+members=Meðlimar
teams=Lið
lower_members=meðlimar
lower_repositories=hugbúnaðarsöfn
@@ -1194,6 +1213,8 @@ users.edit=Breyta
users.local=Staðbundið
users.list_status_filter.menu_text=Sía
users.list_status_filter.reset=Endurstilla
+users.list_status_filter.is_active=Virkt
+users.list_status_filter.is_admin=Stjórnandi
users.list_status_filter.is_prohibit_login=Stöðva Innskráningu
users.list_status_filter.not_prohibit_login=Leyfa Innskráningu
users.list_status_filter.not_2fa_enabled=Tvíþætt Auðkenning Óvirk
@@ -1216,6 +1237,7 @@ repos.issues=Vandamál
repos.size=Stærð
packages.total_size=Heildarstærð: %s
+packages.owner=Eigandi
packages.name=Heiti
packages.version=Útgáfa
packages.type=Tegund
@@ -1238,7 +1260,7 @@ auths.oauth2_icon_url=Táknmyndarvefslóð
auths.oauth2_profileURL=Notandasíðuslóð
auths.tips=Ãbendingar
auths.tip.dropbox=Búðu til nýtt forrit á https://www.dropbox.com/developers/apps
-auths.tip.yandex=Búðu til nýja umsókn á https://oauth.yandex.com/client/new. Veldu eftirfarandi heimildir úr „Yandex.Passport API“ kaflanum: "Aðgangur að netfangi", "Aðgangur að notandamynd" og "Aðgangur að notendanafni, fornafni og eftirnafni, kyni"
+auths.tip.yandex=`Búðu til nýja umsókn á https://oauth.yandex.com/client/new. Veldu eftirfarandi heimildir úr „Yandex.Passport API“ kaflanum: "Aðgangur að netfangi", "Aðgangur að notandamynd" og "Aðgangur að notendanafni, fornafni og eftirnafni, kyni"`
config.app_name=Heiti Vefsvæðis
config.app_ver=Útgáfu Gitea
@@ -1264,6 +1286,7 @@ config.db_path=Slóð
config.mailer_name=Heiti
+config.mailer_smtp_port=SMTP Gátt
config.mailer_user=Notandi
@@ -1364,3 +1387,24 @@ pypi.requires=Þarfnast Python
pypi.documentation=Frekari upplýsingar um PyPI skrána er hægt að finna <a target="_blank" rel="noopener noreferrer" href="https://docs.gitea.io/en-us/packages/pypi/">hér</a>.
rubygems.documentation=Frekari upplýsingar um RubyGems skrána er hægt að finna <a target="_blank" rel="noopener noreferrer" href="https://docs.gitea.io/en-us/packages/rubygems/">hér</a>.
+[secrets]
+value=Gildi
+name=Heiti
+
+[actions]
+
+
+
+runners.id=Auðkenni
+runners.name=Heiti
+runners.owner_type=Tegund
+runners.description=Lýsing
+runners.labels=Lýsingar
+runners.task_list.run=Keyra
+runners.task_list.repository=Hugbúnaðarsafn
+runners.task_list.commit=Framlag
+runners.status.active=Virkt
+
+runs.commit=Framlag
+
+
diff --git a/options/locale/locale_it-IT.ini b/options/locale/locale_it-IT.ini
index 2c859a93e..d77baee6e 100644
--- a/options/locale/locale_it-IT.ini
+++ b/options/locale/locale_it-IT.ini
@@ -41,7 +41,7 @@ webauthn_use_twofa=Usa un codice a due fattori dal tuo telefono
webauthn_error=Impossibile leggere la tua chiave di sicurezza.
webauthn_unsupported_browser=Il tuo browser al momento non supporta WebAuthn.
webauthn_error_unknown=Si è verificato un errore sconosciuto. Riprova.
-webauthn_error_insecure=WebAuthn supporta solo connessioni sicure. Per il test su HTTP, è possibile utilizzare l'origine "localhost" o "127.0.0.1"
+webauthn_error_insecure=`WebAuthn supporta solo connessioni sicure. Per il test su HTTP, è possibile utilizzare l'origine "localhost" o "127.0.0.1"`
webauthn_error_unable_to_process=Il server non può elaborare la richiesta.
webauthn_error_duplicated=La chiave di sicurezza non è consentita per questa richiesta. Assicurati che la chiave non sia già registrata.
webauthn_error_empty=Devi impostare un nome per questa chiave.
@@ -57,7 +57,6 @@ new_mirror=Nuovo Mirror
new_fork=Nuovo Fork
new_org=Nuova organizzazione
new_project=Nuovo progetto
-new_project_board=Nuova scheda del progetto
manage_org=Gestisci le organizzazioni
admin_panel=Amministrazione Sito
account_settings=Impostazioni dell'account
@@ -86,6 +85,9 @@ remove=Rimuovi
remove_all=Rimuovi tutti
edit=Modifica
+enabled=Attivo
+disabled=Disabilitato
+
copy=Copia
copy_url=Copia URL
copy_branch=Copia nome del ramo
@@ -106,6 +108,8 @@ never=Mai
rss_feed=Feed RSS
+[aria]
+
[filter]
[error]
@@ -224,7 +228,6 @@ internal_token_failed=Generazione del token interno non riuscita: %v
secret_key_failed=Generazione della chiave segreta non riuscita: %v
save_config_failed=Salvataggio della configurazione non riuscito: %v
invalid_admin_setting=Le impostazioni dell'account amministratore sono invalide: %v
-install_success=Benvenuto! Grazie per aver scelto Gitea. Attenzione e buon divertimento!
invalid_log_root_path=Il percorso del log non è valido: %v
default_keep_email_private=Nascondi Indirizzo Email di Default
default_keep_email_private_popup=Nasconi l'indirizzo email dei nuovi account utente di default.
@@ -250,7 +253,7 @@ view_home=Vedi %s
search_repos=Trova un repository…
filter=Altro filtri
filter_by_team_repositories=Filtra per repository del team
-feed_of=Feed di "%s"
+feed_of=`Feed di "%s"`
show_archived=Archiviato
show_both_archived_unarchived=Mostra sia gli archiviati che i non archiviati
@@ -489,14 +492,14 @@ cannot_add_org_to_team=Un'organizzazione non può essere aggiunto come membro de
invalid_ssh_key=Impossibile verificare la tua chiave SSH: %s
invalid_gpg_key=Impossibile verificare la tua chiave GPG: %s
invalid_ssh_principal=Principal non valido: %s
-unable_verify_ssh_key=Impossibile verificare la tua chiave SSH; si prega di ricontrollarla per verificare eventuali errori.
+unable_verify_ssh_key=Impossibile verificare la tua chiave SSH
auth_failed=Autenticazione non riuscita: %v
-still_own_repo=Il tuo account possiede una o più repositories; rimuovile o trasferiscile per proseguire.
-still_has_org=Il tuo account è un membro di una o più organizzazioni; abbandonali prima di proseguire.
-still_own_packages=Il tuo account possiede uno o più pacchetti; eliminali prima.
+still_own_repo=Il tuo account possiede una o più repositories
+still_has_org=Il tuo account è un membro di una o più organizzazioni
+still_own_packages=Il tuo account possiede uno o più pacchetti
org_still_own_repo=Questa organizzazione possiede ancora una o più repositories, rimuoverle o trasferirle per continuare.
-org_still_own_packages=Questa organizzazione possiede ancora uno o più pacchetti; eliminarli prima.
+org_still_own_packages=Questa organizzazione possiede ancora uno o più pacchetti
target_branch_not_exist=Il ramo (branch) di destinazione non esiste.
@@ -786,6 +789,7 @@ remove_account_link=Rimuovi account collegato
remove_account_link_desc=Rimuovere un account collegato ne revoca l'accesso al tuo account Gitea. Continuare?
remove_account_link_success=L'account collegato è stato rimosso.
+
orgs_none=Non sei membro di alcuna organizzazione.
repos_none=Non possiedi alcun repository
@@ -897,9 +901,9 @@ delete_preexisting_success=Eliminato file non adottati in %s
blame_prior=Visualizza la colpa prima di questa modifica
transfer.accept=Accetta trasferimento
-transfer.accept_desc=Trasferisci a "%s"
+transfer.accept_desc=`Trasferisci a "%s"`
transfer.reject=Rifiuta trasferimento
-transfer.reject_desc=Annulla il trasferimento a "%s"
+transfer.reject_desc=`Annulla il trasferimento a "%s"`
transfer.no_permission_to_accept=Non hai i permessi per accettare
transfer.no_permission_to_reject=Non hai i permessi per rifiutare
@@ -1148,7 +1152,6 @@ commits.signed_by_untrusted_user_unmatched=Firmato da un utente non attendibile
commits.gpg_key_id=ID Chiave GPG
commits.ssh_key_fingerprint=Impronta Digitale Chiave SSH
-commit.actions=Azioni
commit.revert=Ripristina
commit.revert-header=Ripristina: %s
commit.revert-content=Selezionare il ramo su cui ripristinare:
@@ -1181,19 +1184,11 @@ projects.type.bug_triage=Bug Triage
projects.template.desc=Template di progetto
projects.template.desc_helper=Seleziona un modello di progetto per iniziare
projects.type.uncategorized=Senza categoria
-projects.board.edit=Modifica scheda
-projects.board.edit_title=Nuovo Nome Della Scheda
-projects.board.new_title=Nuovo Nome Della Scheda
-projects.board.new_submit=Invia
-projects.board.new=Nuova Scheda
-projects.board.set_default=Imposta come predefinito
-projects.board.set_default_desc=Imposta questa scheda come predefinita per problemi non categorizzati e pull
-projects.board.delete=Elimina Scheda
-projects.board.deletion_desc=L'eliminazione di una scheda di progetto sposta tutti i problemi correlati a 'Uncategorized'. Continuare?
-projects.board.color=Colore
+projects.column.edit_title=Nome
+projects.column.new_title=Nome
+projects.column.color=Colore
projects.open=Apri
projects.close=Chiudi
-projects.board.assigned_to=Assegnato a
issues.desc=Organizza le segnalazioni di bug, attività e pietre miliari.
issues.filter_assignees=Filtra assegnatario
@@ -1267,6 +1262,8 @@ issues.filter_label_exclude=`Usa <code>alt</code> + <code>click/enter</code> per
issues.filter_label_no_select=Tutte le etichette
issues.filter_milestone=Traguardo
issues.filter_milestone_no_select=Tutte le pietre miliari
+issues.filter_project=Progetto
+issues.filter_project_none=Nessun progetto
issues.filter_assignee=Assegnatario
issues.filter_assginee_no_select=Tutte le assegnazioni
issues.filter_poster=Autore
@@ -1418,6 +1415,7 @@ issues.error_removing_due_date=Impossibile rimuovere la data di scadenza.
issues.push_commit_1=aggiunto %d commit %s
issues.push_commits_n=aggiunto %d commit %s
issues.force_push_codes=`force-pushed %[1]s from <a class="ui sha" href="%[3]s"><code>%[2]s</code></a> to <a class="ui sha" href="%[5]s"><code>%[4]s</code></a> %[6]s`
+issues.force_push_compare=Confronta
issues.due_date_form=yyyy-mm-dd
issues.due_date_form_add=Aggiungi data di scadenza
issues.due_date_form_edit=Modifica
@@ -1818,11 +1816,6 @@ settings.enable_timetracker=Abilita il cronografo
settings.allow_only_contributors_to_track_time=Consenti soltanto ai contributori di utilizzare il cronografo
settings.pulls_desc=Abilita le pull request del repository
settings.pulls.ignore_whitespace=Ignora gli spazi bianchi per evitare conflitti
-settings.pulls.allow_merge_commits=Abilita il merging dei commit
-settings.pulls.allow_rebase_merge=Abilita l'unione dei commit mediante riassegnazione
-settings.pulls.allow_rebase_merge_commit=Abilita il rebase con commit ad unione esplicita (--no-ff)
-settings.pulls.allow_squash_commits=Abilita lo Squashing per unire i commits via merge
-settings.pulls.allow_manual_merge=Abilita Mark PR come unito manualmente
settings.pulls.enable_autodetect_manual_merge=Abilita il rilevamento automatico della fusione manuale (Nota: in alcuni casi speciali possono verificarsi errori)
settings.pulls.allow_rebase_update=Abilita l'aggiornamento del ramo pull request per rebase
settings.pulls.default_delete_branch_after_merge=Elimina il ramo pull request dopo la fusione per impostazione predefinita
@@ -1863,7 +1856,7 @@ settings.transfer_notices_2=-Si manterrà l'accesso al repository se si trasferi
settings.transfer_notices_3=- Se il repository è privato e viene trasferito a un singolo utente, questa azione si assicura che l'utente abbia almeno i permessi di lettura (e le modifiche se necessario).
settings.transfer_owner=Nuovo Proprietario
settings.transfer_perform=Esegui trasferimento
-settings.transfer_started=Questo repository è stato contrassegnato per il trasferimento e attende conferma da "%s"
+settings.transfer_started=`Questo repository è stato contrassegnato per il trasferimento e attende conferma da "%s"`
settings.transfer_succeed=Il repository è stato trasferito.
settings.signing_settings=Impostazioni Verifica Firma
settings.trust_model=Modello di Fiducia per la Firma
@@ -1952,6 +1945,7 @@ settings.event_delete=Elimina
settings.event_delete_desc=Branch o tag eliminati.
settings.event_fork=Fork
settings.event_fork_desc=Repository forkato.
+settings.event_wiki=Wiki
settings.event_release=Release
settings.event_release_desc=Release pubblicata, aggiornata o rimossa in una repository.
settings.event_push=Push
@@ -2102,7 +2096,6 @@ settings.bot_token=Token del Bot
settings.chat_id=ID chat
settings.matrix.homeserver_url=URL Homeserver
settings.matrix.room_id=ID della stanza
-settings.matrix.access_token=Token di accesso
settings.matrix.message_type=Tipo di messaggio
settings.archive.button=Archivia Repo
settings.archive.header=Archivia questo Repo
@@ -2301,7 +2294,7 @@ org_full_name_holder=Nome completo dell'organizzazione
org_name_helper=I nomi delle organizzazioni devono essere brevi e semplici da ricordare.
create_org=Crea Organizzazione
repo_updated=Aggiornato
-people=Utenti
+members=Membri
teams=Team
lower_members=membri
lower_repositories=repository
@@ -2698,12 +2691,15 @@ auths.sspi_default_language=Lingua predefinita dell'utente
auths.sspi_default_language_helper=Lingua predefinita per gli utenti creati automaticamente dal metodo di autenticazione SSPI. Lascia vuoto se preferisci che la lingua venga rilevata automaticamente.
auths.tips=Consigli
auths.tips.oauth2.general=Autenticazione OAuth2
-auths.tips.oauth2.general.tip="Quando si registra una nuova autenticazione OAuth2, l'URL di callback/reindirizzamento deve essere:<host>/user/oauth2/<Authentication Name>/callback
+auths.tips.oauth2.general.tip=`"Quando si registra una nuova autenticazione OAuth2, l'URL di callback/reindirizzamento deve essere:<host>/user/oauth2/<Authentication Name>/callback`
auths.tip.oauth2_provider=OAuth2 Provider
auths.tip.bitbucket=Registra un nuovo cliente OAuth su https://bitbucket.org/account/user/<your username>/oauth-consumers/new e aggiungi il permesso 'Account' - 'Read'
-auths.tip.nextcloud=Registra un nuovo OAuth sulla tua istanza utilizzando il seguente menu "Impostazioni -> Sicurezza -> OAuth 2.0 client"
+auths.tip.nextcloud=`Registra un nuovo OAuth sulla tua istanza utilizzando il seguente menu "`
+auths.tip.oauth2_provider=OAuth2 Provider
+auths.tip.bitbucket=Registra un nuovo cliente OAuth su https://bitbucket.org/account/user/<your username>/oauth-consumers/new e aggiungi il permesso 'Account' - 'Read'
+auths.tip.nextcloud=`Registra un nuovo OAuth sulla tua istanza utilizzando il seguente menu "Impostazioni -> Sicurezza -> OAuth 2.0 client"`
auths.tip.dropbox=Crea una nuova applicazione su https://www.dropbox.com/developers/apps
-auths.tip.facebook=Registra una nuova applicazione su https://developers.facebook.com/apps e aggiungi il prodotto "Facebook Login"
+auths.tip.facebook=`Registra una nuova applicazione su https://developers.facebook.com/apps e aggiungi il prodotto "Facebook Login"`
auths.tip.github=Registra una nuova applicazione OAuth su https://github.com/settings/applications/new
auths.tip.gitlab=Registra una nuova applicazione su https://gitlab.com/profile/applications
auths.tip.google_plus=Ottieni le credenziali del client OAuth2 dalla console API di Google su https://console.developers.google.com/
@@ -2711,7 +2707,7 @@ auths.tip.openid_connect=Utilizza l'OpenID Connect Discovery URL (<server>/.well
auths.tip.twitter=Vai su https://dev.twitter.com/apps, crea una applicazione e assicurati che l'opzione "Allow this application to be used to Sign In with Twitter" sia abilitata
auths.tip.discord=Registra una nuova applicazione su https://discordapp.com/developers/applications/me
auths.tip.gitea=Registra una nuova applicazione OAuth2. La guida può essere trovata a https://docs.gitea.io/en-us/oauth2-provider/
-auths.tip.yandex=Crea una nuova applicazione su https://oauth.yandex.com/client/new. Seleziona i seguenti permessi da "Yandex. assport API": "Access to email address", "Access to user avatar" e "Access to username, name and surname, gender"
+auths.tip.yandex=`Crea una nuova applicazione su https://oauth.yandex.com/client/new. Seleziona i seguenti permessi da "Yandex. assport API": "Access to email address", "Access to user avatar" e "Access to username, name and surname, gender"`
auths.tip.mastodon=Inserisci un URL di istanza personalizzato per l'istanza mastodon con cui vuoi autenticarti (o usa quella predefinita)
auths.edit=Modifica fonte di autenticazione
auths.activated=Questa fonte di autenticazione è attiva
@@ -2945,7 +2941,6 @@ monitor.queue.pool.cancel_desc=Lasciare una coda senza alcun gruppo di worker pu
notices.system_notice_list=Avvisi di Sistema
notices.view_detail_header=Visualizza dettagli dell'avviso
-notices.actions=Azioni
notices.select_all=Seleziona tutto
notices.deselect_all=Deseleziona tutto
notices.inverse_selection=Inverti selezione
@@ -2961,7 +2956,6 @@ notices.delete_success=Gli avvisi di sistema sono stati eliminati.
[action]
create_repo=ha creato il repository <a href="%s">%s</a>
rename_repo=repository rinominato da <code>%[1]s</code> a <a href="%[2]s">[3]s</a>
-commit_repo=a inviato a <a href="%[2]s">%[3]s</a> di <a href="%[1]s">%[4]s</a>
create_issue=`ha aperto il problema <a href="%[1]s">%[3]s#%[2]s</a>`
close_issue=`ha chiuso il problema <a href="%[1]s">%[3]s#%[2]s</a>`
reopen_issue=`ha riaperto il problema <a href="%[1]s">%[3]s#%[2]s</a>`
@@ -3073,6 +3067,7 @@ versions.on=su
versions.view_all=Vedi tutti
dependency.id=ID
dependency.version=Versione
+chef.install=Per installare il pacchetto, eseguire il seguente comando:
composer.registry=Imposta questo registro nel tuo file <code>~/.composer/config.json</code>:
composer.install=Per installare il pacchetto utilizzando Composer, eseguire il seguente comando:
composer.documentation=Per ulteriori informazioni sul registro dei compositori, consultare <a target="_blank" rel="noopener noreferrer" href="https://docs.gitea.io/en-us/packages/composer/">la documentazione</a>.
@@ -3084,8 +3079,6 @@ conan.install=Per installare il pacchetto usando Conan, eseguire il seguente com
conan.documentation=Per ulteriori informazioni sul registro di Conan, consultare <a target="_blank" rel="noopener noreferrer" href="https://docs.gitea.io/en-us/packages/conan/">la documentazione</a>.
container.details.type=Tipo Immagine
container.details.platform=Piattaforma
-container.details.repository_site=Sito Repository
-container.details.documentation_site=Sito Documentazione
container.pull=Tirare l'immagine dalla riga di comando:
container.documentation=Per ulteriori informazioni sul registro Container, vedere <a target="_blank" rel="noopener noreferrer" href="https://docs.gitea.io/en-us/packages/container/">la documentazione</a>.
container.multi_arch=OS / Arch
@@ -3118,7 +3111,6 @@ npm.dependencies.optional=Dipendenze Opzionali
npm.details.tag=Tag
pub.install=Per installare il pacchetto utilizzando NuGet, eseguire il seguente comando:
pub.documentation=Per ulteriori informazioni sul registro Pub, consultare <a target="_blank" rel="noopener noreferrer" href="https://docs.gitea.io/en-us/packages/pub/">la documentazione</a>.
-pub.details.repository_site=Sito Repository
pypi.requires=Richiede Python
pypi.install=Per installare il pacchetto usando pip, eseguire il seguente comando:
pypi.documentation=Per ulteriori informazioni sul registro PyPI, consultare <a target="_blank" rel="noopener noreferrer" href="https://docs.gitea.io/en-us/packages/pypi/">la documentazione</a>.
@@ -3140,4 +3132,26 @@ settings.delete.description=L'eliminazione di un pacchetto è permanente e non p
settings.delete.notice=Stai per eliminare %s (%s). Questa operazione è irreversibile, sei sicuro?
settings.delete.success=Il pacchetto è stato eliminato.
settings.delete.error=Impossibile eliminare il pacchetto.
+owner.settings.cleanuprules.enabled=Attivo
+
+[secrets]
+value=Valore
+name=Nome
+
+[actions]
+
+
+
+runners.id=ID
+runners.name=Nome
+runners.owner_type=Tipo
+runners.description=Descrizione
+runners.labels=Etichette
+runners.task_list.run=Esegui
+runners.task_list.repository=Repository
+runners.task_list.commit=Commit
+runners.status.active=Attivo
+
+runs.commit=Commit
+
diff --git a/options/locale/locale_ja-JP.ini b/options/locale/locale_ja-JP.ini
index abb58a4f2..8e77329f5 100644
--- a/options/locale/locale_ja-JP.ini
+++ b/options/locale/locale_ja-JP.ini
@@ -57,7 +57,7 @@ new_mirror=æ–°ã—ã„ミラー
new_fork=æ–°ã—ã„フォーク
new_org=æ–°ã—ã„組織
new_project=æ–°ã—ã„プロジェクト
-new_project_board=æ–°ã—ã„プロジェクトボード
+new_project_column=æ–°ã—ã„列
manage_org=組織を管ç†
admin_panel=サイト管ç†
account_settings=アカウント設定
@@ -86,11 +86,16 @@ remove=除去
remove_all=ã™ã¹ã¦é™¤åŽ»
edit=編集
+enabled=有効
+disabled=無効
+
copy=コピー
copy_url=URLをコピー
+copy_content=内容をコピー
copy_branch=ブランãƒåをコピー
copy_success=コピーã•ã‚Œã¾ã—ãŸï¼
copy_error=コピーã«å¤±æ•—ã—ã¾ã—ãŸ
+copy_type_unsupported=ã“ã®ãƒ•ã‚¡ã‚¤ãƒ«ã‚¿ã‚¤ãƒ—ã¯ã‚³ãƒ”ーã§ãã¾ã›ã‚“
write=書ãè¾¼ã¿
preview=プレビュー
@@ -106,6 +111,12 @@ never=ç„¡ã—
rss_feed=RSSフィード
+[aria]
+navbar=ナビゲーションãƒãƒ¼
+footer=フッター
+footer.software=ソフトウェアã«ã¤ã„ã¦
+footer.links=リンク
+
[filter]
string.asc=A - Z
string.desc=Z - A
@@ -226,7 +237,6 @@ internal_token_failed=内部トークンã®ç”Ÿæˆã«å¤±æ•—ã—ã¾ã—ãŸ: %v
secret_key_failed=シークレットキーã®ç”Ÿæˆã«å¤±æ•—ã—ã¾ã—ãŸ: %v
save_config_failed=設定ファイルã®ä¿å­˜ã«å¤±æ•—ã—ã¾ã—ãŸ: %v
invalid_admin_setting=管ç†è€…アカウントã®è¨­å®šãŒç„¡åŠ¹ã§ã™: %v
-install_success=よã†ã“ã! Giteaã‚’é¸æŠžã—ã¦ã„ãŸã ãã€ã‚ã‚ŠãŒã¨ã†ã”ã–ã„ã¾ã™ã€‚楽ã—ã‚“ã§ãã ã•ã„!
invalid_log_root_path=ログã®ä¿å­˜å…ˆãƒ‘スãŒç„¡åŠ¹ã§ã™: %v
default_keep_email_private=デフォルトã§ãƒ¡ãƒ¼ãƒ«ã‚¢ãƒ‰ãƒ¬ã‚¹ã‚’éš ã™
default_keep_email_private_popup=æ–°ã—ã„ユーザーアカウントã§ã€ãƒ‡ãƒ•ã‚©ãƒ«ãƒˆã§ãƒ¡ãƒ¼ãƒ«ã‚¢ãƒ‰ãƒ¬ã‚¹ã‚’éš ã™è¨­å®šã«ã—ã¾ã™ã€‚
@@ -237,7 +247,10 @@ default_enable_timetracking_popup=æ–°ã—ã„リãƒã‚¸ãƒˆãƒªã®ã‚¿ã‚¤ãƒ ãƒˆãƒ©ãƒƒã
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ã«æŽ¥ç¶šã—ã¦å®šæœŸçš„ã«æ–°ã—ã„ãƒãƒ¼ã‚¸ãƒ§ãƒ³ã®ãƒªãƒªãƒ¼ã‚¹ã‚’確èªã—ã¾ã™ã€‚
[home]
uname_holder=ユーザーåã¾ãŸã¯ãƒ¡ãƒ¼ãƒ«ã‚¢ãƒ‰ãƒ¬ã‚¹
@@ -252,7 +265,7 @@ view_home=%s を表示
search_repos=リãƒã‚¸ãƒˆãƒªã‚’探ã™â€¦
filter=ãã®ä»–ã®ãƒ•ã‚£ãƒ«ã‚¿ãƒ¼
filter_by_team_repositories=ãƒãƒ¼ãƒ ãƒªãƒã‚¸ãƒˆãƒªã§çµžã‚Šè¾¼ã¿
-feed_of="%s" ã®ãƒ•ã‚£ãƒ¼ãƒ‰
+feed_of=`"%s" ã®ãƒ•ã‚£ãƒ¼ãƒ‰`
show_archived=アーカイブ
show_both_archived_unarchived=アーカイブã¨éžã‚¢ãƒ¼ã‚«ã‚¤ãƒ–ã®ä¸¡æ–¹ã‚’表示
@@ -315,6 +328,7 @@ email_not_associate=ã“ã®ãƒ¡ãƒ¼ãƒ«ã‚¢ãƒ‰ãƒ¬ã‚¹ã¯ã€ã©ã®ã‚¢ã‚«ã‚¦ãƒ³ãƒˆã«ã‚‚
send_reset_mail=アカウント回復メールをé€ä¿¡
reset_password=アカウントã®å›žå¾©
invalid_code=確èªã‚³ãƒ¼ãƒ‰ãŒç„¡åŠ¹ã‹æœŸé™åˆ‡ã‚Œã§ã™ã€‚
+invalid_password=アカウントã®ä½œæˆã«ä½¿ç”¨ã•ã‚ŒãŸãƒ‘スワードã¨ä¸€è‡´ã—ã¾ã›ã‚“。
reset_password_helper=アカウント回復
reset_password_wrong_user=アカウント回復ã®ãƒªãƒ³ã‚¯ã¯ %[2]s ã®ã‚‚ã®ã§ã™ãŒã€ã‚ãªãŸã¯ %[1]s ã§ã‚µã‚¤ãƒ³ã‚¤ãƒ³ä¸­ã§ã™
password_too_short=%d文字未満ã®ãƒ‘スワードã¯è¨­å®šã§ãã¾ã›ã‚“。
@@ -349,7 +363,7 @@ authorize_application=アプリケーションを許å¯
authorize_redirect_notice=ã“ã®ã‚¢ãƒ—リケーションを許å¯ã™ã‚‹ã¨ %s ã«ãƒªãƒ€ã‚¤ãƒ¬ã‚¯ãƒˆã—ã¾ã™ã€‚
authorize_application_created_by=ã“ã®ã‚¢ãƒ—リケーション㯠%s ãŒä½œæˆã—ã¾ã—ãŸã€‚
authorize_application_description=アクセスを許å¯ã™ã‚‹ã¨ã€ã“ã®ã‚¢ãƒ—リケーションã¯ã€ãƒ—ライベート リãƒã‚¸ãƒˆãƒªã‚„組織をå«ã‚€ã‚ãªãŸã®ã™ã¹ã¦ã®ã‚¢ã‚«ã‚¦ãƒ³ãƒˆæƒ…å ±ã«å¯¾ã—ã¦ã€ã‚¢ã‚¯ã‚»ã‚¹ã¨æ›¸ãè¾¼ã¿ãŒã§ãるよã†ã«ãªã‚Šã¾ã™ã€‚
-authorize_title="%s"ã«ã‚ãªãŸã®ã‚¢ã‚«ã‚¦ãƒ³ãƒˆã¸ã®ã‚¢ã‚¯ã‚»ã‚¹ã‚’許å¯ã—ã¾ã™ã‹ï¼Ÿ
+authorize_title=`"%s"ã«ã‚ãªãŸã®ã‚¢ã‚«ã‚¦ãƒ³ãƒˆã¸ã®ã‚¢ã‚¯ã‚»ã‚¹ã‚’許å¯ã—ã¾ã™ã‹ï¼Ÿ`
authorization_failed=èªå¯å¤±æ•—
authorization_failed_desc=ä¸æ­£ãªãƒªã‚¯ã‚¨ã‚¹ãƒˆã§ã‚ã£ãŸãŸã‚èªå¯ãŒå¤±æ•—ã—ã¾ã—ãŸã€‚ èªå¯ã—よã†ã¨ã—ãŸã‚¢ãƒ—リã®é–‹ç™ºè€…ã«é€£çµ¡ã—ã¦ãã ã•ã„。
sspi_auth_failed=SSPIèªè¨¼ã«å¤±æ•—ã—ã¾ã—ãŸ
@@ -358,6 +372,7 @@ password_pwned_err=HaveIBeenPwnedã¸ã®ãƒªã‚¯ã‚¨ã‚¹ãƒˆã‚’完了ã§ãã¾ã›ã‚“ã
[mail]
view_it_on=%s ã§è¦‹ã‚‹
+reply=ã¾ãŸã¯ã“ã®ãƒ¡ãƒ¼ãƒ«ã«ç›´æŽ¥è¿”ä¿¡ã—ã¦ãã ã•ã„
link_not_working_do_paste=é–‹ã‹ãªã„ã§ã™ã‹ï¼Ÿ コピーã—ã¦ãƒ–ラウザーã«è²¼ã‚Šä»˜ã‘ã¦ã¿ã¦ãã ã•ã„。
hi_user_x=ã“ã‚“ã«ã¡ã¯ã€<b>%s</b> ã•ã‚“。
@@ -461,6 +476,8 @@ url_error=`'%s' ã¯æœ‰åŠ¹ãªURLã§ã¯ã‚ã‚Šã¾ã›ã‚“。`
include_error=`ã¯æ–‡å­—列 '%s' ã‚’å«ã‚“ã§ã„ã‚‹å¿…è¦ãŒã‚ã‚Šã¾ã™ã€‚`
glob_pattern_error=`ã®globパターンãŒä¸æ­£ã§ã™: %s.`
regex_pattern_error=`ã®æ­£è¦è¡¨ç¾ãƒ‘ターンãŒä¸æ­£ã§ã™: %s.`
+username_error=`ã¯ã€è‹±æ•°å­—('0-9','a-z','A-Z')ã€ãƒ€ãƒƒã‚·ãƒ¥('-')ã€ã‚¢ãƒ³ãƒ€ãƒ¼ã‚¹ã‚³ã‚¢('_')ã€ãƒ‰ãƒƒãƒˆ('.')ã ã‘ã‚’å«ã‚ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚ 先頭ã¨æœ«å°¾ã¯è‹±æ•°å­—以外ã®æ–‡å­—ã«ã¯ã§ãã¾ã›ã‚“。 ã¾ãŸã€é€£ç¶šã—ãŸè‹±æ•°å­—以外ã®æ–‡å­—も許ã•ã‚Œã¾ã›ã‚“。`
+invalid_group_team_map_error=`ã®ãƒžãƒƒãƒ”ングãŒç„¡åŠ¹ã§ã™: %s`
unknown_error=ä¸æ˜Žãªã‚¨ãƒ©ãƒ¼:
captcha_incorrect=CAPTCHAコードãŒæ­£ã—ãã‚ã‚Šã¾ã›ã‚“。
password_not_match=パスワードãŒä¸€è‡´ã—ã¾ã›ã‚“。
@@ -497,10 +514,12 @@ team_not_exist=ãƒãƒ¼ãƒ ãŒå­˜åœ¨ã—ã¦ã„ã¾ã›ã‚“。
last_org_owner='Owners'ãƒãƒ¼ãƒ ã‹ã‚‰æœ€å¾Œã®ãƒ¦ãƒ¼ã‚¶ãƒ¼ã‚’削除ã™ã‚‹ã“ã¨ã¯ã§ãã¾ã›ã‚“。ã²ã¨ã¤ã®çµ„ç¹”ã«ã¯å°‘ãªãã¨ã‚‚一人ã®ã‚ªãƒ¼ãƒŠãƒ¼ãŒå¿…è¦ã§ã™ã€‚
cannot_add_org_to_team=組織ã¯ãƒãƒ¼ãƒ ãƒ¡ãƒ³ãƒãƒ¼ã¨ã—ã¦è¿½åŠ ã§ãã¾ã›ã‚“。
duplicate_invite_to_team=指定ã—ãŸãƒ¦ãƒ¼ã‚¶ãƒ¼ã¯ã™ã§ã«ãƒãƒ¼ãƒ ãƒ¡ãƒ³ãƒãƒ¼ã«æ‹›å¾…ã•ã‚Œã¦ã„ã¾ã™ã€‚
+organization_leave_success=ã‚ãªãŸã¯çµ„ç¹” %s ã‹ã‚‰è„±é€€ã—ã¾ã—ãŸã€‚
invalid_ssh_key=SSHキーãŒç¢ºèªã§ãã¾ã›ã‚“: %s
invalid_gpg_key=GPGキーãŒç¢ºèªã§ãã¾ã›ã‚“: %s
invalid_ssh_principal=無効ãªãƒ—リンシパル: %s
+must_use_public_key=ã‚ãªãŸãŒæä¾›ã—ãŸã‚­ãƒ¼ã¯ç§˜å¯†éµã§ã™ã€‚秘密éµã‚’ã©ã“ã«ã‚‚アップロードã—ãªã„ã§ãã ã•ã„。代ã‚ã‚Šã«å…¬é–‹éµã‚’使用ã—ã¦ãã ã•ã„。
unable_verify_ssh_key=SSHキーãŒç¢ºèªã§ãã¾ã›ã‚“。間é•ã„ãŒç„¡ã„ã‹ã€ã‚ˆã確èªã—ã¦ãã ã•ã„。
auth_failed=èªè¨¼ã«å¤±æ•—ã—ã¾ã—ãŸ: %v
@@ -737,6 +756,8 @@ access_token_deletion_cancel_action=キャンセル
access_token_deletion_confirm_action=削除
access_token_deletion_desc=トークンを削除ã™ã‚‹ã¨ã€ãれを使用ã—ã¦ã„るアプリケーションã¯ã€ã‚¢ã‚«ã‚¦ãƒ³ãƒˆã¸ã®ã‚¢ã‚¯ã‚»ã‚¹ãŒã§ããªããªã‚Šã¾ã™ã€‚ã“ã‚Œã¯å…ƒã«æˆ»ã›ã¾ã›ã‚“。続行ã—ã¾ã™ã‹ï¼Ÿ
delete_token_success=トークンを削除ã—ã¾ã—ãŸã€‚ 削除ã—ãŸãƒˆãƒ¼ã‚¯ãƒ³ã‚’使用ã—ã¦ã„るアプリケーションã¯ã€ä»Šå¾Œã‚ãªãŸã®ã‚¢ã‚«ã‚¦ãƒ³ãƒˆã«ã‚¢ã‚¯ã‚»ã‚¹ã§ãã¾ã›ã‚“。
+select_scopes=スコープをé¸æŠž
+scopes_list=スコープ:
manage_oauth2_applications=OAuth2アプリケーションã®ç®¡ç†
edit_oauth2_application=OAuth2アプリケーションã®ç·¨é›†
@@ -800,6 +821,7 @@ remove_account_link=連æºã‚¢ã‚«ã‚¦ãƒ³ãƒˆã®å‰Šé™¤
remove_account_link_desc=連æºã‚¢ã‚«ã‚¦ãƒ³ãƒˆã‚’削除ã—ã€Giteaアカウントã¸ã®ã‚¢ã‚¯ã‚»ã‚¹æ¨©ã‚’å–り消ã—ã¾ã™ã€‚ 続行ã—ã¾ã™ã‹ï¼Ÿ
remove_account_link_success=連æºã‚¢ã‚«ã‚¦ãƒ³ãƒˆã‚’削除ã—ã¾ã—ãŸã€‚
+
orgs_none=ã‚ãªãŸã¯ã©ã®çµ„ç¹”ã®ãƒ¡ãƒ³ãƒãƒ¼ã§ã‚‚ã‚ã‚Šã¾ã›ã‚“。
repos_none=ã‚ãªãŸã¯ãƒªãƒã‚¸ãƒˆãƒªã‚’所有ã—ã¦ã„ã¾ã›ã‚“。
@@ -911,9 +933,9 @@ delete_preexisting_success=%s ã®æœªç™»éŒ²ãƒ•ã‚¡ã‚¤ãƒ«ã‚’削除ã—ã¾ã—ãŸ
blame_prior=ã“ã®å¤‰æ›´ã‚ˆã‚Šå‰ã®Blameを表示
transfer.accept=転é€ã‚’承èª
-transfer.accept_desc="%s" ã«è»¢é€
+transfer.accept_desc=`"%s" ã«è»¢é€`
transfer.reject=転é€ã‚’æ‹’å¦
-transfer.reject_desc="%s" ã¸ã®è»¢é€ã‚’キャンセル
+transfer.reject_desc=`"%s" ã¸ã®è»¢é€ã‚’キャンセル`
transfer.no_permission_to_accept=承èªã‚’è¡Œã†æ¨©é™ãŒã‚ã‚Šã¾ã›ã‚“
transfer.no_permission_to_reject=æ‹’å¦ã‚’è¡Œã†æ¨©é™ãŒã‚ã‚Šã¾ã›ã‚“
@@ -1009,10 +1031,12 @@ unstar=スターå–消
star=スター
fork=フォーク
download_archive=リãƒã‚¸ãƒˆãƒªã‚’ダウンロード
+more_operations=ãã®ä»–ã®æ“作
no_desc=説明ãªã—
quick_guide=クイック ガイド
clone_this_repo=ã“ã®ãƒªãƒã‚¸ãƒˆãƒªã®ã‚¯ãƒ­ãƒ¼ãƒ³ã‚’作æˆ
+cite_this_repo=ã“ã®ãƒªãƒã‚¸ãƒˆãƒªã‚’引用
create_new_repo_command=コマンドラインã‹ã‚‰æ–°ã—ã„リãƒã‚¸ãƒˆãƒªã‚’作æˆ
push_exist_repo=コマンドラインã‹ã‚‰æ—¢å­˜ã®ãƒªãƒã‚¸ãƒˆãƒªã‚’プッシュ
empty_message=ã“ã®ãƒªãƒã‚¸ãƒˆãƒªã®ä¸­ã«ã¯ä½•ã‚‚ã‚ã‚Šã¾ã›ã‚“。
@@ -1111,6 +1135,7 @@ editor.commit_directly_to_this_branch=ブランãƒ<strong class="branch-name">%s
editor.create_new_branch=<strong>æ–°ã—ã„ブランãƒ</strong>ã«ã‚³ãƒŸãƒƒãƒˆã—ã¦ãƒ—ルリクエストを作æˆã™ã‚‹ã€‚
editor.create_new_branch_np=<strong>æ–°ã—ã„ブランãƒ</strong>ã«ã‚³ãƒŸãƒƒãƒˆã™ã‚‹ã€‚
editor.propose_file_change=ファイル修正をæ案
+editor.new_branch_name=ã“ã®ã‚³ãƒŸãƒƒãƒˆã®æ–°ã—ã„ブランãƒã«åå‰ã‚’付ã‘ã¾ã™
editor.new_branch_name_desc=æ–°ã—ã„ブランãƒå…
editor.cancel=キャンセル
editor.filename_cannot_be_empty=ファイルåã¯ç©ºã«ã§ãã¾ã›ã‚“。
@@ -1148,7 +1173,7 @@ commits.commits=コミット
commits.no_commits=共通ã®ã‚³ãƒŸãƒƒãƒˆã¯ã‚ã‚Šã¾ã›ã‚“。 '%s' 㨠'%s' ã®å±¥æ­´ã¯ã™ã¹ã¦ç•°ãªã£ã¦ã„ã¾ã™ã€‚
commits.nothing_to_compare=二ã¤ã®ãƒ–ランãƒã¯åŒã˜å†…容ã§ã™ã€‚
commits.search=コミットã®æ¤œç´¢â€¦
-commits.search.tooltip=キーワード "author:"ã€"committer:"ã€"after:"ã€"before:" を付ã‘ã¦æŒ‡å®šã§ãã¾ã™ã€‚ 例 "revert author:Alice before:2019-04-01"
+commits.search.tooltip=`キーワード "author:"ã€"committer:"ã€"after:"ã€"before:" を付ã‘ã¦æŒ‡å®šã§ãã¾ã™ã€‚ 例 "revert author:Alice before:2019-04-01"`
commits.find=検索
commits.search_all=ã™ã¹ã¦ã®ãƒ–ランãƒ
commits.author=作æˆè€…
@@ -1162,7 +1187,7 @@ commits.signed_by_untrusted_user_unmatched=コミッターã¨ä¸€è‡´ã—ãªã„ä¿¡é
commits.gpg_key_id=GPGキーID
commits.ssh_key_fingerprint=SSHéµã®ãƒ•ã‚£ãƒ³ã‚¬ãƒ¼ãƒ—リント
-commit.actions=アクション
+commit.operations=æ“作
commit.revert=リãƒãƒ¼ãƒˆ
commit.revert-header=リãƒãƒ¼ãƒˆ: %s
commit.revert-content=リãƒãƒ¼ãƒˆã™ã‚‹ãƒ–ランãƒã‚’é¸æŠž:
@@ -1187,27 +1212,30 @@ projects.deletion_desc=プロジェクトを削除ã—ã€é–¢é€£ã™ã‚‹ã™ã¹ã¦ã®
projects.deletion_success=プロジェクトを削除ã—ã¾ã—ãŸã€‚
projects.edit=プロジェクトã®ç·¨é›†
projects.edit_subheader=プロジェクトã¯ã‚¤ã‚·ãƒ¥ãƒ¼ã‚’ã¾ã¨ã‚ã€é€²æ—を管ç†ã—ã¾ã™ã€‚
-projects.modify=プロジェクトを更新
+projects.modify=プロジェクトを編集
projects.edit_success=プロジェクト '%s' ã‚’æ›´æ–°ã—ã¾ã—ãŸã€‚
projects.type.none=ãªã—
projects.type.basic_kanban=基本的ãªã‚«ãƒ³ãƒãƒ³
projects.type.bug_triage=ãƒã‚° トリアージ
-projects.template.desc=プロジェクト テンプレート
+projects.template.desc=テンプレート
projects.template.desc_helper=開始ã™ã‚‹ãƒ—ロジェクトテンプレートをé¸æŠž
projects.type.uncategorized=未分類
-projects.board.edit=ボードを編集
-projects.board.edit_title=æ–°ã—ã„ボードã®åå‰
-projects.board.new_title=æ–°ã—ã„ボードã®åå‰
-projects.board.new_submit=é€ä¿¡
-projects.board.new=æ–°ã—ã„ボード
-projects.board.set_default=デフォルトã«è¨­å®š
-projects.board.set_default_desc=ã“ã®ãƒœãƒ¼ãƒ‰ã‚’未分類ã®ã‚¤ã‚·ãƒ¥ãƒ¼ã‚„プルリクエストãŒå…¥ã‚‹ãƒ‡ãƒ•ã‚©ãƒ«ãƒˆã®ãƒœãƒ¼ãƒ‰ã«è¨­å®šã—ã¾ã™
-projects.board.delete=ボードを削除
-projects.board.deletion_desc=プロジェクトボードを削除ã™ã‚‹ã¨ã€é–¢é€£ã™ã‚‹ã™ã¹ã¦ã®ã‚¤ã‚·ãƒ¥ãƒ¼ãŒ '未分類' ã«ç§»å‹•ã—ã¾ã™ã€‚ 続行ã—ã¾ã™ã‹ï¼Ÿ
-projects.board.color=色
+projects.column.edit=列を編集
+projects.column.edit_title=å称
+projects.column.new_title=å称
+projects.column.new_submit=列を作æˆ
+projects.column.new=æ–°ã—ã„列
+projects.column.set_default=デフォルトã«è¨­å®š
+projects.column.set_default_desc=ã“ã®åˆ—を未分類ã®ã‚¤ã‚·ãƒ¥ãƒ¼ã‚„プルリクエストãŒå…¥ã‚‹ãƒ‡ãƒ•ã‚©ãƒ«ãƒˆã®åˆ—ã«ã—ã¾ã™
+projects.column.delete=列を削除
+projects.column.deletion_desc=プロジェクト列を削除ã™ã‚‹ã¨ã€é–¢é€£ã™ã‚‹ã™ã¹ã¦ã®ã‚¤ã‚·ãƒ¥ãƒ¼ãŒ '未分類' ã«ç§»å‹•ã—ã¾ã™ã€‚ 続行ã—ã¾ã™ã‹ï¼Ÿ
+projects.column.color=カラー
projects.open=オープン
projects.close=クローズ
-projects.board.assigned_to=担当
+projects.column.assigned_to=担当
+projects.card_type.desc=カードプレビュー
+projects.card_type.images_and_text=ç”»åƒã¨ãƒ†ã‚­ã‚¹ãƒˆ
+projects.card_type.text_only=テキストã®ã¿
issues.desc=ãƒã‚°å ±å‘Šã€ã‚¿ã‚¹ã‚¯ã€ãƒžã‚¤ãƒ«ã‚¹ãƒˆãƒ¼ãƒ³ã®ä½œæˆã€‚
issues.filter_assignees=候補者ã®çµžã‚Šè¾¼ã¿
@@ -1283,6 +1311,9 @@ issues.filter_label_exclude=`ラベルã§é™¤å¤–ã™ã‚‹ã«ã¯ <code>alt</code> + <
issues.filter_label_no_select=ã™ã¹ã¦ã®ãƒ©ãƒ™ãƒ«
issues.filter_milestone=マイルストーン
issues.filter_milestone_no_select=ã™ã¹ã¦ã®ãƒžã‚¤ãƒ«ã‚¹ãƒˆãƒ¼ãƒ³
+issues.filter_project=プロジェクト
+issues.filter_project_all=ã™ã¹ã¦ã®ãƒ—ロジェクト
+issues.filter_project_none=プロジェクトãªã—
issues.filter_assignee=担当者
issues.filter_assginee_no_select=ã™ã¹ã¦ã®æ‹…当者
issues.filter_poster=作æˆè€…
@@ -1293,6 +1324,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_sort=並ã¹æ›¿ãˆ
issues.filter_sort.latest=æ–°ã—ã„é †
issues.filter_sort.oldest=å¤ã„é †
@@ -1314,6 +1346,8 @@ issues.action_milestone=マイルストーン
issues.action_milestone_no_select=マイルストーンãªã—
issues.action_assignee=担当者
issues.action_assignee_no_select=担当者ãªã—
+issues.action_check=ãƒã‚§ãƒƒã‚¯ã‚’設定/解除ã—ã¾ã™
+issues.action_check_all=ã™ã¹ã¦ã®é …ç›®ã®ãƒã‚§ãƒƒã‚¯ã‚’設定/解除ã—ã¾ã™
issues.opened_by=<a href="%[2]s">%[3]s</a>ãŒ%[1]sã«ä½œæˆ
pulls.merged_by=<a href="%[2]s">%[3]s</a>ãŒä½œæˆã€%[1]sã«ãƒžãƒ¼ã‚¸
pulls.merged_by_fake=%[2]sãŒä½œæˆã€%[1]sã«ãƒžãƒ¼ã‚¸
@@ -1364,9 +1398,12 @@ issues.sign_in_require_desc=<a href="%s">サインイン</a>ã—ã¦ã“ã®ä¼šè©±ã
issues.edit=編集
issues.cancel=キャンセル
issues.save=ä¿å­˜
-issues.label_title=ラベルå
-issues.label_description=ラベルã®èª¬æ˜Ž
-issues.label_color=ラベルã®è‰²
+issues.label_title=åå‰
+issues.label_description=説明
+issues.label_color=カラー
+issues.label_exclusive=排他
+issues.label_exclusive_desc=ラベルåã‚’ <code>スコープ/アイテム</code> ã®å½¢ã«ã™ã‚‹ã“ã¨ã§ã€ä»–ã® <code>スコープ/</code> ラベルã¨æŽ’ä»–çš„ã«ãªã‚Šã¾ã™ã€‚
+issues.label_exclusive_warning=イシューやプルリクエストã®ãƒ©ãƒ™ãƒ«ç·¨é›†ã§ã¯ã€ç«¶åˆã™ã‚‹ã‚¹ã‚³ãƒ¼ãƒ—付ãラベルã¯è§£é™¤ã•ã‚Œã¾ã™ã€‚
issues.label_count=ラベル %d件
issues.label_open_issues=オープン中ã®ã‚¤ã‚·ãƒ¥ãƒ¼ %d件
issues.label_edit=編集
@@ -1434,6 +1471,7 @@ issues.error_removing_due_date=期日を削除ã§ãã¾ã›ã‚“ã§ã—ãŸã€‚
issues.push_commit_1=㌠%d コミット追加 %s
issues.push_commits_n=㌠%d コミット追加 %s
issues.force_push_codes=`㌠%[1]s を強制プッシュ ( <a class="ui sha" href="%[3]s"><code>%[2]s</code></a> ã‹ã‚‰ <a class="ui sha" href="%[5]s"><code>%[4]s</code></a> 㸠) %[6]s`
+issues.force_push_compare=比較
issues.due_date_form=yyyy-mm-dd
issues.due_date_form_add=期日ã®è¿½åŠ 
issues.due_date_form_edit=変更
@@ -1620,6 +1658,8 @@ pulls.reopened_at=`ãŒãƒ—ルリクエストをå†ã‚ªãƒ¼ãƒ—ン <a id="%[1]s" href
pulls.merge_instruction_hint=`<a class="show-instruction">コマンドラインã®æ‰‹é †</a>も確èªã§ãã¾ã™ã€‚`
pulls.merge_instruction_step1_desc=ã‚ãªãŸã®ãƒ—ロジェクトリãƒã‚¸ãƒˆãƒªã§æ–°ã—ã„ブランãƒã‚’ãƒã‚§ãƒƒã‚¯ã‚¢ã‚¦ãƒˆã—ã€å¤‰æ›´å†…容をテストã—ã¾ã™ã€‚
pulls.merge_instruction_step2_desc=変更内容をマージã—ã¦ã€Giteaã«å映ã—ã¾ã™ã€‚
+pulls.clear_merge_message=マージメッセージをクリア
+pulls.clear_merge_message_hint=マージメッセージã®ã‚¯ãƒªã‚¢ã¯ã€ã‚³ãƒŸãƒƒãƒˆãƒ¡ãƒƒã‚»ãƒ¼ã‚¸ã®é™¤åŽ»ã ã‘ã‚’è¡Œã„ã¾ã™ã€‚ 生æˆã•ã‚ŒãŸGitトレーラー("Co-Authored-By …" ç­‰)ã¯ãã®ã¾ã¾æ®‹ã‚Šã¾ã™ã€‚
pulls.auto_merge_button_when_succeed=(ãƒã‚§ãƒƒã‚¯ãŒã™ã¹ã¦æˆåŠŸã—ãŸå ´åˆ)
pulls.auto_merge_when_succeed=ã™ã¹ã¦ã®ãƒã‚§ãƒƒã‚¯ãŒæˆåŠŸã—ãŸã‚‰è‡ªå‹•ãƒžãƒ¼ã‚¸
@@ -1811,6 +1851,7 @@ settings.mirror_sync_in_progress=ミラーåŒæœŸã‚’実行ã—ã¦ã„ã¾ã™ã€‚ ã—ã
settings.site=Webサイト
settings.update_settings=設定を更新
settings.branches.update_default_branch=デフォルトブランãƒã‚’æ›´æ–°
+settings.branches.add_new_rule=æ–°ã—ã„ルールを追加
settings.advanced_settings=拡張設定
settings.wiki_desc=Wikiを有効ã«ã™ã‚‹
settings.use_internal_wiki=ビルトインã®Wikiを使用ã™ã‚‹
@@ -1837,16 +1878,14 @@ settings.enable_timetracker=タイムトラッキングを有効ã«ã™ã‚‹
settings.allow_only_contributors_to_track_time=コントリビューターã ã‘タイムトラッキングã™ã‚‹
settings.pulls_desc=プルリクエストを有効ã«ã™ã‚‹
settings.pulls.ignore_whitespace=空白文字ã®ã‚³ãƒ³ãƒ•ãƒªã‚¯ãƒˆã‚’無視ã™ã‚‹
-settings.pulls.allow_merge_commits=マージコミットを有効ã«ã™ã‚‹
-settings.pulls.allow_rebase_merge=リベースã«ã‚ˆã‚‹ã‚³ãƒŸãƒƒãƒˆã®ãƒžãƒ¼ã‚¸ã‚’有効ã«ã™ã‚‹
-settings.pulls.allow_rebase_merge_commit=マージコミット(--no-ff)ã‚’ä¼´ã†ãƒªãƒ™ãƒ¼ã‚¹ã‚’有効ã«ã™ã‚‹
-settings.pulls.allow_squash_commits=スカッシュã«ã‚ˆã‚‹ã‚³ãƒŸãƒƒãƒˆã®ãƒžãƒ¼ã‚¸ã‚’有効ã«ã™ã‚‹
-settings.pulls.allow_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=デフォルトã§ãƒ¡ãƒ³ãƒ†ãƒŠã‹ã‚‰ã®ç·¨é›†ã‚’許å¯ã™ã‚‹
+settings.releases_desc=リリースを有効ã«ã™ã‚‹
settings.packages_desc=リãƒã‚¸ãƒˆãƒªãƒ‘ッケージレジストリを有効ã«ã™ã‚‹
settings.projects_desc=リãƒã‚¸ãƒˆãƒªãƒ—ロジェクトを有効ã«ã™ã‚‹
+settings.actions_desc=Actionsを有効ã«ã™ã‚‹
settings.admin_settings=管ç†è€…用設定
settings.admin_enable_health_check=リãƒã‚¸ãƒˆãƒªã®ãƒ˜ãƒ«ã‚¹ãƒã‚§ãƒƒã‚¯ã‚’有効ã«ã™ã‚‹ (git fsck)
settings.admin_code_indexer=コードインデクサ
@@ -2010,6 +2049,8 @@ settings.event_package=パッケージ
settings.event_package_desc=リãƒã‚¸ãƒˆãƒªã«ãƒ‘ッケージãŒä½œæˆã¾ãŸã¯å‰Šé™¤ã•ã‚ŒãŸã¨ã。
settings.branch_filter=ブランムフィルター
settings.branch_filter_desc=プッシュã€ãƒ–ランãƒä½œæˆã€ãƒ–ランãƒå‰Šé™¤ã®ã‚¤ãƒ™ãƒ³ãƒˆã‚’通知ã™ã‚‹ãƒ–ランãƒã‚’ã€globパターンã§æŒ‡å®šã™ã‚‹ãƒ›ãƒ¯ã‚¤ãƒˆãƒªã‚¹ãƒˆã§ã™ã€‚ 空ã‹<code>*</code>ã®ã¨ãã¯ã€ã™ã¹ã¦ã®ãƒ–ランãƒã®ã‚¤ãƒ™ãƒ³ãƒˆã‚’通知ã—ã¾ã™ã€‚ 文法ã«ã¤ã„ã¦ã¯ <a href="https://pkg.go.dev/github.com/gobwas/glob#Compile">github.com/gobwas/glob</a> ã‚’å‚ç…§ã—ã¦ãã ã•ã„。 例: <code>master</code> 〠<code>{master,release*}</code>
+settings.authorization_header=Authorizationヘッダー
+settings.authorization_header_desc=入力ã—ãŸå ´åˆã€ãƒªã‚¯ã‚¨ã‚¹ãƒˆã«Authorizationヘッダーã¨ã—ã¦ä»˜åŠ ã—ã¾ã™ã€‚ 例: %s
settings.active=有効
settings.active_helper=トリガーã¨ãªã£ãŸã‚¤ãƒ™ãƒ³ãƒˆã«é–¢ã™ã‚‹æƒ…å ±ãŒã€ã“ã®Webhookã®URLã«é€ä¿¡ã•ã‚Œã¾ã™ã€‚
settings.add_hook_success=Webhookを追加ã—ã¾ã—ãŸã€‚
@@ -2054,6 +2095,8 @@ settings.deploy_key_deletion_desc=デプロイキーを削除ã—ã€ãƒªãƒã‚¸ãƒˆã
settings.deploy_key_deletion_success=デプロイキーを削除ã—ã¾ã—ãŸã€‚
settings.branches=ブランãƒ
settings.protected_branch=ブランãƒã®ä¿è­·
+settings.protected_branch.save_rule=ルールをä¿å­˜
+settings.protected_branch.delete_rule=ルールを削除
settings.protected_branch_can_push=プッシュを許å¯ã™ã‚‹
settings.protected_branch_can_push_yes=プッシュã§ãã¾ã™
settings.protected_branch_can_push_no=プッシュã§ãã¾ã›ã‚“
@@ -2088,15 +2131,17 @@ settings.dismiss_stale_approvals=å¤ããªã£ãŸæ‰¿èªã‚’å–り消ã™
settings.dismiss_stale_approvals_desc=プルリクエストã®å†…容を変ãˆã‚‹æ–°ãŸãªã‚³ãƒŸãƒƒãƒˆãŒãƒ–ランãƒã«ãƒ—ッシュã•ã‚ŒãŸå ´åˆã€ä»¥å‰ã®æ‰¿èªã‚’å–り消ã—ã¾ã™ã€‚
settings.require_signed_commits=コミット署åå¿…é ˆ
settings.require_signed_commits_desc=ç½²åã•ã‚Œã¦ã„ãªã„å ´åˆã€ã¾ãŸã¯ç½²åãŒæ¤œè¨¼ã§ããªã‹ã£ãŸå ´åˆã¯ã€ã“ã®ãƒ–ランãƒã¸ã®ãƒ—ッシュを拒å¦ã—ã¾ã™ã€‚
+settings.protect_branch_name_pattern=ä¿è­·ãƒ–ランãƒåã®ãƒ‘ターン
settings.protect_protected_file_patterns=ä¿è­·ã•ã‚Œã‚‹ãƒ•ã‚¡ã‚¤ãƒ«ã®ãƒ‘ターン (セミコロン'\;'ã§åŒºåˆ‡ã‚‹):
settings.protect_protected_file_patterns_desc=ä¿è­·ã•ã‚ŒãŸãƒ•ã‚¡ã‚¤ãƒ«ã¯ã€ã“ã®ãƒ–ランãƒã«ãƒ•ã‚¡ã‚¤ãƒ«ã‚’追加・編集・削除ã™ã‚‹æ¨©é™ã‚’æŒã¤ãƒ¦ãƒ¼ã‚¶ãƒ¼ã§ã‚ã£ã¦ã‚‚ã€ç›´æŽ¥å¤‰æ›´ã™ã‚‹ã“ã¨ãŒã§ããªããªã‚Šã¾ã™ã€‚ セミコロン('\;')ã§åŒºåˆ‡ã£ã¦è¤‡æ•°ã®ãƒ‘ターンを指定ã§ãã¾ã™ã€‚ パターンã®æ–‡æ³•ã«ã¤ã„ã¦ã¯ <a href="https://pkg.go.dev/github.com/gobwas/glob#Compile">github.com/gobwas/glob</a> ã‚’å‚ç…§ã—ã¦ãã ã•ã„。 例: <code>.drone.yml</code>, <code>/docs/**/*.txt</code>
settings.protect_unprotected_file_patterns=ä¿è­·ã—ãªã„ファイルã®ãƒ‘ターン (セミコロン'\;'ã§åŒºåˆ‡ã‚‹):
settings.protect_unprotected_file_patterns_desc=ä¿è­·ã—ãªã„ファイルã¯ã€ãƒ¦ãƒ¼ã‚¶ãƒ¼ã«æ›¸ãè¾¼ã¿æ¨©é™ãŒã‚ã‚Œã°ãƒ—ッシュ制é™ã‚’ãƒã‚¤ãƒ‘スã—ã¦ç›´æŽ¥å¤‰æ›´ã§ãã¾ã™ã€‚ セミコロン('\;')ã§åŒºåˆ‡ã£ã¦è¤‡æ•°ã®ãƒ‘ターンを指定ã§ãã¾ã™ã€‚ パターンã®æ–‡æ³•ã«ã¤ã„ã¦ã¯ <a href="https://pkg.go.dev/github.com/gobwas/glob#Compile">github.com/gobwas/glob</a> ã‚’å‚ç…§ã—ã¦ãã ã•ã„。 例: <code>.drone.yml</code>, <code>/docs/**/*.txt</code>
settings.add_protected_branch=ä¿è­·ã‚’有効ã«ã™ã‚‹
settings.delete_protected_branch=ä¿è­·ã‚’無効ã«ã™ã‚‹
-settings.update_protect_branch_success=ブランム'%s' ã®ä¿è­·ã‚’æ›´æ–°ã—ã¾ã—ãŸã€‚
-settings.remove_protected_branch_success=ブランム'%s' ã®ä¿è­·ã‚’無効ã«ã—ã¾ã—ãŸã€‚
-settings.protected_branch_deletion=ブランãƒä¿è­·ã®ç„¡åŠ¹åŒ–
+settings.update_protect_branch_success=ルール '%s' ã«å¯¾ã™ã‚‹ãƒ–ランãƒä¿è­·ã‚’æ›´æ–°ã—ã¾ã—ãŸã€‚
+settings.remove_protected_branch_success=ルール '%s' ã«å¯¾ã™ã‚‹ãƒ–ランãƒä¿è­·ã‚’削除ã—ã¾ã—ãŸã€‚
+settings.remove_protected_branch_failed=ブランãƒä¿è­·ãƒ«ãƒ¼ãƒ« '%s' を削除ã§ãã¾ã›ã‚“ã§ã—ãŸã€‚
+settings.protected_branch_deletion=ブランãƒä¿è­·ã®å‰Šé™¤
settings.protected_branch_deletion_desc=ブランãƒä¿è­·ã‚’無効ã«ã™ã‚‹ã¨ã€æ›¸ãè¾¼ã¿æ¨©é™ã‚’æŒã¤ãƒ¦ãƒ¼ã‚¶ãƒ¼ã«ãƒ–ランãƒã¸ã®ãƒ—ッシュを許å¯ã™ã‚‹ã“ã¨ã«ãªã‚Šã¾ã™ã€‚ 続行ã—ã¾ã™ã‹ï¼Ÿ
settings.block_rejected_reviews=ä¸æ‰¿èªãƒ¬ãƒ“ューã§ãƒžãƒ¼ã‚¸ã‚’ブロック
settings.block_rejected_reviews_desc=å…¬å¼ãƒ¬ãƒ“ューアãŒå¤‰æ›´ã‚’è¦è«‹ã—ã¦ã„ã‚‹ã¨ãã¯ã€æ‰¿èªæ•°ã‚’満ãŸã—ã¦ã„ã¦ã‚‚マージã§ããªã„よã†ã«ã—ã¾ã™ã€‚
@@ -2105,10 +2150,13 @@ settings.block_on_official_review_requests_desc=å…¬å¼ãƒ¬ãƒ“ューä¾é ¼ãŒã‚ã‚
settings.block_outdated_branch=é…ã‚Œã¦ã„るプルリクエストã®ãƒžãƒ¼ã‚¸ã‚’ブロック
settings.block_outdated_branch_desc=baseブランãƒãŒheadブランãƒã‚ˆã‚Šé€²ã‚“ã§ã„ã‚‹å ´åˆã€ãƒžãƒ¼ã‚¸ã§ããªã„よã†ã«ã—ã¾ã™ã€‚
settings.default_branch_desc=プルリクエストやコミット表示ã®ãƒ‡ãƒ•ã‚©ãƒ«ãƒˆã®ãƒ–ランãƒã‚’é¸æŠž:
-settings.default_merge_style_desc=プルリクエストã®ãƒ‡ãƒ•ã‚©ãƒ«ãƒˆã®ãƒžãƒ¼ã‚¸æ–¹æ³•:
+settings.merge_style_desc=マージ スタイル
+settings.default_merge_style_desc=デフォルトã®ãƒžãƒ¼ã‚¸ã‚¹ã‚¿ã‚¤ãƒ«
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=ã‚¿ã‚°ã®ä¿è­·
@@ -2124,7 +2172,6 @@ settings.bot_token=Botトークン
settings.chat_id=ãƒãƒ£ãƒƒãƒˆID
settings.matrix.homeserver_url=ホームサーãƒãƒ¼ URL
settings.matrix.room_id=ルーム ID
-settings.matrix.access_token=アクセストークン
settings.matrix.message_type=メッセージ種別
settings.archive.button=アーカイブ
settings.archive.header=ã“ã®ãƒªãƒã‚¸ãƒˆãƒªã‚’アーカイブ
@@ -2265,6 +2312,8 @@ release.downloads=ダウンロード
release.download_count=ダウンロード数: %s
release.add_tag_msg=リリースã®ã‚¿ã‚¤ãƒˆãƒ«ã¨å†…容をタグã®ãƒ¡ãƒƒã‚»ãƒ¼ã‚¸ã«ã™ã‚‹
release.add_tag=ã‚¿ã‚°ã®ã¿ä½œæˆ
+release.releases_for=%s ã®ãƒªãƒªãƒ¼ã‚¹
+release.tags_for=%s ã®ã‚¿ã‚°
branch.name=ブランãƒå
branch.search=ブランãƒã‚’検索
@@ -2323,7 +2372,7 @@ org_full_name_holder=組織ã®ãƒ•ãƒ«ãƒãƒ¼ãƒ 
org_name_helper=組織åã¯çŸ­ã覚ãˆã‚„ã™ã„ã‚‚ã®ã«ã—ã¾ã—ょã†ã€‚
create_org=組織を作æˆ
repo_updated=最終更新
-people=メンãƒãƒ¼
+members=メンãƒãƒ¼
teams=ãƒãƒ¼ãƒ 
code=コード
lower_members=メンãƒãƒ¼
@@ -2532,6 +2581,10 @@ 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=放置ã•ã‚ŒãŸã¾ã¾ã®ã‚¸ãƒ§ãƒ–をキャンセル
users.user_manage_panel=ユーザーアカウント管ç†
users.new_account=ユーザーアカウントを作æˆ
@@ -2620,6 +2673,7 @@ repos.size=サイズ
packages.package_manage_panel=パッケージ管ç†
packages.total_size=åˆè¨ˆã‚µã‚¤ã‚º: %s
+packages.unreferenced_size=éžå‚照サイズ: %s
packages.owner=オーナー
packages.creator=作æˆè€…
packages.name=åå‰
@@ -2713,6 +2767,8 @@ auths.oauth2_required_claim_value_helper=ã“ã®å€¤ã‚’設定ã™ã‚‹ã¨ã€ã“ã®ã‚½
auths.oauth2_group_claim_name=ã“ã®ã‚½ãƒ¼ã‚¹ã§ã‚°ãƒ«ãƒ¼ãƒ—åã‚’æä¾›ã™ã‚‹Claimå (オプション)
auths.oauth2_admin_group=管ç†è€…ユーザーã®ã‚°ãƒ«ãƒ¼ãƒ—Claim値 (オプション - 上ã®ClaimåãŒå¿…è¦)
auths.oauth2_restricted_group=制é™ä»˜ãユーザーã®ã‚°ãƒ«ãƒ¼ãƒ—Claim値 (オプション - 上ã®ClaimåãŒå¿…è¦)
+auths.oauth2_map_group_to_team=見ã¤ã‹ã£ãŸã‚°ãƒ«ãƒ¼ãƒ—を組織ã®ãƒãƒ¼ãƒ ã«ãƒžãƒƒãƒ— (オプション - 上ã®ClaimåãŒå¿…è¦)
+auths.oauth2_map_group_to_team_removal=対応ã™ã‚‹ã‚°ãƒ«ãƒ¼ãƒ—ã«ãƒ¦ãƒ¼ã‚¶ãƒ¼ãŒå«ã¾ã‚Œãªã„å ´åˆã€åŒæœŸã—ã¦ã„ã‚‹ãƒãƒ¼ãƒ ã‹ã‚‰ãƒ¦ãƒ¼ã‚¶ãƒ¼ã‚’削除ã™ã‚‹
auths.enable_auto_register=自動登録を有効ã«ã™ã‚‹
auths.sspi_auto_create_users=自動的ã«ãƒ¦ãƒ¼ã‚¶ãƒ¼ã‚’作æˆ
auths.sspi_auto_create_users_helper=åˆå›žãƒ­ã‚°ã‚¤ãƒ³ã®ãƒ¦ãƒ¼ã‚¶ãƒ¼ã«å¯¾ã—ã¦ã€SSPIèªè¨¼å‡¦ç†ãŒæ–°ã—ã„アカウントを自動的ã«ä½œæˆã™ã‚‹ã“ã¨ã‚’許å¯ã—ã¾ã™
@@ -2739,7 +2795,7 @@ auths.tip.openid_connect=OpenID Connect Discoveryã®URL (<server>/.well-known/op
auths.tip.twitter=https://dev.twitter.com/apps ã¸ã‚¢ã‚¯ã‚»ã‚¹ã—ã¦ã‚¢ãƒ—リケーションを作æˆã—ã€â€œAllow this application to be used to Sign in with Twitterâ€ã‚ªãƒ—ションを有効ã«ã—ã¦ãã ã•ã„。
auths.tip.discord=æ–°ã—ã„アプリケーションを https://discordapp.com/developers/applications/me ã‹ã‚‰ç™»éŒ²ã—ã¦ãã ã•ã„。
auths.tip.gitea=æ–°ã—ã„OAuthアプリケーションを登録ã—ã¦ãã ã•ã„。 利用ガイド㯠https://docs.gitea.io/en-us/oauth2-provider/
-auths.tip.yandex=https://oauth.yandex.com/client/new ã§æ–°ã—ã„アプリケーションを作æˆã—ã¦ãã ã•ã„。 "Yandex.Passport API" セクションã§æ¬¡ã®é …目を許å¯ã—ã¾ã™: "Access to email address"ã€"Access to user avatar"ã€"Access to username, first name and surname, gender"
+auths.tip.yandex=`https://oauth.yandex.com/client/new ã§æ–°ã—ã„アプリケーションを作æˆã—ã¦ãã ã•ã„。 "Yandex.Passport API" セクションã§æ¬¡ã®é …目を許å¯ã—ã¾ã™: "Access to email address"ã€"Access to user avatar"ã€"Access to username, first name and surname, gender"`
auths.tip.mastodon=èªè¨¼ã—ãŸã„Mastodonインスタンスã®ã‚«ã‚¹ã‚¿ãƒ URLを入力ã—ã¦ãã ã•ã„ (入力ã—ãªã„å ´åˆã¯ãƒ‡ãƒ•ã‚©ãƒ«ãƒˆã®URLを使用ã—ã¾ã™)
auths.edit=èªè¨¼ã‚½ãƒ¼ã‚¹ã®ç·¨é›†
auths.activated=èªè¨¼ã‚½ãƒ¼ã‚¹ã¯ã‚¢ã‚¯ãƒ†ã‚£ãƒ™ãƒ¼ãƒˆæ¸ˆã¿
@@ -2975,7 +3031,7 @@ monitor.queue.pool.cancel_desc=キューをワーカーグループ無ã—ã®ã¾ã
notices.system_notice_list=システム通知
notices.view_detail_header=通知ã®è©³ç´°ã‚’表示
-notices.actions=アクション
+notices.operations=æ“作
notices.select_all=ã™ã¹ã¦é¸æŠž
notices.deselect_all=ã™ã¹ã¦é¸æŠžè§£é™¤
notices.inverse_selection=é¸æŠžã‚’å転
@@ -3001,6 +3057,7 @@ reopen_pull_request=`ãŒãƒ—ルリクエスト <a href="%[1]s">%[3]s#%[2]s</a> ã‚
comment_issue=`ãŒã‚¤ã‚·ãƒ¥ãƒ¼ <a href="%[1]s">%[3]s#%[2]s</a> ã«ã‚³ãƒ¡ãƒ³ãƒˆã—ã¾ã—ãŸ`
comment_pull=`ãŒãƒ—ルリクエスト <a href="%[1]s">%[3]s#%[2]s</a> ã«ã‚³ãƒ¡ãƒ³ãƒˆã—ã¾ã—ãŸ`
merge_pull_request=`ãŒãƒ—ルリクエスト <a href="%[1]s">%[3]s#%[2]s</a> をマージã—ã¾ã—ãŸ`
+auto_merge_pull_request=`ãŒãƒ—ルリクエスト <a href="%[1]s">%[3]s#%[2]s</a> を自動マージã—ã¾ã—ãŸ`
transfer_repo=ãŒãƒªãƒã‚¸ãƒˆãƒª <code>%s</code> ã‚’ <a href="%s">%s</a> ã¸ç§»è»¢ã—ã¾ã—ãŸ
push_tag=ãŒã‚¿ã‚° <a href="%[2]s">%[3]s</a> ã‚’ <a href="%[1]s">%[4]s</a> ã«ãƒ—ッシュã—ã¾ã—ãŸ
delete_tag=ãŒã‚¿ã‚° %[2]s ã‚’ <a href="%[1]s">%[3]s</a> ã‹ã‚‰å‰Šé™¤ã—ã¾ã—ãŸ
@@ -3099,6 +3156,8 @@ keywords=キーワード
details=詳細
details.author=著作者
details.project_site=プロジェクトサイト
+details.repository_site=リãƒã‚¸ãƒˆãƒªã‚µã‚¤ãƒˆ
+details.documentation_site=ドキュメンテーションサイト
details.license=ライセンス
assets=アセット
versions=ãƒãƒ¼ã‚¸ãƒ§ãƒ³
@@ -3106,6 +3165,14 @@ versions.on=on
versions.view_all=ã™ã¹ã¦è¡¨ç¤º
dependency.id=ID
dependency.version=ãƒãƒ¼ã‚¸ãƒ§ãƒ³
+cargo.registry=Cargo 設定ファイルã§ã“ã®ãƒ¬ã‚¸ã‚¹ãƒˆãƒªã‚’セットアップã—ã¾ã™ã€‚(例 <code>~/.cargo/config.toml</code>):
+cargo.install=Cargo を使用ã—ã¦ãƒ‘ッケージをインストールã™ã‚‹ã«ã¯ã€æ¬¡ã®ã‚³ãƒžãƒ³ãƒ‰ã‚’実行ã—ã¾ã™:
+cargo.documentation=Cargoレジストリã®è©³ç´°ã«ã¤ã„ã¦ã¯ã€ <a target="_blank" rel="noopener noreferrer" href="https://docs.gitea.io/en-us/packages/cargo/">ドキュメント</a> ã‚’å‚ç…§ã—ã¦ãã ã•ã„。
+cargo.details.repository_site=リãƒã‚¸ãƒˆãƒªã‚µã‚¤ãƒˆ
+cargo.details.documentation_site=ドキュメンテーションサイト
+chef.registry=ã‚ãªãŸã® <code>~/.chef/config.rb</code> ファイルã«ã€ã“ã®ãƒ¬ã‚¸ã‚¹ãƒˆãƒªã‚’セットアップã—ã¾ã™:
+chef.install=パッケージをインストールã™ã‚‹ã«ã¯ã€æ¬¡ã®ã‚³ãƒžãƒ³ãƒ‰ã‚’実行ã—ã¾ã™:
+chef.documentation=Chefレジストリã®è©³ç´°ã«ã¤ã„ã¦ã¯ã€<a target="_blank" rel="noopener noreferrer" href="https://docs.gitea.io/en-us/packages/chef/">ドキュメント</a> ã‚’å‚ç…§ã—ã¦ãã ã•ã„。
composer.registry=ã‚ãªãŸã® <code>~/.composer/config.json</code> ファイルã«ã€ã“ã®ãƒ¬ã‚¸ã‚¹ãƒˆãƒªã‚’セットアップã—ã¾ã™:
composer.install=Composer を使用ã—ã¦ãƒ‘ッケージをインストールã™ã‚‹ã«ã¯ã€æ¬¡ã®ã‚³ãƒžãƒ³ãƒ‰ã‚’実行ã—ã¾ã™:
composer.documentation=Composer レジストリã®è©³ç´°ã«ã¤ã„ã¦ã¯ã€ <a target="_blank" rel="noopener noreferrer" href="https://docs.gitea.io/en-us/packages/composer/">ドキュメント</a> ã‚’å‚ç…§ã—ã¦ãã ã•ã„。
@@ -3115,10 +3182,13 @@ conan.details.repository=リãƒã‚¸ãƒˆãƒª
conan.registry=ã“ã®ãƒ¬ã‚¸ã‚¹ãƒˆãƒªã‚’コマンドラインã‹ã‚‰ã‚»ãƒƒãƒˆã‚¢ãƒƒãƒ—ã—ã¾ã™:
conan.install=Conan を使用ã—ã¦ãƒ‘ッケージをインストールã™ã‚‹ã«ã¯ã€æ¬¡ã®ã‚³ãƒžãƒ³ãƒ‰ã‚’実行ã—ã¾ã™:
conan.documentation=Conan レジストリã®è©³ç´°ã«ã¤ã„ã¦ã¯ã€ <a target="_blank" rel="noopener noreferrer" href="https://docs.gitea.io/en-us/packages/conan/">ドキュメント</a> ã‚’å‚ç…§ã—ã¦ãã ã•ã„。
+conda.registry=ã‚ãªãŸã® <code>.condarc</code> ファイルã«ã€ã“ã®ãƒ¬ã‚¸ã‚¹ãƒˆãƒªã‚’ Conda リãƒã‚¸ãƒˆãƒªã¨ã—ã¦ã‚»ãƒƒãƒˆã‚¢ãƒƒãƒ—ã—ã¾ã™:
+conda.install=Conda を使用ã—ã¦ãƒ‘ッケージをインストールã™ã‚‹ã«ã¯ã€æ¬¡ã®ã‚³ãƒžãƒ³ãƒ‰ã‚’実行ã—ã¾ã™:
+conda.documentation=Condaレジストリã®è©³ç´°ã«ã¤ã„ã¦ã¯ã€ <a target="_blank" rel="noopener noreferrer" href="https://docs.gitea.io/en-us/packages/conda/">ドキュメント</a> ã‚’å‚ç…§ã—ã¦ãã ã•ã„。
+conda.details.repository_site=リãƒã‚¸ãƒˆãƒªã‚µã‚¤ãƒˆ
+conda.details.documentation_site=ドキュメンテーションサイト
container.details.type=イメージタイプ
container.details.platform=プラットフォーム
-container.details.repository_site=リãƒã‚¸ãƒˆãƒªã‚µã‚¤ãƒˆ
-container.details.documentation_site=ドキュメントサイト
container.pull=コマンドラインã§ã‚¤ãƒ¡ãƒ¼ã‚¸ã‚’å–å¾—ã—ã¾ã™:
container.digest=ダイジェスト:
container.documentation=Container レジストリã®è©³ç´°ã«ã¤ã„ã¦ã¯ã€ <a target="_blank" rel="noopener noreferrer" href="https://docs.gitea.io/en-us/packages/container/">ドキュメント</a> ã‚’å‚ç…§ã—ã¦ãã ã•ã„。
@@ -3152,8 +3222,6 @@ npm.dependencies.optional=オプションã®ä¾å­˜é–¢ä¿‚
npm.details.tag=ã‚¿ã‚°
pub.install=Dart を使用ã—ã¦ãƒ‘ッケージをインストールã™ã‚‹ã«ã¯ã€æ¬¡ã®ã‚³ãƒžãƒ³ãƒ‰ã‚’実行ã—ã¾ã™:
pub.documentation=Pub レジストリã®è©³ç´°ã«ã¤ã„ã¦ã¯ã€<a target="_blank" rel="noopener noreferrer" href="https://docs.gitea.io/en-us/packages/pub/">ドキュメント</a> ã‚’å‚ç…§ã—ã¦ãã ã•ã„。
-pub.details.repository_site=リãƒã‚¸ãƒˆãƒªã‚µã‚¤ãƒˆ
-pub.details.documentation_site=ドキュメントサイト
pypi.requires=å¿…è¦ãªPython
pypi.install=pip を使用ã—ã¦ãƒ‘ッケージをインストールã™ã‚‹ã«ã¯ã€æ¬¡ã®ã‚³ãƒžãƒ³ãƒ‰ã‚’実行ã—ã¾ã™:
pypi.documentation=PyPI レジストリã®è©³ç´°ã«ã¤ã„ã¦ã¯ã€<a target="_blank" rel="noopener noreferrer" href="https://docs.gitea.io/en-us/packages/pypi/">ドキュメント</a> ã‚’å‚ç…§ã—ã¦ãã ã•ã„。
@@ -3177,4 +3245,110 @@ settings.delete.description=パッケージã®å‰Šé™¤ã¯æ’ä¹…çš„ã§å…ƒã«æˆ»ã™ã
settings.delete.notice=%s (%s) を削除ã—よã†ã¨ã—ã¦ã„ã¾ã™ã€‚ã“ã®æ“作ã¯å…ƒã«æˆ»ã›ã¾ã›ã‚“。よã‚ã—ã„ã§ã™ã‹ï¼Ÿ
settings.delete.success=パッケージを削除ã—ã¾ã—ãŸã€‚
settings.delete.error=パッケージã®å‰Šé™¤ã«å¤±æ•—ã—ã¾ã—ãŸã€‚
+owner.settings.cargo.title=Cargoレジストリ インデックス
+owner.settings.cargo.initialize=インデックスをåˆæœŸåŒ–
+owner.settings.cargo.initialize.description=Cargoレジストリを使用ã™ã‚‹ã«ã¯ã€ã‚¤ãƒ³ãƒ‡ãƒƒã‚¯ã‚¹ç”¨ã®ç‰¹åˆ¥ãªgitリãƒã‚¸ãƒˆãƒªãŒå¿…è¦ã§ã™ã€‚ ã“ã“ã§ãã®ãƒªãƒã‚¸ãƒˆãƒªã‚’å¿…è¦ãªæ§‹æˆã§(å†)作æˆã—ã¾ã™ã€‚
+owner.settings.cargo.initialize.error=Cargoインデックスã®åˆæœŸåŒ–ã«å¤±æ•—ã—ã¾ã—ãŸ: %v
+owner.settings.cargo.initialize.success=Cargoインデックスã¯æ­£å¸¸ã«ä½œæˆã•ã‚Œã¾ã—ãŸã€‚
+owner.settings.cargo.rebuild=インデックスをå†æ§‹ç¯‰
+owner.settings.cargo.rebuild.description=ä¿å­˜ã—ãŸCargoパッケージã¨ã‚¤ãƒ³ãƒ‡ãƒƒã‚¯ã‚¹ãŒåŒæœŸã—ãªã„å ´åˆã€ã“ã“ã§ã‚¤ãƒ³ãƒ‡ãƒƒã‚¯ã‚¹ã‚’å†æ§‹ç¯‰ã§ãã¾ã™ã€‚
+owner.settings.cargo.rebuild.error=Cargoインデックスã®å†æ§‹ç¯‰ã«å¤±æ•—ã—ã¾ã—ãŸ: %v
+owner.settings.cargo.rebuild.success=Cargoインデックスã¯æ­£å¸¸ã«å†æ§‹ç¯‰ã•ã‚Œã¾ã—ãŸã€‚
+owner.settings.cleanuprules.title=クリーンアップルールã®ç®¡ç†
+owner.settings.cleanuprules.add=クリーンアップルールを追加
+owner.settings.cleanuprules.edit=クリーンアップルールを編集
+owner.settings.cleanuprules.none=クリーンアップルールã¯ã‚ã‚Šã¾ã›ã‚“。詳細ã¯ãƒ‰ã‚­ãƒ¥ãƒ¡ãƒ³ãƒˆã‚’ã”覧ãã ã•ã„。
+owner.settings.cleanuprules.preview=クリーンアップルールをプレビュー
+owner.settings.cleanuprules.preview.overview=%d パッケージãŒå‰Šé™¤ã•ã‚Œã‚‹äºˆå®šã§ã™ã€‚
+owner.settings.cleanuprules.preview.none=クリーンアップルールã¨ä¸€è‡´ã™ã‚‹ãƒ‘ッケージãŒã‚ã‚Šã¾ã›ã‚“。
+owner.settings.cleanuprules.enabled=有効
+owner.settings.cleanuprules.pattern_full_match=フルパッケージåã«ãƒ‘ターンをé©ç”¨
+owner.settings.cleanuprules.keep.title=以下ã®ãƒ«ãƒ¼ãƒ«ã«ãƒžãƒƒãƒã™ã‚‹ãƒãƒ¼ã‚¸ãƒ§ãƒ³ã‚’残ã—ã¾ã™ã€‚ (下ã«ã‚る削除ルールã«ãƒžãƒƒãƒã—ã¦ã„ã¦ã‚‚残ã—ã¾ã™)
+owner.settings.cleanuprules.keep.count=最近ã®ã‚‚ã®ã‚’残ã™
+owner.settings.cleanuprules.keep.count.1=1 パッケージã«ã¤ã 1 ãƒãƒ¼ã‚¸ãƒ§ãƒ³
+owner.settings.cleanuprules.keep.count.n=1 パッケージã«ã¤ã %d ãƒãƒ¼ã‚¸ãƒ§ãƒ³
+owner.settings.cleanuprules.keep.pattern=マッãƒã™ã‚‹ãƒãƒ¼ã‚¸ãƒ§ãƒ³ã‚’残ã™
+owner.settings.cleanuprules.keep.pattern.container=Containerパッケージã®å ´åˆã€<code>最新</code>ãƒãƒ¼ã‚¸ãƒ§ãƒ³ã¯å¸¸ã«æ®‹ã—ã¾ã™ã€‚
+owner.settings.cleanuprules.remove.title=以下ã®ãƒ«ãƒ¼ãƒ«ã«ãƒžãƒƒãƒã™ã‚‹ãƒãƒ¼ã‚¸ãƒ§ãƒ³ã‚’削除ã—ã¾ã™ã€‚ (上ã«ã‚るルールãŒæ®‹ã™å¯¾è±¡ã¨ã—ã¦ã„ã‚‹å ´åˆã‚’除ãã¾ã™)
+owner.settings.cleanuprules.remove.days=ã“れよりå¤ã„ãƒãƒ¼ã‚¸ãƒ§ãƒ³ã‚’削除ã™ã‚‹
+owner.settings.cleanuprules.remove.pattern=マッãƒã™ã‚‹ãƒãƒ¼ã‚¸ãƒ§ãƒ³ã‚’削除ã™ã‚‹
+owner.settings.cleanuprules.success.update=クリーンアップルールãŒæ›´æ–°ã•ã‚Œã¾ã—ãŸã€‚
+owner.settings.cleanuprules.success.delete=クリーンアップルールãŒå‰Šé™¤ã•ã‚Œã¾ã—ãŸã€‚
+owner.settings.chef.title=Chefレジストリ
+owner.settings.chef.keypair=キーペアを生æˆ
+owner.settings.chef.keypair.description=Chefレジストリã®èªè¨¼ã«ä½¿ç”¨ã™ã‚‹ã‚­ãƒ¼ãƒšã‚¢ã‚’生æˆã—ã¾ã™ã€‚ ãれ以é™ã¯ã€ä»¥å‰ã®ã‚­ãƒ¼ã¯ä½¿ç”¨ã§ããªããªã‚Šã¾ã™ã€‚
+
+[secrets]
+secrets=シークレット
+description=シークレットã¯ç‰¹å®šã®Actionsã«æ¸¡ã•ã‚Œã¾ã™ã€‚ ãれ以外ã§èª­ã¿å‡ºã•ã‚Œã‚‹ã“ã¨ã¯ã‚ã‚Šã¾ã›ã‚“。
+none=ã¾ã ã‚·ãƒ¼ã‚¯ãƒ¬ãƒƒãƒˆã¯ã‚ã‚Šã¾ã›ã‚“。
+value=値
+name=å称
+creation=シークレットを追加
+creation.name_placeholder=大文字å°æ–‡å­—ã®åŒºåˆ¥ãªã—ã€è‹±æ•°å­—ã¨ã‚¢ãƒ³ãƒ€ãƒ¼ã‚¹ã‚³ã‚¢ã®ã¿ã€GITEA_ ã‚„ GITHUB_ ã§å§‹ã¾ã‚‹ã‚‚ã®ã¯ä¸å¯
+creation.value_placeholder=内容を入力ã—ã¦ãã ã•ã„。å‰å¾Œã®ç©ºç™½ã¯é™¤åŽ»ã•ã‚Œã¾ã™ã€‚
+creation.success=シークレット '%s' を追加ã—ã¾ã—ãŸã€‚
+creation.failed=シークレットã®è¿½åŠ ã«å¤±æ•—ã—ã¾ã—ãŸã€‚
+deletion=シークレットã®å‰Šé™¤
+deletion.description=シークレットã®å‰Šé™¤ã¯æ’ä¹…çš„ã§å…ƒã«æˆ»ã™ã“ã¨ã¯ã§ãã¾ã›ã‚“。 続行ã—ã¾ã™ã‹ï¼Ÿ
+deletion.success=シークレットを削除ã—ã¾ã—ãŸã€‚
+deletion.failed=シークレットã®å‰Šé™¤ã«å¤±æ•—ã—ã¾ã—ãŸã€‚
+
+[actions]
+actions=Actions
+
+unit.desc=Actionsã®ç®¡ç†
+
+status.unknown=ä¸æ˜Ž
+status.waiting=待機中
+status.running=実行中
+status.success=æˆåŠŸ
+status.failure=失敗
+status.cancelled=キャンセルã•ã‚ŒãŸ
+status.skipped=スキップ
+status.blocked=ブロックã•ã‚ŒãŸ
+
+runners=ランナー
+runners.runner_manage_panel=ランナーã®ç®¡ç†
+runners.new=æ–°ã—ã„ランナーを作æˆ
+runners.new_notice=ランナーã®é–‹å§‹æ–¹æ³•
+runners.status=ステータス
+runners.id=ID
+runners.name=å称
+runners.owner_type=タイプ
+runners.description=説明
+runners.labels=ラベル
+runners.last_online=最終オンライン時刻
+runners.agent_labels=エージェントã®ãƒ©ãƒ™ãƒ«
+runners.custom_labels=カスタムラベル
+runners.custom_labels_helper=カスタムラベルã¯ç®¡ç†è€…ã«ã‚ˆã‚Šæ‰‹å‹•ã§è¿½åŠ ã•ã‚ŒãŸãƒ©ãƒ™ãƒ«ã§ã™ã€‚ ラベルã¯ã‚«ãƒ³ãƒžã§åŒºåˆ‡ã‚Šã€å„ラベルã®å‰å¾Œã®ç©ºç™½ã¯ç„¡è¦–ã•ã‚Œã¾ã™ã€‚
+runners.runner_title=ランナー
+runners.task_list=ã“ã®ãƒ©ãƒ³ãƒŠãƒ¼ã®æœ€è¿‘ã®ã‚¿ã‚¹ã‚¯
+runners.task_list.run=実行
+runners.task_list.status=ステータス
+runners.task_list.repository=リãƒã‚¸ãƒˆãƒª
+runners.task_list.commit=コミット
+runners.task_list.done_at=終了時刻
+runners.edit_runner=ランナーã®ç·¨é›†
+runners.update_runner=変更をä¿å­˜
+runners.update_runner_success=ランナーを更新ã—ã¾ã—ãŸ
+runners.update_runner_failed=ランナーã®æ›´æ–°ã«å¤±æ•—ã—ã¾ã—ãŸ
+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=アイドル
+runners.status.active=稼åƒä¸­
+runners.status.offline=オフライン
+
+runs.all_workflows=ã™ã¹ã¦ã®ãƒ¯ãƒ¼ã‚¯ãƒ•ãƒ­ãƒ¼
+runs.open_tab=%d オープン
+runs.closed_tab=%d クローズ
+runs.commit=コミット
+runs.pushed_by=Pushed by
+
+need_approval_desc=フォークプルリクエストã®ãƒ¯ãƒ¼ã‚¯ãƒ•ãƒ­ãƒ¼ã‚’実行ã™ã‚‹ã«ã¯æ‰¿èªãŒå¿…è¦ã§ã™ã€‚
diff --git a/options/locale/locale_ko-KR.ini b/options/locale/locale_ko-KR.ini
index 46aec0475..ca642ebf0 100644
--- a/options/locale/locale_ko-KR.ini
+++ b/options/locale/locale_ko-KR.ini
@@ -38,7 +38,6 @@ new_mirror=새로운 미러
new_fork=새 저장소 í¬í¬
new_org=새로운 ì¡°ì§
new_project=새 프로ì íŠ¸
-new_project_board=새 프로ì íŠ¸ ë³´ë“œ
manage_org=ì¡°ì§ ê´€ë¦¬
admin_panel=사ì´íŠ¸ 관리
account_settings=계정 설정
@@ -64,6 +63,9 @@ add=추가
add_all=ëª¨ë‘ ì¶”ê°€
remove=삭제
remove_all=ëª¨ë‘ ì‚­ì œ
+edit=수정하기
+
+enabled=활성화ë¨
write=쓰기
@@ -74,6 +76,8 @@ loading=불러오는 중...
+[aria]
+
[filter]
[error]
@@ -127,6 +131,8 @@ log_root_path_helper=로그파ì¼ì€ ì´ ë””ë ‰í† ë¦¬ì— ì €ìž¥ë©ë‹ˆë‹¤.
optional_title=추가설정
email_title=ì´ë©”ì¼ ì„¤ì •
+smtp_addr=SMTP 호스트
+smtp_port=SMTP í¬íŠ¸
smtp_from=ì´ë©”ì¼ ë°œì‹ ì¸
smtp_from_helper=Gitea ê°€ 사용할 ì´ë©”ì¼ ì£¼ì†Œ. ì´ë©”ì¼ ì£¼ì†Œ ë˜ëŠ” "ì´ë¦„" <email@example.com> 형ì‹ìœ¼ë¡œ 입력하세요.
mailer_user=SMTP 사용ìžì´ë¦„
@@ -164,7 +170,6 @@ invalid_repo_path=저장소(레파지토리) ì˜ ê²½ë¡œê°€ 올바르지 않습ë‹
run_user_not_match=실행 사용ìžëª…ì´ í˜„ìž¬ 사용ìžëª…ê³¼ 다릅니다.: %s -> %s
save_config_failed=ì„¤ì •ì„ ì €ìž¥í•  수 없습니다: %v
invalid_admin_setting=ê´€ë¦¬ìž ê³„ì • ì„¤ì •ì´ ì˜¬ë°”ë¥´ì§€ 않습니다: %v
-install_success=환ì˜í•©ë‹ˆë‹¤! Gitea를 찾아주셔서 ê°ì‚¬í•©ë‹ˆë‹¤. ì¦ê±°ìš´ 시간 보내세요!
invalid_log_root_path=로그(Log) ì˜ ê²½ë¡œê°€ 올바르지 않습니다: %v
default_keep_email_private=ì´ë©”ì¼ ì£¼ì†Œ 숨김처리를 기본값으로 설정합니다.
default_keep_email_private_popup=새 사용ìžì— 대한 ì´ë©”ì¼ ì£¼ì†Œ 숨김처리를 기본값으로 설정합니다.
@@ -188,6 +193,7 @@ view_home=%s 보기
search_repos=저장소 찾기..
+show_private=비공개
issues.in_your_repos=ë‹¹ì‹ ì˜ ì €ìž¥ì†Œì—
@@ -392,6 +398,7 @@ continue=계ì†í•˜ê¸°
cancel=취소
language=언어
ui=테마
+comment_type_group_title=제목
lookup_avatar_by_mail=ì´ë©”ì¼ ì£¼ì†Œë¡œ 아바타 찾기
federated_avatar_lookup=연합 아바타 조회
@@ -418,6 +425,7 @@ manage_openid=OpenID 주소 관리
email_desc=주 사용 ì´ë©”ì¼ ì£¼ì†ŒëŠ” 알림과 기타 ìž‘ì—…ì— ì‚¬ìš©ë©ë‹ˆë‹¤.
theme_desc=ì´ í…Œë§ˆê°€ 사ì´íŠ¸ ì „ì²´ 기본 테마가 ë©ë‹ˆë‹¤.
primary=기본
+activated=활성화ë¨
primary_email=프ë¼ì´ë¨¸ë¦¬ë¡œ 만들기
delete_email=삭제
email_deletion=ì´ë©”ì¼ ì£¼ì†Œ ì‚­ì œ
@@ -449,10 +457,15 @@ gpg_helper=<strong>ë„ì›€ì´ í•„ìš”í•˜ì„¸ìš”?</strong> GitHubì˜ ì„¤ëª…ì„œë¥¼ ì°
add_new_key=SSH 키 추가
add_new_gpg_key=GPG 키 추가
gpg_key_id_used=ê°™ì€ IDì˜ GPG 공개키가 ì´ë¯¸ 존재합니다.
+gpg_key_verify=확ì¸
+gpg_token=토í°
+ssh_key_verify=확ì¸
+ssh_token=토í°
subkeys=하위 키
key_id=키 ID
key_name=키 ì´ë¦„
key_content=컨í…츠
+principal_content=ë‚´ìš©
add_key_success=SSH 키('%s') ê°€ 추가 ë˜ì—ˆìŠµë‹ˆë‹¤.
add_gpg_key_success=GPG 키('%s') ê°€ 추가 ë˜ì—ˆìŠµë‹ˆë‹¤.
delete_key=제거
@@ -488,11 +501,14 @@ generate_token=í† í° ìƒì„±
generate_token_success=새로운 토í°ì´ ìƒì„±ë˜ì—ˆìŠµë‹ˆë‹¤. ì´ í† í°ì€ 다시 ë³´ì´ì§€ 않으니 지금 복사하십시오.
delete_token=삭제
access_token_deletion=액세스 í† í° ì‚­ì œ
+access_token_deletion_cancel_action=취소
+access_token_deletion_confirm_action=삭제
delete_token_success=토í°ì´ ì‚­ì œë˜ì—ˆìŠµë‹ˆë‹¤. 해당 토í°ì„ 사용하는 어플리케ì´ì…˜ì€ ë” ì´ìƒ ì´ ê³„ì •ìœ¼ë¡œ 접근할 수 없습니다.
manage_oauth2_applications=OAuth2 애플리케ì´ì…˜ 관리
save_application=저장하기
oauth2_client_id=í´ë¼ì´ì–¸íŠ¸ ID
+oauth2_client_secret=í´ë¼ì´ì–¸íŠ¸ ì‹œí¬ë¦¿
oauth2_regenerate_secret=ì‹œí¬ë¦¿í‚¤ 재발급
oauth2_application_edit=수정하기
@@ -520,10 +536,12 @@ twofa_enrolled=ë‹¹ì‹ ì˜ ê³„ì •ì— 2단계 ì¸ì¦ì´ 설정ë˜ì—ˆìŠµë‹ˆë‹¤. 스í
manage_account_links=ì—°ê²°ëœ ê³„ì • 관리
manage_account_links_desc=Gitea ê³„ì •ì— ì—°ê²°ëœ ì™¸ë¶€ 계정입니다.
account_links_not_available=현재 Gitea ê³„ì •ì— ì—°ê²°ëœ ì™¸ë¶€ ê³„ì •ì´ ì—†ìŠµë‹ˆë‹¤.
+link_account=계정 연결
remove_account_link=ì—°ê²°ëœ ê³„ì • 제거
remove_account_link_desc=해당 ê³„ì •ì„ ì—°ê²°í•´ì œ 하는 경우 Gitea ê³„ì •ì— ëŒ€í•œ ì ‘ê·¼ ê¶Œí•œì´ ì‚¬ë¼ì§€ê²Œ ë©ë‹ˆë‹¤. 계ì†í•˜ì‹œê² ìŠµë‹ˆê¹Œ?
remove_account_link_success=ì—°ê²°ëœ ê³„ì •ì´ ì œê±° ë˜ì—ˆìŠµë‹ˆë‹¤.
+
orgs_none=ë‹¹ì‹ ì€ ì–´ë–¤ ì¡°ì§ì˜ 구성ì›ë„ 아닙니다.
repos_none=ì–´ë–¤ ë ˆí¬ì§€í„°ë¦¬ë„ 존재하지 않습니다.
@@ -535,6 +553,7 @@ delete_account_desc=ì´ ê³„ì •ì„ ì •ë§ë¡œ 삭제하시겠습니까?
email_notifications.enable=ì´ë©”ì¼ ì•Œë¦¼ 켜기
email_notifications.disable=ì´ë©”ì¼ ì•Œë¦¼ ë„기
+visibility.private=비공개
[repo]
owner=소유ìž
@@ -574,17 +593,23 @@ forks=í¬í¬
pick_reaction=리액션 ì„ íƒ
reactions_more=그리고 %d ë”
language_other=기타
+delete_preexisting_label=삭제
+desc.private=비공개
template.topics=토론 주제
+template.avatar=아바타
form.name_reserved=저장소 ì´ë¦„ '%s'ì€ ì˜ˆì•½ ë˜ì–´ 있습니다.
form.name_pattern_not_allowed='%s' íŒ¨í„´ì€ ì €ìž¥ì†Œëª…ìœ¼ë¡œ 허용ë˜ì§€ 않습니다.
migrate_items_wiki=위키
+migrate_items_milestones=마ì¼ìŠ¤í†¤
migrate_items_issues=ì´ìŠˆ
+migrate_items_pullrequests=풀 리퀘스트
+migrate_items_releases=릴리즈
migrate_repo=저장소 마ì´ê·¸ë ˆì´ì…˜
migrate.clone_address=URLë¡œ 부터 마ì´ê·¸ë ˆì´íŠ¸ / í´ë¡ 
migrate.clone_local_path=ë˜ëŠ” 로컬 ì„œë²„ì˜ ê²½ë¡œ
@@ -681,6 +706,11 @@ commits.gpg_key_id=GPG 키 ID
ext_issues.desc=외부 ì´ìŠˆ 트래커 ì—°ê²°.
+projects.description_placeholder=설명
+projects.title=제목
+projects.new=새 프로ì íŠ¸
+projects.column.edit_title=ì´ë¦„
+projects.column.new_title=ì´ë¦„
issues.new=새로운 ì´ìŠˆ
issues.new.title_empty=ì œëª©ì€ ë¹„ì›Œë‘˜ 수 없습니다.
@@ -710,6 +740,7 @@ issues.add_milestone_at=`<b>%s</b> %s 마ì¼ìŠ¤í†¤ì„ 추가하였습니다.`
issues.change_milestone_at=`<b>%s</b> ì—ì„œ <b>%s</b> %s 마ì¼ìŠ¤í†¤ìœ¼ë¡œ 변경ë˜ì—ˆìŠµë‹ˆë‹¤`
issues.remove_milestone_at=`<b>%s</b> %s 마ì¼ìŠ¤í†¤ì´ ì‚­ì œë˜ì—ˆìŠµë‹ˆë‹¤.`
issues.deleted_milestone=`(ì‚­ì œë¨)`
+issues.deleted_project=`(ì‚­ì œë¨)`
issues.self_assign_at=`ìžì²´ì ìœ¼ë¡œ í• ë‹¹ë¨ %s`
issues.add_assignee_at=`다ìŒìœ¼ë¡œë¶€í„° í• ë‹¹ë¨ <b>%s</b> %s`
issues.remove_assignee_at=`다ìŒìœ¼ë¡œë¶€í„° í• ë‹¹ì·¨ì†Œë¨ <b>%s</b> %s`
@@ -749,9 +780,12 @@ issues.previous=ì´ì „
issues.next=다ìŒ
issues.open_title=오픈
issues.closed_title=닫힘
+issues.draft_title=초안
issues.num_comments=%dê°œì˜ ì½”ë©˜íŠ¸
issues.commented_at=`코멘트ë¨, <a href="#%s">%s</a>`
issues.delete_comment_confirm=ì´ ëŒ“ê¸€ì„ ì •ë§ ì‚­ì œí•˜ì‹œê² ìŠµë‹ˆê¹Œ?
+issues.context.edit=수정하기
+issues.context.delete=삭제
issues.no_content=ì•„ì§ ì½˜í…츠가 없습니다.
issues.close_issue=닫기
issues.close_comment_issue=í´ë¡œì¦ˆ ë° ì½”ë©˜íŠ¸
@@ -784,6 +818,7 @@ issues.attachment.open_tab=`í´ë¦­í•˜ì—¬ "%s" 새탭으로 보기`
issues.attachment.download=' "%s"를 다운로드 하려면 í´ë¦­ 하십시오 '
issues.subscribe=구ë…하기
issues.unsubscribe=êµ¬ë… ì·¨ì†Œ
+issues.delete=삭제
issues.tracker=타임 트래커
issues.start_tracking=타임 트래킹 시작
issues.start_tracking_history=`%s가 작업 시작`
@@ -921,6 +956,7 @@ activity.period.daily=1ì¼
activity.period.halfweekly=3ì¼
activity.period.weekly=1주
activity.period.monthly=1개월
+activity.period.yearly=1 ë…„
activity.overview=개요
activity.merged_prs_count_1=풀 리퀘스트 병합
activity.merged_prs_count_n=풀 리퀘스트 병합
@@ -957,6 +993,7 @@ activity.published_release_label=ë°°í¬ë¨
search=검색
search.search_repo=저장소 검색
search.results=<a href="%s">%s</a> ì—ì„œ "%s" ì— ëŒ€í•œ 검색 ê²°ê³¼
+search.code_no_results=검색어와 ì¼ì¹˜í•˜ëŠ” 소스코드가 없습니다.
settings=설정
settings.desc=ì„¤ì •ì€ ì €ìž¥ì†Œ ì„¤ì •ì„ ê´€ë¦¬í•  수 있습니다.
@@ -965,6 +1002,7 @@ settings.collaboration=ê³µë™ìž‘ì—…ìž
settings.collaboration.admin=관리ìž
settings.collaboration.write=쓰기
settings.collaboration.read=ì½ê¸°
+settings.collaboration.owner=소유ìž
settings.collaboration.undefined=미정ì˜
settings.hooks=웹훅
settings.githooks=Git í›…
@@ -993,16 +1031,18 @@ settings.enable_timetracker=시간 ì¶”ì  í™œì„±í™”
settings.allow_only_contributors_to_track_time=ê¸°ì—¬ìž íŠ¸ëž™ 타임만
settings.pulls_desc=저장소 풀 리퀘스트 활성화
settings.pulls.ignore_whitespace=ê³µë°±ì€ ì¶©ëŒì—ì„œ 무시하기
-settings.pulls.allow_merge_commits=커밋 병합 활성화
settings.admin_settings=ê´€ë¦¬ìž ì„¤ì •
settings.admin_enable_health_check=저장소 헬스 ì²´í¬ í™œì„±í™” (git fsck)
settings.danger_zone=위험 설정
settings.new_owner_has_same_repo=새로운 소유ìžê°€ ê°™ì€ ì´ë¦„ì˜ ì €ìž¥ì†Œë¥¼ ì´ë¯¸ 가지고 있습니다. 다른 ì´ë¦„ì„ ì„ íƒí•´ì£¼ì„¸ìš”.
settings.convert=ì¼ë°˜ 저장소로 변환
settings.convert_confirm=저장소 변환
+settings.convert_fork=ì¼ë°˜ 저장소로 변환
+settings.convert_fork_confirm=저장소 변환
settings.transfer=소유권 ì´ì „
settings.transfer_owner=새 소유ìž
settings.transfer_succeed=저장소가 ì´ì „ ë˜ì—ˆìŠµë‹ˆë‹¤.
+settings.trust_model.collaborator=협업ìž
settings.wiki_delete=위키 ë°ì´í„° ì‚­ì œ
settings.confirm_wiki_delete=위키 ë°ì´í„° ì‚­ì œ
settings.delete=ì´ ì €ìž¥ì†Œ ì‚­ì œ
@@ -1015,6 +1055,7 @@ settings.add_collaborator_success=ê³µë™ìž‘ì—…ìžê°€ 추가 ë˜ì—ˆìŠµë‹ˆë‹¤.
settings.delete_collaborator=제거
settings.collaborator_deletion=ê³µë™ìž‘ì—…ìž ì‚­ì œ
settings.search_user_placeholder=ì‚¬ìš©ìž ê²€ìƒ‰...
+settings.teams=팀
settings.add_webhook=Webhook 추가
settings.webhook_deletion=Webhook 삭제
settings.webhook_deletion_success=Webhookì„ ì‚­ì œí–ˆìŠµë‹ˆë‹¤.
@@ -1044,6 +1085,7 @@ settings.event_create=ìƒì„±
settings.event_create_desc=브랜치 ë˜ëŠ” 태그가 ìƒì„±ë˜ì—ˆìŠµë‹ˆë‹¤.
settings.event_delete=삭제
settings.event_fork=í¬í¬
+settings.event_wiki=위키
settings.event_release=릴리즈
settings.event_release_desc=릴리즈가 저장소ì—ì„œ ë°°í¬, 갱신 ë˜ëŠ” 제거ë˜ì—ˆìŠµë‹ˆë‹¤.
settings.event_push=푸시
@@ -1114,6 +1156,7 @@ diff.whitespace_show_everything=모든 변경사항 보기
diff.stats_desc=<strong>%dê°œì˜ ë³€ê²½ëœ íŒŒì¼</strong>ê³¼ <strong>%dê°œì˜ ì¶”ê°€ìž‘ì—…</strong> 그리고 <strong>%dê°œì˜ íŒŒì¼ì„ ì‚­ì œ</strong>
diff.bin=BIN
diff.view_file=íŒŒì¼ ë³´ê¸°
+diff.file_byte_size=í¬ê¸°
diff.file_suppressed=íŒŒì¼ í¬ê¸°ê°€ 너무 í¬ê¸°ë•Œë¬¸ì— 변경 ìƒíƒœë¥¼ 표시하지 않습니다.
diff.comment.placeholder=댓글 남기기
diff.comment.add_single_comment=간단한 설명 추가
@@ -1178,7 +1221,7 @@ org_name_holder=ì¡°ì§ ì´ë¦„
org_full_name_holder=ì¡°ì§ ì „ì²´ ì´ë¦„
create_org=새로운 ì¡°ì§
repo_updated=ì—…ë°ì´íŠ¸ë¨
-people=사람
+members=멤버
teams=팀
lower_members=회ì›
lower_repositories=저장소
@@ -1195,6 +1238,7 @@ settings.options=ì¡°ì§
settings.full_name=성명
settings.website=웹 사ì´íŠ¸
settings.location=위치
+settings.visibility.private_shortname=비공개
settings.update_settings=설정 ì—…ë°ì´íŠ¸
settings.update_setting_success=ì¡°ì§ ì„¤ì •ì´ ë³€ê²½ë˜ì—ˆìŠµë‹ˆë‹¤.
@@ -1221,6 +1265,7 @@ members.invite_now=지금 초대하기
teams.join=가입
teams.leave=탈퇴
+teams.read_access=ì½ìŒ
teams.admin_access=ê´€ë¦¬ìž ì•¡ì„¸ìŠ¤
teams.no_desc=ì´ íŒ€ì€ ì„¤ëª…ì´ ì—†ìŠµë‹ˆë‹¤.
teams.settings=설정
@@ -1289,6 +1334,7 @@ dashboard.gc_times=가비지 콜렉션 시간
users.user_manage_panel=ì‚¬ìš©ìž ê³„ì • 관리
users.new_account=ì‚¬ìš©ìž ê³„ì • ìƒì„±
users.name=사용ìžëª…
+users.full_name=성명
users.activated=활성화ë¨
users.admin=관리ìž
users.repos=저장소
@@ -1314,7 +1360,10 @@ users.allow_create_organization=ì¡°ì§ ìƒì„± 허용
users.update_profile=ì‚¬ìš©ìž ê³„ì • 갱신
users.delete_account=ì‚¬ìš©ìž ê³„ì • ì‚­ì œ
users.deletion_success=ì‚¬ìš©ìž ê³„ì •ì´ ì‚­ì œë˜ì—ˆìŠµë‹ˆë‹¤.
+users.list_status_filter.is_active=사용
+users.list_status_filter.is_admin=관리ìž
+emails.activated=활성화ë¨
orgs.org_manage_panel=ì¡°ì§ ê´€ë¦¬
orgs.name=ì´ë¦„
@@ -1332,6 +1381,11 @@ repos.forks=í¬í¬
repos.issues=ì´ìŠˆ
repos.size=í¬ê¸°
+packages.owner=소유ìž
+packages.name=ì´ë¦„
+packages.type=유형
+packages.repository=저장소
+packages.size=í¬ê¸°
@@ -1418,6 +1472,7 @@ config.ssh_keygen_path=키 ìƒì„± ('ssh-keygen') 경로
config.ssh_minimum_key_size_check=최소 키 사ì´ì¦ˆ 검사
config.ssh_minimum_key_sizes=최소 키 사ì´ì¦ˆ
+config.lfs_enabled=활성화ë¨
config.db_config=ë°ì´í„°ë² ì´ìŠ¤ 설정
config.db_type=유형
@@ -1454,6 +1509,7 @@ config.skip_tls_verify=TLS ê²€ì¦ ê±´ë„ˆë›°ê¸°
config.mailer_enabled=활성화ë¨
config.mailer_name=ì´ë¦„
+config.mailer_smtp_port=SMTP í¬íŠ¸
config.mailer_user=사용ìž
config.mailer_use_sendmail=Sendmail 사용
config.mailer_sendmail_path=Sendmail 경로
@@ -1510,13 +1566,15 @@ monitor.process=ì‹¤í–‰ì¤‘ì¸ í”„ë¡œì„¸ìŠ¤ë“¤
monitor.desc=설명
monitor.start=시작 시간
monitor.execute_time=실행 시간
+monitor.queue.name=ì´ë¦„
+monitor.queue.type=유형
monitor.queue.configuration=초기 설정
+monitor.queue.settings.submit=설정 ì—…ë°ì´íŠ¸
notices.system_notice_list=시스템 공지
notices.view_detail_header=알림 세부정보 보기
-notices.actions=ë™ìž‘
notices.select_all=ëª¨ë‘ ì„ íƒ
notices.deselect_all=ëª¨ë‘ ì„ íƒ í•´ì œ
notices.inverse_selection=ì„ íƒ ë°˜ì „
@@ -1582,4 +1640,25 @@ error.no_unit_allowed_repo=ì´ ì €ìž¥ì†Œì˜ ì–´ë–¤ 섹션ì—ë„ ì ‘ê·¼í•  수 ì—
error.unit_not_allowed=ì´ ì €ìž¥ì†Œ ì„¹ì…˜ì— ì ‘ê·¼í•  수 없습니다.
[packages]
+filter.type=유형
+conan.details.repository=저장소
+owner.settings.cleanuprules.enabled=활성화ë¨
+
+[secrets]
+name=ì´ë¦„
+
+[actions]
+
+
+
+runners.name=ì´ë¦„
+runners.owner_type=유형
+runners.description=설명
+runners.task_list.run=실행
+runners.task_list.repository=저장소
+runners.task_list.commit=커밋
+runners.status.active=사용
+
+runs.commit=커밋
+
diff --git a/options/locale/locale_lv-LV.ini b/options/locale/locale_lv-LV.ini
index 4f91e7e07..0f7862f8a 100644
--- a/options/locale/locale_lv-LV.ini
+++ b/options/locale/locale_lv-LV.ini
@@ -57,7 +57,7 @@ new_mirror=Jauns spogulis
new_fork=Jauns atdalīts repozitorijs
new_org=Jauna organizÄcija
new_project=Jauns projekts
-new_project_board=Jauns projekta dēlis
+new_project_column=Jauna kolonna
manage_org=PÄrvaldÄ«t organizÄcijas
admin_panel=Lapas administrēšana
account_settings=Konta iestatījumi
@@ -86,11 +86,16 @@ remove=Noņemt
remove_all=Noņemt visus
edit=Labot
+enabled=Iespējots
+disabled=Atspējots
+
copy=Kopēt
copy_url=Kopēt saiti
+copy_content=Kopēt saturu
copy_branch=Kopēt atzara nosaukumu
copy_success=Nokopēts!
copy_error=KopÄ“Å¡ana neizdevÄs
+copy_type_unsupported=Šī veida failus nav iespējams nokopēt
write=Rakstīt
preview=Priekšskatītījums
@@ -106,7 +111,15 @@ never=Nekad
rss_feed=RSS barotne
+[aria]
+navbar=NavigÄcijas josla
+footer=KÄjene
+footer.software=Par programmatūru
+footer.links=Saites
+
[filter]
+string.asc=A - Z
+string.desc=Z - A
[error]
occurred=Radusies kļūda
@@ -224,7 +237,6 @@ internal_token_failed=NeizdevÄs uzÄ£enerÄ“t iekÅ¡Ä“jÄs saziņas talonu: %v
secret_key_failed=NeizdevÄs uzÄ£enerÄ“t droÅ¡Ä«bas atslÄ“gu: %v
save_config_failed=NeizdevÄs saglabÄt konfigurÄciju: %v
invalid_admin_setting=Nederīgs administratora iestatījums: %v
-install_success=Laipni lÅ«dzam! Paldies, ka izvÄ“lÄ“jÄties Gitea, patÄ«kamu lietoÅ¡anu!
invalid_log_root_path=Nederīgs žurnalizēšanas ceļš: %v
default_keep_email_private=Pēc noklusējuma slēpt e-pasta adreses
default_keep_email_private_popup=Å Ä« ir noklusÄ“tÄ pazÄ«me, lai noteiktu lietotÄja e-pasta adreses redzamÄ«bu. AtzÄ«mÄ“jot to e-pasta adrese visiem jaunajiem lietotÄjiem nebÅ«s redzama lÄ«dz lietotÄjs neizmainÄ«s to savos iestatÄ«jumos.
@@ -235,7 +247,10 @@ default_enable_timetracking_popup=Repozitorijiem pēc noklusējuma tiks iespējo
no_reply_address=Neatbildēt e-pasta adreses domēns
no_reply_address_helper=DomÄ“ns lietotÄja e-pasta adresei git žurnÄlos, ja lietotÄjs izvÄ“las paturÄ“t savu e-pasta adresi privÄtu. PiemÄ“ram, ja lietotÄjs ir 'janis' un domÄ“ns 'neatbildet.piemers.lv', tad e-pasta adrese bÅ«s 'janis@neatbildet.piemers.lv'.
password_algorithm=Paroles jaucējsummas algoritms
+invalid_password_algorithm=Kļūdaina paroles jaucējfunkcija
password_algorithm_helper=NorÄdiet paroles jaucÄ“jkoda algoritmu. Alogritmiem ir dažÄdas prasÄ«bas un stiprums. Lai arÄ« `argon2` ir nodroÅ¡ina labu droÅ¡Ä«ba, tas patÄ“rÄ“ daudz operatÄ«vÄs atmiņas un var nebÅ«t piemÄ“rots sistÄ“mÄm ar nelieliem resursiem.
+enable_update_checker=Iespējot jaunu versiju paziņojumus
+enable_update_checker_helper=Periodiski pÄrbaudÄ«t jaunu version pieejamÄ«bu, izgÅ«stot datus no gitea.io.
[home]
uname_holder=LietotÄjvÄrds vai e-pasts
@@ -250,7 +265,7 @@ view_home=Skatīties %s
search_repos=Meklēt repozitoriju…
filter=Citi filtri
filter_by_team_repositories=Filtrēt pēc komandas repozitorijiem
-feed_of="%s" plūsma
+feed_of=`"%s\" plūsma`
show_archived=Arhivētie
show_both_archived_unarchived=Attēlo gan arhivētie, gan nearhivētie
@@ -342,6 +357,104 @@ authorize_application=Autorizēt lietotni
authorize_redirect_notice=Jūs tiksiet nosūtīts uz %s, ja autorizēsiet šo lietotni.
authorize_application_created_by=Å o lietotni izveidoja %s.
authorize_application_description=Ja pieÅ¡Ä·irsiet tiesÄ«bas, tÄ varÄ“s piekļūt un mainÄ«t JÅ«su konta informÄciju, ieskaitot privÄtos repozitorijus un organizÄcijas.
+authorize_title=`Autorizēt "`
+
+show_archived=Arhivētie
+show_both_archived_unarchived=Attēlot gan arhivētos, gan nearhivētos
+show_only_archived=Attēlot tikai arhivētos
+show_only_unarchived=Attēlot tikai nearhivētos
+
+show_private=PrivÄts
+show_both_private_public=AttÄ“lot gan publiskos, gan privÄtos
+show_only_private=AttÄ“lot tikai privÄtos
+show_only_public=Attēlot tikai publiskos
+
+issues.in_your_repos=JÅ«su repozitorijos
+
+[explore]
+repos=Repozitoriji
+users=LietotÄji
+organizations=OrganizÄcijas
+search=Meklēt
+code=Kods
+search.type.tooltip=Meklēšanas veids
+search.fuzzy=Aptuveni
+search.fuzzy.tooltip=Iekļaut meklÄ“Å¡anas rezultÄtos arÄ« aptuvenas sakritÄ«bas
+search.match=Precīzi
+search.match.tooltip=Iekļaut meklÄ“Å¡anas rezultÄtos tikai precÄ«zas sakritÄ«bas
+code_search_unavailable=Pašlaik koda meklēšana nav pieejama. Sazinieties ar lapas administratoru.
+repo_no_results=Netika atrasts neviens repozitorijs, kas atbilstu kritērijiem.
+user_no_results=Netika atrasts neviens lietotÄjs, kas atbilstu kritÄ“rijiem.
+org_no_results=Netika atrasta neviena organizÄcija, kas atbilstu kritÄ“rijiem.
+code_no_results=Netika atrasts pirmkods, kas atbilstu kritērijiem.
+code_search_results=MeklÄ“Å¡anas rezultÄti '%s'
+code_last_indexed_at=Pēdējo reizi indeksēts %s
+relevant_repositories_tooltip=Repozitoriju, kas ir atdalīti vai kuriem nav tēmas, ikonas un apraksta ir paslēpti.
+relevant_repositories=Tikai bÅ«tiskie repozitoriji tiek rÄdÄ«ti, <a href="%s">pÄrÄdÄ«t nefiltrÄ“tus rezultÄtus</a>.
+
+
+[auth]
+create_new_account=Reģistrēt kontu
+register_helper_msg=Jau ir konts? Pieraksties tagad!
+social_register_helper_msg=Jau ir konts? Piesaisti to!
+disable_register_prompt=ReÄ£istrÄcija ir atspÄ“jota. LÅ«dzu, sazinieties ar vietnes administratoru.
+disable_register_mail=ReÄ£istrÄcijas e-pasta apstiprinÄÅ¡ana ir atspÄ“jota.
+manual_activation_only=Sazinieties ar lapas administratoru, lai pabeigtu konta aktivizÄciju.
+remember_me=Atcerēties šo ierīci
+forgot_password_title=Aizmirsu paroli
+forgot_password=Aizmirsi paroli?
+sign_up_now=Nepieciešams konts? Reģistrējies tagad.
+sign_up_successful=Konts tika veiksmīgi izveidots.
+confirmation_mail_sent_prompt=Jauns apstiprinÄÅ¡anas e-pasts ir nosÅ«tÄ«ts uz <b>%s</b>, pÄrbaudies savu e-pasta kontu tuvÄko %s laikÄ, lai pabeigtu reÄ£istrÄcijas procesu.
+must_change_password=Mainīt paroli
+allow_password_change=PieprasÄ«t lietotÄjam mainÄ«t paroli (ieteicams)
+reset_password_mail_sent_prompt=ApstiprinÄÅ¡anas e-pasts tika nosÅ«tÄ«ts uz <b>%s</b>. PÄrbaudiet savu e-pasta kontu tuvÄko %s laikÄ, lai pabeigtu paroles atjaunoÅ¡anas procesu.
+active_your_account=Aktivizēt savu kontu
+account_activated=Konts ir aktivizēts
+prohibit_login=Aizliegt pieteikšanos
+prohibit_login_desc=Jūsu konts ir bloķēts, sazinieties ar sistēmas administratoru.
+resent_limit_prompt=JÅ«s pieprasÄ«jÄt aktivizÄcijas e-pastu pÄrÄk bieži. LÅ«dzu, uzgaidiet 3 minÅ«tes un mÄ“Ä£iniet vÄ“lreiz.
+has_unconfirmed_mail=Sveiki %s, Jums ir neapstiprinÄta e-pasta adrese (<b>%s</b>). Ja neesat saņēmis apstiprinÄÅ¡anas e-pastu vai Jums ir nepiecieÅ¡ams nosÅ«tÄ«t jaunu, lÅ«dzu, nospiediet pogu, kas atrodas zemÄk.
+resend_mail=Nospiediet Å¡eit, lai vÄ“lreiz nosÅ«tÄ«tu aktivizÄcijas e-pastu
+email_not_associate=Šī e-pasta adrese nav saistīta ar nevienu kontu.
+send_reset_mail=Nosūtīt paroles atjaunošanas e-pastu
+reset_password=Paroles atjaunošana
+invalid_code=JÅ«su apstiprinÄÅ¡anas kodam ir beidzies derÄ«guma termiņš vai arÄ« tas ir nepareizs.
+invalid_password=Jūsu parole neatbilst parolei, kas tika ievadīta veidojot so kontu.
+reset_password_helper=Atjaunot paroli
+reset_password_wrong_user=JÅ«s esat autorizÄ“jies kÄ %s, bet paroles atjaunoÅ¡anas saite ir lietotÄjam %s
+password_too_short=Paroles garums nedrÄ«kst bÅ«t mazÄks par %d simboliem.
+non_local_account=Ārējie konti nevar mainīt paroli, izmantojot, Gitea saskarni.
+verify=PÄrbaudÄ«t
+scratch_code=Vienreizējais kods
+use_scratch_code=Izmantot vienreizējo kodu
+twofa_scratch_used=JÅ«s esat izmantojis vienreizÄ“jo kodu. JÅ«s tikÄt pÄrsÅ«tÄ«ts uz divu faktoru iestatÄ«jumu lapu, lai varÄ“tu piesaistÄ«to ierÄ«ci vai lai uzÄ£enerÄ“tu jaunu vienreizÄ“jo kodu.
+twofa_passcode_incorrect=Jūsu kods nav pareizs. Ja esat pazaudējis ierīci, izmantojiet vienreizējo kodu, lai autorizētos.
+twofa_scratch_token_incorrect=Ievadīts nepareizs vienreizējais kods.
+login_userpass=Pierakstīties
+login_openid=OpenID
+oauth_signup_tab=Reģistrēt jaunu kontu
+oauth_signup_title=Pabeigt konta veidošanu
+oauth_signup_submit=Pabeigt reÄ£istrÄciju
+oauth_signin_tab=Savienot ar esošu kontu
+oauth_signin_title=Pierakstīties, lai autorizētu saistīto kontu
+oauth_signin_submit=Saistītie konti
+oauth.signin.error=RadÄs kļūda apstrÄdÄjot autorizÄcijas pieprasÄ«jumu. Ja Å¡Ä« kļūda atkÄrtojas, sazinieties ar lapas administratoru.
+oauth.signin.error.access_denied=AutorizÄcijas pieprasÄ«jums tika noraidÄ«ts.
+oauth.signin.error.temporarily_unavailable=AutorizÄcija neizdevÄs, jo autentifikÄcijas serveris ir Ä«slaicÄ«gi nepieejams. MÄ“Ä£iniet autorizÄ“ties vÄ“lÄk.
+openid_connect_submit=Pievienoties
+openid_connect_title=Pievienoties jau esošam kontam
+openid_connect_desc=IzvÄ“lÄ“tais OpenID konts sistÄ“mÄ netika atpazÄ«ts, bet JÅ«s to varat piesaistÄ«t esoÅ¡am kontam.
+openid_register_title=Izveidot jaunu kontu
+openid_register_desc=IzvÄ“lÄ“tais OpenID konts sistÄ“mÄ netika atpazÄ«ts, bet JÅ«s to varat piesaistÄ«t esoÅ¡am kontam.
+openid_signin_desc=Ievadiet savu OpenID URI, piemēram: https://anna.me, peteris.openid.org.lv, gnusocial.net/janis.
+disable_forgot_password_mail=Konta atjaunoÅ¡ana ir atspÄ“jota, jo nav uzstÄdÄ«ti e-pasta servera iestatÄ«jumi. Sazinieties ar lapas administratoru.
+disable_forgot_password_mail_admin=Kontu atjaunoÅ¡ana ir pieejama tikai, ja ir veikta e-pasta servera iestatÄ«jumu konfigurÄ“Å¡ana. NorÄdiet e-pasta servera iestatÄ«jumus, lai iespÄ“jotu kontu atjaunoÅ¡anu.
+email_domain_blacklisted=Nav atļauts reÄ£istrÄ“ties ar Å¡Ädu e-pasta adresi.
+authorize_application=Autorizēt lietotni
+authorize_redirect_notice=Jūs tiksiet nosūtīts uz %s, ja autorizēsiet šo lietotni.
+authorize_application_created_by=Å o lietotni izveidoja %s.
+authorize_application_description=Ja pieÅ¡Ä·irsiet tiesÄ«bas, tÄ varÄ“s piekļūt un mainÄ«t JÅ«su konta informÄciju, ieskaitot privÄtos repozitorijus un organizÄcijas.
authorize_title=Autorizēt "%s" piekļuvi jūsu kontam?
authorization_failed=AutorizÄcija neizdevÄs
authorization_failed_desc=AutorizÄcija neizdevÄs, jo tika veikts kļūdains pieprasÄ«jums. Sazinieties ar lietojumprogrammas, ar kuru mÄ“Ä£inÄjÄt autorizÄ“ties, uzturÄ“tÄju.
@@ -351,6 +464,7 @@ password_pwned_err=NeizdevÄs pabeigt pieprasÄ«jumu uz HaveIBeenPwned
[mail]
view_it_on=Aplūkot %s
+reply=vai atbildiet uz e-pastu
link_not_working_do_paste=Ja saite nestrÄdÄ, mÄ“Ä£iniet to nokopÄ“t un atvÄ“rt pÄrlÅ«kÄ.
hi_user_x=Sveiki <b>%s</b>,
@@ -402,13 +516,17 @@ release.download.zip=Izejas kods (ZIP)
release.download.targz=Izejas kods (TAR.GZ)
repo.transfer.subject_to=%s vÄ“las pÄrsÅ«tÄ«t repozitoriju "%s" organizÄcijai %s
-repo.transfer.subject_to_you=%s vÄ“las Jums pÄrsÅ«tÄ«t repozitoriju "%s"
+repo.transfer.subject_to_you=`%s vÄ“las Jums pÄrsÅ«tÄ«t repozitoriju "%s"`
repo.transfer.to_you=Jums
repo.transfer.body=Ja vÄ“laties to noraidÄ«t vai apstiprinÄt, tad apmeklÄ“jiet saiti %s.
repo.collaborator.added.subject=%s pievienoja JÅ«s repozitorijam %s
repo.collaborator.added.text=JÅ«s tikÄt pievienots kÄ lÄ«dzstrÄdnieks repozitorijam:
+team_invite.subject=%[1]s uzaicinÄja JÅ«s pievienoties organizÄcijai %[2]s
+team_invite.text_1=%[1]s uzaicinÄja JÅ«s pievienoties komandai %[2] organizÄcijÄ %[3]s.
+team_invite.text_2=Uzspiediet uz Å¡Ä«s saites, lai pievienoties komandai:
+team_invite.text_3=PiezÄ«me: Å is uzaicinÄjums ir paredzÄ“ts %[1]s. Ja uzskatÄt, ka tas nav domÄts Jums, varat ignorÄ“t Å¡o e-pastu.
[modal]
yes=JÄ
@@ -450,6 +568,8 @@ url_error=`'%s' nav korekts URL.`
include_error=` ir jÄsatur tekstu '%s'.`
glob_pattern_error=` glob Å¡ablons nav korekts: %s.`
regex_pattern_error=` regulÄrÄ izteiksme nav korekta: %s.`
+username_error=` drÄ«kst saturÄ“t tikai burtus un ciparus ('0-9','a-z','A-Z'), domuzÄ«me ('-'), apakÅ¡svÄ«tra ('_') un punkts ('.'). Nevar sÄkties vai beigties ar simbolu, kas nav burts vai skaitlis, kÄ arÄ« nevar bÅ«t vairÄki simboli pÄ“c kÄrtas, kas nav burti vai skaitļi.`
+invalid_group_team_map_error=` sasaiste nav korekta: %s`
unknown_error=NezinÄma kļūda:
captcha_incorrect=Ievadīts nepareizs drošības kods.
password_not_match=IzvÄ“lÄ“tÄ parole nesakrÄ«t ar atkÄrtoti ievadÄ«to.
@@ -485,10 +605,13 @@ user_not_exist=LietotÄjs neeksistÄ“.
team_not_exist=Komanda neeksistē.
last_org_owner=Nevar noņemt pÄ“dejo lietotÄju no Ä«paÅ¡nieku komandas. OrganizÄcijai ir jÄbÅ«t vismaz vienam Ä«paÅ¡niekam.
cannot_add_org_to_team=OrganizÄciju nevar pievienot kÄ komandas biedru.
+duplicate_invite_to_team=LietotÄjs jau ir uzaicinÄts kÄ komandas biedrs.
+organization_leave_success=JÅ«s esat pametis organizÄciju %s.
invalid_ssh_key=Nav iespÄ“jams pÄrbaudÄ«t SSH atslÄ“gu: %s
invalid_gpg_key=Nav iespÄ“jams pÄrbaudÄ«t GPG atslÄ“gu: %s
invalid_ssh_principal=Kļūdaina identitÄte: %s
+must_use_public_key=AtslÄ“ga, ko norÄdÄ«jÄt ir privÄtÄ atslÄ“ga. Nekad nenodotiet savu privÄtu atslÄ“gu nevienam. Izmantojiet publisko atslÄ“gu.
unable_verify_ssh_key=SSH atslÄ“gu nav iespÄ“jams pÄrbaudÄ«t, pÄrliecinieties, ka tajÄ nav kļūdu.
auth_failed=AutentifikÄcija neizdevÄs: %v
@@ -508,6 +631,7 @@ activity=PubliskÄ aktivitÄte
followers=SekotÄji
starred=Atzīmēti repozitoriji
watched=VÄ“rotie repozitoriji
+code=Kods
projects=Projekti
following=Seko
follow=Sekot
@@ -724,6 +848,8 @@ access_token_deletion_cancel_action=Atcelt
access_token_deletion_confirm_action=Dzēst
access_token_deletion_desc=IzdzÄ“Å¡ot talonu, tam tiks liegta piekļuve Å¡im kontam. Å Ä« darbÄ«ba ir neatgriezeniska. Vai turpinÄt?
delete_token_success=Piekļuves talons tika noņemts. Neaizmirstiet atjaunot informÄciju lietojumprogrammÄs, kas izmantoja Å¡o talonu.
+select_scopes=NorÄdiet apgabalus
+scopes_list=Apgabali:
manage_oauth2_applications=PÄrvaldÄ«t OAuth2 lietotnes
edit_oauth2_application=Labot OAuth2 lietotni
@@ -736,6 +862,7 @@ create_oauth2_application_button=Izveidot lietotni
create_oauth2_application_success=OAuth2 lietotne veiksmīgi izveidota.
update_oauth2_application_success=OAuth2 lietotne veiksmÄ«gi atjauninÄta.
oauth2_application_name=Lietotnes nosaukums
+oauth2_confidential_client=KonfidenciÄls klients. NorÄdiet lietotÄ“m, kas glabÄ noslÄ“pumu slepenÄ«bÄ, piemÄ“ram, tÄ«mekļa lietotnÄ“m. NenorÄdiet instalÄ“jamÄm lietotnÄ“m, tai skaitÄ darbavirsmas vai mobilajÄm lietotnÄ“m.
oauth2_redirect_uri=Novirzīšanas URI
save_application=SaglabÄt
oauth2_client_id=Klienta ID
@@ -786,6 +913,8 @@ remove_account_link=Noņemt saistīto kontu
remove_account_link_desc=Noņemot saistÄ«to kontu, tam tiks liegta piekļuve JÅ«su Gitea kontam. Vai turpinÄt?
remove_account_link_success=Saistītais konts tika noņemts.
+hooks.desc=Pievienot tÄ«mekÄ¼Ä ÄÄ·us, kas izpildÄ«sies <strong>visiem repozitorijiem</strong>, kas pieder Å¡im lietotÄjam.
+
orgs_none=JÅ«s neesat nevienas organizÄcijas biedrs.
repos_none=Jums nepieder neviens repozitorijs
@@ -897,9 +1026,9 @@ delete_preexisting_success=DzÄ“st nepÄrņemtos failus direktorijÄ %s
blame_prior=AplÅ«kot vainÄ«go par izmaiņÄm pirms Å¡Ä«s revÄ«zijas
transfer.accept=ApstiprinÄt Ä«paÅ¡nieka maiņu
-transfer.accept_desc=Mainīt īpašnieku uz "%s"
+transfer.accept_desc=`Mainīt īpašnieku uz "%s"`
transfer.reject=Noraidīt īpašnieka maiņu
-transfer.reject_desc=Atcelt īpašnieka maiņu uz "%s"
+transfer.reject_desc=`Atcelt īpašnieka maiņu uz "%s"`
transfer.no_permission_to_accept=Jums nav tiesÄ«bu apstiprinÄt
transfer.no_permission_to_reject=Jums nav tiesību noraidīt
@@ -995,10 +1124,12 @@ unstar=Noņemt zvaigznīti
star=Pievienot zvaigznīti
fork=Atdalīts
download_archive=LejupielÄdÄ“t repozitoriju
+more_operations=VairÄk darbÄ«bu
no_desc=Nav apraksta
quick_guide=Īsa pamÄcÄ«ba
clone_this_repo=Klonēt šo repozitoriju
+cite_this_repo=Citēt šo repozitoriju
create_new_repo_command=Izveidot jaunu repozitoriju komandrindÄ
push_exist_repo=Nosūtīt izmaiņas no komandrindas eksistējošam repozitorijam
empty_message=Repozitorijs ir tukšs.
@@ -1036,6 +1167,13 @@ file_view_rendered=SkatÄ«t rezultÄtu
file_view_raw=RÄdÄ«t neapstrÄdÄtu
file_permalink=PatstÄvÄ«gÄ saite
file_too_large=Å is fails ir par lielu, lai to parÄdÄ«tu.
+invisible_runes_header=`Å is fails satur satur neredzamus unikoda simbolus!`
+invisible_runes_description=`Å is fails satur neredzamus unikoda simbolus, kas var mainÄ«t kÄ saturs tiek attÄ“lots. Ja tie ir izmantoti ar pamatotu nodumu, tad varat ignorÄ“t Å¡o brÄ«dinÄjumu. Izmantojiet KodÄ“t pogu, lai parÄdÄ«tu Å¡os neredzamos simbolus.`
+ambiguous_runes_header=`Šis fails satur neviennozīmīgus unikoda simbolus!`
+ambiguous_runes_description=`Å is fails satur nevienozÄ«mÄ«gus unikoda simbolus, kas var bÅ«t mulsinoÅ¡i un grÅ«ti atÅ¡Ä·irami. Ja tie ir izmantoti ar pamatotu nodumu, tad varat ignorÄ“t Å¡o brÄ«dinÄjumu. Izmantojiet KodÄ“t pogu, lai parÄdÄ«tu Å¡os neredzamos simbolus.`
+invisible_runes_line=`Šī līnija satur neredzamus unikoda simbolus`
+ambiguous_runes_line=`Šī līnija satur neviennozīmīgus unikoda simbolus`
+ambiguous_character=`%[1]c [U+%04[1]X] var tikt sajaukts ar %[2]c [U+%04[2]X]`
escape_control_characters=Kodēt
unescape_control_characters=Atkodēt
@@ -1090,6 +1228,7 @@ editor.commit_directly_to_this_branch=ApstiprinÄt revÄ«zijas izmaiņas atzarÄ
editor.create_new_branch=Izveidot <strong>jaunu atzaru</strong> un izmaiņu pieprasījumu šai revīzijai.
editor.create_new_branch_np=Izveidot <strong>jaunu atzaru</strong> šai revīzijai.
editor.propose_file_change=Ieteikt faila izmaiņas
+editor.new_branch_name=JaunÄ atzara nosaukums Å¡ai revÄ«zijai
editor.new_branch_name_desc=JaunÄ atzara nosaukums…
editor.cancel=Atcelt
editor.filename_cannot_be_empty=Faila nosaukums nevar būt tukšs.
@@ -1141,7 +1280,7 @@ commits.signed_by_untrusted_user_unmatched=ParakstÄ«jis neuzticams lietotÄjs, k
commits.gpg_key_id=GPG atslēgas ID
commits.ssh_key_fingerprint=SSH atslÄ“gas identificÄ“joÅ¡Ä zÄ«mju virkne
-commit.actions=Darbības
+commit.operations=Darbības
commit.revert=Atgriezt
commit.revert-header=Atgriezt: %s
commit.revert-content=NorÄdiet atzaru uz kuru atgriezt:
@@ -1169,24 +1308,27 @@ projects.edit_subheader=Projekti organizē problēmas un ļauj izsekot to progre
projects.modify=Mainīt projektu
projects.edit_success=Projekta '%s' izmaiņas tika saglabÄtas.
projects.type.none=Nav
-projects.type.basic_kanban=VienkÄrÅ¡ots "Kanban"
+projects.type.basic_kanban=`VienkÄrÅ¡ots "Kanban"`
projects.type.bug_triage=Kļūdu šķirošana
projects.template.desc=Projekta sagatave
projects.template.desc_helper=IzvÄ“lieties projekta sagatavi, lai sÄktu darbu
projects.type.uncategorized=Bez kategorijas
-projects.board.edit=Labot dēli
-projects.board.edit_title=Dēļa nosaukums
-projects.board.new_title=Dēļa nosaukums
-projects.board.new_submit=ApstiprinÄt
-projects.board.new=Jauns dēlis
-projects.board.set_default=IzvÄ“lÄ“ties kÄ noklusÄ“to
-projects.board.set_default_desc=IzvÄ“lÄ“ties Å¡o dÄ“li kÄ noklusÄ“to nekategorizÄ“tÄm problÄ“mÄm un izmaiņu pieteikumiem
-projects.board.delete=Dzēst dēli
-projects.board.deletion_desc=DzÄ“Å¡ot projekta dÄ“li visas tam piesaistÄ«tÄs problÄ“mas tiks pÄrliktas kÄ nekategorizÄ“tas. Vai turpinÄt?
-projects.board.color=KrÄsa
+projects.column.edit=Rediģēt kolonnas
+projects.column.edit_title=Nosaukums
+projects.column.new_title=Nosaukums
+projects.column.new_submit=Izveidot kolonnu
+projects.column.new=Jauna kolonna
+projects.column.set_default=IzvÄ“lÄ“ties kÄ noklusÄ“to
+projects.column.set_default_desc=IzvÄ“lÄ“ties Å¡o kolonnu kÄ noklusÄ“to nekategorizÄ“tÄm problÄ“mÄm un izmaiņu pieteikumiem
+projects.column.delete=Dzēst kolonnu
+projects.column.deletion_desc=DzÄ“Å¡ot projekta kolonnu visas tam piesaistÄ«tÄs problÄ“mas tiks pÄrliktas kÄ nekategorizÄ“tas. Vai turpinÄt?
+projects.column.color=KrÄsa
projects.open=Aktīvie
projects.close=Pabeigtie
-projects.board.assigned_to=Piešķirts
+projects.column.assigned_to=Piešķirts
+projects.card_type.desc=Kartītes priekšskatījums
+projects.card_type.images_and_text=Attēli un teksts
+projects.card_type.text_only=Tikai teksts
issues.desc=Organizēt kļūdu ziņojumus, uzdevumus un atskaites punktus.
issues.filter_assignees=Filtrēt pēc atbildīgajiem
@@ -1222,6 +1364,8 @@ issues.new.add_reviewer_title=Pieprasīt recenziju
issues.choose.get_started=SÄkt darbu
issues.choose.blank=Noklusējuma
issues.choose.blank_about=Izveidot problēmu ar noklusējuma sagatavi.
+issues.choose.ignore_invalid_templates=KļūdainÄs sagataves tika izlaistas
+issues.choose.invalid_templates=%v ķļūdaina sagatave(s) atrastas
issues.no_ref=Nav norÄdÄ«ts atzars/tags
issues.create=Pieteikt problēmu
issues.new_label=Jauna etiÄ·ete
@@ -1260,14 +1404,20 @@ issues.filter_label_exclude=`Izmantojiet <code>alt</code> + <code>peles klikšķ
issues.filter_label_no_select=Visas etiÄ·etes
issues.filter_milestone=Atskaites punkts
issues.filter_milestone_no_select=Visi atskaites punkti
+issues.filter_project=Projektus
+issues.filter_project_all=Visi projekti
+issues.filter_project_none=Nav projektu
issues.filter_assignee=Atbildīgais
issues.filter_assginee_no_select=Visi atbildīgie
+issues.filter_poster=Autors
+issues.filter_poster_no_select=Visi autori
issues.filter_type=Veids
issues.filter_type.all_issues=Visas problēmas
issues.filter_type.assigned_to_you=PieÅ¡Ä·irtÄs Jums
issues.filter_type.created_by_you=JÅ«su izveidotÄs
issues.filter_type.mentioning_you=Esat pieminēts
issues.filter_type.review_requested=Pieprasīta recenzija
+issues.filter_type.reviewed_by_you=Tavi recenzētie
issues.filter_sort=KÄrtot
issues.filter_sort.latest=JaunÄkie
issues.filter_sort.oldest=Vecakie
@@ -1289,6 +1439,8 @@ issues.action_milestone=Atskaites punkts
issues.action_milestone_no_select=Nav atskaites punkta
issues.action_assignee=Atbildīgais
issues.action_assignee_no_select=Nav atbildÄ«gÄ
+issues.action_check=Atzīmēt/Notīrīt
+issues.action_check_all=Atzīmēt/Notīrīt visus ierakstus
issues.opened_by=<a href="%[2]s">%[3]s</a> atvēra %[1]s
pulls.merged_by=<a href="%[2]s">%[3]s</a> sapludinÄja %[1]s
pulls.merged_by_fake=%[2]s sapludinÄja %[1]s
@@ -1342,6 +1494,9 @@ issues.save=SaglabÄt
issues.label_title=EtiÄ·etes nosaukums
issues.label_description=EtiÄ·etes apraksts
issues.label_color=EtiÄ·etes krÄsa
+issues.label_exclusive=Ekskluzīvs
+issues.label_exclusive_desc=Nosauciet etiÄ·eti <code>grupa/nosaukums</code>, lai grupÄ“tu etiÄ·Ä“tes un varÄ“tu norÄdÄ«t tÄs kÄ ekskluzÄ«vas ar citÄm <code>grupa/</code> etiÄ·etÄ“m.
+issues.label_exclusive_warning=Jebkura konfliktējoša ekskluzīvas grupas etiķete tiks noņemta, labojot pieteikumu vai izmaiņu pietikumu etiķetes.
issues.label_count=%d etiÄ·etes
issues.label_open_issues=%d atvērtas problēmas
issues.label_edit=Labot
@@ -1409,7 +1564,8 @@ issues.error_removing_due_date=NeizdevÄs noņemt izpildes termiņu.
issues.push_commit_1=iesūtīja %d revīziju %s
issues.push_commits_n=iesūtīja %d revīzijas %s
issues.force_push_codes=`veica piespiedu izmaiņu iesÅ«tÄ«Å¡anu atzarÄ %[1]s no revÄ«zijas <a class="ui sha" href="%[3]s"><code>%[2]s</code></a> uz <a class="ui sha" href="%[5]s"><code>%[4]s</code></a> %[6]s`
-issues.due_date_form=yyyy-mm-dd
+issues.force_push_compare=SalÄ«dzinÄt
+issues.due_date_form=dd.mm.yyyy
issues.due_date_form_add=Pievienot izpildes termiņu
issues.due_date_form_edit=Labot
issues.due_date_form_remove=Noņemt
@@ -1595,6 +1751,8 @@ pulls.reopened_at=`atkÄrtoti atvÄ“ra Å¡o izmaiņu pieprasÄ«jumu <a id="%[1]s" h
pulls.merge_instruction_hint=`Varat aplūkot arī <a class="show-instruction">komandrindas instrukcijas</a>.`
pulls.merge_instruction_step1_desc=Projekta repozitorijÄ izveidojiet jaunu jaunu atzaru un pÄrbaudiet savas izmaiņas.
pulls.merge_instruction_step2_desc=SapludinÄt izmaiņas un atjaunot tÄs Gitea.
+pulls.clear_merge_message=NotÄ«rÄ«t sapludinÄÅ¡anas ziņojumu
+pulls.clear_merge_message_hint=NotÄ«rot sapludinÄÅ¡anas ziņojumu tiks noņemts tikai pats ziņojums, bet tiks paturÄ“ti Ä£enerÄ“tie git ziņojumu, kÄ "Co-Authored-By …".
pulls.auto_merge_button_when_succeed=(Kad pÄrbaudes veiksmÄ«gas)
pulls.auto_merge_when_succeed=AutomÄtiski sapludinÄt, kad visas pÄrbaudes veiksmÄ«gas
@@ -1750,8 +1908,11 @@ activity.git_stats_deletion_n=%d dzēšanas
search=Meklēt
search.search_repo=MeklÄ“Å¡ana repozitorijÄ
+search.type.tooltip=Meklēšanas veids
search.fuzzy=Aptuveni
+search.fuzzy.tooltip=Iekļaut meklÄ“Å¡anas rezultÄtos arÄ« aptuvenas sakritÄ«bas
search.match=Precīzi
+search.match.tooltip=Iekļaut meklÄ“Å¡anas rezultÄtos tikai precÄ«zas sakritÄ«bas
search.results=MeklÄ“Å¡anas rezultÄti nosacÄ«jumam "%s" repozitorijÄ <a href="%s">%s</a>
search.code_no_results=Netika atrasts pirmkods, kas atbilstu kritērijiem.
search.code_search_unavailable=Pašlaik koda meklēšana nav pieejama. Sazinieties ar lapas administratoru.
@@ -1783,6 +1944,7 @@ settings.mirror_sync_in_progress=Notiek spoguļa sinhronizÄcija. Atjaunojiet la
settings.site=MÄjas lapa
settings.update_settings=Mainīt iestatījumus
settings.branches.update_default_branch=Atjaunot noklusēto atzaru
+settings.branches.add_new_rule=Pievienot jaunu noteikumu
settings.advanced_settings=Papildu iestatījumi
settings.wiki_desc=Iespējot vikivietnes
settings.use_internal_wiki=Izmantot iebūvēto vikivietni
@@ -1809,16 +1971,14 @@ settings.enable_timetracker=Iespējot laika uzskaiti
settings.allow_only_contributors_to_track_time=Atļaut tikai dalībniekiem uzskaitīt laiku
settings.pulls_desc=Iespējot repozitorija izmaiņu pieprasījumus
settings.pulls.ignore_whitespace=PÄrbaudot konfliktus, ignorÄ“t izmaiņas atstarpÄ“s
-settings.pulls.allow_merge_commits=IespÄ“jot revÄ«ziju sapludinÄÅ¡anu
-settings.pulls.allow_rebase_merge=IespÄ“jot pÄrbÄzÄ“Å¡anu sapludinot revÄ«zijas
-settings.pulls.allow_rebase_merge_commit=IespÄ“jot pÄrbÄzÄ“Å¡anu sapludinot revÄ«zijas (--no-ff)
-settings.pulls.allow_squash_commits=Iespējot saspiešanu sapludinot revīzijas
-settings.pulls.allow_manual_merge=IespÄ“jot atzÄ«mÄ“t izmaiņu pieprasÄ«jumu kÄ manuÄli sapludinÄtu
settings.pulls.enable_autodetect_manual_merge=IespÄ“jot manuÄlo sapludinÄÅ¡anas noteikÅ¡anu (PiezÄ«me: dažos speciÄlos gadÄ«jumos, tas var nostrÄdÄt nekorekti)
settings.pulls.allow_rebase_update=IespÄ“jot izmaiņu pieprasÄ«juma atjaunoÅ¡anu ar pÄrbÄzÄ“Å¡anu
settings.pulls.default_delete_branch_after_merge=PÄ“c noklusÄ“juma dzÄ“st izmaiņu pieprasÄ«juma atzaru pÄ“c sapludinÄÅ¡anas
+settings.pulls.default_allow_edits_from_maintainers=Atļaut uzturÄ“tÄjiem labot pÄ“c noklusÄ“juma
+settings.releases_desc=Iespējot repozitorija laidienus
settings.packages_desc=Iespējot repozitorija pakotņu reģistru
settings.projects_desc=Iespējot repozitorija projektus
+settings.actions_desc=Iespējot repozitorija darbības
settings.admin_settings=Administratora iestatījumi
settings.admin_enable_health_check=IespÄ“jot veselÄ«bas pÄrbaudi (git fsck) Å¡im repozitorijam
settings.admin_code_indexer=Izejas koda indeksÄ“tÄjs
@@ -1854,7 +2014,7 @@ settings.transfer_notices_2=- JÅ«s saglabÄsiet piekļuvi, ja jaunais Ä«paÅ¡niek
settings.transfer_notices_3=- Ja repozitorijs ir privÄts un tas tiks pÄrsÅ«tÄ«ts lietotÄjam, tad pÄrliecinÄties, ka lietotÄjam ir vismaz skatÄ«Å¡anÄs tiesÄ«bas (veiciet nepiecieÅ¡amÄs izmaiņas, ja nepiecieÅ¡ams).
settings.transfer_owner=Jaunais īpašnieks
settings.transfer_perform=Veikt īpašnieka maiņu
-settings.transfer_started=Å im repozitorijam tiek veikta Ä«paÅ¡nieka maiņa un nepiecieÅ¡ams apstiprinÄjums no "%s"
+settings.transfer_started=`Å im repozitorijam tiek veikta Ä«paÅ¡nieka maiņa un nepiecieÅ¡ams apstiprinÄjums no "%s"`
settings.transfer_succeed=Repozitorijs tika pÄrcelts.
settings.signing_settings=Parakstu pÄrbaudes iestatÄ«jumi
settings.trust_model=UzticÄ“Å¡anÄs modelis parakstiem
@@ -1885,6 +2045,7 @@ settings.confirm_delete=Dzēst repozitoriju
settings.add_collaborator=Pievienot lÄ«dzstrÄdnieku
settings.add_collaborator_success=Jauns lÄ«dzstrÄdnieks tika pievienots.
settings.add_collaborator_inactive_user=Nevar pievienot neaktÄ«vu lietotÄju kÄ lÄ«dzstrÄdnieku.
+settings.add_collaborator_owner=Nevar pievienot Ä«paÅ¡nieku kÄ lÄ«dzstrÄdnieku.
settings.add_collaborator_duplicate=LÄ«dzstrÄdnieks jau ir pievienots Å¡im repozitorijam.
settings.delete_collaborator=Noņemt
settings.collaborator_deletion=Noņemt lÄ«dzstrÄdnieku
@@ -1943,6 +2104,8 @@ settings.event_delete=Dzēst
settings.event_delete_desc=Atzars vai tags izdzēsts.
settings.event_fork=Atdalīts
settings.event_fork_desc=Repozitorijs atdalīts.
+settings.event_wiki=Vikivietni
+settings.event_wiki_desc=Vikivietnes lapa izveidota, pÄrsaukta, labota vai dzÄ“sta.
settings.event_release=Laidiens
settings.event_release_desc=PublicÄ“ts, atjaunots vai dzÄ“sts laidiens repozitorijÄ.
settings.event_push=Izmaiņu nosūtīšana
@@ -1979,6 +2142,8 @@ settings.event_package=Pakotne
settings.event_package_desc=RepozitorijÄ izveidota vai dzÄ“sta pakotne.
settings.branch_filter=Atzaru filtrs
settings.branch_filter_desc=Atzaru ierobežojumi izmaiņu iesÅ«tÄ«Å¡anas, zaru izveidoÅ¡anas vai dzÄ“Å¡anas notikumiem, izmantojot, glob Å¡ablonu. Ja norÄdÄ«ts tukÅ¡s vai <code>*</code>, tiks nosÅ«tÄ«ti notikumi no visiem zariem. Skatieties <a href="https://pkg.go.dev/github.com/gobwas/glob#Compile">github.com/gobwas/glob</a> pieraksta dokumentÄciju. PiemÄ“rs: <code>master</code>, <code>{master,release*}</code>.
+settings.authorization_header=AutorizÄcijas galvene
+settings.authorization_header_desc=Tiks iekļauta kÄ autorizÄcijas galvenei pieprasÄ«jumiem, ja ir norÄdÄ«ta. PiemÄ“ram: %s.
settings.active=Aktīvs
settings.active_helper=InformÄcija par notikumiem tiks nosÅ«tÄ«ta uz Å¡o tÄ«mekļa ÄÄ·a URL.
settings.add_hook_success=TÄ«mekļa ÄÄ·is tika pievienots.
@@ -2023,6 +2188,8 @@ settings.deploy_key_deletion_desc=Noņemot izvietošanas atslēgu, tai tiks lieg
settings.deploy_key_deletion_success=Izvietošanas atslēga tika noņemta.
settings.branches=Atzari
settings.protected_branch=Atzaru aizsargÄÅ¡ana
+settings.protected_branch.save_rule=SaglabÄt noteikumu
+settings.protected_branch.delete_rule=Dzēst noteikumu
settings.protected_branch_can_push=Atļaut izmaiņu nosūtīšanu?
settings.protected_branch_can_push_yes=Jūs varat nosūtīt izmaiņas
settings.protected_branch_can_push_no=Jūs nevarat nosūtīt izmaiņas
@@ -2057,6 +2224,7 @@ settings.dismiss_stale_approvals=PieprasÄ«t apstiprinÄjumus jaunÄkajÄm izmaiÅ
settings.dismiss_stale_approvals_desc=Kad tiek iesÅ«tÄ«tas jaunas revÄ«zijas, kas izmaina izmaiņu pieprasÄ«juma saturu, iepriekÅ¡Ä“jie apstiprinÄjumi tiks atzÄ«mÄ“ti kÄ novecojuÅ¡i un bÅ«s nepiecieÅ¡ams apstiprinÄt tos atkÄroti.
settings.require_signed_commits=Pieprasīt parakstītas revīzijas
settings.require_signed_commits_desc=NoraidÄ«t iesÅ«tÄ«tÄs izmaiņas Å¡im atzaram, ja tÄs nav parakstÄ«tas vai nav iespÄ“jams pÄrbaudÄ«t.
+settings.protect_branch_name_pattern=AizsargÄtÄ zara Å¡ablons
settings.protect_protected_file_patterns=AizsargÄto failu Å¡ablons (vairÄkus var norÄdÄ«t atdalot ar semikolu '\;'):
settings.protect_protected_file_patterns_desc=AizsargÄtie faili, ko nevar mainÄ«t, pat ja lietotÄjam ir tiesÄ«bas veidot jaunus, labot vai dzÄ“st failus Å¡ajÄ atzarÄ. VairÄkus Å¡ablons ir iespÄ“jams norÄdÄ«t atdalot tos ar semikolu ('\;'). SÄ«kÄka informÄcija par Å¡abloniem pieejama <a href="https://pkg.go.dev/github.com/gobwas/glob#Compile">github.com/gobwas/glob</a> dokumentÄcijÄ. PiemÄ“ram, <code>.drone.yml</code>, <code>/docs/**/*.txt</code>.
settings.protect_unprotected_file_patterns=NeaizsargÄto failu Å¡ablons (vairÄkus var norÄdÄ«t atdalot ar semikolu '\;'):
@@ -2065,6 +2233,7 @@ settings.add_protected_branch=IespÄ“jot aizsargÄÅ¡anu
settings.delete_protected_branch=AtspÄ“jot aizsargÄÅ¡anu
settings.update_protect_branch_success=Atzara aizsardzÄ«ba atzaram '%s' tika saglabÄta.
settings.remove_protected_branch_success=Atzara aizsardzība atzaram '%s' tika atspējota.
+settings.remove_protected_branch_failed=NeizdevÄs izdzÄ“st atzara '%s' aizsardzÄ«bu.
settings.protected_branch_deletion=Atspējot atzara aizsardzību
settings.protected_branch_deletion_desc=AtspÄ“jojot atzara aizsardzÄ«bu, ļaus lietotÄjiem ar rakstÄ«Å¡anas tiesÄ«bÄm nosÅ«tÄ«t izmaiņas uz atzaru. Vai turpinÄt?
settings.block_rejected_reviews=Neļaut sapludinÄt izmaiņu pieprasÄ«jumus, kam ir pieprasÄ«tas izmaiņas
@@ -2074,10 +2243,13 @@ settings.block_on_official_review_requests_desc=SapludinÄÅ¡ana nebÅ«s iespÄ“jam
settings.block_outdated_branch=BloÄ·Ä“t sapludinÄÅ¡anau, ja izmaiņu pieprasÄ«jums ir novecojis
settings.block_outdated_branch_desc=SapludinÄÅ¡ana nebÅ«s pieejama, ja atzars bÅ«s atpalicis no bÄzes atzara.
settings.default_branch_desc=NorÄdiet noklusÄ“to repozitorija atzaru izmaiņu pieprasÄ«jumiem un koda revÄ«zijÄm:
+settings.merge_style_desc=SapludinÄÅ¡anas veidi
settings.default_merge_style_desc=NoklusÄ“tais sapludinÄÅ¡anas veids izmaiņu pieprasÄ«jumiem:
settings.choose_branch=Izvēlieties atzaru…
settings.no_protected_branch=Nav neviena aizsargÄtÄ atzara.
settings.edit_protected_branch=Labot
+settings.protected_branch_required_rule_name=Nav norÄdÄ«ts noteikuma nosaukums
+settings.protected_branch_duplicate_rule_name=Dublējošs noteikuma nosaukumu
settings.protected_branch_required_approvals_min=Pieprasīto recenziju skaits nevar būt negatīvs.
settings.tags=Tagi
settings.tags.protection=Tagu aizsargÄÅ¡ana
@@ -2093,7 +2265,6 @@ settings.bot_token=Bota talons
settings.chat_id=Tērzēšanas ID
settings.matrix.homeserver_url=MÄjas servera URL
settings.matrix.room_id=Istabas ID
-settings.matrix.access_token=Piekļuves talons
settings.matrix.message_type=Ziņas veids
settings.archive.button=Arhivēt
settings.archive.header=Arhivēt repozitoriju
@@ -2211,6 +2382,8 @@ release.edit_subheader=Laidieni palīdz organizēt projekta versijas.
release.tag_name=Taga nosaukums
release.target=MÄ“rÄ·is
release.tag_helper=Izvēlieties jau esošu tagu vai izveidojiet jaunu.
+release.tag_helper_new=Jauns tags. Šis tags tiks izveidots no mērķa.
+release.tag_helper_existing=Esošs tags.
release.title=Virsraksts
release.content=Saturs
release.prerelease_desc=AtzÄ«mÄ“t kÄ pirmslaidiena versiju
@@ -2234,6 +2407,8 @@ release.downloads=LejupielÄdes
release.download_count=LejupielÄdes: %s
release.add_tag_msg=Izmantot laidiena nosaukumu un saturu kÄ taga aprakstu.
release.add_tag=Izveidot tikai tagu
+release.releases_for=Repozitorja %s laidieni
+release.tags_for=Repozitorija %s tagi
branch.name=Atzara nosaukums
branch.search=Meklēt atzarus
@@ -2292,8 +2467,9 @@ org_full_name_holder=OrganizÄcijas pilnais nosaukums
org_name_helper=OrganizÄciju nosaukumiem vÄ“lams bÅ«t Ä«siem un tÄdiem, ko viegli atcerÄ“ties.
create_org=Izveidot organizÄciju
repo_updated=AtjauninÄts
-people=Personas
+members=Dalībnieki
teams=Komandas
+code=Kods
lower_members=dalībnieki
lower_repositories=repozitoriji
create_new_team=Jauna komanda
@@ -2378,6 +2554,8 @@ teams.members=Komandas biedri
teams.update_settings=SaglabÄt iestatÄ«jumus
teams.delete_team=Dzēst komandu
teams.add_team_member=Pievienot komandas biedru
+teams.invite_team_member=`UzaicinÄt komandÄ "%s"`
+teams.invite_team_member.list=NeapstiprinÄtie uzaicinÄjumi
teams.delete_team_title=Dzēst komandu
teams.delete_team_desc=DzÄ“Å¡ot komandu, tÄs biedri var zaudÄ“t piekļuvi dažiem vai pat visiem repozitorijiem. Vai turpinÄt?
teams.delete_team_success=Komanda tika izdzēsta.
@@ -2402,6 +2580,9 @@ teams.all_repositories_helper=Šai komandai ir piekļuve visiem repozitorijiem.
teams.all_repositories_read_permission_desc=Å Ä« komanda pieÅ¡Ä·irt <strong>skatÄ«Å¡anÄs</strong> tiesÄ«bas <strong>visiem repozitorijiem</strong>: komandas biedri var skatÄ«ties un klonÄ“t visus organizÄcijas repozitorijus.
teams.all_repositories_write_permission_desc=Å Ä« komanda pieÅ¡Ä·irt <strong>laboÅ¡anas</strong> tiesÄ«bas <strong>visiem repozitorijiem</strong>: komandas biedri var skatÄ«ties un nosÅ«tÄ«t izmaiņas visiem organizÄcijas repozitorijiem.
teams.all_repositories_admin_permission_desc=Å Ä« komanda pieÅ¡Ä·irt <strong>administratora</strong> tiesÄ«bas <strong>visiem repozitorijiem</strong>: komandas biedri var skatÄ«ties, nosÅ«tÄ«t izmaiņas un mainÄ«t iestatÄ«jumus visiem organizÄcijas repozitorijiem.
+teams.invite.title=JÅ«s esat uzaicinÄts pievienoties komandai <strong>%s</strong> organizÄcijÄ <strong>%s</strong>.
+teams.invite.by=UzaicinÄja %s
+teams.invite.description=Nospiediet pogu zemÄk, lai pievienotos komandai.
[admin]
dashboard=Infopanelis
@@ -2495,6 +2676,10 @@ dashboard.delete_old_actions=DzÄ“st visas darbÄ«bas no datu bÄzes
dashboard.delete_old_actions.started=UzsÄkta visu novecojuÅ¡o darbÄ«bu dzÄ“Å¡ana no datu bÄzes.
dashboard.update_checker=AtjauninÄjumu pÄrbaudÄ«tÄjs
dashboard.delete_old_system_notices=DzÄ“st vecos sistÄ“mas paziņojumus no datubÄzes
+dashboard.gc_lfs=Veikt atkritumu uzkopšanas darbus LFS meta objektiem
+dashboard.stop_zombie_tasks=Apturēt zombija uzdevumus
+dashboard.stop_endless_tasks=ApturÄ“t nepÄrtrauktus uzdevumus
+dashboard.cancel_abandoned_jobs=Atcelt pamestus darbus
users.user_manage_panel=LietotÄju kontu pÄrvaldÄ«ba
users.new_account=Izveidot lietotÄja kontu
@@ -2583,6 +2768,7 @@ repos.size=Izmērs
packages.package_manage_panel=Pakotņu pÄrvaldÄ«ba
packages.total_size=Kopējais izmērs: %s
+packages.unreferenced_size=Izmērs bez atsauces: %s
packages.owner=Īpašnieks
packages.creator=IzveidotÄjs
packages.name=Nosaukums
@@ -2676,6 +2862,8 @@ auths.oauth2_required_claim_value_helper=UzstÄdiet Å¡o vÄ“rtÄ«bu, lai ierobežo
auths.oauth2_group_claim_name=PrasÄ«bas nosaukums, kas nodroÅ¡ina grupu nosaukumus Å¡im avotam. (NeobligÄts)
auths.oauth2_admin_group=Grupas prasÄ«bas vÄ“rtÄ«ba administratoriem. (NeobligÄta - nepiecieÅ¡ams prasÄ«bas nosaukums augstÄk)
auths.oauth2_restricted_group=Grupas prasÄ«bas vÄ“rtÄ«ba ierobežotajiem lietotÄjiem. (NeobligÄta - nepiecieÅ¡ams prasÄ«bas nosaukums augstÄk)
+auths.oauth2_map_group_to_team=SasaistÄ«t prasÄ«bas grupas ar organizÄcijas komandÄm. (NeobligÄts - nepiecieÅ¡ams prasÄ«bas nosaukums augstÄk)
+auths.oauth2_map_group_to_team_removal=Noņemt lietotÄjus no sinhronizÄ“tajÄm komandÄm, ja lietotÄjs nav piesaistÄ«ts attiecÄ«gajai grupai.
auths.enable_auto_register=IespÄ“jot automÄtisko reÄ£istrÄciju
auths.sspi_auto_create_users=AutomÄtiski izveidot lietotÄjus
auths.sspi_auto_create_users_helper=Ä»auj SSPI autentifikÄcijas metodei automÄtiski izveidot jaunus kontus lietotÄjiem, kas autorizÄ“jas pirmo reizi
@@ -2692,9 +2880,9 @@ auths.tips.oauth2.general=OAuth2 autentifikÄcija
auths.tips.oauth2.general.tip=ReÄ£istrÄ“jot jaunu OAuth2 autentifikÄciju, atsauces/pÄrsÅ«tÄ«Å¡anas URL ir jÄbÅ«t: <host>/user/oauth2/<Authentication Name>/callback
auths.tip.oauth2_provider=OAuth2 pakalpojuma sniedzējs
auths.tip.bitbucket=ReÄ£istrÄ“jiet jaunu OAuth klientu adresÄ“ https://bitbucket.org/account/user/<jÅ«su lietotÄjvÄrds>/oauth-consumers/new un pieÅ¡Ä·iriet tam "Account" - "Read" tiesÄ«bas
-auths.tip.nextcloud=ReÄ£istrÄ“jiet jaunu OAuth klientu jÅ«su instances sadÄÄ¼Ä "Settings -> Security -> OAuth 2.0 client"
+auths.tip.nextcloud=`ReÄ£istrÄ“jiet jaunu OAuth klientu jÅ«su instances sadÄÄ¼Ä "Settings -> Security -> OAuth 2.0 client"`
auths.tip.dropbox=Izveidojiet jaunu aplikÄciju adresÄ“ https://www.dropbox.com/developers/apps
-auths.tip.facebook=ReÄ£istrÄ“jiet jaunu aplikÄciju adresÄ“ https://developers.facebook.com/apps un pievienojiet produktu "Facebook Login"
+auths.tip.facebook=`ReÄ£istrÄ“jiet jaunu aplikÄciju adresÄ“ https://developers.facebook.com/apps un pievienojiet produktu "Facebook Login"`
auths.tip.github=ReÄ£istrÄ“jiet jaunu aplikÄciju adresÄ“ https://github.com/settings/applications/new
auths.tip.gitlab=ReÄ£istrÄ“jiet jaunu aplikÄciju adresÄ“ https://gitlab.com/profile/applications
auths.tip.google_plus=Iegūstiet OAuth2 klienta pilnvaru no Google API konsoles adresē https://console.developers.google.com/
@@ -2702,7 +2890,7 @@ auths.tip.openid_connect=Izmantojiet OpenID pieslÄ“gÅ¡anÄs atklÄÅ¡anas URL (<s
auths.tip.twitter=Dodieties uz adresi https://dev.twitter.com/apps, izveidojiet aplikÄciju un pÄrliecinieties, ka ir atzÄ«mÄ“ts “Allow this application to be used to Sign in with Twitterâ€
auths.tip.discord=ReÄ£istrÄ“jiet jaunu aplikÄciju adresÄ“ https://discordapp.com/developers/applications/me
auths.tip.gitea=ReÄ£istrÄ“t jaunu OAuth2 lietojumprogrammu. PamÄcÄ«bu iespÄ“jams atrast https://docs.gitea.io/en-us/oauth2-provider/
-auths.tip.yandex=Izveidojiet jaunu aplikÄciju adresÄ“ https://oauth.yandex.com/client/new. IzvÄ“lieties sekojoÅ¡as tiesÄ«bas "Yandex.Passport API" sadaļÄ: "Access to email address", "Access to user avatar" un "Access to username, first name and surname, gender"
+auths.tip.yandex=`Izveidojiet jaunu aplikÄciju adresÄ“ https://oauth.yandex.com/client/new. IzvÄ“lieties sekojoÅ¡as tiesÄ«bas "Yandex.Passport API" sadaļÄ: "Access to email address", "Access to user avatar" un "Access to username, first name and surname, gender"`
auths.tip.mastodon=NorÄdiet pielÄgotu mastodon instances URL, ar kuru vÄ“laties autorizÄ“ties (vai izmantojiet noklusÄ“to)
auths.edit=Labot autentifikÄcijas avotu
auths.activated=AutentifikÄcijas avots ir atkivizÄ“ts
@@ -2716,6 +2904,8 @@ auths.still_in_used=Å o autentificÄ“Å¡anÄs avotu joprojÄm izmanto viens vai va
auths.deletion_success=AutentifikÄcijas avots tika atjaunots.
auths.login_source_exist=AutentifikÄcijas avots ar nosaukumu '%s' jau eksistÄ“.
auths.login_source_of_type_exist=AutentifikÄcijas avots ar Å¡Ädu veidu jau eksistÄ“.
+auths.unable_to_initialize_openid=Nevarēja inicializēt OpenID Connect sliedzēju: %s
+auths.invalid_openIdConnectAutoDiscoveryURL=Kļūdains automÄtiskÄs atklÄÅ¡anas URL (jÄbÅ«t korektam URL, kas sÄkas ar http:// vai https://)
config.server_config=Servera konfigurÄcija
config.app_name=Vietnes nosaukums
@@ -2855,6 +3045,8 @@ config.access_log_template=Å ablons
config.xorm_log_mode=XORM žurnalizēšanas veids
config.xorm_log_sql=SQL žurnalizēšana
+config.get_setting_failed=`NeizdevÄs izgÅ«t iestatÄ«jumu "%s"`
+config.set_setting_failed=`NeizdevÄs uzstÄdÄ«t iestatÄ«jumu "%s"`
monitor.cron=Cron uzdevumi
monitor.name=Nosaukums
@@ -2888,6 +3080,7 @@ monitor.queue.nopool.title=Nav strÄdņu pÅ«la
monitor.queue.nopool.desc=Å Ä« rinda apvieno citas rindas un tai nav strÄdņu pÅ«la.
monitor.queue.wrapped.desc=ApvienojoÅ¡Ä rinda apvieno lÄ“ni startÄ“joÅ¡Äs rindas, uzkrÄjot sarindotos pieprasÄ«jumus kanÄlÄ. Tai nav strÄdņu pÅ«la.
monitor.queue.persistable-channel.desc=PatstÄvÄ«gas kanÄli apvieno divas rindas, kanÄla rindu, kurai ir savs strÄdņu pÅ«ls un lÄ«meņu rindu patstÄvÄ«gajiem pieprasÄ«jumiem no iepriekÅ¡ejÄm izslÄ“gÅ¡anÄm. Tai nav strÄdņu pÅ«la.
+monitor.queue.flush=NotÄ«rÄ«t strÄdnes
monitor.queue.pool.timeout=Noildze
monitor.queue.pool.addworkers.title=Pievienot strÄdņus
monitor.queue.pool.addworkers.submit=Pievienot
@@ -2935,7 +3128,7 @@ monitor.queue.pool.cancel_desc=AtstÄjot rindu bez nevienas strÄdņu grupas, va
notices.system_notice_list=Sistēmas paziņojumi
notices.view_detail_header=Skatīt paziņojuma detaļas
-notices.actions=Darbības
+notices.operations=Darbības
notices.select_all=Iezīmēt visu
notices.deselect_all=Atcelt visa iezīmēšanu
notices.inverse_selection=ApgriezeniskÄ iezÄ«mÄ“Å¡ana
@@ -2961,6 +3154,7 @@ reopen_pull_request=`atkÄrtoti atvÄ“ra izmaiņu pieprasÄ«jumu <a href="%[1]s">%
comment_issue=`pievienoja komentÄru problÄ“mai <a href="%[1]s">%[3]s#%[2]s</a>`
comment_pull=`pievienoja komentÄru izmaiņu pieprasÄ«jumam <a href="%[1]s">%[3]s#%[2]s</a>`
merge_pull_request=`sapludinÄja izmaiņu pieprasÄ«jumu <a href="%[1]s">%[3]s#%[2]s</a>`
+auto_merge_pull_request=`automÄtiski sapludinÄja izmaiņu pieprasÄ«jumu <a href="%[1]s">%[3]s#%[2]s</a>`
transfer_repo=mainīja repozitorija <code>%s</code> īpašnieku uz <a href="%s">%s</a>
push_tag=iesÅ«tÄ«ja tagu <a href="%[2]s">%[3]s</a> repozitorijÄ <a href="%[1]s">%[4]s</a>
delete_tag=izdzēsa tagu %[2]s no <a href="%[1]s">%[3]s</a>
@@ -3018,6 +3212,9 @@ pin=Piespraust paziņojumu
mark_as_read=AtzÄ«mÄ“t kÄ izlasÄ«tu
mark_as_unread=AtzÄ«mÄ“t kÄ nelasÄ«tu
mark_all_as_read=AtzÄ«mÄ“t visus kÄ izlasÄ«tus
+subscriptions=Abonementi
+watching=SkatÄs
+no_subscriptions=Nav abonementu
[gpg]
default_key=Parakstīts ar noklusēto atslēgu
@@ -3056,6 +3253,8 @@ keywords=AtslÄ“gvÄrdi
details=Papildu informÄcija
details.author=Autors
details.project_site=Projekta lapa
+details.repository_site=Repozitorija lapa
+details.documentation_site=DokumentÄcijas lapa
details.license=Licence
assets=Resursi
versions=Versijas
@@ -3063,6 +3262,14 @@ versions.on=publicēta
versions.view_all=ParÄdÄ«t visas
dependency.id=ID
dependency.version=Versija
+cargo.registry=UzstÄdiet Å¡o reÄ£istru Cargo konfigurÄcijas failÄ, piemÄ“ram, <code>~/.cargo/config.toml</code>:
+cargo.install=Lai instalētu Cargo pakotni, izpildiet sekojošu komandu:
+cargo.documentation=Papildus informÄcija par Cargo reÄ£istru pieejama <a target="_blank" rel="noopener noreferrer" href="https://docs.gitea.io/en-us/packages/cargo/">dokumentÄcijÄ</a>.
+cargo.details.repository_site=Repozitorija lapa
+cargo.details.documentation_site=DokumentÄcijas lapa
+chef.registry=UzstÄdiet Å¡o reÄ£istru failÄ <code>~/.chef/config.rb</code>:
+chef.install=Lai instalētu pakotni, nepieciešams izpildīt sekojošu komandu:
+chef.documentation=Papildus informÄcija par Chef reÄ£istru pieejama <a target="_blank" rel="noopener noreferrer" href="https://docs.gitea.io/en-us/packages/chef/">dokumentÄcijÄ</a>.
composer.registry=Pievienojiet Å¡o reÄ£istru savÄ <code>~/.composer/config.json</code> failÄ:
composer.install=Lai instalētu Composer pakotni, izpildiet sekojošu komandu:
composer.documentation=Papildus informÄcija par Composer reÄ£istru pieejama <a target="_blank" rel="noopener noreferrer" href="https://docs.gitea.io/en-us/packages/composer/">dokumentÄcijÄ</a>.
@@ -3072,11 +3279,15 @@ conan.details.repository=Repozitorijs
conan.registry=Konfigurējiet šo reģistru no komandrindas:
conan.install=Lai instalētu Conan pakotni, izpildiet sekojošu komandu:
conan.documentation=Papildus informÄcija par Conan reÄ£istru pieejama <a target="_blank" rel="noopener noreferrer" href="https://docs.gitea.io/en-us/packages/conan/">dokumentÄcijÄ</a>.
+conda.registry=UzstÄdiet Å¡o reÄ£istru kÄ Conda repozitoriju failÄ <code>.condarc</code>:
+conda.install=Lai instalētu Conda pakotni, izpildiet sekojošu komandu:
+conda.documentation=Papildus informÄcija par Conda reÄ£istru pieejama <a target="_blank" rel="noopener noreferrer" href="https://docs.gitea.io/en-us/packages/conda/">dokumentÄcijÄ</a>.
+conda.details.repository_site=Repozitorija lapa
+conda.details.documentation_site=DokumentÄcijas lapa
container.details.type=AttÄ“la formÄts
container.details.platform=Platforma
-container.details.repository_site=Repozitorija lapa
-container.details.documentation_site=DokumentÄcijas lapa
container.pull=AtgÄdÄjiet Å¡o attÄ“lu no komandrindas:
+container.digest=Īssavilkums:
container.documentation=Papildus informÄcija par konteineru reÄ£istru pieejama <a target="_blank" rel="noopener noreferrer" href="https://docs.gitea.io/en-us/packages/container/">dokumentÄcijÄ</a>.
container.multi_arch=OS / arhitektūra
container.layers=AttÄ“la slÄņi
@@ -3108,8 +3319,6 @@ npm.dependencies.optional=NeobligÄtÄs atkarÄ«bas
npm.details.tag=Tags
pub.install=Lai instalētu Dart pakotni, izpildiet sekojošu komandu:
pub.documentation=Papildus informÄcija par Pub reÄ£istru pieejama <a target="_blank" rel="noopener noreferrer" href="https://docs.gitea.io/en-us/packages/pub/">dokumentÄcijÄ</a>.
-pub.details.repository_site=Repozitorija izmērs
-pub.details.documentation_site=DokumentÄcijas lapa
pypi.requires=Nepieciešams Python
pypi.install=Lai instalētu pip pakotni, izpildiet sekojošu komandu:
pypi.documentation=Papildus informÄcija par PyPI reÄ£istru pieejama <a target="_blank" rel="noopener noreferrer" href="https://docs.gitea.io/en-us/packages/pypi/">dokumentÄcijÄ</a>.
@@ -3120,6 +3329,8 @@ rubygems.dependencies.development=IzstrÄdes atkarÄ«bas
rubygems.required.ruby=NepiecieÅ¡amÄ Ruby versija
rubygems.required.rubygems=NepiecieÅ¡amÄ RubyGem versija
rubygems.documentation=Papildus informÄcija par RubyGems reÄ£istru pieejama <a target="_blank" rel="noopener noreferrer" href="https://docs.gitea.io/en-us/packages/rubygems/">dokumentÄcijÄ</a>.
+vagrant.install=Lai pievienotu Vagrant kasti, izpildiet sekojošu komandu:
+vagrant.documentation=Papildus informÄcija par Vagrant reÄ£istru pieejama <a target="_blank" rel="noopener noreferrer" href="https://docs.gitea.io/en-us/packages/vagrant/">dokumentÄcijÄ</a>.
settings.link=Piesaistīt pakotni šim repozitorijam
settings.link.description=Sasaistot pakotni ar repozitoriju, tÄ tiks attÄ“lota repozitorija pakotņu sarakstÄ.
settings.link.select=NorÄdiet repozitoriju
@@ -3131,4 +3342,110 @@ settings.delete.description=Pakotne tiks neatgriezeniski izdzēsta.
settings.delete.notice=Tiks dzÄ“sts %s (%s). Å Ä« darbÄ«ba ir neatgriezeniska. Vai vÄ“laties turpinÄt?
settings.delete.success=Pakotne tika izdzēsta.
settings.delete.error=NeizdevÄs izdzÄ“st pakotni.
+owner.settings.cargo.title=Cargo reģistra inkdess
+owner.settings.cargo.initialize=Inicializēt indeksu
+owner.settings.cargo.initialize.description=Lai izmantotu Cargo reÄ£istru, nepiecieÅ¡ams speciÄls indeksa git repozitorijs. Å eit to var izveidot ar nepiecieÅ¡amo konfigurÄciju.
+owner.settings.cargo.initialize.error=NeizdevÄs inicializÄ“t Cargo indeksu: %v
+owner.settings.cargo.initialize.success=Cargo indekss tika veiksmīgi inicializēts.
+owner.settings.cargo.rebuild=PÄrbÅ«vÄ“t indeksu
+owner.settings.cargo.rebuild.description=Ja indekss neatbilst tajÄ saglabÄtajÄm Cargo pakotnÄ“, to var pÄrbÅ«vÄ“t Å¡eit.
+owner.settings.cargo.rebuild.error=NeizdevÄs pÄrbÅ«vÄ“t Cargo indeksu: %v
+owner.settings.cargo.rebuild.success=Cargo indekss tika veiksmÄ«gi pÄrbÅ«vÄ“ts.
+owner.settings.cleanuprules.title=PÄrvaldÄ«t notÄ«rÄ«Å¡anas noteikumus
+owner.settings.cleanuprules.add=Pievienot notīrīšanas noteikumu
+owner.settings.cleanuprules.edit=Labot notīrīšanas noteikumu
+owner.settings.cleanuprules.none=Nav pieejams neviens notÄ«rÄ«Å¡anas noteikums. SÄ«kÄka informÄcija ir pieejama dokumentÄcijÄ.
+owner.settings.cleanuprules.preview=NotÄ«rÄ«Å¡Änas noteikuma priekÅ¡skatÄ«jums
+owner.settings.cleanuprules.preview.overview=Ir ieplÄnota %d paku dzÄ“Å¡ana.
+owner.settings.cleanuprules.preview.none=Notīrīšanas noteikumam neatbilst neviena pakotne.
+owner.settings.cleanuprules.enabled=Iespējots
+owner.settings.cleanuprules.pattern_full_match=Piešķirt šablonu visam pakotnes nosaukumam
+owner.settings.cleanuprules.keep.title=Versijas, kas atbilst Å¡iem noteikumiem tiks saglabÄtas, pat ja tÄs atbilst noņemÅ¡anas noteikumiem zemÄk.
+owner.settings.cleanuprules.keep.count=SaglabÄt jaunÄko versiju
+owner.settings.cleanuprules.keep.count.1=1 versija katrai pakotnei
+owner.settings.cleanuprules.keep.count.n=%d versijas katrai pakotnei
+owner.settings.cleanuprules.keep.pattern=Paturēt versijas, kas atbilst
+owner.settings.cleanuprules.keep.pattern.container=Versija <code>latest</code> vienmēr tiks paturēta konteineru pakotnēm.
+owner.settings.cleanuprules.remove.title=Versijas, kas atbilst Å¡iem noteikumiem tiks noņemtas, ja vien neatbilst arÄ« noteikumiem augstÄk, lai tÄs paturÄ“tu.
+owner.settings.cleanuprules.remove.days=Noņemt versijas vecÄkas kÄ
+owner.settings.cleanuprules.remove.pattern=Noņemt versijas, kas atbilst
+owner.settings.cleanuprules.success.update=Notīrīšanas noteikumi tika atjaunoti.
+owner.settings.cleanuprules.success.delete=Notīrīšanas noteikumi tika izdzēsti.
+owner.settings.chef.title=Chef reģistrs
+owner.settings.chef.keypair=Ä¢enerÄ“t atslÄ“gu pÄri
+owner.settings.chef.keypair.description=Ä¢enerÄ“t atslÄ“gu pÄri, ko izmantot, lai autentificÄ“tos pret Chef reÄ£istru. IepriekÅ¡Ä“jo atslÄ“gu vairs nevarÄ“s izmantot.
+
+[secrets]
+secrets=Noslēpumi
+description=NoslÄ“pumi tiks padoti atseviÅ¡Ä·Äm darbÄ«bÄm un citÄdi nevar tikt nolasÄ«ti.
+none=PagaidÄm nav neviena noslÄ“puma.
+value=Vērtība
+name=Nosaukums
+creation=Pievienot noslēpumu
+creation.name_placeholder=reÄ£istr-nejÅ«tÄ«gs, tikai burti, cipari un apakÅ¡svÄ«tras, nevar sÄkties ar GITEA_ vai GITHUB_
+creation.value_placeholder=Ievadiet jebkÄdu saturu. Atstarpes sÄkumÄ un beigÄ tiks noņemtas.
+creation.success=Noslēpums '%s' tika pievienots.
+creation.failed=NeizdevÄs pievienot noslÄ“pumu.
+deletion=Dzēst noslēpumu
+deletion.description=NoslÄ“puma dzÄ“Å¡ana ir neatgriezeniska. Vai turpinÄt?
+deletion.success=Noslēpums tika izdzēsts.
+deletion.failed=NeizdevÄs dzÄ“st noslÄ“pumu.
+
+[actions]
+actions=Darbības
+
+unit.desc=PÄrvaldÄ«t darbÄ«bas
+
+status.unknown=NezinÄms
+status.waiting=Gaida
+status.running=IzpildÄs
+status.success=Pabeigts
+status.failure=Neveiksmīgs
+status.cancelled=Atcelts
+status.skipped=Izlaists
+status.blocked=BloÄ·Ä“ts
+
+runners=IzpildÄ«tÄji
+runners.runner_manage_panel=IzpildÄ«tÄju pÄrvaldÄ«ba
+runners.new=Pievienot jaunu izpildÄ«tÄju
+runners.new_notice=KÄ uzstÄdÄ«t izpildÄ«tÄju
+runners.status=Statuss
+runners.id=ID
+runners.name=Nosaukums
+runners.owner_type=Veids
+runners.description=Apraksts
+runners.labels=EtiÄ·etes
+runners.last_online=Pēdējo reizi tiešsaistē
+runners.agent_labels=AÄ£enta etiÄ·etes
+runners.custom_labels=PielÄgotas etiÄ·etes
+runners.custom_labels_helper=PielÄgotas etiÄ·etes, ko administrators pievienojis manuÄli. Ar komatu atdalÄ«tas etiÄ·etes, atstapres pirms un pÄ“c etiÄ·etes nosaukuma tiek ignorÄ“tas.
+runners.runner_title=IzpildÄ«tÄjs
+runners.task_list=PÄ“dÄ“jÄs darbÄ«bas, kas izpildÄ«tas
+runners.task_list.run=Palaist
+runners.task_list.status=Statuss
+runners.task_list.repository=Repozitorijs
+runners.task_list.commit=Revīzija
+runners.task_list.done_at=Beigu laiks
+runners.edit_runner=Labot izpildÄ«tÄju
+runners.update_runner=Atjaunot izpildÄ«tÄju
+runners.update_runner_success=IzpildÄ«tÄjs veiksmÄ«gi atjaunots
+runners.update_runner_failed=NeizdevÄs atjaunot izpildÄ«tÄju
+runners.delete_runner=DzÄ“st izpildÄ«tÄju
+runners.delete_runner_success=IzpildÄ«tÄjs veiksmÄ«gi izdzÄ“sts
+runners.delete_runner_failed=NeizdevÄs izdzÄ“st izpildÄ«tÄju
+runners.delete_runner_header=ApstiprinÄt izpildÄ«tÄja izdzÄ“Å¡anu
+runners.delete_runner_notice=Ja Å¡is izpildÄ«tÄjs veic kÄdus uzdevumus, tad tie tiks apturÄ“ti un atzÄ«mÄ“ti kÄ neizdevuÅ¡ies. Tas var sabojÄt bÅ«vÄ“Å¡anas darbaplÅ«smas.
+runners.none=Nav pieejami izpildÄ«tÄji
+runners.status.unspecified=NezinÄms
+runners.status.idle=DÄ«kstÄvÄ“
+runners.status.active=Aktīvs
+runners.status.offline=Bezsaistē
+
+runs.all_workflows=Visas darbaplūsmas
+runs.open_tab=%d atvērti
+runs.closed_tab=%d aizvērti
+runs.commit=Revīzija
+runs.pushed_by=IesÅ«tÄ«tÄjs
+
+need_approval_desc=NepiecieÅ¡ams apstiprinÄjums, lai izpildÄ«tu izmaiņu pieprasÄ«jumu darbaplÅ«smas no atdalÄ«tiem repozitorijiem.
diff --git a/options/locale/locale_ml-IN.ini b/options/locale/locale_ml-IN.ini
deleted file mode 100644
index 0b91ce8fa..000000000
--- a/options/locale/locale_ml-IN.ini
+++ /dev/null
@@ -1,804 +0,0 @@
-home=പൂമàµà´–à´‚
-dashboard=ഡാഷàµà´¬àµ‡à´¾àµ¼à´¡àµ
-explore=à´•à´£àµà´Ÿàµ†à´¤àµà´¤àµ‚
-help=സഹായം
-sign_in=à´ªàµà´°à´µàµ‡à´¶à´¿à´•àµà´•àµà´•
-sign_in_with=ഉപയോഗിചàµà´šàµàµ à´ªàµà´°à´µàµ‡à´¶à´¿à´¯àµà´•àµà´•àµà´•
-sign_out=à´ªàµà´±à´¤àµà´¤àµà´•à´Ÿà´•àµà´•àµà´•
-sign_up=രജിസàµà´±àµà´±àµ¼
-link_account=à´…à´•àµà´•àµŒà´£àµà´Ÿàµ ബനàµà´§à´¿à´ªàµà´ªà´¿à´¯àµà´•àµà´•àµà´•
-register=രജിസàµà´±àµà´±àµ¼
-version=പതിപàµà´ªàµ
-page=പേജàµ
-template=ടെംപàµà´²àµ‡à´±àµà´±àµ
-language=ഭാഷ
-notifications=അറിയിപàµà´ªàµà´•àµ¾
-create_new=സൃഷàµà´Ÿà´¿à´•àµà´•àµà´•â€¦
-user_profile_and_more=à´ªàµà´°àµŠà´«àµˆà´²àµà´‚ à´•àµà´°à´®àµ€à´•à´°à´£à´™àµà´™à´³àµà´‚…
-signed_in_as=ഇയാളായി à´ªàµà´°à´µàµ‡à´¶à´¿à´¯àµà´•àµà´•àµà´•
-enable_javascript=à´ˆ വെബàµâ€Œà´¸àµˆà´±àµà´±àµ ജാവാസàµà´•àµà´°à´¿à´ªàµà´±àµà´±à´¿à´¨àµŠà´ªàµà´ªà´‚ മികചàµà´š രീതിയിൽ à´ªàµà´°à´µàµ¼à´¤àµà´¤à´¿à´•àµà´•àµà´¨àµà´¨àµ.
-
-username=ഉപയോകàµà´¤àµà´°àµ നാമം
-email=ഈമെയിലàµâ€ വിലാസം
-password=രഹസàµà´¯à´µà´¾à´•àµà´•àµàµ
-re_type=രഹസàµà´¯à´µà´¾à´•àµà´•àµàµ വീണàµà´Ÿàµà´‚ നലàµâ€à´•àµà´•
-captcha=à´•àµà´¯à´¾à´ªàµà´š
-twofa=ഇരടàµà´Ÿ ഘടക à´ªàµà´°à´¾à´®à´¾à´£àµ€à´•à´°à´£à´‚
-twofa_scratch=ഇരടàµà´Ÿ ഫാകàµà´Ÿàµ¼ à´¸àµà´•àµà´°à´¾à´šàµà´šàµ കോഡàµ
-passcode=രഹസàµà´¯ കോഡàµ
-
-
-repository=കലവറ
-organization=സംഘടന
-mirror=മിറരàµâ€
-new_repo=à´ªàµà´¤à´¿à´¯ കലവറ
-new_migrate=à´ªàµà´¤à´¿à´¯ à´•àµà´Ÿà´¿à´¯àµ‡à´±àµà´±à´¿à´ªàµà´ªà´¾à´°àµâ€à´ªàµà´ªà´¿à´•àµà´•à´²àµâ€
-new_mirror=à´ªàµà´¤à´¿à´¯ മിറരàµâ€
-new_fork=കലവറയàµà´Ÿàµ† à´ªàµà´¤à´¿à´¯ ശിഖരം
-new_org=à´ªàµà´¤à´¿à´¯ സംഘടന
-manage_org=സംഘടനകളെ നിയനàµà´¤àµà´°à´¿à´•àµà´•àµà´•
-admin_panel=സൈറàµà´±à´¿à´¨àµà´±àµ† കാരàµà´¯à´¨à´¿à´°àµâ€à´µàµà´µà´¾à´¹à´£à´‚
-account_settings=à´…à´•àµà´•àµŒà´£àµà´Ÿàµ à´•àµà´°à´®àµ€à´•à´°à´£à´™à´³àµâ€
-settings=à´•àµà´°à´®àµ€à´•à´°à´£à´™àµà´™à´³àµâ€
-your_profile=à´ªàµà´°àµŠà´«àµˆàµ½
-your_starred=നകàµà´·à´¤àµà´° à´šà´¿à´¹àµà´¨à´®à´¿à´Ÿàµà´Ÿà´µ
-your_settings=à´•àµà´°à´®àµ€à´•à´°à´£à´™àµà´™à´³àµâ€
-
-all=à´Žà´²àµà´²à´¾à´‚
-sources=ഉറവിടങàµà´™àµ¾
-mirrors=മിററàµà´•à´³àµâ€
-collaborative=സഹകരികàµà´•àµà´¨àµà´¨
-forks=ശാഖകളàµâ€
-
-activities=à´ªàµà´°à´µà´°àµâ€à´¤àµà´¤à´¨à´™àµà´™à´³àµâ€
-pull_requests=ലയന à´…à´­àµà´¯àµ¼à´¤àµà´¥à´¨à´•àµ¾
-issues=à´ªàµà´°à´¶àµà´¨à´™àµà´™àµ¾
-
-cancel=റദàµà´¦à´¾à´•àµà´•àµà´•
-
-
-write=à´Žà´´àµà´¤àµà´•
-preview=തിരനോടàµà´Ÿà´‚
-loading=ലഭàµà´¯à´®à´¾à´•àµà´•àµà´¨àµà´¨àµâ€¦
-
-
-
-
-
-[filter]
-
-[error]
-
-[startpage]
-
-[install]
-install=സനàµà´¨à´¿à´µàµ‡à´¶à´¿à´ªàµà´ªà´¿à´¯àµà´•àµà´•àµà´•
-title=à´ªàµà´°à´¾à´°à´‚à´­ à´•àµà´°à´®àµ€à´•à´°à´£à´™àµà´™à´³àµâ€
-docker_helper=ഡോകàµà´•à´±à´¿à´¨àµà´³àµà´³à´¿à´²à´¾à´£àµ à´—à´¿à´±àµà´±àµ€ à´ªàµà´°à´µà´°àµâ€à´¤àµà´¤à´¿à´ªàµà´ªà´¿à´¯àµà´•àµà´•àµà´¨àµà´¨à´¤àµ†à´™àµà´•à´¿à´²àµâ€, മാറàµà´±à´™àµà´™à´³àµâ€ വരàµà´¤àµà´¤àµà´¨àµà´¨à´¤à´¿à´¨àµ à´®àµà´®àµà´ªàµàµ ദയവായി <a target="_blank" rel="noopener noreferrer" href="%s">ഡോകàµà´¯àµà´®àµ†à´¨àµà´±àµ‡à´·àµ»</a> വായിയàµà´•àµà´•àµà´•.
-db_title=ഡാറàµà´±à´¾à´¬àµ‡à´¸àµ à´•àµà´°à´®àµ€à´•à´°à´£à´™àµà´™àµ¾
-db_type=ഡാറàµà´±à´¾à´¬àµ‡à´¸à´¿à´¨àµà´±àµ† തരം
-host=ഹോസàµà´±àµà´±àµ
-user=ഉപയോകàµà´¤àµà´°àµ നാമം
-password=രഹസàµà´¯à´µà´¾à´•àµà´•àµàµ
-db_name=ഡാറàµà´±à´¾à´¬àµ‡à´¸à´¿à´¨àµà´±àµ† പേരàµ
-db_helper=MySQL ഉപയോകàµà´¤à´¾à´•àµà´•àµ¾à´•àµà´•àµà´³àµà´³ à´•àµà´±à´¿à´ªàµà´ªàµ: ദയവായി InnoDB à´¸àµà´±àµà´±àµ‹à´±àµ‡à´œàµ à´Žà´žàµà´šà´¿àµ» ഉപയോഗികàµà´•àµà´•. നിങàµà´™àµ¾ "utf8mb4" ഉപയോഗികàµà´•àµà´•à´¯à´¾à´£àµ†à´™àµà´•à´¿àµ½, InnoDB പതിപàµà´ªàµ 5.6 നേകàµà´•à´¾àµ¾ വലàµà´¤à´¾à´¯à´¿à´°à´¿à´•àµà´•à´£à´‚.
-ssl_mode=SSL
-charset=à´•àµà´¯à´¾à´°àµâ€à´¸àµ†à´±àµà´±àµ
-path=പാത
-sqlite_helper=SQLite3 ഡാറàµà´±à´¾à´¬àµ‡à´¸à´¿à´¨àµà´±àµ† ഫയലàµâ€ പാതàµà´¤àµ.<br>നിങàµà´™àµ¾ à´—à´¿à´±àµà´±àµ€à´¯àµ† ഒരൠസേവനമായി à´ªàµà´°à´µàµ¼à´¤àµà´¤à´¿à´ªàµà´ªà´¿à´•àµà´•àµà´•à´¯à´¾à´£àµ†à´™àµà´•à´¿àµ½ സമàµà´ªàµ‚à´°àµâ€à´£àµà´£ ഫയലàµâ€ പാത നൽകàµà´•.
-err_empty_db_path=SQLite3 ഡാറàµà´±à´¾à´¬àµ‡à´¸àµ പാതàµà´¤àµ ശൂനàµà´¯à´®à´¾à´¯à´¿à´°à´¿à´•àµà´•à´°àµà´¤àµ.
-no_admin_and_disable_registration=ഒരൠഅഡàµà´®à´¿à´¨à´¿à´¸àµà´Ÿàµà´°àµ‡à´±àµà´±àµ¼ à´…à´•àµà´•àµŒà´£àµà´Ÿàµ സൃഷàµà´Ÿà´¿à´•àµà´•à´¾à´¤àµ† നിങàµà´™àµ¾à´•àµà´•àµ ഉപയോകàµà´¤àµƒ à´¸àµà´µà´¯à´‚ രജിസàµà´Ÿàµà´°àµ‡à´·àµ» à´…à´ªàµà´°à´¾à´ªàµà´¤à´®à´¾à´•àµà´•à´¾àµ» കഴിയിലàµà´².
-err_empty_admin_password=à´…à´¡àµà´®à´¿à´¨à´¿à´¸àµà´Ÿàµà´°àµ‡à´±àµà´±à´±àµà´Ÿàµ† രഹസàµà´¯à´µà´¾à´•àµà´•àµàµ ശൂനàµà´¯à´®à´¾à´¯à´¿à´°à´¿à´•àµà´•à´°àµà´¤àµ.
-err_empty_admin_email=à´…à´¡àµà´®à´¿à´¨à´¿à´¸àµà´Ÿàµà´°àµ‡à´±àµà´±à´±àµà´Ÿàµ† ഇമെയിലàµâ€ വിലാസം ശൂനàµà´¯à´®à´¾à´¯à´¿à´°à´¿à´•àµà´•à´°àµà´¤àµ.
-err_admin_name_is_reserved=à´…à´¡àµà´®à´¿à´¨à´¿à´¸àµà´Ÿàµà´°àµ‡à´±àµà´±à´°àµâ€ ഉപയോകàµà´¤àµƒà´¨à´¾à´®à´‚ അസാധàµà´µà´¾à´£àµ, ഉപയോകàµà´¤àµƒà´¨à´¾à´®à´‚ റിസരàµâ€à´µàµà´µàµ ചെയàµà´¤à´¤à´¾à´£àµ
-err_admin_name_is_invalid=à´…à´¡àµà´®à´¿à´¨à´¿à´¸àµà´Ÿàµà´°àµ‡à´±àµà´±àµ¼ ഉപയോകàµà´¤àµƒà´¨à´¾à´®à´‚ അസാധàµà´µà´¾à´£àµ
-
-general_title=പൊതàµà´µà´¾à´¯ à´•àµà´°à´®àµ€à´•à´°à´£à´™àµà´™àµ¾
-app_name=സൈറàµà´±àµ ശീർഷകം
-app_name_helper=നിങàµà´™à´³àµà´Ÿàµ† à´•à´®àµà´ªà´¨à´¿à´¯àµà´Ÿàµ† പേരൠഇവിടെ നൽകാം.
-repo_path=സംഭരണിയàµà´Ÿàµ† റൂടàµà´Ÿàµ പാതàµà´¤àµ
-repo_path_helper=വിദൂര à´—à´¿à´±àµà´±àµàµ സംഭരണികളàµâ€ à´ˆ ഡയറകàµà´Ÿà´±à´¿à´¯à´¿à´²àµ‡à´•àµà´•àµ സംരകàµà´·à´¿à´•àµà´•àµà´‚.
-lfs_path=Git LFS റൂടàµà´Ÿàµ പാതàµà´¤àµ
-lfs_path_helper=Git LFS à´Ÿàµà´°à´¾à´•àµà´•àµà´šàµ†à´¯àµà´¤ ഫയലàµà´•àµ¾ à´ˆ ഡയറകàµà´Ÿà´±à´¿à´¯à´¿àµ½ സൂകàµà´·à´¿à´•àµà´•àµà´‚. à´ªàµà´°à´µàµ¼à´¤àµà´¤à´¨à´°à´¹à´¿à´¤à´®à´¾à´•àµà´•à´¾àµ» à´ˆ കളം ശൂനàµà´¯à´®à´¾à´¯à´¿ വിടàµà´•.
-run_user=ഉപയോകàµà´¤à´¾à´µà´¾à´¯à´¿ à´ªàµà´°à´µà´°àµâ€à´¤àµà´¤à´¿à´ªàµà´ªà´¿à´•àµà´•àµà´•
-run_user_helper=à´—à´¿à´±àµà´±àµ€ à´ªàµà´°à´µàµ¼à´¤àµà´¤à´¿à´•àµà´•àµà´¨àµà´¨ à´“à´ªàµà´ªà´±àµ‡à´±àµà´±à´¿à´‚ഗൠസിസàµà´±àµà´±à´¤àµà´¤à´¿à´¨àµà´±àµ† ഉപയോകàµà´¤àµƒà´¨à´¾à´®à´‚ നലàµà´•àµà´•. à´ˆ ഉപയോകàµà´¤à´¾à´µà´¿à´¨àµ സംഭരണിയàµà´Ÿàµ† റൂടàµà´Ÿàµ പാതàµà´¤à´¿à´²àµ‡à´•àµà´•àµ à´ªàµà´°à´µàµ‡à´¶à´¨à´‚ ഉണàµà´Ÿà´¾à´¯à´¿à´°à´¿à´•àµà´•à´£à´‚.
-ssh_port=SSH സെർവർ പോരàµâ€à´Ÿàµà´Ÿàµ
-ssh_port_helper=നിങàµà´™à´³àµà´Ÿàµ† SSH സെർവർ à´¶àµà´°à´µà´¿à´•àµà´•àµà´¨àµà´¨ പോർടàµà´Ÿàµ നമàµà´ªàµ¼ നലàµâ€à´•àµà´•. à´ªàµà´°à´µàµ¼à´¤àµà´¤à´¨à´°à´¹à´¿à´¤à´®à´¾à´•àµà´•à´¾àµ» കളം ശൂനàµà´¯à´®à´¾à´¯à´¿ വിടàµà´•.
-http_port=à´—à´¿à´±àµà´±àµ€ à´Žà´šàµà´šàµà´Ÿà´¿à´Ÿà´¿à´ªà´¿ à´¶àµà´°à´µà´¿à´¯àµà´•àµà´•àµà´¨àµà´¨ പോർടàµà´Ÿàµ
-http_port_helper=à´—à´¿à´±àµà´±àµ€ വെബൠസെർവർ à´¶àµà´°à´µà´¿à´¯àµà´•àµà´•àµà´¨àµà´¨ പോർടàµà´Ÿàµ നമàµà´ªàµ¼.
-app_url=à´—à´¿à´±àµà´±àµ€à´¯àµà´Ÿàµ† à´…à´Ÿà´¿à´¸àµà´¥à´¾à´¨ വിലാസം
-app_url_helper=à´Žà´šàµà´šàµà´Ÿà´¿à´Ÿà´¿à´ªà´¿(à´Žà´¸àµ) à´•àµà´²àµ‹à´£àµà´•à´³àµâ€à´•àµà´•àµà´‚ ഇമെയിൽ അറിയിപàµà´ªàµà´•àµ¾à´•àµà´•àµà´®à´¾à´¯àµà´³àµà´³ à´…à´Ÿà´¿à´¸àµà´¥à´¾à´¨ വിലാസം.
-log_root_path=ലോഗൠപാതàµà´¤àµ
-log_root_path_helper=ലോഗൠഫയലàµà´•àµ¾ à´ˆ ഡയറകàµà´Ÿà´±à´¿à´¯à´¿à´²àµ‡à´•àµà´•àµ à´Žà´´àµà´¤à´ªàµà´ªàµ†à´Ÿàµà´‚.
-
-optional_title=à´à´šàµà´›à´¿à´•à´®à´¾à´¯ à´•àµà´°à´®àµ€à´•à´°à´£à´™àµà´™àµ¾
-email_title=ഇമെയിൽ à´•àµà´°à´®àµ€à´•à´°à´£à´™àµà´™àµ¾
-smtp_from=à´ˆ വിലാസതàµà´¤à´¿à´²àµâ€ ഇമെയിൽ അയയàµâ€Œà´•àµà´•àµà´•
-smtp_from_helper=à´—à´¿à´±àµà´±àµ€ ഉപയോഗിയàµà´•àµà´•àµà´¨àµà´¨ ഇമെയിലàµâ€ വിലാസം. ഒരൠസാധാ ഇമെയിൽ വിലാസം നൽകàµà´• à´…à´²àµà´²àµ†à´™àµà´•à´¿àµ½ "പേരàµ"<email@example.com> à´Žà´¨àµà´¨ ഘടന ഉപയോഗികàµà´•àµà´•.
-mailer_user=SMTP ഉപയോകàµà´¤àµƒà´¨à´¾à´®à´‚
-mailer_password=SMTP രഹസàµà´¯à´µà´¾à´•àµà´•àµàµ
-register_confirm=രജിസàµà´±àµà´±àµ¼ ചെയàµà´¯àµà´¨àµà´¨à´¤à´¿à´¨àµ ഇമെയിൽ à´¸àµà´¥à´¿à´°àµ€à´•à´°à´£à´‚ ആവശàµà´¯à´®à´¾à´•àµà´•àµà´•
-mail_notify=ഇമെയിൽ അറിയിപàµà´ªàµà´•àµ¾ à´ªàµà´°à´¾à´ªàµà´¤à´®à´¾à´•àµà´•àµà´•
-server_service_title=സെർവറിനàµà´±àµ†à´¯àµà´‚ മൂനàµà´¨à´¾à´‚ à´•à´•àµà´·à´¿ സേവനങàµà´™à´³àµà´Ÿàµ†à´¯àµà´‚ à´•àµà´°à´®àµ€à´•à´°à´£à´™àµà´™à´³àµâ€
-offline_mode=à´ªàµà´°à´¾à´¦àµ‡à´¶à´¿à´• മോഡൠപàµà´°à´µàµ¼à´¤àµà´¤à´¨à´•àµà´·à´®à´®à´¾à´•àµà´•àµà´•
-offline_mode_popup=മൂനàµà´¨à´¾à´‚ à´•à´•àµà´·à´¿ ഉളàµà´³à´Ÿà´•àµà´• ഡെലിവറി നെറàµà´±àµâ€Œà´µàµ¼à´•àµà´•àµà´•àµ¾ à´…à´ªàµà´°à´¾à´ªàµâ€Œà´¤à´®à´¾à´•àµà´•à´¿ à´Žà´²àµà´²à´¾ വിഭവങàµà´™à´³àµà´‚ à´ªàµà´°à´¾à´¦àµ‡à´¶à´¿à´•à´®à´¾à´¯à´¿ നലàµâ€à´•àµà´•.
-disable_gravatar=à´—àµà´°à´µà´¤à´¾à´°àµâ€ à´ªàµà´°à´µàµ¼à´¤àµà´¤à´¨à´°à´¹à´¿à´¤à´®à´¾à´•àµà´•àµà´•
-disable_gravatar_popup=à´—àµà´°à´µà´¤à´¾à´°àµâ€ à´…à´²àµà´²àµ†à´™àµà´•à´¿à´²àµâ€ മൂനàµà´¨à´¾à´‚ à´•à´•àµà´·à´¿ അവതാർ ഉറവിടങàµà´™àµ¾ à´ªàµà´°à´µàµ¼à´¤àµà´¤à´¨à´°à´¹à´¿à´¤à´®à´¾à´•àµà´•àµà´•. ഒരൠഉപയോകàµà´¤à´¾à´µàµ à´ªàµà´°à´¾à´¦àµ‡à´¶à´¿à´•à´®à´¾à´¯à´¿ ഒരൠഅവതാർ à´…à´ªàµâ€Œà´²àµ‹à´¡àµà´šàµ†à´¯àµà´¯àµà´¨àµà´¨à´¿à´²àµà´²àµ†à´™àµà´•à´¿àµ½ à´¸àµà´¥à´¿à´°à´¸àµà´¥à´¿à´¤à´¿ അവതാർ ഉപയോഗികàµà´•àµà´‚.
-federated_avatar_lookup=കേനàµà´¦àµà´°àµ€à´•àµƒà´¤ അവതാരàµâ€ à´ªàµà´°à´¾à´ªàµà´¤à´®à´¾à´•àµà´•àµà´•
-federated_avatar_lookup_popup=ലിബàµà´°à´¾à´µà´¤à´¾àµ¼ ഉപയോഗിചàµà´šàµ കേനàµà´¦àµà´°àµ€à´•àµà´°à´¤ അവതാർ തിരയൽ à´ªàµà´°à´¾à´ªàµà´¤à´®à´¾à´•àµà´•àµà´•.
-disable_registration=à´¸àµà´µà´¯à´‚ രജിസàµà´Ÿàµà´°àµ‡à´·àµ» à´…à´ªàµà´°à´¾à´ªàµà´¤à´®à´¾à´•àµà´•àµà´•
-disable_registration_popup=ഉപയോകàµà´¤à´¾à´•àµà´•à´³àµâ€ à´¸àµà´µà´¯à´‚ രജിസàµà´±àµà´±à´°àµâ€ ചെയàµà´¯àµà´¨àµà´¨à´¤àµ à´…à´ªàµà´°à´¾à´ªàµà´¯à´®à´¾à´•àµà´•àµà´•. à´…à´¡àµà´®à´¿à´¨à´¿à´¸àµà´Ÿàµà´°àµ‡à´±àµà´±àµ¼à´®à´¾àµ¼à´•àµà´•àµ മാതàµà´°à´®àµ‡ à´ªàµà´¤à´¿à´¯ ഉപയോകàµà´¤àµƒ à´…à´•àµà´•àµŒà´£àµà´Ÿàµà´•àµ¾ സൃഷàµà´Ÿà´¿à´•àµà´•à´¾à´¨àµâ€ കഴിയൂ.
-allow_only_external_registration_popup=ബാഹàµà´¯ സേവനങàµà´™à´³à´¿à´²àµ‚ടെ മാതàµà´°à´‚ രജിസàµà´Ÿàµà´°àµ‡à´·à´¨àµâ€ à´…à´¨àµà´µà´¦à´¿à´•àµà´•àµà´•
-openid_signin=OpenID à´ªàµà´°à´µàµ‡à´¶à´¨à´‚ à´ªàµà´°à´µàµ¼à´¤àµà´¤à´¨à´•àµà´·à´®à´®à´¾à´•àµà´•àµà´•
-openid_signin_popup=OpenID വഴി ഉപയോകàµà´¤àµƒ à´ªàµà´°à´µàµ‡à´¶à´¨à´‚ à´ªàµà´°à´¾à´ªàµà´¤à´®à´¾à´•àµà´•àµà´•.
-openid_signup=OpenID à´¸àµà´µà´¯à´‚ രജിസàµà´Ÿàµà´°àµ‡à´·àµ» à´ªàµà´°à´¾à´ªàµà´¤à´®à´¾à´•àµà´•àµà´•
-openid_signup_popup=OpenID à´…à´Ÿà´¿à´¸àµà´¥à´¾à´¨à´®à´¾à´•àµà´•à´¿à´¯àµà´³àµà´³ ഉപയോകàµà´¤àµƒ à´¸àµà´µà´¯à´‚ രജിസàµà´Ÿàµà´°àµ‡à´·àµ» à´ªàµà´°à´¾à´ªàµà´¤à´®à´¾à´•àµà´•àµà´•.
-enable_captcha_popup=ഉപയോകàµà´¤à´¾à´•àµà´•à´³àµâ€ à´¸àµà´µà´¯à´‚ രജിസàµà´Ÿàµà´°àµ‡à´·à´¨àµâ€ ചെയàµà´¯àµà´¨àµà´¨à´¤à´¿à´¨àµàµ ഒരൠകàµà´¯à´¾à´ªàµà´š ആവശàµà´¯à´®à´¾à´£àµ.
-require_sign_in_view=പേജàµà´•àµ¾ കാണàµà´¨àµà´¨à´¤à´¿à´¨àµ സൈറàµà´±à´¿à´²àµâ€ à´ªàµà´°à´µàµ‡à´¶à´¿à´•àµà´•à´£à´‚
-require_sign_in_view_popup=പേജൠആകàµâ€Œà´¸à´¸àµà´¸àµ, à´ªàµà´°à´µàµ‡à´¶à´¿à´šàµà´š ഉപയോകàµà´¤à´¾à´•àµà´•àµ¾à´•àµà´•àµà´®à´¾à´¤àµà´°à´®à´¾à´¯à´¿ പരിമിതപàµà´ªàµ†à´Ÿàµà´¤àµà´¤àµà´•. സനàµà´¦àµ¼à´¶à´•àµ¼ 'à´ªàµà´°à´µàµ‡à´¶à´¨à´‚', രജിസàµà´Ÿàµà´°àµ‡à´·àµ» പേജàµà´•àµ¾ à´Žà´¨àµà´¨à´¿à´µ മാതàµà´°à´®àµ‡ കാണൂ.
-admin_setting_desc=ഒരൠഅഡàµà´®à´¿à´¨à´¿à´¸àµà´Ÿàµà´°àµ‡à´±àµà´±à´°àµâ€ à´…à´•àµà´•àµ—à´£àµà´Ÿàµ സൃഷàµà´Ÿà´¿à´•àµà´•àµà´¨àµà´¨à´¤àµ à´à´šàµà´›à´¿à´•à´®à´¾à´£àµ. ആദàµà´¯à´‚ രജിസàµà´±àµà´±à´°àµâ€ ചെയàµà´¤ ഉപയോകàµà´¤à´¾à´µàµ യാനàµà´¤àµà´°à´¿à´•à´®à´¾à´¯à´¿ ഒരൠഅഡàµà´®à´¿à´¨à´¿à´¸àµà´Ÿàµà´°àµ‡à´±àµà´±à´±à´¾à´¯à´¿ മാറàµà´‚.
-admin_title=à´…à´¡àµà´®à´¿à´¨à´¿à´¸àµà´Ÿàµà´°àµ‡à´±àµà´±à´°àµâ€ à´…à´•àµà´•àµ—à´£àµà´Ÿàµ à´•àµà´°à´®àµ€à´•à´°à´£à´™àµà´™àµ¾
-admin_name=à´…à´¡àµà´®à´¿à´¨à´¿à´¸àµà´Ÿàµà´°àµ‡à´±àµà´±à´±àµà´Ÿàµ† ഉപയോകàµà´¤àµƒà´¨à´¾à´®à´‚
-admin_password=രഹസàµà´¯à´µà´¾à´•àµà´•àµàµ
-confirm_password=രഹസàµà´¯à´µà´¾à´•àµà´•àµàµ à´¸àµà´¥à´¿à´°àµ€à´•à´°à´¿à´•àµà´•àµà´•
-admin_email=à´‡-മെയിലàµâ€ വിലാസം
-install_btn_confirm=à´—à´¿à´±àµà´±àµ€ സനàµà´¨à´¿à´µàµ‡à´¶à´¿à´ªàµà´ªà´¿à´¯àµà´•àµà´•àµà´•
-test_git_failed='git' കമാനàµâ€à´¡àµ പരീകàµà´·à´¿à´•àµà´•à´¾à´¨àµâ€ à´•à´´à´¿à´žàµà´žà´¿à´²àµà´²: %v
-sqlite3_not_available=à´—à´¿à´±àµà´±àµ€à´¯àµà´Ÿàµ† à´ˆ വേരàµâ€à´·à´¨àµâ€ SQLite3യെ പിനàµà´¤àµà´£à´•àµà´•àµà´¨àµà´¨à´¿à´²àµà´². %s ൽ നിനàµà´¨àµà´‚ ഔദàµà´¯àµ‹à´—à´¿à´• ബൈനറി പതിപàµà´ªàµ ഡൌണàµâ€â€Œà´²àµ‹à´¡àµ ചെയàµà´¯àµà´• ('gobuild' പതിപàµà´ªà´²àµà´²).
-invalid_db_setting=ഡാറàµà´±à´¾à´¬àµ‡à´¸àµ à´•àµà´°à´®àµ€à´•à´°à´£à´™àµà´™àµ¾ അസാധàµà´µà´¾à´£àµ: %v
-invalid_repo_path=കലവറയàµà´Ÿàµ† റൂടàµà´Ÿàµ പാതàµà´¤àµ അസാധàµà´µà´¾à´£àµ: %v
-run_user_not_match='റൺ ആസàµ' ഉപയോകàµà´¤àµƒà´¨à´¾à´®à´‚ നിലവിലെ ഉപയോകàµà´¤àµƒà´¨à´¾à´®à´®à´²àµà´²: %s -> %s
-save_config_failed=കോൺഫിഗറേഷൻ സംരകàµà´·à´¿à´•àµà´•àµà´¨àµà´¨à´¤à´¿àµ½ പരാജയപàµà´ªàµ†à´Ÿàµà´Ÿàµ: %v
-invalid_admin_setting=à´…à´¡àµà´®à´¿à´¨à´¿à´¸àµà´Ÿàµà´°àµ‡à´±àµà´±à´°àµâ€ à´…à´•àµà´•àµŒà´£àµà´Ÿàµ à´•àµà´°à´®àµ€à´•à´°à´£à´‚ അസാധàµà´µà´¾à´£àµ: %v
-install_success=à´¸àµà´µà´¾à´—തം! à´—à´¿à´±àµà´±àµ€ തിരഞàµà´žàµ†à´Ÿàµà´¤àµà´¤à´¤à´¿à´¨àµ നനàµà´¦à´¿. സൂകàµà´·à´¿à´•àµà´•àµà´•, ആസàµà´µà´¦à´¿à´•àµà´•àµ‚,!
-invalid_log_root_path=ലോഗൠപാതàµà´¤àµ അസാധàµà´µà´¾à´£àµ: %v
-default_keep_email_private=à´¸àµà´¥à´¿à´°à´¸àµà´¥à´¿à´¤à´¿à´¯à´¾à´¯à´¿ ഇമെയിലàµâ€ വിലാസങàµà´™à´³àµâ€ മറയàµâ€Œà´•àµà´•àµà´•
-default_keep_email_private_popup=à´¸àµà´¥à´¿à´°à´¸àµà´¥à´¿à´¤à´¿à´¯à´¾à´¯à´¿ à´ªàµà´¤à´¿à´¯ ഉപയോകàµà´¤àµƒ à´…à´•àµà´•àµ—à´£àµà´Ÿàµà´•à´³àµà´Ÿàµ† ഇമെയിലàµâ€ വിലാസങàµà´™à´³àµâ€ മറയàµà´•àµà´•àµà´•.
-default_allow_create_organization=à´¸àµà´¥à´¿à´°à´¸àµà´¥à´¿à´¤à´¿à´¯à´¾à´¯à´¿ സംഘടനകളàµâ€ സൃഷàµà´Ÿà´¿à´•àµà´•à´¾à´¨àµâ€ à´…à´¨àµà´µà´¦à´¿à´•àµà´•àµà´•
-default_allow_create_organization_popup=à´¸àµà´¥à´¿à´°à´¸àµà´¥à´¿à´¤à´¿à´¯à´¾à´¯à´¿ സംഘടനകളàµâ€ സൃഷàµà´Ÿà´¿à´•àµà´•à´¾à´¨àµâ€ à´ªàµà´¤à´¿à´¯ ഉപയോകàµà´¤àµƒ à´…à´•àµà´•àµ—à´£àµà´Ÿàµà´•à´³àµ† à´…à´¨àµà´µà´¦à´¿à´•àµà´•àµà´•.
-default_enable_timetracking=à´¸àµà´¥à´¿à´°à´¸àµà´¥à´¿à´¤à´¿à´¯à´¾à´¯à´¿ സമയം à´Ÿàµà´°à´¾à´•àµà´•àµàµ ചെയàµà´¯àµà´¨àµà´¨à´¤àµ à´ªàµà´°à´¾à´ªàµà´¤à´®à´¾à´•àµà´•àµà´•
-default_enable_timetracking_popup=à´¸àµà´¥à´¿à´°à´¸àµà´¥à´¿à´¤à´¿à´¯à´¾à´¯à´¿ à´ªàµà´¤à´¿à´¯ കലവറകളàµâ€à´•àµà´•àµàµ സമയം à´Ÿàµà´°à´¾à´•àµà´•àµàµ ചെയàµà´¯àµà´¨àµà´¨à´¤àµàµ à´ªàµà´°à´¾à´ªàµà´¤à´®à´¾à´•àµà´•àµà´•.
-no_reply_address=മറചàµà´š ഇമെയിൽ ഡൊമെയàµàµ»
-no_reply_address_helper=മറഞàµà´žà´¿à´°à´¿à´•àµà´•àµà´¨àµà´¨ ഇമെയിൽ വിലാസമàµà´³àµà´³ ഉപയോകàµà´¤à´¾à´•àµà´•àµ¾à´•àµà´•àµà´³àµà´³ ഡൊമെയàµàµ» നാമം. ഉദാഹരണതàµà´¤à´¿à´¨àµ, മറഞàµà´žà´¿à´°à´¿à´•àµà´•àµà´¨àµà´¨ ഇമെയിൽ ഡൊമെയàµàµ» 'noreply.example.org' ആയി സജàµà´œàµ€à´•à´°à´¿à´šàµà´šà´¿à´Ÿàµà´Ÿàµà´£àµà´Ÿàµ†à´™àµà´•à´¿àµ½ 'joe' à´Žà´¨àµà´¨ ഉപയോകàµà´¤à´¾à´µàµàµ 'joe@noreply.example.org' ആയി ലോഗിൻ ചെയàµà´¯àµà´‚.
-
-[home]
-uname_holder=ഉപയോകàµà´¤àµƒà´¨à´¾à´®à´®àµ‹ ഇമെയിൽ വിലാസമോ
-password_holder=രഹസàµà´¯à´µà´¾à´•àµà´•àµàµ
-switch_dashboard_context=ഡാഷàµâ€Œà´¬àµ‹àµ¼à´¡àµ സനàµà´¦àµ¼à´­à´‚ മാറàµà´±àµà´•
-my_repos=കലവറകളàµâ€
-show_more_repos=കൂടàµà´¤àµ½ കലവറകളàµâ€ കാണികàµà´•àµà´•â€¦
-collaborative_repos=സഹകരികàµà´•à´¾à´µàµà´¨àµà´¨ കലവറകളàµâ€
-my_orgs=à´Žà´¨àµà´±àµ† സംഘടനകളàµâ€
-my_mirrors=à´Žà´¨àµà´±àµ† മിററàµà´•à´³àµâ€
-view_home=%s കാണàµà´•
-search_repos=ഒരൠകലവറ à´•à´£àµà´Ÿàµ†à´¤àµà´¤àµà´•â€¦
-
-
-
-issues.in_your_repos=നിങàµà´™à´³àµà´Ÿàµ† കലവറകളിലàµâ€
-
-[explore]
-repos=കലവറകളàµâ€
-users=ഉപയോകàµà´¤à´¾à´•àµà´•à´³àµâ€
-organizations=സംഘടനകളàµâ€
-search=തിരയàµà´•
-code=കോഡàµ
-repo_no_results=പൊരàµà´¤àµà´¤à´ªàµà´ªàµ†à´Ÿàµà´¨àµà´¨ കലവറകളൊനàµà´¨àµà´‚ à´•à´£àµà´Ÿàµ†à´¤àµà´¤à´¾à´¨à´¾à´¯à´¿à´²àµà´².
-user_no_results=പൊരàµà´¤àµà´¤à´ªàµà´ªàµ†à´Ÿàµà´¨àµà´¨ ഉപയോകàµà´¤à´¾à´•àµà´•à´³àµ†à´¯àµŠà´¨àµà´¨àµà´‚ à´•à´£àµà´Ÿàµ†à´¤àµà´¤à´¾à´¨à´¾à´¯à´¿à´²àµà´².
-org_no_results=പൊരàµà´¤àµà´¤à´ªàµà´ªàµ†à´Ÿàµà´¨àµà´¨ സംഘടനകളൊനàµà´¨àµà´‚ à´•à´£àµà´Ÿàµ†à´¤àµà´¤à´¾à´¨à´¾à´¯à´¿à´²àµà´².
-code_no_results=നിങàµà´™à´³àµà´Ÿàµ† തിരയൽ പദവàµà´®à´¾à´¯à´¿ പൊരàµà´¤àµà´¤à´ªàµà´ªàµ†à´Ÿàµà´¨àµà´¨ സോഴàµà´¸àµ കോഡàµà´•à´³àµŠà´¨àµà´¨àµà´‚ à´•à´£àµà´Ÿàµ†à´¤àµà´¤à´¾à´¨à´¾à´¯à´¿à´²àµà´².
-code_search_results=%s à´Žà´¨àµà´¨à´¤à´¿à´¨à´¾à´¯àµà´³àµà´³ തിരയൽ ഫലങàµà´™àµ¾
-
-
-[auth]
-create_new_account=à´…à´•àµà´•àµ—à´£àµà´Ÿàµ രജിസàµà´±àµà´±àµ¼ ചെയàµà´¯àµà´•
-register_helper_msg=ഇതിനകം ഒരൠഅകàµà´•àµ—à´£àµà´Ÿàµ ഉണàµà´Ÿàµ‡à´¾? ഇപàµà´ªàµ‹àµ¾ à´ªàµà´°à´µàµ‡à´¶à´¿à´•àµà´•àµà´•!
-social_register_helper_msg=ഇതിനകം ഒരൠഅകàµà´•àµ—à´£àµà´Ÿàµ ഉണàµà´Ÿàµ‡à´¾? ഇതൠഇപàµà´ªàµ‹àµ¾ ബനàµà´§à´¿à´ªàµà´ªà´¿à´¯àµà´•àµà´•àµà´•!
-disable_register_prompt=രജിസàµà´Ÿàµà´°àµ‡à´·àµ» à´…à´ªàµà´°à´¾à´ªàµà´¤à´®à´¾à´•àµà´•à´¿. നിങàµà´™à´³àµà´Ÿàµ† സൈറàµà´±àµ à´…à´¡àµà´®à´¿à´¨à´¿à´¸àµà´Ÿàµà´°àµ‡à´±àµà´±à´±àµà´®à´¾à´¯à´¿ ബനàµà´§à´ªàµà´ªàµ†à´Ÿàµà´•.
-disable_register_mail=രജിസàµà´Ÿàµà´°àµ‡à´·à´¨à´¾à´¯àµà´³àµà´³ ഇമെയിൽ à´¸àµà´¥à´¿à´°àµ€à´•à´°à´£à´‚ à´…à´ªàµà´°à´¾à´ªàµà´¤à´®à´¾à´•àµà´•à´¿.
-forgot_password_title=അടയാളവാകàµà´¯à´‚ മറനàµà´¨àµà´ªàµ‹à´¯àµ‹
-forgot_password=അടയാള വാകàµà´•àµ ഓർകàµà´•àµà´¨àµà´¨à´¿à´²àµà´²àµ‡?
-sign_up_now=ഒരൠഅകàµà´•àµ—à´£àµà´Ÿàµ ആവശàµà´¯à´®àµà´£àµà´Ÿàµ‹? ഇപàµà´ªàµ‡à´¾à´³àµâ€ രജിസàµà´±àµà´±à´°àµâ€ ചെയàµà´¯àµà´•.
-sign_up_successful=à´…à´•àµà´•àµ—à´£àµà´Ÿàµ വിജയകരമായി സൃഷàµà´Ÿà´¿à´šàµà´šàµ.
-confirmation_mail_sent_prompt=<b>%s</b> ലേകàµà´•àµ ഒരൠപàµà´¤à´¿à´¯ à´¸àµà´¥à´¿à´°àµ€à´•à´°à´£ ഇമെയിൽ അയചàµà´šàµ. രജിസàµà´Ÿàµà´°àµ‡à´·àµ» à´ªàµà´°à´•àµà´°à´¿à´¯ പൂർതàµà´¤à´¿à´¯à´¾à´•àµà´•àµà´¨àµà´¨à´¤à´¿à´¨àµ à´…à´Ÿàµà´¤àµà´¤ %s à´¨àµà´³àµà´³à´¿àµ½ നിങàµà´™à´³àµà´Ÿàµ† ഇൻ‌ബോകàµà´¸àµ പരിശോധികàµà´•àµà´•.
-must_change_password=നിങàµà´™à´³àµà´Ÿàµ† രഹസàµà´¯à´µà´¾à´•àµà´•àµàµ à´ªàµà´¤àµà´•àµà´•àµà´•
-allow_password_change=രഹസàµà´¯à´µà´¾à´•àµà´•àµàµ മാറàµà´±à´¾àµ» ഉപയോകàµà´¤à´¾à´µà´¿à´¨àµ‹à´Ÿàµ ആവശàµà´¯à´ªàµà´ªàµ†à´Ÿàµà´• (à´¶àµà´ªà´¾àµ¼à´¶à´¿à´¤à´‚)
-reset_password_mail_sent_prompt=<b>%s</b> ലേകàµà´•àµ ഒരൠപàµà´¤à´¿à´¯ à´¸àµà´¥à´¿à´°àµ€à´•à´°à´£ ഇമെയിൽ അയചàµà´šàµ. à´…à´•àµà´•àµ—à´£àµà´Ÿàµ വീണàµà´Ÿàµ†à´Ÿàµà´•àµà´•àµ½ à´ªàµà´°à´•àµà´°à´¿à´¯ പൂർതàµà´¤à´¿à´¯à´¾à´•àµà´•àµà´¨àµà´¨à´¤à´¿à´¨àµ à´…à´Ÿàµà´¤àµà´¤ %s à´¨àµà´³àµà´³à´¿àµ½ നിങàµà´™à´³àµà´Ÿàµ† ഇൻ‌ബോകàµà´¸àµ പരിശോധികàµà´•àµà´•.
-active_your_account=നിങàµà´™à´³àµà´Ÿàµ† à´…à´•àµà´•àµ—à´£àµà´Ÿàµ സജീവമാകàµà´•àµà´•
-account_activated=നിങàµà´™à´³àµà´Ÿàµ† à´…à´•àµà´•àµ—à´£àµà´Ÿàµ സജീവമാകàµà´•à´¿
-prohibit_login=à´ªàµà´°à´µàµ‡à´¶à´¨à´‚ നിരോധിചàµà´šà´¿à´°à´¿à´•àµà´•àµà´¨àµà´¨àµ
-prohibit_login_desc=നിങàµà´™à´³àµà´Ÿàµ† à´…à´•àµà´•àµ—à´£àµà´Ÿà´¿à´²àµ‡à´¯àµà´•àµà´•àµà´³àµà´³ à´ªàµà´°à´µàµ‡à´¶à´¨à´‚ നിരോധിചàµà´šà´¿à´°à´¿à´•àµà´•àµà´¨àµà´¨àµ, ദയവായി നിങàµà´™à´³àµà´Ÿàµ† സൈറàµà´±àµ à´…à´¡àµà´®à´¿à´¨à´¿à´¸àµà´Ÿàµà´°àµ‡à´±àµà´±à´±àµà´®à´¾à´¯à´¿ ബനàµà´§à´ªàµà´ªàµ†à´Ÿàµà´•.
-resent_limit_prompt=നിങàµà´™àµ¾ à´…à´Ÿàµà´¤àµà´¤à´¿à´Ÿàµ† ഒരൠസജീവമാകàµà´•àµ½ ഇമെയിൽ à´…à´­àµà´¯àµ¼à´¤àµà´¥à´¿à´šàµà´šàµ. 3 മിനിറàµà´±àµ കാതàµà´¤à´¿à´°àµà´¨àµà´¨àµ വീണàµà´Ÿàµà´‚ à´¶àµà´°à´®à´¿à´•àµà´•àµà´•.
-has_unconfirmed_mail=ഹായൠ%s, നിങàµà´™àµ¾à´•àµà´•àµ à´¸àµà´¥à´¿à´°àµ€à´•à´°à´¿à´•àµà´•à´¾à´¤àµà´¤ ഇമെയിൽ വിലാസം (<b>%s</b>) ഉണàµà´Ÿàµ. നിങàµà´™àµ¾à´•àµà´•àµ ഒരൠസàµà´¥à´¿à´°àµ€à´•à´°à´£ ഇമെയിൽ ലഭിചàµà´šà´¿à´²àµà´²àµ†à´™àµà´•à´¿à´²àµ‹ à´ªàµà´¤à´¿à´¯à´¤àµŠà´¨àµà´¨àµ വീണàµà´Ÿàµà´‚ അയയàµâ€Œà´•àµà´•àµ‡à´£àµà´Ÿà´¤àµà´£àµà´Ÿàµ†à´™àµà´•à´¿à´²àµ‹, à´šàµà´µà´Ÿàµ†à´¯àµà´³àµà´³ ബടàµà´Ÿà´£à´¿àµ½ à´•àµà´²à´¿à´•àµà´•àµà´šàµ†à´¯àµà´¯àµà´•.
-resend_mail=നിങàµà´™à´³àµà´Ÿàµ† സജീവമാകàµà´•àµ½ ഇമെയിൽ വീണàµà´Ÿàµà´‚ അയയàµâ€Œà´•àµà´•à´¾àµ» ഇവിടെ à´•àµà´²à´¿à´•àµà´•àµà´šàµ†à´¯àµà´¯àµà´•
-email_not_associate=ഇമെയിൽ വിലാസം à´à´¤àµ†à´™àµà´•à´¿à´²àµà´‚ à´…à´•àµà´•àµ—à´£àµà´Ÿàµà´®à´¾à´¯à´¿ ബനàµà´§à´ªàµà´ªàµ†à´Ÿàµà´¤àµà´¤à´¿à´¯à´¿à´Ÿàµà´Ÿà´¿à´²àµà´².
-send_reset_mail=à´…à´•àµà´•àµ—à´£àµà´Ÿàµ വീണàµà´Ÿàµ†à´Ÿàµà´•àµà´•àµ½ ഇമെയിൽ അയയàµâ€Œà´•àµà´•àµà´•
-reset_password=à´…à´•àµà´•àµ—à´£àµà´Ÿàµ വീണàµà´Ÿàµ†à´Ÿàµà´•àµà´•àµ½
-invalid_code=നിങàµà´™à´³àµà´Ÿàµ† à´¸àµà´¥à´¿à´°àµ€à´•à´°à´£ കോഡൠഅസാധàµà´µà´¾à´£àµ à´…à´²àµà´²àµ†à´™àµà´•à´¿àµ½ കാലഹരണപàµà´ªàµ†à´Ÿàµà´Ÿàµ.
-reset_password_helper=à´…à´•àµà´•àµ—à´£àµà´Ÿàµ വീണàµà´Ÿàµ†à´Ÿàµà´•àµà´•àµà´•
-reset_password_wrong_user=നിങàµà´™àµ¾ %s ആയി സൈൻ ഇൻ ചെയàµâ€Œà´¤àµ, പകàµà´·àµ‡ à´…à´•àµà´•àµ—à´£àµà´Ÿàµ വീണàµà´Ÿàµ†à´Ÿàµà´•àµà´•àµ½ ലിങàµà´•àµ %s à´Žà´¨àµà´¨à´¤à´¿à´¨à´¾à´£àµ
-password_too_short=പാസàµâ€Œà´µàµ‡à´¡àµ ദൈർഘàµà´¯à´‚ %d à´…à´•àµà´·à´°à´™àµà´™à´³à´¿à´²àµà´‚ à´•àµà´±à´µà´¾à´¯à´¿à´°à´¿à´•àµà´•à´°àµà´¤àµ.
-non_local_account=à´ªàµà´°à´¾à´¦àµ‡à´¶à´¿à´• ഇതര ഉപയോകàµà´¤à´¾à´•àµà´•àµ¾à´•àµà´•àµ à´—à´¿à´±àµà´±àµ€ വെബൠവഴി പാസàµâ€Œà´µàµ‡à´¡àµ à´ªàµà´¤àµà´•àµà´•à´¾à´¨àµâ€ ചെയàµà´¯à´¾àµ» കഴിയിലàµà´².
-verify=à´ªàµà´°à´®à´¾à´£àµ€à´•à´°à´¿à´¯àµà´•àµà´•àµà´•
-scratch_code=à´¸àµà´•àµà´°à´¾à´šàµà´šàµ കോഡàµ
-use_scratch_code=ഒരൠസàµà´•àµà´°à´¾à´šàµà´šàµ കോഡൠഉപയോഗികàµà´•àµà´•
-twofa_scratch_used=നിങàµà´™à´³àµà´Ÿàµ† à´¸àµà´•àµà´°à´¾à´šàµà´šàµ കോഡൠഉപയോഗിചàµà´šàµ. നിങàµà´™à´³àµ† à´°à´£àµà´Ÿàµ-ഘടക à´•àµà´°à´®àµ€à´•à´°à´£ പേജിലേകàµà´•àµ റീഡയറകàµâ€Œà´Ÿàµ ചെയàµâ€Œà´¤à´¿à´°à´¿à´•àµà´•àµà´¨àµà´¨à´¤à´¿à´¨à´¾àµ½ നിങàµà´™à´³àµà´Ÿàµ† ഉപകരണ എൻറോൾമെനàµà´±àµ നീകàµà´•à´‚ചെയàµà´¯à´¾à´¨àµ‹ à´ªàµà´¤à´¿à´¯ à´¸àµâ€Œà´•àµà´°à´¾à´šàµà´šàµ കോഡൠസൃഷàµâ€Œà´Ÿà´¿à´•àµà´•à´¾à´¨àµ‹ à´•à´´à´¿à´¯àµà´‚.
-twofa_passcode_incorrect=നിങàµà´™à´³àµà´Ÿàµ† പാസàµâ€Œà´•àµ‹à´¡àµ തെറàµà´±à´¾à´£àµ. നിങàµà´™à´³àµà´Ÿàµ† ഉപകരണം തെറàµà´±à´¾à´¯à´¿ à´¸àµà´¥à´¾à´ªà´¿à´šàµà´šà´¿à´Ÿàµà´Ÿàµà´£àµà´Ÿàµ†à´™àµà´•à´¿àµ½, à´ªàµà´°à´µàµ‡à´¶à´¿à´•àµà´•à´¾àµ» നിങàµà´™à´³àµà´Ÿàµ† à´¸àµà´•àµà´°à´¾à´šàµà´šàµ കോഡൠഉപയോഗികàµà´•àµà´•.
-twofa_scratch_token_incorrect=നിങàµà´™à´³àµà´Ÿàµ† à´¸àµà´•àµà´°à´¾à´šàµà´šàµ കോഡൠതെറàµà´±à´¾à´£àµ.
-login_userpass=à´ªàµà´°à´µàµ‡à´¶à´¿à´•àµà´•àµà´•
-login_openid=OpenID
-oauth_signup_tab=à´ªàµà´¤à´¿à´¯ à´…à´•àµà´•àµ—à´£àµà´Ÿàµ രജിസàµà´±àµà´±àµ¼ ചെയàµà´¯àµà´•
-oauth_signup_submit=à´…à´•àµà´•àµ—à´£àµà´Ÿàµ പൂർതàµà´¤à´¿à´¯à´¾à´•àµà´•àµà´•
-oauth_signin_tab=നിലവിലàµà´³àµà´³ à´…à´•àµà´•àµŒà´£àµà´Ÿàµà´®à´¾à´¯à´¿ ബനàµà´§à´¿à´ªàµà´ªà´¿à´¯àµà´•àµà´•àµà´•
-oauth_signin_title=à´…à´•àµà´•àµ—à´£àµà´Ÿàµ ബനàµà´§à´¿à´ªàµà´ªà´¿à´¯àµà´•àµà´•àµà´¨àµà´¨à´¤àµàµ അംഗീകരികàµà´•àµà´¨àµà´¨à´¤à´¿à´¨à´¾à´¯à´¿ സൈറàµà´±à´¿à´²àµ‡à´¯àµà´•àµà´•àµàµ à´ªàµà´°à´µàµ‡à´¶à´¿à´•àµà´•àµà´•
-oauth_signin_submit=à´…à´•àµà´•àµŒà´£àµà´Ÿàµ ബനàµà´§à´¿à´ªàµà´ªà´¿à´¯àµà´•àµà´•àµà´•
-openid_connect_submit=ബനàµà´§à´¿à´ªàµà´ªà´¿à´•àµà´•àµà´•
-openid_connect_title=നിലവിലàµà´³àµà´³ à´…à´•àµà´•àµ—à´£àµà´Ÿàµà´®à´¾à´¯à´¿ ബനàµà´§à´¿à´ªàµà´ªà´¿à´¯àµà´•àµà´•àµà´•
-openid_connect_desc=തിരഞàµà´žàµ†à´Ÿàµà´¤àµà´¤ à´“à´ªàµà´ªàµºà´à´¡à´¿ à´¯àµà´†àµ¼à´ à´…à´œàµà´žà´¾à´¤à´®à´¾à´£àµ. ഇവിടെ നിനàµà´¨àµà´‚ ഒരൠപàµà´¤à´¿à´¯ à´…à´•àµà´•àµ—à´£àµà´Ÿàµà´®à´¾à´¯à´¿ ബനàµà´§à´ªàµà´ªàµ†à´Ÿàµà´¤àµà´¤àµà´•.
-openid_register_title=à´…à´‚à´—à´¤àµà´µà´®àµ†à´Ÿàµà´•àµà´•àµà´•
-openid_register_desc=തിരഞàµà´žàµ†à´Ÿàµà´¤àµà´¤ à´“à´ªàµà´ªàµºà´à´¡à´¿ à´¯àµà´†àµ¼à´ à´…à´œàµà´žà´¾à´¤à´®à´¾à´£àµ. ഇവിടെ നിനàµà´¨àµà´‚ ഒരൠപàµà´¤à´¿à´¯ à´…à´•àµà´•àµ—à´£àµà´Ÿàµà´®à´¾à´¯à´¿ ബനàµà´§à´ªàµà´ªàµ†à´Ÿàµà´¤àµà´¤àµà´•.
-openid_signin_desc=നിങàµà´™à´³àµà´Ÿàµ† OpenID URI നൽകàµà´•. ഉദാഹരണതàµà´¤à´¿à´¨àµ: https://anne.me, bob.openid.org.cn à´…à´²àµà´²àµ†à´™àµà´•à´¿àµ½ gnusocial.net/carry.
-email_domain_blacklisted=നിങàµà´™à´³àµà´Ÿàµ† ഇമെയിൽ വിലാസതàµà´¤à´¿àµ½ രജിസàµà´±àµà´±àµ¼ ചെയàµà´¯à´¾àµ» കഴിയിലàµà´².
-authorize_application=à´…à´ªàµà´²à´¿à´•àµà´•àµ‡à´·à´¨àµàµ അംഗീകാരം നലàµà´•àµà´•
-authorize_application_created_by=%s സൃഷàµâ€Œà´Ÿà´¿à´šàµà´š à´…à´ªàµà´²à´¿à´•àµà´•àµ‡à´·àµ» ആണàµ.
-authorize_application_description=നിങàµà´™àµ¾ à´ªàµà´°à´µàµ‡à´¶à´¨à´‚ à´…à´¨àµà´µà´¦à´¿à´•àµà´•àµà´•à´¯à´¾à´£àµ†à´™àµà´•à´¿àµ½, à´¸àµà´µà´•à´¾à´°àµà´¯ റിപàµà´ªàµ‹à´•à´³àµà´‚ ഓർഗനൈസേഷനàµà´•à´³àµà´‚ ഉൾപàµà´ªàµ†à´Ÿàµ† നിങàµà´™à´³àµà´Ÿàµ† à´Žà´²àµà´²à´¾ à´…à´•àµà´•àµŒà´£àµà´Ÿàµ വിവരങàµà´™à´³àµâ€ നേടാനàµà´‚ വേണമെങàµà´•à´¿à´²àµâ€â€ മാറàµà´±à´™àµà´™à´³àµâ€ വരàµà´¤àµà´¤à´¾à´¨àµà´‚ അതിനൠകഴിയàµà´‚.
-authorize_title=നിങàµà´™à´³àµà´Ÿàµ† à´…à´•àµà´•àµŒà´£àµà´Ÿà´¿à´²àµâ€ à´ªàµà´°à´µàµ‡à´¶à´¿à´¯àµà´•àµà´•àµà´¨àµà´¨à´¤à´¿à´¨àµàµ "%s"à´¨àµàµ അംഗീകാരം നൽകണോ?
-authorization_failed=അംഗീകാരം നലàµâ€à´•àµà´¨àµà´¨à´¤à´¿à´²àµâ€ പരാജയപàµà´ªàµ†à´Ÿàµà´Ÿàµ
-authorization_failed_desc=അസാധàµà´µà´¾à´¯ ഒരൠഅഭàµà´¯àµ¼à´¤àµà´¥à´¨ à´•à´£àµà´Ÿàµ†à´¤àµà´¤à´¿à´¯à´¤à´¿à´¨à´¾àµ½ à´žà´™àµà´™àµ¾ അംഗീകാരം പരാജയപàµà´ªàµ†à´Ÿàµà´¤àµà´¤à´¿. ദയവായി നിങàµà´™àµ¾ അംഗീകരികàµà´•à´¾àµ» à´¶àµà´°à´®à´¿à´šàµà´š à´…à´ªàµà´²à´¿à´•àµà´•àµ‡à´·à´¨àµà´±àµ† പരിപാലകനàµà´®à´¾à´¯à´¿ ബനàµà´§à´ªàµà´ªàµ†à´Ÿàµà´•.
-
-[mail]
-
-activate_account=നിങàµà´™à´³àµà´Ÿàµ† à´…à´•àµà´•àµ—à´£àµà´Ÿàµ സജീവമാകàµà´•àµà´•
-
-activate_email=ഇമെയിലàµâ€ വിലാസം à´¸àµà´¥à´¿à´°àµ€à´•à´°à´¿à´¯àµà´•àµà´•àµà´•
-
-register_notify=à´—à´¿à´±àµà´±àµ€à´¯à´¿à´²àµ‡à´¯àµà´•àµà´•àµàµ à´¸àµà´µà´¾à´—തം
-
-reset_password=നിങàµà´™à´³àµà´Ÿàµ† à´…à´•àµà´•àµ—à´£àµà´Ÿàµ വീണàµà´Ÿàµ†à´Ÿàµà´•àµà´•àµà´•
-
-register_success=രജിസàµà´Ÿàµà´°àµ‡à´·àµ» വിജയകരം
-
-
-
-
-
-
-
-[modal]
-yes=അതെ
-no=ഇലàµà´²
-modify=à´ªàµà´¤àµà´•àµà´•àµà´•
-
-[form]
-UserName=ഉപയോകàµà´¤àµà´°àµ നാമം
-RepoName=കലവറയàµà´Ÿàµ† പേരàµàµ
-Email=à´‡-മെയിലàµâ€ വിലാസം
-Password=രഹസàµà´¯à´µà´¾à´•àµà´•àµàµ
-Retype=രഹസàµà´¯à´µà´¾à´•àµà´•àµàµ വീണàµà´Ÿàµà´‚ നലàµâ€à´•àµà´•
-SSHTitle=SSH കീയàµà´Ÿàµ† പേരàµàµ
-HttpsUrl=HTTPS URL
-PayloadUrl=പേലോഡൠURL
-TeamName=ടീമിനàµà´±àµ† പേരàµàµ
-AuthName=അംഗീകാരതàµà´¤à´¿à´¨àµà´±àµ† പേരàµàµ
-AdminEmail=à´…à´¡àµâ€Œà´®à´¿àµ» ഇമെയിൽ
-
-NewBranchName=à´ªàµà´¤à´¿à´¯ ശാഖയàµà´Ÿàµ† പേരàµàµ
-CommitSummary=നിയോഗതàµà´¤à´¿à´¨àµà´±àµ† സംഗàµà´°à´¹à´‚
-CommitMessage=നിയോഗതàµà´¤à´¿à´¨àµà´±àµ† സനàµà´¦àµ‡à´¶à´‚
-CommitChoice=നിയോഗതàµà´¤à´¿à´¨àµà´±àµ† തിരഞàµà´žàµ†à´Ÿàµà´•àµà´•à´²àµâ€
-TreeName=ഫയലàµâ€ പാതàµà´¤àµ
-Content=ഉളàµà´³à´Ÿà´•àµà´•à´‚
-
-
-require_error=`ശൂനàµà´¯à´®à´¾à´¯à´¿à´°à´¿à´•àµà´•à´°àµà´¤àµ.`
-alpha_dash_error=`ആൽ‌ഫാനàµà´¯àµ‚മെറികàµ, ഡാഷൠ('-'), അടിവരയിടàµà´Ÿ ('_') à´Žà´¨àµà´¨àµ€ à´šà´¿à´¹àµà´¨à´™àµà´™à´³àµâ€ മാതàµà´°à´‚ à´…à´Ÿà´™àµà´™à´¿à´¯à´¿à´°à´¿à´•àµà´•à´£à´‚.`
-alpha_dash_dot_error=`ആൽ‌ഫാനàµà´¯àµ‚മെറികàµ, ഡാഷൠ('-'), അടിവരയിടàµà´• ('_'), ഡോടàµà´Ÿàµ ('.') à´Žà´¨àµà´¨àµ€ à´šàµà´¹àµà´¨à´™àµà´™à´³àµâ€ മാതàµà´°à´‚ à´…à´Ÿà´™àµà´™à´¿à´¯à´¿à´°à´¿à´•àµà´•à´£à´‚.`
-git_ref_name_error=`നനàµà´¨à´¾à´¯à´¿ രൂപപàµà´ªàµ†à´Ÿàµà´¤àµà´¤à´¿à´¯ Git റഫറൻസൠനാമമായിരികàµà´•à´£à´‚.`
-size_error=`വലàµà´ªàµà´ªà´‚ %s ആയിരികàµà´•à´£à´‚.`
-min_size_error=`à´•àµà´±à´žàµà´žà´¤àµ %s à´…à´•àµà´·à´°à´™àµà´™à´³àµâ€ à´…à´Ÿà´™àµà´™à´¿à´¯à´¿à´°à´¿à´•àµà´•à´£à´‚.`
-max_size_error=`പരമാവധി %s à´…à´•àµà´·à´°à´™àµà´™à´³àµâ€ à´…à´Ÿà´™àµà´™à´¿à´¯à´¿à´°à´¿à´•àµà´•à´£à´‚.`
-email_error=സാധàµà´µà´¾à´¯ ഒരൠഈ-മെയിൽ വിലാസം à´…à´²àµà´²
-include_error=`%s'à´Žà´¨àµà´¨ ഉപവാകàµà´¯à´‚ à´…à´Ÿà´™àµà´™à´¿à´¯à´¿à´°à´¿à´•àµà´•à´£à´‚.`
-glob_pattern_error=à´—àµà´²àµ‹à´¬àµàµ ശൃേണി തെറàµà´±à´¾à´£àµàµ: %s
-unknown_error=à´…à´œàµà´žà´¾à´¤à´®à´¾à´¯ പിശകàµ:
-captcha_incorrect=à´•àµà´¯à´¾à´ªàµà´š കോഡൠതെറàµà´±à´¾à´£àµ.
-password_not_match=രഹസàµà´¯à´µà´¾à´•àµà´•àµà´•à´³àµâ€ യോജികàµà´•àµà´¨àµà´¨à´¿à´²àµà´².
-
-username_been_taken=ഉപയോകàµà´¤àµƒà´¨à´¾à´®à´‚ ലഭàµà´¯à´®à´²àµà´².
-repo_name_been_taken=കലവറയàµà´Ÿàµ† പേരàµàµ ഇതിനോടകം ഉപയോഗിചàµà´šà´¿à´Ÿàµà´Ÿàµà´£àµà´Ÿàµàµ.
-visit_rate_limit=വിദൂര വിലാസം വിവരകൈമാറàµà´±à´¤àµà´¤à´¿à´¨àµàµ പരിധി നിശàµà´šà´¯à´¿à´šàµà´šà´¿à´Ÿàµà´Ÿàµà´£àµà´Ÿàµàµ.
-2fa_auth_required=വിദൂര വിലാസം ഇരടàµà´Ÿ ഘടക à´ªàµà´°à´¾à´®à´¾à´£àµ€à´•à´°à´£à´‚ ആവശàµà´¯à´ªàµà´ªàµ†à´Ÿàµà´¨àµà´¨àµà´£àµà´Ÿàµàµ.
-org_name_been_taken=സംഘടനയàµà´Ÿàµ† പേരൠഇതിനകം à´Žà´Ÿàµà´¤àµà´¤à´¿à´Ÿàµà´Ÿàµà´£àµà´Ÿàµ.
-team_name_been_taken=ടീമിനàµà´±àµ† പേരൠഇതിനകം à´Žà´Ÿàµà´¤àµà´¤à´¿à´Ÿàµà´Ÿàµà´£àµà´Ÿàµ.
-team_no_units_error=à´•àµà´±à´žàµà´žà´¤àµ ഒരൠകലവറ വിഭാഗതàµà´¤à´¿à´²àµ‡à´•àµà´•àµ à´ªàµà´°à´µàµ‡à´¶à´¨à´‚ à´…à´¨àµà´µà´¦à´¿à´•àµà´•àµà´•.
-email_been_used=à´ˆ ഇമെയിൽ വിലാസം ഇതിനൠമàµà´¨àµà´¨àµ‡ à´Žà´Ÿàµà´¤àµà´¤à´¿à´Ÿàµà´Ÿàµà´£àµà´Ÿàµ.
-openid_been_used=%s à´Žà´¨àµà´¨ à´“à´ªàµà´ªà´£àµâ€à´à´¡à´¿ വിലാസം ഇതിനൠമàµà´¨àµà´¨àµ‡ à´Žà´Ÿàµà´¤àµà´¤à´¿à´Ÿàµà´Ÿàµà´£àµà´Ÿàµ.
-username_password_incorrect=ഉപഭോകàµà´¤àµƒà´¨à´¾à´®à´®àµ‹ രഹസàµà´¯à´µà´¾à´•àµà´•àµ‹ തെറàµà´±à´¾à´£àµ.
-enterred_invalid_repo_name=à´ˆ കവവറയàµà´Ÿàµ† പേരàµàµ തെറàµà´±à´¾à´£àµàµ.
-enterred_invalid_owner_name=à´ªàµà´¤à´¿à´¯ ഉടമസàµà´¥à´¨àµà´±àµ† പേരàµàµ സാധàµà´µà´²àµà´².
-enterred_invalid_password=താങàµà´•à´³àµâ€ നലàµâ€à´•à´¿à´¯ രഹസàµà´¯à´µà´¾à´•àµà´•àµàµ തെറàµà´±à´¾à´£àµ.
-user_not_exist=ഉപയോകàµà´¤à´¾à´µàµ നിലവിലിലàµà´².
-cannot_add_org_to_team=ഒരൠസംഘടനയെ ടീം അംഗമായി ചേർകàµà´•à´¾àµ» കഴിയിലàµà´².
-
-invalid_ssh_key=നിങàµà´™à´³àµà´Ÿàµ† SSH കീ à´¸àµà´¥à´¿à´°àµ€à´•à´°à´¿à´•àµà´•à´¾àµ» കഴിയിലàµà´²: %s
-invalid_gpg_key=നിങàµà´™à´³àµà´Ÿàµ† GPG കീ à´¸àµà´¥à´¿à´°àµ€à´•à´°à´¿à´•àµà´•à´¾àµ» കഴിയിലàµà´²: %s
-unable_verify_ssh_key=SSH കീ à´¸àµà´¥à´¿à´°àµ€à´•à´°à´¿à´•àµà´•à´¾àµ» കഴിയിലàµà´²; തെറàµà´±àµà´•à´³àµà´£àµà´Ÿàµ‹à´¯àµ†à´¨àµà´¨àµàµ à´’à´¨àµà´¨àµà´•àµ‚à´Ÿà´¿ പരിശോധികàµà´•àµà´•.
-auth_failed=à´ªàµà´°à´¾à´®à´¾à´£àµ€à´•à´°à´£à´‚ പരാജയപàµà´ªàµ†à´Ÿàµà´Ÿàµ: %v
-
-still_own_repo=നിങàµà´™à´³àµà´Ÿàµ† à´…à´•àµà´•àµ—à´£àµà´Ÿà´¿à´¨àµ à´’à´¨àµà´¨àµ‹ അതിലധികമോ കലവറകളàµâ€ ഉണàµà´Ÿàµ; ആദàµà´¯à´‚ à´…à´µ ഇലàµà´²à´¾à´¤à´¾à´•àµà´•àµà´• à´…à´²àµà´²àµ†à´™àµà´•à´¿àµ½ കൈമാറàµà´•.
-still_has_org=നിങàµà´™à´³àµà´Ÿàµ† à´…à´•àµà´•àµ—à´£àµà´Ÿàµ à´’à´¨àµà´¨àµ‹ അതിലധികമോ സംഘടനകളിലàµâ€ അംഗമാണàµ; ആദàµà´¯à´‚ à´…à´µ വിടàµà´•.
-org_still_own_repo=നിങàµà´™à´³àµà´Ÿàµ† സംഘടന ഇനിയàµà´‚ à´’à´¨àµà´¨àµ‹ അതിലധികമോ കലവറകളàµà´Ÿàµ† ഉടമസàµà´¥à´¨à´¾à´£àµàµ; ആദàµà´¯à´‚ à´…à´µ ഇലàµà´²à´¾à´¤à´¾à´•àµà´•àµà´• à´…à´²àµà´²àµ†à´™àµà´•à´¿àµ½ കൈമാറàµà´•.
-
-target_branch_not_exist=ലകàµà´·àµà´¯à´®à´¾à´•àµà´•à´¿à´¯ ശാഖ നിലവിലിലàµà´².
-
-[user]
-change_avatar=നിങàµà´™à´³àµà´Ÿàµ† അവതാർ മാറàµà´±àµà´•â€¦
-join_on=ചേർനàµà´¨à´¤àµàµ
-repositories=കലവറകളàµâ€
-activity=പൊതàµà´µà´¾à´¯ à´ªàµà´°à´µàµ¼à´¤àµà´¤à´¨à´™àµà´™à´³àµâ€
-followers=പിനàµà´¤àµà´Ÿà´°àµà´¨àµà´¨à´µà´°àµâ€â€Œ
-starred=നകàµà´·à´¤àµà´°à´®à´¿à´Ÿàµà´Ÿ കലവറകളàµâ€
-following=പിനàµà´¤àµà´Ÿà´°àµà´¨àµà´¨à´µà´°àµâ€
-follow=പിനàµà´¤àµà´Ÿà´°àµ‚
-unfollow=പിനàµà´¤àµà´Ÿà´°àµà´¨àµà´¨à´¤àµ നിരàµâ€à´¤àµà´¤àµà´•
-heatmap.loading=ഹീറàµà´±àµà´®à´¾à´ªàµà´ªàµ ലോഡàµà´šàµ†à´¯àµà´¯àµà´¨àµà´¨àµâ€¦
-user_bio=ജീവചരിതàµà´°à´‚
-
-form.name_reserved='%s' à´Žà´¨àµà´¨ ഉപയോകàµà´¤àµƒà´¨à´¾à´®à´‚ മറàµà´±à´¾à´µà´¶àµà´¯à´™àµà´™à´³àµâ€à´•àµà´•à´¾à´¯à´¿ നീകàµà´•à´¿à´µà´šàµà´šà´¿à´°à´¿à´•àµà´•àµà´¨àµà´¨àµ.
-form.name_pattern_not_allowed=ഉപയോകàµà´¤àµƒà´¨à´¾à´®à´¤àµà´¤à´¿àµ½ '%s' à´Žà´¨àµà´¨ à´¶àµà´°àµ‡à´£à´¿ à´…à´¨àµà´µà´¦à´¨àµ€à´¯à´®à´²àµà´².
-
-[settings]
-profile=à´ªàµà´°àµŠà´«àµˆàµ½
-account=à´…à´•àµà´•àµ—à´£àµà´Ÿàµ
-password=രഹസàµà´¯à´µà´¾à´•àµà´•àµàµ
-security=à´¸àµà´°à´•àµà´·
-avatar=അവതാരàµâ€
-ssh_gpg_keys=SSH / GPG കീകളàµâ€
-social=സോഷàµà´¯àµ½ à´…à´•àµà´•àµ—à´£àµà´Ÿàµà´•àµ¾
-applications=à´…à´ªàµà´²à´¿à´•àµà´•àµ‡à´·à´¨àµà´•àµ¾
-orgs=സംഘടനകളെ നിയനàµà´¤àµà´°à´¿à´•àµà´•àµà´•
-repos=കലവറകളàµâ€
-delete=à´…à´•àµà´•àµ—à´£àµà´Ÿàµ ഇലàµà´²à´¾à´¤à´¾à´•àµà´•àµà´•
-twofa=ഇരടàµà´Ÿ ഘടക à´ªàµà´°à´¾à´®à´¾à´£àµ€à´•à´°à´£à´‚
-account_link=ബനàµà´§à´¿à´ªàµà´ªà´¿à´šàµà´š à´…à´•àµà´•àµŒà´£àµà´Ÿàµà´•à´³àµâ€
-organization=സംഘടനകളàµâ€
-uid=Uid
-
-public_profile=പരസàµà´¯à´®à´¾à´¯ à´ªàµà´°àµŠà´«àµˆàµ½
-profile_desc=അറിയിപàµà´ªàµà´•àµ¾à´•àµà´•àµà´‚ മറàµà´±àµ à´ªàµà´°à´µàµ¼à´¤àµà´¤à´¨à´™àµà´™àµ¾à´•àµà´•àµà´®à´¾à´¯à´¿ നിങàµà´™à´³àµà´Ÿàµ† ഇമെയിൽ വിലാസം ഉപയോഗികàµà´•àµà´‚.
-password_username_disabled=à´ªàµà´°à´¾à´¦àµ‡à´¶à´¿à´•à´®à´²àµà´²à´¾à´¤àµà´¤ ഉപയോകàµà´¤à´¾à´•àµà´•àµ¾à´•àµà´•àµ അവരàµà´Ÿàµ† ഉപയോകàµà´¤àµƒà´¨à´¾à´®à´‚ മാറàµà´±à´¾àµ» à´…à´¨àµà´µà´¾à´¦à´®à´¿à´²àµà´². കൂടàµà´¤àµ½ വിവരങàµà´™àµ¾à´•àµà´•àµ നിങàµà´™à´³àµà´Ÿàµ† സൈറàµà´±àµ à´…à´¡àµà´®à´¿à´¨à´¿à´¸àµà´Ÿàµà´°àµ‡à´±àµà´±à´±àµà´®à´¾à´¯à´¿ ബനàµà´§à´ªàµà´ªàµ†à´Ÿàµà´•.
-full_name=പൂർണàµà´£à´®à´¾à´¯ പേരàµ
-website=വെബൠസൈറàµà´±àµ
-location=à´¸àµà´¥à´²à´‚
-update_theme=à´ªàµà´°à´®àµ‡à´¯à´‚ à´ªàµà´¤àµà´•àµà´•àµà´•
-update_profile=à´ªàµà´°àµ‹à´«àµˆà´²àµâ€ പരിഷàµà´•à´°à´¿à´•àµà´•àµà´•
-update_profile_success=നിങàµà´™à´³àµà´Ÿàµ† à´ªàµà´°àµ†à´¾à´«àµˆàµ½ പരിഷàµà´•à´°à´¿à´šàµà´šà´¿à´°à´¿à´•àµà´•àµà´¨àµà´¨àµ.
-change_username=നിങàµà´™à´³àµà´Ÿàµ† ഉപയോകàµà´¤àµƒà´¨à´¾à´®à´‚ മാറàµà´±à´¿.
-change_username_prompt=à´•àµà´±à´¿à´ªàµà´ªàµ: ഉപയോകàµà´¤àµƒà´¨à´¾à´®à´¤àµà´¤à´¿à´²àµ† മാറàµà´±à´‚ നിങàµà´™à´³àµà´Ÿàµ† à´…à´•àµà´•àµ—à´£àµà´Ÿàµ URLഉം മാറàµà´±àµà´¨àµà´¨àµ.
-continue=à´¤àµà´Ÿà´°àµà´•
-cancel=റദàµà´¦à´¾à´•àµà´•àµà´•
-language=ഭാഷ
-ui=à´ªàµà´°à´®àµ‡à´¯à´™àµà´™à´³àµâ€
-
-lookup_avatar_by_mail=ഇമെയിൽ വിലാസം à´…à´¨àµà´¸à´°à´¿à´šàµà´šàµ അവതാർ à´•à´£àµà´Ÿàµ†à´¤àµà´¤àµà´•
-federated_avatar_lookup=കേനàµà´¦àµà´°àµ€à´•àµà´°à´¤ അവതാരàµâ€ à´•à´£àµà´Ÿàµ†à´¤àµà´¤à´²àµâ€
-enable_custom_avatar=ഇഷàµâ€Œà´Ÿà´¾à´¨àµà´¸àµƒà´¤ അവതാർ ഉപയോഗികàµà´•àµà´•
-choose_new_avatar=à´ªàµà´¤à´¿à´¯ അവതാർ തിരഞàµà´žàµ†à´Ÿàµà´•àµà´•àµà´•
-update_avatar=അവതാർ à´ªàµà´¤àµà´•àµà´•àµà´•
-delete_current_avatar=നിലവിലെ അവതാർ ഇലàµà´²à´¾à´¤à´¾à´•àµà´•àµà´•
-uploaded_avatar_not_a_image=à´…à´ªàµâ€Œà´²àµ‹à´¡àµà´šàµ†à´¯àµâ€Œà´¤ ഫയൽ ഒരൠചിതàµà´°à´®à´²àµà´².
-uploaded_avatar_is_too_big=à´…à´ªàµâ€Œà´²àµ‹à´¡àµà´šàµ†à´¯àµâ€Œà´¤ ഫയൽ പരമാവധി വലàµà´ªàµà´ªà´‚ കവിഞàµà´žàµ.
-update_avatar_success=നിങàµà´™à´³àµà´Ÿàµ† അവതാരàµâ€ പരിഷàµà´•à´°à´¿à´šàµà´šà´¿à´°à´¿à´•àµà´•àµà´¨àµà´¨àµ.
-
-change_password=പാസàµâ€Œà´µàµ‡à´¡àµ à´ªàµà´¤àµà´•àµà´•àµà´•
-old_password=നിലവിലàµà´³àµà´³ രഹസàµà´¯à´µà´¾à´•àµà´•àµàµ
-new_password=à´ªàµà´¤à´¿à´¯ രഹസàµà´¯à´µà´¾à´•àµà´•àµàµ
-retype_new_password=à´ªàµà´¤à´¿à´¯ രഹസàµà´¯à´µà´¾à´•àµà´•àµàµ വീണàµà´Ÿàµà´‚ നലàµâ€à´•àµà´•
-password_incorrect=നിലവിലെ പാസàµâ€Œà´µàµ‡à´¡àµ തെറàµà´±à´¾à´£àµ.
-change_password_success=നിങàµà´™à´³àµà´Ÿàµ† പാസàµâ€Œà´µàµ‡à´¡àµ à´…à´ªàµâ€Œà´¡àµ‡à´±àµà´±àµà´šàµ†à´¯àµâ€Œà´¤àµ. ഇനി à´®àµà´¤àµ½ നിങàµà´™à´³àµà´Ÿàµ† à´ªàµà´¤à´¿à´¯ പാസàµâ€Œà´µàµ‡à´¡àµ ഉപയോഗിചàµà´šàµ à´ªàµà´°à´µàµ‡à´¶à´¿à´•àµà´•àµà´•.
-password_change_disabled=à´ªàµà´°à´¾à´¦àµ‡à´¶à´¿à´• ഇതര ഉപയോകàµà´¤à´¾à´•àµà´•àµ¾à´•àµà´•àµ à´—à´¿à´±àµà´±àµ€ വെബൠവഴി പാസàµâ€Œà´µàµ‡à´¡àµ à´ªàµà´¤àµà´•àµà´•à´¾à´¨àµâ€ ചെയàµà´¯à´¾àµ» കഴിയിലàµà´².
-
-emails=à´‡-മെയിലàµâ€ വിലാസങàµà´™à´³àµâ€
-manage_emails=ഇമെയിൽ വിലാസങàµà´™àµ¾ നിയനàµà´¤àµà´°à´¿à´•àµà´•àµà´•
-manage_themes=à´¸àµà´¥à´¿à´°à´¸àµà´¥à´¿à´¤à´¿ à´ªàµà´°à´®àµ‡à´¯à´‚ തിരഞàµà´žàµ†à´Ÿàµà´•àµà´•àµà´•
-manage_openid=à´“à´ªàµà´ªàµºà´à´¡à´¿ വിലാസങàµà´™àµ¾ നിയനàµà´¤àµà´°à´¿à´•àµà´•àµà´•
-email_desc=അറിയിപàµà´ªàµà´•àµ¾à´•àµà´•àµà´‚ മറàµà´±àµ à´ªàµà´°à´µàµ¼à´¤àµà´¤à´¨à´™àµà´™àµ¾à´•àµà´•àµà´®à´¾à´¯à´¿ നിങàµà´™à´³àµà´Ÿàµ† à´ªàµà´°à´¾à´¥à´®à´¿à´• ഇമെയിൽ വിലാസം ഉപയോഗികàµà´•àµà´‚.
-theme_desc=സൈറàµà´±à´¿à´²àµà´Ÿà´¨àµ€à´³à´‚ ഇതൠനിങàµà´™à´³àµà´Ÿàµ† à´¸àµà´¥à´¿à´°à´¸àµà´¥à´¿à´¤à´¿ à´ªàµà´°à´®àµ‡à´¯à´‚ ആയിരികàµà´•àµà´‚.
-primary=à´ªàµà´°à´¾à´¥à´®à´¿à´•à´‚
-primary_email=à´ªàµà´°à´¾à´¥à´®à´¿à´•à´®à´¾à´•àµà´•àµà´•
-delete_email=നീകàµà´•à´‚ ചെയàµà´¯àµà´•
-email_deletion=à´ˆ-മെയിലàµâ€ വിലാസം നീകàµà´•à´‚ ചെയàµà´¯àµà´•
-email_deletion_desc=ഇമെയിൽ വിലാസവàµà´‚ à´…à´¨àµà´¬à´¨àµà´§ വിവരങàµà´™à´³àµà´‚ നിങàµà´™à´³àµà´Ÿàµ† à´…à´•àµà´•àµ—à´£àµà´Ÿà´¿àµ½ നിനàµà´¨àµ നീകàµà´•à´‚ചെയàµà´¯àµà´‚. à´ˆ ഇമെയിൽ വിലാസം വഴിയàµà´³àµà´³ à´—à´¿à´±àµà´±àµàµ നിയോഗങàµà´™à´³àµà´‚ മാറàµà´±à´®à´¿à´²àµà´²à´¾à´¤àµ† ഉണàµà´Ÿà´¾à´•àµà´‚. à´¤àµà´Ÿà´°à´Ÿàµà´Ÿàµ†?
-email_deletion_success=ഇമെയിൽ വിലാസം നീകàµà´•à´‚ചെയàµâ€Œà´¤àµ.
-theme_update_success=നിങàµà´™à´³àµà´Ÿàµ† à´ªàµà´°à´®àµ‡à´¯à´‚ à´ªàµà´¤àµà´•àµà´•à´¿.
-theme_update_error=തിരഞàµà´žàµ†à´Ÿàµà´¤àµà´¤ à´ªàµà´°à´®àµ‡à´¯à´‚ നിലവിലിലàµà´².
-openid_deletion=OpenID വിലാസം നീകàµà´•à´‚ ചെയàµà´¯àµà´•
-openid_deletion_desc=നിങàµà´™à´³àµà´Ÿàµ† à´…à´•àµà´•àµ—à´£àµà´Ÿà´¿àµ½ നിനàµà´¨àµ à´“à´ªàµà´ªàµºà´à´¡à´¿ വിലാസം നീകàµà´•à´‚ചെയàµà´¯àµà´¨àµà´¨à´¤àµ ഇതàµà´ªà´¯àµ‹à´—à´¿à´šàµà´šàµàµ ഇനി à´ªàµà´°à´µàµ‡à´¶à´¿à´•àµà´•àµà´¨àµà´¨à´¤à´¿àµ½ നിനàµà´¨àµ നിങàµà´™à´³àµ† തടയàµà´‚. à´¤àµà´Ÿà´°à´Ÿàµà´Ÿàµ†?
-openid_deletion_success=à´“à´ªàµà´ªàµºà´à´¡à´¿ വിലാസം നീകàµà´•à´‚ചെയàµâ€Œà´¤àµ.
-add_new_email=à´ˆ-മെയിലàµâ€ വിലാസം ചേരàµâ€à´•àµà´•àµà´•
-add_new_openid=à´ªàµà´¤à´¿à´¯ à´“à´ªàµà´ªà´£àµâ€ à´à´¡à´¿ വിലാസം ചേരàµâ€à´•àµà´•àµà´•
-add_email=à´ˆ-മെയിലàµâ€ വിലാസം ചേരàµâ€à´•àµà´•àµà´•
-add_openid=à´“à´ªàµà´ªà´£àµâ€ à´à´¡à´¿ വിലാസം ചേരàµâ€à´•àµà´•àµà´•
-add_email_confirmation_sent=ഒരൠസàµà´¥à´¿à´°àµ€à´•à´°à´£ ഇമെയിൽ '%s' ലേകàµà´•àµ അയചàµà´šàµ. നിങàµà´™à´³àµà´Ÿàµ† ഇമെയിൽ വിലാസം à´¸àµà´¥à´¿à´°àµ€à´•à´°à´¿à´•àµà´•àµà´¨àµà´¨à´¤à´¿à´¨àµ à´…à´Ÿàµà´¤àµà´¤ %s à´¨àµà´³àµà´³à´¿àµ½ നിങàµà´™à´³àµà´Ÿàµ† ഇൻ‌ബോകàµà´¸àµ പരിശോധികàµà´•àµà´•.
-add_email_success=à´ªàµà´¤à´¿à´¯ ഇമെയിൽ വിലാസം ചേരàµâ€à´¤àµà´¤àµ.
-add_openid_success=à´ªàµà´¤à´¿à´¯ à´“à´ªàµà´ªà´£àµâ€à´à´¡à´¿ വിലാസം ചേരàµâ€à´¤àµà´¤àµ.
-keep_email_private=à´ˆ-മെയിലàµâ€ വിലാസം മറയàµà´•àµà´•àµà´•
-keep_email_private_popup=നിങàµà´™à´³àµà´Ÿàµ† ഇമെയിൽ വിലാസം മറàµà´±àµ ഉപയോകàµà´¤à´¾à´•àµà´•àµàµ കാണാനാകിലàµà´².
-openid_desc=ഒരൠബാഹàµà´¯ ദാതാവിനൠപàµà´°à´¾à´®à´¾à´£àµ€à´•à´°à´£à´‚ നിയàµà´•àµà´¤à´®à´¾à´•àµà´•à´¾àµ» à´“à´ªàµà´ªàµºà´à´¡à´¿ നിങàµà´™à´³àµ† à´…à´¨àµà´µà´¦à´¿à´•àµà´•àµà´¨àµà´¨àµ.
-
-manage_ssh_keys=​എസàµ. à´Žà´¸àµ. à´Žà´šàµà´šàµ കീകളàµâ€ നിയനàµà´¤àµà´°à´¿à´•àµà´•àµà´•
-manage_gpg_keys=ജീ പീ. ജി കീകളàµâ€ നിയനàµà´¤àµà´°à´¿à´•àµà´•àµà´•
-add_key=കീ ചേരàµâ€à´•àµà´•àµà´•
-ssh_desc=ഇവയാണàµàµ നിങàµà´™à´³àµà´Ÿàµ† à´…à´•àµà´•àµ—à´£àµà´Ÿàµà´®à´¾à´¯à´¿ ബനàµà´§à´ªàµà´ªàµ†à´Ÿàµà´¤àµà´¤à´¿à´¯à´¿à´°à´¿à´•àµà´•àµà´¨àµà´¨ പൊതàµà´µà´¾à´¯ à´Žà´¸àµ. à´Žà´¸àµ. à´Žà´šàµà´šàµ കീകൾ. ഇതിനോടനൠബനàµà´§à´¿à´ªàµà´ªà´¿à´šàµà´šà´¿à´Ÿàµà´Ÿàµà´³àµà´³ à´¸àµà´µà´•à´¾à´°àµà´¯ കീകൾ നിങàµà´™à´³àµà´Ÿàµ† കലവറകളിലേയàµà´•àµà´•àµàµ പൂർണàµà´£ ആകàµà´¸à´¸àµ à´…à´¨àµà´µà´¦à´¿à´•àµà´•àµà´¨àµà´¨àµ.
-gpg_desc=à´ˆ പൊതൠGPG കീകൾ നിങàµà´™à´³àµà´Ÿàµ† à´…à´•àµà´•àµ—à´£àµà´Ÿàµà´®à´¾à´¯à´¿ ബനàµà´§à´ªàµà´ªàµ†à´Ÿàµà´Ÿà´¿à´°à´¿à´•àµà´•àµà´¨àµà´¨àµ. à´•à´®àµà´®à´¿à´±àµà´±àµà´•à´³àµ† പരിശോധിചàµà´šàµà´±à´ªàµà´ªà´¿à´•àµà´•à´¾àµ» നിങàµà´™à´³àµà´Ÿàµ† à´¸àµà´µà´•à´¾à´°àµà´¯ കീകൾ à´…à´¨àµà´µà´¦à´¿à´•àµà´•àµà´¨àµà´¨à´¤à´¿à´¨à´¾àµ½ à´…à´µ à´¸àµà´°à´•àµà´·à´¿à´¤à´®à´¾à´¯à´¿ സൂകàµà´·à´¿à´•àµà´•àµà´•.
-ssh_helper=<strong>സഹായം ആവശàµà´¯à´®àµà´£àµà´Ÿàµ‹?</strong> <a href="%s"> നിങàµà´™à´³àµà´Ÿàµ† à´¸àµà´µà´¨àµà´¤à´‚ SSH കീകൾ സൃഷàµà´Ÿà´¿à´•àµà´•àµà´•,</a> à´…à´²àµà´²àµ†à´™àµà´•à´¿àµ½ <a href="%s"> പൊതàµà´µà´¾à´¯ à´ªàµà´°à´¶àµà´¨à´™àµà´™àµ¾ </a> à´Žà´¨àµà´¨à´¿à´µà´¯àµà´•àµà´•à´¾à´¯àµà´³àµà´³ à´—à´¿à´±àµà´±àµà´¹à´¬àµà´¬à´¿à´¨àµà´±àµ† മാരàµâ€à´—ദരàµâ€à´¶à´¨à´™àµà´™à´³àµâ€ ഉപയോഗിചàµà´šàµàµ നിങàµà´™àµ¾à´•àµà´•àµ à´Žà´¸àµ. à´Žà´¸àµ. à´Žà´šàµà´šàµà´®à´¾à´¯à´¿ ബനàµà´§à´ªàµà´ªàµ†à´Ÿàµà´Ÿ à´ªàµà´°à´¶àµà´¨à´™àµà´™à´³àµâ€ പരിഹരികàµà´•à´¾à´‚.
-gpg_helper=<strong> സഹായം ആവശàµà´¯à´®àµà´£àµà´Ÿàµ‹? </strong> ജിപിജിയെകàµà´•àµà´±à´¿à´šàµà´šàµ à´—à´¿à´±àµà´±àµà´¹à´¬à´¿à´¨àµà´±àµ† മാരàµâ€à´—àµà´—നിരàµâ€à´¦àµà´¦àµ‡à´¶à´™àµà´™à´³àµâ€ <a href="%s"> പരിശോധിയàµà´•àµà´•àµà´•</a>.
-add_new_key=SSH കീ ചേർകàµà´•àµà´•
-add_new_gpg_key=GPG കീ ചേർകàµà´•àµà´•
-ssh_key_been_used=à´ˆ SSH കീ ഇതിനകം ചേർതàµà´¤àµ.
-gpg_key_id_used=സമാന à´à´¡à´¿à´¯àµà´³àµà´³ ഒരൠപൊതൠജിപിജി കീ ഇതിനകം നിലവിലàµà´£àµà´Ÿàµ.
-subkeys=സബൠകീകളàµâ€
-key_id=കീ à´à´¡à´¿
-key_name=കീയàµà´Ÿàµ† പേരàµàµ
-key_content=ഉളàµà´³à´Ÿà´•àµà´•à´‚
-add_key_success='%s' à´Žà´¨àµà´¨ SSH കീ ചേർതàµà´¤àµ.
-add_gpg_key_success='%s' à´Žà´¨àµà´¨ GPG കീ ചേർതàµà´¤àµ.
-delete_key=നീകàµà´•à´‚ ചെയàµà´¯àµà´•
-ssh_key_deletion=SSH കീ നീകàµà´•à´‚ ചെയàµà´¯àµà´•
-gpg_key_deletion=GPG കീ നീകàµà´•à´‚ ചെയàµà´¯àµà´•
-ssh_key_deletion_desc=ഒരൠSSH കീ നീകàµà´•à´‚ചെയàµà´¯àµà´¨àµà´¨à´¤àµ നിങàµà´™à´³àµà´Ÿàµ† à´…à´•àµà´•àµŒà´£àµà´Ÿà´¿à´²àµ‡à´•àµà´•àµà´³àµà´³ à´ªàµà´°à´µàµ‡à´¶à´¨à´‚ അസാധàµà´µà´¾à´•àµà´•àµà´¨àµà´¨àµ. à´¤àµà´Ÿà´°à´Ÿàµà´Ÿàµ†?
-gpg_key_deletion_desc=ഒരൠജി‌പി‌ജി കീ നീകàµà´•à´‚ചെയàµà´¯àµà´¨àµà´¨à´¤àµ അതിൽ à´’à´ªàµà´ªà´¿à´Ÿàµà´Ÿ à´•à´®àµà´®à´¿à´±àµà´±àµà´•à´³àµ† à´¸àµà´¥à´¿à´°àµ€à´•à´°à´¿à´•àµà´•à´¿à´²àµà´². à´¤àµà´Ÿà´°à´Ÿàµà´Ÿàµ†?
-ssh_key_deletion_success=SSH കീ നീകàµà´•à´‚ചെയàµâ€Œà´¤àµ.
-gpg_key_deletion_success=GPG കീ നീകàµà´•à´‚ചെയàµâ€Œà´¤àµ.
-add_on=ചേരàµâ€à´¤àµà´¤à´¤àµàµ
-valid_until=വരെ സാധàµà´µà´¾à´£àµ
-valid_forever=à´Žà´¨àµà´¨àµà´‚ സാധàµà´µà´¾à´£àµàµ
-last_used=അവസാനം ഉപയോഗിചàµà´šà´¤àµ
-no_activity=സമീപകാലതàµà´¤àµàµ à´ªàµà´°à´µàµ¼à´¤àµà´¤à´¨à´™àµà´™à´³àµŠà´¨àµà´¨àµà´®à´¿à´²àµà´²
-can_read_info=വായിയàµà´•àµà´•àµà´•
-can_write_info=à´Žà´´àµà´¤àµà´•
-key_state_desc=à´•à´´à´¿à´žàµà´ž 7 ദിവസങàµà´™à´³à´¿àµ½ à´ˆ കീ ഉപയോഗിചàµà´šàµ
-token_state_desc=à´ˆ ടോകàµà´•àµº à´•à´´à´¿à´žàµà´ž 7 ദിവസങàµà´™à´³à´¿àµ½ ഉപയോഗിചàµà´šàµ
-show_openid=à´ªàµà´°àµŠà´«àµˆà´²à´¿àµ½ കാണàµà´•
-hide_openid=à´ªàµà´°àµŠà´«àµˆà´²à´¿àµ½ നിനàµà´¨àµ മറയàµâ€Œà´•àµà´•àµà´•
-ssh_disabled=SSH à´…à´ªàµà´°à´¾à´ªàµâ€Œà´¤à´®à´¾à´•àµà´•à´¿
-manage_social=സഹവസികàµà´•àµà´¨àµà´¨ സോഷàµà´¯àµ½ à´…à´•àµà´•àµ—à´£àµà´Ÿàµà´•à´³àµ† നിയനàµà´¤àµà´°à´¿à´•àµà´•àµà´•
-social_desc=à´ˆ സോഷàµà´¯àµ½ à´…à´•àµà´•àµ—à´£àµà´Ÿàµà´•àµ¾ നിങàµà´™à´³àµà´Ÿàµ† à´—à´¿à´±àµà´±àµ€ à´…à´•àµà´•àµ—à´£àµà´Ÿàµà´®à´¾à´¯à´¿ ലിങàµà´•àµà´šàµ†à´¯àµâ€Œà´¤àµ. ഇവ നിങàµà´™à´³àµà´Ÿàµ† ഗീറàµà´±àµ€ à´…à´•àµà´•àµ—à´£àµà´Ÿà´¿à´²àµ‡à´•àµà´•àµ à´ªàµà´°à´µàµ‡à´¶à´¿à´•àµà´•à´¾àµ» ഉപയോഗികàµà´•à´¾à´µàµà´¨àµà´¨à´¤à´¿à´¨à´¾àµ½ അവയെലàµà´²à´¾à´‚ നിങàµà´™àµ¾ തിരിചàµà´šà´±à´¿à´žàµà´žàµà´µàµ†à´¨àµà´¨àµ ഉറപàµà´ªà´¾à´•àµà´•àµà´•.
-unbind=അൺലിങàµà´•àµ ചെയàµà´¯àµà´•
-unbind_success=നിങàµà´™à´³àµà´Ÿàµ† ഗീറàµà´±àµ€ à´…à´•àµà´•àµ—à´£àµà´Ÿà´¿àµ½ നിനàµà´¨àµ സോഷàµà´¯àµ½ à´…à´•àµà´•àµ—à´£àµà´Ÿàµ അൺലിങàµà´•àµ ചെയàµà´¤àµ.
-
-manage_access_token=ആകàµâ€Œà´¸à´¸àµà´¸àµ ടോകàµà´•à´£àµà´•àµ¾ നിയനàµà´¤àµà´°à´¿à´•àµà´•àµà´•
-generate_new_token=à´ªàµà´¤à´¿à´¯ ടോകàµà´•àµº സൃഷàµâ€Œà´Ÿà´¿à´•àµà´•àµà´•
-tokens_desc=à´ˆ ടോകàµà´•à´£àµà´•àµ¾ à´—à´¿à´±àµà´±àµ€ API ഉപയോഗിചàµà´šàµ നിങàµà´™à´³àµà´Ÿàµ† à´…à´•àµà´•àµŒà´£àµà´Ÿà´¿à´²àµ‡à´•àµà´•àµ à´ªàµà´°à´µàµ‡à´¶à´¨à´‚ നൽകàµà´¨àµà´¨àµ.
-new_token_desc=ഒരൠടോകàµà´•àµº ഉപയോഗികàµà´•àµà´¨àµà´¨ à´…à´ªàµà´²à´¿à´•àµà´•àµ‡à´·à´¨àµà´•àµ¾à´•àµà´•àµ നിങàµà´™à´³àµà´Ÿàµ† à´…à´•àµà´•àµŒà´£àµà´Ÿà´¿à´²àµ‡à´•àµà´•àµ പൂർണàµà´£ à´ªàµà´°à´µàµ‡à´¶à´¨à´‚ ഉണàµà´Ÿàµ.
-token_name=ടോകàµà´•à´£à´¿à´¨àµà´±àµ† പേരàµàµ
-generate_token=ടോകàµà´•àµº സൃഷàµâ€Œà´Ÿà´¿à´•àµà´•àµà´•
-generate_token_success=നിങàµà´™à´³àµà´Ÿàµ† à´ªàµà´¤à´¿à´¯ ടോകàµà´•àµº ജനറേറàµà´±àµà´šàµ†à´¯àµâ€Œà´¤àµ. ഇതൠവീണàµà´Ÿàµà´‚ കാണികàµà´•à´¾à´¤àµà´¤à´¤à´¿à´¨à´¾àµ½ ഇപàµà´ªàµ‹àµ¾ തനàµà´¨àµ† പകർതàµà´¤àµà´•.
-delete_token=നീകàµà´•à´‚ ചെയàµà´¯àµà´•
-access_token_deletion=ആകàµâ€Œà´¸à´¸àµà´¸àµ ടോകàµà´•à´£àµâ€ നീകàµà´•à´‚ ചെയàµà´¯àµà´•
-delete_token_success=ടോകàµà´•àµº ഇലàµà´²à´¾à´¤à´¾à´•àµà´•à´¿. ഇനി ഇതൠഉപയോഗികàµà´•àµà´¨àµà´¨ à´…à´ªàµà´²à´¿à´•àµà´•àµ‡à´·à´¨àµà´•àµ¾à´•àµà´•àµ നിങàµà´™à´³àµà´Ÿàµ† à´…à´•àµà´•àµŒà´£àµà´Ÿà´¿à´²àµ‡à´•àµà´•àµ à´ªàµà´°à´µàµ‡à´¶à´¨à´‚ ഉണàµà´Ÿà´¾à´•à´¿à´²àµà´².
-
-manage_oauth2_applications=OAuth2 à´…à´ªàµà´²à´¿à´•àµà´•àµ‡à´·à´¨àµà´•àµ¾ നിയനàµà´¤àµà´°à´¿à´•àµà´•àµà´•
-edit_oauth2_application=OAuth2 à´…à´ªàµà´²à´¿à´•àµà´•àµ‡à´·àµ» à´Žà´¡à´¿à´±àµà´±àµà´šàµ†à´¯àµà´¯àµà´•
-oauth2_applications_desc=നിങàµà´™à´³àµà´Ÿàµ† മൂനàµà´¨à´¾à´‚ à´•à´•àµà´·à´¿ à´…à´ªàµà´²à´¿à´•àµà´•àµ‡à´·à´¨àµ†, à´ˆ à´—à´¿à´±àµà´±àµ€ ഇനàµâ€à´¸àµà´±àµà´±à´¾à´³àµ‡à´·à´¨àµà´®à´¾à´¯à´¿ à´¸àµà´°à´•àµà´·à´¿à´¤à´®à´¾à´¯à´¿ ഉപയോകàµà´¤à´¾à´•àµà´•à´³àµ† à´ªàµà´°à´¾à´®à´¾à´£àµ€à´•à´°à´¿à´•àµà´•à´¾àµ» OAuth2 à´…à´ªàµà´²à´¿à´•àµà´•àµ‡à´·à´¨àµà´•àµ¾ à´ªàµà´°à´¾à´ªàµà´¤à´®à´¾à´•àµà´•àµà´¨àµà´¨àµ.
-remove_oauth2_application=OAuth2 à´…à´ªàµà´²à´¿à´•àµà´•àµ‡à´·à´¨àµà´•àµ¾ നീകàµà´•à´‚ചെയàµà´¯àµà´•
-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 à´…à´ªàµà´²à´¿à´•àµà´•àµ‡à´·àµ» à´ªàµà´¤àµà´•àµà´•à´¿.
-oauth2_application_name=à´…à´ªàµà´²à´¿à´•àµà´•àµ‡à´·à´¨àµà´±àµ† പേരàµ
-oauth2_redirect_uri=URI റീഡയറകàµâ€Œà´Ÿàµ ചെയàµà´¯àµà´•
-save_application=സംരകàµà´·à´¿à´¯àµà´•àµà´•àµà´•
-oauth2_client_id=à´•àµà´²àµˆà´¨àµà´±àµ à´à´¡à´¿
-oauth2_client_secret=à´•àµà´²àµˆà´¨àµà´±àµàµ രഹസàµà´¯à´‚
-oauth2_regenerate_secret=രഹസàµà´¯à´‚ à´ªàµà´¨à´ƒà´¸àµƒà´·àµà´Ÿà´¿à´¯àµà´•àµà´•àµà´•
-oauth2_regenerate_secret_hint=നിങàµà´™à´³àµà´Ÿàµ† രഹസàµà´¯à´‚ നഷàµà´Ÿà´ªàµà´ªàµ†à´Ÿàµà´Ÿàµ‹?
-oauth2_client_secret_hint=നിങàµà´™àµ¾ à´ˆ പേജൠവീണàµà´Ÿàµà´‚ സനàµà´¦àµ¼à´¶à´¿à´•àµà´•àµà´•à´¯à´¾à´£àµ†à´™àµà´•à´¿àµ½ രഹസàµà´¯à´‚ ദൃശàµà´¯à´®à´¾à´•à´¿à´²àµà´². നിങàµà´™à´³àµà´Ÿàµ† രഹസàµà´¯à´‚ സംരകàµà´·à´¿à´•àµà´•àµà´•.
-oauth2_application_edit=à´•àµà´°à´®àµ€à´•à´°à´¿à´•àµà´•àµà´•
-oauth2_application_create_description=OAuth2 ആപàµà´²à´¿à´•àµà´•àµ‡à´·à´¨àµà´•àµ¾ നിങàµà´™à´³àµà´Ÿàµ† മൂനàµà´¨à´¾à´‚ à´•à´•àµà´·à´¿ ആപàµà´²à´¿à´•àµà´•àµ‡à´·àµ» ഉപയോകàµà´¤àµƒ à´…à´•àµà´•àµŒà´£àµà´Ÿàµà´•à´³à´¿à´²àµ‡à´•àµà´•àµ ആകàµà´¸à´¸àµ നൽകàµà´¨àµà´¨àµ.
-oauth2_application_remove_description=ഒരൠOAuth2 ആപàµà´²à´¿à´•àµà´•àµ‡à´·àµ» നീകàµà´•à´‚ചെയàµà´¯àµà´¨àµà´¨à´¤àµ à´ˆ സനàµà´¦àµ¼à´­à´¤àµà´¤à´¿àµ½ അംഗീകൃത ഉപയോകàµà´¤àµƒ à´…à´•àµà´•àµŒà´£àµà´Ÿàµà´•à´³à´¿à´²àµ‡à´•àµà´•àµ à´ªàµà´°à´µàµ‡à´¶à´¿à´•àµà´•àµà´¨àµà´¨à´¤àµ തടയàµà´‚. à´¤àµà´Ÿà´°à´Ÿàµà´Ÿàµ†?
-
-authorized_oauth2_applications=അംഗീകൃത OAuth2 à´…à´ªàµà´²à´¿à´•àµà´•àµ‡à´·à´¨àµà´•àµ¾
-authorized_oauth2_applications_description=à´ˆ മൂനàµà´¨à´¾à´‚ à´•à´•àµà´·à´¿ à´…à´ªàµà´²à´¿à´•àµà´•àµ‡à´·à´¨àµà´•à´³à´¿à´²àµ‡à´•àµà´•àµ നിങàµà´™à´³àµà´Ÿàµ† à´¸àµà´µà´•à´¾à´°àµà´¯ ഗീറàµà´±àµ€ à´…à´•àµà´•àµ—à´£àµà´Ÿà´¿à´²àµ‡à´•àµà´•àµ à´ªàµà´°à´µàµ‡à´¶à´¨à´‚ à´…à´¨àµà´µà´¦à´¿à´šàµà´šàµ. à´…à´ªàµà´²à´¿à´•àµà´•àµ‡à´·à´¨àµà´•àµ¾à´•àµà´•à´¾à´¯àµà´³àµà´³ നിയനàµà´¤àµà´°à´£à´‚ ഇനി ആവശàµà´¯à´®à´¿à´²àµà´².
-revoke_key=അസാധàµà´µà´¾à´•àµà´•àµà´•
-revoke_oauth2_grant=നിയനàµà´¤àµà´°à´£à´‚ തിരിചàµà´šàµ†à´Ÿàµà´•àµà´•àµà´•
-revoke_oauth2_grant_description=à´ˆ മൂനàµà´¨à´¾à´‚ à´•à´•àµà´·à´¿ ആപàµà´²à´¿à´•àµà´•àµ‡à´·à´¨à´¾à´¯à´¿ ആകàµà´¸à´¸àµ അസാധàµà´µà´¾à´•àµà´•àµà´¨àµà´¨à´¤àµ നിങàµà´™à´³àµà´Ÿàµ† ഡാറàµà´± ആകàµà´¸à´¸àµ ചെയàµà´¯àµà´¨àµà´¨à´¤à´¿àµ½ നിനàµà´¨àµ à´ˆ ആപàµà´²à´¿à´•àµà´•àµ‡à´·à´¨àµ† തടയàµà´‚. നിങàµà´™à´³àµâ€à´•àµà´•àµ ഉറപàµà´ªà´¾à´£àµ‡à´¾?
-revoke_oauth2_grant_success=നിങàµà´™àµ¾ വിജയകരമായി à´ªàµà´°à´µàµ‡à´¶à´¨à´‚ റദàµà´¦à´¾à´•àµà´•à´¿.
-
-twofa_desc=ഇരടàµà´Ÿ ഘടക à´ªàµà´°à´¾à´®à´¾à´£àµ€à´•à´°à´£à´‚ നിങàµà´™à´³àµà´Ÿàµ† à´…à´•àµà´•àµ—à´£àµà´Ÿà´¿à´¨àµà´±àµ† à´¸àµà´°à´•àµà´· വർദàµà´§à´¿à´ªàµà´ªà´¿à´•àµà´•àµà´¨àµà´¨àµ.
-twofa_is_enrolled=നിങàµà´™à´³àµà´Ÿàµ† à´…à´•àµà´•àµ—à´£àµà´Ÿàµ നിലവിൽ ഇരടàµà´Ÿ ഘടക à´ªàµà´°à´®à´¾à´£àµ€à´•à´°à´£à´¤àµà´¤à´¿à´¨àµàµ <strong> എൻറോൾ ചെയàµà´¤à´¿à´Ÿàµà´Ÿàµà´£àµà´Ÿàµ. </strong>.
-twofa_not_enrolled=നിങàµà´™à´³àµà´Ÿàµ† à´…à´•àµà´•àµ—à´£àµà´Ÿàµ നിലവിൽ ഇരടàµà´Ÿ ഘടക à´ªàµà´°à´®à´¾à´£àµ€à´•à´°à´£à´¤àµà´¤à´¿à´¨àµàµ <strong> എൻറോൾ ചെയàµà´¤à´¿à´Ÿàµà´Ÿà´¿à´²àµà´².</strong>.
-twofa_disable=ഇരടàµà´Ÿ ഘടക à´ªàµà´°à´¾à´®à´¾à´£àµ€à´•à´°à´£à´‚ റദàµà´¦à´¾à´•àµà´•à´¿
-twofa_scratch_token_regenerate=à´¸àµà´•àµà´°à´¾à´šàµà´šàµ ടോകàµà´•àµº à´ªàµà´¨à´ƒà´¨à´¿à´°àµâ€à´®àµà´®à´¿à´¯àµà´•àµà´•àµà´•
-twofa_scratch_token_regenerated=%s ആണൠഇപàµà´ªàµ‹àµ¾ നിങàµà´™à´³àµà´Ÿàµ† à´¸àµà´•àµà´°à´¾à´šàµà´šàµ ടോകàµà´•àµº. à´¸àµà´°à´•àµà´·à´¿à´¤à´®à´¾à´¯ à´¸àµà´¥à´²à´¤àµà´¤àµ സൂകàµà´·à´¿à´•àµà´•àµà´•.
-twofa_enroll=ഇരടàµà´Ÿ ഘടക à´ªàµà´°à´¾à´®à´¾à´£àµ€à´•à´°à´£à´¤àµà´¤à´¿à´²àµâ€ അംഗമാകàµà´•
-twofa_disable_note=ആവശàµà´¯à´®àµ†à´™àµà´•à´¿àµ½ നിങàµà´™àµ¾à´•àµà´•àµ à´°à´£àµà´Ÿàµ-ഘടക à´ªàµà´°à´¾à´®à´¾à´£àµ€à´•à´°à´£à´‚ à´…à´ªàµà´°à´¾à´ªàµà´¤à´®à´¾à´•àµà´•à´¾àµ» à´•à´´à´¿à´¯àµà´‚.
-twofa_disable_desc=à´°à´£àµà´Ÿàµ-ഘടക à´ªàµà´°à´¾à´®à´¾à´£àµ€à´•à´°à´£à´‚ à´…à´ªàµà´°à´¾à´ªàµâ€Œà´¤à´®à´¾à´•àµà´•àµà´¨àµà´¨à´¤àµ നിങàµà´™à´³àµà´Ÿàµ† à´…à´•àµà´•àµ—à´£àµà´Ÿàµ à´¸àµà´°à´•àµà´·à´¿à´¤à´®à´²àµà´²à´¾à´¤àµà´¤à´¤à´¾à´•àµà´•àµà´‚. à´¤àµà´Ÿà´°à´Ÿàµà´Ÿàµ†?
-regenerate_scratch_token_desc=നിങàµà´™à´³àµà´Ÿàµ† à´¸àµà´•àµà´°à´¾à´šàµà´šàµ ടോകàµà´•àµº തെറàµà´±à´¾à´¯à´¿ à´¸àµà´¥à´¾à´ªà´¿à´•àµà´•àµà´•à´¯àµ‹ à´…à´²àµà´²àµ†à´™àµà´•à´¿àµ½ സൈൻ ഇൻ ചെയàµà´¯à´¾àµ» ഇതിനകം ഉപയോഗികàµà´•àµà´•à´¯àµ‹ ചെയàµà´¤à´¿à´Ÿàµà´Ÿàµà´£àµà´Ÿàµ†à´™àµà´•à´¿àµ½ അതൠഇവിടെനിനàµà´¨àµàµ à´ªàµà´¨à´ƒà´¸à´œàµà´œà´®à´¾à´•àµà´•à´¾àµ» à´•à´´à´¿à´¯àµà´‚.
-twofa_disabled=à´°à´£àµà´Ÿàµ-ഘടàµà´Ÿ à´ªàµà´°à´¾à´®à´¾à´£àµ€à´•à´°à´£à´‚ à´…à´ªàµà´°à´¾à´ªàµâ€Œà´¤à´®à´¾à´•àµà´•à´¿.
-scan_this_image=നിങàµà´™à´³àµà´Ÿàµ† à´ªàµà´°à´¾à´®à´¾à´£àµ€à´•à´°à´£ ആപàµà´²à´¿à´•àµà´•àµ‡à´·àµ» ഉപയോഗിചàµà´šàµ à´ˆ à´šà´¿à´¤àµà´°à´‚ സൂകàµà´·àµâ€Œà´®à´ªà´°à´¿à´¶àµ‡à´¾à´§à´¨ നടതàµà´¤àµà´•:
-or_enter_secret=à´…à´²àµà´²àµ†à´™àµà´•à´¿àµ½ രഹസàµà´¯ കോഡൠനൽകàµà´•: %s
-then_enter_passcode=à´…à´ªàµà´²à´¿à´•àµà´•àµ‡à´·à´¨à´¿àµ½ കാണിചàµà´šà´¿à´°à´¿à´•àµà´•àµà´¨àµà´¨ പാസàµâ€Œà´•àµ‹à´¡àµ നൽകàµà´•:
-passcode_invalid=പാസàµâ€Œà´•àµ‹à´¡àµ തെറàµà´±à´¾à´£àµ. വീണàµà´Ÿàµà´‚ à´¶àµà´°à´®à´¿à´•àµà´•àµà´•.
-twofa_enrolled=നിങàµà´™à´³àµà´Ÿàµ† à´…à´•àµà´•àµŒà´£àµà´Ÿàµ à´°à´£àµà´Ÿàµ-ഘടàµà´Ÿ à´ªàµà´°à´¾à´®à´¾à´£àµ€à´•à´°à´£à´¤àµà´¤à´¿à´²àµ‡à´•àµà´•àµ ചേർതàµà´¤à´¿à´Ÿàµà´Ÿàµà´£àµà´Ÿàµ. നിങàµà´™à´³àµà´Ÿàµ† à´¸àµà´•àµà´°à´¾à´šàµà´šàµ ടോകàµà´•àµº (%s) ഒരൠതവണ മാതàµà´°à´‚ കാണികàµà´•àµà´¨àµà´¨à´¤à´¿à´¨à´¾àµ½ à´…à´¤àµàµ à´¸àµà´°à´•àµà´·à´¿à´¤à´®à´¾à´¯ à´¸àµà´¥à´²à´¤àµà´¤àµ സൂകàµà´·à´¿à´•àµà´•àµà´•!
-
-
-manage_account_links=ബനàµà´§à´¿à´ªàµà´ªà´¿à´šàµà´šà´¿à´Ÿàµà´Ÿàµà´³àµà´³ à´…à´•àµà´•àµ—à´£àµà´Ÿàµà´•àµ¾ നിയനàµà´¤àµà´°à´¿à´•àµà´•àµà´•
-manage_account_links_desc=à´ˆ ബാഹàµà´¯ à´…à´•àµà´•àµ—à´£àµà´Ÿàµà´•àµ¾ നിങàµà´™à´³àµà´Ÿàµ† à´—à´¿à´±àµà´±àµ€ à´…à´•àµà´•àµ—à´£àµà´Ÿàµà´®à´¾à´¯à´¿ ലിങàµà´•àµà´šàµ†à´¯àµâ€Œà´¤àµ.
-account_links_not_available=നിങàµà´™à´³àµà´Ÿàµ† à´—à´¿à´±àµà´±àµ€ à´…à´•àµà´•àµŒà´£àµà´Ÿàµà´®à´¾à´¯à´¿ നിലവിൽ മറàµà´±àµàµ ബാഹàµà´¯ à´…à´•àµà´•àµŒà´£àµà´Ÿàµà´•à´³àµŠà´¨àµà´¨àµà´‚ ബനàµà´§à´¿à´ªàµà´ªà´¿à´šàµà´šà´¿à´Ÿàµà´Ÿà´¿à´²àµà´².
-remove_account_link=ബനàµà´§à´¿à´ªàµà´ªà´¿à´šàµà´š à´…à´•àµà´•àµ—à´£àµà´Ÿàµ നീകàµà´•à´‚ചെയàµà´¯àµà´•
-remove_account_link_desc=ഒരൠബനàµà´§à´¿à´ªàµà´ªà´¿à´šàµà´š à´…à´•àµà´•àµ—à´£àµà´Ÿàµ നീകàµà´•à´‚ചെയàµà´¯àµà´¨àµà´¨à´¤àµ നിങàµà´™à´³àµà´Ÿàµ† à´—à´¿à´±àµà´±àµ€ à´…à´•àµà´•àµ—à´£àµà´Ÿà´¿à´²àµ‡à´•àµà´•àµà´³àµà´³ à´ªàµà´°à´µàµ‡à´¶à´¨à´‚ അസാധàµà´µà´¾à´•àµà´•àµà´‚. à´¤àµà´Ÿà´°à´Ÿàµà´Ÿàµ†?
-remove_account_link_success=ബനàµà´§à´¿à´ªàµà´ªà´¿à´šàµà´š à´…à´•àµà´•àµ—à´£àµà´Ÿàµ നീകàµà´•à´‚ചെയàµâ€Œà´¤àµ.
-
-orgs_none=നിങàµà´™àµ¾ à´à´¤àµ†à´™àµà´•à´¿à´²àµà´‚ സംഘടനയിലàµâ€ അംഗമലàµà´².
-repos_none=നിങàµà´™àµ¾à´•àµà´•àµ ഒരൠകലവറയàµà´‚ à´¸àµà´µà´¨àµà´¤à´®à´¾à´¯à´¿ ഇലàµà´²
-
-delete_account=à´…à´•àµà´•àµ—à´£àµà´Ÿàµ ഇലàµà´²à´¾à´¤à´¾à´•àµà´•àµà´•
-delete_prompt=à´ˆ à´ªàµà´°à´µàµ¼à´¤àµà´¤à´¨à´‚ നിങàµà´™à´³àµà´Ÿàµ† ഉപയോകàµà´¤àµƒ à´…à´•àµà´•àµ—à´£àµà´Ÿàµ ശാശàµà´µà´¤à´®à´¾à´¯à´¿ ഇലàµà´²à´¾à´¤à´¾à´•àµà´•àµà´‚. ഇതൠ<strong> പൂർ‌വàµà´µà´¾à´µà´¸àµà´¥à´¯à´¿à´²à´¾à´•àµà´•à´¾àµ»â€Œ കഴിയിലàµà´².</strong>.
-confirm_delete_account=ഇലàµà´²à´¾à´¤à´¾à´•àµà´•àµ½ à´¸àµà´¥à´¿à´°àµ€à´•à´°à´¿à´•àµà´•àµà´•
-delete_account_title=ഉപയോകàµà´¤àµƒ à´…à´•àµà´•àµ—à´£àµà´Ÿàµ ഇലàµà´²à´¾à´¤à´¾à´•àµà´•àµà´•
-delete_account_desc=à´ˆ ഉപയോകàµà´¤àµƒ à´…à´•àµà´•àµ—à´£àµà´Ÿàµ ശാശàµà´µà´¤à´®à´¾à´¯à´¿ ഇലàµà´²à´¾à´¤à´¾à´•àµà´•à´¾àµ» നിങàµà´™àµ¾ ആഗàµà´°à´¹à´¿à´•àµà´•àµà´¨àµà´¨àµà´£àµà´Ÿàµ‹?
-
-email_notifications.enable=ഇമെയിൽ അറിയിപàµà´ªàµà´•àµ¾ à´ªàµà´°à´¾à´ªàµà´¤à´®à´¾à´•àµà´•àµà´•
-email_notifications.onmention=à´‡-മെയിൽ പരാമരàµâ€à´¶à´¿à´šàµà´šà´¾àµ½ മാതàµà´°à´‚ അയയàµà´•àµà´•àµà´•
-email_notifications.disable=ഇമെയിൽ അറിയിപàµà´ªàµà´•àµ¾ à´…à´ªàµà´°à´¾à´ªàµà´¤à´®à´¾à´•àµà´•àµà´•
-email_notifications.submit=à´‡-മെയിലàµâ€ à´®àµàµ»à´—ണനകളàµâ€
-
-
-[repo]
-owner=ഉടമസàµà´¥à´¨àµâ€
-repo_name=കലവറയàµà´Ÿàµ† പേരàµàµ
-repo_name_helper=നലàµà´² കലവറയàµà´Ÿàµ† പേരàµàµ à´¹àµà´°à´¸àµà´µà´µàµà´‚ അവിസàµà´®à´°à´£àµ€à´¯à´µàµà´‚ à´…à´¤àµà´²àµà´¯à´µàµà´®à´¾à´¯ കീവേഡàµà´•àµ¾ ഉപയോഗികàµà´•àµà´¨àµà´¨àµ.
-visibility=കാണാനാവàµà´¨àµà´¨à´¤àµàµ
-visibility_description=ഉടമയàµâ€Œà´•àµà´•àµ‹ ഓർഗനൈസേഷൻ à´…à´‚à´—à´™àµà´™àµ¾à´•àµà´•àµ‹ അവകാശങàµà´™à´³àµà´£àµà´Ÿàµ†à´™àµà´•à´¿àµ½ മാതàµà´°à´®àµ‡ കാണാൻ കഴിയൂ.
-visibility_helper=കലവറ à´¸àµà´µà´•à´¾à´°àµà´¯à´®à´¾à´•àµà´•àµà´•
-visibility_helper_forced=നിങàµà´™à´³àµà´Ÿàµ† സൈറàµà´±àµ à´…à´¡àµà´®à´¿à´¨à´¿à´¸àµà´Ÿàµà´°àµ‡à´±àµà´±àµ¼ à´ªàµà´¤à´¿à´¯ കലവറകളെ à´¸àµà´µà´•à´¾à´°àµà´¯à´®à´¾à´•àµà´•à´¾àµ» നിർബനàµà´§à´¿à´•àµà´•àµà´¨àµà´¨àµ.
-visibility_fork_helper=(മാറàµà´±à´‚ à´Žà´²àµà´²à´¾ ഫോർകàµà´•àµà´•à´³àµ†à´¯àµà´‚ ബാധികàµà´•àµà´‚.)
-clone_helper=à´•àµà´²àµ‹à´£àµâ€ ചെയàµà´¯à´¾à´¨àµâ€ സഹായം വേണോ? <a target="_blank" rel="noopener noreferrer" href="%s">സഹായം</a> സനàµà´¦à´°àµâ€à´¶à´¿à´•àµà´•àµà´•.
-fork_repo=കലവറ ഫോരàµâ€à´•àµà´•àµàµ ചെയàµà´¯àµà´•
-fork_from=à´²àµâ€ നിനàµà´¨àµà´‚ ഫോരàµâ€à´•àµà´•àµàµ ചെയàµà´¯àµ‚
-fork_visibility_helper=ഒരൠകലവറയàµà´Ÿàµ† ഫോരàµâ€à´•àµà´•à´¿à´¨àµà´±àµ† ദൃശàµà´¯à´ªà´°à´¤ മാറàµà´±à´¾àµ» കഴിയിലàµà´².
-repo_desc=വിരരണം
-repo_lang=ഭാഷ
-repo_gitignore_helper=.gitignore ടെംപàµà´²àµ‡à´±àµà´±àµà´•àµ¾ തിരഞàµà´žàµ†à´Ÿàµà´•àµà´•àµà´•.
-license=ലൈസൻസàµ
-license_helper=ഒരൠലൈസൻസൠഫയൽ തിരഞàµà´žàµ†à´Ÿàµà´•àµà´•àµà´•.
-readme=റീഡàµâ€à´®àµ€
-readme_helper=ഒരൠറീഡàµâ€à´®àµ€ ഫയൽ ടെംപàµà´²àµ‡à´±àµà´±àµ തിരഞàµà´žàµ†à´Ÿàµà´•àµà´•àµà´•.
-auto_init=കലവറ സമാരംഭികàµà´•àµà´• (.gitignore, ലൈസൻസàµ, റീഡàµâ€à´®àµ€ à´Žà´¨àµà´¨à´¿à´µ ചേർകàµà´•àµà´¨àµà´¨àµ)
-create_repo=കലവറ സൃഷàµà´Ÿà´¿à´•àµà´•àµà´•
-default_branch=à´¸àµà´¥à´¿à´°à´¸àµà´¥à´¿à´¤à´¿ ശാഖ
-mirror_prune=വെടàµà´Ÿà´¿à´’à´¤àµà´•àµà´•àµà´•
-mirror_prune_desc=കാലഹരണപàµà´ªàµ†à´Ÿàµà´Ÿ വിദൂര à´Ÿàµà´°à´¾à´•àµà´•à´¿à´‚ഗൠറഫറൻസàµà´•àµ¾ നീകàµà´•à´‚ചെയàµà´¯àµà´•
-mirror_interval_invalid=മിറർ ചെയàµà´¯à´¾à´¨àµà´³àµà´³ ഇടവേള സാധàµà´µà´²àµà´².
-mirror_address=URL- ൽ നിനàµà´¨àµà´³àµà´³ à´•àµà´²àµ‹àµº
-mirror_address_url_invalid=നൽകിയ url അസാധàµà´µà´¾à´£àµ. നിങàµà´™àµ¾ url- à´¨àµà´±àµ† à´Žà´²àµà´²à´¾ ഘടകങàµà´™à´³àµà´‚ ശരിയായി നലàµâ€à´•à´£à´‚.
-mirror_address_protocol_invalid=നൽകിയ url അസാധàµà´µà´¾à´£àµ. http(s):// à´…à´²àµà´²àµ†à´™àµà´•à´¿àµ½ git:// ലൊകàµà´•àµ‡à´·à´¨àµà´•àµ¾ മാതàµà´°à´®àµ‡ മിറർ ചെയàµà´¯à´¾àµ» കഴിയൂ.
-mirror_last_synced=അവസാനം സമനàµà´µà´¯à´¿à´ªàµà´ªà´¿à´šàµà´šà´¤àµàµ
-watchers=നിരീകàµà´·à´•àµ¼
-stargazers=à´¸àµà´±àµà´±à´¾àµ¼à´—ാസറàµà´•àµ¾
-forks=ശാഖകളàµâ€
-pick_reaction=നിങàµà´™à´³àµà´Ÿàµ† à´ªàµà´°à´¤à´¿à´•à´°à´£à´‚ തിരഞàµà´žàµ†à´Ÿàµà´•àµà´•àµà´•
-reactions_more=കൂടാതെ %d അധികം
-
-
-
-
-archive.title=à´ˆ കലവറ à´šà´°à´¿à´¤àµà´°à´°àµ‡à´–ാപരമായി നിലനിരàµâ€à´¤àµà´¤à´¿à´¯à´¿à´°à´¿à´•àµà´•àµà´¨àµà´¨àµ. നിങàµà´™àµ¾à´•àµà´•àµ ഫയലàµà´•àµ¾ കാണാനàµà´‚ à´•àµà´²àµ‹àµº ചെയàµà´¯à´¾à´¨àµà´‚ à´•à´´à´¿à´¯àµà´‚, പകàµà´·àµ‡ à´ªàµà´°à´¶àµâ€Œà´¨à´™àµà´™àµ¾ / ലയന à´…à´­àµà´¯àµ¼à´¤àµà´¥à´¨à´•àµ¾ ഉണàµà´Ÿà´¾à´•àµà´•à´¾à´¨àµ‹ à´¤àµà´±à´•àµà´•à´¾à´¨àµ‹ കഴിയിലàµà´².
-archive.issue.nocomment=à´ˆ കലവറ à´šà´°à´¿à´¤àµà´°à´ªà´°à´®à´¾à´¯à´¿ നിലനിരàµâ€à´¤àµà´¤à´¿à´¯à´¿à´°à´¿à´•àµà´•àµà´¨àµà´¨à´¤à´¾à´£àµàµ. നിങàµà´™àµ¾à´•àµà´•àµ à´ªàµà´°à´¶àµà´¨à´™àµà´™à´³à´¿àµ½ à´…à´­à´¿à´ªàµà´°à´¾à´¯à´®à´¿à´Ÿà´¾àµ» കഴിയിലàµà´².
-archive.pull.nocomment=à´ˆ കലവറ à´šà´°à´¿à´¤àµà´°à´ªà´°à´®à´¾à´¯à´¿ നിലനിരàµâ€à´¤àµà´¤à´¿à´¯à´¿à´°à´¿à´•àµà´•àµà´¨àµà´¨à´¤à´¾à´£àµàµ. നിങàµà´™àµ¾à´•àµà´•àµ ലയന à´…à´­àµà´¯àµ¼à´¤àµà´¥à´¨à´•à´³à´¿à´²àµâ€ à´…à´­à´¿à´ªàµà´°à´¾à´¯à´®à´¿à´Ÿà´¾àµ» കഴിയിലàµà´².
-
-form.name_reserved='%s' à´Žà´¨àµà´¨ കലവറയàµà´Ÿàµ† പേരàµàµ മറàµà´±à´¾à´µà´¶àµà´¯à´™àµà´™à´³àµâ€à´•àµà´•à´¾à´¯à´¿ നീകàµà´•à´¿à´µà´šàµà´šà´¿à´°à´¿à´•àµà´•àµà´¨àµà´¨àµ.
-form.name_pattern_not_allowed=കലവറനാമതàµà´¤à´¿àµ½ '%s' à´Žà´¨àµà´¨ à´¶àµà´°àµ‡à´£à´¿ à´…à´¨àµà´µà´¦à´¨àµ€à´¯à´®à´²àµà´².
-
-migrate_items=മൈഗàµà´°àµ‡à´·àµ» ഇനങàµà´™àµ¾
-migrate_items_wiki=വികàµà´•à´¿
-migrate_items_milestones=നാഴികകàµà´•à´²àµà´²àµà´•à´³àµâ€
-migrate_items_labels=ലേബലàµà´•à´³àµâ€
-migrate_items_issues=à´ªàµà´°à´¶àµà´¨à´™àµà´™àµ¾
-migrate_items_pullrequests=ലയന à´…à´­àµà´¯àµ¼à´¤àµà´¥à´¨à´•àµ¾
-migrate_items_releases=à´ªàµà´°à´¸à´¿à´¦àµà´§àµ€à´•à´°à´£à´™àµà´™à´³àµâ€
-migrate_repo=കലവറ മൈഗàµà´°àµ‡à´±àµà´±àµ ചെയàµà´¯àµà´•
-migrate.clone_address=URL- ൽ നിനàµà´¨àµ മൈഗàµà´°àµ‡à´±àµà´±àµ / à´•àµà´²àµ‹àµº ചെയàµà´¯àµà´•
-migrate.clone_address_desc=നിലവിലàµà´³àµà´³ ഒരൠകലവറയàµà´Ÿàµ† HTTP(S) à´…à´²àµà´²àµ†à´™àµà´•à´¿àµ½ à´—à´¿à´±àµà´±àµàµ 'à´•àµà´²àµ‹àµº' URL
-migrate.clone_local_path=à´…à´²àµà´²àµ†à´™àµà´•à´¿àµ½ ഒരൠപàµà´°à´¾à´¦àµ‡à´¶à´¿à´• സെർവർ പാത
-migrate.permission_denied=à´ªàµà´°à´¾à´¦àµ‡à´¶à´¿à´• കലവറകളàµâ€ ഇറകàµà´•àµà´®à´¤à´¿ ചെയàµà´¯à´¾àµ» നിങàµà´™à´³àµâ€à´•àµà´•àµàµ à´…à´¨àµà´µà´¾à´¦à´®à´¿à´²àµà´².
-migrate.invalid_local_path=à´ªàµà´°à´¾à´¦àµ‡à´¶à´¿à´• പാത അസാധàµà´µà´¾à´£àµ. ഇതൠനിലവിലിലàµà´² à´…à´²àµà´²àµ†à´™àµà´•à´¿àµ½ ഒരൠഡയറകàµà´Ÿà´±à´¿à´¯à´²àµà´².
-migrate.failed=മൈഗàµà´°àµ‡à´·àµ» പരാജയപàµà´ªàµ†à´Ÿàµà´Ÿàµ: %v
-migrated_from=<a href="%[1]s">%[2]s</a> നിനàµà´¨àµ മൈഗàµà´°àµ‡à´±àµà´±àµà´šàµ†à´¯àµâ€Œà´¤àµ
-migrated_from_fake=%[1]s നിനàµà´¨àµ മൈഗàµà´°àµ‡à´±àµà´±àµà´šàµ†à´¯àµà´¤àµ
-
-mirror_from=à´¨àµà´±àµ† à´•à´£àµà´£à´¾à´Ÿà´¿
-forked_from=à´²àµâ€ നിനàµà´¨àµà´‚ വഴിപിരിഞàµà´žà´¤àµàµ
-fork_from_self=നിങàµà´™à´³àµà´Ÿàµ† ഉടമസàµà´¥à´¤à´¯à´¿à´²àµà´³àµà´³ ഒരൠശേഖരം നിങàµà´™àµ¾à´•àµà´•àµ ഫോരàµâ€à´•àµà´•àµàµ ചെയàµà´¯à´¾àµ» കഴിയിലàµà´².
-fork_guest_user=à´ˆ ശേഖരം ഫോർകàµà´•àµ ചെയàµà´¯àµà´¨àµà´¨à´¤à´¿à´¨àµ സൈൻ ഇൻ ചെയàµà´¯àµà´•.
-unwatch=à´¶àµà´°à´¦àµà´§à´¿à´•àµà´•à´¾à´¤à´¿à´°à´¿à´¯àµà´•àµà´•àµà´•
-watch=à´¶àµà´°à´¦àµà´§à´¿à´¯àµà´•àµà´•àµà´•
-unstar=നകàµà´·à´¤àµà´°à´‚ നീകàµà´•àµà´•
-star=നകàµà´·à´¤àµà´°à´‚ നലàµâ€à´•àµà´•àµà´•
-fork=ഫോരàµâ€à´•àµà´•àµàµ
-download_archive=കലവറ ഡൗൺലോഡàµà´šàµ†à´¯àµà´¯àµà´•
-
-no_desc=വിവരണം ലഭàµà´¯à´®à´²àµà´²
-quick_guide=à´¦àµà´°àµà´¤ മാരàµâ€à´—ദരàµâ€à´¶à´¨à´‚
-clone_this_repo=à´ˆ കലവറ à´•àµà´²àµ‹àµº ചെയàµà´¯àµà´•
-create_new_repo_command=കമാൻഡൠലൈനàµâ€ വഴി ഒരൠപàµà´¤à´¿à´¯ കലവറ സൃഷàµà´Ÿà´¿à´•àµà´•àµà´•
-push_exist_repo=കമാൻഡൠലൈനിൽ നിനàµà´¨àµ നിലവിലàµà´³àµà´³ ഒരൠകലവറ തളàµà´³à´¿à´•àµà´•à´¯à´±àµà´±àµà´•
-empty_message=à´ˆ കലവറയിലàµâ€ ഉളàµà´³à´Ÿà´•àµà´•à´®àµŠà´¨àµà´¨àµà´‚ à´…à´Ÿà´™àµà´™à´¿à´¯à´¿à´Ÿàµà´Ÿà´¿à´²àµà´².
-
-code=കോഡàµ
-code.desc=ഉറവിട കോഡàµ, ഫയലàµà´•àµ¾, à´•à´®àµà´®à´¿à´±àµà´±àµà´•à´³àµà´‚ ശാഖകളàµà´‚ à´ªàµà´°à´µàµ‡à´¶à´¿à´¯àµà´•àµà´•àµà´•.
-branch=ശാഖ
-tree=മരം
-filter_branch_and_tag=ശാഖ à´…à´²àµà´²àµ†à´™àµà´•à´¿àµ½ ടാഗൠഅരിചàµà´šàµ†à´Ÿàµà´•àµà´•àµà´•
-branches=ശാഖകളàµâ€
-tags=ടാഗàµà´•à´³àµâ€
-issues=à´ªàµà´°à´¶àµà´¨à´™àµà´™àµ¾
-pulls=ലയന à´…à´­àµà´¯àµ¼à´¤àµà´¥à´¨à´•àµ¾
-labels=ലേബലàµà´•à´³àµâ€
-
-milestones=നാഴികകàµà´•à´²àµà´²àµà´•à´³àµâ€
-commits=à´•à´®àµà´®à´¿à´±àµà´±àµà´•à´³àµâ€
-commit=à´•à´®àµà´®à´¿à´±àµà´±àµ
-releases=à´ªàµà´°à´¸à´¿à´¦àµà´§à´ªàµà´ªàµ†à´Ÿàµà´¤àµà´¤àµà´•
-file_raw=കലരàµâ€à´ªàµà´ªà´¿à´²àµà´²à´¾à´¤àµà´¤à´¤àµàµ
-file_history=നാളàµâ€à´µà´´à´¿
-file_view_raw=കലരàµâ€à´ªàµà´ªà´¿à´²àµà´²à´¾à´¤àµ† കാണàµà´•
-file_permalink=à´¸àµà´¥à´¿à´°à´®à´¾à´¯ à´•à´£àµà´£à´¿
-file_too_large=à´ˆ ഫയൽ കാണികàµà´•à´¾àµ» കഴിയാതàµà´¤à´¤àµà´° വലàµà´¤à´¾à´£àµ.
-
-video_not_supported_in_browser=നിങàµà´™à´³àµà´Ÿàµ† à´¬àµà´°àµŒà´¸àµ¼ HTML5 'വീഡിയോ' ടാഗിനെ പിനàµà´¤àµà´£à´¯àµà´•àµà´•àµà´¨àµà´¨à´¿à´²àµà´².
-audio_not_supported_in_browser=നിങàµà´™à´³àµà´Ÿàµ† à´¬àµà´° browser സർ HTML5 'ഓഡിയോ' ടാഗിനെ പിനàµà´¤àµà´£à´¯àµà´•àµà´•àµà´¨àµà´¨à´¿à´²àµà´².
-stored_lfs=à´—à´¿à´±àµà´±àµàµ LFS ഉപയോഗിചàµà´šàµ സംഭരിചàµà´šàµ
-commit_graph=à´•à´®àµà´®à´¿à´±àµà´±àµ à´—àµà´°à´¾à´«àµ
-blame=à´šàµà´®à´¤à´²
-normal_view=സാധാരണ കാഴàµà´š
-
-editor.new_file=à´ªàµà´¤à´¿à´¯ ഫയൽ
-editor.upload_file=ഫയൽ à´…à´ªàµâ€Œà´²àµ‹à´¡àµ
-editor.edit_file=ഫയൽ തിരàµà´¤àµà´¤àµà´•
-editor.preview_changes=മാറàµà´±à´™àµà´™àµ¾ കാണàµà´•
-editor.cannot_edit_lfs_files=വെബൠഇനàµà´±àµ¼à´«àµ‡à´¸à´¿àµ½ LFS ഫയലàµà´•àµ¾ à´Žà´¡à´¿à´±àµà´±àµà´šàµ†à´¯àµà´¯à´¾àµ» കഴിയിലàµà´².
-editor.cannot_edit_non_text_files=വെബൠഇനàµà´±àµ¼à´«àµ‡à´¸à´¿àµ½ ബൈനറി ഫയലàµà´•àµ¾ à´Žà´¡à´¿à´±àµà´±àµà´šàµ†à´¯àµà´¯à´¾àµ» കഴിയിലàµà´².
-editor.edit_this_file=ഫയൽ തിരàµà´¤àµà´¤àµà´•
-editor.must_be_on_a_branch=à´ˆ ഫയലിൽ മാറàµà´±à´™àµà´™àµ¾ വരàµà´¤àµà´¤à´¾à´¨àµ‹ നിർദàµà´¦àµ‡à´¶à´¿à´•àµà´•à´¾à´¨àµ‹ നിങàµà´™àµ¾ à´à´¤àµ†à´™àµà´•à´¿à´²àµà´‚ ഒരൠശാഖയിൽ ആയിരികàµà´•à´£à´‚.
-editor.fork_before_edit=à´ˆ ഫയലിൽ മാറàµà´±à´™àµà´™àµ¾ വരàµà´¤àµà´¤à´¾à´¨àµ‹ നിർദàµà´¦àµ‡à´¶à´¿à´•àµà´•à´¾à´¨àµ‹ നിങàµà´™àµ¾ à´ˆ ശേഖരം ഫോരàµâ€à´•àµà´•àµ ചെയàµà´¤à´¿à´°à´¿à´•àµà´•à´£à´‚.
-editor.delete_this_file=ഫയൽ ഇലàµà´²à´¾à´¤à´¾à´•àµà´•àµà´•
-editor.must_have_write_access=à´ˆ ഫയലിൽ മാറàµà´±à´™àµà´™àµ¾ വരàµà´¤àµà´¤à´¾à´¨àµ‹ നിർദàµà´¦àµ‡à´¶à´¿à´•àµà´•à´¾à´¨àµ‹ നിങàµà´™àµ¾à´•àµà´•àµ à´Žà´´àµà´¤à´¾à´¨àµà´³àµà´³ à´…à´¨àµà´®à´¤à´¿ ഉണàµà´Ÿà´¾à´¯à´¿à´°à´¿à´•àµà´•à´£à´‚.
-editor.file_delete_success=%s ഫയൽ ഇലàµà´²à´¾à´¤à´¾à´•àµà´•à´¿.
-editor.name_your_file=നിങàµà´™à´³àµà´Ÿàµ† ഫയലിനൠപേരൠനൽകàµà´•â€¦
-editor.filename_help=ഒരൠഡയറകàµâ€Œà´Ÿà´±à´¿à´¯àµà´Ÿàµ† പേരൠടൈപàµà´ªàµà´šàµ†à´¯àµâ€Œà´¤àµ à´¸àµà´²à´¾à´·àµà´‚ ('/') ചേർതàµà´¤àµ ചേർകàµà´•àµà´•. ഇൻപàµà´Ÿàµà´Ÿàµ ഫീൽഡിനàµà´±àµ† à´¤àµà´Ÿà´•àµà´•à´¤àµà´¤à´¿àµ½ ബാകàµà´•àµâ€Œà´¸àµâ€Œà´ªàµ†à´¯àµâ€Œà´¸àµ ടൈപàµà´ªàµà´šàµ†à´¯àµâ€Œà´¤àµ ഒരൠഡയറകàµâ€Œà´Ÿà´±à´¿ നീകàµà´•à´‚ചെയàµà´¯àµà´•.
-editor.or=അഥവാ
-editor.cancel_lower=റദàµà´¦à´¾à´•àµà´•àµà´•
-editor.commit_changes=മാറàµà´±à´™àµà´™àµ¾ വരàµà´¤àµà´¤àµà´•
-editor.add_tmpl='<ഫയലàµâ€>' ചേർകàµà´•àµà´•
-editor.add=%s ചേരàµâ€à´•àµà´•àµà´•
-editor.update=%s à´ªàµà´¤àµà´•àµà´•àµà´•
-editor.delete=%s നീകàµà´•à´‚ ചെയàµà´¯àµà´•
-editor.propose_file_change=ഫയലിനàµàµ മാറàµà´±à´™àµà´™à´³àµâ€ നിർദàµà´¦àµ‡à´¶à´¿à´•àµà´•àµà´•
-editor.new_branch_name_desc=à´ªàµà´¤à´¿à´¯ ശാഖയàµà´Ÿàµ† പേരàµàµâ€¦
-editor.cancel=റദàµà´¦à´¾à´•àµà´•àµà´•
-editor.filename_cannot_be_empty=ഫയലിനàµà´±àµ† പേരàµàµ ശൂനàµà´¯à´®à´¾à´¯à´¿à´°à´¿à´•àµà´•à´°àµà´¤àµ.
-editor.add_subdir=ഒരൠഡയറകàµà´Ÿà´±à´¿ ചേർകàµà´•àµà´•â€¦
-editor.upload_files_to_dir=ഫയലàµà´•àµ¾ %s ലേകàµà´•àµ à´…à´ªàµâ€Œà´²àµ‹à´¡àµà´šàµ†à´¯àµà´¯àµà´•
-
-
-
-
-
-issues.new.clear_labels=ലേബലàµà´•àµ¾ മായàµâ€Œà´•àµà´•àµà´•
-issues.new.milestone=നാഴികകàµà´•à´²àµà´²àµ
-issues.new.no_milestone=നാഴികകàµà´•à´²àµà´²àµ ഇലàµà´²
-issues.new.clear_milestone=നാഴികകàµà´•à´²àµà´²àµ à´Žà´Ÿàµà´¤àµà´¤àµ മാറàµà´±àµà´•
-issues.new.open_milestone=നാഴികകàµà´•à´²àµà´²àµà´•àµ¾ à´¤àµà´±à´•àµà´•àµà´•
-issues.new.closed_milestone=à´…à´Ÿà´šàµà´š നാഴികകàµà´•à´²àµà´²àµà´•àµ¾
-issues.new.assignees=നിശàµà´šà´¯à´¿à´•àµà´•àµà´¨àµà´¨à´µà´°àµâ€
-issues.new.clear_assignees=നിശàµà´šà´¯à´¿à´•àµà´•àµà´¨àµà´¨à´µà´°àµ† നീകàµà´•à´‚ ചെയàµà´¯àµà´•
-issues.new.no_assignees=നിശàµà´šà´¯à´¿à´•àµà´•àµà´¨àµà´¨à´µà´°àµâ€ ഇലàµà´²
-issues.no_ref=ശാഖാ അഥവാ ടാഗൠവàµà´¯à´•àµà´¤à´®à´¾à´•àµà´•à´¿à´¯à´¿à´Ÿàµà´Ÿà´¿à´²àµà´²
-issues.create=à´ªàµà´°à´¶àµà´¨à´‚ സൃഷàµà´Ÿà´¿à´•àµà´•àµà´•
-issues.new_label=à´ªàµà´¤à´¿à´¯ അടയാളം
-issues.new_label_placeholder=അടയാള നാമം
-issues.new_label_desc_placeholder=വിരരണം
-issues.create_label=അടയാളം സൃഷàµà´Ÿà´¿à´•àµà´•àµà´•
-issues.label_templates.title=à´®àµàµ»â€Œà´¨à´¿à´¶àµà´šà´¯à´¿à´šàµà´š ഒരൠകൂടàµà´Ÿà´‚ ലേബലàµà´•àµ¾â€Œ നിറയàµâ€Œà´•àµà´•àµà´•
-issues.label_templates.info=ലേബലàµà´•à´³àµŠà´¨àµà´¨àµà´‚ ഇതàµà´µà´°àµ† നിലവിലിലàµà´². 'à´ªàµà´¤à´¿à´¯ ലേബൽ' ഉപയോഗിചàµà´šàµ ഒരൠലേബൽ സൃഷàµà´Ÿà´¿à´•àµà´•àµà´• à´…à´²àµà´²àµ†à´™àµà´•à´¿àµ½ à´®àµàµ»â€Œà´¨à´¿à´¶àµà´šà´¯à´¿à´šàµà´š ലേബൽ സെറàµà´±àµ ഉപയോഗികàµà´•àµà´•:
-issues.label_templates.helper=ഒരൠലേബൽ സെറàµà´±àµ തിരഞàµà´žàµ†à´Ÿàµà´•àµà´•àµà´•
-issues.label_templates.use=ലേബൽ സെറàµà´±àµ ഉപയോഗികàµà´•àµà´•
-issues.deleted_milestone=`(ഇലàµà´²à´¾à´¤à´¾à´•àµà´•à´¿)`
-issues.filter_type.all_issues=à´Žà´²àµà´²à´¾ ഇഷàµà´¯àµ‚à´•à´³àµà´‚
-issues.label_open_issues=%d à´¤àµà´±à´¨àµà´¨à´¨à´¿à´²à´¯à´¿à´²àµà´³àµà´³ ഇഷàµà´¯àµ‚à´•à´³àµâ€
-issues.label_deletion_desc=ഒരൠലേബൽ ഇലàµà´²à´¾à´¤à´¾à´•àµà´•à´¿à´¯à´¾à´²àµâ€, à´…à´¤àµàµ നിയàµà´•à´¤à´®à´¾à´•àµà´•à´¿à´¯ à´Žà´²àµà´²à´¾ ഇഷàµà´¯àµ‚കളിലàµâ€ നിനàµà´¨àµà´‚ നീകàµà´•à´‚ചെയàµà´¯àµà´‚. à´¤àµà´Ÿà´°à´Ÿàµà´Ÿàµ†?
-issues.dependency.issue_close_blocks=à´ˆ ഇഷàµà´¯àµ à´…à´Ÿà´¯àµâ€Œà´•àµà´•àµà´¨àµà´¨à´¤àµ ഇനിപàµà´ªà´±à´¯àµà´¨àµà´¨ ഇഷàµà´¯àµ‚à´•à´³àµâ€ തടയàµà´¨àµà´¨àµàµ
-issues.dependency.pr_close_blocks=à´ˆ ഇഷàµà´¯àµ‚à´•à´³àµâ€ à´…à´Ÿà´¯àµâ€Œà´•àµà´•àµà´¨àµà´¨à´¤àµ à´ˆ ലയന à´…à´­àµà´¯à´°àµâ€à´¤àµà´¥à´¨ തടയàµà´¨àµà´¨àµàµ
-issues.dependency.issue_close_blocked=à´ˆ ഇഷàµà´¯àµ‚ à´…à´Ÿà´¯àµâ€Œà´•àµà´•àµà´¨àµà´¨à´¤à´¿à´¨àµ à´®àµà´®àµà´ªàµ ഇതിനെ തടയàµà´¨àµà´¨ à´Žà´²àµà´²à´¾ ഇഷàµà´¯àµ‚à´•à´³àµà´‚ നിങàµà´™àµ¾ à´…à´Ÿà´¯àµâ€Œà´•àµà´•àµ‡à´£àµà´Ÿà´¤àµà´£àµà´Ÿàµ.
-issues.dependency.pr_close_blocked=à´ˆ ലയന à´…à´­àµà´¯à´°àµâ€à´¤àµà´¥à´¨ à´¸àµà´¥à´¿à´°àµ€à´•à´°à´¿à´¯àµà´•àµà´•àµà´¨àµà´¨à´¤à´¿à´¨àµ à´®àµà´®àµà´ªàµ ഇതിനെ തടയàµà´¨àµà´¨ à´Žà´²àµà´²à´¾ ഇഷàµà´¯àµ‚à´•à´³àµà´‚ നിങàµà´™àµ¾ à´…à´Ÿà´¯àµâ€Œà´•àµà´•àµ‡à´£àµà´Ÿà´¤àµà´£àµà´Ÿàµ.
-issues.dependency.setting=ലയന à´…à´­àµà´¯à´°àµâ€à´¤àµà´¥à´¨à´•à´³àµâ€à´•àµà´•àµà´‚ ഇഷàµà´¯àµ‚à´•à´³àµâ€à´•àµà´•àµà´®à´¾à´¯à´¿ ആശàµà´°à´¿à´¤à´¤àµà´µà´‚ സജàµà´œà´®à´¾à´•àµà´•àµà´•
-issues.dependency.add_error_cannot_create_circular=à´°à´£àµà´Ÿàµ ഇഷàµà´¯àµ‚à´•à´³àµà´‚ പരസàµà´ªà´°à´‚ തടയàµà´¨àµà´¨à´¤à´¾à´•àµà´¨àµà´¨à´¤à´¿à´²àµ‚ടെ നിങàµà´™àµ¾à´•àµà´•àµ ഒരൠആശàµà´°à´¯à´¤àµà´µà´‚ സൃഷàµà´Ÿà´¿à´•àµà´•à´¾àµ» കഴിയിലàµà´².
-issues.dependency.add_error_dep_not_same_repo=à´°à´£àµà´Ÿàµ à´ªàµà´°à´¶àµà´¨à´™àµà´™à´³àµà´‚ ഒരേ കലവറയിലേതàµàµ ആയിരികàµà´•à´£à´‚.
-
-
-
-
-; </summary><code>%[2]s<br>%[3]s</code></details>
-
-
-
-
-
-milestones.filter_sort.most_issues=മികàµà´• ഇഷàµà´¯àµ‚à´•à´³àµà´‚
-milestones.filter_sort.least_issues=à´•àµà´±à´žàµà´ž ഇഷàµà´¯àµ‚കളെങàµà´•à´¿à´²àµà´‚
-
-
-
-
-activity.active_issues_count_n=<strong>%d</strong> സജàµà´œàµ€à´µ ഇഷàµà´¯àµ‚à´•à´³àµâ€
-activity.closed_issues_count_n=à´…à´Ÿà´šàµà´š ഇഷàµà´¯àµ‚à´•à´³àµâ€
-activity.title.issues_n=%d ഇഷàµà´¯àµ‚à´•à´³àµâ€
-activity.new_issues_count_n=à´ªàµà´¤à´¿à´¯ ഇഷàµà´¯àµ‚à´•à´³àµâ€
-
-
-settings.event_issues=ഇഷàµà´¯àµ‚à´•à´³àµâ€
-
-
-
-
-
-
-
-
-
-[org]
-
-
-
-
-
-
-
-[admin]
-
-
-
-
-
-repos.issues=ഇഷàµà´¯àµ‚à´•à´³àµâ€
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-[action]
-
-[tool]
-
-[dropzone]
-
-[notification]
-
-[gpg]
-
-[units]
-
-[packages]
-
diff --git a/options/locale/locale_nl-NL.ini b/options/locale/locale_nl-NL.ini
index 294ba7e34..450df1c3a 100644
--- a/options/locale/locale_nl-NL.ini
+++ b/options/locale/locale_nl-NL.ini
@@ -57,7 +57,6 @@ new_mirror=Nieuwe kopie
new_fork=Nieuwe Repository Fork
new_org=Nieuwe organisatie
new_project=Nieuw project
-new_project_board=Nieuw projectbord
manage_org=Beheer organisaties
admin_panel=Website Administratie
account_settings=Accountinstellingen
@@ -86,6 +85,9 @@ remove=Verwijder
remove_all=Alles verwijderen
edit=Bewerk
+enabled=Ingeschakeld
+disabled=Uitgeschakeld
+
copy=Kopieer
copy_url=Kopieer URL
copy_branch=Kopieer branchnaam
@@ -106,6 +108,8 @@ never=Nooit
rss_feed=RSS Feed
+[aria]
+
[filter]
[error]
@@ -224,7 +228,6 @@ internal_token_failed=Interne token genereren mislukt: %v
secret_key_failed=Geheime sleutel genereren mislukt: %v
save_config_failed=Kan de configuratie niet opslaan: %v
invalid_admin_setting=Instelling van de administrator-account is ongeldig: %v
-install_success=Welkom! Bedankt dat u voor Gitea heeft gekozen. Veel plezier en succes ermee!
invalid_log_root_path=Ongeldig log-pad: %v
default_keep_email_private=Verberg standaard alle e-mailadressen
default_keep_email_private_popup=Verberg standaard de email-adressen van nieuwe gebruikers.
@@ -250,7 +253,7 @@ view_home=Bekijk %s
search_repos=Zoek een repository…
filter=Andere filters
filter_by_team_repositories=Filter op team repositories
-feed_of=Feed van "%s"
+feed_of=`Feed van "%s"`
show_archived=Gearchiveerd
show_both_archived_unarchived=Toont zowel gearchiveerd als niet-gearchiveerd
@@ -489,14 +492,14 @@ cannot_add_org_to_team=Een organisatie kan niet worden toegevoegd als een teamli
invalid_ssh_key=Kan de SSH-sleutel niet verifiëren: %s
invalid_gpg_key=Kan de GPG-sleutel niet verifiëren: %s
invalid_ssh_principal=Ongeldige verantwoordelijke: %s
-unable_verify_ssh_key=Kan de SSH-sleutel niet verifiëren; controleer hem op fouten.
+unable_verify_ssh_key=Kan de SSH-sleutel niet verifiëren
auth_failed=Verificatie mislukt: %v
still_own_repo=Je account is nog eigenaar van één of meerdere repositories. Deze moeten eerst verwijderd of overgedragen worden.
still_has_org=Je account is lid van één of meerdere organisaties. Verlaat deze eerst.
-still_own_packages=Uw account bezit één of meer pakketten; verwijder deze eerst.
+still_own_packages=Uw account bezit één of meer pakketten
org_still_own_repo=Deze organisatie bezit minstens één repositories. Verwijder deze of draag deze eerst over.
-org_still_own_packages=Deze organisatie is nog eigenaar van één of meer pakketten; verwijder deze eerst.
+org_still_own_packages=Deze organisatie is nog eigenaar van één of meer pakketten
target_branch_not_exist=Doel branch bestaat niet
@@ -786,6 +789,7 @@ remove_account_link=Gekoppeld account verwijderen
remove_account_link_desc=Als je een gekoppeld account verwijdert, verliest dit account toegang tot je Gitea-account. Doorgaan?
remove_account_link_success=Het gekoppelde account is verwijderd.
+
orgs_none=U bent geen lid van een organisatie.
repos_none=U bezit geen repositories
@@ -897,9 +901,9 @@ delete_preexisting_success=Niet-geadopteerde bestanden verwijderd in %s
blame_prior=Bekijk de schuld voorafgaand aan deze verandering
transfer.accept=Accepteer overdracht
-transfer.accept_desc=Overmaken naar "%s"
+transfer.accept_desc=`Overmaken naar "%s"`
transfer.reject=Overdracht afwijzen
-transfer.reject_desc=Annuleer overdracht naar "%s"
+transfer.reject_desc=`Annuleer overdracht naar "%s"`
transfer.no_permission_to_accept=Je hebt geen toestemming om te accepteren
transfer.no_permission_to_reject=Je hebt geen toestemming om te weigeren
@@ -1148,7 +1152,6 @@ commits.signed_by_untrusted_user_unmatched=Ondertekend door niet-vertrouwde gebr
commits.gpg_key_id=GPG sleutel-ID
commits.ssh_key_fingerprint=SSH sleutel vingerafdruk
-commit.actions=Acties
commit.revert=Ongedaan maken
commit.revert-header=Maak %s ongedaan
commit.revert-content=Selecteer een branch om terug te zetten:
@@ -1181,19 +1184,11 @@ projects.type.bug_triage=Bug Triage
projects.template.desc=Project sjabloon
projects.template.desc_helper=Selecteer een projecttemplate om aan de slag te gaan
projects.type.uncategorized=Ongecategoriseerd
-projects.board.edit=Bord bewerken
-projects.board.edit_title=Nieuwe boardnaam
-projects.board.new_title=Nieuwe boardnaam
-projects.board.new_submit=Versturen
-projects.board.new=Nieuw bord
-projects.board.set_default=Instellen als standaard
-projects.board.set_default_desc=Stel dit board in als standaard voor niet gecategoriseerde issues en pulls
-projects.board.delete=Verwijder bord
-projects.board.deletion_desc=Als een projectbord wordt verwijdert, worden alle gerelateerde kwesties naar 'Ongecategoriseerd' verplaatst. Doorgaan?
-projects.board.color=Kleur
+projects.column.edit_title=Naam
+projects.column.new_title=Naam
+projects.column.color=Kleur
projects.open=Open
projects.close=Sluiten
-projects.board.assigned_to=Toegewezen aan
issues.desc=Organiseer bugrapporten, taken en mijlpalen.
issues.filter_assignees=Filter verantwoordelijke
@@ -1267,6 +1262,8 @@ issues.filter_label_exclude=`Gebruik <code>alt</code> + <code>klik/voer</code> i
issues.filter_label_no_select=Alle labels
issues.filter_milestone=Mijlpaal
issues.filter_milestone_no_select=Alle mijlpalen
+issues.filter_project=Project
+issues.filter_project_none=Geen project
issues.filter_assignee=Aangewezene
issues.filter_assginee_no_select=Alle toegewezen personen
issues.filter_poster=Auteur
@@ -1418,6 +1415,7 @@ issues.error_removing_due_date=Deadline verwijderen mislukt.
issues.push_commit_1=toegevoegd %d commit %s
issues.push_commits_n=toegevoegd %d commits %s
issues.force_push_codes=`force-push %[1]s van <a class="ui sha" href="%[3]s"><code>%[2]s</code></a> naar <a class="ui sha" href="%[5]s"><code>%[4]s</code></a> %[6]s`
+issues.force_push_compare=Vergelijk
issues.due_date_form=jjjj-mm-dd
issues.due_date_form_add=Vervaldatum toevoegen
issues.due_date_form_edit=Bewerk
@@ -1813,40 +1811,8 @@ settings.enable_timetracker=Tijdregistratie inschakelen
settings.allow_only_contributors_to_track_time=Sta alleen bijdragers toe tijdregistratie te gebruiken
settings.pulls_desc=Repository-pull-aanvragen inschakelen
settings.pulls.ignore_whitespace=Witruimte negeren voor conflicten
-settings.pulls.allow_merge_commits=Samenvoegen van commits inschakelen
-settings.pulls.allow_rebase_merge=Rebasen om samen te voegen inschakelen
-settings.pulls.allow_rebase_merge_commit=Samenvoegen met expliciete samenvoegingscommits (--no-ff) inschakelen
-settings.pulls.allow_squash_commits="Squash"-en om samen te voegen inschakelen
-settings.projects_desc=Repository-projecten inschakelen
-settings.admin_settings=Beheerdersinstellingen
-settings.admin_enable_health_check=Repositoryintegriteitschecks ingeschakelen (git fsck)
-settings.admin_enable_close_issues_via_commit_in_any_branch=Sluit een issue via een commit gemaakt in een niet-standaard branch
-settings.danger_zone=Gevaren zone
-settings.new_owner_has_same_repo=De nieuwe eigenaar heeft al een repository met deze naam
-settings.convert=Converteren naar gewone repository
-settings.convert_desc=U kunt deze kopie converteren naar een gewone repository. Dit kan niet ongedaan worden gemaakt.
-settings.convert_notices_1=Deze operatie zet de kopie repository om in een gewone repository en dit kan niet ongedaan gemaakt worden.
-settings.convert_confirm=Converteer Repository
-settings.convert_succeed=De mirror is omgezet in een gewone repository.
-settings.convert_fork=Converteren naar gewone repository
-settings.convert_fork_desc=U kunt deze fork converteren naar een gewone repository. Dit kan niet ongedaan worden gemaakt.
-settings.convert_fork_notices_1=Deze operatie zet de fork om in een gewone repository en dit kan niet ongedaan gemaakt worden.
-settings.convert_fork_confirm=Converteer Repository
-settings.convert_fork_succeed=De fork is omgezet in een gewone repository.
-settings.transfer=Eigendom overdragen
-settings.transfer_desc=Draag deze repo over aan een andere gebruiker of een organisatie waar u beheerders rechten heeft.
-settings.transfer_form_title=Voer de repository naam in als bevestiging:
-settings.transfer_notices_1=- U verliest de toegang tot de repository als u deze overdraagt aan een individuele gebruiker.
-settings.transfer_notices_2=- U behoudt toegang tot de repository als u deze overdraag aan een organisatie waar u (mede)eigenaar van bent.
-settings.transfer_owner=Nieuwe eigenaar
-settings.transfer_succeed=De repository is overgedragen.
-settings.signing_settings=Ondertekening verificatie Instellingen
-settings.trust_model=Handtekening vertrouwensmodel
-settings.trust_model.default=Standaard vertrouwensmodel
-settings.trust_model.default.desc=Gebruik het standaard repository vertrouwensmodel voor deze installatie.
settings.trust_model.collaborator=Medewerker
settings.trust_model.collaborator.long=Medewerker: Vertrouw handtekeningen door medewerkers
-settings.trust_model.collaborator.desc=Geldige handtekeningen door medewerkers van deze repository worden gemarkeerd als "vertrouwd" - (ongeacht of ze overeenkomen met de committer of niet). Anders worden geldige handtekeningen gemarkeerd als "niet vertrouwd" als de handtekening overeenkomt met de committer en "niet overeenkomend" als dat niet het geval is.
settings.trust_model.committer=Committer
settings.trust_model.committer.long=Committer: Vertrouw handtekeningen die overeenkomen met committers (Dit komt overeen met GitHub en zal Gitea ondertekende commits dwingen om Gitea als de committer te hebben)
settings.trust_model.committer.desc=Geldige handtekeningen worden alleen gemarkeerd als "vertrouwd" als ze overeenkomen met de committer, anders worden ze gemarkeerd als "niet overeenkomend". Dit zal Gitea dwingen om de committer te zijn aan ondertekende commits met de eigenlijke committer gemarkeerd als Co-Authored-By: en Co-Committed-By: trailer in de commit. De standaard Gitea-sleutel moet overeenkomen met een gebruiker in de database.
@@ -1923,6 +1889,7 @@ settings.event_delete=Verwijder
settings.event_delete_desc=Branch of tag verwijderd.
settings.event_fork=Fork
settings.event_fork_desc=Repository geforked.
+settings.event_wiki=Wiki
settings.event_release=Release
settings.event_release_desc=Release gepubliceerd, bijgewerkt of verwijderd in een repository.
settings.event_push=Push
@@ -2069,7 +2036,6 @@ settings.bot_token=Bot Token
settings.chat_id=Chat-ID
settings.matrix.homeserver_url=Homeserver URL
settings.matrix.room_id=Kamer ID
-settings.matrix.access_token=Toegangstoken
settings.matrix.message_type=Bericht type
settings.archive.button=Repo archiveren
settings.archive.header=Deze Repo archiveren
@@ -2242,7 +2208,7 @@ org_full_name_holder=Volledige naam organisatie
org_name_helper=Organisatienamen horen kort en memorabel zijn.
create_org=Nieuwe organisatie aanmaken
repo_updated=Geupdate
-people=Mensen
+members=Leden
teams=Teams
lower_members=leden
lower_repositories=repositories
@@ -2307,6 +2273,7 @@ teams.join=Lid worden
teams.leave=Vertlaat
teams.can_create_org_repo=Maak repositories
teams.can_create_org_repo_helper=Leden kunnen nieuwe repositories aanmaken in de organisatie. De maker krijgt beheerder toegang tot de nieuwe repository.
+teams.read_access=Gelezen
teams.read_access_helper=Leden kunnen teamrepositories bekijken en klonen.
teams.write_access_helper=Leden kunnen lezen en pushen naar teamrepositories.
teams.admin_access=Beheerder toegang
@@ -2466,6 +2433,7 @@ users.list_status_filter.menu_text=Filter
users.list_status_filter.is_active=Actief
users.list_status_filter.not_active=Inactief
users.list_status_filter.is_admin=Beheerder
+users.list_status_filter.is_restricted=Beperkt
emails.email_manage_panel=Gebruikers e-mail beheer
emails.primary=Primair
@@ -2498,6 +2466,11 @@ repos.forks=Forks
repos.issues=Kwesties
repos.size=Grootte
+packages.owner=Eigenaar
+packages.name=Naam
+packages.type=Type
+packages.repository=Opslagplaats
+packages.size=Grootte
systemhooks=Systeem webhooks
@@ -2566,14 +2539,14 @@ auths.sspi_default_language_helper=Standaardtaal voor gebruikers wordt automatis
auths.tips=Tips
auths.tips.oauth2.general=OAuth2 authenticatie
auths.tip.oauth2_provider=OAuth2 Provider
-auths.tip.nextcloud=Registreer een nieuwe OAuth consument op je installatie met behulp van het volgende menu "Instellingen -> Security -> OAuth 2.0 client"
+auths.tip.nextcloud=`Registreer een nieuwe OAuth consument op je installatie met behulp van het volgende menu "Instellingen -> Security -> OAuth 2.0 client"`
auths.tip.dropbox=Maak een nieuwe applicatie aan op https://www.dropbox.com/developers/apps
auths.tip.facebook=Registreer een nieuwe applicatie op https://developers.facebook.com/apps en voeg het product "Facebook Login" toe
auths.tip.github=Registreer een nieuwe OAuth toepassing op https://github.com/settings/applications/new
auths.tip.gitlab=Registreer een nieuwe applicatie op https://gitlab.com/profile/applicaties
auths.tip.google_plus=Verkrijg OAuth2 client referenties van de Google API console op https://console.developers.google.com/
auths.tip.openid_connect=Gebruik de OpenID Connect Discovery URL (<server>/.well-known/openid-configuration) om de eindpunten op te geven
-auths.tip.yandex=Maak een nieuwe applicatie aan op https://oauth.yandex.com/client/new. Selecteer de volgende machtigingen van de "Yandex". assport API" sectie: "Toegang tot e-mailadres", "Toegang tot avatar" en "Toegang tot gebruikersnaam, voornaam en achternaam, geslacht"
+auths.tip.yandex=`Maak een nieuwe applicatie aan op https://oauth.yandex.com/client/new. Selecteer de volgende machtigingen van de "Yandex". assport API" sectie: "Toegang tot e-mailadres", "Toegang tot avatar" en "Toegang tot gebruikersnaam, voornaam en achternaam, geslacht"`
auths.edit=Authenticatiebron bewerken
auths.activated=Deze authenticatiebron is geactiveerd
auths.new_success=De authenticatie-bron '%s' is toegevoegd.
@@ -2779,7 +2752,6 @@ monitor.queue.pool.cancel_notices=Deze groep van %s workers afsluiten?
notices.system_notice_list=Systeem aankondigingen
notices.view_detail_header=Bekijk notificatie details
-notices.actions=Acties
notices.select_all=Alles selecteren
notices.deselect_all=Alles deselecteren
notices.inverse_selection=Selectie omkeren
@@ -2855,8 +2827,29 @@ error.no_unit_allowed_repo=U heeft geen toegang tot een enkele sectie van deze r
error.unit_not_allowed=U heeft geen toegang tot deze sectie van de repository.
[packages]
+filter.type=Type
assets=Assets
+conan.details.repository=Opslagplaats
rubygems.required.ruby=Vereist Ruby versie
rubygems.required.rubygems=Vereist RubyGem versie
settings.link.button=Repository link bijwerken
+owner.settings.cleanuprules.enabled=Ingeschakeld
+
+[secrets]
+name=Naam
+
+[actions]
+
+
+
+runners.name=Naam
+runners.owner_type=Type
+runners.description=Omschrijving
+runners.task_list.run=Uitvoeren
+runners.task_list.repository=Opslagplaats
+runners.task_list.commit=Commit
+runners.status.active=Actief
+
+runs.commit=Commit
+
diff --git a/options/locale/locale_pl-PL.ini b/options/locale/locale_pl-PL.ini
index 8d2b7461d..e43e7a554 100644
--- a/options/locale/locale_pl-PL.ini
+++ b/options/locale/locale_pl-PL.ini
@@ -40,7 +40,7 @@ webauthn_use_twofa=Użyj kodu uwierzytelniania dwuskładnikowego ze swojego tele
webauthn_error=Nie można odczytać Twojego klucza bezpieczeństwa.
webauthn_unsupported_browser=Twoja przeglądarka nie obsługuje obecnie WebAuthn.
webauthn_error_unknown=Wystąpił nieznany błąd. Spróbuj ponownie.
-webauthn_error_insecure=WebAuthn obsługuje tylko bezpieczne połączenia. Do testowania przez HTTP można użyć "localhost" lub "127.0.0.1"
+webauthn_error_insecure=`WebAuthn obsługuje tylko bezpieczne połączenia. Do testowania przez HTTP można użyć "localhost" lub "127.0.0.1"`
webauthn_error_unable_to_process=Serwer nie mógł obsłużyć Twojego żądania.
webauthn_error_duplicated=Klucz bezpieczeństwa nie jest dozwolony dla tego żądania. Upewnij się, że klucz nie jest już zarejestrowany.
webauthn_error_empty=Musisz ustawić nazwę dla tego klucza.
@@ -56,7 +56,6 @@ new_mirror=Nowa kopia lustrzana
new_fork=Nowy fork repozytorium
new_org=Nowa organizacja
new_project=Nowy projekt
-new_project_board=Tablica nowego projektu
manage_org=ZarzÄ…dzaj organizacjami
admin_panel=Administracja witryny
account_settings=Ustawienia konta
@@ -85,6 +84,9 @@ remove=Usuń
remove_all=Usuń wszystko
edit=Edytuj
+enabled=WÅ‚Ä…czone
+disabled=Wyłączone
+
copy=Kopiuj
copy_url=Kopiuj adres URL
copy_branch=Kopiuj nazwę gałęzi
@@ -104,6 +106,8 @@ error404=Strona, do której próbujesz dotrzeć <strong>nie istnieje</strong> lu
never=Nigdy
+[aria]
+
[filter]
[error]
@@ -178,6 +182,8 @@ log_root_path_helper=Pliki logów będą zapisywane w tym katalogu.
optional_title=Ustawienia opcjonalne
email_title=Ustawienia e-mail
+smtp_addr=Serwer SMTP
+smtp_port=Port SMTP
smtp_from=Wyślij e-mail jako
smtp_from_helper=Adres e-mail, z którego Gitea będzie korzystać. Wpisz prosty adres e-mail, lub użyj formatu "Nazwa" <email@example.com>.
mailer_user=Nazwa użytkownika SMTP
@@ -220,7 +226,6 @@ internal_token_failed=Nie udało się wygenerować tokenu wewnętrznego: %v
secret_key_failed=Nie udało się wygenerować tajnego klucza: %v
save_config_failed=Nie udało się zapisać konfiguracji: %v
invalid_admin_setting=Nieprawidłowe ustawienia konta administratora: %v
-install_success=Witaj! Dziękujemy za wybranie Gitea. Miłej zabawy i trzymaj się!
invalid_log_root_path=Ścieżka dla logów jest niepoprawna: %v
default_keep_email_private=Domyślne ukrywanie adresów e-mail
default_keep_email_private_popup=Domyślnie ukrywaj adresy e-mail nowych kont użytkowników.
@@ -246,7 +251,7 @@ view_home=Zobacz %s
search_repos=Znajdź repozytorium…
filter=Inne filtry
filter_by_team_repositories=Filtruj według repozytoriów zespołu
-feed_of=Kanał "%s"
+feed_of=`Kanał "%s"`
show_archived=Zarchiwizowane
show_both_archived_unarchived=Wyświetlanie zarchiwizowanych i niezarchiwizowanych
@@ -537,6 +542,7 @@ continue=Kontynuuj
cancel=Anuluj
language=Język
ui=Motyw
+comment_type_group_title=Tytuł
privacy=Prywatność
keep_activity_private=Ukryj moją aktywność na stronie profilu
keep_activity_private_popup=Aktywność staje się widoczna tylko dla Ciebie i administratorów
@@ -675,6 +681,8 @@ generate_token_success=Twój nowy token został wygenerowany. Skopiuj go teraz,
generate_token_name_duplicate=<strong>%s</strong> istnieje już jako nazwa aplikacji. Użyj nowej.
delete_token=Usuń
access_token_deletion=Usuń token dostępu
+access_token_deletion_cancel_action=Anuluj
+access_token_deletion_confirm_action=Usuń
delete_token_success=Token został usunięty. Aplikacje używające go nie będą miały już dostępu do Twojego konta.
manage_oauth2_applications=ZarzÄ…dzaj aplikacjami OAuth2
@@ -731,10 +739,12 @@ webauthn_delete_key_desc=Jeżeli usuniesz klucz bezpieczeństwa, utracisz możli
manage_account_links=ZarzÄ…dzaj powiÄ…zanymi kontami
manage_account_links_desc=Te konta zewnętrzne są powiązane z Twoim kontem Gitea.
account_links_not_available=Obecnie nie ma żadnych zewnętrznych kont powiązanych z tym kontem Gitea.
+link_account=Powiąż konto
remove_account_link=Usuń powiązane konto
remove_account_link_desc=Usunięcie powiązanego konta unieważni jego dostęp do Twojego konta Gitea. Kontynuować?
remove_account_link_success=Powiązane konto zostało odłączone.
+
orgs_none=Nie jesteś członkiem żadnej organizacji.
repos_none=Nie posiadasz żadnych repozytoriów
@@ -833,9 +843,9 @@ delete_preexisting_content=Usuń pliki w %s
delete_preexisting_success=Usunięto nieprzyjęte pliki w %s
transfer.accept=Akceptuj transfer
-transfer.accept_desc=PrzenieÅ› do "%s"
+transfer.accept_desc=`PrzenieÅ› do "%s"`
transfer.reject=Odrzuć transfer
-transfer.reject_desc=Anuluj transfer do "%s"
+transfer.reject_desc=`Anuluj transfer do "%s"`
transfer.no_permission_to_accept=Nie masz uprawnień do akceptacji
transfer.no_permission_to_reject=Nie masz uprawnień do odrzucenia
@@ -1081,16 +1091,9 @@ projects.type.bug_triage=Bug Triage
projects.template.desc=Szablon projektu
projects.template.desc_helper=Wybierz szablon projektu do rozpoczęcia
projects.type.uncategorized=Bez kategorii
-projects.board.edit=Edytuj tablicÄ™
-projects.board.edit_title=Nazwa nowej tablicy
-projects.board.new_title=Nazwa nowej tablicy
-projects.board.new_submit=Zatwierdź
-projects.board.new=Nowa tablica
-projects.board.set_default=Ustaw domyślne
-projects.board.set_default_desc=Ustaw ten dział jako domyślny dla niekategoryzowanych problemów i pullów
-projects.board.delete=Usuń tablicę
-projects.board.deletion_desc=Usunięcie tablicy projektowej przeniesie wszystkie powiązane zagadnienia do "Nieskategoryzowanych". Kontynuować?
-projects.board.color=Kolor
+projects.column.edit_title=Nazwa
+projects.column.new_title=Nazwa
+projects.column.color=Kolor
projects.open=Otwórz
projects.close=Zamknij
@@ -1163,6 +1166,7 @@ issues.filter_label_exclude=`Użyj <code>Alt</code> + <code>Kliknij/Enter</code>
issues.filter_label_no_select=Wszystkie etykiety
issues.filter_milestone=Kamień milowy
issues.filter_milestone_no_select=Wszystkie kamienie milowe
+issues.filter_project_none=Brak projektu
issues.filter_assignee=Przypisany
issues.filter_assginee_no_select=Wszyscy przypisani
issues.filter_type=Typ
@@ -1195,6 +1199,7 @@ issues.previous=Poprzedni
issues.next=Następny
issues.open_title=Otwarty
issues.closed_title=Zamknięty
+issues.draft_title=Szkic
issues.num_comments=%d komentarzy
issues.commented_at=`skomentował(-a) <a href="#%s">%s</a>`
issues.delete_comment_confirm=Czy na pewno chcesz usunąć ten komentarz?
@@ -1267,6 +1272,7 @@ issues.lock.reason=Powód blokady
issues.lock.title=Zablokuj konwersację w tym zgłoszeniu.
issues.unlock.title=Odblokuj konwersację w tym zgłoszeniu.
issues.comment_on_locked=Nie możesz umieszczać komentarzy pod zablokowanym zgłoszeniem.
+issues.delete=Usuń
issues.tracker=Åšledzenie czasu
issues.start_tracking=Rozpocznij śledzenie czasu
issues.start_tracking_history=`rozpoczął(-ęła) pracę nad %s`
@@ -1291,6 +1297,7 @@ issues.error_modifying_due_date=Nie udało się zmodyfikować terminu realizacji
issues.error_removing_due_date=Nie udało się usunąć terminu realizacji.
issues.push_commit_1=dodał(-a) %d commit %s
issues.push_commits_n=dodał(-a) %d commity(-ów) %s
+issues.force_push_compare=Porównaj
issues.due_date_form=yyyy-mm-dd
issues.due_date_form_add=Dodaj termin realizacji
issues.due_date_form_edit=Edytuj
@@ -1585,6 +1592,7 @@ search.search_repo=Przeszukaj repozytorium
search.fuzzy=Fuzzy
search.match=Dopasuj
search.results=Wyniki wyszukiwania dla "%s" w <a href="%s">%s</a>
+search.code_no_results=Nie znaleziono kodu źródłowego odpowiadającego Twojej frazie wyszukiwania.
settings=Ustawienia
settings.desc=Ustawienia to miejsce, w którym możesz zmieniać parametry repozytorium
@@ -1635,10 +1643,6 @@ settings.enable_timetracker=Włącz śledzenie czasu
settings.allow_only_contributors_to_track_time=Zezwalaj wyłącznie współpracownikom na śledzenie czasu
settings.pulls_desc=WÅ‚Ä…cz Pull Requesty w repozytorium
settings.pulls.ignore_whitespace=Ignoruj znaki białe w konfliktach
-settings.pulls.allow_merge_commits=WÅ‚Ä…cz scalanie poprzez commity
-settings.pulls.allow_rebase_merge=Włącz zmianę bazy do scalania commitów
-settings.pulls.allow_rebase_merge_commit=WÅ‚Ä…cz zmianÄ™ bazy ze stworzeniem commita ze scaleniem (--no-ff)
-settings.pulls.allow_squash_commits=Włącz miażdżenie do scalania commitów
settings.projects_desc=WÅ‚Ä…cz projekty w repozytorium
settings.admin_settings=Ustawienia administratora
settings.admin_enable_health_check=Włącz sprawdzanie stanu zdrowia repozytoriów (git fsck)
@@ -1669,7 +1673,7 @@ settings.transfer_notices_2=- Utrzymasz dostęp do tego repozytorium, jeśli prz
settings.transfer_notices_3=- Jeśli repozytorium jest prywatne i jest przenoszone do indywidualnego użytkownika, ta czynność upewnia się, że użytkownik ma co najmniej uprawnienia do odczytu (i w razie potrzeby zmienia uprawnienia).
settings.transfer_owner=Nowy właściciel
settings.transfer_perform=Wykonaj transfer
-settings.transfer_started=To repozytorium zostało oznaczone do transferu i oczekuje na potwierdzenie od "%s"
+settings.transfer_started=`To repozytorium zostało oznaczone do transferu i oczekuje na potwierdzenie od "%s"`
settings.transfer_succeed=Repozytorium zostało przeniesione.
settings.signing_settings=Ustawienia weryfikacji podpisu
settings.trust_model=Model zaufania do podpisu
@@ -1738,6 +1742,7 @@ settings.content_type=Typ zawartości POST
settings.secret=Sekret
settings.slack_username=Użytkownik
settings.slack_icon_url=Adres URL ikony
+settings.slack_color=Kolor
settings.discord_username=Nazwa użytkownika
settings.discord_icon_url=Adres URL ikony
settings.event_desc=Wywołaj przy:
@@ -1751,6 +1756,7 @@ settings.event_delete=Usuń
settings.event_delete_desc=Gałąź lub tag usunięty.
settings.event_fork=Fork
settings.event_fork_desc=Repozytorium sforkowane.
+settings.event_wiki=Wiki
settings.event_release=Wydanie
settings.event_release_desc=Wydanie opublikowane, zaktualizowane lub usunięte z repozytorium.
settings.event_push=Wypchnięcie
@@ -1814,7 +1820,7 @@ settings.protected_branch=Ochrona gałęzi
settings.protected_branch_can_push=Umożliwić push?
settings.protected_branch_can_push_yes=Możesz wysyłać
settings.protected_branch_can_push_no=Nie możesz wysyłać
-settings.branch_protection=Ochrona gałęzi dla "<b>%s</b>"
+settings.branch_protection=`Ochrona gałęzi dla "<b>%s</b>"`
settings.protect_this_branch=Włącz ochronę gałęzi
settings.protect_this_branch_desc=Zapobiega usunięciu oraz ogranicza wypychanie i scalanie zmian do tej gałęzi.
settings.protect_disable_push=Wyłącz wypychanie
@@ -1878,7 +1884,6 @@ settings.bot_token=Token bota
settings.chat_id=ID czatu
settings.matrix.homeserver_url=Adres URL serwera domowego
settings.matrix.room_id=ID pokoju
-settings.matrix.access_token=Token dostępu
settings.matrix.message_type=Typ wiadomości
settings.archive.button=Zarchiwizuj repozytorium
settings.archive.header=Zarchiwizuj to repozytorium
@@ -2035,6 +2040,7 @@ branch.included_desc=Ta gałąź jest częścią domyślnej gałęzi
branch.included=Zawarte
branch.create_new_branch=Utwórz branch z branch'a:
branch.confirm_create_branch=Utwórz gałąź
+branch.create_branch_operation=Utwórz gałąź
branch.new_branch=Utwórz nową gałąź
branch.new_branch_from=Utwórz nowy branch z '%s'
@@ -2058,7 +2064,7 @@ org_full_name_holder=Pełna nazwa organizacji
org_name_helper=Nazwa organizacji powinna być krótka i łatwa do zapamiętania.
create_org=Utwórz organizację
repo_updated=Zaktualizowano
-people=Ludzie
+members=Członkowie
teams=Zespoły
lower_members=członkowie
lower_repositories=repozytoria
@@ -2126,6 +2132,7 @@ teams.leave=Opuść
teams.leave.detail=Opuścić %s?
teams.can_create_org_repo=Tworzenie repozytoriów
teams.can_create_org_repo_helper=Członkowie mogą tworzyć nowe repozytoria w organizacji. Twórca otrzyma uprawnienia administracyjne do nowego repozytorium.
+teams.read_access=Przeczytane
teams.read_access_helper=Członkowie mogą wyświetlać i klonować repozytoria zespołów.
teams.write_access_helper=Członkowie mają uprawnienia odczytu i wypychania do repozytoriów zespołu.
teams.admin_access=Dostęp administratora
@@ -2286,6 +2293,9 @@ users.still_own_repo=Ten użytkownik jest właścicielem jednego lub większej i
users.still_has_org=Ten użytkownik jest członkiem organizacji. Musisz go najpierw usunąć ze wszystkich organizacji.
users.deletion_success=Konto użytkownika zostało usunięte.
users.reset_2fa=Zresetuj 2FA
+users.list_status_filter.is_active=Aktywne
+users.list_status_filter.is_admin=Administrator
+users.list_status_filter.is_restricted=Ograniczone
emails.email_manage_panel=ZarzÄ…dzanie adresami email
emails.primary=Podstawowy
@@ -2318,6 +2328,11 @@ repos.forks=Forki
repos.issues=Zgłoszenia
repos.size=Rozmiar
+packages.owner=Właściciel
+packages.name=Nazwa
+packages.type=Typ
+packages.repository=Repozytorium
+packages.size=Rozmiar
defaulthooks=Domyślne Webhooki
defaulthooks.desc=Webhooki automatycznie wysyłają zapytania HTTP POST na serwer, gdy niektóre zdarzenia Gitea je wyzwalają. Webhooki zdefiniowane tutaj są domyślne i zostaną skopiowane do wszystkich nowych repozytoriów. Przeczytaj więcej w <a target="_blank" rel="noopener" href="https://docs.gitea.io/en-us/webhooks/">przewodniku webhooków</a>.
@@ -2396,10 +2411,10 @@ auths.tips=Wskazówki
auths.tips.oauth2.general=Uwierzytelnianie OAuth2
auths.tips.oauth2.general.tip=Przy rejestracji nowego uwierzytelnienia OAuth2, URL zwrotny/przekierowań powinien mieć postać <serwer>/user/oauth2/<nazwa uwierzytelnienia>/callback
auths.tip.oauth2_provider=Dostawca OAuth2
-auths.tip.bitbucket=Zarejestruj nowego konsumenta OAuth na https://bitbucket.org/account/user/<twoja nazwa użytkownika>/oauth-consumers/new i dodaj uprawnienie "Account" - "Read"
-auths.tip.nextcloud=Zarejestruj nowego klienta OAuth w swojej instancji za pomocą menu "Ustawienia -> Bezpieczeństwo -> Klient OAuth 2.0"
+auths.tip.bitbucket=`Zarejestruj nowego konsumenta OAuth na https://bitbucket.org/account/user/<twoja nazwa użytkownika>/oauth-consumers/new i dodaj uprawnienie "Account" - "Read"`
+auths.tip.nextcloud=`Zarejestruj nowego klienta OAuth w swojej instancji za pomocą menu "Ustawienia -> Bezpieczeństwo -> Klient OAuth 2.0"`
auths.tip.dropbox=Stwórz nową aplikację na https://www.dropbox.com/developers/apps
-auths.tip.facebook=Zarejestruj nowÄ… aplikacjÄ™ na https://developers.facebook.com/apps i dodaj produkt "Facebook Login"
+auths.tip.facebook=`Zarejestruj nowÄ… aplikacjÄ™ na https://developers.facebook.com/apps i dodaj produkt "Facebook Login"`
auths.tip.github=Zarejestruj nowÄ… aplikacjÄ™ OAuth na https://github.com/settings/applications/new
auths.tip.gitlab=Zarejestruj nowÄ… aplikacjÄ™ na https://gitlab.com/profile/applications
auths.tip.google_plus=Uzyskaj dane uwierzytelniajÄ…ce klienta OAuth2 z konsoli Google API na https://console.developers.google.com/
@@ -2407,7 +2422,7 @@ auths.tip.openid_connect=Użyj adresu URL OpenID Connect Discovery (<server>/.we
auths.tip.twitter=Przejdź na https://dev.twitter.com/apps, stwórz aplikację i upewnij się, że opcja “Allow this application to be used to Sign in with Twitter†jest włączona
auths.tip.discord=Zarejestruj nowÄ… aplikacjÄ™ na https://discordapp.com/developers/applications/me
auths.tip.gitea=Zarejestruj nową aplikację OAuth2. Przewodnik można znaleźć na https://docs.gitea.io/en-us/oauth2-provider/
-auths.tip.yandex=Utwórz nową aplikację na https://oauth.yandex.com/client/new. Wybierz następujące uprawnienia z "Yandex.Passport API": "Access to email address", "Access to user avatar" and "Access to username, first name and surname, gender"
+auths.tip.yandex=`Utwórz nową aplikację na https://oauth.yandex.com/client/new. Wybierz następujące uprawnienia z "Yandex.Passport API": "Access to email address", "Access to user avatar" and "Access to username, first name and surname, gender"`
auths.tip.mastodon=Wprowadź niestandardowy adres URL instancji mastodona, którą chcesz uwierzytelnić (lub użyj domyślnego)
auths.edit=Edytuj źródło uwierzytelniania
auths.activated=To źródło uwierzytelniania jest aktywne
@@ -2495,6 +2510,7 @@ config.skip_tls_verify=Pomiń weryfikację TLS
config.mailer_enabled=WÅ‚Ä…czona
config.mailer_name=Nazwa
+config.mailer_smtp_port=Port SMTP
config.mailer_user=Użytkownik
config.mailer_use_sendmail=Używaj Sendmail
config.mailer_sendmail_path=Ścieżka Sendmail
@@ -2618,7 +2634,6 @@ monitor.queue.pool.cancel_desc=Pozostawienie kolejki bez żadnej grupy pracownik
notices.system_notice_list=Powiadomienia systemu
notices.view_detail_header=Pokaż szczegóły powiadomienia
-notices.actions=Czynności
notices.select_all=Wybierz wszystkie
notices.deselect_all=Odznacz wszystkie
notices.inverse_selection=Odwróć wybór
@@ -2698,4 +2713,25 @@ error.no_unit_allowed_repo=Nie masz uprawnień do żadnej sekcji tego repozytori
error.unit_not_allowed=Nie masz uprawnień do tej sekcji repozytorium.
[packages]
+filter.type=Typ
+conan.details.repository=Repozytorium
+owner.settings.cleanuprules.enabled=WÅ‚Ä…czone
+
+[secrets]
+name=Nazwa
+
+[actions]
+
+
+
+runners.name=Nazwa
+runners.owner_type=Typ
+runners.description=Opis
+runners.task_list.run=Uruchom
+runners.task_list.repository=Repozytorium
+runners.task_list.commit=Commit
+runners.status.active=Aktywne
+
+runs.commit=Commit
+
diff --git a/options/locale/locale_pt-BR.ini b/options/locale/locale_pt-BR.ini
index 41710ce6f..55529df88 100644
--- a/options/locale/locale_pt-BR.ini
+++ b/options/locale/locale_pt-BR.ini
@@ -41,7 +41,7 @@ webauthn_use_twofa=Use um código de duas etapas do seu telefone
webauthn_error=Não foi possível ler sua chave de segurança.
webauthn_unsupported_browser=Seu navegador não oferece suporte ao WebAuthn.
webauthn_error_unknown=Ocorreu um erro desconhecido. Por favor, tente novamente.
-webauthn_error_insecure=WebAuthn suporta apenas conexões seguras. Para testar via HTTP, você pode usar a origem "localhost" ou "127.0.0.1"
+webauthn_error_insecure=`WebAuthn suporta apenas conexões seguras. Para testar via HTTP, você pode usar a origem "localhost" ou "127.0.0.1"`
webauthn_error_unable_to_process=O servidor não pôde processar sua solicitação.
webauthn_error_duplicated=A chave de segurança não é permitida para esta solicitação. Por favor, certifique-se que a chave já não está registrada.
webauthn_error_empty=Você deve definir um nome para esta chave.
@@ -57,7 +57,7 @@ new_mirror=Novo espelhamento
new_fork=Novo Fork de Repositório
new_org=Nova organização
new_project=Novo Projeto
-new_project_board=Novo quadro de projeto
+new_project_column=Nova Coluna
manage_org=Gerenciar organizações
admin_panel=Administração geral
account_settings=Configurações da conta
@@ -86,11 +86,16 @@ remove=Remover
remove_all=Excluir todos
edit=Editar
+enabled=Habilitado
+disabled=Desabilitado
+
copy=Copiar
copy_url=Copiar URL
+copy_content=Copiar conteúdo
copy_branch=Copiar nome do branch
copy_success=Copiado!
copy_error=A cópia falhou
+copy_type_unsupported=Este tipo de arquivo não pode ser copiado
write=Escrever
preview=Pré-visualização
@@ -106,7 +111,15 @@ never=Nunca
rss_feed=Feed RSS
+[aria]
+navbar=Barra de navegação
+footer=Rodapé
+footer.software=Sobre o Software
+footer.links=Links
+
[filter]
+string.asc=A - Z
+string.desc=Z - A
[error]
occurred=Ocorreu um erro
@@ -224,7 +237,6 @@ internal_token_failed=Falha ao gerar o token interno: %v
secret_key_failed=Falha ao gerar a chave secreta: %v
save_config_failed=Falha ao salvar a configuração: %v
invalid_admin_setting=Configuração da conta de administrador está inválida: %v
-install_success=Bem-vindo! Obrigado por escolher Gitea. Divertir-se. E, tome cuidado!
invalid_log_root_path=Pasta raíz do log está inválida: %v
default_keep_email_private=Ocultar endereços de e-mail por padrão
default_keep_email_private_popup=Ocultar endereços de e-mail de novas contas de usuário por padrão.
@@ -236,6 +248,8 @@ no_reply_address=Domínio de e-mail oculto
no_reply_address_helper=Nome de domínio para usuários com um endereço de e-mail oculto. Por exemplo, o nome de usuário 'joe' será registrado no Git como 'joe@noreply.example.org' se o domínio de e-mail oculto estiver definido como 'noreply.example.org'.
password_algorithm=Algoritmo Hash de Senha
password_algorithm_helper=Escolha o algoritmo de hash para as senhas. Diferentes algoritmos têm requerimentos e forças diversos. O `Argon2` possui boa qualidade, porém usa muita memória e pode ser inapropriado para sistemas com menos recursos.
+enable_update_checker=Habilitar Verificador de Atualizações
+enable_update_checker_helper=Procura por novas versões periodicamente conectando-se ao gitea.io.
[home]
uname_holder=Usuário ou e-mail
@@ -250,7 +264,7 @@ view_home=Ver %s
search_repos=Encontre um repositório…
filter=Outros filtros
filter_by_team_repositories=Filtrar por repositórios da equipe
-feed_of=Feed de "%s"
+feed_of=`Feed de "%s"`
show_archived=Arquivado
show_both_archived_unarchived=Mostrando arquivados e não arquivados
@@ -271,7 +285,9 @@ organizations=Organizações
search=Pesquisar
code=Código
search.fuzzy=Similar
+search.fuzzy.tooltip=Incluir resultados que sejam próximos ao termo de busca
search.match=Correspondência
+search.match.tooltip=Incluir somente resultados que correspondam exatamente ao termo de busca
code_search_unavailable=A pesquisa por código não está disponível no momento. Entre em contato com o administrador do site.
repo_no_results=Nenhum repositório correspondente foi encontrado.
user_no_results=Nenhum usuário correspondente foi encontrado.
@@ -310,6 +326,7 @@ email_not_associate=O endereço de e-mail não está associado à nenhuma conta.
send_reset_mail=Enviar e-mail de recuperação de conta
reset_password=Recuperação de conta
invalid_code=Seu código de confirmação é inválido ou expirou.
+invalid_password=Sua senha não coincide com a senha que foi usada para criar a conta.
reset_password_helper=Recuperar conta
reset_password_wrong_user=Você está conectado como %s, mas o link de recuperação de conta é para %s
password_too_short=A senha deve ter %d ou mais caracteres.
@@ -353,6 +370,7 @@ password_pwned_err=Não foi possível concluir a requisição ao HaveIBeenPwned
[mail]
view_it_on=Veja em %s
+reply=ou responda diretamente a este email
link_not_working_do_paste=Não está funcionando? Tente copiá-lo e colá-lo no seu navegador.
hi_user_x=Olá <b>%s</b>,
@@ -411,6 +429,10 @@ repo.transfer.body=Para o aceitar ou rejeitar visite %s, ou simplesmente o ignor
repo.collaborator.added.subject=%s adicionou você a %s
repo.collaborator.added.text=Você foi adicionado como um colaborador do repositório:
+team_invite.subject=%[1]s convidou você para participar da organização %[2]s
+team_invite.text_1=%[1]s convidou você para participar da equipe %[2]s na organização %[3]s.
+team_invite.text_2=Por favor, clique no seguinte link para se juntar à equipe:
+team_invite.text_3=Nota: este convite foi destinado a %[1]s. Se você não estava esperando este convite, você pode ignorar este e-mail.
[modal]
yes=Sim
@@ -452,6 +474,8 @@ url_error=`'%s' não é uma URL válida.`
include_error=` deve conter '%s'.`
glob_pattern_error=` padrão glob é inválido: %s.`
regex_pattern_error=` o regex é inválido: %s.`
+username_error=` só pode conter caracteres alfanuméricos ('0-9','a-z','A-Z'), traço ('-'), sublinhado ('_') e ponto ('.'). Não pode começar ou terminar com caracteres não alfanuméricos, e caracteres não-alfanuméricos consecutivos também são proibidos.`
+invalid_group_team_map_error=` mapeamento é inválido: %s`
unknown_error=Erro desconhecido:
captcha_incorrect=O código CAPTCHA está incorreto.
password_not_match=As senhas não coincidem.
@@ -487,18 +511,21 @@ user_not_exist=O usuário não existe.
team_not_exist=A equipe não existe.
last_org_owner=Você não pode remover o último usuário do time 'proprietários'. Deve haver pelo menos um proprietário em uma organização.
cannot_add_org_to_team=Uma organização não pode ser adicionada como membro de uma equipe.
+duplicate_invite_to_team=O usuário já foi convidado para se juntar da equipe.
+organization_leave_success=Você saiu da organização %s com sucesso.
invalid_ssh_key=Não é possível verificar sua chave SSH: %s
invalid_gpg_key=Não é possível verificar sua chave GPG: %s
invalid_ssh_principal=Nome principal inválido: %s
-unable_verify_ssh_key=Não é possível verificar sua chave SSH; verifique novamente se há erros.
+must_use_public_key=A chave que você forneceu é uma chave privada. Por favor, não envie sua chave privada em nenhum lugar. Use sua chave pública em vez disso.
+unable_verify_ssh_key=Não é possível verificar sua chave SSH
auth_failed=Autenticação falhou: %v
-still_own_repo=Sua conta possui um ou mais repositórios; você deve excluí-los ou transferi-los primeiro.
-still_has_org=Sua conta é um membro de uma ou mais organizações; você deve deixá-las primeiro.
-still_own_packages=Sua conta possui um ou mais pacotes; você deve excluí-los primeiro.
-org_still_own_repo=Esta organização ainda possui repositórios; você deve excluí-los ou transferi-los primeiro.
-org_still_own_packages=Esta organização ainda possui pacotes; você deve excluí-los primeiro.
+still_own_repo=Sua conta possui um ou mais repositórios
+still_has_org=Sua conta é um membro de uma ou mais organizações
+still_own_packages=Sua conta possui um ou mais pacotes
+org_still_own_repo=Esta organização ainda possui repositórios
+org_still_own_packages=Esta organização ainda possui pacotes
target_branch_not_exist=O branch de destino não existe.
@@ -510,6 +537,7 @@ activity=Atividade pública
followers=Seguidores
starred=Repositórios favoritos
watched=Repositórios observados
+code=Código
projects=Projetos
following=Seguindo
follow=Seguir
@@ -726,6 +754,8 @@ access_token_deletion_cancel_action=Cancelar
access_token_deletion_confirm_action=Excluir
access_token_deletion_desc=A exclusão de um token revoga o acesso à sua conta para aplicativos que o usam. Continuar?
delete_token_success=O token foi excluído. Os aplicativos que o utilizam já não têm acesso à sua conta.
+select_scopes=Selecione os escopos
+scopes_list=Escopos:
manage_oauth2_applications=Gerenciar aplicativos OAuth2
edit_oauth2_application=Editar aplicativo OAuth2
@@ -738,6 +768,7 @@ create_oauth2_application_button=Criar aplicativo
create_oauth2_application_success=Você criou com sucesso um novo aplicativo OAuth2.
update_oauth2_application_success=Você alterou com sucesso o aplicativo OAuth2.
oauth2_application_name=Nome do aplicativo
+oauth2_confidential_client=Cliente Confidencial. Selecione para aplicativos que mantêm a confidencialidade do segredo, como aplicativos web. Não selecione para aplicativos nativos, incluindo aplicativos desktop e celulares.
oauth2_redirect_uri=Redirecionar URI
save_application=Salvar
oauth2_client_id=Client ID
@@ -788,6 +819,7 @@ remove_account_link=Remover conta vinculada
remove_account_link_desc=A exclusão da chave SSH revogará o acesso à sua conta. Continuar?
remove_account_link_success=A conta vinculada foi removida.
+
orgs_none=Você não é membro de nenhuma organização.
repos_none=Você não possui nenhum repositório
@@ -899,9 +931,9 @@ delete_preexisting_success=Arquivos órfãos excluídos em %s
blame_prior=Ver a responsabilização anterior a esta modificação
transfer.accept=Aceitar transferência
-transfer.accept_desc=Transferir para "%s"
+transfer.accept_desc=`Transferir para "%s"`
transfer.reject=Rejeitar transferência
-transfer.reject_desc=Cancelar a transferência para "%s"
+transfer.reject_desc=`Cancelar a transferência para "%s"`
transfer.no_permission_to_accept=Você não tem permissão para Aceitar
transfer.no_permission_to_reject=Você não tem permissão para Rejeitar
@@ -997,10 +1029,12 @@ unstar=Retirar dos favoritos
star=Juntar aos favoritos
fork=Fork
download_archive=Baixar repositório
+more_operations=Mais Operações
no_desc=Nenhuma descrição
quick_guide=Guia Rápido
clone_this_repo=Clonar este repositório
+cite_this_repo=Citar este repositório
create_new_repo_command=Criando um novo repositório por linha de comando
push_exist_repo=Realizando push para um repositório existente por linha de comando
empty_message=Este repositório está vazio.
@@ -1099,6 +1133,7 @@ editor.commit_directly_to_this_branch=Commit diretamente no branch <strong class
editor.create_new_branch=Crie um <strong>novo branch</strong> para este commit e crie um pull request.
editor.create_new_branch_np=Crie um <strong>novo branch</strong> para este commit.
editor.propose_file_change=Propor alteração de arquivo
+editor.new_branch_name=Nome do novo branch para este commit
editor.new_branch_name_desc=Novo nome do branch...
editor.cancel=Cancelar
editor.filename_cannot_be_empty=Nome do arquivo não pode ser em branco.
@@ -1150,7 +1185,7 @@ commits.signed_by_untrusted_user_unmatched=Assinado por usuário não confiável
commits.gpg_key_id=ID da chave GPG
commits.ssh_key_fingerprint=Impressão Digital da Chave SSH
-commit.actions=Ações
+commit.operations=Operações
commit.revert=Reverter
commit.revert-header=Reverter: %s
commit.revert-content=Selecione a branch para reverter para:
@@ -1183,19 +1218,21 @@ projects.type.bug_triage=Triagem de Bugs
projects.template.desc=Modelo de projeto
projects.template.desc_helper=Selecione um modelo de projeto para começar
projects.type.uncategorized=Sem categoria
-projects.board.edit=Editar quadro
-projects.board.edit_title=Novo nome do quadro
-projects.board.new_title=Novo nome do quadro
-projects.board.new_submit=Enviar
-projects.board.new=Novo Quadro
-projects.board.set_default=Definir como padrão
-projects.board.set_default_desc=Definir este quadro como padrão para pull e issues sem categoria
-projects.board.delete=Excluir Quadro
-projects.board.deletion_desc=Excluir um quadro de projeto move todas as issues relacionadas para 'Sem Categoria'. Continuar?
-projects.board.color=Cor
+projects.column.edit=Editar coluna
+projects.column.edit_title=Nome
+projects.column.new_title=Nome
+projects.column.new_submit=Criar coluna
+projects.column.new=Nova Coluna
+projects.column.set_default=Definir padrão
+projects.column.set_default_desc=Definir esta coluna como padrão para pull e issues sem categoria
+projects.column.delete=Excluir coluna
+projects.column.deletion_desc=Excluir uma coluna do projeto move todas as issues relacionadas para 'Sem categoria'. Continuar?
+projects.column.color=Colorido
projects.open=Abrir
projects.close=Fechar
-projects.board.assigned_to=Atribuído a
+projects.column.assigned_to=Atribuído a
+projects.card_type.images_and_text=Imagens e Texto
+projects.card_type.text_only=Somente texto
issues.desc=Organize relatórios de bugs, tarefas e marcos.
issues.filter_assignees=Filtrar Atribuição
@@ -1271,6 +1308,9 @@ issues.filter_label_exclude=`Use <code>alt</code> + <code>clique/enter</code> pa
issues.filter_label_no_select=Todas as etiquetas
issues.filter_milestone=Marco
issues.filter_milestone_no_select=Todos os marcos
+issues.filter_project=Projeto
+issues.filter_project_all=Todos os projetos
+issues.filter_project_none=Sem projeto
issues.filter_assignee=Atribuído
issues.filter_assginee_no_select=Todos os responsáveis
issues.filter_poster=Autor
@@ -1281,6 +1321,7 @@ issues.filter_type.assigned_to_you=Atribuídos a você
issues.filter_type.created_by_you=Criado por você
issues.filter_type.mentioning_you=Mencionando você
issues.filter_type.review_requested=Revisão solicitada
+issues.filter_type.reviewed_by_you=Revisado por você
issues.filter_sort=Ordenação
issues.filter_sort.latest=Mais recentes
issues.filter_sort.oldest=Mais antigos
@@ -1302,6 +1343,8 @@ issues.action_milestone=Marco
issues.action_milestone_no_select=Sem marco
issues.action_assignee=Responsável
issues.action_assignee_no_select=Sem responsável
+issues.action_check=Marcar/Desmarcar
+issues.action_check_all=Marcar/Desmarcar todos os itens
issues.opened_by=aberto por <a href="%[2]s">%[3]s</a> %[1]s
pulls.merged_by=por <a href="%[2]s">%[3]s</a> foi aplicado em %[1]s
pulls.merged_by_fake=por %[2]s foi aplicado %[1]s
@@ -1355,6 +1398,8 @@ issues.save=Salvar
issues.label_title=Nome da etiqueta
issues.label_description=Descrição da etiqueta
issues.label_color=Cor da etiqueta
+issues.label_exclusive=Exclusivo
+issues.label_exclusive_warning=Quaisquer rótulos com escopo conflitantes serão removidos ao editar os rótulos de uma issue ou pull request.
issues.label_count=%d etiquetas
issues.label_open_issues=%d issues abertas
issues.label_edit=Editar
@@ -1422,6 +1467,7 @@ issues.error_removing_due_date=Falha ao remover a data limite.
issues.push_commit_1=adicionou %d commit %s
issues.push_commits_n=adicionou %d commits %s
issues.force_push_codes=`forçou o push %[1]s de <a class="ui sha" href="%[3]s"><code>%[2]s</code></a> para <a class="ui sha" href="%[5]s"><code>%[4]s</code></a> %[6]s`
+issues.force_push_compare=Comparar
issues.due_date_form=dd/mm/aaaa
issues.due_date_form_add=Adicionar data limite
issues.due_date_form_edit=Editar
@@ -1608,6 +1654,7 @@ pulls.reopened_at=`reabriu este pull request <a id="%[1]s" href="#%[1]s">%[2]s</
pulls.merge_instruction_hint=`Você também pode ver as <a class="show-instruction">instruções para a linha de comandos</a>.`
pulls.merge_instruction_step1_desc=No repositório do seu projeto, crie um novo branch e teste as alterações.
pulls.merge_instruction_step2_desc=Faça merge das alterações e atualize no Gitea.
+pulls.clear_merge_message=Limpar mensagem do merge
pulls.auto_merge_button_when_succeed=(Quando a verificação for bem-sucedida)
pulls.auto_merge_when_succeed=Mesclar automaticamente quando todas as verificações forem bem sucedidas
@@ -1764,7 +1811,9 @@ activity.git_stats_deletion_n=%d exclusões
search=Pesquisar
search.search_repo=Pesquisar no repositório...
search.fuzzy=Aproximada
+search.fuzzy.tooltip=Incluir resultados que sejam próximos ao termo de busca
search.match=Corresponde
+search.match.tooltip=Incluir somente resultados que correspondam exatamente ao termo de busca
search.results=Resultados da pesquisa para "%s" em <a href="%s">%s</a>
search.code_no_results=Nenhum código-fonte correspondente ao seu termo de pesquisa foi encontrado.
search.code_search_unavailable=A pesquisa por código não está disponível no momento. Entre em contato com o administrador do site.
@@ -1796,6 +1845,7 @@ settings.mirror_sync_in_progress=Sincronização do espelhamento está em andame
settings.site=Site
settings.update_settings=Atualizar configurações
settings.branches.update_default_branch=Atualizar Branch Padrão
+settings.branches.add_new_rule=Adicionar Nova Regra
settings.advanced_settings=Configurações avançadas
settings.wiki_desc=Habilitar a wiki do repositório
settings.use_internal_wiki=Usar a wiki nativa
@@ -1822,16 +1872,14 @@ settings.enable_timetracker=Habilitar Cronômetro
settings.allow_only_contributors_to_track_time=Permitir que apenas os colaboradores acompanhem o contador de tempo
settings.pulls_desc=Habilitar pull requests no repositório
settings.pulls.ignore_whitespace=Ignorar espaço em branco em conflitos
-settings.pulls.allow_merge_commits=Habilitar commit no merge
-settings.pulls.allow_rebase_merge=Habilitar Rebasing em commits via merge
-settings.pulls.allow_rebase_merge_commit=Habilitar Rebasing com commits explícitos no merge (--no-ff)
-settings.pulls.allow_squash_commits=Habilitar Squashing em commits via merge
-settings.pulls.allow_manual_merge=Habilitar Marcar PR como aplicado manualmente
settings.pulls.enable_autodetect_manual_merge=Habilitar a detecção automática de merge manual (Nota: Em alguns casos especiais, podem ocorrer julgamentos errados)
settings.pulls.allow_rebase_update=Ativar atualização do branch do pull request por rebase
settings.pulls.default_delete_branch_after_merge=Excluir o branch de pull request após o merge por padrão
+settings.pulls.default_allow_edits_from_maintainers=Permitir edições de mantenedores por padrão
+settings.releases_desc=Habilitar versões do Repositório
settings.packages_desc=Habilitar Registro de Pacotes de Repositório
settings.projects_desc=Habilitar Projetos do Repositório
+settings.actions_desc=Habilitar ações do repositório
settings.admin_settings=Configurações do administrador
settings.admin_enable_health_check=Habilitar verificações de integridade (git fsck) no repositório
settings.admin_code_indexer=Indexador de código
@@ -1867,7 +1915,7 @@ settings.transfer_notices_2=- Você manterá acesso ao repositório se transferi
settings.transfer_notices_3=- Se o repositório for privado e for transferido para um usuário individual, esta ação certifica que o usuário tem pelo menos permissão de leitura (e altera as permissões se necessário).
settings.transfer_owner=Novo proprietário
settings.transfer_perform=Executar Transferência
-settings.transfer_started=Este repositório foi marcado para transferência e aguarda a confirmação de "%s"
+settings.transfer_started=`Este repositório foi marcado para transferência e aguarda a confirmação de "%s"`
settings.transfer_succeed=O repositório foi transferido.
settings.signing_settings=Configurações de Verificação de Assinatura
settings.trust_model=Modelo de Confiança na Assinatura
@@ -1995,6 +2043,7 @@ settings.event_package=Pacote
settings.event_package_desc=Pacote criado ou excluído em um repositório.
settings.branch_filter=Filtro de branch
settings.branch_filter_desc=Lista dos branches a serem considerados nos eventos push, criação de branch e exclusão de branch, especificados como padrão glob. Se estiver vazio ou for <code>*</code>, eventos para todos os branches serão relatados. Veja <a href="https://pkg.go.dev/github.com/gobwas/glob#Compile">github.com/gobwas/glob</a> documentação da sintaxe. Exemplos: <code>master</code>, <code>{master,release*}</code>.
+settings.authorization_header=Header de Autorização
settings.active=Ativo
settings.active_helper=Informações sobre eventos disparados serão enviadas para esta URL do webhook.
settings.add_hook_success=O webhook foi adicionado.
@@ -2039,6 +2088,8 @@ settings.deploy_key_deletion_desc=A exclusão de uma chave de deploy irá revoga
settings.deploy_key_deletion_success=A chave de deploy foi removida.
settings.branches=Branches
settings.protected_branch=Proteção de Branch
+settings.protected_branch.save_rule=Salvar Regra
+settings.protected_branch.delete_rule=Excluir Regra
settings.protected_branch_can_push=Permitir push?
settings.protected_branch_can_push_yes=Você pode fazer push
settings.protected_branch_can_push_no=Você não pode fazer push
@@ -2090,6 +2141,7 @@ settings.block_on_official_review_requests_desc=O merge não será possível qua
settings.block_outdated_branch=Bloquear o merge se o pull request estiver desatualizado
settings.block_outdated_branch_desc=O merge não será possível quando o branch de topo estiver atrás do branch base.
settings.default_branch_desc=Selecione um branch padrão para pull requests e commits de código:
+settings.merge_style_desc=Estilos de Merge
settings.default_merge_style_desc=Estilo de merge padrão para pull requests:
settings.choose_branch=Escolha um branch...
settings.no_protected_branch=Não há branches protegidos.
@@ -2109,7 +2161,6 @@ settings.bot_token=Token do Bot
settings.chat_id=ID do Chat
settings.matrix.homeserver_url=URL do Homeserver
settings.matrix.room_id=ID da Sala
-settings.matrix.access_token=Token de Acesso
settings.matrix.message_type=Tipo de Mensagem
settings.archive.button=Arquivar repositório
settings.archive.header=Arquivar este repositório
@@ -2250,6 +2301,8 @@ release.downloads=Downloads
release.download_count=Downloads: %s
release.add_tag_msg=Use o título e o conteúdo do lançamento como mensagem da tag.
release.add_tag=Criar apenas a tag
+release.releases_for=Versões para %s
+release.tags_for=Tags para %s
branch.name=Nome do Branch
branch.search=Pesquisar branches
@@ -2308,8 +2361,9 @@ org_full_name_holder=Nome completo da organização
org_name_helper=Nomes de organização devem ser curtos e memoráveis.
create_org=Criar organização
repo_updated=Atualizado
-people=Pessoas
+members=Membros
teams=Equipes
+code=Código
lower_members=membros
lower_repositories=repositórios
create_new_team=Nova equipe
@@ -2394,6 +2448,8 @@ teams.members=Membros da equipe
teams.update_settings=Atualizar configurações
teams.delete_team=Excluir equipe
teams.add_team_member=Adicionar membro na equipe
+teams.invite_team_member=Convidar para %s
+teams.invite_team_member.list=Convites pendentes
teams.delete_team_title=Excluir equipe
teams.delete_team_desc=A exclusão de uma equipe revoga o acesso ao repositório de seus membros. Continuar?
teams.delete_team_success=A equipe foi excluída.
@@ -2418,6 +2474,9 @@ teams.all_repositories_helper=A equipe tem acesso a todos os repositórios. Sele
teams.all_repositories_read_permission_desc=Esta equipe concede acesso <strong>Leitura</strong> a <strong>todos os repositórios</strong>: membros podem ver e clonar repositórios.
teams.all_repositories_write_permission_desc=Esta equipe concede acesso <strong>Escrita</strong> a <strong>todos os repositórios</strong>: os membros podem ler de e fazer push para os repositórios.
teams.all_repositories_admin_permission_desc=Esta equipe concede acesso <strong>Administrativo</strong> a <strong>todos os repositórios</strong>: os membros podem ler, fazer push e adicionar colaboradores aos repositórios.
+teams.invite.title=Você foi convidado para se juntar à equipe <strong>%s</strong> na organização <strong>%s</strong>.
+teams.invite.by=Convidado por %s
+teams.invite.description=Por favor, clique no botão abaixo para se juntar à equipe.
[admin]
dashboard=Painel
@@ -2467,6 +2526,7 @@ dashboard.repo_health_check=Verificar estado de saúde de todos os repositórios
dashboard.check_repo_stats=Verificar estatísticas de todos os repositórios
dashboard.archive_cleanup=Apagar arquivos antigos de repositório
dashboard.deleted_branches_cleanup=Realizar limpeza de branches apagados
+dashboard.update_migration_poster_id=Sincronizar os IDs do remetente da migração
dashboard.git_gc_repos=Coleta de lixo em todos os repositórios
dashboard.resync_all_sshkeys=Atualizar o arquivo '.ssh/authorized_keys' com as chaves SSH do Gitea.
dashboard.resync_all_sshkeys.desc=(Não necessário para o servidor SSH embutido.)
@@ -2649,7 +2709,12 @@ auths.filter=Filtro de usuário
auths.admin_filter=Filtro de administrador
auths.restricted_filter=Filtro de restrição
auths.restricted_filter_helper=Deixe em branco para não definir nenhum usuário como restrito. Use um asterisco ('*') para definir todos os usuários que não correspondem ao Filtro de administrador como restritos.
+auths.verify_group_membership=Verificar associação ao grupo no LDAP (deixe o filtro vazio para ignorar)
+auths.group_search_base=Grupo de Pesquisa DN Base
auths.group_attribute_list_users=Atributo do Grupo que Contém a Lista de Usuários
+auths.user_attribute_in_group=Atributo do Usuário Listado em Grupo
+auths.map_group_to_team=Mapear grupos LDAP para Organizações (deixe o campo vazio para pular)
+auths.map_group_to_team_removal=Remover usuários de equipes sincronizadas se o usuário não pertence ao grupo LDAP correspondente
auths.enable_ldap_groups=Habilitar grupos do LDAP
auths.ms_ad_sa=Atributos de pesquisa do MS AD
auths.smtp_auth=Tipo de autenticação SMTP
@@ -2679,6 +2744,13 @@ auths.skip_local_two_fa=Pular 2FA local
auths.skip_local_two_fa_helper=Deixar desligado significa que os usuários locais com 2FA ligada ainda terão que fazer login com 2FA
auths.oauth2_tenant=Tenant
auths.oauth2_scopes=Escopos Adicionais
+auths.oauth2_required_claim_name=Nome do Claim Obrigatorio
+auths.oauth2_required_claim_name_helper=Defina este nome para permitir o login desta fonte apenas para usuários que tenham um claim com este nome
+auths.oauth2_required_claim_value=Valor do Claim Obrigatorio
+auths.oauth2_required_claim_value_helper=Defina este valor para permitir o login desta fonte apenas para usuários que tenham um claim com este nome e valor
+auths.oauth2_group_claim_name=Nome do claim que fornece os nomes dos grupos para esta fonte. (Opcional)
+auths.oauth2_admin_group=Valor do Claim de Grupo para os usuários administradores. (Opcional - requer nome do claim acima)
+auths.oauth2_restricted_group=Valor do Claim de Grupo para os usuários restritos. (Opcional - requer nome do claim acima)
auths.enable_auto_register=Habilitar cadastro automático
auths.sspi_auto_create_users=Criar usuários automaticamente
auths.sspi_auto_create_users_helper=Permitir que o método de autenticação SSPI crie automaticamente novas contas para usuários que fazem o login pela primeira vez
@@ -2695,9 +2767,9 @@ auths.tips.oauth2.general=Autenticação OAuth2
auths.tips.oauth2.general.tip=Ao cadastrar uma nova autenticação OAuth2, o retorno de chamada/redirecionamento URL deve ser: <host>/user/oauth2/<Nome da Autenticação>/callback
auths.tip.oauth2_provider=Provedor OAuth2
auths.tip.bitbucket=Cadastrar um novo consumidor de OAuth em https://bitbucket.org/account/user/<seu nome de usuário> e adicionar a permissão 'Account' - 'Read'
-auths.tip.nextcloud=Registre um novo consumidor OAuth em sua instância usando o seguinte menu "Configurações -> Segurança -> Cliente OAuth 2.0"
+auths.tip.nextcloud=`Registre um novo consumidor OAuth em sua instância usando o seguinte menu "Configurações -> Segurança -> Cliente OAuth 2.0"`
auths.tip.dropbox=Criar um novo aplicativo em https://www.dropbox.com/developers/apps
-auths.tip.facebook=Cadastrar um novo aplicativo em https://developers.facebook.com/apps e adicionar o produto "Facebook Login"
+auths.tip.facebook=`Cadastrar um novo aplicativo em https://developers.facebook.com/apps e adicionar o produto "Facebook Login"`
auths.tip.github=Cadastrar um novo aplicativo de OAuth na https://github.com/settings/applications/new
auths.tip.gitlab=Cadastrar um novo aplicativo em https://gitlab.com/profile/applications
auths.tip.google_plus=Obter credenciais de cliente OAuth2 do console de API do Google em https://console.developers.google.com/
@@ -2705,7 +2777,7 @@ auths.tip.openid_connect=Use o OpenID Connect Discovery URL (<servidor>/.well-kn
auths.tip.twitter=Vá em https://dev.twitter.com/apps, crie um aplicativo e certifique-se de que está habilitada a opção “Allow this application to be used to Sign in with Twitter“
auths.tip.discord=Cadastrar um novo aplicativo em https://discordapp.com/developers/applications/me
auths.tip.gitea=Cadastrar um novo aplicativo OAuth2. Guia pode ser encontrado em https://docs.gitea.io/en-us/oauth2-provider/
-auths.tip.yandex=Crie um novo aplicativo em https://oauth.yandex.com/client/new. Selecione as seguintes permissões da seção "Yandex.Passport API": "Access to email address", "Access to user avatar" and "Access to username, first name and surname, gender"
+auths.tip.yandex=`Crie um novo aplicativo em https://oauth.yandex.com/client/new. Selecione as seguintes permissões da seção "Yandex.Passport API": "Access to email address", "Access to user avatar" and "Access to username, first name and surname, gender"`
auths.tip.mastodon=Insira a URL da instância personalizada do mastodon que você deseja usar para autenticar (ou use o padrão)
auths.edit=Editar fonte de autenticação
auths.activated=Esta fonte de autenticação está ativada
@@ -2805,6 +2877,7 @@ config.mailer_use_sendmail=Usar o Sendmail
config.mailer_sendmail_path=Caminho do Sendmail
config.mailer_sendmail_args=Argumentos extras para o Sendmail
config.mailer_sendmail_timeout=Tempo limite do Sendmail
+config.mailer_use_dummy=Dummy
config.test_email_placeholder=E-mail (por exemplo, teste@exemplo.com.br)
config.send_test_mail=Enviar e-mail de teste
config.test_mail_failed=Falha ao enviar o e-mail de teste para '%s': %v
@@ -2857,6 +2930,8 @@ config.access_log_template=Modelo
config.xorm_log_mode=Modo log XORM
config.xorm_log_sql=Log SQL
+config.get_setting_failed=Falha ao obter configuração %s
+config.set_setting_failed=Falha ao definir configuração %s
monitor.cron=Tarefas cron
monitor.name=Nome
@@ -2938,7 +3013,7 @@ monitor.queue.pool.cancel_desc=Deixar uma fila sem grupos de executores pode faz
notices.system_notice_list=Avisos do sistema
notices.view_detail_header=Ver detalhes do aviso
-notices.actions=Ações
+notices.operations=Operações
notices.select_all=Marcar todos
notices.deselect_all=Desmarcar todos
notices.inverse_selection=Inverter seleção
@@ -3062,6 +3137,8 @@ keywords=Palavras-chave
details=Detalhes
details.author=Autor
details.project_site=Site do Projeto
+details.repository_site=Site do Repositório
+details.documentation_site=Site da Documentação
details.license=Licença
assets=Recursos
versions=Versões
@@ -3069,6 +3146,12 @@ versions.on=em
versions.view_all=Ver todas
dependency.id=ID
dependency.version=Versão
+cargo.registry=Configurar este registro no arquivo de configuração de Cargo (por exemplo <code>~/.cargo/config.toml</code>):
+cargo.install=Para instalar o pacote usando Cargo, execute o seguinte comando:
+cargo.details.repository_site=Site do Repositório
+cargo.details.documentation_site=Site da Documentação
+chef.registry=Configure este registro em seu arquivo <code>~/.chef/config.rb</code>:
+chef.install=Para instalar o pacote, execute o seguinte comando:
composer.registry=Configure este registro em seu arquivo <code>~/.composer/config.json</code>:
composer.install=Para instalar o pacote usando o Composer, execute o seguinte comando:
composer.documentation=Para obter mais informações sobre o registro do Composer, consulte <a target="_blank" rel="noopener noreferrer" href="https://docs.gitea.io/en-us/packages/composer/">a documentação</a>.
@@ -3078,10 +3161,13 @@ conan.details.repository=Repositório
conan.registry=Configure este registro pela linha de comando:
conan.install=Para instalar o pacote usando o Conan, execute o seguinte comando:
conan.documentation=Para obter mais informações sobre o registro Conan, consulte <a target="_blank" rel="noopener noreferrer" href="https://docs.gitea.io/en-us/packages/conan/">a documentação</a>.
+conda.registry=Configure este registro como um repositório Conda no arquivo <code>.condarc</code>:
+conda.install=Para instalar o pacote usando o Conda, execute o seguinte comando:
+conda.documentation=Para obter mais informações sobre o registro Conda, consulte <a target="_blank" rel="noopener noreferrer" href="https://docs.gitea.io/en-us/packages/conda/">a documentação</a>.
+conda.details.repository_site=Site do Repositório
+conda.details.documentation_site=Site da Documentação
container.details.type=Tipo de Imagem
container.details.platform=Plataforma
-container.details.repository_site=Site do Repositório
-container.details.documentation_site=Site da Documentação
container.pull=Puxe a imagem pela linha de comando:
container.digest=Digest:
container.documentation=Para obter mais informações sobre o registro de Container, consulte <a target="_blank" rel="noopener noreferrer" href="https://docs.gitea.io/en-us/packages/container/">a documentação</a>.
@@ -3115,8 +3201,6 @@ npm.dependencies.optional=Dependências Opcionais
npm.details.tag=Tag
pub.install=Para instalar o pacote usando Dart, execute o seguinte comando:
pub.documentation=Para obter mais informações sobre o registro Pub, consulte <a target="_blank" rel="noopener noreferrer" href="https://docs.gitea.io/en-us/packages/pub/">a documentação</a>.
-pub.details.repository_site=Site do Repositório
-pub.details.documentation_site=Site da Documentação
pypi.requires=Requer Python
pypi.install=Para instalar o pacote usando pip, execute o seguinte comando:
pypi.documentation=Para obter mais informações sobre o registro PyPI, consulte <a target="_blank" rel="noopener noreferrer" href="https://docs.gitea.io/en-us/packages/pypi/">a documentação</a>.
@@ -3140,4 +3224,78 @@ settings.delete.description=A exclusão de um pacote é permanente e não pode s
settings.delete.notice=Você está prestes a excluir %s (%s). Esta operação é irreversível, tem certeza?
settings.delete.success=O pacote foi excluído.
settings.delete.error=Falha ao excluir o pacote.
+owner.settings.cleanuprules.title=Gerenciar Regras de Limpeza
+owner.settings.cleanuprules.add=Adicionar Regra de Limpeza
+owner.settings.cleanuprules.edit=Editar Regra de Limpeza
+owner.settings.cleanuprules.none=Não há regras de limpeza disponíveis. Leia a documentação para saber mais.
+owner.settings.cleanuprules.preview=Pré-visualizar Regra de Limpeza
+owner.settings.cleanuprules.preview.overview=%d pacotes agendados para serem removidos.
+owner.settings.cleanuprules.preview.none=A regra de limpeza não corresponde a nenhum pacote.
+owner.settings.cleanuprules.enabled=Habilitado
+owner.settings.cleanuprules.keep.title=Versões que correspondem a estas regras são mantidas, mesmo se corresponderem a uma regra de remoção abaixo.
+owner.settings.cleanuprules.keep.count=Manter o mais recente
+owner.settings.cleanuprules.keep.count.1=1 versão por pacote
+owner.settings.cleanuprules.keep.count.n=%d versões por pacote
+owner.settings.cleanuprules.keep.pattern=Manter versões correspondentes
+owner.settings.cleanuprules.keep.pattern.container=A versão <code>latest</code> é sempre mantida para pacotes de Container.
+owner.settings.cleanuprules.remove.title=Versões que correspondem a essas regras são removidas, a menos que uma regra acima diga para mantê-las.
+owner.settings.cleanuprules.remove.days=Remover versões mais antigas que
+owner.settings.cleanuprules.remove.pattern=Remover versões correspondentes
+owner.settings.cleanuprules.success.update=Regra de limpeza foi atualizada.
+owner.settings.cleanuprules.success.delete=Regra de limpeza foi excluída.
+owner.settings.chef.title=Registro Chef
+owner.settings.chef.keypair=Gerar par de chaves
+
+[secrets]
+secrets=Segredos
+description=Os segredos serão passados a certas ações e não poderão ser lidos de outra forma.
+none=Não há segredos ainda.
+value=Valor
+name=Nome
+creation=Adicionar Segredo
+creation.success=O segredo '%s' foi adicionado.
+creation.failed=Falha ao adicionar segredo.
+deletion=Excluir segredo
+deletion.description=A exclusão de um segredo é permanente e não pode ser desfeita. Continuar?
+deletion.success=O segredo foi excluído.
+deletion.failed=Falha ao excluir segredo.
+
+[actions]
+actions=Ações
+
+unit.desc=Gerenciar ações
+
+status.unknown=Desconhecido
+status.waiting=Em espera
+status.running=Rodando
+status.success=Sucesso
+status.failure=Falha
+status.cancelled=Cancelado
+status.skipped=Ignorado
+status.blocked=Bloqueado
+
+runners.status=Status
+runners.id=ID
+runners.name=Nome
+runners.owner_type=Tipo
+runners.description=Descrição
+runners.labels=Rótulos
+runners.last_online=Última Vez Online
+runners.custom_labels=Etiquetas Personalizadas
+runners.custom_labels_helper=Etiquetas personalizadas são etiquetas que são adicionadas manualmente por um administrador. Separe as etiquetas com vírgula. Espaço em branco no começo ou no final de cada etiqueta é ignorado.
+runners.task_list.run=Executar
+runners.task_list.status=Status
+runners.task_list.repository=Repositório
+runners.task_list.commit=Commit
+runners.update_runner=Atualizar as Alterações
+runners.status.unspecified=Desconhecido
+runners.status.idle=Inativo
+runners.status.active=Ativo
+runners.status.offline=Offiline
+
+runs.open_tab=%d Aberto
+runs.closed_tab=%d Fechado
+runs.commit=Commit
+runs.pushed_by=Push realizado por
+
diff --git a/options/locale/locale_pt-PT.ini b/options/locale/locale_pt-PT.ini
index 9c38a1727..ef7a400ec 100644
--- a/options/locale/locale_pt-PT.ini
+++ b/options/locale/locale_pt-PT.ini
@@ -41,7 +41,7 @@ webauthn_use_twofa=Usar um código de dois passos do seu telefone
webauthn_error=Não foi possível ler a sua chave de segurança.
webauthn_unsupported_browser=O seu navegador não oferece suporte ao WebAuthn.
webauthn_error_unknown=Ocorreu um erro desconhecido. Tente novamente, por favor.
-webauthn_error_insecure=WebAuthn apenas suporta conexões seguras. Para testar sobre HTTP, pode usar a origem "localhost" ou "127.0.0.1"
+webauthn_error_insecure=`WebAuthn apenas suporta conexões seguras. Para testar sobre HTTP, pode usar a origem "localhost" ou "127.0.0.1"`
webauthn_error_unable_to_process=O servidor não conseguiu processar o seu pedido.
webauthn_error_duplicated=A chave de segurança não é permitida neste pedido. Certifique-se de que a chave não está já registada.
webauthn_error_empty=Você tem que definir um nome para esta chave.
@@ -57,7 +57,7 @@ new_mirror=Nova réplica
new_fork=Nova derivação do repositório
new_org=Nova organização
new_project=Novo planeamento
-new_project_board=Novo painel para o planeamento
+new_project_column=Nova coluna
manage_org=Gerir organizações
admin_panel=Administração do sítio
account_settings=Configurações da conta
@@ -86,11 +86,16 @@ remove=Remover
remove_all=Remover tudo
edit=Editar
+enabled=Habilitado
+disabled=Desabilitado
+
copy=Copiar
copy_url=Copiar URL
+copy_content=Copiar conteúdo
copy_branch=Copiar nome do ramo
copy_success=Copiado!
copy_error=Falha ao copiar
+copy_type_unsupported=Este tipo de ficheiro não pode ser copiado
write=Escrever
preview=Pré-visualizar
@@ -106,6 +111,12 @@ never=Nunca
rss_feed=Fonte RSS
+[aria]
+navbar=Barra de navegação
+footer=Rodapé
+footer.software=Sobre o Software
+footer.links=Ligações
+
[filter]
string.asc=A - Z
string.desc=Z - A
@@ -226,7 +237,6 @@ internal_token_failed=Falha ao gerar o código interno: %v
secret_key_failed=Falha ao gerar a chave secreta: %v
save_config_failed=Falhou ao guardar a configuração: %v
invalid_admin_setting=A configuração da conta de administrador é inválida: %v
-install_success=Bem-vindo(a)! Obrigado por escolher o Gitea. Divirta-se e aproveite!
invalid_log_root_path=A localização dos registos é inválida: %v
default_keep_email_private=Esconder, por norma, os endereços de email
default_keep_email_private_popup=Esconder, por norma, os endereços de email de novos utilizadores.
@@ -237,6 +247,7 @@ default_enable_timetracking_popup=Habilitar, por norma, a contagem do tempo nos
no_reply_address=Domínio dos emails ocultos
no_reply_address_helper=Nome de domínio para utilizadores com um endereço de email oculto. Por exemplo, o nome de utilizador 'silva' será registado no Git como 'silva@semresposta.exemplo.org' se o domínio de email oculto estiver definido como 'semresposta.exemplo.org'.
password_algorithm=Algoritmo de Hash da Senha
+invalid_password_algorithm=Algoritmo de hash da senha inválido
password_algorithm_helper=Definir o algoritmo de hash da senha. Os algoritmos têm requisitos e resistência distintos. `argon2`, embora tenha boas características, usa muita memória e pode ser inapropriado para sistemas pequenos.
enable_update_checker=Habilitar verificador de novidades
enable_update_checker_helper=Verifica, periodicamente, se foi lançada alguma versão nova, fazendo uma ligação ao gitea.io.
@@ -254,7 +265,7 @@ view_home=Ver %s
search_repos=Procurar um repositório…
filter=Outros filtros
filter_by_team_repositories=Filtrar por repositórios da equipa
-feed_of=Fonte de "%s"
+feed_of=`Fonte de "%s"`
show_archived=Arquivado
show_both_archived_unarchived=Apresentando arquivados e não arquivados
@@ -317,6 +328,7 @@ email_not_associate=O endereço de email não está associado a qualquer conta.
send_reset_mail=Enviar email de recuperação da conta
reset_password=Recuperação de conta
invalid_code=O seu código de confirmação é inválido ou expirou.
+invalid_password=A sua senha não corresponde à senha que foi usada para criar a conta.
reset_password_helper=Recuperar conta
reset_password_wrong_user=Tem conta iniciada como %s, mas a ligação de recuperação de conta é para %s
password_too_short=O tamanho da senha não pode ser inferior a %d caracteres.
@@ -360,6 +372,7 @@ password_pwned_err=Não foi possível completar o pedido ao HaveIBeenPwned
[mail]
view_it_on=Ver em %s
+reply=ou responda a este email imediatamente
link_not_working_do_paste=Não está a funcionar? Tente copiar e colar no seu navegador.
hi_user_x=Olá <b>%s</b>,
@@ -463,6 +476,8 @@ url_error=`'%s' não é um URL válido.`
include_error=` tem que conter o texto '%s'.`
glob_pattern_error=` o padrão glob é inválido: %s.`
regex_pattern_error=` o padrão regex é inválido: %s.`
+username_error=` só pode conter caracteres alfanuméricos ('0-9','a-z','A-Z'), hífen ('-'), sublinhado ('_') e ponto ('.') Não pode começar nem terminar com caracteres não alfanuméricos, e caracteres não alfanuméricos consecutivos também são proibidos.`
+invalid_group_team_map_error=` o mapeamento é inválido: %s`
unknown_error=Erro desconhecido:
captcha_incorrect=O código CAPTCHA está errado.
password_not_match=As senhas não coincidem.
@@ -499,18 +514,20 @@ team_not_exist=A equipa não existe.
last_org_owner=Não pode remover o último utilizador da equipa 'proprietários'. Tem que haver pelo menos um proprietário numa organização.
cannot_add_org_to_team=Uma organização não pode ser adicionada como membro de uma equipa.
duplicate_invite_to_team=O(A) utilizador(a) já tinha sido convidado(a) para ser membro da equipa.
+organization_leave_success=Você deixou a organização %s com sucesso.
invalid_ssh_key=Não é possível validar a sua chave SSH: %s
invalid_gpg_key=Não é possível validar a sua chave GPG: %s
invalid_ssh_principal=Protagonista inválido: %s
-unable_verify_ssh_key=Não é possível validar a chave SSH; verifique novamente se há erros.
+must_use_public_key=A chave que você forneceu é privada. Não carregue a sua chave em lugar nenhum, em vez disso use a sua chave pública.
+unable_verify_ssh_key=Não é possível validar a chave SSH
auth_failed=Falhou a autenticação: %v
-still_own_repo=A sua conta possui um ou mais repositórios; deve excluí-los ou transferi-los primeiro.
-still_has_org=A sua conta é membro de uma ou mais organizações; deixe-as primeiro.
-still_own_packages=A sua conta possui um ou mais pacotes; elimine-os primeiro.
-org_still_own_repo=Esta organização ainda possui repositórios; deve excluí-los ou transferi-los primeiro.
-org_still_own_packages=Esta organização ainda possui um ou mais pacotes; elimine-os primeiro.
+still_own_repo=A sua conta possui um ou mais repositórios
+still_has_org=A sua conta é membro de uma ou mais organizações
+still_own_packages=A sua conta possui um ou mais pacotes
+org_still_own_repo=Esta organização ainda possui repositórios
+org_still_own_packages=Esta organização ainda possui um ou mais pacotes
target_branch_not_exist=O ramo de destino não existe.
@@ -739,6 +756,8 @@ access_token_deletion_cancel_action=Cancelar
access_token_deletion_confirm_action=Eliminar
access_token_deletion_desc=Eliminar um código revoga o acesso à sua conta nas aplicações que o usem. Esta operação não poderá ser revertida. Quer continuar?
delete_token_success=O código foi eliminado. Aplicações que o usavam deixaram de ter acesso à sua conta.
+select_scopes=Escolha os âmbitos
+scopes_list=Âmbitos:
manage_oauth2_applications=Gerir aplicações OAuth2
edit_oauth2_application=Editar aplicação OAuth2
@@ -802,6 +821,8 @@ remove_account_link=Remover conta vinculada
remove_account_link_desc=A remoção de uma conta vinculada revogará o acesso dessa conta à sua conta do Gitea. Quer continuar?
remove_account_link_success=A conta vinculada foi removida.
+hooks.desc=Adicionar automatismos web que serão despoletados para <strong>todos os repositórios</strong> pertencentes a este utilizador.
+
orgs_none=Não é membro de nenhuma organização.
repos_none=Não tem nenhum repositório
@@ -913,9 +934,9 @@ delete_preexisting_success=Eliminados os ficheiros não adoptados em %s
blame_prior=Ver a responsabilização anterior a esta modificação
transfer.accept=Aceitar transferência
-transfer.accept_desc=Transferir para "%s"
+transfer.accept_desc=`Transferir para "%s"`
transfer.reject=Rejeitar transferência
-transfer.reject_desc=Cancelar transferência para "%s"
+transfer.reject_desc=`Cancelar transferência para "%s"`
transfer.no_permission_to_accept=Não tem permissão para Aceitar
transfer.no_permission_to_reject=Não tem permissão para Rejeitar
@@ -1011,10 +1032,12 @@ unstar=Tirar dos favoritos
star=Juntar aos favoritos
fork=Derivar
download_archive=Descarregar repositório
+more_operations=Mais operações
no_desc=Sem descrição
quick_guide=Guia rápido
clone_this_repo=Clonar este repositório
+cite_this_repo=Citar este repositório
create_new_repo_command=Criando um novo repositório na linha de comandos
push_exist_repo=Enviando, pela linha de comandos, um repositório existente
empty_message=Este repositório não contém qualquer conteúdo.
@@ -1113,6 +1136,7 @@ editor.commit_directly_to_this_branch=Cometer imediatamente no ramo <strong clas
editor.create_new_branch=Crie um <strong>novo ramo</strong> para este cometimento e inicie um pedido de integração.
editor.create_new_branch_np=Criar um <strong>novo ramo</strong> para este cometimento.
editor.propose_file_change=Propor modificação do ficheiro
+editor.new_branch_name=Dê um nome ao novo ramo para este cometimento
editor.new_branch_name_desc=Nome do novo ramo…
editor.cancel=Cancelar
editor.filename_cannot_be_empty=O nome do ficheiro não pode estar em branco.
@@ -1164,7 +1188,7 @@ commits.signed_by_untrusted_user_unmatched=Assinado por um utilizador não fiáv
commits.gpg_key_id=ID da chave GPG
commits.ssh_key_fingerprint=Identificação digital da chave SSH
-commit.actions=Operações
+commit.operations=Operações
commit.revert=Reverter
commit.revert-header=Reverter: %s
commit.revert-content=Escolha o ramo para onde vai reverter:
@@ -1197,19 +1221,22 @@ projects.type.bug_triage=Triagem de erros
projects.template.desc=Modelo de planeamento
projects.template.desc_helper=Escolha um modelo de planeamento para começar
projects.type.uncategorized=Sem categoria
-projects.board.edit=Editar painel
-projects.board.edit_title=Novo nome para o painel
-projects.board.new_title=Novo nome para o painel
-projects.board.new_submit=Submeter
-projects.board.new=Novo painel
-projects.board.set_default=Definir como padrão
-projects.board.set_default_desc=Definir este painel como padrão para questões e pedidos de integração não categorizados
-projects.board.delete=Eliminar painel
-projects.board.deletion_desc=Eliminar um painel do planeamento faz com que todas as questões nesse painel sejam movidas para o painel 'Sem categoria'. Continuar?
-projects.board.color=Cor
+projects.column.edit=Editar coluna
+projects.column.edit_title=Nome
+projects.column.new_title=Nome
+projects.column.new_submit=Criar coluna
+projects.column.new=Nova coluna
+projects.column.set_default=Definir como padrão
+projects.column.set_default_desc=Defina esta coluna como padrão para questões e pedidos de integração não categorizados
+projects.column.delete=Eliminar coluna
+projects.column.deletion_desc=Eliminar uma coluna de um planeamento faz com que todas as questões que nela constam sejam movidas para a coluna 'Sem categoria'. Continuar?
+projects.column.color=Colorido
projects.open=Abrir
projects.close=Fechar
-projects.board.assigned_to=Atribuído a
+projects.column.assigned_to=Atribuída a
+projects.card_type.desc=Previsão dos cartões
+projects.card_type.images_and_text=Imagens e texto
+projects.card_type.text_only=Apenas texto
issues.desc=Organize relatórios de erros, tarefas e etapas.
issues.filter_assignees=Filtrar encarregado
@@ -1285,6 +1312,9 @@ issues.filter_label_exclude=`Use <code>alt</code> + <code>clique/enter</code> pa
issues.filter_label_no_select=Todos os rótulos
issues.filter_milestone=Etapa
issues.filter_milestone_no_select=Todas as etapas
+issues.filter_project=Planeamento
+issues.filter_project_all=Todos os planeamentos
+issues.filter_project_none=Nenhum planeamento
issues.filter_assignee=Encarregado
issues.filter_assginee_no_select=Todos os encarregados
issues.filter_poster=Autor(a)
@@ -1295,6 +1325,7 @@ issues.filter_type.assigned_to_you=Atribuídas a si
issues.filter_type.created_by_you=Criadas por si
issues.filter_type.mentioning_you=Mencionando a si
issues.filter_type.review_requested=Revisão solicitada
+issues.filter_type.reviewed_by_you=Revistos por si
issues.filter_sort=Ordem
issues.filter_sort.latest=Mais recentes
issues.filter_sort.oldest=Mais antigas
@@ -1316,6 +1347,8 @@ issues.action_milestone=Etapa
issues.action_milestone_no_select=Sem etapa
issues.action_assignee=Encarregado
issues.action_assignee_no_select=Sem encarregado
+issues.action_check=Marcar/desmarcar
+issues.action_check_all=Marcar/desmarcar todos os itens
issues.opened_by=aberta %[1]s por <a href="%[2]s">%[3]s</a>
pulls.merged_by=por <a href="%[2]s">%[3]s</a> foi executado %[1]s
pulls.merged_by_fake=por %[2]s foi executado %[1]s
@@ -1369,6 +1402,9 @@ issues.save=Guardar
issues.label_title=Nome do rótulo
issues.label_description=Descrição do rótulo
issues.label_color=Cor do rótulo
+issues.label_exclusive=Exclusivo
+issues.label_exclusive_desc=Nomeie o rótulo <code>âmbito/item</code> para torná-lo mutuamente exclusivo com outros rótulos do <code>âmbito/</code>.
+issues.label_exclusive_warning=Quaisquer rótulos com âmbito que estejam em conflito irão ser removidos ao editar os rótulos de uma questão ou de um pedido de integração.
issues.label_count=%d rótulos
issues.label_open_issues=%d questões abertas
issues.label_edit=Editar
@@ -1436,6 +1472,7 @@ issues.error_removing_due_date=Falhou a remoção da data de vencimento.
issues.push_commit_1=adicionou %d cometimento %s
issues.push_commits_n=adicionou %d cometimentos %s
issues.force_push_codes=`forçou o envio %[1]s de <a class="ui sha" href="%[3]s"><code>%[2]s</code></a> para <a class="ui sha" href="%[5]s"><code>%[4]s</code></a> %[6]s`
+issues.force_push_compare=Comparar
issues.due_date_form=yyyy-mm-dd
issues.due_date_form_add=Adicionar data de vencimento
issues.due_date_form_edit=Editar
@@ -1622,6 +1659,8 @@ pulls.reopened_at=`reabriu este pedido de integração <a id="%[1]s" href="#%[1]
pulls.merge_instruction_hint=`Também pode ver as <a class="show-instruction">instruções para a linha de comandos</a>.`
pulls.merge_instruction_step1_desc=No seu repositório, crie um novo ramo e teste as modificações.
pulls.merge_instruction_step2_desc=Integre as modificações e envie para o Gitea.
+pulls.clear_merge_message=Apagar mensagem de integração
+pulls.clear_merge_message_hint=Apagar a mensagem de integração apenas remove o conteúdo da mensagem de cometimento e mantém os rodapés do git, tais como "Co-Autorado-Por …".
pulls.auto_merge_button_when_succeed=(quando as verificações forem bem-sucedidas)
pulls.auto_merge_when_succeed=Integrar automaticamente quando todas as verificações forem bem-sucedidas
@@ -1813,6 +1852,7 @@ settings.mirror_sync_in_progress=A sincronização da réplica está em andament
settings.site=Sítio web
settings.update_settings=Modificar configurações
settings.branches.update_default_branch=Definir o ramo principal
+settings.branches.add_new_rule=Adicionar nova regra
settings.advanced_settings=Configurações avançadas
settings.wiki_desc=Habilitar wiki do repositório
settings.use_internal_wiki=Usar o wiki nativo
@@ -1839,16 +1879,14 @@ settings.enable_timetracker=Habilitar a contagem de tempo
settings.allow_only_contributors_to_track_time=Permitir a contagem de tempo somente aos contribuidores
settings.pulls_desc=Habilitar pedidos de integração no repositório
settings.pulls.ignore_whitespace=Ignorar espaços em branco nos conflitos
-settings.pulls.allow_merge_commits=Habilitar integração de cometimentos
-settings.pulls.allow_rebase_merge=Habilitar cometimentos de mudança de base para integrar
-settings.pulls.allow_rebase_merge_commit=Habilitar mudança de base com cometimentos de integração explícitos (--no-ff)
-settings.pulls.allow_squash_commits=Habilitar cometimentos de compactar para integrar
-settings.pulls.allow_manual_merge=Habilitar a marcação dos pedidos de integração como tendo sido executados manualmente
settings.pulls.enable_autodetect_manual_merge=Habilitar a identificação automática de integrações manuais (obs.: nalguns casos especiais a avaliação pode ser errada)
settings.pulls.allow_rebase_update=Habilitar a modificação do ramo do pedido de integração através da mudança de base
settings.pulls.default_delete_branch_after_merge=Eliminar o ramo do pedido de integração depois de finalizada a integração, como predefinição
+settings.pulls.default_allow_edits_from_maintainers=Permitir, por padrão, que os responsáveis editem
+settings.releases_desc=Habilitar lançamentos no repositório
settings.packages_desc=Habilitar o registo de pacotes do repositório
settings.projects_desc=Habilitar planeamentos no repositório
+settings.actions_desc=Habilitar operações no repositório
settings.admin_settings=Configurações do administrador
settings.admin_enable_health_check=Habilitar verificações de integridade (git fsck) no repositório
settings.admin_code_indexer=Indexador de código
@@ -1884,7 +1922,7 @@ settings.transfer_notices_2=- Você manterá o acesso ao repositório se o trans
settings.transfer_notices_3=- Se o repositório for privado e for transferido para um utilizador individual, esta operação certifica que o utilizador tem pelo menos a permissão de leitura (e altera as permissões se for necessário).
settings.transfer_owner=Novo proprietário
settings.transfer_perform=Executar transferência
-settings.transfer_started=Este repositório foi marcado para ser transferido e aguarda a confirmação de "%s"
+settings.transfer_started=`Este repositório foi marcado para ser transferido e aguarda a confirmação de "%s"`
settings.transfer_succeed=O repositório foi transferido.
settings.signing_settings=Configuração da validação de assinaturas
settings.trust_model=Modelo de confiança na assinatura
@@ -2012,6 +2050,8 @@ settings.event_package=Pacote
settings.event_package_desc=Pacote criado ou eliminado num repositório.
settings.branch_filter=Filtro de ramos
settings.branch_filter_desc=Lista dos ramos a serem considerados nos eventos de envio e de criação e eliminação de ramos, especificada como um padrão glob. Se estiver em branco ou for <code>*</code>, serão reportados eventos para todos os ramos. Veja a documentação <a href="https://pkg.go.dev/github.com/gobwas/glob#Compile">github.com/gobwas/glob</a> para ver os detalhes da sintaxe. Exemplos: <code>trunk</code>, <code>{trunk,release*}</code>.
+settings.authorization_header=Cabeçalho de Autorização
+settings.authorization_header_desc=Será incluído como cabeçalho de autorização para pedidos, quando estiver presente. Exemplos: %s.
settings.active=Em funcionamento
settings.active_helper=Será enviada informação sobre os eventos despoletadores para o URL deste automatismo web.
settings.add_hook_success=O automatismo web foi adicionado.
@@ -2056,6 +2096,8 @@ settings.deploy_key_deletion_desc=Remover uma chave de instalação irá revogar
settings.deploy_key_deletion_success=A chave de instalação foi removida.
settings.branches=Ramos
settings.protected_branch=Salvaguarda do ramo
+settings.protected_branch.save_rule=Guardar regra
+settings.protected_branch.delete_rule=Eliminar regra
settings.protected_branch_can_push=Permitir envios?
settings.protected_branch_can_push_yes=Pode enviar
settings.protected_branch_can_push_no=Não pode enviar
@@ -2090,6 +2132,7 @@ settings.dismiss_stale_approvals=Descartar aprovações obsoletas
settings.dismiss_stale_approvals_desc=Quando novos cometimentos que mudam o conteúdo do pedido de integração forem enviados para o ramo, as aprovações antigas serão descartadas.
settings.require_signed_commits=Exigir cometimentos assinados
settings.require_signed_commits_desc=Rejeitar envios para este ramo que não estejam assinados ou que não sejam validáveis.
+settings.protect_branch_name_pattern=Padrão do nome do ramo protegido
settings.protect_protected_file_patterns=Padrões de ficheiros protegidos (separados com ponto e vírgula '\;'):
settings.protect_protected_file_patterns_desc=Ficheiros protegidos que não podem ser modificados, mesmo que o utilizador tenha direitos para adicionar, editar ou eliminar ficheiros neste ramo. Múltiplos padrões podem ser separados com ponto e vírgula ('\;'). Veja a documentação em <a href="https://godoc.org/github.com/gobwas/glob#Compile">github.com/gobwas/glob</a> para ver a sintaxe. Exemplos: <code>.drone.yml</code>, <code>/docs/**/*.txt</code>.
settings.protect_unprotected_file_patterns=Padrões de ficheiros desprotegidos (separados com ponto e vírgula '\;'):
@@ -2098,6 +2141,7 @@ settings.add_protected_branch=Habilitar salvaguarda
settings.delete_protected_branch=Desabilitar salvaguarda
settings.update_protect_branch_success=A salvaguarda do ramo '%s' foi modificada.
settings.remove_protected_branch_success=A salvaguarda do ramo '%s' foi desabilitada.
+settings.remove_protected_branch_failed=A remoção da regra '%s' de salvaguarda do ramo falhou.
settings.protected_branch_deletion=Desabilitar salvaguarda do ramo
settings.protected_branch_deletion_desc=Desabilitar a salvaguarda do ramo irá permitir que os utilizadores que tenham permissão de escrita enviem para o ramo. Quer continuar?
settings.block_rejected_reviews=Bloquear a integração quando há revisões rejeitadas
@@ -2107,10 +2151,13 @@ settings.block_on_official_review_requests_desc=A integração não será possí
settings.block_outdated_branch=Bloquear integração se o pedido de integração for obsoleto
settings.block_outdated_branch_desc=A integração não será possível quando o ramo de topo estiver abaixo do ramo base.
settings.default_branch_desc=Escolha um ramo do repositório como sendo o predefinido para pedidos de integração e cometimentos:
+settings.merge_style_desc=Estilos de integração
settings.default_merge_style_desc=Tipo de integração predefinido para pedidos de integração:
settings.choose_branch=Escolha um ramo…
settings.no_protected_branch=Não existem ramos protegidos.
settings.edit_protected_branch=Editar
+settings.protected_branch_required_rule_name=Nome de regra obrigatório
+settings.protected_branch_duplicate_rule_name=Nome de regra duplicado
settings.protected_branch_required_approvals_min=O número mínimo exigido de aprovações não pode ser negativo.
settings.tags=Etiquetas
settings.tags.protection=Proteger etiquetas
@@ -2126,7 +2173,6 @@ settings.bot_token=Código do bot
settings.chat_id=ID do diálogo
settings.matrix.homeserver_url=URL do servidor caseiro
settings.matrix.room_id=ID da sala
-settings.matrix.access_token=Código de acesso
settings.matrix.message_type=Tipo de mensagem
settings.archive.button=Arquivar repositório
settings.archive.header=Arquivar este repositório
@@ -2244,6 +2290,8 @@ release.edit_subheader=Lançamentos organizam as versões do trabalho.
release.tag_name=Nome da etiqueta
release.target=Alvo
release.tag_helper=Escolha uma etiqueta existente ou crie uma nova.
+release.tag_helper_new=Nova etiqueta. Esta etiqueta será criada a partir do destino.
+release.tag_helper_existing=Etiqueta existente.
release.title=Título
release.content=Conteúdo
release.prerelease_desc=Marcar como pré-lançamento
@@ -2267,6 +2315,8 @@ release.downloads=Descargas
release.download_count=Descargas: %s
release.add_tag_msg=Usar o título e o conteúdo do lançamento como mensagem da etiqueta.
release.add_tag=Criar apenas a etiqueta
+release.releases_for=Lançamentos para %s
+release.tags_for=Etiquetas para %s
branch.name=Nome do ramo
branch.search=Procurar ramos
@@ -2325,7 +2375,7 @@ org_full_name_holder=Nome completo da organização
org_name_helper=Nomes das organizações devem ser curtos e memoráveis.
create_org=Criar organização
repo_updated=Modificado
-people=Pessoas
+members=Membros
teams=Equipas
code=Código
lower_members=membros
@@ -2427,7 +2477,7 @@ teams.remove_all_repos_title=Remover todos os repositórios da equipa
teams.remove_all_repos_desc=Isto irá remover todos os repositórios da equipa.
teams.add_all_repos_title=Adicionar todos os repositórios
teams.add_all_repos_desc=Isto irá adicionar todos os repositórios da organização à equipa.
-teams.add_nonexistent_repo=O repositório que está a tentar adicionar não existe; por favor, crie-o primeiro.
+teams.add_nonexistent_repo=O repositório que está a tentar adicionar não existe
teams.add_duplicate_users=O utilizador já é um membro da equipa.
teams.repos.none=Não há repositórios que possam ser acedidos por esta equipa.
teams.members.none=Não há membros nesta equipa.
@@ -2534,6 +2584,10 @@ dashboard.delete_old_actions=Eliminar todas as operações antigas da base de da
dashboard.delete_old_actions.started=Foi iniciado o processo de eliminação de todas as operações antigas da base de dados.
dashboard.update_checker=Verificador de novas versões
dashboard.delete_old_system_notices=Eliminar todas as notificações do sistema antigas da base de dados
+dashboard.gc_lfs=Recolher lixo dos meta-elementos LFS
+dashboard.stop_zombie_tasks=Parar tarefas zombies
+dashboard.stop_endless_tasks=Parar tarefas intermináveis
+dashboard.cancel_abandoned_jobs=Cancelar trabalhos abandonados
users.user_manage_panel=Gestão das contas de utilizadores
users.new_account=Criar conta de utilizador
@@ -2622,6 +2676,7 @@ repos.size=Tamanho
packages.package_manage_panel=Gestão de pacotes
packages.total_size=Tamanho total: %s
+packages.unreferenced_size=Tamanho não referenciado: %s
packages.owner=Proprietário
packages.creator=Criador
packages.name=Nome
@@ -2715,6 +2770,8 @@ auths.oauth2_required_claim_value_helper=Defina este valor para restringir o inÃ
auths.oauth2_group_claim_name=Reivindicar nome que fornece nomes de grupo para esta fonte. (Opcional)
auths.oauth2_admin_group=Valor da Reivindicação de Grupo para utilizadores administradores. (Opcional - exige a reivindicação de nome acima)
auths.oauth2_restricted_group=Valor da Reivindicação de Grupo para utilizadores restritos. (Opcional - exige a reivindicação de nome acima)
+auths.oauth2_map_group_to_team=Mapear grupos reclamados em equipas da organização (opcional — requer nome de reclamação acima).
+auths.oauth2_map_group_to_team_removal=Remover utilizadores das equipas sincronizadas se esses utilizadores não pertencerem ao grupo correspondente.
auths.enable_auto_register=Habilitar o registo automático
auths.sspi_auto_create_users=Criar utilizadores automaticamente
auths.sspi_auto_create_users_helper=Permitir que o método de autenticação SSPI crie, automaticamente, novas contas para utilizadores que iniciam a sessão pela primeira vez
@@ -2731,17 +2788,17 @@ auths.tips.oauth2.general=Autenticação OAuth2
auths.tips.oauth2.general.tip=Ao registar uma nova autenticação OAuth2, o URL de retorno de chamada/reencaminhamento deve ser: <host>/user/oauth2/<Authentication Name>/callback
auths.tip.oauth2_provider=Fornecedor OAuth2
auths.tip.bitbucket=Registe um novo consumidor de OAuth em https://bitbucket.org/account/user/<o_seu_nome_de_utilizador>/oauth-consumers/new e adicione a permissão 'Account' - 'Read'
-auths.tip.nextcloud=Registe um novo consumidor OAuth na sua instância usando o seguinte menu "Configurações → Segurança → Cliente OAuth 2.0"
+auths.tip.nextcloud=`Registe um novo consumidor OAuth na sua instância usando o seguinte menu "Configurações → Segurança → Cliente OAuth 2.0"`
auths.tip.dropbox=Crie uma nova aplicação em https://www.dropbox.com/developers/apps
-auths.tip.facebook=Registe uma nova aplicação em https://developers.facebook.com/apps e adicione o produto "Facebook Login"
+auths.tip.facebook=`Registe uma nova aplicação em https://developers.facebook.com/apps e adicione o produto "Facebook Login"`
auths.tip.github=Registe uma nova aplicação OAuth em https://github.com/settings/applications/new
auths.tip.gitlab=Registe uma nova aplicação em https://gitlab.com/profile/applications
auths.tip.google_plus=Obtenha credenciais de cliente OAuth2 a partir da consola do Google API em https://console.developers.google.com/
auths.tip.openid_connect=Use o URL da descoberta de conexão OpenID (<server>/.well-known/openid-configuration) para especificar os extremos
-auths.tip.twitter=Vá a https://dev.twitter.com/apps, crie uma aplicação e certifique-se de que está habilitada a opção "Allow this application to be used to Sign in with Twitter"
+auths.tip.twitter=`Vá a https://dev.twitter.com/apps, crie uma aplicação e certifique-se de que está habilitada a opção "Allow this application to be used to Sign in with Twitter"`
auths.tip.discord=Registe uma nova aplicação em https://discordapp.com/developers/applications/me
auths.tip.gitea=Registe uma nova aplicação OAuth2. O guia pode ser encontrado em https://docs.gitea.io/en-us/oauth2-provider/
-auths.tip.yandex=Crie uma nova aplicação em https://oauth.yandex.com/client/new. Escolha as seguintes permissões da secção "Yandex.Passport API": "Acesso ao endereço de email", "Acesso ao avatar do utilizador" e "Acesso ao nome de utilizador, nome e sobrenome, género"
+auths.tip.yandex=`Crie uma nova aplicação em https://oauth.yandex.com/client/new. Escolha as seguintes permissões da secção "Yandex.Passport API": "Acesso ao endereço de email", "Acesso ao avatar do utilizador" e "Acesso ao nome de utilizador, nome e sobrenome, género"`
auths.tip.mastodon=Insira o URL de uma instância personalizada para a instância do mastodon com que se pretende autenticar (ou então use a predefinida)
auths.edit=Editar fonte de autenticação
auths.activated=Esta fonte de autenticação está em funcionamento
@@ -2755,6 +2812,8 @@ auths.still_in_used=A fonte de autenticação ainda está em uso. Tem que primei
auths.deletion_success=A fonte de autenticação foi eliminada.
auths.login_source_exist=A fonte de autenticação '%s' já existe.
auths.login_source_of_type_exist=Já existe uma fonte de autenticação deste tipo.
+auths.unable_to_initialize_openid=Não é possível inicializar o Fornecedor de Ligação OpenID: %s
+auths.invalid_openIdConnectAutoDiscoveryURL=URL de descoberta automática inválido (tem que ser um URL válido começando com http:// ou https://)
config.server_config=Configuração do servidor
config.app_name=Título do sítio
@@ -2977,7 +3036,7 @@ monitor.queue.pool.cancel_desc=Deixar uma fila sem quaisquer grupos de trabalhad
notices.system_notice_list=Notificações do sistema
notices.view_detail_header=Ver os detalhes da notificação
-notices.actions=Operações
+notices.operations=Operações
notices.select_all=Marcar todas
notices.deselect_all=Desmarcar todas
notices.inverse_selection=Inverter as marcações
@@ -3003,6 +3062,7 @@ reopen_pull_request=`reabriu o pedido de integração <a href="%[1]s">%[3]s#%[2]
comment_issue=`comentou na questão <a href="%[1]s">%[3]s#%[2]s</a>`
comment_pull=`comentou no pedido de integração <a href="%[1]s">%[3]s#%[2]s</a>`
merge_pull_request=`fez a integração constante no pedido <a href="%[1]s">%[3]s#%[2]s</a>`
+auto_merge_pull_request=`fez automaticamente a integração constante no pedido <a href="%[1]s">%[3]s#%[2]s</a>`
transfer_repo=transferiu o repositório <code>%s</code> para <a href="%s">%s</a>
push_tag=enviou a etiqueta <a href="%[2]s">%[3]s</a> para <a href="%[1]s">%[4]s</a>
delete_tag=eliminou a etiqueta %[2]de <a href="%[1]s">%[3]s</a>
@@ -3101,6 +3161,8 @@ keywords=Palavras-chave
details=Detalhes
details.author=Autor(a)
details.project_site=Página web do projecto
+details.repository_site=Página web do repositório
+details.documentation_site=Página web da documentação
details.license=Licença
assets=Recursos
versions=Versões
@@ -3108,6 +3170,14 @@ versions.on=ligado
versions.view_all=Ver todas
dependency.id=ID
dependency.version=Versão
+cargo.registry=Configurar este registo no ficheiro de configuração do Cargo (por exemplo: <code>~/.cargo/config.toml</code>):
+cargo.install=Para instalar o pacote usando o Cargo, execute o seguinte comando:
+cargo.documentation=Para obter mais informações sobre o registo do Cargo, consulte <a target="_blank" rel="noopener noreferrer" href="https://docs.gitea.io/en-us/packages/cargo/">a documentação</a>.
+cargo.details.repository_site=Página web do repositório
+cargo.details.documentation_site=Página web da documentação
+chef.registry=Configure este registo no seu ficheiro <code>~/.chef/config.rb</code>:
+chef.install=Para instalar o pacote, execute o seguinte comando:
+chef.documentation=Para obter mais informações sobre o registo do Chef, consulte <a target="_blank" rel="noopener noreferrer" href="https://docs.gitea.io/en-us/packages/chef/">a documentação</a>.
composer.registry=Configure este registo no seu ficheiro <code>~/.composer/config.json</code>:
composer.install=Para instalar o pacote usando o Composer, execute o seguinte comando:
composer.documentation=Para obter mais informações sobre o registo do Composer, consulte <a target="_blank" rel="noopener noreferrer" href="https://docs.gitea.io/en-us/packages/composer/">a documentação</a>.
@@ -3117,10 +3187,13 @@ conan.details.repository=Repositório
conan.registry=Configurar este registo usando a linha de comandos:
conan.install=Para instalar o pacote usando o Conan, execute o seguinte comando:
conan.documentation=Para obter mais informações sobre o registo do Conan, consulte <a target="_blank" rel="noopener noreferrer" href="https://docs.gitea.io/en-us/packages/conan/">a documentação</a>.
+conda.registry=Configure este registo como um repositório Conda no seu ficheiro <code>.condarc</code>:
+conda.install=Para instalar o pacote usando o Conda, execute o seguinte comando:
+conda.documentation=Para obter mais informações sobre o registo do Conda, consulte <a target="_blank" rel="noopener noreferrer" href="https://docs.gitea.io/en-us/packages/conda/">a documentação</a>.
+conda.details.repository_site=Página web do repositório
+conda.details.documentation_site=Página web da documentação
container.details.type=Tipo de imagem
container.details.platform=Plataforma
-container.details.repository_site=Página web do repositório
-container.details.documentation_site=Página web da documentação
container.pull=Puxar a imagem usando a linha de comandos:
container.digest=Resumo:
container.documentation=Para obter mais informações sobre o registo do Container, consulte <a target="_blank" rel="noopener noreferrer" href="https://docs.gitea.io/en-us/packages/container/">a documentação</a>.
@@ -3154,8 +3227,6 @@ npm.dependencies.optional=Dependências opcionais
npm.details.tag=Etiqueta
pub.install=Para instalar o pacote usando o Dart, execute o seguinte comando:
pub.documentation=Para obter mais informações sobre o registo Pub, consulte <a target="_blank" rel="noopener noreferrer" href="https://docs.gitea.io/en-us/packages/pub/">a documentação</a>.
-pub.details.repository_site=Página web do repositório
-pub.details.documentation_site=Página web da documentação
pypi.requires=Requer Python
pypi.install=Para instalar o pacote usando o pip, execute o seguinte comando:
pypi.documentation=Para obter mais informações sobre o registo do PyPI, consulte <a target="_blank" rel="noopener noreferrer" href="https://docs.gitea.io/en-us/packages/pypi/">a documentação</a>.
@@ -3179,4 +3250,110 @@ settings.delete.description=Eliminar o pacote é permanente e não pode ser desf
settings.delete.notice=Está prestes a eliminar %s (%s). Esta operação é irreversível. Tem a certeza?
settings.delete.success=O pacote foi eliminado.
settings.delete.error=Falhou a eliminação do pacote.
+owner.settings.cargo.title=Ãndice do registo do Cargo
+owner.settings.cargo.initialize=Inicializar índice
+owner.settings.cargo.initialize.description=Para usar o registo Cargo, é necessário um repositório git de índice especial. Aqui pode (re)criá-lo com a configuração necessária.
+owner.settings.cargo.initialize.error=Falhou ao inicializar o índice do Cargo: %v
+owner.settings.cargo.initialize.success=O índice do Cargo foi criado com sucesso.
+owner.settings.cargo.rebuild=Reconstruir índice
+owner.settings.cargo.rebuild.description=Se o índice não estiver sincronizado com os pacotes Cargo armazenados, pode reconstruí-lo aqui.
+owner.settings.cargo.rebuild.error=Falhou ao reconstruir o índice do Cargo: %v
+owner.settings.cargo.rebuild.success=O índice do Cargo foi reconstruído com sucesso.
+owner.settings.cleanuprules.title=Gerir regras de limpeza
+owner.settings.cleanuprules.add=Adicionar regra de limpeza
+owner.settings.cleanuprules.edit=Editar regra de limpeza
+owner.settings.cleanuprules.none=Não há regras de limpeza disponíveis. Leia a documentação para obter mais informação.
+owner.settings.cleanuprules.preview=Previsão da regra de limpeza
+owner.settings.cleanuprules.preview.overview=%d pacotes estão agendados para serem removidos.
+owner.settings.cleanuprules.preview.none=A regra de limpeza não corresponde a nenhum pacote.
+owner.settings.cleanuprules.enabled=Habilitado
+owner.settings.cleanuprules.pattern_full_match=Aplicar o padrão ao nome completo do pacote
+owner.settings.cleanuprules.keep.title=As versões que correspondem a estas regras serão mantidas, mesmo que correspondam à regra de remoção abaixo.
+owner.settings.cleanuprules.keep.count=Manter a mais recente
+owner.settings.cleanuprules.keep.count.1=1 versão por pacote
+owner.settings.cleanuprules.keep.count.n=%d versões por pacote
+owner.settings.cleanuprules.keep.pattern=Manter as versões correspondentes
+owner.settings.cleanuprules.keep.pattern.container=A <code>última</code> versão será sempre mantida para pacotes de contentor.
+owner.settings.cleanuprules.remove.title=Versões que correspondam a estas regras serão removidos, a não ser que a regra acima diga para os manter.
+owner.settings.cleanuprules.remove.days=Remover versões mais antigas do que
+owner.settings.cleanuprules.remove.pattern=Remover as versões correspondentes
+owner.settings.cleanuprules.success.update=A regra de limpeza foi modificada.
+owner.settings.cleanuprules.success.delete=A regra de limpeza foi eliminada.
+owner.settings.chef.title=Registo do Chef
+owner.settings.chef.keypair=Gerar par de chaves
+owner.settings.chef.keypair.description=Gerar um par de chaves para se autenticar no registo do Chef. A chave anterior deixará de poder ser utilizada.
+
+[secrets]
+secrets=Segredos
+description=Os segredos serão transmitidos a certas operações e não poderão ser lidos de outra forma.
+none=Ainda não há segredos.
+value=Valor
+name=Nome
+creation=Adicionar segredo
+creation.name_placeholder=apenas caracteres sem distinção de maiúsculas, alfanuméricos ou sublinhados, não podem começar com GITEA_ nem com GITHUB_
+creation.value_placeholder=Insira um conteúdo qualquer. Espaços em branco no início ou no fim serão omitidos.
+creation.success=O segredo '%s' foi adicionado.
+creation.failed=Falhou ao adicionar o segredo.
+deletion=Remover segredo
+deletion.description=Remover um segredo é permanente e não pode ser revertido. Continuar?
+deletion.success=O segredo foi removido.
+deletion.failed=Falhou ao remover o segredo.
+
+[actions]
+actions=Operações
+
+unit.desc=Gerir operações
+
+status.unknown=Desconhecido
+status.waiting=Aguardando
+status.running=Em execução
+status.success=Sucesso
+status.failure=Falha
+status.cancelled=Cancelada
+status.skipped=Ignorada
+status.blocked=Bloqueada
+
+runners=Executores
+runners.runner_manage_panel=Gestão de executores
+runners.new=Criar um novo executor
+runners.new_notice=Como iniciar um executor
+runners.status=Estado
+runners.id=ID
+runners.name=Nome
+runners.owner_type=Tipo
+runners.description=Descrição
+runners.labels=Rótulos
+runners.last_online=Última vez ligado
+runners.agent_labels=Rótulos do agente
+runners.custom_labels=Rótulos personalizados
+runners.custom_labels_helper=Rótulos personalizados são rótulos que são adicionados manualmente por um administrador. São separados por vírgulas e espaços em branco antes e após cada rótulo são ignorados.
+runners.runner_title=Executor
+runners.task_list=Tarefas recentes deste executor
+runners.task_list.run=Executar
+runners.task_list.status=Estado
+runners.task_list.repository=Repositório
+runners.task_list.commit=Cometimento
+runners.task_list.done_at=Feito em
+runners.edit_runner=Editar executor
+runners.update_runner=Guardar alterações
+runners.update_runner_success=O executor foi modificado com sucesso
+runners.update_runner_failed=Falhou ao modificar o executor
+runners.delete_runner=Eliminar o executor
+runners.delete_runner_success=O executor foi eliminado com sucesso
+runners.delete_runner_failed=Falhou ao eliminar o executor
+runners.delete_runner_header=Confirme que quer eliminar este executor
+runners.delete_runner_notice=Se uma tarefa estiver a correr sob este executor, será terminada e marcada como tendo falhado. Pode quebrar o fluxo de trabalho de construção.
+runners.none=Não há executores disponíveis
+runners.status.unspecified=Desconhecido
+runners.status.idle=Parada
+runners.status.active=Em funcionamento
+runners.status.offline=Desconectada
+
+runs.all_workflows=Todos os fluxos de trabalho
+runs.open_tab=%d abertas
+runs.closed_tab=%d fechadas
+runs.commit=Cometimento
+runs.pushed_by=Enviada por
+
+need_approval_desc=É necessária aprovação para executar fluxos de trabalho para a derivação do pedido de integração.
diff --git a/options/locale/locale_ru-RU.ini b/options/locale/locale_ru-RU.ini
index f3efcf8c7..9516a2963 100644
--- a/options/locale/locale_ru-RU.ini
+++ b/options/locale/locale_ru-RU.ini
@@ -41,7 +41,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_insecure=`WebAuthn поддерживает только безопаÑные ÑоединениÑ. Ð”Ð»Ñ Ñ‚ÐµÑÑ‚Ð¸Ñ€Ð¾Ð²Ð°Ð½Ð¸Ñ Ð¿Ð¾ HTTP, вы можете иÑпользовать "localhost" или "127.0.0.1"`
webauthn_error_unable_to_process=Сервер не Ñмог обработать ваш запроÑ.
webauthn_error_duplicated=ПредÑтавленный ключ не подходит Ð´Ð»Ñ Ñтого запроÑа. ЕÑли вы пытаетеÑÑŒ зарегиÑтрировать его, убедитеÑÑŒ, что ключ ещё не зарегиÑтрирован.
webauthn_error_empty=Ð’Ñ‹ должны указать Ð¸Ð¼Ñ Ð´Ð»Ñ Ñтого ключа.
@@ -57,7 +57,6 @@ new_mirror=Ðовое зеркало
new_fork=Ðовый форк репозиториÑ
new_org=ÐÐ¾Ð²Ð°Ñ Ð¾Ñ€Ð³Ð°Ð½Ð¸Ð·Ð°Ñ†Ð¸Ñ
new_project=Ðовый проект
-new_project_board=ÐÐ¾Ð²Ð°Ñ Ð´Ð¾Ñка проекта
manage_org=Управление организациÑми
admin_panel=Панель управлениÑ
account_settings=ÐаÑтройки аккаунта
@@ -86,6 +85,9 @@ remove=Удалить
remove_all=Удалить вÑе
edit=Изменить
+enabled=Включено
+disabled=Отключен
+
copy=Скопировать
copy_url=Копировать URL
copy_branch=Скопировать Ð¸Ð¼Ñ Ð²ÐµÑ‚ÐºÐ¸
@@ -106,6 +108,8 @@ never=Ðикогда
rss_feed=RSS-лента
+[aria]
+
[filter]
[error]
@@ -178,6 +182,8 @@ log_root_path_helper=Файлы журнала будут запиÑыватьÑ
optional_title=РаÑширенные наÑтройки
email_title=ÐаÑтройки Ñлектронной почты
+smtp_addr=Узел SMTP
+smtp_port=SMTP-порт
smtp_from=Отправить Ñл. почту как
smtp_from_helper=ÐÐ´Ñ€ÐµÑ Ñлектронной почты, который будет иÑпользоватьÑÑ Gitea. Введите обычный Ð°Ð´Ñ€ÐµÑ Ñлектронной почты или иÑпользуйте формат "ИмÑ" <email@example.com>.
mailer_user=SMTP логин
@@ -220,7 +226,6 @@ internal_token_failed=Ðе удалоÑÑŒ Ñоздать внутренний Ñ‚
secret_key_failed=Ðе удалоÑÑŒ Ñоздать Ñекретный ключ: %v
save_config_failed=Ðе удалоÑÑŒ Ñохранить конфигурацию: %v
invalid_admin_setting=Ðекорректные наÑтройки учётной запиÑи админиÑтратора: %v
-install_success=Добро пожаловать! Благодарим Ð²Ð°Ñ Ð·Ð° выбор Gitea, пользуйтеÑÑŒ Ñ ÑƒÐ´Ð¾Ð²Ð¾Ð»ÑŒÑтвием!
invalid_log_root_path=ÐедопуÑтимый путь Ð´Ð»Ñ Ð»Ð¾Ð³Ð¾Ð²: %v
default_keep_email_private=Скрывать адреÑа Ñлектронной почты по умолчанию
default_keep_email_private_popup=Скрывать адреÑа Ñлектронной почты новых учетных запиÑей по умолчанию.
@@ -246,7 +251,7 @@ view_home=Показать %s
search_repos=ПоиÑк репозиториÑ…
filter=Другие фильтры
filter_by_team_repositories=Фильтровать по репозиториÑм команды
-feed_of=Лента "%s"
+feed_of=`Лента "%s"`
show_archived=Ðрхивировано
show_both_archived_unarchived=Показаны архивированные и разархивированные
@@ -484,13 +489,13 @@ cannot_add_org_to_team=Организацию Ð½ÐµÐ»ÑŒÐ·Ñ Ð´Ð¾Ð±Ð°Ð²Ð¸Ñ‚ÑŒ в Ð
invalid_ssh_key=Ðе удаетÑÑ Ð¿Ñ€Ð¾Ð²ÐµÑ€Ð¸Ñ‚ÑŒ SSH ключ: %s
invalid_gpg_key=Ðе удаетÑÑ Ð¿Ñ€Ð¾Ð²ÐµÑ€Ð¸Ñ‚ÑŒ GPG ключ: %s
invalid_ssh_principal=Ðеверный учаÑтник: %s
-unable_verify_ssh_key=Ðе удаётÑÑ Ð¿Ñ€Ð¾Ð²ÐµÑ€Ð¸Ñ‚ÑŒ ключ SSH; перепроверьте его на наличие ошибок.
+unable_verify_ssh_key=Ðе удаётÑÑ Ð¿Ñ€Ð¾Ð²ÐµÑ€Ð¸Ñ‚ÑŒ ключ SSH
auth_failed=Ошибка аутентификации: %v
-still_own_repo=Ваша ÑƒÑ‡Ñ‘Ñ‚Ð½Ð°Ñ Ð·Ð°Ð¿Ð¸ÑÑŒ владеет одним или неÑколькими репозиториÑми; Ñначала удалите или перенеÑите их.
-still_has_org=Ваша ÑƒÑ‡Ñ‘Ñ‚Ð½Ð°Ñ Ð·Ð°Ð¿Ð¸ÑÑŒ ÑвлÑетÑÑ Ñ‡Ð»ÐµÐ½Ð¾Ð¼ одной или неÑкольких организаций; Ñначала выйдите из них.
+still_own_repo=Ваша ÑƒÑ‡Ñ‘Ñ‚Ð½Ð°Ñ Ð·Ð°Ð¿Ð¸ÑÑŒ владеет одним или неÑколькими репозиториÑми
+still_has_org=Ваша ÑƒÑ‡Ñ‘Ñ‚Ð½Ð°Ñ Ð·Ð°Ð¿Ð¸ÑÑŒ ÑвлÑетÑÑ Ñ‡Ð»ÐµÐ½Ð¾Ð¼ одной или неÑкольких организаций
still_own_packages=Ваша ÑƒÑ‡Ñ‘Ñ‚Ð½Ð°Ñ Ð·Ð°Ð¿Ð¸ÑÑŒ владеет одним или неÑколькими пакетами, Ñначала удалите их.
-org_still_own_repo=Эта Ð¾Ñ€Ð³Ð°Ð½Ð¸Ð·Ð°Ñ†Ð¸Ñ Ð¿Ð¾-прежнему владеет одним или неÑколькими репозиториÑми; Ñначала удалите или перенеÑите их.
+org_still_own_repo=Эта Ð¾Ñ€Ð³Ð°Ð½Ð¸Ð·Ð°Ñ†Ð¸Ñ Ð¿Ð¾-прежнему владеет одним или неÑколькими репозиториÑми
org_still_own_packages=Эта Ð¾Ñ€Ð³Ð°Ð½Ð¸Ð·Ð°Ñ†Ð¸Ñ Ð²ÑÑ‘ ещё имеет пакеты, Ñначала удалите их.
target_branch_not_exist=Ð¦ÐµÐ»ÐµÐ²Ð°Ñ Ð²ÐµÑ‚ÐºÐ° не ÑущеÑтвует.
@@ -712,6 +717,8 @@ generate_token_success=Ðовый токен Ñоздан. Скопируйте
generate_token_name_duplicate=<strong>%s</strong> уже иÑпользуетÑÑ Ð² качеÑтве имени приложениÑ. ПожалуйÑта, иÑпользуйте другое имÑ.
delete_token=Удалить
access_token_deletion=Удалить токен доÑтупа
+access_token_deletion_cancel_action=Отменить
+access_token_deletion_confirm_action=Удалить
delete_token_success=Токен удалён. ПриложениÑ, иÑпользующие его, больше не имеют доÑтупа к вашему аккаунту.
manage_oauth2_applications=Управление приложениÑми OAuth2
@@ -770,10 +777,12 @@ webauthn_delete_key_desc=ЕÑли вы удалите ключ безопаÑнÐ
manage_account_links=Управление привÑзанными аккаунтами
manage_account_links_desc=Эти внешние аккаунты привÑзаны к вашему аккаунту Gitea.
account_links_not_available=Ð’ наÑтоÑщее Ð²Ñ€ÐµÐ¼Ñ Ð½ÐµÑ‚ внешних аккаунтов, привÑзанных к вашему аккаунту Gitea.
+link_account=ПривÑзать аккаунт
remove_account_link=Удалить привÑзанный аккаунт
remove_account_link_desc=Удаление привÑзанной учетной запиÑи отменит её доÑтуп к вашей учетной запиÑи Gitea. Продолжить?
remove_account_link_success=ПривÑÐ·Ð°Ð½Ð½Ð°Ñ ÑƒÑ‡ÐµÑ‚Ð½Ð°Ñ Ð·Ð°Ð¿Ð¸ÑÑŒ удалена.
+
orgs_none=Ð’Ñ‹ не ÑоÑтоите ни в одной организации.
repos_none=Ð’Ñ‹ не владеете репозиториÑми
@@ -881,9 +890,9 @@ delete_preexisting_success=Удалены непринÑтые файлы в %s
blame_prior=ПоÑмотреть авторÑтво до Ñтих изменений
transfer.accept=ПринÑÑ‚ÑŒ транÑфер
-transfer.accept_desc=ПеремеÑтить в "%s"
+transfer.accept_desc=`ПеремеÑтить в "%s"`
transfer.reject=ОтказатьÑÑ Ð¾Ñ‚ перемещениÑ
-transfer.reject_desc=Отменить перемещение в "%s"
+transfer.reject_desc=`Отменить перемещение в "%s"`
transfer.no_permission_to_accept=ÐедоÑтаточно прав чтобы принÑÑ‚ÑŒ
transfer.no_permission_to_reject=ÐедоÑтаточно прав чтобы отказать
@@ -996,6 +1005,7 @@ tags=Теги
issues=Задачи
pulls=ЗапроÑÑ‹ на ÑлиÑние
project_board=Проекты
+packages=Пакеты
labels=Метки
org_labels_desc=Метки ÑƒÑ€Ð¾Ð²Ð½Ñ Ð¾Ñ€Ð³Ð°Ð½Ð¸Ð·Ð°Ñ†Ð¸Ð¸, которые можно иÑпользовать Ñ <strong>вÑеми репозиториÑми< / strong> в Ñтой организации
org_labels_desc_manage=управлÑÑ‚ÑŒ
@@ -1140,16 +1150,9 @@ projects.type.bug_triage=Планирование работы Ñ Ð±Ð°Ð³Ð°Ð¼Ð¸
projects.template.desc=Шаблон проекта
projects.template.desc_helper=Выберите шаблон проекта Ð´Ð»Ñ Ð½Ð°Ñ‡Ð°Ð»Ð°
projects.type.uncategorized=Без категории
-projects.board.edit=Редактировать доÑку
-projects.board.edit_title=Ðовое Ð¸Ð¼Ñ Ð´Ð¾Ñки
-projects.board.new_title=Ðазвание новой доÑки
-projects.board.new_submit=Отправить
-projects.board.new=ÐÐ¾Ð²Ð°Ñ Ð´Ð¾Ñка
-projects.board.set_default=УÑтановить по умолчанию
-projects.board.set_default_desc=УÑтановить Ñту доÑку по умолчанию Ð´Ð»Ñ Ð½ÐµÐºÐ»Ð°ÑÑифицированных задач и pull-ов
-projects.board.delete=Удалить доÑку
-projects.board.deletion_desc=Удаление доÑки проектов перемещает вÑе ÑвÑзанные задачи в 'Без категории'. Продолжить?
-projects.board.color=Цвет
+projects.column.edit_title=Ðазвание
+projects.column.new_title=Ðазвание
+projects.column.color=Цвет
projects.open=Открыть
projects.close=Закрыть
@@ -1225,6 +1228,7 @@ issues.filter_label_exclude=`ИÑпользуйте <code>alt</code> + <code>cli
issues.filter_label_no_select=Ð’Ñе метки
issues.filter_milestone=Этап
issues.filter_milestone_no_select=Ð’Ñе Ñтапы
+issues.filter_project_none=Ðет проекта
issues.filter_assignee=Ðазначено
issues.filter_assginee_no_select=Ð’Ñе назначениÑ
issues.filter_type=Тип
@@ -1370,6 +1374,7 @@ issues.error_removing_due_date=Ðе удалоÑÑŒ убрать Ñрок выпÐ
issues.push_commit_1=добавил(а) %d коммит %s
issues.push_commits_n=добавил(а) %d коммитов %s
issues.force_push_codes=`принудительно залито %[1]s от <a class="ui sha" href="%[3]s"><code>%[2]s</code></a> к <a class="ui sha" href="%[5]s"><code>%[4]s</code></a> %[6]s`
+issues.force_push_compare=Сравнить
issues.due_date_form=гггг-мм-дд
issues.due_date_form_add=Добавить Ñрок выполнениÑ
issues.due_date_form_edit=Редактировать
@@ -1743,11 +1748,6 @@ settings.enable_timetracker=Включить отÑлеживание време
settings.allow_only_contributors_to_track_time=Учитывать только учаÑтников разработки в подÑчёте времени
settings.pulls_desc=Включить запроÑÑ‹ на ÑлиÑние
settings.pulls.ignore_whitespace=Игнорировать незначащие Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ (пробелы, табулÑциÑ) при проверке на конфликты ÑлиÑниÑ
-settings.pulls.allow_merge_commits=Разрешить коммиты ÑлиÑниÑ
-settings.pulls.allow_rebase_merge=Разрешить rebase-ÑлиÑние
-settings.pulls.allow_rebase_merge_commit=Разрешить rebase Ñ Ñвным коммитом ÑлиÑÐ½Ð¸Ñ (--no-ff)
-settings.pulls.allow_squash_commits=Разрешить объединÑÑ‚ÑŒ коммиты перед ÑлиÑнием (squash)
-settings.pulls.allow_manual_merge=Пометить PR как Ñлитый вручную
settings.pulls.enable_autodetect_manual_merge=Включить автоопределение ручного ÑлиÑÐ½Ð¸Ñ (Примечание: в некоторых оÑобых ÑлучаÑÑ… могут возникнуть ошибки)
settings.pulls.default_delete_branch_after_merge=Удалить ветку запроÑа поÑле его ÑлиÑÐ½Ð¸Ñ Ð¿Ð¾ умолчанию
settings.projects_desc=Включить проекты репозиториÑ
@@ -1786,7 +1786,7 @@ settings.transfer_notices_2=- Ð’Ñ‹ Ñохраните доÑтуп, еÑли нÐ
settings.transfer_notices_3=- еÑли репозиторий ÑвлÑетÑÑ Ð¿Ñ€Ð¸Ð²Ð°Ñ‚Ð½Ñ‹Ð¼ и передаетÑÑ Ð¾Ñ‚Ð´ÐµÐ»ÑŒÐ½Ð¾Ð¼Ñƒ пользователю, Ñто дейÑтвие позволÑет убедитьÑÑ, что пользователь имеет Ñ…Ð¾Ñ‚Ñ Ð±Ñ‹ права на чтение (и при необходимоÑти изменÑет права доÑтупа).
settings.transfer_owner=Ðовый владелец
settings.transfer_perform=Выполнить транÑфер
-settings.transfer_started=Репозиторий ожидает Ð¿Ð¾Ð´Ñ‚Ð²ÐµÑ€Ð¶Ð´ÐµÐ½Ð¸Ñ Ñ‚Ñ€Ð°Ð½Ñфера от "%s"
+settings.transfer_started=`Репозиторий ожидает Ð¿Ð¾Ð´Ñ‚Ð²ÐµÑ€Ð¶Ð´ÐµÐ½Ð¸Ñ Ñ‚Ñ€Ð°Ð½Ñфера от "%s"`
settings.transfer_succeed=Репозиторий перенеÑён.
settings.signing_settings=ÐаÑтройки подпиÑи верификации
settings.trust_model=Модель Ð´Ð¾Ð²ÐµÑ€Ð¸Ñ Ð¿Ð¾Ð´Ð¿Ð¸Ñи
@@ -1873,6 +1873,7 @@ settings.event_delete=Удалить
settings.event_delete_desc=Ветка или тег удалены.
settings.event_fork=Форкнуть
settings.event_fork_desc=Репозиторий форкнут.
+settings.event_wiki=Вики
settings.event_release=Релиз
settings.event_release_desc=Релиз опубликован, обновлён или удалён из репозиториÑ.
settings.event_push=Push
@@ -2013,7 +2014,6 @@ settings.bot_token=Токен Ð´Ð»Ñ Ð±Ð¾Ñ‚Ð°
settings.chat_id=ID чата
settings.matrix.homeserver_url=URL домашнего Ñервера
settings.matrix.room_id=ID комнаты
-settings.matrix.access_token=Токен доÑтупа
settings.matrix.message_type=Тип ÑообщениÑ
settings.archive.button=Ðрхивировать репозиторий
settings.archive.header=Ðрхивировать Ñтот репозиторий
@@ -2108,7 +2108,7 @@ diff.review.approve=Утвердить
diff.review.reject=Ð—Ð°Ð¿Ñ€Ð¾Ñ Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ð¹
diff.committed_by=коммит произвёл
diff.protected=Защищено
-diff.image.side_by_side=Режим "Ñ€Ñдом"
+diff.image.side_by_side=`Режим "Ñ€Ñдом"`
diff.image.swipe=Свайп
diff.image.overlay=Оверлей
@@ -2208,7 +2208,7 @@ org_full_name_holder=Полное название организации
org_name_helper=Лучшие Ð½Ð°Ð·Ð²Ð°Ð½Ð¸Ñ Ð¾Ñ€Ð³Ð°Ð½Ð¸Ð·Ð°Ñ†Ð¸Ð¹ коротки и запоминаемы.
create_org=Создать организацию
repo_updated=Обновлено
-people=Люди
+members=УчаÑтники
teams=Команды
lower_members=УчаÑтники
lower_repositories=Репозитории
@@ -2581,10 +2581,10 @@ auths.tips=Советы
auths.tips.oauth2.general=OAuth2 аутентификациÑ
auths.tips.oauth2.general.tip=При добавлении нового OAuth2 провайдера, URL Ð°Ð´Ñ€ÐµÑ Ð¿ÐµÑ€ÐµÐ°Ð´Ñ€ÐµÑации по завершении аутентификации должен выглÑдеть так: <host>/user/oauth2/<Authentication Name>/callback
auths.tip.oauth2_provider=ПоÑтавщик OAuth2
-auths.tip.bitbucket=Создайте OAuth URI на Ñтранице https://bitbucket.org/account/user/<Ð¸Ð¼Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ>/oauth-consumers/new и добавьте права "Account" - "Read"
-auths.tip.nextcloud=ЗарегиÑтрируйте нового Ð¿Ð¾Ñ‚Ñ€ÐµÐ±Ð¸Ñ‚ÐµÐ»Ñ OAuth в вашем ÑкземплÑре, иÑÐ¿Ð¾Ð»ÑŒÐ·ÑƒÑ Ð¼ÐµÐ½ÑŽ "Settings -> Security -> OAuth 2.0 client"
+auths.tip.bitbucket=`Создайте OAuth URI на Ñтранице https://bitbucket.org/account/user/<Ð¸Ð¼Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ>/oauth-consumers/new и добавьте права "Account" - "Read"`
+auths.tip.nextcloud=`ЗарегиÑтрируйте нового Ð¿Ð¾Ñ‚Ñ€ÐµÐ±Ð¸Ñ‚ÐµÐ»Ñ OAuth в вашем ÑкземплÑре, иÑÐ¿Ð¾Ð»ÑŒÐ·ÑƒÑ Ð¼ÐµÐ½ÑŽ "Settings -> Security -> OAuth 2.0 client"`
auths.tip.dropbox=Добавьте новое приложение на https://www.dropbox.com/developers/apps
-auths.tip.facebook=Создайте новое приложение на https://developers.facebook.com/apps и добавьте модуль "Facebook Login"
+auths.tip.facebook=`Создайте новое приложение на https://developers.facebook.com/apps и добавьте модуль "Facebook Login"`
auths.tip.github=Добавьте OAuth приложение на https://github.com/settings/applications/new
auths.tip.gitlab=Добавьте новое приложение на https://gitlab.com/profile/applications
auths.tip.google_plus=Получите учетные данные клиента OAuth2 в конÑоли Google API на Ñтранице https://console.developers.google.com/
@@ -2592,7 +2592,7 @@ auths.tip.openid_connect=ИÑпользуйте OpenID Connect Discovery URL (<s
auths.tip.twitter=Перейдите на https://dev.twitter.com/apps, Ñоздайте приложение и убедитеÑÑŒ, что включена Ð¾Ð¿Ñ†Ð¸Ñ Â«Ð Ð°Ð·Ñ€ÐµÑˆÐ¸Ñ‚ÑŒ Ñто приложение Ð´Ð»Ñ Ð²Ñ…Ð¾Ð´Ð° в ÑиÑтему Ñ Ð¿Ð¾Ð¼Ð¾Ñ‰ÑŒÑŽ Twitter»
auths.tip.discord=Добавьте новое приложение на https://discordapp.com/developers/applications/me
auths.tip.gitea=ЗарегиÑтрировать новое приложение OAuth2. РуководÑтво можно найти на https://docs.gitea.io/ru-us/oauth2-provider/
-auths.tip.yandex=Создайте новое приложение по адреÑу https://oauth.yandex.com/client/new. Ð’ разделе "API ЯндекÑ.ПаÑпорта" выберите Ñледующие разрешениÑ: "ДоÑтуп к адреÑу Ñлектронной почты", "ДоÑтуп к аватару пользователÑ" и "ДоÑтуп к имени пользователÑ, фамилии и полу"
+auths.tip.yandex=`Создайте новое приложение по адреÑу https://oauth.yandex.com/client/new. Ð’ разделе "API ЯндекÑ.ПаÑпорта" выберите Ñледующие разрешениÑ: "ДоÑтуп к адреÑу Ñлектронной почты", "ДоÑтуп к аватару пользователÑ" и "ДоÑтуп к имени пользователÑ, фамилии и полу"`
auths.tip.mastodon=Введите пользовательÑкий URL ÑкземплÑра Ð´Ð»Ñ ÑкземплÑра mastodon, Ñ ÐºÐ¾Ñ‚Ð¾Ñ€Ñ‹Ð¼ вы хотите аутентифицироватьÑÑ (или иÑпользовать его по умолчанию)
auths.edit=Обновить параметры аутентификации
auths.activated=Эта Ð°ÑƒÑ‚ÐµÐ½Ñ‚Ð¸Ñ„Ð¸ÐºÐ°Ñ†Ð¸Ñ Ð°ÐºÑ‚Ð¸Ð²Ð¸Ñ€Ð¾Ð²Ð°Ð½Ð°
@@ -2682,6 +2682,7 @@ config.skip_tls_verify=ПропуÑтить проверку TLS
config.mailer_enabled=Почта включена
config.mailer_name=ИмÑ
+config.mailer_smtp_port=SMTP-порт
config.mailer_user=Пользователь
config.mailer_use_sendmail=ИÑпользовать Sendmail
config.mailer_sendmail_path=Путь к Sendmail
@@ -2816,7 +2817,6 @@ monitor.queue.pool.cancel_desc=Выход из очереди без групп
notices.system_notice_list=Ð£Ð²ÐµÐ´Ð¾Ð¼Ð»ÐµÐ½Ð¸Ñ ÑиÑтемы
notices.view_detail_header=ПодробноÑти уведомлениÑ
-notices.actions=ДейÑтвиÑ
notices.select_all=Выбрать вÑÑ‘
notices.deselect_all=Отменить выделение
notices.inverse_selection=ИнверÑÐ¸Ñ Ð²Ñ‹Ð´ÐµÐ»ÐµÐ½Ð¸Ñ
@@ -2927,9 +2927,31 @@ installation=УÑтановка
about=Об Ñтом пакете
requirements=ТребованиÑ
dependencies=ЗавиÑимоÑти
+dependency.version=ВерÑиÑ
composer.dependencies=ЗавиÑимоÑти
conan.details.repository=Репозиторий
container.multi_arch=ОС / архитектура
container.labels.key=Ключ
container.labels.value=Значение
+npm.dependencies=ЗавиÑимоÑти
+owner.settings.cleanuprules.enabled=Включено
+
+[secrets]
+value=Значение
+name=Ðазвание
+
+[actions]
+
+
+
+runners.name=Ðазвание
+runners.owner_type=Тип
+runners.description=ОпиÑание
+runners.task_list.run=ЗапуÑк
+runners.task_list.repository=Репозиторий
+runners.task_list.commit=коммит
+runners.status.active=Ðктивный
+
+runs.commit=коммит
+
diff --git a/options/locale/locale_si-LK.ini b/options/locale/locale_si-LK.ini
index 530888663..1f8700900 100644
--- a/options/locale/locale_si-LK.ini
+++ b/options/locale/locale_si-LK.ini
@@ -43,7 +43,6 @@ new_mirror=නව මිරර්
new_fork=නව ගබඩà·à·€ à·†à·à¶šà·Š
new_org=නව සංවිධà·à¶±à¶º
new_project=නව ව්â€à¶ºà·à¶´à·˜à¶­à·’ය
-new_project_board=නව ව්යà·à¶´à·˜à¶­à·’ මණ්ඩලය
manage_org=සංවිධà·à¶± කළමනà·à¶šà¶»à¶«à¶º
admin_panel=අඩවිය පරිපà·à¶½à¶±à¶º
account_settings=ගිණුමේ à·ƒà·à¶šà·ƒà·”ම්
@@ -72,6 +71,9 @@ remove=ඉවත් කරන්න
remove_all=සියල්ල ඉවත් කරන්න
edit=සංස්කරණය
+enabled=සබල කර ඇත
+disabled=අබල කර ඇත
+
copy=පිටපත් කරන්න
copy_url=ඒ.ස.නි. පිටපත්
copy_branch=à·à·à¶›à·à·€à·š නම පිටපත් කරන්න
@@ -91,6 +93,8 @@ error404=ඔබ ළඟ෠වීමට උත්සà·à·„ කරන පිටු
never=කිසි විටෙකත්
+[aria]
+
[filter]
[error]
@@ -152,6 +156,8 @@ log_root_path_helper=ලොග් ගොනු මෙම ඩිරෙක්ටà¶
optional_title=වෛකල්පිත à·ƒà·à¶šà·ƒà·”ම්
email_title=වි-තà·à¶´à·‘ලේ à·ƒà·à¶šà·ƒà·”ම්
+smtp_addr=SMTP සත්කà·à¶»à¶š
+smtp_port=ප්රà·à·Šà¶±à¶º විසඳිල෠වරà·à¶º
smtp_from=ලෙස වි-තà·à¶´à·‘ල යවන්න
smtp_from_helper=විද්යුත් තà·à¶´à·à¶½à·Š ලිපිනය Gitea භà·à·€à·’ත෠කරනු ඇත. සරල විද්යුත් තà·à¶´à·à¶½à·Š ලිපිනයක් ඇතුළත් කරන්න හ෠“නම†<email@example.com> ආකෘතිය භà·à·€à·’ත෠කරන්න.
mailer_user=SMTP පරිà·à·“ලක නà·à¶¸à¶º
@@ -190,7 +196,6 @@ invalid_repo_path=නිධි මූල මà·à¶»à·Šà¶œà¶º අවලංගුà¶
run_user_not_match='ලෙස ධà·à·€à¶±à¶º කරන්න' පරිà·à·“ලක නà·à¶¸à¶º වත්මන් පරිà·à·“ලක නà·à¶¸à¶º නොවේ: %s -> %s
save_config_failed=වින්යà·à·ƒà¶º සුරà·à¶šà·“මට අසමත් විය: %v
invalid_admin_setting=පරිපà·à¶½à¶š ගිණුම් à·ƒà·à¶šà·ƒà·”ම අවලංගුයි: %v
-install_success=à·ƒà·à¶¯à¶»à¶ºà·™à¶±à·Š පිළිගනිමු! ගිටිය෠තà·à¶»à· ගà·à¶±à·“ම ගà·à¶± ස්තූතියි. විනà·à¶¯ වන්න!
invalid_log_root_path=ලොග් මà·à¶»à·Šà¶œà¶º අවලංගුයි: %v
default_keep_email_private=පෙරනිමියෙන් ඊමේල් ලිපින සඟවන්න
default_keep_email_private_popup=පෙරනිමියෙන් නව පරිà·à·“ලක ගිණුම්වල විද්යුත් තà·à¶´à·à¶½à·Š ලිපින සඟවන්න.
@@ -444,12 +449,12 @@ cannot_add_org_to_team=කණ්ඩà·à¶ºà¶¸à·Š à·ƒà·à¶¸à·à¶¢à·’කයෙකà·
invalid_ssh_key=ඔබගේ SSH යතුර සත්යà·à¶´à¶±à¶º කළ නොහà·à¶š: %s
invalid_gpg_key=ඔබගේ GPG යතුර සත්යà·à¶´à¶±à¶º කළ නොහà·à¶š: %s
invalid_ssh_principal=වලංගු නොවන විදුහල්පති: %s
-unable_verify_ssh_key=SSH යතුර සත්යà·à¶´à¶±à¶º කළ නොහà·à¶š; à·€à·à¶»à¶¯à·’ සඳහ෠එය දෙවරක් පරීක්ෂ෠කරන්න.
+unable_verify_ssh_key=SSH යතුර සත්යà·à¶´à¶±à¶º කළ නොහà·à¶š
auth_failed=සත්යà·à¶´à¶± අසමත් විය: %v
-still_own_repo=ඔබගේ ගිණුම සතුව ගබඩà·à·€à¶šà·Š හ෠කිහිපයක් තිබේ; පළමුව ඒව෠මක෠දà·à¶¸à·“ම හ෠මà·à¶»à·” කිරීම.
-still_has_org=ඔබගේ ගිණුම සංවිධà·à¶± එකක් à·„à· à·€à·à¶©à·’ ගණනක à·ƒà·à¶¸à·à¶¢à·’කයෙකි; පළමුව ඒව෠තබන්න.
-org_still_own_repo=මෙම සංවිධà·à¶±à¶º තවමත් ගබඩà·à·€à¶šà·Š à·„à· à·€à·à¶©à·’ ගණනක් සතුය; පළමුව ඒව෠මක෠දà·à¶¸à·“ම හ෠මà·à¶»à·” කිරීම.
+still_own_repo=ඔබගේ ගිණුම සතුව ගබඩà·à·€à¶šà·Š හ෠කිහිපයක් තිබේ
+still_has_org=ඔබගේ ගිණුම සංවිධà·à¶± එකක් à·„à· à·€à·à¶©à·’ ගණනක à·ƒà·à¶¸à·à¶¢à·’කයෙකි
+org_still_own_repo=මෙම සංවිධà·à¶±à¶º තවමත් ගබඩà·à·€à¶šà·Š à·„à· à·€à·à¶©à·’ ගණනක් සතුය
target_branch_not_exist=ඉලක්කගත à·à·à¶›à·à·€ නොපවතී.
@@ -510,6 +515,7 @@ continue=ඉදිරියට
cancel=අවලංගු කරන්න
language=භà·à·‚à·à·€
ui=තේමà·à·€
+comment_type_group_title=සිරà·à·ƒà·’ය
privacy=පෞද්ගලිකත්වය
keep_activity_private=පà·à¶­à·’කඩ පිටුවෙන් ක්රියà·à¶šà·à¶»à¶šà¶¸à·Š සඟවන්න
keep_activity_private_popup=ක්රියà·à¶šà·à¶»à¶šà¶¸à·Š දෘà·à·Šà¶ºà¶¸à·à¶± වන්නේ ඔබට සහ පරිපà·à¶½à¶šà·€à¶»à·” සඳහ෠පමණි
@@ -597,6 +603,11 @@ gpg_token_help=ඔබට අත්සනක් ජනනය කළ à·„à·à¶šà·’à
gpg_token_code=දà·à¶‚කà·à¶»à¶º "%s" | gpg -a -පà·à·„à·à¶» à·„à·à¶»à·“ම-යතුර %s —වෙන්ච-සිග්
gpg_token_signature=සන්නද්ධ GPG අත්සන
key_signature_gpg_placeholder=ආරම්භ වන්නේ '—ආරම්භ කරන්න PGP සිග්නේටුර්—'
+ssh_key_verified=සත්යà·à¶´à·’ත යතුර
+ssh_key_verify=සත්යà·à¶´à¶±à¶º කරන්න
+ssh_token_required=පහත ටà·à¶šà¶±à¶º සඳහ෠ඔබ අත්සනක් ලබ෠දිය යුතුය
+ssh_token=ටà·à¶šà¶±à¶º
+ssh_token_help=ඔබට අත්සනක් ජනනය කළ à·„à·à¶šà·’ය:
subkeys=උප යතුරු
key_id=යතුරෙහි à·„à·à¶³à·”.
key_name=යතුරෙහි නම
@@ -644,6 +655,8 @@ generate_token_success=ඔබේ නව ටà·à¶šà¶±à¶º ජනනය කර ඇà
generate_token_name_duplicate=<strong>%s</strong> දà·à¶±à¶§à¶¸à¶­à·Š යෙදුම් නà·à¶¸à¶ºà¶šà·Š ලෙස භà·à·€à·’ත෠කර ඇත. කරුණà·à¶šà¶» අලුත් එකක් භà·à·€à·’ත෠කරන්න.
delete_token=මකන්න
access_token_deletion=ප්රවේ෠ටà·à¶šà¶±à¶º මකන්න
+access_token_deletion_cancel_action=අවලංගු කරන්න
+access_token_deletion_confirm_action=මකන්න
delete_token_success=ටà·à¶šà¶±à¶º මක෠දම෠ඇත. එය භà·à·€à·’ත෠කරන යෙදුම් තවදුරටත් ඔබගේ ගිණුමට ප්රවේà·à¶º නොමà·à¶­.
manage_oauth2_applications=OUTU2 යෙදුම් කළමනà·à¶šà¶»à¶«à¶º කරන්න
@@ -697,10 +710,12 @@ twofa_failed_get_secret=රහස්ය වීමට අසමත් විය.
manage_account_links=සම්බන්ධිත ගිණුම් කළමනà·à¶šà¶»à¶«à¶º කරන්න
manage_account_links_desc=මෙම බà·à·„ිර ගිණුම් ඔබගේ Gitea ගිණුමට සම්බන්ධ කර ඇත.
account_links_not_available=දà·à¶±à¶§ ඔබගේ Gitea ගිණුමට සම්බන්ධ බà·à·„ිර ගිණුම් නොමà·à¶­.
+link_account=ගිණුම සබà·à¶³à·’න්න
remove_account_link=සම්බන්ධිත ගිණුම ඉවත් කරන්න
remove_account_link_desc=සම්බන්ධිත ගිණුමක් ඉවත් කිරීම ඔබගේ Gitea ගිණුමට එහි ප්රවේà·à¶º අවලංගු කරනු ඇත. දිගටම?
remove_account_link_success=සම්බන්ධිත ගිණුම ඉවත් කර ඇත.
+
orgs_none=ඔබ කිසිදු සංවිධà·à¶±à¶ºà¶š à·ƒà·à¶¸à·à¶¢à·’කයෙකු නොවේ.
repos_none=ඔබට කිසිදු ගබඩà·à·€à¶šà·Š නොමà·à¶­
@@ -807,15 +822,19 @@ delete_preexisting_success=%sදී සම්මත නොකළ ගොනු à¶
blame_prior=මෙම වෙනසට පෙර දොස් බලන්න
transfer.accept=මà·à¶»à·” කිරීම පිළිගන්න
-transfer.accept_desc="%s" වෙත මà·à¶»à·” කරන්න
-transfer.reject_desc="%s" වෙත මà·à¶»à·” කිරීම අවලංගු කරන්න
+transfer.accept_desc=`"%s\" වෙත මà·à¶»à·” කරන්න`
+transfer.reject_desc="
desc.private=පෞද්ගලික
desc.public=ප්â€à¶»à·ƒà·’ද්ධ
+desc.public_template=à·ƒà·à¶šà·’ල්ල
desc.internal=අභ්â€à¶ºà¶±à·Šà¶­à¶»
desc.archived=සංරක්ෂිත
+template.webhooks=වෙබ්කොකු
template.topics=මà·à¶­à·˜à¶šà·
+template.avatar=අවතà·à¶»à·Š
+template.issue_labels=නිකුත් ලේබල
@@ -1030,16 +1049,9 @@ projects.type.bug_triage=දà·à·‚ ට්රයිජ්
projects.template.desc=ව්යà·à¶´à·˜à¶­à·’ à·ƒà·à¶šà·’ල්ල
projects.template.desc_helper=ආරම්භ කිරීම සඳහ෠ව්යà·à¶´à·˜à¶­à·’ à·ƒà·à¶šà·’ල්ලක් තà·à¶»à¶±à·Šà¶±
projects.type.uncategorized=ප්â€à¶»à·€à¶»à·Šà¶œ ගත නà·à¶­à·’
-projects.board.edit=පුවරුව සංස්කරණය
-projects.board.edit_title=නව පුවරුවේ නම
-projects.board.new_title=නව පුවරුවේ නම
-projects.board.new_submit=යොමන්න
-projects.board.new=නව පුවරුව
-projects.board.set_default=පෙරනිමි සකසන්න
-projects.board.set_default_desc=වර්ගීකරණය නොකළ ගà·à¶§à·…à·” සහ අදින සඳහ෠පෙරනිමි ලෙස මෙම පුවරුව සකසන්න
-projects.board.delete=මකන්න මණ්ඩලය
-projects.board.deletion_desc=ව්යà·à¶´à·˜à¶­à·’ මණ්ඩලයක් මක෠දà·à¶¸à·“ම සම්බන්ධ සියලු ගà·à¶§à·…à·” 'Uncategorized' වෙත යොමු කරයි. දිගටම?
-projects.board.color=වර්ණය
+projects.column.edit_title=නම
+projects.column.new_title=නම
+projects.column.color=වර්ණය
projects.open=විවෘත
projects.close=වසන්න
@@ -1107,6 +1119,7 @@ issues.filter_label_exclude=Labels` ඉවත් කිරීමට <code>alt</c
issues.filter_label_no_select=සියලු ලේබල
issues.filter_milestone=සන්ධිස්ථà·à¶±à¶º
issues.filter_milestone_no_select=සියලු සන්ධිස්ථà·à¶±
+issues.filter_project_none=ව්â€à¶ºà·à¶´à·˜à¶­à·’ නà·à¶­
issues.filter_assignee=අස්ගිනී
issues.filter_assginee_no_select=සියලුම ඇග්රි
issues.filter_type=වර්ගය
@@ -1141,6 +1154,7 @@ issues.previous=පසුගිය
issues.next=ඊළඟ
issues.open_title=විවෘත
issues.closed_title=වස෠ඇත
+issues.draft_title=කටුපිටපත
issues.num_comments=අදහස් %d
issues.commented_at=`අදහස් <a href="#%s">%s</a>`
issues.delete_comment_confirm=ඔබට මෙම අදහස මක෠දà·à¶¸à·“මට අවà·à·Šà¶º බව ඔබට විà·à·Šà·€à·à·ƒà¶¯?
@@ -1218,6 +1232,7 @@ issues.lock.reason=අගුළු දà·à¶¸à·“මට හේතුව
issues.lock.title=මෙම ගà·à¶§à·…ුව පිළිබඳ ලොක් සංවà·à¶¯à¶º.
issues.unlock.title=මෙම ගà·à¶§à·…ුව පිළිබඳ සංවà·à¶¯à¶º අගුළු ඇරීමට.
issues.comment_on_locked=අගුලු දම෠ඇති ගà·à¶§à·…ුවක් පිළිබඳව ඔබට අදහස් දà·à¶šà·Šà·€à·’ය නොහà·à¶š.
+issues.delete=මකන්න
issues.tracker=වේලà·à·€ ට්රà·à¶šà¶»à·Š
issues.start_tracking_short=ටයිමරයට ගà·à¶½à¶´à·™à¶± ලෙස
issues.start_tracking=ආරම්භ වේලà·à·€ ට්රà·à¶šà·’න්
@@ -1246,6 +1261,7 @@ issues.error_removing_due_date=නියමිත දිනය ඉවත් කà
issues.push_commit_1=එකතු %d කà·à¶´ %s
issues.push_commits_n=එකතු %d විවරයන් %s
issues.force_push_codes=`බලය-pushed%[1]s සිට <a class="ui sha" href="%[3]s"><code>%[2]s</code></a> <a class="ui sha" href="%[5]s"><code>%[4]ගේ</code></a> %[6]s`
+issues.force_push_compare=සසඳන්න
issues.due_date_form=Yyy-mm-dd
issues.due_date_form_add=නියමිත දිනය එකතු කරන්න
issues.due_date_form_edit=සංස්කරණය
@@ -1559,6 +1575,7 @@ search.search_repo=කà·à·‚්ඨය සොයන්න
search.fuzzy=සිනිඳු
search.match=තරගය
search.results=<a href="%s">%s</a> à·„à·’ "%s" සඳහ෠සෙවුම් ප්â€à¶»à¶­à·’ඵල
+search.code_no_results=ඔබගේ සෙවුම් පදය ගà·à¶½à¶´à·™à¶± ප්රභව කේතයක් නොමà·à¶­.
settings=à·ƒà·à¶šà·ƒà·”ම්
settings.desc=à·ƒà·à¶šà·ƒà·”ම් යනු ගබඩà·à·€ සඳහ෠සà·à¶šà·ƒà·”ම් කළමනà·à¶šà¶»à¶«à¶º කළ à·„à·à¶šà·’ ස්ථà·à¶±à¶ºà¶ºà·’
@@ -1610,11 +1627,6 @@ settings.enable_timetracker=වේලà·à·€ ට්රà·à¶šà·’න් සක්à¶
settings.allow_only_contributors_to_track_time=දà·à¶ºà¶šà¶ºà·’න්ට පමණක් වේලà·à·€ නිරීක්ෂණය කිරීමට ඉඩ දෙන්න
settings.pulls_desc=ගබඩà·à·€à¶šà·Š අදින්න ඉල්ලීම් සක්රීය කරන්න
settings.pulls.ignore_whitespace=ගà·à¶§à·”ම් සඳහ෠වයිට්ස්පේස් නොසලක෠හරින්න
-settings.pulls.allow_merge_commits=සක්රිය කරන්න ඒකà·à¶¶à¶¯à·Šà¶°
-settings.pulls.allow_rebase_merge=ලකුණු ඒකà·à¶¶à¶¯à·Šà¶° කිරීම සඳහ෠නà·à·€à¶­ සකස් කිරීම සක්රීය කරන්න
-settings.pulls.allow_rebase_merge_commit=පà·à·„à·à¶¯à·’ලි ඒකà·à¶¶à¶¯à·Šà¶° කිරීම් සමඟ නà·à·€à¶­ පදනම් කිරීම සක්රීය කරන්න (—No-ff)
-settings.pulls.allow_squash_commits=කà·à¶´à·“ම් ඒකà·à¶¶à¶¯à·Šà¶° කිරීම සඳහ෠ස්කොෂිං සක්රීය කරන්න
-settings.pulls.allow_manual_merge=අතින් ඒකà·à¶¶à¶¯à·Šà¶° ලෙස ලකුණ PR සක්රීය
settings.pulls.enable_autodetect_manual_merge=ස්වයංක්රීය හඳුනà·à¶œà·à¶±à·“මේ අත්පොත ඒකà·à¶¶à¶¯à·Šà¶° කිරීම සක්රීය කරන්න (සටහන: සමහර විà·à·šà·‚ අවස්ථ෠වලදී à·€à·à¶»à¶¯à·’ විනිà·à·Šà¶ à¶ºà¶±à·Š සිදුවිය à·„à·à¶š)
settings.pulls.default_delete_branch_after_merge=පෙරනිමියෙන් ඒකà·à¶¶à¶¯à·Šà¶° කිරීමෙන් පසු අදින්න ඉල්ලීම à·à·à¶›à·à·€ මකන්න
settings.projects_desc=ගබඩà·à·€à¶± ව්යà·à¶´à·˜à¶­à·’ සක්රීය කරන්න
@@ -1733,6 +1745,7 @@ settings.event_delete=මකන්න
settings.event_delete_desc=à·à·à¶›à· හ෠ටà·à¶œà¶º මක෠දමන ලදි.
settings.event_fork=දෙබලක
settings.event_fork_desc=ගබඩà·à·€ à·†à·à¶šà·Š කර ඇත.
+settings.event_wiki=විකි
settings.event_release=නිකුතුව
settings.event_release_desc=ගබඩà·à·€à¶šà·Š තුළ ප්රකà·à·à¶ºà¶§ පත් කරන ලද, යà·à·€à¶­à·Šà¶šà·à¶½à·“න කරන ලද හ෠මක෠දමන ලද නිකුත් කිරීම.
settings.event_push=තල්ලුව
@@ -1860,7 +1873,6 @@ settings.bot_token=බොට් ටà·à¶šà¶±à¶º
settings.chat_id=චà·à¶§à·Š à·„à·à¶³à·”නුම්පත
settings.matrix.homeserver_url=à·„à·à¶¸à·Šà·ƒà¶»à·Šà·€à¶»à·Š URL
settings.matrix.room_id=කà·à¶¸à¶»à¶ºà·š à·„à·à¶³à·”.
-settings.matrix.access_token=ප්රවේ෠ටà·à¶šà¶±à¶º
settings.matrix.message_type=පණිවිඩ වර්ගය
settings.archive.button=කà·à·‚්ඨය සංරක්â€à·‚ණය
settings.archive.header=මෙම කà·à·‚්ඨය සංරක්â€à·‚ණය
@@ -2026,6 +2038,7 @@ branch.included_desc=මෙම à·à·à¶›à·à·€ පෙරනිමි à·à·à¶›à·
branch.included=ඇතුළත්
branch.create_new_branch=à·à·à¶›à·à·€à·™à¶±à·Š à·à·à¶›à·à·€ à·ƒà·à¶¯à¶±à·Šà¶±:
branch.confirm_create_branch=à·à·à¶›à·à·€ à·ƒà·à¶¯à¶±à·Šà¶±
+branch.create_branch_operation=à·à·à¶›à·à·€ à·ƒà·à¶¯à¶±à·Šà¶±
branch.new_branch=නව à·à·à¶›à·à·€à¶šà·Š à·ƒà·à¶¯à¶±à·Šà¶±
branch.new_branch_from='%s' වෙතින් නව à·à·à¶›à·à·€à¶šà·Š à·ƒà·à¶¯à¶±à·Šà¶±
branch.renamed=à·à·à¶›à·à·€ %s %sලෙස නම් කරන ලදී.
@@ -2050,7 +2063,7 @@ org_full_name_holder=සංවිධà·à¶±à¶ºà·š සම්පූර්ණ නම
org_name_helper=සංවිධà·à¶± නම් කෙටි හ෠අමතක නොවන විය යුතුය.
create_org=සංවිධà·à¶±à¶º à·ƒà·à¶¯à¶±à·Šà¶±
repo_updated=යà·à·€à¶­à·Šà¶šà·à¶½ කෙරිණි
-people=මිනිසුන්
+members=à·ƒà·à¶¸à·à¶¢à·’කයින්
teams=කණ්ඩà·à¶ºà¶¸à·Š
lower_members=à·ƒà·à¶¸à·à¶¢à·’කයින්
lower_repositories=කà·à·‚්ඨ
@@ -2119,6 +2132,7 @@ teams.leave=à·„à·à¶»à¶ºà¶±à·Šà¶±
teams.leave.detail=%s à·„à·à¶»à¶ºà¶±à·€à·à¶¯?
teams.can_create_org_repo=කà·à·‚්ඨය à·ƒà·à¶¯à¶±à·Šà¶±
teams.can_create_org_repo_helper=à·ƒà·à¶¸à·à¶¢à·’කයින්ට සංවිධà·à¶±à¶ºà·™à·„à·’ නව කà·à·‚්ඨ සෑදීමට à·„à·à¶šà·’ය. නිර්මà·à¶­à·˜ ට නව කà·à·‚්ඨයෙහි පරිපà·à¶½à¶š ප්â€à¶»à·€à·šà·à¶º ලà·à¶¶à·™à¶±à·” ඇත.
+teams.read_access=කියවූ
teams.read_access_helper=à·ƒà·à¶¸à·à¶¢à·’කයින්ට කණ්ඩà·à¶ºà¶¸à·Š ගබඩà·à·€ බà·à¶½à·“මට හ෠පරිගණක ක්රිඩà·à·€à¶§ සමà·à¶± කළ à·„à·à¶šà·’ය.
teams.write_access_helper=à·ƒà·à¶¸à·à¶¢à·’කයින්ට කණ්ඩà·à¶ºà¶¸à·Š ගබඩà·à·€à¶§ කියව෠තල්ලු කළ à·„à·à¶šà·’ය.
teams.admin_access=පරිපà·à¶½à¶š ප්â€à¶»à·€à·šà·à¶º
@@ -2143,7 +2157,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_nonexistent_repo=ඔබ එකතු කිරීමට උත්සà·à·„ කරන කෝෂ්ඨය නොපවතී
teams.add_duplicate_users=පරිà·à·“ලක දà·à¶±à¶§à¶¸à¶­à·Š කණ්ඩà·à¶ºà¶¸à·š à·ƒà·à¶¸à·à¶¢à·’කයෙකි.
teams.repos.none=මෙම කණ්ඩà·à¶ºà¶¸à¶§ කිසිදු ගබඩà·à·€à¶šà·Š ලබ෠ගත නොහà·à¶šà·’ විය.
teams.members.none=මෙම කණ්ඩà·à¶ºà¶¸à·™à·„à·’ à·ƒà·à¶¸à·à¶¢à·’කයින් නà·à¶­.
@@ -2323,6 +2337,11 @@ repos.forks=දෙබලක
repos.issues=ගà·à¶§à·…à·”
repos.size=ප්â€à¶»à¶¸à·à¶«à¶º
+packages.owner=හිමිකරු
+packages.name=නම
+packages.type=වර්ගය
+packages.repository=කà·à·‚්ඨය
+packages.size=ප්â€à¶»à¶¸à·à¶«à¶º
defaulthooks=පෙරනිමි වෙබ් කොකු
defaulthooks.desc=ඇතà·à¶¸à·Š Gitea සිදුවීම් අවුලුවà·à¶½à¶± විට වෙබ් හූක්ස් ස්වයංක්රීයව සේවà·à¶¯à·à¶ºà¶šà¶ºà¶šà¶§ HTTP පà·à·ƒà·Šà¶§à·Š ඉල්ලීම් කරයි. මෙහි අර්ථ දක්ව෠ඇති වෙබ්කොකු පà·à·„à·à¶» à·„à·à¶»à·“ම් වන අතර සියලු නව ගබඩà·à·€à¶±à·Š වෙත පිටපත් කරනු ලà·à¶¶à·š. තව දුරටත් කියවන්න <a target="_blank" rel="noopener" href="https://docs.gitea.io/en-us/webhooks/">වෙබ් කොකු මà·à¶»à·Šà¶œà·à¶´à¶¯à·šà·à¶º</a>.
@@ -2509,6 +2528,7 @@ config.skip_tls_verify=TLS සත්යà·à¶´à¶±à¶º මඟ හරින්න
config.mailer_enabled=සබල කර ඇත
config.mailer_name=නම
+config.mailer_smtp_port=ප්රà·à·Šà¶±à¶º විසඳිල෠වරà·à¶º
config.mailer_user=පරිà·à·“ලක
config.mailer_use_sendmail=සෙන්ඩ්මේල් භà·à·€à·’ත෠කරන්න
config.mailer_sendmail_path=සෙන්ඩ්මේල් මà·à¶»à·Šà¶œà¶º
@@ -2634,7 +2654,6 @@ monitor.queue.pool.cancel_desc=කිසිදු සේවක කණ්ඩà·à¶
notices.system_notice_list=පද්ධතියේ දà·à¶±à·Šà·€à·“ම්
notices.view_detail_header=දà·à¶±à·Šà·€à·“මේ විස්තර දකින්න
-notices.actions=ක්â€à¶»à·’යà·à¶¸à·à¶»à·Šà¶œ
notices.select_all=සියල්ල තà·à¶»à¶±à·Šà¶±
notices.deselect_all=සියලු විස්තර
notices.inverse_selection=ප්රතිලà·à¶¸ තේරීම
@@ -2715,4 +2734,25 @@ no_read=කියවූ දà·à¶±à·”ම්දීම් නà·à¶­.
[units]
[packages]
+filter.type=වර්ගය
+conan.details.repository=කà·à·‚්ඨය
+owner.settings.cleanuprules.enabled=සබල කර ඇත
+
+[secrets]
+name=නම
+
+[actions]
+
+
+
+runners.name=නම
+runners.owner_type=වර්ගය
+runners.description=සවිස්තරය
+runners.task_list.run=ධà·à·€à¶±à¶º
+runners.task_list.repository=කà·à·‚්ඨය
+runners.task_list.commit=කà·à¶´
+runners.status.active=ක්රියà·à¶šà·à¶»à·“
+
+runs.commit=කà·à¶´
+
diff --git a/options/locale/locale_sk-SK.ini b/options/locale/locale_sk-SK.ini
index be254f65b..87942926e 100644
--- a/options/locale/locale_sk-SK.ini
+++ b/options/locale/locale_sk-SK.ini
@@ -41,7 +41,7 @@ webauthn_use_twofa=Použite kód dvojfaktorového overenia z vášho telefónu
webauthn_error=Nie je možné preÄítaÅ¥ váš bezpeÄnostný kód.
webauthn_unsupported_browser=Váš prehliadaÄ aktuálne nepodporuje WebAuthn.
webauthn_error_unknown=Vyskytla sa neznáma chyba. Skúste to znova.
-webauthn_error_insecure=WebAuthn podporuje iba bezpeÄné spojenia. Na testovanie cez HTTP môžete použiÅ¥ "localhost" alebo "127.0.0.1"
+webauthn_error_insecure=`WebAuthn podporuje iba bezpeÄné spojenia. Na testovanie cez HTTP môžete použiÅ¥ "localhost" alebo "127.0.0.1"`
webauthn_error_unable_to_process=Server nemohol spracovať vašu požiadavku.
webauthn_error_duplicated=BezpeÄnostný kÄ¾ÃºÄ nie je pre túto požiadavku povolený. Uistite sa, že kÄ¾ÃºÄ eÅ¡te nie je zaregistrovaný.
webauthn_error_empty=Musíte nastaviÅ¥ meno pre tento kľúÄ.
@@ -57,7 +57,6 @@ new_mirror=Nové zrkadlo
new_fork=Nový fork repozitára
new_org=Nová organizácia
new_project=Nový projekt
-new_project_board=Nová nástenka projektu
manage_org=Spravovať organizácie
admin_panel=Administrácia
account_settings=Nastavenia úÄtu
@@ -86,6 +85,8 @@ remove=Odstrániť
remove_all=Odstrániť všetko
edit=Upraviť
+enabled=Povolené
+
copy=Kopírovať
copy_url=Kopírovať URL
copy_branch=Kopírovať meno vetvy
@@ -106,6 +107,8 @@ never=Nikdy
rss_feed=RSS kanál
+[aria]
+
[filter]
[error]
@@ -224,7 +227,6 @@ internal_token_failed=Nepodarilo sa vygenerovať interný token: %v
secret_key_failed=Nepodarilo sa vygenerovaÅ¥ tajný kľúÄ: %v
save_config_failed=Nepodarilo sa uložiť konfiguráciu: %v
invalid_admin_setting=Nastavenie administrátorského úÄtu je neplatné: %v
-install_success=Vitajte! Ďakujeme že ste si vybrali Gitea. Veľa zábavy a opatrujte sa!
invalid_log_root_path=Cesta k logom je neplatná: %v
default_keep_email_private=Skrývanie e-mail adries ako predvolené
default_keep_email_private_popup=Predvolene skryÅ¥ e-mailové adresy nových používateľských úÄtov.
@@ -491,14 +493,14 @@ cannot_add_org_to_team=Organizácia nemôže byÅ¥ pridaná ako Älen tímu.
invalid_ssh_key=Nie je možné overiÅ¥ váš SSH kľúÄ: %s
invalid_gpg_key=Nie je možné overiÅ¥ váš GPG kľúÄ: %s
invalid_ssh_principal=Neplatná identita: %s
-unable_verify_ssh_key=Nie je možné overiÅ¥ SSH kľúÄ; znovu skontrolujte chyby.
+unable_verify_ssh_key=Nie je možné overiÅ¥ SSH kľúÄ
auth_failed=Overenie zlyhalo: %v
-still_own_repo=Váš úÄet je vlastníkom jedného alebo viacerých repozitárov; najskôr ich zmažte alebo preveÄte.
-still_has_org=Váš úÄet je Älenom jednej alebo viacerých organizácií; najskôr ich opustite.
-still_own_packages=Váš úÄet je vlastníkom jedného alebo viacerých repozitárov; najskôr ich zmažte alebo preveÄte.
-org_still_own_repo=Váš úÄet je stále vlastníkom jedného alebo viacerých repozitárov; najskôr ich zmažte alebo preveÄte.
-org_still_own_packages=Váš organizácia je vlastníkom jedného alebo viacerých repozitárov; najskôr ich zmažte alebo preveÄte.
+still_own_repo=Váš úÄet je vlastníkom jedného alebo viacerých repozitárov
+still_has_org=Váš úÄet je Älenom jednej alebo viacerých organizácií
+still_own_packages=Váš úÄet je vlastníkom jedného alebo viacerých repozitárov
+org_still_own_repo=Váš úÄet je stále vlastníkom jedného alebo viacerých repozitárov
+org_still_own_packages=Váš organizácia je vlastníkom jedného alebo viacerých repozitárov
target_branch_not_exist=Cieľová vetva neexistuje.
@@ -783,6 +785,7 @@ manage_account_links=Spravovať prepojené kontá
manage_account_links_desc=Tieto externé úÄty sú prepojené s vaším úÄtom Gitea.
link_account=PripojiÅ¥ úÄet
+
orgs_none=Nieste Älenom žiadnej organizácie.
repos_none=Nevlastníte žiadne repozitáre
@@ -878,9 +881,9 @@ delete_preexisting_content=Vymazať súbory v %s
delete_preexisting_success=Vymazané neprijaté súbory v %s
transfer.accept=Prijať prevod
-transfer.accept_desc=Previesť do "%s"
+transfer.accept_desc=`Previesť do "%s"`
transfer.reject=Odmietnuť prevod
-transfer.reject_desc=Zrušiť prevod do "%s"
+transfer.reject_desc=`Zrušiť prevod do "%s"`
transfer.no_permission_to_accept=Nemáte povolenie na prijatie
desc.private=Súkromný
@@ -894,6 +897,7 @@ desc.archived=Archivovaný
template.items=Položky šablóny
template.git_hooks=Git hooky
template.webhooks=Webhooky
+template.avatar=Avatar
template.issue_labels=Štítky úkolov
template.invalid=Vyberte šablónu repozitára
@@ -905,7 +909,9 @@ form.name_reserved=Repozitár s názvom '%s' je rezervovaný.
form.name_pattern_not_allowed=Vzor '%s' nie je povolený v mene repozitára.
migrate_options_mirror_helper=Tento repozitár bude zrkadlom
+migrate_options_lfs_endpoint.label=Koncový bod LFS
migrate_options_lfs_endpoint.description=Migrácia sa pokúsi použiÅ¥ váš vzdialený Git na <a target="_blank" rel="noopener noreferrer" href="%s">urÄenie servera LFS</a>. Môžete tiež zadaÅ¥ vlastný koncový bod, ak sú dáta repozitára LFS uložené niekde inde.
+migrate_items_milestones=Míľniky
migrate_items_issues=Úkoly
migrate_items_pullrequests=Pull requesty
migrate_repo=Migrovať repozitár
@@ -950,6 +956,7 @@ issues=Úkoly
pulls=Pull requesty
project_board=Projekty
+milestones=Míľniky
commits=Commitov
commit=Commit
@@ -999,7 +1006,6 @@ commits.signed_by_untrusted_user_unmatched=Podpísané nedôveryhodným užívat
commits.gpg_key_id=ID GPG kľúÄa
commits.ssh_key_fingerprint=odtlaÄok SSH kľúÄa
-commit.actions=Akcie
commit.revert=Vrátiť
commit.revert-header=Vrátiť: %s
commit.revert-content=Vyberte vetvu pre návrat na:
@@ -1017,22 +1023,33 @@ projects.deletion=Vymazať projekt
projects.edit=Upraviť projekty
projects.modify=Aktualizovať projekt
projects.type.none=Žiadny
-projects.board.new_submit=Poslať
projects.open=Otvoriť
projects.close=Zavrieť
-projects.board.assigned_to=Priradené k
issues.filter_reviewers=Filtrovať revidentov
issues.new=Nový úkol
+issues.new.projects=Projekty
+issues.new.milestone=Míľnik
issues.new.no_reviewers=Žiadni revidenti
issues.new.add_reviewer_title=Požiadať o revíziu
issues.choose.blank_about=Vytvoriť úkol z predvolenej šablóny.
issues.create=Vytvoriť úkol
+issues.filter_label=Štítok
+issues.filter_milestone=Míľnik
+issues.filter_project=Projekt
+issues.filter_assignee=Príjemca
issues.filter_type.all_issues=Všetky úkoly
issues.filter_type.review_requested=Požiadané o revíziu
issues.filter_sort.mostforks=Najviac forkov
issues.filter_sort.fewestforks=Najmenej forkov
+issues.action_open=Otvoriť
+issues.action_close=Zavrieť
+issues.action_label=Štítok
+issues.action_milestone=Míľnik
+issues.action_assignee=Príjemca
+issues.open_title=Otvoriť
issues.context.reference_issue=Odkázať v novom úkole
+issues.close_issue=Zavrieť
issues.closed_at=`uzavrel/a tento úkol <a id="%[1]s" href="#%[1]s">%[2]s</a>`
issues.reopened_at=`znovuotvoril/a tento úkol <a id="%[1]s" href="#%[1]s">%[2]s</a>`
issues.commit_ref_at=`odkázal na tento úkol z commitu <a id="%[1]s" href="#%[1]s">%[2]s</a>`
@@ -1049,6 +1066,7 @@ issues.remove_request_review_block=Nie je možné odstrániť žiadosť o revíz
issues.dismiss_review=Zamietnuť revíziu
issues.dismiss_review_warning=Naozaj chcete zrušiť túto revíziu?
issues.cancel=Zrušiť
+issues.save=Uložiť
issues.label_open_issues=%d otvorených úkolov
issues.label_deletion_desc=Odstránenie štítka ho odstráni zo všetkých úkolov. Ďalej?
issues.lock.unknown_reason=Nie je možné uzamknúť úkol bez dôvodu.
@@ -1105,24 +1123,30 @@ pulls.merge_commit_id=ID zluÄovacieho commitu
+milestones.open=Otvoriť
+milestones.close=Zavrieť
milestones.cancel=Zrušiť
+wiki.page=Stránka
+wiki.new_page=Stránka
+activity.new_issues_count_1=Nový úkol
+activity.unresolved_conv_label=Otvoriť
activity.git_stats_commit_1=%d commit
activity.git_stats_commit_n=%d commity
+search=Hľadať
+search.fuzzy=Fuzzy
+search.match=Zhoda
+search.code_no_results=Nenašiel sa žiaden zdrojový kód zodpovedajúci hľadanému výrazu.
+search.code_search_unavailable=Vyhľadávanie kódu momentálne nie je dostupné. Kontaktujte, prosím, správcu.
settings.collaboration.owner=Vlastník
settings.hooks=Webhooky
settings.githooks=Git hooky
settings.mirror_settings.mirrored_repository=Zrkadlený repozitár
-settings.pulls.allow_merge_commits=Povoliť Commit Merging
-settings.pulls.allow_rebase_merge_commit=Povoliť Rebase s explicitnými potvrdeniami commitov (--no-ff)
-
-
-settings.pulls.allow_squash_commits=Povoliť Squash pre merge commity
settings.admin_enable_close_issues_via_commit_in_any_branch=Zavrieť úkol pomocou commitu v inej ako východzej vetve
settings.new_owner_has_same_repo=Nový vlastník už repozitár s rovnakým názvom má. Vyberte, prosím, iné meno.
settings.convert_fork=Konvertovať na bežný repozitár
@@ -1134,8 +1158,9 @@ settings.transfer=Previesť vlastníctvo
settings.transfer_notices_1=- Ak prenesiete repozitár na užívateľa, stratíte k nemu prístup.
settings.transfer_notices_2=- Prístup k repozitáru si ponecháte, ak ho prevediete na organizáciu, ktorú (spolu)vlastníte.
settings.transfer_owner=Nový vlastník
-settings.transfer_started=Tento repozitár bol oznaÄený na prenos a Äaká na potvrdenie od "%s"
+settings.transfer_started=`Tento repozitár bol oznaÄený na prenos a Äaká na potvrdenie od "%s"`
settings.transfer_succeed=Repozitár bol prenesený.
+settings.trust_model.collaborator.long=Spolupracovník: Dôverovať podpisom spolupracovníkov
settings.trust_model.collaborator.desc=Platné podpisy spolupracovníkov tohto úložiska budú oznaÄené ako "dôveryhodné" - (bez ohľadu na to, Äi sa zhodujú s prispievateľom alebo nie). V opaÄnom prípade budú platné podpisy oznaÄené ako „nedôveryhodné“, ak sa podpis zhoduje s prispievateľom, a „nezhodujúce sa“, ak nie.
settings.trust_model.committer=Prispievateľ
settings.trust_model.committer.long=Prispievateľ: Dôverovať podpisom, ktoré sa zhodujú s prispievateľmi (toto sa zhoduje s GitHubom a prinúti Gitea podpísané príkazy, aby mali Gitea ako prispievateľa)
@@ -1191,7 +1216,6 @@ settings.block_rejected_reviews_desc=ZlúÄenie nebude možné v prípade že of
settings.block_on_official_review_requests=BlokovaÅ¥ zlúÄenie pri oficiálnych žiadostiach o revíziu
settings.block_on_official_review_requests_desc=ZlúÄenie nebude možné v prípade že existujú oficiálne žiadosti o revíziu, aj keÄ je k dispozícii dostatok schválení.
settings.bot_token=Token robota
-settings.matrix.access_token=Prístupový token
settings.lfs_findcommits=Hľadať commity
settings.lfs_lfs_file_no_commits=Pre tento súbor LFS sa nenašli žiadne commity
@@ -1317,6 +1341,16 @@ error.not_signed_commit=Nie je podpísaný commit
[packages]
conan.details.repository=Repozitár
-container.details.repository_site=Stránka repozitára
-pub.details.repository_site=Stránka repozitára
+owner.settings.cleanuprules.enabled=Povolené
+
+[secrets]
+
+[actions]
+
+
+
+runners.task_list.commit=Commit
+
+runs.commit=Commit
+
diff --git a/options/locale/locale_sv-SE.ini b/options/locale/locale_sv-SE.ini
index 55bfbcb5b..c79f99d51 100644
--- a/options/locale/locale_sv-SE.ini
+++ b/options/locale/locale_sv-SE.ini
@@ -42,7 +42,6 @@ new_mirror=Ny Spegling
new_fork=Ny förgrening av utvecklingskatalog
new_org=Ny organisation
new_project=Nytt projekt
-new_project_board=Ny projekttavla
manage_org=Hantera organisationer
admin_panel=Sidadministration
account_settings=Kontoinställningar
@@ -68,6 +67,10 @@ add=Lägg till
add_all=Lägg till alla
remove=Ta bort
remove_all=Ta bort alla
+edit=Redigera
+
+enabled=Aktiv
+disabled=Inaktiverad
write=Skriv
@@ -79,6 +82,8 @@ error404=Sidan du försöker nå <strong>finns inte</strong> eller så <strong>h
+[aria]
+
[filter]
[error]
@@ -139,6 +144,8 @@ log_root_path_helper=Loggfiler kommer skrivas till denna katalog.
optional_title=Övriga inställningar
email_title=Mejlinställningar
+smtp_addr=SMTP-server
+smtp_port=SMTP-port
smtp_from=Skicka Mejl Som
smtp_from_helper=Mejladress som Gitea kommer att använda. Anges i simpelt ('email@example.com') eller fullständigt ('Name <email@example.com>') format.
mailer_user=SMTP-Användarnamn
@@ -177,7 +184,6 @@ invalid_repo_path=Utvecklingskatalogens rotsökväg är ogiltig: %v
run_user_not_match=Systemtjänstanvändaren är inte den nuvarande användaren: %s -> %s
save_config_failed=Misslyckades att spara konfigurationen: %v
invalid_admin_setting=Inställning för administartörskontot är ogiltig: %v
-install_success=Välkommen! Tack för att du valt Gitea. Ha det så roligt, väl mött!
invalid_log_root_path=Sökvägen för loggar är ogiltig: %v
default_keep_email_private=Dölj mailadresser som standard
default_keep_email_private_popup=Dölj mailadresser för nya användarkonton som standard.
@@ -441,6 +447,7 @@ continue=Fortsätt
cancel=Avbryt
language=Språk
ui=Tema
+comment_type_group_title=Titel
privacy=Sekretess
keep_activity_private=Dölj aktiviteten från profilsidan
keep_activity_private_popup=Gör aktiviteten endast synlig för dig och administratörerna
@@ -508,10 +515,15 @@ add_new_gpg_key=Lägg till GPG-nyckel
key_content_gpg_placeholder=Börjar med '-----BEGIN PGP PUBLIC KEY BLOCK-----'
ssh_key_been_used=Denna SSH-nyckel har redan lagts till på servern.
gpg_key_id_used=En publik GPG-nyckel med samma ID existerar redan.
+gpg_key_verify=Verifiera
+gpg_token=Pollett
+ssh_key_verify=Verifiera
+ssh_token=Pollett
subkeys=Undernycklar
key_id=Nyckel-ID
key_name=Nyckelnamn
key_content=Innehåll
+principal_content=Innehåll
add_key_success=SSH-nyckel '%s' har lagts till.
add_gpg_key_success=GPG-nyckel '%s' har lagts till.
delete_key=Ta bort
@@ -548,6 +560,8 @@ generate_token_success=Din nya token har genererats. Kopiera nu då den inte kom
generate_token_name_duplicate=<strong>%s</strong> finns redan som programnamn. Välj ett annat.
delete_token=Radera
access_token_deletion=Ta bort åtkomst token
+access_token_deletion_cancel_action=Avbryt
+access_token_deletion_confirm_action=Radera
delete_token_success=Token har tagits bort. Applikationer som använder den kommer inte längre ha åtkomst till ditt konto.
manage_oauth2_applications=Hantera OAuth2-applikationer
@@ -600,10 +614,12 @@ twofa_enrolled=Tvåfaktorsautentisering har aktiverats för ditt konto. Förvara
manage_account_links=Hantera Länkade Konton
manage_account_links_desc=Dessa externa konton är länkade till ditt Gitea-konto.
account_links_not_available=Det finns för närvarande inga externa konton länkade till ditt Gitea-konto.
+link_account=Länka konto
remove_account_link=Ta Bort Länkat Konto
remove_account_link_desc=Borttagning av länkade konton kommer häva dess åtkomst till ditt Gitea-konto. Vill du fortsätta?
remove_account_link_success=Det länkade konton har tagits bort.
+
orgs_none=Du är inte en medlem i någon organisation.
repos_none=Du har inga utvecklingskataloger associerade med ditt konto
@@ -618,6 +634,8 @@ email_notifications.onmention=Endast e-post vid omnämnanden
email_notifications.disable=Inaktivera notiser via mejl
email_notifications.submit=Ställ in e-post inställningar
+visibility.public=Offentlig
+visibility.private=Privat
[repo]
owner=Ägare
@@ -858,6 +876,7 @@ commits.gpg_key_id=GPG-nyckel ID
ext_issues.desc=Länk till externt ärendehanteringssystem.
projects=Projekt
+projects.description_placeholder=Beskrivning
projects.create=Skapa projekt
projects.title=Titel
projects.new=Nytt projekt
@@ -870,10 +889,8 @@ projects.edit_success=Projektet '%s' har uppdaterats.
projects.type.none=Ingen
projects.template.desc=Projektmall
projects.type.uncategorized=Okatergoriserad
-projects.board.edit=Redigera tavla
-projects.board.new_submit=Skicka
-projects.board.new=Ny tavla
-projects.board.delete=Ta bort tavla
+projects.column.edit_title=Namn
+projects.column.new_title=Namn
projects.open=Öppna
projects.close=Stäng
@@ -940,6 +957,7 @@ issues.filter_label_exclude=`Använd <code>alt</code> + <code>klicka/enter</code
issues.filter_label_no_select=Alla etiketter
issues.filter_milestone=Milsten
issues.filter_milestone_no_select=Alla milstolpar
+issues.filter_project_none=Inget projekt
issues.filter_assignee=Förvärvare
issues.filter_assginee_no_select=Alla tilldelade
issues.filter_type=Typ
@@ -972,6 +990,7 @@ issues.previous=Föregående
issues.next=Nästa
issues.open_title=Öppen
issues.closed_title=Stängd
+issues.draft_title=Utkast
issues.num_comments=%d kommentarer
issues.commented_at=`kommenterad <a href="#%s">%s</a>`
issues.delete_comment_confirm=Är du säker på att du vill ta bort den här kommentaren?
@@ -1045,6 +1064,7 @@ issues.lock.reason=Anledningen till att låsa
issues.lock.title=Lås konversationen för detta ärende.
issues.unlock.title=Lås upp konversation för ärendet.
issues.comment_on_locked=Du kan inte kommentera ett låst ärende.
+issues.delete=Radera
issues.delete.title=Radera detta ärende?
issues.delete.text=Vill du verkligen ta bort detta ärende? (Detta kommer att permanent ta bort allt innehåll. Överväg att stänga det istället om du avser att hålla det arkiverat)
issues.tracker=Tidsredovisning
@@ -1070,6 +1090,7 @@ issues.error_modifying_due_date=Det gick inte att ändra förfallodatumet.
issues.error_removing_due_date=Det gick inte att ta bort förfallodatumet.
issues.push_commit_1=lade till %d commit %s
issues.push_commits_n=lade till %d committer %s
+issues.force_push_compare=Jämför
issues.due_date_form=yyyy-MM-dd
issues.due_date_form_add=Lägg till förfallodatum
issues.due_date_form_edit=Ändra
@@ -1295,6 +1316,7 @@ activity.git_stats_deletion_n=%d borttagningar
search=Sök
search.search_repo=Sök utvecklingskatalog
search.results=Sökresultat för â€%s†i <a href="%s"> %s</a>
+search.code_no_results=Ingen källkod hittades som matchar din sökterm.
settings=Inställningar
settings.desc=Inställningarna är där du kan hantera inställningar för utvecklingskatalogen
@@ -1336,9 +1358,6 @@ settings.enable_timetracker=Aktivera tidsredovisning
settings.allow_only_contributors_to_track_time=Låt endast medarbetare spåra tidsredovisning
settings.pulls_desc=Aktivera Pull Requests för utvecklingskatalog
settings.pulls.ignore_whitespace=Ignorera blanksteg vid konflikter
-settings.pulls.allow_merge_commits=Aktivera Commit Merging
-settings.pulls.allow_rebase_merge=Gör det möjligt för rebasing vid sammanfogning av commits
-settings.pulls.allow_squash_commits=Gör det möjligt att squasha commits vid sammanfogning
settings.admin_settings=Administratörsinställningar
settings.admin_enable_health_check=Aktivera hälsokontroll för utvecklingskataloger (git fsck)
settings.admin_enable_close_issues_via_commit_in_any_branch=Stäng ett ärende via en commit gjord i en icke standard-gren
@@ -1350,6 +1369,7 @@ settings.convert_notices_1=Denna operation kommer att omvandla speglingen till e
settings.convert_confirm=Konvertera utvecklingskatalog
settings.convert_succeed=Speglingen har blivit konverterad till en vanlig utvecklingskatalog.
settings.convert_fork=Konvertera till vanlig utvecklingskatalog
+settings.convert_fork_confirm=Konvertera utvecklingskatalog
settings.transfer=Överför Ägarskap
settings.transfer_desc=Överför denna utvecklingskatalog till en användare eller organisation för vilken du har administratörsrättigheter till.
settings.transfer_form_title=Ange utvecklingskatalogens namn för att bekräfta:
@@ -1382,6 +1402,7 @@ settings.search_user_placeholder=Sök användare…
settings.org_not_allowed_to_be_collaborator=Organisationer kan inte läggas till som en medarbetare.
settings.change_team_access_not_allowed=Att ändra teamåtkomst för utvecklingskatalogen har begränsats till organisationsägaren
settings.team_not_in_organization=Teamet är inte i samma organisation som utvecklingskatalogen
+settings.teams=Grupper
settings.add_team_duplicate=Teamet har redan utvecklingskatalogen
settings.add_team_success=Teamet har nu tillgång till utvecklingskatalogen.
settings.remove_team_success=Teamets åtkomst till utvecklingskatalogen har tagits bort.
@@ -1420,6 +1441,7 @@ settings.event_create_desc=Branch eller tagg skapad.
settings.event_delete=Ta bort
settings.event_fork=Fork
settings.event_fork_desc=Utvecklingskatalog forkad.
+settings.event_wiki=Wiki
settings.event_release=Release
settings.event_release_desc=Releasen publicerad, uppdaterad eller raderad i en utvecklingskatalog.
settings.event_push=Pusha
@@ -1498,7 +1520,6 @@ settings.protected_branch_required_approvals_min=Antal erforderliga godkännande
settings.bot_token=Bot Token
settings.chat_id=Chatt-ID
settings.matrix.room_id=Rum-ID
-settings.matrix.access_token=Ã…tkomsttoken
settings.matrix.message_type=Typ av meddelande
settings.archive.button=Arkivera förråd
settings.archive.header=Arkivera detta förråd
@@ -1571,6 +1592,7 @@ release.new_release=Nytt Släpp
release.draft=Utkast
release.prerelease=Försläpp
release.stable=Stabil
+release.compare=Jämför
release.edit=redigera
release.ahead.commits=<strong>%d</strong> committer
release.ahead.target=till %s sedan denna utgåva
@@ -1634,7 +1656,7 @@ org_full_name_holder=Organisationens Fullständiga Namn
org_name_helper=Organisationsnamn bör vara korta och enkla att komma ihåg.
create_org=Skapa organisation
repo_updated=Uppdaterad
-people=Personer
+members=Medlemmar
teams=Grupper
lower_members=medlemmar
lower_repositories=utvecklingskataloger
@@ -1665,6 +1687,7 @@ settings.visibility=Synlighet
settings.visibility.public=Offentlig
settings.visibility.limited=Begränsad (visas endast för inloggade användare)
settings.visibility.private=Privat (synlig endast för organisationens medlemmar)
+settings.visibility.private_shortname=Privat
settings.update_settings=Uppdatera inställningar
settings.update_setting_success=Organisationsinställningarna har uppdaterats.
@@ -1697,6 +1720,7 @@ teams.join=GÃ¥ med
teams.leave=GÃ¥ ur
teams.can_create_org_repo=Skapa utvecklingskataloger
teams.can_create_org_repo_helper=Medlemmar kan skapa nya utvecklingskataloger i organisationen. Skaparen får administratörsåtkomst till den nya katalogen.
+teams.read_access=Lästa
teams.read_access_helper=Medlemmar kan se och klona teamets utvecklingskataloger.
teams.write_access_helper=Medlemmar kan läsa och pusha till teamets utvecklingskataloger.
teams.admin_access=Administratörsåtkomst
@@ -1822,6 +1846,8 @@ users.delete_account=Ta bort användarkontot
users.still_own_repo=Denna användare äger fortfarande en eller flera utvecklingskataloger. Ta bort eller överför dessa utvecklingskataloger först.
users.still_has_org=Denna användare är medlem i en eller flera organisationer. Ta bort användaren från dessa först.
users.deletion_success=Användarkontot har blivit borttaget.
+users.list_status_filter.is_active=Aktiv
+users.list_status_filter.is_admin=Administratör
emails.primary=Primär
emails.activated=Aktiverad
@@ -1846,6 +1872,11 @@ repos.forks=Forkar
repos.issues=Ärenden
repos.size=Storlek
+packages.owner=Ägare
+packages.name=Namn
+packages.type=Typ
+packages.repository=Utvecklingskatalog
+packages.size=Storlek
systemhooks=Systemets webbhooks
@@ -1985,6 +2016,7 @@ config.skip_tls_verify=Skippa TLS verifiering
config.mailer_enabled=Aktiverad
config.mailer_name=Namn
+config.mailer_smtp_port=SMTP-port
config.mailer_user=Användare
config.mailer_use_sendmail=Använd Sendmail
config.mailer_sendmail_path=Sendmail sökväg
@@ -2059,12 +2091,12 @@ monitor.queue.pool.addworkers.numberworkers.placeholder=Antal arbetare
monitor.queue.pool.flush.title=Töm kö
monitor.queue.pool.flush.desc=Töm komma att lägga till en arbetare som kommer lämna när kön är tom eller när tidsgränsen är nådd.
+monitor.queue.settings.submit=Uppdatera inställningar
monitor.queue.settings.changed=Inställningar uppdaterade
notices.system_notice_list=Systemnotiser
notices.view_detail_header=Visa notisdetaljer
-notices.actions=Åtgärder
notices.select_all=Markera Alla
notices.deselect_all=Avmarkera alla
notices.inverse_selection=Invertera Markeringar
@@ -2143,4 +2175,25 @@ error.no_unit_allowed_repo=Du tillåts inte åtkomst till någon del av denna ut
error.unit_not_allowed=Du har inte åtkomst till denna del av utvecklingskatalogen.
[packages]
+filter.type=Typ
+conan.details.repository=Utvecklingskatalog
+owner.settings.cleanuprules.enabled=Aktiv
+
+[secrets]
+name=Namn
+
+[actions]
+
+
+
+runners.name=Namn
+runners.owner_type=Typ
+runners.description=Beskrivning
+runners.task_list.run=Kör
+runners.task_list.repository=Utvecklingskatalog
+runners.task_list.commit=Commit
+runners.status.active=Aktiv
+
+runs.commit=Commit
+
diff --git a/options/locale/locale_tr-TR.ini b/options/locale/locale_tr-TR.ini
index 37b7491f6..131dfa69a 100644
--- a/options/locale/locale_tr-TR.ini
+++ b/options/locale/locale_tr-TR.ini
@@ -57,7 +57,6 @@ new_mirror=Yeni Yansı
new_fork=Yeni Depo Çatalı
new_org=Yeni Organizasyon
new_project=Yeni Proje
-new_project_board=Yeni Proje panosu
manage_org=Organizasyonları Yönet
admin_panel=Site Yönetimi
account_settings=Hesap Ayarları
@@ -86,6 +85,9 @@ remove=Kaldır
remove_all=Tümünü Kaldır
edit=Düzenle
+enabled=AktifleÅŸtirilmiÅŸ
+disabled=Devre Dışı
+
copy=Kopyala
copy_url=URL'yi kopyala
copy_branch=Dal adını kopyala
@@ -106,6 +108,8 @@ never=Asla
rss_feed=RSS Beslemesi
+[aria]
+
[filter]
string.asc=A - Z
string.desc=Z - A
@@ -226,7 +230,6 @@ internal_token_failed=Dahili belirteç oluşturulamadı: %v
secret_key_failed=Gizli anahtar oluşturulamadı: %v
save_config_failed=%v Yapılandırması kaydedilirken hata oluştu
invalid_admin_setting=Yönetici hesap ayarları geçersiz: %v
-install_success=Hoşgeldiniz! Gitea'yı seçtiğiniz için teşekkür ederiz. Eğlenin ve kendinize iyi bakın!
invalid_log_root_path=Log dosya yolu geçersiz: %v
default_keep_email_private=E-posta adreslerini varsayılan olarak gizle
default_keep_email_private_popup=Yeni kullanıcı hesaplarının e-posta adreslerini varsayılan olarak gizle.
@@ -252,7 +255,7 @@ view_home=%s Görüntüle
search_repos=Depo bul…
filter=Diğer Süzgeçler
filter_by_team_repositories=Takım depolarına göre süz
-feed_of="%s" beslemesi
+feed_of=`"%s\" beslemesi`
show_archived=ArÅŸivlenmiÅŸ
show_both_archived_unarchived=Arşivlenenler ve arşivlenmeyenlerin hepsi gösteriliyor
@@ -285,7 +288,16 @@ code_no_results=Aranan terimlerle eşleşen bir kaynak kod bulunamadı.
code_search_results='%s' için arama sonuçları
code_last_indexed_at=Son endekslenen %s
relevant_repositories_tooltip=Çatal olan veya konusu, simgesi veya açıklaması olmayan depolar gizlenmiştir.
-relevant_repositories=Sadece ilişkili depolar gösteriliyor, <a href="%s">filtrelenmemiş sonuçları göster</a>.
+relevant_repositories=`Sadece ilişkili depolar gösteriliyor, <a href="`
+
+
+show_private=Özel
+
+
+[explore]
+repos=Depolar
+organizations=Organizasyonlar
+code=Kod
[auth]
@@ -322,7 +334,7 @@ non_local_account=Yerel olmayan kullanıcılar parolalarını Gitea web arayüzÃ
verify=DoÄŸrula
scratch_code=Çizgi kodu
use_scratch_code=Bir çizgi kodu kullanınız
-twofa_scratch_used=Çizgi kodunuzu kullandınız. İki aşamalı ayarlar sayfasına yönlendirildiniz, burada cihaz kaydınızı kaldırabilir veya yeni bir çizgi kodu oluşturabilirsiniz.
+twofa_scratch_used=Geçici kodunuzu kullandınız. İki aşamalı ayarlar sayfasına yönlendirildiniz, burada aygıt kaydınızı kaldırabilir veya yeni bir geçici kod oluşturabilirsiniz.
twofa_passcode_incorrect=Şifreniz yanlış. Aygıtınızı yanlış yerleştirdiyseniz, oturum açmak için çizgi kodunuzu kullanın.
twofa_scratch_token_incorrect=Çizgi kodunuz doğru değildir.
login_userpass=Oturum Aç
@@ -501,14 +513,14 @@ duplicate_invite_to_team=Bu kullanıcı zaten takım üyesi olarak davet edilmiÅ
invalid_ssh_key=SSH anahtarınız doğrulanamıyor: %s
invalid_gpg_key=GPG anahtarınız doğrulanamıyor: %s
invalid_ssh_principal=Geçersiz sorumlu: %s
-unable_verify_ssh_key=SSH anahtarı doğrulanamıyor; hatalar için lütfen tekrar kontrol edin.
+unable_verify_ssh_key=SSH anahtarı doğrulanamıyor
auth_failed=Kimlik doğrulaması başarısız oldu: %v
-still_own_repo=Hesabınız bir veya daha fazla depoya sahip; önce onları silin veya transfer edin.
-still_has_org=Hesabınız bir veya daha fazla organizasyonun üyesi; öncelikle onlardan ayrılın.
-still_own_packages=Hesabınız bir veya daha fazla pakete sahip; önce onları silin.
-org_still_own_repo=Bu organizasyon hala bir veya daha fazla depoya sahip; önce onları silin veya transfer edin.
-org_still_own_packages=Bu organizasyon hala bir veya daha fazla pakete sahip; önce onları silin.
+still_own_repo=Hesabınız bir veya daha fazla depoya sahip
+still_has_org=Hesabınız bir veya daha fazla organizasyonun üyesi
+still_own_packages=Hesabınız bir veya daha fazla pakete sahip
+org_still_own_repo=Bu organizasyon hala bir veya daha fazla depoya sahip
+org_still_own_packages=Bu organizasyon hala bir veya daha fazla pakete sahip
target_branch_not_exist=Hedef dal mevcut deÄŸil.
@@ -724,12 +736,12 @@ unbind=Bağlantıyı Kaldır
unbind_success=Sosyal hesabın bağlantısı Gitea hesabınızdan kaldırılmıştır.
manage_access_token=Erişim Jetonlarını Yönet
-generate_new_token=Yeni Jeton Ãœret
+generate_new_token=Yeni Erişim Anahtarı Üret
tokens_desc=Bu jetonlar Gitea API'sini kullanarak hesabınıza erişim sağlar.
new_token_desc=Jeton kullanan uygulamalar hesabınıza tam erişime sahiptir.
token_name=Jeton Ä°smi
-generate_token=Jeton Ãœret
-generate_token_success=Yeni bir jeton oluşturuldu. Tekrar gösterilmeyeceği için şimdi kopyalayın.
+generate_token=Erişim Anahtarı Üret
+generate_token_success=Yeni bir erişim anahtarı oluşturuldu. Tekrar gösterilmeyeceği için şimdi kopyalayın.
generate_token_name_duplicate=<strong>%s</strong> zaten bir uygulama adı olarak kullanılmış. Lütfen yeni bir tane kullanın.
delete_token=Sil
access_token_deletion=EriÅŸim Jetonunu Sil
@@ -772,12 +784,12 @@ twofa_desc=İki faktörlü kimlik doğrulama, hesabınızın güvenliğini artı
twofa_is_enrolled=Hesabınız şu anda iki faktörlü kimlik doğrulaması içinde <strong>kaydedilmiş</strong>.
twofa_not_enrolled=Hesabınız şu anda iki faktörlü kimlik doğrulaması içinde kaydedilmemiş.
twofa_disable=İki Aşamalı Doğrulamayı Devre Dışı Bırak
-twofa_scratch_token_regenerate=Kazıma Belirtecini Yenile
-twofa_scratch_token_regenerated=Kazıma belirteciniz şimdi %s. Güvenli bir yerde saklayın.
+twofa_scratch_token_regenerate=Geçici Kodu Yeniden Üret
+twofa_scratch_token_regenerated=Geçici kodunuz artık %s. Güvenilir bir yerde saklayın.
twofa_enroll=İki Faktörlü Kimlik Doğrulamaya Kaydolun
twofa_disable_note=Gerekirse iki faktörlü kimlik doğrulamayı devre dışı bırakabilirsiniz.
twofa_disable_desc=İki faktörlü kimlik doğrulamayı devre dışı bırakmak hesabınızı daha az güvenli hale getirir. Devam edilsin mi?
-regenerate_scratch_token_desc=Karalama belirtecinizi yanlış yerleştirdiyseniz veya oturum açmak için kullandıysanız, buradan sıfırlayabilirsiniz.
+regenerate_scratch_token_desc=Geçici kodunuzu kaybettiyseniz veya oturum açmak için kullandıysanız, buradan sıfırlayabilirsiniz.
twofa_disabled=İki faktörlü kimlik doğrulama devre dışı bırakıldı.
scan_this_image=Kim doğrulama uygulamanızla bu görüntüyü tarayın:
or_enter_secret=Veya gizli ÅŸeyi girin: %s
@@ -800,6 +812,7 @@ remove_account_link=Bağlantılı Hesabı Kaldır
remove_account_link_desc=Bağlantılı bir hesabı kaldırmak, onunla Gitea hesabınıza erişimi iptal edecektir. Devam edilsin mi?
remove_account_link_success=Bağlantılı hesap kaldırıldı.
+
orgs_none=Herhangi bir organizasyonun bir üyesi değilsiniz.
repos_none=Herhangi bir depoya sahip deÄŸilsiniz
@@ -911,9 +924,9 @@ delete_preexisting_success=%s içindeki kabul edilmeyen dosyalar silindi
blame_prior=Bu değişiklikten önceki suçu görüntüle
transfer.accept=Aktarımı Kabul Et
-transfer.accept_desc="%s" tarafına aktar
+transfer.accept_desc=`"%s\" tarafına aktar`
transfer.reject=Aktarımı Reddet
-transfer.reject_desc="%s" tarafına aktarımı iptal et
+transfer.reject_desc="
transfer.no_permission_to_accept=Kabul Etme iznine sahip deÄŸilsiniz
transfer.no_permission_to_reject=Reddetme iznine sahip deÄŸilsiniz
@@ -1148,7 +1161,7 @@ commits.commits=Ä°ÅŸleme
commits.no_commits=Ortak bir işleme yok. '%s' ve '%s' tamamen farklı geçmişlere sahip.
commits.nothing_to_compare=Bu dallar eÅŸit.
commits.search=İşlemeleri ara…
-commits.search.tooltip=Anahtar kelimeleri "yazar:", "işleyici:", "sonra:" veya "önce:", örneğin; "eski haline yazan: Alice önce: 2019-04-01" ile önekleyebilirsiniz.
+commits.search.tooltip=Anahtar kelimeleri "yazar:", "işleyici:", "sonra:" veya "önce:", örneğin
commits.find=Ara
commits.search_all=Tüm Dallar
commits.author=Yazar
@@ -1162,7 +1175,6 @@ commits.signed_by_untrusted_user_unmatched=İşleyici ile eşleşmeyen güvenilm
commits.gpg_key_id=GPG Anahtar KimliÄŸi
commits.ssh_key_fingerprint=SSH Anahtar Parmak Ä°zi
-commit.actions=Eylemler
commit.revert=Geri Al
commit.revert-header=Geri al: %s
commit.revert-content=Geri almak için dal seçin:
@@ -1195,19 +1207,11 @@ projects.type.bug_triage=Hata Triyajı
projects.template.desc=Proje ÅŸablonu
projects.template.desc_helper=Başlamak için bir proje şablonu seçin
projects.type.uncategorized=Kategorize edilmemiÅŸ
-projects.board.edit=Panoyu düzenle
-projects.board.edit_title=Yeni Pano Adı
-projects.board.new_title=Yeni Pano Adı
-projects.board.new_submit=Gönder
-projects.board.new=Yeni Pano
-projects.board.set_default=Varsayılana Ayarla
-projects.board.set_default_desc=Kategorize edilmemiş konular ve çekme istekleri için bu panoyu varsayılan olarak ayarlayın
-projects.board.delete=Panoyu Sil
-projects.board.deletion_desc=Bir proje panosunun silinmesi, ilgili tüm konuları 'Kategorize edilmemiş'e taşır. Devam edilsin mi?
-projects.board.color=Renk
+projects.column.edit_title=Ä°sim
+projects.column.new_title=Ä°sim
+projects.column.color=Renk
projects.open=Aç
projects.close=Kapat
-projects.board.assigned_to=Atanan
issues.desc=Hata raporlarını, görevleri ve kilometre taşlarını yönetmenizi sağlar.
issues.filter_assignees=Atama Süzgeci
@@ -1283,6 +1287,8 @@ issues.filter_label_exclude=`Etiketleri hariç tutmak için <code>alt</code> + <
issues.filter_label_no_select=Tüm etiketler
issues.filter_milestone=Kilometre Taşı
issues.filter_milestone_no_select=Tüm kilometre taşları
+issues.filter_project=Proje
+issues.filter_project_none=Proje yok
issues.filter_assignee=Atanan
issues.filter_assginee_no_select=Tüm atananlar
issues.filter_poster=Yazar
@@ -1434,6 +1440,7 @@ issues.error_removing_due_date=BitiÅŸ tarihi silinemedi.
issues.push_commit_1=%d iÅŸlemeyi %s ekledi
issues.push_commits_n=%d iÅŸlemeyi %s ekledi
issues.force_push_codes=`%[1]s <a class="ui sha" href="%[3]s"><code>%[2]s</code></a> hedefinden <a class="ui sha" href="%[5]s"><code>%[4]s</code></a> hedefine zorla gönderildi %[6]s`
+issues.force_push_compare=Karşılaştır
issues.due_date_form=yyyy-aa-gg
issues.due_date_form_add=BitiÅŸ tarihi ekle
issues.due_date_form_edit=Düzenle
@@ -1755,8 +1762,6 @@ activity.no_git_activity=Bu dönemde herhangi bir işleme yapılmamıştır.
activity.git_stats_exclude_merges=Birleştirmeler hariç,
activity.git_stats_author_1=%d yazar
activity.git_stats_author_n=%d yazar
-activity.git_stats_pushed_1=
-activity.git_stats_pushed_n=
activity.git_stats_commit_1=%d iÅŸlemeyi
activity.git_stats_commit_n=%d iÅŸlemeyi
activity.git_stats_push_to_branch=%s dalına ve
@@ -1780,7 +1785,7 @@ search.fuzzy=Belirsiz
search.fuzzy.tooltip=Arama terimine benzeyen sonuçları da içer
search.match=EÅŸleÅŸtir
search.match.tooltip=Sadece arama terimiyle tamamen eşleşen sonuçları içer
-search.results="%s" için <a href="%s">%s</a> içinde sonuçları ara
+search.results=`"%s\" için <a href=\"%s\">%s</a> içinde sonuçları ara`
search.code_no_results=Arama teriminizle eşleşen bir kaynak kod bulunamadı.
search.code_search_unavailable=Kod arama şu an mevcut değil. Lütfen site yöneticisiyle iletişime geçin.
@@ -1797,7 +1802,15 @@ settings.hooks=Web Ä°stemcileri
settings.githooks=Git Ä°stemcileri
settings.basic_settings=Temel Ayarlar
settings.mirror_settings=Yansıma Ayarları
-settings.mirror_settings.docs=Projenizi, değişiklikleri başka bir depoya/depodan otomatik olarak gönderecek ve/veya çekecek şekilde ayarlayın. Dallar, etiketler ve işlemeler otomatik olarak senkronize edilecektir. <a target="_blank" rel="noopener noreferrer" href="https://docs.gitea.io/en-us/repo-mirror/">Depoları nasıl yansıtrım?</a>
+settings.mirror_settings.docs=`Projenizi, değişiklikleri başka bir depoya/depodan otomatik olarak gönderecek ve/veya çekecek şekilde ayarlayın. Dallar, etiketler ve işlemeler otomatik olarak senkronize edilecektir. <a target="`
+
+settings=Ayarlar
+settings.options=Depo
+settings.collaboration.write=Yazma
+settings.collaboration.read=OkunmuÅŸ
+settings.collaboration.owner=Sahibi
+settings.hooks=Web Ä°stemcileri
+settings.githooks=Git Ä°stemcileri
settings.mirror_settings.mirrored_repository=Yansıtılmış depo
settings.mirror_settings.direction=Yön
settings.mirror_settings.direction.pull=Çek
@@ -1837,11 +1850,6 @@ settings.enable_timetracker=Zaman Takibini EtkinleÅŸtir
settings.allow_only_contributors_to_track_time=Sadece Katkıcılar İçin Zaman Takibine İzin Ver
settings.pulls_desc=DeÄŸiÅŸiklik Ä°steklerini EtkinleÅŸtir
settings.pulls.ignore_whitespace=Çakışmalar için Boşlukları Gözardı Et
-settings.pulls.allow_merge_commits=Ä°ÅŸleme BirleÅŸtirmeyi EtkinleÅŸtir
-settings.pulls.allow_rebase_merge=İşlemeleri Birleştirmek için Yeniden Yapılandırmayı Etkinleştir
-settings.pulls.allow_rebase_merge_commit=Açık birleştirme işlemeleri ile Yeniden Yapılandırmayı Etkinleştir (--no-ff)
-settings.pulls.allow_squash_commits=İşlemeleri Birleştirmek için Ezmeyi Etkinleştir
-settings.pulls.allow_manual_merge=DÄ°'yi elle birleÅŸtirilmiÅŸ olarak iÅŸaretlemeyi etkinleÅŸtir
settings.pulls.enable_autodetect_manual_merge=Kendiliğinden algılamalı elle birleştirmeyi etkinleştir (Not: Bazı özel durumlarda yanlış kararlar olabilir)
settings.pulls.allow_rebase_update=Değişiklik isteği dalının yeniden yapılandırmayla güncellenmesine izin ver
settings.pulls.default_delete_branch_after_merge=Varsayılan olarak birleştirmeden sonra değişiklik isteği dalını sil
@@ -2010,6 +2018,8 @@ settings.event_package=Paket
settings.event_package_desc=Bir depoda paket oluÅŸturuldu veya silindi.
settings.branch_filter=Dal filtresi
settings.branch_filter_desc=Gönderme, dal oluşturma ve dal silme olayları için glob deseni olarak belirtilen dal beyaz listesi. Boşsa veya <code>*</code> ise, tüm dallar için olaylar raporlanır. Sözdizimi için <a href="https://pkg.go.dev/github.com/gobwas/glob#Compile">github.com/gobwas/glob</a> belgelerine bakın. Örnekler: <code>master</code>, <code>{master,release*}</code>.
+settings.authorization_header=Yetkilendirme Başlığı
+settings.authorization_header_desc=Mevcutsa isteklere yetkilendirme başlığı olarak eklenecektir. Örnekler: %s.
settings.active=Etkin
settings.active_helper=Tetiklenen olaylar hakkındaki bilgiler bu web isteği URL'sine gönderilir.
settings.add_hook_success=Web isteÄŸi eklendi.
@@ -2124,7 +2134,6 @@ settings.bot_token=Bot Jetonu
settings.chat_id=Sohbet KimliÄŸi
settings.matrix.homeserver_url=Ev sunucusu URL'si
settings.matrix.room_id=Oda KimliÄŸi
-settings.matrix.access_token=EriÅŸim Kodu
settings.matrix.message_type=Mesaj Türü
settings.archive.button=Depoyu ArÅŸivle
settings.archive.header=Bu Depoyu ArÅŸivle
@@ -2282,7 +2291,7 @@ branch.create_success='%s' dalı oluşturuldu.
branch.branch_already_exists='%s' dalı zaten bu depoda var.
branch.branch_name_conflict='%s' dal adı zaten mevcut olan '%s' dalıyla çakışıyor.
branch.tag_collision='%s' dalı, depoda aynı ada sahip bir etiket olduğundan oluşturulamıyor.
-branch.deleted_by=%s tarafından silindi
+branch.deleted_by=%s tarafından silindi
branch.restore_success='%s' dalı geri yüklendi.
branch.restore_failed='%s' dalı geri yüklenemedi.
branch.protected_deletion_failed='%s' dalı korunuyor. Silinemez.
@@ -2323,7 +2332,7 @@ org_full_name_holder=Organizasyon Tam Adı
org_name_helper=Organizasyon adları kısa ve hatırlanabilir olmalıdır.
create_org=Organizasyon OluÅŸtur
repo_updated=Güncellendi
-people=Ä°nsanlar
+members=Ãœyeler
teams=Takımlar
code=Kod
lower_members=üyeler
@@ -2436,6 +2445,7 @@ teams.all_repositories_helper=Takımın tüm depolara eriÅŸimi vardır. Bunu seÃ
teams.all_repositories_read_permission_desc=Bu takım <strong>tüm depolara Okuma</strong> erişimi sağlar: üyeler depoları görüntüleyebilir ve kopyalayabilir.
teams.all_repositories_write_permission_desc=Bu takım <strong>tüm depolara Yazma</strong> erişimi sağlar: üyeler depolardan okuyabilir ve depolara itebilir.
teams.all_repositories_admin_permission_desc=Bu takım <strong>tüm depolara Yönetici</strong> erişimi sağlar: üyeler depolardan okuyabilir, itebilir ve katkıcıları ekleyebilir.
+teams.invite.title=<strong>%s</strong> takımına (Organizasyon: <strong>%s</strong>) katılmaya davet edildiniz.
teams.invite.by=%s tarafından davet edildi
teams.invite.description=Takıma katılmak için aşağıdaki düğmeye tıklayın.
@@ -2738,7 +2748,7 @@ auths.tip.openid_connect=Bitiş noktalarını belirlemek için OpenID Connect Di
auths.tip.twitter=https://dev.twitter.com/apps adresine gidin, bir uygulama oluşturun ve “Bu uygulamanın Twitter ile oturum açmak için kullanılmasına izin ver†seçeneğinin etkin olduğundan emin olun
auths.tip.discord=https://discordapp.com/developers/applications/me adresinde yeni bir uygulama kaydedin
auths.tip.gitea=Yeni bir OAuth2 uygulaması kaydedin. Rehber https://docs.gitea.io/en-us/oauth2-provider/ adresinde bulunabilir
-auths.tip.yandex=https://oauth.yandex.com/client/new adresinde yeni bir uygulama oluşturun. "Yandex.Passport API'sı" bölümünden aşağıdaki izinleri seçin: "E-posta adresine erişim", "Kullanıcı avatarına erişim" ve "Kullanıcı adına, ad ve soyadına, cinsiyete erişim"
+auths.tip.yandex=`https://oauth.yandex.com/client/new adresinde yeni bir uygulama oluşturun. "Yandex.Passport API'sı" bölümünden aşağıdaki izinleri seçin: "E-posta adresine erişim", "Kullanıcı avatarına erişim" ve "Kullanıcı adına, ad ve soyadına, cinsiyete erişim"`
auths.tip.mastodon=Kimlik doğrulaması yapmak istediğiniz mastodon örneği için özel bir örnek URL girin (veya varsayılan olanı kullanın)
auths.edit=Kimlik Doğrulama Kaynağı Düzenle
auths.activated=Bu Kimlik Doğrulama Kaynağı Etkinleştirildi
@@ -2974,7 +2984,6 @@ monitor.queue.pool.cancel_desc=Herhangi bir çalışan grubu olmadan bir kuyruk
notices.system_notice_list=Sistem Bildirimleri
notices.view_detail_header=Bildirim Ayrıntılarını Görüntüle
-notices.actions=Ä°ÅŸlemler
notices.select_all=Tümünü Seç
notices.deselect_all=Tümünü Seçmeyi Bırak
notices.inverse_selection=Seçimi Tersine Çevir
@@ -3000,6 +3009,7 @@ reopen_pull_request=`<a href="%[1]s">%[3]s#%[2]s</a> deÄŸiÅŸiklik isteÄŸini yeni
comment_issue=`<a href="%[1]s">%[3]s#%[2]s</a> konusuna yorum yaptı`
comment_pull=`<a href="%[1]s">%[3]s#%[2]s</a> değişiklik isteğine yorum yaptı`
merge_pull_request=`<a href="%[1]s">%[3]s#%[2]s</a> deÄŸiÅŸiklik isteÄŸini birleÅŸtirdi`
+auto_merge_pull_request=`<a href="%[1]s">%[3]s#%[2]s</a> deÄŸiÅŸiklik isteÄŸi otomatik olarak birleÅŸtirildi`
transfer_repo=depo <code>%s</code> <a href="%s">%s</a>'a aktarıldı
push_tag=<a href="%[2]s">%[3]s</a> etiketini <a href="%[1]s">%[4]s</a> dalına gönderdi
delete_tag=%[2]s etiketi <a href="%[1]s">%[3]s</a> deposundan silindi
@@ -3105,6 +3115,7 @@ versions.on=açık
versions.view_all=Tümünü görüntüle
dependency.id=Kimlik
dependency.version=Sürüm
+chef.install=Paketi kurmak için, aşağıdaki komutu çalıştırın:
composer.registry=Bu kütüğü <code>~/.composer/config.json</code> dosyasında ayarlayın:
composer.install=Paketi Composer ile kurmak için, şu komutu çalıştırın:
composer.documentation=Composer kütüğü hakkında daha fazla bilgi için, <a target="_blank" rel="noopener noreferrer" href="https://docs.gitea.io/en-us/packages/composer/">belgeye</a> bakabilirsiniz.
@@ -3116,8 +3127,6 @@ conan.install=Conan ile paket kurmak için aşağıdaki komutu çalıştırın:
conan.documentation=Conan kütüğü hakkında daha fazla bilgi için, <a target="_blank" rel="noopener noreferrer" href="https://docs.gitea.io/en-us/packages/conan/">belgeye</a> bakabilirsiniz.
container.details.type=Görüntü Türü
container.details.platform=Platform
-container.details.repository_site=Depo Sitesi
-container.details.documentation_site=Belge Sitesi
container.pull=Görüntüyü komut satırını kullanarak çekin:
container.digest=Özet:
container.documentation=Taşıyıcı kütüğü hakkında daha fazla bilgi için, <a target="_blank" rel="noopener noreferrer" href="https://docs.gitea.io/en-us/packages/container/">belgeye</a> bakabilirsiniz.
@@ -3151,8 +3160,6 @@ npm.dependencies.optional=İsteğe Bağlı Bağımlılıklar
npm.details.tag=Etiket
pub.install=Paketi Dart ile kurmak için, şu komutu çalıştırın:
pub.documentation=Pub kütüğü hakkında daha fazla bilgi için, <a target="_blank" rel="noopener noreferrer" href="https://docs.gitea.io/en-us/packages/pub/">belgeye</a> bakabilirsiniz.
-pub.details.repository_site=Depo Sitesi
-pub.details.documentation_site=Belge Sitesi
pypi.requires=Gereken Python
pypi.install=Paketi pip ile kurmak için, şu komutu çalıştırın:
pypi.documentation=PyPI kütüğü hakkında daha fazla bilgi için, <a target="_blank" rel="noopener noreferrer" href="https://docs.gitea.io/en-us/packages/pypi/">belgeye</a> bakabilirsiniz.
@@ -3176,4 +3183,26 @@ settings.delete.description=Bir paketi silmek kalıcıdır ve geri alınamaz.
settings.delete.notice=%s (%s) paketini silmek üzeresiniz. Bu işlem geri alınamaz, emin misiniz?
settings.delete.success=Paket silindi.
settings.delete.error=Paket silinemedi.
+owner.settings.cleanuprules.enabled=AktifleÅŸtirilmiÅŸ
+
+[secrets]
+value=DeÄŸer
+name=Ä°sim
+
+[actions]
+
+
+
+runners.id=Kimlik
+runners.name=Ä°sim
+runners.owner_type=Tür
+runners.description=Açıklama
+runners.labels=Etiketler
+runners.task_list.run=Çalıştır
+runners.task_list.repository=Depo
+runners.task_list.commit=Ä°ÅŸle
+runners.status.active=Etkin
+
+runs.commit=Ä°ÅŸle
+
diff --git a/options/locale/locale_uk-UA.ini b/options/locale/locale_uk-UA.ini
index 0b02a82ec..3f39f0baf 100644
--- a/options/locale/locale_uk-UA.ini
+++ b/options/locale/locale_uk-UA.ini
@@ -44,7 +44,6 @@ new_mirror=Ðове дзеркало
new_fork=Ðовий репозиторій - копіÑ
new_org=Ðова організаціÑ
new_project=Ðовий проєкт
-new_project_board=Ðова дошка проєкту
manage_org=ÐšÐµÑ€ÑƒÐ²Ð°Ð½Ð½Ñ Ð¾Ñ€Ð³Ð°Ð½Ñ–Ð·Ð°Ñ†Ñ–Ñми
admin_panel=Панель ÐдмініÑтратора
account_settings=ÐÐ°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ð¾Ð±Ð»Ñ–ÐºÐ¾Ð²Ð¾Ð³Ð¾ запиÑу
@@ -73,6 +72,9 @@ remove=Видалити
remove_all=Видалити вÑе
edit=Редагувати
+enabled=Увімкнено
+disabled=Вимкнено
+
copy=Копіювати
copy_url=Копіювати URL
copy_branch=Копіювати назву гілки
@@ -92,6 +94,8 @@ error404=Сторінка, до Ñкої ви намагаєтеÑÑ Ð·Ð²ÐµÑ€Ð½Ñ
never=Ðіколи
+[aria]
+
[filter]
[error]
@@ -162,6 +166,8 @@ log_root_path_helper=Файли журналу будуть запиÑані в
optional_title=Додаткові налаштуваннÑ
email_title=ÐÐ°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Email
+smtp_addr=SMTP хоÑÑ‚
+smtp_port=SMTP порт
smtp_from=ВідправлÑти Email від імені
smtp_from_helper=Електронна пошта Ð´Ð»Ñ Ð²Ð¸ÐºÐ¾Ñ€Ð¸ÑÑ‚Ð°Ð½Ð½Ñ Ð² GÑ–tea. Введіть звичайну електронну адреÑу або викориÑтовуйте формат: "Ім'Ñ" <email@example.com>.
mailer_user=SMTP Ім'Ñ ÐºÑ€Ð¸Ñтувача
@@ -204,7 +210,6 @@ internal_token_failed=Ðе вдалоÑÑ Ð·Ð³ÐµÐ½ÐµÑ€ÑƒÐ²Ð°Ñ‚Ð¸ внутрішÐ
secret_key_failed=Ðе вдалоÑÑ Ð·Ð³ÐµÐ½ÐµÑ€ÑƒÐ²Ð°Ñ‚Ð¸ Ñекретний ключ: %v
save_config_failed=Ðе в змозі зберегти конфігурацію: %v
invalid_admin_setting=ÐеприпуÑтимі Ð½Ð°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ð¾Ð±Ð»Ñ–ÐºÐ¾Ð²Ð¾Ð³Ð¾ запиÑу адмініÑтратора: %v
-install_success=ЛаÑкаво проÑимо! ДÑкуємо вам за вибір Gitea. РозважайтеÑÑ, Ñ– будьте обережні!
invalid_log_root_path=ÐеприпуÑтимий шлÑÑ… Ð´Ð»Ñ Ð»Ð¾Ð³Ñ–Ð²: %v
default_keep_email_private=Приховати адреÑу електронної пошти за замовчуваннÑм
default_keep_email_private_popup=Приховати адреÑу електронної пошти нових облікових запиÑів за замовчуваннÑм.
@@ -230,7 +235,7 @@ view_home=ПереглÑнути %s
search_repos=Шукати репозиторій…
filter=Інші фільтри
filter_by_team_repositories=Фільтрувати за репозиторіÑми команд
-feed_of=Стрічка "%s"
+feed_of=`Стрічка "%s"`
show_archived=Ðрхівовані
show_both_archived_unarchived=Показано архівовані і не архівовані
@@ -462,12 +467,12 @@ cannot_add_org_to_team=Організацію неможливо додати Ñ
invalid_ssh_key=Ðеможливо перевірити ваш SSH ключ: %s
invalid_gpg_key=Ðеможливо перевірити ваш GPG ключ: %s
invalid_ssh_principal=Ðекоректний відповідальний: %s
-unable_verify_ssh_key=Ðе вдаєтьÑÑ Ð¿Ñ–Ð´Ñ‚Ð²ÐµÑ€Ð´Ð¸Ñ‚Ð¸ ключ SSH; подвійно перевірте його на наÑвніÑÑ‚ÑŒ похибки.
+unable_verify_ssh_key=Ðе вдаєтьÑÑ Ð¿Ñ–Ð´Ñ‚Ð²ÐµÑ€Ð´Ð¸Ñ‚Ð¸ ключ SSH
auth_failed=Помилка автентифікації: %v
-still_own_repo=Ваш обліковий Ð·Ð°Ð¿Ð¸Ñ Ð²Ð¾Ð»Ð¾Ð´Ñ–Ñ” одним або декількома репозиторіÑми; видаліть або перенеÑÑ–Ñ‚ÑŒ Ñ—Ñ… в першу чергу.
-still_has_org=Ваш обліковий Ð·Ð°Ð¿Ð¸Ñ Ñ” учаÑником однієї чи декількох організацій; вийдіть з них в першу чергу.
-org_still_own_repo=Ð¦Ñ Ð¾Ñ€Ð³Ð°Ð½Ñ–Ð·Ð°Ñ†Ñ–Ñ Ñк Ñ– раніше володіє одним або декількома репозиторіÑми; Ñпочатку видаліть або перенеÑÑ–Ñ‚ÑŒ Ñ—Ñ….
+still_own_repo=Ваш обліковий Ð·Ð°Ð¿Ð¸Ñ Ð²Ð¾Ð»Ð¾Ð´Ñ–Ñ” одним або декількома репозиторіÑми
+still_has_org=Ваш обліковий Ð·Ð°Ð¿Ð¸Ñ Ñ” учаÑником однієї чи декількох організацій
+org_still_own_repo=Ð¦Ñ Ð¾Ñ€Ð³Ð°Ð½Ñ–Ð·Ð°Ñ†Ñ–Ñ Ñк Ñ– раніше володіє одним або декількома репозиторіÑми
target_branch_not_exist=Цільової гілки не Ñ–Ñнує.
@@ -574,7 +579,7 @@ delete_email=Видалити
email_deletion=Видалити адреÑу електронної пошти
email_deletion_desc=Електронна адреÑа та пов'Ñзана з нею Ñ–Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ñ–Ñ Ð±ÑƒÐ´Ðµ видалена з вашого облікового запиÑу. Git коміти, здійÑнені через цю електронну адреÑу, залишитьÑÑ Ð±ÐµÐ· змін. Продовжити?
email_deletion_success=ÐдреÑу електронної пошти було видалено.
-theme_update_success=Тему оновлено.
+theme_update_success=Тему оновлено.
theme_update_error=Вибрана тема не Ñ–Ñнує.
openid_deletion=Видалити адреÑу OpenID
openid_deletion_desc=Ð’Ð¸Ð´Ð°Ð»ÐµÐ½Ð½Ñ Ñ†Ñ–Ñ”Ñ— OpenID-адреÑи з вашого облікового запиÑу заборонÑÑ” вам входити з ним. Продовжити?
@@ -621,8 +626,12 @@ gpg_token=Токен
gpg_token_help=Ви можете Ñтворити Ð¿Ñ–Ð´Ð¿Ð¸Ñ Ð·Ð° допомогою:
gpg_token_code=echo "%s" | gpg -a --default-key %s --detach-sig
gpg_token_signature=ТекÑтовий (armored) Ð¿Ñ–Ð´Ð¿Ð¸Ñ GPG
-key_signature_gpg_placeholder=ПочинаєтьÑÑ Ð· "-----BEGIN PGP SIGNATURE-----"
+key_signature_gpg_placeholder=`ПочинаєтьÑÑ Ð· "-----BEGIN PGP SIGNATURE-----"`
+ssh_key_verified=Перевірений ключ
+ssh_key_verify=Підтвердити
+ssh_token_required=Вам потрібно надати Ð¿Ñ–Ð´Ð¿Ð¸Ñ Ð´Ð»Ñ Ð½Ð¸Ð¶Ñ‡ÐµÐ²ÐºÐ°Ð·Ð°Ð½Ð¾Ð³Ð¾ токена
ssh_token=Токен
+ssh_token_help=Ви можете Ñтворити Ð¿Ñ–Ð´Ð¿Ð¸Ñ Ð·Ð° допомогою:
subkeys=Підключі
key_id=ID ключа
key_name=Ім'Ñ ÐºÐ»ÑŽÑ‡Ð°
@@ -670,6 +679,8 @@ generate_token_success=Ваш новий токен був Ñтворений. Ð
generate_token_name_duplicate=Ðазва програми <strong>%s</strong> вже викориÑтовуєтьÑÑ. Будь лаÑка, викориÑтайте нову.
delete_token=Видалити
access_token_deletion=Видалити токен доÑтупу
+access_token_deletion_cancel_action=Відмінити
+access_token_deletion_confirm_action=Видалити
delete_token_success=Токен був знищений. Програми, що викориÑтовують його, більше не мають доÑтупу до вашого облікового запиÑу.
manage_oauth2_applications=ÐšÐµÑ€ÑƒÐ²Ð°Ð½Ð½Ñ Ð¿Ñ€Ð¾Ð³Ñ€Ð°Ð¼Ð°Ð¼Ð¸ OAuth2
@@ -723,10 +734,12 @@ twofa_failed_get_secret=Ðе вдалоÑÑ Ð¾Ñ‚Ñ€Ð¸Ð¼Ð°Ñ‚Ð¸ Ñекрет.
manage_account_links=ÐšÐµÑ€ÑƒÐ²Ð°Ð½Ð½Ñ Ð¾Ð±Ð»Ñ–ÐºÐ¾Ð²Ð¸Ð¼Ð¸ запиÑами
manage_account_links_desc=Ці зовнішні акаунти прив'Ñзані до вашого аккаунту Gitea.
account_links_not_available=Ðаразі немає зовнішніх облікових запиÑів, пов'Ñзаних із вашим обліковим запиÑом Gitea.
+link_account=Прив'Ñзати обліковий запиÑ
remove_account_link=Видалити облікові запиÑи
remove_account_link_desc=Ð’Ð¸Ð´Ð°Ð»ÐµÐ½Ð½Ñ Ð¿Ð¾Ð²'Ñзаного облікового запиÑу відкликає його доÑтуп до вашого облікового запиÑу Gitea. Продовжити?
remove_account_link_success=Зв'Ñзаний обліковий Ð·Ð°Ð¿Ð¸Ñ Ð²Ð¸Ð´Ð°Ð»ÐµÐ½Ð¾.
+
orgs_none=Ви не Ñ” учаÑником будь-Ñкої організації.
repos_none=У Ð²Ð°Ñ Ð½ÐµÐ¼Ð°Ñ” влаÑних репозиторіїв
@@ -833,9 +846,9 @@ delete_preexisting_success=Видалено неприйнÑÑ‚Ñ– файли в %
blame_prior=ПереглÑнути анотацію, що передує цій зміні
transfer.accept=Дозволити транÑфер
-transfer.accept_desc=ПереміÑтити до "%s"
+transfer.accept_desc=`ПереміÑтити до "%s"`
transfer.reject=Відхилити транÑфер
-transfer.reject_desc=СкаÑувати Ð¿ÐµÑ€ÐµÐ¼Ñ–Ñ‰ÐµÐ½Ð½Ñ Ð´Ð¾ "%s"
+transfer.reject_desc=`СкаÑувати Ð¿ÐµÑ€ÐµÐ¼Ñ–Ñ‰ÐµÐ½Ð½Ñ Ð´Ð¾ "%s"`
transfer.no_permission_to_accept=У Ð²Ð°Ñ Ð½ÐµÐ¼Ð°Ñ” дозволу на прийнÑÑ‚Ñ‚Ñ
transfer.no_permission_to_reject=У Ð²Ð°Ñ Ð½ÐµÐ¼Ð°Ñ” дозволу Ð´Ð»Ñ Ð²Ñ–Ð´Ñ…Ð¸Ð»ÐµÐ½Ð½Ñ
@@ -1084,16 +1097,9 @@ projects.type.bug_triage=Ð¡Ð¾Ñ€Ñ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ð¿Ð¾Ð¼Ð¸Ð»Ð¾Ðº
projects.template.desc=Шаблон проєкту
projects.template.desc_helper=Оберіть шаблон проєкту, аби почати
projects.type.uncategorized=Без категорії
-projects.board.edit=Редагувати дошку
-projects.board.edit_title=Ðова назва дошки
-projects.board.new_title=Ðазва нової дошки
-projects.board.new_submit=Створити
-projects.board.new=Ðова дошка
-projects.board.set_default=Ð’Ñтановити за замовчуваннÑм
-projects.board.set_default_desc=Ð’Ñтановити цю дошку за замовчуваннÑм Ð´Ð»Ñ Ð·Ð°Ð´Ð°Ñ‡ без категорії та витÑгувань
-projects.board.delete=Видалити дошку
-projects.board.deletion_desc=Ð’Ð¸Ð´Ð°Ð»ÐµÐ½Ð½Ñ Ð´Ð¾ÑˆÐºÐ¸ проєкту перенеÑе вÑÑ– пов'Ñзані задачі в дошку 'Без категорії'. Продовжити?
-projects.board.color=Колір
+projects.column.edit_title=Ðазва
+projects.column.new_title=Ðазва
+projects.column.color=Колір
projects.open=Відкрити
projects.close=Закрити
@@ -1169,6 +1175,8 @@ issues.filter_label_exclude=`ВикориÑтовуйте <code>Alt</code> + <co
issues.filter_label_no_select=Ð’ÑÑ– мітки
issues.filter_milestone=Етап
issues.filter_milestone_no_select=Ð’ÑÑ– етапи
+issues.filter_project=Проєкт
+issues.filter_project_none=Проєкт відÑутній
issues.filter_assignee=Виконавець
issues.filter_assginee_no_select=Ð’ÑÑ– виконавці
issues.filter_type=Тип
@@ -1203,6 +1211,7 @@ issues.previous=Попередній
issues.next=Далі
issues.open_title=Відкрито
issues.closed_title=Закрито
+issues.draft_title=Чернетка
issues.num_comments=%d коментарів
issues.commented_at=`прокоментував(ла) <a href="#%s">%s</a>`
issues.delete_comment_confirm=Ви впевнені, що хочете видалити цей коментар?
@@ -1281,6 +1290,7 @@ issues.lock.reason=Причина блокуваннÑ
issues.lock.title=Заблокувати Ð¾Ð±Ð³Ð¾Ð²Ð¾Ñ€ÐµÐ½Ð½Ñ Ñ†Ñ–Ñ”Ñ— задачі.
issues.unlock.title=Розблокувати Ð¾Ð±Ð³Ð¾Ð²Ð¾Ñ€ÐµÐ½Ð½Ñ Ñ†Ñ–Ñ”Ñ— задачі.
issues.comment_on_locked=Ви не можете коментувати заблоковану задачу.
+issues.delete=Видалити
issues.tracker=ВідÑÑ‚ÐµÐ¶ÐµÐ½Ð½Ñ Ñ‡Ð°Ñу
issues.start_tracking_short=ЗапуÑтити таймер
issues.start_tracking=Почати відÑÑ‚ÐµÐ¶ÐµÐ½Ð½Ñ Ñ‡Ð°Ñу
@@ -1309,6 +1319,7 @@ issues.error_removing_due_date=Ðе вдалоÑÑ Ð²Ð¸Ð´Ð°Ð»Ð¸Ñ‚Ð¸ дату зÐ
issues.push_commit_1=додав %d коміт %s
issues.push_commits_n=додав %d коміти(-ів) %s
issues.force_push_codes=`примуÑово залито %[1]s з <a class="ui sha" href="%[3]s"><code>%[2]</code></a> до <a class="ui sha" href="%[5]s"><code>%[4]s</code></a> %[6]s`
+issues.force_push_compare=ПорівнÑти
issues.due_date_form=рррр-мм-дд
issues.due_date_form_add=Додати дату завершеннÑ
issues.due_date_form_edit=Редагувати
@@ -1624,6 +1635,7 @@ search.search_repo=Пошук репозиторію
search.fuzzy=Ðеточний
search.match=ЗбігаєтьÑÑ
search.results=Результати пошуку Ð´Ð»Ñ "%s" в <a href="%s">%s</a>
+search.code_no_results=Відповідний пошуковому запитанню код не знайдено.
settings=ÐалаштуваннÑ
settings.desc=У налаштуваннÑÑ… ви можете змінювати різні параметри цього репозиторіÑ
@@ -1675,11 +1687,6 @@ settings.enable_timetracker=Увімкнути відÑÑ‚ÐµÐ¶ÐµÐ½Ð½Ñ Ñ‡Ð°Ñу
settings.allow_only_contributors_to_track_time=Враховувати тільки учаÑників розробки в підрахунку чаÑу
settings.pulls_desc=Увімкнути запити на Ð·Ð»Ð¸Ñ‚Ñ‚Ñ Ð² репозиторій
settings.pulls.ignore_whitespace=Ігнорувати пробіл у конфліктах
-settings.pulls.allow_merge_commits=Дозволити коміти злиттÑ
-settings.pulls.allow_rebase_merge=Увімкнути Rebasing коміти перед злиттÑм
-settings.pulls.allow_rebase_merge_commit=Ввімкнути Rebase з Ñвним злиттÑм (--no-ff)
-settings.pulls.allow_squash_commits=Увімкнути об'єднувати коміти перед злиттÑм
-settings.pulls.allow_manual_merge=Позначити PR Ñк об'єднаний вручну
settings.pulls.enable_autodetect_manual_merge=Увімкнути Ð°Ð²Ñ‚Ð¾Ð²Ð¸Ð·Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ Ñ€ÑƒÑ‡Ð½Ð¾Ð³Ð¾ Ð·Ð»Ð¸Ñ‚Ñ‚Ñ (Примітка: у деÑких оÑобливий випадках можуть виникнуть помилки)
settings.pulls.default_delete_branch_after_merge=ВидалÑти гілку запиту злиттÑ, коли його прийнÑто
settings.projects_desc=Увімкнути проєкти у репозиторії
@@ -1712,7 +1719,7 @@ settings.transfer_notices_2=- Ви збережете доÑтуп, Ñкщо нÐ
settings.transfer_notices_3=- Якщо репозиторій Ñ” приватним Ñ– передаєтьÑÑ Ð¾ÐºÑ€ÐµÐ¼Ð¾Ð¼Ñƒ кориÑтувачеві, Ñ†Ñ Ð´Ñ–Ñ Ð³Ð°Ñ€Ð°Ð½Ñ‚ÑƒÑ”, що кориÑтувач має хоча б дозвіл на Ñ‡Ð¸Ñ‚Ð°Ð½Ñ Ñ€ÐµÐ¿Ð¾Ð·Ð¸Ñ‚Ð°Ñ€Ñ–ÑŽ (Ñ– при необхідноÑÑ‚Ñ– змінює права дозволів).
settings.transfer_owner=Ðовий влаÑник
settings.transfer_perform=ЗдіÑнити перенеÑеннÑ
-settings.transfer_started=Цей репозиторій чекає Ð¿Ñ–Ð´Ñ‚Ð²ÐµÑ€Ð´Ð¶ÐµÐ½Ð½Ñ Ð¿ÐµÑ€ÐµÐ½ÐµÑÐµÐ½Ð½Ñ Ð²Ñ–Ð´ "%s"
+settings.transfer_started=`Цей репозиторій чекає Ð¿Ñ–Ð´Ñ‚Ð²ÐµÑ€Ð´Ð¶ÐµÐ½Ð½Ñ Ð¿ÐµÑ€ÐµÐ½ÐµÑÐµÐ½Ð½Ñ Ð²Ñ–Ð´ "%s"`
settings.transfer_succeed=Репозиторій був перенеÑений.
settings.signing_settings=Параметри перевірки підпиÑу
settings.trust_model=Модель довіри Ð´Ð»Ñ Ð¿Ñ–Ð´Ð¿Ð¸Ñу
@@ -1798,6 +1805,7 @@ settings.event_delete=Видалити
settings.event_delete_desc=Гілку або мітку було видалено.
settings.event_fork=Форк
settings.event_fork_desc=Репозиторій було форкнуто.
+settings.event_wiki=Вікі
settings.event_release=Реліз
settings.event_release_desc=Реліз опублікований, оновлений або видалений з репозиторіÑ.
settings.event_push=Push
@@ -1929,7 +1937,6 @@ settings.bot_token=Токен Ð´Ð»Ñ Ð±Ð¾Ñ‚Ð°
settings.chat_id=Чат ID
settings.matrix.homeserver_url=URL домашньої Ñторінки
settings.matrix.room_id=Ðомер кімнати
-settings.matrix.access_token=Токен ДоÑтупу
settings.matrix.message_type=Тип повідомленнÑ
settings.archive.button=Ðрхівний репозиторій
settings.archive.header=Відправити репозиторій в архів
@@ -2097,6 +2104,7 @@ branch.included_desc=Ð¦Ñ Ð³Ñ–Ð»ÐºÐ° Ñ” чаÑтиною типової гілк
branch.included=Включено
branch.create_new_branch=Створити гілку з гілки:
branch.confirm_create_branch=Створити гілку
+branch.create_branch_operation=Створити гілку
branch.new_branch=Створити нову гілку
branch.new_branch_from=Створити нову гілку з '%s'
branch.renamed=Гілку %s перейменовано на %s.
@@ -2121,7 +2129,7 @@ org_full_name_holder=Повна назва організації
org_name_helper=Ðазва організації має бути проÑтою та зрозумілою.
create_org=Створити організацію
repo_updated=Оновлено
-people=УчаÑники
+members=УчаÑники
teams=Команди
lower_members=учаÑники
lower_repositories=репозиторії
@@ -2190,6 +2198,7 @@ teams.leave=Покинути
teams.leave.detail=Покинути %s?
teams.can_create_org_repo=Створити репозиторії
teams.can_create_org_repo_helper=УчаÑники можуть Ñтворювати нові репозиторії в організації. Ðвтор отримає доÑтуп адмініÑтратора до нового репозиторію.
+teams.read_access=Прочитані
teams.read_access_helper=УчаÑники можуть переглÑдати та клонувати репозиторії команд.
teams.write_access_helper=УчаÑники можуть читати Ñ– виконувати push в репозиторії команд.
teams.admin_access=ДоÑтуп адмініÑтратора
@@ -2395,6 +2404,11 @@ repos.forks=Форки
repos.issues=Задачі
repos.size=Розмір
+packages.owner=ВлаÑник
+packages.name=Ðазва
+packages.type=Тип
+packages.repository=Репозиторій
+packages.size=Розмір
defaulthooks=Веб-хуки за замовчуваннÑм
defaulthooks.desc=Веб-хуки автоматично Ñтворюють HTTP POST-запити до Ñервера, коли виконуютьÑÑ Ð¿ÐµÐ²Ð½Ñ– події Gitea. Визначені тут веб-хуки Ñ” типовими Ñ– копіюютьÑÑ Ñƒ вÑÑ– нові Ñховища. Детальніше читайте в <a target="_blank" rel="noopener" href="https://docs.gitea.io/en-us/webhooks/">інÑтрукції по викориÑтанню web-хуків</a>.
@@ -2483,9 +2497,9 @@ auths.tips.oauth2.general=OAuth2 автентифікаціÑ
auths.tips.oauth2.general.tip=При додаванні нового OAuth2 провайдера, URL адреÑа переадреÑації по завершенні автентифікації повинена виглÑдати так:<host>/user/oauth2/<Authentication Name>/callback
auths.tip.oauth2_provider=ПоÑтачальник OAuth2
auths.tip.bitbucket=Створіть OAuth URI на Ñторінці https://bitbucket.org/account/user/<your username>/oauth-consumers/new Ñ– додайте права 'Account' - 'Read'
-auths.tip.nextcloud=ЗареєÑтруйте нового Ñпоживача OAuth у вашому екземплÑрі за допомогою наÑтупного меню "ÐÐ°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ -> Безпека -> клієнт OAuth 2.0"
+auths.tip.nextcloud=`ЗареєÑтруйте нового Ñпоживача OAuth у вашому екземплÑрі за допомогою наÑтупного меню "ÐÐ°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ -> Безпека -> клієнт OAuth 2.0"`
auths.tip.dropbox=Додайте новий додаток на https://www.dropbox.com/developers/apps
-auths.tip.facebook=Створіть новий додаток на https://developers.facebook.com/apps і додайте модуль "Facebook Login"
+auths.tip.facebook=`Створіть новий додаток на https://developers.facebook.com/apps і додайте модуль "Facebook Login"`
auths.tip.github=Додайте OAuth додаток на https://github.com/settings/applications/new
auths.tip.gitlab=Додайте новий додаток на https://gitlab.com/profile/applications
auths.tip.google_plus=Отримайте облікові дані клієнта OAuth2 в конÑолі Google API на Ñторінці https://console.developers.google.com/
@@ -2493,7 +2507,7 @@ auths.tip.openid_connect=ВикориÑтовуйте OpenID Connect Discovery U
auths.tip.twitter=Перейдіть на https://dev.twitter.com/apps, Ñтворіть програму Ñ– переконайтеÑÑ, що включена Ð¾Ð¿Ñ†Ñ–Ñ Â«Ð”Ð¾Ð·Ð²Ð¾Ð»Ð¸Ñ‚Ð¸ цю програму Ð´Ð»Ñ Ð²Ñ…Ð¾Ð´Ñƒ в ÑиÑтему за допомогою Twitter»
auths.tip.discord=ЗареєÑтруйте новий додаток на https://discordapp.com/developers/applications/me
auths.tip.gitea=ЗареєÑтруйте новий додаток OAuth2. Керівництво можна знайти на https://docs.gitea.io/en-us/oauth2-provider/
-auths.tip.yandex=Створіть нову програму в https://oauth.yandex.com/client/new. Виберіть наÑтупні дозволи з "Yandex. assport API": "ДоÑтуп до адреÑи електронної пошти", "ДоÑтуп до аватара" Ñ– "ДоÑтуп до імені кориÑтувача, імені та прізвища, Ñтаті"
+auths.tip.yandex=`Створіть нову програму в https://oauth.yandex.com/client/new. Виберіть наÑтупні дозволи з "Yandex. assport API": "ДоÑтуп до адреÑи електронної пошти", "ДоÑтуп до аватара" Ñ– "ДоÑтуп до імені кориÑтувача, імені та прізвища, Ñтаті"`
auths.tip.mastodon=Введіть URL Ñпеціального екземплÑра Ð´Ð»Ñ ÐµÐºÐ·ÐµÐ¼Ð¿Ð»Ñра mastodon, Ñкий ви хочете автентифікувати за допомогою (або викориÑтовувати за замовчуваннÑм)
auths.edit=Редагувати джерело автентифікації
auths.activated=Ð¦Ñ Ð°ÑƒÑ‚ÐµÐ½Ñ‚Ð¸Ñ„Ñ–ÐºÐ°Ñ†Ñ–Ñ Ð°ÐºÑ‚Ð¸Ð²Ð¾Ð²Ð°Ð½Ð°
@@ -2560,7 +2574,7 @@ config.allow_only_internal_registration=Дозволити реєÑтрацію
config.allow_only_external_registration=Дозволити реєÑтрацію тільки через Ñторонні ÑервіÑи
config.enable_openid_signup=Увімкнути ÑамоÑтійну реєÑтрацію за допомогою OpenID
config.enable_openid_signin=Увімкнути реєÑтрацію за допомогою OpenID
-config.show_registration_button=Показувати кнопку "РеєÑтраціÑ"
+config.show_registration_button=`Показувати кнопку "РеєÑтраціÑ"`
config.require_sign_in_view=Вимагати авторизації Ð´Ð»Ñ Ð¿ÐµÑ€ÐµÐ³Ð»Ñду Ñторінок
config.mail_notify=Увімкнути ÑÐ¿Ð¾Ð²Ñ–Ñ‰ÐµÐ½Ð½Ñ ÐµÐ»ÐµÐºÑ‚Ñ€Ð¾Ð½Ð½Ð¾ÑŽ поштою
config.disable_key_size_check=Вимкнути перевірку мінімального розміру ключа
@@ -2583,6 +2597,7 @@ config.skip_tls_verify=ПропуÑтити перевірку TLS
config.mailer_enabled=Увімкнено
config.mailer_name=Ім'Ñ
+config.mailer_smtp_port=SMTP порт
config.mailer_user=КориÑтувач
config.mailer_use_sendmail=ВикориÑтовувати Sendmail
config.mailer_sendmail_path=ШлÑÑ… до Sendmail
@@ -2679,7 +2694,7 @@ monitor.queue.pool.addworkers.mustnumbergreaterzero=КількіÑÑ‚ÑŒ додаÐ
monitor.queue.pool.addworkers.musttimeoutduration=Тайм-аут має бути довжиною golang, наприклад 5m або 0
monitor.queue.pool.flush.title=ОчиÑтити чергу
monitor.queue.pool.flush.desc=ОчиÑтка додаÑÑ‚ÑŒ потік, Ñкий припинитьÑÑ, коли черга буде порожньою, або по тайм-ауту.
-monitor.queue.pool.flush.submit=Додати робочий потік "ОчиÑтка"
+monitor.queue.pool.flush.submit=`Додати робочий потік "ОчиÑтка"`
monitor.queue.pool.flush.added=Потік очиÑтки додано до %[1]s
monitor.queue.settings.title=ÐÐ°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ð¿ÑƒÐ»Ñƒ
@@ -2710,7 +2725,6 @@ monitor.queue.pool.cancel_desc=Ð—Ð°Ð»Ð¸ÑˆÐµÐ½Ð½Ñ Ñ‡ÐµÑ€Ð³Ð¸ без робочи
notices.system_notice_list=Ð¡Ð¿Ð¾Ð²Ñ–Ñ‰ÐµÐ½Ð½Ñ ÑиÑтеми
notices.view_detail_header=ПереглÑнути деталі повідомленнÑ
-notices.actions=Дії
notices.select_all=Вибрати вÑе
notices.deselect_all=СкаÑувати виділеннÑ
notices.inverse_selection=Інвертувати виділене
@@ -2810,4 +2824,25 @@ error.no_unit_allowed_repo=У Ð²Ð°Ñ Ð½ÐµÐ¼Ð°Ñ” доÑтупу до жодног
error.unit_not_allowed=У Ð²Ð°Ñ Ð½ÐµÐ¼Ð°Ñ” доÑтупу до жодного розділу цього репозиториÑ.
[packages]
+filter.type=Тип
+conan.details.repository=Репозиторій
+owner.settings.cleanuprules.enabled=Увімкнено
+
+[secrets]
+name=Ðазва
+
+[actions]
+
+
+
+runners.name=Ðазва
+runners.owner_type=Тип
+runners.description=ОпиÑ
+runners.task_list.run=ЗапуÑтити
+runners.task_list.repository=Репозиторій
+runners.task_list.commit=Коміт
+runners.status.active=Ðктивний
+
+runs.commit=Коміт
+
diff --git a/options/locale/locale_zh-CN.ini b/options/locale/locale_zh-CN.ini
index ee6f686a8..aa4cc4dde 100644
--- a/options/locale/locale_zh-CN.ini
+++ b/options/locale/locale_zh-CN.ini
@@ -57,7 +57,7 @@ new_mirror=创建新的镜åƒ
new_fork=新的仓库Fork
new_org=创建组织
new_project=创建项目
-new_project_board=创建看æ¿
+new_project_column=创建列
manage_org=管ç†æˆ‘的组织
admin_panel=管ç†åŽå°
account_settings=å¸æˆ·è®¾ç½®
@@ -86,11 +86,16 @@ remove=移除
remove_all=移除所有
edit=编辑
+enabled=å¯ç”¨
+disabled=ç¦ç”¨
+
copy=å¤åˆ¶
copy_url=å¤åˆ¶ç½‘å€
+copy_content=å¤åˆ¶å†…容
copy_branch=å¤åˆ¶åˆ†æ”¯å
copy_success=å¤åˆ¶æˆåŠŸï¼
copy_error=å¤åˆ¶å¤±è´¥
+copy_type_unsupported=无法å¤åˆ¶æ­¤ç±»åž‹çš„文件内容
write=撰写
preview=预览
@@ -106,6 +111,12 @@ never=从ä¸
rss_feed=RSS 订阅æº
+[aria]
+navbar=导航æ 
+footer=页脚
+footer.software=关于软件
+footer.links=链接
+
[filter]
string.asc=A - Z
string.desc=Z - A
@@ -226,7 +237,6 @@ internal_token_failed=生æˆå†…部令牌失败: %v
secret_key_failed=生æˆå¯†é’¥å¤±è´¥ï¼š %v
save_config_failed=应用é…ç½®ä¿å­˜å¤±è´¥ï¼š%v
invalid_admin_setting=管ç†å‘˜å¸æˆ·è®¾ç½®æ— æ•ˆ: %v
-install_success=欢迎 ï¼éžå¸¸æ„Ÿè°¢æ‚¨é€‰æ‹© Gitea,玩得开心。
invalid_log_root_path=日志路径无效: %v
default_keep_email_private=默认情况下éšè—电å­é‚®ä»¶åœ°å€
default_keep_email_private_popup=默认情况下, éšè—新用户å¸æˆ·çš„电å­é‚®ä»¶åœ°å€ã€‚
@@ -237,6 +247,7 @@ default_enable_timetracking_popup=默认情况下å¯ç”¨æ–°ä»“库的时间跟踪ã
no_reply_address=éšè—电å­é‚®ä»¶
no_reply_address_helper=具有éšè—电å­é‚®ä»¶åœ°å€çš„用户的域å。例如, 用户å "joe" 将以 "joe@noreply.example.org" 的身份登录到 Git 中. 如果éšè—的电å­é‚®ä»¶åŸŸè®¾ç½®ä¸º "noreply.example.org"。
password_algorithm=密ç å“ˆå¸Œç®—法
+invalid_password_algorithm=无效的密ç å“ˆå¸Œç®—法
password_algorithm_helper=设置密ç å“ˆå¸Œç®—法。 算法具有ä¸åŒçš„è¦æ±‚和强度。 具有良好特性的`argon2`å´ä¼šå ç”¨å¤§é‡å†…存,å¯èƒ½ä¸é€‚用于å°åž‹ç³»ç»Ÿã€‚
enable_update_checker=å¯ç”¨æ›´æ–°æ£€æŸ¥
enable_update_checker_helper=通过连接到 gitea.io 定期检查新版本å‘布。
@@ -254,24 +265,24 @@ view_home=访问 %s
search_repos=查找仓库…
filter=其他过滤器
filter_by_team_repositories=按团队仓库筛选
-feed_of="%s" çš„æº
+feed_of=`"%s"çš„æº`
-show_archived=已存档
-show_both_archived_unarchived=显示已存档和未存档的
+show_archived=已归档
+show_both_archived_unarchived=显示已归档和未归档的
show_only_archived=åªæ˜¾ç¤ºå·²å½’档的
-show_only_unarchived=åªæ˜¾ç¤ºæœªå­˜æ¡£çš„
+show_only_unarchived=åªæ˜¾ç¤ºæœªå½’档的
-show_private=ç§æœ‰
-show_both_private_public=显示公开的和ç§æœ‰çš„
+show_private=ç§æœ‰åº“
+show_both_private_public=åŒæ—¶æ˜¾ç¤ºå…¬å¼€çš„å’Œç§æœ‰çš„
show_only_private=åªæ˜¾ç¤ºç§æœ‰çš„
show_only_public=åªæ˜¾ç¤ºå…¬å¼€çš„
-issues.in_your_repos=属于该用户仓库的
+issues.in_your_repos=在您的仓库中
[explore]
-repos=仓库
+repos=仓库管ç†
users=用户
-organizations=组织
+organizations=组织管ç†
search=æœç´¢
code=代ç 
search.type.tooltip=æœç´¢ç±»åž‹
@@ -279,12 +290,12 @@ search.fuzzy=模糊
search.fuzzy.tooltip=包å«è¿‘似匹é…æœç´¢è¯çš„结果
search.match=匹é…
search.match.tooltip=仅包å«ç²¾ç¡®åŒ¹é…æœç´¢è¯çš„结果
-code_search_unavailable=当å‰ä»£ç æœç´¢ä¸å¯ç”¨ã€‚请与网站管ç†å‘˜è”系。
+code_search_unavailable=ç›®å‰ä»£ç æœç´¢ä¸å¯ç”¨ã€‚请与网站管ç†å‘˜è”系。
repo_no_results=未找到匹é…的仓库。
user_no_results=未找到匹é…的用户。
org_no_results=未找到匹é…的组织。
code_no_results=未找到与æœç´¢å­—è¯åŒ¹é…çš„æºä»£ç ã€‚
-code_search_results=“%s†的æœç´¢ç»“果是
+code_search_results=“%s†的æœç´¢ç»“æžœ
code_last_indexed_at=最åŽç´¢å¼•äºŽ %s
relevant_repositories_tooltip=派生的仓库,以åŠç¼ºå°‘主题ã€å›¾æ ‡å’Œæ述的仓库将被éšè—。
relevant_repositories=åªæ˜¾ç¤ºç›¸å…³çš„仓库, <a href="%s">显示未过滤结果</a>。
@@ -317,6 +328,7 @@ email_not_associate=您输入的邮箱地å€æœªè¢«å…³è”到任何å¸å·ï¼
send_reset_mail=å‘é€è´¦æˆ·æ¢å¤é‚®ä»¶
reset_password=账户æ¢å¤
invalid_code=此确认密钥无效或已过期。
+invalid_password=您的密ç ä¸Žç”¨äºŽåˆ›å»ºè´¦æˆ·çš„密ç ä¸åŒ¹é…。
reset_password_helper=æ¢å¤è´¦æˆ·
reset_password_wrong_user=您已作为 %s 登录,无法使用链接æ¢å¤ %s 的账户。
password_too_short=密ç é•¿åº¦ä¸èƒ½å°‘于 %d ä½ã€‚
@@ -360,6 +372,7 @@ password_pwned_err=无法完æˆå¯¹ HaveIBeenPwned 的请求
[mail]
view_it_on=在 %s 上查看
+reply=或直接回å¤æ­¤é‚®ä»¶
link_not_working_do_paste=ä¸èµ·ä½œç”¨ï¼Ÿå°è¯•å¤åˆ¶å¹¶ç²˜è´´åˆ°æ‚¨çš„æµè§ˆå™¨ã€‚
hi_user_x=<b>%s</b> 您好,
@@ -463,6 +476,8 @@ 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=验è¯ç ä¸æ­£ç¡®ã€‚
password_not_match=密ç ä¸åŒ¹é…。
@@ -499,10 +514,12 @@ team_not_exist=团队ä¸å­˜åœ¨
last_org_owner=您ä¸èƒ½ä»Ž "所有者" 团队中删除最åŽä¸€ä¸ªç”¨æˆ·ã€‚组织中必须至少有一个所有者。
cannot_add_org_to_team=组织ä¸èƒ½è¢«åŠ å…¥åˆ°å›¢é˜Ÿä¸­ã€‚
duplicate_invite_to_team=此用户已被邀请为团队æˆå‘˜ã€‚
+organization_leave_success=您已æˆåŠŸç¦»å¼€ç»„织 %s。
invalid_ssh_key=无法验è¯æ‚¨çš„ SSH 密钥: %s
invalid_gpg_key=无法验è¯æ‚¨çš„ GPG 密钥: %s
invalid_ssh_principal=无效的规则: %s
+must_use_public_key=您æ供的密钥是ç§é’¥ã€‚ä¸è¦åœ¨ä»»ä½•åœ°æ–¹ä¸Šä¼ æ‚¨çš„ç§é’¥ï¼Œè¯·æ”¹ç”¨æ‚¨çš„公钥。
unable_verify_ssh_key=无法验è¯SSH密钥,å†æ¬¡æ£€æŸ¥æ˜¯å¦æœ‰è¯¯ã€‚
auth_failed=授æƒéªŒè¯å¤±è´¥ï¼š%v
@@ -675,7 +692,7 @@ gpg_token_required=您必须为下é¢çš„令牌æ供签å
gpg_token=令牌
gpg_token_help=您å¯ä»¥ä½¿ç”¨ä»¥ä¸‹æ–¹å¼ç”Ÿæˆç­¾å:
gpg_token_code=echo "%s" | gpg -a --default-key %s --detach-sig
-gpg_token_signature= GPG 增强签å
+gpg_token_signature=GPG 增强签å
key_signature_gpg_placeholder=以 '-----BEGIN PGP PUBLIC KEY BLOCK-----' 开头
verify_gpg_key_success=GPG 密钥 %s 已被验è¯ã€‚
ssh_key_verified=已验è¯çš„密钥
@@ -713,8 +730,8 @@ last_used=上次使用在
no_activity=没有最近活动
can_read_info=读å–
can_write_info=写入
-key_state_desc=7 天内使用过该密钥
-token_state_desc=7 天内使用过该密钥
+key_state_desc=7 天内使用过该密钥
+token_state_desc=7 天内使用过该密钥
principal_state_desc=7 天内使用过该规则
show_openid=在个人信æ¯ä¸Šæ˜¾ç¤º
hide_openid=在个人信æ¯ä¸Šéšè—
@@ -739,6 +756,8 @@ access_token_deletion_cancel_action=å–消
access_token_deletion_confirm_action=刪除
access_token_deletion_desc=删除令牌将撤销程åºå¯¹æ‚¨è´¦æˆ·çš„访问æƒé™ã€‚æ­¤æ“作无法撤消。是å¦ç»§ç»­ï¼Ÿ
delete_token_success=令牌已ç»è¢«åˆ é™¤ã€‚使用该令牌的应用将ä¸å†èƒ½å¤Ÿè®¿é—®ä½ çš„è´¦å·ã€‚
+select_scopes=选择范围
+scopes_list=范围:
manage_oauth2_applications=ç®¡ç† OAuth2 应用程åº
edit_oauth2_application=编辑 OAuth2 应用程åº
@@ -802,6 +821,7 @@ remove_account_link=删除已绑定的账å·
remove_account_link_desc=删除已绑定å¸æˆ·å°†åŠé”€å…¶å¯¹æ‚¨çš„ Gitea å¸æˆ·çš„访问æƒé™ã€‚继续?
remove_account_link_success=å·²å–消绑定å¸æˆ·ã€‚
+
orgs_none=您现在还ä¸æ˜¯ä»»ä½•ç»„织的æˆå‘˜ã€‚
repos_none=你并ä¸æ‹¥æœ‰ä»»ä½•ä»“库
@@ -898,7 +918,7 @@ watchers=关注者
stargazers=称赞者
forks=派生仓库
pick_reaction=选择你的表情
-reactions_more=å†åŠ è½½ %d
+reactions_more=å†åŠ è½½ %d
unit_disabled=站点管ç†å‘˜å·²ç¦ç”¨æ­¤ä»“库å•å…ƒã€‚
language_other=其它
adopt_search=输入用户å以æœç´¢æœªè¢«æ”¶å½•çš„仓库... (留空以查找全部)
@@ -913,9 +933,9 @@ delete_preexisting_success=删除 %s 中未收录的文件
blame_prior=查看此更改å‰çš„ blame
transfer.accept=接å—转移
-transfer.accept_desc=转移到 "%s"
+transfer.accept_desc=`转移到 "%s"`
transfer.reject=æ‹’ç»è½¬ç§»
-transfer.reject_desc=å–消转移到 "%s"
+transfer.reject_desc=`å–消转移到 "%s"`
transfer.no_permission_to_accept=您没有接å—çš„æƒé™
transfer.no_permission_to_reject=您没有拒ç»çš„æƒé™
@@ -1011,10 +1031,12 @@ unstar=å–消点赞
star=点赞
fork=派生
download_archive=下载此仓库
+more_operations=更多æ“作
no_desc=æš‚æ— æè¿°
quick_guide=快速帮助
clone_this_repo=克隆当å‰ä»“库
+cite_this_repo=引用此仓库
create_new_repo_command=从命令行创建一个新的仓库
push_exist_repo=从命令行推é€å·²ç»åˆ›å»ºçš„仓库
empty_message=这个家伙很懒,什么都没有推é€ã€‚
@@ -1113,6 +1135,7 @@ editor.commit_directly_to_this_branch=直接æ交至 <strong class="branch-name
editor.create_new_branch=为此æ交创建一个 <strong>新的分支</strong> 并å‘èµ·åˆå¹¶è¯·æ±‚。
editor.create_new_branch_np=为此æ交创建 <strong>新分支</strong>。
editor.propose_file_change=æ议文件更改
+editor.new_branch_name=为这次æ交的新分支命å
editor.new_branch_name_desc=新的分支å称...
editor.cancel=å–消
editor.filename_cannot_be_empty=文件åä¸èƒ½ä¸ºç©ºã€‚
@@ -1164,7 +1187,7 @@ commits.signed_by_untrusted_user_unmatched=由与æ交者ä¸åŒ¹é…的未授信ç
commits.gpg_key_id=GPG 密钥 ID
commits.ssh_key_fingerprint=SSH 密钥指纹
-commit.actions=æ“作
+commit.operations=æ“作
commit.revert=还原
commit.revert-header=还原: %s
commit.revert-content=选择è¦è¿˜åŽŸçš„分支:
@@ -1197,19 +1220,22 @@ projects.type.bug_triage=Bug分类看æ¿
projects.template.desc=项目模æ¿
projects.template.desc_helper=选择一个项目模æ¿ä»¥å¼€å§‹
projects.type.uncategorized=未分类
-projects.board.edit=编辑看æ¿
-projects.board.edit_title=新看æ¿å称
-projects.board.new_title=新看æ¿å称
-projects.board.new_submit=æ交
-projects.board.new=创建看æ¿
-projects.board.set_default=设为默认
-projects.board.set_default_desc=将此é¢æ¿è®¾ä¸ºæœªåˆ†ç±»é—®é¢˜å’Œåˆå¹¶è¯·æ±‚的默认值
-projects.board.delete=删除看æ¿
-projects.board.deletion_desc=删除项目看æ¿ä¼šå°†æ‰€æœ‰ç›¸å…³é—®é¢˜ç§»è‡³â€œæœªåˆ†ç±»â€ã€‚继续å—?
-projects.board.color=颜色
+projects.column.edit=编辑列
+projects.column.edit_title=å称
+projects.column.new_title=å称
+projects.column.new_submit=创建列
+projects.column.new=创建列
+projects.column.set_default=设为默认
+projects.column.set_default_desc=设置此列为未分类问题和åˆå¹¶è¯·æ±‚的默认值
+projects.column.delete=删除列
+projects.column.deletion_desc=删除项目列会将所有相关问题移到“未分类â€ã€‚是å¦ç»§ç»­ï¼Ÿ
+projects.column.color=彩色
projects.open=å¼€å¯
projects.close=关闭
-projects.board.assigned_to=指派给
+projects.column.assigned_to=指派给
+projects.card_type.desc=å¡ç‰‡é¢„览
+projects.card_type.images_and_text=图标和文字
+projects.card_type.text_only=仅文本
issues.desc=组织 bug 报告ã€ä»»åŠ¡å’Œé‡Œç¨‹ç¢‘。
issues.filter_assignees=筛选指派人
@@ -1269,7 +1295,7 @@ issues.change_milestone_at=`%[3]s 修改了里程碑从 <b>%[1]s</b> 到 <b>%[2]
issues.change_project_at=`修改项目从 <b>%s</b> 到 <b>%s</b> %s
issues.remove_milestone_at=`%[2]s 删除了里程碑 <b>%[1]s</b>`
issues.remove_project_at=`从 <b>%s</b> 项目 %s 中删除`
-issues.deleted_milestone= (已删除)
+issues.deleted_milestone=(已删除)
issues.deleted_project=`(已删除)`
issues.self_assign_at=`于 %s 指派给自己`
issues.add_assignee_at=`于 %[2]s 被 <b>%[1]s</b> 指派`
@@ -1285,6 +1311,9 @@ issues.filter_label_exclude=`使用 <code>alt</code> + <code>鼠标左键 / 回è
issues.filter_label_no_select=所有标签
issues.filter_milestone=里程碑筛选
issues.filter_milestone_no_select=所有里程碑
+issues.filter_project=项目
+issues.filter_project_all=所有项目
+issues.filter_project_none=暂无项目
issues.filter_assignee=指派人筛选
issues.filter_assginee_no_select=所有指派æˆå‘˜
issues.filter_poster=作者
@@ -1295,6 +1324,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_sort=排åº
issues.filter_sort.latest=最新创建
issues.filter_sort.oldest=最早创建
@@ -1316,6 +1346,8 @@ issues.action_milestone=里程碑
issues.action_milestone_no_select=无里程碑
issues.action_assignee=指派人筛选
issues.action_assignee_no_select=未指派
+issues.action_check=选中/å–消选中
+issues.action_check_all=选中/å–消选中所有项目
issues.opened_by=由 <a href="%[2]s">%[3]s</a> 于 %[1]s创建
pulls.merged_by=ç”± <a href="%[2]s">%[3]s</a> 创建,被åˆå¹¶äºŽ %[1]s
pulls.merged_by_fake=ç”± %[2]s 创建,被åˆå¹¶äºŽ %[1]s
@@ -1369,6 +1401,9 @@ issues.save=ä¿å­˜
issues.label_title=标签å称
issues.label_description=标签æè¿°
issues.label_color=标签颜色
+issues.label_exclusive=独有
+issues.label_exclusive_desc=命å标签为 <code>scope/item</code> 以使其与其他以 <code>scope/</code> 开头的标签互斥。
+issues.label_exclusive_warning=在编辑工å•æˆ–åˆå¹¶è¯·æ±‚的标签时,任何冲çªçš„范围标签都将被删除。
issues.label_count=%d 个标签
issues.label_open_issues=%d 个开å¯çš„å·¥å•
issues.label_edit=编辑
@@ -1436,6 +1471,7 @@ 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,从 <a class="ui sha" href="%[3]s"><code>%[2]s</code></a>,至 <a class="ui sha" href="%[5]s"><code>%[4]s</code></a>`
+issues.force_push_compare=比较
issues.due_date_form=yyyy年mm月dd日
issues.due_date_form_add=设置到期时间
issues.due_date_form_edit=编辑
@@ -1531,7 +1567,7 @@ pulls.filter_branch=过滤分支
pulls.no_results=未找到结果
pulls.nothing_to_compare=分支内容相åŒï¼Œæ— éœ€åˆ›å»ºåˆå¹¶è¯·æ±‚。
pulls.nothing_to_compare_and_allow_empty_pr=这些分支是相等的,此åˆå¹¶è¯·æ±‚将为空。
-pulls.has_pull_request="这些分支之间的åˆå¹¶è¯·æ±‚已存在: <a href="%[1]s">%[2]s#%[3]d</a>"
+pulls.has_pull_request=这些分支之间的åˆå¹¶è¯·æ±‚已存在: <a href="%[1]s">%[2]s#%[3]d</a>
pulls.create=创建åˆå¹¶è¯·æ±‚
pulls.title_desc=请求将 %[1]d 次代ç æ交从 <code>%[2]s</code> åˆå¹¶è‡³ <code id="branch_target">%[3]s</code>
pulls.merged_title_desc=于 %[4]s å°† %[1]d 次代ç æ交从 <code>%[2]s</code>åˆå¹¶è‡³ <code>%[3]s</code>
@@ -1622,6 +1658,8 @@ pulls.reopened_at=`é‡æ–°æ‰“开此åˆå¹¶è¯·æ±‚ <a id="%[1]s" href="#%[1]s">%[2]s
pulls.merge_instruction_hint=`你也å¯ä»¥æŸ¥çœ‹ <a class="show-instruction">命令行指令</a>`
pulls.merge_instruction_step1_desc=从你的仓库中签出一个新的分支并测试å˜æ›´ã€‚
pulls.merge_instruction_step2_desc=åˆå¹¶å˜æ›´å¹¶æ›´æ–°åˆ° Gitea 上
+pulls.clear_merge_message=清除åˆå¹¶ä¿¡æ¯
+pulls.clear_merge_message_hint=清除åˆå¹¶æ¶ˆæ¯åªä¼šåˆ é™¤æ交消æ¯å†…容,并ä¿ç•™ç”Ÿæˆçš„ git 附加内容,如“Co-Authored-By …â€ã€‚
pulls.auto_merge_button_when_succeed=(当检查æˆåŠŸæ—¶)
pulls.auto_merge_when_succeed=在所有检查æˆåŠŸåŽè‡ªåŠ¨åˆå¹¶
@@ -1813,6 +1851,7 @@ settings.mirror_sync_in_progress=é•œåƒåŒæ­¥æ­£åœ¨è¿›è¡Œä¸­ï¼Œè¯·ç¨åŽå†è¯•ã€
settings.site=网站
settings.update_settings=更新仓库设置
settings.branches.update_default_branch=更新默认分支
+settings.branches.add_new_rule=添加新规则
settings.advanced_settings=高级设置
settings.wiki_desc=å¯ç”¨ä»“库百科
settings.use_internal_wiki=使用内置百科
@@ -1839,16 +1878,14 @@ settings.enable_timetracker=å¯ç”¨æ—¶é—´è·Ÿè¸ª
settings.allow_only_contributors_to_track_time=ä»…å…许æˆå‘˜è·Ÿè¸ªæ—¶é—´
settings.pulls_desc=å¯ç”¨åˆå¹¶è¯·æ±‚
settings.pulls.ignore_whitespace=忽略空白冲çª
-settings.pulls.allow_merge_commits=å…许åˆå¹¶
-settings.pulls.allow_rebase_merge=å¯ç”¨å˜åŸºåˆå¹¶æ交
-settings.pulls.allow_rebase_merge_commit=å¯ç”¨å˜åŸºæ˜¾å¼åˆå¹¶ (--no-ff)
-settings.pulls.allow_squash_commits=å¯ç”¨Squashåˆå¹¶æ交
-settings.pulls.allow_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=默认开å¯å…许维护者编辑
+settings.releases_desc=å¯ç”¨å‘布
settings.packages_desc=å¯ç”¨ä»“库软件包注册中心
settings.projects_desc=å¯ç”¨ä»“库项目
+settings.actions_desc=å¯ç”¨ Actions
settings.admin_settings=管ç†å‘˜è®¾ç½®
settings.admin_enable_health_check=å¯ç”¨ä»“库å¥åº·æ£€æŸ¥ (git fsck)
settings.admin_code_indexer=代ç ç´¢å¼•å™¨
@@ -2012,6 +2049,8 @@ settings.event_package=软件包
settings.event_package_desc=软件包已在仓库中被创建或删除。
settings.branch_filter=分支过滤
settings.branch_filter_desc=推é€ã€åˆ›å»ºï¼Œåˆ é™¤åˆ†æ”¯äº‹ä»¶çš„分支白åå•ï¼Œä½¿ç”¨ glob 模å¼åŒ¹é…指定。若为空或 <code>*</code>ï¼Œåˆ™å°†æŠ¥å‘Šæ‰€æœ‰åˆ†æ”¯çš„äº‹ä»¶ã€‚è¯­æ³•æ–‡æ¡£è§ <a href="https://pkg.go.dev/github.com/gobwas/glob#Compile">github.com/gobwas/glob</a>。示例:<code>master</code>,<code>{master,release*}</code>。
+settings.authorization_header=授æƒæ ‡å¤´
+settings.authorization_header_desc=当存在时将被作为授æƒæ ‡å¤´åŒ…å«åœ¨å†…。例如: %s。
settings.active=激活
settings.active_helper=触å‘事件的信æ¯å°†å‘é€åˆ°æ­¤ webhook 网å€ã€‚
settings.add_hook_success=Web é’©å­æ·»åŠ æˆåŠŸï¼
@@ -2056,6 +2095,8 @@ settings.deploy_key_deletion_desc=删除部署密钥将å–消此密钥对此仓å
settings.deploy_key_deletion_success=部署密钥已删除。
settings.branches=分支
settings.protected_branch=分支ä¿æŠ¤
+settings.protected_branch.save_rule=ä¿å­˜è§„则
+settings.protected_branch.delete_rule=删除规则
settings.protected_branch_can_push=å…许推å—?
settings.protected_branch_can_push_yes=ä½ å¯ä»¥æŽ¨
settings.protected_branch_can_push_no=ä½ ä¸èƒ½æŽ¨
@@ -2090,6 +2131,7 @@ settings.dismiss_stale_approvals=å–消过时的批准
settings.dismiss_stale_approvals_desc=当新的æ交更改åˆå¹¶è¯·æ±‚内容被推é€åˆ°åˆ†æ”¯æ—¶ï¼Œæ—§çš„批准将被撤销。
settings.require_signed_commits=需è¦ç­¾åæ交
settings.require_signed_commits_desc=æ‹’ç»æŽ¨é€æœªç­¾å或无法验è¯çš„æ交到分支
+settings.protect_branch_name_pattern=å—ä¿æŠ¤çš„分支å称模å¼
settings.protect_protected_file_patterns=å—ä¿æŠ¤çš„文件模å¼(使用分å·åˆ†éš”)
settings.protect_protected_file_patterns_desc=å³ä½¿ç”¨æˆ·æœ‰æƒåœ¨æ­¤åˆ†æ”¯ä¸­æ·»åŠ ã€ç¼–辑或删除文件,也ä¸å…许直接更改å—ä¿æŠ¤æ–‡ä»¶ã€‚ å¯ä»¥ä½¿ç”¨åˆ†å·åˆ†éš”å¤šä¸ªæ¨¡å¼ ('\;')ã€‚è¯­æ³•æ–‡æ¡£è§ <a href="https://pkg.go.dev/github.com/gobwas/glob#Compile">github.com/gobwas/glob</a>。示例:<code>.drone.yml</code>,<code>/docs/**/*.txt</code>。
settings.protect_unprotected_file_patterns=ä¸å—ä¿æŠ¤çš„æ–‡ä»¶æ¨¡å¼ (ä½¿ç”¨åˆ†å· '\;' 分隔):
@@ -2098,6 +2140,7 @@ settings.add_protected_branch=å¯ç”¨ä¿æŠ¤
settings.delete_protected_branch=ç¦ç”¨ä¿æŠ¤
settings.update_protect_branch_success=分支 "%s" 的分支ä¿æŠ¤å·²æ›´æ–°ã€‚
settings.remove_protected_branch_success=分支 "%s" 的分支ä¿æŠ¤å·²è¢«ç¦ç”¨ã€‚
+settings.remove_protected_branch_failed=删除分支ä¿æŠ¤è§„则 '%s' 失败。
settings.protected_branch_deletion=ç¦ç”¨åˆ†æ”¯ä¿æŠ¤
settings.protected_branch_deletion_desc=ç¦ç”¨åˆ†æ”¯ä¿æŠ¤å…许具有写入æƒé™çš„用户推é€æ交到此分支。继续?
settings.block_rejected_reviews=æ‹’ç»å®¡æ ¸é˜»æ­¢äº†æ­¤åˆå¹¶
@@ -2107,10 +2150,13 @@ settings.block_on_official_review_requests_desc=处于评审状æ€æ—¶ï¼Œå³ä½¿æœ
settings.block_outdated_branch=如果拉å–请求已ç»è¿‡æ—¶ï¼Œé˜»æ­¢åˆå¹¶
settings.block_outdated_branch_desc=当头部分支è½åŽåŸºç¡€åˆ†æ”¯æ—¶ï¼Œä¸èƒ½åˆå¹¶ã€‚
settings.default_branch_desc=请选择一个默认的分支用于åˆå¹¶è¯·æ±‚å’Œæ交:
+settings.merge_style_desc=åˆå¹¶æ–¹å¼
settings.default_merge_style_desc=åˆå¹¶è¯·æ±‚的默认åˆå¹¶æ ·å¼ï¼š
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=Git标签ä¿æŠ¤
@@ -2126,7 +2172,6 @@ settings.bot_token=Bot 令牌
settings.chat_id=èŠå¤© ID
settings.matrix.homeserver_url=主æœåŠ¡å™¨ç½‘å€
settings.matrix.room_id=房间ID
-settings.matrix.access_token=访问令牌(Access Token)
settings.matrix.message_type=消æ¯ç±»åž‹
settings.archive.button=归档仓库
settings.archive.header=归档此仓库
@@ -2267,6 +2312,8 @@ release.downloads=下载附件
release.download_count=下载:%s
release.add_tag_msg=使用å‘布的标题和内容作为标签消æ¯ã€‚
release.add_tag=仅创建标签
+release.releases_for=%s 的版本å‘布
+release.tags_for=%s 的标签
branch.name=分支å称
branch.search=æœç´¢åˆ†æ”¯
@@ -2325,7 +2372,7 @@ org_full_name_holder=组织全å
org_name_helper=组织å字应该简å•æ˜Žäº†ã€‚
create_org=创建组织
repo_updated=最åŽæ›´æ–°äºŽ
-people=组织æˆå‘˜
+members=æˆå‘˜
teams=组织团队
code=代ç 
lower_members=åæˆå‘˜
@@ -2534,6 +2581,10 @@ 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=å–消丢弃的任务
users.user_manage_panel=用户å¸æˆ·ç®¡ç†
users.new_account=创建新å¸æˆ·
@@ -2622,6 +2673,7 @@ repos.size=大å°
packages.package_manage_panel=软件包管ç†
packages.total_size=总大å°ï¼š%s
+packages.unreferenced_size=未引用大å°ï¼š %s
packages.owner=所有者
packages.creator=创建者
packages.name=å称
@@ -2715,6 +2767,8 @@ auths.oauth2_required_claim_value_helper=设置此值,åªæœ‰æ‹¥æœ‰å¯¹åº”的声
auths.oauth2_group_claim_name=用于æ供用户组å称的 Claim 声明å称。(å¯é€‰)
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=自动创建用户
auths.sspi_auto_create_users_helper=å…许 SSPI 认è¯åœ¨ç”¨æˆ·ç¬¬ä¸€æ¬¡ç™»å½•æ—¶è‡ªåŠ¨åˆ›å»ºæ–°è´¦å·
@@ -2730,10 +2784,10 @@ auths.tips=帮助æ示
auths.tips.oauth2.general=OAuth2 认è¯
auths.tips.oauth2.general.tip=当注册一个新的 OAuth2 认è¯ï¼Œå›žè°ƒ/é‡å®šå‘ URL 应该是: <host>/user/oauth2/<Authentication Name>/callback
auths.tip.oauth2_provider=OAuth2 æ供程åº
-auths.tip.bitbucket=在 https://bitbucket.org/account/user/<your username>/oauth-consumers/new 注册新的 OAuth 消费者åŒæ—¶æ·»åŠ æƒé™"å¸æˆ·"-"读"
+auths.tip.bitbucket=`在 https://bitbucket.org/account/user/<your username>/oauth-consumers/new 注册新的 OAuth 消费者åŒæ—¶æ·»åŠ æƒé™"å¸æˆ·"-"读"`
auths.tip.nextcloud=使用下é¢çš„èœå•â€œè®¾ç½®ï¼ˆSettings) -> 安全(Security) -> OAuth 2.0 clientâ€åœ¨æ‚¨çš„实例上注册一个新的 OAuth 客户端。
auths.tip.dropbox=在 https://www.dropbox.com/developers/apps 上创建一个新的应用程åº
-auths.tip.facebook=在 https://developers.facebook.com/apps 注册一个新的应用,并添加产å“"Facebook 登录"
+auths.tip.facebook=`在 https://developers.facebook.com/apps 注册一个新的应用,并添加产å“"Facebook 登录"`
auths.tip.github=在 https://github.com/settings/applications/new 注册一个 OAuth 应用程åº
auths.tip.gitlab=在 https://gitlab.com/profile/applications 上注册新应用程åº
auths.tip.google_plus=从谷歌 API æŽ§åˆ¶å° (https://console.developers.google.com/) 获得 OAuth2 客户端凭æ®
@@ -2977,7 +3031,7 @@ monitor.queue.pool.cancel_desc=没有工作者组的队列将会引起请求永ä
notices.system_notice_list=系统æ示管ç†
notices.view_detail_header=查看æ示详情
-notices.actions=æ“作
+notices.operations=æ“作
notices.select_all=选中全部
notices.deselect_all=å–消全选
notices.inverse_selection=åå‘选中
@@ -3003,6 +3057,7 @@ reopen_pull_request=`é‡æ–°å¼€å¯äº†åˆå¹¶è¯·æ±‚ <a href="%[1]s">%[3]s#%[2]s</a>
comment_issue=`è¯„è®ºäº†å·¥å• <a href="%[1]s">%[3]s#%[2]s</a>`
comment_pull=`评论了åˆå¹¶è¯·æ±‚ <a href="%[1]s">%[3]s#%[2]s</a>`
merge_pull_request=`åˆå¹¶äº†åˆå¹¶è¯·æ±‚ <a href="%[1]s">%[3]s#%[2]s</a>`
+auto_merge_pull_request=`自动åˆå¹¶äº†æ‹‰å–请求 <a href="%[1]s">%[3]s#%[2]s</a>`
transfer_repo=将仓库 <code>%s</code> 转移至 <a href="%s">%s</a>
push_tag=推é€äº†æ ‡ç­¾ <a href="%[2]s">%[3]s</a> 至仓库 <a href="%[1]s">%[4]s</a>
delete_tag=从<a href="%[1]s">%[3]s</a> 删除了标签 %[2]s
@@ -3101,6 +3156,8 @@ keywords=关键è¯
details=详情
details.author=作者
details.project_site=项目站点
+details.repository_site=仓库站点
+details.documentation_site=文档站点
details.license=许å¯åè®®
assets=文件
versions=版本
@@ -3108,6 +3165,14 @@ versions.on=于
versions.view_all=查看全部
dependency.id=ID
dependency.version=版本
+cargo.registry=在 Cargo é…置文件中设置此注册中心(例如:<code>~/.cargo/config.toml</code>):
+cargo.install=è¦ä½¿ç”¨ Cargo 安装软件包,请è¿è¡Œä»¥ä¸‹å‘½ä»¤ï¼š
+cargo.documentation=关于 Cargo 注册中心的更多信æ¯ï¼Œè¯·å‚阅 <a target="_blank" rel="noopener noreferrer" href="https://docs.gitea.io/en-us/packages/cargo/">文档</a>。
+cargo.details.repository_site=仓库站点
+cargo.details.documentation_site=文档站点
+chef.registry=在您的 <code>~/.chef/config.rb</code> 文件中设置此注册中心:
+chef.install=è¦å®‰è£…包,请è¿è¡Œä»¥ä¸‹å‘½ä»¤ï¼š
+chef.documentation=关于 Chef 注册中心的更多信æ¯ï¼Œè¯·å‚阅 <a target="_blank" rel="noopener noreferrer" href="https://docs.gitea.io/en-us/packages/chef/">文档</a>。
composer.registry=在您的 <code>~/.composer/config.json</code> 文件中设置此注册中心:
composer.install=è¦ä½¿ç”¨ Composer 安装软件包,请è¿è¡Œä»¥ä¸‹å‘½ä»¤ï¼š
composer.documentation=关于 Composer 注册中心的更多信æ¯ï¼Œè¯·å‚阅 <a target="_blank" rel="noopener noreferrer" href="https://docs.gitea.io/en-us/packages/composer/"> 文档 </a>。
@@ -3117,10 +3182,13 @@ conan.details.repository=仓库
conan.registry=从命令行设置此注册中心:
conan.install=è¦ä½¿ç”¨ Conan 安装软件包,请è¿è¡Œä»¥ä¸‹å‘½ä»¤ï¼š
conan.documentation=关于 Conan 注册中心的更多信æ¯ï¼Œè¯·å‚阅 <a target="_blank" rel="noopener noreferrer" href="https://docs.gitea.io/en-us/packages/conan/">文档</a>。
+conda.registry=在您的 <code>.condarc</code> 文件中将此注册中心设置为 Conda 仓库:
+conda.install=è¦ä½¿ç”¨ Conda 安装软件包,请è¿è¡Œä»¥ä¸‹å‘½ä»¤ï¼š
+conda.documentation=关于 Conda 注册中心的更多信æ¯ï¼Œè¯·å‚阅 <a target="_blank" rel="noopener noreferrer" href="https://docs.gitea.io/en-us/packages/conda/">文档</a>。
+conda.details.repository_site=仓库站点
+conda.details.documentation_site=文档站点
container.details.type=é•œåƒç±»åž‹
container.details.platform=å¹³å°
-container.details.repository_site=仓库站点
-container.details.documentation_site=文档网站
container.pull=从命令行拉å–é•œåƒï¼š
container.digest=摘è¦ï¼š
container.documentation=关于 Container 注册中心的更多信æ¯ï¼Œè¯·å‚阅 <a target="_blank" rel="noopener noreferrer" href="https://docs.gitea.io/en-us/packages/container/">文档</a>。
@@ -3154,8 +3222,6 @@ npm.dependencies.optional=å¯é€‰ä¾èµ–
npm.details.tag=标签
pub.install=è¦ä½¿ç”¨ Dart 安装软件包,请è¿è¡Œä»¥ä¸‹å‘½ä»¤ï¼š
pub.documentation=关于 Pub 注册中心的信æ¯ï¼Œè¯·å‚阅 <a target="_blank" rel="noopener noreferrer" href="https://docs.gitea.io/en-us/packages/pub/">文档</a>。
-pub.details.repository_site=仓库站点
-pub.details.documentation_site=文档站点
pypi.requires=éœ€è¦ Python
pypi.install=è¦ä½¿ç”¨ pip 安装软件包,请è¿è¡Œä»¥ä¸‹å‘½ä»¤ï¼š
pypi.documentation=关于 PyPI 注册中心的信æ¯ï¼Œè¯·å‚阅 <a target="_blank" rel="noopener noreferrer" href="https://docs.gitea.io/en-us/packages/pypi/">文档</a>。
@@ -3179,4 +3245,110 @@ settings.delete.description=删除软件包是永久性的,无法撤消。
settings.delete.notice=您将è¦åˆ é™¤ %s (%s)。此æ“作是ä¸å¯é€†çš„,您确定å—?
settings.delete.success=软件包已被删除。
settings.delete.error=删除软件包失败。
+owner.settings.cargo.title=Cargo 注册中心索引
+owner.settings.cargo.initialize=åˆå§‹åŒ–索引
+owner.settings.cargo.initialize.description=使用 Cargo 包管ç†éœ€è¦ä¸€ä¸ªç‰¹æ®Šçš„ Git 仓库。你å¯ä»¥åœ¨è¿™é‡Œä½¿ç”¨è¦æ±‚çš„é…置创建或é‡å»ºå®ƒã€‚
+owner.settings.cargo.initialize.error=åˆå§‹åŒ–Cargo索引失败: %v
+owner.settings.cargo.initialize.success=Cargo索引已ç»æˆåŠŸåˆ›å»ºã€‚
+owner.settings.cargo.rebuild=é‡å»ºç´¢å¼•
+owner.settings.cargo.rebuild.description=如果 cargo 包的索引没有åŒæ­¥ï¼Œä½ å¯ä»¥é‡å»ºç´¢å¼•ã€‚
+owner.settings.cargo.rebuild.error=无法é‡å»º Cargo 索引: %v
+owner.settings.cargo.rebuild.success=Cargo 索引已æˆåŠŸé‡å»ºã€‚
+owner.settings.cleanuprules.title=管ç†æ¸…ç†è§„则
+owner.settings.cleanuprules.add=添加清ç†è§„则
+owner.settings.cleanuprules.edit=编辑清ç†è§„则
+owner.settings.cleanuprules.none=没有å¯ç”¨çš„清ç†è§„则。请阅读文档了解更多信æ¯ã€‚
+owner.settings.cleanuprules.preview=清ç†è§„则预览
+owner.settings.cleanuprules.preview.overview=%d 个软件包计划被删除。
+owner.settings.cleanuprules.preview.none=清ç†è§„则与任何软件包都ä¸åŒ¹é…。
+owner.settings.cleanuprules.enabled=å¯ç”¨
+owner.settings.cleanuprules.pattern_full_match=应用规则到完整软件包å称
+owner.settings.cleanuprules.keep.title=与这些规则相匹é…的版本å³ä½¿ä¸Žä¸‹é¢çš„删除规则相匹é…,也将予以ä¿ç•™ã€‚
+owner.settings.cleanuprules.keep.count=ä¿ç•™æœ€æ–°çš„
+owner.settings.cleanuprules.keep.count.1=æ¯ä¸ªè½¯ä»¶åŒ…1个版本
+owner.settings.cleanuprules.keep.count.n=æ¯ä¸ªè½¯ä»¶åŒ… %d 个版本
+owner.settings.cleanuprules.keep.pattern=ä¿æŒç‰ˆæœ¬åŒ¹é…
+owner.settings.cleanuprules.keep.pattern.container=容器包的 <code>最新版本</code> 总是会ä¿ç•™ã€‚
+owner.settings.cleanuprules.remove.title=与这些规则相匹é…的版本将被删除,除éžå…¶ä¸­å­˜åœ¨æŸä¸ªä¿ç•™å®ƒä»¬çš„规则。
+owner.settings.cleanuprules.remove.days=移除旧于天数的版本
+owner.settings.cleanuprules.remove.pattern=删除匹é…的版本
+owner.settings.cleanuprules.success.update=清ç†è§„则已更新。
+owner.settings.cleanuprules.success.delete=清ç†è§„则已删除。
+owner.settings.chef.title=Chef 注册中心
+owner.settings.chef.keypair=生æˆå¯†é’¥å¯¹
+owner.settings.chef.keypair.description=生æˆç”¨äºŽéªŒè¯Chef 注册中心的密钥对。之å‰çš„密钥ä¸èƒ½åœ¨ä»¥åŽä½¿ç”¨ã€‚
+
+[secrets]
+secrets=密钥
+description=Secrets 将被传给特定的 Actions,其它情况将ä¸èƒ½è¯»å–
+none=还没有密钥。
+value=值
+name=å称
+creation=添加密钥
+creation.name_placeholder=ä¸åŒºåˆ†å¤§å°å†™ï¼Œå­—æ¯æ•°å­—或下划线ä¸èƒ½ä»¥GITEA_ 或 GITHUB_ 开头。
+creation.value_placeholder=输入任何内容,开头和结尾的空白都会被çœç•¥
+creation.success=您的密钥 '%s' 添加æˆåŠŸã€‚
+creation.failed=添加密钥失败。
+deletion=删除密钥
+deletion.description=删除密钥是永久性的,无法撤消。继续å—?
+deletion.success=此Secret已被删除。
+deletion.failed=删除密钥失败。
+
+[actions]
+actions=Actions
+
+unit.desc=管ç†Actions
+
+status.unknown=未知
+status.waiting=等待中
+status.running=正在è¿è¡Œ
+status.success=æˆåŠŸ
+status.failure=失败
+status.cancelled=å·²å–消
+status.skipped=已忽略
+status.blocked=阻塞中
+
+runners=Runners
+runners.runner_manage_panel=Runners管ç†
+runners.new=创建 Runner
+runners.new_notice=如何å¯åŠ¨ä¸€ä¸ªè¿è¡Œå™¨
+runners.status=状æ€
+runners.id=ID
+runners.name=å称
+runners.owner_type=类型
+runners.description=组织æè¿°
+runners.labels=标签
+runners.last_online=上次在线时间
+runners.agent_labels=代ç†æ ‡ç­¾
+runners.custom_labels=自定义标签
+runners.custom_labels_helper=自定义标签是由管ç†å‘˜æ‰‹åŠ¨æ·»åŠ çš„标签。标签之间用逗å·åˆ†éš”,æ¯ä¸ªæ ‡ç­¾çš„开头和结尾的空白被忽略。
+runners.runner_title=Runner
+runners.task_list=最近在此runner上的任务
+runners.task_list.run=执行
+runners.task_list.status=状æ€
+runners.task_list.repository=仓库
+runners.task_list.commit=æ交
+runners.task_list.done_at=完æˆäºŽ
+runners.edit_runner=编辑è¿è¡Œå™¨
+runners.update_runner=更新更改
+runners.update_runner_success=è¿è¡Œå™¨æ›´æ–°æˆåŠŸ
+runners.update_runner_failed=æ›´æ–°è¿è¡Œå™¨å¤±è´¥
+runners.delete_runner=删除è¿è¡Œå™¨
+runners.delete_runner_success=è¿è¡Œå™¨åˆ é™¤æˆåŠŸ
+runners.delete_runner_failed=删除è¿è¡Œå™¨å¤±è´¥
+runners.delete_runner_header=确认è¦åˆ é™¤æ­¤è¿è¡Œå™¨
+runners.delete_runner_notice=如果一个任务正在è¿è¡Œåœ¨æ­¤è¿è¡Œå™¨ä¸Šï¼Œå®ƒå°†è¢«ç»ˆæ­¢å¹¶æ ‡è®°ä¸ºå¤±è´¥ã€‚它å¯èƒ½ä¼šæ‰“断正在构建的工作æµã€‚
+runners.none=æ— å¯ç”¨çš„ Runner
+runners.status.unspecified=未知
+runners.status.idle=空闲
+runners.status.active=激活
+runners.status.offline=离线
+
+runs.all_workflows=所有工作æµ
+runs.open_tab=%d å¼€å¯ä¸­
+runs.closed_tab=%d 已关闭
+runs.commit=æ交
+runs.pushed_by=推é€è€…
+
+need_approval_desc=该工作æµç”±æ´¾ç”Ÿä»“库的åˆå¹¶è¯·æ±‚所触å‘,需è¦æ‰¹å‡†æ–¹å¯è¿è¡Œã€‚
diff --git a/options/locale/locale_zh-HK.ini b/options/locale/locale_zh-HK.ini
index 71e6f7a50..6fa062fc6 100644
--- a/options/locale/locale_zh-HK.ini
+++ b/options/locale/locale_zh-HK.ini
@@ -27,6 +27,7 @@ new_org=新增組織
manage_org=管ç†çµ„ç¹”
account_settings=帳號設定
settings=設定
+your_settings=組織設定
all=所有
sources=來æº
@@ -39,13 +40,19 @@ pull_requests=åˆä½µè«‹æ±‚
issues=å•é¡Œ
cancel=å–消
+remove=移除æˆå“¡
+edit=編輯
+enabled=已啟用
+
+[aria]
+
[filter]
[error]
@@ -65,6 +72,10 @@ repo_path=儲存庫的根目錄
log_root_path=日誌路徑
optional_title=å¯é¸è¨­å®š
+smtp_addr=SMTP 主機地å€
+smtp_port=SMTP 主機端å£
+disable_gravatar=ç¦ç”¨ Gravatar é ­åƒ
+federated_avatar_lookup=é–‹å•Ÿè¯åˆé ­åƒ
federated_avatar_lookup_popup=é–‹å•Ÿè¯åˆé ­åƒæŸ¥è©¢ä¸¦ä½¿ç”¨åŸºæ–¼é–‹æ”¾æºç¢¼çš„ libravatar æœå‹™
enable_captcha_popup=è¦æ±‚在用戶註冊時輸入驗證碼
admin_password=管ç†å“¡å¯†ç¢¼
@@ -76,12 +87,14 @@ save_config_failed=儲存設定失敗:%v
[home]
password_holder=密碼
switch_dashboard_context=切æ›æŽ§åˆ¶é¢ç‰ˆç”¨æˆ¶
+my_repos=儲存庫管ç†
collaborative_repos=åƒèˆ‡å”作的儲存庫
my_orgs=我的組織
my_mirrors=我的é¡åƒ
view_home=è¨ªå• %s
+show_private=ç§æœ‰åº«
issues.in_your_repos=屬於該用戶儲存庫的
@@ -106,6 +119,8 @@ scratch_code=備用碼
use_scratch_code=使用備用碼
twofa_scratch_used=你已經使用了你的備用碼。你將會被轉到兩步驟驗證設定é é¢ä»¥ä¾¿ç§»é™¤ä½ å·²è¨»å†Šè¨­å‚™æˆ–é‡æ–°ç”¢ç”Ÿæ–°çš„備用碼。
twofa_scratch_token_incorrect=您的備用碼ä¸æ­£ç¢º
+login_userpass=登入
+oauth_signin_submit=連çµå¸³æˆ¶
openid_connect_submit=連接
openid_connect_title=連接到ç¾æœ‰å¸³æˆ¶
openid_register_title=建立新帳戶
@@ -183,8 +198,11 @@ password=修改密碼
avatar=é ­åƒ
ssh_gpg_keys=SSH / GPG 金鑰
social=社交帳號ç¶å®š
+orgs=管ç†çµ„ç¹”
+repos=儲存庫管ç†
delete=刪除帳戶
twofa=兩步驟驗證
+organization=組織管ç†
uid=使用者 ID
public_profile=公開訊æ¯
@@ -195,6 +213,8 @@ update_profile=更新訊æ¯
update_profile_success=您的個人資料已被更新
continue=繼續æ“作
cancel=å–消æ“作
+language=語言
+comment_type_group_title=標題
federated_avatar_lookup=Federated Avatar 查詢
enable_custom_avatar=啟動自定義頭åƒ
@@ -207,6 +227,8 @@ new_password=新的密碼
emails=é›»å­éƒµä»¶åœ°å€
email_desc=您的主è¦é‚®ç®±åœ°å€å°†è¢«ç”¨äºŽé€šçŸ¥æ醒和其它æ“作。
primary=主è¦
+activated=已啟用
+delete_email=移除æˆå“¡
add_openid=新增 OpenID URI
manage_ssh_keys=ç®¡ç† SSH 金鑰
@@ -216,15 +238,22 @@ ssh_helper=<strong>需è¦å”助?</strong> 查詢GitHub的文件以 <a href="%s">
gpg_helper=<strong>需è¦å”助嗎?</strong>建議å¯çœ‹çœ‹ GitHub çš„ <a href="%s">about GPG</a> 文件。
add_new_key=增加 SSH 金鑰
add_new_gpg_key=新增 GPG 金鑰
+gpg_key_verify=é©—è­‰
+gpg_token=令牌
+ssh_key_verify=é©—è­‰
+ssh_token=令牌
subkeys=次金鑰
key_id=金鑰 ID
key_name=金鑰å稱
key_content=金鑰內容
+principal_content=金鑰文本
+delete_key=移除æˆå“¡
add_on=增加於
valid_until=有效期至
valid_forever=æ°¸é æœ‰æ•ˆ
last_used=上次使用在
no_activity=沒有最近活動
+can_read_info=已讀
key_state_desc=該金鑰在 7 天內被使用éŽ
token_state_desc=æ­¤ token 在éŽåŽ»ä¸ƒå¤©å…§æ›¾ç¶“被使用éŽ
show_openid=在設定檔顯示
@@ -235,7 +264,10 @@ generate_new_token=生æˆæ–°çš„令牌
token_name=令牌å稱
generate_token=生æˆä»¤ç‰Œ
delete_token=删除令牌
+access_token_deletion_cancel_action=å–消
+oauth2_client_secret=用戶端金鑰
+oauth2_application_edit=編輯
twofa_is_enrolled=您的帳號已經<strong>啟用</strong>兩步驟驗證。
@@ -245,6 +277,8 @@ scan_this_image=使用您的授權應用程å¼ä¾†æŽƒçž„圖片:
or_enter_secret=或者輸入密碼: %s
+link_account=連çµå¸³æˆ¶
+
orgs_none=您尚未æˆç‚ºä»»ä¸€çµ„織的æˆå“¡ã€‚
repos_none=您ä¸æ“有任何存儲庫
@@ -253,6 +287,7 @@ delete_account=刪除當å‰å¸³æˆ¶
confirm_delete_account=確èªåˆªé™¤å¸³æˆ¶
+visibility.private=ç§æœ‰åº«
[repo]
owner=æ“有者
@@ -271,11 +306,16 @@ stargazers=稱讚者
forks=複製儲存庫
+desc.private=ç§æœ‰åº«
+template.avatar=é ­åƒ
form.name_reserved=儲存庫å稱 '%s' 是é ç•™çš„。
+migrate_items_issues=å•é¡Œæ•¸
+migrate_items_pullrequests=åˆä½µè«‹æ±‚
+migrate_items_releases=版本發佈
migrate_repo=é·ç§»å„²å­˜åº«
migrate.permission_denied=您並沒有導入本地儲存庫的權é™ã€‚
migrate.failed=é·ç§»å¤±æ•—:%v
@@ -316,6 +356,7 @@ stored_lfs=儲存到到 Git LFS
editor.preview_changes=é è¦½æ›´æ”¹
editor.or=或
+editor.cancel_lower=å–消
editor.commit_changes=æ交更改嗎?
editor.add=新增 '%s'
editor.update=æ›´æ–° '%s'
@@ -339,6 +380,10 @@ commits.signed_by=簽署人
+projects.description_placeholder=組織æè¿°
+projects.title=標題
+projects.column.edit_title=組織å稱
+projects.column.new_title=組織å稱
issues.new=建立å•é¡Œ
issues.new.labels=標籤
@@ -351,6 +396,7 @@ issues.new.open_milestone=開啟中的里程碑
issues.new.closed_milestone=已關閉的里程碑
issues.create=建立å•é¡Œ
issues.new_label=建立標籤
+issues.new_label_desc_placeholder=組織æè¿°
issues.create_label=建立標籤
issues.label_templates.title=載入一組é å®šç¾©çš„標籤
issues.label_templates.helper=é¸æ“‡ä¸€å€‹æ¨™ç±¤é›†
@@ -359,6 +405,7 @@ issues.add_milestone_at=`新增至<b>%s</b> 里程碑 %s`
issues.change_milestone_at=`%[3]s 修改了里程碑 <b>%[1]s</b> 到 <b>%[2]s</b>`
issues.remove_milestone_at=`從里程碑 %[2]s 刪除 <b>%[1]s</b>`
issues.deleted_milestone=`(已刪除)`
+issues.deleted_project=`(已刪除)`
issues.self_assign_at=將 %s 指派給自己
issues.add_assignee_at=`被<b>%s</b> %s指派`
issues.delete_branch_at=`刪除分支 <b>%s</b> %s`
@@ -389,9 +436,11 @@ issues.previous=上一é 
issues.next=下一é 
issues.open_title=開啟中
issues.closed_title=已關閉
+issues.draft_title=è‰ç¨¿
issues.num_comments=%d æ¢è©•è«–
issues.commented_at=` è©•è«– <a href="#%s"> %s</a>`
issues.delete_comment_confirm=您確定è¦åˆªé™¤è©²æ¢è©•è«–嗎?
+issues.context.edit=編輯
issues.no_content=尚未有任何內容
issues.close_issue=關閉
issues.reopen_issue=é‡æ–°é–‹å•Ÿ
@@ -405,6 +454,7 @@ issues.edit=編輯
issues.cancel=å–消
issues.save=儲存
issues.label_title=標籤å稱
+issues.label_description=組織æè¿°
issues.label_color=標籤é¡è‰²
issues.label_count=%d 個標籤
issues.label_open_issues=%d 個開啓的å•é¡Œ
@@ -417,9 +467,15 @@ issues.attachment.open_tab=`在新的標籤é ä¸­æŸ¥çœ‹ '%s'`
issues.attachment.download=`點擊下載 '%s'`
issues.subscribe=訂閱
issues.unsubscribe=å–消訂閱
+issues.add_time_cancel=å–消
+issues.due_date_form_edit=編輯
+issues.due_date_form_remove=移除æˆå“¡
+issues.dependency.cancel=å–消
+issues.dependency.remove=移除æˆå“¡
pulls.new=建立åˆä½µè«‹æ±‚
+pulls.compare_changes=建立åˆä½µè«‹æ±‚
pulls.filter_branch=éŽæ¿¾åˆ†æ”¯
pulls.no_results=未找到çµæžœ
pulls.create=建立åˆä½µè«‹æ±‚
@@ -460,6 +516,7 @@ milestones.filter_sort.least_issues=å•é¡Œç”±å°‘到多
wiki.page=é é¢
wiki.filter_page=éŽæ¿¾é é¢
+wiki.new_page=é é¢
wiki.default_commit_message=關於此次é é¢ä¿®æ”¹çš„說明(éžå¿…è¦)。
wiki.save_page=儲存é é¢
wiki.last_commit_info=%s æ–¼ %s 修改了此é é¢
@@ -470,17 +527,28 @@ wiki.page_already_exists=相åŒå稱的 Wiki é é¢å·²ç¶“存在。
wiki.pages=所有é é¢
wiki.last_updated=最後更新於 %s
+activity.period.daily=1 天
+activity.period.weekly=1 周
+activity.period.monthly=1 月
+activity.period.yearly=1 å¹´
+activity.merged_prs_label=å·²åˆä½µ
+activity.closed_issue_label=已關閉
+activity.new_issues_count_1=建立å•é¡Œ
+search=æœå°‹
settings=儲存庫設定
settings.desc=設定是您å¯ä»¥ç®¡ç†å„²å­˜åº«è¨­å®šçš„地方
+settings.options=儲存庫
settings.collaboration.write=å¯å¯«æ¬Šé™
settings.collaboration.read=å¯è®€æ¬Šé™
+settings.collaboration.owner=管ç†å“¡
settings.collaboration.undefined=未定義
settings.hooks=ç®¡ç† Webhooks
settings.githooks=ç®¡ç† Git Hooks
settings.basic_settings=基本設定
settings.mirror_settings=é¡åƒè¨­å®š
+settings.site=官方網站
settings.update_settings=更新儲存庫設定
settings.advanced_settings=高級設定
settings.external_wiki_url=外部 Wiki 連çµ
@@ -492,13 +560,17 @@ settings.danger_zone=å±éšªæ“作å€
settings.new_owner_has_same_repo=新的儲存庫æ“有者已經存在åŒå儲存庫ï¼
settings.transfer=轉移儲存庫所有權
settings.transfer_owner=æ–°æ“有者
+settings.trust_model.collaborator=å”åŒè€…
settings.delete=刪除本儲存庫
settings.delete_notices_1=- æ­¤æ“作 <strong>ä¸å¯ä»¥</strong> 被回滾。
+settings.delete_collaborator=移除æˆå“¡
+settings.teams=組織團隊
settings.add_webhook=建立 Webhook
settings.webhook.test_delivery=測試推é€
settings.webhook.request=請求內容
settings.webhook.response=響應內容
settings.webhook.headers=標題
+settings.webhook.payload=金鑰文本
settings.webhook.body=響應內容
settings.githook_edit_desc=如果 Hook 未啟動,則會顯示樣例文件中的內容。如果想è¦åˆªé™¤æŸå€‹ Hook,則æ交空白文本å³å¯ã€‚
settings.githook_name=Hook å稱
@@ -508,7 +580,10 @@ settings.secret=金鑰文本
settings.slack_username=æœå‹™å稱
settings.slack_icon_url=圖標 URL
settings.event_create=建立
+settings.event_fork=複製
settings.event_push=推é€
+settings.event_repository=儲存庫
+settings.event_issues=å•é¡Œæ•¸
settings.event_pull_request=åˆä½µè«‹æ±‚
settings.update_webhook=æ›´æ–° Webhook
settings.recent_deliveries=最近推é€è¨˜éŒ„
@@ -527,6 +602,7 @@ settings.protected_branch_can_push_yes=ä½ å¯ä»¥æŽ¨é€
settings.protected_branch_can_push_no=ä½ ä¸èƒ½æŽ¨é€
settings.add_protected_branch=啟用ä¿è­·
settings.delete_protected_branch=åœç”¨ä¿è­·
+settings.edit_protected_branch=編輯
diff.browse_source=ç€è¦½ä»£ç¢¼
diff.parent=父節點
@@ -537,6 +613,7 @@ diff.show_unified_view=統一視圖
diff.stats_desc=共有 <strong> %d 個文件被更改</strong>,包括 <strong>%d 次æ’å…¥</strong> å’Œ <strong>%d 次删除</strong>
diff.bin=二進制
diff.view_file=查看文件
+diff.file_byte_size=大å°
diff.file_suppressed=文件差異éŽå¤§å°Žè‡´ç„¡æ³•é¡¯ç¤º
release.releases=版本發佈
@@ -567,7 +644,7 @@ org_name_holder=組織å稱
org_full_name_holder=組織全å
create_org=建立組織
repo_updated=最後更新於
-people=組織æˆå“¡
+members=æˆå“¡æ•¸
teams=組織團隊
lower_members=åæˆå“¡
lower_repositories=個儲存庫
@@ -580,12 +657,14 @@ settings=組織設定
settings.full_name=組織全å
settings.website=官方網站
settings.location=所在地å€
+settings.visibility.private_shortname=ç§æœ‰åº«
settings.update_settings=更新組織設定
settings.update_setting_success=組織設定已更新。
settings.delete=刪除組織
settings.delete_account=刪除當å‰çµ„ç¹”
settings.confirm_delete_account=確èªåˆªé™¤çµ„ç¹”
+settings.delete_org_title=刪除組織
settings.hooks_desc=新增 webhooks 將觸發在這個組織下 <strong>全部的儲存庫</strong> 。
@@ -600,6 +679,7 @@ members.invite_now=ç«‹å³é‚€è«‹
teams.join=加入團隊
teams.leave=離開團隊
+teams.read_access=已讀
teams.no_desc=該團隊暫無æè¿°
teams.settings=團隊設定
teams.members=團隊æˆå“¡
@@ -655,6 +735,7 @@ dashboard.total_gc_pause=垃圾收集暫åœæ™‚間總é‡
dashboard.last_gc_pause=上次垃圾收集暫åœæ™‚é–“
dashboard.gc_times=垃圾收集執行次數
+users.full_name=組織全å
users.activated=已啟用
users.admin=管ç†å“¡
users.repos=儲存庫數
@@ -662,7 +743,9 @@ users.created=建立時間
users.edit=編輯
users.auth_source=èªè­‰æº
users.local=本地
+users.list_status_filter.is_admin=管ç†å“¡
+emails.activated=已啟用
orgs.org_manage_panel=組織管ç†
orgs.name=組織å稱
@@ -678,6 +761,11 @@ repos.stars=讚好數
repos.issues=å•é¡Œæ•¸
repos.size=大å°
+packages.owner=管ç†å“¡
+packages.name=組織å稱
+packages.type=èªè­‰é¡žåž‹
+packages.repository=儲存庫
+packages.size=大å°
@@ -721,6 +809,7 @@ auths.tip.github=在 https://github.com/settings/applications/new 註冊一個æ–
auths.tip.gitlab=在 https://gitlab.com/profile/applications 註冊一個新的應用程å¼
auths.tip.openid_connect=使用 OpenID 連接探索 URL (<server>/.well-known/openid-configuration) 來指定節點
auths.new_success=已增加èªè­‰'%s'。
+auths.delete=刪除èªè­‰ä¾†æº
auths.delete_auth_title=刪除èªè­‰ä¾†æº
config.server_config=伺æœå™¨è¨­å®š
@@ -744,6 +833,7 @@ config.ssh_keygen_path=金鑰產生 (' ssh-keygen ') 路徑
config.ssh_minimum_key_size_check=金鑰最å°å¤§å°æª¢æŸ¥
config.ssh_minimum_key_sizes=金鑰最å°å¤§å°
+config.lfs_enabled=已啟用
config.db_config=資料庫設定
config.db_type=資料庫類型
@@ -763,6 +853,7 @@ config.skip_tls_verify=ç•¥éŽ TLS é©—è­‰
config.mailer_enabled=啟用æœå‹™
config.mailer_name=發é€è€…å稱
+config.mailer_smtp_port=SMTP 主機端å£
config.mailer_user=發é€è€…帳號
config.oauth_config=社交帳號設定
@@ -811,12 +902,14 @@ monitor.process=執行中進程
monitor.desc=進程æè¿°
monitor.start=開始時間
monitor.execute_time=已執行時間
+monitor.queue.name=組織å稱
+monitor.queue.type=èªè­‰é¡žåž‹
+monitor.queue.settings.submit=更新組織設定
notices.system_notice_list=系統æ示管ç†
notices.view_detail_header=查看æ示細節
-notices.actions=æ“作
notices.select_all=é¸å–全部
notices.deselect_all=å–消所有é¸å–
notices.inverse_selection=åå‘é¸å–
@@ -877,4 +970,22 @@ error.not_signed_commit=未簽åçš„æ交
[units]
[packages]
+filter.type=èªè­‰é¡žåž‹
+conan.details.repository=儲存庫
+owner.settings.cleanuprules.enabled=已啟用
+
+[secrets]
+name=組織å稱
+
+[actions]
+
+
+
+runners.name=組織å稱
+runners.owner_type=èªè­‰é¡žåž‹
+runners.description=組織æè¿°
+runners.task_list.run=執行
+runners.task_list.repository=儲存庫
+
+
diff --git a/options/locale/locale_zh-TW.ini b/options/locale/locale_zh-TW.ini
index ff2a238fa..e98e55b77 100644
--- a/options/locale/locale_zh-TW.ini
+++ b/options/locale/locale_zh-TW.ini
@@ -54,10 +54,10 @@ mirror=é¡åƒ
new_repo=新增儲存庫
new_migrate=é·ç§»å¤–部儲存庫
new_mirror=æ–°é¡åƒ
-new_fork=新增儲存庫 fork
+new_fork=新增儲存庫 Fork
new_org=新增組織
new_project=新增專案
-new_project_board=新增專案看æ¿
+new_project_column=新增欄ä½
manage_org=管ç†çµ„ç¹”
admin_panel=網站管ç†
account_settings=帳戶設定
@@ -86,11 +86,16 @@ remove=移除
remove_all=全部移除
edit=編輯
+enabled=已啟用
+disabled=å·²åœç”¨
+
copy=複製
copy_url=複製 URL
+copy_content=複製內容
copy_branch=複製分支å稱
copy_success=複製æˆåŠŸï¼
copy_error=複製失敗
+copy_type_unsupported=無法複製此類型的檔案
write=撰寫
preview=é è¦½
@@ -106,7 +111,15 @@ never=從來沒有
rss_feed=RSS 摘è¦
+[aria]
+navbar=導航列
+footer=é å°¾
+footer.software=關於軟體
+footer.links=連çµ
+
[filter]
+string.asc=A - Z
+string.desc=Z - A
[error]
occurred=發生錯誤
@@ -224,7 +237,6 @@ internal_token_failed=產生內部 Token 失敗:%v
secret_key_failed=產生密鑰失敗:%v
save_config_failed=儲存設定失敗:%v
invalid_admin_setting=管ç†å“¡å¸³æˆ¶è¨­å®šä¸æ­£ç¢ºï¼š%v
-install_success=æ­¡è¿Žï¼éžå¸¸æ„Ÿè¬æ‚¨é¸æ“‡ Gitea,ç¥ä½ ä¸€åˆ‡é †åˆ©ã€‚
invalid_log_root_path=日誌根目錄設定ä¸æ­£ç¢º: %v
default_keep_email_private=é è¨­éš±è—é›»å­ä¿¡ç®±
default_keep_email_private_popup=é è¨­éš±è—新使用者的電å­ä¿¡ç®±ã€‚
@@ -235,7 +247,10 @@ default_enable_timetracking_popup=é è¨­æƒ…æ³ä¸‹å•Ÿç”¨æ–°å­˜å„²åº«çš„時間跟è
no_reply_address=éš±è—é›»å­ä¿¡ç®±åŸŸå
no_reply_address_helper=作為隱è—é›»å­ä¿¡ç®±ä½¿ç”¨è€…的域å。例如,如果隱è—çš„é›»å­ä¿¡ç®±åŸŸå設定為「noreply.example.orgã€ï¼Œå¸³è™Ÿã€Œjoeã€å°‡ä»¥ã€Œjoe@noreply.example.orgã€çš„身分登錄到 Git 中。
password_algorithm=密碼雜湊演算法
+invalid_password_algorithm=無效的密碼雜湊演算法
password_algorithm_helper=設定密碼雜湊演算法。演算法有ä¸åŒçš„需求和強度。「argon2ã€é›–然有優秀的特性但會å ç”¨å¤§é‡è¨˜æ†¶é«”,所以å¯èƒ½ä¸é©ç”¨æ–¼å°åž‹ç³»çµ±ã€‚
+enable_update_checker=啟用更新檢查器
+enable_update_checker_helper=定期連線到 gitea.io 檢查更新。
[home]
uname_holder=帳號或電å­ä¿¡ç®±
@@ -282,6 +297,8 @@ org_no_results=沒有找到符åˆçš„組織。
code_no_results=找ä¸åˆ°ç¬¦åˆæ‚¨é—œéµå­—的原始碼。
code_search_results=「%sã€çš„æœå°‹çµæžœ
code_last_indexed_at=最後索引 %s
+relevant_repositories_tooltip=已隱è—缺少主題ã€åœ–示ã€èªªæ˜Žã€Fork 的儲存庫。
+relevant_repositories=åªé¡¯ç¤ºç›¸é—œçš„儲存庫,<a href="%s">顯示未篩é¸çš„çµæžœ</a>。
[auth]
@@ -311,6 +328,7 @@ email_not_associate=此電å­ä¿¡ç®±æœªèˆ‡ä»»ä½•å¸³æˆ¶é€£çµ
send_reset_mail=發é€å¸³æˆ¶æ•‘æ´ä¿¡
reset_password=帳戶救æ´
invalid_code=您的確èªä»£ç¢¼ç„¡æ•ˆæˆ–å·²éŽæœŸã€‚
+invalid_password=您的密碼和用來建立帳戶的ä¸ç¬¦ã€‚
reset_password_helper=帳戶救æ´
reset_password_wrong_user=您已經使用 %s 的帳戶登入,但帳戶救æ´é€£çµæ˜¯çµ¦ %s çš„
password_too_short=密碼長度ä¸èƒ½å°‘æ–¼ %d 個字ï¼
@@ -354,6 +372,7 @@ password_pwned_err=無法完æˆå° HaveIBeenPwned 的請求。
[mail]
view_it_on=在 %s 上查看
+reply=或是直接回覆此電å­éƒµä»¶
link_not_working_do_paste=無法開啟?請複製超連çµåˆ°ç€è¦½å™¨è²¼ä¸Šã€‚
hi_user_x=<b>%s</b> 您好,
@@ -412,6 +431,10 @@ repo.transfer.body=請造訪 %s 以接å—或拒絕轉移,您也å¯ä»¥å¿½ç•¥å®ƒ
repo.collaborator.added.subject=%s 把您加入到 %s
repo.collaborator.added.text=您已被新增為儲存庫的å”作者:
+team_invite.subject=%[1]s 邀請您加入組織 %[2]s
+team_invite.text_1=%[1]s 邀請您加入組織 %[3]s 中的 %[2]s 團隊
+team_invite.text_2=請點擊下方連çµåŠ å…¥åœ˜éšŠ:
+team_invite.text_3=備註: 這是寄給 %[1]s 的邀請。若您未é æœŸæ”¶åˆ°æ­¤é‚€è«‹ï¼Œè«‹å¿½ç•¥æ­¤éƒµä»¶ã€‚
[modal]
yes=是
@@ -428,7 +451,7 @@ SSHTitle=SSH 金鑰å稱
HttpsUrl=HTTPS URL 地å€
PayloadUrl=推é€åœ°å€
TeamName=團隊å稱
-AuthName=èªè­‰å稱
+AuthName=授權å稱
AdminEmail=管ç†å“¡é›»å­ä¿¡ç®±
NewBranchName=新的分支å稱
@@ -453,6 +476,8 @@ url_error=`'%s' 是無效的 URL。`
include_error=` 必須包å«å­å­—串「%sã€ã€‚
glob_pattern_error=` glob 比å°æ¨¡å¼ç„¡æ•ˆï¼š%s.`
regex_pattern_error=` æ­£è¦è¡¨ç¤ºå¼æ¨¡å¼ç„¡æ•ˆï¼š%s.`
+username_error=`åªèƒ½åŒ…å«è‹±æ–‡å­—æ¯æ•¸å­— ('0-9'ã€'a-z'ã€'A-Z')ã€ç ´æŠ˜è™Ÿ ('-')ã€åº•ç·š ('_')ã€å¥é»ž ('.'),ä¸èƒ½ä»¥éžè‹±æ–‡å­—æ¯æ•¸å­—開頭或çµå°¾ï¼Œä¹Ÿä¸å…許連續的éžè‹±æ–‡å­—æ¯æ•¸å­—。`
+invalid_group_team_map_error=` å°æ‡‰ç„¡æ•ˆ: %s`
unknown_error=未知錯誤:
captcha_incorrect=驗證碼ä¸æ­£ç¢ºã€‚
password_not_match=密碼錯誤。
@@ -488,18 +513,21 @@ user_not_exist=該用戶åä¸å­˜åœ¨
team_not_exist=團隊ä¸å­˜åœ¨
last_org_owner=ä½ ä¸èƒ½å¾žã€ŒOwnersã€åœ˜éšŠä¸­åˆªé™¤æœ€å¾Œä¸€å€‹ä½¿ç”¨è€…。æ¯å€‹çµ„織中至少è¦æœ‰ä¸€å€‹æ“有者。
cannot_add_org_to_team=組織ä¸èƒ½è¢«æ–°å¢žç‚ºåœ˜éšŠæˆå“¡ã€‚
+duplicate_invite_to_team=該使用者已經被邀請為團隊æˆå“¡ã€‚
+organization_leave_success=您已æˆåŠŸé›¢é–‹çµ„ç¹” %s。
invalid_ssh_key=無法驗證您的 SSH 密鑰:%s
invalid_gpg_key=無法驗證您的 GPG 密鑰:%s
invalid_ssh_principal=無效的主體: %s
-unable_verify_ssh_key=無法驗證 SSH 密鑰; è«‹å†æ¬¡æª¢æŸ¥æ˜¯å¦æœ‰éŒ¯èª¤ã€‚
+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=此組織æ“有一個或多個套件,請先刪除他們。
+still_own_repo=您的帳戶æ“有一個以上的儲存庫,請先刪除或轉移它們。
+still_has_org=您的帳戶是一個或多個組織的æˆå“¡ï¼Œè«‹å…ˆé›¢é–‹å®ƒå€‘。
+still_own_packages=您的帳戶æ“有一個以上的套件,請先刪除它們。
+org_still_own_repo=此組織ä»ç„¶æ“有一個以上的儲存庫,請先刪除或轉移它們。
+org_still_own_packages=此組織ä»ç„¶æ“有一個以上的套件,請先刪除它們。
target_branch_not_exist=目標分支ä¸å­˜åœ¨
@@ -728,6 +756,8 @@ access_token_deletion_cancel_action=å–消
access_token_deletion_confirm_action=刪除
access_token_deletion_desc=刪除 Token 後,使用此 Token 的應用程å¼å°‡ç„¡æ³•å†å­˜å–您的帳戶,此動作ä¸å¯é‚„原。是å¦ç¹¼çºŒï¼Ÿ
delete_token_success=已刪除 Token。使用此 Token 的應用程å¼ç„¡æ³•å†å­˜å–您的帳戶。
+select_scopes=é¸æ“‡ç¯„åœ (Scope)
+scopes_list=ç¯„åœ (Scope):
manage_oauth2_applications=ç®¡ç† OAuth2 應用程å¼
edit_oauth2_application=編輯 OAuth2 應用程å¼
@@ -740,6 +770,7 @@ create_oauth2_application_button=建立應用程å¼
create_oauth2_application_success=您已æˆåŠŸæ–°å¢žä¸€å€‹ OAuth2 應用程å¼ã€‚
update_oauth2_application_success=您已æˆåŠŸæ›´æ–°äº† OAuth2 應用程å¼ã€‚
oauth2_application_name=應用程å¼å稱
+oauth2_confidential_client=機密客戶端 (Confidential Client)。請為能ä¿æŒæ©Ÿå¯†æ€§çš„程å¼å‹¾é¸ï¼Œä¾‹å¦‚網é æ‡‰ç”¨ç¨‹å¼ã€‚使用原生程å¼æ™‚ä¸è¦å‹¾é¸ï¼ŒåŒ…å«æ¡Œé¢ã€è¡Œå‹•æ‡‰ç”¨ç¨‹å¼ã€‚
oauth2_redirect_uri=é‡æ–°å°Žå‘ URI
save_application=儲存
oauth2_client_id=客戶端 ID
@@ -790,6 +821,7 @@ remove_account_link=刪除已連çµçš„帳戶
remove_account_link_desc=刪除連çµå¸³æˆ¶å°‡æ’¤éŠ·å…¶å° Gitea 帳戶的存å–權é™ã€‚是å¦ç¹¼çºŒï¼Ÿ
remove_account_link_success=已移除連çµçš„帳戶。
+
orgs_none=您尚未æˆç‚ºä»»ä¸€çµ„織的æˆå“¡ã€‚
repos_none=您ä¸æ“有任何存儲庫
@@ -999,10 +1031,12 @@ unstar=移除星號
star=加上星號
fork=Fork
download_archive=下載此儲存庫
+more_operations=更多æ“作
no_desc=æš«ç„¡æè¿°
quick_guide=快速幫助
clone_this_repo=Clone 此儲存庫
+cite_this_repo=引用此儲存庫
create_new_repo_command=從命令列建立新儲存庫。
push_exist_repo=從命令列推é€å·²å­˜åœ¨çš„儲存庫
empty_message=此儲存庫未包å«ä»»ä½•å…§å®¹ã€‚
@@ -1101,6 +1135,7 @@ editor.commit_directly_to_this_branch=直接æ交到 <strong class="branch-name
editor.create_new_branch=為此æ交建立<strong>新分支</strong>並æ出åˆä½µè«‹æ±‚。
editor.create_new_branch_np=為本次æ交建立<strong>新分支</strong>。
editor.propose_file_change=æ出檔案變更
+editor.new_branch_name=命åæ­¤æ交的新分支
editor.new_branch_name_desc=新的分支å稱...
editor.cancel=å–消
editor.filename_cannot_be_empty=檔案å稱ä¸èƒ½ç‚ºç©ºã€‚
@@ -1152,7 +1187,7 @@ commits.signed_by_untrusted_user_unmatched=ç”±ä¸å—信任且與æ交者ä¸ç›¸ç
commits.gpg_key_id=GPG 金鑰 ID
commits.ssh_key_fingerprint=SSH 金鑰指紋
-commit.actions=æ“作
+commit.operations=æ“作
commit.revert=還原
commit.revert-header=還原: %s
commit.revert-content=é¸æ“‡é‚„原的目標分支:
@@ -1182,29 +1217,32 @@ projects.edit_success=已更新專案「%sã€ã€‚
projects.type.none=ç„¡
projects.type.basic_kanban=基本看æ¿
projects.type.bug_triage=Bug 檢傷分類
-projects.template.desc=專案範本
+projects.template.desc=範本
projects.template.desc_helper=é¸æ“‡å°ˆæ¡ˆç¯„本以開始
projects.type.uncategorized=未分類
-projects.board.edit=編輯看æ¿
-projects.board.edit_title=新看æ¿å稱
-projects.board.new_title=新看æ¿å稱
-projects.board.new_submit=é€å‡º
-projects.board.new=新增看æ¿
-projects.board.set_default=設為é è¨­
-projects.board.set_default_desc=將此看æ¿è¨­å®šç‚ºæœªåˆ†é¡žå•é¡ŒåŠåˆä½µè«‹æ±‚çš„é è¨­çœ‹æ¿
-projects.board.delete=刪除看æ¿
-projects.board.deletion_desc=刪除專案看æ¿æœƒå°‡æ‰€æœ‰ç›¸é—œçš„å•é¡Œç§»å‹•åˆ°ã€Œæœªåˆ†é¡žã€ï¼Œæ˜¯å¦ç¹¼çºŒï¼Ÿ
-projects.board.color=é¡è‰²
+projects.column.edit=編輯欄ä½
+projects.column.edit_title=å稱
+projects.column.new_title=å稱
+projects.column.new_submit=建立欄ä½
+projects.column.new=新增欄ä½
+projects.column.set_default=設為é è¨­
+projects.column.set_default_desc=將此欄ä½è¨­å®šç‚ºæœªåˆ†é¡žå•é¡ŒåŠåˆä½µè«‹æ±‚çš„é è¨­é è¨­å€¼
+projects.column.delete=刪除欄ä½
+projects.column.deletion_desc=刪除專案欄ä½æœƒå°‡æ‰€æœ‰ç›¸é—œçš„å•é¡Œç§»å‹•åˆ°ã€Œæœªåˆ†é¡žã€ï¼Œæ˜¯å¦ç¹¼çºŒï¼Ÿ
+projects.column.color=é¡è‰²
projects.open=é–‹å•Ÿ
projects.close=關閉
-projects.board.assigned_to=指派給
+projects.column.assigned_to=已指派給
+projects.card_type.desc=å¡ç‰‡é è¦½
+projects.card_type.images_and_text=圖片和文字
+projects.card_type.text_only=純文字
issues.desc=管ç†éŒ¯èª¤å ±å‘Šã€ä»»å‹™å’Œé‡Œç¨‹ç¢‘。
issues.filter_assignees=篩é¸è² è²¬äºº
issues.filter_milestones=篩é¸é‡Œç¨‹ç¢‘
issues.filter_projects=篩é¸å°ˆæ¡ˆ
issues.filter_labels=篩é¸æ¨™ç±¤
-issues.filter_reviewers=篩é¸å¯©æŸ¥è€…
+issues.filter_reviewers=篩é¸å¯©æ ¸è€…
issues.new=新增å•é¡Œ
issues.new.title_empty=標題ä¸å¯ç‚ºç©º
issues.new.labels=標籤
@@ -1273,6 +1311,9 @@ issues.filter_label_exclude=`使用 <code>alt</code> + <code>click/enter</code>
issues.filter_label_no_select=所有標籤
issues.filter_milestone=里程碑
issues.filter_milestone_no_select=所有里程碑
+issues.filter_project=專案
+issues.filter_project_all=所有專案
+issues.filter_project_none=未é¸æ“‡å°ˆæ¡ˆ
issues.filter_assignee=負責人
issues.filter_assginee_no_select=所有負責人
issues.filter_poster=作者
@@ -1283,6 +1324,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_sort=排åº
issues.filter_sort.latest=最新建立
issues.filter_sort.oldest=最早建立
@@ -1304,6 +1346,8 @@ issues.action_milestone=里程碑
issues.action_milestone_no_select=無里程碑
issues.action_assignee=負責人
issues.action_assignee_no_select=沒有負責人
+issues.action_check=é¸å–/å–消é¸å–
+issues.action_check_all=å…¨é¸/å–消全é¸
issues.opened_by=建立於 %[1]s 由 <a href="%[2]s">%[3]s</a>
pulls.merged_by=ç”± <a href="%[2]s">%[3]s</a> 建立,åˆä½µæ–¼ %[1]s
pulls.merged_by_fake=ç”± %[2]s 建立,åˆä½µæ–¼ %[1]s
@@ -1354,11 +1398,14 @@ issues.sign_in_require_desc=<a href="%s"> 登入</a> æ‰èƒ½åŠ å…¥é€™å°è©±ã€‚
issues.edit=編輯
issues.cancel=å–消
issues.save=儲存
-issues.label_title=標籤å稱
-issues.label_description=標籤æè¿°
-issues.label_color=標籤é¡è‰²
+issues.label_title=å稱
+issues.label_description=æè¿°
+issues.label_color=é¡è‰²
+issues.label_exclusive=互斥
+issues.label_exclusive_desc=請以此格å¼å‘½å標籤: <code>scope/item</code>,使它和其他 <code>scope/</code> (相åŒç¯„åœ) 標籤互斥。
+issues.label_exclusive_warning=在編輯å•é¡ŒåŠåˆä½µè«‹æ±‚的標籤時,將會刪除任何有相åŒç¯„åœçš„標籤。
issues.label_count=%d 個標籤
-issues.label_open_issues=%d 個開放中的å•é¡Œ
+issues.label_open_issues=%d 個開放中的å•é¡Œ/åˆä½µè«‹æ±‚
issues.label_edit=編輯
issues.label_delete=刪除
issues.label_modify=編輯標籤
@@ -1424,6 +1471,7 @@ issues.error_removing_due_date=無法移除截止日期。
issues.push_commit_1=加入了 %d 個æ交 %s
issues.push_commits_n=加入了 %d 個æ交 %s
issues.force_push_codes=`強制推é€äº† %[1]s 自 <a class="ui sha" href="%[3]s"><code>%[2]s</code></a> 至 <a class="ui sha" href="%[5]s"><code>%[4]s</code></a> %[6]s`
+issues.force_push_compare=比較
issues.due_date_form=yyyy年mm月dd日
issues.due_date_form_add=新增截止日期
issues.due_date_form_edit=編輯
@@ -1610,6 +1658,8 @@ pulls.reopened_at=`é‡æ–°é–‹æ”¾äº†é€™å€‹åˆä½µè«‹æ±‚ <a id="%[1]s" href="#%[1]s"
pulls.merge_instruction_hint=`您也å¯ä»¥æŸ¥çœ‹<a class="show-instruction">命令列指å—</a>。`
pulls.merge_instruction_step1_desc=在您的儲存庫中切æ›åˆ°æ–°åˆ†æ”¯ä¸¦æ¸¬è©¦è®Šæ›´ã€‚
pulls.merge_instruction_step2_desc=åˆä½µè®Šæ›´ä¸¦æ›´æ–°åˆ° Gitea。
+pulls.clear_merge_message=清除åˆä½µè¨Šæ¯
+pulls.clear_merge_message_hint=清除åˆä½µè¨Šæ¯å°‡åƒ…移除æ交訊æ¯å…§å®¹ï¼Œç•™ä¸‹ç”¢ç”Ÿçš„ git çµå°¾ï¼Œå¦‚「Co-Authored-By …ã€ã€‚
pulls.auto_merge_button_when_succeed=(當通éŽæª¢æŸ¥å¾Œ)
pulls.auto_merge_when_succeed=通éŽæ‰€æœ‰æª¢æŸ¥å¾Œè‡ªå‹•åˆä½µ
@@ -1801,6 +1851,7 @@ settings.mirror_sync_in_progress=é¡åƒåŒæ­¥æ­£åœ¨é€²è¡Œä¸­ã€‚ è«‹ç¨å¾Œå†å›žä
settings.site=網站
settings.update_settings=更新設定
settings.branches.update_default_branch=æ›´æ–°é è¨­åˆ†æ”¯
+settings.branches.add_new_rule=加入新è¦å‰‡
settings.advanced_settings=進階設定
settings.wiki_desc=啟用儲存庫 Wiki
settings.use_internal_wiki=使用內建 Wiki
@@ -1827,16 +1878,14 @@ settings.enable_timetracker=啟用時間追蹤
settings.allow_only_contributors_to_track_time=åªè®“è²¢ç»è€…追蹤時間
settings.pulls_desc=啟用儲存庫åˆä½µè«‹æ±‚
settings.pulls.ignore_whitespace=è¡çªæ™‚忽略空白
-settings.pulls.allow_merge_commits=啟用æ交åˆä½µ
-settings.pulls.allow_rebase_merge=啟用 Rebase åˆä½µæ交
-settings.pulls.allow_rebase_merge_commit=啟用 Rebase 顯å¼åˆä½µæ交(--no-ff)
-settings.pulls.allow_squash_commits=啟用 Squash åˆä½µæ交
-settings.pulls.allow_manual_merge=å…許將åˆä½µè«‹æ±‚標記為手動åˆä½µ
settings.pulls.enable_autodetect_manual_merge=啟用自動åµæ¸¬æ‰‹å‹•åˆä½µ (注æ„: 在æŸäº›ç‰¹æ®Šæƒ…æ³ä¸‹å¯èƒ½ç™¼ç”Ÿèª¤åˆ¤)
settings.pulls.allow_rebase_update=啟用é€éŽ Rebase æ›´æ–°åˆä½µè«‹æ±‚分支
settings.pulls.default_delete_branch_after_merge=é è¨­åœ¨åˆä½µå¾Œåˆªé™¤åˆä½µè«‹æ±‚分支
+settings.pulls.default_allow_edits_from_maintainers=é è¨­å…許維護者進行編輯
+settings.releases_desc=啟用儲存庫版本發佈
settings.packages_desc=啟用儲存庫套件註冊中心
settings.projects_desc=啟用儲存庫專案
+settings.actions_desc=啟用儲存庫 Actions
settings.admin_settings=管ç†å“¡è¨­å®š
settings.admin_enable_health_check=啟用儲存庫的å¥åº·æª¢æŸ¥ (git fsck)
settings.admin_code_indexer=程å¼ç¢¼ç´¢å¼•å™¨
@@ -2000,6 +2049,8 @@ settings.event_package=套件
settings.event_package_desc=套件已在儲存庫中建立或刪除。
settings.branch_filter=分支篩é¸
settings.branch_filter_desc=推é€ã€å»ºç«‹åˆ†æ”¯ã€åˆªé™¤åˆ†æ”¯äº‹ä»¶çš„白å單,請使用 glob 比å°æ¨¡å¼ã€‚如果留白或輸入<code>*</code>,所有分支的事件都會被回報。語法åƒè¦‹ <a href="https://pkg.go.dev/github.com/gobwas/glob#Compile">github.com/gobwas/glob</a>。範例:<code>master</code>, <code>{master,release*}</code>。
+settings.authorization_header=Authorization 標頭
+settings.authorization_header_desc=存在時將將包å«æ­¤ Authorization 標頭在請求中。例: %s。
settings.active=啟用
settings.active_helper=觸發事件的資訊將會被é€åˆ°æ­¤ Webhook URL。
settings.add_hook_success=Webhook 新增æˆåŠŸï¼
@@ -2044,6 +2095,8 @@ settings.deploy_key_deletion_desc=移除部署金鑰將拒絕它存å–此儲存å
settings.deploy_key_deletion_success=部署金鑰已移除。
settings.branches=分支
settings.protected_branch=分支ä¿è­·
+settings.protected_branch.save_rule=儲存è¦å‰‡
+settings.protected_branch.delete_rule=刪除è¦å‰‡
settings.protected_branch_can_push=å…許推é€ï¼Ÿ
settings.protected_branch_can_push_yes=ä½ å¯ä»¥æŽ¨é€
settings.protected_branch_can_push_no=ä½ ä¸èƒ½æŽ¨é€
@@ -2078,6 +2131,7 @@ settings.dismiss_stale_approvals=æ¨æ£„éŽæ™‚çš„æ ¸å¯
settings.dismiss_stale_approvals_desc=當新的æ交有修改到åˆä½µè«‹æ±‚的內容,並被推é€åˆ°æ­¤åˆ†æ”¯æ™‚,將æ¨æ£„舊的核å¯ã€‚
settings.require_signed_commits=僅接å—經簽署的æ交
settings.require_signed_commits_desc=拒絕未經簽署或未經驗證的æ交推é€åˆ°æ­¤åˆ†æ”¯ã€‚
+settings.protect_branch_name_pattern=å—ä¿è­·çš„分支å稱模å¼
settings.protect_protected_file_patterns=å—ä¿è­·çš„æª”æ¡ˆæ¨¡å¼ (以分號å€éš”「\;ã€):
settings.protect_protected_file_patterns_desc=å³ä¾¿ä½¿ç”¨è€…有權é™æ–°å¢žã€ä¿®æ”¹ã€åˆªé™¤æ­¤åˆ†æ”¯çš„檔案,ä»ä¸å…許直接修改å—ä¿è­·çš„檔案。å¯ä»¥ç”¨åŠå½¢åˆ†è™Ÿã€Œ\;ã€åˆ†éš”多個模å¼ã€‚è«‹æ–¼<a href="https://pkg.go.dev/github.com/gobwas/glob#Compile">github.com/gobwas/glob</a> 文件查看模å¼æ ¼å¼ã€‚範例:<code>.drone.yml</code>, <code>/docs/**/*.txt</code>。
settings.protect_unprotected_file_patterns=未å—ä¿è­·çš„æª”æ¡ˆæ¨¡å¼ (以分號å€éš”「\;ã€):
@@ -2086,6 +2140,7 @@ settings.add_protected_branch=啟用ä¿è­·
settings.delete_protected_branch=åœç”¨ä¿è­·
settings.update_protect_branch_success=已更新「%sã€çš„分支ä¿è­·ã€‚
settings.remove_protected_branch_success=å·²åœç”¨ã€Œ%sã€çš„分支ä¿è­·ã€‚
+settings.remove_protected_branch_failed=刪除分支ä¿è­·è¦å‰‡ã€Œ%sã€å¤±æ•—。
settings.protected_branch_deletion=åœç”¨åˆ†æ”¯ä¿è­·
settings.protected_branch_deletion_desc=åœç”¨åˆ†æ”¯ä¿è­·å°‡å…許有寫入權é™çš„使用者推é€è‡³è©²åˆ†æ”¯ï¼Œæ˜¯å¦ç¹¼çºŒï¼Ÿ
settings.block_rejected_reviews=有退回的審核時阻擋åˆä½µ
@@ -2095,10 +2150,13 @@ settings.block_on_official_review_requests_desc=如果有官方的審核請求æ™
settings.block_outdated_branch=如果åˆä½µè«‹æ±‚已經éŽæ™‚則阻擋åˆä½µ
settings.block_outdated_branch_desc=當 head 分支è½å¾Œæ–¼åŸºç¤Žåˆ†æ”¯æ™‚ä¸å¾—åˆä½µã€‚
settings.default_branch_desc=è«‹é¸æ“‡ç”¨ä¾†æ交程å¼ç¢¼å’Œåˆä½µè«‹æ±‚çš„é è¨­åˆ†æ”¯ã€‚
-settings.default_merge_style_desc=åˆä½µè«‹æ±‚çš„é è¨­æ–¹å¼ï¼š
+settings.merge_style_desc=åˆä½µæ–¹å¼
+settings.default_merge_style_desc=é è¨­åˆä½µæ–¹å¼
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=標籤ä¿è­·
@@ -2114,7 +2172,6 @@ settings.bot_token=Bot Token
settings.chat_id=Chat ID
settings.matrix.homeserver_url=Homeserver 網å€
settings.matrix.room_id=èŠå¤©å®¤ ID
-settings.matrix.access_token=Access Token
settings.matrix.message_type=訊æ¯é¡žåž‹
settings.archive.button=å°å­˜å„²å­˜åº«
settings.archive.header=å°å­˜æœ¬å„²å­˜åº«
@@ -2231,7 +2288,7 @@ release.new_subheader=發布ã€æ•´ç†å°ˆæ¡ˆçš„版本。
release.edit_subheader=發布ã€æ•´ç†å°ˆæ¡ˆçš„版本。
release.tag_name=標籤å稱
release.target=目標分支
-release.tag_helper=新增或é¸æ“‡æ—¢æœ‰çš„標籤。
+release.tag_helper=新增或é¸æ“‡ç¾æœ‰çš„標籤。
release.title=標題
release.content=內容
release.prerelease_desc=標記為 Pre-Release
@@ -2255,6 +2312,8 @@ release.downloads=下載附件
release.download_count=下載次數:%s
release.add_tag_msg=使用此版本的標題和內容作為標籤訊æ¯ã€‚
release.add_tag=åªå»ºç«‹æ¨™ç±¤
+release.releases_for=%s 的版本發佈
+release.tags_for=%s 的標籤
branch.name=分支å稱
branch.search=æœå°‹åˆ†æ”¯
@@ -2313,7 +2372,7 @@ org_full_name_holder=組織全å
org_name_helper=組織å稱應該è¦ç°¡çŸ­ä¸”方便記憶
create_org=建立組織
repo_updated=æ›´æ–°æ–¼
-people=æˆå“¡
+members=æˆå“¡
teams=團隊
code=程å¼ç¢¼
lower_members=åæˆå“¡
@@ -2384,7 +2443,7 @@ teams.leave.detail=確定è¦é›¢é–‹ %s 嗎?
teams.can_create_org_repo=建立儲存庫
teams.can_create_org_repo_helper=æˆå“¡å¯ä»¥åœ¨çµ„織中新增儲存庫。建立者將自動å–得新儲存庫的管ç†å“¡æ¬Šé™ã€‚
teams.none_access=沒有權é™
-teams.none_access_helper=æˆå“¡ç„¡æ³•æª¢è¦–此單元或å°å…¶åŸ·è¡Œå…¶ä»–動作。
+teams.none_access_helper=æˆå“¡ç„¡æ³•æª¢è¦–此單元或å°å…¶åŸ·è¡Œå…¶ä»–動作,這å°å…¬é–‹å„²å­˜åº«æ²’有影響。
teams.general_access=一般權é™
teams.general_access_helper=æˆå“¡æ¬Šé™å°‡ç”±ä¸‹åˆ—權é™è¡¨æ±ºå®šã€‚
teams.read_access=讀å–
@@ -2400,6 +2459,8 @@ teams.members=團隊æˆå“¡
teams.update_settings=更新設定
teams.delete_team=刪除團隊
teams.add_team_member=增加團隊æˆå“¡
+teams.invite_team_member=邀請至 %s
+teams.invite_team_member.list=待處ç†çš„邀請
teams.delete_team_title=刪除團隊
teams.delete_team_desc=刪除團隊將會撤銷æˆå“¡çš„儲存庫存å–權,是å¦ç¹¼çºŒï¼Ÿ
teams.delete_team_success=該團隊已被刪除。
@@ -2424,6 +2485,9 @@ teams.all_repositories_helper=團隊æ“有å¯å­˜å–所有儲存庫。é¸æ“‡æ­¤é
teams.all_repositories_read_permission_desc=這個團隊æ“有<strong>所有儲存庫</strong>çš„<strong>讀å–</strong> 權é™ï¼šæˆå“¡å¯ä»¥æŸ¥çœ‹å’Œ Clone 儲存庫。
teams.all_repositories_write_permission_desc=這個團隊æ“有<strong>所有儲存庫</strong>çš„<strong>寫入</strong> 權é™ï¼šæˆå“¡å¯ä»¥è®€å–和推é€åˆ°å„²å­˜åº«ã€‚
teams.all_repositories_admin_permission_desc=這個團隊æ“有<strong>所有儲存庫</strong>çš„<strong>管ç†å“¡</strong> 權é™ï¼šæˆå“¡å¯ä»¥è®€å–ã€æŽ¨é€å’Œå¢žåŠ å”作者到儲存庫。
+teams.invite.title=您正å—邀加入組織 <strong>%[2]s</strong> 中的 <strong>%[1]s</strong> 團隊。
+teams.invite.by=邀請人 %s
+teams.invite.description=請點擊下方按鈕加入團隊。
[admin]
dashboard=資訊主é 
@@ -2517,6 +2581,10 @@ dashboard.delete_old_actions=從資料庫刪除所有舊行為
dashboard.delete_old_actions.started=從資料庫刪除所有舊行為的任務已啟動。
dashboard.update_checker=更新檢查器
dashboard.delete_old_system_notices=從資料庫刪除所有舊系統æ示
+dashboard.gc_lfs=å° LFS meta objects 進行垃圾回收
+dashboard.stop_zombie_tasks=åœæ­¢æ®­å±ä»»å‹™
+dashboard.stop_endless_tasks=åœæ­¢æ°¸ä¸åœæ­¢çš„任務
+dashboard.cancel_abandoned_jobs=å–消已放棄的工作
users.user_manage_panel=使用者帳戶管ç†
users.new_account=建立使用者帳戶
@@ -2556,7 +2624,7 @@ users.still_own_repo=這個使用者還æ“有一個或更多的儲存庫。請å…
users.still_has_org=此使用者是組織的æˆå“¡ã€‚請先將他從組織中移除。
users.purge=清除使用者
users.purge_help=強制刪除使用者和他æ“有的所有儲存庫ã€çµ„ç¹”ã€å¥—件,所有留言也會被刪除。
-users.still_own_packages=此使用者æ“有一個或多個套件,請先刪除這些套件。
+users.still_own_packages=此使用者ä»ç„¶æ“有一個以上的套件,請先刪除這些套件。
users.deletion_success=使用者帳戶已被刪除。
users.reset_2fa=é‡è¨­å…©æ­¥é©Ÿé©—è­‰
users.list_status_filter.menu_text=篩é¸
@@ -2586,7 +2654,7 @@ emails.change_email_header=æ›´æ–°é›»å­ä¿¡ç®±å±¬æ€§
emails.change_email_text=您確定è¦æ›´æ–°é€™å€‹é›»å­ä¿¡ç®±ï¼Ÿ
orgs.org_manage_panel=組織管ç†
-orgs.name=組織å稱
+orgs.name=å稱
orgs.teams=團隊數
orgs.members=æˆå“¡æ•¸
orgs.new_orga=新增組織
@@ -2595,7 +2663,7 @@ repos.repo_manage_panel=儲存庫管ç†
repos.unadopted=未接管的儲存庫
repos.unadopted.no_more=找ä¸åˆ°å…¶ä»–未接管的儲存庫
repos.owner=æ“有者
-repos.name=儲存庫å稱
+repos.name=å稱
repos.private=ç§æœ‰
repos.watches=關注數
repos.stars=星號數
@@ -2605,6 +2673,7 @@ repos.size=大å°
packages.package_manage_panel=套件管ç†
packages.total_size=總大å°: %s
+packages.unreferenced_size=未åƒè€ƒå¤§å°: %s
packages.owner=æ“有者
packages.creator=建立者
packages.name=å稱
@@ -2626,8 +2695,8 @@ systemhooks.update_webhook=更新系統 Webhook
auths.auth_manage_panel=èªè­‰ä¾†æºç®¡ç†
auths.new=新增èªè­‰ä¾†æº
-auths.name=èªè­‰å稱
-auths.type=èªè­‰é¡žåž‹
+auths.name=å稱
+auths.type=é¡žåž‹
auths.enabled=已啟用
auths.syncenabled=啟用使用者åŒæ­¥
auths.updated=最後更新時間
@@ -2698,6 +2767,8 @@ auths.oauth2_required_claim_value_helper=填寫此å稱以é™åˆ¶ Claim 中有æ­
auths.oauth2_group_claim_name=Claim å稱æ供群組å稱給此來æºã€‚(é¸ç”¨)
auths.oauth2_admin_group=管ç†å“¡ä½¿ç”¨è€…的群組 Claim 值。(é¸ç”¨ - 需è¦ä¸Šé¢çš„ Claim å稱)
auths.oauth2_restricted_group=å—é™åˆ¶ä½¿ç”¨è€…的群組 Claim 值。(é¸ç”¨ - 需è¦ä¸Šé¢çš„ Claim å稱)
+auths.oauth2_map_group_to_team=將已 Claim 的群組å°æ‡‰åˆ°çµ„織團隊。(é¸ç”¨ - 需è¦ä¸Šè¿° Claim å稱)
+auths.oauth2_map_group_to_team_removal=如果使用者ä¸å±¬æ–¼ç›¸å°æ‡‰çš„群組,將使用者從已åŒæ­¥çš„團隊移除。
auths.enable_auto_register=å…許授權用戶自動註冊
auths.sspi_auto_create_users=自動建立使用者
auths.sspi_auto_create_users_helper=å…許 SSPI èªè­‰æ–¹æ³•æ–¼ä½¿ç”¨è€…首次登入時自動建立新帳戶
@@ -2778,7 +2849,7 @@ config.lfs_http_auth_expiry=LFS HTTP 驗證有效時間
config.db_config=資料庫組態
config.db_type=資料庫類型
config.db_host=主機地å€
-config.db_name=資料庫å稱
+config.db_name=å稱
config.db_user=使用者å稱
config.db_schema=çµæ§‹æè¿°
config.db_ssl_mode=SSL
@@ -2877,9 +2948,11 @@ config.access_log_template=範本
config.xorm_log_mode=XORM 日誌模å¼
config.xorm_log_sql=記錄 SQL
+config.get_setting_failed=讀å–設定值 %s 失敗
+config.set_setting_failed=寫入設定值 %s 失敗
monitor.cron=Cron 任務
-monitor.name=任務å稱
+monitor.name=å稱
monitor.schedule=任務安排
monitor.next=下次執行時間
monitor.previous=上次執行時間
@@ -2958,13 +3031,13 @@ monitor.queue.pool.cancel_desc=讓佇列沒有任何工作者群組å¯èƒ½é€ æˆè
notices.system_notice_list=系統æ示
notices.view_detail_header=查看æ示細節
-notices.actions=æ“作
+notices.operations=æ“作
notices.select_all=é¸å–全部
notices.deselect_all=å–消所有é¸å–
notices.inverse_selection=åå‘é¸å–
notices.delete_selected=刪除é¸å–é …
notices.delete_all=刪除所有æ示
-notices.type=æ示類型
+notices.type=é¡žåž‹
notices.type_1=儲存庫
notices.type_2=任務
notices.desc=æè¿°
@@ -2984,6 +3057,7 @@ reopen_pull_request=`é‡æ–°é–‹æ”¾äº†åˆä½µè«‹æ±‚ <a href="%[1]s">%[3]s#%[2]s</a>
comment_issue=`在å•é¡Œä¸Šç•™è¨€ <a href="%[1]s">%[3]s#%[2]s</a>`
comment_pull=`在åˆä½µè«‹æ±‚上留言 <a href="%[1]s">%[3]s#%[2]s</a>`
merge_pull_request=`åˆä½µäº†åˆä½µè«‹æ±‚ <a href="%[1]s">%[3]s#%[2]s</a>`
+auto_merge_pull_request=`自動åˆä½µäº†åˆä½µè«‹æ±‚ <a href="%[1]s">%[3]s#%[2]s</a>`
transfer_repo=將儲存庫 <code>%s</code> 轉移至 <a href="%s">%s</a>
push_tag=推é€äº†æ¨™ç±¤ <a href="%[2]s">%[3]s</a> 到 <a href="%[1]s">%[4]s</a>
delete_tag=刪除了 <a href="%[1]s">%[3]s</a> 的標籤 %[2]s
@@ -3082,6 +3156,8 @@ keywords=é—œéµå­—
details=詳情
details.author=作者
details.project_site=專案網站
+details.repository_site=儲存庫網站
+details.documentation_site=文件網站
details.license=授權æ¢æ¬¾
assets=檔案
versions=版本
@@ -3089,6 +3165,14 @@ versions.on=æ–¼
versions.view_all=檢視全部
dependency.id=ID
dependency.version=版本
+cargo.registry=在 Cargo 組態檔設定此註冊中心 (例如: <code>~/.cargo/config.toml</code>):
+cargo.install=執行下列命令以使用 Cargo 安è£æ­¤å¥—件:
+cargo.documentation=關於 Cargo registry 的詳情請åƒé–±<a target="_blank" rel="noopener noreferrer" href="https://docs.gitea.io/en-us/packages/cargo/">說明文件</a>。
+cargo.details.repository_site=儲存庫網站
+cargo.details.documentation_site=文件網站
+chef.registry=在您的 <code>~/.chef/config.rb</code> 檔設定此註冊中心:
+chef.install=執行下列命令安è£æ­¤å¥—件:
+chef.documentation=關於 Chef registry 的詳情請åƒé–±<a target="_blank" rel="noopener noreferrer" href="https://docs.gitea.io/en-us/packages/chef/">說明文件</a>。
composer.registry=在您的 <code>~/.composer/config.json</code> 檔設定此註冊中心:
composer.install=執行下列命令以使用 Composer 安è£æ­¤å¥—件:
composer.documentation=關於 Composer registry 的詳情請åƒé–±<a target="_blank" rel="noopener noreferrer" href="https://docs.gitea.io/en-us/packages/composer/">說明文件</a>。
@@ -3098,10 +3182,13 @@ conan.details.repository=儲存庫
conan.registry=é€éŽä¸‹åˆ—命令設定此註冊中心:
conan.install=執行下列命令以使用 Conan 安è£æ­¤å¥—件:
conan.documentation=關於 Conan registry 的詳情請åƒé–±<a target="_blank" rel="noopener noreferrer" href="https://docs.gitea.io/en-us/packages/conan/">說明文件</a>。
+conda.registry=在您的 <code>.condarc</code> 檔設定此註冊中心為 Conda 存儲庫:
+conda.install=執行下列命令以使用 Conda 安è£æ­¤å¥—件:
+conda.documentation=關於 Conda registry 的詳情請åƒé–±<a target="_blank" rel="noopener noreferrer" href="https://docs.gitea.io/en-us/packages/conda/">說明文件</a>。
+conda.details.repository_site=儲存庫網站
+conda.details.documentation_site=文件網站
container.details.type=映åƒæª”é¡žåž‹
container.details.platform=å¹³å°
-container.details.repository_site=儲存庫網站
-container.details.documentation_site=文件網站
container.pull=é€éŽä¸‹åˆ—命令拉å–映åƒæª”:
container.digest=摘è¦:
container.documentation=關於 Container registry 的詳情請åƒé–±<a target="_blank" rel="noopener noreferrer" href="https://docs.gitea.io/en-us/packages/container/">說明文件</a>。
@@ -3115,7 +3202,7 @@ generic.documentation=關於通用 registry 的詳情請åƒé–±<a target="_blank"
helm.registry=é€éŽä¸‹åˆ—命令設定此註冊中心:
helm.install=執行下列命令安è£æ­¤å¥—件:
helm.documentation=關於 Helm registry 的詳情請åƒé–±<a target="_blank" rel="noopener noreferrer" href="https://docs.gitea.io/en-us/packages/helm/">說明文件</a>。
-maven.registry=在您的 <code>pom.xml</code> 檔設定此註冊中心:
+maven.registry=在您專案的 <code>pom.xml</code> 檔設定此註冊中心:
maven.install=è‹¥è¦ä½¿ç”¨æ­¤å¥—件,請在您 <code>pom.xml</code> 檔的 <code>dependencies</code> 段è½åŠ å…¥ä¸‹åˆ—內容:
maven.install2=é€éŽä¸‹åˆ—命令執行:
maven.download=é€éŽä¸‹åˆ—命令下載相ä¾æ€§:
@@ -3124,7 +3211,7 @@ nuget.registry=é€éŽä¸‹åˆ—命令設定此註冊中心:
nuget.install=執行下列命令以使用 NuGet 安è£æ­¤å¥—件:
nuget.documentation=關於 NuGet registry 的詳情請åƒé–±<a target="_blank" rel="noopener noreferrer" href="https://docs.gitea.io/en-us/packages/nuget/">說明文件</a>。
nuget.dependency.framework=目標框架
-npm.registry=在您的 <code>.npmrc</code> 檔設定此註冊中心:
+npm.registry=在您專案的 <code>.npmrc</code> 檔設定此註冊中心:
npm.install=執行下列命令以使用 npm 安è£æ­¤å¥—件:
npm.install2=或將它加到 package.json 檔:
npm.documentation=關於 npm registry 的詳情請åƒé–±<a target="_blank" rel="noopener noreferrer" href="https://docs.gitea.io/en-us/packages/npm/">說明文件</a>。
@@ -3135,8 +3222,6 @@ npm.dependencies.optional=é¸ç”¨ç›¸ä¾æ€§
npm.details.tag=標籤
pub.install=執行下列命令以使用 Dart 安è£æ­¤å¥—件:
pub.documentation=關於 Pub registry 的詳情請åƒé–±<a target="_blank" rel="noopener noreferrer" href="https://docs.gitea.io/en-us/packages/pub/">說明文件</a>。
-pub.details.repository_site=儲存庫網站
-pub.details.documentation_site=文件網站
pypi.requires=éœ€è¦ Python
pypi.install=執行下列命令以使用 pip 安è£æ­¤å¥—件:
pypi.documentation=關於 PyPI registry 的詳情請åƒé–±<a target="_blank" rel="noopener noreferrer" href="https://docs.gitea.io/en-us/packages/pypi/">說明文件</a>。
@@ -3160,4 +3245,110 @@ settings.delete.description=刪除套件是永久且ä¸å¯é‚„原的。
settings.delete.notice=您正è¦åˆªé™¤ %s (%s),此動作是無法還原的,您確定嗎?
settings.delete.success=已刪除該套件。
settings.delete.error=刪除套件失敗。
+owner.settings.cargo.title=Cargo Registry 索引
+owner.settings.cargo.initialize=åˆå§‹åŒ–索引
+owner.settings.cargo.initialize.description=使用 Cargo Registry 時需è¦ä¸€å€‹ç‰¹åˆ¥çš„ Git 儲存庫作為索引。您å¯ä»¥åœ¨æ­¤ä½¿ç”¨å¿…è¦çš„設定建立和é‡å»ºå®ƒã€‚
+owner.settings.cargo.initialize.error=åˆå§‹åŒ– Cargo 索引失敗: %v
+owner.settings.cargo.initialize.success=æˆåŠŸå»ºç«‹äº† Cargo 索引。
+owner.settings.cargo.rebuild=é‡å»ºç´¢å¼•
+owner.settings.cargo.rebuild.description=如果索引和 Cargo 套件ä¸åŒæ­¥ï¼Œæ‚¨å¯åœ¨æ­¤é‡å»ºå®ƒã€‚
+owner.settings.cargo.rebuild.error=é‡å»º Cargo 索引失敗: %v
+owner.settings.cargo.rebuild.success=æˆåŠŸé‡å»ºäº† Cargo 索引。
+owner.settings.cleanuprules.title=管ç†æ¸…ç†è¦å‰‡
+owner.settings.cleanuprules.add=加入清ç†è¦å‰‡
+owner.settings.cleanuprules.edit=編輯清ç†è¦å‰‡
+owner.settings.cleanuprules.none=沒有å¯ç”¨çš„清ç†è¦å‰‡ã€‚閱讀文件以了解更多。
+owner.settings.cleanuprules.preview=清ç†è¦å‰‡é è¦½
+owner.settings.cleanuprules.preview.overview=已排定è¦ç§»é™¤ %d 個套件。
+owner.settings.cleanuprules.preview.none=清ç†è¦å‰‡ä¸ç¬¦åˆä»»ä½•å¥—件。
+owner.settings.cleanuprules.enabled=已啟用
+owner.settings.cleanuprules.pattern_full_match=將比å°è¦å‰‡å¥—用到完整的套件å稱
+owner.settings.cleanuprules.keep.title=符åˆé€™äº›è¦å‰‡çš„版本å³ä½¿ç¬¦åˆä¸‹é¢çš„刪除è¦å‰‡ä¹Ÿæœƒè¢«ä¿ç•™ã€‚
+owner.settings.cleanuprules.keep.count=ä¿ç•™æœ€æ–°çš„
+owner.settings.cleanuprules.keep.count.1=æ¯å€‹å¥—件 1 個版本
+owner.settings.cleanuprules.keep.count.n=æ¯å€‹å¥—件 %d 個版本
+owner.settings.cleanuprules.keep.pattern=ä¿ç•™ç‰ˆæœ¬çš„比å°è¦å‰‡
+owner.settings.cleanuprules.keep.pattern.container=Container 套件的<code>最新</code>版本總是會ä¿ç•™ã€‚
+owner.settings.cleanuprules.remove.title=符åˆé€™äº›è¦å‰‡çš„版本將被移除,除éžå‰è¿°çš„è¦å‰‡è¦æ±‚ä¿ç•™å®ƒå€‘。
+owner.settings.cleanuprules.remove.days=移除早於天數的版本
+owner.settings.cleanuprules.remove.pattern=移除版本的比å°è¦å‰‡
+owner.settings.cleanuprules.success.update=已更新清ç†è¦å‰‡ã€‚
+owner.settings.cleanuprules.success.delete=已刪除清ç†è¦å‰‡ã€‚
+owner.settings.chef.title=Chef Registry
+owner.settings.chef.keypair=產生密鑰組
+owner.settings.chef.keypair.description=產生用來èªè­‰ Chef Registry 的密鑰組,之å‰çš„密鑰未來將無法使用。
+
+[secrets]
+secrets=Secret
+description=Secret 會被傳給特定的 Action,其他情æ³ç„¡æ³•è®€å–。
+none=還沒有 Secret。
+value=值
+name=å稱
+creation=加入 Secret
+creation.name_placeholder=ä¸å€åˆ†å¤§å°å¯«ï¼Œåªèƒ½åŒ…å«è‹±æ–‡å­—æ¯ã€æ•¸å­—ã€åº•ç·š ('_'),ä¸èƒ½ä»¥ GITEA_ 或 GITHUB_ 開頭。
+creation.value_placeholder=輸入任何內容,頭尾的空白都會被忽略。
+creation.success=已加入 Secret「%sã€ã€‚
+creation.failed=加入 Secret 失敗。
+deletion=移除 Secret
+deletion.description=移除 Secret 是永久的且ä¸å¯é‚„原,是å¦ç¹¼çºŒï¼Ÿ
+deletion.success=已移除此 Secret。
+deletion.failed=移除 Secret 失敗。
+
+[actions]
+actions=Actions
+
+unit.desc=ç®¡ç† Actions
+
+status.unknown=未知
+status.waiting=正在等候
+status.running=正在執行
+status.success=æˆåŠŸ
+status.failure=失敗
+status.cancelled=å·²å–消
+status.skipped=已略éŽ
+status.blocked=已阻塞
+
+runners=Runner
+runners.runner_manage_panel=Runner 管ç†
+runners.new=建立 Runner
+runners.new_notice=如何啟動 Runner
+runners.status=狀態
+runners.id=ID
+runners.name=å稱
+runners.owner_type=é¡žåž‹
+runners.description=組織æè¿°
+runners.labels=標籤
+runners.last_online=最後上線時間
+runners.agent_labels=代ç†ç¨‹å¼æ¨™ç±¤
+runners.custom_labels=自訂標籤
+runners.custom_labels_helper=自訂標籤是由管ç†å“¡æ‰‹å‹•åŠ ä¸Šçš„標籤。標籤之間以åŠå½¢é€—號「,ã€åˆ†éš”,標籤頭尾的空白將被忽略。
+runners.runner_title=Runner
+runners.task_list=最近在此 Runner 上的任務
+runners.task_list.run=執行
+runners.task_list.status=狀態
+runners.task_list.repository=儲存庫
+runners.task_list.commit=æ交
+runners.task_list.done_at=完æˆæ–¼
+runners.edit_runner=編輯 Runner
+runners.update_runner=更新變更
+runners.update_runner_success=æ›´æ–° Runner æˆåŠŸ
+runners.update_runner_failed=更新 Runner 失敗
+runners.delete_runner=刪除此 Runner
+runners.delete_runner_success=刪除 Runner æˆåŠŸ
+runners.delete_runner_failed=刪除 Runner 失敗
+runners.delete_runner_header=確èªåˆªé™¤æ­¤ Runner
+runners.delete_runner_notice=如果有任務正在此 Runner 上執行,它å¯èƒ½æœƒè¢«ä¸­æ­¢ä¸¦æ¨™è¨˜ç‚ºå¤±æ•—,這å¯èƒ½æœƒæ‰“斷建置工作æµç¨‹ã€‚
+runners.none=沒有å¯ç”¨çš„ Runner
+runners.status.unspecified=未知
+runners.status.idle=é–’ç½®
+runners.status.active=啟用
+runners.status.offline=離線
+
+runs.all_workflows=所有工作æµç¨‹
+runs.open_tab=%d 開放中
+runs.closed_tab=%d 已關閉
+runs.commit=æ交
+runs.pushed_by=推é€è€…
+
+need_approval_desc=來自 Frok 儲存庫的åˆä½µè«‹æ±‚需è¦æ ¸å¯æ‰èƒ½åŸ·è¡Œå·¥ä½œæµç¨‹ã€‚
diff --git a/package-lock.json b/package-lock.json
index 641a42b84..7ec6d09d1 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -31,7 +31,7 @@
"less": "4.1.3",
"less-loader": "11.1.0",
"license-checker-webpack-plugin": "0.2.1",
- "mermaid": "9.3.0",
+ "mermaid": "10.0.2",
"mini-css-extract-plugin": "2.7.2",
"monaco-editor": "0.34.1",
"monaco-editor-webpack-plugin": "7.0.1",
@@ -2680,6 +2680,14 @@
"integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==",
"dev": true
},
+ "node_modules/cose-base": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/cose-base/-/cose-base-1.0.3.tgz",
+ "integrity": "sha512-s9whTXInMSgAp/NVXVNuVxVKzGH2qck3aQlVHxDCdAEPgtMKwc4Wq6/QKhgdEdgbLSi9rBTAcPoRa6JpiG4ksg==",
+ "dependencies": {
+ "layout-base": "^1.0.0"
+ }
+ },
"node_modules/cosmiconfig": {
"version": "8.0.0",
"resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-8.0.0.tgz",
@@ -2888,6 +2896,53 @@
"resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.1.tgz",
"integrity": "sha512-DJR/VvkAvSZW9bTouZue2sSxDwdTN92uHjqeKVm+0dAqdfNykRzQ95tay8aXMBAAPpUiq4Qcug2L7neoRh2Egw=="
},
+ "node_modules/cytoscape": {
+ "version": "3.23.0",
+ "resolved": "https://registry.npmjs.org/cytoscape/-/cytoscape-3.23.0.tgz",
+ "integrity": "sha512-gRZqJj/1kiAVPkrVFvz/GccxsXhF3Qwpptl32gKKypO4IlqnKBjTOu+HbXtEggSGzC5KCaHp3/F7GgENrtsFkA==",
+ "dependencies": {
+ "heap": "^0.2.6",
+ "lodash": "^4.17.21"
+ },
+ "engines": {
+ "node": ">=0.10"
+ }
+ },
+ "node_modules/cytoscape-cose-bilkent": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/cytoscape-cose-bilkent/-/cytoscape-cose-bilkent-4.1.0.tgz",
+ "integrity": "sha512-wgQlVIUJF13Quxiv5e1gstZ08rnZj2XaLHGoFMYXz7SkNfCDOOteKBE6SYRfA9WxxI/iBc3ajfDoc6hb/MRAHQ==",
+ "dependencies": {
+ "cose-base": "^1.0.0"
+ },
+ "peerDependencies": {
+ "cytoscape": "^3.2.0"
+ }
+ },
+ "node_modules/cytoscape-fcose": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/cytoscape-fcose/-/cytoscape-fcose-2.2.0.tgz",
+ "integrity": "sha512-ki1/VuRIHFCzxWNrsshHYPs6L7TvLu3DL+TyIGEsRcvVERmxokbf5Gdk7mFxZnTdiGtnA4cfSmjZJMviqSuZrQ==",
+ "dependencies": {
+ "cose-base": "^2.2.0"
+ },
+ "peerDependencies": {
+ "cytoscape": "^3.2.0"
+ }
+ },
+ "node_modules/cytoscape-fcose/node_modules/cose-base": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/cose-base/-/cose-base-2.2.0.tgz",
+ "integrity": "sha512-AzlgcsCbUMymkADOJtQm3wO9S3ltPfYOFD5033keQn9NJzIbtnZj+UdBJe7DYml/8TdbtHJW3j58SOnKhWY/5g==",
+ "dependencies": {
+ "layout-base": "^2.0.0"
+ }
+ },
+ "node_modules/cytoscape-fcose/node_modules/layout-base": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/layout-base/-/layout-base-2.0.1.tgz",
+ "integrity": "sha512-dp3s92+uNI1hWIpPGH3jK2kxE2lMjdXdr+DH8ynZHpd6PUlH6x6cbuXnoMmiNumznqaNO31xu9e79F0uuZ0JFg=="
+ },
"node_modules/d3": {
"version": "7.8.2",
"resolved": "https://registry.npmjs.org/d3/-/d3-7.8.2.tgz",
@@ -3267,11 +3322,11 @@
}
},
"node_modules/dagre-d3-es": {
- "version": "7.0.6",
- "resolved": "https://registry.npmjs.org/dagre-d3-es/-/dagre-d3-es-7.0.6.tgz",
- "integrity": "sha512-CaaE/nZh205ix+Up4xsnlGmpog5GGm81Upi2+/SBHxwNwrccBb3K51LzjZ1U6hgvOlAEUsVWf1xSTzCyKpJ6+Q==",
+ "version": "7.0.9",
+ "resolved": "https://registry.npmjs.org/dagre-d3-es/-/dagre-d3-es-7.0.9.tgz",
+ "integrity": "sha512-rYR4QfVmy+sR44IBDvVtcAmOReGBvRCWDpO2QjYwqgh9yijw6eSHBqaPG/LIOEy7aBsniLvtMW6pg19qJhq60w==",
"dependencies": {
- "d3": "^7.7.0",
+ "d3": "^7.8.2",
"lodash-es": "^4.17.21"
}
},
@@ -3298,6 +3353,11 @@
"node": ">=12"
}
},
+ "node_modules/dayjs": {
+ "version": "1.11.7",
+ "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.7.tgz",
+ "integrity": "sha512-+Yw9U6YO5TQohxLcIkrXBeY73WP3ejHWVvx8XCk3gxvQDCTEmS48ZrSZCKciI7Bhl/uCMyxYtE9UqRILmFphkQ=="
+ },
"node_modules/debug": {
"version": "4.3.4",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
@@ -3632,9 +3692,9 @@
}
},
"node_modules/dompurify": {
- "version": "2.4.1",
- "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-2.4.1.tgz",
- "integrity": "sha512-ewwFzHzrrneRjxzmK6oVz/rZn9VWspGFRDb4/rRtIsM1n36t9AKma/ye8syCpcw+XJ25kOK/hOG7t1j2I2yBqA=="
+ "version": "2.4.3",
+ "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-2.4.3.tgz",
+ "integrity": "sha512-q6QaLcakcRjebxjg8/+NP+h0rPfatOgOzc46Fst9VAA3jF2ApfKBNKMzdP4DYTqtUMXSCd5pRS/8Po/OmoCHZQ=="
},
"node_modules/domutils": {
"version": "3.0.1",
@@ -3681,6 +3741,11 @@
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.284.tgz",
"integrity": "sha512-M8WEXFuKXMYMVr45fo8mq0wUrrJHheiKZf6BArTKk9ZBYCKJEOU5H8cdWgDT+qCVZf7Na4lVUaZsA+h6uA9+PA=="
},
+ "node_modules/elkjs": {
+ "version": "0.8.2",
+ "resolved": "https://registry.npmjs.org/elkjs/-/elkjs-0.8.2.tgz",
+ "integrity": "sha512-L6uRgvZTH+4OF5NE/MBbzQx/WYpru1xCBE9respNj6qznEewGUIfhzmm7horWWxbNO2M0WckQypGctR8lH79xQ=="
+ },
"node_modules/emoji-regex": {
"version": "8.0.0",
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
@@ -5043,6 +5108,11 @@
"resolved": "https://registry.npmjs.org/hash-sum/-/hash-sum-2.0.0.tgz",
"integrity": "sha512-WdZTbAByD+pHfl/g9QSsBIIwy8IT+EsPiKDs0KNX+zSHhdDLFKdZu0BQHljvO+0QI/BasbMSUa8wYNCZTvhslg=="
},
+ "node_modules/heap": {
+ "version": "0.2.7",
+ "resolved": "https://registry.npmjs.org/heap/-/heap-0.2.7.tgz",
+ "integrity": "sha512-2bsegYkkHO+h/9MGbn6KWcE45cHZgPANo5LXF7EvWdT0yT2EguSVO1nDgU5c8+ZOPwp2vMNa7YFsJhVcDR9Sdg=="
+ },
"node_modules/hosted-git-info": {
"version": "2.8.9",
"resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz",
@@ -5877,6 +5947,11 @@
"integrity": "sha512-5FZRzrZzNTBruuurWpvZnvP9pum+fe0HcK8z/ooo+U+Hmp4vtbyp1/QDsqmufirXy4egGzbaH/y2uCZf+6W5Kg==",
"dev": true
},
+ "node_modules/layout-base": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/layout-base/-/layout-base-1.0.2.tgz",
+ "integrity": "sha512-8h2oVEZNktL4BH2JCOI90iD1yXwL6iNW7KcCKT2QZgQJR2vbqDsldCTPRU9NifTCqHZci57XvQQ15YTu+sTYPg=="
+ },
"node_modules/less": {
"version": "4.1.3",
"resolved": "https://registry.npmjs.org/less/-/less-4.1.3.tgz",
@@ -6049,8 +6124,7 @@
"node_modules/lodash": {
"version": "4.17.21",
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
- "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==",
- "dev": true
+ "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg=="
},
"node_modules/lodash-es": {
"version": "4.17.21",
@@ -6393,20 +6467,26 @@
}
},
"node_modules/mermaid": {
- "version": "9.3.0",
- "resolved": "https://registry.npmjs.org/mermaid/-/mermaid-9.3.0.tgz",
- "integrity": "sha512-mGl0BM19TD/HbU/LmlaZbjBi//tojelg8P/mxD6pPZTAYaI+VawcyBdqRsoUHSc7j71PrMdJ3HBadoQNdvP5cg==",
+ "version": "10.0.2",
+ "resolved": "https://registry.npmjs.org/mermaid/-/mermaid-10.0.2.tgz",
+ "integrity": "sha512-slwoB9WdNUT+/W9VhxLYRLZ0Ey12fIE+cAZjm3FmHTD+0F1uoJETfsNbVS1POnvQZhFYzfT6/z6hJZXgecqVBA==",
"dependencies": {
"@braintree/sanitize-url": "^6.0.0",
- "d3": "^7.0.0",
- "dagre-d3-es": "7.0.6",
- "dompurify": "2.4.1",
+ "cytoscape": "^3.23.0",
+ "cytoscape-cose-bilkent": "^4.1.0",
+ "cytoscape-fcose": "^2.1.0",
+ "d3": "^7.4.0",
+ "dagre-d3-es": "7.0.9",
+ "dayjs": "^1.11.7",
+ "dompurify": "2.4.3",
+ "elkjs": "^0.8.2",
"khroma": "^2.0.0",
"lodash-es": "^4.17.21",
- "moment-mini": "^2.24.0",
"non-layered-tidy-tree-layout": "^2.0.2",
"stylis": "^4.1.2",
- "uuid": "^9.0.0"
+ "ts-dedent": "^2.2.0",
+ "uuid": "^9.0.0",
+ "web-worker": "^1.2.0"
}
},
"node_modules/micromatch": {
@@ -6531,11 +6611,6 @@
"integrity": "sha512-nPdMG0Pd09HuSsr7QOKUXO2Jr9eqaDiZvDwdyIhNG5SHYujkQHYKDfGQkulBxvbDHz8oHLsTgKN86LSwYzSHAg==",
"dev": true
},
- "node_modules/moment-mini": {
- "version": "2.29.4",
- "resolved": "https://registry.npmjs.org/moment-mini/-/moment-mini-2.29.4.tgz",
- "integrity": "sha512-uhXpYwHFeiTbY9KSgPPRoo1nt8OxNVdMVoTBYHfSEKeRkIkwGpO+gERmhuhBtzfaeOyTkykSrm2+noJBgqt3Hg=="
- },
"node_modules/monaco-editor": {
"version": "0.34.1",
"resolved": "https://registry.npmjs.org/monaco-editor/-/monaco-editor-0.34.1.tgz",
@@ -8807,6 +8882,14 @@
"node": ">=8"
}
},
+ "node_modules/ts-dedent": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/ts-dedent/-/ts-dedent-2.2.0.tgz",
+ "integrity": "sha512-q5W7tVM71e2xjHZTlgfTDoPF/SmqKG5hddq9SzR49CH2hayqRKJtQ4mtRlSxKaJlR/+9rEM+mnBHf7I2/BQcpQ==",
+ "engines": {
+ "node": ">=6.10"
+ }
+ },
"node_modules/tsconfig-paths": {
"version": "3.14.1",
"resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.14.1.tgz",
@@ -9315,6 +9398,11 @@
"node": ">=10.13.0"
}
},
+ "node_modules/web-worker": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/web-worker/-/web-worker-1.2.0.tgz",
+ "integrity": "sha512-PgF341avzqyx60neE9DD+XS26MMNMoUQRz9NOZwW32nPQrF6p77f1htcnjBSEV8BGMKZ16choqUG4hyI0Hx7mA=="
+ },
"node_modules/webidl-conversions": {
"version": "7.0.0",
"resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz",
@@ -11774,6 +11862,14 @@
"integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==",
"dev": true
},
+ "cose-base": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/cose-base/-/cose-base-1.0.3.tgz",
+ "integrity": "sha512-s9whTXInMSgAp/NVXVNuVxVKzGH2qck3aQlVHxDCdAEPgtMKwc4Wq6/QKhgdEdgbLSi9rBTAcPoRa6JpiG4ksg==",
+ "requires": {
+ "layout-base": "^1.0.0"
+ }
+ },
"cosmiconfig": {
"version": "8.0.0",
"resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-8.0.0.tgz",
@@ -11937,6 +12033,46 @@
"resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.1.tgz",
"integrity": "sha512-DJR/VvkAvSZW9bTouZue2sSxDwdTN92uHjqeKVm+0dAqdfNykRzQ95tay8aXMBAAPpUiq4Qcug2L7neoRh2Egw=="
},
+ "cytoscape": {
+ "version": "3.23.0",
+ "resolved": "https://registry.npmjs.org/cytoscape/-/cytoscape-3.23.0.tgz",
+ "integrity": "sha512-gRZqJj/1kiAVPkrVFvz/GccxsXhF3Qwpptl32gKKypO4IlqnKBjTOu+HbXtEggSGzC5KCaHp3/F7GgENrtsFkA==",
+ "requires": {
+ "heap": "^0.2.6",
+ "lodash": "^4.17.21"
+ }
+ },
+ "cytoscape-cose-bilkent": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/cytoscape-cose-bilkent/-/cytoscape-cose-bilkent-4.1.0.tgz",
+ "integrity": "sha512-wgQlVIUJF13Quxiv5e1gstZ08rnZj2XaLHGoFMYXz7SkNfCDOOteKBE6SYRfA9WxxI/iBc3ajfDoc6hb/MRAHQ==",
+ "requires": {
+ "cose-base": "^1.0.0"
+ }
+ },
+ "cytoscape-fcose": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/cytoscape-fcose/-/cytoscape-fcose-2.2.0.tgz",
+ "integrity": "sha512-ki1/VuRIHFCzxWNrsshHYPs6L7TvLu3DL+TyIGEsRcvVERmxokbf5Gdk7mFxZnTdiGtnA4cfSmjZJMviqSuZrQ==",
+ "requires": {
+ "cose-base": "^2.2.0"
+ },
+ "dependencies": {
+ "cose-base": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/cose-base/-/cose-base-2.2.0.tgz",
+ "integrity": "sha512-AzlgcsCbUMymkADOJtQm3wO9S3ltPfYOFD5033keQn9NJzIbtnZj+UdBJe7DYml/8TdbtHJW3j58SOnKhWY/5g==",
+ "requires": {
+ "layout-base": "^2.0.0"
+ }
+ },
+ "layout-base": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/layout-base/-/layout-base-2.0.1.tgz",
+ "integrity": "sha512-dp3s92+uNI1hWIpPGH3jK2kxE2lMjdXdr+DH8ynZHpd6PUlH6x6cbuXnoMmiNumznqaNO31xu9e79F0uuZ0JFg=="
+ }
+ }
+ },
"d3": {
"version": "7.8.2",
"resolved": "https://registry.npmjs.org/d3/-/d3-7.8.2.tgz",
@@ -12208,11 +12344,11 @@
}
},
"dagre-d3-es": {
- "version": "7.0.6",
- "resolved": "https://registry.npmjs.org/dagre-d3-es/-/dagre-d3-es-7.0.6.tgz",
- "integrity": "sha512-CaaE/nZh205ix+Up4xsnlGmpog5GGm81Upi2+/SBHxwNwrccBb3K51LzjZ1U6hgvOlAEUsVWf1xSTzCyKpJ6+Q==",
+ "version": "7.0.9",
+ "resolved": "https://registry.npmjs.org/dagre-d3-es/-/dagre-d3-es-7.0.9.tgz",
+ "integrity": "sha512-rYR4QfVmy+sR44IBDvVtcAmOReGBvRCWDpO2QjYwqgh9yijw6eSHBqaPG/LIOEy7aBsniLvtMW6pg19qJhq60w==",
"requires": {
- "d3": "^7.7.0",
+ "d3": "^7.8.2",
"lodash-es": "^4.17.21"
}
},
@@ -12233,6 +12369,11 @@
"whatwg-url": "^11.0.0"
}
},
+ "dayjs": {
+ "version": "1.11.7",
+ "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.7.tgz",
+ "integrity": "sha512-+Yw9U6YO5TQohxLcIkrXBeY73WP3ejHWVvx8XCk3gxvQDCTEmS48ZrSZCKciI7Bhl/uCMyxYtE9UqRILmFphkQ=="
+ },
"debug": {
"version": "4.3.4",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
@@ -12472,9 +12613,9 @@
}
},
"dompurify": {
- "version": "2.4.1",
- "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-2.4.1.tgz",
- "integrity": "sha512-ewwFzHzrrneRjxzmK6oVz/rZn9VWspGFRDb4/rRtIsM1n36t9AKma/ye8syCpcw+XJ25kOK/hOG7t1j2I2yBqA=="
+ "version": "2.4.3",
+ "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-2.4.3.tgz",
+ "integrity": "sha512-q6QaLcakcRjebxjg8/+NP+h0rPfatOgOzc46Fst9VAA3jF2ApfKBNKMzdP4DYTqtUMXSCd5pRS/8Po/OmoCHZQ=="
},
"domutils": {
"version": "3.0.1",
@@ -12518,6 +12659,11 @@
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.284.tgz",
"integrity": "sha512-M8WEXFuKXMYMVr45fo8mq0wUrrJHheiKZf6BArTKk9ZBYCKJEOU5H8cdWgDT+qCVZf7Na4lVUaZsA+h6uA9+PA=="
},
+ "elkjs": {
+ "version": "0.8.2",
+ "resolved": "https://registry.npmjs.org/elkjs/-/elkjs-0.8.2.tgz",
+ "integrity": "sha512-L6uRgvZTH+4OF5NE/MBbzQx/WYpru1xCBE9respNj6qznEewGUIfhzmm7horWWxbNO2M0WckQypGctR8lH79xQ=="
+ },
"emoji-regex": {
"version": "8.0.0",
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
@@ -13548,6 +13694,11 @@
"resolved": "https://registry.npmjs.org/hash-sum/-/hash-sum-2.0.0.tgz",
"integrity": "sha512-WdZTbAByD+pHfl/g9QSsBIIwy8IT+EsPiKDs0KNX+zSHhdDLFKdZu0BQHljvO+0QI/BasbMSUa8wYNCZTvhslg=="
},
+ "heap": {
+ "version": "0.2.7",
+ "resolved": "https://registry.npmjs.org/heap/-/heap-0.2.7.tgz",
+ "integrity": "sha512-2bsegYkkHO+h/9MGbn6KWcE45cHZgPANo5LXF7EvWdT0yT2EguSVO1nDgU5c8+ZOPwp2vMNa7YFsJhVcDR9Sdg=="
+ },
"hosted-git-info": {
"version": "2.8.9",
"resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz",
@@ -14129,6 +14280,11 @@
"integrity": "sha512-5FZRzrZzNTBruuurWpvZnvP9pum+fe0HcK8z/ooo+U+Hmp4vtbyp1/QDsqmufirXy4egGzbaH/y2uCZf+6W5Kg==",
"dev": true
},
+ "layout-base": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/layout-base/-/layout-base-1.0.2.tgz",
+ "integrity": "sha512-8h2oVEZNktL4BH2JCOI90iD1yXwL6iNW7KcCKT2QZgQJR2vbqDsldCTPRU9NifTCqHZci57XvQQ15YTu+sTYPg=="
+ },
"less": {
"version": "4.1.3",
"resolved": "https://registry.npmjs.org/less/-/less-4.1.3.tgz",
@@ -14251,8 +14407,7 @@
"lodash": {
"version": "4.17.21",
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
- "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==",
- "dev": true
+ "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg=="
},
"lodash-es": {
"version": "4.17.21",
@@ -14531,20 +14686,26 @@
"integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg=="
},
"mermaid": {
- "version": "9.3.0",
- "resolved": "https://registry.npmjs.org/mermaid/-/mermaid-9.3.0.tgz",
- "integrity": "sha512-mGl0BM19TD/HbU/LmlaZbjBi//tojelg8P/mxD6pPZTAYaI+VawcyBdqRsoUHSc7j71PrMdJ3HBadoQNdvP5cg==",
+ "version": "10.0.2",
+ "resolved": "https://registry.npmjs.org/mermaid/-/mermaid-10.0.2.tgz",
+ "integrity": "sha512-slwoB9WdNUT+/W9VhxLYRLZ0Ey12fIE+cAZjm3FmHTD+0F1uoJETfsNbVS1POnvQZhFYzfT6/z6hJZXgecqVBA==",
"requires": {
"@braintree/sanitize-url": "^6.0.0",
- "d3": "^7.0.0",
- "dagre-d3-es": "7.0.6",
- "dompurify": "2.4.1",
+ "cytoscape": "^3.23.0",
+ "cytoscape-cose-bilkent": "^4.1.0",
+ "cytoscape-fcose": "^2.1.0",
+ "d3": "^7.4.0",
+ "dagre-d3-es": "7.0.9",
+ "dayjs": "^1.11.7",
+ "dompurify": "2.4.3",
+ "elkjs": "^0.8.2",
"khroma": "^2.0.0",
"lodash-es": "^4.17.21",
- "moment-mini": "^2.24.0",
"non-layered-tidy-tree-layout": "^2.0.2",
"stylis": "^4.1.2",
- "uuid": "^9.0.0"
+ "ts-dedent": "^2.2.0",
+ "uuid": "^9.0.0",
+ "web-worker": "^1.2.0"
}
},
"micromatch": {
@@ -14634,11 +14795,6 @@
}
}
},
- "moment-mini": {
- "version": "2.29.4",
- "resolved": "https://registry.npmjs.org/moment-mini/-/moment-mini-2.29.4.tgz",
- "integrity": "sha512-uhXpYwHFeiTbY9KSgPPRoo1nt8OxNVdMVoTBYHfSEKeRkIkwGpO+gERmhuhBtzfaeOyTkykSrm2+noJBgqt3Hg=="
- },
"monaco-editor": {
"version": "0.34.1",
"resolved": "https://registry.npmjs.org/monaco-editor/-/monaco-editor-0.34.1.tgz",
@@ -16340,6 +16496,11 @@
"integrity": "sha512-c1PTsA3tYrIsLGkJkzHF+w9F2EyxfXGo4UyJc4pFL++FMjnq0HJS69T3M7d//gKrFKwy429bouPescbjecU+Zw==",
"dev": true
},
+ "ts-dedent": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/ts-dedent/-/ts-dedent-2.2.0.tgz",
+ "integrity": "sha512-q5W7tVM71e2xjHZTlgfTDoPF/SmqKG5hddq9SzR49CH2hayqRKJtQ4mtRlSxKaJlR/+9rEM+mnBHf7I2/BQcpQ=="
+ },
"tsconfig-paths": {
"version": "3.14.1",
"resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.14.1.tgz",
@@ -16674,6 +16835,11 @@
"graceful-fs": "^4.1.2"
}
},
+ "web-worker": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/web-worker/-/web-worker-1.2.0.tgz",
+ "integrity": "sha512-PgF341avzqyx60neE9DD+XS26MMNMoUQRz9NOZwW32nPQrF6p77f1htcnjBSEV8BGMKZ16choqUG4hyI0Hx7mA=="
+ },
"webidl-conversions": {
"version": "7.0.0",
"resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz",
diff --git a/package.json b/package.json
index fc063d66d..c4457fe97 100644
--- a/package.json
+++ b/package.json
@@ -31,7 +31,7 @@
"less": "4.1.3",
"less-loader": "11.1.0",
"license-checker-webpack-plugin": "0.2.1",
- "mermaid": "9.3.0",
+ "mermaid": "10.0.2",
"mini-css-extract-plugin": "2.7.2",
"monaco-editor": "0.34.1",
"monaco-editor-webpack-plugin": "7.0.1",
diff --git a/routers/api/actions/runner/runner.go b/routers/api/actions/runner/runner.go
index 7dbab9da0..07657c912 100644
--- a/routers/api/actions/runner/runner.go
+++ b/routers/api/actions/runner/runner.go
@@ -12,6 +12,7 @@ import (
"code.gitea.io/gitea/modules/actions"
"code.gitea.io/gitea/modules/json"
"code.gitea.io/gitea/modules/log"
+ "code.gitea.io/gitea/modules/util"
actions_service "code.gitea.io/gitea/services/actions"
runnerv1 "code.gitea.io/actions-proto-go/runner/v1"
@@ -51,13 +52,14 @@ func (s *Service) Register(
}
if runnerToken.IsActive {
- return nil, errors.New("runner token has already activated")
+ return nil, errors.New("runner token has already been activated")
}
// create new runner
+ name, _ := util.SplitStringAtByteN(req.Msg.Name, 255)
runner := &actions_model.ActionRunner{
UUID: gouuid.New().String(),
- Name: req.Msg.Name,
+ Name: name,
OwnerID: runnerToken.OwnerID,
RepoID: runnerToken.RepoID,
AgentLabels: req.Msg.AgentLabels,
@@ -148,7 +150,7 @@ func (s *Service) UpdateTask(
}
if err := actions_service.CreateCommitStatus(ctx, task.Job); err != nil {
- log.Error("Update commit status failed: %v", err)
+ log.Error("Update commit status for job %v failed: %v", task.Job.ID, err)
// go on
}
diff --git a/routers/api/v1/activitypub/create.go b/routers/api/v1/activitypub/create.go
index b8f005970..591671c0c 100644
--- a/routers/api/v1/activitypub/create.go
+++ b/routers/api/v1/activitypub/create.go
@@ -142,7 +142,7 @@ func createRepository(ctx context.Context, repository *forgefed.Repository) erro
return err
}
- repo, err := repo_service.CreateRepository(user, user, repo_module.CreateRepoOptions{
+ repo, err := repo_service.CreateRepository(ctx, user, user, repo_module.CreateRepoOptions{
Name: repository.Name.String(),
OriginalURL: repository.GetLink().String(),
})
diff --git a/routers/api/v1/admin/adopt.go b/routers/api/v1/admin/adopt.go
index 0e4e498e9..47fd0ef3c 100644
--- a/routers/api/v1/admin/adopt.go
+++ b/routers/api/v1/admin/adopt.go
@@ -45,7 +45,7 @@ func ListUnadoptedRepositories(ctx *context.APIContext) {
if listOptions.Page == 0 {
listOptions.Page = 1
}
- repoNames, count, err := repo_service.ListUnadoptedRepositories(ctx.FormString("query"), &listOptions)
+ repoNames, count, err := repo_service.ListUnadoptedRepositories(ctx, ctx.FormString("query"), &listOptions)
if err != nil {
ctx.InternalServerError(err)
return
@@ -109,7 +109,7 @@ func AdoptRepository(ctx *context.APIContext) {
ctx.NotFound()
return
}
- if _, err := repo_service.AdoptRepository(ctx.Doer, ctxUser, repo_module.CreateRepoOptions{
+ if _, err := repo_service.AdoptRepository(ctx, ctx.Doer, ctxUser, repo_module.CreateRepoOptions{
Name: repoName,
IsPrivate: true,
}); err != nil {
@@ -172,7 +172,7 @@ func DeleteUnadoptedRepository(ctx *context.APIContext) {
return
}
- if err := repo_service.DeleteUnadoptedRepository(ctx.Doer, ctxUser, repoName); err != nil {
+ if err := repo_service.DeleteUnadoptedRepository(ctx, ctx.Doer, ctxUser, repoName); err != nil {
ctx.InternalServerError(err)
return
}
diff --git a/routers/api/v1/admin/hooks.go b/routers/api/v1/admin/hooks.go
index 2aed4139f..8264503c9 100644
--- a/routers/api/v1/admin/hooks.go
+++ b/routers/api/v1/admin/hooks.go
@@ -105,10 +105,7 @@ func CreateHook(ctx *context.APIContext) {
// "$ref": "#/responses/Hook"
form := web.GetForm(ctx).(*api.CreateHookOption)
- // TODO in body params
- if !utils.CheckCreateHookOption(ctx, form) {
- return
- }
+
utils.AddSystemHook(ctx, form)
}
diff --git a/routers/api/v1/api.go b/routers/api/v1/api.go
index 861c17175..e1f34199a 100644
--- a/routers/api/v1/api.go
+++ b/routers/api/v1/api.go
@@ -848,6 +848,13 @@ func Routes(ctx gocontext.Context) *web.Route {
m.Get("/stopwatches", reqToken(auth_model.AccessTokenScopeRepo), repo.GetStopwatches)
m.Get("/subscriptions", reqToken(auth_model.AccessTokenScopeRepo), user.GetMyWatchedRepos)
m.Get("/teams", reqToken(auth_model.AccessTokenScopeRepo), org.ListUserTeams)
+ m.Group("/hooks", func() {
+ m.Combo("").Get(user.ListHooks).
+ Post(bind(api.CreateHookOption{}), user.CreateHook)
+ m.Combo("/{id}").Get(user.GetHook).
+ Patch(bind(api.EditHookOption{}), user.EditHook).
+ Delete(user.DeleteHook)
+ }, reqToken(auth_model.AccessTokenScopeAdminUserHook), reqWebhooksEnabled())
}, reqToken(""))
// Repositories
diff --git a/routers/api/v1/org/hook.go b/routers/api/v1/org/hook.go
index 4e435c959..a6ea618a7 100644
--- a/routers/api/v1/org/hook.go
+++ b/routers/api/v1/org/hook.go
@@ -6,7 +6,6 @@ package org
import (
"net/http"
- webhook_model "code.gitea.io/gitea/models/webhook"
"code.gitea.io/gitea/modules/context"
api "code.gitea.io/gitea/modules/structs"
"code.gitea.io/gitea/modules/web"
@@ -39,34 +38,10 @@ func ListHooks(ctx *context.APIContext) {
// "200":
// "$ref": "#/responses/HookList"
- opts := &webhook_model.ListWebhookOptions{
- ListOptions: utils.GetListOptions(ctx),
- OrgID: ctx.Org.Organization.ID,
- }
-
- count, err := webhook_model.CountWebhooksByOpts(opts)
- if err != nil {
- ctx.InternalServerError(err)
- return
- }
-
- orgHooks, err := webhook_model.ListWebhooksByOpts(ctx, opts)
- if err != nil {
- ctx.InternalServerError(err)
- return
- }
-
- hooks := make([]*api.Hook, len(orgHooks))
- for i, hook := range orgHooks {
- hooks[i], err = webhook_service.ToHook(ctx.Org.Organization.AsUser().HomeLink(), hook)
- if err != nil {
- ctx.InternalServerError(err)
- return
- }
- }
-
- ctx.SetTotalCountHeader(count)
- ctx.JSON(http.StatusOK, hooks)
+ utils.ListOwnerHooks(
+ ctx,
+ ctx.ContextUser,
+ )
}
// GetHook get an organization's hook by id
@@ -92,14 +67,12 @@ func GetHook(ctx *context.APIContext) {
// "200":
// "$ref": "#/responses/Hook"
- org := ctx.Org.Organization
- hookID := ctx.ParamsInt64(":id")
- hook, err := utils.GetOrgHook(ctx, org.ID, hookID)
+ hook, err := utils.GetOwnerHook(ctx, ctx.ContextUser.ID, ctx.ParamsInt64("id"))
if err != nil {
return
}
- apiHook, err := webhook_service.ToHook(org.AsUser().HomeLink(), hook)
+ apiHook, err := webhook_service.ToHook(ctx.ContextUser.HomeLink(), hook)
if err != nil {
ctx.InternalServerError(err)
return
@@ -131,15 +104,14 @@ func CreateHook(ctx *context.APIContext) {
// "201":
// "$ref": "#/responses/Hook"
- form := web.GetForm(ctx).(*api.CreateHookOption)
- // TODO in body params
- if !utils.CheckCreateHookOption(ctx, form) {
- return
- }
- utils.AddOrgHook(ctx, form)
+ utils.AddOwnerHook(
+ ctx,
+ ctx.ContextUser,
+ web.GetForm(ctx).(*api.CreateHookOption),
+ )
}
-// EditHook modify a hook of a repository
+// EditHook modify a hook of an organization
func EditHook(ctx *context.APIContext) {
// swagger:operation PATCH /orgs/{org}/hooks/{id} organization orgEditHook
// ---
@@ -168,11 +140,12 @@ func EditHook(ctx *context.APIContext) {
// "200":
// "$ref": "#/responses/Hook"
- form := web.GetForm(ctx).(*api.EditHookOption)
-
- // TODO in body params
- hookID := ctx.ParamsInt64(":id")
- utils.EditOrgHook(ctx, form, hookID)
+ utils.EditOwnerHook(
+ ctx,
+ ctx.ContextUser,
+ web.GetForm(ctx).(*api.EditHookOption),
+ ctx.ParamsInt64("id"),
+ )
}
// DeleteHook delete a hook of an organization
@@ -198,15 +171,9 @@ func DeleteHook(ctx *context.APIContext) {
// "204":
// "$ref": "#/responses/empty"
- org := ctx.Org.Organization
- hookID := ctx.ParamsInt64(":id")
- if err := webhook_model.DeleteWebhookByOrgID(org.ID, hookID); err != nil {
- if webhook_model.IsErrWebhookNotExist(err) {
- ctx.NotFound()
- } else {
- ctx.Error(http.StatusInternalServerError, "DeleteWebhookByOrgID", err)
- }
- return
- }
- ctx.Status(http.StatusNoContent)
+ utils.DeleteOwnerHook(
+ ctx,
+ ctx.ContextUser,
+ ctx.ParamsInt64("id"),
+ )
}
diff --git a/routers/api/v1/org/label.go b/routers/api/v1/org/label.go
index 938fe79df..183c1e6cc 100644
--- a/routers/api/v1/org/label.go
+++ b/routers/api/v1/org/label.go
@@ -4,13 +4,13 @@
package org
import (
- "fmt"
"net/http"
"strconv"
"strings"
issues_model "code.gitea.io/gitea/models/issues"
"code.gitea.io/gitea/modules/context"
+ "code.gitea.io/gitea/modules/label"
api "code.gitea.io/gitea/modules/structs"
"code.gitea.io/gitea/modules/web"
"code.gitea.io/gitea/routers/api/v1/utils"
@@ -84,13 +84,12 @@ func CreateLabel(ctx *context.APIContext) {
// "$ref": "#/responses/validationError"
form := web.GetForm(ctx).(*api.CreateLabelOption)
form.Color = strings.Trim(form.Color, " ")
- if len(form.Color) == 6 {
- form.Color = "#" + form.Color
- }
- if !issues_model.LabelColorPattern.MatchString(form.Color) {
- ctx.Error(http.StatusUnprocessableEntity, "ColorPattern", fmt.Errorf("bad color code: %s", form.Color))
+ color, err := label.NormalizeColor(form.Color)
+ if err != nil {
+ ctx.Error(http.StatusUnprocessableEntity, "Color", err)
return
}
+ form.Color = color
label := &issues_model.Label{
Name: form.Name,
@@ -183,7 +182,7 @@ func EditLabel(ctx *context.APIContext) {
// "422":
// "$ref": "#/responses/validationError"
form := web.GetForm(ctx).(*api.EditLabelOption)
- label, err := issues_model.GetLabelInOrgByID(ctx, ctx.Org.Organization.ID, ctx.ParamsInt64(":id"))
+ l, err := issues_model.GetLabelInOrgByID(ctx, ctx.Org.Organization.ID, ctx.ParamsInt64(":id"))
if err != nil {
if issues_model.IsErrOrgLabelNotExist(err) {
ctx.NotFound()
@@ -194,30 +193,28 @@ func EditLabel(ctx *context.APIContext) {
}
if form.Name != nil {
- label.Name = *form.Name
+ l.Name = *form.Name
}
if form.Exclusive != nil {
- label.Exclusive = *form.Exclusive
+ l.Exclusive = *form.Exclusive
}
if form.Color != nil {
- label.Color = strings.Trim(*form.Color, " ")
- if len(label.Color) == 6 {
- label.Color = "#" + label.Color
- }
- if !issues_model.LabelColorPattern.MatchString(label.Color) {
- ctx.Error(http.StatusUnprocessableEntity, "ColorPattern", fmt.Errorf("bad color code: %s", label.Color))
+ color, err := label.NormalizeColor(*form.Color)
+ if err != nil {
+ ctx.Error(http.StatusUnprocessableEntity, "Color", err)
return
}
+ l.Color = color
}
if form.Description != nil {
- label.Description = *form.Description
+ l.Description = *form.Description
}
- if err := issues_model.UpdateLabel(label); err != nil {
+ if err := issues_model.UpdateLabel(l); err != nil {
ctx.Error(http.StatusInternalServerError, "UpdateLabel", err)
return
}
- ctx.JSON(http.StatusOK, convert.ToLabel(label, nil, ctx.Org.Organization.AsUser()))
+ ctx.JSON(http.StatusOK, convert.ToLabel(l, nil, ctx.Org.Organization.AsUser()))
}
// DeleteLabel delete a label for an organization
diff --git a/routers/api/v1/repo/branch.go b/routers/api/v1/repo/branch.go
index 8acaeaffb..dff47fbcf 100644
--- a/routers/api/v1/repo/branch.go
+++ b/routers/api/v1/repo/branch.go
@@ -118,7 +118,7 @@ func DeleteBranch(ctx *context.APIContext) {
branchName := ctx.Params("*")
- if err := repo_service.DeleteBranch(ctx.Doer, ctx.Repo.Repository, ctx.Repo.GitRepo, branchName); err != nil {
+ if err := repo_service.DeleteBranch(ctx, ctx.Doer, ctx.Repo.Repository, ctx.Repo.GitRepo, branchName); err != nil {
switch {
case git.IsErrBranchNotExist(err):
ctx.NotFound(err)
diff --git a/routers/api/v1/repo/hook.go b/routers/api/v1/repo/hook.go
index fd54d1f74..39d83912b 100644
--- a/routers/api/v1/repo/hook.go
+++ b/routers/api/v1/repo/hook.go
@@ -223,12 +223,8 @@ func CreateHook(ctx *context.APIContext) {
// responses:
// "201":
// "$ref": "#/responses/Hook"
- form := web.GetForm(ctx).(*api.CreateHookOption)
- if !utils.CheckCreateHookOption(ctx, form) {
- return
- }
- utils.AddRepoHook(ctx, form)
+ utils.AddRepoHook(ctx, web.GetForm(ctx).(*api.CreateHookOption))
}
// EditHook modify a hook of a repository
diff --git a/routers/api/v1/repo/issue_attachment.go b/routers/api/v1/repo/issue_attachment.go
index 8cbd2e11b..92e113868 100644
--- a/routers/api/v1/repo/issue_attachment.go
+++ b/routers/api/v1/repo/issue_attachment.go
@@ -176,7 +176,7 @@ func CreateIssueAttachment(ctx *context.APIContext) {
filename = query
}
- attachment, err := attachment.UploadAttachment(file, setting.Attachment.AllowedTypes, &repo_model.Attachment{
+ attachment, err := attachment.UploadAttachment(file, setting.Attachment.AllowedTypes, header.Size, &repo_model.Attachment{
Name: filename,
UploaderID: ctx.Doer.ID,
RepoID: ctx.Repo.Repository.ID,
diff --git a/routers/api/v1/repo/issue_comment_attachment.go b/routers/api/v1/repo/issue_comment_attachment.go
index 4c8452380..6fe4dbc97 100644
--- a/routers/api/v1/repo/issue_comment_attachment.go
+++ b/routers/api/v1/repo/issue_comment_attachment.go
@@ -180,7 +180,7 @@ func CreateIssueCommentAttachment(ctx *context.APIContext) {
filename = query
}
- attachment, err := attachment.UploadAttachment(file, setting.Attachment.AllowedTypes, &repo_model.Attachment{
+ attachment, err := attachment.UploadAttachment(file, setting.Attachment.AllowedTypes, header.Size, &repo_model.Attachment{
Name: filename,
UploaderID: ctx.Doer.ID,
RepoID: ctx.Repo.Repository.ID,
diff --git a/routers/api/v1/repo/label.go b/routers/api/v1/repo/label.go
index a06d26e83..6cb231f59 100644
--- a/routers/api/v1/repo/label.go
+++ b/routers/api/v1/repo/label.go
@@ -5,13 +5,12 @@
package repo
import (
- "fmt"
"net/http"
"strconv"
- "strings"
issues_model "code.gitea.io/gitea/models/issues"
"code.gitea.io/gitea/modules/context"
+ "code.gitea.io/gitea/modules/label"
api "code.gitea.io/gitea/modules/structs"
"code.gitea.io/gitea/modules/web"
"code.gitea.io/gitea/routers/api/v1/utils"
@@ -93,14 +92,14 @@ func GetLabel(ctx *context.APIContext) {
// "$ref": "#/responses/Label"
var (
- label *issues_model.Label
- err error
+ l *issues_model.Label
+ err error
)
strID := ctx.Params(":id")
if intID, err2 := strconv.ParseInt(strID, 10, 64); err2 != nil {
- label, err = issues_model.GetLabelInRepoByName(ctx, ctx.Repo.Repository.ID, strID)
+ l, err = issues_model.GetLabelInRepoByName(ctx, ctx.Repo.Repository.ID, strID)
} else {
- label, err = issues_model.GetLabelInRepoByID(ctx, ctx.Repo.Repository.ID, intID)
+ l, err = issues_model.GetLabelInRepoByID(ctx, ctx.Repo.Repository.ID, intID)
}
if err != nil {
if issues_model.IsErrRepoLabelNotExist(err) {
@@ -111,7 +110,7 @@ func GetLabel(ctx *context.APIContext) {
return
}
- ctx.JSON(http.StatusOK, convert.ToLabel(label, ctx.Repo.Repository, nil))
+ ctx.JSON(http.StatusOK, convert.ToLabel(l, ctx.Repo.Repository, nil))
}
// CreateLabel create a label for a repository
@@ -145,28 +144,27 @@ func CreateLabel(ctx *context.APIContext) {
// "$ref": "#/responses/validationError"
form := web.GetForm(ctx).(*api.CreateLabelOption)
- form.Color = strings.Trim(form.Color, " ")
- if len(form.Color) == 6 {
- form.Color = "#" + form.Color
- }
- if !issues_model.LabelColorPattern.MatchString(form.Color) {
- ctx.Error(http.StatusUnprocessableEntity, "ColorPattern", fmt.Errorf("bad color code: %s", form.Color))
+
+ color, err := label.NormalizeColor(form.Color)
+ if err != nil {
+ ctx.Error(http.StatusUnprocessableEntity, "StringToColor", err)
return
}
+ form.Color = color
- label := &issues_model.Label{
+ l := &issues_model.Label{
Name: form.Name,
Exclusive: form.Exclusive,
Color: form.Color,
RepoID: ctx.Repo.Repository.ID,
Description: form.Description,
}
- if err := issues_model.NewLabel(ctx, label); err != nil {
+ if err := issues_model.NewLabel(ctx, l); err != nil {
ctx.Error(http.StatusInternalServerError, "NewLabel", err)
return
}
- ctx.JSON(http.StatusCreated, convert.ToLabel(label, ctx.Repo.Repository, nil))
+ ctx.JSON(http.StatusCreated, convert.ToLabel(l, ctx.Repo.Repository, nil))
}
// EditLabel modify a label for a repository
@@ -206,7 +204,7 @@ func EditLabel(ctx *context.APIContext) {
// "$ref": "#/responses/validationError"
form := web.GetForm(ctx).(*api.EditLabelOption)
- label, err := issues_model.GetLabelInRepoByID(ctx, ctx.Repo.Repository.ID, ctx.ParamsInt64(":id"))
+ l, err := issues_model.GetLabelInRepoByID(ctx, ctx.Repo.Repository.ID, ctx.ParamsInt64(":id"))
if err != nil {
if issues_model.IsErrRepoLabelNotExist(err) {
ctx.NotFound()
@@ -217,30 +215,28 @@ func EditLabel(ctx *context.APIContext) {
}
if form.Name != nil {
- label.Name = *form.Name
+ l.Name = *form.Name
}
if form.Exclusive != nil {
- label.Exclusive = *form.Exclusive
+ l.Exclusive = *form.Exclusive
}
if form.Color != nil {
- label.Color = strings.Trim(*form.Color, " ")
- if len(label.Color) == 6 {
- label.Color = "#" + label.Color
- }
- if !issues_model.LabelColorPattern.MatchString(label.Color) {
- ctx.Error(http.StatusUnprocessableEntity, "ColorPattern", fmt.Errorf("bad color code: %s", label.Color))
+ color, err := label.NormalizeColor(*form.Color)
+ if err != nil {
+ ctx.Error(http.StatusUnprocessableEntity, "StringToColor", err)
return
}
+ l.Color = color
}
if form.Description != nil {
- label.Description = *form.Description
+ l.Description = *form.Description
}
- if err := issues_model.UpdateLabel(label); err != nil {
+ if err := issues_model.UpdateLabel(l); err != nil {
ctx.Error(http.StatusInternalServerError, "UpdateLabel", err)
return
}
- ctx.JSON(http.StatusOK, convert.ToLabel(label, ctx.Repo.Repository, nil))
+ ctx.JSON(http.StatusOK, convert.ToLabel(l, ctx.Repo.Repository, nil))
}
// DeleteLabel delete a label for a repository
diff --git a/routers/api/v1/repo/notes.go b/routers/api/v1/repo/notes.go
index 2d1f3291f..74969f2ca 100644
--- a/routers/api/v1/repo/notes.go
+++ b/routers/api/v1/repo/notes.go
@@ -58,8 +58,18 @@ func getNote(ctx *context.APIContext, identifier string) {
return
}
+ commitSHA, err := ctx.Repo.GitRepo.ConvertToSHA1(identifier)
+ if err != nil {
+ if git.IsErrNotExist(err) {
+ ctx.NotFound(err)
+ } else {
+ ctx.Error(http.StatusInternalServerError, "ConvertToSHA1", err)
+ }
+ return
+ }
+
var note git.Note
- if err := git.GetNote(ctx, ctx.Repo.GitRepo, identifier, &note); err != nil {
+ if err := git.GetNote(ctx, ctx.Repo.GitRepo, commitSHA.String(), &note); err != nil {
if git.IsErrNotExist(err) {
ctx.NotFound(identifier)
return
diff --git a/routers/api/v1/repo/pull.go b/routers/api/v1/repo/pull.go
index 84eebeb94..9b5ec0b3f 100644
--- a/routers/api/v1/repo/pull.go
+++ b/routers/api/v1/repo/pull.go
@@ -904,7 +904,7 @@ func MergePullRequest(ctx *context.APIContext) {
}
defer headRepo.Close()
}
- if err := repo_service.DeleteBranch(ctx.Doer, pr.HeadRepo, headRepo, pr.HeadBranch); err != nil {
+ if err := repo_service.DeleteBranch(ctx, ctx.Doer, pr.HeadRepo, headRepo, pr.HeadBranch); err != nil {
switch {
case git.IsErrBranchNotExist(err):
ctx.NotFound(err)
diff --git a/routers/api/v1/repo/pull_review.go b/routers/api/v1/repo/pull_review.go
index f6acaa780..8f4b9dafe 100644
--- a/routers/api/v1/repo/pull_review.go
+++ b/routers/api/v1/repo/pull_review.go
@@ -268,7 +268,7 @@ func DeletePullReview(ctx *context.APIContext) {
ctx.Status(http.StatusNoContent)
}
-// CreatePullReview create a review to an pull request
+// CreatePullReview create a review to a pull request
func CreatePullReview(ctx *context.APIContext) {
// swagger:operation POST /repos/{owner}/{repo}/pulls/{index}/reviews repository repoCreatePullReview
// ---
@@ -360,7 +360,7 @@ func CreatePullReview(ctx *context.APIContext) {
line,
c.Body,
c.Path,
- true, // is review
+ true, // pending review
0, // no reply
opts.CommitID,
); err != nil {
diff --git a/routers/api/v1/repo/release_attachment.go b/routers/api/v1/repo/release_attachment.go
index 597578aac..305b2808d 100644
--- a/routers/api/v1/repo/release_attachment.go
+++ b/routers/api/v1/repo/release_attachment.go
@@ -194,7 +194,7 @@ func CreateReleaseAttachment(ctx *context.APIContext) {
}
// Create a new attachment and save the file
- attach, err := attachment.UploadAttachment(file, setting.Repository.Release.AllowedTypes, &repo_model.Attachment{
+ attach, err := attachment.UploadAttachment(file, setting.Repository.Release.AllowedTypes, header.Size, &repo_model.Attachment{
Name: filename,
UploaderID: ctx.Doer.ID,
RepoID: release.RepoID,
diff --git a/routers/api/v1/repo/repo.go b/routers/api/v1/repo/repo.go
index 0395198e2..397600dc5 100644
--- a/routers/api/v1/repo/repo.go
+++ b/routers/api/v1/repo/repo.go
@@ -19,6 +19,7 @@ import (
user_model "code.gitea.io/gitea/models/user"
"code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/git"
+ "code.gitea.io/gitea/modules/label"
"code.gitea.io/gitea/modules/log"
repo_module "code.gitea.io/gitea/modules/repository"
"code.gitea.io/gitea/modules/setting"
@@ -230,7 +231,7 @@ func CreateUserRepo(ctx *context.APIContext, owner *user_model.User, opt api.Cre
if opt.AutoInit && opt.Readme == "" {
opt.Readme = "Default"
}
- repo, err := repo_service.CreateRepository(ctx.Doer, owner, repo_module.CreateRepoOptions{
+ repo, err := repo_service.CreateRepository(ctx, ctx.Doer, owner, repo_module.CreateRepoOptions{
Name: opt.Name,
Description: opt.Description,
IssueLabels: opt.IssueLabels,
@@ -248,7 +249,7 @@ func CreateUserRepo(ctx *context.APIContext, owner *user_model.User, opt api.Cre
ctx.Error(http.StatusConflict, "", "The repository with the same name already exists.")
} else if db.IsErrNameReserved(err) ||
db.IsErrNamePatternNotAllowed(err) ||
- repo_module.IsErrIssueLabelTemplateLoad(err) {
+ label.IsErrTemplateLoad(err) {
ctx.Error(http.StatusUnprocessableEntity, "", err)
} else {
ctx.Error(http.StatusInternalServerError, "CreateRepository", err)
@@ -393,7 +394,7 @@ func Generate(ctx *context.APIContext) {
}
}
- repo, err := repo_service.GenerateRepository(ctx.Doer, ctxUser, ctx.Repo.Repository, opts)
+ repo, err := repo_service.GenerateRepository(ctx, ctx.Doer, ctxUser, ctx.Repo.Repository, opts)
if err != nil {
if repo_model.IsErrRepoAlreadyExist(err) {
ctx.Error(http.StatusConflict, "", "The repository with the same name already exists.")
@@ -637,7 +638,7 @@ func updateBasicProperties(ctx *context.APIContext, opts api.EditRepoOption) err
}
// Check if repository name has been changed and not just a case change
if repo.LowerName != strings.ToLower(newRepoName) {
- if err := repo_service.ChangeRepositoryName(ctx.Doer, repo, newRepoName); err != nil {
+ if err := repo_service.ChangeRepositoryName(ctx, ctx.Doer, repo, newRepoName); err != nil {
switch {
case repo_model.IsErrRepoAlreadyExist(err):
ctx.Error(http.StatusUnprocessableEntity, fmt.Sprintf("repo name is already taken [name: %s]", newRepoName), err)
@@ -714,7 +715,7 @@ func updateBasicProperties(ctx *context.APIContext, opts api.EditRepoOption) err
repo.DefaultBranch = *opts.DefaultBranch
}
- if err := repo_service.UpdateRepository(repo, visibilityChanged); err != nil {
+ if err := repo_service.UpdateRepository(ctx, repo, visibilityChanged); err != nil {
ctx.Error(http.StatusInternalServerError, "UpdateRepository", err)
return err
}
diff --git a/routers/api/v1/user/hook.go b/routers/api/v1/user/hook.go
new file mode 100644
index 000000000..50be519c8
--- /dev/null
+++ b/routers/api/v1/user/hook.go
@@ -0,0 +1,154 @@
+// Copyright 2022 The Gitea Authors. All rights reserved.
+// SPDX-License-Identifier: MIT
+
+package user
+
+import (
+ "net/http"
+
+ "code.gitea.io/gitea/modules/context"
+ api "code.gitea.io/gitea/modules/structs"
+ "code.gitea.io/gitea/modules/web"
+ "code.gitea.io/gitea/routers/api/v1/utils"
+ webhook_service "code.gitea.io/gitea/services/webhook"
+)
+
+// ListHooks list the authenticated user's webhooks
+func ListHooks(ctx *context.APIContext) {
+ // swagger:operation GET /user/hooks user userListHooks
+ // ---
+ // summary: List the authenticated user's webhooks
+ // produces:
+ // - application/json
+ // parameters:
+ // - name: page
+ // in: query
+ // description: page number of results to return (1-based)
+ // type: integer
+ // - name: limit
+ // in: query
+ // description: page size of results
+ // type: integer
+ // responses:
+ // "200":
+ // "$ref": "#/responses/HookList"
+
+ utils.ListOwnerHooks(
+ ctx,
+ ctx.Doer,
+ )
+}
+
+// GetHook get the authenticated user's hook by id
+func GetHook(ctx *context.APIContext) {
+ // swagger:operation GET /user/hooks/{id} user userGetHook
+ // ---
+ // summary: Get a hook
+ // produces:
+ // - application/json
+ // parameters:
+ // - name: id
+ // in: path
+ // description: id of the hook to get
+ // type: integer
+ // format: int64
+ // required: true
+ // responses:
+ // "200":
+ // "$ref": "#/responses/Hook"
+
+ hook, err := utils.GetOwnerHook(ctx, ctx.Doer.ID, ctx.ParamsInt64("id"))
+ if err != nil {
+ return
+ }
+
+ apiHook, err := webhook_service.ToHook(ctx.Doer.HomeLink(), hook)
+ if err != nil {
+ ctx.InternalServerError(err)
+ return
+ }
+ ctx.JSON(http.StatusOK, apiHook)
+}
+
+// CreateHook create a hook for the authenticated user
+func CreateHook(ctx *context.APIContext) {
+ // swagger:operation POST /user/hooks user userCreateHook
+ // ---
+ // summary: Create a hook
+ // consumes:
+ // - application/json
+ // produces:
+ // - application/json
+ // parameters:
+ // - name: body
+ // in: body
+ // required: true
+ // schema:
+ // "$ref": "#/definitions/CreateHookOption"
+ // responses:
+ // "201":
+ // "$ref": "#/responses/Hook"
+
+ utils.AddOwnerHook(
+ ctx,
+ ctx.Doer,
+ web.GetForm(ctx).(*api.CreateHookOption),
+ )
+}
+
+// EditHook modify a hook of the authenticated user
+func EditHook(ctx *context.APIContext) {
+ // swagger:operation PATCH /user/hooks/{id} user userEditHook
+ // ---
+ // summary: Update a hook
+ // consumes:
+ // - application/json
+ // produces:
+ // - application/json
+ // parameters:
+ // - name: id
+ // in: path
+ // description: id of the hook to update
+ // type: integer
+ // format: int64
+ // required: true
+ // - name: body
+ // in: body
+ // schema:
+ // "$ref": "#/definitions/EditHookOption"
+ // responses:
+ // "200":
+ // "$ref": "#/responses/Hook"
+
+ utils.EditOwnerHook(
+ ctx,
+ ctx.Doer,
+ web.GetForm(ctx).(*api.EditHookOption),
+ ctx.ParamsInt64("id"),
+ )
+}
+
+// DeleteHook delete a hook of the authenticated user
+func DeleteHook(ctx *context.APIContext) {
+ // swagger:operation DELETE /user/hooks/{id} user userDeleteHook
+ // ---
+ // summary: Delete a hook
+ // produces:
+ // - application/json
+ // parameters:
+ // - name: id
+ // in: path
+ // description: id of the hook to delete
+ // type: integer
+ // format: int64
+ // required: true
+ // responses:
+ // "204":
+ // "$ref": "#/responses/empty"
+
+ utils.DeleteOwnerHook(
+ ctx,
+ ctx.Doer,
+ ctx.ParamsInt64("id"),
+ )
+}
diff --git a/routers/api/v1/utils/hook.go b/routers/api/v1/utils/hook.go
index f6aaf74af..44625cc9b 100644
--- a/routers/api/v1/utils/hook.go
+++ b/routers/api/v1/utils/hook.go
@@ -8,6 +8,7 @@ import (
"net/http"
"strings"
+ user_model "code.gitea.io/gitea/models/user"
"code.gitea.io/gitea/models/webhook"
"code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/json"
@@ -18,15 +19,46 @@ import (
webhook_service "code.gitea.io/gitea/services/webhook"
)
-// GetOrgHook get an organization's webhook. If there is an error, write to
-// `ctx` accordingly and return the error
-func GetOrgHook(ctx *context.APIContext, orgID, hookID int64) (*webhook.Webhook, error) {
- w, err := webhook.GetWebhookByOrgID(orgID, hookID)
+// ListOwnerHooks lists the webhooks of the provided owner
+func ListOwnerHooks(ctx *context.APIContext, owner *user_model.User) {
+ opts := &webhook.ListWebhookOptions{
+ ListOptions: GetListOptions(ctx),
+ OwnerID: owner.ID,
+ }
+
+ count, err := webhook.CountWebhooksByOpts(opts)
+ if err != nil {
+ ctx.InternalServerError(err)
+ return
+ }
+
+ hooks, err := webhook.ListWebhooksByOpts(ctx, opts)
+ if err != nil {
+ ctx.InternalServerError(err)
+ return
+ }
+
+ apiHooks := make([]*api.Hook, len(hooks))
+ for i, hook := range hooks {
+ apiHooks[i], err = webhook_service.ToHook(owner.HomeLink(), hook)
+ if err != nil {
+ ctx.InternalServerError(err)
+ return
+ }
+ }
+
+ ctx.SetTotalCountHeader(count)
+ ctx.JSON(http.StatusOK, apiHooks)
+}
+
+// GetOwnerHook gets an user or organization webhook. Errors are written to ctx.
+func GetOwnerHook(ctx *context.APIContext, ownerID, hookID int64) (*webhook.Webhook, error) {
+ w, err := webhook.GetWebhookByOwnerID(ownerID, hookID)
if err != nil {
if webhook.IsErrWebhookNotExist(err) {
ctx.NotFound()
} else {
- ctx.Error(http.StatusInternalServerError, "GetWebhookByOrgID", err)
+ ctx.Error(http.StatusInternalServerError, "GetWebhookByOwnerID", err)
}
return nil, err
}
@@ -48,9 +80,9 @@ func GetRepoHook(ctx *context.APIContext, repoID, hookID int64) (*webhook.Webhoo
return w, nil
}
-// CheckCreateHookOption check if a CreateHookOption form is valid. If invalid,
+// checkCreateHookOption check if a CreateHookOption form is valid. If invalid,
// write the appropriate error to `ctx`. Return whether the form is valid
-func CheckCreateHookOption(ctx *context.APIContext, form *api.CreateHookOption) bool {
+func checkCreateHookOption(ctx *context.APIContext, form *api.CreateHookOption) bool {
if !webhook_service.IsValidHookTaskType(form.Type) {
ctx.Error(http.StatusUnprocessableEntity, "", fmt.Sprintf("Invalid hook type: %s", form.Type))
return false
@@ -81,14 +113,13 @@ func AddSystemHook(ctx *context.APIContext, form *api.CreateHookOption) {
}
}
-// AddOrgHook add a hook to an organization. Writes to `ctx` accordingly
-func AddOrgHook(ctx *context.APIContext, form *api.CreateHookOption) {
- org := ctx.Org.Organization
- hook, ok := addHook(ctx, form, org.ID, 0)
+// AddOwnerHook adds a hook to an user or organization
+func AddOwnerHook(ctx *context.APIContext, owner *user_model.User, form *api.CreateHookOption) {
+ hook, ok := addHook(ctx, form, owner.ID, 0)
if !ok {
return
}
- apiHook, ok := toAPIHook(ctx, org.AsUser().HomeLink(), hook)
+ apiHook, ok := toAPIHook(ctx, owner.HomeLink(), hook)
if !ok {
return
}
@@ -128,14 +159,18 @@ func pullHook(events []string, event string) bool {
return util.SliceContainsString(events, event, true) || util.SliceContainsString(events, string(webhook_module.HookEventPullRequest), true)
}
-// addHook add the hook specified by `form`, `orgID` and `repoID`. If there is
+// addHook add the hook specified by `form`, `ownerID` and `repoID`. If there is
// an error, write to `ctx` accordingly. Return (webhook, ok)
-func addHook(ctx *context.APIContext, form *api.CreateHookOption, orgID, repoID int64) (*webhook.Webhook, bool) {
+func addHook(ctx *context.APIContext, form *api.CreateHookOption, ownerID, repoID int64) (*webhook.Webhook, bool) {
+ if !checkCreateHookOption(ctx, form) {
+ return nil, false
+ }
+
if len(form.Events) == 0 {
form.Events = []string{"push"}
}
w := &webhook.Webhook{
- OrgID: orgID,
+ OwnerID: ownerID,
RepoID: repoID,
URL: form.Config["url"],
ContentType: webhook.ToHookContentType(form.Config["content_type"]),
@@ -234,21 +269,20 @@ func EditSystemHook(ctx *context.APIContext, form *api.EditHookOption, hookID in
ctx.JSON(http.StatusOK, h)
}
-// EditOrgHook edit webhook `w` according to `form`. Writes to `ctx` accordingly
-func EditOrgHook(ctx *context.APIContext, form *api.EditHookOption, hookID int64) {
- org := ctx.Org.Organization
- hook, err := GetOrgHook(ctx, org.ID, hookID)
+// EditOwnerHook updates a webhook of an user or organization
+func EditOwnerHook(ctx *context.APIContext, owner *user_model.User, form *api.EditHookOption, hookID int64) {
+ hook, err := GetOwnerHook(ctx, owner.ID, hookID)
if err != nil {
return
}
if !editHook(ctx, form, hook) {
return
}
- updated, err := GetOrgHook(ctx, org.ID, hookID)
+ updated, err := GetOwnerHook(ctx, owner.ID, hookID)
if err != nil {
return
}
- apiHook, ok := toAPIHook(ctx, org.AsUser().HomeLink(), updated)
+ apiHook, ok := toAPIHook(ctx, owner.HomeLink(), updated)
if !ok {
return
}
@@ -362,3 +396,16 @@ func editHook(ctx *context.APIContext, form *api.EditHookOption, w *webhook.Webh
}
return true
}
+
+// DeleteOwnerHook deletes the hook owned by the owner.
+func DeleteOwnerHook(ctx *context.APIContext, owner *user_model.User, hookID int64) {
+ if err := webhook.DeleteWebhookByOwnerID(owner.ID, hookID); err != nil {
+ if webhook.IsErrWebhookNotExist(err) {
+ ctx.NotFound()
+ } else {
+ ctx.Error(http.StatusInternalServerError, "DeleteWebhookByOwnerID", err)
+ }
+ return
+ }
+ ctx.Status(http.StatusNoContent)
+}
diff --git a/routers/common/middleware.go b/routers/common/middleware.go
index 4f9d43c36..2abdcb583 100644
--- a/routers/common/middleware.go
+++ b/routers/common/middleware.go
@@ -16,7 +16,7 @@ import (
"code.gitea.io/gitea/modules/web/routing"
"github.com/chi-middleware/proxy"
- "github.com/go-chi/chi/v5/middleware"
+ chi "github.com/go-chi/chi/v5"
)
// Middlewares returns common middlewares
@@ -48,7 +48,8 @@ func Middlewares() []func(http.Handler) http.Handler {
handlers = append(handlers, proxy.ForwardedHeaders(opt))
}
- handlers = append(handlers, middleware.StripSlashes)
+ // Strip slashes.
+ handlers = append(handlers, stripSlashesMiddleware)
if !setting.Log.DisableRouterLog {
handlers = append(handlers, routing.NewLoggerHandler())
@@ -81,3 +82,33 @@ func Middlewares() []func(http.Handler) http.Handler {
})
return handlers
}
+
+func stripSlashesMiddleware(next http.Handler) http.Handler {
+ return http.HandlerFunc(func(resp http.ResponseWriter, req *http.Request) {
+ var urlPath string
+ rctx := chi.RouteContext(req.Context())
+ if rctx != nil && rctx.RoutePath != "" {
+ urlPath = rctx.RoutePath
+ } else if req.URL.RawPath != "" {
+ urlPath = req.URL.RawPath
+ } else {
+ urlPath = req.URL.Path
+ }
+
+ sanitizedPath := &strings.Builder{}
+ prevWasSlash := false
+ for _, chr := range strings.TrimRight(urlPath, "/") {
+ if chr != '/' || !prevWasSlash {
+ sanitizedPath.WriteRune(chr)
+ }
+ prevWasSlash = chr == '/'
+ }
+
+ if rctx == nil {
+ req.URL.Path = sanitizedPath.String()
+ } else {
+ rctx.RoutePath = sanitizedPath.String()
+ }
+ next.ServeHTTP(resp, req)
+ })
+}
diff --git a/routers/common/middleware_test.go b/routers/common/middleware_test.go
new file mode 100644
index 000000000..f16b9374e
--- /dev/null
+++ b/routers/common/middleware_test.go
@@ -0,0 +1,70 @@
+// Copyright 2022 The Gitea Authors. All rights reserved.
+// SPDX-License-Identifier: MIT
+package common
+
+import (
+ "net/http"
+ "net/http/httptest"
+ "testing"
+
+ "github.com/stretchr/testify/assert"
+)
+
+func TestStripSlashesMiddleware(t *testing.T) {
+ type test struct {
+ name string
+ expectedPath string
+ inputPath string
+ }
+
+ tests := []test{
+ {
+ name: "path with multiple slashes",
+ inputPath: "https://github.com///go-gitea//gitea.git",
+ expectedPath: "/go-gitea/gitea.git",
+ },
+ {
+ name: "path with no slashes",
+ inputPath: "https://github.com/go-gitea/gitea.git",
+ expectedPath: "/go-gitea/gitea.git",
+ },
+ {
+ name: "path with slashes in the middle",
+ inputPath: "https://git.data.coop//halfd/new-website.git",
+ expectedPath: "/halfd/new-website.git",
+ },
+ {
+ name: "path with slashes in the middle",
+ inputPath: "https://git.data.coop//halfd/new-website.git",
+ expectedPath: "/halfd/new-website.git",
+ },
+ {
+ name: "path with slashes in the end",
+ inputPath: "/user2//repo1/",
+ expectedPath: "/user2/repo1",
+ },
+ {
+ name: "path with slashes and query params",
+ inputPath: "/repo//migrate?service_type=3",
+ expectedPath: "/repo/migrate",
+ },
+ {
+ name: "path with encoded slash",
+ inputPath: "/user2/%2F%2Frepo1",
+ expectedPath: "/user2/%2F%2Frepo1",
+ },
+ }
+
+ for _, tt := range tests {
+ testMiddleware := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ assert.Equal(t, tt.expectedPath, r.URL.Path)
+ })
+
+ // pass the test middleware to validate the changes
+ handlerToTest := stripSlashesMiddleware(testMiddleware)
+ // create a mock request to use
+ req := httptest.NewRequest("GET", tt.inputPath, nil)
+ // call the handler using a mock response recorder
+ handlerToTest.ServeHTTP(httptest.NewRecorder(), req)
+ }
+}
diff --git a/routers/init.go b/routers/init.go
index d3f822dc8..8cf53fc10 100644
--- a/routers/init.go
+++ b/routers/init.go
@@ -141,7 +141,7 @@ func GlobalInitInstalled(ctx context.Context) {
if setting.EnableSQLite3 {
log.Info("SQLite3 support is enabled")
- } else if setting.Database.UseSQLite3 {
+ } else if setting.Database.Type.IsSQLite3() {
log.Fatal("SQLite3 support is disabled, but it is used for database setting. Please get or build a Gitea release with SQLite3 support.")
}
diff --git a/routers/install/install.go b/routers/install/install.go
index a3d64e5f7..8e2d19c73 100644
--- a/routers/install/install.go
+++ b/routers/install/install.go
@@ -59,11 +59,6 @@ func Init(ctx goctx.Context) func(next http.Handler) http.Handler {
dbTypeNames := getSupportedDbTypeNames()
return func(next http.Handler) http.Handler {
return http.HandlerFunc(func(resp http.ResponseWriter, req *http.Request) {
- if setting.InstallLock {
- resp.Header().Add("Refresh", "1; url="+setting.AppURL+"user/login")
- _ = rnd.HTML(resp, http.StatusOK, string(tplPostInstall), nil)
- return
- }
locale := middleware.Locale(resp, req)
startTime := time.Now()
ctx := context.Context{
@@ -93,6 +88,11 @@ func Init(ctx goctx.Context) func(next http.Handler) http.Handler {
// Install render installation page
func Install(ctx *context.Context) {
+ if setting.InstallLock {
+ InstallDone(ctx)
+ return
+ }
+
form := forms.InstallForm{}
// Database settings
@@ -104,7 +104,7 @@ func Install(ctx *context.Context) {
form.DbSchema = setting.Database.Schema
form.Charset = setting.Database.Charset
- curDBType := setting.Database.Type
+ curDBType := setting.Database.Type.String()
var isCurDBTypeSupported bool
for _, dbType := range setting.SupportedDatabaseTypes {
if dbType == curDBType {
@@ -162,7 +162,7 @@ func Install(ctx *context.Context) {
form.DefaultAllowCreateOrganization = setting.Service.DefaultAllowCreateOrganization
form.DefaultEnableTimetracking = setting.Service.DefaultEnableTimetracking
form.NoReplyAddress = setting.Service.NoReplyAddress
- form.PasswordAlgorithm = setting.PasswordHashAlgo
+ form.PasswordAlgorithm = hash.ConfigHashAlgorithm(setting.PasswordHashAlgo)
middleware.AssignForm(form, ctx.Data)
ctx.HTML(http.StatusOK, tplInstall)
@@ -234,6 +234,11 @@ func checkDatabase(ctx *context.Context, form *forms.InstallForm) bool {
// SubmitInstall response for submit install items
func SubmitInstall(ctx *context.Context) {
+ if setting.InstallLock {
+ InstallDone(ctx)
+ return
+ }
+
var err error
form := *web.GetForm(ctx).(*forms.InstallForm)
@@ -267,7 +272,7 @@ func SubmitInstall(ctx *context.Context) {
// ---- Basic checks are passed, now test configuration.
// Test database setting.
- setting.Database.Type = form.DbType
+ setting.Database.Type = setting.DatabaseType(form.DbType)
setting.Database.Host = form.DbHost
setting.Database.User = form.DbUser
setting.Database.Passwd = form.DbPasswd
@@ -277,7 +282,6 @@ func SubmitInstall(ctx *context.Context) {
setting.Database.Charset = form.Charset
setting.Database.Path = form.DbPath
setting.Database.LogSQL = !setting.IsProd
- setting.PasswordHashAlgo = form.PasswordAlgorithm
if !checkDatabase(ctx, &form) {
return
@@ -388,7 +392,7 @@ func SubmitInstall(ctx *context.Context) {
log.Error("Failed to load custom conf '%s': %v", setting.CustomConf, err)
}
}
- cfg.Section("database").Key("DB_TYPE").SetValue(setting.Database.Type)
+ cfg.Section("database").Key("DB_TYPE").SetValue(setting.Database.Type.String())
cfg.Section("database").Key("HOST").SetValue(setting.Database.Host)
cfg.Section("database").Key("NAME").SetValue(setting.Database.Name)
cfg.Section("database").Key("USER").SetValue(setting.Database.User)
@@ -499,6 +503,12 @@ func SubmitInstall(ctx *context.Context) {
}
if len(form.PasswordAlgorithm) > 0 {
+ var algorithm *hash.PasswordHashAlgorithm
+ setting.PasswordHashAlgo, algorithm = hash.SetDefaultPasswordHashAlgorithm(form.PasswordAlgorithm)
+ if algorithm == nil {
+ ctx.RenderWithErr(ctx.Tr("install.invalid_password_algorithm"), tplInstall, &form)
+ return
+ }
cfg.Section("security").Key("PASSWORD_HASH_ALGO").SetValue(form.PasswordAlgorithm)
}
@@ -571,18 +581,26 @@ func SubmitInstall(ctx *context.Context) {
}
log.Info("First-time run install finished!")
+ InstallDone(ctx)
- ctx.Flash.Success(ctx.Tr("install.install_success"))
-
- ctx.RespHeader().Add("Refresh", "1; url="+setting.AppURL+"user/login")
- ctx.HTML(http.StatusOK, tplPostInstall)
-
- // Now get the http.Server from this request and shut it down
- // NB: This is not our hammerable graceful shutdown this is http.Server.Shutdown
- srv := ctx.Value(http.ServerContextKey).(*http.Server)
go func() {
+ // Sleep for a while to make sure the user's browser has loaded the post-install page and its assets (images, css, js)
+ // What if this duration is not long enough? That's impossible -- if the user can't load the simple page in time, how could they install or use Gitea in the future ....
+ time.Sleep(3 * time.Second)
+
+ // Now get the http.Server from this request and shut it down
+ // NB: This is not our hammerable graceful shutdown this is http.Server.Shutdown
+ srv := ctx.Value(http.ServerContextKey).(*http.Server)
if err := srv.Shutdown(graceful.GetManager().HammerContext()); err != nil {
log.Error("Unable to shutdown the install server! Error: %v", err)
}
+
+ // After the HTTP server for "install" shuts down, the `runWeb()` will continue to run the "normal" server
}()
}
+
+// InstallDone shows the "post-install" page, makes it easier to develop the page.
+// The name is not called as "PostInstall" to avoid misinterpretation as a handler for "POST /install"
+func InstallDone(ctx *context.Context) { //nolint
+ ctx.HTML(http.StatusOK, tplPostInstall)
+}
diff --git a/routers/install/routes.go b/routers/install/routes.go
index 9aa5a88d2..82d9c34b4 100644
--- a/routers/install/routes.go
+++ b/routers/install/routes.go
@@ -6,6 +6,7 @@ package install
import (
goctx "context"
"fmt"
+ "html"
"net/http"
"path"
@@ -37,7 +38,7 @@ func installRecovery(ctx goctx.Context) func(next http.Handler) http.Handler {
// Why we need this? The first recover will try to render a beautiful
// error page for user, but the process can still panic again, then
// we have to just recover twice and send a simple error page that
- // should not panic any more.
+ // should not panic anymore.
defer func() {
if err := recover(); err != nil {
combinedErr := fmt.Sprintf("PANIC: %v\n%s", err, log.Stack(2))
@@ -63,7 +64,7 @@ func installRecovery(ctx goctx.Context) func(next http.Handler) http.Handler {
"SignedUserName": "",
}
- httpcache.AddCacheControlToHeader(w.Header(), 0, "no-transform")
+ httpcache.SetCacheControlInHeader(w.Header(), 0, "no-transform")
w.Header().Set(`X-Frame-Options`, setting.CORSConfig.XFrameOptions)
if !setting.IsProd {
@@ -107,8 +108,9 @@ func Routes(ctx goctx.Context) *web.Route {
r.Use(installRecovery(ctx))
r.Use(Init(ctx))
- r.Get("/", Install)
+ r.Get("/", Install) // it must be on the root, because the "install.js" use the window.location to replace the "localhost" AppURL
r.Post("/", web.Bind(forms.InstallForm{}), SubmitInstall)
+ r.Get("/post-install", InstallDone)
r.Get("/api/healthz", healthcheck.Check)
r.NotFound(web.Wrap(installNotFound))
@@ -116,5 +118,10 @@ func Routes(ctx goctx.Context) *web.Route {
}
func installNotFound(w http.ResponseWriter, req *http.Request) {
- http.Redirect(w, req, setting.AppURL, http.StatusFound)
+ w.Header().Add("Content-Type", "text/html; charset=utf-8")
+ w.Header().Add("Refresh", fmt.Sprintf("1; url=%s", setting.AppSubURL+"/"))
+ // do not use 30x status, because the "post-install" page needs to use 404/200 to detect if Gitea has been installed.
+ // the fetch API could follow 30x requests to the page with 200 status.
+ w.WriteHeader(http.StatusNotFound)
+ _, _ = fmt.Fprintf(w, `Not Found. <a href="%s">Go to default page</a>.`, html.EscapeString(setting.AppSubURL+"/"))
}
diff --git a/routers/private/serv.go b/routers/private/serv.go
index 17f966e3e..23ac011cf 100644
--- a/routers/private/serv.go
+++ b/routers/private/serv.go
@@ -368,7 +368,7 @@ func ServCommand(ctx *context.PrivateContext) {
return
}
- repo, err = repo_service.PushCreateRepo(user, owner, results.RepoName)
+ repo, err = repo_service.PushCreateRepo(ctx, user, owner, results.RepoName)
if err != nil {
log.Error("pushCreateRepo: %v", err)
ctx.JSON(http.StatusNotFound, private.ErrServCommand{
diff --git a/routers/web/admin/auths.go b/routers/web/admin/auths.go
index 8ce45720f..d2953f753 100644
--- a/routers/web/admin/auths.go
+++ b/routers/web/admin/auths.go
@@ -271,6 +271,15 @@ func NewAuthSourcePost(ctx *context.Context) {
}
case auth.OAuth2:
config = parseOAuth2Config(form)
+ oauth2Config := config.(*oauth2.Source)
+ if oauth2Config.Provider == "openidConnect" {
+ discoveryURL, err := url.Parse(oauth2Config.OpenIDConnectAutoDiscoveryURL)
+ if err != nil || (discoveryURL.Scheme != "http" && discoveryURL.Scheme != "https") {
+ ctx.Data["Err_DiscoveryURL"] = true
+ ctx.RenderWithErr(ctx.Tr("admin.auths.invalid_openIdConnectAutoDiscoveryURL"), tplAuthNew, form)
+ return
+ }
+ }
case auth.SSPI:
var err error
config, err = parseSSPIConfig(ctx, form)
@@ -305,6 +314,10 @@ func NewAuthSourcePost(ctx *context.Context) {
if auth.IsErrSourceAlreadyExist(err) {
ctx.Data["Err_Name"] = true
ctx.RenderWithErr(ctx.Tr("admin.auths.login_source_exist", err.(auth.ErrSourceAlreadyExist).Name), tplAuthNew, form)
+ } else if oauth2.IsErrOpenIDConnectInitialize(err) {
+ ctx.Data["Err_DiscoveryURL"] = true
+ unwrapped := err.(oauth2.ErrOpenIDConnectInitialize).Unwrap()
+ ctx.RenderWithErr(ctx.Tr("admin.auths.unable_to_initialize_openid", unwrapped), tplAuthNew, form)
} else {
ctx.ServerError("auth.CreateSource", err)
}
@@ -389,6 +402,15 @@ func EditAuthSourcePost(ctx *context.Context) {
}
case auth.OAuth2:
config = parseOAuth2Config(form)
+ oauth2Config := config.(*oauth2.Source)
+ if oauth2Config.Provider == "openidConnect" {
+ discoveryURL, err := url.Parse(oauth2Config.OpenIDConnectAutoDiscoveryURL)
+ if err != nil || (discoveryURL.Scheme != "http" && discoveryURL.Scheme != "https") {
+ ctx.Data["Err_DiscoveryURL"] = true
+ ctx.RenderWithErr(ctx.Tr("admin.auths.invalid_openIdConnectAutoDiscoveryURL"), tplAuthEdit, form)
+ return
+ }
+ }
case auth.SSPI:
config, err = parseSSPIConfig(ctx, form)
if err != nil {
@@ -408,6 +430,7 @@ func EditAuthSourcePost(ctx *context.Context) {
if err := auth.UpdateSource(source); err != nil {
if oauth2.IsErrOpenIDConnectInitialize(err) {
ctx.Flash.Error(err.Error(), true)
+ ctx.Data["Err_DiscoveryURL"] = true
ctx.HTML(http.StatusOK, tplAuthEdit)
} else {
ctx.ServerError("UpdateSource", err)
diff --git a/routers/web/admin/repos.go b/routers/web/admin/repos.go
index 1c4754f6d..53b609af9 100644
--- a/routers/web/admin/repos.go
+++ b/routers/web/admin/repos.go
@@ -96,7 +96,7 @@ func UnadoptedRepos(ctx *context.Context) {
}
ctx.Data["Keyword"] = q
- repoNames, count, err := repo_service.ListUnadoptedRepositories(q, &opts)
+ repoNames, count, err := repo_service.ListUnadoptedRepositories(ctx, q, &opts)
if err != nil {
ctx.ServerError("ListUnadoptedRepositories", err)
}
@@ -148,7 +148,7 @@ func AdoptOrDeleteRepository(ctx *context.Context) {
if has || !isDir {
// Fallthrough to failure mode
} else if action == "adopt" {
- if _, err := repo_service.AdoptRepository(ctx.Doer, ctxUser, repo_module.CreateRepoOptions{
+ if _, err := repo_service.AdoptRepository(ctx, ctx.Doer, ctxUser, repo_module.CreateRepoOptions{
Name: dirSplit[1],
IsPrivate: true,
}); err != nil {
@@ -157,7 +157,7 @@ func AdoptOrDeleteRepository(ctx *context.Context) {
}
ctx.Flash.Success(ctx.Tr("repo.adopt_preexisting_success", dir))
} else if action == "delete" {
- if err := repo_service.DeleteUnadoptedRepository(ctx.Doer, ctxUser, dirSplit[1]); err != nil {
+ if err := repo_service.DeleteUnadoptedRepository(ctx, ctx.Doer, ctxUser, dirSplit[1]); err != nil {
ctx.ServerError("repository.AdoptRepository", err)
return
}
diff --git a/routers/web/base.go b/routers/web/base.go
index b0d8a7c3f..2eb0b6f39 100644
--- a/routers/web/base.go
+++ b/routers/web/base.go
@@ -19,6 +19,7 @@ import (
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/storage"
"code.gitea.io/gitea/modules/templates"
+ "code.gitea.io/gitea/modules/util"
"code.gitea.io/gitea/modules/web/middleware"
"code.gitea.io/gitea/modules/web/routing"
"code.gitea.io/gitea/services/auth"
@@ -44,7 +45,7 @@ func storageHandler(storageSetting setting.Storage, prefix string, objStore stor
routing.UpdateFuncInfo(req.Context(), funcInfo)
rPath := strings.TrimPrefix(req.URL.Path, "/"+prefix+"/")
- rPath = path.Clean("/" + strings.ReplaceAll(rPath, "\\", "/"))[1:]
+ rPath = util.CleanPath(strings.ReplaceAll(rPath, "\\", "/"))
u, err := objStore.URL(rPath, path.Base(rPath))
if err != nil {
@@ -80,7 +81,7 @@ func storageHandler(storageSetting setting.Storage, prefix string, objStore stor
routing.UpdateFuncInfo(req.Context(), funcInfo)
rPath := strings.TrimPrefix(req.URL.Path, "/"+prefix+"/")
- rPath = path.Clean("/" + strings.ReplaceAll(rPath, "\\", "/"))[1:]
+ rPath = util.CleanPath(strings.ReplaceAll(rPath, "\\", "/"))
if rPath == "" {
http.Error(w, "file not found", http.StatusNotFound)
return
@@ -158,7 +159,7 @@ func Recovery(ctx goctx.Context) func(next http.Handler) http.Handler {
store["SignedUserName"] = ""
}
- httpcache.AddCacheControlToHeader(w.Header(), 0, "no-transform")
+ httpcache.SetCacheControlInHeader(w.Header(), 0, "no-transform")
w.Header().Set(`X-Frame-Options`, setting.CORSConfig.XFrameOptions)
if !setting.IsProd {
diff --git a/routers/web/explore/repo.go b/routers/web/explore/repo.go
index 058971b9b..cc3af8cb2 100644
--- a/routers/web/explore/repo.go
+++ b/routers/web/explore/repo.go
@@ -33,7 +33,6 @@ type RepoSearchOptions struct {
// RenderRepoSearch render repositories search page
// This function is also used to render the Admin Repository Management page.
-// The isAdmin param should be set to true when rendering the Admin page.
func RenderRepoSearch(ctx *context.Context, opts *RepoSearchOptions) {
// Sitemap index for sitemap paths
page := int(ctx.ParamsInt64("idx"))
diff --git a/routers/web/healthcheck/check.go b/routers/web/healthcheck/check.go
index 1142a0aec..e11dd2aca 100644
--- a/routers/web/healthcheck/check.go
+++ b/routers/web/healthcheck/check.go
@@ -100,7 +100,7 @@ func checkDatabase(checks checks) status {
st.Time = getCheckTime()
}
- if setting.Database.UseSQLite3 && st.Status == pass {
+ if setting.Database.Type.IsSQLite3() && st.Status == pass {
if !setting.EnableSQLite3 {
st.Status = fail
st.Time = getCheckTime()
diff --git a/routers/web/org/home.go b/routers/web/org/home.go
index 4cc364acd..8c9cc8a9d 100644
--- a/routers/web/org/home.go
+++ b/routers/web/org/home.go
@@ -156,6 +156,7 @@ func Home(ctx *context.Context) {
pager.SetDefaultParams(ctx)
pager.AddParam(ctx, "language", "Language")
ctx.Data["Page"] = pager
+ ctx.Data["ContextUser"] = ctx.ContextUser
ctx.HTML(http.StatusOK, tplOrgHome)
}
diff --git a/routers/web/org/org_labels.go b/routers/web/org/org_labels.go
index e96627762..9ce05680d 100644
--- a/routers/web/org/org_labels.go
+++ b/routers/web/org/org_labels.go
@@ -9,6 +9,7 @@ import (
"code.gitea.io/gitea/models/db"
issues_model "code.gitea.io/gitea/models/issues"
"code.gitea.io/gitea/modules/context"
+ "code.gitea.io/gitea/modules/label"
repo_module "code.gitea.io/gitea/modules/repository"
"code.gitea.io/gitea/modules/web"
"code.gitea.io/gitea/services/forms"
@@ -103,8 +104,8 @@ func InitializeLabels(ctx *context.Context) {
}
if err := repo_module.InitializeLabels(ctx, ctx.Org.Organization.ID, form.TemplateName, true); err != nil {
- if repo_module.IsErrIssueLabelTemplateLoad(err) {
- originalErr := err.(repo_module.ErrIssueLabelTemplateLoad).OriginalError
+ if label.IsErrTemplateLoad(err) {
+ originalErr := err.(label.ErrTemplateLoad).OriginalError
ctx.Flash.Error(ctx.Tr("repo.issues.label_templates.fail_to_load_file", form.TemplateName, originalErr))
ctx.Redirect(ctx.Org.OrgLink + "/settings/labels")
return
diff --git a/routers/web/org/projects.go b/routers/web/org/projects.go
index 6449d12de..c9d63fec5 100644
--- a/routers/web/org/projects.go
+++ b/routers/web/org/projects.go
@@ -103,7 +103,7 @@ func Projects(ctx *context.Context) {
pager.AddParam(ctx, "state", "State")
ctx.Data["Page"] = pager
- ctx.Data["CanWriteProjects"] = canWriteUnit(ctx)
+ ctx.Data["CanWriteProjects"] = canWriteProjects(ctx)
ctx.Data["IsShowClosed"] = isShowClosed
ctx.Data["PageIsViewProjects"] = true
ctx.Data["SortType"] = sortType
@@ -111,7 +111,7 @@ func Projects(ctx *context.Context) {
ctx.HTML(http.StatusOK, tplProjects)
}
-func canWriteUnit(ctx *context.Context) bool {
+func canWriteProjects(ctx *context.Context) bool {
if ctx.ContextUser.IsOrganization() {
return ctx.Org.CanWriteUnit(ctx, unit.TypeProjects)
}
@@ -122,7 +122,8 @@ func canWriteUnit(ctx *context.Context) bool {
func NewProject(ctx *context.Context) {
ctx.Data["Title"] = ctx.Tr("repo.projects.new")
ctx.Data["BoardTypes"] = project_model.GetBoardConfig()
- ctx.Data["CanWriteProjects"] = canWriteUnit(ctx)
+ ctx.Data["CanWriteProjects"] = canWriteProjects(ctx)
+ ctx.Data["PageIsViewProjects"] = true
ctx.Data["HomeLink"] = ctx.ContextUser.HomeLink()
shared_user.RenderUserHeader(ctx)
ctx.HTML(http.StatusOK, tplProjectsNew)
@@ -135,7 +136,7 @@ func NewProjectPost(ctx *context.Context) {
shared_user.RenderUserHeader(ctx)
if ctx.HasError() {
- ctx.Data["CanWriteProjects"] = canWriteUnit(ctx)
+ ctx.Data["CanWriteProjects"] = canWriteProjects(ctx)
ctx.Data["PageIsViewProjects"] = true
ctx.Data["BoardTypes"] = project_model.GetBoardConfig()
ctx.HTML(http.StatusOK, tplProjectsNew)
@@ -193,7 +194,7 @@ func DeleteProject(ctx *context.Context) {
}
return
}
- if p.RepoID != ctx.Repo.Repository.ID {
+ if p.OwnerID != ctx.ContextUser.ID {
ctx.NotFound("", nil)
return
}
@@ -205,7 +206,7 @@ func DeleteProject(ctx *context.Context) {
}
ctx.JSON(http.StatusOK, map[string]interface{}{
- "redirect": ctx.Repo.RepoLink + "/projects",
+ "redirect": ctx.ContextUser.HomeLink() + "/-/projects",
})
}
@@ -214,7 +215,7 @@ func EditProject(ctx *context.Context) {
ctx.Data["Title"] = ctx.Tr("repo.projects.edit")
ctx.Data["PageIsEditProjects"] = true
ctx.Data["PageIsViewProjects"] = true
- ctx.Data["CanWriteProjects"] = canWriteUnit(ctx)
+ ctx.Data["CanWriteProjects"] = canWriteProjects(ctx)
shared_user.RenderUserHeader(ctx)
p, err := project_model.GetProjectByID(ctx, ctx.ParamsInt64(":id"))
@@ -226,13 +227,14 @@ func EditProject(ctx *context.Context) {
}
return
}
- if p.RepoID != ctx.Repo.Repository.ID {
+ if p.OwnerID != ctx.ContextUser.ID {
ctx.NotFound("", nil)
return
}
ctx.Data["title"] = p.Title
ctx.Data["content"] = p.Description
+ ctx.Data["redirect"] = ctx.FormString("redirect")
ctx.HTML(http.StatusOK, tplProjectsNew)
}
@@ -243,7 +245,7 @@ func EditProjectPost(ctx *context.Context) {
ctx.Data["Title"] = ctx.Tr("repo.projects.edit")
ctx.Data["PageIsEditProjects"] = true
ctx.Data["PageIsViewProjects"] = true
- ctx.Data["CanWriteProjects"] = canWriteUnit(ctx)
+ ctx.Data["CanWriteProjects"] = canWriteProjects(ctx)
shared_user.RenderUserHeader(ctx)
if ctx.HasError() {
@@ -260,7 +262,7 @@ func EditProjectPost(ctx *context.Context) {
}
return
}
- if p.RepoID != ctx.Repo.Repository.ID {
+ if p.OwnerID != ctx.ContextUser.ID {
ctx.NotFound("", nil)
return
}
@@ -273,7 +275,11 @@ func EditProjectPost(ctx *context.Context) {
}
ctx.Flash.Success(ctx.Tr("repo.projects.edit_success", p.Title))
- ctx.Redirect(ctx.Repo.RepoLink + "/projects")
+ if ctx.FormString("redirect") == "project" {
+ ctx.Redirect(p.Link())
+ } else {
+ ctx.Redirect(ctx.ContextUser.HomeLink() + "/-/projects")
+ }
}
// ViewProject renders the project board for a project
@@ -332,7 +338,7 @@ func ViewProject(ctx *context.Context) {
project.RenderedContent = project.Description
ctx.Data["LinkedPRs"] = linkedPrsMap
ctx.Data["PageIsViewProjects"] = true
- ctx.Data["CanWriteProjects"] = canWriteUnit(ctx)
+ ctx.Data["CanWriteProjects"] = canWriteProjects(ctx)
ctx.Data["Project"] = project
ctx.Data["IssuesMap"] = issuesMap
ctx.Data["Boards"] = boards
diff --git a/routers/web/org/setting.go b/routers/web/org/setting.go
index 5c9b7967c..b57ebfbcd 100644
--- a/routers/web/org/setting.go
+++ b/routers/web/org/setting.go
@@ -137,7 +137,7 @@ func SettingsPost(ctx *context.Context) {
}
for _, repo := range repos {
repo.OwnerName = org.Name
- if err := repo_service.UpdateRepository(repo, true); err != nil {
+ if err := repo_service.UpdateRepository(ctx, repo, true); err != nil {
ctx.ServerError("UpdateRepository", err)
return
}
@@ -218,9 +218,9 @@ func Webhooks(ctx *context.Context) {
ctx.Data["BaseLinkNew"] = ctx.Org.OrgLink + "/settings/hooks"
ctx.Data["Description"] = ctx.Tr("org.settings.hooks_desc")
- ws, err := webhook.ListWebhooksByOpts(ctx, &webhook.ListWebhookOptions{OrgID: ctx.Org.Organization.ID})
+ ws, err := webhook.ListWebhooksByOpts(ctx, &webhook.ListWebhookOptions{OwnerID: ctx.Org.Organization.ID})
if err != nil {
- ctx.ServerError("GetWebhooksByOrgId", err)
+ ctx.ServerError("ListWebhooksByOpts", err)
return
}
@@ -230,8 +230,8 @@ func Webhooks(ctx *context.Context) {
// DeleteWebhook response for delete webhook
func DeleteWebhook(ctx *context.Context) {
- if err := webhook.DeleteWebhookByOrgID(ctx.Org.Organization.ID, ctx.FormInt64("id")); err != nil {
- ctx.Flash.Error("DeleteWebhookByOrgID: " + err.Error())
+ if err := webhook.DeleteWebhookByOwnerID(ctx.Org.Organization.ID, ctx.FormInt64("id")); err != nil {
+ ctx.Flash.Error("DeleteWebhookByOwnerID: " + err.Error())
} else {
ctx.Flash.Success(ctx.Tr("repo.settings.webhook_deletion_success"))
}
diff --git a/routers/web/repo/actions/view.go b/routers/web/repo/actions/view.go
index dd2750f90..35b99d577 100644
--- a/routers/web/repo/actions/view.go
+++ b/routers/web/repo/actions/view.go
@@ -15,6 +15,7 @@ import (
"code.gitea.io/gitea/models/unit"
"code.gitea.io/gitea/modules/actions"
context_module "code.gitea.io/gitea/modules/context"
+ "code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/timeutil"
"code.gitea.io/gitea/modules/util"
"code.gitea.io/gitea/modules/web"
@@ -51,6 +52,7 @@ type ViewResponse struct {
Run struct {
Link string `json:"link"`
Title string `json:"title"`
+ Status string `json:"status"`
CanCancel bool `json:"canCancel"`
CanApprove bool `json:"canApprove"` // the run needs an approval and the doer has permission to approve
Done bool `json:"done"`
@@ -111,6 +113,7 @@ func ViewPost(ctx *context_module.Context) {
resp.State.Run.CanApprove = run.NeedApproval && ctx.Repo.CanWrite(unit.TypeActions)
resp.State.Run.Done = run.Status.IsDone()
resp.State.Run.Jobs = make([]*ViewJob, 0, len(jobs)) // marshal to '[]' instead fo 'null' in json
+ resp.State.Run.Status = run.Status.String()
for _, v := range jobs {
resp.State.Run.Jobs = append(resp.State.Run.Jobs, &ViewJob{
ID: v.ID,
@@ -212,15 +215,18 @@ func Rerun(ctx *context_module.Context) {
job.Stopped = 0
if err := db.WithTx(ctx, func(ctx context.Context) error {
- if _, err := actions_model.UpdateRunJob(ctx, job, builder.Eq{"status": status}, "task_id", "status", "started", "stopped"); err != nil {
- return err
- }
- return actions_service.CreateCommitStatus(ctx, job)
+ _, err := actions_model.UpdateRunJob(ctx, job, builder.Eq{"status": status}, "task_id", "status", "started", "stopped")
+ return err
}); err != nil {
ctx.Error(http.StatusInternalServerError, err.Error())
return
}
+ if err := actions_service.CreateCommitStatus(ctx, job); err != nil {
+ log.Error("Update commit status for job %v failed: %v", job.ID, err)
+ // go on
+ }
+
ctx.JSON(http.StatusOK, struct{}{})
}
@@ -253,9 +259,6 @@ func Cancel(ctx *context_module.Context) {
if err := actions_model.StopTask(ctx, job.TaskID, actions_model.StatusCancelled); err != nil {
return err
}
- if err := actions_service.CreateCommitStatus(ctx, job); err != nil {
- return err
- }
}
return nil
}); err != nil {
@@ -263,6 +266,13 @@ func Cancel(ctx *context_module.Context) {
return
}
+ for _, job := range jobs {
+ if err := actions_service.CreateCommitStatus(ctx, job); err != nil {
+ log.Error("Update commit status for job %v failed: %v", job.ID, err)
+ // go on
+ }
+ }
+
ctx.JSON(http.StatusOK, struct{}{})
}
diff --git a/routers/web/repo/attachment.go b/routers/web/repo/attachment.go
index 589632ad6..c6d8828fa 100644
--- a/routers/web/repo/attachment.go
+++ b/routers/web/repo/attachment.go
@@ -44,7 +44,7 @@ func uploadAttachment(ctx *context.Context, repoID int64, allowedTypes string) {
}
defer file.Close()
- attach, err := attachment.UploadAttachment(file, allowedTypes, &repo_model.Attachment{
+ attach, err := attachment.UploadAttachment(file, allowedTypes, header.Size, &repo_model.Attachment{
Name: header.Filename,
UploaderID: ctx.Doer.ID,
RepoID: repoID,
diff --git a/routers/web/repo/branch.go b/routers/web/repo/branch.go
index b34ccf853..d23367e04 100644
--- a/routers/web/repo/branch.go
+++ b/routers/web/repo/branch.go
@@ -91,7 +91,7 @@ func DeleteBranchPost(ctx *context.Context) {
defer redirect(ctx)
branchName := ctx.FormString("name")
- if err := repo_service.DeleteBranch(ctx.Doer, ctx.Repo.Repository, ctx.Repo.GitRepo, branchName); err != nil {
+ if err := repo_service.DeleteBranch(ctx, ctx.Doer, ctx.Repo.Repository, ctx.Repo.GitRepo, branchName); err != nil {
switch {
case git.IsErrBranchNotExist(err):
log.Debug("DeleteBranch: Can't delete non existing branch '%s'", branchName)
diff --git a/routers/web/repo/editor.go b/routers/web/repo/editor.go
index e5ba4ad2c..4f208098e 100644
--- a/routers/web/repo/editor.go
+++ b/routers/web/repo/editor.go
@@ -726,7 +726,7 @@ func UploadFilePost(ctx *context.Context) {
func cleanUploadFileName(name string) string {
// Rebase the filename
- name = strings.Trim(path.Clean("/"+name), "/")
+ name = strings.Trim(util.CleanPath(name), "/")
// Git disallows any filenames to have a .git directory in them.
for _, part := range strings.Split(name, "/") {
if strings.ToLower(part) == ".git" {
diff --git a/routers/web/repo/http.go b/routers/web/repo/http.go
index 9d4ffccc6..cd32d9953 100644
--- a/routers/web/repo/http.go
+++ b/routers/web/repo/http.go
@@ -228,7 +228,7 @@ func httpBase(ctx *context.Context) (h *serviceHandler) {
}
if !p.CanAccess(accessMode, unitType) {
- ctx.PlainText(http.StatusForbidden, "User permission denied")
+ ctx.PlainText(http.StatusNotFound, "Repository not found")
return
}
}
@@ -276,7 +276,7 @@ func httpBase(ctx *context.Context) (h *serviceHandler) {
return
}
- repo, err = repo_service.PushCreateRepo(ctx.Doer, owner, reponame)
+ repo, err = repo_service.PushCreateRepo(ctx, ctx.Doer, owner, reponame)
if err != nil {
log.Error("pushCreateRepo: %v", err)
ctx.Status(http.StatusNotFound)
diff --git a/routers/web/repo/issue.go b/routers/web/repo/issue.go
index f8cc4daeb..f937d93d0 100644
--- a/routers/web/repo/issue.go
+++ b/routers/web/repo/issue.go
@@ -589,7 +589,7 @@ func RetrieveRepoReviewers(ctx *context.Context, repo *repo_model.Repository, is
return
}
- teamReviewers, err = repo_service.GetReviewerTeams(repo)
+ teamReviewers, err = repo_service.GetReviewerTeams(ctx, repo)
if err != nil {
ctx.ServerError("GetReviewerTeams", err)
return
@@ -1420,11 +1420,12 @@ func ViewIssue(ctx *context.Context) {
}
var (
- role issues_model.RoleDescriptor
- ok bool
- marked = make(map[int64]issues_model.RoleDescriptor)
- comment *issues_model.Comment
- participants = make([]*user_model.User, 1, 10)
+ role issues_model.RoleDescriptor
+ ok bool
+ marked = make(map[int64]issues_model.RoleDescriptor)
+ comment *issues_model.Comment
+ participants = make([]*user_model.User, 1, 10)
+ latestCloseCommentID int64
)
if ctx.Repo.Repository.IsTimetrackerEnabled(ctx) {
if ctx.IsSigned {
@@ -1432,25 +1433,16 @@ func ViewIssue(ctx *context.Context) {
ctx.Data["IsStopwatchRunning"] = issues_model.StopwatchExists(ctx.Doer.ID, issue.ID)
if !ctx.Data["IsStopwatchRunning"].(bool) {
var exists bool
- var sw *issues_model.Stopwatch
- if exists, sw, err = issues_model.HasUserStopwatch(ctx, ctx.Doer.ID); err != nil {
+ var swIssue *issues_model.Issue
+ if exists, _, swIssue, err = issues_model.HasUserStopwatch(ctx, ctx.Doer.ID); err != nil {
ctx.ServerError("HasUserStopwatch", err)
return
}
ctx.Data["HasUserStopwatch"] = exists
if exists {
// Add warning if the user has already a stopwatch
- var otherIssue *issues_model.Issue
- if otherIssue, err = issues_model.GetIssueByID(ctx, sw.IssueID); err != nil {
- ctx.ServerError("GetIssueByID", err)
- return
- }
- if err = otherIssue.LoadRepo(ctx); err != nil {
- ctx.ServerError("LoadRepo", err)
- return
- }
// Add link to the issue of the already running stopwatch
- ctx.Data["OtherStopwatchURL"] = otherIssue.Link()
+ ctx.Data["OtherStopwatchURL"] = swIssue.Link()
}
}
ctx.Data["CanUseTimetracker"] = ctx.Repo.CanUseTimetracker(issue, ctx.Doer)
@@ -1631,9 +1623,15 @@ func ViewIssue(ctx *context.Context) {
comment.Type == issues_model.CommentTypeStopTracking {
// drop error since times could be pruned from DB..
_ = comment.LoadTime()
+ } else if comment.Type == issues_model.CommentTypeClose {
+ // record ID of latest closed comment.
+ // if PR is closed, the comments whose type is CommentTypePullRequestPush(29) after latestCloseCommentID won't be rendered.
+ latestCloseCommentID = comment.ID
}
}
+ ctx.Data["LatestCloseCommentID"] = latestCloseCommentID
+
// Combine multiple label assignments into a single comment
combineLabelComments(issue)
@@ -2961,7 +2959,7 @@ func ChangeIssueReaction(ctx *context.Context) {
}
html, err := ctx.RenderToString(tplReactions, map[string]interface{}{
- "ctx": ctx.Data,
+ "ctxData": ctx.Data,
"ActionURL": fmt.Sprintf("%s/issues/%d/reactions", ctx.Repo.RepoLink, issue.Index),
"Reactions": issue.Reactions.GroupByType(),
})
@@ -3063,7 +3061,7 @@ func ChangeCommentReaction(ctx *context.Context) {
}
html, err := ctx.RenderToString(tplReactions, map[string]interface{}{
- "ctx": ctx.Data,
+ "ctxData": ctx.Data,
"ActionURL": fmt.Sprintf("%s/comments/%d/reactions", ctx.Repo.RepoLink, comment.ID),
"Reactions": comment.Reactions.GroupByType(),
})
@@ -3185,7 +3183,7 @@ func updateAttachments(ctx *context.Context, item interface{}, files []string) e
func attachmentsHTML(ctx *context.Context, attachments []*repo_model.Attachment, content string) string {
attachHTML, err := ctx.RenderToString(tplAttachment, map[string]interface{}{
- "ctx": ctx.Data,
+ "ctxData": ctx.Data,
"Attachments": attachments,
"Content": content,
})
diff --git a/routers/web/repo/issue_label.go b/routers/web/repo/issue_label.go
index d4fece9f0..31bf85fed 100644
--- a/routers/web/repo/issue_label.go
+++ b/routers/web/repo/issue_label.go
@@ -11,6 +11,7 @@ import (
"code.gitea.io/gitea/models/organization"
"code.gitea.io/gitea/modules/base"
"code.gitea.io/gitea/modules/context"
+ "code.gitea.io/gitea/modules/label"
"code.gitea.io/gitea/modules/log"
repo_module "code.gitea.io/gitea/modules/repository"
"code.gitea.io/gitea/modules/web"
@@ -41,8 +42,8 @@ func InitializeLabels(ctx *context.Context) {
}
if err := repo_module.InitializeLabels(ctx, ctx.Repo.Repository.ID, form.TemplateName, false); err != nil {
- if repo_module.IsErrIssueLabelTemplateLoad(err) {
- originalErr := err.(repo_module.ErrIssueLabelTemplateLoad).OriginalError
+ if label.IsErrTemplateLoad(err) {
+ originalErr := err.(label.ErrTemplateLoad).OriginalError
ctx.Flash.Error(ctx.Tr("repo.issues.label_templates.fail_to_load_file", form.TemplateName, originalErr))
ctx.Redirect(ctx.Repo.RepoLink + "/labels")
return
diff --git a/routers/web/repo/issue_stopwatch.go b/routers/web/repo/issue_stopwatch.go
index 3d20b08b4..3e715437e 100644
--- a/routers/web/repo/issue_stopwatch.go
+++ b/routers/web/repo/issue_stopwatch.go
@@ -86,7 +86,7 @@ func GetActiveStopwatch(ctx *context.Context) {
return
}
- _, sw, err := issues_model.HasUserStopwatch(ctx, ctx.Doer.ID)
+ _, sw, issue, err := issues_model.HasUserStopwatch(ctx, ctx.Doer.ID)
if err != nil {
ctx.ServerError("HasUserStopwatch", err)
return
@@ -96,18 +96,6 @@ func GetActiveStopwatch(ctx *context.Context) {
return
}
- issue, err := issues_model.GetIssueByID(ctx, sw.IssueID)
- if err != nil || issue == nil {
- if !issues_model.IsErrIssueNotExist(err) {
- ctx.ServerError("GetIssueByID", err)
- }
- return
- }
- if err = issue.LoadRepo(ctx); err != nil {
- ctx.ServerError("LoadRepo", err)
- return
- }
-
ctx.Data["ActiveStopwatch"] = StopwatchTmplInfo{
issue.Link(),
issue.Repo.FullName(),
diff --git a/routers/web/repo/lfs.go b/routers/web/repo/lfs.go
index 869a69c37..43f552798 100644
--- a/routers/web/repo/lfs.go
+++ b/routers/web/repo/lfs.go
@@ -207,7 +207,7 @@ func LFSLockFile(ctx *context.Context) {
ctx.Redirect(ctx.Repo.RepoLink + "/settings/lfs/locks")
return
}
- lockPath = path.Clean("/" + lockPath)[1:]
+ lockPath = util.CleanPath(lockPath)
if len(lockPath) == 0 {
ctx.Flash.Error(ctx.Tr("repo.settings.lfs_invalid_locking_path", originalPath))
ctx.Redirect(ctx.Repo.RepoLink + "/settings/lfs/locks")
diff --git a/routers/web/repo/projects.go b/routers/web/repo/projects.go
index 967b81c60..29bd59c7a 100644
--- a/routers/web/repo/projects.go
+++ b/routers/web/repo/projects.go
@@ -235,6 +235,7 @@ func EditProject(ctx *context.Context) {
ctx.Data["title"] = p.Title
ctx.Data["content"] = p.Description
ctx.Data["card_type"] = p.CardType
+ ctx.Data["redirect"] = ctx.FormString("redirect")
ctx.HTML(http.StatusOK, tplProjectsNew)
}
@@ -275,7 +276,11 @@ func EditProjectPost(ctx *context.Context) {
}
ctx.Flash.Success(ctx.Tr("repo.projects.edit_success", p.Title))
- ctx.Redirect(ctx.Repo.RepoLink + "/projects")
+ if ctx.FormString("redirect") == "project" {
+ ctx.Redirect(p.Link())
+ } else {
+ ctx.Redirect(ctx.Repo.RepoLink + "/projects")
+ }
}
// ViewProject renders the project board for a project
diff --git a/routers/web/repo/pull.go b/routers/web/repo/pull.go
index 38b9f22cb..4f9968773 100644
--- a/routers/web/repo/pull.go
+++ b/routers/web/repo/pull.go
@@ -587,7 +587,7 @@ func PrepareViewPullInfo(ctx *context.Context, issue *issues_model.Issue) *git.C
ctx.Data["HeadBranchCommitID"] = headBranchSha
ctx.Data["PullHeadCommitID"] = sha
- if pull.HeadRepo == nil || !headBranchExist || headBranchSha != sha {
+ if pull.HeadRepo == nil || !headBranchExist || (!pull.Issue.IsClosed && (headBranchSha != sha)) {
ctx.Data["IsPullRequestBroken"] = true
if pull.IsSameRepo() {
ctx.Data["HeadTarget"] = pull.HeadBranch
@@ -1399,7 +1399,7 @@ func CleanUpPullRequest(ctx *context.Context) {
func deleteBranch(ctx *context.Context, pr *issues_model.PullRequest, gitRepo *git.Repository) {
fullBranchName := pr.HeadRepo.FullName() + ":" + pr.HeadBranch
- if err := repo_service.DeleteBranch(ctx.Doer, pr.HeadRepo, gitRepo, pr.HeadBranch); err != nil {
+ if err := repo_service.DeleteBranch(ctx, ctx.Doer, pr.HeadRepo, gitRepo, pr.HeadBranch); err != nil {
switch {
case git.IsErrBranchNotExist(err):
ctx.Flash.Error(ctx.Tr("repo.branch.deletion_failed", fullBranchName))
diff --git a/routers/web/repo/pull_review.go b/routers/web/repo/pull_review.go
index d43a786c5..90cfd5bfc 100644
--- a/routers/web/repo/pull_review.go
+++ b/routers/web/repo/pull_review.go
@@ -77,7 +77,7 @@ func CreateCodeComment(ctx *context.Context) {
signedLine,
form.Content,
form.TreePath,
- form.IsReview,
+ !form.SingleReview,
form.Reply,
form.LatestCommitID,
)
diff --git a/routers/web/repo/repo.go b/routers/web/repo/repo.go
index aeac7cfa3..d72fd39f9 100644
--- a/routers/web/repo/repo.go
+++ b/routers/web/repo/repo.go
@@ -248,14 +248,14 @@ func CreatePost(ctx *context.Context) {
return
}
- repo, err = repo_service.GenerateRepository(ctx.Doer, ctxUser, templateRepo, opts)
+ repo, err = repo_service.GenerateRepository(ctx, ctx.Doer, ctxUser, templateRepo, opts)
if err == nil {
log.Trace("Repository generated [%d]: %s/%s", repo.ID, ctxUser.Name, repo.Name)
ctx.Redirect(repo.Link())
return
}
} else {
- repo, err = repo_service.CreateRepository(ctx.Doer, ctxUser, repo_module.CreateRepoOptions{
+ repo, err = repo_service.CreateRepository(ctx, ctx.Doer, ctxUser, repo_module.CreateRepoOptions{
Name: form.RepoName,
Description: form.Description,
Gitignores: form.Gitignores,
@@ -302,7 +302,7 @@ func Action(ctx *context.Context) {
ctx.Repo.Repository.Description = ctx.FormString("desc")
ctx.Repo.Repository.Website = ctx.FormString("site")
- err = repo_service.UpdateRepository(ctx.Repo.Repository, false)
+ err = repo_service.UpdateRepository(ctx, ctx.Repo.Repository, false)
}
if err != nil {
diff --git a/routers/web/repo/setting.go b/routers/web/repo/setting.go
index 387a91741..0c36503b3 100644
--- a/routers/web/repo/setting.go
+++ b/routers/web/repo/setting.go
@@ -134,7 +134,7 @@ func SettingsPost(ctx *context.Context) {
ctx.Repo.GitRepo.Close()
ctx.Repo.GitRepo = nil
}
- if err := repo_service.ChangeRepositoryName(ctx.Doer, repo, newRepoName); err != nil {
+ if err := repo_service.ChangeRepositoryName(ctx, ctx.Doer, repo, newRepoName); err != nil {
ctx.Data["Err_RepoName"] = true
switch {
case repo_model.IsErrRepoAlreadyExist(err):
@@ -183,7 +183,7 @@ func SettingsPost(ctx *context.Context) {
}
repo.IsPrivate = form.Private
- if err := repo_service.UpdateRepository(repo, visibilityChanged); err != nil {
+ if err := repo_service.UpdateRepository(ctx, repo, visibilityChanged); err != nil {
ctx.ServerError("UpdateRepository", err)
return
}
@@ -541,7 +541,7 @@ func SettingsPost(ctx *context.Context) {
return
}
if repoChanged {
- if err := repo_service.UpdateRepository(repo, false); err != nil {
+ if err := repo_service.UpdateRepository(ctx, repo, false); err != nil {
ctx.ServerError("UpdateRepository", err)
return
}
@@ -560,7 +560,7 @@ func SettingsPost(ctx *context.Context) {
}
if changed {
- if err := repo_service.UpdateRepository(repo, false); err != nil {
+ if err := repo_service.UpdateRepository(ctx, repo, false); err != nil {
ctx.ServerError("UpdateRepository", err)
return
}
@@ -580,7 +580,7 @@ func SettingsPost(ctx *context.Context) {
repo.IsFsckEnabled = form.EnableHealthCheck
}
- if err := repo_service.UpdateRepository(repo, false); err != nil {
+ if err := repo_service.UpdateRepository(ctx, repo, false); err != nil {
ctx.ServerError("UpdateRepository", err)
return
}
@@ -672,7 +672,7 @@ func SettingsPost(ctx *context.Context) {
return
}
- if err := repo_service.ConvertForkToNormalRepository(repo); err != nil {
+ if err := repo_service.ConvertForkToNormalRepository(ctx, repo); err != nil {
log.Error("Unable to convert repository %-v from fork. Error: %v", repo, err)
ctx.ServerError("Convert Fork", err)
return
@@ -1244,7 +1244,7 @@ func UpdateAvatarSetting(ctx *context.Context, form forms.AvatarForm) error {
if !(st.IsImage() && !st.IsSvgImage()) {
return errors.New(ctx.Tr("settings.uploaded_avatar_not_a_image"))
}
- if err = repo_service.UploadAvatar(ctxRepo, data); err != nil {
+ if err = repo_service.UploadAvatar(ctx, ctxRepo, data); err != nil {
return fmt.Errorf("UploadAvatar: %w", err)
}
return nil
@@ -1264,7 +1264,7 @@ func SettingsAvatar(ctx *context.Context) {
// SettingsDeleteAvatar delete repository avatar
func SettingsDeleteAvatar(ctx *context.Context) {
- if err := repo_service.DeleteAvatar(ctx.Repo.Repository); err != nil {
+ if err := repo_service.DeleteAvatar(ctx, ctx.Repo.Repository); err != nil {
ctx.Flash.Error(fmt.Sprintf("DeleteAvatar: %v", err))
}
ctx.Redirect(ctx.Repo.RepoLink + "/settings")
diff --git a/routers/web/repo/setting_protected_branch.go b/routers/web/repo/setting_protected_branch.go
index 0a8c39fef..34e84c465 100644
--- a/routers/web/repo/setting_protected_branch.go
+++ b/routers/web/repo/setting_protected_branch.go
@@ -356,7 +356,7 @@ func RenameBranchPost(ctx *context.Context) {
return
}
- msg, err := repository.RenameBranch(ctx.Repo.Repository, ctx.Doer, ctx.Repo.GitRepo, form.From, form.To)
+ msg, err := repository.RenameBranch(ctx, ctx.Repo.Repository, ctx.Doer, ctx.Repo.GitRepo, form.From, form.To)
if err != nil {
ctx.ServerError("RenameBranch", err)
return
diff --git a/routers/web/repo/view.go b/routers/web/repo/view.go
index e3c61fa40..8663e1138 100644
--- a/routers/web/repo/view.go
+++ b/routers/web/repo/view.go
@@ -186,7 +186,7 @@ func renderDirectory(ctx *context.Context, treeLink string) {
return
}
- renderReadmeFile(ctx, readmeFile, treeLink)
+ renderReadmeFile(ctx, readmeFile, fmt.Sprintf("%s/%s", treeLink, readmeFile.name))
}
// localizedExtensions prepends the provided language code with and without a
diff --git a/routers/web/repo/webhook.go b/routers/web/repo/webhook.go
index d27d0f1bf..f30588967 100644
--- a/routers/web/repo/webhook.go
+++ b/routers/web/repo/webhook.go
@@ -33,6 +33,7 @@ const (
tplHooks base.TplName = "repo/settings/webhook/base"
tplHookNew base.TplName = "repo/settings/webhook/new"
tplOrgHookNew base.TplName = "org/settings/hook_new"
+ tplUserHookNew base.TplName = "user/settings/hook_new"
tplAdminHookNew base.TplName = "admin/hook_new"
)
@@ -54,8 +55,8 @@ func Webhooks(ctx *context.Context) {
ctx.HTML(http.StatusOK, tplHooks)
}
-type orgRepoCtx struct {
- OrgID int64
+type ownerRepoCtx struct {
+ OwnerID int64
RepoID int64
IsAdmin bool
IsSystemWebhook bool
@@ -64,10 +65,10 @@ type orgRepoCtx struct {
NewTemplate base.TplName
}
-// getOrgRepoCtx determines whether this is a repo, organization, or admin (both default and system) context.
-func getOrgRepoCtx(ctx *context.Context) (*orgRepoCtx, error) {
- if len(ctx.Repo.RepoLink) > 0 {
- return &orgRepoCtx{
+// getOwnerRepoCtx determines whether this is a repo, owner, or admin (both default and system) context.
+func getOwnerRepoCtx(ctx *context.Context) (*ownerRepoCtx, error) {
+ if is, ok := ctx.Data["IsRepositoryWebhook"]; ok && is.(bool) {
+ return &ownerRepoCtx{
RepoID: ctx.Repo.Repository.ID,
Link: path.Join(ctx.Repo.RepoLink, "settings/hooks"),
LinkNew: path.Join(ctx.Repo.RepoLink, "settings/hooks"),
@@ -75,37 +76,35 @@ func getOrgRepoCtx(ctx *context.Context) (*orgRepoCtx, error) {
}, nil
}
- if len(ctx.Org.OrgLink) > 0 {
- return &orgRepoCtx{
- OrgID: ctx.Org.Organization.ID,
+ if is, ok := ctx.Data["IsOrganizationWebhook"]; ok && is.(bool) {
+ return &ownerRepoCtx{
+ OwnerID: ctx.ContextUser.ID,
Link: path.Join(ctx.Org.OrgLink, "settings/hooks"),
LinkNew: path.Join(ctx.Org.OrgLink, "settings/hooks"),
NewTemplate: tplOrgHookNew,
}, nil
}
- if ctx.Doer.IsAdmin {
- // Are we looking at default webhooks?
- if ctx.Params(":configType") == "default-hooks" {
- return &orgRepoCtx{
- IsAdmin: true,
- Link: path.Join(setting.AppSubURL, "/admin/hooks"),
- LinkNew: path.Join(setting.AppSubURL, "/admin/default-hooks"),
- NewTemplate: tplAdminHookNew,
- }, nil
- }
+ if is, ok := ctx.Data["IsUserWebhook"]; ok && is.(bool) {
+ return &ownerRepoCtx{
+ OwnerID: ctx.Doer.ID,
+ Link: path.Join(setting.AppSubURL, "/user/settings/hooks"),
+ LinkNew: path.Join(setting.AppSubURL, "/user/settings/hooks"),
+ NewTemplate: tplUserHookNew,
+ }, nil
+ }
- // Must be system webhooks instead
- return &orgRepoCtx{
+ if ctx.Doer.IsAdmin {
+ return &ownerRepoCtx{
IsAdmin: true,
- IsSystemWebhook: true,
+ IsSystemWebhook: ctx.Params(":configType") == "system-hooks",
Link: path.Join(setting.AppSubURL, "/admin/hooks"),
LinkNew: path.Join(setting.AppSubURL, "/admin/system-hooks"),
NewTemplate: tplAdminHookNew,
}, nil
}
- return nil, errors.New("unable to set OrgRepo context")
+ return nil, errors.New("unable to set OwnerRepo context")
}
func checkHookType(ctx *context.Context) string {
@@ -122,9 +121,9 @@ func WebhooksNew(ctx *context.Context) {
ctx.Data["Title"] = ctx.Tr("repo.settings.add_webhook")
ctx.Data["Webhook"] = webhook.Webhook{HookEvent: &webhook_module.HookEvent{}}
- orCtx, err := getOrgRepoCtx(ctx)
+ orCtx, err := getOwnerRepoCtx(ctx)
if err != nil {
- ctx.ServerError("getOrgRepoCtx", err)
+ ctx.ServerError("getOwnerRepoCtx", err)
return
}
@@ -205,9 +204,9 @@ func createWebhook(ctx *context.Context, params webhookParams) {
ctx.Data["Webhook"] = webhook.Webhook{HookEvent: &webhook_module.HookEvent{}}
ctx.Data["HookType"] = params.Type
- orCtx, err := getOrgRepoCtx(ctx)
+ orCtx, err := getOwnerRepoCtx(ctx)
if err != nil {
- ctx.ServerError("getOrgRepoCtx", err)
+ ctx.ServerError("getOwnerRepoCtx", err)
return
}
ctx.Data["BaseLink"] = orCtx.LinkNew
@@ -236,7 +235,7 @@ func createWebhook(ctx *context.Context, params webhookParams) {
IsActive: params.WebhookForm.Active,
Type: params.Type,
Meta: string(meta),
- OrgID: orCtx.OrgID,
+ OwnerID: orCtx.OwnerID,
IsSystemWebhook: orCtx.IsSystemWebhook,
}
err = w.SetHeaderAuthorization(params.WebhookForm.AuthorizationHeader)
@@ -577,19 +576,19 @@ func packagistHookParams(ctx *context.Context) webhookParams {
}
}
-func checkWebhook(ctx *context.Context) (*orgRepoCtx, *webhook.Webhook) {
- orCtx, err := getOrgRepoCtx(ctx)
+func checkWebhook(ctx *context.Context) (*ownerRepoCtx, *webhook.Webhook) {
+ orCtx, err := getOwnerRepoCtx(ctx)
if err != nil {
- ctx.ServerError("getOrgRepoCtx", err)
+ ctx.ServerError("getOwnerRepoCtx", err)
return nil, nil
}
ctx.Data["BaseLink"] = orCtx.Link
var w *webhook.Webhook
if orCtx.RepoID > 0 {
- w, err = webhook.GetWebhookByRepoID(ctx.Repo.Repository.ID, ctx.ParamsInt64(":id"))
- } else if orCtx.OrgID > 0 {
- w, err = webhook.GetWebhookByOrgID(ctx.Org.Organization.ID, ctx.ParamsInt64(":id"))
+ w, err = webhook.GetWebhookByRepoID(orCtx.RepoID, ctx.ParamsInt64(":id"))
+ } else if orCtx.OwnerID > 0 {
+ w, err = webhook.GetWebhookByOwnerID(orCtx.OwnerID, ctx.ParamsInt64(":id"))
} else if orCtx.IsAdmin {
w, err = webhook.GetSystemOrDefaultWebhook(ctx, ctx.ParamsInt64(":id"))
}
diff --git a/routers/web/shared/user/header.go b/routers/web/shared/user/header.go
index 94e59e2a4..05e45f999 100644
--- a/routers/web/shared/user/header.go
+++ b/routers/web/shared/user/header.go
@@ -9,6 +9,8 @@ import (
)
func RenderUserHeader(ctx *context.Context) {
+ ctx.Data["IsProjectEnabled"] = true
+ ctx.Data["IsPackageEnabled"] = setting.Packages.Enabled
ctx.Data["IsRepoIndexerEnabled"] = setting.Indexer.RepoIndexerEnabled
ctx.Data["ContextUser"] = ctx.ContextUser
}
diff --git a/routers/web/user/avatar.go b/routers/web/user/avatar.go
index 2dba74822..7ad65cd51 100644
--- a/routers/web/user/avatar.go
+++ b/routers/web/user/avatar.go
@@ -17,7 +17,7 @@ func cacheableRedirect(ctx *context.Context, location string) {
// here we should not use `setting.StaticCacheTime`, it is pretty long (default: 6 hours)
// we must make sure the redirection cache time is short enough, otherwise a user won't see the updated avatar in 6 hours
// it's OK to make the cache time short, it is only a redirection, and doesn't cost much to make a new request
- httpcache.AddCacheControlToHeader(ctx.Resp.Header(), 5*time.Minute)
+ httpcache.SetCacheControlInHeader(ctx.Resp.Header(), 5*time.Minute)
ctx.Redirect(location)
}
diff --git a/routers/web/user/code.go b/routers/web/user/code.go
index 81e3e65b4..b3adbcb8d 100644
--- a/routers/web/user/code.go
+++ b/routers/web/user/code.go
@@ -24,6 +24,7 @@ func CodeSearch(ctx *context.Context) {
return
}
+ ctx.Data["IsProjectEnabled"] = true
ctx.Data["IsPackageEnabled"] = setting.Packages.Enabled
ctx.Data["IsRepoIndexerEnabled"] = setting.Indexer.RepoIndexerEnabled
ctx.Data["Title"] = ctx.Tr("explore.code")
diff --git a/routers/web/user/profile.go b/routers/web/user/profile.go
index 5d34df79b..e7f200aa8 100644
--- a/routers/web/user/profile.go
+++ b/routers/web/user/profile.go
@@ -305,6 +305,7 @@ func Profile(ctx *context.Context) {
pager.AddParam(ctx, "date", "Date")
}
ctx.Data["Page"] = pager
+ ctx.Data["IsProjectEnabled"] = true
ctx.Data["IsPackageEnabled"] = setting.Packages.Enabled
ctx.Data["IsRepoIndexerEnabled"] = setting.Indexer.RepoIndexerEnabled
diff --git a/routers/web/user/setting/adopt.go b/routers/web/user/setting/adopt.go
index 844d6fa16..c9995e727 100644
--- a/routers/web/user/setting/adopt.go
+++ b/routers/web/user/setting/adopt.go
@@ -45,7 +45,7 @@ func AdoptOrDeleteRepository(ctx *context.Context) {
if has || !isDir {
// Fallthrough to failure mode
} else if action == "adopt" && allowAdopt {
- if _, err := repo_service.AdoptRepository(ctxUser, ctxUser, repo_module.CreateRepoOptions{
+ if _, err := repo_service.AdoptRepository(ctx, ctxUser, ctxUser, repo_module.CreateRepoOptions{
Name: dir,
IsPrivate: true,
}); err != nil {
@@ -54,7 +54,7 @@ func AdoptOrDeleteRepository(ctx *context.Context) {
}
ctx.Flash.Success(ctx.Tr("repo.adopt_preexisting_success", dir))
} else if action == "delete" && allowDelete {
- if err := repo_service.DeleteUnadoptedRepository(ctxUser, ctxUser, dir); err != nil {
+ if err := repo_service.DeleteUnadoptedRepository(ctx, ctxUser, ctxUser, dir); err != nil {
ctx.ServerError("repository.AdoptRepository", err)
return
}
diff --git a/routers/web/user/setting/webhooks.go b/routers/web/user/setting/webhooks.go
new file mode 100644
index 000000000..9b0b0c961
--- /dev/null
+++ b/routers/web/user/setting/webhooks.go
@@ -0,0 +1,48 @@
+// Copyright 2023 The Gitea Authors. All rights reserved.
+// SPDX-License-Identifier: MIT
+
+package setting
+
+import (
+ "net/http"
+
+ "code.gitea.io/gitea/models/webhook"
+ "code.gitea.io/gitea/modules/base"
+ "code.gitea.io/gitea/modules/context"
+ "code.gitea.io/gitea/modules/setting"
+)
+
+const (
+ tplSettingsHooks base.TplName = "user/settings/hooks"
+)
+
+// Webhooks render webhook list page
+func Webhooks(ctx *context.Context) {
+ ctx.Data["Title"] = ctx.Tr("settings")
+ ctx.Data["PageIsSettingsHooks"] = true
+ ctx.Data["BaseLink"] = setting.AppSubURL + "/user/settings/hooks"
+ ctx.Data["BaseLinkNew"] = setting.AppSubURL + "/user/settings/hooks"
+ ctx.Data["Description"] = ctx.Tr("settings.hooks.desc")
+
+ ws, err := webhook.ListWebhooksByOpts(ctx, &webhook.ListWebhookOptions{OwnerID: ctx.Doer.ID})
+ if err != nil {
+ ctx.ServerError("ListWebhooksByOpts", err)
+ return
+ }
+
+ ctx.Data["Webhooks"] = ws
+ ctx.HTML(http.StatusOK, tplSettingsHooks)
+}
+
+// DeleteWebhook response for delete webhook
+func DeleteWebhook(ctx *context.Context) {
+ if err := webhook.DeleteWebhookByOwnerID(ctx.Doer.ID, ctx.FormInt64("id")); err != nil {
+ ctx.Flash.Error("DeleteWebhookByOwnerID: " + err.Error())
+ } else {
+ ctx.Flash.Success(ctx.Tr("repo.settings.webhook_deletion_success"))
+ }
+
+ ctx.JSON(http.StatusOK, map[string]interface{}{
+ "redirect": setting.AppSubURL + "/user/settings/hooks",
+ })
+}
diff --git a/routers/web/web.go b/routers/web/web.go
index ff312992d..292268dc8 100644
--- a/routers/web/web.go
+++ b/routers/web/web.go
@@ -315,6 +315,35 @@ func RegisterRoutes(m *web.Route) {
}
}
+ addWebhookAddRoutes := func() {
+ m.Get("/{type}/new", repo.WebhooksNew)
+ m.Post("/gitea/new", web.Bind(forms.NewWebhookForm{}), repo.GiteaHooksNewPost)
+ m.Post("/gogs/new", web.Bind(forms.NewGogshookForm{}), repo.GogsHooksNewPost)
+ m.Post("/slack/new", web.Bind(forms.NewSlackHookForm{}), repo.SlackHooksNewPost)
+ m.Post("/discord/new", web.Bind(forms.NewDiscordHookForm{}), repo.DiscordHooksNewPost)
+ m.Post("/dingtalk/new", web.Bind(forms.NewDingtalkHookForm{}), repo.DingtalkHooksNewPost)
+ m.Post("/telegram/new", web.Bind(forms.NewTelegramHookForm{}), repo.TelegramHooksNewPost)
+ m.Post("/matrix/new", web.Bind(forms.NewMatrixHookForm{}), repo.MatrixHooksNewPost)
+ m.Post("/msteams/new", web.Bind(forms.NewMSTeamsHookForm{}), repo.MSTeamsHooksNewPost)
+ m.Post("/feishu/new", web.Bind(forms.NewFeishuHookForm{}), repo.FeishuHooksNewPost)
+ m.Post("/wechatwork/new", web.Bind(forms.NewWechatWorkHookForm{}), repo.WechatworkHooksNewPost)
+ m.Post("/packagist/new", web.Bind(forms.NewPackagistHookForm{}), repo.PackagistHooksNewPost)
+ }
+
+ addWebhookEditRoutes := func() {
+ m.Post("/gitea/{id}", web.Bind(forms.NewWebhookForm{}), repo.GiteaHooksEditPost)
+ m.Post("/gogs/{id}", web.Bind(forms.NewGogshookForm{}), repo.GogsHooksEditPost)
+ m.Post("/slack/{id}", web.Bind(forms.NewSlackHookForm{}), repo.SlackHooksEditPost)
+ m.Post("/discord/{id}", web.Bind(forms.NewDiscordHookForm{}), repo.DiscordHooksEditPost)
+ m.Post("/dingtalk/{id}", web.Bind(forms.NewDingtalkHookForm{}), repo.DingtalkHooksEditPost)
+ m.Post("/telegram/{id}", web.Bind(forms.NewTelegramHookForm{}), repo.TelegramHooksEditPost)
+ m.Post("/matrix/{id}", web.Bind(forms.NewMatrixHookForm{}), repo.MatrixHooksEditPost)
+ m.Post("/msteams/{id}", web.Bind(forms.NewMSTeamsHookForm{}), repo.MSTeamsHooksEditPost)
+ m.Post("/feishu/{id}", web.Bind(forms.NewFeishuHookForm{}), repo.FeishuHooksEditPost)
+ m.Post("/wechatwork/{id}", web.Bind(forms.NewWechatWorkHookForm{}), repo.WechatworkHooksEditPost)
+ m.Post("/packagist/{id}", web.Bind(forms.NewPackagistHookForm{}), repo.PackagistHooksEditPost)
+ }
+
// FIXME: not all routes need go through same middleware.
// Especially some AJAX requests, we can reduce middleware number to improve performance.
// Routers.
@@ -482,6 +511,19 @@ func RegisterRoutes(m *web.Route) {
m.Get("/organization", user_setting.Organization)
m.Get("/repos", user_setting.Repos)
m.Post("/repos/unadopted", user_setting.AdoptOrDeleteRepository)
+
+ m.Group("/hooks", func() {
+ m.Get("", user_setting.Webhooks)
+ m.Post("/delete", user_setting.DeleteWebhook)
+ addWebhookAddRoutes()
+ m.Group("/{id}", func() {
+ m.Get("", repo.WebHooksEdit)
+ m.Post("/replay/{uuid}", repo.ReplayWebhook)
+ })
+ addWebhookEditRoutes()
+ }, webhooksEnabled, func(ctx *context.Context) {
+ ctx.Data["IsUserWebhook"] = true
+ })
}, reqSignIn, func(ctx *context.Context) {
ctx.Data["PageIsUserSettings"] = true
ctx.Data["AllThemes"] = setting.UI.Themes
@@ -575,32 +617,11 @@ func RegisterRoutes(m *web.Route) {
m.Get("", repo.WebHooksEdit)
m.Post("/replay/{uuid}", repo.ReplayWebhook)
})
- m.Post("/gitea/{id}", web.Bind(forms.NewWebhookForm{}), repo.GiteaHooksEditPost)
- m.Post("/gogs/{id}", web.Bind(forms.NewGogshookForm{}), repo.GogsHooksEditPost)
- m.Post("/slack/{id}", web.Bind(forms.NewSlackHookForm{}), repo.SlackHooksEditPost)
- m.Post("/discord/{id}", web.Bind(forms.NewDiscordHookForm{}), repo.DiscordHooksEditPost)
- m.Post("/dingtalk/{id}", web.Bind(forms.NewDingtalkHookForm{}), repo.DingtalkHooksEditPost)
- m.Post("/telegram/{id}", web.Bind(forms.NewTelegramHookForm{}), repo.TelegramHooksEditPost)
- m.Post("/matrix/{id}", web.Bind(forms.NewMatrixHookForm{}), repo.MatrixHooksEditPost)
- m.Post("/msteams/{id}", web.Bind(forms.NewMSTeamsHookForm{}), repo.MSTeamsHooksEditPost)
- m.Post("/feishu/{id}", web.Bind(forms.NewFeishuHookForm{}), repo.FeishuHooksEditPost)
- m.Post("/wechatwork/{id}", web.Bind(forms.NewWechatWorkHookForm{}), repo.WechatworkHooksEditPost)
- m.Post("/packagist/{id}", web.Bind(forms.NewPackagistHookForm{}), repo.PackagistHooksEditPost)
+ addWebhookEditRoutes()
}, webhooksEnabled)
m.Group("/{configType:default-hooks|system-hooks}", func() {
- m.Get("/{type}/new", repo.WebhooksNew)
- m.Post("/gitea/new", web.Bind(forms.NewWebhookForm{}), repo.GiteaHooksNewPost)
- m.Post("/gogs/new", web.Bind(forms.NewGogshookForm{}), repo.GogsHooksNewPost)
- m.Post("/slack/new", web.Bind(forms.NewSlackHookForm{}), repo.SlackHooksNewPost)
- m.Post("/discord/new", web.Bind(forms.NewDiscordHookForm{}), repo.DiscordHooksNewPost)
- m.Post("/dingtalk/new", web.Bind(forms.NewDingtalkHookForm{}), repo.DingtalkHooksNewPost)
- m.Post("/telegram/new", web.Bind(forms.NewTelegramHookForm{}), repo.TelegramHooksNewPost)
- m.Post("/matrix/new", web.Bind(forms.NewMatrixHookForm{}), repo.MatrixHooksNewPost)
- m.Post("/msteams/new", web.Bind(forms.NewMSTeamsHookForm{}), repo.MSTeamsHooksNewPost)
- m.Post("/feishu/new", web.Bind(forms.NewFeishuHookForm{}), repo.FeishuHooksNewPost)
- m.Post("/wechatwork/new", web.Bind(forms.NewWechatWorkHookForm{}), repo.WechatworkHooksNewPost)
- m.Post("/packagist/new", web.Bind(forms.NewPackagistHookForm{}), repo.PackagistHooksNewPost)
+ addWebhookAddRoutes()
})
m.Group("/auths", func() {
@@ -690,6 +711,21 @@ func RegisterRoutes(m *web.Route) {
}
}
+ reqUnitAccess := func(unitType unit.Type, accessMode perm.AccessMode) func(ctx *context.Context) {
+ return func(ctx *context.Context) {
+ if ctx.ContextUser == nil {
+ ctx.NotFound(unitType.String(), nil)
+ return
+ }
+ if ctx.ContextUser.IsOrganization() {
+ if ctx.Org.Organization.UnitPermission(ctx, ctx.Doer, unitType) < accessMode {
+ ctx.NotFound(unitType.String(), nil)
+ return
+ }
+ }
+ }
+ }
+
// ***** START: Organization *****
m.Group("/org", func() {
m.Group("/{org}", func() {
@@ -759,32 +795,15 @@ func RegisterRoutes(m *web.Route) {
m.Group("/hooks", func() {
m.Get("", org.Webhooks)
m.Post("/delete", org.DeleteWebhook)
- m.Get("/{type}/new", repo.WebhooksNew)
- m.Post("/gitea/new", web.Bind(forms.NewWebhookForm{}), repo.GiteaHooksNewPost)
- m.Post("/gogs/new", web.Bind(forms.NewGogshookForm{}), repo.GogsHooksNewPost)
- m.Post("/slack/new", web.Bind(forms.NewSlackHookForm{}), repo.SlackHooksNewPost)
- m.Post("/discord/new", web.Bind(forms.NewDiscordHookForm{}), repo.DiscordHooksNewPost)
- m.Post("/dingtalk/new", web.Bind(forms.NewDingtalkHookForm{}), repo.DingtalkHooksNewPost)
- m.Post("/telegram/new", web.Bind(forms.NewTelegramHookForm{}), repo.TelegramHooksNewPost)
- m.Post("/matrix/new", web.Bind(forms.NewMatrixHookForm{}), repo.MatrixHooksNewPost)
- m.Post("/msteams/new", web.Bind(forms.NewMSTeamsHookForm{}), repo.MSTeamsHooksNewPost)
- m.Post("/feishu/new", web.Bind(forms.NewFeishuHookForm{}), repo.FeishuHooksNewPost)
- m.Post("/wechatwork/new", web.Bind(forms.NewWechatWorkHookForm{}), repo.WechatworkHooksNewPost)
+ addWebhookAddRoutes()
m.Group("/{id}", func() {
m.Get("", repo.WebHooksEdit)
m.Post("/replay/{uuid}", repo.ReplayWebhook)
})
- m.Post("/gitea/{id}", web.Bind(forms.NewWebhookForm{}), repo.GiteaHooksEditPost)
- m.Post("/gogs/{id}", web.Bind(forms.NewGogshookForm{}), repo.GogsHooksEditPost)
- m.Post("/slack/{id}", web.Bind(forms.NewSlackHookForm{}), repo.SlackHooksEditPost)
- m.Post("/discord/{id}", web.Bind(forms.NewDiscordHookForm{}), repo.DiscordHooksEditPost)
- m.Post("/dingtalk/{id}", web.Bind(forms.NewDingtalkHookForm{}), repo.DingtalkHooksEditPost)
- m.Post("/telegram/{id}", web.Bind(forms.NewTelegramHookForm{}), repo.TelegramHooksEditPost)
- m.Post("/matrix/{id}", web.Bind(forms.NewMatrixHookForm{}), repo.MatrixHooksEditPost)
- m.Post("/msteams/{id}", web.Bind(forms.NewMSTeamsHookForm{}), repo.MSTeamsHooksEditPost)
- m.Post("/feishu/{id}", web.Bind(forms.NewFeishuHookForm{}), repo.FeishuHooksEditPost)
- m.Post("/wechatwork/{id}", web.Bind(forms.NewWechatWorkHookForm{}), repo.WechatworkHooksEditPost)
- }, webhooksEnabled)
+ addWebhookEditRoutes()
+ }, webhooksEnabled, func(ctx *context.Context) {
+ ctx.Data["IsOrganizationWebhook"] = true
+ })
m.Group("/labels", func() {
m.Get("", org.RetrieveLabels, org.Labels)
@@ -869,8 +888,10 @@ func RegisterRoutes(m *web.Route) {
}
m.Group("/projects", func() {
- m.Get("", org.Projects)
- m.Get("/{id}", org.ViewProject)
+ m.Group("", func() {
+ m.Get("", org.Projects)
+ m.Get("/{id}", org.ViewProject)
+ }, reqUnitAccess(unit.TypeProjects, perm.AccessModeRead))
m.Group("", func() { //nolint:dupl
m.Get("/new", org.NewProject)
m.Post("/new", web.Bind(forms.CreateProjectForm{}), org.NewProjectPost)
@@ -890,25 +911,18 @@ func RegisterRoutes(m *web.Route) {
m.Post("/move", org.MoveIssues)
})
})
- }, reqSignIn, func(ctx *context.Context) {
- if ctx.ContextUser == nil {
- ctx.NotFound("NewProject", nil)
- return
- }
- if ctx.ContextUser.IsOrganization() {
- if !ctx.Org.CanWriteUnit(ctx, unit.TypeProjects) {
- ctx.NotFound("NewProject", nil)
- return
- }
- } else if ctx.ContextUser.ID != ctx.Doer.ID {
+ }, reqSignIn, reqUnitAccess(unit.TypeProjects, perm.AccessModeWrite), func(ctx *context.Context) {
+ if ctx.ContextUser.IsIndividual() && ctx.ContextUser.ID != ctx.Doer.ID {
ctx.NotFound("NewProject", nil)
return
}
})
}, repo.MustEnableProjects)
- m.Get("/code", user.CodeSearch)
- }, context_service.UserAssignmentWeb())
+ m.Group("", func() {
+ m.Get("/code", user.CodeSearch)
+ }, reqUnitAccess(unit.TypeCode, perm.AccessModeRead))
+ }, context_service.UserAssignmentWeb(), context.OrgAssignment())
// ***** Release Attachment Download without Signin
m.Get("/{username}/{reponame}/releases/download/{vTag}/{fileName}", ignSignIn, context.RepoAssignment, repo.MustBeNotEmpty, repo.RedirectDownload)
@@ -962,35 +976,16 @@ func RegisterRoutes(m *web.Route) {
m.Group("/hooks", func() {
m.Get("", repo.Webhooks)
m.Post("/delete", repo.DeleteWebhook)
- m.Get("/{type}/new", repo.WebhooksNew)
- m.Post("/gitea/new", web.Bind(forms.NewWebhookForm{}), repo.GiteaHooksNewPost)
- m.Post("/gogs/new", web.Bind(forms.NewGogshookForm{}), repo.GogsHooksNewPost)
- m.Post("/slack/new", web.Bind(forms.NewSlackHookForm{}), repo.SlackHooksNewPost)
- m.Post("/discord/new", web.Bind(forms.NewDiscordHookForm{}), repo.DiscordHooksNewPost)
- m.Post("/dingtalk/new", web.Bind(forms.NewDingtalkHookForm{}), repo.DingtalkHooksNewPost)
- m.Post("/telegram/new", web.Bind(forms.NewTelegramHookForm{}), repo.TelegramHooksNewPost)
- m.Post("/matrix/new", web.Bind(forms.NewMatrixHookForm{}), repo.MatrixHooksNewPost)
- m.Post("/msteams/new", web.Bind(forms.NewMSTeamsHookForm{}), repo.MSTeamsHooksNewPost)
- m.Post("/feishu/new", web.Bind(forms.NewFeishuHookForm{}), repo.FeishuHooksNewPost)
- m.Post("/wechatwork/new", web.Bind(forms.NewWechatWorkHookForm{}), repo.WechatworkHooksNewPost)
- m.Post("/packagist/new", web.Bind(forms.NewPackagistHookForm{}), repo.PackagistHooksNewPost)
+ addWebhookAddRoutes()
m.Group("/{id}", func() {
m.Get("", repo.WebHooksEdit)
m.Post("/test", repo.TestWebhook)
m.Post("/replay/{uuid}", repo.ReplayWebhook)
})
- m.Post("/gitea/{id}", web.Bind(forms.NewWebhookForm{}), repo.GiteaHooksEditPost)
- m.Post("/gogs/{id}", web.Bind(forms.NewGogshookForm{}), repo.GogsHooksEditPost)
- m.Post("/slack/{id}", web.Bind(forms.NewSlackHookForm{}), repo.SlackHooksEditPost)
- m.Post("/discord/{id}", web.Bind(forms.NewDiscordHookForm{}), repo.DiscordHooksEditPost)
- m.Post("/dingtalk/{id}", web.Bind(forms.NewDingtalkHookForm{}), repo.DingtalkHooksEditPost)
- m.Post("/telegram/{id}", web.Bind(forms.NewTelegramHookForm{}), repo.TelegramHooksEditPost)
- m.Post("/matrix/{id}", web.Bind(forms.NewMatrixHookForm{}), repo.MatrixHooksEditPost)
- m.Post("/msteams/{id}", web.Bind(forms.NewMSTeamsHookForm{}), repo.MSTeamsHooksEditPost)
- m.Post("/feishu/{id}", web.Bind(forms.NewFeishuHookForm{}), repo.FeishuHooksEditPost)
- m.Post("/wechatwork/{id}", web.Bind(forms.NewWechatWorkHookForm{}), repo.WechatworkHooksEditPost)
- m.Post("/packagist/{id}", web.Bind(forms.NewPackagistHookForm{}), repo.PackagistHooksEditPost)
- }, webhooksEnabled)
+ addWebhookEditRoutes()
+ }, webhooksEnabled, func(ctx *context.Context) {
+ ctx.Data["IsRepositoryWebhook"] = true
+ })
m.Group("/keys", func() {
m.Combo("").Get(repo.DeployKeys).
diff --git a/services/actions/clear_tasks.go b/services/actions/clear_tasks.go
index 583e588de..6f8e95218 100644
--- a/services/actions/clear_tasks.go
+++ b/services/actions/clear_tasks.go
@@ -43,6 +43,7 @@ func stopTasks(ctx context.Context, opts actions_model.FindTaskOptions) error {
return fmt.Errorf("find tasks: %w", err)
}
+ jobs := make([]*actions_model.ActionRunJob, 0, len(tasks))
for _, task := range tasks {
if err := db.WithTx(ctx, func(ctx context.Context) error {
if err := actions_model.StopTask(ctx, task.ID, actions_model.StatusFailure); err != nil {
@@ -51,7 +52,8 @@ func stopTasks(ctx context.Context, opts actions_model.FindTaskOptions) error {
if err := task.LoadJob(ctx); err != nil {
return err
}
- return CreateCommitStatus(ctx, task.Job)
+ jobs = append(jobs, task.Job)
+ return nil
}); err != nil {
log.Warn("Cannot stop task %v: %v", task.ID, err)
// go on
@@ -61,6 +63,14 @@ func stopTasks(ctx context.Context, opts actions_model.FindTaskOptions) error {
remove()
}
}
+
+ for _, job := range jobs {
+ if err := CreateCommitStatus(ctx, job); err != nil {
+ log.Error("Update commit status for job %v failed: %v", job.ID, err)
+ // go on
+ }
+ }
+
return nil
}
@@ -80,14 +90,16 @@ func CancelAbandonedJobs(ctx context.Context) error {
job.Status = actions_model.StatusCancelled
job.Stopped = now
if err := db.WithTx(ctx, func(ctx context.Context) error {
- if _, err := actions_model.UpdateRunJob(ctx, job, nil, "status", "stopped"); err != nil {
- return err
- }
- return CreateCommitStatus(ctx, job)
+ _, err := actions_model.UpdateRunJob(ctx, job, nil, "status", "stopped")
+ return err
}); err != nil {
log.Warn("cancel abandoned job %v: %v", job.ID, err)
// go on
}
+ if err := CreateCommitStatus(ctx, job); err != nil {
+ log.Error("Update commit status for job %v failed: %v", job.ID, err)
+ // go on
+ }
}
return nil
diff --git a/services/actions/commit_status.go b/services/actions/commit_status.go
index efb5ec6d4..4f3134935 100644
--- a/services/actions/commit_status.go
+++ b/services/actions/commit_status.go
@@ -30,6 +30,16 @@ func CreateCommitStatus(ctx context.Context, job *actions_model.ActionRunJob) er
return fmt.Errorf("GetPushEventPayload: %w", err)
}
+ // Since the payload comes from json data, we should check if it's broken, or it will cause panic
+ switch {
+ case payload.Repo == nil:
+ return fmt.Errorf("repo is missing in event payload")
+ case payload.Pusher == nil:
+ return fmt.Errorf("pusher is missing in event payload")
+ case payload.HeadCommit == nil:
+ return fmt.Errorf("head commit is missing in event payload")
+ }
+
creator, err := user_model.GetUserByID(ctx, payload.Pusher.ID)
if err != nil {
return fmt.Errorf("GetUserByID: %w", err)
diff --git a/services/actions/notifier_helper.go b/services/actions/notifier_helper.go
index ef63b8cf9..574a37e9a 100644
--- a/services/actions/notifier_helper.go
+++ b/services/actions/notifier_helper.go
@@ -187,7 +187,8 @@ func notify(ctx context.Context, input *notifyInput) error {
} else {
for _, job := range jobs {
if err := CreateCommitStatus(ctx, job); err != nil {
- log.Error("CreateCommitStatus: %v", err)
+ log.Error("Update commit status for job %v failed: %v", job.ID, err)
+ // go on
}
}
}
diff --git a/services/attachment/attachment.go b/services/attachment/attachment.go
index 7fdacc6aa..3e7df0cee 100644
--- a/services/attachment/attachment.go
+++ b/services/attachment/attachment.go
@@ -19,14 +19,14 @@ import (
)
// NewAttachment creates a new attachment object, but do not verify.
-func NewAttachment(attach *repo_model.Attachment, file io.Reader) (*repo_model.Attachment, error) {
+func NewAttachment(attach *repo_model.Attachment, file io.Reader, size int64) (*repo_model.Attachment, error) {
if attach.RepoID == 0 {
return nil, fmt.Errorf("attachment %s should belong to a repository", attach.Name)
}
err := db.WithTx(db.DefaultContext, func(ctx context.Context) error {
attach.UUID = uuid.New().String()
- size, err := storage.Attachments.Save(attach.RelativePath(), file, -1)
+ size, err := storage.Attachments.Save(attach.RelativePath(), file, size)
if err != nil {
return fmt.Errorf("Create: %w", err)
}
@@ -39,7 +39,7 @@ func NewAttachment(attach *repo_model.Attachment, file io.Reader) (*repo_model.A
}
// UploadAttachment upload new attachment into storage and update database
-func UploadAttachment(file io.Reader, allowedTypes string, opts *repo_model.Attachment) (*repo_model.Attachment, error) {
+func UploadAttachment(file io.Reader, allowedTypes string, fileSize int64, opts *repo_model.Attachment) (*repo_model.Attachment, error) {
buf := make([]byte, 1024)
n, _ := util.ReadAtMost(file, buf)
buf = buf[:n]
@@ -48,5 +48,5 @@ func UploadAttachment(file io.Reader, allowedTypes string, opts *repo_model.Atta
return nil, err
}
- return NewAttachment(opts, io.MultiReader(bytes.NewReader(buf), file))
+ return NewAttachment(opts, io.MultiReader(bytes.NewReader(buf), file), fileSize)
}
diff --git a/services/attachment/attachment_test.go b/services/attachment/attachment_test.go
index 72d1b2ab3..1b9af3442 100644
--- a/services/attachment/attachment_test.go
+++ b/services/attachment/attachment_test.go
@@ -36,7 +36,7 @@ func TestUploadAttachment(t *testing.T) {
RepoID: 1,
UploaderID: user.ID,
Name: filepath.Base(fPath),
- }, f)
+ }, f, -1)
assert.NoError(t, err)
attachment, err := repo_model.GetAttachmentByUUID(db.DefaultContext, attach.UUID)
diff --git a/services/auth/source/oauth2/source_register.go b/services/auth/source/oauth2/source_register.go
index 3527d54b6..82a36acaa 100644
--- a/services/auth/source/oauth2/source_register.go
+++ b/services/auth/source/oauth2/source_register.go
@@ -36,6 +36,10 @@ func (err ErrOpenIDConnectInitialize) Error() string {
return fmt.Sprintf("Failed to initialize OpenID Connect Provider with name '%s' with url '%s': %v", err.ProviderName, err.OpenIDConnectAutoDiscoveryURL, err.Cause)
}
+func (err ErrOpenIDConnectInitialize) Unwrap() error {
+ return err.Cause
+}
+
// wrapOpenIDConnectInitializeError is used to wrap the error but this cannot be done in modules/auth/oauth2
// inside oauth2: import cycle not allowed models -> modules/auth/oauth2 -> models
func wrapOpenIDConnectInitializeError(err error, providerName string, source *Source) error {
diff --git a/services/context/user.go b/services/context/user.go
index 7642cba4e..9dc84c3ac 100644
--- a/services/context/user.go
+++ b/services/context/user.go
@@ -8,7 +8,6 @@ import (
"net/http"
"strings"
- org_model "code.gitea.io/gitea/models/organization"
user_model "code.gitea.io/gitea/models/user"
"code.gitea.io/gitea/modules/context"
)
@@ -57,14 +56,6 @@ func userAssignment(ctx *context.Context, errCb func(int, string, interface{}))
} else {
errCb(http.StatusInternalServerError, "GetUserByName", err)
}
- } else {
- if ctx.ContextUser.IsOrganization() {
- if ctx.Org == nil {
- ctx.Org = &context.Organization{}
- }
- ctx.Org.Organization = (*org_model.Organization)(ctx.ContextUser)
- ctx.Data["Org"] = ctx.Org.Organization
- }
}
}
}
diff --git a/services/forms/repo_form.go b/services/forms/repo_form.go
index e9645b5ab..3bd073c07 100644
--- a/services/forms/repo_form.go
+++ b/services/forms/repo_form.go
@@ -622,7 +622,7 @@ type CodeCommentForm struct {
Side string `binding:"Required;In(previous,proposed)"`
Line int64
TreePath string `form:"path" binding:"Required"`
- IsReview bool `form:"is_review"`
+ SingleReview bool `form:"single_review"`
Reply int64 `form:"reply"`
LatestCommitID string
}
diff --git a/services/gitdiff/gitdiff.go b/services/gitdiff/gitdiff.go
index 4a74c1a89..c50e8137a 100644
--- a/services/gitdiff/gitdiff.go
+++ b/services/gitdiff/gitdiff.go
@@ -474,7 +474,7 @@ func ParsePatch(maxLines, maxLineCharacters, maxFiles int, reader io.Reader, ski
sb := strings.Builder{}
// OK let's set a reasonable buffer size.
- // This should be let's say at least the size of maxLineCharacters or 4096 whichever is larger.
+ // This should be at least the size of maxLineCharacters or 4096 whichever is larger.
readerSize := maxLineCharacters
if readerSize < 4096 {
readerSize = 4096
diff --git a/services/mailer/incoming/incoming_handler.go b/services/mailer/incoming/incoming_handler.go
index d89a5eab3..b594e3518 100644
--- a/services/mailer/incoming/incoming_handler.go
+++ b/services/mailer/incoming/incoming_handler.go
@@ -87,7 +87,7 @@ func (h *ReplyHandler) Handle(ctx context.Context, content *MailContent, doer *u
attachmentIDs := make([]string, 0, len(content.Attachments))
if setting.Attachment.Enabled {
for _, attachment := range content.Attachments {
- a, err := attachment_service.UploadAttachment(bytes.NewReader(attachment.Content), setting.Attachment.AllowedTypes, &repo_model.Attachment{
+ a, err := attachment_service.UploadAttachment(bytes.NewReader(attachment.Content), setting.Attachment.AllowedTypes, int64(len(attachment.Content)), &repo_model.Attachment{
Name: attachment.Name,
UploaderID: doer.ID,
RepoID: issue.Repo.ID,
@@ -127,7 +127,7 @@ func (h *ReplyHandler) Handle(ctx context.Context, content *MailContent, doer *u
comment.Line,
content.Content,
comment.TreePath,
- false,
+ false, // not pending review but a single review
comment.ReviewID,
"",
)
diff --git a/services/migrations/gitea_uploader.go b/services/migrations/gitea_uploader.go
index 20370d99f..ca961524d 100644
--- a/services/migrations/gitea_uploader.go
+++ b/services/migrations/gitea_uploader.go
@@ -9,7 +9,6 @@ import (
"fmt"
"io"
"os"
- "path"
"path/filepath"
"strconv"
"strings"
@@ -21,6 +20,7 @@ import (
repo_model "code.gitea.io/gitea/models/repo"
user_model "code.gitea.io/gitea/models/user"
"code.gitea.io/gitea/modules/git"
+ "code.gitea.io/gitea/modules/label"
"code.gitea.io/gitea/modules/log"
base "code.gitea.io/gitea/modules/migration"
repo_module "code.gitea.io/gitea/modules/repository"
@@ -29,6 +29,7 @@ import (
"code.gitea.io/gitea/modules/structs"
"code.gitea.io/gitea/modules/timeutil"
"code.gitea.io/gitea/modules/uri"
+ "code.gitea.io/gitea/modules/util"
"code.gitea.io/gitea/services/pull"
"github.com/google/uuid"
@@ -217,18 +218,20 @@ func (g *GiteaLocalUploader) CreateMilestones(milestones ...*base.Milestone) err
// CreateLabels creates labels
func (g *GiteaLocalUploader) CreateLabels(labels ...*base.Label) error {
lbs := make([]*issues_model.Label, 0, len(labels))
- for _, label := range labels {
- // We must validate color here:
- if !issues_model.LabelColorPattern.MatchString("#" + label.Color) {
- log.Warn("Invalid label color: #%s for label: %s in migration to %s/%s", label.Color, label.Name, g.repoOwner, g.repoName)
- label.Color = "ffffff"
+ for _, l := range labels {
+ if color, err := label.NormalizeColor(l.Color); err != nil {
+ log.Warn("Invalid label color: #%s for label: %s in migration to %s/%s", l.Color, l.Name, g.repoOwner, g.repoName)
+ l.Color = "#ffffff"
+ } else {
+ l.Color = color
}
lbs = append(lbs, &issues_model.Label{
RepoID: g.repo.ID,
- Name: label.Name,
- Description: label.Description,
- Color: "#" + label.Color,
+ Name: l.Name,
+ Exclusive: l.Exclusive,
+ Description: l.Description,
+ Color: l.Color,
})
}
@@ -863,7 +866,7 @@ func (g *GiteaLocalUploader) CreateReviews(reviews ...*base.Review) error {
}
// SECURITY: The TreePath must be cleaned!
- comment.TreePath = path.Clean("/" + comment.TreePath)[1:]
+ comment.TreePath = util.CleanPath(comment.TreePath)
var patch string
reader, writer := io.Pipe()
diff --git a/services/mirror/mirror_pull.go b/services/mirror/mirror_pull.go
index 126d2bf35..60699294c 100644
--- a/services/mirror/mirror_pull.go
+++ b/services/mirror/mirror_pull.go
@@ -499,6 +499,13 @@ func SyncPullMirror(ctx context.Context, repoID int64) bool {
theCommits.Commits = theCommits.Commits[:setting.UI.FeedMaxCommitNum]
}
+ if newCommit, err := gitRepo.GetCommit(newCommitID); err != nil {
+ log.Error("SyncMirrors [repo: %-v]: unable to get commit %s: %v", m.Repo, newCommitID, err)
+ continue
+ } else {
+ theCommits.HeadCommit = repo_module.CommitToPushCommit(newCommit)
+ }
+
theCommits.CompareURL = m.Repo.ComposeCompareURL(oldCommitID, newCommitID)
notification.NotifySyncPushCommits(ctx, m.Repo.MustOwner(ctx), m.Repo, &repo_module.PushUpdateOptions{
diff --git a/services/packages/container/blob_uploader.go b/services/packages/container/blob_uploader.go
index ba92b0507..860672587 100644
--- a/services/packages/container/blob_uploader.go
+++ b/services/packages/container/blob_uploader.go
@@ -8,13 +8,13 @@ import (
"errors"
"io"
"os"
- "path"
"path/filepath"
"strings"
packages_model "code.gitea.io/gitea/models/packages"
packages_module "code.gitea.io/gitea/modules/packages"
"code.gitea.io/gitea/modules/setting"
+ "code.gitea.io/gitea/modules/util"
)
var (
@@ -33,7 +33,7 @@ type BlobUploader struct {
}
func buildFilePath(id string) string {
- return filepath.Join(setting.Packages.ChunkedUploadPath, path.Clean("/" + strings.ReplaceAll(id, "\\", "/"))[1:])
+ return filepath.Join(setting.Packages.ChunkedUploadPath, util.CleanPath(strings.ReplaceAll(id, "\\", "/")))
}
// NewBlobUploader creates a new blob uploader for the given id
diff --git a/services/pull/comment.go b/services/pull/comment.go
index 068aca6cd..933ad09a8 100644
--- a/services/pull/comment.go
+++ b/services/pull/comment.go
@@ -14,58 +14,6 @@ import (
issue_service "code.gitea.io/gitea/services/issue"
)
-type commitBranchCheckItem struct {
- Commit *git.Commit
- Checked bool
-}
-
-func commitBranchCheck(gitRepo *git.Repository, startCommit *git.Commit, endCommitID, baseBranch string, commitList map[string]*commitBranchCheckItem) error {
- if startCommit.ID.String() == endCommitID {
- return nil
- }
-
- checkStack := make([]string, 0, 10)
- checkStack = append(checkStack, startCommit.ID.String())
-
- for len(checkStack) > 0 {
- commitID := checkStack[0]
- checkStack = checkStack[1:]
-
- item, ok := commitList[commitID]
- if !ok {
- continue
- }
-
- if item.Commit.ID.String() == endCommitID {
- continue
- }
-
- if err := item.Commit.LoadBranchName(); err != nil {
- return err
- }
-
- if item.Commit.Branch == baseBranch {
- continue
- }
-
- if item.Checked {
- continue
- }
-
- item.Checked = true
-
- parentNum := item.Commit.ParentCount()
- for i := 0; i < parentNum; i++ {
- parentCommit, err := item.Commit.Parent(i)
- if err != nil {
- return err
- }
- checkStack = append(checkStack, parentCommit.ID.String())
- }
- }
- return nil
-}
-
// getCommitIDsFromRepo get commit IDs from repo in between oldCommitID and newCommitID
// isForcePush will be true if oldCommit isn't on the branch
// Commit on baseBranch will skip
@@ -82,47 +30,33 @@ func getCommitIDsFromRepo(ctx context.Context, repo *repo_model.Repository, oldC
return nil, false, err
}
- if err = oldCommit.LoadBranchName(); err != nil {
- return nil, false, err
- }
-
- if len(oldCommit.Branch) == 0 {
- commitIDs = make([]string, 2)
- commitIDs[0] = oldCommitID
- commitIDs[1] = newCommitID
-
- return commitIDs, true, err
- }
-
newCommit, err := gitRepo.GetCommit(newCommitID)
if err != nil {
return nil, false, err
}
- commits, err := newCommit.CommitsBeforeUntil(oldCommitID)
+ isForcePush, err = newCommit.IsForcePush(oldCommitID)
if err != nil {
return nil, false, err
}
- commitIDs = make([]string, 0, len(commits))
- commitChecks := make(map[string]*commitBranchCheckItem)
+ if isForcePush {
+ commitIDs = make([]string, 2)
+ commitIDs[0] = oldCommitID
+ commitIDs[1] = newCommitID
- for _, commit := range commits {
- commitChecks[commit.ID.String()] = &commitBranchCheckItem{
- Commit: commit,
- Checked: false,
- }
+ return commitIDs, isForcePush, err
}
- if err = commitBranchCheck(gitRepo, newCommit, oldCommitID, baseBranch, commitChecks); err != nil {
- return
+ // Find commits between new and old commit exclusing base branch commits
+ commits, err := gitRepo.CommitsBetweenNotBase(newCommit, oldCommit, baseBranch)
+ if err != nil {
+ return nil, false, err
}
+ commitIDs = make([]string, 0, len(commits))
for i := len(commits) - 1; i >= 0; i-- {
- commitID := commits[i].ID.String()
- if item, ok := commitChecks[commitID]; ok && item.Checked {
- commitIDs = append(commitIDs, commitID)
- }
+ commitIDs = append(commitIDs, commits[i].ID.String())
}
return commitIDs, isForcePush, err
diff --git a/services/pull/lfs.go b/services/pull/lfs.go
index dc4ca006e..394337246 100644
--- a/services/pull/lfs.go
+++ b/services/pull/lfs.go
@@ -116,7 +116,7 @@ func createLFSMetaObjectsFromCatFileBatch(catFileBatchReader *io.PipeReader, wg
}
// Then we need to check that this pointer is in the db
- if _, err := git_model.GetLFSMetaObjectByOid(db.DefaultContext, pr.HeadRepo.ID, pointer.Oid); err != nil {
+ if _, err := git_model.GetLFSMetaObjectByOid(db.DefaultContext, pr.HeadRepoID, pointer.Oid); err != nil {
if err == git_model.ErrLFSObjectNotExist {
log.Warn("During merge of: %d in %-v, there is a pointer to LFS Oid: %s which although present in the LFS store is not associated with the head repo %-v", pr.Index, pr.BaseRepo, pointer.Oid, pr.HeadRepo)
continue
diff --git a/services/pull/merge.go b/services/pull/merge.go
index ad428427c..12e01e8ce 100644
--- a/services/pull/merge.go
+++ b/services/pull/merge.go
@@ -5,8 +5,6 @@
package pull
import (
- "bufio"
- "bytes"
"context"
"fmt"
"os"
@@ -14,7 +12,6 @@ import (
"regexp"
"strconv"
"strings"
- "time"
"code.gitea.io/gitea/models"
"code.gitea.io/gitea/models/db"
@@ -34,22 +31,17 @@ import (
repo_module "code.gitea.io/gitea/modules/repository"
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/timeutil"
- asymkey_service "code.gitea.io/gitea/services/asymkey"
issue_service "code.gitea.io/gitea/services/issue"
)
// GetDefaultMergeMessage returns default message used when merging pull request
func GetDefaultMergeMessage(ctx context.Context, baseGitRepo *git.Repository, pr *issues_model.PullRequest, mergeStyle repo_model.MergeStyle) (message, body string, err error) {
- if err := pr.LoadHeadRepo(ctx); err != nil {
- return "", "", err
- }
if err := pr.LoadBaseRepo(ctx); err != nil {
return "", "", err
}
- if pr.BaseRepo == nil {
- return "", "", repo_model.ErrRepoNotExist{ID: pr.BaseRepoID}
+ if err := pr.LoadHeadRepo(ctx); err != nil {
+ return "", "", err
}
-
if err := pr.LoadIssue(ctx); err != nil {
return "", "", err
}
@@ -144,18 +136,19 @@ func expandDefaultMergeMessage(template string, vars map[string]string) (message
// Merge merges pull request to base repository.
// Caller should check PR is ready to be merged (review and status checks)
func Merge(ctx context.Context, pr *issues_model.PullRequest, doer *user_model.User, baseGitRepo *git.Repository, mergeStyle repo_model.MergeStyle, expectedHeadCommitID, message string, wasAutoMerged bool) error {
- if err := pr.LoadHeadRepo(ctx); err != nil {
- log.Error("LoadHeadRepo: %v", err)
- return fmt.Errorf("LoadHeadRepo: %w", err)
- } else if err := pr.LoadBaseRepo(ctx); err != nil {
- log.Error("LoadBaseRepo: %v", err)
- return fmt.Errorf("LoadBaseRepo: %w", err)
+ if err := pr.LoadBaseRepo(ctx); err != nil {
+ log.Error("Unable to load base repo: %v", err)
+ return fmt.Errorf("unable to load base repo: %w", err)
+ } else if err := pr.LoadHeadRepo(ctx); err != nil {
+ log.Error("Unable to load head repo: %v", err)
+ return fmt.Errorf("unable to load head repo: %w", err)
}
pullWorkingPool.CheckIn(fmt.Sprint(pr.ID))
defer pullWorkingPool.CheckOut(fmt.Sprint(pr.ID))
// Removing an auto merge pull and ignore if not exist
+ // FIXME: is this the correct point to do this? Shouldn't this be after IsMergeStyleAllowed?
if err := pull_model.DeleteScheduledAutoMerge(ctx, pr.ID); err != nil && !db.IsErrNotExist(err) {
return err
}
@@ -179,7 +172,7 @@ func Merge(ctx context.Context, pr *issues_model.PullRequest, doer *user_model.U
// Run the merge in the hammer context to prevent cancellation
hammerCtx := graceful.GetManager().HammerContext()
- pr.MergedCommitID, err = rawMerge(hammerCtx, pr, doer, mergeStyle, expectedHeadCommitID, message)
+ pr.MergedCommitID, err = doMergeAndPush(hammerCtx, pr, doer, mergeStyle, expectedHeadCommitID, message)
if err != nil {
return err
}
@@ -189,18 +182,18 @@ func Merge(ctx context.Context, pr *issues_model.PullRequest, doer *user_model.U
pr.MergerID = doer.ID
if _, err := pr.SetMerged(hammerCtx); err != nil {
- log.Error("SetMerged [%d]: %v", pr.ID, err)
+ log.Error("SetMerged %-v: %v", pr, err)
}
if err := pr.LoadIssue(hammerCtx); err != nil {
- log.Error("LoadIssue [%d]: %v", pr.ID, err)
+ log.Error("LoadIssue %-v: %v", pr, err)
}
if err := pr.Issue.LoadRepo(hammerCtx); err != nil {
- log.Error("LoadRepo for issue [%d]: %v", pr.ID, err)
+ log.Error("pr.Issue.LoadRepo %-v: %v", pr, err)
}
if err := pr.Issue.Repo.LoadOwner(hammerCtx); err != nil {
- log.Error("LoadOwner for PR [%d]: %v", pr.ID, err)
+ log.Error("LoadOwner for %-v: %v", pr, err)
}
if wasAutoMerged {
@@ -239,326 +232,43 @@ func Merge(ctx context.Context, pr *issues_model.PullRequest, doer *user_model.U
return nil
}
-// rawMerge perform the merge operation without changing any pull information in database
-func rawMerge(ctx context.Context, pr *issues_model.PullRequest, doer *user_model.User, mergeStyle repo_model.MergeStyle, expectedHeadCommitID, message string) (string, error) {
+// doMergeAndPush performs the merge operation without changing any pull information in database and pushes it up to the base repository
+func doMergeAndPush(ctx context.Context, pr *issues_model.PullRequest, doer *user_model.User, mergeStyle repo_model.MergeStyle, expectedHeadCommitID, message string) (string, error) {
// Clone base repo.
- tmpBasePath, err := createTemporaryRepo(ctx, pr)
+ mergeCtx, cancel, err := createTemporaryRepoForMerge(ctx, pr, doer, expectedHeadCommitID)
if err != nil {
- log.Error("CreateTemporaryPath: %v", err)
return "", err
}
- defer func() {
- if err := repo_module.RemoveTemporaryPath(tmpBasePath); err != nil {
- log.Error("Merge: RemoveTemporaryPath: %s", err)
- }
- }()
-
- baseBranch := "base"
- trackingBranch := "tracking"
- stagingBranch := "staging"
-
- if expectedHeadCommitID != "" {
- trackingCommitID, _, err := git.NewCommand(ctx, "show-ref", "--hash").AddDynamicArguments(git.BranchPrefix + trackingBranch).RunStdString(&git.RunOpts{Dir: tmpBasePath})
- if err != nil {
- log.Error("show-ref[%s] --hash refs/heads/trackingn: %v", tmpBasePath, git.BranchPrefix+trackingBranch, err)
- return "", fmt.Errorf("getDiffTree: %w", err)
- }
- if strings.TrimSpace(trackingCommitID) != expectedHeadCommitID {
- return "", models.ErrSHADoesNotMatch{
- GivenSHA: expectedHeadCommitID,
- CurrentSHA: trackingCommitID,
- }
- }
- }
-
- var outbuf, errbuf strings.Builder
-
- // Enable sparse-checkout
- sparseCheckoutList, err := getDiffTree(ctx, tmpBasePath, baseBranch, trackingBranch)
- if err != nil {
- log.Error("getDiffTree(%s, %s, %s): %v", tmpBasePath, baseBranch, trackingBranch, err)
- return "", fmt.Errorf("getDiffTree: %w", err)
- }
-
- infoPath := filepath.Join(tmpBasePath, ".git", "info")
- if err := os.MkdirAll(infoPath, 0o700); err != nil {
- log.Error("Unable to create .git/info in %s: %v", tmpBasePath, err)
- return "", fmt.Errorf("Unable to create .git/info in tmpBasePath: %w", err)
- }
-
- sparseCheckoutListPath := filepath.Join(infoPath, "sparse-checkout")
- if err := os.WriteFile(sparseCheckoutListPath, []byte(sparseCheckoutList), 0o600); err != nil {
- log.Error("Unable to write .git/info/sparse-checkout file in %s: %v", tmpBasePath, err)
- return "", fmt.Errorf("Unable to write .git/info/sparse-checkout file in tmpBasePath: %w", err)
- }
-
- gitConfigCommand := func() *git.Command {
- return git.NewCommand(ctx, "config", "--local")
- }
-
- // Switch off LFS process (set required, clean and smudge here also)
- if err := gitConfigCommand().AddArguments("filter.lfs.process", "").
- Run(&git.RunOpts{
- Dir: tmpBasePath,
- Stdout: &outbuf,
- Stderr: &errbuf,
- }); err != nil {
- log.Error("git config [filter.lfs.process -> <> ]: %v\n%s\n%s", err, outbuf.String(), errbuf.String())
- return "", fmt.Errorf("git config [filter.lfs.process -> <> ]: %w\n%s\n%s", err, outbuf.String(), errbuf.String())
- }
- outbuf.Reset()
- errbuf.Reset()
-
- if err := gitConfigCommand().AddArguments("filter.lfs.required", "false").
- Run(&git.RunOpts{
- Dir: tmpBasePath,
- Stdout: &outbuf,
- Stderr: &errbuf,
- }); err != nil {
- log.Error("git config [filter.lfs.required -> <false> ]: %v\n%s\n%s", err, outbuf.String(), errbuf.String())
- return "", fmt.Errorf("git config [filter.lfs.required -> <false> ]: %w\n%s\n%s", err, outbuf.String(), errbuf.String())
- }
- outbuf.Reset()
- errbuf.Reset()
-
- if err := gitConfigCommand().AddArguments("filter.lfs.clean", "").
- Run(&git.RunOpts{
- Dir: tmpBasePath,
- Stdout: &outbuf,
- Stderr: &errbuf,
- }); err != nil {
- log.Error("git config [filter.lfs.clean -> <> ]: %v\n%s\n%s", err, outbuf.String(), errbuf.String())
- return "", fmt.Errorf("git config [filter.lfs.clean -> <> ]: %w\n%s\n%s", err, outbuf.String(), errbuf.String())
- }
- outbuf.Reset()
- errbuf.Reset()
-
- if err := gitConfigCommand().AddArguments("filter.lfs.smudge", "").
- Run(&git.RunOpts{
- Dir: tmpBasePath,
- Stdout: &outbuf,
- Stderr: &errbuf,
- }); err != nil {
- log.Error("git config [filter.lfs.smudge -> <> ]: %v\n%s\n%s", err, outbuf.String(), errbuf.String())
- return "", fmt.Errorf("git config [filter.lfs.smudge -> <> ]: %w\n%s\n%s", err, outbuf.String(), errbuf.String())
- }
- outbuf.Reset()
- errbuf.Reset()
-
- if err := gitConfigCommand().AddArguments("core.sparseCheckout", "true").
- Run(&git.RunOpts{
- Dir: tmpBasePath,
- Stdout: &outbuf,
- Stderr: &errbuf,
- }); err != nil {
- log.Error("git config [core.sparseCheckout -> true ]: %v\n%s\n%s", err, outbuf.String(), errbuf.String())
- return "", fmt.Errorf("git config [core.sparsecheckout -> true]: %w\n%s\n%s", err, outbuf.String(), errbuf.String())
- }
- outbuf.Reset()
- errbuf.Reset()
-
- // Read base branch index
- if err := git.NewCommand(ctx, "read-tree", "HEAD").
- Run(&git.RunOpts{
- Dir: tmpBasePath,
- Stdout: &outbuf,
- Stderr: &errbuf,
- }); err != nil {
- log.Error("git read-tree HEAD: %v\n%s\n%s", err, outbuf.String(), errbuf.String())
- return "", fmt.Errorf("Unable to read base branch in to the index: %w\n%s\n%s", err, outbuf.String(), errbuf.String())
- }
- outbuf.Reset()
- errbuf.Reset()
-
- sig := doer.NewGitSig()
- committer := sig
-
- // Determine if we should sign. If no signKeyID, use --no-gpg-sign to countermand the sign config (from gitconfig)
- var signArgs git.TrustedCmdArgs
- sign, signKeyID, signer, _ := asymkey_service.SignMerge(ctx, pr, doer, tmpBasePath, "HEAD", trackingBranch)
- if sign {
- if pr.BaseRepo.GetTrustModel() == repo_model.CommitterTrustModel || pr.BaseRepo.GetTrustModel() == repo_model.CollaboratorCommitterTrustModel {
- committer = signer
- }
- signArgs = git.ToTrustedCmdArgs([]string{"-S" + signKeyID})
- } else {
- signArgs = append(signArgs, "--no-gpg-sign")
- }
-
- commitTimeStr := time.Now().Format(time.RFC3339)
-
- // Because this may call hooks we should pass in the environment
- env := append(os.Environ(),
- "GIT_AUTHOR_NAME="+sig.Name,
- "GIT_AUTHOR_EMAIL="+sig.Email,
- "GIT_AUTHOR_DATE="+commitTimeStr,
- "GIT_COMMITTER_NAME="+committer.Name,
- "GIT_COMMITTER_EMAIL="+committer.Email,
- "GIT_COMMITTER_DATE="+commitTimeStr,
- )
+ defer cancel()
// Merge commits.
switch mergeStyle {
case repo_model.MergeStyleMerge:
- cmd := git.NewCommand(ctx, "merge", "--no-ff", "--no-commit").AddDynamicArguments(trackingBranch)
- if err := runMergeCommand(pr, mergeStyle, cmd, tmpBasePath); err != nil {
- log.Error("Unable to merge tracking into base: %v", err)
+ if err := doMergeStyleMerge(mergeCtx, message); err != nil {
return "", err
}
-
- if err := commitAndSignNoAuthor(ctx, pr, message, signArgs, tmpBasePath, env); err != nil {
- log.Error("Unable to make final commit: %v", err)
+ case repo_model.MergeStyleRebase, repo_model.MergeStyleRebaseMerge:
+ if err := doMergeStyleRebase(mergeCtx, mergeStyle, message); err != nil {
return "", err
}
- case repo_model.MergeStyleRebase:
- fallthrough
- case repo_model.MergeStyleRebaseUpdate:
- fallthrough
- case repo_model.MergeStyleRebaseMerge:
- // Checkout head branch
- if err := git.NewCommand(ctx, "checkout", "-b").AddDynamicArguments(stagingBranch, trackingBranch).
- Run(&git.RunOpts{
- Dir: tmpBasePath,
- Stdout: &outbuf,
- Stderr: &errbuf,
- }); err != nil {
- log.Error("git checkout base prior to merge post staging rebase [%s:%s -> %s:%s]: %v\n%s\n%s", pr.HeadRepo.FullName(), pr.HeadBranch, pr.BaseRepo.FullName(), pr.BaseBranch, err, outbuf.String(), errbuf.String())
- return "", fmt.Errorf("git checkout base prior to merge post staging rebase [%s:%s -> %s:%s]: %w\n%s\n%s", pr.HeadRepo.FullName(), pr.HeadBranch, pr.BaseRepo.FullName(), pr.BaseBranch, err, outbuf.String(), errbuf.String())
- }
- outbuf.Reset()
- errbuf.Reset()
-
- // Rebase before merging
- if err := git.NewCommand(ctx, "rebase").AddDynamicArguments(baseBranch).
- Run(&git.RunOpts{
- Dir: tmpBasePath,
- Stdout: &outbuf,
- Stderr: &errbuf,
- }); err != nil {
- // Rebase will leave a REBASE_HEAD file in .git if there is a conflict
- if _, statErr := os.Stat(filepath.Join(tmpBasePath, ".git", "REBASE_HEAD")); statErr == nil {
- var commitSha string
- ok := false
- failingCommitPaths := []string{
- filepath.Join(tmpBasePath, ".git", "rebase-apply", "original-commit"), // Git < 2.26
- filepath.Join(tmpBasePath, ".git", "rebase-merge", "stopped-sha"), // Git >= 2.26
- }
- for _, failingCommitPath := range failingCommitPaths {
- if _, statErr := os.Stat(failingCommitPath); statErr == nil {
- commitShaBytes, readErr := os.ReadFile(failingCommitPath)
- if readErr != nil {
- // Abandon this attempt to handle the error
- log.Error("git rebase staging on to base [%s:%s -> %s:%s]: %v\n%s\n%s", pr.HeadRepo.FullName(), pr.HeadBranch, pr.BaseRepo.FullName(), pr.BaseBranch, err, outbuf.String(), errbuf.String())
- return "", fmt.Errorf("git rebase staging on to base [%s:%s -> %s:%s]: %w\n%s\n%s", pr.HeadRepo.FullName(), pr.HeadBranch, pr.BaseRepo.FullName(), pr.BaseBranch, err, outbuf.String(), errbuf.String())
- }
- commitSha = strings.TrimSpace(string(commitShaBytes))
- ok = true
- break
- }
- }
- if !ok {
- log.Error("Unable to determine failing commit sha for this rebase message. Cannot cast as models.ErrRebaseConflicts.")
- log.Error("git rebase staging on to base [%s:%s -> %s:%s]: %v\n%s\n%s", pr.HeadRepo.FullName(), pr.HeadBranch, pr.BaseRepo.FullName(), pr.BaseBranch, err, outbuf.String(), errbuf.String())
- return "", fmt.Errorf("git rebase staging on to base [%s:%s -> %s:%s]: %w\n%s\n%s", pr.HeadRepo.FullName(), pr.HeadBranch, pr.BaseRepo.FullName(), pr.BaseBranch, err, outbuf.String(), errbuf.String())
- }
- log.Debug("RebaseConflict at %s [%s:%s -> %s:%s]: %v\n%s\n%s", commitSha, pr.HeadRepo.FullName(), pr.HeadBranch, pr.BaseRepo.FullName(), pr.BaseBranch, err, outbuf.String(), errbuf.String())
- return "", models.ErrRebaseConflicts{
- Style: mergeStyle,
- CommitSHA: commitSha,
- StdOut: outbuf.String(),
- StdErr: errbuf.String(),
- Err: err,
- }
- }
- log.Error("git rebase staging on to base [%s:%s -> %s:%s]: %v\n%s\n%s", pr.HeadRepo.FullName(), pr.HeadBranch, pr.BaseRepo.FullName(), pr.BaseBranch, err, outbuf.String(), errbuf.String())
- return "", fmt.Errorf("git rebase staging on to base [%s:%s -> %s:%s]: %w\n%s\n%s", pr.HeadRepo.FullName(), pr.HeadBranch, pr.BaseRepo.FullName(), pr.BaseBranch, err, outbuf.String(), errbuf.String())
- }
- outbuf.Reset()
- errbuf.Reset()
-
- // not need merge, just update by rebase. so skip
- if mergeStyle == repo_model.MergeStyleRebaseUpdate {
- break
- }
-
- // Checkout base branch again
- if err := git.NewCommand(ctx, "checkout").AddDynamicArguments(baseBranch).
- Run(&git.RunOpts{
- Dir: tmpBasePath,
- Stdout: &outbuf,
- Stderr: &errbuf,
- }); err != nil {
- log.Error("git checkout base prior to merge post staging rebase [%s:%s -> %s:%s]: %v\n%s\n%s", pr.HeadRepo.FullName(), pr.HeadBranch, pr.BaseRepo.FullName(), pr.BaseBranch, err, outbuf.String(), errbuf.String())
- return "", fmt.Errorf("git checkout base prior to merge post staging rebase [%s:%s -> %s:%s]: %w\n%s\n%s", pr.HeadRepo.FullName(), pr.HeadBranch, pr.BaseRepo.FullName(), pr.BaseBranch, err, outbuf.String(), errbuf.String())
- }
- outbuf.Reset()
- errbuf.Reset()
-
- cmd := git.NewCommand(ctx, "merge")
- if mergeStyle == repo_model.MergeStyleRebase {
- cmd.AddArguments("--ff-only")
- } else {
- cmd.AddArguments("--no-ff", "--no-commit")
- }
- cmd.AddDynamicArguments(stagingBranch)
-
- // Prepare merge with commit
- if err := runMergeCommand(pr, mergeStyle, cmd, tmpBasePath); err != nil {
- log.Error("Unable to merge staging into base: %v", err)
- return "", err
- }
- if mergeStyle == repo_model.MergeStyleRebaseMerge {
- if err := commitAndSignNoAuthor(ctx, pr, message, signArgs, tmpBasePath, env); err != nil {
- log.Error("Unable to make final commit: %v", err)
- return "", err
- }
- }
case repo_model.MergeStyleSquash:
- // Merge with squash
- cmd := git.NewCommand(ctx, "merge", "--squash").AddDynamicArguments(trackingBranch)
- if err := runMergeCommand(pr, mergeStyle, cmd, tmpBasePath); err != nil {
- log.Error("Unable to merge --squash tracking into base: %v", err)
+ if err := doMergeStyleSquash(mergeCtx, message); err != nil {
return "", err
}
-
- if err = pr.Issue.LoadPoster(ctx); err != nil {
- log.Error("LoadPoster: %v", err)
- return "", fmt.Errorf("LoadPoster: %w", err)
- }
- sig := pr.Issue.Poster.NewGitSig()
- if setting.Repository.PullRequest.AddCoCommitterTrailers && committer.String() != sig.String() {
- // add trailer
- message += fmt.Sprintf("\nCo-authored-by: %s\nCo-committed-by: %s\n", sig.String(), sig.String())
- }
- if err := git.NewCommand(ctx, "commit").
- AddArguments(signArgs...).
- AddOptionFormat("--author='%s <%s>'", sig.Name, sig.Email).
- AddOptionFormat("--message=%s", message).
- Run(&git.RunOpts{
- Env: env,
- Dir: tmpBasePath,
- Stdout: &outbuf,
- Stderr: &errbuf,
- }); err != nil {
- log.Error("git commit [%s:%s -> %s:%s]: %v\n%s\n%s", pr.HeadRepo.FullName(), pr.HeadBranch, pr.BaseRepo.FullName(), pr.BaseBranch, err, outbuf.String(), errbuf.String())
- return "", fmt.Errorf("git commit [%s:%s -> %s:%s]: %w\n%s\n%s", pr.HeadRepo.FullName(), pr.HeadBranch, pr.BaseRepo.FullName(), pr.BaseBranch, err, outbuf.String(), errbuf.String())
- }
- outbuf.Reset()
- errbuf.Reset()
default:
return "", models.ErrInvalidMergeStyle{ID: pr.BaseRepo.ID, Style: mergeStyle}
}
// OK we should cache our current head and origin/headbranch
- mergeHeadSHA, err := git.GetFullCommitID(ctx, tmpBasePath, "HEAD")
+ mergeHeadSHA, err := git.GetFullCommitID(ctx, mergeCtx.tmpBasePath, "HEAD")
if err != nil {
return "", fmt.Errorf("Failed to get full commit id for HEAD: %w", err)
}
- mergeBaseSHA, err := git.GetFullCommitID(ctx, tmpBasePath, "original_"+baseBranch)
+ mergeBaseSHA, err := git.GetFullCommitID(ctx, mergeCtx.tmpBasePath, "original_"+baseBranch)
if err != nil {
return "", fmt.Errorf("Failed to get full commit id for origin/%s: %w", pr.BaseBranch, err)
}
- mergeCommitID, err := git.GetFullCommitID(ctx, tmpBasePath, baseBranch)
+ mergeCommitID, err := git.GetFullCommitID(ctx, mergeCtx.tmpBasePath, baseBranch)
if err != nil {
return "", fmt.Errorf("Failed to get full commit id for the new merge: %w", err)
}
@@ -567,7 +277,7 @@ func rawMerge(ctx context.Context, pr *issues_model.PullRequest, doer *user_mode
// I think in the interests of data safety - failures to push to the lfs should prevent
// the merge as you can always remerge.
if setting.LFS.StartServer {
- if err := LFSPush(ctx, tmpBasePath, mergeHeadSHA, mergeBaseSHA, pr); err != nil {
+ if err := LFSPush(ctx, mergeCtx.tmpBasePath, mergeHeadSHA, mergeBaseSHA, pr); err != nil {
return "", err
}
}
@@ -576,167 +286,97 @@ func rawMerge(ctx context.Context, pr *issues_model.PullRequest, doer *user_mode
err = pr.HeadRepo.LoadOwner(ctx)
if err != nil {
if !user_model.IsErrUserNotExist(err) {
- log.Error("Can't find user: %d for head repository - %v", pr.HeadRepo.OwnerID, err)
+ log.Error("Can't find user: %d for head repository in %-v: %v", pr.HeadRepo.OwnerID, pr, err)
return "", err
}
- log.Error("Can't find user: %d for head repository - defaulting to doer: %s - %v", pr.HeadRepo.OwnerID, doer.Name, err)
+ log.Warn("Can't find user: %d for head repository in %-v - defaulting to doer: %s - %v", pr.HeadRepo.OwnerID, pr, doer.Name, err)
headUser = doer
} else {
headUser = pr.HeadRepo.Owner
}
- var pushCmd *git.Command
- if mergeStyle == repo_model.MergeStyleRebaseUpdate {
- // force push the rebase result to head branch
- env = repo_module.FullPushingEnvironment(
- headUser,
- doer,
- pr.HeadRepo,
- pr.HeadRepo.Name,
- pr.ID,
- )
- pushCmd = git.NewCommand(ctx, "push", "-f", "head_repo").AddDynamicArguments(stagingBranch + ":" + git.BranchPrefix + pr.HeadBranch)
- } else {
- env = repo_module.FullPushingEnvironment(
- headUser,
- doer,
- pr.BaseRepo,
- pr.BaseRepo.Name,
- pr.ID,
- )
- pushCmd = git.NewCommand(ctx, "push", "origin").AddDynamicArguments(baseBranch + ":" + git.BranchPrefix + pr.BaseBranch)
- }
+ mergeCtx.env = repo_module.FullPushingEnvironment(
+ headUser,
+ doer,
+ pr.BaseRepo,
+ pr.BaseRepo.Name,
+ pr.ID,
+ )
+ pushCmd := git.NewCommand(ctx, "push", "origin").AddDynamicArguments(baseBranch + ":" + git.BranchPrefix + pr.BaseBranch)
// Push back to upstream.
// TODO: this cause an api call to "/api/internal/hook/post-receive/...",
// that prevents us from doint the whole merge in one db transaction
- if err := pushCmd.Run(&git.RunOpts{
- Env: env,
- Dir: tmpBasePath,
- Stdout: &outbuf,
- Stderr: &errbuf,
- }); err != nil {
- if strings.Contains(errbuf.String(), "non-fast-forward") {
+ if err := pushCmd.Run(mergeCtx.RunOpts()); err != nil {
+ if strings.Contains(mergeCtx.errbuf.String(), "non-fast-forward") {
return "", &git.ErrPushOutOfDate{
- StdOut: outbuf.String(),
- StdErr: errbuf.String(),
+ StdOut: mergeCtx.outbuf.String(),
+ StdErr: mergeCtx.errbuf.String(),
Err: err,
}
- } else if strings.Contains(errbuf.String(), "! [remote rejected]") {
+ } else if strings.Contains(mergeCtx.errbuf.String(), "! [remote rejected]") {
err := &git.ErrPushRejected{
- StdOut: outbuf.String(),
- StdErr: errbuf.String(),
+ StdOut: mergeCtx.outbuf.String(),
+ StdErr: mergeCtx.errbuf.String(),
Err: err,
}
err.GenerateMessage()
return "", err
}
- return "", fmt.Errorf("git push: %s", errbuf.String())
+ return "", fmt.Errorf("git push: %s", mergeCtx.errbuf.String())
}
- outbuf.Reset()
- errbuf.Reset()
+ mergeCtx.outbuf.Reset()
+ mergeCtx.errbuf.Reset()
return mergeCommitID, nil
}
-func commitAndSignNoAuthor(ctx context.Context, pr *issues_model.PullRequest, message string, signArgs git.TrustedCmdArgs, tmpBasePath string, env []string) error {
- var outbuf, errbuf strings.Builder
- if err := git.NewCommand(ctx, "commit").AddArguments(signArgs...).AddOptionFormat("--message=%s", message).
- Run(&git.RunOpts{
- Env: env,
- Dir: tmpBasePath,
- Stdout: &outbuf,
- Stderr: &errbuf,
- }); err != nil {
- log.Error("git commit [%s:%s -> %s:%s]: %v\n%s\n%s", pr.HeadRepo.FullName(), pr.HeadBranch, pr.BaseRepo.FullName(), pr.BaseBranch, err, outbuf.String(), errbuf.String())
- return fmt.Errorf("git commit [%s:%s -> %s:%s]: %w\n%s\n%s", pr.HeadRepo.FullName(), pr.HeadBranch, pr.BaseRepo.FullName(), pr.BaseBranch, err, outbuf.String(), errbuf.String())
+func commitAndSignNoAuthor(ctx *mergeContext, message string) error {
+ cmdCommit := git.NewCommand(ctx, "commit").AddOptionFormat("--message=%s", message)
+ if ctx.signKeyID == "" {
+ cmdCommit.AddArguments("--no-gpg-sign")
+ } else {
+ cmdCommit.AddOptionFormat("-S%s", ctx.signKeyID)
+ }
+ if err := cmdCommit.Run(ctx.RunOpts()); err != nil {
+ log.Error("git commit %-v: %v\n%s\n%s", ctx.pr, err, ctx.outbuf.String(), ctx.errbuf.String())
+ return fmt.Errorf("git commit %v: %w\n%s\n%s", ctx.pr, err, ctx.outbuf.String(), ctx.errbuf.String())
}
return nil
}
-func runMergeCommand(pr *issues_model.PullRequest, mergeStyle repo_model.MergeStyle, cmd *git.Command, tmpBasePath string) error {
- var outbuf, errbuf strings.Builder
- if err := cmd.Run(&git.RunOpts{
- Dir: tmpBasePath,
- Stdout: &outbuf,
- Stderr: &errbuf,
- }); err != nil {
+func runMergeCommand(ctx *mergeContext, mergeStyle repo_model.MergeStyle, cmd *git.Command) error {
+ if err := cmd.Run(ctx.RunOpts()); err != nil {
// Merge will leave a MERGE_HEAD file in the .git folder if there is a conflict
- if _, statErr := os.Stat(filepath.Join(tmpBasePath, ".git", "MERGE_HEAD")); statErr == nil {
+ if _, statErr := os.Stat(filepath.Join(ctx.tmpBasePath, ".git", "MERGE_HEAD")); statErr == nil {
// We have a merge conflict error
- log.Debug("MergeConflict [%s:%s -> %s:%s]: %v\n%s\n%s", pr.HeadRepo.FullName(), pr.HeadBranch, pr.BaseRepo.FullName(), pr.BaseBranch, err, outbuf.String(), errbuf.String())
+ log.Debug("MergeConflict %-v: %v\n%s\n%s", ctx.pr, err, ctx.outbuf.String(), ctx.errbuf.String())
return models.ErrMergeConflicts{
Style: mergeStyle,
- StdOut: outbuf.String(),
- StdErr: errbuf.String(),
+ StdOut: ctx.outbuf.String(),
+ StdErr: ctx.errbuf.String(),
Err: err,
}
- } else if strings.Contains(errbuf.String(), "refusing to merge unrelated histories") {
- log.Debug("MergeUnrelatedHistories [%s:%s -> %s:%s]: %v\n%s\n%s", pr.HeadRepo.FullName(), pr.HeadBranch, pr.BaseRepo.FullName(), pr.BaseBranch, err, outbuf.String(), errbuf.String())
+ } else if strings.Contains(ctx.errbuf.String(), "refusing to merge unrelated histories") {
+ log.Debug("MergeUnrelatedHistories %-v: %v\n%s\n%s", ctx.pr, err, ctx.outbuf.String(), ctx.errbuf.String())
return models.ErrMergeUnrelatedHistories{
Style: mergeStyle,
- StdOut: outbuf.String(),
- StdErr: errbuf.String(),
+ StdOut: ctx.outbuf.String(),
+ StdErr: ctx.errbuf.String(),
Err: err,
}
}
- log.Error("git merge [%s:%s -> %s:%s]: %v\n%s\n%s", pr.HeadRepo.FullName(), pr.HeadBranch, pr.BaseRepo.FullName(), pr.BaseBranch, err, outbuf.String(), errbuf.String())
- return fmt.Errorf("git merge [%s:%s -> %s:%s]: %w\n%s\n%s", pr.HeadRepo.FullName(), pr.HeadBranch, pr.BaseRepo.FullName(), pr.BaseBranch, err, outbuf.String(), errbuf.String())
+ log.Error("git merge %-v: %v\n%s\n%s", ctx.pr, err, ctx.outbuf.String(), ctx.errbuf.String())
+ return fmt.Errorf("git merge %v: %w\n%s\n%s", ctx.pr, err, ctx.outbuf.String(), ctx.errbuf.String())
}
+ ctx.outbuf.Reset()
+ ctx.errbuf.Reset()
return nil
}
var escapedSymbols = regexp.MustCompile(`([*[?! \\])`)
-func getDiffTree(ctx context.Context, repoPath, baseBranch, headBranch string) (string, error) {
- getDiffTreeFromBranch := func(repoPath, baseBranch, headBranch string) (string, error) {
- var outbuf, errbuf strings.Builder
- // Compute the diff-tree for sparse-checkout
- if err := git.NewCommand(ctx, "diff-tree", "--no-commit-id", "--name-only", "-r", "-z", "--root").AddDynamicArguments(baseBranch, headBranch).
- Run(&git.RunOpts{
- Dir: repoPath,
- Stdout: &outbuf,
- Stderr: &errbuf,
- }); err != nil {
- return "", fmt.Errorf("git diff-tree [%s base:%s head:%s]: %s", repoPath, baseBranch, headBranch, errbuf.String())
- }
- return outbuf.String(), nil
- }
-
- scanNullTerminatedStrings := func(data []byte, atEOF bool) (advance int, token []byte, err error) {
- if atEOF && len(data) == 0 {
- return 0, nil, nil
- }
- if i := bytes.IndexByte(data, '\x00'); i >= 0 {
- return i + 1, data[0:i], nil
- }
- if atEOF {
- return len(data), data, nil
- }
- return 0, nil, nil
- }
-
- list, err := getDiffTreeFromBranch(repoPath, baseBranch, headBranch)
- if err != nil {
- return "", err
- }
-
- // Prefixing '/' for each entry, otherwise all files with the same name in subdirectories would be matched.
- out := bytes.Buffer{}
- scanner := bufio.NewScanner(strings.NewReader(list))
- scanner.Split(scanNullTerminatedStrings)
- for scanner.Scan() {
- filepath := scanner.Text()
- // escape '*', '?', '[', spaces and '!' prefix
- filepath = escapedSymbols.ReplaceAllString(filepath, `\$1`)
- // no necessary to escape the first '#' symbol because the first symbol is '/'
- fmt.Fprintf(&out, "/%s\n", filepath)
- }
-
- return out.String(), nil
-}
-
// IsUserAllowedToMerge check if user is allowed to merge PR with given permissions and branch protections
func IsUserAllowedToMerge(ctx context.Context, pr *issues_model.PullRequest, p access_model.Permission, user *user_model.User) (bool, error) {
if user == nil {
diff --git a/services/pull/merge_merge.go b/services/pull/merge_merge.go
new file mode 100644
index 000000000..0f7664297
--- /dev/null
+++ b/services/pull/merge_merge.go
@@ -0,0 +1,25 @@
+// Copyright 2023 The Gitea Authors. All rights reserved.
+// SPDX-License-Identifier: MIT
+
+package pull
+
+import (
+ repo_model "code.gitea.io/gitea/models/repo"
+ "code.gitea.io/gitea/modules/git"
+ "code.gitea.io/gitea/modules/log"
+)
+
+// doMergeStyleMerge merges the tracking into the current HEAD - which is assumed to tbe staging branch (equal to the pr.BaseBranch)
+func doMergeStyleMerge(ctx *mergeContext, message string) error {
+ cmd := git.NewCommand(ctx, "merge", "--no-ff", "--no-commit").AddDynamicArguments(trackingBranch)
+ if err := runMergeCommand(ctx, repo_model.MergeStyleMerge, cmd); err != nil {
+ log.Error("%-v Unable to merge tracking into base: %v", ctx.pr, err)
+ return err
+ }
+
+ if err := commitAndSignNoAuthor(ctx, message); err != nil {
+ log.Error("%-v Unable to make final commit: %v", ctx.pr, err)
+ return err
+ }
+ return nil
+}
diff --git a/services/pull/merge_prepare.go b/services/pull/merge_prepare.go
new file mode 100644
index 000000000..88f6c037e
--- /dev/null
+++ b/services/pull/merge_prepare.go
@@ -0,0 +1,288 @@
+// Copyright 2023 The Gitea Authors. All rights reserved.
+// SPDX-License-Identifier: MIT
+
+package pull
+
+import (
+ "bufio"
+ "bytes"
+ "context"
+ "fmt"
+ "io"
+ "os"
+ "path/filepath"
+ "strings"
+ "time"
+
+ "code.gitea.io/gitea/models"
+ issues_model "code.gitea.io/gitea/models/issues"
+ repo_model "code.gitea.io/gitea/models/repo"
+ user_model "code.gitea.io/gitea/models/user"
+ "code.gitea.io/gitea/modules/git"
+ "code.gitea.io/gitea/modules/log"
+ asymkey_service "code.gitea.io/gitea/services/asymkey"
+)
+
+type mergeContext struct {
+ *prContext
+ doer *user_model.User
+ sig *git.Signature
+ committer *git.Signature
+ signKeyID string // empty for no-sign, non-empty to sign
+ env []string
+}
+
+func (ctx *mergeContext) RunOpts() *git.RunOpts {
+ ctx.outbuf.Reset()
+ ctx.errbuf.Reset()
+ return &git.RunOpts{
+ Env: ctx.env,
+ Dir: ctx.tmpBasePath,
+ Stdout: ctx.outbuf,
+ Stderr: ctx.errbuf,
+ }
+}
+
+func createTemporaryRepoForMerge(ctx context.Context, pr *issues_model.PullRequest, doer *user_model.User, expectedHeadCommitID string) (mergeCtx *mergeContext, cancel context.CancelFunc, err error) {
+ // Clone base repo.
+ prCtx, cancel, err := createTemporaryRepoForPR(ctx, pr)
+ if err != nil {
+ log.Error("createTemporaryRepoForPR: %v", err)
+ return nil, cancel, err
+ }
+
+ mergeCtx = &mergeContext{
+ prContext: prCtx,
+ doer: doer,
+ }
+
+ if expectedHeadCommitID != "" {
+ trackingCommitID, _, err := git.NewCommand(ctx, "show-ref", "--hash").AddDynamicArguments(git.BranchPrefix + trackingBranch).RunStdString(&git.RunOpts{Dir: mergeCtx.tmpBasePath})
+ if err != nil {
+ defer cancel()
+ log.Error("failed to get sha of head branch in %-v: show-ref[%s] --hash refs/heads/tracking: %v", mergeCtx.pr, mergeCtx.tmpBasePath, err)
+ return nil, nil, fmt.Errorf("unable to get sha of head branch in %v %w", pr, err)
+ }
+ if strings.TrimSpace(trackingCommitID) != expectedHeadCommitID {
+ defer cancel()
+ return nil, nil, models.ErrSHADoesNotMatch{
+ GivenSHA: expectedHeadCommitID,
+ CurrentSHA: trackingCommitID,
+ }
+ }
+ }
+
+ mergeCtx.outbuf.Reset()
+ mergeCtx.errbuf.Reset()
+ if err := prepareTemporaryRepoForMerge(mergeCtx); err != nil {
+ defer cancel()
+ return nil, nil, err
+ }
+
+ mergeCtx.sig = doer.NewGitSig()
+ mergeCtx.committer = mergeCtx.sig
+
+ // Determine if we should sign
+ sign, keyID, signer, _ := asymkey_service.SignMerge(ctx, mergeCtx.pr, mergeCtx.doer, mergeCtx.tmpBasePath, "HEAD", trackingBranch)
+ if sign {
+ mergeCtx.signKeyID = keyID
+ if pr.BaseRepo.GetTrustModel() == repo_model.CommitterTrustModel || pr.BaseRepo.GetTrustModel() == repo_model.CollaboratorCommitterTrustModel {
+ mergeCtx.committer = signer
+ }
+ }
+
+ commitTimeStr := time.Now().Format(time.RFC3339)
+
+ // Because this may call hooks we should pass in the environment
+ mergeCtx.env = append(os.Environ(),
+ "GIT_AUTHOR_NAME="+mergeCtx.sig.Name,
+ "GIT_AUTHOR_EMAIL="+mergeCtx.sig.Email,
+ "GIT_AUTHOR_DATE="+commitTimeStr,
+ "GIT_COMMITTER_NAME="+mergeCtx.committer.Name,
+ "GIT_COMMITTER_EMAIL="+mergeCtx.committer.Email,
+ "GIT_COMMITTER_DATE="+commitTimeStr,
+ )
+
+ return mergeCtx, cancel, nil
+}
+
+// prepareTemporaryRepoForMerge takes a repository that has been created using createTemporaryRepo
+// it then sets up the sparse-checkout and other things
+func prepareTemporaryRepoForMerge(ctx *mergeContext) error {
+ infoPath := filepath.Join(ctx.tmpBasePath, ".git", "info")
+ if err := os.MkdirAll(infoPath, 0o700); err != nil {
+ log.Error("%-v Unable to create .git/info in %s: %v", ctx.pr, ctx.tmpBasePath, err)
+ return fmt.Errorf("Unable to create .git/info in tmpBasePath: %w", err)
+ }
+
+ // Enable sparse-checkout
+ // Here we use the .git/info/sparse-checkout file as described in the git documentation
+ sparseCheckoutListFile, err := os.OpenFile(filepath.Join(infoPath, "sparse-checkout"), os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0o600)
+ if err != nil {
+ log.Error("%-v Unable to write .git/info/sparse-checkout file in %s: %v", ctx.pr, ctx.tmpBasePath, err)
+ return fmt.Errorf("Unable to write .git/info/sparse-checkout file in tmpBasePath: %w", err)
+ }
+ defer sparseCheckoutListFile.Close() // we will close it earlier but we need to ensure it is closed if there is an error
+
+ if err := getDiffTree(ctx, ctx.tmpBasePath, baseBranch, trackingBranch, sparseCheckoutListFile); err != nil {
+ log.Error("%-v getDiffTree(%s, %s, %s): %v", ctx.pr, ctx.tmpBasePath, baseBranch, trackingBranch, err)
+ return fmt.Errorf("getDiffTree: %w", err)
+ }
+
+ if err := sparseCheckoutListFile.Close(); err != nil {
+ log.Error("%-v Unable to close .git/info/sparse-checkout file in %s: %v", ctx.pr, ctx.tmpBasePath, err)
+ return fmt.Errorf("Unable to close .git/info/sparse-checkout file in tmpBasePath: %w", err)
+ }
+
+ setConfig := func(key, value string) error {
+ if err := git.NewCommand(ctx, "config", "--local").AddDynamicArguments(key, value).
+ Run(ctx.RunOpts()); err != nil {
+ log.Error("git config [%s -> %q]: %v\n%s\n%s", key, value, err, ctx.outbuf.String(), ctx.errbuf.String())
+ return fmt.Errorf("git config [%s -> %q]: %w\n%s\n%s", key, value, err, ctx.outbuf.String(), ctx.errbuf.String())
+ }
+ ctx.outbuf.Reset()
+ ctx.errbuf.Reset()
+
+ return nil
+ }
+
+ // Switch off LFS process (set required, clean and smudge here also)
+ if err := setConfig("filter.lfs.process", ""); err != nil {
+ return err
+ }
+
+ if err := setConfig("filter.lfs.required", "false"); err != nil {
+ return err
+ }
+
+ if err := setConfig("filter.lfs.clean", ""); err != nil {
+ return err
+ }
+
+ if err := setConfig("filter.lfs.smudge", ""); err != nil {
+ return err
+ }
+
+ if err := setConfig("core.sparseCheckout", "true"); err != nil {
+ return err
+ }
+
+ // Read base branch index
+ if err := git.NewCommand(ctx, "read-tree", "HEAD").
+ Run(ctx.RunOpts()); err != nil {
+ log.Error("git read-tree HEAD: %v\n%s\n%s", err, ctx.outbuf.String(), ctx.errbuf.String())
+ return fmt.Errorf("Unable to read base branch in to the index: %w\n%s\n%s", err, ctx.outbuf.String(), ctx.errbuf.String())
+ }
+ ctx.outbuf.Reset()
+ ctx.errbuf.Reset()
+
+ return nil
+}
+
+// getDiffTree returns a string containing all the files that were changed between headBranch and baseBranch
+// the filenames are escaped so as to fit the format required for .git/info/sparse-checkout
+func getDiffTree(ctx context.Context, repoPath, baseBranch, headBranch string, out io.Writer) error {
+ diffOutReader, diffOutWriter, err := os.Pipe()
+ if err != nil {
+ log.Error("Unable to create os.Pipe for %s", repoPath)
+ return err
+ }
+ defer func() {
+ _ = diffOutReader.Close()
+ _ = diffOutWriter.Close()
+ }()
+
+ scanNullTerminatedStrings := func(data []byte, atEOF bool) (advance int, token []byte, err error) {
+ if atEOF && len(data) == 0 {
+ return 0, nil, nil
+ }
+ if i := bytes.IndexByte(data, '\x00'); i >= 0 {
+ return i + 1, data[0:i], nil
+ }
+ if atEOF {
+ return len(data), data, nil
+ }
+ return 0, nil, nil
+ }
+
+ err = git.NewCommand(ctx, "diff-tree", "--no-commit-id", "--name-only", "-r", "-r", "-z", "--root").AddDynamicArguments(baseBranch, headBranch).
+ Run(&git.RunOpts{
+ Dir: repoPath,
+ Stdout: diffOutWriter,
+ PipelineFunc: func(ctx context.Context, cancel context.CancelFunc) error {
+ // Close the writer end of the pipe to begin processing
+ _ = diffOutWriter.Close()
+ defer func() {
+ // Close the reader on return to terminate the git command if necessary
+ _ = diffOutReader.Close()
+ }()
+
+ // Now scan the output from the command
+ scanner := bufio.NewScanner(diffOutReader)
+ scanner.Split(scanNullTerminatedStrings)
+ for scanner.Scan() {
+ filepath := scanner.Text()
+ // escape '*', '?', '[', spaces and '!' prefix
+ filepath = escapedSymbols.ReplaceAllString(filepath, `\$1`)
+ // no necessary to escape the first '#' symbol because the first symbol is '/'
+ fmt.Fprintf(out, "/%s\n", filepath)
+ }
+ return scanner.Err()
+ },
+ })
+ return err
+}
+
+// rebaseTrackingOnToBase checks out the tracking branch as staging and rebases it on to the base branch
+// if there is a conflict it will return a models.ErrRebaseConflicts
+func rebaseTrackingOnToBase(ctx *mergeContext, mergeStyle repo_model.MergeStyle) error {
+ // Checkout head branch
+ if err := git.NewCommand(ctx, "checkout", "-b").AddDynamicArguments(stagingBranch, trackingBranch).
+ Run(ctx.RunOpts()); err != nil {
+ return fmt.Errorf("unable to git checkout tracking as staging in temp repo for %v: %w\n%s\n%s", ctx.pr, err, ctx.outbuf.String(), ctx.errbuf.String())
+ }
+ ctx.outbuf.Reset()
+ ctx.errbuf.Reset()
+
+ // Rebase before merging
+ if err := git.NewCommand(ctx, "rebase").AddDynamicArguments(baseBranch).
+ Run(ctx.RunOpts()); err != nil {
+ // Rebase will leave a REBASE_HEAD file in .git if there is a conflict
+ if _, statErr := os.Stat(filepath.Join(ctx.tmpBasePath, ".git", "REBASE_HEAD")); statErr == nil {
+ var commitSha string
+ ok := false
+ failingCommitPaths := []string{
+ filepath.Join(ctx.tmpBasePath, ".git", "rebase-apply", "original-commit"), // Git < 2.26
+ filepath.Join(ctx.tmpBasePath, ".git", "rebase-merge", "stopped-sha"), // Git >= 2.26
+ }
+ for _, failingCommitPath := range failingCommitPaths {
+ if _, statErr := os.Stat(failingCommitPath); statErr == nil {
+ commitShaBytes, readErr := os.ReadFile(failingCommitPath)
+ if readErr != nil {
+ // Abandon this attempt to handle the error
+ return fmt.Errorf("unable to git rebase staging on to base in temp repo for %v: %w\n%s\n%s", ctx.pr, err, ctx.outbuf.String(), ctx.errbuf.String())
+ }
+ commitSha = strings.TrimSpace(string(commitShaBytes))
+ ok = true
+ break
+ }
+ }
+ if !ok {
+ log.Error("Unable to determine failing commit sha for failing rebase in temp repo for %-v. Cannot cast as models.ErrRebaseConflicts.", ctx.pr)
+ return fmt.Errorf("unable to git rebase staging on to base in temp repo for %v: %w\n%s\n%s", ctx.pr, err, ctx.outbuf.String(), ctx.errbuf.String())
+ }
+ log.Debug("Conflict when rebasing staging on to base in %-v at %s: %v\n%s\n%s", ctx.pr, commitSha, err, ctx.outbuf.String(), ctx.errbuf.String())
+ return models.ErrRebaseConflicts{
+ CommitSHA: commitSha,
+ Style: mergeStyle,
+ StdOut: ctx.outbuf.String(),
+ StdErr: ctx.errbuf.String(),
+ Err: err,
+ }
+ }
+ return fmt.Errorf("unable to git rebase staging on to base in temp repo for %v: %w\n%s\n%s", ctx.pr, err, ctx.outbuf.String(), ctx.errbuf.String())
+ }
+ ctx.outbuf.Reset()
+ ctx.errbuf.Reset()
+ return nil
+}
diff --git a/services/pull/merge_rebase.go b/services/pull/merge_rebase.go
new file mode 100644
index 000000000..d3bb86d4a
--- /dev/null
+++ b/services/pull/merge_rebase.go
@@ -0,0 +1,50 @@
+// Copyright 2023 The Gitea Authors. All rights reserved.
+// SPDX-License-Identifier: MIT
+
+package pull
+
+import (
+ "fmt"
+
+ repo_model "code.gitea.io/gitea/models/repo"
+ "code.gitea.io/gitea/modules/git"
+ "code.gitea.io/gitea/modules/log"
+)
+
+// doMergeStyleRebase rebaases the tracking branch on the base branch as the current HEAD with or with a merge commit to the original pr branch
+func doMergeStyleRebase(ctx *mergeContext, mergeStyle repo_model.MergeStyle, message string) error {
+ if err := rebaseTrackingOnToBase(ctx, mergeStyle); err != nil {
+ return err
+ }
+
+ // Checkout base branch again
+ if err := git.NewCommand(ctx, "checkout").AddDynamicArguments(baseBranch).
+ Run(ctx.RunOpts()); err != nil {
+ log.Error("git checkout base prior to merge post staging rebase %-v: %v\n%s\n%s", ctx.pr, err, ctx.outbuf.String(), ctx.errbuf.String())
+ return fmt.Errorf("git checkout base prior to merge post staging rebase %v: %w\n%s\n%s", ctx.pr, err, ctx.outbuf.String(), ctx.errbuf.String())
+ }
+ ctx.outbuf.Reset()
+ ctx.errbuf.Reset()
+
+ cmd := git.NewCommand(ctx, "merge")
+ if mergeStyle == repo_model.MergeStyleRebase {
+ cmd.AddArguments("--ff-only")
+ } else {
+ cmd.AddArguments("--no-ff", "--no-commit")
+ }
+ cmd.AddDynamicArguments(stagingBranch)
+
+ // Prepare merge with commit
+ if err := runMergeCommand(ctx, mergeStyle, cmd); err != nil {
+ log.Error("Unable to merge staging into base: %v", err)
+ return err
+ }
+ if mergeStyle == repo_model.MergeStyleRebaseMerge {
+ if err := commitAndSignNoAuthor(ctx, message); err != nil {
+ log.Error("Unable to make final commit: %v", err)
+ return err
+ }
+ }
+
+ return nil
+}
diff --git a/services/pull/merge_squash.go b/services/pull/merge_squash.go
new file mode 100644
index 000000000..f52a2301d
--- /dev/null
+++ b/services/pull/merge_squash.go
@@ -0,0 +1,85 @@
+// Copyright 2023 The Gitea Authors. All rights reserved.
+// SPDX-License-Identifier: MIT
+
+package pull
+
+import (
+ "fmt"
+
+ repo_model "code.gitea.io/gitea/models/repo"
+ user_model "code.gitea.io/gitea/models/user"
+ "code.gitea.io/gitea/modules/container"
+ "code.gitea.io/gitea/modules/git"
+ "code.gitea.io/gitea/modules/log"
+ "code.gitea.io/gitea/modules/setting"
+)
+
+// doMergeStyleSquash gets a commit author signature for squash commits
+func getAuthorSignatureSquash(ctx *mergeContext) (*git.Signature, error) {
+ if err := ctx.pr.Issue.LoadPoster(ctx); err != nil {
+ log.Error("%-v Issue[%d].LoadPoster: %v", ctx.pr, ctx.pr.Issue.ID, err)
+ return nil, err
+ }
+
+ // Try to get an signature from the same user in one of the commits, as the
+ // poster email might be private or commits might have a different signature
+ // than the primary email address of the poster.
+ gitRepo, closer, err := git.RepositoryFromContextOrOpen(ctx, ctx.tmpBasePath)
+ if err != nil {
+ log.Error("%-v Unable to open base repository: %v", ctx.pr, err)
+ return nil, err
+ }
+ defer closer.Close()
+
+ commits, err := gitRepo.CommitsBetweenIDs(trackingBranch, "HEAD")
+ if err != nil {
+ log.Error("%-v Unable to get commits between: %s %s: %v", ctx.pr, "HEAD", trackingBranch, err)
+ return nil, err
+ }
+
+ uniqueEmails := make(container.Set[string])
+ for _, commit := range commits {
+ if commit.Author != nil && uniqueEmails.Add(commit.Author.Email) {
+ commitUser, _ := user_model.GetUserByEmail(ctx, commit.Author.Email)
+ if commitUser != nil && commitUser.ID == ctx.pr.Issue.Poster.ID {
+ return commit.Author, nil
+ }
+ }
+ }
+
+ return ctx.pr.Issue.Poster.NewGitSig(), nil
+}
+
+// doMergeStyleSquash squashes the tracking branch on the current HEAD (=base)
+func doMergeStyleSquash(ctx *mergeContext, message string) error {
+ sig, err := getAuthorSignatureSquash(ctx)
+ if err != nil {
+ return fmt.Errorf("getAuthorSignatureSquash: %w", err)
+ }
+
+ cmdMerge := git.NewCommand(ctx, "merge", "--squash").AddDynamicArguments(trackingBranch)
+ if err := runMergeCommand(ctx, repo_model.MergeStyleSquash, cmdMerge); err != nil {
+ log.Error("%-v Unable to merge --squash tracking into base: %v", ctx.pr, err)
+ return err
+ }
+
+ if setting.Repository.PullRequest.AddCoCommitterTrailers && ctx.committer.String() != sig.String() {
+ // add trailer
+ message += fmt.Sprintf("\nCo-authored-by: %s\nCo-committed-by: %s\n", sig.String(), sig.String())
+ }
+ cmdCommit := git.NewCommand(ctx, "commit").
+ AddOptionFormat("--author='%s <%s>'", sig.Name, sig.Email).
+ AddOptionFormat("--message=%s", message)
+ if ctx.signKeyID == "" {
+ cmdCommit.AddArguments("--no-gpg-sign")
+ } else {
+ cmdCommit.AddOptionFormat("-S%s", ctx.signKeyID)
+ }
+ if err := cmdCommit.Run(ctx.RunOpts()); err != nil {
+ log.Error("git commit %-v: %v\n%s\n%s", ctx.pr, err, ctx.outbuf.String(), ctx.errbuf.String())
+ return fmt.Errorf("git commit [%s:%s -> %s:%s]: %w\n%s\n%s", ctx.pr.HeadRepo.FullName(), ctx.pr.HeadBranch, ctx.pr.BaseRepo.FullName(), ctx.pr.BaseBranch, err, ctx.outbuf.String(), ctx.errbuf.String())
+ }
+ ctx.outbuf.Reset()
+ ctx.errbuf.Reset()
+ return nil
+}
diff --git a/services/pull/patch.go b/services/pull/patch.go
index c2ccc75bd..927735572 100644
--- a/services/pull/patch.go
+++ b/services/pull/patch.go
@@ -22,7 +22,6 @@ import (
"code.gitea.io/gitea/modules/graceful"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/process"
- repo_module "code.gitea.io/gitea/modules/repository"
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/util"
@@ -64,25 +63,21 @@ func TestPatch(pr *issues_model.PullRequest) error {
defer finished()
// Clone base repo.
- tmpBasePath, err := createTemporaryRepo(ctx, pr)
+ prCtx, cancel, err := createTemporaryRepoForPR(ctx, pr)
if err != nil {
- log.Error("CreateTemporaryPath: %v", err)
+ log.Error("createTemporaryRepoForPR %-v: %v", pr, err)
return err
}
- defer func() {
- if err := repo_module.RemoveTemporaryPath(tmpBasePath); err != nil {
- log.Error("Merge: RemoveTemporaryPath: %s", err)
- }
- }()
+ defer cancel()
- gitRepo, err := git.OpenRepository(ctx, tmpBasePath)
+ gitRepo, err := git.OpenRepository(ctx, prCtx.tmpBasePath)
if err != nil {
return fmt.Errorf("OpenRepository: %w", err)
}
defer gitRepo.Close()
// 1. update merge base
- pr.MergeBase, _, err = git.NewCommand(ctx, "merge-base", "--", "base", "tracking").RunStdString(&git.RunOpts{Dir: tmpBasePath})
+ pr.MergeBase, _, err = git.NewCommand(ctx, "merge-base", "--", "base", "tracking").RunStdString(&git.RunOpts{Dir: prCtx.tmpBasePath})
if err != nil {
var err2 error
pr.MergeBase, err2 = gitRepo.GetRefCommitID(git.BranchPrefix + "base")
@@ -101,7 +96,7 @@ func TestPatch(pr *issues_model.PullRequest) error {
}
// 2. Check for conflicts
- if conflicts, err := checkConflicts(ctx, pr, gitRepo, tmpBasePath); err != nil || conflicts || pr.Status == issues_model.PullRequestStatusEmpty {
+ if conflicts, err := checkConflicts(ctx, pr, gitRepo, prCtx.tmpBasePath); err != nil || conflicts || pr.Status == issues_model.PullRequestStatusEmpty {
return err
}
diff --git a/services/pull/pull.go b/services/pull/pull.go
index 0d260c93b..e40e59a2c 100644
--- a/services/pull/pull.go
+++ b/services/pull/pull.go
@@ -257,7 +257,7 @@ func AddTestPullRequestTask(doer *user_model.User, repoID int64, branch string,
// If you don't let it run all the way then you will lose data
// TODO: graceful: AddTestPullRequestTask needs to become a queue!
- prs, err := issues_model.GetUnmergedPullRequestsByHeadInfo(repoID, branch)
+ prs, err := issues_model.GetUnmergedPullRequestsByHeadInfo(repoID, branch, true)
if err != nil {
log.Error("Find pull requests [head_repo_id: %d, head_branch: %s]: %v", repoID, branch, err)
return
@@ -349,18 +349,14 @@ func AddTestPullRequestTask(doer *user_model.User, repoID int64, branch string,
// checkIfPRContentChanged checks if diff to target branch has changed by push
// A commit can be considered to leave the PR untouched if the patch/diff with its merge base is unchanged
func checkIfPRContentChanged(ctx context.Context, pr *issues_model.PullRequest, oldCommitID, newCommitID string) (hasChanged bool, err error) {
- tmpBasePath, err := createTemporaryRepo(ctx, pr)
+ prCtx, cancel, err := createTemporaryRepoForPR(ctx, pr)
if err != nil {
- log.Error("CreateTemporaryRepo: %v", err)
+ log.Error("CreateTemporaryRepoForPR %-v: %v", pr, err)
return false, err
}
- defer func() {
- if err := repo_module.RemoveTemporaryPath(tmpBasePath); err != nil {
- log.Error("checkIfPRContentChanged: RemoveTemporaryPath: %s", err)
- }
- }()
+ defer cancel()
- tmpRepo, err := git.OpenRepository(ctx, tmpBasePath)
+ tmpRepo, err := git.OpenRepository(ctx, prCtx.tmpBasePath)
if err != nil {
return false, fmt.Errorf("OpenRepository: %w", err)
}
@@ -379,7 +375,7 @@ func checkIfPRContentChanged(ctx context.Context, pr *issues_model.PullRequest,
}
if err := cmd.Run(&git.RunOpts{
- Dir: tmpBasePath,
+ Dir: prCtx.tmpBasePath,
Stdout: stdoutWriter,
PipelineFunc: func(ctx context.Context, cancel context.CancelFunc) error {
_ = stdoutWriter.Close()
@@ -500,7 +496,7 @@ func (errs errlist) Error() string {
// CloseBranchPulls close all the pull requests who's head branch is the branch
func CloseBranchPulls(doer *user_model.User, repoID int64, branch string) error {
- prs, err := issues_model.GetUnmergedPullRequestsByHeadInfo(repoID, branch)
+ prs, err := issues_model.GetUnmergedPullRequestsByHeadInfo(repoID, branch, false)
if err != nil {
return err
}
@@ -536,7 +532,7 @@ func CloseRepoBranchesPulls(ctx context.Context, doer *user_model.User, repo *re
var errs errlist
for _, branch := range branches {
- prs, err := issues_model.GetUnmergedPullRequestsByHeadInfo(repo.ID, branch.Name)
+ prs, err := issues_model.GetUnmergedPullRequestsByHeadInfo(repo.ID, branch.Name, false)
if err != nil {
return err
}
@@ -673,7 +669,12 @@ func GetSquashMergeCommitMessages(ctx context.Context, pr *issues_model.PullRequ
authorString := commit.Author.String()
if uniqueAuthors.Add(authorString) && authorString != posterSig {
- authors = append(authors, authorString)
+ // Compare use account as well to avoid adding the same author multiple times
+ // times when email addresses are private or multiple emails are used.
+ commitUser, _ := user_model.GetUserByEmail(ctx, commit.Author.Email)
+ if commitUser == nil || commitUser.ID != pr.Issue.Poster.ID {
+ authors = append(authors, authorString)
+ }
}
}
@@ -694,7 +695,10 @@ func GetSquashMergeCommitMessages(ctx context.Context, pr *issues_model.PullRequ
for _, commit := range commits {
authorString := commit.Author.String()
if uniqueAuthors.Add(authorString) && authorString != posterSig {
- authors = append(authors, authorString)
+ commitUser, _ := user_model.GetUserByEmail(ctx, commit.Author.Email)
+ if commitUser == nil || commitUser.ID != pr.Issue.Poster.ID {
+ authors = append(authors, authorString)
+ }
}
}
skip += limit
diff --git a/services/pull/review.go b/services/pull/review.go
index ca386ca6b..ba93b5e2f 100644
--- a/services/pull/review.go
+++ b/services/pull/review.go
@@ -71,7 +71,7 @@ func InvalidateCodeComments(ctx context.Context, prs issues_model.PullRequestLis
}
// CreateCodeComment creates a comment on the code line
-func CreateCodeComment(ctx context.Context, doer *user_model.User, gitRepo *git.Repository, issue *issues_model.Issue, line int64, content, treePath string, isReview bool, replyReviewID int64, latestCommitID string) (*issues_model.Comment, error) {
+func CreateCodeComment(ctx context.Context, doer *user_model.User, gitRepo *git.Repository, issue *issues_model.Issue, line int64, content, treePath string, pendingReview bool, replyReviewID int64, latestCommitID string) (*issues_model.Comment, error) {
var (
existsReview bool
err error
@@ -82,7 +82,7 @@ func CreateCodeComment(ctx context.Context, doer *user_model.User, gitRepo *git.
// - Comments that are part of a review
// - Comments that reply to an existing review
- if !isReview && replyReviewID != 0 {
+ if !pendingReview && replyReviewID != 0 {
// It's not part of a review; maybe a reply to a review comment or a single comment.
// Check if there are reviews for that line already; if there are, this is a reply
if existsReview, err = issues_model.ReviewExists(issue, treePath, line); err != nil {
@@ -91,7 +91,7 @@ func CreateCodeComment(ctx context.Context, doer *user_model.User, gitRepo *git.
}
// Comments that are replies don't require a review header to show up in the issue view
- if !isReview && existsReview {
+ if !pendingReview && existsReview {
if err = issue.LoadRepo(ctx); err != nil {
return nil, err
}
@@ -149,7 +149,7 @@ func CreateCodeComment(ctx context.Context, doer *user_model.User, gitRepo *git.
return nil, err
}
- if !isReview && !existsReview {
+ if !pendingReview && !existsReview {
// Submit the review we've just created so the comment shows up in the issue view
if _, _, err = SubmitReview(ctx, doer, gitRepo, issue, issues_model.ReviewTypeComment, "", latestCommitID, nil); err != nil {
return nil, err
diff --git a/services/pull/temp_repo.go b/services/pull/temp_repo.go
index e0d6b4a15..146470780 100644
--- a/services/pull/temp_repo.go
+++ b/services/pull/temp_repo.go
@@ -19,147 +19,153 @@ import (
repo_module "code.gitea.io/gitea/modules/repository"
)
-// createTemporaryRepo creates a temporary repo with "base" for pr.BaseBranch and "tracking" for pr.HeadBranch
+// Temporary repos created here use standard branch names to help simplify
+// merging code
+const (
+ baseBranch = "base" // equivalent to pr.BaseBranch
+ trackingBranch = "tracking" // equivalent to pr.HeadBranch
+ stagingBranch = "staging" // this is used for a working branch
+)
+
+type prContext struct {
+ context.Context
+ tmpBasePath string
+ pr *issues_model.PullRequest
+ outbuf *strings.Builder // we keep these around to help reduce needless buffer recreation,
+ errbuf *strings.Builder // any use should be preceded by a Reset and preferably after use
+}
+
+func (ctx *prContext) RunOpts() *git.RunOpts {
+ ctx.outbuf.Reset()
+ ctx.errbuf.Reset()
+ return &git.RunOpts{
+ Dir: ctx.tmpBasePath,
+ Stdout: ctx.outbuf,
+ Stderr: ctx.errbuf,
+ }
+}
+
+// createTemporaryRepoForPR creates a temporary repo with "base" for pr.BaseBranch and "tracking" for pr.HeadBranch
// it also create a second base branch called "original_base"
-func createTemporaryRepo(ctx context.Context, pr *issues_model.PullRequest) (string, error) {
+func createTemporaryRepoForPR(ctx context.Context, pr *issues_model.PullRequest) (prCtx *prContext, cancel context.CancelFunc, err error) {
if err := pr.LoadHeadRepo(ctx); err != nil {
- log.Error("LoadHeadRepo: %v", err)
- return "", fmt.Errorf("LoadHeadRepo: %w", err)
+ log.Error("%-v LoadHeadRepo: %v", pr, err)
+ return nil, nil, fmt.Errorf("%v LoadHeadRepo: %w", pr, err)
} else if pr.HeadRepo == nil {
- log.Error("Pr %d HeadRepo %d does not exist", pr.ID, pr.HeadRepoID)
- return "", &repo_model.ErrRepoNotExist{
+ log.Error("%-v HeadRepo %d does not exist", pr, pr.HeadRepoID)
+ return nil, nil, &repo_model.ErrRepoNotExist{
ID: pr.HeadRepoID,
}
} else if err := pr.LoadBaseRepo(ctx); err != nil {
- log.Error("LoadBaseRepo: %v", err)
- return "", fmt.Errorf("LoadBaseRepo: %w", err)
+ log.Error("%-v LoadBaseRepo: %v", pr, err)
+ return nil, nil, fmt.Errorf("%v LoadBaseRepo: %w", pr, err)
} else if pr.BaseRepo == nil {
- log.Error("Pr %d BaseRepo %d does not exist", pr.ID, pr.BaseRepoID)
- return "", &repo_model.ErrRepoNotExist{
+ log.Error("%-v BaseRepo %d does not exist", pr, pr.BaseRepoID)
+ return nil, nil, &repo_model.ErrRepoNotExist{
ID: pr.BaseRepoID,
}
} else if err := pr.HeadRepo.LoadOwner(ctx); err != nil {
- log.Error("HeadRepo.LoadOwner: %v", err)
- return "", fmt.Errorf("HeadRepo.LoadOwner: %w", err)
+ log.Error("%-v HeadRepo.LoadOwner: %v", pr, err)
+ return nil, nil, fmt.Errorf("%v HeadRepo.LoadOwner: %w", pr, err)
} else if err := pr.BaseRepo.LoadOwner(ctx); err != nil {
- log.Error("BaseRepo.LoadOwner: %v", err)
- return "", fmt.Errorf("BaseRepo.LoadOwner: %w", err)
+ log.Error("%-v BaseRepo.LoadOwner: %v", pr, err)
+ return nil, nil, fmt.Errorf("%v BaseRepo.LoadOwner: %w", pr, err)
}
// Clone base repo.
tmpBasePath, err := repo_module.CreateTemporaryPath("pull")
if err != nil {
- log.Error("CreateTemporaryPath: %v", err)
- return "", err
+ log.Error("CreateTemporaryPath[%-v]: %v", pr, err)
+ return nil, nil, err
+ }
+ prCtx = &prContext{
+ Context: ctx,
+ tmpBasePath: tmpBasePath,
+ pr: pr,
+ outbuf: &strings.Builder{},
+ errbuf: &strings.Builder{},
+ }
+ cancel = func() {
+ if err := repo_module.RemoveTemporaryPath(tmpBasePath); err != nil {
+ log.Error("Error whilst removing removing temporary repo for %-v: %v", pr, err)
+ }
}
baseRepoPath := pr.BaseRepo.RepoPath()
headRepoPath := pr.HeadRepo.RepoPath()
if err := git.InitRepository(ctx, tmpBasePath, false); err != nil {
- log.Error("git init tmpBasePath: %v", err)
- if err := repo_module.RemoveTemporaryPath(tmpBasePath); err != nil {
- log.Error("CreateTempRepo: RemoveTemporaryPath: %s", err)
- }
- return "", err
+ log.Error("Unable to init tmpBasePath for %-v: %v", pr, err)
+ cancel()
+ return nil, nil, err
}
remoteRepoName := "head_repo"
baseBranch := "base"
- // Add head repo remote.
- addCacheRepo := func(staging, cache string) error {
- p := filepath.Join(staging, ".git", "objects", "info", "alternates")
+ fetchArgs := git.TrustedCmdArgs{"--no-tags"}
+ if git.CheckGitVersionAtLeast("2.25.0") == nil {
+ // Writing the commit graph can be slow and is not needed here
+ fetchArgs = append(fetchArgs, "--no-write-commit-graph")
+ }
+
+ // addCacheRepo adds git alternatives for the cacheRepoPath in the repoPath
+ addCacheRepo := func(repoPath, cacheRepoPath string) error {
+ p := filepath.Join(repoPath, ".git", "objects", "info", "alternates")
f, err := os.OpenFile(p, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0o600)
if err != nil {
- log.Error("Could not create .git/objects/info/alternates file in %s: %v", staging, err)
+ log.Error("Could not create .git/objects/info/alternates file in %s: %v", repoPath, err)
return err
}
defer f.Close()
- data := filepath.Join(cache, "objects")
+ data := filepath.Join(cacheRepoPath, "objects")
if _, err := fmt.Fprintln(f, data); err != nil {
- log.Error("Could not write to .git/objects/info/alternates file in %s: %v", staging, err)
+ log.Error("Could not write to .git/objects/info/alternates file in %s: %v", repoPath, err)
return err
}
return nil
}
+ // Add head repo remote.
if err := addCacheRepo(tmpBasePath, baseRepoPath); err != nil {
- log.Error("Unable to add base repository to temporary repo [%s -> %s]: %v", pr.BaseRepo.FullName(), tmpBasePath, err)
- if err := repo_module.RemoveTemporaryPath(tmpBasePath); err != nil {
- log.Error("CreateTempRepo: RemoveTemporaryPath: %s", err)
- }
- return "", fmt.Errorf("Unable to add base repository to temporary repo [%s -> tmpBasePath]: %w", pr.BaseRepo.FullName(), err)
+ log.Error("%-v Unable to add base repository to temporary repo [%s -> %s]: %v", pr, pr.BaseRepo.FullName(), tmpBasePath, err)
+ cancel()
+ return nil, nil, fmt.Errorf("Unable to add base repository to temporary repo [%s -> tmpBasePath]: %w", pr.BaseRepo.FullName(), err)
}
- var outbuf, errbuf strings.Builder
if err := git.NewCommand(ctx, "remote", "add", "-t").AddDynamicArguments(pr.BaseBranch).AddArguments("-m").AddDynamicArguments(pr.BaseBranch).AddDynamicArguments("origin", baseRepoPath).
- Run(&git.RunOpts{
- Dir: tmpBasePath,
- Stdout: &outbuf,
- Stderr: &errbuf,
- }); err != nil {
- log.Error("Unable to add base repository as origin [%s -> %s]: %v\n%s\n%s", pr.BaseRepo.FullName(), tmpBasePath, err, outbuf.String(), errbuf.String())
- if err := repo_module.RemoveTemporaryPath(tmpBasePath); err != nil {
- log.Error("CreateTempRepo: RemoveTemporaryPath: %s", err)
- }
- return "", fmt.Errorf("Unable to add base repository as origin [%s -> tmpBasePath]: %w\n%s\n%s", pr.BaseRepo.FullName(), err, outbuf.String(), errbuf.String())
- }
- outbuf.Reset()
- errbuf.Reset()
-
- if err := git.NewCommand(ctx, "fetch", "origin", "--no-tags").AddDashesAndList(pr.BaseBranch+":"+baseBranch, pr.BaseBranch+":original_"+baseBranch).
- Run(&git.RunOpts{
- Dir: tmpBasePath,
- Stdout: &outbuf,
- Stderr: &errbuf,
- }); err != nil {
- log.Error("Unable to fetch origin base branch [%s:%s -> base, original_base in %s]: %v:\n%s\n%s", pr.BaseRepo.FullName(), pr.BaseBranch, tmpBasePath, err, outbuf.String(), errbuf.String())
- if err := repo_module.RemoveTemporaryPath(tmpBasePath); err != nil {
- log.Error("CreateTempRepo: RemoveTemporaryPath: %s", err)
- }
- return "", fmt.Errorf("Unable to fetch origin base branch [%s:%s -> base, original_base in tmpBasePath]: %w\n%s\n%s", pr.BaseRepo.FullName(), pr.BaseBranch, err, outbuf.String(), errbuf.String())
+ Run(prCtx.RunOpts()); err != nil {
+ log.Error("%-v Unable to add base repository as origin [%s -> %s]: %v\n%s\n%s", pr, pr.BaseRepo.FullName(), tmpBasePath, err, prCtx.outbuf.String(), prCtx.errbuf.String())
+ cancel()
+ return nil, nil, fmt.Errorf("Unable to add base repository as origin [%s -> tmpBasePath]: %w\n%s\n%s", pr.BaseRepo.FullName(), err, prCtx.outbuf.String(), prCtx.errbuf.String())
+ }
+
+ if err := git.NewCommand(ctx, "fetch", "origin").AddArguments(fetchArgs...).AddDashesAndList(pr.BaseBranch+":"+baseBranch, pr.BaseBranch+":original_"+baseBranch).
+ Run(prCtx.RunOpts()); err != nil {
+ log.Error("%-v Unable to fetch origin base branch [%s:%s -> base, original_base in %s]: %v:\n%s\n%s", pr, pr.BaseRepo.FullName(), pr.BaseBranch, tmpBasePath, err, prCtx.outbuf.String(), prCtx.errbuf.String())
+ cancel()
+ return nil, nil, fmt.Errorf("Unable to fetch origin base branch [%s:%s -> base, original_base in tmpBasePath]: %w\n%s\n%s", pr.BaseRepo.FullName(), pr.BaseBranch, err, prCtx.outbuf.String(), prCtx.errbuf.String())
}
- outbuf.Reset()
- errbuf.Reset()
if err := git.NewCommand(ctx, "symbolic-ref").AddDynamicArguments("HEAD", git.BranchPrefix+baseBranch).
- Run(&git.RunOpts{
- Dir: tmpBasePath,
- Stdout: &outbuf,
- Stderr: &errbuf,
- }); err != nil {
- log.Error("Unable to set HEAD as base branch [%s]: %v\n%s\n%s", tmpBasePath, err, outbuf.String(), errbuf.String())
- if err := repo_module.RemoveTemporaryPath(tmpBasePath); err != nil {
- log.Error("CreateTempRepo: RemoveTemporaryPath: %s", err)
- }
- return "", fmt.Errorf("Unable to set HEAD as base branch [tmpBasePath]: %w\n%s\n%s", err, outbuf.String(), errbuf.String())
+ Run(prCtx.RunOpts()); err != nil {
+ log.Error("%-v Unable to set HEAD as base branch in [%s]: %v\n%s\n%s", pr, tmpBasePath, err, prCtx.outbuf.String(), prCtx.errbuf.String())
+ cancel()
+ return nil, nil, fmt.Errorf("Unable to set HEAD as base branch in tmpBasePath: %w\n%s\n%s", err, prCtx.outbuf.String(), prCtx.errbuf.String())
}
- outbuf.Reset()
- errbuf.Reset()
if err := addCacheRepo(tmpBasePath, headRepoPath); err != nil {
- log.Error("Unable to add head repository to temporary repo [%s -> %s]: %v", pr.HeadRepo.FullName(), tmpBasePath, err)
- if err := repo_module.RemoveTemporaryPath(tmpBasePath); err != nil {
- log.Error("CreateTempRepo: RemoveTemporaryPath: %s", err)
- }
- return "", fmt.Errorf("Unable to head base repository to temporary repo [%s -> tmpBasePath]: %w", pr.HeadRepo.FullName(), err)
+ log.Error("%-v Unable to add head repository to temporary repo [%s -> %s]: %v", pr, pr.HeadRepo.FullName(), tmpBasePath, err)
+ cancel()
+ return nil, nil, fmt.Errorf("Unable to add head base repository to temporary repo [%s -> tmpBasePath]: %w", pr.HeadRepo.FullName(), err)
}
if err := git.NewCommand(ctx, "remote", "add").AddDynamicArguments(remoteRepoName, headRepoPath).
- Run(&git.RunOpts{
- Dir: tmpBasePath,
- Stdout: &outbuf,
- Stderr: &errbuf,
- }); err != nil {
- log.Error("Unable to add head repository as head_repo [%s -> %s]: %v\n%s\n%s", pr.HeadRepo.FullName(), tmpBasePath, err, outbuf.String(), errbuf.String())
- if err := repo_module.RemoveTemporaryPath(tmpBasePath); err != nil {
- log.Error("CreateTempRepo: RemoveTemporaryPath: %s", err)
- }
- return "", fmt.Errorf("Unable to add head repository as head_repo [%s -> tmpBasePath]: %w\n%s\n%s", pr.HeadRepo.FullName(), err, outbuf.String(), errbuf.String())
+ Run(prCtx.RunOpts()); err != nil {
+ log.Error("%-v Unable to add head repository as head_repo [%s -> %s]: %v\n%s\n%s", pr, pr.HeadRepo.FullName(), tmpBasePath, err, prCtx.outbuf.String(), prCtx.errbuf.String())
+ cancel()
+ return nil, nil, fmt.Errorf("Unable to add head repository as head_repo [%s -> tmpBasePath]: %w\n%s\n%s", pr.HeadRepo.FullName(), err, prCtx.outbuf.String(), prCtx.errbuf.String())
}
- outbuf.Reset()
- errbuf.Reset()
trackingBranch := "tracking"
// Fetch head branch
@@ -171,25 +177,19 @@ func createTemporaryRepo(ctx context.Context, pr *issues_model.PullRequest) (str
} else {
headBranch = pr.GetGitRefName()
}
- if err := git.NewCommand(ctx, "fetch", "--no-tags").AddDynamicArguments(remoteRepoName, headBranch+":"+trackingBranch).
- Run(&git.RunOpts{
- Dir: tmpBasePath,
- Stdout: &outbuf,
- Stderr: &errbuf,
- }); err != nil {
- if err := repo_module.RemoveTemporaryPath(tmpBasePath); err != nil {
- log.Error("CreateTempRepo: RemoveTemporaryPath: %s", err)
- }
+ if err := git.NewCommand(ctx, "fetch").AddArguments(fetchArgs...).AddDynamicArguments(remoteRepoName, headBranch+":"+trackingBranch).
+ Run(prCtx.RunOpts()); err != nil {
+ cancel()
if !git.IsBranchExist(ctx, pr.HeadRepo.RepoPath(), pr.HeadBranch) {
- return "", models.ErrBranchDoesNotExist{
+ return nil, nil, models.ErrBranchDoesNotExist{
BranchName: pr.HeadBranch,
}
}
- log.Error("Unable to fetch head_repo head branch [%s:%s -> tracking in %s]: %v:\n%s\n%s", pr.HeadRepo.FullName(), pr.HeadBranch, tmpBasePath, err, outbuf.String(), errbuf.String())
- return "", fmt.Errorf("Unable to fetch head_repo head branch [%s:%s -> tracking in tmpBasePath]: %w\n%s\n%s", pr.HeadRepo.FullName(), headBranch, err, outbuf.String(), errbuf.String())
+ log.Error("%-v Unable to fetch head_repo head branch [%s:%s -> tracking in %s]: %v:\n%s\n%s", pr, pr.HeadRepo.FullName(), pr.HeadBranch, tmpBasePath, err, prCtx.outbuf.String(), prCtx.errbuf.String())
+ return nil, nil, fmt.Errorf("Unable to fetch head_repo head branch [%s:%s -> tracking in tmpBasePath]: %w\n%s\n%s", pr.HeadRepo.FullName(), headBranch, err, prCtx.outbuf.String(), prCtx.errbuf.String())
}
- outbuf.Reset()
- errbuf.Reset()
+ prCtx.outbuf.Reset()
+ prCtx.errbuf.Reset()
- return tmpBasePath, nil
+ return prCtx, cancel, nil
}
diff --git a/services/pull/update.go b/services/pull/update.go
index b9525cf0c..b977dbdba 100644
--- a/services/pull/update.go
+++ b/services/pull/update.go
@@ -16,61 +16,67 @@ import (
user_model "code.gitea.io/gitea/models/user"
"code.gitea.io/gitea/modules/git"
"code.gitea.io/gitea/modules/log"
- repo_module "code.gitea.io/gitea/modules/repository"
)
// Update updates pull request with base branch.
-func Update(ctx context.Context, pull *issues_model.PullRequest, doer *user_model.User, message string, rebase bool) error {
- var (
- pr *issues_model.PullRequest
- style repo_model.MergeStyle
- )
+func Update(ctx context.Context, pr *issues_model.PullRequest, doer *user_model.User, message string, rebase bool) error {
+ if pr.Flow == issues_model.PullRequestFlowAGit {
+ // TODO: update of agit flow pull request's head branch is unsupported
+ return fmt.Errorf("update of agit flow pull request's head branch is unsupported")
+ }
- pullWorkingPool.CheckIn(fmt.Sprint(pull.ID))
- defer pullWorkingPool.CheckOut(fmt.Sprint(pull.ID))
+ pullWorkingPool.CheckIn(fmt.Sprint(pr.ID))
+ defer pullWorkingPool.CheckOut(fmt.Sprint(pr.ID))
- if rebase {
- pr = pull
- style = repo_model.MergeStyleRebaseUpdate
- } else {
- // use merge functions but switch repo's and branch's
- pr = &issues_model.PullRequest{
- HeadRepoID: pull.BaseRepoID,
- BaseRepoID: pull.HeadRepoID,
- HeadBranch: pull.BaseBranch,
- BaseBranch: pull.HeadBranch,
- }
- style = repo_model.MergeStyleMerge
+ diffCount, err := GetDiverging(ctx, pr)
+ if err != nil {
+ return err
+ } else if diffCount.Behind == 0 {
+ return fmt.Errorf("HeadBranch of PR %d is up to date", pr.Index)
}
- if pull.Flow == issues_model.PullRequestFlowAGit {
- // TODO: Not support update agit flow pull request's head branch
- return fmt.Errorf("Not support update agit flow pull request's head branch")
+ if rebase {
+ defer func() {
+ go AddTestPullRequestTask(doer, pr.BaseRepo.ID, pr.BaseBranch, false, "", "")
+ }()
+
+ return updateHeadByRebaseOnToBase(ctx, pr, doer, message)
}
+ if err := pr.LoadBaseRepo(ctx); err != nil {
+ log.Error("unable to load BaseRepo for %-v during update-by-merge: %v", pr, err)
+ return fmt.Errorf("unable to load BaseRepo for PR[%d] during update-by-merge: %w", pr.ID, err)
+ }
if err := pr.LoadHeadRepo(ctx); err != nil {
- log.Error("LoadHeadRepo: %v", err)
- return fmt.Errorf("LoadHeadRepo: %w", err)
- } else if err = pr.LoadBaseRepo(ctx); err != nil {
- log.Error("LoadBaseRepo: %v", err)
- return fmt.Errorf("LoadBaseRepo: %w", err)
+ log.Error("unable to load HeadRepo for PR %-v during update-by-merge: %v", pr, err)
+ return fmt.Errorf("unable to load HeadRepo for PR[%d] during update-by-merge: %w", pr.ID, err)
+ }
+ if pr.HeadRepo == nil {
+ // LoadHeadRepo will swallow ErrRepoNotExist so if pr.HeadRepo is still nil recreate the error
+ err := repo_model.ErrRepoNotExist{
+ ID: pr.HeadRepoID,
+ }
+ log.Error("unable to load HeadRepo for PR %-v during update-by-merge: %v", pr, err)
+ return fmt.Errorf("unable to load HeadRepo for PR[%d] during update-by-merge: %w", pr.ID, err)
}
- diffCount, err := GetDiverging(ctx, pull)
- if err != nil {
- return err
- } else if diffCount.Behind == 0 {
- return fmt.Errorf("HeadBranch of PR %d is up to date", pull.Index)
+ // use merge functions but switch repos and branches
+ reversePR := &issues_model.PullRequest{
+ ID: pr.ID,
+
+ HeadRepoID: pr.BaseRepoID,
+ HeadRepo: pr.BaseRepo,
+ HeadBranch: pr.BaseBranch,
+
+ BaseRepoID: pr.HeadRepoID,
+ BaseRepo: pr.HeadRepo,
+ BaseBranch: pr.HeadBranch,
}
- _, err = rawMerge(ctx, pr, doer, style, "", message)
+ _, err = doMergeAndPush(ctx, reversePR, doer, repo_model.MergeStyleMerge, "", message)
defer func() {
- if rebase {
- go AddTestPullRequestTask(doer, pr.BaseRepo.ID, pr.BaseBranch, false, "", "")
- return
- }
- go AddTestPullRequestTask(doer, pr.HeadRepo.ID, pr.HeadBranch, false, "", "")
+ go AddTestPullRequestTask(doer, reversePR.HeadRepo.ID, reversePR.HeadBranch, false, "", "")
}()
return err
@@ -159,27 +165,16 @@ func IsUserAllowedToUpdate(ctx context.Context, pull *issues_model.PullRequest,
// GetDiverging determines how many commits a PR is ahead or behind the PR base branch
func GetDiverging(ctx context.Context, pr *issues_model.PullRequest) (*git.DivergeObject, error) {
- log.Trace("GetDiverging[%d]: compare commits", pr.ID)
- if err := pr.LoadBaseRepo(ctx); err != nil {
- return nil, err
- }
- if err := pr.LoadHeadRepo(ctx); err != nil {
- return nil, err
- }
-
- tmpRepo, err := createTemporaryRepo(ctx, pr)
+ log.Trace("GetDiverging[%-v]: compare commits", pr)
+ prCtx, cancel, err := createTemporaryRepoForPR(ctx, pr)
if err != nil {
if !models.IsErrBranchDoesNotExist(err) {
- log.Error("CreateTemporaryRepo: %v", err)
+ log.Error("CreateTemporaryRepoForPR %-v: %v", pr, err)
}
return nil, err
}
- defer func() {
- if err := repo_module.RemoveTemporaryPath(tmpRepo); err != nil {
- log.Error("Merge: RemoveTemporaryPath: %s", err)
- }
- }()
+ defer cancel()
- diff, err := git.GetDivergingCommits(ctx, tmpRepo, "base", "tracking")
+ diff, err := git.GetDivergingCommits(ctx, prCtx.tmpBasePath, baseBranch, trackingBranch)
return &diff, err
}
diff --git a/services/pull/update_rebase.go b/services/pull/update_rebase.go
new file mode 100644
index 000000000..8e7bfa0ff
--- /dev/null
+++ b/services/pull/update_rebase.go
@@ -0,0 +1,107 @@
+// Copyright 2023 The Gitea Authors. All rights reserved.
+// SPDX-License-Identifier: MIT
+
+package pull
+
+import (
+ "context"
+ "fmt"
+ "strings"
+
+ issues_model "code.gitea.io/gitea/models/issues"
+ repo_model "code.gitea.io/gitea/models/repo"
+ user_model "code.gitea.io/gitea/models/user"
+ "code.gitea.io/gitea/modules/git"
+ "code.gitea.io/gitea/modules/log"
+ repo_module "code.gitea.io/gitea/modules/repository"
+ "code.gitea.io/gitea/modules/setting"
+)
+
+// updateHeadByRebaseOnToBase handles updating a PR's head branch by rebasing it on the PR current base branch
+func updateHeadByRebaseOnToBase(ctx context.Context, pr *issues_model.PullRequest, doer *user_model.User, message string) error {
+ // "Clone" base repo and add the cache headers for the head repo and branch
+ mergeCtx, cancel, err := createTemporaryRepoForMerge(ctx, pr, doer, "")
+ if err != nil {
+ return err
+ }
+ defer cancel()
+
+ // Determine the old merge-base before the rebase - we use this for LFS push later on
+ oldMergeBase, _, _ := git.NewCommand(ctx, "merge-base").AddDashesAndList(baseBranch, trackingBranch).RunStdString(&git.RunOpts{Dir: mergeCtx.tmpBasePath})
+ oldMergeBase = strings.TrimSpace(oldMergeBase)
+
+ // Rebase the tracking branch on to the base as the staging branch
+ if err := rebaseTrackingOnToBase(mergeCtx, repo_model.MergeStyleRebaseUpdate); err != nil {
+ return err
+ }
+
+ if setting.LFS.StartServer {
+ // Now we need to ensure that the head repository contains any LFS objects between the new base and the old mergebase
+ // It's questionable about where this should go - either after or before the push
+ // I think in the interests of data safety - failures to push to the lfs should prevent
+ // the push as you can always re-rebase.
+ if err := LFSPush(ctx, mergeCtx.tmpBasePath, baseBranch, oldMergeBase, &issues_model.PullRequest{
+ HeadRepoID: pr.BaseRepoID,
+ BaseRepoID: pr.HeadRepoID,
+ }); err != nil {
+ log.Error("Unable to push lfs objects between %s and %s up to head branch in %-v: %v", baseBranch, oldMergeBase, pr, err)
+ return err
+ }
+ }
+
+ // Now determine who the pushing author should be
+ var headUser *user_model.User
+ if err := pr.HeadRepo.LoadOwner(ctx); err != nil {
+ if !user_model.IsErrUserNotExist(err) {
+ log.Error("Can't find user: %d for head repository in %-v - %v", pr.HeadRepo.OwnerID, pr, err)
+ return err
+ }
+ log.Error("Can't find user: %d for head repository in %-v - defaulting to doer: %-v - %v", pr.HeadRepo.OwnerID, pr, doer, err)
+ headUser = doer
+ } else {
+ headUser = pr.HeadRepo.Owner
+ }
+
+ pushCmd := git.NewCommand(ctx, "push", "-f", "head_repo").
+ AddDynamicArguments(stagingBranch + ":" + git.BranchPrefix + pr.HeadBranch)
+
+ // Push back to the head repository.
+ // TODO: this cause an api call to "/api/internal/hook/post-receive/...",
+ // that prevents us from doint the whole merge in one db transaction
+ mergeCtx.outbuf.Reset()
+ mergeCtx.errbuf.Reset()
+
+ if err := pushCmd.Run(&git.RunOpts{
+ Env: repo_module.FullPushingEnvironment(
+ headUser,
+ doer,
+ pr.HeadRepo,
+ pr.HeadRepo.Name,
+ pr.ID,
+ ),
+ Dir: mergeCtx.tmpBasePath,
+ Stdout: mergeCtx.outbuf,
+ Stderr: mergeCtx.errbuf,
+ }); err != nil {
+ if strings.Contains(mergeCtx.errbuf.String(), "non-fast-forward") {
+ return &git.ErrPushOutOfDate{
+ StdOut: mergeCtx.outbuf.String(),
+ StdErr: mergeCtx.errbuf.String(),
+ Err: err,
+ }
+ } else if strings.Contains(mergeCtx.errbuf.String(), "! [remote rejected]") {
+ err := &git.ErrPushRejected{
+ StdOut: mergeCtx.outbuf.String(),
+ StdErr: mergeCtx.errbuf.String(),
+ Err: err,
+ }
+ err.GenerateMessage()
+ return err
+ }
+ return fmt.Errorf("git push: %s", mergeCtx.errbuf.String())
+ }
+ mergeCtx.outbuf.Reset()
+ mergeCtx.errbuf.Reset()
+
+ return nil
+}
diff --git a/services/release/release_test.go b/services/release/release_test.go
index 9b8aaa364..805269413 100644
--- a/services/release/release_test.go
+++ b/services/release/release_test.go
@@ -106,11 +106,13 @@ func TestRelease_Create(t *testing.T) {
IsTag: false,
}, nil, ""))
+ testPlayload := "testtest"
+
attach, err := attachment.NewAttachment(&repo_model.Attachment{
RepoID: repo.ID,
UploaderID: user.ID,
Name: "test.txt",
- }, strings.NewReader("testtest"))
+ }, strings.NewReader(testPlayload), int64(len([]byte(testPlayload))))
assert.NoError(t, err)
release := repo_model.Release{
@@ -239,11 +241,12 @@ func TestRelease_Update(t *testing.T) {
assert.Equal(t, tagName, release.TagName)
// Add new attachments
+ samplePayload := "testtest"
attach, err := attachment.NewAttachment(&repo_model.Attachment{
RepoID: repo.ID,
UploaderID: user.ID,
Name: "test.txt",
- }, strings.NewReader("testtest"))
+ }, strings.NewReader(samplePayload), int64(len([]byte(samplePayload))))
assert.NoError(t, err)
assert.NoError(t, UpdateRelease(user, gitRepo, release, []string{attach.UUID}, nil, nil))
diff --git a/services/repository/adopt.go b/services/repository/adopt.go
index 280c4cc03..94b2c3f3d 100644
--- a/services/repository/adopt.go
+++ b/services/repository/adopt.go
@@ -26,7 +26,7 @@ import (
)
// AdoptRepository adopts pre-existing repository files for the user/organization.
-func AdoptRepository(doer, u *user_model.User, opts repo_module.CreateRepoOptions) (*repo_model.Repository, error) {
+func AdoptRepository(ctx context.Context, doer, u *user_model.User, opts repo_module.CreateRepoOptions) (*repo_model.Repository, error) {
if !doer.IsAdmin && !u.CanCreateRepo() {
return nil, repo_model.ErrReachLimitOfRepo{
Limit: u.MaxRepoCreation,
@@ -53,7 +53,7 @@ func AdoptRepository(doer, u *user_model.User, opts repo_module.CreateRepoOption
IsEmpty: !opts.AutoInit,
}
- if err := db.WithTx(db.DefaultContext, func(ctx context.Context) error {
+ if err := db.WithTx(ctx, func(ctx context.Context) error {
repoPath := repo_model.RepoPath(u.Name, repo.Name)
isExist, err := util.IsExist(repoPath)
if err != nil {
@@ -95,7 +95,7 @@ func AdoptRepository(doer, u *user_model.User, opts repo_module.CreateRepoOption
return nil, err
}
- notification.NotifyCreateRepository(db.DefaultContext, doer, u, repo)
+ notification.NotifyCreateRepository(ctx, doer, u, repo)
return repo, nil
}
@@ -188,7 +188,7 @@ func adoptRepository(ctx context.Context, repoPath string, u *user_model.User, r
}
// DeleteUnadoptedRepository deletes unadopted repository files from the filesystem
-func DeleteUnadoptedRepository(doer, u *user_model.User, repoName string) error {
+func DeleteUnadoptedRepository(ctx context.Context, doer, u *user_model.User, repoName string) error {
if err := repo_model.IsUsableRepoName(repoName); err != nil {
return err
}
@@ -206,7 +206,7 @@ func DeleteUnadoptedRepository(doer, u *user_model.User, repoName string) error
}
}
- if exist, err := repo_model.IsRepositoryExist(db.DefaultContext, u, repoName); err != nil {
+ if exist, err := repo_model.IsRepositoryExist(ctx, u, repoName); err != nil {
return err
} else if exist {
return repo_model.ErrRepoAlreadyExist{
@@ -232,11 +232,11 @@ func (unadopted *unadoptedRepositories) add(repository string) {
unadopted.index++
}
-func checkUnadoptedRepositories(userName string, repoNamesToCheck []string, unadopted *unadoptedRepositories) error {
+func checkUnadoptedRepositories(ctx context.Context, userName string, repoNamesToCheck []string, unadopted *unadoptedRepositories) error {
if len(repoNamesToCheck) == 0 {
return nil
}
- ctxUser, err := user_model.GetUserByName(db.DefaultContext, userName)
+ ctxUser, err := user_model.GetUserByName(ctx, userName)
if err != nil {
if user_model.IsErrUserNotExist(err) {
log.Debug("Missing user: %s", userName)
@@ -271,7 +271,7 @@ func checkUnadoptedRepositories(userName string, repoNamesToCheck []string, unad
}
// ListUnadoptedRepositories lists all the unadopted repositories that match the provided query
-func ListUnadoptedRepositories(query string, opts *db.ListOptions) ([]string, int, error) {
+func ListUnadoptedRepositories(ctx context.Context, query string, opts *db.ListOptions) ([]string, int, error) {
globUser, _ := glob.Compile("*")
globRepo, _ := glob.Compile("*")
@@ -315,7 +315,7 @@ func ListUnadoptedRepositories(query string, opts *db.ListOptions) ([]string, in
if !strings.ContainsRune(path[len(root)+1:], filepath.Separator) {
// Got a new user
- if err = checkUnadoptedRepositories(userName, repoNamesToCheck, unadopted); err != nil {
+ if err = checkUnadoptedRepositories(ctx, userName, repoNamesToCheck, unadopted); err != nil {
return err
}
repoNamesToCheck = repoNamesToCheck[:0]
@@ -338,7 +338,7 @@ func ListUnadoptedRepositories(query string, opts *db.ListOptions) ([]string, in
repoNamesToCheck = append(repoNamesToCheck, name)
if len(repoNamesToCheck) >= setting.Database.IterateBufferSize {
- if err = checkUnadoptedRepositories(userName, repoNamesToCheck, unadopted); err != nil {
+ if err = checkUnadoptedRepositories(ctx, userName, repoNamesToCheck, unadopted); err != nil {
return err
}
repoNamesToCheck = repoNamesToCheck[:0]
@@ -349,7 +349,7 @@ func ListUnadoptedRepositories(query string, opts *db.ListOptions) ([]string, in
return nil, 0, err
}
- if err := checkUnadoptedRepositories(userName, repoNamesToCheck, unadopted); err != nil {
+ if err := checkUnadoptedRepositories(ctx, userName, repoNamesToCheck, unadopted); err != nil {
return nil, 0, err
}
diff --git a/services/repository/adopt_test.go b/services/repository/adopt_test.go
index be8897693..3f777c425 100644
--- a/services/repository/adopt_test.go
+++ b/services/repository/adopt_test.go
@@ -39,7 +39,7 @@ func TestCheckUnadoptedRepositories(t *testing.T) {
// Non existent user
//
unadopted := &unadoptedRepositories{start: 0, end: 100}
- err := checkUnadoptedRepositories("notauser", []string{"repo"}, unadopted)
+ err := checkUnadoptedRepositories(db.DefaultContext, "notauser", []string{"repo"}, unadopted)
assert.NoError(t, err)
assert.Equal(t, 0, len(unadopted.repositories))
//
@@ -50,14 +50,14 @@ func TestCheckUnadoptedRepositories(t *testing.T) {
repoName := "repo2"
unadoptedRepoName := "unadopted"
unadopted = &unadoptedRepositories{start: 0, end: 100}
- err = checkUnadoptedRepositories(userName, []string{repoName, unadoptedRepoName}, unadopted)
+ err = checkUnadoptedRepositories(db.DefaultContext, userName, []string{repoName, unadoptedRepoName}, unadopted)
assert.NoError(t, err)
assert.Equal(t, []string{path.Join(userName, unadoptedRepoName)}, unadopted.repositories)
//
// Existing (adopted) repository is not returned
//
unadopted = &unadoptedRepositories{start: 0, end: 100}
- err = checkUnadoptedRepositories(userName, []string{repoName}, unadopted)
+ err = checkUnadoptedRepositories(db.DefaultContext, userName, []string{repoName}, unadopted)
assert.NoError(t, err)
assert.Equal(t, 0, len(unadopted.repositories))
assert.Equal(t, 0, unadopted.index)
@@ -72,13 +72,13 @@ func TestListUnadoptedRepositories_ListOptions(t *testing.T) {
}
opts := db.ListOptions{Page: 1, PageSize: 1}
- repoNames, count, err := ListUnadoptedRepositories("", &opts)
+ repoNames, count, err := ListUnadoptedRepositories(db.DefaultContext, "", &opts)
assert.NoError(t, err)
assert.Equal(t, 2, count)
assert.Equal(t, unadoptedList[0], repoNames[0])
opts = db.ListOptions{Page: 2, PageSize: 1}
- repoNames, count, err = ListUnadoptedRepositories("", &opts)
+ repoNames, count, err = ListUnadoptedRepositories(db.DefaultContext, "", &opts)
assert.NoError(t, err)
assert.Equal(t, 2, count)
assert.Equal(t, unadoptedList[1], repoNames[0])
diff --git a/services/repository/avatar.go b/services/repository/avatar.go
index 5fe8bd2c7..74e5de877 100644
--- a/services/repository/avatar.go
+++ b/services/repository/avatar.go
@@ -20,7 +20,7 @@ import (
// UploadAvatar saves custom avatar for repository.
// FIXME: split uploads to different subdirs in case we have massive number of repos.
-func UploadAvatar(repo *repo_model.Repository, data []byte) error {
+func UploadAvatar(ctx context.Context, repo *repo_model.Repository, data []byte) error {
m, err := avatar.Prepare(data)
if err != nil {
return err
@@ -31,7 +31,7 @@ func UploadAvatar(repo *repo_model.Repository, data []byte) error {
return nil
}
- ctx, committer, err := db.TxContext(db.DefaultContext)
+ ctx, committer, err := db.TxContext(ctx)
if err != nil {
return err
}
@@ -65,7 +65,7 @@ func UploadAvatar(repo *repo_model.Repository, data []byte) error {
}
// DeleteAvatar deletes the repos's custom avatar.
-func DeleteAvatar(repo *repo_model.Repository) error {
+func DeleteAvatar(ctx context.Context, repo *repo_model.Repository) error {
// Avatar not exists
if len(repo.Avatar) == 0 {
return nil
@@ -74,7 +74,7 @@ func DeleteAvatar(repo *repo_model.Repository) error {
avatarPath := repo.CustomAvatarRelativePath()
log.Trace("DeleteAvatar[%d]: %s", repo.ID, avatarPath)
- ctx, committer, err := db.TxContext(db.DefaultContext)
+ ctx, committer, err := db.TxContext(ctx)
if err != nil {
return err
}
@@ -102,7 +102,7 @@ func RemoveRandomAvatars(ctx context.Context) error {
}
stringifiedID := strconv.FormatInt(repository.ID, 10)
if repository.Avatar == stringifiedID {
- return DeleteAvatar(repository)
+ return DeleteAvatar(ctx, repository)
}
return nil
})
diff --git a/services/repository/avatar_test.go b/services/repository/avatar_test.go
index 5ec899ec3..4a0ba6185 100644
--- a/services/repository/avatar_test.go
+++ b/services/repository/avatar_test.go
@@ -9,6 +9,7 @@ import (
"image/png"
"testing"
+ "code.gitea.io/gitea/models/db"
repo_model "code.gitea.io/gitea/models/repo"
"code.gitea.io/gitea/models/unittest"
"code.gitea.io/gitea/modules/avatar"
@@ -25,7 +26,7 @@ func TestUploadAvatar(t *testing.T) {
assert.NoError(t, unittest.PrepareTestDatabase())
repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 10})
- err := UploadAvatar(repo, buff.Bytes())
+ err := UploadAvatar(db.DefaultContext, repo, buff.Bytes())
assert.NoError(t, err)
assert.Equal(t, avatar.HashAvatar(10, buff.Bytes()), repo.Avatar)
}
@@ -39,7 +40,7 @@ func TestUploadBigAvatar(t *testing.T) {
assert.NoError(t, unittest.PrepareTestDatabase())
repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 10})
- err := UploadAvatar(repo, buff.Bytes())
+ err := UploadAvatar(db.DefaultContext, repo, buff.Bytes())
assert.Error(t, err)
}
@@ -52,10 +53,10 @@ func TestDeleteAvatar(t *testing.T) {
assert.NoError(t, unittest.PrepareTestDatabase())
repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 10})
- err := UploadAvatar(repo, buff.Bytes())
+ err := UploadAvatar(db.DefaultContext, repo, buff.Bytes())
assert.NoError(t, err)
- err = DeleteAvatar(repo)
+ err = DeleteAvatar(db.DefaultContext, repo)
assert.NoError(t, err)
assert.Equal(t, "", repo.Avatar)
diff --git a/services/repository/branch.go b/services/repository/branch.go
index 291fb4a92..a085026ae 100644
--- a/services/repository/branch.go
+++ b/services/repository/branch.go
@@ -10,7 +10,6 @@ import (
"strings"
"code.gitea.io/gitea/models"
- "code.gitea.io/gitea/models/db"
git_model "code.gitea.io/gitea/models/git"
repo_model "code.gitea.io/gitea/models/repo"
user_model "code.gitea.io/gitea/models/user"
@@ -106,7 +105,7 @@ func CreateNewBranchFromCommit(ctx context.Context, doer *user_model.User, repo
}
// RenameBranch rename a branch
-func RenameBranch(repo *repo_model.Repository, doer *user_model.User, gitRepo *git.Repository, from, to string) (string, error) {
+func RenameBranch(ctx context.Context, repo *repo_model.Repository, doer *user_model.User, gitRepo *git.Repository, from, to string) (string, error) {
if from == to {
return "target_exist", nil
}
@@ -119,7 +118,7 @@ func RenameBranch(repo *repo_model.Repository, doer *user_model.User, gitRepo *g
return "from_not_exist", nil
}
- if err := git_model.RenameBranch(db.DefaultContext, repo, from, to, func(isDefault bool) error {
+ if err := git_model.RenameBranch(ctx, repo, from, to, func(isDefault bool) error {
err2 := gitRepo.RenameBranch(from, to)
if err2 != nil {
return err2
@@ -141,8 +140,8 @@ func RenameBranch(repo *repo_model.Repository, doer *user_model.User, gitRepo *g
return "", err
}
- notification.NotifyDeleteRef(db.DefaultContext, doer, repo, "branch", git.BranchPrefix+from)
- notification.NotifyCreateRef(db.DefaultContext, doer, repo, "branch", git.BranchPrefix+to, refID)
+ notification.NotifyDeleteRef(ctx, doer, repo, "branch", git.BranchPrefix+from)
+ notification.NotifyCreateRef(ctx, doer, repo, "branch", git.BranchPrefix+to, refID)
return "", nil
}
@@ -153,12 +152,12 @@ var (
)
// DeleteBranch delete branch
-func DeleteBranch(doer *user_model.User, repo *repo_model.Repository, gitRepo *git.Repository, branchName string) error {
+func DeleteBranch(ctx context.Context, doer *user_model.User, repo *repo_model.Repository, gitRepo *git.Repository, branchName string) error {
if branchName == repo.DefaultBranch {
return ErrBranchIsDefault
}
- isProtected, err := git_model.IsBranchProtected(db.DefaultContext, repo.ID, branchName)
+ isProtected, err := git_model.IsBranchProtected(ctx, repo.ID, branchName)
if err != nil {
return err
}
@@ -195,7 +194,7 @@ func DeleteBranch(doer *user_model.User, repo *repo_model.Repository, gitRepo *g
log.Error("Update: %v", err)
}
- if err := git_model.AddDeletedBranch(db.DefaultContext, repo.ID, branchName, commit.ID.String(), doer.ID); err != nil {
+ if err := git_model.AddDeletedBranch(ctx, repo.ID, branchName, commit.ID.String(), doer.ID); err != nil {
log.Warn("AddDeletedBranch: %v", err)
}
diff --git a/services/repository/files/file.go b/services/repository/files/file.go
index 2bac4372d..7939491ae 100644
--- a/services/repository/files/file.go
+++ b/services/repository/files/file.go
@@ -7,7 +7,6 @@ import (
"context"
"fmt"
"net/url"
- "path"
"strings"
"time"
@@ -15,6 +14,7 @@ import (
user_model "code.gitea.io/gitea/models/user"
"code.gitea.io/gitea/modules/git"
api "code.gitea.io/gitea/modules/structs"
+ "code.gitea.io/gitea/modules/util"
)
// GetFileResponseFromCommit Constructs a FileResponse from a Commit object
@@ -129,7 +129,7 @@ func GetAuthorAndCommitterUsers(author, committer *IdentityOptions, doer *user_m
// CleanUploadFileName Trims a filename and returns empty string if it is a .git directory
func CleanUploadFileName(name string) string {
// Rebase the filename
- name = strings.Trim(path.Clean("/"+name), "/")
+ name = strings.Trim(util.CleanPath(name), "/")
// Git disallows any filenames to have a .git directory in them.
for _, part := range strings.Split(name, "/") {
if strings.ToLower(part) == ".git" {
diff --git a/services/repository/fork.go b/services/repository/fork.go
index c3ca89e02..fb93b10f1 100644
--- a/services/repository/fork.go
+++ b/services/repository/fork.go
@@ -189,8 +189,8 @@ func ForkRepository(ctx context.Context, doer, owner *user_model.User, opts Fork
}
// ConvertForkToNormalRepository convert the provided repo from a forked repo to normal repo
-func ConvertForkToNormalRepository(repo *repo_model.Repository) error {
- err := db.WithTx(db.DefaultContext, func(ctx context.Context) error {
+func ConvertForkToNormalRepository(ctx context.Context, repo *repo_model.Repository) error {
+ err := db.WithTx(ctx, func(ctx context.Context) error {
repo, err := repo_model.GetRepositoryByID(ctx, repo.ID)
if err != nil {
return err
diff --git a/services/repository/hooks.go b/services/repository/hooks.go
index a8b6f7a62..8506fa341 100644
--- a/services/repository/hooks.go
+++ b/services/repository/hooks.go
@@ -101,7 +101,7 @@ func GenerateWebhooks(ctx context.Context, templateRepo, generateRepo *repo_mode
HookEvent: templateWebhook.HookEvent,
IsActive: templateWebhook.IsActive,
Type: templateWebhook.Type,
- OrgID: templateWebhook.OrgID,
+ OwnerID: templateWebhook.OwnerID,
Events: templateWebhook.Events,
Meta: templateWebhook.Meta,
})
diff --git a/services/repository/push.go b/services/repository/push.go
index 8aa8be6aa..4b574e344 100644
--- a/services/repository/push.go
+++ b/services/repository/push.go
@@ -122,7 +122,7 @@ func pushUpdates(optsList []*repo_module.PushUpdateOptions) error {
tagName := opts.TagName()
if opts.IsDelRef() {
notification.NotifyPushCommits(
- db.DefaultContext, pusher, repo,
+ ctx, pusher, repo,
&repo_module.PushUpdateOptions{
RefFullName: git.TagPrefix + tagName,
OldCommitID: opts.OldCommitID,
@@ -130,7 +130,7 @@ func pushUpdates(optsList []*repo_module.PushUpdateOptions) error {
}, repo_module.NewPushCommits())
delTags = append(delTags, tagName)
- notification.NotifyDeleteRef(db.DefaultContext, pusher, repo, "tag", opts.RefFullName)
+ notification.NotifyDeleteRef(ctx, pusher, repo, "tag", opts.RefFullName)
} else { // is new tag
newCommit, err := gitRepo.GetCommit(opts.NewCommitID)
if err != nil {
@@ -142,7 +142,7 @@ func pushUpdates(optsList []*repo_module.PushUpdateOptions) error {
commits.CompareURL = repo.ComposeCompareURL(git.EmptySHA, opts.NewCommitID)
notification.NotifyPushCommits(
- db.DefaultContext, pusher, repo,
+ ctx, pusher, repo,
&repo_module.PushUpdateOptions{
RefFullName: git.TagPrefix + tagName,
OldCommitID: git.EmptySHA,
@@ -150,7 +150,7 @@ func pushUpdates(optsList []*repo_module.PushUpdateOptions) error {
}, commits)
addTags = append(addTags, tagName)
- notification.NotifyCreateRef(db.DefaultContext, pusher, repo, "tag", opts.RefFullName, opts.NewCommitID)
+ notification.NotifyCreateRef(ctx, pusher, repo, "tag", opts.RefFullName, opts.NewCommitID)
}
} else if opts.IsBranch() { // If is branch reference
if pusher == nil || pusher.ID != opts.PusherID {
@@ -190,7 +190,7 @@ func pushUpdates(optsList []*repo_module.PushUpdateOptions) error {
}
}
// Update the is empty and default_branch columns
- if err := repo_model.UpdateRepositoryCols(db.DefaultContext, repo, "default_branch", "is_empty"); err != nil {
+ if err := repo_model.UpdateRepositoryCols(ctx, repo, "default_branch", "is_empty"); err != nil {
return fmt.Errorf("UpdateRepositoryCols: %w", err)
}
}
@@ -199,19 +199,19 @@ func pushUpdates(optsList []*repo_module.PushUpdateOptions) error {
if err != nil {
return fmt.Errorf("newCommit.CommitsBeforeLimit: %w", err)
}
- notification.NotifyCreateRef(db.DefaultContext, pusher, repo, "branch", opts.RefFullName, opts.NewCommitID)
+ notification.NotifyCreateRef(ctx, pusher, repo, "branch", opts.RefFullName, opts.NewCommitID)
} else {
l, err = newCommit.CommitsBeforeUntil(opts.OldCommitID)
if err != nil {
return fmt.Errorf("newCommit.CommitsBeforeUntil: %w", err)
}
- isForce, err := repo_module.IsForcePush(ctx, opts)
+ isForcePush, err := newCommit.IsForcePush(opts.OldCommitID)
if err != nil {
- log.Error("isForcePush %s:%s failed: %v", repo.FullName(), branch, err)
+ log.Error("IsForcePush %s:%s failed: %v", repo.FullName(), branch, err)
}
- if isForce {
+ if isForcePush {
log.Trace("Push %s is a force push", opts.NewCommitID)
cache.Remove(repo.GetCommitsCountCacheKey(opts.RefName(), true))
@@ -259,7 +259,7 @@ func pushUpdates(optsList []*repo_module.PushUpdateOptions) error {
commits.Commits = commits.Commits[:setting.UI.FeedMaxCommitNum]
}
- notification.NotifyPushCommits(db.DefaultContext, pusher, repo, opts, commits)
+ notification.NotifyPushCommits(ctx, pusher, repo, opts, commits)
if err = git_model.RemoveDeletedBranchByName(ctx, repo.ID, branch); err != nil {
log.Error("models.RemoveDeletedBranch %s/%s failed: %v", repo.ID, branch, err)
@@ -270,7 +270,7 @@ func pushUpdates(optsList []*repo_module.PushUpdateOptions) error {
log.Error("repo_module.CacheRef %s/%s failed: %v", repo.ID, branch, err)
}
} else {
- notification.NotifyDeleteRef(db.DefaultContext, pusher, repo, "branch", opts.RefFullName)
+ notification.NotifyDeleteRef(ctx, pusher, repo, "branch", opts.RefFullName)
if err = pull_service.CloseBranchPulls(pusher, repo.ID, branch); err != nil {
// close all related pulls
log.Error("close related pull request failed: %v", err)
@@ -278,14 +278,14 @@ func pushUpdates(optsList []*repo_module.PushUpdateOptions) error {
}
// Even if user delete a branch on a repository which he didn't watch, he will be watch that.
- if err = repo_model.WatchIfAuto(db.DefaultContext, opts.PusherID, repo.ID, true); err != nil {
+ if err = repo_model.WatchIfAuto(ctx, opts.PusherID, repo.ID, true); err != nil {
log.Warn("Fail to perform auto watch on user %v for repo %v: %v", opts.PusherID, repo.ID, err)
}
} else {
log.Trace("Non-tag and non-branch commits pushed.")
}
}
- if err := PushUpdateAddDeleteTags(repo, gitRepo, addTags, delTags); err != nil {
+ if err := PushUpdateAddDeleteTags(ctx, repo, gitRepo, addTags, delTags); err != nil {
return fmt.Errorf("PushUpdateAddDeleteTags: %w", err)
}
@@ -298,8 +298,8 @@ func pushUpdates(optsList []*repo_module.PushUpdateOptions) error {
}
// PushUpdateAddDeleteTags updates a number of added and delete tags
-func PushUpdateAddDeleteTags(repo *repo_model.Repository, gitRepo *git.Repository, addTags, delTags []string) error {
- return db.WithTx(db.DefaultContext, func(ctx context.Context) error {
+func PushUpdateAddDeleteTags(ctx context.Context, repo *repo_model.Repository, gitRepo *git.Repository, addTags, delTags []string) error {
+ return db.WithTx(ctx, func(ctx context.Context) error {
if err := repo_model.PushUpdateDeleteTagsContext(ctx, repo, delTags); err != nil {
return err
}
diff --git a/services/repository/repository.go b/services/repository/repository.go
index 3c3e7e82c..000b1a3da 100644
--- a/services/repository/repository.go
+++ b/services/repository/repository.go
@@ -24,14 +24,14 @@ import (
)
// CreateRepository creates a repository for the user/organization.
-func CreateRepository(doer, owner *user_model.User, opts repo_module.CreateRepoOptions) (*repo_model.Repository, error) {
+func CreateRepository(ctx context.Context, doer, owner *user_model.User, opts repo_module.CreateRepoOptions) (*repo_model.Repository, error) {
repo, err := repo_module.CreateRepository(doer, owner, opts)
if err != nil {
// No need to rollback here we should do this in CreateRepository...
return nil, err
}
- notification.NotifyCreateRepository(db.DefaultContext, doer, owner, repo)
+ notification.NotifyCreateRepository(ctx, doer, owner, repo)
return repo, nil
}
@@ -55,10 +55,10 @@ func DeleteRepository(ctx context.Context, doer *user_model.User, repo *repo_mod
}
// PushCreateRepo creates a repository when a new repository is pushed to an appropriate namespace
-func PushCreateRepo(authUser, owner *user_model.User, repoName string) (*repo_model.Repository, error) {
+func PushCreateRepo(ctx context.Context, authUser, owner *user_model.User, repoName string) (*repo_model.Repository, error) {
if !authUser.IsAdmin {
if owner.IsOrganization() {
- if ok, err := organization.CanCreateOrgRepo(db.DefaultContext, owner.ID, authUser.ID); err != nil {
+ if ok, err := organization.CanCreateOrgRepo(ctx, owner.ID, authUser.ID); err != nil {
return nil, err
} else if !ok {
return nil, fmt.Errorf("cannot push-create repository for org")
@@ -68,7 +68,7 @@ func PushCreateRepo(authUser, owner *user_model.User, repoName string) (*repo_mo
}
}
- repo, err := CreateRepository(authUser, owner, repo_module.CreateRepoOptions{
+ repo, err := CreateRepository(ctx, authUser, owner, repo_module.CreateRepoOptions{
Name: repoName,
IsPrivate: setting.Repository.DefaultPushCreatePrivate,
})
@@ -88,8 +88,8 @@ func Init() error {
}
// UpdateRepository updates a repository
-func UpdateRepository(repo *repo_model.Repository, visibilityChanged bool) (err error) {
- ctx, committer, err := db.TxContext(db.DefaultContext)
+func UpdateRepository(ctx context.Context, repo *repo_model.Repository, visibilityChanged bool) (err error) {
+ ctx, committer, err := db.TxContext(ctx)
if err != nil {
return err
}
diff --git a/services/repository/review.go b/services/repository/review.go
index 6b5f09605..40513e6bc 100644
--- a/services/repository/review.go
+++ b/services/repository/review.go
@@ -4,20 +4,21 @@
package repository
import (
- "code.gitea.io/gitea/models/db"
+ "context"
+
"code.gitea.io/gitea/models/organization"
"code.gitea.io/gitea/models/perm"
repo_model "code.gitea.io/gitea/models/repo"
)
// GetReviewerTeams get all teams can be requested to review
-func GetReviewerTeams(repo *repo_model.Repository) ([]*organization.Team, error) {
- if err := repo.LoadOwner(db.DefaultContext); err != nil {
+func GetReviewerTeams(ctx context.Context, repo *repo_model.Repository) ([]*organization.Team, error) {
+ if err := repo.LoadOwner(ctx); err != nil {
return nil, err
}
if !repo.Owner.IsOrganization() {
return nil, nil
}
- return organization.GetTeamsWithAccessToRepo(db.DefaultContext, repo.OwnerID, repo.ID, perm.AccessModeRead)
+ return organization.GetTeamsWithAccessToRepo(ctx, repo.OwnerID, repo.ID, perm.AccessModeRead)
}
diff --git a/services/repository/review_test.go b/services/repository/review_test.go
index 2bf4cdbf5..2db56d4e8 100644
--- a/services/repository/review_test.go
+++ b/services/repository/review_test.go
@@ -6,6 +6,7 @@ package repository
import (
"testing"
+ "code.gitea.io/gitea/models/db"
repo_model "code.gitea.io/gitea/models/repo"
"code.gitea.io/gitea/models/unittest"
@@ -16,12 +17,12 @@ func TestRepoGetReviewerTeams(t *testing.T) {
assert.NoError(t, unittest.PrepareTestDatabase())
repo2 := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 2})
- teams, err := GetReviewerTeams(repo2)
+ teams, err := GetReviewerTeams(db.DefaultContext, repo2)
assert.NoError(t, err)
assert.Empty(t, teams)
repo3 := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 3})
- teams, err = GetReviewerTeams(repo3)
+ teams, err = GetReviewerTeams(db.DefaultContext, repo3)
assert.NoError(t, err)
assert.Len(t, teams, 2)
}
diff --git a/services/repository/template.go b/services/repository/template.go
index 8c75948c4..42174d095 100644
--- a/services/repository/template.go
+++ b/services/repository/template.go
@@ -40,7 +40,7 @@ func GenerateIssueLabels(ctx context.Context, templateRepo, generateRepo *repo_m
}
// GenerateRepository generates a repository from a template
-func GenerateRepository(doer, owner *user_model.User, templateRepo *repo_model.Repository, opts repo_module.GenerateRepoOptions) (_ *repo_model.Repository, err error) {
+func GenerateRepository(ctx context.Context, doer, owner *user_model.User, templateRepo *repo_model.Repository, opts repo_module.GenerateRepoOptions) (_ *repo_model.Repository, err error) {
if !doer.IsAdmin && !owner.CanCreateRepo() {
return nil, repo_model.ErrReachLimitOfRepo{
Limit: owner.MaxRepoCreation,
@@ -48,7 +48,7 @@ func GenerateRepository(doer, owner *user_model.User, templateRepo *repo_model.R
}
var generateRepo *repo_model.Repository
- if err = db.WithTx(db.DefaultContext, func(ctx context.Context) error {
+ if err = db.WithTx(ctx, func(ctx context.Context) error {
generateRepo, err = repo_module.GenerateRepository(ctx, doer, owner, templateRepo, opts)
if err != nil {
return err
@@ -101,7 +101,7 @@ func GenerateRepository(doer, owner *user_model.User, templateRepo *repo_model.R
return nil, err
}
- notification.NotifyCreateRepository(db.DefaultContext, doer, owner, generateRepo)
+ notification.NotifyCreateRepository(ctx, doer, owner, generateRepo)
return generateRepo, nil
}
diff --git a/services/repository/transfer.go b/services/repository/transfer.go
index 8c167552d..b9b26f314 100644
--- a/services/repository/transfer.go
+++ b/services/repository/transfer.go
@@ -8,7 +8,6 @@ import (
"fmt"
"code.gitea.io/gitea/models"
- "code.gitea.io/gitea/models/db"
"code.gitea.io/gitea/models/organization"
"code.gitea.io/gitea/models/perm"
access_model "code.gitea.io/gitea/models/perm/access"
@@ -61,7 +60,7 @@ func TransferOwnership(ctx context.Context, doer, newOwner *user_model.User, rep
}
// ChangeRepositoryName changes all corresponding setting from old repository name to new one.
-func ChangeRepositoryName(doer *user_model.User, repo *repo_model.Repository, newRepoName string) error {
+func ChangeRepositoryName(ctx context.Context, doer *user_model.User, repo *repo_model.Repository, newRepoName string) error {
log.Trace("ChangeRepositoryName: %s/%s -> %s", doer.Name, repo.Name, newRepoName)
oldRepoName := repo.Name
@@ -78,7 +77,7 @@ func ChangeRepositoryName(doer *user_model.User, repo *repo_model.Repository, ne
repoWorkingPool.CheckOut(fmt.Sprint(repo.ID))
repo.Name = newRepoName
- notification.NotifyRenameRepository(db.DefaultContext, doer, repo, oldRepoName)
+ notification.NotifyRenameRepository(ctx, doer, repo, oldRepoName)
return nil
}
diff --git a/services/webhook/webhook.go b/services/webhook/webhook.go
index afd8e3c10..b862d5bff 100644
--- a/services/webhook/webhook.go
+++ b/services/webhook/webhook.go
@@ -229,16 +229,16 @@ func PrepareWebhooks(ctx context.Context, source EventSource, event webhook_modu
owner = source.Repository.MustOwner(ctx)
}
- // check if owner is an org and append additional webhooks
- if owner != nil && owner.IsOrganization() {
- orgHooks, err := webhook_model.ListWebhooksByOpts(ctx, &webhook_model.ListWebhookOptions{
- OrgID: owner.ID,
+ // append additional webhooks of a user or organization
+ if owner != nil {
+ ownerHooks, err := webhook_model.ListWebhooksByOpts(ctx, &webhook_model.ListWebhookOptions{
+ OwnerID: owner.ID,
IsActive: util.OptionalBoolTrue,
})
if err != nil {
return fmt.Errorf("ListWebhooksByOpts: %w", err)
}
- ws = append(ws, orgHooks...)
+ ws = append(ws, ownerHooks...)
}
// Add any admin-defined system webhooks
diff --git a/templates/admin/auth/source/oauth.tmpl b/templates/admin/auth/source/oauth.tmpl
index b7ee00822..1080937f9 100644
--- a/templates/admin/auth/source/oauth.tmpl
+++ b/templates/admin/auth/source/oauth.tmpl
@@ -24,7 +24,7 @@
<label for="oauth2_icon_url">{{.locale.Tr "admin.auths.oauth2_icon_url"}}</label>
<input id="oauth2_icon_url" name="oauth2_icon_url" value="{{.oauth2_icon_url}}">
</div>
- <div class="open_id_connect_auto_discovery_url required field">
+ <div class="open_id_connect_auto_discovery_url required field{{if .Err_DiscoveryURL}} error{{end}}">
<label for="open_id_connect_auto_discovery_url">{{.locale.Tr "admin.auths.openIdConnectAutoDiscoveryURL"}}</label>
<input id="open_id_connect_auto_discovery_url" name="open_id_connect_auto_discovery_url" value="{{.open_id_connect_auto_discovery_url}}">
</div>
diff --git a/templates/admin/user/new.tmpl b/templates/admin/user/new.tmpl
index e5ca864cb..2bf1d0ace 100644
--- a/templates/admin/user/new.tmpl
+++ b/templates/admin/user/new.tmpl
@@ -50,7 +50,7 @@
</div>
</div>
- <div class="required non-local field {{if .Err_LoginName}}error{{end}} {{if eq .login_type "0-0"}}hide{{end}}">
+ <div class="required non-local field {{if .Err_LoginName}}error{{end}} {{if eq .login_type "0-0"}}gt-hidden{{end}}">
<label for="login_name">{{.locale.Tr "admin.users.auth_login_name"}}</label>
<input id="login_name" name="login_name" value="{{.login_name}}">
</div>
@@ -62,12 +62,12 @@
<label for="email">{{.locale.Tr "email"}}</label>
<input id="email" name="email" type="email" value="{{.email}}" required>
</div>
- <div class="required local field {{if .Err_Password}}error{{end}} {{if not (eq .login_type "0-0")}}hide{{end}}">
+ <div class="required local field {{if .Err_Password}}error{{end}} {{if not (eq .login_type "0-0")}}gt-hidden{{end}}">
<label for="password">{{.locale.Tr "password"}}</label>
<input id="password" name="password" type="password" autocomplete="new-password" value="{{.password}}" {{if eq .login_type "0-0"}}required{{end}}>
</div>
- <div class="inline field local{{if ne .login_type "0-0"}} hide{{end}}">
+ <div class="inline field local {{if ne .login_type "0-0"}}gt-hidden{{end}}">
<div class="ui checkbox">
<label><strong>{{.locale.Tr "auth.allow_password_change"}}</strong></label>
<input name="must_change_password" type="checkbox" checked>
diff --git a/templates/base/head.tmpl b/templates/base/head.tmpl
index c552dcfd2..d179140b2 100644
--- a/templates/base/head.tmpl
+++ b/templates/base/head.tmpl
@@ -4,7 +4,7 @@
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>{{if .Title}}{{.Title | RenderEmojiPlain}} - {{end}}{{if .Repository.Name}}{{.Repository.Name}} - {{end}}{{AppName}}</title>
- <link rel="manifest" href="data:{{.ManifestData}}">
+ {{if .ManifestData}}<link rel="manifest" href="data:{{.ManifestData}}">{{end}}
<meta name="theme-color" content="{{ThemeColorMetaTag}}">
<meta name="default-theme" content="{{DefaultTheme}}">
<meta name="author" content="{{if .Repository}}{{.Owner.Name}}{{else}}{{MetaAuthor}}{{end}}">
diff --git a/templates/mail/issue/assigned.tmpl b/templates/mail/issue/assigned.tmpl
index 232a41b56..05bed6902 100644
--- a/templates/mail/issue/assigned.tmpl
+++ b/templates/mail/issue/assigned.tmpl
@@ -8,7 +8,7 @@
<title>{{.Subject}}</title>
</head>
-{{$repo_url := printf "<a href='%s'>%s</a>" (Escape .Issue.Repo.Link) (Escape .Issue.Repo.FullName)}}
+{{$repo_url := printf "<a href='%s'>%s</a>" (Escape .Issue.Repo.HTMLURL) (Escape .Issue.Repo.FullName)}}
{{$link := printf "<a href='%s'>#%d</a>" (Escape .Link) .Issue.Index}}
<body>
<p>
diff --git a/templates/mail/issue/default.tmpl b/templates/mail/issue/default.tmpl
index 3bda408a0..64dbb3df6 100644
--- a/templates/mail/issue/default.tmpl
+++ b/templates/mail/issue/default.tmpl
@@ -20,11 +20,11 @@
{{if eq .ActionName "push"}}
<p>
{{if .Comment.IsForcePush}}
- {{$oldCommitUrl := printf "%s/commit/%s" .Comment.Issue.PullRequest.BaseRepo.Link .Comment.OldCommit}}
+ {{$oldCommitUrl := printf "%s/commit/%s" .Comment.Issue.PullRequest.BaseRepo.HTMLURL .Comment.OldCommit}}
{{$oldShortSha := ShortSha .Comment.OldCommit}}
{{$oldCommitLink := printf "<a href='%[1]s'><b>%[2]s</b></a>" (Escape $oldCommitUrl) (Escape $oldShortSha)}}
- {{$newCommitUrl := printf "%s/commit/%s" .Comment.Issue.PullRequest.BaseRepo.Link .Comment.NewCommit}}
+ {{$newCommitUrl := printf "%s/commit/%s" .Comment.Issue.PullRequest.BaseRepo.HTMLURL .Comment.NewCommit}}
{{$newShortSha := ShortSha .Comment.NewCommit}}
{{$newCommitLink := printf "<a href='%[1]s'><b>%[2]s</b></a>" (Escape $newCommitUrl) (Escape $newShortSha)}}
@@ -72,7 +72,7 @@
<ul>
{{range .Comment.Commits}}
<li>
- <a href="{{$.Comment.Issue.PullRequest.BaseRepo.Link}}/commit/{{.ID}}">
+ <a href="{{$.Comment.Issue.PullRequest.BaseRepo.HTMLURL}}/commit/{{.ID}}">
{{ShortSha .ID.String}}
</a> - {{.Summary}}
</li>
diff --git a/templates/mail/release.tmpl b/templates/mail/release.tmpl
index 425043352..b2acdce8b 100644
--- a/templates/mail/release.tmpl
+++ b/templates/mail/release.tmpl
@@ -11,8 +11,8 @@
</head>
-{{$release_url := printf "<a href='%s'>%s</a>" (.Release.Link | Escape) (.Release.TagName | Escape)}}
-{{$repo_url := printf "<a href='%s'>%s</a>" (.Release.Repo.Link | Escape) (.Release.Repo.FullName | Escape)}}
+{{$release_url := printf "<a href='%s'>%s</a>" (.Release.HTMLURL | Escape) (.Release.TagName | Escape)}}
+{{$repo_url := printf "<a href='%s'>%s</a>" (.Release.Repo.HTMLURL | Escape) (.Release.Repo.FullName | Escape)}}
<body>
<p>
{{.locale.Tr "mail.release.new.text" .Release.Publisher.Name $release_url $repo_url | Str2html}}
diff --git a/templates/org/menu.tmpl b/templates/org/menu.tmpl
index 7ca47cd32..2a359d811 100644
--- a/templates/org/menu.tmpl
+++ b/templates/org/menu.tmpl
@@ -3,16 +3,18 @@
<a class="{{if .PageIsViewRepositories}}active {{end}}item" href="{{$.Org.HomeLink}}">
{{svg "octicon-repo"}} {{.locale.Tr "user.repositories"}}
</a>
+ {{if and .IsProjectEnabled .CanReadProjects}}
<a class="{{if .PageIsViewProjects}}active {{end}}item" href="{{$.Org.HomeLink}}/-/projects">
- {{svg "octicon-project"}} {{.locale.Tr "user.projects"}}
+ {{svg "octicon-project-symlink"}} {{.locale.Tr "user.projects"}}
</a>
- {{if .IsPackageEnabled}}
+ {{end}}
+ {{if and .IsPackageEnabled .CanReadPackages}}
<a class="item" href="{{$.Org.HomeLink}}/-/packages">
{{svg "octicon-package"}} {{.locale.Tr "packages.title"}}
</a>
{{end}}
- {{if .IsRepoIndexerEnabled}}
- <a class="{{if $.PageIsOrgCode}}active {{end}}item" href="{{$.Org.HomeLink}}/-/code">
+ {{if and .IsRepoIndexerEnabled .CanReadCode}}
+ <a class="item" href="{{$.Org.HomeLink}}/-/code">
{{svg "octicon-code"}}&nbsp;{{$.locale.Tr "org.code"}}
</a>
{{end}}
diff --git a/templates/post-install.tmpl b/templates/post-install.tmpl
index 0d6cd3082..f237a6e01 100644
--- a/templates/post-install.tmpl
+++ b/templates/post-install.tmpl
@@ -1,5 +1,5 @@
{{template "base/head" .}}
-<div role="main" aria-label="{{.Title}}" class="page-content install">
+<div role="main" aria-label="{{.Title}}" class="page-content install post-install">
<div class="ui container">
<div class="ui grid">
<div class="sixteen wide column content">
@@ -13,7 +13,7 @@
</div>
<div class="ui stackable middle very relaxed page grid">
<div class="sixteen wide center aligned centered column">
- <p><a href="{{AppSubUrl}}/user/login">{{AppSubUrl}}/user/login</a></p>
+ <p><a id="goto-user-login" href="{{AppSubUrl}}/user/login">{{.locale.Tr "loading"}}</a></p>
</div>
</div>
</div>
diff --git a/templates/projects/list.tmpl b/templates/projects/list.tmpl
index 8d9594e2b..489189ec4 100644
--- a/templates/projects/list.tmpl
+++ b/templates/projects/list.tmpl
@@ -12,7 +12,7 @@
{{template "base/alert" .}}
<div class="ui compact tiny menu">
<a class="item{{if not .IsShowClosed}} active{{end}}" href="{{$.Link}}?state=open">
- {{svg "octicon-project" 16 "gt-mr-3"}}
+ {{svg "octicon-project-symlink" 16 "gt-mr-3"}}
{{JsPrettyNumber .OpenCount}}&nbsp;{{.locale.Tr "repo.issues.open_title"}}
</a>
<a class="item{{if .IsShowClosed}} active{{end}}" href="{{$.Link}}?state=closed">
@@ -38,7 +38,7 @@
<div class="milestone list">
{{range .Projects}}
<li class="item">
- {{svg "octicon-project"}} <a href="{{$.Link}}/{{.ID}}">{{.Title}}</a>
+ {{svg "octicon-project-symlink"}} <a href="{{.Link}}">{{.Title}}</a>
<div class="meta">
{{$closedDate:= TimeSinceUnix .ClosedDateUnix $.locale}}
{{if .IsClosed}}
diff --git a/templates/projects/new.tmpl b/templates/projects/new.tmpl
index c96f948de..826869ac5 100644
--- a/templates/projects/new.tmpl
+++ b/templates/projects/new.tmpl
@@ -21,6 +21,7 @@
<form class="ui form grid" action="{{.Link}}" method="post">
{{.CsrfTokenHtml}}
<div class="eleven wide column">
+ <input type="hidden" id="redirect" name="redirect" value="{{.redirect}}">
<div class="field {{if .Err_Title}}error{{end}}">
<label>{{.locale.Tr "repo.projects.title"}}</label>
<input name="title" placeholder="{{.locale.Tr "repo.projects.title"}}" value="{{.title}}" autofocus required>
diff --git a/templates/projects/view.tmpl b/templates/projects/view.tmpl
index 3d0bea35d..06192f630 100644
--- a/templates/projects/view.tmpl
+++ b/templates/projects/view.tmpl
@@ -46,7 +46,7 @@
{{if or $.CanWriteIssues $.CanWritePulls}}
<div class="column right aligned">
<div class="ui compact right small menu">
- <a class="item" href="{{$.Link}}/edit" data-id={{$.Project.ID}} data-title={{$.Project.Title}}>
+ <a class="item" href="{{$.Link}}/edit?redirect=project" data-id={{$.Project.ID}} data-title={{$.Project.Title}}>
{{svg "octicon-pencil"}}
<span class="gt-mx-3">{{$.locale.Tr "repo.issues.label_edit"}}</span>
</a>
@@ -128,7 +128,7 @@
<div class="text right actions">
<div class="ui cancel button">{{$.locale.Tr "settings.cancel"}}</div>
- <button data-url="{{$.Link}}/{{.ID}}" class="ui primary button">{{$.locale.Tr "repo.projects.column.edit"}}</button>
+ <button data-url="{{$.Link}}/{{.ID}}" class="ui primary button edit-column-button">{{$.locale.Tr "repo.projects.column.edit"}}</button>
</div>
</form>
</div>
@@ -234,11 +234,11 @@
{{if or .Labels .Assignees}}
<div class="extra content labels-list gt-p-0 gt-pt-2">
{{range .Labels}}
- <a target="_blank" href="{{$.RepoLink}}/issues?labels={{.ID}}">{{RenderLabel .}}</a>
+ <a target="_blank" href="{{$.RepoLink}}/issues?labels={{.ID}}">{{RenderLabel $.Context .}}</a>
{{end}}
<div class="right floated">
{{range .Assignees}}
- <a class="tooltip" target="_blank" href="{{.HomeLink}}" data-content="{{$.locale.Tr "repo.projects.column.assigned_to"}} {{.Name}}">{{avatar . 28 "mini gt-mr-3"}}</a>
+ <a class="tooltip" target="_blank" href="{{.HomeLink}}" data-content="{{$.locale.Tr "repo.projects.column.assigned_to"}} {{.Name}}">{{avatar $.Context . 28 "mini gt-mr-3"}}</a>
{{end}}
</div>
</div>
diff --git a/templates/repo/actions/runs_list.tmpl b/templates/repo/actions/runs_list.tmpl
index a01d21657..ffabe534c 100644
--- a/templates/repo/actions/runs_list.tmpl
+++ b/templates/repo/actions/runs_list.tmpl
@@ -7,7 +7,7 @@
<div class="issue-item-main gt-f1 gt-fc gt-df">
<div class="issue-item-top-row">
<a class="index gt-ml-0 gt-mr-2" href="{{if .Link}}{{.Link}}{{else}}{{$.Link}}/{{.Index}}{{end}}">
- {{.Title}}
+ {{- .Title -}}
</a>
<span class="ui label">
{{if .RefLink}}
diff --git a/templates/repo/activity.tmpl b/templates/repo/activity.tmpl
index 255951824..ae1d426bc 100644
--- a/templates/repo/activity.tmpl
+++ b/templates/repo/activity.tmpl
@@ -129,7 +129,7 @@
<span class="ui green label">{{$.locale.Tr "repo.activity.published_release_label"}}</span>
{{.TagName}}
{{if not .IsTag}}
- <a class="title" href="{{$.RepoLink}}/src/{{.TagName | PathEscapeSegments}}">{{.Title | RenderEmoji}}</a>
+ <a class="title" href="{{$.RepoLink}}/src/{{.TagName | PathEscapeSegments}}">{{.Title | RenderEmoji $.Context}}</a>
{{end}}
{{TimeSinceUnix .CreatedUnix $.locale}}
</p>
@@ -149,7 +149,7 @@
{{range .Activity.MergedPRs}}
<p class="desc">
<span class="ui purple label">{{$.locale.Tr "repo.activity.merged_prs_label"}}</span>
- #{{.Index}} <a class="title" href="{{$.RepoLink}}/pulls/{{.Index}}">{{.Issue.Title | RenderEmoji}}</a>
+ #{{.Index}} <a class="title" href="{{$.RepoLink}}/pulls/{{.Index}}">{{.Issue.Title | RenderEmoji $.Context}}</a>
{{TimeSinceUnix .MergedUnix $.locale}}
</p>
{{end}}
@@ -168,7 +168,7 @@
{{range .Activity.OpenedPRs}}
<p class="desc">
<span class="ui green label">{{$.locale.Tr "repo.activity.opened_prs_label"}}</span>
- #{{.Index}} <a class="title" href="{{$.RepoLink}}/pulls/{{.Index}}">{{.Issue.Title | RenderEmoji}}</a>
+ #{{.Index}} <a class="title" href="{{$.RepoLink}}/pulls/{{.Index}}">{{.Issue.Title | RenderEmoji $.Context}}</a>
{{TimeSinceUnix .Issue.CreatedUnix $.locale}}
</p>
{{end}}
@@ -187,7 +187,7 @@
{{range .Activity.ClosedIssues}}
<p class="desc">
<span class="ui red label">{{$.locale.Tr "repo.activity.closed_issue_label"}}</span>
- #{{.Index}} <a class="title" href="{{$.RepoLink}}/issues/{{.Index}}">{{.Title | RenderEmoji}}</a>
+ #{{.Index}} <a class="title" href="{{$.RepoLink}}/issues/{{.Index}}">{{.Title | RenderEmoji $.Context}}</a>
{{TimeSinceUnix .ClosedUnix $.locale}}
</p>
{{end}}
@@ -206,7 +206,7 @@
{{range .Activity.OpenedIssues}}
<p class="desc">
<span class="ui green label">{{$.locale.Tr "repo.activity.new_issue_label"}}</span>
- #{{.Index}} <a class="title" href="{{$.RepoLink}}/issues/{{.Index}}">{{.Title | RenderEmoji}}</a>
+ #{{.Index}} <a class="title" href="{{$.RepoLink}}/issues/{{.Index}}">{{.Title | RenderEmoji $.Context}}</a>
{{TimeSinceUnix .CreatedUnix $.locale}}
</p>
{{end}}
@@ -227,9 +227,9 @@
<span class="ui green label">{{$.locale.Tr "repo.activity.unresolved_conv_label"}}</span>
#{{.Index}}
{{if .IsPull}}
- <a class="title" href="{{$.RepoLink}}/pulls/{{.Index}}">{{.Title | RenderEmoji}}</a>
+ <a class="title" href="{{$.RepoLink}}/pulls/{{.Index}}">{{.Title | RenderEmoji $.Context}}</a>
{{else}}
- <a class="title" href="{{$.RepoLink}}/issues/{{.Index}}">{{.Title | RenderEmoji}}</a>
+ <a class="title" href="{{$.RepoLink}}/issues/{{.Index}}">{{.Title | RenderEmoji $.Context}}</a>
{{end}}
{{TimeSinceUnix .UpdatedUnix $.locale}}
</p>
diff --git a/templates/repo/branch_dropdown.tmpl b/templates/repo/branch_dropdown.tmpl
index 89d65146a..8e81373ae 100644
--- a/templates/repo/branch_dropdown.tmpl
+++ b/templates/repo/branch_dropdown.tmpl
@@ -2,101 +2,111 @@
{{$defaultBranch := $.root.BranchName}}{{if and .root.IsViewTag (not .noTag)}}{{$defaultBranch = .root.TagName}}{{end}}{{if eq $defaultBranch ""}}{{$defaultBranch = $.root.Repository.DefaultBranch}}{{end}}
{{$type := ""}}{{if and .root.IsViewTag (not .noTag)}}{{$type = "tag"}}{{else if .root.IsViewBranch}}{{$type = "branch"}}{{else}}{{$type = "tree"}}{{end}}
{{$showBranchesInDropdown := not .root.HideBranchesInDropdown}}
+
+<script type="module">
+ const data = {
+ 'textReleaseCompare': {{.root.locale.Tr "repo.release.compare"}},
+ 'textCreateTag': {{.root.locale.Tr "repo.tag.create_tag"}},
+ 'textCreateBranch': {{.root.locale.Tr "repo.branch.create_branch"}},
+ 'textCreateBranchFrom': {{.root.locale.Tr "repo.branch.create_from"}},
+ 'textBranches': {{.root.locale.Tr "repo.branches"}},
+ 'textTags': {{.root.locale.Tr "repo.tags"}},
+
+ 'mode': '{{if or .root.IsViewTag .isTag}}tags{{else}}branches{{end}}',
+ 'showBranchesInDropdown': {{$showBranchesInDropdown}},
+ 'searchFieldPlaceholder': '{{if $.noTag}}{{.root.locale.Tr "repo.pulls.filter_branch"}}{{else if $showBranchesInDropdown}}{{.root.locale.Tr "repo.filter_branch_and_tag"}}{{else}}{{.root.locale.Tr "repo.find_tag"}}{{end}}...',
+ 'branchForm': {{$.branchForm}},
+ 'disableCreateBranch': {{if .disableCreateBranch}}{{.disableCreateBranch}}{{else}}{{not .root.CanCreateBranch}}{{end}},
+ 'setAction': {{.setAction}},
+ 'submitForm': {{.submitForm}},
+ 'viewType': {{$type}},
+ 'refName': {{if and .root.IsViewTag (not .noTag)}}{{.root.TagName}}{{else if .root.IsViewBranch}}{{.root.BranchName}}{{else}}{{ShortSha .root.CommitID}}{{end}},
+ 'commitIdShort': {{ShortSha .root.CommitID}},
+ 'tagName': {{.root.TagName}},
+ 'branchName': {{.root.BranchName}},
+ 'noTag': {{.noTag}},
+ 'branches': {{.root.Branches}},
+ 'tags': {{.root.Tags}},
+ 'defaultBranch': {{$defaultBranch}},
+ 'branchURLPrefix': '{{if .branchURLPrefix}}{{.branchURLPrefix}}{{else}}{{$.root.RepoLink}}/{{if $.root.PageIsCommits}}commits{{else}}src{{end}}/branch/{{end}}',
+ 'branchURLSuffix': '{{if .branchURLSuffix}}{{.branchURLSuffix}}{{else}}{{if $.root.TreePath}}/{{PathEscapeSegments $.root.TreePath}}{{end}}{{end}}',
+ 'tagURLPrefix': '{{if .tagURLPrefix}}{{.tagURLPrefix}}{{else if $release}}{{$.root.RepoLink}}/compare/{{else}}{{$.root.RepoLink}}/{{if $.root.PageIsCommits}}commits{{else}}src{{end}}/tag/{{end}}',
+ 'tagURLSuffix': '{{if .tagURLSuffix}}{{.tagURLSuffix}}{{else if $release}}...{{if $release.IsDraft}}{{PathEscapeSegments $release.Target}}{{else}}{{if $release.TagName}}{{PathEscapeSegments $release.TagName}}{{else}}{{PathEscapeSegments $release.Sha1}}{{end}}{{end}}{{else}}{{if $.root.TreePath}}/{{PathEscapeSegments $.root.TreePath}}{{end}}{{end}}',
+ 'repoLink': {{.root.RepoLink}},
+ 'treePath': {{.root.TreePath}},
+ 'branchNameSubURL': {{.root.BranchNameSubURL}},
+ 'noResults': {{.root.locale.Tr "repo.pulls.no_results"}},
+ };
+ {{if .release}}
+ data.release = {
+ 'tagName': {{.release.TagName}},
+ };
+ {{end}}
+ window.config.pageData.branchDropdownDataList = window.config.pageData.branchDropdownDataList || [];
+ window.config.pageData.branchDropdownDataList.push(data);
+</script>
+
<div class="fitted item choose reference">
- <div class="ui floating filter dropdown custom"
- data-branch-form="{{if $.branchForm}}{{$.branchForm}}{{end}}"
- data-can-create-branch="{{if .canCreateBranch}}{{.canCreateBranch}}{{else}}{{.root.CanCreateBranch}}{{end}}"
- data-no-results="{{.root.locale.Tr "repo.pulls.no_results"}}"
- data-set-action="{{.setAction}}" data-submit-form="{{.submitForm}}"
- data-view-type="{{$type}}"
- data-ref-name="{{if and .root.IsViewTag (not .noTag)}}{{.root.TagName}}{{else if .root.IsViewBranch}}{{.root.BranchName}}{{else}}{{ShortSha .root.CommitID}}{{end}}"
- data-branch-url-prefix="{{if .branchURLPrefix}}{{.branchURLPrefix}}{{else}}{{$.root.RepoLink}}/{{if $.root.PageIsCommits}}commits{{else}}src{{end}}/branch/{{end}}"
- data-branch-url-suffix="{{if .branchURLSuffix}}{{.branchURLSuffix}}{{else}}{{if $.root.TreePath}}/{{PathEscapeSegments $.root.TreePath}}{{end}}{{end}}"
- data-tag-url-prefix="{{if .tagURLPrefix}}{{.tagURLPrefix}}{{else if $release}}{{$.root.RepoLink}}/compare/{{else}}{{$.root.RepoLink}}/{{if $.root.PageIsCommits}}commits{{else}}src{{end}}/tag/{{end}}"
- data-tag-url-suffix="{{if .tagURLSuffix}}{{.tagURLSuffix}}{{else if $release}}...{{if $release.IsDraft}}{{PathEscapeSegments $release.Target}}{{else}}{{if $release.TagName}}{{PathEscapeSegments $release.TagName}}{{else}}{{PathEscapeSegments $release.Sha1}}{{end}}{{end}}{{else}}{{if $.root.TreePath}}/{{PathEscapeSegments $.root.TreePath}}{{end}}{{end}}">
+ <div class="ui floating filter dropdown custom">
<button class="branch-dropdown-button gt-ellipsis ui basic small compact button gt-df" @click="menuVisible = !menuVisible" @keyup.enter="menuVisible = !menuVisible">
<span class="text gt-df gt-ac gt-mr-2">
- {{if $release}}
- {{.root.locale.Tr "repo.release.compare"}}
- {{else}}
- <span :class="{visible: isViewTag}" v-if="isViewTag" {{if not (eq $type "tag")}}v-cloak{{end}}>{{svg "octicon-tag"}}</span>
- <span :class="{visible: isViewBranch}" v-if="isViewBranch" {{if not (eq $type "branch")}}v-cloak{{end}}>{{svg "octicon-git-branch"}}</span>
- <span :class="{visible: isViewTree}" v-if="isViewTree" {{if not (eq $type "tree")}}v-cloak{{end}}>{{svg "octicon-git-branch"}}</span>
- <strong ref="dropdownRefName" class="gt-ml-3">{{if and .root.IsViewTag (not .noTag)}}{{.root.TagName}}{{else if .root.IsViewBranch}}{{.root.BranchName}}{{else}}{{ShortSha .root.CommitID}}{{end}}</strong>
- {{end}}
+ {{/* v-cloak is used to hide unnecessary elements before Vue componment is mounted */}}
+ <span v-cloak v-if="release">${ textReleaseCompare }</span>
+ <span :class="{visible: isViewTag}" v-if="isViewTag" {{if not (eq $type "tag")}}v-cloak{{end}}>{{svg "octicon-tag"}}</span>
+ <span :class="{visible: isViewBranch}" v-if="isViewBranch" {{if not (eq $type "branch")}}v-cloak{{end}}>{{svg "octicon-git-branch"}}</span>
+ <span :class="{visible: isViewTree}" v-if="isViewTree" {{if not (eq $type "tree")}}v-cloak{{end}}>{{svg "octicon-git-branch"}}</span>
+ <strong ref="dropdownRefName" class="gt-ml-3">{{if and .root.IsViewTag (not .noTag)}}{{.root.TagName}}{{else if .root.IsViewBranch}}{{.root.BranchName}}{{else}}{{ShortSha .root.CommitID}}{{end}}</strong>
</span>
{{svg "octicon-triangle-down" 14 "dropdown icon"}}
</button>
- <div class="data gt-hidden" data-mode="{{if or .root.IsViewTag .isTag}}tags{{else}}branches{{end}}">
- {{if $showBranchesInDropdown}}
- {{range .root.Branches}}
- <div class="item branch {{if eq $defaultBranch .}}selected{{end}}" data-url="{{PathEscapeSegments .}}">{{.}}</div>
- {{end}}
- {{end}}
- {{if (not .noTag)}}
- {{range .root.Tags}}
- {{if $release}}
- <div class="item tag {{if eq $release.TagName .}}selected{{end}}" data-url="{{PathEscapeSegments .}}">{{.}}</div>
- {{else}}
- <div class="item tag {{if eq $defaultBranch .}}selected{{end}}" data-url="{{PathEscapeSegments .}}">{{.}}</div>
- {{end}}
- {{end}}
- {{end}}
- </div>
<div class="menu transition" :class="{visible: menuVisible}" v-if="menuVisible" v-cloak>
<div class="ui icon search input">
<i class="icon gt-df gt-ac gt-jc gt-m-0">{{svg "octicon-filter" 16}}</i>
- <input name="search" ref="searchField" autocomplete="off" v-model="searchTerm" @keydown="keydown($event)" placeholder="{{if $.noTag}}{{.root.locale.Tr "repo.pulls.filter_branch"}}{{else if $showBranchesInDropdown}}{{.root.locale.Tr "repo.filter_branch_and_tag"}}{{else}}{{.root.locale.Tr "repo.find_tag"}}{{end}}...">
+ <input name="search" ref="searchField" autocomplete="off" v-model="searchTerm" @keydown="keydown($event)" :placeholder="searchFieldPlaceholder">
</div>
- {{if $showBranchesInDropdown}}
+ <template v-if="showBranchesInDropdown">
<div class="header branch-tag-choice">
<div class="ui grid">
<div class="two column row">
<a class="reference column" href="#" @click="createTag = false; mode = 'branches'; focusSearchField()">
- <span class="text" :class="{black: mode == 'branches'}">
- {{svg "octicon-git-branch" 16 "gt-mr-2"}}{{.root.locale.Tr "repo.branches"}}
+ <span class="text" :class="{black: mode === 'branches'}">
+ {{svg "octicon-git-branch" 16 "gt-mr-2"}}${ textBranches }
</span>
</a>
- {{if not .noTag}}
+ <template v-if="!noTag">
<a class="reference column" href="#" @click="createTag = true; mode = 'tags'; focusSearchField()">
- <span class="text" :class="{black: mode == 'tags'}">
- {{svg "octicon-tag" 16 "gt-mr-2"}}{{.root.locale.Tr "repo.tags"}}
+ <span class="text" :class="{black: mode === 'tags'}">
+ {{svg "octicon-tag" 16 "gt-mr-2"}}${ textTags }
</span>
</a>
- {{end}}
+ </template>
</div>
</div>
</div>
- {{end}}
+ </template>
<div class="scrolling menu" ref="scrollContainer">
- <div v-for="(item, index) in filteredItems" :key="item.name" class="item" :class="{selected: item.selected, active: active == index}" @click="selectItem(item)" :ref="'listItem' + index">${ item.name }</div>
- <div class="item" v-if="showCreateNewBranch" :class="{active: active == filteredItems.length}" :ref="'listItem' + filteredItems.length">
+ <div v-for="(item, index) in filteredItems" :key="item.name" class="item" :class="{selected: item.selected, active: active === index}" @click="selectItem(item)" :ref="'listItem' + index">${ item.name }</div>
+ <div class="item" v-if="showCreateNewBranch" :class="{active: active === filteredItems.length}" :ref="'listItem' + filteredItems.length">
<a href="#" @click="createNewBranch()">
<div v-show="createTag">
<i class="reference tags icon"></i>
- {{.root.locale.Tr "repo.tag.create_tag" `${ searchTerm }` | Safe}}
+ <span v-html="textCreateTag.replace('%s', searchTerm)"></span>
</div>
<div v-show="!createTag">
{{svg "octicon-git-branch"}}
- {{.root.locale.Tr "repo.branch.create_branch" `${ searchTerm }` | Safe}}
+ <span v-html="textCreateBranch.replace('%s', searchTerm)"></span>
</div>
<div class="text small">
- {{if or .root.IsViewBranch $release}}
- {{.root.locale.Tr "repo.branch.create_from" .root.BranchName}}
- {{else if .root.IsViewTag}}
- {{.root.locale.Tr "repo.branch.create_from" .root.TagName}}
- {{else}}
- {{.root.locale.Tr "repo.branch.create_from" (ShortSha .root.CommitID)}}
- {{end}}
+ <span v-if="isViewBranch || release">${ textCreateBranchFrom.replace('%s', branchName) }</span>
+ <span v-else-if="isViewTag">${ textCreateBranchFrom.replace('%s', tagName) }</span>
+ <span v-else>${ textCreateBranchFrom.replace('%s', commitIdShort) }</span>
</div>
</a>
<form ref="newBranchForm" action="{{.root.RepoLink}}/branches/_new/{{.root.BranchNameSubURL}}" method="post">
- {{.root.CsrfTokenHtml}}
+ <input type="hidden" name="_csrf" :value="csrfToken">
<input type="hidden" name="new_branch_name" v-model="searchTerm">
<input type="hidden" name="create_tag" v-model="createTag">
- {{if $.root.TreePath}}
- <input type="hidden" name="current_path" value="{{.root.TreePath}}">
- {{end}}
+ <input type="hidden" name="current_path" v-model="treePath" v-if="treePath">
</form>
</div>
</div>
diff --git a/templates/repo/commit_page.tmpl b/templates/repo/commit_page.tmpl
index 028fdc7e5..f19a4d422 100644
--- a/templates/repo/commit_page.tmpl
+++ b/templates/repo/commit_page.tmpl
@@ -52,13 +52,13 @@
data-modal-cherry-pick-type="revert"
data-modal-cherry-pick-header="{{$.locale.Tr "repo.commit.revert-header" (ShortSha .CommitID)}}"
data-modal-cherry-pick-content="{{$.locale.Tr "repo.commit.revert-content"}}"
- data-modal-cherry-pick-submit="{{.locale.Tr "repo.commit.revert"}}">{{.locale.Tr "repo.commit.revert"}}</a></div>
+ data-modal-cherry-pick-submit="{{.locale.Tr "repo.commit.revert"}}">{{.locale.Tr "repo.commit.revert"}}</div>
<div class="item cherry-pick-button show-modal"
data-modal="#cherry-pick-modal"
data-modal-cherry-pick-type="cherry-pick"
data-modal-cherry-pick-header="{{$.locale.Tr "repo.commit.cherry-pick-header" (ShortSha .CommitID)}}"
data-modal-cherry-pick-content="{{$.locale.Tr "repo.commit.cherry-pick-content"}}"
- data-modal-cherry-pick-submit="{{.locale.Tr "repo.commit.cherry-pick"}}">{{.locale.Tr "repo.commit.cherry-pick"}}</a></div>
+ data-modal-cherry-pick-submit="{{.locale.Tr "repo.commit.cherry-pick"}}">{{.locale.Tr "repo.commit.cherry-pick"}}</div>
<div class="ui basic modal" id="cherry-pick-modal">
<div class="ui icon header">
<span id="cherry-pick-header"></span>
@@ -66,10 +66,10 @@
<div class="content center">
<p id="cherry-pick-content" class="branch-dropdown"></p>
{{template "repo/branch_dropdown" dict "root" .
- "noTag" "true" "canCreateBranch" "false"
+ "noTag" true "disableCreateBranch" true
"branchForm" "branch-dropdown-form"
"branchURLPrefix" (printf "%s/_cherrypick/%s/" $.RepoLink .CommitID) "branchURLSuffix" ""
- "setAction" "true" "submitForm" "true"}}
+ "setAction" true "submitForm" true}}
<form method="GET" action="{{$.RepoLink}}/_cherrypick/{{.CommitID}}/{{if $.BranchName}}{{PathEscapeSegments $.BranchName}}{{else}}{{PathEscapeSegments $.Repository.DefaultBranch}}{{end}}" id="branch-dropdown-form">
<input type="hidden" name="ref" value="{{if $.BranchName}}{{$.BranchName}}{{else}}{{$.Repository.DefaultBranch}}{{end}}">
<input type="hidden" name="refType" value="branch">
diff --git a/templates/repo/commits_list.tmpl b/templates/repo/commits_list.tmpl
index eaf86ab4e..36333c554 100644
--- a/templates/repo/commits_list.tmpl
+++ b/templates/repo/commits_list.tmpl
@@ -61,7 +61,7 @@
<td class="message">
<span class="message-wrapper">
{{if $.PageIsWiki}}
- <span class="commit-summary {{if gt .ParentCount 1}} grey text{{end}}" title="{{.Summary}}">{{.Summary | RenderEmoji}}</span>
+ <span class="commit-summary {{if gt .ParentCount 1}} grey text{{end}}" title="{{.Summary}}">{{.Summary | RenderEmoji $.Context}}</span>
{{else}}
{{$commitLink:= printf "%s/commit/%s" $commitRepoLink (PathEscape .ID.String)}}
<span class="commit-summary {{if gt .ParentCount 1}} grey text{{end}}" title="{{.Summary}}">{{RenderCommitMessageLinkSubject $.Context .Message $commitRepoLink $commitLink $.Repository.ComposeMetas}}</span>
diff --git a/templates/repo/diff/box.tmpl b/templates/repo/diff/box.tmpl
index 4e6879650..afd471368 100644
--- a/templates/repo/diff/box.tmpl
+++ b/templates/repo/diff/box.tmpl
@@ -79,7 +79,7 @@
{{$isExpandable := or (gt $file.Addition 0) (gt $file.Deletion 0) $file.IsBin}}
<div class="diff-file-box diff-box file-content {{TabSizeClass $.Editorconfig $file.Name}} gt-mt-3" id="diff-{{$file.NameHash}}" data-old-filename="{{$file.OldName}}" data-new-filename="{{$file.Name}}" {{if or ($file.ShouldBeHidden) (not $isExpandable)}}data-folded="true"{{end}}>
<h4 class="diff-file-header sticky-2nd-row ui top attached normal header gt-df gt-ac gt-sb">
- <div class="gt-df gt-ac">
+ <div class="diff-file-name gt-df gt-ac gt-mr-3">
<a role="button" class="fold-file muted gt-mr-2" {{if not $isExpandable}}style="visibility: hidden"{{end}}>
{{if $file.ShouldBeHidden}}
{{svg "octicon-chevron-right" 18}}
@@ -96,7 +96,7 @@
{{template "repo/diff/stats" dict "file" . "root" $}}
{{end}}
</div>
- <span class="file gt-mono"><a class="muted" href="#diff-{{$file.NameHash}}">{{if $file.IsRenamed}}{{$file.OldName}} &rarr; {{end}}{{$file.Name}}</a>{{if .IsLFSFile}} ({{$.locale.Tr "repo.stored_lfs"}}){{end}}</span>
+ <span class="file gt-mono"><a class="muted file-link" title="{{if $file.IsRenamed}}{{$file.OldName}} &rarr; {{end}}{{$file.Name}}" href="#diff-{{$file.NameHash}}">{{if $file.IsRenamed}}{{$file.OldName}} &rarr; {{end}}{{$file.Name}}</a>{{if .IsLFSFile}} ({{$.locale.Tr "repo.stored_lfs"}}){{end}}</span>
{{if $file.IsGenerated}}
<span class="ui label gt-ml-3">{{$.locale.Tr "repo.diff.generated"}}</span>
{{end}}
diff --git a/templates/repo/diff/comment_form.tmpl b/templates/repo/diff/comment_form.tmpl
index 407f84e5c..225e40f7f 100644
--- a/templates/repo/diff/comment_form.tmpl
+++ b/templates/repo/diff/comment_form.tmpl
@@ -1,5 +1,5 @@
{{if and $.root.SignedUserID (not $.Repository.IsArchived)}}
- <form class="ui form {{if $.hidden}}gt-hidden comment-form comment-form-reply{{end}}" action="{{$.root.Issue.Link}}/files/reviews/comments" method="post">
+ <form class="ui form {{if $.hidden}}gt-hidden comment-form{{end}}" action="{{$.root.Issue.Link}}/files/reviews/comments" method="post">
{{$.root.CsrfTokenHtml}}
<input type="hidden" name="origin" value="{{if $.root.PageIsPullFiles}}diff{{else}}timeline{{end}}">
<input type="hidden" name="latest_commit_id" value="{{$.root.AfterCommitID}}"/>
@@ -29,15 +29,10 @@
<input type="hidden" name="reply" value="{{$.reply}}">
{{else}}
{{if $.root.CurrentReview}}
- {{/* if there is only one "Add comment" button, the quick-submit should submit the form with is_review=true even if the "Add comment" button is not really clicked */}}
- <input type="hidden" name="is_review" value="true">
- <button name="is_review" value="true" type="submit"
- class="ui submit green tiny button btn-add-comment">{{$.root.locale.Tr "repo.diff.comment.add_review_comment"}}</button>
+ <button name="pending_review" type="submit" class="ui submit green tiny button btn-add-comment">{{$.root.locale.Tr "repo.diff.comment.add_review_comment"}}</button>
{{else}}
- <button name="is_review" value="true" type="submit"
- class="ui submit green tiny button btn-start-review">{{$.root.locale.Tr "repo.diff.comment.start_review"}}</button>
- <button type="submit"
- class="ui submit tiny basic button btn-add-single">{{$.root.locale.Tr "repo.diff.comment.add_single_comment"}}</button>
+ <button name="pending_review" type="submit" class="ui submit green tiny button btn-start-review">{{$.root.locale.Tr "repo.diff.comment.start_review"}}</button>
+ <button name="single_review" value="true" type="submit" class="ui submit tiny basic button btn-add-single">{{$.root.locale.Tr "repo.diff.comment.add_single_comment"}}</button>
{{end}}
{{end}}
{{if or (not $.HasComments) $.hidden}}
diff --git a/templates/repo/diff/comments.tmpl b/templates/repo/diff/comments.tmpl
index 985ad0655..f28a3c5b5 100644
--- a/templates/repo/diff/comments.tmpl
+++ b/templates/repo/diff/comments.tmpl
@@ -42,8 +42,8 @@
</div>
{{end}}
{{end}}
- {{template "repo/issue/view_content/add_reaction" Dict "ctx" $.root "ActionURL" (Printf "%s/comments/%d/reactions" $.root.RepoLink .ID)}}
- {{template "repo/issue/view_content/context_menu" Dict "ctx" $.root "item" . "delete" true "issue" false "diff" true "IsCommentPoster" (and $.root.IsSigned (eq $.root.SignedUserID .PosterID))}}
+ {{template "repo/issue/view_content/add_reaction" Dict "ctxData" $.root "ActionURL" (Printf "%s/comments/%d/reactions" $.root.RepoLink .ID)}}
+ {{template "repo/issue/view_content/context_menu" Dict "ctxData" $.root "item" . "delete" true "issue" false "diff" true "IsCommentPoster" (and $.root.IsSigned (eq $.root.SignedUserID .PosterID))}}
</div>
</div>
<div class="ui attached segment comment-body">
@@ -60,7 +60,7 @@
{{$reactions := .Reactions.GroupByType}}
{{if $reactions}}
<div class="ui attached segment reactions">
- {{template "repo/issue/view_content/reactions" Dict "ctx" $.root "ActionURL" (Printf "%s/comments/%d/reactions" $.root.RepoLink .ID) "Reactions" $reactions}}
+ {{template "repo/issue/view_content/reactions" Dict "ctxData" $.root "ActionURL" (Printf "%s/comments/%d/reactions" $.root.RepoLink .ID) "Reactions" $reactions}}
</div>
{{end}}
</div>
diff --git a/templates/repo/diff/section_unified.tmpl b/templates/repo/diff/section_unified.tmpl
index 63cd51022..e0ec85f9a 100644
--- a/templates/repo/diff/section_unified.tmpl
+++ b/templates/repo/diff/section_unified.tmpl
@@ -1,9 +1,9 @@
{{$file := .file}}
{{range $j, $section := $file.Sections}}
{{range $k, $line := $section.Lines}}
- {{if or $.root.AfterCommitID (ne .GetType 4)}}
- <tr class="{{DiffLineTypeToStr .GetType}}-code nl-{{$k}} ol-{{$k}}" data-line-type="{{DiffLineTypeToStr .GetType}}">
- {{if eq .GetType 4}}
+ <tr class="{{DiffLineTypeToStr .GetType}}-code nl-{{$k}} ol-{{$k}}" data-line-type="{{DiffLineTypeToStr .GetType}}">
+ {{if eq .GetType 4}}
+ {{if $.root.AfterCommitID}}
<td colspan="2" class="lines-num">
{{if or (eq $line.GetExpandDirection 3) (eq $line.GetExpandDirection 5)}}
<a role="button" class="blob-excerpt" data-url="{{$.root.RepoLink}}/blob_excerpt/{{PathEscape $.root.AfterCommitID}}" data-query="{{$line.GetBlobExcerptQuery}}&style=unified&direction=down&wiki={{$.root.PageIsWiki}}" data-anchor="diff-{{$file.NameHash}}K{{$line.SectionInfo.RightIdx}}">
@@ -22,35 +22,38 @@
{{end}}
</td>
{{else}}
- <td class="lines-num lines-num-old" data-line-num="{{if $line.LeftIdx}}{{$line.LeftIdx}}{{end}}"><span rel="{{if $line.LeftIdx}}diff-{{$file.NameHash}}L{{$line.LeftIdx}}{{end}}"></span></td>
- <td class="lines-num lines-num-new" data-line-num="{{if $line.RightIdx}}{{$line.RightIdx}}{{end}}"><span rel="{{if $line.RightIdx}}diff-{{$file.NameHash}}R{{$line.RightIdx}}{{end}}"></span></td>
+ {{/* for code file preview page or comment diffs on pull comment pages, do not show the expansion arrows */}}
+ <td colspan="2" class="lines-num"></td>
{{end}}
- {{$inlineDiff := $section.GetComputedInlineDiffFor $line $.root.locale -}}
- <td class="lines-escape">{{if $inlineDiff.EscapeStatus.Escaped}}<a href="" class="toggle-escape-button" title="{{template "repo/diff/escape_title" dict "diff" $inlineDiff "locale" $.root.locale}}"></a>{{end}}</td>
- <td class="lines-type-marker"><span class="gt-mono" data-type-marker="{{$line.GetLineTypeMarker}}"></span></td>
- {{if eq .GetType 4}}
- <td class="chroma lines-code blob-hunk">{{/*
- */}}{{template "repo/diff/section_code" dict "diff" $inlineDiff "locale" $.root.locale}}{{/*
- */}}</td>
- {{else}}
- <td class="chroma lines-code{{if (not $line.RightIdx)}} lines-code-old{{end}}">{{/*
- */}}{{if and $.root.SignedUserID $.root.PageIsPullFiles}}{{/*
- */}}<a class="ui primary button add-code-comment add-code-comment-{{if $line.RightIdx}}right{{else}}left{{end}}{{if (not $line.CanComment)}} invisible{{end}}" data-side="{{if $line.RightIdx}}right{{else}}left{{end}}" data-idx="{{if $line.RightIdx}}{{$line.RightIdx}}{{else}}{{$line.LeftIdx}}{{end}}">{{/*
- */}}{{svg "octicon-plus"}}{{/*
- */}}</a>{{/*
- */}}{{end}}{{/*
- */}}{{template "repo/diff/section_code" dict "diff" $inlineDiff "locale" $.root.locale}}{{/*
- */}}</td>
- {{end}}
- </tr>
- {{if gt (len $line.Comments) 0}}
- <tr class="add-comment" data-line-type="{{DiffLineTypeToStr .GetType}}">
- <td colspan="3" class="lines-num"></td>
- <td class="add-comment-left add-comment-right" colspan="5">
- {{template "repo/diff/conversation" mergeinto $.root "comments" $line.Comments}}
- </td>
- </tr>
+ {{else}}
+ <td class="lines-num lines-num-old" data-line-num="{{if $line.LeftIdx}}{{$line.LeftIdx}}{{end}}"><span rel="{{if $line.LeftIdx}}diff-{{$file.NameHash}}L{{$line.LeftIdx}}{{end}}"></span></td>
+ <td class="lines-num lines-num-new" data-line-num="{{if $line.RightIdx}}{{$line.RightIdx}}{{end}}"><span rel="{{if $line.RightIdx}}diff-{{$file.NameHash}}R{{$line.RightIdx}}{{end}}"></span></td>
+ {{end}}
+ {{$inlineDiff := $section.GetComputedInlineDiffFor $line $.root.locale -}}
+ <td class="lines-escape">{{if $inlineDiff.EscapeStatus.Escaped}}<a href="" class="toggle-escape-button" title="{{template "repo/diff/escape_title" dict "diff" $inlineDiff "locale" $.root.locale}}"></a>{{end}}</td>
+ <td class="lines-type-marker"><span class="gt-mono" data-type-marker="{{$line.GetLineTypeMarker}}"></span></td>
+ {{if eq .GetType 4}}
+ <td class="chroma lines-code blob-hunk">{{/*
+ */}}{{template "repo/diff/section_code" dict "diff" $inlineDiff "locale" $.root.locale}}{{/*
+ */}}</td>
+ {{else}}
+ <td class="chroma lines-code{{if (not $line.RightIdx)}} lines-code-old{{end}}">{{/*
+ */}}{{if and $.root.SignedUserID $.root.PageIsPullFiles}}{{/*
+ */}}<a class="ui primary button add-code-comment add-code-comment-{{if $line.RightIdx}}right{{else}}left{{end}}{{if (not $line.CanComment)}} invisible{{end}}" data-side="{{if $line.RightIdx}}right{{else}}left{{end}}" data-idx="{{if $line.RightIdx}}{{$line.RightIdx}}{{else}}{{$line.LeftIdx}}{{end}}">{{/*
+ */}}{{svg "octicon-plus"}}{{/*
+ */}}</a>{{/*
+ */}}{{end}}{{/*
+ */}}{{template "repo/diff/section_code" dict "diff" $inlineDiff "locale" $.root.locale}}{{/*
+ */}}</td>
{{end}}
+ </tr>
+ {{if gt (len $line.Comments) 0}}
+ <tr class="add-comment" data-line-type="{{DiffLineTypeToStr .GetType}}">
+ <td colspan="3" class="lines-num"></td>
+ <td class="add-comment-left add-comment-right" colspan="5">
+ {{template "repo/diff/conversation" mergeinto $.root "comments" $line.Comments}}
+ </td>
+ </tr>
{{end}}
{{end}}
{{end}}
diff --git a/templates/repo/editor/commit_form.tmpl b/templates/repo/editor/commit_form.tmpl
index c6c48c5a8..7ac0ed3df 100644
--- a/templates/repo/editor/commit_form.tmpl
+++ b/templates/repo/editor/commit_form.tmpl
@@ -58,7 +58,7 @@
</label>
</div>
</div>
- <div class="quick-pull-branch-name {{if not (eq .commit_choice "commit-to-new-branch")}}hide{{end}}">
+ <div class="quick-pull-branch-name {{if not (eq .commit_choice "commit-to-new-branch")}}gt-hidden{{end}}">
<div class="new-branch-name-input field {{if .Err_NewBranchName}}error{{end}}">
{{svg "octicon-git-branch"}}
<input type="text" name="new_branch_name" value="{{.new_branch_name}}" class="input-contrast gt-mr-2 js-quick-pull-new-branch-name" placeholder="{{.locale.Tr "repo.editor.new_branch_name_desc"}}" {{if eq .commit_choice "commit-to-new-branch"}}required{{end}} title="{{.locale.Tr "repo.editor.new_branch_name"}}">
diff --git a/templates/repo/editor/diff_preview.tmpl b/templates/repo/editor/diff_preview.tmpl
index e6956648c..e2e922be3 100644
--- a/templates/repo/editor/diff_preview.tmpl
+++ b/templates/repo/editor/diff_preview.tmpl
@@ -1,6 +1,6 @@
<div class="diff-file-box">
<div class="ui attached table segment">
- <div class="file-body file-code code-view code-diff-unified unicode-escaped">
+ <div class="file-body file-code code-diff code-diff-unified unicode-escaped">
<table>
<tbody>
{{template "repo/diff/section_unified" dict "file" .File "root" $}}
diff --git a/templates/repo/home.tmpl b/templates/repo/home.tmpl
index 2a79c51dd..73afbd663 100644
--- a/templates/repo/home.tmpl
+++ b/templates/repo/home.tmpl
@@ -63,7 +63,7 @@
{{end}}
{{template "repo/sub_menu" .}}
<div class="repo-button-row gt-df gt-ac gt-sb gt-fw">
- <div class="gt-df gt-ac">
+ <div class="gt-df gt-ac gt-fw gt-gap-y-3">
{{template "repo/branch_dropdown" dict "root" .}}
{{$n := len .TreeNames}}
{{$l := Subtract $n 1}}
@@ -99,20 +99,16 @@
{{svg "octicon-triangle-down" 14 "dropdown icon"}}
</button>
{{end}}
+ {{if and (eq $n 0) (.Repository.IsTemplate)}}
+ <a role="button" class="ui primary compact button" href="{{AppSubUrl}}/repo/create?template_id={{.Repository.ID}}">
+ {{.locale.Tr "repo.use_template"}}
+ </a>
+ {{end}}
{{if ne $n 0}}
<span class="ui breadcrumb repo-path gt-ml-2"><a class="section" href="{{.RepoLink}}/src/{{.BranchNameSubURL}}" title="{{.Repository.Name}}">{{EllipsisString .Repository.Name 30}}</a>{{range $i, $v := .TreeNames}}<span class="divider">/</span>{{if eq $i $l}}<span class="active section" title="{{$v}}">{{EllipsisString $v 30}}</span>{{else}}{{$p := index $.Paths $i}}<span class="section"><a href="{{$.BranchLink}}/{{PathEscapeSegments $p}}" title="{{$v}}">{{EllipsisString $v 30}}</a></span>{{end}}{{end}}</span>
{{end}}
</div>
<div class="gt-df gt-ac">
- {{if eq $n 0}}
- {{if .Repository.IsTemplate}}
- <div class="ui tiny primary buttons">
- <a href="{{AppSubUrl}}/repo/create?template_id={{.Repository.ID}}" class="ui button">
- {{.locale.Tr "repo.use_template"}}
- </a>
- </div>
- {{end}}
- {{end}}
<!-- Only show clone panel in repository home page -->
{{if eq $n 0}}
<div class="ui action tiny input" id="clone-panel">
diff --git a/templates/repo/issue/labels/label.tmpl b/templates/repo/issue/labels/label.tmpl
index 6e9177aec..01016281a 100644
--- a/templates/repo/issue/labels/label.tmpl
+++ b/templates/repo/issue/labels/label.tmpl
@@ -3,5 +3,5 @@
id="label_{{.label.ID}}"
href="{{.root.RepoLink}}/{{if or .root.IsPull .root.Issue.IsPull}}pulls{{else}}issues{{end}}?labels={{.label.ID}}"{{/* FIXME: use .root.Issue.Link or create .root.Link */}}
>
- {{RenderLabel .label}}
+ {{RenderLabel $.Context .label}}
</a>
diff --git a/templates/repo/issue/labels/label_list.tmpl b/templates/repo/issue/labels/label_list.tmpl
index e8f00fa25..2c8ace8d7 100644
--- a/templates/repo/issue/labels/label_list.tmpl
+++ b/templates/repo/issue/labels/label_list.tmpl
@@ -31,8 +31,8 @@
<li class="item">
<div class="ui grid middle aligned">
<div class="nine wide column">
- {{RenderLabel .}}
- {{if .Description}}<br><small class="desc">{{.Description | RenderEmoji}}</small>{{end}}
+ {{RenderLabel $.Context .}}
+ {{if .Description}}<br><small class="desc">{{.Description | RenderEmoji $.Context}}</small>{{end}}
</div>
<div class="four wide column">
{{if $.PageIsOrgSettingsLabels}}
@@ -70,8 +70,8 @@
<li class="item">
<div class="ui grid middle aligned">
<div class="nine wide column">
- {{RenderLabel .}}
- {{if .Description}}<br><small class="desc">{{.Description | RenderEmoji}}</small>{{end}}
+ {{RenderLabel $.Context .}}
+ {{if .Description}}<br><small class="desc">{{.Description | RenderEmoji $.Context}}</small>{{end}}
</div>
<div class="four wide column">
<a class="ui left open-issues" href="{{$.RepoLink}}/issues?labels={{.ID}}">{{svg "octicon-issue-opened"}} {{$.locale.Tr "repo.issues.label_open_issues" .NumOpenRepoIssues}}</a>
diff --git a/templates/repo/issue/labels/labels_sidebar.tmpl b/templates/repo/issue/labels/labels_sidebar.tmpl
index bd878d6f5..89fe26b75 100644
--- a/templates/repo/issue/labels/labels_sidebar.tmpl
+++ b/templates/repo/issue/labels/labels_sidebar.tmpl
@@ -1,10 +1,10 @@
<div class="ui labels list">
- <span class="no-select item {{if .ctx.HasSelectedLabel}}gt-hidden{{end}}">{{.ctx.locale.Tr "repo.issues.new.no_label"}}</span>
+ <span class="no-select item {{if .root.HasSelectedLabel}}gt-hidden{{end}}">{{.root.locale.Tr "repo.issues.new.no_label"}}</span>
<span class="labels-list">
- {{range .ctx.Labels}}
+ {{range .root.Labels}}
{{template "repo/issue/labels/label" dict "root" $.root "label" .}}
{{end}}
- {{range .ctx.OrgLabels}}
+ {{range .root.OrgLabels}}
{{template "repo/issue/labels/label" dict "root" $.root "label" .}}
{{end}}
</span>
diff --git a/templates/repo/issue/list.tmpl b/templates/repo/issue/list.tmpl
index 23a8a1d0e..ca05264e7 100644
--- a/templates/repo/issue/list.tmpl
+++ b/templates/repo/issue/list.tmpl
@@ -57,7 +57,7 @@
<div class="ui divider"></div>
{{end}}
{{$previousExclusiveScope = $exclusiveScope}}
- <a class="item label-filter-item" href="{{$.Link}}?q={{$.Keyword}}&type={{$.ViewType}}&sort={{$.SortType}}&state={{$.State}}&labels={{.QueryString}}&milestone={{$.MilestoneID}}&project={{$.ProjectID}}&assignee={{$.AssigneeID}}&poster={{$.PosterID}}" data-label-id="{{.ID}}">{{if .IsExcluded}}{{svg "octicon-circle-slash"}}{{else if .IsSelected}}{{if $exclusiveScope}}{{svg "octicon-dot-fill"}}{{else}}{{svg "octicon-check"}}{{end}}{{end}} {{RenderLabel .}}</a>
+ <a class="item label-filter-item" href="{{$.Link}}?q={{$.Keyword}}&type={{$.ViewType}}&sort={{$.SortType}}&state={{$.State}}&labels={{.QueryString}}&milestone={{$.MilestoneID}}&project={{$.ProjectID}}&assignee={{$.AssigneeID}}&poster={{$.PosterID}}" data-label-id="{{.ID}}">{{if .IsExcluded}}{{svg "octicon-circle-slash"}}{{else if .IsSelected}}{{if $exclusiveScope}}{{svg "octicon-dot-fill"}}{{else}}{{svg "octicon-check"}}{{end}}{{end}} {{RenderLabel $.Context .}}</a>
{{end}}
</div>
</div>
@@ -232,7 +232,7 @@
{{end}}
{{$previousExclusiveScope = $exclusiveScope}}
<div class="item issue-action" data-action="toggle" data-element-id="{{.ID}}" data-url="{{$.RepoLink}}/issues/labels">
- {{if contain $.SelLabelIDs .ID}}{{if $exclusiveScope}}{{svg "octicon-dot-fill"}}{{else}}{{svg "octicon-check"}}{{end}}{{end}} {{RenderLabel .}}
+ {{if contain $.SelLabelIDs .ID}}{{if $exclusiveScope}}{{svg "octicon-dot-fill"}}{{else}}{{svg "octicon-check"}}{{end}}{{end}} {{RenderLabel $.Context .}}
</div>
{{end}}
</div>
diff --git a/templates/repo/issue/milestone_issues.tmpl b/templates/repo/issue/milestone_issues.tmpl
index d73fb56fb..2918c4359 100644
--- a/templates/repo/issue/milestone_issues.tmpl
+++ b/templates/repo/issue/milestone_issues.tmpl
@@ -58,7 +58,7 @@
<span class="info">{{.locale.Tr "repo.issues.filter_label_exclude" | Safe}}</span>
<a class="item" href="{{$.Link}}?q={{$.Keyword}}&type={{$.ViewType}}&sort={{$.SortType}}&state={{$.State}}&assignee={{$.AssigneeID}}&poster={{$.PosterID}}">{{.locale.Tr "repo.issues.filter_label_no_select"}}</a>
{{range .Labels}}
- <a class="item label-filter-item" href="{{$.Link}}?q={{$.Keyword}}&type={{$.ViewType}}&sort={{$.SortType}}&state={{$.State}}&labels={{.QueryString}}&assignee={{$.AssigneeID}}&poster={{$.PosterID}}" data-label-id="{{.ID}}">{{if .IsExcluded}}{{svg "octicon-circle-slash"}}{{else if contain $.SelLabelIDs .ID}}{{svg "octicon-check"}}{{end}} {{RenderLabel .}}</a>
+ <a class="item label-filter-item" href="{{$.Link}}?q={{$.Keyword}}&type={{$.ViewType}}&sort={{$.SortType}}&state={{$.State}}&labels={{.QueryString}}&assignee={{$.AssigneeID}}&poster={{$.PosterID}}" data-label-id="{{.ID}}">{{if .IsExcluded}}{{svg "octicon-circle-slash"}}{{else if contain $.SelLabelIDs .ID}}{{svg "octicon-check"}}{{end}} {{RenderLabel $.Context .}}</a>
{{end}}
</div>
</div>
@@ -162,7 +162,7 @@
<div class="menu">
{{range .Labels}}
<div class="item issue-action" data-action="toggle" data-element-id="{{.ID}}" data-url="{{$.RepoLink}}/issues/labels">
- {{if contain $.SelLabelIDs .ID}}{{svg "octicon-check"}}{{end}} {{RenderLabel .}}
+ {{if contain $.SelLabelIDs .ID}}{{svg "octicon-check"}}{{end}} {{RenderLabel $.Context .}}
</div>
{{end}}
</div>
diff --git a/templates/repo/issue/new_form.tmpl b/templates/repo/issue/new_form.tmpl
index 8346d07a1..9fd6c99a5 100644
--- a/templates/repo/issue/new_form.tmpl
+++ b/templates/repo/issue/new_form.tmpl
@@ -60,8 +60,8 @@
<div class="ui divider"></div>
{{end}}
{{$previousExclusiveScope = $exclusiveScope}}
- <a class="{{if .IsChecked}}checked{{end}} item" href="#" data-id="{{.ID}}" data-id-selector="#label_{{.ID}}" data-scope="{{$exclusiveScope}}"><span class="octicon-check {{if not .IsChecked}}invisible{{end}}">{{if $exclusiveScope}}{{svg "octicon-dot-fill"}}{{else}}{{svg "octicon-check"}}{{end}}</span>&nbsp;&nbsp;{{RenderLabel .}}
- {{if .Description}}<br><small class="desc">{{.Description | RenderEmoji}}</small>{{end}}</a>
+ <a class="{{if .IsChecked}}checked{{end}} item" href="#" data-id="{{.ID}}" data-id-selector="#label_{{.ID}}" data-scope="{{$exclusiveScope}}"><span class="octicon-check {{if not .IsChecked}}invisible{{end}}">{{if $exclusiveScope}}{{svg "octicon-dot-fill"}}{{else}}{{svg "octicon-check"}}{{end}}</span>&nbsp;&nbsp;{{RenderLabel $.Context .}}
+ {{if .Description}}<br><small class="desc">{{.Description | RenderEmoji $.Context}}</small>{{end}}</a>
{{end}}
<div class="ui divider"></div>
@@ -72,15 +72,15 @@
<div class="ui divider"></div>
{{end}}
{{$previousExclusiveScope = $exclusiveScope}}
- <a class="{{if .IsChecked}}checked{{end}} item" href="#" data-id="{{.ID}}" data-id-selector="#label_{{.ID}}" data-scope="{{$exclusiveScope}}"><span class="octicon-check {{if not .IsChecked}}invisible{{end}}">{{if $exclusiveScope}}{{svg "octicon-dot-fill"}}{{else}}{{svg "octicon-check"}}{{end}}</span>&nbsp;&nbsp;{{RenderLabel .}}
- {{if .Description}}<br><small class="desc">{{.Description | RenderEmoji}}</small>{{end}}</a>
+ <a class="{{if .IsChecked}}checked{{end}} item" href="#" data-id="{{.ID}}" data-id-selector="#label_{{.ID}}" data-scope="{{$exclusiveScope}}"><span class="octicon-check {{if not .IsChecked}}invisible{{end}}">{{if $exclusiveScope}}{{svg "octicon-dot-fill"}}{{else}}{{svg "octicon-check"}}{{end}}</span>&nbsp;&nbsp;{{RenderLabel $.Context .}}
+ {{if .Description}}<br><small class="desc">{{.Description | RenderEmoji $.Context}}</small>{{end}}</a>
{{end}}
{{else}}
<div class="header" style="text-transform: none;font-size:14px;">{{.locale.Tr "repo.issues.new.no_items"}}</div>
{{end}}
</div>
</div>
- {{template "repo/issue/labels/labels_sidebar" dict "root" $ "ctx" .}}
+ {{template "repo/issue/labels/labels_sidebar" dict "root" $}}
<div class="ui divider"></div>
@@ -176,8 +176,8 @@
{{.locale.Tr "repo.issues.new.open_projects"}}
</div>
{{range .OpenProjects}}
- <a class="item muted sidebar-item-link" data-id="{{.ID}}" data-href="{{$.RepoLink}}/projects/{{.ID}}">
- {{svg "octicon-project" 18 "gt-mr-3"}}
+ <a class="item muted sidebar-item-link" data-id="{{.ID}}" data-href="{{.Link}}">
+ {{if .IsOrganizationProject}}{{svg "octicon-project-symlink" 18 "gt-mr-3"}}{{else}}{{svg "octicon-project" 18 "gt-mr-3"}}{{end}}
{{.Title}}
</a>
{{end}}
@@ -188,8 +188,8 @@
{{.locale.Tr "repo.issues.new.closed_projects"}}
</div>
{{range .ClosedProjects}}
- <a class="item muted sidebar-item-link" data-id="{{.ID}}" data-href="{{$.RepoLink}}/projects/{{.ID}}">
- {{svg "octicon-project" 18 "gt-mr-3"}}
+ <a class="item muted sidebar-item-link" data-id="{{.ID}}" data-href="{{.Link}}">
+ {{if .IsOrganizationProject}}{{svg "octicon-project-symlink" 18 "gt-mr-3"}}{{else}}{{svg "octicon-project" 18 "gt-mr-3"}}{{end}}
{{.Title}}
</a>
{{end}}
@@ -201,8 +201,8 @@
<span class="no-select item {{if .Project}}gt-hidden{{end}}">{{.locale.Tr "repo.issues.new.no_projects"}}</span>
<div class="selected">
{{if .Project}}
- <a class="item muted sidebar-item-link" href="{{.RepoLink}}/projects/{{.Project.ID}}">
- {{svg "octicon-project" 18 "gt-mr-3"}}
+ <a class="item muted sidebar-item-link" href="{{.Project.Link}}">
+ {{if .IsOrganizationProject}}{{svg "octicon-project-symlink" 18 "gt-mr-3"}}{{else}}{{svg "octicon-project" 18 "gt-mr-3"}}{{end}}
{{.Project.Title}}
</a>
{{end}}
diff --git a/templates/repo/issue/view_content.tmpl b/templates/repo/issue/view_content.tmpl
index 08ba50904..6aec6e315 100644
--- a/templates/repo/issue/view_content.tmpl
+++ b/templates/repo/issue/view_content.tmpl
@@ -64,8 +64,8 @@
{{end}}
{{end}}
{{if not $.Repository.IsArchived}}
- {{template "repo/issue/view_content/add_reaction" Dict "ctx" $ "ActionURL" (Printf "%s/issues/%d/reactions" $.RepoLink .Issue.Index)}}
- {{template "repo/issue/view_content/context_menu" Dict "ctx" $ "item" .Issue "delete" false "issue" true "diff" false "IsCommentPoster" $.IsIssuePoster}}
+ {{template "repo/issue/view_content/add_reaction" Dict "ctxData" $ "ActionURL" (Printf "%s/issues/%d/reactions" $.RepoLink .Issue.Index)}}
+ {{template "repo/issue/view_content/context_menu" Dict "ctxData" $ "item" .Issue "delete" false "issue" true "diff" false "IsCommentPoster" $.IsIssuePoster}}
{{end}}
</div>
</div>
@@ -80,13 +80,13 @@
<div id="issue-{{.Issue.ID}}-raw" class="raw-content gt-hidden">{{.Issue.Content}}</div>
<div class="edit-content-zone gt-hidden" data-write="issue-{{.Issue.ID}}-write" data-preview="issue-{{.Issue.ID}}-preview" data-update-url="{{$.RepoLink}}/issues/{{.Issue.Index}}/content" data-context="{{.RepoLink}}" data-attachment-url="{{$.RepoLink}}/issues/{{.Issue.Index}}/attachments" data-view-attachment-url="{{$.RepoLink}}/issues/{{.Issue.Index}}/view-attachments"></div>
{{if .Issue.Attachments}}
- {{template "repo/issue/view_content/attachments" Dict "ctx" $ "Attachments" .Issue.Attachments "Content" .Issue.RenderedContent}}
+ {{template "repo/issue/view_content/attachments" Dict "ctxData" $ "Attachments" .Issue.Attachments "Content" .Issue.RenderedContent}}
{{end}}
</div>
{{$reactions := .Issue.Reactions.GroupByType}}
{{if $reactions}}
<div class="ui attached segment reactions" role="note">
- {{template "repo/issue/view_content/reactions" Dict "ctx" $ "ActionURL" (Printf "%s/issues/%d/reactions" $.RepoLink .Issue.Index) "Reactions" $reactions}}
+ {{template "repo/issue/view_content/reactions" Dict "ctxData" $ "ActionURL" (Printf "%s/issues/%d/reactions" $.RepoLink .Issue.Index) "Reactions" $reactions}}
</div>
{{end}}
</div>
diff --git a/templates/repo/issue/view_content/add_reaction.tmpl b/templates/repo/issue/view_content/add_reaction.tmpl
index bfa8a7e12..692d09e67 100644
--- a/templates/repo/issue/view_content/add_reaction.tmpl
+++ b/templates/repo/issue/view_content/add_reaction.tmpl
@@ -1,10 +1,10 @@
-{{if .ctx.IsSigned}}
+{{if .ctxData.IsSigned}}
<div class="item action ui pointing select-reaction dropdown top right" data-action-url="{{.ActionURL}}">
<a class="add-reaction">
{{svg "octicon-smiley"}}
</a>
<div class="menu">
- <div class="header">{{.ctx.locale.Tr "repo.pick_reaction"}}</div>
+ <div class="header">{{.ctxData.locale.Tr "repo.pick_reaction"}}</div>
<div class="divider"></div>
{{range $value := AllowedReactions}}
<a class="item reaction tooltip" data-content="{{$value}}">{{ReactionToEmoji $value}}</a>
diff --git a/templates/repo/issue/view_content/attachments.tmpl b/templates/repo/issue/view_content/attachments.tmpl
index 86696ec62..3c0190b7d 100644
--- a/templates/repo/issue/view_content/attachments.tmpl
+++ b/templates/repo/issue/view_content/attachments.tmpl
@@ -6,7 +6,7 @@
{{$hasThumbnails := false}}
{{- range .Attachments -}}
<div class="twelve wide column" style="padding: 6px;">
- <a target="_blank" rel="noopener noreferrer" href="{{.DownloadURL}}" title='{{$.ctx.locale.Tr "repo.issues.attachment.open_tab" .Name}}'>
+ <a target="_blank" rel="noopener noreferrer" href="{{.DownloadURL}}" title='{{$.ctxData.locale.Tr "repo.issues.attachment.open_tab" .Name}}'>
{{if FilenameIsImage .Name}}
{{if not (containGeneric $.Content .UUID)}}
{{$hasThumbnails = true}}
@@ -31,7 +31,7 @@
{{if FilenameIsImage .Name}}
{{if not (containGeneric $.Content .UUID)}}
<a target="_blank" rel="noopener noreferrer" href="{{.DownloadURL}}">
- <img src="{{.DownloadURL}}" title='{{$.ctx.locale.Tr "repo.issues.attachment.open_tab" .Name}}'>
+ <img src="{{.DownloadURL}}" title='{{$.ctxData.locale.Tr "repo.issues.attachment.open_tab" .Name}}'>
</a>
{{end}}
{{end}}
diff --git a/templates/repo/issue/view_content/comments.tmpl b/templates/repo/issue/view_content/comments.tmpl
index 94b46bd9f..9f2b7ec2d 100644
--- a/templates/repo/issue/view_content/comments.tmpl
+++ b/templates/repo/issue/view_content/comments.tmpl
@@ -64,8 +64,8 @@
</div>
{{end}}
{{if not $.Repository.IsArchived}}
- {{template "repo/issue/view_content/add_reaction" Dict "ctx" $ "ActionURL" (Printf "%s/comments/%d/reactions" $.RepoLink .ID)}}
- {{template "repo/issue/view_content/context_menu" Dict "ctx" $ "item" . "delete" true "issue" true "diff" false "IsCommentPoster" (and $.IsSigned (eq $.SignedUserID .PosterID))}}
+ {{template "repo/issue/view_content/add_reaction" Dict "ctxData" $ "ActionURL" (Printf "%s/comments/%d/reactions" $.RepoLink .ID)}}
+ {{template "repo/issue/view_content/context_menu" Dict "ctxData" $ "item" . "delete" true "issue" true "diff" false "IsCommentPoster" (and $.IsSigned (eq $.SignedUserID .PosterID))}}
{{end}}
</div>
</div>
@@ -80,13 +80,13 @@
<div id="issuecomment-{{.ID}}-raw" class="raw-content gt-hidden">{{.Content}}</div>
<div class="edit-content-zone gt-hidden" data-write="issuecomment-{{.ID}}-write" data-preview="issuecomment-{{.ID}}-preview" data-update-url="{{$.RepoLink}}/comments/{{.ID}}" data-context="{{$.RepoLink}}" data-attachment-url="{{$.RepoLink}}/comments/{{.ID}}/attachments"></div>
{{if .Attachments}}
- {{template "repo/issue/view_content/attachments" Dict "ctx" $ "Attachments" .Attachments "Content" .RenderedContent}}
+ {{template "repo/issue/view_content/attachments" Dict "ctxData" $ "Attachments" .Attachments "Content" .RenderedContent}}
{{end}}
</div>
{{$reactions := .Reactions.GroupByType}}
{{if $reactions}}
<div class="ui attached segment reactions" role="note">
- {{template "repo/issue/view_content/reactions" Dict "ctx" $ "ActionURL" (Printf "%s/comments/%d/reactions" $.RepoLink .ID) "Reactions" $reactions}}
+ {{template "repo/issue/view_content/reactions" Dict "ctxData" $ "ActionURL" (Printf "%s/comments/%d/reactions" $.RepoLink .ID) "Reactions" $reactions}}
</div>
{{end}}
</div>
@@ -180,11 +180,11 @@
<span class="text grey muted-links">
{{template "shared/user/authorlink" .Poster}}
{{if and .AddedLabels (not .RemovedLabels)}}
- {{$.locale.TrN (len .AddedLabels) "repo.issues.add_label" "repo.issues.add_labels" (RenderLabels .AddedLabels $.RepoLink) $createdStr | Safe}}
+ {{$.locale.TrN (len .AddedLabels) "repo.issues.add_label" "repo.issues.add_labels" (RenderLabels $.Context .AddedLabels $.RepoLink) $createdStr | Safe}}
{{else if and (not .AddedLabels) .RemovedLabels}}
- {{$.locale.TrN (len .RemovedLabels) "repo.issues.remove_label" "repo.issues.remove_labels" (RenderLabels .RemovedLabels $.RepoLink) $createdStr | Safe}}
+ {{$.locale.TrN (len .RemovedLabels) "repo.issues.remove_label" "repo.issues.remove_labels" (RenderLabels $.Context .RemovedLabels $.RepoLink) $createdStr | Safe}}
{{else}}
- {{$.locale.Tr "repo.issues.add_remove_labels" (RenderLabels .AddedLabels $.RepoLink) (RenderLabels .RemovedLabels $.RepoLink) $createdStr | Safe}}
+ {{$.locale.Tr "repo.issues.add_remove_labels" (RenderLabels $.Context .AddedLabels $.RepoLink) (RenderLabels $.Context .RemovedLabels $.RepoLink) $createdStr | Safe}}
{{end}}
</span>
</div>
@@ -231,7 +231,7 @@
{{template "shared/user/avatarlink" Dict "Context" $.Context "user" .Poster}}
<span class="text grey muted-links">
{{template "shared/user/authorlink" .Poster}}
- {{$.locale.Tr "repo.issues.change_title_at" (.OldTitle|RenderEmoji) (.NewTitle|RenderEmoji) $createdStr | Safe}}
+ {{$.locale.Tr "repo.issues.change_title_at" (.OldTitle|RenderEmoji $.Context) (.NewTitle|RenderEmoji $.Context) $createdStr | Safe}}
</span>
</div>
{{else if eq .Type 11}}
@@ -260,7 +260,7 @@
{{template "shared/user/authorlink" .Poster}}
{{$.locale.Tr "repo.issues.stop_tracking_history" $createdStr | Safe}}
</span>
- {{template "repo/issue/view_content/comments_delete_time" Dict "ctx" $ "comment" .}}
+ {{template "repo/issue/view_content/comments_delete_time" Dict "ctxData" $ "comment" .}}
<div class="detail">
{{svg "octicon-clock"}}
<span class="text grey muted-links">{{.Content}}</span>
@@ -274,7 +274,7 @@
{{template "shared/user/authorlink" .Poster}}
{{$.locale.Tr "repo.issues.add_time_history" $createdStr | Safe}}
</span>
- {{template "repo/issue/view_content/comments_delete_time" Dict "ctx" $ "comment" .}}
+ {{template "repo/issue/view_content/comments_delete_time" Dict "ctxData" $ "comment" .}}
<div class="detail">
{{svg "octicon-clock"}}
<span class="text grey muted-links">{{.Content}}</span>
@@ -436,8 +436,8 @@
</div>
{{end}}
{{if not $.Repository.IsArchived}}
- {{template "repo/issue/view_content/add_reaction" Dict "ctx" $ "ActionURL" (Printf "%s/comments/%d/reactions" $.RepoLink .ID)}}
- {{template "repo/issue/view_content/context_menu" Dict "ctx" $ "item" . "delete" false "issue" true "diff" false "IsCommentPoster" (and $.IsSigned (eq $.SignedUserID .PosterID))}}
+ {{template "repo/issue/view_content/add_reaction" Dict "ctxData" $ "ActionURL" (Printf "%s/comments/%d/reactions" $.RepoLink .ID)}}
+ {{template "repo/issue/view_content/context_menu" Dict "ctxData" $ "item" . "delete" false "issue" true "diff" false "IsCommentPoster" (and $.IsSigned (eq $.SignedUserID .PosterID))}}
{{end}}
</div>
</div>
@@ -452,13 +452,13 @@
<div id="issuecomment-{{.ID}}-raw" class="raw-content gt-hidden">{{.Content}}</div>
<div class="edit-content-zone gt-hidden" data-write="issuecomment-{{.ID}}-write" data-preview="issuecomment-{{.ID}}-preview" data-update-url="{{$.RepoLink}}/comments/{{.ID}}" data-context="{{$.RepoLink}}" data-attachment-url="{{$.RepoLink}}/comments/{{.ID}}/attachments"></div>
{{if .Attachments}}
- {{template "repo/issue/view_content/attachments" Dict "ctx" $ "Attachments" .Attachments "Content" .RenderedContent}}
+ {{template "repo/issue/view_content/attachments" Dict "ctxData" $ "Attachments" .Attachments "Content" .RenderedContent}}
{{end}}
</div>
{{$reactions := .Reactions.GroupByType}}
{{if $reactions}}
<div class="ui attached segment reactions">
- {{template "repo/issue/view_content/reactions" Dict "ctx" $ "ActionURL" (Printf "%s/comments/%d/reactions" $.RepoLink .ID) "Reactions" $reactions}}
+ {{template "repo/issue/view_content/reactions" Dict "ctxData" $ "ActionURL" (Printf "%s/comments/%d/reactions" $.RepoLink .ID) "Reactions" $reactions}}
</div>
{{end}}
</div>
@@ -563,8 +563,8 @@
</div>
{{end}}
{{if not $.Repository.IsArchived}}
- {{template "repo/issue/view_content/add_reaction" Dict "ctx" $ "ActionURL" (Printf "%s/comments/%d/reactions" $.RepoLink .ID)}}
- {{template "repo/issue/view_content/context_menu" Dict "ctx" $ "item" . "delete" true "issue" true "diff" true "IsCommentPoster" (and $.IsSigned (eq $.SignedUserID .PosterID))}}
+ {{template "repo/issue/view_content/add_reaction" Dict "ctxData" $ "ActionURL" (Printf "%s/comments/%d/reactions" $.RepoLink .ID)}}
+ {{template "repo/issue/view_content/context_menu" Dict "ctxData" $ "item" . "delete" true "issue" true "diff" true "IsCommentPoster" (and $.IsSigned (eq $.SignedUserID .PosterID))}}
{{end}}
</div>
</div>
@@ -582,7 +582,7 @@
{{$reactions := .Reactions.GroupByType}}
{{if $reactions}}
<div class="ui attached segment reactions">
- {{template "repo/issue/view_content/reactions" Dict "ctx" $ "ActionURL" (Printf "%s/comments/%d/reactions" $.RepoLink .ID) "Reactions" $reactions}}
+ {{template "repo/issue/view_content/reactions" Dict "ctxData" $ "ActionURL" (Printf "%s/comments/%d/reactions" $.RepoLink .ID) "Reactions" $reactions}}
</div>
{{end}}
</div>
@@ -697,6 +697,10 @@
</span>
</div>
{{else if and (eq .Type 29) (or (gt .CommitsNum 0) .IsForcePush)}}
+ <!-- If PR is closed, the comments whose type is CommentTypePullRequestPush(29) after latestCloseCommentID won't be rendered. //-->
+ {{if and .Issue.IsClosed (gt .ID $.LatestCloseCommentID)}}
+ {{continue}}
+ {{end}}
<div class="timeline-item event" id="{{.HashTag}}">
<span class="badge">{{svg "octicon-repo-push"}}</span>
<span class="text grey muted-links">
@@ -707,6 +711,11 @@
{{$.locale.TrN (len .Commits) "repo.issues.push_commit_1" "repo.issues.push_commits_n" (len .Commits) $createdStr | Safe}}
{{end}}
</span>
+ {{if and .IsForcePush $.Issue.PullRequest.BaseRepo.Name}}
+ <span class="ui float right comparebox">
+ <a href="{{$.Issue.PullRequest.BaseRepo.Link}}/compare/{{PathEscape .OldCommit}}..{{PathEscape .NewCommit}}" rel="nofollow" class="ui compare label">{{$.locale.Tr "repo.issues.force_push_compare"}}</a>
+ </span>
+ {{end}}
</div>
{{if not .IsForcePush}}
{{template "repo/commits_list_small" dict "comment" . "root" $}}
diff --git a/templates/repo/issue/view_content/comments_delete_time.tmpl b/templates/repo/issue/view_content/comments_delete_time.tmpl
index e01d2602f..bc08d7fde 100644
--- a/templates/repo/issue/view_content/comments_delete_time.tmpl
+++ b/templates/repo/issue/view_content/comments_delete_time.tmpl
@@ -1,18 +1,18 @@
{{if .comment.Time}} {{/* compatibility with time comments made before v1.14 */}}
{{if (not .comment.Time.Deleted)}}
- {{if (or .ctx.IsAdmin (and .ctx.IsSigned (eq .ctx.SignedUserID .comment.PosterID)))}}
+ {{if (or .ctxData.IsAdmin (and .ctxData.IsSigned (eq .ctxData.SignedUserID .comment.PosterID)))}}
<span class="ui float right">
<div class="ui mini modal issue-delete-time-modal" data-id="{{.comment.Time.ID}}">
- <form method="POST" class="delete-time-form" action="{{.ctx.RepoLink}}/issues/{{.ctx.Issue.Index}}/times/{{.comment.TimeID}}/delete">
- {{.ctx.CsrfTokenHtml}}
+ <form method="POST" class="delete-time-form" action="{{.ctxData.RepoLink}}/issues/{{.ctxData.Issue.Index}}/times/{{.comment.TimeID}}/delete">
+ {{.ctxData.CsrfTokenHtml}}
</form>
- <div class="header">{{.ctx.locale.Tr "repo.issues.del_time"}}</div>
+ <div class="header">{{.ctxData.locale.Tr "repo.issues.del_time"}}</div>
<div class="actions">
- <div class="ui red approve button">{{.ctx.locale.Tr "repo.issues.context.delete"}}</div>
- <div class="ui cancel button">{{.ctx.locale.Tr "repo.issues.add_time_cancel"}}</div>
+ <div class="ui red approve button">{{.ctxData.locale.Tr "repo.issues.context.delete"}}</div>
+ <div class="ui cancel button">{{.ctxData.locale.Tr "repo.issues.add_time_cancel"}}</div>
</div>
</div>
- <button class="ui icon button compact mini issue-delete-time tooltip" data-id="{{.comment.Time.ID}}" data-content="{{.ctx.locale.Tr "repo.issues.del_time"}}" data-position="top right">
+ <button class="ui icon button compact mini issue-delete-time tooltip" data-id="{{.comment.Time.ID}}" data-content="{{.ctxData.locale.Tr "repo.issues.del_time"}}" data-position="top right">
{{svg "octicon-trash"}}
</button>
</span>
diff --git a/templates/repo/issue/view_content/context_menu.tmpl b/templates/repo/issue/view_content/context_menu.tmpl
index b4b9403b2..c073c74ea 100644
--- a/templates/repo/issue/view_content/context_menu.tmpl
+++ b/templates/repo/issue/view_content/context_menu.tmpl
@@ -1,4 +1,4 @@
-{{if .ctx.IsSigned}}
+{{if .ctxData.IsSigned}}
<div class="item action ui pointing custom dropdown top right context-dropdown">
<a class="context-menu">
{{svg "octicon-kebab-horizontal"}}
@@ -6,20 +6,20 @@
<div class="menu">
{{$referenceUrl := ""}}
{{if .issue}}
- {{$referenceUrl = Printf "%s#%s" .ctx.Issue.Link .item.HashTag}}
+ {{$referenceUrl = Printf "%s#%s" .ctxData.Issue.Link .item.HashTag}}
{{else}}
- {{$referenceUrl = Printf "%s/files#%s" .ctx.Issue.Link .item.HashTag}}
+ {{$referenceUrl = Printf "%s/files#%s" .ctxData.Issue.Link .item.HashTag}}
{{end}}
- <a class="item context" data-clipboard-text-type="url" data-clipboard-text="{{AppSubUrl}}{{$referenceUrl}}">{{.ctx.locale.Tr "repo.issues.context.copy_link"}}</a>
- <a class="item context quote-reply {{if .diff}}quote-reply-diff{{end}}" data-target="{{.item.HashTag}}-raw">{{.ctx.locale.Tr "repo.issues.context.quote_reply"}}</a>
- {{if not .ctx.UnitIssuesGlobalDisabled}}
- <a class="item context reference-issue" data-target="{{.item.HashTag}}-raw" data-modal="#reference-issue-modal" data-poster="{{.item.Poster.GetDisplayName}}" data-poster-username="{{.item.Poster.Name}}" data-reference="{{$referenceUrl}}">{{.ctx.locale.Tr "repo.issues.context.reference_issue"}}</a>
+ <div class="item context js-aria-clickable" data-clipboard-text-type="url" data-clipboard-text="{{AppSubUrl}}{{$referenceUrl}}">{{.ctxData.locale.Tr "repo.issues.context.copy_link"}}</div>
+ <div class="item context js-aria-clickable quote-reply {{if .diff}}quote-reply-diff{{end}}" data-target="{{.item.HashTag}}-raw">{{.ctxData.locale.Tr "repo.issues.context.quote_reply"}}</div>
+ {{if not .ctxData.UnitIssuesGlobalDisabled}}
+ <div class="item context js-aria-clickable reference-issue" data-target="{{.item.HashTag}}-raw" data-modal="#reference-issue-modal" data-poster="{{.item.Poster.GetDisplayName}}" data-poster-username="{{.item.Poster.Name}}" data-reference="{{$referenceUrl}}">{{.ctxData.locale.Tr "repo.issues.context.reference_issue"}}</div>
{{end}}
- {{if or .ctx.Permission.IsAdmin .IsCommentPoster .ctx.HasIssuesOrPullsWritePermission}}
+ {{if or .ctxData.Permission.IsAdmin .IsCommentPoster .ctxData.HasIssuesOrPullsWritePermission}}
<div class="divider"></div>
- <a class="item context edit-content">{{.ctx.locale.Tr "repo.issues.context.edit"}}</a>
+ <div class="item context js-aria-clickable edit-content">{{.ctxData.locale.Tr "repo.issues.context.edit"}}</div>
{{if .delete}}
- <a class="item context delete-comment" data-comment-id={{.item.HashTag}} data-url="{{.ctx.RepoLink}}/comments/{{.item.ID}}/delete" data-locale="{{.ctx.locale.Tr "repo.issues.delete_comment_confirm"}}">{{.ctx.locale.Tr "repo.issues.context.delete"}}</a>
+ <div class="item context js-aria-clickable delete-comment" data-comment-id={{.item.HashTag}} data-url="{{.ctxData.RepoLink}}/comments/{{.item.ID}}/delete" data-locale="{{.ctxData.locale.Tr "repo.issues.delete_comment_confirm"}}">{{.ctxData.locale.Tr "repo.issues.context.delete"}}</div>
{{end}}
{{end}}
</div>
diff --git a/templates/repo/issue/view_content/reactions.tmpl b/templates/repo/issue/view_content/reactions.tmpl
index c0a925d18..8e7eabd4b 100644
--- a/templates/repo/issue/view_content/reactions.tmpl
+++ b/templates/repo/issue/view_content/reactions.tmpl
@@ -1,9 +1,9 @@
{{range $key, $value := .Reactions}}
- <a class="ui label basic{{if $value.HasUser $.ctx.SignedUserID}} primary{{end}}{{if not $.ctx.IsSigned}} disabled{{end}}" data-title="{{$value.GetFirstUsers}}{{if gt ($value.GetMoreUserCount) 0}} {{$.ctx.locale.Tr "repo.reactions_more" $value.GetMoreUserCount}}{{end}}" data-content="{{$key}}" data-action-url="{{$.ActionURL}}">
+ <a class="ui label basic{{if $value.HasUser $.ctxData.SignedUserID}} primary{{end}}{{if not $.ctxData.IsSigned}} disabled{{end}}" data-title="{{$value.GetFirstUsers}}{{if gt ($value.GetMoreUserCount) 0}} {{$.ctxData.locale.Tr "repo.reactions_more" $value.GetMoreUserCount}}{{end}}" data-content="{{$key}}" data-action-url="{{$.ActionURL}}">
<span class="reaction">{{ReactionToEmoji $key}}</span>
<span class="reaction-count">{{len $value}}</span>
</a>
{{end}}
{{if AllowedReactions}}
- {{template "repo/issue/view_content/add_reaction" Dict "ctx" $.ctx "ActionURL" .ActionURL}}
+ {{template "repo/issue/view_content/add_reaction" Dict "ctxData" $.ctxData "ActionURL" .ActionURL}}
{{end}}
diff --git a/templates/repo/issue/view_content/sidebar.tmpl b/templates/repo/issue/view_content/sidebar.tmpl
index d9c506243..29bfac7c2 100644
--- a/templates/repo/issue/view_content/sidebar.tmpl
+++ b/templates/repo/issue/view_content/sidebar.tmpl
@@ -130,8 +130,8 @@
<div class="ui divider"></div>
{{end}}
{{$previousExclusiveScope = $exclusiveScope}}
- <a class="{{if .IsChecked}}checked{{end}} item" href="#" data-id="{{.ID}}" data-id-selector="#label_{{.ID}}" data-scope="{{$exclusiveScope}}"><span class="octicon-check {{if not .IsChecked}}invisible{{end}}">{{if $exclusiveScope}}{{svg "octicon-dot-fill"}}{{else}}{{svg "octicon-check"}}{{end}}</span>&nbsp;&nbsp;{{RenderLabel .}}
- {{if .Description}}<br><small class="desc">{{.Description | RenderEmoji}}</small>{{end}}</a>
+ <a class="{{if .IsChecked}}checked{{end}} item" href="#" data-id="{{.ID}}" data-id-selector="#label_{{.ID}}" data-scope="{{$exclusiveScope}}"><span class="octicon-check {{if not .IsChecked}}invisible{{end}}">{{if $exclusiveScope}}{{svg "octicon-dot-fill"}}{{else}}{{svg "octicon-check"}}{{end}}</span>&nbsp;&nbsp;{{RenderLabel $.Context .}}
+ {{if .Description}}<br><small class="desc">{{.Description | RenderEmoji $.Context}}</small>{{end}}</a>
{{end}}
<div class="ui divider"></div>
{{$previousExclusiveScope := "_no_scope"}}
@@ -141,15 +141,15 @@
<div class="ui divider"></div>
{{end}}
{{$previousExclusiveScope = $exclusiveScope}}
- <a class="{{if .IsChecked}}checked{{end}} item" href="#" data-id="{{.ID}}" data-id-selector="#label_{{.ID}}" data-scope="{{$exclusiveScope}}"><span class="octicon-check {{if not .IsChecked}}invisible{{end}}">{{if $exclusiveScope}}{{svg "octicon-dot-fill"}}{{else}}{{svg "octicon-check"}}{{end}}</span>&nbsp;&nbsp;{{RenderLabel .}}
- {{if .Description}}<br><small class="desc">{{.Description | RenderEmoji}}</small>{{end}}</a>
+ <a class="{{if .IsChecked}}checked{{end}} item" href="#" data-id="{{.ID}}" data-id-selector="#label_{{.ID}}" data-scope="{{$exclusiveScope}}"><span class="octicon-check {{if not .IsChecked}}invisible{{end}}">{{if $exclusiveScope}}{{svg "octicon-dot-fill"}}{{else}}{{svg "octicon-check"}}{{end}}</span>&nbsp;&nbsp;{{RenderLabel $.Context .}}
+ {{if .Description}}<br><small class="desc">{{.Description | RenderEmoji $.Context}}</small>{{end}}</a>
{{end}}
{{else}}
<div class="header" style="text-transform: none;font-size:14px;">{{.locale.Tr "repo.issues.new.no_items"}}</div>
{{end}}
</div>
</div>
- {{template "repo/issue/labels/labels_sidebar" dict "root" $ "ctx" .}}
+ {{template "repo/issue/labels/labels_sidebar" dict "root" $}}
<div class="ui divider"></div>
@@ -487,8 +487,8 @@
{{range .BlockingDependencies}}
<div class="item dependency{{if .Issue.IsClosed}} is-closed{{end}} gt-df gt-ac gt-sb">
<div class="item-left gt-df gt-jc gt-fc gt-f1">
- <a class="title tooltip" href="{{.Issue.Link}}" data-content="#{{.Issue.Index}} {{.Issue.Title | RenderEmoji}}">
- #{{.Issue.Index}} {{.Issue.Title | RenderEmoji}}
+ <a class="title tooltip" href="{{.Issue.Link}}" data-content="#{{.Issue.Index}} {{.Issue.Title | RenderEmoji $.Context}}">
+ #{{.Issue.Index}} {{.Issue.Title | RenderEmoji $.Context}}
</a>
<div class="text small">
{{.Repository.OwnerName}}/{{.Repository.Name}}
@@ -514,8 +514,8 @@
{{range .BlockedByDependencies}}
<div class="item dependency{{if .Issue.IsClosed}} is-closed{{end}} gt-df gt-ac gt-sb">
<div class="item-left gt-df gt-jc gt-fc gt-f1">
- <a class="title tooltip" href="{{.Issue.Link}}" data-content="#{{.Issue.Index}} {{.Issue.Title | RenderEmoji}}">
- #{{.Issue.Index}} {{.Issue.Title | RenderEmoji}}
+ <a class="title tooltip" href="{{.Issue.Link}}" data-content="#{{.Issue.Index}} {{.Issue.Title | RenderEmoji $.Context}}">
+ #{{.Issue.Index}} {{.Issue.Title | RenderEmoji $.Context}}
</a>
<div class="text small">
{{.Repository.OwnerName}}/{{.Repository.Name}}
diff --git a/templates/repo/projects/list.tmpl b/templates/repo/projects/list.tmpl
index fc4770e5d..929a1b4c6 100644
--- a/templates/repo/projects/list.tmpl
+++ b/templates/repo/projects/list.tmpl
@@ -40,7 +40,7 @@
<div class="milestone list">
{{range .Projects}}
<li class="item">
- {{svg "octicon-project"}} <a href="{{$.RepoLink}}/projects/{{.ID}}">{{.Title}}</a>
+ {{svg "octicon-project"}} <a href="{{.Link}}">{{.Title}}</a>
<div class="meta">
{{$closedDate:= TimeSinceUnix .ClosedDateUnix $.locale}}
{{if .IsClosed}}
diff --git a/templates/repo/projects/new.tmpl b/templates/repo/projects/new.tmpl
index b65601c15..b53a47dc5 100644
--- a/templates/repo/projects/new.tmpl
+++ b/templates/repo/projects/new.tmpl
@@ -24,6 +24,7 @@
<form class="ui form grid" action="{{.Link}}" method="post">
{{.CsrfTokenHtml}}
<div class="eleven wide column">
+ <input type="hidden" id="redirect" name="redirect" value="{{.redirect}}">
<div class="field {{if .Err_Title}}error{{end}}">
<label>{{.locale.Tr "repo.projects.title"}}</label>
<input name="title" placeholder="{{.locale.Tr "repo.projects.title"}}" value="{{.title}}" autofocus required>
diff --git a/templates/repo/projects/view.tmpl b/templates/repo/projects/view.tmpl
index 1450fdac1..bef9cb9bf 100644
--- a/templates/repo/projects/view.tmpl
+++ b/templates/repo/projects/view.tmpl
@@ -50,7 +50,7 @@
{{if and (or $.CanWriteIssues $.CanWritePulls) (not $.Repository.IsArchived)}}
<div class="column right aligned">
<div class="ui compact right small menu">
- <a class="item" href="{{$.RepoLink}}/projects/{{.Project.ID}}/edit" data-id={{$.Project.ID}} data-title={{$.Project.Title}}>
+ <a class="item" href="{{$.RepoLink}}/projects/{{.Project.ID}}/edit?redirect=project" data-id={{$.Project.ID}} data-title={{$.Project.Title}}>
{{svg "octicon-pencil"}}
<span class="gt-mx-3">{{$.locale.Tr "repo.issues.label_edit"}}</span>
</a>
@@ -245,7 +245,7 @@
{{if or .Labels .Assignees}}
<div class="extra content labels-list gt-p-0 gt-pt-2">
{{range .Labels}}
- <a target="_blank" href="{{$.RepoLink}}/issues?labels={{.ID}}">{{RenderLabel .}}</a>
+ <a target="_blank" href="{{$.RepoLink}}/issues?labels={{.ID}}">{{RenderLabel $.Context .}}</a>
{{end}}
<div class="right floated">
{{range .Assignees}}
diff --git a/templates/repo/release/new.tmpl b/templates/repo/release/new.tmpl
index 37d7ca032..d7c580fed 100644
--- a/templates/repo/release/new.tmpl
+++ b/templates/repo/release/new.tmpl
@@ -20,22 +20,27 @@
<b>{{.tag_name}}</b><span class="at">@</span><strong>{{.tag_target}}</strong>
{{else}}
<input id="tag-name" name="tag_name" value="{{.tag_name}}" placeholder="{{.locale.Tr "repo.release.tag_name"}}" autofocus required maxlength="255">
- <span class="at">@</span>
- <div class="ui selection dropdown">
- <input type="hidden" name="tag_target" value="{{.tag_target}}"/>
- {{svg "octicon-git-branch"}}
- <div class="text">
- {{.locale.Tr "repo.release.target"}} :
- <strong id="repo-branch-current">{{.Repository.DefaultBranch}}</strong>
- </div>
- {{svg "octicon-triangle-down" 14 "dropdown icon"}}
- <div class="menu">
- {{range .Branches}}
- <div class="item" data-value="{{.}}">{{.}}</div>
- {{end}}
+ <input id="tag-name-editor" type="hidden" data-existing-tags={{Json .Tags}} data-tag-helper={{.locale.Tr "repo.release.tag_helper"}} data-tag-helper-new={{.locale.Tr "repo.release.tag_helper_new"}} data-tag-helper-existing={{.locale.Tr "repo.release.tag_helper_existing"}} />
+ <div id="tag-target-selector" class="gt-dib">
+ <span class="at">@</span>
+ <div class="ui selection dropdown">
+ <input type="hidden" name="tag_target" value="{{.tag_target}}"/>
+ {{svg "octicon-git-branch"}}
+ <div class="text">
+ {{.locale.Tr "repo.release.target"}} :
+ <strong id="repo-branch-current">{{.Repository.DefaultBranch}}</strong>
+ </div>
+ {{svg "octicon-triangle-down" 14 "dropdown icon"}}
+ <div class="menu">
+ {{range .Branches}}
+ <div class="item" data-value="{{.}}">{{.}}</div>
+ {{end}}
+ </div>
</div>
</div>
- <span class="help">{{.locale.Tr "repo.release.tag_helper"}}</span>
+ <div>
+ <span id="tag-helper" class="help gt-mt-2">{{.locale.Tr "repo.release.tag_helper"}}</span>
+ </div>
{{end}}
</div>
</div>
diff --git a/templates/repo/settings/lfs_file_find.tmpl b/templates/repo/settings/lfs_file_find.tmpl
index d5983ca1c..81cb64983 100644
--- a/templates/repo/settings/lfs_file_find.tmpl
+++ b/templates/repo/settings/lfs_file_find.tmpl
@@ -19,7 +19,7 @@
<td class="message">
<span class="truncate">
<a href="{{$.RepoLink}}/commit/{{.SHA}}" title="{{.Summary | RenderEmojiPlain}}">
- {{.Summary | RenderEmoji}}
+ {{.Summary | RenderEmoji $.Context}}
</a>
</span>
</td>
diff --git a/templates/repo/settings/webhook/history.tmpl b/templates/repo/settings/webhook/history.tmpl
index bf7fe05de..f76cdb147 100644
--- a/templates/repo/settings/webhook/history.tmpl
+++ b/templates/repo/settings/webhook/history.tmpl
@@ -40,7 +40,7 @@
<span class="ui label">N/A</span>
{{end}}
</a>
- {{if or $.Permission.IsAdmin $.IsOrganizationOwner $.PageIsAdmin}}
+ {{if or $.Permission.IsAdmin $.IsOrganizationOwner $.PageIsAdmin $.PageIsUserSettings}}
<div class="right menu">
<form class="item" action="{{$.Link}}/replay/{{.UUID}}" method="post">
{{$.CsrfTokenHtml}}
diff --git a/templates/shared/issuelist.tmpl b/templates/shared/issuelist.tmpl
index a43047c79..16bb3c1ec 100644
--- a/templates/shared/issuelist.tmpl
+++ b/templates/shared/issuelist.tmpl
@@ -34,7 +34,7 @@
</div>
<div class="issue-item-main gt-f1 gt-fc gt-df">
<div class="issue-item-top-row">
- <a class="title gt-tdn issue-title" href="{{if .Link}}{{.Link}}{{else}}{{$.Link}}/{{.Index}}{{end}}">{{RenderEmoji .Title | RenderCodeBlock}}</a>
+ <a class="title gt-tdn issue-title" href="{{if .Link}}{{.Link}}{{else}}{{$.Link}}/{{.Index}}{{end}}">{{RenderEmoji $.Context .Title | RenderCodeBlock}}</a>
{{if .IsPull}}
{{if (index $.CommitStatuses .PullRequest.ID)}}
{{template "repo/commit_statuses" dict "Status" (index $.CommitLastStatus .PullRequest.ID) "Statuses" (index $.CommitStatuses .PullRequest.ID) "root" $}}
@@ -42,7 +42,7 @@
{{end}}
<span class="labels-list gt-ml-2">
{{range .Labels}}
- <a href="{{$.Link}}?q={{$.Keyword}}&type={{$.ViewType}}&state={{$.State}}&labels={{.ID}}{{if ne $.listType "milestone"}}&milestone={{$.MilestoneID}}{{end}}&assignee={{$.AssigneeID}}&poster={{$.PosterID}}">{{RenderLabel .}}</a>
+ <a href="{{$.Link}}?q={{$.Keyword}}&type={{$.ViewType}}&state={{$.State}}&labels={{.ID}}{{if ne $.listType "milestone"}}&milestone={{$.MilestoneID}}{{end}}&assignee={{$.AssigneeID}}&poster={{$.PosterID}}">{{RenderLabel $.Context .}}</a>
{{end}}
</span>
</div>
@@ -87,8 +87,8 @@
</a>
{{end}}
{{if .Project}}
- <a class="project" {{if $.RepoLink}}href="{{$.RepoLink}}/projects/{{.Project.ID}}"{{else}}href="{{.Repo.Link}}/projects/{{.Project.ID}}"{{end}}>
- {{svg "octicon-project" 14 "gt-mr-2"}}{{.Project.Title}}
+ <a class="project" href="{{.Project.Link}}">
+ {{if .Project.IsOrganizationProject}}{{svg "octicon-project-symlink" 14 "gt-mr-2"}}{{else}}{{svg "octicon-project" 14 "gt-mr-2"}}{{end}}{{.Project.Title}}
</a>
{{end}}
{{if .Ref}}
diff --git a/templates/swagger/v1_json.tmpl b/templates/swagger/v1_json.tmpl
index d1c0a6f18..a1f143ad5 100644
--- a/templates/swagger/v1_json.tmpl
+++ b/templates/swagger/v1_json.tmpl
@@ -13313,6 +13313,152 @@
}
}
},
+ "/user/hooks": {
+ "get": {
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "user"
+ ],
+ "summary": "List the authenticated user's webhooks",
+ "operationId": "userListHooks",
+ "parameters": [
+ {
+ "type": "integer",
+ "description": "page number of results to return (1-based)",
+ "name": "page",
+ "in": "query"
+ },
+ {
+ "type": "integer",
+ "description": "page size of results",
+ "name": "limit",
+ "in": "query"
+ }
+ ],
+ "responses": {
+ "200": {
+ "$ref": "#/responses/HookList"
+ }
+ }
+ },
+ "post": {
+ "consumes": [
+ "application/json"
+ ],
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "user"
+ ],
+ "summary": "Create a hook",
+ "operationId": "userCreateHook",
+ "parameters": [
+ {
+ "name": "body",
+ "in": "body",
+ "required": true,
+ "schema": {
+ "$ref": "#/definitions/CreateHookOption"
+ }
+ }
+ ],
+ "responses": {
+ "201": {
+ "$ref": "#/responses/Hook"
+ }
+ }
+ }
+ },
+ "/user/hooks/{id}": {
+ "get": {
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "user"
+ ],
+ "summary": "Get a hook",
+ "operationId": "userGetHook",
+ "parameters": [
+ {
+ "type": "integer",
+ "format": "int64",
+ "description": "id of the hook to get",
+ "name": "id",
+ "in": "path",
+ "required": true
+ }
+ ],
+ "responses": {
+ "200": {
+ "$ref": "#/responses/Hook"
+ }
+ }
+ },
+ "delete": {
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "user"
+ ],
+ "summary": "Delete a hook",
+ "operationId": "userDeleteHook",
+ "parameters": [
+ {
+ "type": "integer",
+ "format": "int64",
+ "description": "id of the hook to delete",
+ "name": "id",
+ "in": "path",
+ "required": true
+ }
+ ],
+ "responses": {
+ "204": {
+ "$ref": "#/responses/empty"
+ }
+ }
+ },
+ "patch": {
+ "consumes": [
+ "application/json"
+ ],
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "user"
+ ],
+ "summary": "Update a hook",
+ "operationId": "userEditHook",
+ "parameters": [
+ {
+ "type": "integer",
+ "format": "int64",
+ "description": "id of the hook to update",
+ "name": "id",
+ "in": "path",
+ "required": true
+ },
+ {
+ "name": "body",
+ "in": "body",
+ "schema": {
+ "$ref": "#/definitions/EditHookOption"
+ }
+ }
+ ],
+ "responses": {
+ "200": {
+ "$ref": "#/responses/Hook"
+ }
+ }
+ }
+ },
"/user/keys": {
"get": {
"produces": [
diff --git a/templates/user/dashboard/feeds.tmpl b/templates/user/dashboard/feeds.tmpl
index 75a76db57..64daf4b2e 100644
--- a/templates/user/dashboard/feeds.tmpl
+++ b/templates/user/dashboard/feeds.tmpl
@@ -72,7 +72,7 @@
{{$index := index .GetIssueInfos 0}}
{{$.locale.Tr "action.comment_pull" ((printf "%s/pulls/%s" .GetRepoLink $index) |Escape) $index (.ShortRepoPath|Escape) | Str2html}}
{{else if eq .GetOpType 24}}
- {{$linkText := .Content | RenderEmoji}}
+ {{$linkText := .Content | RenderEmoji $.Context}}
{{$.locale.Tr "action.publish_release" (.GetRepoLink|Escape) ((printf "%s/releases/tag/%s" .GetRepoLink .GetTag)|Escape) (.ShortRepoPath|Escape) $linkText | Str2html}}
{{else if eq .GetOpType 25}}
{{$index := index .GetIssueInfos 0}}
@@ -99,20 +99,20 @@
</ul>
</div>
{{else if eq .GetOpType 6}}
- <span class="text truncate issue title">{{index .GetIssueInfos 1 | RenderEmoji | RenderCodeBlock}}</span>
+ <span class="text truncate issue title">{{index .GetIssueInfos 1 | RenderEmoji $.Context | RenderCodeBlock}}</span>
{{else if eq .GetOpType 7}}
- <span class="text truncate issue title">{{index .GetIssueInfos 1 | RenderEmoji | RenderCodeBlock}}</span>
+ <span class="text truncate issue title">{{index .GetIssueInfos 1 | RenderEmoji $.Context | RenderCodeBlock}}</span>
{{else if or (eq .GetOpType 10) (eq .GetOpType 21) (eq .GetOpType 22) (eq .GetOpType 23)}}
- <a href="{{.GetCommentLink}}" class="text truncate issue title">{{.GetIssueTitle | RenderEmoji | RenderCodeBlock}}</a>
+ <a href="{{.GetCommentLink}}" class="text truncate issue title">{{.GetIssueTitle | RenderEmoji $.Context | RenderCodeBlock}}</a>
{{$comment := index .GetIssueInfos 1}}
- {{if gt (len $comment) 0}}<p class="text light grey">{{$comment | RenderEmoji}}</p>{{end}}
+ {{if gt (len $comment) 0}}<p class="text light grey">{{$comment | RenderEmoji $.Context}}</p>{{end}}
{{else if eq .GetOpType 11}}
<p class="text light grey">{{index .GetIssueInfos 1}}</p>
{{else if or (eq .GetOpType 12) (eq .GetOpType 13) (eq .GetOpType 14) (eq .GetOpType 15)}}
- <span class="text truncate issue title">{{.GetIssueTitle | RenderEmoji | RenderCodeBlock}}</span>
+ <span class="text truncate issue title">{{.GetIssueTitle | RenderEmoji $.Context | RenderCodeBlock}}</span>
{{else if eq .GetOpType 25}}
<p class="text light grey">{{$.locale.Tr "action.review_dismissed_reason"}}</p>
- <p class="text light grey">{{index .GetIssueInfos 2 | RenderEmoji}}</p>
+ <p class="text light grey">{{index .GetIssueInfos 2 | RenderEmoji $.Context}}</p>
{{end}}
<p class="text italic light grey">{{TimeSince .GetCreate $.locale}}</p>
</div>
diff --git a/templates/user/dashboard/navbar.tmpl b/templates/user/dashboard/navbar.tmpl
index 719d5b06b..ab6f1bc58 100644
--- a/templates/user/dashboard/navbar.tmpl
+++ b/templates/user/dashboard/navbar.tmpl
@@ -5,12 +5,10 @@
<span class="text truncated-item-container">
{{avatar $.Context .ContextUser}}
<span class="truncated-item-name">{{.ContextUser.ShortName 40}}</span>
- {{if .ContextUser.IsOrganization}}
- <span class="org-visibility">
- {{if .ContextUser.Visibility.IsLimited}}<div class="ui basic tiny horizontal label">{{.locale.Tr "org.settings.visibility.limited_shortname"}}</div>{{end}}
- {{if .ContextUser.Visibility.IsPrivate}}<div class="ui basic tiny horizontal label">{{.locale.Tr "org.settings.visibility.private_shortname"}}</div>{{end}}
- </span>
- {{end}}
+ <span class="org-visibility">
+ {{if .ContextUser.Visibility.IsLimited}}<div class="ui basic tiny horizontal label">{{.locale.Tr "org.settings.visibility.limited_shortname"}}</div>{{end}}
+ {{if .ContextUser.Visibility.IsPrivate}}<div class="ui basic tiny horizontal label">{{.locale.Tr "org.settings.visibility.private_shortname"}}</div>{{end}}
+ </span>
{{svg "octicon-triangle-down" 14 "dropdown icon"}}
</span>
<div class="context user overflow menu" tabindex="-1">
@@ -21,6 +19,10 @@
<a class="{{if eq .ContextUser.ID .SignedUser.ID}}active selected{{end}} item truncated-item-container" href="{{AppSubUrl}}/{{if .PageIsIssues}}issues{{else if .PageIsPulls}}pulls{{else if .PageIsMilestonesDashboard}}milestones{{end}}">
{{avatar $.Context .SignedUser}}
<span class="truncated-item-name">{{.SignedUser.ShortName 40}}</span>
+ <span class="org-visibility">
+ {{if .ContextUser.Visibility.IsLimited}}<div class="ui basic tiny horizontal label">{{$.locale.Tr "org.settings.visibility.limited_shortname"}}</div>{{end}}
+ {{if .ContextUser.Visibility.IsPrivate}}<div class="ui basic tiny horizontal label">{{$.locale.Tr "org.settings.visibility.private_shortname"}}</div>{{end}}
+ </span>
</a>
{{range .Orgs}}
<a class="{{if eq $.ContextUser.ID .ID}}active selected{{end}} item truncated-item-container" title="{{.Name}}" href="{{.OrganisationLink}}/{{if $.PageIsIssues}}issues{{else if $.PageIsPulls}}pulls{{else if $.PageIsMilestonesDashboard}}milestones{{else}}dashboard{{end}}">
diff --git a/templates/user/dashboard/repolist.tmpl b/templates/user/dashboard/repolist.tmpl
index 22af578fc..97234176b 100644
--- a/templates/user/dashboard/repolist.tmpl
+++ b/templates/user/dashboard/repolist.tmpl
@@ -46,56 +46,38 @@
<div class="ui dropdown icon button" title="{{.locale.Tr "home.filter"}}">
<i class="icon gt-df gt-ac gt-jc gt-m-0">{{svg "octicon-filter" 16}}</i>
<div class="menu">
- <div class="item">
- <a @click="toggleArchivedFilter()">
- <div class="ui checkbox" id="archivedFilterCheckbox" title="{{.locale.Tr "home.show_both_archived_unarchived"}}" v-if="archivedFilter === 'both'">
- <input type="checkbox">
- <label>
- {{svg "octicon-archive" 16 "gt-mr-2"}}
- {{.locale.Tr "home.show_archived"}}
- </label>
- </div>
- <div class="ui checkbox" id="archivedFilterCheckbox" title="{{.locale.Tr "home.show_only_unarchived"}}" v-if="archivedFilter === 'unarchived'">
- <input type="checkbox">
- <label>
- {{svg "octicon-archive" 16 "gt-mr-2"}}
- {{.locale.Tr "home.show_archived"}}
- </label>
- </div>
- <div class="ui checkbox" id="archivedFilterCheckbox" title="{{.locale.Tr "home.show_only_archived"}}" v-if="archivedFilter === 'archived'">
- <input type="checkbox">
- <label>
- {{svg "octicon-archive" 16 "gt-mr-2"}}
- {{.locale.Tr "home.show_archived"}}
- </label>
- </div>
- </a>
- </div>
- <div class="item">
- <a @click="togglePrivateFilter()">
- <div class="ui checkbox" id="privateFilterCheckbox" title="{{.locale.Tr "home.show_both_private_public"}}" v-if="privateFilter === 'both'">
- <input type="checkbox">
- <label>
- {{svg "octicon-lock" 16 "gt-mr-2"}}
- {{.locale.Tr "home.show_private"}}
- </label>
- </div>
- <div class="ui checkbox" id="privateFilterCheckbox" title="{{.locale.Tr "home.show_only_public"}}" v-if="privateFilter === 'public'">
- <input type="checkbox">
- <label>
- {{svg "octicon-lock" 16 "gt-mr-2"}}
- {{.locale.Tr "home.show_private"}}
- </label>
- </div>
- <div class="ui checkbox" id="privateFilterCheckbox" title="{{.locale.Tr "home.show_only_private"}}" v-if="privateFilter === 'private'">
- <input type="checkbox">
- <label>
- {{svg "octicon-lock" 16 "gt-mr-2"}}
- {{.locale.Tr "home.show_private"}}
- </label>
- </div>
- </a>
- </div>
+ <a class="item" @click="toggleArchivedFilter()">
+ <div class="ui checkbox"
+ ref="checkboxArchivedFilter"
+ data-title-both="{{.locale.Tr "home.show_both_archived_unarchived"}}"
+ data-title-unarchived="{{.locale.Tr "home.show_only_unarchived"}}"
+ data-title-archived="{{.locale.Tr "home.show_only_archived"}}"
+ :title="checkboxArchivedFilterTitle"
+ >
+ <!--the "hidden" is necessary to make the checkbox work without Fomantic UI js,
+ otherwise if the "input" handles click event for intermediate status, it breaks the internal state-->
+ <input type="checkbox" class="hidden" v-bind.prop="checkboxArchivedFilterProps">
+ <label>
+ {{svg "octicon-archive" 16 "gt-mr-2"}}
+ {{.locale.Tr "home.show_archived"}}
+ </label>
+ </div>
+ </a>
+ <a class="item" @click="togglePrivateFilter()">
+ <div class="ui checkbox"
+ ref="checkboxPrivateFilter"
+ data-title-both="{{.locale.Tr "home.show_both_private_public"}}"
+ data-title-public="{{.locale.Tr "home.show_only_public"}}"
+ data-title-private="{{.locale.Tr "home.show_only_private"}}"
+ :title="checkboxPrivateFilterTitle"
+ >
+ <input type="checkbox" class="hidden" v-bind.prop="checkboxPrivateFilterProps">
+ <label>
+ {{svg "octicon-lock" 16 "gt-mr-2"}}
+ {{.locale.Tr "home.show_private"}}
+ </label>
+ </div>
+ </a>
</div>
</div>
</div>
diff --git a/templates/user/overview/header.tmpl b/templates/user/overview/header.tmpl
index 2449f5fc3..b4f7d6f90 100644
--- a/templates/user/overview/header.tmpl
+++ b/templates/user/overview/header.tmpl
@@ -22,15 +22,17 @@
<a class="item" href="{{.ContextUser.HomeLink}}">
{{svg "octicon-repo"}} {{.locale.Tr "user.repositories"}}
</a>
+ {{if and .IsProjectEnabled (or .ContextUser.IsIndividual (and .ContextUser.IsOrganization .CanReadProjects))}}
<a href="{{.ContextUser.HomeLink}}/-/projects" class="{{if .PageIsViewProjects}}active {{end}}item">
- {{svg "octicon-project"}} {{.locale.Tr "user.projects"}}
+ {{svg "octicon-project-symlink"}} {{.locale.Tr "user.projects"}}
</a>
- {{if (not .UnitPackagesGlobalDisabled)}}
+ {{end}}
+ {{if and .IsPackageEnabled (or .ContextUser.IsIndividual (and .ContextUser.IsOrganization .CanReadPackages))}}
<a href="{{.ContextUser.HomeLink}}/-/packages" class="{{if .IsPackagesPage}}active {{end}}item">
{{svg "octicon-package"}} {{.locale.Tr "packages.title"}}
</a>
{{end}}
- {{if .IsRepoIndexerEnabled}}
+ {{if and .IsRepoIndexerEnabled (or .ContextUser.IsIndividual (and .ContextUser.IsOrganization .CanReadCode))}}
<a href="{{.ContextUser.HomeLink}}/-/code" class="{{if .IsCodePage}}active {{end}}item">
{{svg "octicon-code"}} {{.locale.Tr "user.code"}}
</a>
diff --git a/templates/user/profile.tmpl b/templates/user/profile.tmpl
index fcaec60ea..5b445bdb0 100644
--- a/templates/user/profile.tmpl
+++ b/templates/user/profile.tmpl
@@ -107,7 +107,7 @@
{{svg "octicon-repo"}} {{.locale.Tr "user.repositories"}}
</a>
<a href="{{.Owner.HomeLink}}/-/projects" class="{{if eq .TabName "projects"}}active {{end}}item">
- {{svg "octicon-project"}} {{.locale.Tr "user.projects"}}
+ {{svg "octicon-project-symlink"}} {{.locale.Tr "user.projects"}}
</a>
{{if .IsPackageEnabled}}
<a class='{{if eq .TabName "packages"}}active {{end}}item' href="{{.Owner.HomeLink}}/-/packages">
diff --git a/templates/user/settings/applications.tmpl b/templates/user/settings/applications.tmpl
index ef9ac9a97..b0cd37d44 100644
--- a/templates/user/settings/applications.tmpl
+++ b/templates/user/settings/applications.tmpl
@@ -140,6 +140,12 @@
</div>
<div class="field">
<div class="ui checkbox">
+ <input class="enable-system" type="checkbox" name="scope" value="admin:user_hook">
+ <label>admin:user_hook</label>
+ </div>
+ </div>
+ <div class="field">
+ <div class="ui checkbox">
<input class="enable-system" type="checkbox" name="scope" value="notification">
<label>notification</label>
</div>
diff --git a/templates/user/settings/hook_new.tmpl b/templates/user/settings/hook_new.tmpl
new file mode 100644
index 000000000..20aaf65f6
--- /dev/null
+++ b/templates/user/settings/hook_new.tmpl
@@ -0,0 +1,53 @@
+{{template "base/head" .}}
+<div class="page-content user settings new webhook">
+ {{template "user/settings/navbar" .}}
+ <div class="ui container">
+ <div class="twelve wide column content">
+ {{template "base/alert" .}}
+ <h4 class="ui top attached header">
+ {{if .PageIsSettingsHooksNew}}{{.locale.Tr "repo.settings.add_webhook"}}{{else}}{{.locale.Tr "repo.settings.update_webhook"}}{{end}}
+ <div class="ui right">
+ {{if eq .HookType "gitea"}}
+ <img width="26" height="26" src="{{AssetUrlPrefix}}/img/gitea.svg">
+ {{else if eq .HookType "gogs"}}
+ <img width="26" height="26" src="{{AssetUrlPrefix}}/img/gogs.ico">
+ {{else if eq .HookType "slack"}}
+ <img width="26" height="26" src="{{AssetUrlPrefix}}/img/slack.png">
+ {{else if eq .HookType "discord"}}
+ <img width="26" height="26" src="{{AssetUrlPrefix}}/img/discord.png">
+ {{else if eq .HookType "dingtalk"}}
+ <img width="26" height="26" src="{{AssetUrlPrefix}}/img/dingtalk.ico">
+ {{else if eq .HookType "telegram"}}
+ <img width="26" height="26" src="{{AssetUrlPrefix}}/img/telegram.png">
+ {{else if eq .HookType "msteams"}}
+ <img width="26" height="26" src="{{AssetUrlPrefix}}/img/msteams.png">
+ {{else if eq .HookType "feishu"}}
+ <img width="26" height="26" src="{{AssetUrlPrefix}}/img/feishu.png">
+ {{else if eq .HookType "matrix"}}
+ <img width="26" height="26" src="{{AssetUrlPrefix}}/img/matrix.svg">
+ {{else if eq .HookType "wechatwork"}}
+ <img width="26" height="26" src="{{AssetUrlPrefix}}/img/wechatwork.png">
+ {{else if eq .HookType "packagist"}}
+ <img width="26" height="26" src="{{AssetUrlPrefix}}/img/packagist.png">
+ {{end}}
+ </div>
+ </h4>
+ <div class="ui attached segment">
+ {{template "repo/settings/webhook/gitea" .}}
+ {{template "repo/settings/webhook/gogs" .}}
+ {{template "repo/settings/webhook/slack" .}}
+ {{template "repo/settings/webhook/discord" .}}
+ {{template "repo/settings/webhook/dingtalk" .}}
+ {{template "repo/settings/webhook/telegram" .}}
+ {{template "repo/settings/webhook/msteams" .}}
+ {{template "repo/settings/webhook/feishu" .}}
+ {{template "repo/settings/webhook/matrix" .}}
+ {{template "repo/settings/webhook/wechatwork" .}}
+ {{template "repo/settings/webhook/packagist" .}}
+ </div>
+
+ {{template "repo/settings/webhook/history" .}}
+ </div>
+ </div>
+</div>
+{{template "base/footer" .}}
diff --git a/templates/user/settings/hooks.tmpl b/templates/user/settings/hooks.tmpl
new file mode 100644
index 000000000..02bfa8a4e
--- /dev/null
+++ b/templates/user/settings/hooks.tmpl
@@ -0,0 +1,8 @@
+{{template "base/head" .}}
+<div class="page-content user settings webhooks">
+ {{template "user/settings/navbar" .}}
+ <div class="ui container">
+ {{template "repo/settings/webhook/list" .}}
+ </div>
+</div>
+{{template "base/footer" .}}
diff --git a/templates/user/settings/navbar.tmpl b/templates/user/settings/navbar.tmpl
index 8deffde0b..4afe2173c 100644
--- a/templates/user/settings/navbar.tmpl
+++ b/templates/user/settings/navbar.tmpl
@@ -26,6 +26,11 @@
{{.locale.Tr "packages.title"}}
</a>
{{end}}
+ {{if not DisableWebhooks}}
+ <a class="{{if .PageIsSettingsHooks}}active {{end}}item" href="{{AppSubUrl}}/user/settings/hooks">
+ {{.locale.Tr "repo.settings.hooks"}}
+ </a>
+ {{end}}
<a class="{{if .PageIsSettingsOrganization}}active {{end}}item" href="{{AppSubUrl}}/user/settings/organization">
{{.locale.Tr "settings.organization"}}
</a>
diff --git a/tests/gitea-repositories-meta/user2/readme-test.git/HEAD b/tests/gitea-repositories-meta/user2/readme-test.git/HEAD
new file mode 100644
index 000000000..cb089cd89
--- /dev/null
+++ b/tests/gitea-repositories-meta/user2/readme-test.git/HEAD
@@ -0,0 +1 @@
+ref: refs/heads/master
diff --git a/tests/gitea-repositories-meta/user2/readme-test.git/config b/tests/gitea-repositories-meta/user2/readme-test.git/config
new file mode 100644
index 000000000..07d359d07
--- /dev/null
+++ b/tests/gitea-repositories-meta/user2/readme-test.git/config
@@ -0,0 +1,4 @@
+[core]
+ repositoryformatversion = 0
+ filemode = true
+ bare = true
diff --git a/tests/gitea-repositories-meta/user2/readme-test.git/info/exclude b/tests/gitea-repositories-meta/user2/readme-test.git/info/exclude
new file mode 100644
index 000000000..a5196d1be
--- /dev/null
+++ b/tests/gitea-repositories-meta/user2/readme-test.git/info/exclude
@@ -0,0 +1,6 @@
+# git ls-files --others --exclude-from=.git/info/exclude
+# Lines that start with '#' are comments.
+# For a project mostly in C, the following would be a good set of
+# exclude patterns (uncomment them if you want to use them):
+# *.[oa]
+# *~
diff --git a/tests/gitea-repositories-meta/user2/readme-test.git/info/refs b/tests/gitea-repositories-meta/user2/readme-test.git/info/refs
new file mode 100644
index 000000000..fd5f1b98e
--- /dev/null
+++ b/tests/gitea-repositories-meta/user2/readme-test.git/info/refs
@@ -0,0 +1,21 @@
+ea9ef877d1d88af76682d8798418081264f10cfc refs/heads/fallbacks
+0d4c14db927c9ffba01fa7e126cc748b5c02c01e refs/heads/fallbacks2
+c66d5b07c2063d3268707f22226c708b589574ef refs/heads/fallbacks3
+89f8426e9eb5eff35c09b3565836c8f8e15d0ce9 refs/heads/fallbacks4
+b0e902496eae435ad03c92a5d479f916ef2d4893 refs/heads/fallbacks5
+84a5500b5cc040b11daf53fc42c542a99589dc76 refs/heads/fallbacks6
+cf406a96e416d7de5c4c1bbfffdd672300c822bf refs/heads/fallbacks7
+0d6ac644b969e9199915a492da9dba08c179fd23 refs/heads/fallbacks8
+5038febc0c57215beb3748d7ae4091a25a4acc93 refs/heads/fallbacks9
+9134e1f178ca4cccf1a197142646f2d7627e8cd5 refs/heads/i18n
+744d2441e55bc0010d6b340d303f0106a627ad29 refs/heads/master
+3c492566170b057e962c025515ab38bbd7444077 refs/heads/plain
+3882d6373a0882a6739b3cd9b24d21c630621234 refs/heads/sp-ace
+bf5ed898252eaa50dcc01108ed4417c3ea98a294 refs/heads/special-subdir-.gitea
+c03543573ab088ce1cf7090a387d2be621426234 refs/heads/special-subdir-.github
+e75957ad9b7e6ed16dda183529ec283db0bbc5fe refs/heads/special-subdir-docs
+46f5d5ab33d701642e08c713fab42af89fdd4fea refs/heads/special-subdir-nested
+9c0f872256b839c2b97ec22fd348d87b14045513 refs/heads/subdir
+d7a854fff61e45b98234d7aa79ecbcb1619cd3dd refs/heads/symlink
+30b9c0ed4b1039dbd99f3fb537b84ca507e0549d refs/heads/symlink-loop
+41489b7be5c2244d2b7b524dcb31caf3bd1f9ccc refs/heads/txt
diff --git a/tests/gitea-repositories-meta/user2/readme-test.git/objects/12/11481f7314efbfe4e44703170d96c8fac8172b b/tests/gitea-repositories-meta/user2/readme-test.git/objects/12/11481f7314efbfe4e44703170d96c8fac8172b
new file mode 100644
index 000000000..b9009e324
--- /dev/null
+++ b/tests/gitea-repositories-meta/user2/readme-test.git/objects/12/11481f7314efbfe4e44703170d96c8fac8172b
Binary files differ
diff --git a/tests/gitea-repositories-meta/user2/readme-test.git/objects/17/2343566bf11fc71ba4acf8d2ea70d12bc1d037 b/tests/gitea-repositories-meta/user2/readme-test.git/objects/17/2343566bf11fc71ba4acf8d2ea70d12bc1d037
new file mode 100644
index 000000000..c7a4deca9
--- /dev/null
+++ b/tests/gitea-repositories-meta/user2/readme-test.git/objects/17/2343566bf11fc71ba4acf8d2ea70d12bc1d037
Binary files differ
diff --git a/tests/gitea-repositories-meta/user2/readme-test.git/objects/1a/48cae3f18ccd9c929e6608f67087dbaac3cf9e b/tests/gitea-repositories-meta/user2/readme-test.git/objects/1a/48cae3f18ccd9c929e6608f67087dbaac3cf9e
new file mode 100644
index 000000000..d8522ae6d
--- /dev/null
+++ b/tests/gitea-repositories-meta/user2/readme-test.git/objects/1a/48cae3f18ccd9c929e6608f67087dbaac3cf9e
Binary files differ
diff --git a/tests/gitea-repositories-meta/user2/readme-test.git/objects/1e/1e08102cf1b1fc01c069c88ee75445974363ab b/tests/gitea-repositories-meta/user2/readme-test.git/objects/1e/1e08102cf1b1fc01c069c88ee75445974363ab
new file mode 100644
index 000000000..d4152e535
--- /dev/null
+++ b/tests/gitea-repositories-meta/user2/readme-test.git/objects/1e/1e08102cf1b1fc01c069c88ee75445974363ab
Binary files differ
diff --git a/tests/gitea-repositories-meta/user2/readme-test.git/objects/21/470f9b3e8ff24e0fa083d2dbc447f4c3401355 b/tests/gitea-repositories-meta/user2/readme-test.git/objects/21/470f9b3e8ff24e0fa083d2dbc447f4c3401355
new file mode 100644
index 000000000..8aabb78c6
--- /dev/null
+++ b/tests/gitea-repositories-meta/user2/readme-test.git/objects/21/470f9b3e8ff24e0fa083d2dbc447f4c3401355
@@ -0,0 +1,2 @@
+xŽ;Â0 @™s
+_€*NÒÄH±±1q×u(¢?•tàöTˆ0¾á==™†áQÀ·+‹*4¤Ìd¹¥h“SÌη.z¢à°¢Í™Z3ó¢ctˆ0'As“5hÉzL¶=D¡ÌB˜\cx-Ý´Àõ!O¸¬›ÚéÇqÃêþÃó<õï¡ô•ð 0¦T×装½­­5ò=-›õÃÜôU sß7,Oó#ÆMÜ \ No newline at end of file
diff --git a/tests/gitea-repositories-meta/user2/readme-test.git/objects/23/65bfe0c5714e2e3f2d53bb302b10d8d5b4fc7d b/tests/gitea-repositories-meta/user2/readme-test.git/objects/23/65bfe0c5714e2e3f2d53bb302b10d8d5b4fc7d
new file mode 100644
index 000000000..715977676
--- /dev/null
+++ b/tests/gitea-repositories-meta/user2/readme-test.git/objects/23/65bfe0c5714e2e3f2d53bb302b10d8d5b4fc7d
Binary files differ
diff --git a/tests/gitea-repositories-meta/user2/readme-test.git/objects/38/9d08c6a71d024a91f14089007cd789cd977ca6 b/tests/gitea-repositories-meta/user2/readme-test.git/objects/38/9d08c6a71d024a91f14089007cd789cd977ca6
new file mode 100644
index 000000000..c5929ae89
--- /dev/null
+++ b/tests/gitea-repositories-meta/user2/readme-test.git/objects/38/9d08c6a71d024a91f14089007cd789cd977ca6
Binary files differ
diff --git a/tests/gitea-repositories-meta/user2/readme-test.git/objects/3a/a8f4e0e1a535f0f9e0ae40e6ec1bce42642bc4 b/tests/gitea-repositories-meta/user2/readme-test.git/objects/3a/a8f4e0e1a535f0f9e0ae40e6ec1bce42642bc4
new file mode 100644
index 000000000..106393d72
--- /dev/null
+++ b/tests/gitea-repositories-meta/user2/readme-test.git/objects/3a/a8f4e0e1a535f0f9e0ae40e6ec1bce42642bc4
Binary files differ
diff --git a/tests/gitea-repositories-meta/user2/readme-test.git/objects/3b/23d7f1a9cb904cb46f5f2272bfa5ed5f871fb9 b/tests/gitea-repositories-meta/user2/readme-test.git/objects/3b/23d7f1a9cb904cb46f5f2272bfa5ed5f871fb9
new file mode 100644
index 000000000..c36705ba2
--- /dev/null
+++ b/tests/gitea-repositories-meta/user2/readme-test.git/objects/3b/23d7f1a9cb904cb46f5f2272bfa5ed5f871fb9
@@ -0,0 +1 @@
+xÎM †aל‚ Ø 0&ƸsçÊ ئô'•.¼½Õx—ïâùòñ4 ]•õ®.)ÉDÖñQÅ|@b6Xbdƒì}Ö2+b¦%Tè ƒI>g 27QÇÀˆ. (c­ µ¶Ó"o÷òºn´M‹<[6_^橼†Z¦³Tç¬Uƹ øû´nêÿ qOÏ*3•ˆ{ñ™²N\ \ No newline at end of file
diff --git a/tests/gitea-repositories-meta/user2/readme-test.git/objects/50/6ff7310f420e878595b4bc8f11688e3f0ae14e b/tests/gitea-repositories-meta/user2/readme-test.git/objects/50/6ff7310f420e878595b4bc8f11688e3f0ae14e
new file mode 100644
index 000000000..a7f4501ea
--- /dev/null
+++ b/tests/gitea-repositories-meta/user2/readme-test.git/objects/50/6ff7310f420e878595b4bc8f11688e3f0ae14e
Binary files differ
diff --git a/tests/gitea-repositories-meta/user2/readme-test.git/objects/58/3eb775c596858380273492759d39081d65d029 b/tests/gitea-repositories-meta/user2/readme-test.git/objects/58/3eb775c596858380273492759d39081d65d029
new file mode 100644
index 000000000..a2dadacf8
--- /dev/null
+++ b/tests/gitea-repositories-meta/user2/readme-test.git/objects/58/3eb775c596858380273492759d39081d65d029
Binary files differ
diff --git a/tests/gitea-repositories-meta/user2/readme-test.git/objects/60/ea618ae7d4ecbe9c1962591c7da1b05bb1a5c8 b/tests/gitea-repositories-meta/user2/readme-test.git/objects/60/ea618ae7d4ecbe9c1962591c7da1b05bb1a5c8
new file mode 100644
index 000000000..4367c41e2
--- /dev/null
+++ b/tests/gitea-repositories-meta/user2/readme-test.git/objects/60/ea618ae7d4ecbe9c1962591c7da1b05bb1a5c8
@@ -0,0 +1,3 @@
+xŽ;Â0 @™s
+_€*N뤕bccâŽëЊþTÒÛS!NÀø†÷ôdÇ>ƒ«Ü!¯ª­Ö„Lu­UlÙ#qô¡´”líQÅ,¼ê”¡Œ®lCBn$6¶’XùDɹàbbÒ–R0ÅÆð–»y…[/O¸n»Úé
+§iÇâñÃË2ï1…ðЇ@„ep´d­‘ïiÞ­ÿ殯 ‰‡!²<Í™ÜN— \ No newline at end of file
diff --git a/tests/gitea-repositories-meta/user2/readme-test.git/objects/6a/b05db4c52530726c1856eb558228e9d1949e7f b/tests/gitea-repositories-meta/user2/readme-test.git/objects/6a/b05db4c52530726c1856eb558228e9d1949e7f
new file mode 100644
index 000000000..3e4c8247d
--- /dev/null
+++ b/tests/gitea-repositories-meta/user2/readme-test.git/objects/6a/b05db4c52530726c1856eb558228e9d1949e7f
Binary files differ
diff --git a/tests/gitea-repositories-meta/user2/readme-test.git/objects/71/60a063b5544b5a78131b94f47bfd200046eda2 b/tests/gitea-repositories-meta/user2/readme-test.git/objects/71/60a063b5544b5a78131b94f47bfd200046eda2
new file mode 100644
index 000000000..477d5b1f1
--- /dev/null
+++ b/tests/gitea-repositories-meta/user2/readme-test.git/objects/71/60a063b5544b5a78131b94f47bfd200046eda2
Binary files differ
diff --git a/tests/gitea-repositories-meta/user2/readme-test.git/objects/75/6c70c97047d8aeb11ca3c71edd9fb76cefee9c b/tests/gitea-repositories-meta/user2/readme-test.git/objects/75/6c70c97047d8aeb11ca3c71edd9fb76cefee9c
new file mode 100644
index 000000000..3ef179698
--- /dev/null
+++ b/tests/gitea-repositories-meta/user2/readme-test.git/objects/75/6c70c97047d8aeb11ca3c71edd9fb76cefee9c
Binary files differ
diff --git a/tests/gitea-repositories-meta/user2/readme-test.git/objects/7f/2b9f991d99362eb827b67f4ae2f5fbc5fa2271 b/tests/gitea-repositories-meta/user2/readme-test.git/objects/7f/2b9f991d99362eb827b67f4ae2f5fbc5fa2271
new file mode 100644
index 000000000..4e39c0306
--- /dev/null
+++ b/tests/gitea-repositories-meta/user2/readme-test.git/objects/7f/2b9f991d99362eb827b67f4ae2f5fbc5fa2271
Binary files differ
diff --git a/tests/gitea-repositories-meta/user2/readme-test.git/objects/7f/792e709143fb0f021da2371e5f40d1bcc284fd b/tests/gitea-repositories-meta/user2/readme-test.git/objects/7f/792e709143fb0f021da2371e5f40d1bcc284fd
new file mode 100644
index 000000000..90fae2388
--- /dev/null
+++ b/tests/gitea-repositories-meta/user2/readme-test.git/objects/7f/792e709143fb0f021da2371e5f40d1bcc284fd
Binary files differ
diff --git a/tests/gitea-repositories-meta/user2/readme-test.git/objects/82/817856dadc7f6b944633e1b77d5b6e302dde06 b/tests/gitea-repositories-meta/user2/readme-test.git/objects/82/817856dadc7f6b944633e1b77d5b6e302dde06
new file mode 100644
index 000000000..0428af472
--- /dev/null
+++ b/tests/gitea-repositories-meta/user2/readme-test.git/objects/82/817856dadc7f6b944633e1b77d5b6e302dde06
Binary files differ
diff --git a/tests/gitea-repositories-meta/user2/readme-test.git/objects/8b/4149e7dede3cd53ba11c64c88b057c5fe2c200 b/tests/gitea-repositories-meta/user2/readme-test.git/objects/8b/4149e7dede3cd53ba11c64c88b057c5fe2c200
new file mode 100644
index 000000000..64542d375
--- /dev/null
+++ b/tests/gitea-repositories-meta/user2/readme-test.git/objects/8b/4149e7dede3cd53ba11c64c88b057c5fe2c200
Binary files differ
diff --git a/tests/gitea-repositories-meta/user2/readme-test.git/objects/93/54813d81053c14afe878a9f056b937ec42bb48 b/tests/gitea-repositories-meta/user2/readme-test.git/objects/93/54813d81053c14afe878a9f056b937ec42bb48
new file mode 100644
index 000000000..8542b45c7
--- /dev/null
+++ b/tests/gitea-repositories-meta/user2/readme-test.git/objects/93/54813d81053c14afe878a9f056b937ec42bb48
Binary files differ
diff --git a/tests/gitea-repositories-meta/user2/readme-test.git/objects/9c/72c10e55e7d6ea21f591aa424e2625e8ad8094 b/tests/gitea-repositories-meta/user2/readme-test.git/objects/9c/72c10e55e7d6ea21f591aa424e2625e8ad8094
new file mode 100644
index 000000000..b53d42aee
--- /dev/null
+++ b/tests/gitea-repositories-meta/user2/readme-test.git/objects/9c/72c10e55e7d6ea21f591aa424e2625e8ad8094
Binary files differ
diff --git a/tests/gitea-repositories-meta/user2/readme-test.git/objects/a3/cd04bb110e17591ac04e156c7df2c2f5c96fa6 b/tests/gitea-repositories-meta/user2/readme-test.git/objects/a3/cd04bb110e17591ac04e156c7df2c2f5c96fa6
new file mode 100644
index 000000000..6d9bc2a76
--- /dev/null
+++ b/tests/gitea-repositories-meta/user2/readme-test.git/objects/a3/cd04bb110e17591ac04e156c7df2c2f5c96fa6
Binary files differ
diff --git a/tests/gitea-repositories-meta/user2/readme-test.git/objects/b0/e851a5619e2d6cee1da25a15ab67305f0861ec b/tests/gitea-repositories-meta/user2/readme-test.git/objects/b0/e851a5619e2d6cee1da25a15ab67305f0861ec
new file mode 100644
index 000000000..2f88dbd36
--- /dev/null
+++ b/tests/gitea-repositories-meta/user2/readme-test.git/objects/b0/e851a5619e2d6cee1da25a15ab67305f0861ec
Binary files differ
diff --git a/tests/gitea-repositories-meta/user2/readme-test.git/objects/b4/4c8eb00bdaf0522de61e591fee5f66851ef4b5 b/tests/gitea-repositories-meta/user2/readme-test.git/objects/b4/4c8eb00bdaf0522de61e591fee5f66851ef4b5
new file mode 100644
index 000000000..55bb8491a
--- /dev/null
+++ b/tests/gitea-repositories-meta/user2/readme-test.git/objects/b4/4c8eb00bdaf0522de61e591fee5f66851ef4b5
Binary files differ
diff --git a/tests/gitea-repositories-meta/user2/readme-test.git/objects/b8/eaa80ad86072e1f23d2638842154ce9aceff8d b/tests/gitea-repositories-meta/user2/readme-test.git/objects/b8/eaa80ad86072e1f23d2638842154ce9aceff8d
new file mode 100644
index 000000000..84ab5684a
--- /dev/null
+++ b/tests/gitea-repositories-meta/user2/readme-test.git/objects/b8/eaa80ad86072e1f23d2638842154ce9aceff8d
Binary files differ
diff --git a/tests/gitea-repositories-meta/user2/readme-test.git/objects/d5/34f914944c3c943a6bdb677d869ac54934928d b/tests/gitea-repositories-meta/user2/readme-test.git/objects/d5/34f914944c3c943a6bdb677d869ac54934928d
new file mode 100644
index 000000000..7bb434442
--- /dev/null
+++ b/tests/gitea-repositories-meta/user2/readme-test.git/objects/d5/34f914944c3c943a6bdb677d869ac54934928d
Binary files differ
diff --git a/tests/gitea-repositories-meta/user2/readme-test.git/objects/e2/f9904cd97b4045feecfffef5a426e9461bee70 b/tests/gitea-repositories-meta/user2/readme-test.git/objects/e2/f9904cd97b4045feecfffef5a426e9461bee70
new file mode 100644
index 000000000..9654f877b
--- /dev/null
+++ b/tests/gitea-repositories-meta/user2/readme-test.git/objects/e2/f9904cd97b4045feecfffef5a426e9461bee70
Binary files differ
diff --git a/tests/gitea-repositories-meta/user2/readme-test.git/objects/e3/a6fd8fe49e323ee10017f72b777a53fbd8076f b/tests/gitea-repositories-meta/user2/readme-test.git/objects/e3/a6fd8fe49e323ee10017f72b777a53fbd8076f
new file mode 100644
index 000000000..2307ba82d
--- /dev/null
+++ b/tests/gitea-repositories-meta/user2/readme-test.git/objects/e3/a6fd8fe49e323ee10017f72b777a53fbd8076f
@@ -0,0 +1,3 @@
+xÎM
+1 †a×=E. ¤mšŽ âÎwh›¨ƒó#µ"ÞÞA<Ëgñ~|eǾ#»jU:×ÙØ–$%ž9o‰Ø{µ9F ™Õ£QdsOU§‘H‘ÕrA´(œ=¡xôçEœØÅ$nkÒ³]ç
+§¾Üàø\Ò«VØM 7—÷yxmØ”´Ë1ê-¬1 šò}Ú–êÿ 3Ì/­%=úf>&L¨ \ No newline at end of file
diff --git a/tests/gitea-repositories-meta/user2/readme-test.git/objects/e7/bf02fcfa7a86f7fe9e8158b55d58ddf9d877ec b/tests/gitea-repositories-meta/user2/readme-test.git/objects/e7/bf02fcfa7a86f7fe9e8158b55d58ddf9d877ec
new file mode 100644
index 000000000..9f898ef87
--- /dev/null
+++ b/tests/gitea-repositories-meta/user2/readme-test.git/objects/e7/bf02fcfa7a86f7fe9e8158b55d58ddf9d877ec
Binary files differ
diff --git a/tests/gitea-repositories-meta/user2/readme-test.git/objects/ea/57c91ddb8b4ac705b5ac4c34c7a48f2d0fc180 b/tests/gitea-repositories-meta/user2/readme-test.git/objects/ea/57c91ddb8b4ac705b5ac4c34c7a48f2d0fc180
new file mode 100644
index 000000000..d1eff5286
--- /dev/null
+++ b/tests/gitea-repositories-meta/user2/readme-test.git/objects/ea/57c91ddb8b4ac705b5ac4c34c7a48f2d0fc180
Binary files differ
diff --git a/tests/gitea-repositories-meta/user2/readme-test.git/objects/fe/495ea336f079ef2bed68648d0ba9a37cdbd4aa b/tests/gitea-repositories-meta/user2/readme-test.git/objects/fe/495ea336f079ef2bed68648d0ba9a37cdbd4aa
new file mode 100644
index 000000000..48c0b5a4d
--- /dev/null
+++ b/tests/gitea-repositories-meta/user2/readme-test.git/objects/fe/495ea336f079ef2bed68648d0ba9a37cdbd4aa
Binary files differ
diff --git a/tests/gitea-repositories-meta/user2/readme-test.git/objects/info/commit-graph b/tests/gitea-repositories-meta/user2/readme-test.git/objects/info/commit-graph
new file mode 100644
index 000000000..9bb0976fd
--- /dev/null
+++ b/tests/gitea-repositories-meta/user2/readme-test.git/objects/info/commit-graph
Binary files differ
diff --git a/tests/gitea-repositories-meta/user2/readme-test.git/objects/info/packs b/tests/gitea-repositories-meta/user2/readme-test.git/objects/info/packs
new file mode 100644
index 000000000..aad10862f
--- /dev/null
+++ b/tests/gitea-repositories-meta/user2/readme-test.git/objects/info/packs
@@ -0,0 +1,2 @@
+P pack-8933bd634b76f8154310cccb52537a0195e43166.pack
+
diff --git a/tests/gitea-repositories-meta/user2/readme-test.git/objects/pack/pack-8933bd634b76f8154310cccb52537a0195e43166.bitmap b/tests/gitea-repositories-meta/user2/readme-test.git/objects/pack/pack-8933bd634b76f8154310cccb52537a0195e43166.bitmap
new file mode 100644
index 000000000..db39955a2
--- /dev/null
+++ b/tests/gitea-repositories-meta/user2/readme-test.git/objects/pack/pack-8933bd634b76f8154310cccb52537a0195e43166.bitmap
Binary files differ
diff --git a/tests/gitea-repositories-meta/user2/readme-test.git/objects/pack/pack-8933bd634b76f8154310cccb52537a0195e43166.idx b/tests/gitea-repositories-meta/user2/readme-test.git/objects/pack/pack-8933bd634b76f8154310cccb52537a0195e43166.idx
new file mode 100644
index 000000000..561e0f2e9
--- /dev/null
+++ b/tests/gitea-repositories-meta/user2/readme-test.git/objects/pack/pack-8933bd634b76f8154310cccb52537a0195e43166.idx
Binary files differ
diff --git a/tests/gitea-repositories-meta/user2/readme-test.git/objects/pack/pack-8933bd634b76f8154310cccb52537a0195e43166.pack b/tests/gitea-repositories-meta/user2/readme-test.git/objects/pack/pack-8933bd634b76f8154310cccb52537a0195e43166.pack
new file mode 100644
index 000000000..6f5bf1f04
--- /dev/null
+++ b/tests/gitea-repositories-meta/user2/readme-test.git/objects/pack/pack-8933bd634b76f8154310cccb52537a0195e43166.pack
Binary files differ
diff --git a/tests/gitea-repositories-meta/user2/readme-test.git/packed-refs b/tests/gitea-repositories-meta/user2/readme-test.git/packed-refs
new file mode 100644
index 000000000..2399a8008
--- /dev/null
+++ b/tests/gitea-repositories-meta/user2/readme-test.git/packed-refs
@@ -0,0 +1,22 @@
+# pack-refs with: peeled fully-peeled sorted
+ea9ef877d1d88af76682d8798418081264f10cfc refs/heads/fallbacks
+0d4c14db927c9ffba01fa7e126cc748b5c02c01e refs/heads/fallbacks2
+c66d5b07c2063d3268707f22226c708b589574ef refs/heads/fallbacks3
+89f8426e9eb5eff35c09b3565836c8f8e15d0ce9 refs/heads/fallbacks4
+b0e902496eae435ad03c92a5d479f916ef2d4893 refs/heads/fallbacks5
+84a5500b5cc040b11daf53fc42c542a99589dc76 refs/heads/fallbacks6
+cf406a96e416d7de5c4c1bbfffdd672300c822bf refs/heads/fallbacks7
+0d6ac644b969e9199915a492da9dba08c179fd23 refs/heads/fallbacks8
+5038febc0c57215beb3748d7ae4091a25a4acc93 refs/heads/fallbacks9
+9134e1f178ca4cccf1a197142646f2d7627e8cd5 refs/heads/i18n
+744d2441e55bc0010d6b340d303f0106a627ad29 refs/heads/master
+3c492566170b057e962c025515ab38bbd7444077 refs/heads/plain
+3882d6373a0882a6739b3cd9b24d21c630621234 refs/heads/sp-ace
+bf5ed898252eaa50dcc01108ed4417c3ea98a294 refs/heads/special-subdir-.gitea
+c03543573ab088ce1cf7090a387d2be621426234 refs/heads/special-subdir-.github
+e75957ad9b7e6ed16dda183529ec283db0bbc5fe refs/heads/special-subdir-docs
+46f5d5ab33d701642e08c713fab42af89fdd4fea refs/heads/special-subdir-nested
+9c0f872256b839c2b97ec22fd348d87b14045513 refs/heads/subdir
+d7a854fff61e45b98234d7aa79ecbcb1619cd3dd refs/heads/symlink
+30b9c0ed4b1039dbd99f3fb537b84ca507e0549d refs/heads/symlink-loop
+41489b7be5c2244d2b7b524dcb31caf3bd1f9ccc refs/heads/txt
diff --git a/tests/gitea-repositories-meta/user2/readme-test.git/refs/heads/fallbacks-broken-symlinks b/tests/gitea-repositories-meta/user2/readme-test.git/refs/heads/fallbacks-broken-symlinks
new file mode 100644
index 000000000..cf36865a7
--- /dev/null
+++ b/tests/gitea-repositories-meta/user2/readme-test.git/refs/heads/fallbacks-broken-symlinks
@@ -0,0 +1 @@
+fe495ea336f079ef2bed68648d0ba9a37cdbd4aa
diff --git a/tests/gitea-repositories-meta/user2/repo1.git/objects/40/3d76c604cb569323864e06a07b85d466924802 b/tests/gitea-repositories-meta/user2/repo1.git/objects/40/3d76c604cb569323864e06a07b85d466924802
new file mode 100644
index 000000000..ea0bf76d0
--- /dev/null
+++ b/tests/gitea-repositories-meta/user2/repo1.git/objects/40/3d76c604cb569323864e06a07b85d466924802
Binary files differ
diff --git a/tests/gitea-repositories-meta/user2/repo1.git/objects/78/fb907e3a3309eae4fe8fef030874cebbf1cd5e b/tests/gitea-repositories-meta/user2/repo1.git/objects/78/fb907e3a3309eae4fe8fef030874cebbf1cd5e
new file mode 100644
index 000000000..6a25f7409
--- /dev/null
+++ b/tests/gitea-repositories-meta/user2/repo1.git/objects/78/fb907e3a3309eae4fe8fef030874cebbf1cd5e
Binary files differ
diff --git a/tests/gitea-repositories-meta/user2/repo1.git/objects/f3/fa0f5cc797fc4c02a1b8bec9de4b2072fcdbdf b/tests/gitea-repositories-meta/user2/repo1.git/objects/f3/fa0f5cc797fc4c02a1b8bec9de4b2072fcdbdf
new file mode 100644
index 000000000..9b20f8af3
--- /dev/null
+++ b/tests/gitea-repositories-meta/user2/repo1.git/objects/f3/fa0f5cc797fc4c02a1b8bec9de4b2072fcdbdf
Binary files differ
diff --git a/tests/gitea-repositories-meta/user2/repo1.git/refs/heads/home-md-img-check b/tests/gitea-repositories-meta/user2/repo1.git/refs/heads/home-md-img-check
new file mode 100644
index 000000000..a254e4292
--- /dev/null
+++ b/tests/gitea-repositories-meta/user2/repo1.git/refs/heads/home-md-img-check
@@ -0,0 +1 @@
+78fb907e3a3309eae4fe8fef030874cebbf1cd5e
diff --git a/tests/integration/markup_external_test.go b/tests/integration/markup_external_test.go
index 6ea0226ec..c0e08a4f4 100644
--- a/tests/integration/markup_external_test.go
+++ b/tests/integration/markup_external_test.go
@@ -19,7 +19,7 @@ import (
func TestExternalMarkupRenderer(t *testing.T) {
defer tests.PrepareTestEnv(t)()
- if !setting.Database.UseSQLite3 {
+ if !setting.Database.Type.IsSQLite3() {
t.Skip()
return
}
diff --git a/tests/integration/migration-test/migration_test.go b/tests/integration/migration-test/migration_test.go
index f030f566c..4152379a9 100644
--- a/tests/integration/migration-test/migration_test.go
+++ b/tests/integration/migration-test/migration_test.go
@@ -94,7 +94,7 @@ func availableVersions() ([]string, error) {
return nil, err
}
defer migrationsDir.Close()
- versionRE, err := regexp.Compile("gitea-v(?P<version>.+)\\." + regexp.QuoteMeta(setting.Database.Type) + "\\.sql.gz")
+ versionRE, err := regexp.Compile("gitea-v(?P<version>.+)\\." + regexp.QuoteMeta(setting.Database.Type.String()) + "\\.sql.gz")
if err != nil {
return nil, err
}
@@ -149,7 +149,7 @@ func restoreOldDB(t *testing.T, version string) bool {
}
switch {
- case setting.Database.UseSQLite3:
+ case setting.Database.Type.IsSQLite3():
util.Remove(setting.Database.Path)
err := os.MkdirAll(path.Dir(setting.Database.Path), os.ModePerm)
assert.NoError(t, err)
@@ -162,7 +162,7 @@ func restoreOldDB(t *testing.T, version string) bool {
assert.NoError(t, err)
db.Close()
- case setting.Database.UseMySQL:
+ case setting.Database.Type.IsMySQL():
db, err := sql.Open("mysql", fmt.Sprintf("%s:%s@tcp(%s)/",
setting.Database.User, setting.Database.Passwd, setting.Database.Host))
assert.NoError(t, err)
@@ -184,7 +184,7 @@ func restoreOldDB(t *testing.T, version string) bool {
assert.NoError(t, err)
db.Close()
- case setting.Database.UsePostgreSQL:
+ case setting.Database.Type.IsPostgreSQL():
var db *sql.DB
var err error
if setting.Database.Host[0] == '/' {
@@ -252,7 +252,7 @@ func restoreOldDB(t *testing.T, version string) bool {
assert.NoError(t, err)
db.Close()
- case setting.Database.UseMSSQL:
+ case setting.Database.Type.IsMSSQL():
host, port := setting.ParseMSSQLHostPort(setting.Database.Host)
db, err := sql.Open("mssql", fmt.Sprintf("server=%s; port=%s; database=%s; user id=%s; password=%s;",
host, port, "master", setting.Database.User, setting.Database.Passwd))
diff --git a/tests/integration/pull_merge_test.go b/tests/integration/pull_merge_test.go
index 090a27c39..55cf29525 100644
--- a/tests/integration/pull_merge_test.go
+++ b/tests/integration/pull_merge_test.go
@@ -356,7 +356,7 @@ func TestConflictChecking(t *testing.T) {
user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
// Create new clean repo to test conflict checking.
- baseRepo, err := repo_service.CreateRepository(user, user, repo_module.CreateRepoOptions{
+ baseRepo, err := repo_service.CreateRepository(db.DefaultContext, user, user, repo_module.CreateRepoOptions{
Name: "conflict-checking",
Description: "Tempo repo",
AutoInit: true,
diff --git a/tests/integration/pull_update_test.go b/tests/integration/pull_update_test.go
index bd416e5bc..1b6665651 100644
--- a/tests/integration/pull_update_test.go
+++ b/tests/integration/pull_update_test.go
@@ -80,7 +80,7 @@ func TestAPIPullUpdateByRebase(t *testing.T) {
}
func createOutdatedPR(t *testing.T, actor, forkOrg *user_model.User) *issues_model.PullRequest {
- baseRepo, err := repo_service.CreateRepository(actor, actor, repo_module.CreateRepoOptions{
+ baseRepo, err := repo_service.CreateRepository(db.DefaultContext, actor, actor, repo_module.CreateRepoOptions{
Name: "repo-pr-update",
Description: "repo-tmp-pr-update description",
AutoInit: true,
diff --git a/tests/integration/repo_test.go b/tests/integration/repo_test.go
index 3692b11ec..cef9dccf2 100644
--- a/tests/integration/repo_test.go
+++ b/tests/integration/repo_test.go
@@ -256,3 +256,128 @@ func TestViewRepoDirectory(t *testing.T) {
assert.Zero(t, repoTopics.Length())
assert.Zero(t, repoSummary.Length())
}
+
+// ensure that the all the different ways to find and render a README work
+func TestViewRepoDirectoryReadme(t *testing.T) {
+ defer tests.PrepareTestEnv(t)()
+
+ // there are many combinations:
+ // - READMEs can be .md, .txt, or have no extension
+ // - READMEs can be tagged with a language and even a country code
+ // - READMEs can be stored in docs/, .gitea/, or .github/
+ // - READMEs can be symlinks to other files
+ // - READMEs can be broken symlinks which should not render
+ //
+ // this doesn't cover all possible cases, just the major branches of the code
+
+ session := loginUser(t, "user2")
+
+ check := func(name, url, expectedFilename, expectedReadmeType, expectedContent string) {
+ t.Run(name, func(t *testing.T) {
+ defer tests.PrintCurrentTest(t)()
+
+ req := NewRequest(t, "GET", url)
+ resp := session.MakeRequest(t, req, http.StatusOK)
+
+ htmlDoc := NewHTMLParser(t, resp.Body)
+ readmeName := htmlDoc.doc.Find("h4.file-header")
+ readmeContent := htmlDoc.doc.Find(".file-view") // TODO: add a id="readme" to the output to make this test more precise
+ readmeType, _ := readmeContent.Attr("class")
+
+ assert.Equal(t, expectedFilename, strings.TrimSpace(readmeName.Text()))
+ assert.Contains(t, readmeType, expectedReadmeType)
+ assert.Contains(t, readmeContent.Text(), expectedContent)
+ })
+ }
+
+ // viewing the top level
+ check("Home", "/user2/readme-test/", "README.md", "markdown", "The cake is a lie.")
+
+ // viewing different file extensions
+ check("md", "/user2/readme-test/src/branch/master/", "README.md", "markdown", "The cake is a lie.")
+ check("txt", "/user2/readme-test/src/branch/txt/", "README.txt", "plain-text", "My spoon is too big.")
+ check("plain", "/user2/readme-test/src/branch/plain/", "README", "plain-text", "Birken my stocks gee howdy")
+ check("i18n", "/user2/readme-test/src/branch/i18n/", "README.zh.md", "markdown", "蛋糕是一个谎言")
+
+ // viewing different subdirectories
+ check("subdir", "/user2/readme-test/src/branch/subdir/libcake", "README.md", "markdown", "Four pints of sugar.")
+ check("docs-direct", "/user2/readme-test/src/branch/special-subdir-docs/docs/", "README.md", "markdown", "This is in docs/")
+ check("docs", "/user2/readme-test/src/branch/special-subdir-docs/", "docs/README.md", "markdown", "This is in docs/")
+ check(".gitea", "/user2/readme-test/src/branch/special-subdir-.gitea/", ".gitea/README.md", "markdown", "This is in .gitea/")
+ check(".github", "/user2/readme-test/src/branch/special-subdir-.github/", ".github/README.md", "markdown", "This is in .github/")
+
+ // symlinks
+ // symlinks are subtle:
+ // - they should be able to handle going a reasonable number of times up and down in the tree
+ // - they shouldn't get stuck on link cycles
+ // - they should determine the filetype based on the name of the link, not the target
+ check("symlink", "/user2/readme-test/src/branch/symlink/", "README.md", "markdown", "This is in some/other/path")
+ check("symlink-multiple", "/user2/readme-test/src/branch/symlink/some/", "README.txt", "plain-text", "This is in some/other/path")
+ check("symlink-up-and-down", "/user2/readme-test/src/branch/symlink/up/back/down/down", "README.md", "markdown", "It's a me, mario")
+
+ // testing fallback rules
+ // READMEs are searched in this order:
+ // - [README.zh-cn.md, README.zh_cn.md, README.zh.md, README_zh.md, README.md, README.txt, README,
+ // docs/README.zh-cn.md, docs/README.zh_cn.md, docs/README.zh.md, docs/README_zh.md, docs/README.md, docs/README.txt, docs/README,
+ // .gitea/README.zh-cn.md, .gitea/README.zh_cn.md, .gitea/README.zh.md, .gitea/README_zh.md, .gitea/README.md, .gitea/README.txt, .gitea/README,
+
+ // .github/README.zh-cn.md, .github/README.zh_cn.md, .github/README.zh.md, .github/README_zh.md, .github/README.md, .github/README.txt, .github/README]
+ // and a broken/looped symlink counts as not existing at all and should be skipped.
+ // again, this doesn't cover all cases, but it covers a few
+ check("fallback/top", "/user2/readme-test/src/branch/fallbacks/", "README.en.md", "markdown", "This is README.en.md")
+ check("fallback/2", "/user2/readme-test/src/branch/fallbacks2/", "README.md", "markdown", "This is README.md")
+ check("fallback/3", "/user2/readme-test/src/branch/fallbacks3/", "README", "plain-text", "This is README")
+ check("fallback/4", "/user2/readme-test/src/branch/fallbacks4/", "docs/README.en.md", "markdown", "This is docs/README.en.md")
+ check("fallback/5", "/user2/readme-test/src/branch/fallbacks5/", "docs/README.md", "markdown", "This is docs/README.md")
+ check("fallback/6", "/user2/readme-test/src/branch/fallbacks6/", "docs/README", "plain-text", "This is docs/README")
+ check("fallback/7", "/user2/readme-test/src/branch/fallbacks7/", ".gitea/README.en.md", "markdown", "This is .gitea/README.en.md")
+ check("fallback/8", "/user2/readme-test/src/branch/fallbacks8/", ".gitea/README.md", "markdown", "This is .gitea/README.md")
+ check("fallback/9", "/user2/readme-test/src/branch/fallbacks9/", ".gitea/README", "plain-text", "This is .gitea/README")
+
+ // this case tests that broken symlinks count as missing files, instead of rendering their contents
+ check("fallbacks-broken-symlinks", "/user2/readme-test/src/branch/fallbacks-broken-symlinks/", "docs/README", "plain-text", "This is docs/README")
+
+ // some cases that should NOT render a README
+ // - /readme
+ // - /.github/docs/README.md
+ // - a symlink loop
+
+ missing := func(name, url string) {
+ t.Run("missing/"+name, func(t *testing.T) {
+ defer tests.PrintCurrentTest(t)()
+
+ req := NewRequest(t, "GET", url)
+ resp := session.MakeRequest(t, req, http.StatusOK)
+
+ htmlDoc := NewHTMLParser(t, resp.Body)
+ _, exists := htmlDoc.doc.Find(".file-view").Attr("class")
+ fmt.Printf("%s", resp.Body)
+
+ assert.False(t, exists, "README should not have rendered")
+ })
+ }
+ missing("sp-ace", "/user2/readme-test/src/branch/sp-ace/")
+ missing("nested-special", "/user2/readme-test/src/branch/special-subdir-nested/subproject") // the special subdirs should only trigger on the repo root
+ // missing("special-subdir-nested", "/user2/readme-test/src/branch/special-subdir-nested/") // This is currently FAILING, due to a bug introduced in https://github.com/go-gitea/gitea/pull/22177
+ missing("symlink-loop", "/user2/readme-test/src/branch/symlink-loop/")
+}
+
+func TestMarkDownImage(t *testing.T) {
+ defer tests.PrepareTestEnv(t)()
+
+ session := loginUser(t, "user2")
+
+ req := NewRequest(t, "GET", "/user2/repo1/src/branch/home-md-img-check")
+ resp := session.MakeRequest(t, req, http.StatusOK)
+
+ htmlDoc := NewHTMLParser(t, resp.Body)
+ _, exists := htmlDoc.doc.Find(`img[src="/user2/repo1/media/branch/home-md-img-check/test-fake-img.jpg"]`).Attr("src")
+ assert.True(t, exists, "Repo home page markdown image link check failed")
+
+ req = NewRequest(t, "GET", "/user2/repo1/src/branch/home-md-img-check/README.md")
+ resp = session.MakeRequest(t, req, http.StatusOK)
+
+ htmlDoc = NewHTMLParser(t, resp.Body)
+ _, exists = htmlDoc.doc.Find(`img[src="/user2/repo1/media/branch/home-md-img-check/test-fake-img.jpg"]`).Attr("src")
+ assert.True(t, exists, "Repo src page markdown image link check failed")
+}
diff --git a/tests/mysql.ini.tmpl b/tests/mysql.ini.tmpl
index 1dd7bfab2..b286f37bf 100644
--- a/tests/mysql.ini.tmpl
+++ b/tests/mysql.ini.tmpl
@@ -55,28 +55,6 @@ LFS_START_SERVER = true
LFS_JWT_SECRET = Tv_MjmZuHqpIY6GFl12ebgkRAMt4RlWt0v4EHKSXO0w
SSH_TRUSTED_USER_CA_KEYS = ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQCb4DC1dMFnJ6pXWo7GMxTchtzmJHYzfN6sZ9FAPFR4ijMLfGki+olvOMO5Fql1/yGnGfbELQa1S6y4shSvj/5K+zUFScmEXYf3Gcr87RqilLkyk16RS+cHNB1u87xTHbETaa3nyCJeGQRpd4IQ4NKob745mwDZ7jQBH8AZEng50Oh8y8fi8skBBBzaYp1ilgvzG740L7uex6fHV62myq0SXeCa+oJUjq326FU8y+Vsa32H8A3e7tOgXZPdt2TVNltx2S9H2WO8RMi7LfaSwARNfy1zu+bfR50r6ef8Yx5YKCMz4wWb1SHU1GS800mjOjlInLQORYRNMlSwR1+vLlVDciOqFapDSbj+YOVOawR0R1aqlSKpZkt33DuOBPx9qe6CVnIi7Z+Px/KqM+OLCzlLY/RS+LbxQpDWcfTVRiP+S5qRTcE3M3UioN/e0BE/1+MpX90IGpvVkA63ILYbKEa4bM3ASL7ChTCr6xN5XT+GpVJveFKK1cfNx9ExHI4rzYE=
-[lfs]
-MINIO_BASE_PATH = lfs/
-
-[attachment]
-MINIO_BASE_PATH = attachments/
-
-[avatars]
-MINIO_BASE_PATH = avatars/
-
-[repo-avatars]
-MINIO_BASE_PATH = repo-avatars/
-
-[storage]
-STORAGE_TYPE = minio
-SERVE_DIRECT = false
-MINIO_ENDPOINT = minio:9000
-MINIO_ACCESS_KEY_ID = 123456
-MINIO_SECRET_ACCESS_KEY = 12345678
-MINIO_BUCKET = gitea
-MINIO_LOCATION = us-east-1
-MINIO_USE_SSL = false
-
[mailer]
ENABLED = true
MAILER_TYPE = dummy
@@ -122,6 +100,9 @@ INSTALL_LOCK = true
SECRET_KEY = 9pCviYTWSb
INTERNAL_TOKEN = eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYmYiOjE0OTU1NTE2MTh9.hhSVGOANkaKk3vfCd2jDOIww4pUk0xtg9JRde5UogyQ
+[lfs]
+PATH = tests/{{TEST_TYPE}}/gitea-{{TEST_TYPE}}-mysql/data/lfs
+
[packages]
ENABLED = true
diff --git a/tests/pgsql.ini.tmpl b/tests/pgsql.ini.tmpl
index c39b6a79c..fbfbae7c6 100644
--- a/tests/pgsql.ini.tmpl
+++ b/tests/pgsql.ini.tmpl
@@ -105,7 +105,26 @@ SECRET_KEY = 9pCviYTWSb
INTERNAL_TOKEN = eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYmYiOjE0OTU1NTE2MTh9.hhSVGOANkaKk3vfCd2jDOIww4pUk0xtg9JRde5UogyQ
[lfs]
-PATH = tests/{{TEST_TYPE}}/gitea-{{TEST_TYPE}}-pgsql/data/lfs
+MINIO_BASE_PATH = lfs/
+
+[attachment]
+MINIO_BASE_PATH = attachments/
+
+[avatars]
+MINIO_BASE_PATH = avatars/
+
+[repo-avatars]
+MINIO_BASE_PATH = repo-avatars/
+
+[storage]
+STORAGE_TYPE = minio
+SERVE_DIRECT = false
+MINIO_ENDPOINT = minio:9000
+MINIO_ACCESS_KEY_ID = 123456
+MINIO_SECRET_ACCESS_KEY = 12345678
+MINIO_BUCKET = gitea
+MINIO_LOCATION = us-east-1
+MINIO_USE_SSL = false
[packages]
ENABLED = true
diff --git a/tests/test_utils.go b/tests/test_utils.go
index 5cc31b814..e3e5becfb 100644
--- a/tests/test_utils.go
+++ b/tests/test_utils.go
@@ -74,7 +74,7 @@ func InitTest(requireGitea bool) {
}
switch {
- case setting.Database.UseMySQL:
+ case setting.Database.Type.IsMySQL():
connType := "tcp"
if len(setting.Database.Host) > 0 && setting.Database.Host[0] == '/' { // looks like a unix socket
connType = "unix"
@@ -89,7 +89,7 @@ func InitTest(requireGitea bool) {
if _, err = db.Exec(fmt.Sprintf("CREATE DATABASE IF NOT EXISTS %s", setting.Database.Name)); err != nil {
log.Fatal("db.Exec: %v", err)
}
- case setting.Database.UsePostgreSQL:
+ case setting.Database.Type.IsPostgreSQL():
var db *sql.DB
var err error
if setting.Database.Host[0] == '/' {
@@ -146,7 +146,7 @@ func InitTest(requireGitea bool) {
}
}
- case setting.Database.UseMSSQL:
+ case setting.Database.Type.IsMSSQL():
host, port := setting.ParseMSSQLHostPort(setting.Database.Host)
db, err := sql.Open("mssql", fmt.Sprintf("server=%s; port=%s; database=%s; user id=%s; password=%s;",
host, port, "master", setting.Database.User, setting.Database.Passwd))
diff --git a/web_src/fomantic/build/semantic.js b/web_src/fomantic/build/semantic.js
index 77c82ca6f..6304c6faf 100644
--- a/web_src/fomantic/build/semantic.js
+++ b/web_src/fomantic/build/semantic.js
@@ -2118,7 +2118,7 @@ $.fn.dimmer = function(parameters) {
moduleNamespace = 'module-' + namespace,
moduleSelector = $allModules.selector || '',
- clickEvent = ('ontouchstart' in document.documentElement)
+ clickEvent = "click", unstableClickEvent = ('ontouchstart' in document.documentElement)
? 'touchstart'
: 'click',
@@ -2850,7 +2850,7 @@ $.fn.dropdown = function(parameters) {
moduleSelector = $allModules.selector || '',
hasTouch = ('ontouchstart' in document.documentElement),
- clickEvent = hasTouch
+ clickEvent = "click", unstableClickEvent = hasTouch
? 'touchstart'
: 'click',
diff --git a/web_src/js/components/ActionRunStatus.vue b/web_src/js/components/ActionRunStatus.vue
new file mode 100644
index 000000000..3717b6495
--- /dev/null
+++ b/web_src/js/components/ActionRunStatus.vue
@@ -0,0 +1,30 @@
+<template>
+ <SvgIcon name="octicon-check-circle-fill" class="green" :size="size" :class-name="className" v-if="status === 'success'"/>
+ <SvgIcon name="octicon-skip" class="ui text grey" :size="size" :class-name="className" v-else-if="status === 'skipped'"/>
+ <SvgIcon name="octicon-clock" class="ui text yellow" :size="size" :class-name="className" v-else-if="status === 'waiting'"/>
+ <SvgIcon name="octicon-blocked" class="ui text yellow" :size="size" :class-name="className" v-else-if="status === 'blocked'"/>
+ <SvgIcon name="octicon-meter" class="ui text yellow" :size="size" :class-name="'job-status-rotate ' + className" v-else-if="status === 'running'"/>
+ <SvgIcon name="octicon-x-circle-fill" class="red" :size="size" v-else/>
+</template>
+
+<script>
+import {SvgIcon} from '../svg.js';
+
+export default {
+ components: {SvgIcon},
+ props: {
+ status: {
+ type: String,
+ required: true
+ },
+ size: {
+ type: Number,
+ default: 16
+ },
+ className: {
+ type: String,
+ default: ''
+ }
+ },
+};
+</script>
diff --git a/web_src/js/components/ContextPopup.vue b/web_src/js/components/ContextPopup.vue
index 324403478..ad305b23a 100644
--- a/web_src/js/components/ContextPopup.vue
+++ b/web_src/js/components/ContextPopup.vue
@@ -87,7 +87,7 @@ export default {
}
},
mounted() {
- this.$refs.root.addEventListener('us-load-context-popup', (e) => {
+ this.$refs.root.addEventListener('ce-load-context-popup', (e) => {
const data = e.detail;
if (!this.loading && this.issue === null) {
this.load(data);
diff --git a/web_src/js/components/DashboardRepoList.js b/web_src/js/components/DashboardRepoList.js
index 0a009e78d..2328cc83a 100644
--- a/web_src/js/components/DashboardRepoList.js
+++ b/web_src/js/components/DashboardRepoList.js
@@ -87,6 +87,7 @@ function initVueComponents(app) {
}
return {
+ hasMounted: false, // accessing $refs in computed() need to wait for mounted
tab,
repos: [],
reposTotalCount: 0,
@@ -134,7 +135,19 @@ function initVueComponents(app) {
},
repoTypeCount() {
return this.counts[`${this.reposFilter}:${this.archivedFilter}:${this.privateFilter}`];
- }
+ },
+ checkboxArchivedFilterTitle() {
+ return this.hasMounted && this.$refs.checkboxArchivedFilter?.getAttribute(`data-title-${this.archivedFilter}`);
+ },
+ checkboxArchivedFilterProps() {
+ return {checked: this.archivedFilter === 'archived', indeterminate: this.archivedFilter === 'both'};
+ },
+ checkboxPrivateFilterTitle() {
+ return this.hasMounted && this.$refs.checkboxPrivateFilter?.getAttribute(`data-title-${this.privateFilter}`);
+ },
+ checkboxPrivateFilterProps() {
+ return {checked: this.privateFilter === 'private', indeterminate: this.privateFilter === 'both'};
+ },
},
mounted() {
@@ -144,10 +157,11 @@ function initVueComponents(app) {
initTooltip(elTooltip);
}
$(el).find('.dropdown').dropdown();
- this.setCheckboxes();
nextTick(() => {
this.$refs.search.focus();
});
+
+ this.hasMounted = true;
},
methods: {
@@ -156,39 +170,6 @@ function initVueComponents(app) {
this.updateHistory();
},
- setCheckboxes() {
- switch (this.archivedFilter) {
- case 'unarchived':
- $('#archivedFilterCheckbox').checkbox('set unchecked');
- break;
- case 'archived':
- $('#archivedFilterCheckbox').checkbox('set checked');
- break;
- case 'both':
- $('#archivedFilterCheckbox').checkbox('set indeterminate');
- break;
- default:
- this.archivedFilter = 'unarchived';
- $('#archivedFilterCheckbox').checkbox('set unchecked');
- break;
- }
- switch (this.privateFilter) {
- case 'public':
- $('#privateFilterCheckbox').checkbox('set unchecked');
- break;
- case 'private':
- $('#privateFilterCheckbox').checkbox('set checked');
- break;
- case 'both':
- $('#privateFilterCheckbox').checkbox('set indeterminate');
- break;
- default:
- this.privateFilter = 'both';
- $('#privateFilterCheckbox').checkbox('set indeterminate');
- break;
- }
- },
-
changeReposFilter(filter) {
this.reposFilter = filter;
this.repos = [];
@@ -245,45 +226,29 @@ function initVueComponents(app) {
},
toggleArchivedFilter() {
- switch (this.archivedFilter) {
- case 'both':
- this.archivedFilter = 'unarchived';
- break;
- case 'unarchived':
- this.archivedFilter = 'archived';
- break;
- case 'archived':
- this.archivedFilter = 'both';
- break;
- default:
- this.archivedFilter = 'unarchived';
- break;
+ if (this.archivedFilter === 'unarchived') {
+ this.archivedFilter = 'archived';
+ } else if (this.archivedFilter === 'archived') {
+ this.archivedFilter = 'both';
+ } else { // including both
+ this.archivedFilter = 'unarchived';
}
this.page = 1;
this.repos = [];
- this.setCheckboxes();
this.counts[`${this.reposFilter}:${this.archivedFilter}:${this.privateFilter}`] = 0;
this.searchRepos();
},
togglePrivateFilter() {
- switch (this.privateFilter) {
- case 'both':
- this.privateFilter = 'public';
- break;
- case 'public':
- this.privateFilter = 'private';
- break;
- case 'private':
- this.privateFilter = 'both';
- break;
- default:
- this.privateFilter = 'both';
- break;
+ if (this.privateFilter === 'both') {
+ this.privateFilter = 'public';
+ } else if (this.privateFilter === 'public') {
+ this.privateFilter = 'private';
+ } else { // including private
+ this.privateFilter = 'both';
}
this.page = 1;
this.repos = [];
- this.setCheckboxes();
this.counts[`${this.reposFilter}:${this.archivedFilter}:${this.privateFilter}`] = 0;
this.searchRepos();
},
diff --git a/web_src/js/components/RepoActionView.vue b/web_src/js/components/RepoActionView.vue
index 762067f52..aadc8369b 100644
--- a/web_src/js/components/RepoActionView.vue
+++ b/web_src/js/components/RepoActionView.vue
@@ -2,7 +2,10 @@
<div class="action-view-container">
<div class="action-view-header">
<div class="action-info-summary">
- {{ run.title }}
+ <ActionRunStatus :status="run.status" :size="20"/>
+ <div class="action-title">
+ {{ run.title }}
+ </div>
<button class="run_approve" @click="approveRun()" v-if="run.canApprove">
<i class="play circle outline icon"/>
</button>
@@ -17,12 +20,7 @@
<div class="job-brief-list">
<div class="job-brief-item" v-for="(job, index) in run.jobs" :key="job.id">
<a class="job-brief-link" :href="run.link+'/jobs/'+index">
- <SvgIcon name="octicon-check-circle-fill" class="green" v-if="job.status === 'success'"/>
- <SvgIcon name="octicon-skip" class="ui text grey" v-else-if="job.status === 'skipped'"/>
- <SvgIcon name="octicon-clock" class="ui text yellow" v-else-if="job.status === 'waiting'"/>
- <SvgIcon name="octicon-blocked" class="ui text yellow" v-else-if="job.status === 'blocked'"/>
- <SvgIcon name="octicon-meter" class="ui text yellow" class-name="job-status-rotate" v-else-if="job.status === 'running'"/>
- <SvgIcon name="octicon-x-circle-fill" class="red" v-else/>
+ <ActionRunStatus :status="job.status"/>
<span class="ui text">{{ job.name }}</span>
</a>
<button class="job-brief-rerun" @click="rerunJob(index)" v-if="job.canRerun">
@@ -48,12 +46,7 @@
<SvgIcon name="octicon-chevron-down" class="gt-mr-3" v-show="currentJobStepsStates[i].expanded"/>
<SvgIcon name="octicon-chevron-right" class="gt-mr-3" v-show="!currentJobStepsStates[i].expanded"/>
- <SvgIcon name="octicon-check-circle-fill" class="green gt-mr-3" v-if="jobStep.status === 'success'"/>
- <SvgIcon name="octicon-skip" class="ui text grey gt-mr-3" v-else-if="jobStep.status === 'skipped'"/>
- <SvgIcon name="octicon-clock" class="ui text yellow gt-mr-3" v-else-if="jobStep.status === 'waiting'"/>
- <SvgIcon name="octicon-blocked" class="ui text yellow gt-mr-3" v-else-if="jobStep.status === 'blocked'"/>
- <SvgIcon name="octicon-meter" class="ui text yellow gt-mr-3" class-name="job-status-rotate" v-else-if="jobStep.status === 'running'"/>
- <SvgIcon name="octicon-x-circle-fill" class="red gt-mr-3 " v-else/>
+ <ActionRunStatus :status="jobStep.status" class="gt-mr-3"/>
<span class="step-summary-msg">{{ jobStep.summary }}</span>
<span class="step-summary-dur">{{ jobStep.duration }}</span>
@@ -70,6 +63,7 @@
<script>
import {SvgIcon} from '../svg.js';
+import ActionRunStatus from './ActionRunStatus.vue';
import {createApp} from 'vue';
import AnsiToHTML from 'ansi-to-html';
@@ -79,6 +73,7 @@ const sfc = {
name: 'RepoActionView',
components: {
SvgIcon,
+ ActionRunStatus,
},
props: {
runIndex: String,
@@ -99,6 +94,7 @@ const sfc = {
run: {
link: '',
title: '',
+ status: '',
canCancel: false,
canApprove: false,
done: false,
@@ -327,7 +323,11 @@ export function initRepositoryActionView() {
.action-info-summary {
font-size: 150%;
height: 20px;
- padding: 0 10px;
+ display: flex;
+
+ .action-title {
+ padding: 0 5px;
+ }
}
// ================
diff --git a/web_src/js/components/RepoBranchTagDropdown.js b/web_src/js/components/RepoBranchTagDropdown.js
index 8bed305fc..e1bf35c12 100644
--- a/web_src/js/components/RepoBranchTagDropdown.js
+++ b/web_src/js/components/RepoBranchTagDropdown.js
@@ -3,43 +3,41 @@ import $ from 'jquery';
import {vueDelimiters} from './VueComponentLoader.js';
export function initRepoBranchTagDropdown(selector) {
- $(selector).each(function () {
- const $dropdown = $(this);
- const $data = $dropdown.find('.data');
+ $(selector).each(function (dropdownIndex, elRoot) {
const data = {
+ csrfToken: window.config.csrfToken,
items: [],
- mode: $data.data('mode'),
searchTerm: '',
- refName: '',
- noResults: '',
- canCreateBranch: false,
menuVisible: false,
createTag: false,
+ release: null,
+
isViewTag: false,
isViewBranch: false,
isViewTree: false,
+
active: 0,
- branchForm: '',
- branchURLPrefix: '',
- branchURLSuffix: '',
- tagURLPrefix: '',
- tagURLSuffix: '',
- setAction: false,
- submitForm: false,
+
+ ...window.config.pageData.branchDropdownDataList[dropdownIndex],
};
- $data.find('.item').each(function () {
- data.items.push({
- name: $(this).text(),
- url: $(this).data('url'),
- branch: $(this).hasClass('branch'),
- tag: $(this).hasClass('tag'),
- selected: $(this).hasClass('selected')
- });
- });
- $data.remove();
- // eslint-disable-next-line unicorn/no-this-assignment
- const elRoot = this;
+ // the "data.defaultBranch" is ambiguous, it could be "branch name" or "tag name"
+
+ if (data.showBranchesInDropdown && data.branches) {
+ for (const branch of data.branches) {
+ data.items.push({name: branch, url: branch, branch: true, tag: false, selected: branch === data.defaultBranch});
+ }
+ }
+ if (!data.noTag && data.tags) {
+ for (const tag of data.tags) {
+ if (data.release) {
+ data.items.push({name: tag, url: tag, branch: false, tag: true, selected: tag === data.release.tagName});
+ } else {
+ data.items.push({name: tag, url: tag, branch: false, tag: true, selected: tag === data.defaultBranch});
+ }
+ }
+ }
+
const view = createApp({
delimiters: vueDelimiters,
data() {
@@ -60,7 +58,7 @@ export function initRepoBranchTagDropdown(selector) {
return this.filteredItems.length === 0 && !this.showCreateNewBranch;
},
showCreateNewBranch() {
- if (!this.canCreateBranch || !this.searchTerm) {
+ if (this.disableCreateBranch || !this.searchTerm) {
return false;
}
@@ -77,10 +75,7 @@ export function initRepoBranchTagDropdown(selector) {
},
beforeMount() {
- this.noResults = elRoot.getAttribute('data-no-results');
- this.canCreateBranch = elRoot.getAttribute('data-can-create-branch') === 'true';
- this.branchForm = elRoot.getAttribute('data-branch-form');
- switch (elRoot.getAttribute('data-view-type')) {
+ switch (data.viewType) {
case 'tree':
this.isViewTree = true;
break;
@@ -91,14 +86,6 @@ export function initRepoBranchTagDropdown(selector) {
this.isViewBranch = true;
break;
}
- this.refName = elRoot.getAttribute('data-ref-name');
- this.branchURLPrefix = elRoot.getAttribute('data-branch-url-prefix');
- this.branchURLSuffix = elRoot.getAttribute('data-branch-url-suffix');
- this.tagURLPrefix = elRoot.getAttribute('data-tag-url-prefix');
- this.tagURLSuffix = elRoot.getAttribute('data-tag-url-suffix');
- this.setAction = elRoot.getAttribute('data-set-action') === 'true';
- this.submitForm = elRoot.getAttribute('data-submit-form') === 'true';
-
document.body.addEventListener('click', (event) => {
if (elRoot.contains(event.target)) return;
@@ -116,7 +103,7 @@ export function initRepoBranchTagDropdown(selector) {
}
item.selected = true;
const url = (item.tag) ? this.tagURLPrefix + item.url + this.tagURLSuffix : this.branchURLPrefix + item.url + this.branchURLSuffix;
- if (this.branchForm === '') {
+ if (!this.branchForm) {
window.location.href = url;
} else {
this.isViewTree = false;
diff --git a/web_src/js/features/aria.js b/web_src/js/features/aria.js
index 373d667c5..46944336a 100644
--- a/web_src/js/features/aria.js
+++ b/web_src/js/features/aria.js
@@ -83,8 +83,9 @@ function attachOneDropdownAria($dropdown) {
if (e.key === 'Enter') {
let $item = $dropdown.dropdown('get item', $dropdown.dropdown('get value'));
if (!$item) $item = $menu.find('> .item.selected'); // when dropdown filters items by input, there is no "value", so query the "selected" item
- // if the selected item is clickable, then trigger the click event. in the future there could be a special CSS class for it.
- if ($item && $item.is('a')) $item[0].click();
+ // if the selected item is clickable, then trigger the click event.
+ // we can not click any item without check, because Fomantic code might also handle the Enter event. that would result in double click.
+ if ($item && ($item.is('a') || $item.is('.js-aria-clickable'))) $item[0].click();
}
});
diff --git a/web_src/js/features/citation.js b/web_src/js/features/citation.js
index 382884562..c40b1addd 100644
--- a/web_src/js/features/citation.js
+++ b/web_src/js/features/citation.js
@@ -2,7 +2,7 @@ import $ from 'jquery';
const {pageData} = window.config;
-const initInputCitationValue = async ($citationCopyBibtex, $citationCopyApa) => {
+const initInputCitationValue = async ($citationCopyApa, $citationCopyBibtex) => {
const [{Cite, plugins}] = await Promise.all([
import(/* webpackChunkName: "citation-js-core" */'@citation-js/core'),
import(/* webpackChunkName: "citation-js-formats" */'@citation-js/plugin-software-formats'),
diff --git a/web_src/js/features/comp/EasyMDE.js b/web_src/js/features/comp/EasyMDE.js
index 182e6b429..2979627b0 100644
--- a/web_src/js/features/comp/EasyMDE.js
+++ b/web_src/js/features/comp/EasyMDE.js
@@ -77,6 +77,9 @@ export async function createCommentEasyMDE(textarea, easyMDEOptions = {}) {
const inputField = easyMDE.codemirror.getInputField();
+ easyMDE.codemirror.on('change', (...args) => {
+ easyMDEOptions?.onChange?.(...args);
+ });
easyMDE.codemirror.setOption('extraKeys', {
'Cmd-Enter': codeMirrorQuickSubmit,
'Ctrl-Enter': codeMirrorQuickSubmit,
diff --git a/web_src/js/features/comp/LabelEdit.js b/web_src/js/features/comp/LabelEdit.js
index 313d40682..18676d25e 100644
--- a/web_src/js/features/comp/LabelEdit.js
+++ b/web_src/js/features/comp/LabelEdit.js
@@ -13,6 +13,7 @@ function updateExclusiveLabelEdit(form) {
if (isExclusiveScopeName(nameInput.val())) {
exclusiveField.removeClass('muted');
+ exclusiveField.removeAttr('aria-disabled');
if (exclusiveCheckbox.prop('checked') && exclusiveCheckbox.data('exclusive-warn')) {
exclusiveWarning.removeClass('gt-hidden');
} else {
@@ -20,6 +21,7 @@ function updateExclusiveLabelEdit(form) {
}
} else {
exclusiveField.addClass('muted');
+ exclusiveField.attr('aria-disabled', 'true');
exclusiveWarning.addClass('gt-hidden');
}
}
diff --git a/web_src/js/features/contextpopup.js b/web_src/js/features/contextpopup.js
index 61f712090..8e0ef92bd 100644
--- a/web_src/js/features/contextpopup.js
+++ b/web_src/js/features/contextpopup.js
@@ -31,8 +31,9 @@ export function initContextPopups() {
createTippy(this, {
content: el,
interactive: true,
+ interactiveBorder: 5,
onShow: () => {
- el.firstChild.dispatchEvent(new CustomEvent('us-load-context-popup', {detail: {owner, repo, index}}));
+ el.firstChild.dispatchEvent(new CustomEvent('ce-load-context-popup', {detail: {owner, repo, index}}));
}
});
});
diff --git a/web_src/js/features/imagediff.js b/web_src/js/features/imagediff.js
index 7a285f1f8..a26b927c3 100644
--- a/web_src/js/features/imagediff.js
+++ b/web_src/js/features/imagediff.js
@@ -129,8 +129,8 @@ export function initImageDiff() {
initOverlay(createContext($imageAfter[2], $imageBefore[2]));
}
- hideElem($container.find('> .loader'));
$container.find('> .gt-hidden').removeClass('gt-hidden');
+ hideElem($container.find('.ui.loader'));
}
function initSideBySide(sizes) {
@@ -155,7 +155,7 @@ export function initImageDiff() {
height: sizes.size1.height * factor
});
sizes.image1.parent().css({
- margin: `${sizes.ratio[1] * factor + 15}px ${sizes.ratio[0] * factor}px ${sizes.ratio[1] * factor}px`,
+ margin: `10px auto`,
width: sizes.size1.width * factor + 2,
height: sizes.size1.height * factor + 2
});
@@ -164,7 +164,7 @@ export function initImageDiff() {
height: sizes.size2.height * factor
});
sizes.image2.parent().css({
- margin: `${sizes.ratio[3] * factor}px ${sizes.ratio[2] * factor}px`,
+ margin: `10px auto`,
width: sizes.size2.width * factor + 2,
height: sizes.size2.height * factor + 2
});
@@ -255,13 +255,12 @@ export function initImageDiff() {
width: sizes.size2.width * factor + 2,
height: sizes.size2.height * factor + 2
});
+
+ // some inner elements are `position: absolute`, so the container's height must be large enough
+ // the "css(width, height)" is somewhat hacky and not easy to understand, it could be improved in the future
sizes.image2.parent().parent().css({
width: sizes.max.width * factor + 2,
- height: sizes.max.height * factor + 2
- });
- $container.find('.onion-skin').css({
- width: sizes.max.width * factor + 2,
- height: sizes.max.height * factor + 4
+ height: sizes.max.height * factor + 2 + 20 /* extra height for inner "position: absolute" elements */,
});
const $range = $container.find("input[type='range']");
diff --git a/web_src/js/features/install.js b/web_src/js/features/install.js
index 2ba6fe127..23122ca4c 100644
--- a/web_src/js/features/install.js
+++ b/web_src/js/features/install.js
@@ -2,10 +2,18 @@ import $ from 'jquery';
import {hideElem, showElem} from '../utils/dom.js';
export function initInstall() {
- if ($('.page-content.install').length === 0) {
+ const $page = $('.page-content.install');
+ if ($page.length === 0) {
return;
}
+ if ($page.is('.post-install')) {
+ initPostInstall();
+ } else {
+ initPreInstall();
+ }
+}
+function initPreInstall() {
const defaultDbUser = 'gitea';
const defaultDbName = 'gitea';
@@ -40,6 +48,18 @@ export function initInstall() {
} // else: for SQLite3, the default path is always prepared by backend code (setting)
}).trigger('change');
+ const $appUrl = $('#app_url');
+ const configAppUrl = $appUrl.val();
+ if (configAppUrl.includes('://localhost')) {
+ $appUrl.val(window.location.href);
+ }
+
+ const $domain = $('#domain');
+ const configDomain = $domain.val().trim();
+ if (configDomain === 'localhost') {
+ $domain.val(window.location.hostname);
+ }
+
// TODO: better handling of exclusive relations.
$('#offline-mode input').on('change', function () {
if ($(this).is(':checked')) {
@@ -83,3 +103,20 @@ export function initInstall() {
}
});
}
+
+function initPostInstall() {
+ const el = document.getElementById('goto-user-login');
+ if (!el) return;
+
+ const targetUrl = el.getAttribute('href');
+ let tid = setInterval(async () => {
+ try {
+ const resp = await fetch(targetUrl);
+ if (tid && resp.status === 200) {
+ clearInterval(tid);
+ tid = null;
+ window.location.href = targetUrl;
+ }
+ } catch {}
+ }, 1000);
+}
diff --git a/web_src/js/features/repo-diff.js b/web_src/js/features/repo-diff.js
index d2559b123..56ebe4fc9 100644
--- a/web_src/js/features/repo-diff.js
+++ b/web_src/js/features/repo-diff.js
@@ -11,10 +11,8 @@ export function initRepoDiffReviewButton() {
const $reviewBox = $('#review-box');
const $counter = $reviewBox.find('.review-comments-counter');
- $(document).on('click', 'button[name="is_review"]', (e) => {
+ $(document).on('click', 'button[name="pending_review"]', (e) => {
const $form = $(e.target).closest('form');
- $form.append('<input type="hidden" name="is_review" value="true">');
-
// Watch for the form's submit event.
$form.on('submit', () => {
const num = parseInt($counter.attr('data-pending-comment-number')) + 1 || 1;
@@ -50,7 +48,15 @@ export function initRepoDiffConversationForm() {
return;
}
- const formDataString = String(new URLSearchParams(new FormData($form[0])));
+ const formData = new FormData($form[0]);
+
+ // if the form is submitted by a button, append the button's name and value to the form data
+ const submitter = e.originalEvent?.submitter;
+ const isSubmittedByButton = (submitter?.nodeName === 'BUTTON') || (submitter?.nodeName === 'INPUT' && submitter.type === 'submit');
+ if (isSubmittedByButton && submitter.name) {
+ formData.append(submitter.name, submitter.value);
+ }
+ const formDataString = String(new URLSearchParams(formData));
const $newConversationHolder = $(await $.post($form.attr('action'), formDataString));
const {path, side, idx} = $newConversationHolder.data();
diff --git a/web_src/js/features/repo-editor.js b/web_src/js/features/repo-editor.js
index a9d143847..b3e9b65f2 100644
--- a/web_src/js/features/repo-editor.js
+++ b/web_src/js/features/repo-editor.js
@@ -91,24 +91,27 @@ export function initRepoEditor() {
$('#commit-button').text($(this).attr('button_text'));
});
+ const joinTreePath = ($fileNameEl) => {
+ const parts = [];
+ $('.breadcrumb span.section').each(function () {
+ const element = $(this);
+ if (element.find('a').length) {
+ parts.push(element.find('a').text());
+ } else {
+ parts.push(element.text());
+ }
+ });
+ if ($fileNameEl.val()) parts.push($fileNameEl.val());
+ $('#tree_path').val(parts.join('/'));
+ };
+
const $editFilename = $('#file-name');
- $editFilename.on('keyup', function (e) {
- const $section = $('.breadcrumb span.section');
- const $divider = $('.breadcrumb div.divider');
- let value;
- let parts;
+ $editFilename.on('input', function () {
+ const parts = $(this).val().split('/');
- if (e.keyCode === 8 && getCursorPosition($(this)) === 0 && $section.length > 0) {
- value = $section.last().find('a').text();
- $(this).val(value + $(this).val());
- $(this)[0].setSelectionRange(value.length, value.length);
- $section.last().remove();
- $divider.last().remove();
- }
- if (e.keyCode === 191) {
- parts = $(this).val().split('/');
+ if (parts.length > 1) {
for (let i = 0; i < parts.length; ++i) {
- value = parts[i];
+ const value = parts[i];
if (i < parts.length - 1) {
if (value.length) {
$(`<span class="section"><a href="#">${htmlEscape(value)}</a></span>`).insertBefore($(this));
@@ -117,21 +120,28 @@ export function initRepoEditor() {
} else {
$(this).val(value);
}
- $(this)[0].setSelectionRange(0, 0);
+ this.setSelectionRange(0, 0);
}
}
- parts = [];
- $('.breadcrumb span.section').each(function () {
- const element = $(this);
- if (element.find('a').length) {
- parts.push(element.find('a').text());
- } else {
- parts.push(element.text());
- }
- });
- if ($(this).val()) parts.push($(this).val());
- $('#tree_path').val(parts.join('/'));
- }).trigger('keyup');
+
+ joinTreePath($(this));
+ });
+
+ $editFilename.on('keydown', function (e) {
+ const $section = $('.breadcrumb span.section');
+
+ // Jump back to last directory once the filename is empty
+ if (e.code === 'Backspace' && getCursorPosition($(this)) === 0 && $section.length > 0) {
+ e.preventDefault();
+ const $divider = $('.breadcrumb div.divider');
+ const value = $section.last().find('a').text();
+ $(this).val(value + $(this).val());
+ this.setSelectionRange(value.length, value.length);
+ $section.last().remove();
+ $divider.last().remove();
+ joinTreePath($(this));
+ }
+ });
const $editArea = $('.repository.editor textarea#edit_area');
if (!$editArea.length) return;
diff --git a/web_src/js/features/repo-issue.js b/web_src/js/features/repo-issue.js
index 4fc8bb5e6..41c9dd118 100644
--- a/web_src/js/features/repo-issue.js
+++ b/web_src/js/features/repo-issue.js
@@ -418,6 +418,22 @@ function assignMenuAttributes(menu) {
return id;
}
+export async function handleReply($el) {
+ hideElem($el);
+ const form = $el.closest('.comment-code-cloud').find('.comment-form');
+ form.removeClass('gt-hidden');
+ const $textarea = form.find('textarea');
+ let easyMDE = getAttachedEasyMDE($textarea);
+ if (!easyMDE) {
+ await attachTribute($textarea.get(), {mentions: true, emoji: true});
+ easyMDE = await createCommentEasyMDE($textarea);
+ }
+ $textarea.focus();
+ easyMDE.codemirror.focus();
+ assignMenuAttributes(form.find('.menu'));
+ return easyMDE;
+}
+
export function initRepoPullRequestReview() {
if (window.location.hash && window.location.hash.startsWith('#issuecomment-')) {
const commentDiv = $(window.location.hash);
@@ -455,19 +471,7 @@ export function initRepoPullRequestReview() {
$(document).on('click', 'button.comment-form-reply', async function (e) {
e.preventDefault();
-
- hideElem($(this));
- const form = $(this).closest('.comment-code-cloud').find('.comment-form');
- form.removeClass('gt-hidden');
- const $textarea = form.find('textarea');
- let easyMDE = getAttachedEasyMDE($textarea);
- if (!easyMDE) {
- await attachTribute($textarea.get(), {mentions: true, emoji: true});
- easyMDE = await createCommentEasyMDE($textarea);
- }
- $textarea.focus();
- easyMDE.codemirror.focus();
- assignMenuAttributes(form.find('.menu'));
+ await handleReply($(this));
});
const $reviewBox = $('.review-box-panel');
@@ -531,7 +535,7 @@ export function initRepoPullRequestReview() {
const td = ntr.find(`.add-comment-${side}`);
let commentCloud = td.find('.comment-code-cloud');
- if (commentCloud.length === 0 && !ntr.find('button[name="is_review"]').length) {
+ if (commentCloud.length === 0 && !ntr.find('button[name="pending_review"]').length) {
const data = await $.get($(this).closest('[data-new-comment-url]').data('new-comment-url'));
td.html(data);
commentCloud = td.find('.comment-code-cloud');
diff --git a/web_src/js/features/repo-legacy.js b/web_src/js/features/repo-legacy.js
index a9229c0d1..70542ad88 100644
--- a/web_src/js/features/repo-legacy.js
+++ b/web_src/js/features/repo-legacy.js
@@ -6,7 +6,7 @@ import {
initRepoIssueBranchSelect, initRepoIssueCodeCommentCancel, initRepoIssueCommentDelete,
initRepoIssueComments, initRepoIssueDependencyDelete, initRepoIssueReferenceIssue,
initRepoIssueStatusButton, initRepoIssueTitleEdit, initRepoIssueWipToggle,
- initRepoPullRequestUpdate, updateIssuesMeta,
+ initRepoPullRequestUpdate, updateIssuesMeta, handleReply
} from './repo-issue.js';
import {initUnicodeEscapeButton} from './repo-unicode-escape.js';
import {svg} from '../svg.js';
@@ -85,12 +85,18 @@ export function initRepoCommentForm() {
}
(async () => {
+ const $statusButton = $('#status-button');
for (const textarea of $commentForm.find('textarea:not(.review-textarea, .no-easymde)')) {
// Don't initialize EasyMDE for the dormant #edit-content-form
if (textarea.closest('#edit-content-form')) {
continue;
}
- const easyMDE = await createCommentEasyMDE(textarea);
+ const easyMDE = await createCommentEasyMDE(textarea, {
+ 'onChange': () => {
+ const value = easyMDE?.value().trim();
+ $statusButton.text($statusButton.attr(value.length === 0 ? 'data-status' : 'data-status-and-comment'));
+ },
+ });
initEasyMDEImagePaste(easyMDE, $commentForm.find('.dropzone'));
}
})();
@@ -139,7 +145,6 @@ export function initRepoCommentForm() {
const clickedItem = $(this);
const scope = $(this).attr('data-scope');
- const canRemoveScope = e.altKey;
$(this).parent().find('.item').each(function () {
if (scope) {
@@ -147,11 +152,7 @@ export function initRepoCommentForm() {
if ($(this).attr('data-scope') !== scope) {
return true;
}
- if ($(this).is(clickedItem)) {
- if (!canRemoveScope && $(this).hasClass('checked')) {
- return true;
- }
- } else if (!$(this).hasClass('checked')) {
+ if (!$(this).is(clickedItem) && !$(this).hasClass('checked')) {
return true;
}
} else if (!$(this).is(clickedItem)) {
@@ -226,7 +227,7 @@ export function initRepoCommentForm() {
$(this).parent().find('.item').each(function () {
$(this).removeClass('checked');
- $(this).find('.octicon').addClass('invisible');
+ $(this).find('.octicon-check').addClass('invisible');
});
if (selector === 'select-reviewers-modify' || selector === 'select-assignees-modify') {
@@ -484,7 +485,7 @@ export function initRepository() {
// File list and commits
if ($('.repository.file.list').length > 0 || $('.branch-dropdown').length > 0 ||
$('.repository.commits').length > 0 || $('.repository.release').length > 0) {
- initRepoBranchTagDropdown('.choose.reference .dropdown');
+ initRepoBranchTagDropdown('.choose.reference .ui.dropdown');
}
// Wiki
@@ -607,15 +608,15 @@ function initRepoIssueCommentEdit() {
$(document).on('click', '.edit-content', onEditContent);
// Quote reply
- $(document).on('click', '.quote-reply', function (event) {
+ $(document).on('click', '.quote-reply', async function (event) {
+ event.preventDefault();
const target = $(this).data('target');
const quote = $(`#${target}`).text().replace(/\n/g, '\n> ');
const content = `> ${quote}\n\n`;
let easyMDE;
if ($(this).hasClass('quote-reply-diff')) {
- const $parent = $(this).closest('.comment-code-cloud');
- $parent.find('button.comment-form-reply').trigger('click');
- easyMDE = getAttachedEasyMDE($parent.find('[name="content"]'));
+ const $replyBtn = $(this).closest('.comment-code-cloud').find('button.comment-form-reply');
+ easyMDE = await handleReply($replyBtn);
} else {
// for normal issue/comment page
easyMDE = getAttachedEasyMDE($('#comment-form .edit_area'));
@@ -631,6 +632,5 @@ function initRepoIssueCommentEdit() {
easyMDE.codemirror.setCursor(easyMDE.codemirror.lineCount(), 0);
});
}
- event.preventDefault();
});
}
diff --git a/web_src/js/features/repo-projects.js b/web_src/js/features/repo-projects.js
index 534f51785..a1e177e46 100644
--- a/web_src/js/features/repo-projects.js
+++ b/web_src/js/features/repo-projects.js
@@ -95,39 +95,35 @@ export function initRepoProject() {
$('.edit-project-board').each(function () {
const projectHeader = $(this).closest('.board-column-header');
const projectTitleLabel = projectHeader.find('.board-label');
- const projectTitleInput = $(this).find(
- '.content > .form > .field > .project-board-title',
- );
- const projectColorInput = $(this).find('.content > .form > .field #new_board_color');
+ const projectTitleInput = $(this).find('.project-board-title');
+ const projectColorInput = $(this).find('#new_board_color');
const boardColumn = $(this).closest('.board-column');
if (boardColumn.css('backgroundColor')) {
setLabelColor(projectHeader, rgbToHex(boardColumn.css('backgroundColor')));
}
- $(this)
- .find('.content > .form > .actions > .red')
- .on('click', function (e) {
- e.preventDefault();
-
- $.ajax({
- url: $(this).data('url'),
- data: JSON.stringify({title: projectTitleInput.val(), color: projectColorInput.val()}),
- headers: {
- 'X-Csrf-Token': csrfToken,
- },
- contentType: 'application/json',
- method: 'PUT',
- }).done(() => {
- projectTitleLabel.text(projectTitleInput.val());
- projectTitleInput.closest('form').removeClass('dirty');
- if (projectColorInput.val()) {
- setLabelColor(projectHeader, projectColorInput.val());
- }
- boardColumn.attr('style', `background: ${projectColorInput.val()}!important`);
- $('.ui.modal').modal('hide');
- });
+ $(this).find('.edit-column-button').on('click', function (e) {
+ e.preventDefault();
+
+ $.ajax({
+ url: $(this).data('url'),
+ data: JSON.stringify({title: projectTitleInput.val(), color: projectColorInput.val()}),
+ headers: {
+ 'X-Csrf-Token': csrfToken,
+ },
+ contentType: 'application/json',
+ method: 'PUT',
+ }).done(() => {
+ projectTitleLabel.text(projectTitleInput.val());
+ projectTitleInput.closest('form').removeClass('dirty');
+ if (projectColorInput.val()) {
+ setLabelColor(projectHeader, projectColorInput.val());
+ }
+ boardColumn.attr('style', `background: ${projectColorInput.val()}!important`);
+ $('.ui.modal').modal('hide');
});
+ });
});
$(document).on('click', '.set-default-project-board', async function (e) {
diff --git a/web_src/js/features/repo-release.js b/web_src/js/features/repo-release.js
index a061c6b23..a230d7765 100644
--- a/web_src/js/features/repo-release.js
+++ b/web_src/js/features/repo-release.js
@@ -3,7 +3,7 @@ import {attachTribute} from './tribute.js';
import {initCompMarkupContentPreviewTab} from './comp/MarkupContentPreview.js';
import {initEasyMDEImagePaste} from './comp/ImagePaste.js';
import {createCommentEasyMDE} from './comp/EasyMDE.js';
-import {hideElem} from '../utils/dom.js';
+import {hideElem, showElem} from '../utils/dom.js';
export function initRepoRelease() {
$(document).on('click', '.remove-rel-attach', function() {
@@ -14,8 +14,43 @@ export function initRepoRelease() {
});
}
+export function initRepoReleaseNew() {
+ const $repoReleaseNew = $('.repository.new.release');
+ if (!$repoReleaseNew.length) return;
-export function initRepoReleaseEditor() {
+ initTagNameEditor();
+ initRepoReleaseEditor();
+}
+
+function initTagNameEditor() {
+ const el = document.getElementById('tag-name-editor');
+ if (!el) return;
+
+ const existingTags = JSON.parse(el.getAttribute('data-existing-tags'));
+ if (!Array.isArray(existingTags)) return;
+
+ const defaultTagHelperText = el.getAttribute('data-tag-helper');
+ const newTagHelperText = el.getAttribute('data-tag-helper-new');
+ const existingTagHelperText = el.getAttribute('data-tag-helper-existing');
+
+ document.getElementById('tag-name').addEventListener('keyup', (e) => {
+ const value = e.target.value;
+ if (existingTags.includes(value)) {
+ // If the tag already exists, hide the target branch selector.
+ hideElem('#tag-target-selector');
+ document.getElementById('tag-helper').innerText = existingTagHelperText;
+ } else {
+ showElem('#tag-target-selector');
+ if (value) {
+ document.getElementById('tag-helper').innerText = newTagHelperText;
+ } else {
+ document.getElementById('tag-helper').innerText = defaultTagHelperText;
+ }
+ }
+ });
+}
+
+function initRepoReleaseEditor() {
const $editor = $('.repository.new.release .content-editor');
if ($editor.length === 0) {
return;
diff --git a/web_src/js/index.js b/web_src/js/index.js
index 611c09d2b..6b4f4ef3e 100644
--- a/web_src/js/index.js
+++ b/web_src/js/index.js
@@ -76,7 +76,7 @@ import {
import {initViewedCheckboxListenerFor} from './features/pull-view-file.js';
import {initOrgTeamSearchRepoBox, initOrgTeamSettings} from './features/org-team.js';
import {initUserAuthWebAuthn, initUserAuthWebAuthnRegister} from './features/user-auth-webauthn.js';
-import {initRepoRelease, initRepoReleaseEditor} from './features/repo-release.js';
+import {initRepoRelease, initRepoReleaseNew} from './features/repo-release.js';
import {initRepoEditor} from './features/repo-editor.js';
import {initCompSearchUserBox} from './features/comp/SearchUserBox.js';
import {initInstall} from './features/install.js';
@@ -179,7 +179,7 @@ $(document).ready(() => {
initRepoPullRequestAllowMaintainerEdit();
initRepoPullRequestReview();
initRepoRelease();
- initRepoReleaseEditor();
+ initRepoReleaseNew();
initRepoSettingGitHook();
initRepoSettingSearchTeamBox();
initRepoSettingsCollaboration();
diff --git a/web_src/js/markup/mermaid.js b/web_src/js/markup/mermaid.js
index 60f53d2b3..b519e2dcd 100644
--- a/web_src/js/markup/mermaid.js
+++ b/web_src/js/markup/mermaid.js
@@ -37,14 +37,10 @@ export async function renderMermaid() {
continue;
}
- let valid;
try {
- valid = mermaid.parse(source);
+ await mermaid.parse(source);
} catch (err) {
displayError(el, err);
- }
-
- if (!valid) {
el.closest('pre').classList.remove('is-loading');
continue;
}
@@ -52,22 +48,25 @@ export async function renderMermaid() {
try {
// can't use bindFunctions here because we can't cross the iframe boundary. This
// means js-based interactions won't work but they aren't intended to work either
- mermaid.mermaidAPI.render('mermaid', source, (svgStr) => {
- const heightStr = (svgStr.match(/viewBox="(.+?)"/) || ['', ''])[1].split(/\s+/)[3];
- if (!heightStr) return displayError(el, new Error('Could not determine chart height'));
- const iframe = document.createElement('iframe');
- iframe.classList.add('markup-render');
- iframe.sandbox = 'allow-scripts';
- iframe.style.height = `${Math.ceil(parseFloat(heightStr))}px`;
- iframe.srcdoc = `<html><head><style>${iframeCss}</style></head><body>${svgStr}</body></html>`;
- const mermaidBlock = document.createElement('div');
- mermaidBlock.classList.add('mermaid-block');
- mermaidBlock.append(iframe);
- const btn = makeCodeCopyButton();
- btn.setAttribute('data-clipboard-text', source);
- mermaidBlock.append(btn);
- el.closest('pre').replaceWith(mermaidBlock);
- });
+ const {svg} = await mermaid.render('mermaid', source);
+ const heightStr = (svg.match(/viewBox="(.+?)"/) || ['', ''])[1].split(/\s+/)[3];
+ if (!heightStr) return displayError(el, new Error('Could not determine chart height'));
+
+ const iframe = document.createElement('iframe');
+ iframe.classList.add('markup-render');
+ iframe.sandbox = 'allow-scripts';
+ iframe.style.height = `${Math.ceil(parseFloat(heightStr))}px`;
+ iframe.srcdoc = `<html><head><style>${iframeCss}</style></head><body>${svg}</body></html>`;
+
+ const mermaidBlock = document.createElement('div');
+ mermaidBlock.classList.add('mermaid-block');
+ mermaidBlock.append(iframe);
+
+ const btn = makeCodeCopyButton();
+ btn.setAttribute('data-clipboard-text', source);
+
+ mermaidBlock.append(btn);
+ el.closest('pre').replaceWith(mermaidBlock);
} catch (err) {
displayError(el, err);
}
diff --git a/web_src/js/svg.js b/web_src/js/svg.js
index 2132ad312..6476f16bf 100644
--- a/web_src/js/svg.js
+++ b/web_src/js/svg.js
@@ -80,7 +80,8 @@ export function svg(name, size = 16, className = '') {
const svgNode = document.firstChild;
if (size !== 16) svgNode.setAttribute('width', String(size));
if (size !== 16) svgNode.setAttribute('height', String(size));
- if (className) svgNode.classList.add(...className.split(/\s+/));
+ // filter array to remove empty string
+ if (className) svgNode.classList.add(...className.split(/\s+/).filter(Boolean));
return serializer.serializeToString(svgNode);
}
diff --git a/web_src/js/webcomponents/README.md b/web_src/js/webcomponents/README.md
new file mode 100644
index 000000000..eabbc24ad
--- /dev/null
+++ b/web_src/js/webcomponents/README.md
@@ -0,0 +1,19 @@
+# Web Components
+
+This `webcomponents` directory contains the source code for the web components used in the Gitea Web UI.
+
+https://developer.mozilla.org/en-US/docs/Web/Web_Components
+
+# Guidelines
+
+* These components are loaded in `<head>` (before DOM body),
+ so they should have their own dependencies and should be very light,
+ then they won't affect the page loading time too much.
+* If the component is not a public one, it's suggested to have its own `Gitea` or `gitea-` prefix to avoid conflicts.
+
+# TODO
+
+There are still some components that are not migrated to web components yet:
+
+* `<span class="js-pretty-number">`
+* `<time data-format>`
diff --git a/web_src/less/_base.less b/web_src/less/_base.less
index a73dae6bf..1cf65e784 100644
--- a/web_src/less/_base.less
+++ b/web_src/less/_base.less
@@ -2121,8 +2121,7 @@ a.ui.label:hover {
font: 12px var(--fonts-monospace);
white-space: pre-wrap;
word-break: break-all;
- overflow-wrap: break-word;
- word-wrap: break-word;
+ overflow-wrap: anywhere;
}
.blame .code-inner {
diff --git a/web_src/less/_repository.less b/web_src/less/_repository.less
index 4862e3096..2c47135a2 100644
--- a/web_src/less/_repository.less
+++ b/web_src/less/_repository.less
@@ -952,8 +952,15 @@
margin-top: 4px;
}
- .comment-form-reply .footer {
- padding-bottom: 1em;
+ .comparebox {
+ line-height: 32px;
+ vertical-align: middle;
+
+ .compare.label {
+ font-size: 1rem;
+ margin: 0;
+ border: 1px solid var(--color-light-border);
+ }
}
@media @mediaSm {
@@ -1663,8 +1670,14 @@
align-items: center;
.file {
- flex: 1;
- word-break: break-all;
+ min-width: 0;
+ .file-link {
+ max-width: fit-content;
+ display: -webkit-box;
+ -webkit-box-orient: vertical;
+ -webkit-line-clamp: 2;
+ overflow: hidden;
+ }
}
.button {
@@ -2863,7 +2876,7 @@
}
.repo-button-row > * {
- margin-top: 10px;
+ margin-top: 8px;
}
.wiki .repo-button-row {
@@ -3250,8 +3263,8 @@ td.blob-excerpt {
}
.sidebar-item-link {
- display: inline-flex;
align-items: center;
+ word-break: break-all;
}
.diff-file-box[data-folded="true"] .diff-file-body {
@@ -3271,11 +3284,20 @@ td.blob-excerpt {
position: sticky;
top: 77px;
z-index: 7;
-
+
@media (max-width: 480px) {
position: static;
}
}
+
+ .diff-file-header-actions {
+ flex-shrink: 0;
+ }
+
+ .diff-file-name {
+ flex: auto;
+ min-width: 100px;
+ }
}
.diff-file-body {
diff --git a/web_src/less/chroma/chroma-style-diff.go b/web_src/less/chroma/chroma-style-diff.go
new file mode 100644
index 000000000..424325968
--- /dev/null
+++ b/web_src/less/chroma/chroma-style-diff.go
@@ -0,0 +1,79 @@
+// Copyright 2023 The Gitea Authors. All rights reserved.
+// SPDX-License-Identifier: MIT
+
+//go:build ignore
+
+/*
+This tool is used to compare the CSS names in a chroma builtin styles with the Gitea theme CSS names.
+
+It outputs the difference between the two sets of CSS names, eg:
+
+```
+CSS names not in builtin:
+.chroma .ln
+----
+Builtin CSS names not in file:
+.chroma .vm
+```
+
+Developers could use this tool to re-sync the CSS names in the Gitea theme.
+*/
+
+package main
+
+import (
+ "os"
+ "regexp"
+ "strings"
+
+ "github.com/alecthomas/chroma/v2"
+)
+
+func main() {
+ if len(os.Args) != 2 {
+ println("Usage: chroma-style-diff css-or-less-file")
+ os.Exit(1)
+ }
+
+ data, err := os.ReadFile(os.Args[1])
+ if err != nil {
+ println(err.Error())
+ os.Exit(1)
+ }
+
+ content := string(data)
+
+ // a simple CSS parser to collect CSS names
+ content = regexp.MustCompile("//.*\r?\n").ReplaceAllString(content, "\n")
+ content = regexp.MustCompile("/\\*.*?\\*/").ReplaceAllString(content, "")
+ matches := regexp.MustCompile("\\s*([-.#:\\w\\s]+)\\s*\\{[^}]*}").FindAllStringSubmatch(content, -1)
+
+ cssNames := map[string]bool{}
+ for _, matchGroup := range matches {
+ cssName := strings.TrimSpace(matchGroup[1])
+ cssNames[cssName] = true
+ }
+
+ // collect Chroma builtin CSS names
+ builtin := map[string]bool{}
+ for tokenType, cssName := range chroma.StandardTypes {
+ if tokenType > 0 && cssName != "" {
+ builtin[".chroma ."+cssName] = true
+ }
+ }
+
+ // show the diff
+ println("CSS names not in builtin:")
+ for cssName := range cssNames {
+ if !builtin[cssName] {
+ println(cssName)
+ }
+ }
+ println("----")
+ println("Builtin CSS names not in file:")
+ for cssName := range builtin {
+ if !cssNames[cssName] {
+ println(cssName)
+ }
+ }
+}
diff --git a/web_src/less/chroma/dark.less b/web_src/less/chroma/dark.less
index 4be9cf791..1b0c722a1 100644
--- a/web_src/less/chroma/dark.less
+++ b/web_src/less/chroma/dark.less
@@ -7,17 +7,19 @@
.chroma .cpf { color: #649bc4; } /* CommentPreprocFile */
.chroma .cs { color: #9075cd; } /* CommentSpecial */
.chroma .dl { color: #649bc4; } /* LiteralStringDelimiter */
+.chroma .fm {} /* NameFunctionMagic */
+.chroma .g {} /* Generic */
.chroma .gd { color: #ffffff; background-color: #5f3737; } /* GenericDeleted */
.chroma .ge { color: #ddee30; } /* GenericEmph */
.chroma .gh { color: #ffaa10; } /* GenericHeading */
.chroma .gi { color: #ffffff; background-color: #3a523a; } /* GenericInserted */
+.chroma .gl {} /* GenericUnderline */
.chroma .go { color: #777e94; } /* GenericOutput */
.chroma .gp { color: #ebdbb2; } /* GenericPrompt */
.chroma .gr { color: #ff4433; } /* GenericError */
.chroma .gs { color: #ebdbb2; } /* GenericStrong */
.chroma .gt { color: #ff7540; } /* GenericTraceback */
.chroma .gu { color: #b8bb26; } /* GenericSubheading */
-.chroma .hl { background-color: #3f424d; } /* LineHighlight */
.chroma .il { color: #649bc4; } /* LiteralNumberIntegerLong */
.chroma .k { color: #ff7540; } /* Keyword */
.chroma .kc { color: #649bc4; } /* KeywordConstant */
@@ -25,16 +27,16 @@
.chroma .kn { color: #ffaa10; } /* KeywordNamespace */
.chroma .kp { color: #5f8700; } /* KeywordPseudo */
.chroma .kr { color: #ff7540; } /* KeywordReserved */
-.chroma .kt { color: #fabd2f; } /* KeywordType */
-.chroma .ln { color: #7f8699; } /* LineNumbers */
-.chroma .lnt { color: #7f8699; } /* LineNumbersTable */
+.chroma .kt { color: #ff7b72; } /* KeywordType */
+.chroma .l {} /* Literal */
+.chroma .ld {} /* LiteralDate */
.chroma .m { color: #649bc4; } /* LiteralNumber */
.chroma .mb { color: #649bc4; } /* LiteralNumberBin */
.chroma .mf { color: #649bc4; } /* LiteralNumberFloat */
.chroma .mh { color: #649bc4; } /* LiteralNumberHex */
.chroma .mi { color: #649bc4; } /* LiteralNumberInteger */
.chroma .mo { color: #649bc4; } /* LiteralNumberOct */
-.chroma .n { color: #fabd2f; } /* Name */
+.chroma .n { color: #c9d1d9; } /* Name */
.chroma .na { color: #b8bb26; } /* NameAttribute */
.chroma .nb { color: #fabd2f; } /* NameBuiltin */
.chroma .nc { color: #ffaa10; } /* NameClass */
@@ -51,6 +53,7 @@
.chroma .o { color: #ff7540; } /* Operator */
.chroma .ow { color: #5f8700; } /* OperatorWord */
.chroma .p { color: #d2d4db; } /* Punctuation */
+.chroma .py {} /* NameProperty */
.chroma .s { color: #b8bb26; } /* LiteralString */
.chroma .s1 { color: #b8bb26; } /* LiteralStringSingle */
.chroma .s2 { color: #b8bb26; } /* LiteralStringDouble */
@@ -67,4 +70,5 @@
.chroma .vc { color: #ff7540; } /* NameVariableClass */
.chroma .vg { color: #ffaa10; } /* NameVariableGlobal */
.chroma .vi { color: #ffaa10; } /* NameVariableInstance */
+.chroma .vm {} /* NameVariableMagic */
.chroma .w { color: #7f8699; } /* TextWhitespace */
diff --git a/web_src/less/chroma/light.less b/web_src/less/chroma/light.less
index 2e811844c..4bfce8fe7 100644
--- a/web_src/less/chroma/light.less
+++ b/web_src/less/chroma/light.less
@@ -7,16 +7,19 @@
.chroma .cpf { color: #4c4dbc; } /* CommentPreprocFile */
.chroma .cs { color: #999999; } /* CommentSpecial */
.chroma .dl { color: #106303; } /* LiteralStringDelimiter */
+.chroma .fm {} /* NameFunctionMagic */
+.chroma .g {} /* Generic */
.chroma .gd { color: #000000; background-color: #ffdddd; } /* GenericDeleted */
.chroma .ge { color: #000000; } /* GenericEmph */
.chroma .gh { color: #999999; } /* GenericHeading */
.chroma .gi { color: #000000; background-color: #ddffdd; } /* GenericInserted */
+.chroma .gl {} /* GenericUnderline */
.chroma .go { color: #888888; } /* GenericOutput */
.chroma .gp { color: #555555; } /* GenericPrompt */
.chroma .gr { color: #aa0000; } /* GenericError */
+.chroma .gs {} /* GenericStrong */
.chroma .gt { color: #aa0000; } /* GenericTraceback */
.chroma .gu { color: #aaaaaa; } /* GenericSubheading */
-.chroma .hl { background-color: #e5e5e5; } /* LineHighlight */
.chroma .il { color: #009999; } /* LiteralNumberIntegerLong */
.chroma .k { color: #d73a49; } /* Keyword */
.chroma .kc { color: #d73a49; } /* KeywordConstant */
@@ -25,14 +28,15 @@
.chroma .kp { color: #d73a49; } /* KeywordPseudo */
.chroma .kr { color: #d73a49; } /* KeywordReserved */
.chroma .kt { color: #445588; } /* KeywordType */
-.chroma .ln { color: #7f7f7f; } /* LineNumbers */
-.chroma .lnt { color: #7f7f7f; } /* LineNumbersTable */
+.chroma .l {} /* Literal */
+.chroma .ld {} /* LiteralDate */
.chroma .m { color: #009999; } /* LiteralNumber */
.chroma .mb { color: #009999; } /* LiteralNumberBin */
.chroma .mf { color: #009999; } /* LiteralNumberFloat */
.chroma .mh { color: #009999; } /* LiteralNumberHex */
.chroma .mi { color: #009999; } /* LiteralNumberInteger */
.chroma .mo { color: #009999; } /* LiteralNumberOct */
+.chroma .n {} /* Name */
.chroma .na { color: #d73a49; } /* NameAttribute */
.chroma .nb { color: #005cc5; } /* NameBuiltin */
.chroma .nc { color: #445588; } /* NameClass */
@@ -48,6 +52,8 @@
.chroma .nx { color: #24292e; } /* NameOther */
.chroma .o { color: #d73a49; } /* Operator */
.chroma .ow { color: #d73a49; } /* OperatorWord */
+.chroma .p {} /* Punctuation */
+.chroma .py {} /* NameProperty */
.chroma .s { color: #106303; } /* LiteralString */
.chroma .s1 { color: #cc7a00; } /* LiteralStringSingle */
.chroma .s2 { color: #106303; } /* LiteralStringDouble */
@@ -64,4 +70,5 @@
.chroma .vc { color: #008080; } /* NameVariableClass */
.chroma .vg { color: #008080; } /* NameVariableGlobal */
.chroma .vi { color: #008080; } /* NameVariableInstance */
+.chroma .vm {} /* NameVariableMagic */
.chroma .w { color: #bbbbbb; } /* TextWhitespace */
diff --git a/web_src/less/features/imagediff.less b/web_src/less/features/imagediff.less
index a9ba7f8c8..07763c15e 100644
--- a/web_src/less/features/imagediff.less
+++ b/web_src/less/features/imagediff.less
@@ -1,6 +1,6 @@
.image-diff-container {
text-align: center;
- padding: 30px 0;
+ padding: 1em 0;
img {
border: 1px solid var(--color-primary-light-7);
@@ -22,6 +22,7 @@
display: inline-block;
line-height: 0;
vertical-align: top;
+ margin: 0 1em;
.side-header {
font-weight: bold;
@@ -98,7 +99,7 @@
}
input {
- width: 300px;
+ max-width: 300px;
}
}
}
diff --git a/web_src/less/helpers.less b/web_src/less/helpers.less
index baa595994..08589fdaa 100644
--- a/web_src/less/helpers.less
+++ b/web_src/less/helpers.less
@@ -172,6 +172,27 @@
.gt-py-4 { padding-top: 1rem !important; padding-bottom: 1rem !important; }
.gt-py-5 { padding-top: 2rem !important; padding-bottom: 2rem !important; }
+.gt-gap-0 { gap: 0 !important; }
+.gt-gap-1 { gap: .125rem !important; }
+.gt-gap-2 { gap: .25rem !important; }
+.gt-gap-3 { gap: .5rem !important; }
+.gt-gap-4 { gap: 1rem !important; }
+.gt-gap-5 { gap: 2rem !important; }
+
+.gt-gap-x-0 { column-gap: 0 !important; }
+.gt-gap-x-1 { column-gap: .125rem !important; }
+.gt-gap-x-2 { column-gap: .25rem !important; }
+.gt-gap-x-3 { column-gap: .5rem !important; }
+.gt-gap-x-4 { column-gap: 1rem !important; }
+.gt-gap-x-5 { column-gap: 2rem !important; }
+
+.gt-gap-y-0 { row-gap: 0 !important; }
+.gt-gap-y-1 { row-gap: .125rem !important; }
+.gt-gap-y-2 { row-gap: .25rem !important; }
+.gt-gap-y-3 { row-gap: .5rem !important; }
+.gt-gap-y-4 { row-gap: 1rem !important; }
+.gt-gap-y-5 { row-gap: 2rem !important; }
+
.gt-content-center { align-content: center !important; }
@media @mediaSm {
diff --git a/web_src/less/themes/theme-arc-green.less b/web_src/less/themes/theme-arc-green.less
index 2f06f33ac..17b8f9bae 100644
--- a/web_src/less/themes/theme-arc-green.less
+++ b/web_src/less/themes/theme-arc-green.less
@@ -1,3 +1,4 @@
+@import "../chroma/base.less";
@import "../chroma/dark.less";
@import "../codemirror/dark.less";
diff --git a/webpack.config.js b/webpack.config.js
index 2ac463abe..245791e7e 100644
--- a/webpack.config.js
+++ b/webpack.config.js
@@ -234,7 +234,7 @@ export default {
'khroma@*': {licenseName: 'MIT'}, // https://github.com/fabiospampinato/khroma/pull/33
},
emitError: true,
- allow: '(Apache-2.0 OR BSD-2-Clause OR BSD-3-Clause OR MIT OR ISC OR CPAL-1.0 OR Unlicense)',
+ allow: '(Apache-2.0 OR BSD-2-Clause OR BSD-3-Clause OR MIT OR ISC OR CPAL-1.0 OR Unlicense OR EPL-1.0 OR EPL-2.0)',
ignore: [
'font-awesome',
],