diff options
author | Anthony Wang | 2023-03-12 23:17:11 +0000 |
---|---|---|
committer | Anthony Wang | 2023-03-12 23:19:57 +0000 |
commit | dbc3eb7fa071307e623fde961bfdff0894856948 (patch) | |
tree | 8961dc6a935d9ee89f5adf680a142d36900aaebb | |
parent | b4640101f3c8938ed689743606a79601201141ca (diff) | |
parent | e72290fd9aeb77a47311483d1d565e428ce40cd9 (diff) |
Merge remote-tracking branch 'origin/main' into forgejo-federation
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) @@ -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: | **write:public_key** | Grant read/write access to public keys | | **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 | | **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 Binary files differnew file mode 100644 index 000000000..65d675154 --- /dev/null +++ b/modules/git/tests/repos/repo1_bare/index 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 Binary files differnew file mode 100644 index 000000000..fb50b65f9 --- /dev/null +++ b/modules/git/tests/repos/repo1_bare/objects/1c/91d130dc5fb75fd2d9f586a058650889cfe7fb diff --git a/modules/git/tests/repos/repo1_bare/objects/28/b55526e7100924d864dd89e35c1ea62e7a5a32 b/modules/git/tests/repos/repo1_bare/objects/28/b55526e7100924d864dd89e35c1ea62e7a5a32 Binary files differnew file mode 100644 index 000000000..7779599a0 --- /dev/null +++ b/modules/git/tests/repos/repo1_bare/objects/28/b55526e7100924d864dd89e35c1ea62e7a5a32 diff --git a/modules/git/tests/repos/repo1_bare/objects/36/f97d9a96457e2bab511db30fe2db03893ebc64 b/modules/git/tests/repos/repo1_bare/objects/36/f97d9a96457e2bab511db30fe2db03893ebc64 Binary files differnew file mode 100644 index 000000000..c96b84390 --- /dev/null +++ b/modules/git/tests/repos/repo1_bare/objects/36/f97d9a96457e2bab511db30fe2db03893ebc64 diff --git a/modules/git/tests/repos/repo1_bare/objects/4b/825dc642cb6eb9a060e54bf8d69288fbee4904 b/modules/git/tests/repos/repo1_bare/objects/4b/825dc642cb6eb9a060e54bf8d69288fbee4904 Binary files differnew file mode 100644 index 000000000..adf64119a --- /dev/null +++ b/modules/git/tests/repos/repo1_bare/objects/4b/825dc642cb6eb9a060e54bf8d69288fbee4904 diff --git a/modules/git/tests/repos/repo1_bare/objects/93/3305878a3c9ad485c29b87fb662a73a9675c4b b/modules/git/tests/repos/repo1_bare/objects/93/3305878a3c9ad485c29b87fb662a73a9675c4b Binary files differnew file mode 100644 index 000000000..e198e7658 --- /dev/null +++ b/modules/git/tests/repos/repo1_bare/objects/93/3305878a3c9ad485c29b87fb662a73a9675c4b diff --git a/modules/git/tests/repos/repo1_bare/objects/ce/064814f4a0d337b333e646ece456cd39fab612 b/modules/git/tests/repos/repo1_bare/objects/ce/064814f4a0d337b333e646ece456cd39fab612 Binary files differnew file mode 100644 index 000000000..93f1525e5 --- /dev/null +++ b/modules/git/tests/repos/repo1_bare/objects/ce/064814f4a0d337b333e646ece456cd39fab612 diff --git a/modules/git/tests/repos/repo1_bare/objects/cf/8b0b492a950b358a7ce7f9d01b18aef48a6b2d b/modules/git/tests/repos/repo1_bare/objects/cf/8b0b492a950b358a7ce7f9d01b18aef48a6b2d Binary files differnew file mode 100644 index 000000000..1152b25bb --- /dev/null +++ b/modules/git/tests/repos/repo1_bare/objects/cf/8b0b492a950b358a7ce7f9d01b18aef48a6b2d 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, "&", "&") 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, ¬e); err != nil { + if err := git.GetNote(ctx, ctx.Repo.GitRepo, commitSHA.String(), ¬e); 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"}} {{$.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}} {{.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}} → {{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}} → {{end}}{{$file.Name}}" href="#diff-{{$file.NameHash}}">{{if $file.IsRenamed}}{{$file.OldName}} → {{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> {{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> {{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> {{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> {{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> {{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> {{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> {{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> {{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 Binary files differnew file mode 100644 index 000000000..b9009e324 --- /dev/null +++ b/tests/gitea-repositories-meta/user2/readme-test.git/objects/12/11481f7314efbfe4e44703170d96c8fac8172b 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 Binary files differnew file mode 100644 index 000000000..c7a4deca9 --- /dev/null +++ b/tests/gitea-repositories-meta/user2/readme-test.git/objects/17/2343566bf11fc71ba4acf8d2ea70d12bc1d037 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 Binary files differnew file mode 100644 index 000000000..d8522ae6d --- /dev/null +++ b/tests/gitea-repositories-meta/user2/readme-test.git/objects/1a/48cae3f18ccd9c929e6608f67087dbaac3cf9e 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 Binary files differnew file mode 100644 index 000000000..d4152e535 --- /dev/null +++ b/tests/gitea-repositories-meta/user2/readme-test.git/objects/1e/1e08102cf1b1fc01c069c88ee75445974363ab 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 Binary files differnew file mode 100644 index 000000000..715977676 --- /dev/null +++ b/tests/gitea-repositories-meta/user2/readme-test.git/objects/23/65bfe0c5714e2e3f2d53bb302b10d8d5b4fc7d 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 Binary files differnew file mode 100644 index 000000000..c5929ae89 --- /dev/null +++ b/tests/gitea-repositories-meta/user2/readme-test.git/objects/38/9d08c6a71d024a91f14089007cd789cd977ca6 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 Binary files differnew file mode 100644 index 000000000..106393d72 --- /dev/null +++ b/tests/gitea-repositories-meta/user2/readme-test.git/objects/3a/a8f4e0e1a535f0f9e0ae40e6ec1bce42642bc4 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 Binary files differnew file mode 100644 index 000000000..a7f4501ea --- /dev/null +++ b/tests/gitea-repositories-meta/user2/readme-test.git/objects/50/6ff7310f420e878595b4bc8f11688e3f0ae14e 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 Binary files differnew file mode 100644 index 000000000..a2dadacf8 --- /dev/null +++ b/tests/gitea-repositories-meta/user2/readme-test.git/objects/58/3eb775c596858380273492759d39081d65d029 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Ç>ƒ«Ü!¯ªÖ„LuUlÙ#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 Binary files differnew file mode 100644 index 000000000..3e4c8247d --- /dev/null +++ b/tests/gitea-repositories-meta/user2/readme-test.git/objects/6a/b05db4c52530726c1856eb558228e9d1949e7f 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 Binary files differnew file mode 100644 index 000000000..477d5b1f1 --- /dev/null +++ b/tests/gitea-repositories-meta/user2/readme-test.git/objects/71/60a063b5544b5a78131b94f47bfd200046eda2 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 Binary files differnew file mode 100644 index 000000000..3ef179698 --- /dev/null +++ b/tests/gitea-repositories-meta/user2/readme-test.git/objects/75/6c70c97047d8aeb11ca3c71edd9fb76cefee9c 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 Binary files differnew file mode 100644 index 000000000..4e39c0306 --- /dev/null +++ b/tests/gitea-repositories-meta/user2/readme-test.git/objects/7f/2b9f991d99362eb827b67f4ae2f5fbc5fa2271 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 Binary files differnew file mode 100644 index 000000000..90fae2388 --- /dev/null +++ b/tests/gitea-repositories-meta/user2/readme-test.git/objects/7f/792e709143fb0f021da2371e5f40d1bcc284fd 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 Binary files differnew file mode 100644 index 000000000..0428af472 --- /dev/null +++ b/tests/gitea-repositories-meta/user2/readme-test.git/objects/82/817856dadc7f6b944633e1b77d5b6e302dde06 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 Binary files differnew file mode 100644 index 000000000..64542d375 --- /dev/null +++ b/tests/gitea-repositories-meta/user2/readme-test.git/objects/8b/4149e7dede3cd53ba11c64c88b057c5fe2c200 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 Binary files differnew file mode 100644 index 000000000..8542b45c7 --- /dev/null +++ b/tests/gitea-repositories-meta/user2/readme-test.git/objects/93/54813d81053c14afe878a9f056b937ec42bb48 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 Binary files differnew file mode 100644 index 000000000..b53d42aee --- /dev/null +++ b/tests/gitea-repositories-meta/user2/readme-test.git/objects/9c/72c10e55e7d6ea21f591aa424e2625e8ad8094 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 Binary files differnew file mode 100644 index 000000000..6d9bc2a76 --- /dev/null +++ b/tests/gitea-repositories-meta/user2/readme-test.git/objects/a3/cd04bb110e17591ac04e156c7df2c2f5c96fa6 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 Binary files differnew file mode 100644 index 000000000..2f88dbd36 --- /dev/null +++ b/tests/gitea-repositories-meta/user2/readme-test.git/objects/b0/e851a5619e2d6cee1da25a15ab67305f0861ec 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 Binary files differnew file mode 100644 index 000000000..55bb8491a --- /dev/null +++ b/tests/gitea-repositories-meta/user2/readme-test.git/objects/b4/4c8eb00bdaf0522de61e591fee5f66851ef4b5 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 Binary files differnew file mode 100644 index 000000000..84ab5684a --- /dev/null +++ b/tests/gitea-repositories-meta/user2/readme-test.git/objects/b8/eaa80ad86072e1f23d2638842154ce9aceff8d 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 Binary files differnew file mode 100644 index 000000000..7bb434442 --- /dev/null +++ b/tests/gitea-repositories-meta/user2/readme-test.git/objects/d5/34f914944c3c943a6bdb677d869ac54934928d 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 Binary files differnew file mode 100644 index 000000000..9654f877b --- /dev/null +++ b/tests/gitea-repositories-meta/user2/readme-test.git/objects/e2/f9904cd97b4045feecfffef5a426e9461bee70 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ØM7—÷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 Binary files differnew file mode 100644 index 000000000..9f898ef87 --- /dev/null +++ b/tests/gitea-repositories-meta/user2/readme-test.git/objects/e7/bf02fcfa7a86f7fe9e8158b55d58ddf9d877ec 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 Binary files differnew file mode 100644 index 000000000..d1eff5286 --- /dev/null +++ b/tests/gitea-repositories-meta/user2/readme-test.git/objects/ea/57c91ddb8b4ac705b5ac4c34c7a48f2d0fc180 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 Binary files differnew file mode 100644 index 000000000..48c0b5a4d --- /dev/null +++ b/tests/gitea-repositories-meta/user2/readme-test.git/objects/fe/495ea336f079ef2bed68648d0ba9a37cdbd4aa 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 Binary files differnew file mode 100644 index 000000000..9bb0976fd --- /dev/null +++ b/tests/gitea-repositories-meta/user2/readme-test.git/objects/info/commit-graph 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 Binary files differnew file mode 100644 index 000000000..db39955a2 --- /dev/null +++ b/tests/gitea-repositories-meta/user2/readme-test.git/objects/pack/pack-8933bd634b76f8154310cccb52537a0195e43166.bitmap 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 Binary files differnew file mode 100644 index 000000000..561e0f2e9 --- /dev/null +++ b/tests/gitea-repositories-meta/user2/readme-test.git/objects/pack/pack-8933bd634b76f8154310cccb52537a0195e43166.idx 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 Binary files differnew file mode 100644 index 000000000..6f5bf1f04 --- /dev/null +++ b/tests/gitea-repositories-meta/user2/readme-test.git/objects/pack/pack-8933bd634b76f8154310cccb52537a0195e43166.pack 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 Binary files differnew file mode 100644 index 000000000..ea0bf76d0 --- /dev/null +++ b/tests/gitea-repositories-meta/user2/repo1.git/objects/40/3d76c604cb569323864e06a07b85d466924802 diff --git a/tests/gitea-repositories-meta/user2/repo1.git/objects/78/fb907e3a3309eae4fe8fef030874cebbf1cd5e b/tests/gitea-repositories-meta/user2/repo1.git/objects/78/fb907e3a3309eae4fe8fef030874cebbf1cd5e Binary files differnew file mode 100644 index 000000000..6a25f7409 --- /dev/null +++ b/tests/gitea-repositories-meta/user2/repo1.git/objects/78/fb907e3a3309eae4fe8fef030874cebbf1cd5e diff --git a/tests/gitea-repositories-meta/user2/repo1.git/objects/f3/fa0f5cc797fc4c02a1b8bec9de4b2072fcdbdf b/tests/gitea-repositories-meta/user2/repo1.git/objects/f3/fa0f5cc797fc4c02a1b8bec9de4b2072fcdbdf Binary files differnew file mode 100644 index 000000000..9b20f8af3 --- /dev/null +++ b/tests/gitea-repositories-meta/user2/repo1.git/objects/f3/fa0f5cc797fc4c02a1b8bec9de4b2072fcdbdf 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', ], |